[
  {
    "path": ".github/ISSUE_TEMPLATE/Bug.md",
    "content": "---\nname: Bug report\nabout: Report a bug\nlabels: ''\nassignees: ''\n---\n\n<!---WARNING!!! YOUR ISSUE WILL BE CLOSED AND DELETED IMMEDIATELY IF YOU DID NOT USE THE FOLLOWING TEMPLATE--->\n\n**Have You Read Our Docs**\n<!---Yes or No--->\n\n**Are You Reporting A Bug**\n<!---Yes or No--->\n\n**Environment**\n\n- Kext Version: \n- WiFi Card Model: \n- PCI Product ID: \n- macOS Version: \n\n**Description**\n<!---A clear and concise description of what the bug is--->\n\n**Bug Report Archive**\n<!---Open HeliPort while clicking Option, click \"create diagnostic report\", then drag and drop the zip file into this window--->\n<!---Read this guide if you are using AirportItlwm http://docs.oiw.workers.dev/itlwm/Troubleshooting.html#manually-for-airportitlwm--->\n\n**Kext Download Source**\n<!---To help us identify your issue, please tell us where did you download the kext and whether it's custom built--->\n"
  },
  {
    "path": ".github/workflows/main.yml",
    "content": "name: CD\n\non:\n  push:\n    branches: master\n\nenv:\n  BUILD_OUTPUT: 'build/Build/Products/Debug'\n\njobs:\n\n  build:\n    \n    runs-on: macos-latest\n\n    steps:\n\n    - uses: actions/checkout@v2\n      with:\n        fetch-depth: '5'\n\n    - name: Manage Version\n      run: |\n        git fetch --prune --unshallow --tags\n        GIT_SHA=\"$(git rev-parse --short HEAD)\"\n        CUR_TAG=\"$(git tag -l | grep 'alpha\\|beta' | tail -1)\"\n        eval $(grep -m 1 \"MODULE_VERSION =\" itlwm.xcodeproj/project.pbxproj | tr -d ';' | tr -d '\\t' | tr -d \" \")\n        echo \"SHORT_SHA=$GIT_SHA\" >> $GITHUB_ENV\n        echo \"ITLWM_VER=$MODULE_VERSION\" >> $GITHUB_ENV\n        if [[ -z $CUR_TAG ]]; then\n          echo \"OLD_PRE_TAG=NULL\" >> $GITHUB_ENV\n        else\n          echo \"OLD_PRE_TAG=$CUR_TAG\" >> $GITHUB_ENV\n        fi\n\n    - name: Install MacKernelSDK\n      run: |\n        git clone --depth=1 https://github.com/acidanthera/MacKernelSDK.git\n\n    - name: Build itlwm\n      run: |\n        xcodebuild -scheme itlwm -configuration Debug -derivedDataPath build GIT_COMMIT=_${SHORT_SHA} | xcpretty && exit ${PIPESTATUS[0]}\n\n    - name: Build AirportItlwm\n      run: |\n        xcodebuild -scheme \"AirportItlwm (all)\" -configuration Debug -derivedDataPath build GIT_COMMIT=_${SHORT_SHA} | xcpretty && exit ${PIPESTATUS[0]}\n\n    - name: Pack Artifacts\n      run: |\n        cd $BUILD_OUTPUT\n          zip -r itlwm-v${ITLWM_VER}-DEBUG-alpha-${SHORT_SHA}.zip itlwm.kext\n          while read -r tgt ; do\n            zip -r AirportItlwm-${tgt// /_}-v${ITLWM_VER}-DEBUG-alpha-${SHORT_SHA}.zip \"$tgt\"\n          done < <(find . -mindepth 1 -maxdepth 1 -type d -not -path \"*.kext\" | cut -c 3-)\n        cd -\n\n    - name: Generate Prerelease Release Notes\n      run: |\n        echo '### Disclaimer:' >> ReleaseNotes.md\n        echo '***This alpha version is for testing only.***' >> ReleaseNotes.md\n        echo 'It is not ready for daily use and we do not guarantee its usability.' >> ReleaseNotes.md\n        echo 'If you discovered an issue and you do not have debugging skills, please check with the [Gitter Chat Room](https://gitter.im/OpenIntelWireless/itlwm) in advance before opening an Issue.' >> ReleaseNotes.md\n        echo '### The latest five updates are:' >> ReleaseNotes.md\n        git log -\"5\" --format=\"- %H %s\" | sed '/^$/d' >> ReleaseNotes.md\n\n    - name: Delete Old Prerelease\n      uses: dev-drprasad/delete-tag-and-release@v0.2.1\n      with:\n        tag_name: ${{ env.OLD_PRE_TAG }}\n      env:\n        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n\n    - name: Publish GitHub Release\n      if: contains(github.event.head_commit.message, 'Bump version') == false\n      uses: ncipollo/release-action@v1.12.0\n      with:\n        prerelease: true\n        bodyFile: ReleaseNotes.md\n        artifacts: \"${{ env.BUILD_OUTPUT }}/*.zip\"\n        tag: \"v${{ env.ITLWM_VER }}-alpha\"\n        token: ${{ secrets.GITHUB_TOKEN }}\n"
  },
  {
    "path": ".gitignore",
    "content": ".DS_Store\nDerivedData\nbuild\nxcuserdata\nproject.xcworkspace\nFwBinary.cpp\n*.pyc\nMacKernelSDK\n"
  },
  {
    "path": "AirportItlwm/AirportAWDL.cpp",
    "content": "//\n//  AirportAWDL.cpp\n//  AirportItlwm\n//\n//  Created by qcwap on 2020/9/4.\n//  Copyright © 2020 钟先耀. All rights reserved.\n//\n\n#include \"AirportItlwm.hpp\"\n\n#include <net80211/ieee80211_priv.h>\n#include <net80211/ieee80211_var.h>\n\n#define INTERFACE_NAME(object) \\\n OSDynamicCast(IO80211Interface, object) == nullptr ? (OSDynamicCast(IO80211P2PInterface, object) == nullptr ? \"???\" : OSDynamicCast(IO80211P2PInterface, object)->getBSDName()) : OSDynamicCast(IO80211Interface, object)->getBSDName()\n\nIOReturn AirportItlwm::\ngetIE(OSObject *object, struct apple80211_ie_data *data)\n{\n    XYLog(\"%s %s Error\\n\", __FUNCTION__,  INTERFACE_NAME(object));\n    return kIOReturnError;\n}\n\nIOReturn AirportItlwm::\nsetIE(OSObject *object, struct apple80211_ie_data *data)\n{\n    XYLog(\"%s %s frame_type_flags %x add %d signature_len %d ie_len %d\\n\", __FUNCTION__, INTERFACE_NAME(object), data->frame_type_flags, data->add, data->signature_len, data->ie_len);\n    if (data->frame_type_flags == APPLE80211_IE_FLAG_ASSOC_REQ && data->add && data->ie_len && *(uint8_t*)data->ie == 68) {\n        XYLog(\"%s setCustomAssocIE\\n\", __FUNCTION__);\n        return kIOReturnSuccess;\n    }\n\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\nsetP2P_SCAN(OSObject *object, struct apple80211_scan_data *data)\n{\n    XYLog(\"%s %s ssid=%s bssid=%s channel=%d phy_mode=%d scan_type=%d\\n\", __FUNCTION__, INTERFACE_NAME(object), data->ssid, ether_sprintf(data->bssid.octet), data->num_channels, data->phy_mode, data->scan_type);\n\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\nsetP2P_LISTEN(OSObject *object, struct apple80211_p2p_listen_data *data)\n{\n    XYLog(\"%s %s channel=%d pad1=%d flags=%d duration=%d\\n\", __FUNCTION__, INTERFACE_NAME(object), data->channel, data->pad1, data->flags, data->duration);\n\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\nsetP2P_GO_CONF(OSObject *object, struct apple80211_p2p_go_conf_data *data)\n{\n    XYLog(\"%s %s auth_upper=%d auth_lower=%d channel=%d bcn_len=%d ssid=%s suppress_beacon=%d\\n\", __FUNCTION__, INTERFACE_NAME(object), data->auth_upper, data->auth_lower, data->channel, data->bcn_len, data->ssid, data->suppress_beacon);\n\n    return kIOReturnSuccess;\n}\n"
  },
  {
    "path": "AirportItlwm/AirportItlwm-Monterey-Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>$(DEVELOPMENT_LANGUAGE)</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>$(MODULE_VERSION)</string>\n\t<key>CFBundleVersion</key>\n\t<string>$(MODULE_VERSION)</string>\n\t<key>IOKitPersonalities</key>\n\t<dict>\n\t\t<key>itlwm</key>\n\t\t<dict>\n\t\t\t<key>CFBundleIdentifier</key>\n\t\t\t<string>com.zxystd.AirportItlwm</string>\n\t\t\t<key>IOClass</key>\n\t\t\t<string>AirportItlwm</string>\n\t\t\t<key>IOMatchCategory</key>\n\t\t\t<string>IODefaultMatchCategory</string>\n\t\t\t<key>IOPCIMatch</key>\n\t\t\t<string>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</string>\n\t\t\t<key>IOProbeScore</key>\n\t\t\t<integer>2000</integer>\n\t\t\t<key>IOProviderClass</key>\n\t\t\t<string>IOPCIDevice</string>\n\t\t</dict>\n\t</dict>\n\t<key>NSHumanReadableCopyright</key>\n\t<string>Copyright © 2020 钟先耀. All rights reserved.</string>\n\t<key>OSBundleLibraries</key>\n\t<dict>\n\t\t<key>com.apple.iokit.IO80211FamilyLegacy</key>\n\t\t<string>600.0</string>\n\t\t<key>com.apple.iokit.IONetworkingFamily</key>\n\t\t<string>3.2</string>\n\t\t<key>com.apple.iokit.IOPCIFamily</key>\n\t\t<string>2.9</string>\n\t\t<key>com.apple.kpi.bsd</key>\n\t\t<string>16.7</string>\n\t\t<key>com.apple.kpi.iokit</key>\n\t\t<string>16.7</string>\n\t\t<key>com.apple.kpi.libkern</key>\n\t\t<string>16.7</string>\n\t\t<key>com.apple.kpi.mach</key>\n\t\t<string>16.7</string>\n\t</dict>\n\t<key>OSBundleRequired</key>\n\t<string>Network-Root</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "AirportItlwm/AirportItlwm-Sonoma-Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>$(DEVELOPMENT_LANGUAGE)</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>$(MODULE_VERSION)</string>\n\t<key>CFBundleVersion</key>\n\t<string>$(MODULE_VERSION)</string>\n\t<key>IOKitPersonalities</key>\n\t<dict>\n\t\t<key>NetworkController</key>\n\t\t<dict>\n\t\t\t<key>CFBundleIdentifier</key>\n\t\t\t<string>com.zxystd.AirportItlwm</string>\n\t\t\t<key>IOClass</key>\n\t\t\t<string>AirportItlwm</string>\n\t\t\t<key>IOMatchCategory</key>\n\t\t\t<string>WiFiDriver</string>\n\t\t\t<key>IONetworkRootType</key>\n\t\t\t<string>airport</string>\n\t\t\t<key>IOProbeScore</key>\n\t\t\t<integer>70000</integer>\n\t\t\t<key>IOProviderClass</key>\n\t\t\t<string>IOPCIEDeviceWrapper</string>\n\t\t\t<key>IOResourceMatch</key>\n\t\t\t<string>IOBSD</string>\n\t\t</dict>\n\t\t<key>itlwm</key>\n\t\t<dict>\n\t\t\t<key>CFBundleIdentifier</key>\n\t\t\t<string>com.zxystd.AirportItlwm</string>\n\t\t\t<key>IOClass</key>\n\t\t\t<string>IOPCIEDeviceWrapper</string>\n\t\t\t<key>IOPCIMatch</key>\n\t\t\t<string>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</string>\n\t\t\t<key>IOProbeScore</key>\n\t\t\t<integer>70000</integer>\n\t\t\t<key>IOProviderClass</key>\n\t\t\t<string>IOPCIDevice</string>\n\t\t</dict>\n\t</dict>\n\t<key>NSHumanReadableCopyright</key>\n\t<string>Copyright © 2020 钟先耀. All rights reserved.</string>\n\t<key>OSBundleLibraries</key>\n\t<dict>\n\t\t<key>com.apple.driver.corecapture</key>\n\t\t<string>1.0.0</string>\n\t\t<key>com.apple.iokit.IO80211Family</key>\n\t\t<string>1.5.0</string>\n\t\t<key>com.apple.iokit.IONetworkingFamily</key>\n\t\t<string>3.2</string>\n\t\t<key>com.apple.iokit.IOPCIFamily</key>\n\t\t<string>2.9</string>\n\t\t<key>com.apple.iokit.IOSkywalkFamily</key>\n\t\t<string>1.0</string>\n\t\t<key>com.apple.kpi.bsd</key>\n\t\t<string>16.7</string>\n\t\t<key>com.apple.kpi.iokit</key>\n\t\t<string>16.7</string>\n\t\t<key>com.apple.kpi.libkern</key>\n\t\t<string>16.7</string>\n\t\t<key>com.apple.kpi.mach</key>\n\t\t<string>16.7</string>\n\t</dict>\n\t<key>OSBundleRequired</key>\n\t<string>Network-Root</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "AirportItlwm/AirportItlwm.cpp",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n#include \"AirportItlwm.hpp\"\n\n#include <crypto/sha1.h>\n#include <net80211/ieee80211_priv.h>\n#include <net80211/ieee80211_var.h>\n\n#define super IO80211Controller\nOSDefineMetaClassAndStructors(AirportItlwm, IO80211Controller);\nOSDefineMetaClassAndStructors(CTimeout, OSObject)\n\nIO80211WorkLoop *_fWorkloop;\nIOCommandGate *_fCommandGate;\n\nbool AirportItlwm::init(OSDictionary *properties)\n{\n    bool ret = super::init(properties);\n    awdlSyncEnable = true;\n    power_state = 0;\n    memset(geo_location_cc, 0, sizeof(geo_location_cc));\n    return ret;\n}\n\n#define  PCI_MSI_FLAGS        2    /* Message Control */\n#define  PCI_CAP_ID_MSI        0x05    /* Message Signalled Interrupts */\n#define  PCI_MSIX_FLAGS        2    /* Message Control */\n#define  PCI_CAP_ID_MSIX    0x11    /* MSI-X */\n#define  PCI_MSIX_FLAGS_ENABLE    0x8000    /* MSI-X enable */\n#define  PCI_MSI_FLAGS_ENABLE    0x0001    /* MSI feature enabled */\n\nstatic void pciMsiSetEnable(IOPCIDevice *device, UInt8 msiCap, int enable)\n{\n    u16 control;\n    \n    control = device->configRead16(msiCap + PCI_MSI_FLAGS);\n    control &= ~PCI_MSI_FLAGS_ENABLE;\n    if (enable)\n        control |= PCI_MSI_FLAGS_ENABLE;\n    device->configWrite16(msiCap + PCI_MSI_FLAGS, control);\n}\n\nstatic void pciMsiXClearAndSet(IOPCIDevice *device, UInt8 msixCap, UInt16 clear, UInt16 set)\n{\n    u16 ctrl;\n    \n    ctrl = device->configRead16(msixCap + PCI_MSIX_FLAGS);\n    ctrl &= ~clear;\n    ctrl |= set;\n    device->configWrite16(msixCap + PCI_MSIX_FLAGS, ctrl);\n}\n\nIOService* AirportItlwm::probe(IOService *provider, SInt32 *score)\n{\n    bool isMatch = false;\n    super::probe(provider, score);\n    UInt8 msiCap;\n    UInt8 msixCap;\n    IOPCIDevice* device = OSDynamicCast(IOPCIDevice, provider);\n    if (!device)\n        return NULL;\n    if (ItlIwx::iwx_match(device)) {\n        isMatch = true;\n        fHalService = new ItlIwx;\n    }\n    if (!isMatch && ItlIwm::iwm_match(device)) {\n        isMatch = true;\n        fHalService = new ItlIwm;\n    }\n    if (!isMatch && ItlIwn::iwn_match(device)) {\n        isMatch = true;\n        fHalService = new ItlIwn;\n    }\n    if (isMatch) {\n        device->findPCICapability(PCI_CAP_ID_MSIX, &msixCap);\n        if (msixCap)\n            pciMsiXClearAndSet(device, msixCap, PCI_MSIX_FLAGS_ENABLE, 0);\n        device->findPCICapability(PCI_CAP_ID_MSI, &msiCap);\n        if (msiCap)\n            pciMsiSetEnable(device, msiCap, 1);\n        if (!msiCap && !msixCap) {\n            XYLog(\"%s No MSI cap\\n\", __FUNCTION__);\n            fHalService->release();\n            fHalService = NULL;\n            return NULL;\n        }\n        return this;\n    }\n    return NULL;\n}\n\nbool AirportItlwm::configureInterface(IONetworkInterface *netif)\n{\n    IONetworkData *nd;\n    struct _ifnet *ifp = &fHalService->get80211Controller()->ic_ac.ac_if;\n    \n    if (super::configureInterface(netif) == false) {\n        XYLog(\"super failed\\n\");\n        return false;\n    }\n    \n    nd = netif->getParameter(kIONetworkStatsKey);\n    if (!nd || !(fpNetStats = (IONetworkStats *)nd->getBuffer())) {\n        XYLog(\"network statistics buffer unavailable?\\n\");\n        return false;\n    }\n    ifp->netStat = fpNetStats;\n    ether_ifattach(ifp, OSDynamicCast(IOEthernetInterface, netif));\n    fpNetStats->collisions = 0;\n#ifdef __PRIVATE_SPI__\n    netif->configureOutputPullModel(fHalService->getDriverInfo()->getTxQueueSize(), 0, 0, IOEthernetInterface::kOutputPacketSchedulingModelNormal, 0);\n#endif\n    \n    return true;\n}\n\nIONetworkInterface *AirportItlwm::createInterface()\n{\n    AirportItlwmInterface *netif = new AirportItlwmInterface;\n    if (!netif)\n        return NULL;\n    if (!netif->init(this, fHalService)) {\n        netif->release();\n        return NULL;\n    }\n    return netif;\n}\n\nvoid 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) \n{\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    \n    ieee80211_disable_rsn(ic);\n    ieee80211_disable_wep(ic);\n    \n    struct ieee80211_wpaparams\t wpa;\n    struct ieee80211_nwkey\t\t nwkey;\n    bzero(&wpa, sizeof(wpa));\n    bzero(&nwkey, sizeof(nwkey));\n    \n    memset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN);\n    memcpy(ic->ic_des_essid, ssid, ssid_len);\n    ic->ic_des_esslen = ssid_len;\n    \n    bool is_zero = true;\n    for (int i = 0; i < IEEE80211_ADDR_LEN; i++)\n    is_zero &= bssid.octet[i] == 0;\n    \n    if (!is_zero) {\n        IEEE80211_ADDR_COPY(ic->ic_des_bssid, bssid.octet);\n        ic->ic_flags |= IEEE80211_F_DESBSSID;\n    }\n    else {\n        memset(ic->ic_des_bssid, 0, IEEE80211_ADDR_LEN);\t\n        ic->ic_flags &= ~IEEE80211_F_DESBSSID;\n    }\n\n    // AUTHTYPE_WPA3_SAE AUTHTYPE_WPA3_FT_SAE\n    // 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.\n    if (authtype_upper == APPLE80211_AUTHTYPE_WPA3_SAE || authtype_upper == APPLE80211_AUTHTYPE_WPA3_FT_SAE) {\n        wpa.i_protos |= IEEE80211_WPA_PROTO_WPA2;\n        authtype_upper |= APPLE80211_AUTHTYPE_WPA2_PSK;// hack\n    }\n    // AUTHTYPE_WPA3_ENTERPRISE AUTHTYPE_WPA3_FT_ENTERPRISE\n    if (authtype_upper == APPLE80211_AUTHTYPE_WPA3_ENTERPRISE || authtype_upper == APPLE80211_AUTHTYPE_WPA3_FT_ENTERPRISE) {\n        wpa.i_protos |= IEEE80211_WPA_PROTO_WPA2;\n        authtype_upper |= APPLE80211_AUTHTYPE_WPA2;// hack\n    }\n    \n    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)) {\n        XYLog(\"%s %d\\n\", __FUNCTION__, __LINE__);\n        wpa.i_protos = IEEE80211_WPA_PROTO_WPA1 | IEEE80211_WPA_PROTO_WPA2;\n    }\n    \n    if (authtype_upper & (APPLE80211_AUTHTYPE_WPA_PSK | APPLE80211_AUTHTYPE_WPA2_PSK | APPLE80211_AUTHTYPE_SHA256_PSK)) {\n        XYLog(\"%s %d\\n\", __FUNCTION__, __LINE__);\n        wpa.i_akms |= IEEE80211_WPA_AKM_PSK | IEEE80211_WPA_AKM_SHA256_PSK;\n        wpa.i_enabled = 1;\n        memcpy(ic->ic_psk, key, sizeof(ic->ic_psk));\n        ic->ic_flags |= IEEE80211_F_PSK;\n        ieee80211_ioctl_setwpaparms(ic, &wpa);\n    }\n    if (authtype_upper & (APPLE80211_AUTHTYPE_WPA | APPLE80211_AUTHTYPE_WPA2 | APPLE80211_AUTHTYPE_SHA256_8021X)) {\n        XYLog(\"%s %d\\n\", __FUNCTION__, __LINE__);\n        wpa.i_akms |= IEEE80211_WPA_AKM_8021X | IEEE80211_WPA_AKM_SHA256_8021X;\t\n        wpa.i_enabled = 1;\n        ieee80211_ioctl_setwpaparms(ic, &wpa);\n    }\n    \n    if (authtype_lower == APPLE80211_AUTHTYPE_SHARED) {\n        XYLog(\"shared key authentication is not supported!\\n\");\n        return;\n    }\n    \n    if (authtype_upper == APPLE80211_AUTHTYPE_NONE && authtype_lower == APPLE80211_AUTHTYPE_OPEN) { // Open or WEP Open System\n        if (key_len > 0) {\n            XYLog(\"%s %d\\n\", __FUNCTION__, __LINE__);\n            nwkey.i_wepon = IEEE80211_NWKEY_WEP;\n            nwkey.i_defkid = key_index + 1;\n            nwkey.i_key[key_index].i_keylen = (int)key_len;\n            nwkey.i_key[key_index].i_keydat = key;\n            ieee80211_ioctl_setnwkeys(ic, &nwkey);\n        }\n    }\n}\n\nvoid AirportItlwm::setPTK(const u_int8_t *key, size_t key_len) {\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    struct ieee80211_node\t* ni = ic->ic_bss;\n    struct ieee80211_key *k;\n    int keylen;\n    \n    ni->ni_rsn_supp_state = RNSA_SUPP_PTKDONE;\n    \n    if (ni->ni_rsncipher != IEEE80211_CIPHER_USEGROUP) {\n        u_int64_t prsc;\n        \n        /* check that key length matches that of pairwise cipher */\n        keylen = ieee80211_cipher_keylen(ni->ni_rsncipher);\n        if (key_len != keylen) {\n            XYLog(\"PTK length mismatch. expected %d, got %zu\\n\", keylen, key_len);\n            return;\n        }\n        prsc = /*(gtk == NULL) ? LE_READ_6(key->rsc) :*/ 0;\n        \n        /* map PTK to 802.11 key */\n        k = &ni->ni_pairwise_key;\n        memset(k, 0, sizeof(*k));\n        k->k_cipher = ni->ni_rsncipher;\n        k->k_rsc[0] = prsc;\n        k->k_len = keylen;\n        memcpy(k->k_key, key, k->k_len);\n        /* install the PTK */\n        if ((*ic->ic_set_key)(ic, ni, k) != 0) {\n            XYLog(\"setting PTK failed\\n\");\n            return;\n        }\n        else\n            XYLog(\"setting PTK successfully\\n\");\n        ni->ni_flags &= ~IEEE80211_NODE_RSN_NEW_PTK;\n        ni->ni_flags &= ~IEEE80211_NODE_TXRXPROT;\n        ni->ni_flags |= IEEE80211_NODE_RXPROT;\n    } else if (ni->ni_rsncipher != IEEE80211_CIPHER_USEGROUP)\n        XYLog(\"%s: unexpected pairwise key update received from %s\\n\",\n              ic->ic_if.if_xname, ether_sprintf(ni->ni_macaddr));\n}\n\nvoid AirportItlwm::setGTK(const u_int8_t *gtk, size_t key_len, u_int8_t kid, u_int8_t *rsc) {\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    struct ieee80211_node\t* ni = ic->ic_bss;\n    struct ieee80211_key *k;\n    int keylen;\n    \n    if (gtk != NULL) {\n        /* check that key length matches that of group cipher */\n        keylen = ieee80211_cipher_keylen(ni->ni_rsngroupcipher);\n        if (key_len != keylen) {\n            XYLog(\"GTK length mismatch. expected %d, got %zu\\n\", keylen, key_len);\n            return;\n        }\n        /* map GTK to 802.11 key */\n        k = &ic->ic_nw_keys[kid];\n        if (k->k_cipher == IEEE80211_CIPHER_NONE || k->k_len != keylen || memcmp(k->k_key, gtk, keylen) != 0) {\n            memset(k, 0, sizeof(*k));\n            k->k_id = kid;    /* 0-3 */\n            k->k_cipher = ni->ni_rsngroupcipher;\n            k->k_flags = IEEE80211_KEY_GROUP;\n            //if (gtk[6] & (1 << 2))\n            //  k->k_flags |= IEEE80211_KEY_TX;\n            k->k_rsc[0] = LE_READ_6(rsc);\n            k->k_len = keylen;\n            memcpy(k->k_key, gtk, k->k_len);\n            /* install the GTK */\n            if ((*ic->ic_set_key)(ic, ni, k) != 0) {\n                XYLog(\"setting GTK failed\\n\");\n                return;\n            }\n            else\n                XYLog(\"setting GTK successfully\\n\");\n        }\n    }\n    \n    if (true) {\n        ni->ni_flags |= IEEE80211_NODE_TXRXPROT;\n#ifndef IEEE80211_STA_ONLY\n        if (ic->ic_opmode != IEEE80211_M_IBSS ||\n            ++ni->ni_key_count == 2)\n#endif\n        {\n            XYLog(\"marking port %s valid\\n\",\n                  ether_sprintf(ni->ni_macaddr));\n            ni->ni_port_valid = 1;\n            ieee80211_set_link_state(ic, LINK_STATE_UP);\n            ni->ni_assoc_fail = 0;\n            if (ic->ic_opmode == IEEE80211_M_STA)\n                ic->ic_rsngroupcipher = ni->ni_rsngroupcipher;\n        }\n    }\n}\n\n\nbool AirportItlwm::\ncreateMediumTables(const IONetworkMedium **primary)\n{\n    IONetworkMedium    *medium;\n    \n    OSDictionary *mediumDict = OSDictionary::withCapacity(1);\n    if (mediumDict == NULL) {\n        XYLog(\"Cannot allocate OSDictionary\\n\");\n        return false;\n    }\n    \n    medium = IONetworkMedium::medium(0x80, 11000000);\n    IONetworkMedium::addMedium(mediumDict, medium);\n    medium->release();\n    if (primary) {\n        *primary = medium;\n    }\n    \n    bool result = publishMediumDictionary(mediumDict);\n    if (!result)\n        XYLog(\"Cannot publish medium dictionary!\\n\");\n\n    mediumDict->release();\n    return result;\n}\n\nbool AirportItlwm::start(IOService *provider)\n{\n    int boot_value = 0;\n    if (!super::start(provider)) {\n        return false;\n    }\n    if (!serviceMatching(\"AppleSMC\")) {\n        super::stop(provider);\n        XYLog(\"No matching AppleSMC dictionary, failing\\n\");\n        return false;\n    }\n    pciNub = OSDynamicCast(IOPCIDevice, provider);\n    if (!pciNub) {\n        super::stop(provider);\n        return false;\n    }\n    pciNub->setBusMasterEnable(true);\n    pciNub->setIOEnable(true);\n    pciNub->setMemoryEnable(true);\n    pciNub->configWrite8(0x41, 0);\n    if (pciNub->requestPowerDomainState(kIOPMPowerOn,\n                                        (IOPowerConnection *) getParentEntry(gIOPowerPlane), IOPMLowestState) != IOPMNoErr) {\n        super::stop(provider);\n        return false;\n    }\n    if (initPCIPowerManagment(pciNub) == false) {\n        super::stop(pciNub);\n        return false;\n    }\n    if (_fWorkloop == NULL) {\n        XYLog(\"No _fWorkloop!!\\n\");\n        super::stop(pciNub);\n        releaseAll();\n        return false;\n    }\n    _fCommandGate = IOCommandGate::commandGate(this, (IOCommandGate::Action)AirportItlwm::tsleepHandler);\n    if (_fCommandGate == 0) {\n        XYLog(\"No command gate!!\\n\");\n        super::stop(pciNub);\n        releaseAll();\n        return false;\n    }\n    _fWorkloop->addEventSource(_fCommandGate);\n    const IONetworkMedium *primaryMedium;\n    if (!createMediumTables(&primaryMedium) ||\n        !setCurrentMedium(primaryMedium) || !setSelectedMedium(primaryMedium)) {\n        XYLog(\"setup medium fail\\n\");\n        releaseAll();\n        return false;\n    }\n    fHalService->initWithController(this, _fWorkloop, _fCommandGate);\n    fHalService->get80211Controller()->ic_event_handler = eventHandler;\n    \n    if (PE_parse_boot_argn(\"-novht\", &boot_value, sizeof(boot_value)))\n        fHalService->get80211Controller()->ic_userflags |= IEEE80211_F_NOVHT;\n    if (PE_parse_boot_argn(\"-noht40\", &boot_value, sizeof(boot_value)))\n        fHalService->get80211Controller()->ic_userflags |= IEEE80211_F_NOHT40;\n    \n    if (!fHalService->attach(pciNub)) {\n        XYLog(\"attach fail\\n\");\n        super::stop(pciNub);\n        releaseAll();\n        return false;\n    }\n    if (!attachInterface((IONetworkInterface **)&fNetIf, true)) {\n        XYLog(\"attach to interface fail\\n\");\n        fHalService->detach(pciNub);\n        super::stop(pciNub);\n        releaseAll();\n        return false;\n    }\n    fWatchdogWorkLoop = IOWorkLoop::workLoop();\n    if (fWatchdogWorkLoop == NULL) {\n        XYLog(\"init watchdog workloop fail\\n\");\n        fHalService->detach(pciNub);\n        super::stop(pciNub);\n        releaseAll();\n        return false;\n    }\n    watchdogTimer = IOTimerEventSource::timerEventSource(this, OSMemberFunctionCast(IOTimerEventSource::Action, this, &AirportItlwm::watchdogAction));\n    if (!watchdogTimer) {\n        XYLog(\"init watchdog fail\\n\");\n        fHalService->detach(pciNub);\n        super::stop(pciNub);\n        releaseAll();\n        return false;\n    }\n    fWatchdogWorkLoop->addEventSource(watchdogTimer);\n    scanSource = IOTimerEventSource::timerEventSource(this, &fakeScanDone);\n    _fWorkloop->addEventSource(scanSource);\n    scanSource->enable();\n    setLinkStatus(kIONetworkLinkValid);\n    if (TAILQ_EMPTY(&fHalService->get80211Controller()->ic_ess))\n        fHalService->get80211Controller()->ic_flags |= IEEE80211_F_AUTO_JOIN;\n    registerService();\n    fNetIf->registerService();\n    return true;\n}\n\nvoid AirportItlwm::watchdogAction(IOTimerEventSource *timer)\n{\n    struct _ifnet *ifp = &fHalService->get80211Controller()->ic_ac.ac_if;\n    (*ifp->if_watchdog)(ifp);\n    watchdogTimer->setTimeoutMS(kWatchDogTimerPeriod);\n}\n\nvoid AirportItlwm::fakeScanDone(OSObject *owner, IOTimerEventSource *sender)\n{\n    AirportItlwm *that = (AirportItlwm *)owner;\n    that->getNetworkInterface()->postMessage(APPLE80211_M_SCAN_DONE);\n}\n\nconst OSString * AirportItlwm::newVendorString() const\n{\n    return OSString::withCString(\"Apple\");\n}\n\nconst OSString * AirportItlwm::newModelString() const\n{\n    return OSString::withCString(fHalService->getDriverInfo()->getFirmwareName());\n}\n\nbool AirportItlwm::initPCIPowerManagment(IOPCIDevice *provider)\n{\n    UInt16 reg16;\n\n    reg16 = provider->configRead16(kIOPCIConfigCommand);\n\n    reg16 |= ( kIOPCICommandBusMaster       |\n               kIOPCICommandMemorySpace     |\n               kIOPCICommandMemWrInvalidate );\n\n    reg16 &= ~kIOPCICommandIOSpace;  // disable I/O space\n\n    provider->configWrite16( kIOPCIConfigCommand, reg16 );\n    provider->findPCICapability(kIOPCIPowerManagementCapability,\n                                &pmPCICapPtr);\n    if (pmPCICapPtr) {\n        UInt16 pciPMCReg = provider->configRead32( pmPCICapPtr ) >> 16;\n        if (pciPMCReg & kPCIPMCPMESupportFromD3Cold)\n            magicPacketSupported = true;\n        provider->configWrite16((pmPCICapPtr + 4), 0x8000 );\n        IOSleep(10);\n    }\n    return true;\n}\n\nbool AirportItlwm::createWorkLoop()\n{\n    _fWorkloop = IO80211WorkLoop::workLoop();\n    return _fWorkloop != 0;\n}\n\nIOWorkLoop *AirportItlwm::getWorkLoop() const\n{\n    return _fWorkloop;\n}\n\nIOReturn AirportItlwm::selectMedium(const IONetworkMedium *medium)\n{\n    setSelectedMedium(medium);\n    return kIOReturnSuccess;\n}\n\nvoid AirportItlwm::stop(IOService *provider)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct _ifnet *ifp = &fHalService->get80211Controller()->ic_ac.ac_if;\n    super::stop(provider);\n    disableAdapter(fNetIf);\n    setLinkStatus(kIONetworkLinkValid);\n    fHalService->detach(pciNub);\n    ether_ifdetach(ifp);\n    detachInterface(fNetIf, true);\n    OSSafeReleaseNULL(fNetIf);\n    releaseAll();\n}\n\nbool AirportItlwm::\nsetLinkStatus(UInt32 status, const IONetworkMedium * activeMedium, UInt64 speed, OSData * data)\n{\n    struct _ifnet *ifq = &fHalService->get80211Controller()->ic_ac.ac_if;\n    if (status == currentStatus) {\n        return true;\n    }\n    bool ret = super::setLinkStatus(status, activeMedium, speed, data);\n    currentStatus = status;\n    if (fNetIf) {\n        if (status & kIONetworkLinkActive) {\n#ifdef __PRIVATE_SPI__\n            fNetIf->startOutputThread();\n#endif\n            getCommandGate()->runAction(setLinkStateGated, (void *)kIO80211NetworkLinkUp, (void *)0);\n            fNetIf->setLinkQualityMetric(100);\n        } else if (!(status & kIONetworkLinkNoNetworkChange)) {\n#ifdef __PRIVATE_SPI__\n            fNetIf->stopOutputThread();\n            fNetIf->flushOutputQueue();\n#endif\n            ifq_flush(&ifq->if_snd);\n            mq_purge(&fHalService->get80211Controller()->ic_mgtq);\n            getCommandGate()->runAction(setLinkStateGated, (void *)kIO80211NetworkLinkDown, (void *)fHalService->get80211Controller()->ic_deauth_reason);\n        }\n    }\n    return ret;\n}\n\nIOReturn AirportItlwm::\nsetLinkStateGated(OSObject *target, void *arg0, void *arg1, void *arg2, void *arg3)\n{\n    AirportItlwm *that = OSDynamicCast(AirportItlwm, target);\n    IOReturn ret = that->getNetworkInterface()->setLinkState((IO80211LinkState)(uint64_t)arg0, (unsigned int)(uint64_t)arg1);\n    if (that->fAWDLInterface) {\n#if __IO80211_TARGET >= __MAC_13_0\n        that->fAWDLInterface->setEnabledBySystem(true);\n#endif\n        that->fAWDLInterface->setLinkState((IO80211LinkState)(uint64_t)arg0, (unsigned int)(uint64_t)arg1);\n    }\n    return ret;\n}\n\nvoid AirportItlwm::releaseAll()\n{\n    if (fHalService) {\n        fHalService->release();\n        fHalService = NULL;\n    }\n    if (_fWorkloop) {\n        if (_fCommandGate) {\n//            _fCommandGate->disable();\n            _fWorkloop->removeEventSource(_fCommandGate);\n            _fCommandGate->release();\n            _fCommandGate = NULL;\n        }\n        if (scanSource) {\n            scanSource->cancelTimeout();\n            scanSource->disable();\n            _fWorkloop->removeEventSource(scanSource);\n            scanSource->release();\n            scanSource = NULL;\n        }\n        if (fWatchdogWorkLoop && watchdogTimer) {\n            watchdogTimer->cancelTimeout();\n            fWatchdogWorkLoop->removeEventSource(watchdogTimer);\n            watchdogTimer->release();\n            watchdogTimer = NULL;\n            fWatchdogWorkLoop->release();\n            fWatchdogWorkLoop = NULL;\n        }\n        _fWorkloop->release();\n        _fWorkloop = NULL;\n    }\n    unregistPM();\n}\n\nvoid AirportItlwm::free()\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    if (fHalService != NULL) {\n        fHalService->release();\n        fHalService = NULL;\n    }\n    if (syncFrameTemplate != NULL && syncFrameTemplateLength > 0) {\n        IOFree(syncFrameTemplate, syncFrameTemplateLength);\n        syncFrameTemplateLength = 0;\n        syncFrameTemplate = NULL;\n    }\n    if (roamProfile != NULL) {\n        IOFree(roamProfile, sizeof(struct apple80211_roam_profile_band_data));\n        roamProfile = NULL;\n    }\n    if (btcProfile != NULL) {\n        IOFree(btcProfile, sizeof(struct apple80211_btc_profiles_data));\n        btcProfile = NULL;\n    }\n    super::free();\n}\n\nIOReturn AirportItlwm::enable(IONetworkInterface *netif)\n{\n    XYLog(\"%s\\n\", __PRETTY_FUNCTION__);\n    super::enable(netif);\n    _fCommandGate->enable();\n    if (power_state)\n        enableAdapter(netif);\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::disable(IONetworkInterface *netif)\n{\n    XYLog(\"%s\\n\", __PRETTY_FUNCTION__);\n    super::disable(netif);\n    setLinkStatus(kIONetworkLinkValid);\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::enableAdapter(IONetworkInterface *netif)\n{\n    fHalService->enable(netif);\n    watchdogTimer->setTimeoutMS(kWatchDogTimerPeriod);\n    watchdogTimer->enable();\n    return kIOReturnSuccess;\n}\n\nvoid AirportItlwm::disableAdapter(IONetworkInterface *netif)\n{\n    watchdogTimer->cancelTimeout();\n    watchdogTimer->disable();\n    fHalService->disable(netif);\n}\n\nIOReturn AirportItlwm::getHardwareAddress(IOEthernetAddress *addrP)\n{\n    if (IEEE80211_ADDR_EQ(etheranyaddr, fHalService->get80211Controller()->ic_myaddr))\n        return kIOReturnError;\n    else {\n        IEEE80211_ADDR_COPY(addrP, fHalService->get80211Controller()->ic_myaddr);\n        return kIOReturnSuccess;\n    }\n}\n\nIOReturn AirportItlwm::setHardwareAddress(const IOEthernetAddress *addrP)\n{\n    if (!fNetIf || !addrP)\n        return kIOReturnError;\n    if_setlladdr(&fHalService->get80211Controller()->ic_ac.ac_if, addrP->bytes);\n    if (fHalService->get80211Controller()->ic_state > IEEE80211_S_INIT) {\n        fHalService->disable(fNetIf);\n        fHalService->enable(fNetIf);\n    }\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::getHardwareAddressForInterface(\n                                               IO80211Interface *netif, IOEthernetAddress *addr)\n{\n    return getHardwareAddress(addr);\n}\n\n#ifdef __PRIVATE_SPI__\nIOReturn AirportItlwm::outputStart(IONetworkInterface *interface, IOOptionBits options)\n{\n    struct _ifnet *ifp = &fHalService->get80211Controller()->ic_ac.ac_if;\n    mbuf_t m = NULL;\n    if (ifq_is_oactive(&ifp->if_snd))\n        return kIOReturnNoResources;\n    while (kIOReturnSuccess == interface->dequeueOutputPackets(1, &m)) {\n        if (outputPacket(m, NULL)!= kIOReturnOutputSuccess ||\n            ifq_is_oactive(&ifp->if_snd))\n            return kIOReturnNoResources;\n    }\n    return kIOReturnSuccess;\n}\n#endif\n\nUInt32 AirportItlwm::outputPacket(mbuf_t m, void *param)\n{\n//    XYLog(\"%s\\n\", __FUNCTION__);\n    IOReturn ret = kIOReturnOutputSuccess;\n    struct _ifnet *ifp = &fHalService->get80211Controller()->ic_ac.ac_if;\n    \n    if (fHalService->get80211Controller()->ic_state != IEEE80211_S_RUN || ifp->if_snd.queue == NULL) {\n        if (m && mbuf_type(m) != MBUF_TYPE_FREE)\n            freePacket(m);\n        return kIOReturnOutputDropped;\n    }\n    if (m == NULL) {\n        XYLog(\"%s m==NULL!!\\n\", __FUNCTION__);\n        ifp->netStat->outputErrors++;\n        ret = kIOReturnOutputDropped;\n    }\n    if (!(mbuf_flags(m) & MBUF_PKTHDR) ){\n        XYLog(\"%s pkthdr is NULL!!\\n\", __FUNCTION__);\n        ifp->netStat->outputErrors++;\n        freePacket(m);\n        ret = kIOReturnOutputDropped;\n    }\n    if (mbuf_type(m) == MBUF_TYPE_FREE) {\n        XYLog(\"%s mbuf is FREE!!\\n\", __FUNCTION__);\n        ifp->netStat->outputErrors++;\n        ret = kIOReturnOutputDropped;\n    }\n    if (!ifp->if_snd.queue->lockEnqueue(m)) {\n        freePacket(m);\n        ret = kIOReturnOutputDropped;\n    }\n    (*ifp->if_start)(ifp);\n    return ret;\n}\n\nUInt32 AirportItlwm::getFeatures() const\n{\n    return fHalService->getDriverInfo()->supportedFeatures();\n}\n\nIOReturn AirportItlwm::setPromiscuousMode(IOEnetPromiscuousMode mode)\n{\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::setMulticastMode(IOEnetMulticastMode mode)\n{\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::setMulticastList(IOEthernetAddress* addr, UInt32 len)\n{\n    return fHalService->getDriverController()->setMulticastList(addr, len);\n}\n\nSInt32 AirportItlwm::monitorModeSetEnabled(\n                                    IO80211Interface *interface, bool enabled, UInt32 dlt)\n{\n    return kIOReturnSuccess;\n}\n\nbool AirportItlwm::\nuseAppleRSNSupplicant(IO80211Interface *interface)\n{\n#ifdef USE_APPLE_SUPPLICANT\n    return true;\n#else\n    return false;\n#endif\n}\n\nIOReturn AirportItlwm::getPacketFilters(const OSSymbol *group, UInt32 *filters) const\n{\n    IOReturn    rtn = kIOReturnSuccess;\n    if (group == gIOEthernetWakeOnLANFilterGroup && magicPacketSupported)\n        *filters = kIOEthernetWakeOnMagicPacket;\n    else if (group == gIONetworkFilterGroup)\n        *filters = kIOPacketFilterMulticast | kIOPacketFilterPromiscuous;\n    else\n        rtn = IOEthernetController::getPacketFilters(group, filters);\n    return rtn;\n}\n\nIOReturn AirportItlwm::\ntsleepHandler(OSObject* owner, void* arg0, void* arg1, void* arg2, void* arg3)\n{\n    AirportItlwm* dev = OSDynamicCast(AirportItlwm, owner);\n    if (dev == 0)\n        return kIOReturnError;\n    \n    if (arg1 == 0) {\n        if (_fCommandGate->commandSleep(arg0, THREAD_INTERRUPTIBLE) == THREAD_AWAKENED)\n            return kIOReturnSuccess;\n        else\n            return kIOReturnTimeout;\n    } else {\n        AbsoluteTime deadline;\n        clock_interval_to_deadline((*(int*)arg1), kNanosecondScale, reinterpret_cast<uint64_t*> (&deadline));\n        if (_fCommandGate->commandSleep(arg0, deadline, THREAD_INTERRUPTIBLE) == THREAD_AWAKENED)\n            return kIOReturnSuccess;\n        else\n            return kIOReturnTimeout;\n    }\n}\n\nstatic IOPMPowerState powerStateArray[kPowerStateCount] =\n{\n    {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},\n    {1, kIOPMDeviceUsable, kIOPMPowerOn, kIOPMPowerOn, 0, 0, 0, 0, 0, 0, 0, 0}\n};\n\nvoid AirportItlwm::unregistPM()\n{\n    if (powerOffThreadCall) {\n        thread_call_free(powerOffThreadCall);\n        powerOffThreadCall = NULL;\n    }\n    if (powerOnThreadCall) {\n        thread_call_free(powerOnThreadCall);\n        powerOnThreadCall = NULL;\n    }\n}\n\nIOReturn AirportItlwm::setPowerState(unsigned long powerStateOrdinal, IOService *policyMaker)\n{\n    IOReturn result = IOPMAckImplied;\n    \n    if (pmPowerState == powerStateOrdinal)\n        return result;\n    switch (powerStateOrdinal) {\n        case kPowerStateOff:\n            if (powerOffThreadCall) {\n                retain();\n                if (thread_call_enter(powerOffThreadCall))\n                    release();\n                result = 5000000;\n            }\n            break;\n        case kPowerStateOn:\n            if (powerOnThreadCall) {\n                retain();\n                if (thread_call_enter(powerOnThreadCall))\n                    release();\n                result = 5000000;\n            }\n            break;\n            \n        default:\n            break;\n    }\n    return result;\n}\n\nIOReturn AirportItlwm::setWakeOnMagicPacket(bool active)\n{\n    magicPacketEnabled = active;\n    return kIOReturnSuccess;\n}\n\nstatic void handleSetPowerStateOff(thread_call_param_t param0,\n                             thread_call_param_t param1)\n{\n    AirportItlwm *self = (AirportItlwm *)param0;\n\n    if (param1 == 0)\n    {\n        self->getCommandGate()->runAction((IOCommandGate::Action)\n                                           handleSetPowerStateOff,\n                                           (void *) 1);\n    }\n    else\n    {\n        self->setPowerStateOff();\n        self->release();\n    }\n}\n\nstatic void handleSetPowerStateOn(thread_call_param_t param0,\n                            thread_call_param_t param1)\n{\n    AirportItlwm *self = (AirportItlwm *) param0;\n\n    if (param1 == 0)\n    {\n        self->getCommandGate()->runAction((IOCommandGate::Action)\n                                           handleSetPowerStateOn,\n                                           (void *) 1);\n    }\n    else\n    {\n        self->setPowerStateOn();\n        self->release();\n    }\n}\n\nIOReturn AirportItlwm::registerWithPolicyMaker(IOService *policyMaker)\n{\n    IOReturn ret;\n    \n    pmPowerState = kPowerStateOn;\n    pmPolicyMaker = policyMaker;\n    \n    powerOffThreadCall = thread_call_allocate(\n                                            (thread_call_func_t)handleSetPowerStateOff,\n                                            (thread_call_param_t)this);\n    powerOnThreadCall  = thread_call_allocate(\n                                            (thread_call_func_t)handleSetPowerStateOn,\n                                              (thread_call_param_t)this);\n    ret = pmPolicyMaker->registerPowerDriver(this,\n                                             powerStateArray,\n                                             kPowerStateCount);\n    return ret;\n}\n\nvoid AirportItlwm::setPowerStateOff()\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    pmPowerState = kPowerStateOff;\n    disableAdapter(fNetIf);\n    pmPolicyMaker->acknowledgeSetPowerState();\n}\n\nvoid AirportItlwm::setPowerStateOn()\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    pmPowerState = kPowerStateOn;\n    pmPolicyMaker->acknowledgeSetPowerState();\n}\n\nint AirportItlwm::\noutputRaw80211Packet(IO80211Interface *interface, mbuf_t m)\n{\n    XYLog(\"%s len=%zu\\n\", __FUNCTION__, mbuf_len(m));\n    freePacket(m);\n    return kIOReturnOutputDropped;\n}\n\nUInt32 AirportItlwm::\nhardwareOutputQueueDepth(IO80211Interface *interface)\n{\n    return 0;\n}\n\nSInt32 AirportItlwm::\nperformCountryCodeOperation(IO80211Interface *interface, IO80211CountryCodeOp op)\n{\n    return 0;\n}\n\nSInt32 AirportItlwm::\nstopDMA()\n{\n    if (fNetIf)\n        disable(fNetIf);\n    return 0;\n}\n\nSInt32 AirportItlwm::\nenableFeature(IO80211FeatureCode code, void *data)\n{\n    if (code == kIO80211Feature80211n) {\n        return 0;\n    }\n    return 102;\n}\n\nint AirportItlwm::\noutputActionFrame(OSObject *object, mbuf_t m)\n{\n    XYLog(\"%s len=%zu\\n\", __FUNCTION__, mbuf_len(m));\n    mbuf_freem(m);\n    return 0;\n}\n\nint AirportItlwm::\nbpfOutput80211Radio(OSObject *object, mbuf_t m)\n{\n    XYLog(\"%s len=%zu\\n\", __FUNCTION__, mbuf_len(m));\n    mbuf_freem(m);\n    return 0;\n}\n\nSInt32 AirportItlwm::\nenableVirtualInterface(IO80211VirtualInterface *interface)\n{\n    XYLog(\"%s interface=%s role=%d\\n\", __FUNCTION__, interface->getBSDName(), interface->getInterfaceRole());\n    SInt32 ret = super::enableVirtualInterface(interface);\n    if (!ret) {\n#if __IO80211_TARGET >= __MAC_13_0\n        interface->setEnabledBySystem(true);\n#endif\n        interface->setLinkState(kIO80211NetworkLinkUp, 0);\n        interface->postMessage(APPLE80211_M_LINK_CHANGED);\n        return kIOReturnSuccess;\n    }\n    return ret;\n}\n\nSInt32 AirportItlwm::\ndisableVirtualInterface(IO80211VirtualInterface *interface)\n{\n    XYLog(\"%s interface=%s role=%d\\n\", __FUNCTION__, interface->getBSDName(), interface->getInterfaceRole());\n    SInt32 ret = super::disableVirtualInterface(interface);\n    if (!ret) {\n        interface->setLinkState(kIO80211NetworkLinkDown, 0);\n        interface->postMessage(APPLE80211_M_LINK_CHANGED);\n        return kIOReturnSuccess;\n    }\n    return ret;\n}\n\nIO80211VirtualInterface *AirportItlwm::\ncreateVirtualInterface(ether_addr *ether, UInt role)\n{\n    if (role - 1 > 3)\n        return super::createVirtualInterface(ether, role);\n    IO80211VirtualInterface *inf = new IO80211VirtualInterface;\n    if (inf) {\n        if (inf->init(this, ether, role, role == APPLE80211_VIF_AWDL ? \"awdl\" : \"p2p\"))\n            XYLog(\"%s role=%d succeed\\n\", __FUNCTION__, role);\n        else {\n            inf->release();\n            return NULL;\n        }\n    }\n    return inf;\n}\n\nint AirportItlwm::\nbpfOutputPacket(OSObject *object, UInt dltType, mbuf_t m)\n{\n    XYLog(\"%s dltType=%d\\n\", __FUNCTION__, dltType);\n    if (dltType == DLT_IEEE802_11_RADIO || dltType == DLT_IEEE802_11)\n        return bpfOutput80211Radio(object, m);\n    if (dltType == DLT_RAW)\n        return outputActionFrame(object, m);\n    mbuf_freem(m);\n    return 1;\n}\n\nvoid AirportItlwm::\nrequestPacketTx(void *object, UInt )\n{\n    UInt32 ret;\n    struct TxPacketRequest request;\n    if (object == NULL)\n        return;\n    IO80211VirtualInterface *interface = OSDynamicCast(IO80211VirtualInterface, (OSObject *)object);\n    if (interface) {\n        memset(&request, 0, sizeof(request));\n        if (interface->getInterfaceRole() == APPLE80211_VIF_AWDL) {\n//            interface->dequeueTxPackets(&request);\n//\n//            ret = outputPacket(NULL, interface);\n//            if (ret == kIOReturnSuccess) {\n//                interface->reportTransmitStatus(NULL, ret, NULL);\n//            }\n        }\n    }\n}\n"
  },
  {
    "path": "AirportItlwm/AirportItlwm.hpp",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n#include \"Apple80211.h\"\n\n#include \"IOKit/network/IOGatedOutputQueue.h\"\n#include <libkern/c++/OSString.h>\n#include <IOKit/IOService.h>\n#include <IOKit/pci/IOPCIDevice.h>\n#include <IOKit/IOLib.h>\n#include <libkern/OSKextLib.h>\n#include <libkern/c++/OSMetaClass.h>\n#include <IOKit/IOFilterInterruptEventSource.h>\n\n#include \"ItlIwm.hpp\"\n#include \"ItlIwx.hpp\"\n#include \"ItlIwn.hpp\"\n\n#include \"AirportItlwmInterface.hpp\"\n\nenum\n{\n    kPowerStateOff = 0,\n    kPowerStateOn,\n    kPowerStateCount\n};\n\n#define kWatchDogTimerPeriod 1000\n\nclass AirportItlwm : public IO80211Controller {\n    OSDeclareDefaultStructors(AirportItlwm)\n#define IOCTL(REQ_TYPE, REQ, DATA_TYPE) \\\nif (REQ_TYPE == SIOCGA80211) { \\\nret = get##REQ(interface, (struct DATA_TYPE* )data); \\\n} else { \\\nret = set##REQ(interface, (struct DATA_TYPE* )data); \\\n}\n    \n#define IOCTL_GET(REQ_TYPE, REQ, DATA_TYPE) \\\nif (REQ_TYPE == SIOCGA80211) { \\\nret = get##REQ(interface, (struct DATA_TYPE* )data); \\\n}\n#define IOCTL_SET(REQ_TYPE, REQ, DATA_TYPE) \\\nif (REQ_TYPE == SIOCSA80211) { \\\nret = set##REQ(interface, (struct DATA_TYPE* )data); \\\n}\n#define FUNC_IOCTL(REQ, DATA_TYPE) \\\nFUNC_IOCTL_GET(REQ, DATA_TYPE) \\\nFUNC_IOCTL_SET(REQ, DATA_TYPE)\n#define FUNC_IOCTL_GET(REQ, DATA_TYPE) \\\nIOReturn get##REQ(OSObject *object, struct DATA_TYPE *data);\n#define FUNC_IOCTL_SET(REQ, DATA_TYPE) \\\nIOReturn set##REQ(OSObject *object, struct DATA_TYPE *data);\n    \npublic:\n    virtual bool init(OSDictionary *properties) override;\n    virtual void free() override;\n    virtual IOService* probe(IOService* provider, SInt32* score) override;\n    virtual bool start(IOService *provider) override;\n    virtual void stop(IOService *provider) override;\n    virtual IOReturn getHardwareAddress(IOEthernetAddress* addrP) override;\n    virtual IOReturn setHardwareAddress(const IOEthernetAddress * addrP) override;\n    virtual IOReturn enable(IONetworkInterface *netif) override;\n    virtual IOReturn disable(IONetworkInterface *netif) override;\n    virtual UInt32 outputPacket(mbuf_t, void * param) override;\n    virtual IOReturn setPromiscuousMode(IOEnetPromiscuousMode mode) override;\n    virtual IOReturn setMulticastMode(IOEnetMulticastMode mode) override;\n    virtual IOReturn setMulticastList(IOEthernetAddress* addr, UInt32 len) override;\n    virtual bool configureInterface(IONetworkInterface *netif) override;\n    virtual bool createWorkLoop() override;\n    virtual IOWorkLoop* getWorkLoop() const override;\n    virtual const OSString * newVendorString() const override;\n    virtual const OSString * newModelString() const override;\n    virtual IONetworkInterface * createInterface() override;\n    virtual bool setLinkStatus(\n                               UInt32                  status,\n                               const IONetworkMedium * activeMedium = 0,\n                               UInt64                  speed        = 0,\n                               OSData *                data         = 0) override;\n    \n    static IOReturn setLinkStateGated(OSObject *target, void *arg0, void *arg1, void *arg2, void *arg3);\n    \n#ifdef __PRIVATE_SPI__\n    virtual IOReturn outputStart(IONetworkInterface *interface, IOOptionBits options) override;\n#endif\n    \n    void releaseAll();\n    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);\n    void setPTK(const u_int8_t *key, size_t key_len);\n    void setGTK(const u_int8_t *key, size_t key_len, u_int8_t kid, u_int8_t *rsc);\n    void watchdogAction(IOTimerEventSource *timer);\n    bool initPCIPowerManagment(IOPCIDevice *provider);\n    static IOReturn tsleepHandler(OSObject* owner, void* arg0 = 0, void* arg1 = 0, void* arg2 = 0, void* arg3 = 0);\n    static void eventHandler(struct ieee80211com *, int, void *);\n    IOReturn enableAdapter(IONetworkInterface *netif);\n    void disableAdapter(IONetworkInterface *netif);\n    \n    //IO80211\n    virtual IOReturn getHardwareAddressForInterface(IO80211Interface* netif,\n                                            IOEthernetAddress* addr) override;\n    virtual SInt32 monitorModeSetEnabled(IO80211Interface* interface, bool enabled,\n                                 UInt32 dlt) override;\n    virtual SInt32 apple80211Request(unsigned int request_type, int request_number,\n                             IO80211Interface* interface, void* data) override;\n    //scan\n    static void fakeScanDone(OSObject *owner, IOTimerEventSource *sender);\n    //authentication\n    virtual bool useAppleRSNSupplicant(IO80211Interface *interface) override;\n    virtual int outputRaw80211Packet(IO80211Interface *interface, mbuf_t m) override;\n    //virtual interface\n    virtual SInt32 enableVirtualInterface(IO80211VirtualInterface *interface) override;\n    virtual SInt32 disableVirtualInterface(IO80211VirtualInterface *interface) override;\n    virtual IO80211VirtualInterface* createVirtualInterface(ether_addr *eth,uint role) override;\n    virtual SInt32 apple80211VirtualRequest(uint request_type, int request_number,IO80211VirtualInterface *interface,void *data) override;\n    virtual SInt32 stopDMA() override;\n    virtual UInt32 hardwareOutputQueueDepth(IO80211Interface* interface) override;\n    virtual SInt32 performCountryCodeOperation(IO80211Interface* interface, IO80211CountryCodeOp op) override;\n    virtual SInt32 enableFeature(IO80211FeatureCode code, void* data) override;\n    virtual void requestPacketTx(void*, UInt) override;\n    virtual int bpfOutputPacket(OSObject *,UInt,mbuf_t) override;\n    int outputActionFrame(OSObject *, mbuf_t m);\n    int bpfOutput80211Radio(OSObject *, mbuf_t m);\n    \n    \n    \n    //AirportSTAIOCTL\n    FUNC_IOCTL(SSID, apple80211_ssid_data)\n    FUNC_IOCTL(AUTH_TYPE, apple80211_authtype_data)\n    FUNC_IOCTL(CHANNEL, apple80211_channel_data)\n    FUNC_IOCTL(PROTMODE, apple80211_protmode_data)\n    FUNC_IOCTL_GET(TXPOWER, apple80211_txpower_data)\n    FUNC_IOCTL_GET(RATE, apple80211_rate_data)\n    FUNC_IOCTL(BSSID, apple80211_bssid_data)\n    FUNC_IOCTL_SET(SCAN_REQ, apple80211_scan_data)\n    FUNC_IOCTL_SET(SCAN_REQ_MULTIPLE, apple80211_scan_multiple_data)\n    FUNC_IOCTL_GET(SCAN_RESULT, apple80211_scan_result*)\n    FUNC_IOCTL_GET(CARD_CAPABILITIES, apple80211_capability_data)\n    FUNC_IOCTL_GET(STATE, apple80211_state_data)\n    FUNC_IOCTL_GET(PHY_MODE, apple80211_phymode_data)\n    FUNC_IOCTL_GET(OP_MODE, apple80211_opmode_data)\n    FUNC_IOCTL_GET(RSSI, apple80211_rssi_data)\n    FUNC_IOCTL_GET(NOISE, apple80211_noise_data)\n    FUNC_IOCTL_GET(INT_MIT, apple80211_intmit_data)\n    FUNC_IOCTL(POWER, apple80211_power_data)\n    FUNC_IOCTL_SET(ASSOCIATE, apple80211_assoc_data)\n    FUNC_IOCTL_GET(ASSOCIATE_RESULT, apple80211_assoc_result_data)\n    IOReturn setDISASSOCIATE(OSObject *);\n    FUNC_IOCTL_GET(RATE_SET, apple80211_rate_set_data)\n    FUNC_IOCTL_GET(MCS_INDEX_SET, apple80211_mcs_index_set_data)\n    FUNC_IOCTL_GET(VHT_MCS_INDEX_SET, apple80211_vht_mcs_index_set_data)\n    FUNC_IOCTL(MCS_VHT, apple80211_mcs_vht_data)\n    FUNC_IOCTL_GET(SUPPORTED_CHANNELS, apple80211_sup_channel_data)\n    FUNC_IOCTL_GET(LOCALE, apple80211_locale_data)\n    FUNC_IOCTL(DEAUTH, apple80211_deauth_data)\n    FUNC_IOCTL_GET(TX_ANTENNA, apple80211_antenna_data)\n    FUNC_IOCTL_GET(ANTENNA_DIVERSITY, apple80211_antenna_data)\n    FUNC_IOCTL_GET(DRIVER_VERSION, apple80211_version_data)\n    FUNC_IOCTL_GET(HARDWARE_VERSION, apple80211_version_data)\n    FUNC_IOCTL(RSN_IE, apple80211_rsn_ie_data)\n    FUNC_IOCTL_GET(AP_IE_LIST, apple80211_ap_ie_data)\n    FUNC_IOCTL_GET(LINK_CHANGED_EVENT_DATA, apple80211_link_changed_event_data)\n    FUNC_IOCTL_GET(ASSOCIATION_STATUS, apple80211_assoc_status_data)\n    FUNC_IOCTL(COUNTRY_CODE, apple80211_country_code_data)\n    FUNC_IOCTL_GET(RADIO_INFO, apple80211_radio_info_data)\n    FUNC_IOCTL_GET(MCS, apple80211_mcs_data)\n    FUNC_IOCTL_SET(VIRTUAL_IF_CREATE, apple80211_virt_if_create_data)\n    FUNC_IOCTL_SET(VIRTUAL_IF_DELETE, apple80211_virt_if_delete_data)\n    FUNC_IOCTL_GET(ROAM_THRESH, apple80211_roam_threshold_data)\n    FUNC_IOCTL_GET(POWERSAVE, apple80211_powersave_data)\n    FUNC_IOCTL_SET(CIPHER_KEY, apple80211_key)\n    FUNC_IOCTL_SET(SCANCACHE_CLEAR, apple80211req)\n    FUNC_IOCTL(TX_NSS, apple80211_tx_nss_data)\n    FUNC_IOCTL_GET(NSS, apple80211_nss_data)\n    FUNC_IOCTL_SET(ROAM, apple80211_sta_roam_data);\n    \n    //AirportVirtualIOCTL\n    FUNC_IOCTL(AWDL_PEER_TRAFFIC_REGISTRATION, apple80211_awdl_peer_traffic_registration)\n    FUNC_IOCTL(AWDL_ELECTION_METRIC, apple80211_awdl_election_metric)\n    FUNC_IOCTL(SYNC_ENABLED, apple80211_awdl_sync_enabled)\n    FUNC_IOCTL(SYNC_FRAME_TEMPLATE, apple80211_awdl_sync_frame_template)\n    FUNC_IOCTL_GET(AWDL_HT_CAPABILITY, apple80211_ht_capability)\n    FUNC_IOCTL_GET(AWDL_VHT_CAPABILITY, apple80211_vht_capability)\n    \n    //AWDL\n    FUNC_IOCTL(AWDL_BSSID, apple80211_awdl_bssid)\n    FUNC_IOCTL_GET(CHANNELS_INFO, apple80211_channels_info)\n    FUNC_IOCTL(PEER_CACHE_MAXIMUM_SIZE, apple80211_peer_cache_maximum_size)\n    FUNC_IOCTL(AWDL_ELECTION_ID, apple80211_awdl_election_id)\n    FUNC_IOCTL(AWDL_MASTER_CHANNEL, apple80211_awdl_master_channel)\n    FUNC_IOCTL(AWDL_SECONDARY_MASTER_CHANNEL, apple80211_awdl_secondary_master_channel)\n    FUNC_IOCTL(AWDL_MIN_RATE, apple80211_awdl_min_rate)\n    FUNC_IOCTL(AWDL_ELECTION_RSSI_THRESHOLDS, apple80211_awdl_election_rssi_thresholds)\n    FUNC_IOCTL(AWDL_SYNCHRONIZATION_CHANNEL_SEQUENCE, apple80211_awdl_sync_channel_sequence)\n    FUNC_IOCTL(AWDL_PRESENCE_MODE, apple80211_awdl_presence_mode)\n    FUNC_IOCTL(AWDL_EXTENSION_STATE_MACHINE_PARAMETERS, apple80211_awdl_extension_state_machine_parameter)\n    FUNC_IOCTL(AWDL_SYNC_STATE, apple80211_awdl_sync_state)\n    FUNC_IOCTL(AWDL_SYNC_PARAMS, apple80211_awdl_sync_params)\n    FUNC_IOCTL_GET(AWDL_CAPABILITIES, apple80211_awdl_cap)\n    FUNC_IOCTL(AWDL_AF_TX_MODE, apple80211_awdl_af_tx_mode)\n    FUNC_IOCTL_SET(AWDL_OOB_AUTO_REQUEST, apple80211_awdl_oob_request)\n    FUNC_IOCTL(ROAM_PROFILE, apple80211_roam_profile_band_data)\n    FUNC_IOCTL(WOW_PARAMETERS, apple80211_wow_parameter_data)\n    FUNC_IOCTL(IE, apple80211_ie_data)\n    FUNC_IOCTL_SET(P2P_SCAN, apple80211_scan_data)\n    FUNC_IOCTL_SET(P2P_LISTEN, apple80211_p2p_listen_data)\n    FUNC_IOCTL_SET(P2P_GO_CONF, apple80211_p2p_go_conf_data)\n    FUNC_IOCTL(BTCOEX_PROFILES, apple80211_btc_profiles_data)\n    FUNC_IOCTL(BTCOEX_CONFIG, apple80211_btc_config_data)\n    FUNC_IOCTL(BTCOEX_OPTIONS, apple80211_btc_options_data)\n    FUNC_IOCTL(BTCOEX_MODE, apple80211_btc_mode_data)\n    \n    \n    //-----------------------------------------------------------------------\n    // Power management support.\n    //-----------------------------------------------------------------------\n    virtual IOReturn registerWithPolicyMaker( IOService * policyMaker ) override;\n    virtual IOReturn setPowerState( unsigned long powerStateOrdinal,\n                                    IOService *   policyMaker) override;\n    virtual IOReturn setWakeOnMagicPacket( bool active ) override;\n    void setPowerStateOff(void);\n    void setPowerStateOn(void);\n    void unregistPM();\n    \n    bool createMediumTables(const IONetworkMedium **primary);\n    virtual IOReturn getPacketFilters(const OSSymbol *group, UInt32 *filters) const override;\n    virtual IOReturn selectMedium(const IONetworkMedium *medium) override;\n    virtual UInt32 getFeatures() const override;\n    \npublic:\n    IOInterruptEventSource* fInterrupt;\n    IOTimerEventSource *watchdogTimer;\n    IOPCIDevice *pciNub;\n    IONetworkStats *fpNetStats;\n    AirportItlwmInterface *fNetIf;\n    IOWorkLoop *fWatchdogWorkLoop;\n    ItlHalService *fHalService;\n    \n    //pm\n    thread_call_t powerOnThreadCall;\n    thread_call_t powerOffThreadCall;\n    UInt32 pmPowerState;\n    IOService *pmPolicyMaker;\n    UInt8 pmPCICapPtr;\n    bool magicPacketEnabled;\n    bool magicPacketSupported;\n    \n    //IO80211\n    uint8_t power_state;\n    struct ieee80211_node *fNextNodeToSend;\n    bool fScanResultWrapping;\n    IOTimerEventSource *scanSource;\n    \n    u_int32_t current_authtype_lower;\n    u_int32_t current_authtype_upper;\n    UInt64 currentSpeed;\n    UInt32 currentStatus;\n    bool disassocIsVoluntary;\n    char geo_location_cc[3];\n    \n    IO80211P2PInterface *fP2PDISCInterface;\n    IO80211P2PInterface *fP2PGOInterface;\n    IO80211P2PInterface *fAWDLInterface;\n    \n    //AWDL\n    uint8_t *syncFrameTemplate;\n    uint32_t syncFrameTemplateLength;\n    uint8_t awdlBSSID[6];\n    uint32_t awdlSyncState;\n    uint32_t awdlElectionId;\n    uint32_t awdlPresenceMode;\n    uint16_t awdlMasterChannel;\n    uint16_t awdlSecondaryMasterChannel;\n    uint8_t *roamProfile;\n    struct apple80211_btc_profiles_data *btcProfile;\n    struct apple80211_btc_config_data btcConfig;\n    uint32_t btcMode;\n    uint32_t btcOptions;\n    bool awdlSyncEnable;\n};\n"
  },
  {
    "path": "AirportItlwm/AirportItlwmEthernetInterface.cpp",
    "content": "//\n//  AirportItlwmEthernetInterface.cpp\n//  AirportItlwm-Sonoma\n//\n//  Created by qcwap on 2023/6/27.\n//  Copyright © 2023 钟先耀. All rights reserved.\n//\n\n#include \"AirportItlwmEthernetInterface.hpp\"\n\n#include <sys/_if_ether.h>\n#include <net80211/ieee80211_var.h>\n\n#define super IOEthernetInterface\nOSDefineMetaClassAndStructors(AirportItlwmEthernetInterface, IOEthernetInterface);\n\nbool AirportItlwmEthernetInterface::\ninitWithSkywalkInterfaceAndProvider(IONetworkController *controller, IO80211SkywalkInterface *interface)\n{\n    bool ret = super::init(controller);\n    if (ret)\n        this->interface = interface;\n    this->isAttach = false;\n    return ret;\n}\n\nIOReturn AirportItlwmEthernetInterface::\nattachToDataLinkLayer( IOOptionBits options, void *parameter )\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    char infName[IFNAMSIZ];\n    IOReturn ret = super::attachToDataLinkLayer(options, parameter);\n    if (ret == kIOReturnSuccess && interface) {\n        UInt8 builtIn = 0;\n        IOEthernetAddress addr;\n        interface->setProperty(\"built-in\", OSData::withBytes(&builtIn, sizeof(builtIn)));\n        snprintf(infName, sizeof(infName), \"%s%u\", ifnet_name(getIfnet()), ifnet_unit(getIfnet()));\n        interface->setProperty(\"IOInterfaceName\", OSString::withCString(infName));\n        interface->setProperty(kIOInterfaceUnit, OSNumber::withNumber(ifnet_unit(getIfnet()), 8));\n        interface->setProperty(kIOInterfaceNamePrefix, OSString::withCString(ifnet_name(getIfnet())));\n        if (OSDynamicCast(IOEthernetController, getController())->getHardwareAddress(&addr) == kIOReturnSuccess)\n            setProperty(kIOMACAddress,  (void *) &addr,\n                        kIOEthernetAddressSize);\n        interface->registerService();\n        interface->prepareBSDInterface(getIfnet(), 0);\n//        ret = bpf_attach(getIfnet(), DLT_RAW, 0x48, &AirportItlwmEthernetInterface::bpfOutputPacket, &AirportItlwmEthernetInterface::bpfTap);\n    }\n    isAttach = true;\n    return ret;\n}\n\nvoid AirportItlwmEthernetInterface::\ndetachFromDataLinkLayer(IOOptionBits options, void *parameter)\n{\n    super::detachFromDataLinkLayer(options, parameter);\n    isAttach = false;\n}\n\n/**\n Add another hack to fake that the provider is IOSkywalkNetworkInterface, to avoid skywalkfamily instance cast panic.\n */\nIOService *AirportItlwmEthernetInterface::\ngetProvider() const\n{\n    return isAttach ? this->interface : super::getProvider();\n}\n\nerrno_t AirportItlwmEthernetInterface::\nbpfOutputPacket(ifnet_t interface, u_int32_t data_link_type, mbuf_t packet)\n{\n    XYLog(\"%s data_link_type: %d\\n\", __FUNCTION__, data_link_type);\n    AirportItlwmEthernetInterface *networkInterface = (AirportItlwmEthernetInterface *)ifnet_softc(interface);\n    return networkInterface->enqueueOutputPacket(packet);\n}\n\nerrno_t AirportItlwmEthernetInterface::\nbpfTap(ifnet_t interface, u_int32_t data_link_type, bpf_tap_mode direction)\n{\n    XYLog(\"%s data_link_type: %d direction: %d\\n\", __FUNCTION__, data_link_type, direction);\n    return 0;\n}\n\nbool AirportItlwmEthernetInterface::\nsetLinkState(IO80211LinkState state)\n{\n    if (state == kIO80211NetworkLinkUp) {\n        ifnet_set_flags(getIfnet(), ifnet_flags(getIfnet()) | (IFF_UP | IFF_RUNNING), (IFF_UP | IFF_RUNNING));\n    } else {\n        ifnet_set_flags(getIfnet(), ifnet_flags(getIfnet()) & ~(IFF_UP | IFF_RUNNING), 0);\n    }\n    return true;\n}\n\nextern const char* hexdump(uint8_t *buf, size_t len);\n\nUInt32 AirportItlwmEthernetInterface::\ninputPacket(mbuf_t packet, UInt32 length, IOOptionBits options, void *param)\n{\n    ether_header_t *eh;\n    size_t len = mbuf_len(packet);\n    \n    eh = (ether_header_t *)mbuf_data(packet);\n    if (len >= sizeof(ether_header_t) && eh->ether_type == htons(ETHERTYPE_PAE)) { // EAPOL packet\n        const char* dump = hexdump((uint8_t*)mbuf_data(packet), len);\n        XYLog(\"input EAPOL packet, len: %zu, data: %s\\n\", len, dump ? dump : \"Failed to allocate memory\");\n        if (dump)\n            IOFree((void*)dump, 3 * len + 1);\n    }\n    return IOEthernetInterface::inputPacket(packet, length, options, param);\n}\n"
  },
  {
    "path": "AirportItlwm/AirportItlwmEthernetInterface.hpp",
    "content": "//\n//  AirportItlwmEthernetInterface.hpp\n//  AirportItlwm-Sonoma\n//\n//  Created by qcwap on 2023/6/27.\n//  Copyright © 2023 钟先耀. All rights reserved.\n//\n\n#ifndef AirportItlwmEthernetInterface_hpp\n#define AirportItlwmEthernetInterface_hpp\n\nextern \"C\" {\n#include <net/bpf.h>\n}\n#include \"Airport/Apple80211.h\"\n#include <IOKit/IOLib.h>\n#include <libkern/OSKextLib.h>\n#include <sys/kernel_types.h>\n#include <IOKit/network/IOEthernetInterface.h>\n\nclass AirportItlwmEthernetInterface : public IOEthernetInterface {\n    OSDeclareDefaultStructors(AirportItlwmEthernetInterface)\n    \npublic:\n    virtual IOReturn attachToDataLinkLayer( IOOptionBits options,\n                                            void *       parameter ) override;\n    \n    virtual void     detachFromDataLinkLayer( IOOptionBits options,\n                                              void *       parameter ) override;\n    \n    virtual bool initWithSkywalkInterfaceAndProvider(IONetworkController *controller, IO80211SkywalkInterface *interface);\n    \n    virtual bool setLinkState(IO80211LinkState state);\n    \n    static errno_t bpfOutputPacket(ifnet_t interface, u_int32_t data_link_type,\n                                  mbuf_t packet);\n    \n    static errno_t bpfTap(ifnet_t interface, u_int32_t data_link_type,\n                          bpf_tap_mode direction);\n    \n    virtual UInt32   inputPacket(\n                                 mbuf_t          packet,\n                                 UInt32          length  = 0,\n                                 IOOptionBits    options = 0,\n                                 void *          param   = 0 ) override;\n    \n    virtual IOService * getProvider( void ) const override;\n    \nprivate:\n    IO80211SkywalkInterface *interface;\n    bool isAttach;\n};\n\n#endif /* AirportItlwmEthernetInterface_hpp */\n"
  },
  {
    "path": "AirportItlwm/AirportItlwmInterface.cpp",
    "content": "//\n//  AirportItlwmInterface.cpp\n//  AirportItlwm\n//\n//  Created by qcwap on 2020/9/7.\n//  Copyright © 2020 钟先耀. All rights reserved.\n//\n\n#include \"AirportItlwmInterface.hpp\"\n\n#define super IO80211Interface\nOSDefineMetaClassAndStructors(AirportItlwmInterface, IO80211Interface);\n\nconst char* hexdump(uint8_t *buf, size_t len)\n{\n    ssize_t str_len = len * 3 + 1;\n    char *str = (char*)IOMalloc(str_len);\n    if (!str)\n        return nullptr;\n    for (size_t i = 0; i < len; i++)\n    snprintf(str + 3 * i, (len - i) * 3, \"%02x \", buf[i]);\n    str[MAX(str_len - 2, 0)] = 0;\n    return str;\n}\n\nbool AirportItlwmInterface::\ninit(IO80211Controller *controller, ItlHalService *halService)\n{\n    if (!super::init(controller))\n        return false;\n    this->fHalService = halService;\n    return true;\n}\n\nUInt32 AirportItlwmInterface::\ninputPacket(mbuf_t packet, UInt32 length, IOOptionBits options, void *param)\n{\n    ether_header_t *eh;\n    size_t len = mbuf_len(packet);\n    \n    eh = (ether_header_t *)mbuf_data(packet);\n    if (len >= sizeof(ether_header_t) && eh->ether_type == htons(ETHERTYPE_PAE)) { // EAPOL packet\n        const char* dump = hexdump((uint8_t*)mbuf_data(packet), len);\n        XYLog(\"input EAPOL packet, len: %zu, data: %s\\n\", len, dump ? dump : \"Failed to allocate memory\");\n        if (dump)\n            IOFree((void*)dump, 3 * len + 1);\n        return IO80211Interface::inputPacket(packet, (UInt32)len, 0, param);\n    }\n    return IOEthernetInterface::inputPacket(packet, length, options, param);\n}\n"
  },
  {
    "path": "AirportItlwm/AirportItlwmInterface.hpp",
    "content": "//\n//  AirportItlwmInterface.hpp\n//  AirportItlwm\n//\n//  Created by qcwap on 2020/9/7.\n//  Copyright © 2020 钟先耀. All rights reserved.\n//\n\n#ifndef AirportItlwmInterface_hpp\n#define AirportItlwmInterface_hpp\n\n#include \"Airport/Apple80211.h\"\n#include <IOKit/IOLib.h>\n#include <libkern/OSKextLib.h>\n#include <sys/kernel_types.h>\n#include <HAL/ItlHalService.hpp>\n\nclass AirportItlwmInterface : public IO80211Interface {\n    OSDeclareDefaultStructors(AirportItlwmInterface)\n    \npublic:\n    virtual UInt32   inputPacket(\n                                 mbuf_t          packet,\n                                 UInt32          length  = 0,\n                                 IOOptionBits    options = 0,\n                                 void *          param   = 0 ) override;\n\n    bool init(IO80211Controller *controller, ItlHalService *halService);\n\nprivate:\n    ItlHalService *fHalService;\n};\n\n#endif /* AirportItlwmInterface_hpp */\n"
  },
  {
    "path": "AirportItlwm/AirportItlwmSkywalkInterface.cpp",
    "content": "//\n//  AirportItlwmSkywalkInterface.cpp\n//  AirportItlwm-Sonoma\n//\n//  Created by qcwap on 2023/6/27.\n//  Copyright © 2023 钟先耀. All rights reserved.\n//\n#include \"AirportItlwmV2.hpp\"\n#include \"AirportItlwmSkywalkInterface.hpp\"\n#include <sys/CTimeout.hpp>\n#include <libkern/c++/OSMetaClass.h>\n#include <crypto/sha1.h>\n#include <net80211/ieee80211_node.h>\n#include <net80211/ieee80211_ioctl.h>\n#include <net80211/ieee80211_priv.h>\n\n#define super IO80211InfraProtocol\nOSDefineMetaClassAndStructors(AirportItlwmSkywalkInterface, IO80211InfraProtocol);\n\nconst char* hexdump(uint8_t *buf, size_t len) {\n    ssize_t str_len = len * 3 + 1;\n    char *str = (char*)IOMalloc(str_len);\n    if (!str)\n        return nullptr;\n    for (size_t i = 0; i < len; i++)\n    snprintf(str + 3 * i, (len - i) * 3, \"%02x \", buf[i]);\n    str[MAX(str_len - 2, 0)] = 0;\n    return str;\n}\n\nstatic int ieeeChanFlag2appleScanFlagVentura(int flags)\n{\n    int ret = 0;\n    if (flags & IEEE80211_CHAN_2GHZ)\n        ret |= APPLE80211_C_FLAG_2GHZ;\n    if (flags & IEEE80211_CHAN_5GHZ)\n        ret |= APPLE80211_C_FLAG_5GHZ;\n    ret |= (APPLE80211_C_FLAG_ACTIVE | APPLE80211_C_FLAG_20MHZ);\n    return ret;\n}\n\nstatic int ieeeChanFlag2apple(int flags, int bw)\n{\n    int ret = 0;\n    if (flags & IEEE80211_CHAN_2GHZ)\n        ret |= APPLE80211_C_FLAG_2GHZ;\n    if (flags & IEEE80211_CHAN_5GHZ)\n        ret |= APPLE80211_C_FLAG_5GHZ;\n    if (!(flags & IEEE80211_CHAN_PASSIVE))\n        ret |= APPLE80211_C_FLAG_ACTIVE;\n    if (flags & IEEE80211_CHAN_DFS)\n        ret |= APPLE80211_C_FLAG_DFS;\n    if (bw == -1) {\n        if (flags & IEEE80211_CHAN_VHT) {\n            if ((flags & IEEE80211_CHAN_VHT160) || (flags & IEEE80211_CHAN_VHT80_80))\n                ret |= APPLE80211_C_FLAG_160MHZ;\n            if (flags & IEEE80211_CHAN_VHT80)\n                ret |= APPLE80211_C_FLAG_80MHZ;\n        } else if ((flags & IEEE80211_CHAN_HT40) && (flags & IEEE80211_CHAN_HT)) {\n            ret |= APPLE80211_C_FLAG_40MHZ;\n            if (flags & IEEE80211_CHAN_HT40U)\n                ret |= APPLE80211_C_FLAG_EXT_ABV;\n        } else if (flags & IEEE80211_CHAN_HT20)\n            ret |= APPLE80211_C_FLAG_20MHZ;\n        else if ((flags & IEEE80211_CHAN_CCK) || (flags & IEEE80211_CHAN_OFDM))\n            ret |= APPLE80211_C_FLAG_10MHZ;\n    } else {\n        switch (bw) {\n            case IEEE80211_CHAN_WIDTH_80P80:\n            case IEEE80211_CHAN_WIDTH_160:\n                ret |= APPLE80211_C_FLAG_160MHZ;\n                break;\n            case IEEE80211_CHAN_WIDTH_80:\n                ret |= APPLE80211_C_FLAG_80MHZ;\n                break;\n            case IEEE80211_CHAN_WIDTH_40:\n                ret |= APPLE80211_C_FLAG_40MHZ;\n                if (flags & IEEE80211_CHAN_HT40U)\n                    ret |= APPLE80211_C_FLAG_EXT_ABV;\n                break;\n            case IEEE80211_CHAN_WIDTH_20:\n                ret |= APPLE80211_C_FLAG_20MHZ;\n                break;\n            default:\n                if (flags & IEEE80211_CHAN_HT20)\n                    ret |= APPLE80211_C_FLAG_20MHZ;\n                else if ((flags & IEEE80211_CHAN_CCK) || (flags & IEEE80211_CHAN_OFDM))\n                    ret |= APPLE80211_C_FLAG_10MHZ;\n                break;\n        }\n    }\n    return ret;\n}\n\nvoid 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)\n{\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    \n    ieee80211_disable_rsn(ic);\n    ieee80211_disable_wep(ic);\n    \n    struct ieee80211_wpaparams     wpa;\n    struct ieee80211_nwkey         nwkey;\n    bzero(&wpa, sizeof(wpa));\n    bzero(&nwkey, sizeof(nwkey));\n    \n    memset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN);\n    memcpy(ic->ic_des_essid, ssid, ssid_len);\n    ic->ic_des_esslen = ssid_len;\n    \n    bool is_zero = true;\n    for (int i = 0; i < IEEE80211_ADDR_LEN; i++)\n    is_zero &= bssid.octet[i] == 0;\n    \n    if (!is_zero) {\n        IEEE80211_ADDR_COPY(ic->ic_des_bssid, bssid.octet);\n        ic->ic_flags |= IEEE80211_F_DESBSSID;\n    }\n    else {\n        memset(ic->ic_des_bssid, 0, IEEE80211_ADDR_LEN);\n        ic->ic_flags &= ~IEEE80211_F_DESBSSID;\n    }\n\n    // AUTHTYPE_WPA3_SAE AUTHTYPE_WPA3_FT_SAE\n    // 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.\n    if (authtype_upper == APPLE80211_AUTHTYPE_WPA3_SAE || authtype_upper == APPLE80211_AUTHTYPE_WPA3_FT_SAE) {\n        wpa.i_protos |= IEEE80211_WPA_PROTO_WPA2;\n        authtype_upper |= APPLE80211_AUTHTYPE_WPA2_PSK;// hack\n    }\n    // AUTHTYPE_WPA3_ENTERPRISE AUTHTYPE_WPA3_FT_ENTERPRISE\n    if (authtype_upper == APPLE80211_AUTHTYPE_WPA3_ENTERPRISE || authtype_upper == APPLE80211_AUTHTYPE_WPA3_FT_ENTERPRISE) {\n        wpa.i_protos |= IEEE80211_WPA_PROTO_WPA2;\n        authtype_upper |= APPLE80211_AUTHTYPE_WPA2;// hack\n    }\n    \n    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)) {\n        XYLog(\"%s %d\\n\", __FUNCTION__, __LINE__);\n        wpa.i_protos = IEEE80211_WPA_PROTO_WPA1 | IEEE80211_WPA_PROTO_WPA2;\n    }\n    \n    if (authtype_upper & (APPLE80211_AUTHTYPE_WPA_PSK | APPLE80211_AUTHTYPE_WPA2_PSK | APPLE80211_AUTHTYPE_SHA256_PSK)) {\n        XYLog(\"%s %d\\n\", __FUNCTION__, __LINE__);\n        wpa.i_akms |= IEEE80211_WPA_AKM_PSK | IEEE80211_WPA_AKM_SHA256_PSK;\n        wpa.i_enabled = 1;\n        memcpy(ic->ic_psk, key, sizeof(ic->ic_psk));\n        ic->ic_flags |= IEEE80211_F_PSK;\n        ieee80211_ioctl_setwpaparms(ic, &wpa);\n    }\n    if (authtype_upper & (APPLE80211_AUTHTYPE_WPA | APPLE80211_AUTHTYPE_WPA2 | APPLE80211_AUTHTYPE_SHA256_8021X)) {\n        XYLog(\"%s %d\\n\", __FUNCTION__, __LINE__);\n        wpa.i_akms |= IEEE80211_WPA_AKM_8021X | IEEE80211_WPA_AKM_SHA256_8021X;\n        wpa.i_enabled = 1;\n        ieee80211_ioctl_setwpaparms(ic, &wpa);\n    }\n    \n    if (authtype_lower == APPLE80211_AUTHTYPE_SHARED) {\n        XYLog(\"shared key authentication is not supported!\\n\");\n        return;\n    }\n    \n    if (authtype_upper == APPLE80211_AUTHTYPE_NONE && authtype_lower == APPLE80211_AUTHTYPE_OPEN) { // Open or WEP Open System\n        if (key_len > 0) {\n            XYLog(\"%s %d\\n\", __FUNCTION__, __LINE__);\n            nwkey.i_wepon = IEEE80211_NWKEY_WEP;\n            nwkey.i_defkid = key_index + 1;\n            nwkey.i_key[key_index].i_keylen = (int)key_len;\n            nwkey.i_key[key_index].i_keydat = key;\n            ieee80211_ioctl_setnwkeys(ic, &nwkey);\n        }\n    }\n}\n\nvoid AirportItlwmSkywalkInterface::setPTK(const u_int8_t *key, size_t key_len) {\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    struct ieee80211_node    * ni = ic->ic_bss;\n    struct ieee80211_key *k;\n    int keylen;\n    \n    ni->ni_rsn_supp_state = RNSA_SUPP_PTKDONE;\n    \n    if (ni->ni_rsncipher != IEEE80211_CIPHER_USEGROUP) {\n        u_int64_t prsc;\n        \n        /* check that key length matches that of pairwise cipher */\n        keylen = ieee80211_cipher_keylen(ni->ni_rsncipher);\n        if (key_len != keylen) {\n            XYLog(\"PTK length mismatch. expected %d, got %zu\\n\", keylen, key_len);\n            return;\n        }\n        prsc = /*(gtk == NULL) ? LE_READ_6(key->rsc) :*/ 0;\n        \n        /* map PTK to 802.11 key */\n        k = &ni->ni_pairwise_key;\n        memset(k, 0, sizeof(*k));\n        k->k_cipher = ni->ni_rsncipher;\n        k->k_rsc[0] = prsc;\n        k->k_len = keylen;\n        memcpy(k->k_key, key, k->k_len);\n        /* install the PTK */\n        if ((*ic->ic_set_key)(ic, ni, k) != 0) {\n            XYLog(\"setting PTK failed\\n\");\n            return;\n        }\n        else\n            XYLog(\"setting PTK successfully\\n\");\n        ni->ni_flags &= ~IEEE80211_NODE_RSN_NEW_PTK;\n        ni->ni_flags &= ~IEEE80211_NODE_TXRXPROT;\n        ni->ni_flags |= IEEE80211_NODE_RXPROT;\n    } else if (ni->ni_rsncipher != IEEE80211_CIPHER_USEGROUP)\n        XYLog(\"%s: unexpected pairwise key update received from %s\\n\",\n              ic->ic_if.if_xname, ether_sprintf(ni->ni_macaddr));\n}\n\nvoid AirportItlwmSkywalkInterface::setGTK(const u_int8_t *gtk, size_t key_len, u_int8_t kid, u_int8_t *rsc) {\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    struct ieee80211_node    * ni = ic->ic_bss;\n    struct ieee80211_key *k;\n    int keylen;\n    \n    if (gtk != NULL) {\n        /* check that key length matches that of group cipher */\n        keylen = ieee80211_cipher_keylen(ni->ni_rsngroupcipher);\n        if (key_len != keylen) {\n            XYLog(\"GTK length mismatch. expected %d, got %zu\\n\", keylen, key_len);\n            return;\n        }\n        /* map GTK to 802.11 key */\n        k = &ic->ic_nw_keys[kid];\n        if (k->k_cipher == IEEE80211_CIPHER_NONE || k->k_len != keylen || memcmp(k->k_key, gtk, keylen) != 0) {\n            memset(k, 0, sizeof(*k));\n            k->k_id = kid;    /* 0-3 */\n            k->k_cipher = ni->ni_rsngroupcipher;\n            k->k_flags = IEEE80211_KEY_GROUP;\n            //if (gtk[6] & (1 << 2))\n            //  k->k_flags |= IEEE80211_KEY_TX;\n            k->k_rsc[0] = LE_READ_6(rsc);\n            k->k_len = keylen;\n            memcpy(k->k_key, gtk, k->k_len);\n            /* install the GTK */\n            if ((*ic->ic_set_key)(ic, ni, k) != 0) {\n                XYLog(\"setting GTK failed\\n\");\n                return;\n            }\n            else\n                XYLog(\"setting GTK successfully\\n\");\n        }\n    }\n    \n    if (true) {\n        ni->ni_flags |= IEEE80211_NODE_TXRXPROT;\n#ifndef IEEE80211_STA_ONLY\n        if (ic->ic_opmode != IEEE80211_M_IBSS ||\n            ++ni->ni_key_count == 2)\n#endif\n        {\n            XYLog(\"marking port %s valid\\n\",\n                  ether_sprintf(ni->ni_macaddr));\n            ni->ni_port_valid = 1;\n            ieee80211_set_link_state(ic, LINK_STATE_UP);\n            ni->ni_assoc_fail = 0;\n            if (ic->ic_opmode == IEEE80211_M_STA)\n                ic->ic_rsngroupcipher = ni->ni_rsngroupcipher;\n        }\n    }\n}\n\nbool AirportItlwmSkywalkInterface::\ninit(IOService *provider)\n{\n    bool ret = IO80211InfraInterface::init();\n    if (!ret) {\n        XYLog(\"%s IO80211InfraInterface init failed\\n\", __PRETTY_FUNCTION__);\n        return false;\n    }\n    instance = OSDynamicCast(AirportItlwm, provider);\n    if (!instance)\n        return false;\n    this->fHalService = instance->fHalService;\n    this->scanSource = instance->scanSource;\n    return ret;\n}\n\n//ifnet_t AirportItlwmSkywalkInterface::\n//getBSDInterface()\n//{\n//    if (instance->bsdInterface)\n//        return instance->bsdInterface->getIfnet();\n//    return NULL;\n//}\n\nIOReturn AirportItlwmSkywalkInterface::\ngetSSID(struct apple80211_ssid_data *sd)\n{\n    struct ieee80211com * ic = fHalService->get80211Controller();\n    if (ic->ic_state == IEEE80211_S_RUN) {\n        memset(sd, 0, sizeof(*sd));\n        sd->version = APPLE80211_VERSION;\n        memcpy(sd->ssid_bytes, ic->ic_des_essid, strlen((const char*)ic->ic_des_essid));\n        sd->ssid_len = (uint32_t)strlen((const char*)ic->ic_des_essid);\n        return kIOReturnSuccess;\n    }\n    return 6;\n}\n\nIOReturn AirportItlwmSkywalkInterface::\ngetAUTH_TYPE(struct apple80211_authtype_data *ad)\n{\n    ad->version = APPLE80211_VERSION;\n    ad->authtype_lower = current_authtype_lower;\n    ad->authtype_upper = current_authtype_upper;\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwmSkywalkInterface::\nsetAUTH_TYPE(struct apple80211_authtype_data *ad)\n{\n    current_authtype_lower = ad->authtype_lower;\n    current_authtype_upper = ad->authtype_upper;\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwmSkywalkInterface::\nsetCIPHER_KEY(struct apple80211_key *key)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    const char* keydump = hexdump(key->key, key->key_len);\n    const char* rscdump = hexdump(key->key_rsc, key->key_rsc_len);\n    const char* eadump = hexdump(key->key_ea.octet, APPLE80211_ADDR_LEN);\n    static_assert(__offsetof(struct apple80211_key, key_ea) == 92, \"struct corrupted\");\n    static_assert(__offsetof(struct apple80211_key, key_rsc_len) == 80, \"struct corrupted\");\n    static_assert(__offsetof(struct apple80211_key, wowl_kck_len) == 100, \"struct corrupted\");\n    static_assert(__offsetof(struct apple80211_key, wowl_kek_len) == 120, \"struct corrupted\");\n    static_assert(__offsetof(struct apple80211_key, wowl_kck_key) == 104, \"struct corrupted\");\n    if (keydump && rscdump && eadump)\n        XYLog(\"Set key request: len=%d cipher_type=%d flags=%d index=%d key=%s rsc_len=%d rsc=%s ea=%s\\n\",\n              key->key_len, key->key_cipher_type, key->key_flags, key->key_index, keydump, key->key_rsc_len, rscdump, eadump);\n    else\n        XYLog(\"Set key request, but failed to allocate memory for hexdump\\n\");\n    \n    if (keydump)\n        IOFree((void*)keydump, 3 * key->key_len + 1);\n    if (rscdump)\n        IOFree((void*)rscdump, 3 * key->key_rsc_len + 1);\n    if (eadump)\n        IOFree((void*)eadump, 3 * APPLE80211_ADDR_LEN + 1);\n    \n    switch (key->key_cipher_type) {\n        case APPLE80211_CIPHER_NONE:\n            // clear existing key\n//            XYLog(\"Setting NONE key is not supported\\n\");\n            break;\n        case APPLE80211_CIPHER_WEP_40:\n        case APPLE80211_CIPHER_WEP_104:\n            XYLog(\"Setting WEP key %d is not supported\\n\", key->key_index);\n            break;\n        case APPLE80211_CIPHER_TKIP:\n        case APPLE80211_CIPHER_AES_OCB:\n        case APPLE80211_CIPHER_AES_CCM:\n            switch (key->key_flags) {\n                case 4: // PTK\n                    setPTK(key->key, key->key_len);\n                    break;\n                case 0: // GTK\n                    setGTK(key->key, key->key_len, key->key_index, key->key_rsc);\n                    break;\n            }\n            break;\n        case APPLE80211_CIPHER_PMK:\n            XYLog(\"Setting WPA PMK is not supported\\n\");\n            break;\n        case APPLE80211_CIPHER_MSK:\n            XYLog(\"Setting MSK\\n\");\n            ieee80211_pmksa_add(fHalService->get80211Controller(), IEEE80211_AKM_8021X,\n                                fHalService->get80211Controller()->ic_bss->ni_macaddr, key->key, 0);\n            break;\n        case APPLE80211_CIPHER_PMKSA:\n            XYLog(\"Setting WPA PMKSA\\n\");\n            ieee80211_pmksa_add(fHalService->get80211Controller(), IEEE80211_AKM_8021X,\n                                fHalService->get80211Controller()->ic_bss->ni_macaddr, key->key, 0);\n            break;\n    }\n    //fInterface->postMessage(APPLE80211_M_CIPHER_KEY_CHANGED);\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwmSkywalkInterface::\ngetPHY_MODE(struct apple80211_phymode_data *pd)\n{\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    \n    pd->version = APPLE80211_VERSION;\n    pd->phy_mode = APPLE80211_MODE_11A\n    | APPLE80211_MODE_11B\n    | APPLE80211_MODE_11G\n    | APPLE80211_MODE_11N;\n    \n    if (ic->ic_flags & IEEE80211_F_VHTON)\n        pd->phy_mode |= APPLE80211_MODE_11AC;\n    \n    if (ic->ic_flags & IEEE80211_F_HEON)\n        pd->phy_mode |= APPLE80211_MODE_11AX;\n    \n    switch (fHalService->get80211Controller()->ic_curmode) {\n        case IEEE80211_MODE_AUTO:\n            pd->active_phy_mode = APPLE80211_MODE_AUTO;\n            break;\n        case IEEE80211_MODE_11A:\n            pd->active_phy_mode = APPLE80211_MODE_11A;\n            break;\n        case IEEE80211_MODE_11B:\n            pd->active_phy_mode = APPLE80211_MODE_11B;\n            break;\n        case IEEE80211_MODE_11G:\n            pd->active_phy_mode = APPLE80211_MODE_11G;\n            break;\n        case IEEE80211_MODE_11N:\n            pd->active_phy_mode = APPLE80211_MODE_11N;\n            break;\n        case IEEE80211_MODE_11AC:\n            pd->active_phy_mode = APPLE80211_MODE_11AC;\n            break;\n        case IEEE80211_MODE_11AX:\n            pd->active_phy_mode = APPLE80211_MODE_11AX;\n            break;\n            \n        default:\n            pd->active_phy_mode = APPLE80211_MODE_AUTO;\n            break;\n    }\n    \n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwmSkywalkInterface::\ngetCHANNEL(struct apple80211_channel_data *cd)\n{\n    struct ieee80211com * ic = fHalService->get80211Controller();\n    if (ic->ic_state == IEEE80211_S_RUN) {\n        memset(cd, 0, sizeof(apple80211_channel_data));\n        cd->version = APPLE80211_VERSION;\n        cd->channel.version = APPLE80211_VERSION;\n        cd->channel.channel = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan);\n        cd->channel.flags = ieeeChanFlag2apple(ic->ic_bss->ni_chan->ic_flags, ic->ic_bss->ni_chw);\n        return kIOReturnSuccess;\n    }\n    return 6;\n}\n\nIOReturn AirportItlwmSkywalkInterface::\ngetSTATE(struct apple80211_state_data *sd)\n{\n    memset(sd, 0, sizeof(*sd));\n    sd->version = APPLE80211_VERSION;\n    sd->state = fHalService->get80211Controller()->ic_state;\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwmSkywalkInterface::\ngetMCS_INDEX_SET(struct apple80211_mcs_index_set_data *ad)\n{\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    if (ic->ic_state == IEEE80211_S_RUN) {\n        memset(ad, 0, sizeof(*ad));\n        ad->version = APPLE80211_VERSION;\n        size_t size = min(ARRAY_SIZE(ic->ic_bss->ni_rxmcs), ARRAY_SIZE(ad->mcs_set_map));\n        for (int i = 0; i < size; i++)\n            ad->mcs_set_map[i] = ic->ic_bss->ni_rxmcs[i];\n        return kIOReturnSuccess;\n    }\n    return 6;\n}\n\nIOReturn AirportItlwmSkywalkInterface::\ngetVHT_MCS_INDEX_SET(struct apple80211_vht_mcs_index_set_data *data)\n{\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    if (ic->ic_bss == NULL || ic->ic_curmode < IEEE80211_MODE_11AC) {\n        return kIOReturnError;\n    }\n    memset(data, 0, sizeof(struct apple80211_vht_mcs_index_set_data));\n    data->version = APPLE80211_VERSION;\n    data->mcs_map = ic->ic_bss->ni_vht_mcsinfo.tx_mcs_map;\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwmSkywalkInterface::\ngetMCS_VHT(struct apple80211_mcs_vht_data *data)\n{\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    if (ic->ic_bss == NULL || ic->ic_curmode < IEEE80211_MODE_11AC) {\n        return kIOReturnError;\n    }\n    memset(data, 0, sizeof(struct apple80211_mcs_vht_data));\n    data->version = APPLE80211_VERSION;\n    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;\n    data->index = ic->ic_bss->ni_txmcs;\n    data->nss = fHalService->getDriverInfo()->getTxNSS();\n    switch (ic->ic_bss->ni_chw) {\n        case IEEE80211_CHAN_WIDTH_40:\n            data->bw = 40;\n            break;\n        case IEEE80211_CHAN_WIDTH_80:\n            data->bw = 80;\n            break;\n        case IEEE80211_CHAN_WIDTH_80P80:\n        case IEEE80211_CHAN_WIDTH_160:\n            data->bw = 160;\n            break;\n            \n        default:\n            data->bw = 20;\n            break;\n    }\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwmSkywalkInterface::\ngetRATE_SET(struct apple80211_rate_set_data *ad)\n{\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    if (ic->ic_state == IEEE80211_S_RUN) {\n        memset(ad, 0, sizeof(*ad));\n        ad->version = APPLE80211_VERSION;\n        ad->num_rates = ic->ic_bss->ni_rates.rs_nrates;\n        size_t size = min(ic->ic_bss->ni_rates.rs_nrates, ARRAY_SIZE(ad->rates));\n        for (int i=0; i < size; i++) {\n            struct apple80211_rate apple_rate = ad->rates[i];\n            apple_rate.version = APPLE80211_VERSION;\n            apple_rate.rate = ic->ic_bss->ni_rates.rs_rates[i];\n            apple_rate.flags = 0;\n        }\n        return kIOReturnSuccess;\n    }\n    return 6;\n}\n\nIOReturn AirportItlwmSkywalkInterface::\ngetOP_MODE(struct apple80211_opmode_data *od)\n{\n    od->version = APPLE80211_VERSION;\n    od->op_mode = APPLE80211_M_STA;\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwmSkywalkInterface::\ngetTXPOWER(struct apple80211_txpower_data *txd)\n{\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    if (ic->ic_state == IEEE80211_S_RUN) {\n        memset(txd, 0, sizeof(*txd));\n        txd->version = APPLE80211_VERSION;\n        txd->txpower = ic->ic_txpower;\n        txd->txpower_unit = APPLE80211_UNIT_PERCENT;\n        return kIOReturnSuccess;\n    }\n    return 6;\n}\n\nIOReturn AirportItlwmSkywalkInterface::\ngetRATE(struct apple80211_rate_data *rd)\n{\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    if (ic->ic_bss == NULL)\n        return 6;\n    int nss;\n    int sgi;\n    int index = 0;\n    if (ic->ic_state == IEEE80211_S_RUN) {\n        memset(rd, 0, sizeof(*rd));\n        rd->version = APPLE80211_VERSION;\n        rd->num_radios = 1;\n        sgi = ieee80211_node_supports_sgi(ic->ic_bss);\n        if (ic->ic_curmode == IEEE80211_MODE_11AC) {\n            if (sgi)\n                index += 1;\n            nss = fHalService->getDriverInfo()->getTxNSS();\n            switch (ic->ic_bss->ni_chw) {\n                case IEEE80211_CHAN_WIDTH_40:\n                    index += 4;\n                    break;\n                case IEEE80211_CHAN_WIDTH_80:\n                    index += 8;\n                    break;\n                case IEEE80211_CHAN_WIDTH_80P80:\n                case IEEE80211_CHAN_WIDTH_160:\n                    index += 12;\n                    break;\n\n                default:\n                    break;\n            }\n            index += 2 * (nss - 1);\n            const struct ieee80211_vht_rateset *rs = &ieee80211_std_ratesets_11ac[index];\n            rd->rate[0] = rs->rates[ic->ic_bss->ni_txmcs % rs->nrates] / 2;\n        } else if (ic->ic_curmode == IEEE80211_MODE_11N) {\n            int is_40mhz = ic->ic_bss->ni_chw == IEEE80211_CHAN_WIDTH_40;\n            if (sgi)\n                index += 1;\n            if (is_40mhz)\n                index += (IEEE80211_HT_RATESET_MIMO4_SGI + 1);\n            index += (ic->ic_bss->ni_txmcs / 16);\n            nss = ic->ic_bss->ni_txmcs / 8 + 1;\n            index += 2 * (nss - 1);\n            rd->rate[0] = ieee80211_std_ratesets_11n[index].rates[ic->ic_bss->ni_txmcs % 8] / 2;\n        } else\n            rd->rate[0] = ic->ic_bss->ni_rates.rs_rates[ic->ic_bss->ni_txrate];\n        return kIOReturnSuccess;\n    }\n    return 6;\n}\n\nIOReturn AirportItlwmSkywalkInterface::\ngetBSSID(struct apple80211_bssid_data *bd)\n{\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    if (ic->ic_state == IEEE80211_S_RUN) {\n        memset(bd, 0, sizeof(*bd));\n        bd->version = APPLE80211_VERSION;\n        memcpy(bd->bssid.octet, ic->ic_bss->ni_bssid, APPLE80211_ADDR_LEN);\n        return kIOReturnSuccess;\n    }\n    return 6;\n}\n\nIOReturn AirportItlwmSkywalkInterface::\ngetRSSI(struct apple80211_rssi_data *rd)\n{\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    if (ic->ic_state == IEEE80211_S_RUN) {\n        memset(rd, 0, sizeof(*rd));\n        rd->num_radios = 1;\n        rd->rssi_unit = APPLE80211_UNIT_DBM;\n        rd->rssi[0] = rd->aggregate_rssi\n        = rd->rssi_ext[0]\n        = rd->aggregate_rssi_ext\n        = -(0 - IWM_MIN_DBM - ic->ic_bss->ni_rssi);\n        return kIOReturnSuccess;\n    }\n    return 6;\n}\n\nIOReturn AirportItlwmSkywalkInterface::\ngetRSN_IE(struct apple80211_rsn_ie_data *data)\n{\n#ifdef USE_APPLE_SUPPLICANT\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    if (ic->ic_bss == NULL || ic->ic_bss->ni_rsnie == NULL) {\n        return kIOReturnError;\n    }\n    data->version = APPLE80211_VERSION;\n    if (ic->ic_rsn_ie_override[1] > 0) {\n        data->len = 2 + ic->ic_rsn_ie_override[1];\n        memcpy(data->ie, ic->ic_rsn_ie_override, data->len);\n    }\n    else {\n        data->len = 2 + ic->ic_bss->ni_rsnie[1];\n        memcpy(data->ie, ic->ic_bss->ni_rsnie, data->len);\n    }\n    return kIOReturnSuccess;\n#else\n    return kIOReturnUnsupported;\n#endif\n}\n\nIOReturn AirportItlwmSkywalkInterface::\nsetRSN_IE(struct apple80211_rsn_ie_data *data)\n{\n#ifdef USE_APPLE_SUPPLICANT\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    if (!data)\n        return kIOReturnError;\n    static_assert(sizeof(ic->ic_rsn_ie_override) == APPLE80211_MAX_RSN_IE_LEN, \"Max RSN IE length mismatch\");\n    memcpy(ic->ic_rsn_ie_override, data->ie, APPLE80211_MAX_RSN_IE_LEN);\n    if (ic->ic_state == IEEE80211_S_RUN && ic->ic_bss != nullptr)\n        ieee80211_save_ie(data->ie, &ic->ic_bss->ni_rsnie);\n    return kIOReturnSuccess;\n#else\n    return kIOReturnUnsupported;\n#endif\n}\n\nIOReturn AirportItlwmSkywalkInterface::\ngetAP_IE_LIST(struct apple80211_ap_ie_data *data)\n{\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    if (!data)\n        return kIOReturnError;\n    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)\n        return kIOReturnError;\n    data->version = APPLE80211_VERSION;\n    data->len = ic->ic_bss->ni_rsnie_tlv_len;\n    memcpy(data->ie_data, ic->ic_bss->ni_rsnie_tlv, data->len);\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwmSkywalkInterface::\ngetNOISE(struct apple80211_noise_data *nd)\n{\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    if (ic->ic_state == IEEE80211_S_RUN) {\n        memset(nd, 0, sizeof(*nd));\n        nd->version = APPLE80211_VERSION;\n        nd->num_radios = 1;\n        nd->noise[0]\n        = nd->aggregate_noise = -fHalService->getDriverInfo()->getBSSNoise();\n        nd->noise_unit = APPLE80211_UNIT_DBM;\n        return kIOReturnSuccess;\n    }\n    return 6;\n}\n\nIOReturn AirportItlwmSkywalkInterface::\ngetPOWERSAVE(struct apple80211_powersave_data *pd)\n{\n    pd->version = APPLE80211_VERSION;\n    pd->powersave_level = APPLE80211_POWERSAVE_MODE_DISABLED;\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwmSkywalkInterface::\ngetNSS(struct apple80211_nss_data *data)\n{\n    memset(data, 0, sizeof(*data));\n    data->version = APPLE80211_VERSION;\n    data->nss = fHalService->getDriverInfo()->getTxNSS();\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwmSkywalkInterface::\nsetASSOCIATE(struct apple80211_assoc_data *ad)\n{\n    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,\n          (ad->ad_flags & 2) ? \", Instant Hotspot\" : \"\",\n          (ad->ad_flags & 4) ? \", Auto Instant Hotspot\" : \"\",\n          (ad->ad_rsn_ie[APPLE80211_MAX_RSN_IE_LEN] & 1) ? \", don't disassociate\" : \"\",\n          (ad->ad_rsn_ie[APPLE80211_MAX_RSN_IE_LEN] & 2) ? \", don't blacklist\" : \"\",\n          (ad->ad_rsn_ie[APPLE80211_MAX_RSN_IE_LEN] & 4) ? \", closed Network\" : \"\",\n          (ad->ad_rsn_ie[APPLE80211_MAX_RSN_IE_LEN] & 8) ? \", 802.1X\" : \"\",\n          (ad->ad_rsn_ie[APPLE80211_MAX_RSN_IE_LEN] & 0x20) ? \", force BSSID\" : \"\");\n    \n    struct apple80211_rsn_ie_data rsn_ie_data;\n    struct apple80211_authtype_data auth_type_data;\n    struct ieee80211com *ic = fHalService->get80211Controller();\n\n    if (!ad)\n        return kIOReturnError;\n    \n    if (ic->ic_state < IEEE80211_S_SCAN)\n        return kIOReturnSuccess;\n    \n    if (ic->ic_state == IEEE80211_S_ASSOC || ic->ic_state == IEEE80211_S_AUTH)\n        return kIOReturnSuccess;\n\n    if (ad->ad_mode != APPLE80211_AP_MODE_IBSS) {\n        disassocIsVoluntary = false;\n        auth_type_data.version = APPLE80211_VERSION;\n        auth_type_data.authtype_upper = ad->ad_auth_upper;\n        auth_type_data.authtype_lower = ad->ad_auth_lower;\n        setAUTH_TYPE(&auth_type_data);\n        rsn_ie_data.version = APPLE80211_VERSION;\n        rsn_ie_data.len = ad->ad_rsn_ie[1] + 2;\n        memcpy(rsn_ie_data.ie, ad->ad_rsn_ie, rsn_ie_data.len);\n        setRSN_IE(&rsn_ie_data);\n\n        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);\n    }\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwmSkywalkInterface::\nsetDISASSOCIATE(struct apple80211_disassoc_data *ad)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct ieee80211com *ic = fHalService->get80211Controller();\n\n    if (ic->ic_state < IEEE80211_S_SCAN)\n        return kIOReturnSuccess;\n    \n    if (ic->ic_state > IEEE80211_S_AUTH && ic->ic_bss != NULL)\n        IEEE80211_SEND_MGMT(ic, ic->ic_bss, IEEE80211_FC0_SUBTYPE_DEAUTH, IEEE80211_REASON_AUTH_LEAVE);\n    \n    if (ic->ic_state == IEEE80211_S_ASSOC || ic->ic_state == IEEE80211_S_AUTH)\n        return kIOReturnSuccess;\n    \n    disassocIsVoluntary = true;\n\n    ieee80211_del_ess(ic, nullptr, 0, 1);\n    ieee80211_deselect_ess(ic);\n#ifdef USE_APPLE_SUPPLICANT\n    ic->ic_rsn_ie_override[1] = 0;\n#endif\n    ic->ic_assoc_status = APPLE80211_STATUS_UNAVAILABLE;\n    ic->ic_deauth_reason = APPLE80211_REASON_ASSOC_LEAVING;\n    ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwmSkywalkInterface::\ngetSUPPORTED_CHANNELS(struct apple80211_sup_channel_data *ad)\n{\n    if (!ad)\n        return kIOReturnError;\n    ad->version = APPLE80211_VERSION;\n    ad->num_channels = 0;\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    for (int i = 0; i < IEEE80211_CHAN_MAX; i++) {\n        if (ic->ic_channels[i].ic_freq != 0) {\n            ad->supported_channels[ad->num_channels].channel = ieee80211_chan2ieee(ic, &ic->ic_channels[i]);\n            ad->supported_channels[ad->num_channels].flags = ieeeChanFlag2appleScanFlagVentura(ic->ic_channels[i].ic_flags);\n            ad->num_channels++;\n        }\n    }\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwmSkywalkInterface::\ngetLOCALE(struct apple80211_locale_data *ld)\n{\n    if (!ld)\n        return kIOReturnError;\n    ld->version = APPLE80211_VERSION;\n    ld->locale  = APPLE80211_LOCALE_FCC;\n    \n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwmSkywalkInterface::\ngetDEAUTH(struct apple80211_deauth_data *da)\n{\n    if (!da)\n        return kIOReturnError;\n    da->version = APPLE80211_VERSION;\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    da->deauth_reason = ic->ic_deauth_reason;\n//    XYLog(\"%s, %d\\n\", __FUNCTION__, da->deauth_reason);\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwmSkywalkInterface::\ngetASSOCIATION_STATUS(struct apple80211_assoc_status_data *hv)\n{\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    \n    if (!hv)\n        return kIOReturnError;\n    memset(hv, 0, sizeof(*hv));\n    hv->version = APPLE80211_VERSION;\n    if (ic->ic_state == IEEE80211_S_RUN)\n        hv->status = APPLE80211_STATUS_SUCCESS;\n    else\n        hv->status = APPLE80211_STATUS_UNAVAILABLE;\n//    XYLog(\"%s, %d\\n\", __FUNCTION__, hv->status);\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwmSkywalkInterface::\nsetSCANCACHE_CLEAR(void *req)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    //if doing background or active scan, don't free nodes.\n    if ((ic->ic_flags & IEEE80211_F_BGSCAN) || (ic->ic_flags & IEEE80211_F_ASCAN))\n        return kIOReturnSuccess;\n    ieee80211_free_allnodes(ic, 0);\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwmSkywalkInterface::\nsetDEAUTH(struct apple80211_deauth_data *da)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwmSkywalkInterface::\ngetMCS(struct apple80211_mcs_data* md)\n{\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    if (ic->ic_state != IEEE80211_S_RUN ||  ic->ic_bss == NULL || !md)\n        return 6;\n    md->version = APPLE80211_VERSION;\n    md->index = ic->ic_bss->ni_txmcs;\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwmSkywalkInterface::\ngetLINK_CHANGED_EVENT_DATA(struct apple80211_link_changed_event_data *ed)\n{\n    if (ed == nullptr)\n        return 16;\n    \n    struct ieee80211com *ic = fHalService->get80211Controller();\n    \n    bzero(ed, sizeof(apple80211_link_changed_event_data));\n    ed->isLinkDown = !(instance->currentStatus & kIONetworkLinkActive);\n    if (ed->isLinkDown) {\n        ed->voluntary = disassocIsVoluntary;\n        ed->reason = APPLE80211_LINK_DOWN_REASON_DEAUTH;\n    } else\n        ed->rssi = -(0 - IWM_MIN_DBM - ic->ic_bss->ni_rssi);\n    XYLog(\"Link %s, reason: %d, voluntary: %d\\n\", ed->isLinkDown ? \"down\" : \"up\", ed->reason, ed->voluntary);\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwmSkywalkInterface::\nsetSCAN_REQ(struct apple80211_scan_data *sd)\n{\n    struct ieee80211com *ic = fHalService->get80211Controller();\n#if 0\n    XYLog(\"%s Type: %u BSS Type: %u PHY Mode: %u Dwell time: %u Rest time: %u Num channels: %u SSID: %s BSSID: %s\\n\",\n          __FUNCTION__,\n          sd->scan_type,\n          sd->bss_type,\n          sd->phy_mode,\n          sd->dwell_time,\n          sd->rest_time,\n          sd->num_channels,\n          sd->ssid,\n          ether_sprintf(sd->bssid.octet));\n#endif\n    if (fScanResultWrapping)\n        return 22;\n    if (ic->ic_state <= IEEE80211_S_INIT)\n        return 22;\n    if (sd->scan_type == APPLE80211_SCAN_TYPE_FAST || sd->scan_type == APPLE80211_SCAN_TYPE_PASSIVE) {\n        if (scanSource) {\n            scanSource->setTimeoutMS(100);\n            scanSource->enable();\n        }\n        return kIOReturnSuccess;\n    }\n    ieee80211_begin_cache_bgscan(&ic->ic_ac.ac_if);\n    if (scanSource) {\n        scanSource->setTimeoutMS(100);\n        scanSource->enable();\n    }\n    return kIOReturnSuccess;\n}\n\nextern OSDictionary *convertScanToDictionary(apple80211_scan_result *a1);\n\nstatic int convertNodeToScanResult(ItlHalService *fHalService, struct ieee80211_node *fNextNodeToSend, apple80211_scan_result *result)\n{\n    bzero(result, sizeof(*result));\n    result->version = APPLE80211_VERSION;\n    if (fNextNodeToSend->ni_rsnie_tlv && fNextNodeToSend->ni_rsnie_tlv_len > 0) {\n        result->asr_ie_len = fNextNodeToSend->ni_rsnie_tlv_len;\n        memcpy(result->asr_ie_data, fNextNodeToSend->ni_rsnie_tlv, MIN(result->asr_ie_len, sizeof(result->asr_ie_data)));\n    } else {\n        result->asr_ie_len = 0;\n    }\n    result->asr_beacon_int = fNextNodeToSend->ni_intval;\n    for (int i = 0; i < result->asr_nrates; i++ )\n        result->asr_rates[i] = fNextNodeToSend->ni_rates.rs_rates[i];\n    result->asr_nrates = fNextNodeToSend->ni_rates.rs_nrates;\n    result->asr_age = (uint32_t)(airport_up_time() - fNextNodeToSend->ni_age_ts);\n    result->asr_cap = fNextNodeToSend->ni_capinfo;\n    result->asr_channel.version = APPLE80211_VERSION;\n    result->asr_channel.channel = ieee80211_chan2ieee(fHalService->get80211Controller(), fNextNodeToSend->ni_chan);\n    result->asr_channel.flags = ieeeChanFlag2appleScanFlagVentura(fNextNodeToSend->ni_chan->ic_flags);\n    result->asr_noise = -fHalService->getDriverInfo()->getBSSNoise();\n    result->asr_rssi = -(0 - IWM_MIN_DBM - fNextNodeToSend->ni_rssi);\n    memcpy(result->asr_bssid, fNextNodeToSend->ni_bssid, IEEE80211_ADDR_LEN);\n    result->asr_ssid_len = fNextNodeToSend->ni_esslen;\n    if (result->asr_ssid_len != 0)\n        memcpy(&result->asr_ssid, fNextNodeToSend->ni_essid, result->asr_ssid_len);\n    return 0;\n}\n\nIOReturn AirportItlwmSkywalkInterface::\ngetCURRENT_NETWORK(apple80211_scan_result *sr)\n{\n    if (fHalService->get80211Controller()->ic_state != IEEE80211_S_RUN || fHalService->get80211Controller()->ic_bss == NULL)\n        return kIOReturnError;\n    convertNodeToScanResult(fHalService, fHalService->get80211Controller()->ic_bss, sr);\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwmSkywalkInterface::\ngetCOLOCATED_NETWORK_SCOPE_ID(apple80211_colocated_network_scope_id *as)\n{\n    if (!as)\n        return kIOReturnBadArgument;\n    as->version = APPLE80211_VERSION;\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwmSkywalkInterface::\ngetSCAN_RESULT(struct apple80211_scan_result *sr)\n{\n    if (fNextNodeToSend == NULL) {\n        if (fScanResultWrapping) {\n            fScanResultWrapping = false;\n            return 5;\n        } else {\n            fNextNodeToSend = RB_MIN(ieee80211_tree, &fHalService->get80211Controller()->ic_tree);\n            if (fNextNodeToSend == NULL) {\n                return 5;\n            }\n        }\n    }\n//    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);\n    convertNodeToScanResult(fHalService, fNextNodeToSend, sr);\n    \n    fNextNodeToSend = RB_NEXT(ieee80211_tree, &HalService->get80211Controller()->ic_tree, fNextNodeToSend);\n    if (fNextNodeToSend == NULL)\n        fScanResultWrapping = true;\n\n    return kIOReturnSuccess;\n}\n"
  },
  {
    "path": "AirportItlwm/AirportItlwmSkywalkInterface.hpp",
    "content": "//\n//  AirportItlwmSkywalkInterface.hpp\n//  AirportItlwm-Sonoma\n//\n//  Created by qcwap on 2023/6/27.\n//  Copyright © 2023 钟先耀. All rights reserved.\n//\n\n#ifndef AirportItlwmSkywalkInterface_hpp\n#define AirportItlwmSkywalkInterface_hpp\n\n#include <Airport/Apple80211.h>\n\nclass AirportItlwmSkywalkInterface : public IO80211InfraProtocol {\n    OSDeclareDefaultStructors(AirportItlwmSkywalkInterface)\n    \npublic:\n    virtual bool init(IOService *) override;\n//    virtual ifnet_t getBSDInterface(void) override;\n    \n    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);\n    void setPTK(const u_int8_t *key, size_t key_len);\n    void setGTK(const u_int8_t *key, size_t key_len, u_int8_t kid, u_int8_t *rsc);\n    \npublic:\n    virtual IOReturn getSSID(apple80211_ssid_data *) override;\n    virtual IOReturn getAUTH_TYPE(apple80211_authtype_data *) override;\n    virtual IOReturn getCHANNEL(apple80211_channel_data *) override;\n    virtual IOReturn getPOWERSAVE(apple80211_powersave_data *) override;\n    virtual IOReturn getTXPOWER(apple80211_txpower_data *) override;\n    virtual IOReturn getRATE(apple80211_rate_data *) override;\n    virtual IOReturn getBSSID(apple80211_bssid_data *) override;\n    virtual IOReturn getSCAN_RESULT(apple80211_scan_result *) override;\n    virtual IOReturn getSTATE(apple80211_state_data *) override;\n    virtual IOReturn getPHY_MODE(apple80211_phymode_data *) override;\n    virtual IOReturn getOP_MODE(apple80211_opmode_data *) override;\n    virtual IOReturn getRSSI(apple80211_rssi_data *) override;\n    virtual IOReturn getNOISE(apple80211_noise_data *) override;\n    virtual IOReturn getSUPPORTED_CHANNELS(apple80211_sup_channel_data *) override;\n    virtual IOReturn getLOCALE(apple80211_locale_data *) override;\n    virtual IOReturn getDEAUTH(apple80211_deauth_data *) override;\n    virtual IOReturn getRATE_SET(apple80211_rate_set_data *) override;\n    virtual IOReturn getDTIM_INT(apple80211_dtim_int_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getSTATION_LIST(apple80211_sta_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getRSN_IE(apple80211_rsn_ie_data *) override;\n    virtual IOReturn getAP_IE_LIST(apple80211_ap_ie_data *) override;\n    virtual IOReturn getSTATS(apple80211_stats_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getASSOCIATION_STATUS(apple80211_assoc_status_data *) override;\n    virtual IOReturn getGUARD_INTERVAL(apple80211_guard_interval_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getMCS(apple80211_mcs_data *) override;\n    virtual IOReturn getMCS_INDEX_SET(apple80211_mcs_index_set_data *) override;\n    virtual IOReturn getWOW_PARAMETERS(apple80211_wow_parameter_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getWOW_ENABLED(apple80211_state_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getPID_LOCK(apple80211_state_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getSTA_IE_LIST(apple80211_sta_ie_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getSTA_STATS(apple80211_sta_stats_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getBT_COEX_FLAGS(apple80211_state_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getCURRENT_NETWORK(apple80211_scan_result *) override;\n    virtual IOReturn getRSSI_BOUNDS(apple80211_rssi_bounds_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getPOWER_DEBUG_INFO(apple80211_power_debug_info *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getHT_CAPABILITY(apple80211_ht_capability *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getLINK_CHANGED_EVENT_DATA(apple80211_link_changed_event_data *) override;\n    virtual IOReturn getEXTENDED_STATS(apple80211_extended_stats *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getBEACON_PERIOD(apple80211_beacon_period_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getVHT_MCS_INDEX_SET(apple80211_vht_mcs_index_set_data *) override;\n    virtual IOReturn getMCS_VHT(apple80211_mcs_vht_data *) override;\n    virtual IOReturn getGAS_RESULTS(apple80211_gas_result_t *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getCHANNELS_INFO(apple80211_channels_info *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getVHT_CAPABILITY(apple80211_vht_capability *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getBGSCAN_CACHE_RESULTS(apple80211_bgscan_cached_network_data_list *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getROAM_PROFILE(apple80211_roam_profile_band_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getCHIP_COUNTER_STATS(apple80211_chip_stats *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getDBG_GUARD_TIME_PARAMS(apple80211_dbg_guard_time_params *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getLEAKY_AP_STATS_MODE(apple80211_leaky_ap_setting *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getCOUNTRY_CHANNELS(apple80211_country_channel_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getPRIVATE_MAC(apple80211_private_mac_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getRANGING_ENABLE(apple80211_ranging_enable_request_t *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getRANGING_START(apple80211_ranging_start_request_t *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getAWDL_RSDB_CAPS(apple80211_rsdb_capability *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getTKO_PARAMS(apple80211_tko_params *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getTKO_DUMP(apple80211_tko_dump *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getHW_SUPPORTED_CHANNELS(apple80211_sup_channel_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getBTCOEX_PROFILE(apple80211_btcoex_profile *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getBTCOEX_PROFILE_ACTIVE(apple80211_btcoex_profile_active_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getTRAP_INFO(apple80211_trap_info_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getTHERMAL_INDEX(apple80211_thermal_index_t *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getMAX_NSS_FOR_AP(apple80211_btcoex_max_nss_for_ap_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getBTCOEX_2G_CHAIN_DISABLE(apple80211_btcoex_2g_chain_disable *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getPOWER_BUDGET(apple80211_power_budget_t *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getOFFLOAD_TCPKA_ENABLE(apple80211_offload_tcpka_enable_t *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getRANGING_CAPS(apple80211_ranging_capabilities_t *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getSUPPRESS_SCANS(apple80211_suppress_scans_t *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getHOST_AP_MODE_HIDDEN(apple80211_host_ap_mode_hidden_t *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getLQM_CONFIG(apple80211_lqm_config_t *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getTRAP_CRASHTRACER_MINI_DUMP(apple80211_trap_mini_dump_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getHE_CAPABILITY(apple80211_he_capability *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getBEACON_INFO(apple80211_beacon_info_t *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getSOFTAP_PARAMS(apple80211_softap_params *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getCHIP_POWER_RANGE(apple80211_chip_power_limit *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getSOFTAP_STATS(apple80211_softap_stats *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getNSS(apple80211_nss_data *) override;\n    virtual IOReturn getHW_ADDR(apple80211_hw_mac_address *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getHE_MCS_INDEX_SET(apple80211_he_mcs_index_set_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getCHIP_DIAGS(appl80211_chip_diags_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getHP2P_CTRL(apple80211_hp2p_ctrl *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getREQUEST_BSS_BLACKLIST(void *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getASSOC_READY_STATUS(apple80211_assoc_ready *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getTXRX_CHAIN_INFO(apple80211_txrx_chain_info *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getMIMO_STATUS(apple80211_mimo_status *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getCUR_PMK(apple80211_pmk *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getDYNSAR_DETAIL(apple80211_dynsar_detail *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getRANDOMISATION_STATUS(apple80211_mac_randomisation_status *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getCOUNTRY_CHANNELS_INFO(apple80211_channels_info *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getLQM_SUMMARY(apple80211_lqm_summary *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getCOLOCATED_NETWORK_SCOPE_ID(apple80211_colocated_network_scope_id *) override;\n    virtual IOReturn getBEACON_SCAN_CACHE_REQ(apple80211_scan_result *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getSLOW_WIFI_FEATURE_ENABLED(apple80211_slow_wifi_feature_enabled *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getCCA(apple80211_interface_cca_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getRX_RATE(apple80211_rate_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getTIMESYNC_INFO(apple80211_timesync_info *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getSENSING_DATA(apple80211_sensing_data_t *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getCOUNTRY_BAND_SUPPORT(apple80211_country_band_support *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getWCL_FW_HOT_CHANNELS(apple80211_fw_hot_channels *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getWCL_LOW_LATENCY_INFO(apple80211_low_latency_info *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getWCL_BSS_INFO(apple80211_beacon_msg *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getWCL_TRAFFIC_COUNTERS(apple80211_wcl_traffic_counters *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getWCL_GET_TX_BLANKING_STATUS(uint *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getSSID_TRANSITION_SUPPORT(apple80211_ssid_transition_feature_enabled *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getWCL_VALID_CHANNEL_COUNT(unsigned long *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getWCL_P2P_STATUS_FOR_SCAN(p2pStatusForScan *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getWCL_CHANNELS_INFO(apple80211ChannelInfo *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getP2P_STEERING_METRIC(apple80211_p2p_steering_metrics *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getRSN_XE(apple80211_rsn_xe_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getSIB_COEX_STATUS(apple80211_sib_coex_status *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getWCL_EXTENDED_BSS_INFO(apple80211_extended_bss_info *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getWCL_LOW_LATENCY_INFO_STATS(apple80211_wcl_low_latency_stats *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getWCL_BGSCAN_CACHE_RESULT(apple80211_bgscan_cached_network_data_list *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getWIFI_NOISE_PER_ANT(apple80211_noise_per_ant_t *) override { return kIOReturnUnsupported; }\n    virtual IOReturn getBLOCKED_BANDS(apple80211_blocked_bands *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setSSID(apple80211_ssid_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setAUTH_TYPE(apple80211_authtype_data *) override;\n    virtual IOReturn setCIPHER_KEY(apple80211_key *) override;\n    virtual IOReturn setCHANNEL(apple80211_channel_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setPOWERSAVE(apple80211_powersave_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setTXPOWER(apple80211_txpower_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setRATE(apple80211_rate_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setSCAN_REQ(apple80211_scan_data *) override;\n    virtual IOReturn setASSOCIATE(apple80211_assoc_data *) override;\n    virtual IOReturn setDISASSOCIATE(apple80211_disassoc_data *) override;\n    virtual IOReturn setIBSS_MODE(apple80211_network_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setHOST_AP_MODE(apple80211_network_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setAP_MODE(apple80211_apmode_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setDEAUTH(apple80211_deauth_data *) override;\n    virtual IOReturn setTX_ANTENNA(void *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setANTENNA_DIVERSITY(void *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setRSN_IE(apple80211_rsn_ie_data *) override;\n    virtual IOReturn setBACKGROUND_SCAN(apple80211_bgscan_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setWOW_PARAMETERS(apple80211_wow_parameter_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setWOW_ENABLED(apple80211_state_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setPID_LOCK(apple80211_state_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setSTA_AUTHORIZE(apple80211_sta_authorize_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setSTA_DISASSOCIATE(apple80211_sta_disassoc_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setSTA_DEAUTH(apple80211_sta_disassoc_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setRSN_CONF(apple80211_rsn_conf_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setIE(apple80211_ie_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setWOW_TEST(apple80211_wow_test_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setSCANCACHE_CLEAR(void *) override;\n    virtual IOReturn setVIRTUAL_IF_CREATE(apple80211_virt_if_create_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setBT_COEX_FLAGS(apple80211_state_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setROAM(apple80211_sta_roam_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setHT_CAPABILITY(apple80211_ht_capability *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setAWDL_FORCED_ROAM_CONFIG(apple80211_awdl_forced_roam_config *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setOFFLOAD_ARP(apple80211_offload_arp_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setOFFLOAD_NDP(apple80211_offload_ndp_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setOFFLOAD_SCAN(apple80211_offload_scan_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setGAS_REQ(apple80211_gas_query_t *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setGAS_START(apple80211_gas_query_t *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setGAS_SET_PEER(apple80211_gas_peer_t *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setVHT_CAPABILITY(apple80211_vht_capability *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setROAM_PROFILE(apple80211_roam_profile_band_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setAWDL_ENABLE_ROAMING(void *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setDBG_GUARD_TIME_PARAMS(apple80211_dbg_guard_time_params *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setLEAKY_AP_STATS_MODE(apple80211_leaky_ap_setting *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setPRIVATE_MAC(apple80211_private_mac_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setRESET_CHIP(apple80211_reset_command *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setCRASH(apple80211_crash_command *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setRANGING_ENABLE(apple80211_ranging_enable_request_t *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setRANGING_START(apple80211_ranging_start_request_t *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setRANGING_AUTHENTICATE(apple80211_ranging_authenticate_request_t *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setTKO_PARAMS(apple80211_tko_params *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setBTCOEX_PROFILE(apple80211_btcoex_profile *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setBTCOEX_PROFILE_ACTIVE(apple80211_btcoex_profile_active_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setTHERMAL_INDEX(apple80211_thermal_index_t *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setBTCOEX_2G_CHAIN_DISABLE(apple80211_btcoex_2g_chain_disable *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setPOWER_BUDGET(apple80211_power_budget_t *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setOFFLOAD_TCPKA_ENABLE(apple80211_offload_tcpka_enable_t *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setSUPPRESS_SCANS(apple80211_suppress_scans_t *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setHOST_AP_MODE_HIDDEN(apple80211_host_ap_mode_hidden_t *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setLQM_CONFIG(apple80211_lqm_config_t *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setSOFTAP_PARAMS(apple80211_softap_params *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setSOFTAP_TRIGGER_CSA(apple80211_softap_csa_params *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setSOFTAP_WIFI_NETWORK_INFO_IE(apple80211_softap_wifi_network_info *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setBTCOEX_DISABLE_ULOFDMA(uint *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setSCAN_CONTROL(apple80211_scan_control_params *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setUSB_HOST_NOTIFICATION(apple80211_usb_host_notification_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setSET_MAC_ADDRESS(apple80211_set_mac_address *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setHP2P_CTRL(apple80211_hp2p_ctrl *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setABORT_SCAN(apple80211_abort_scan *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setSET_PROPERTY(apple80211_set_property_unserialized_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setROAM_CACHE_UPDATE(apple80211_roam_cache_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setPM_MODE(apple80211_pm_mode *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setSET_WIFI_ASSERTION_STATE(apple80211_wifi_assertion_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setREASSOCIATE_WITH_CORECAPTURE(apple80211_capture_debug_info_t *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setLINKDOWN_DEBOUNCE_STATUS(apple80211_linkdown_debounce_status *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setSOFTAP_EXTENDED_CAPABILITIES_IE(apple80211_softap_extended_capabilities_info *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setREALTIME_QOS_MSCS(apple80211_state_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setSENSING_ENABLE(apple80211_sensing_enable_t *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setSENSING_DISABLE(apple80211_sensing_disable_t *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setNANPHS_ASSOCIATION(apple80211_nan_link_association_info *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setNANPHS_TERMINATED(apple80211_nan_link_association_info *) override { return kIOReturnUnsupported; }\n    virtual IOReturn set6G_MODE(apple80211_6G_mode *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setWCL_LEAVE_NETWORK(apple80211_leave_network *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setWCL_REASSOC(apple80211_reassoc *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setWCL_SET_ROAM_LOCK(apple80211_set_roam_lock *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setWCL_ROAM_PROFILE_CONFIG(apple80211_roam_profile_config *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setWCL_ROAM_PROFILE_CONFIGV1(apple80211_roam_profile_configV1 *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setWCL_ROAM_USER_CACHE(apple80211_user_roam_cache *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setWCL_SET_MULTI_AP_ENV(apple80211_set_multi_ap_env *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setWCL_SCAN_ABORT(void *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setWCL_REAL_TIME_MODE(apple80211_wcl_real_time_mode *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setWCL_GARP_MODE(apple80211_wcl_garp_mode *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setWCL_JOIN_ABORT(void *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setWCL_TRIGGER_CC(triggerCC *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setWCL_SCAN_REQ(apple80211ScanRequest *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setWCL_ASSOCIATE(apple80211_assoc_candidates *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setWCL_PROTECT_IP(apple80211_wcl_protect_ip_mode *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setWCL_LINK_UP_DONE(void *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setWCL_SET_SCAN_HOME_AWAY_TIME(scanHomeAndAwayTime *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setWCL_VOLUNTARY_NETWORK_DISCONNECT(apple80211_wcl_voluntary_network_disconnect *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setWCL_LINK_STATE_UPDATE(apple80211_wcl_update_link_state *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setSLOW_WIFI_RECOVERY(void *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setRSN_XE(apple80211_rsn_xe_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setWCL_ULOFDMA_STATE(apple80211_wcl_ulofdma_state *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setWCL_ACTION_FRAME(apple80211_wcl_action_frame *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setWCL_REAL_TIME_POLICY(apple80211_wcl_real_time_policy *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setGAS_ABORT(void *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setOS_FEATURE_FLAGS(apple80211_feature_flags *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setDHCP_RENEWAL_DATA(apple80211_dhcp_renewal_data *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setMOVING_NETWORK(apple80211_network_flags *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setBATTERY_POWERSAVE_CONFIG(apple80211_battery_ps_config *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setMIMO_CONFIG(apple80211_mimo_config *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setWCL_CONFIG_BG_MOTIONPROFILE(apple80211_bg_motion_profile *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setWCL_CONFIG_BG_NETWORK(apple80211_bg_network *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setWCL_CONFIG_BGSCAN(apple80211_bg_scan *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setWCL_CONFIG_BG_PARAMS(apple80211_bg_params *) override { return kIOReturnUnsupported; }\n    virtual IOReturn setBLOCKED_BANDS(apple80211_blocked_bands *) override { return kIOReturnUnsupported; }\n    \nprivate:\n    AirportItlwm *instance;\n    ItlHalService *fHalService;\n    \n    //IO80211\n    struct ieee80211_node *fNextNodeToSend;\n    IOTimerEventSource *scanSource;\n    bool fScanResultWrapping;\n    \n    u_int32_t current_authtype_lower;\n    u_int32_t current_authtype_upper;\n    bool disassocIsVoluntary;\n};\n\n\n#endif /* AirportItlwmSkywalkInterface_hpp */\n"
  },
  {
    "path": "AirportItlwm/AirportItlwmV2.cpp",
    "content": "//\n//  AirportItlwmV2.cpp\n//  AirportItlwm-Sonoma\n//\n//  Created by qcwap on 2023/6/27.\n//  Copyright © 2023 钟先耀. All rights reserved.\n//\n\n#include \"AirportItlwmV2.hpp\"\n#include <sys/_netstat.h>\n#include <crypto/sha1.h>\n#include <net80211/ieee80211_priv.h>\n#include <net80211/ieee80211_var.h>\n\n#include \"AirportItlwmSkywalkInterface.hpp\"\n#include \"IOPCIEDeviceWrapper.hpp\"\n\n#define super IO80211Controller\nOSDefineMetaClassAndStructors(AirportItlwm, IO80211Controller);\nOSDefineMetaClassAndStructors(CTimeout, OSObject)\n\nIO80211WorkQueue *_fWorkloop;\nIOCommandGate *_fCommandGate;\n\nvoid AirportItlwm::releaseAll()\n{\n    OSSafeReleaseNULL(driverLogPipe);\n    OSSafeReleaseNULL(driverDataPathPipe);\n    OSSafeReleaseNULL(driverSnapshotsPipe);\n    OSSafeReleaseNULL(driverFaultReporter);\n    if (fHalService) {\n        fHalService->release();\n        fHalService = NULL;\n    }\n    if (_fWorkloop) {\n        if (_fCommandGate) {\n//            _fCommandGate->disable();\n            _fWorkloop->removeEventSource(_fCommandGate);\n            _fCommandGate->release();\n            _fCommandGate = NULL;\n        }\n        if (scanSource) {\n            scanSource->cancelTimeout();\n            scanSource->disable();\n            _fWorkloop->removeEventSource(scanSource);\n            scanSource->release();\n            scanSource = NULL;\n        }\n        if (fWatchdogWorkLoop && watchdogTimer) {\n            watchdogTimer->cancelTimeout();\n            fWatchdogWorkLoop->removeEventSource(watchdogTimer);\n            watchdogTimer->release();\n            watchdogTimer = NULL;\n            fWatchdogWorkLoop->release();\n            fWatchdogWorkLoop = NULL;\n        }\n        _fWorkloop->release();\n        _fWorkloop = NULL;\n    }\n    unregistPM();\n}\n\nvoid AirportItlwm::\neventHandler(struct ieee80211com *ic, int msgCode, void *data)\n{\n    AirportItlwm *that = OSDynamicCast(AirportItlwm, ic->ic_ac.ac_if.controller);\n    IO80211SkywalkInterface *interface = that->fNetIf;\n    if (!interface)\n        return;\n    switch (msgCode) {\n        case IEEE80211_EVT_COUNTRY_CODE_UPDATE:\n            interface->postMessage(APPLE80211_M_COUNTRY_CODE_CHANGED, NULL, 0, 0);\n            break;\n        case IEEE80211_EVT_STA_ASSOC_DONE:\n            interface->postMessage(APPLE80211_M_ASSOC_DONE, NULL, 0, 0);\n            break;\n        case IEEE80211_EVT_STA_DEAUTH:\n            interface->postMessage(APPLE80211_M_DEAUTH_RECEIVED, NULL, 0, 0);\n            break;\n        default:\n            break;\n    }\n}\n\nvoid AirportItlwm::watchdogAction(IOTimerEventSource *timer)\n{\n    struct _ifnet *ifp = &fHalService->get80211Controller()->ic_ac.ac_if;\n    (*ifp->if_watchdog)(ifp);\n    watchdogTimer->setTimeoutMS(kWatchDogTimerPeriod);\n}\n\nvoid AirportItlwm::fakeScanDone(OSObject *owner, IOTimerEventSource *sender)\n{\n    UInt32 msg = 0;\n    AirportItlwm *that = (AirportItlwm *)owner;\n    that->fNetIf->postMessage(APPLE80211_M_SCAN_DONE, &msg, 4, 0);\n}\n\nbool AirportItlwm::init(OSDictionary *properties)\n{\n    XYLog(\"%s\\n\", __PRETTY_FUNCTION__);\n    bool ret = super::init(properties);\n    awdlSyncEnable = true;\n    power_state = 0;\n    memset(geo_location_cc, 0, sizeof(geo_location_cc));\n    return ret;\n}\n\nIOService* AirportItlwm::probe(IOService *provider, SInt32 *score)\n{\n    XYLog(\"%s\\n\", __PRETTY_FUNCTION__);\n    IOPCIEDeviceWrapper *wrapper = OSDynamicCast(IOPCIEDeviceWrapper, provider);\n    if (!wrapper) {\n        XYLog(\"%s Not a IOPCIEDeviceWrapper instance\\n\", __FUNCTION__);\n        return NULL;\n    }\n    pciNub = wrapper->pciNub;\n    fHalService = wrapper->fHalService;\n    if (!pciNub || !fHalService) {\n        XYLog(\"%s Not a valid IOPCIEDeviceWrapper instance\\n\", __FUNCTION__);\n        return NULL;\n    }\n    return super::probe(provider, score);\n}\n\n#define LOWER32(x)  ((uint64_t)(x) & 0xffffffff)\n#define HIGHER32(x) ((uint64_t)(x) >> 32)\n\nbool AirportItlwm::\ninitCCLogs()\n{\n    CCPipeOptions driverLogOptions = { 0 };\n    driverLogOptions.pipe_type = 0;\n    driverLogOptions.log_data_type = 1;\n    driverLogOptions.pipe_size = 0x200000;\n    driverLogOptions.min_log_size_notify = 0xccccc;\n    driverLogOptions.notify_threshold = 1000;\n    strlcpy(driverLogOptions.file_name, \"Itlwm_Logs\", sizeof(driverLogOptions.file_name));\n    snprintf(driverLogOptions.name, sizeof(driverLogOptions.name), \"wlan%d\", 0);\n    strlcpy(driverLogOptions.directory_name, \"WiFi\", sizeof(driverLogOptions.directory_name));\n    driverLogOptions.pad9 = 0x1000000;\n    driverLogOptions.pad10 = 2;\n    driverLogOptions.file_options = 0;\n    driverLogOptions.log_policy = 0;\n    driverLogPipe = CCPipe::withOwnerNameCapacity(this, \"com.zxystd.AirportItlwm\", \"DriverLogs\", &driverLogOptions);\n    XYLog(\"%s driverLogPipeRet %d\\n\", __FUNCTION__, driverLogPipe != NULL);\n    \n    memset(&driverLogOptions, 0, sizeof(driverLogOptions));\n    driverLogOptions.pipe_type = 0;\n    driverLogOptions.log_data_type = 0;\n    driverLogOptions.pipe_size = 0x200000;\n    driverLogOptions.min_log_size_notify = 0xccccc;\n    driverLogOptions.notify_threshold = 1000;\n    strlcpy(driverLogOptions.file_name, \"AppleBCMWLAN_Datapath\", sizeof(driverLogOptions.file_name));\n    strlcpy(driverLogOptions.directory_name, \"WiFi\", sizeof(driverLogOptions.directory_name));\n    driverLogOptions.pad9 = HIGHER32(0x202800000);\n    driverLogOptions.pad10 = LOWER32(0x202800000);\n    driverLogOptions.file_options = 0;\n    driverLogOptions.log_policy = 0;\n    driverDataPathPipe = CCPipe::withOwnerNameCapacity(this, \"com.zxystd.AirportItlwm\", \"DatapathEvents\", &driverLogOptions);\n    XYLog(\"%s driverDataPathPipeRet %d\\n\", __FUNCTION__, driverDataPathPipe != NULL);\n    \n    memset(&driverLogOptions, 0, sizeof(driverLogOptions));\n    driverLogOptions.pipe_type = 0x200000001;\n    driverLogOptions.log_data_type = 2;\n    strlcpy(driverLogOptions.file_name, \"StateSnapshots\", sizeof(driverLogOptions.file_name));\n    strlcpy(driverLogOptions.name, \"0\", sizeof(driverLogOptions.name));\n    strlcpy(driverLogOptions.directory_name, \"WiFi\", sizeof(driverLogOptions.directory_name));\n    driverLogOptions.pipe_size = 128;\n    driverSnapshotsPipe = CCPipe::withOwnerNameCapacity(this, \"com.zxystd.AirportItlwm\", \"StateSnapshots\", &driverLogOptions);\n    XYLog(\"%s driverSnapshotsPipeRet %d\\n\", __FUNCTION__, driverSnapshotsPipe != NULL);\n    \n    CCStreamOptions faultReportOptions = { 0 };\n    faultReportOptions.stream_type = 1;\n    faultReportOptions.console_level = 0xFFFFFFFFFFFFFFFF;\n    driverFaultReporter = CCStream::withPipeAndName(driverSnapshotsPipe, \"FaultReporter\", &faultReportOptions);\n    XYLog(\"%s driverFaultReporterRet %d\\n\", __FUNCTION__, driverFaultReporter != NULL);\n    return driverLogPipe && driverDataPathPipe && driverSnapshotsPipe && driverFaultReporter;\n}\n\nbool AirportItlwm::start(IOService *provider)\n{\n    XYLog(\"%s\\n\", __PRETTY_FUNCTION__);\n    struct IOSkywalkEthernetInterface::RegistrationInfo registInfo;\n    int boot_value = 0;\n    \n    UInt8 builtIn = 0;\n    setProperty(\"built-in\", OSData::withBytes(&builtIn, sizeof(builtIn)));\n    setProperty(\"DriverKitDriver\", kOSBooleanFalse);\n    if (!super::start(provider)) {\n        return false;\n    }\n    pciNub->setBusMasterEnable(true);\n    pciNub->setIOEnable(true);\n    pciNub->setMemoryEnable(true);\n    pciNub->configWrite8(0x41, 0);\n    if (pciNub->requestPowerDomainState(kIOPMPowerOn,\n                                        (IOPowerConnection *) getParentEntry(gIOPowerPlane), IOPMLowestState) != IOPMNoErr) {\n        super::stop(provider);\n        return false;\n    }\n    if (initPCIPowerManagment(pciNub) == false) {\n        super::stop(pciNub);\n        return false;\n    }\n    if (_fWorkloop == NULL) {\n        XYLog(\"No _fWorkloop!!\\n\");\n        super::stop(pciNub);\n        releaseAll();\n        return false;\n    }\n    _fCommandGate = IOCommandGate::commandGate(this, (IOCommandGate::Action)AirportItlwm::tsleepHandler);\n    if (_fCommandGate == 0) {\n        XYLog(\"No command gate!!\\n\");\n        super::stop(pciNub);\n        releaseAll();\n        return false;\n    }\n    _fWorkloop->addEventSource(_fCommandGate);\n    const IONetworkMedium *primaryMedium;\n    if (!createMediumTables(&primaryMedium) ||\n        !setCurrentMedium(primaryMedium) || !setSelectedMedium(primaryMedium)) {\n        XYLog(\"setup medium fail\\n\");\n        releaseAll();\n        return false;\n    }\n    fHalService->initWithController(this, _fWorkloop, _fCommandGate);\n    fHalService->get80211Controller()->ic_event_handler = eventHandler;\n    \n    if (PE_parse_boot_argn(\"-novht\", &boot_value, sizeof(boot_value)))\n        fHalService->get80211Controller()->ic_userflags |= IEEE80211_F_NOVHT;\n    if (PE_parse_boot_argn(\"-noht40\", &boot_value, sizeof(boot_value)))\n        fHalService->get80211Controller()->ic_userflags |= IEEE80211_F_NOHT40;\n    \n    if (!fHalService->attach(pciNub)) {\n        XYLog(\"attach fail\\n\");\n        super::stop(pciNub);\n        releaseAll();\n        return false;\n    }\n    fWatchdogWorkLoop = IOWorkLoop::workLoop();\n    if (fWatchdogWorkLoop == NULL) {\n        XYLog(\"init watchdog workloop fail\\n\");\n        fHalService->detach(pciNub);\n        super::stop(pciNub);\n        releaseAll();\n        return false;\n    }\n    watchdogTimer = IOTimerEventSource::timerEventSource(this, OSMemberFunctionCast(IOTimerEventSource::Action, this, &AirportItlwm::watchdogAction));\n    if (!watchdogTimer) {\n        XYLog(\"init watchdog fail\\n\");\n        fHalService->detach(pciNub);\n        super::stop(pciNub);\n        releaseAll();\n        return false;\n    }\n    fWatchdogWorkLoop->addEventSource(watchdogTimer);\n    scanSource = IOTimerEventSource::timerEventSource(this, &fakeScanDone);\n    _fWorkloop->addEventSource(scanSource);\n    scanSource->enable();\n\n    fNetIf = new AirportItlwmSkywalkInterface;\n    if (!fNetIf->init(this)) {\n        XYLog(\"Skywalk interface init fail\\n\");\n        super::stop(provider);\n        releaseAll();\n        return false;\n    }\n    fNetIf->setInterfaceRole(1);\n    fNetIf->setInterfaceId(1);\n    \n    if (!initCCLogs()) {\n        XYLog(\"CCLog init fail\\n\");\n        super::stop(provider);\n        releaseAll();\n        return false;\n    }\n    if (!fNetIf->attach(this)) {\n        XYLog(\"attach to service fail\\n\");\n        super::stop(provider);\n        releaseAll();\n        return false;\n    }\n    if (!attachInterface(fNetIf, this)) {\n        XYLog(\"attach to interface fail\\n\");\n        super::stop(provider);\n        releaseAll();\n        return false;\n    }\n    if (!IONetworkController::attachInterface((IONetworkInterface **)&bsdInterface, true)) {\n        XYLog(\"attach to IONetworkController interface fail\\n\");\n        super::stop(provider);\n        releaseAll();\n        return false;\n    }\n    memset(&registInfo, 0, sizeof(registInfo));\n    if (!fNetIf->initRegistrationInfo(&registInfo, 1, sizeof(registInfo))) {\n        XYLog(\"initRegistrationInfo fail\\n\");\n        super::stop(provider);\n        releaseAll();\n        return false;\n    }\n    if (!fNetIf->initRegistrationInfo(&registInfo, 1, sizeof(registInfo))) {\n        XYLog(\"initRegistrationInfo fail\\n\");\n        super::stop(provider);\n        releaseAll();\n        return false;\n    }\n    fNetIf->mExpansionData->fRegistrationInfo = (struct IOSkywalkNetworkInterface::RegistrationInfo *)IOMalloc(sizeof(struct IOSkywalkNetworkInterface::RegistrationInfo));\n    fNetIf->mExpansionData2->fRegistrationInfo = (struct IOSkywalkEthernetInterface::RegistrationInfo *)IOMalloc(sizeof(struct IOSkywalkEthernetInterface::RegistrationInfo));\n    memcpy(fNetIf->mExpansionData->fRegistrationInfo, &registInfo, sizeof(registInfo));\n    memcpy(fNetIf->mExpansionData2->fRegistrationInfo, &registInfo, sizeof(registInfo));\n    if (fNetIf->getInterfaceRole() == 1)\n        fNetIf->deferBSDAttach(true);\n    fNetIf->start(this);\n    \n    setLinkStatus(kIONetworkLinkValid);\n    if (TAILQ_EMPTY(&fHalService->get80211Controller()->ic_ess))\n        fHalService->get80211Controller()->ic_flags |= IEEE80211_F_AUTO_JOIN;\n    registerService();\n    return true;\n}\n\nvoid AirportItlwm::stop(IOService *provider)\n{\n    XYLog(\"%s\\n\", __PRETTY_FUNCTION__);XYLog(\"%s\\n\", __PRETTY_FUNCTION__);\n    struct _ifnet *ifp = &fHalService->get80211Controller()->ic_ac.ac_if;\n    super::stop(provider);\n    disableAdapter(bsdInterface);\n    setLinkStatus(kIONetworkLinkValid);\n    fHalService->detach(pciNub);\n    ether_ifdetach(ifp);\n    detachInterface(fNetIf, true);\n    OSSafeReleaseNULL(fNetIf);\n    releaseAll();\n}\n\nvoid AirportItlwm::free()\n{\n    XYLog(\"%s\\n\", __PRETTY_FUNCTION__);\n    if (fHalService != NULL) {\n        fHalService->release();\n        fHalService = NULL;\n    }\n    if (syncFrameTemplate != NULL && syncFrameTemplateLength > 0) {\n        IOFree(syncFrameTemplate, syncFrameTemplateLength);\n        syncFrameTemplateLength = 0;\n        syncFrameTemplate = NULL;\n    }\n    if (roamProfile != NULL) {\n        IOFree(roamProfile, sizeof(struct apple80211_roam_profile_band_data));\n        roamProfile = NULL;\n    }\n    if (btcProfile != NULL) {\n        IOFree(btcProfile, sizeof(struct apple80211_btc_profiles_data));\n        btcProfile = NULL;\n    }\n    super::free();\n}\n\nbool AirportItlwm::createWorkQueue()\n{\n    XYLog(\"%s %d\\n\", __FUNCTION__, _fWorkloop != 0);\n    return _fWorkloop != 0;\n}\n\nIO80211WorkQueue *AirportItlwm::getWorkQueue()\n{\n    return _fWorkloop;\n}\n\nvoid *AirportItlwm::getFaultReporterFromDriver()\n{\n    return driverFaultReporter;\n}\n\nIOReturn AirportItlwm::enable(IO80211SkywalkInterface *netif)\n{\n    XYLog(\"%s\\n\", __PRETTY_FUNCTION__);\n    super::enable(netif);\n    _fCommandGate->enable();\n    if (power_state)\n        enableAdapter(bsdInterface);\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::disable(IO80211SkywalkInterface *netif)\n{\n    XYLog(\"%s\\n\", __PRETTY_FUNCTION__);\n    super::disable(netif);\n    setLinkStatus(kIONetworkLinkValid);\n    return kIOReturnSuccess;\n}\n\nbool AirportItlwm::configureInterface(IONetworkInterface *netif)\n{\n    IONetworkData *nd;\n    struct _ifnet *ifp = &fHalService->get80211Controller()->ic_ac.ac_if;\n    \n    if (super::configureInterface(netif) == false) {\n        XYLog(\"super failed\\n\");\n        return false;\n    }\n    \n    nd = netif->getParameter(kIONetworkStatsKey);\n    if (!nd || !(fpNetStats = (IONetworkStats *)nd->getBuffer())) {\n        XYLog(\"network statistics buffer unavailable?\\n\");\n        return false;\n    }\n    ifp->netStat = fpNetStats;\n    ether_ifattach(ifp, OSDynamicCast(IOEthernetInterface, netif));\n    fpNetStats->collisions = 0;\n#ifdef __PRIVATE_SPI__\n    netif->configureOutputPullModel(fHalService->getDriverInfo()->getTxQueueSize(), 0, 0, IOEthernetInterface::kOutputPacketSchedulingModelNormal, 0);\n#endif\n    \n    return true;\n}\n\nIONetworkInterface *AirportItlwm::createInterface()\n{\n    AirportItlwmEthernetInterface *netif = new AirportItlwmEthernetInterface;\n    if (!netif)\n        return NULL;\n    if (!netif->initWithSkywalkInterfaceAndProvider(this, fNetIf)) {\n        netif->release();\n        return NULL;\n    }\n    return netif;\n}\n\nbool AirportItlwm::createMediumTables(const IONetworkMedium **primary)\n{\n    IONetworkMedium    *medium;\n\n    OSDictionary *mediumDict = OSDictionary::withCapacity(2);\n    if (mediumDict == NULL) {\n        XYLog(\"Cannot allocate OSDictionary\\n\");\n        return false;\n    }\n    \n    medium = IONetworkMedium::medium(kIOMediumIEEE80211, 54000000);\n    IONetworkMedium::addMedium(mediumDict, medium);\n    medium->release();\n    if (primary) {\n        *primary = medium;\n    }\n    medium = IONetworkMedium::medium(kIOMediumIEEE80211None, 0);\n    IONetworkMedium::addMedium(mediumDict, medium);\n    medium->release();\n    \n    bool result = publishMediumDictionary(mediumDict);\n    if (!result) {\n        XYLog(\"Cannot publish medium dictionary!\\n\");\n    }\n\n    mediumDict->release();\n    return result;\n}\n\nIOReturn AirportItlwm::selectMedium(const IONetworkMedium *medium) {\n    setSelectedMedium(medium);\n    return kIOReturnSuccess;\n}\n\nbool AirportItlwm::\nsetLinkStatus(UInt32 status, const IONetworkMedium * activeMedium, UInt64 speed, OSData * data)\n{\n    struct _ifnet *ifq = &fHalService->get80211Controller()->ic_ac.ac_if;\n    if (status == currentStatus) {\n        return true;\n    }\n    bool ret = super::setLinkStatus(status, activeMedium, speed, data);\n    currentStatus = status;\n    if (fNetIf) {\n        if (status & kIONetworkLinkActive) {\n#ifdef __PRIVATE_SPI__\n            bsdInterface->startOutputThread();\n#endif\n            getCommandGate()->runAction(setLinkStateGated, (void *)kIO80211NetworkLinkUp, (void *)0);\n//            fNetIf->setLinkQualityMetric(100);\n        } else if (!(status & kIONetworkLinkNoNetworkChange)) {\n#ifdef __PRIVATE_SPI__\n            bsdInterface->stopOutputThread();\n            bsdInterface->flushOutputQueue();\n#endif\n            ifq_flush(&ifq->if_snd);\n            mq_purge(&fHalService->get80211Controller()->ic_mgtq);\n            getCommandGate()->runAction(setLinkStateGated, (void *)kIO80211NetworkLinkDown, (void *)fHalService->get80211Controller()->ic_deauth_reason);\n        }\n    }\n    return ret;\n}\n\nIOReturn AirportItlwm::\nsetLinkStateGated(OSObject *target, void *arg0, void *arg1, void *arg2, void *arg3)\n{\n    AirportItlwm *that = OSDynamicCast(AirportItlwm, target);\n    IOReturn ret = that->fNetIf->setLinkState((IO80211LinkState)(uint64_t)arg0, (unsigned int)(uint64_t)arg1);\n    that->fNetIf->setRunningState((IO80211LinkState)(uint64_t)arg0 == kIO80211NetworkLinkUp);\n    that->fNetIf->postMessage(APPLE80211_M_LINK_CHANGED, NULL, 0, false);\n    that->fNetIf->postMessage(APPLE80211_M_BSSID_CHANGED, NULL, 0, false);\n    that->fNetIf->postMessage(APPLE80211_M_SSID_CHANGED, NULL, 0, false);\n    if ((IO80211LinkState)(uint64_t)arg0 == kIO80211NetworkLinkUp) {\n        that->fNetIf->reportLinkStatus(3, 0x80);\n    } else {\n        that->fNetIf->reportLinkStatus(1, 0);\n    }\n    that->bsdInterface->setLinkState((IO80211LinkState)(uint64_t)arg0);\n    return ret;\n}\n\n#ifdef __PRIVATE_SPI__\nIOReturn AirportItlwm::outputStart(IONetworkInterface *interface, IOOptionBits options)\n{\n    struct _ifnet *ifp = &fHalService->get80211Controller()->ic_ac.ac_if;\n    mbuf_t m = NULL;\n    if (ifq_is_oactive(&ifp->if_snd))\n        return kIOReturnNoResources;\n    while (kIOReturnSuccess == interface->dequeueOutputPackets(1, &m)) {\n        if (outputPacket(m, NULL)!= kIOReturnOutputSuccess ||\n            ifq_is_oactive(&ifp->if_snd))\n            return kIOReturnNoResources;\n    }\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::networkInterfaceNotification(\n                    IONetworkInterface * interface,\n                    uint32_t              type,\n                    void *                  argument )\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    return kIOReturnSuccess;\n}\n#endif\n\nextern const char* hexdump(uint8_t *buf, size_t len);\n\nUInt32 AirportItlwm::outputPacket(mbuf_t m, void *param)\n{\n//    XYLog(\"%s\\n\", __FUNCTION__);\n    IOReturn ret = kIOReturnOutputSuccess;\n    struct _ifnet *ifp = &fHalService->get80211Controller()->ic_ac.ac_if;\n    \n    if (fHalService->get80211Controller()->ic_state != IEEE80211_S_RUN || ifp->if_snd.queue == NULL) {\n        if (m && mbuf_type(m) != MBUF_TYPE_FREE)\n            freePacket(m);\n        return kIOReturnOutputDropped;\n    }\n    if (m == NULL) {\n        XYLog(\"%s m==NULL!!\\n\", __FUNCTION__);\n        ifp->netStat->outputErrors++;\n        ret = kIOReturnOutputDropped;\n    }\n    if (!(mbuf_flags(m) & MBUF_PKTHDR) ){\n        XYLog(\"%s pkthdr is NULL!!\\n\", __FUNCTION__);\n        ifp->netStat->outputErrors++;\n        freePacket(m);\n        ret = kIOReturnOutputDropped;\n    }\n    if (mbuf_type(m) == MBUF_TYPE_FREE) {\n        XYLog(\"%s mbuf is FREE!!\\n\", __FUNCTION__);\n        ifp->netStat->outputErrors++;\n        ret = kIOReturnOutputDropped;\n    }\n    size_t len = mbuf_len(m);\n    ether_header_t *eh = (ether_header_t *)mbuf_data(m);\n    if (len >= sizeof(ether_header_t) && eh->ether_type == htons(ETHERTYPE_PAE)) { // EAPOL packet\n        const char* dump = hexdump((uint8_t*)mbuf_data(m), len);\n        XYLog(\"output EAPOL packet, len: %zu, data: %s\\n\", len, dump ? dump : \"Failed to allocate memory\");\n        if (dump)\n            IOFree((void*)dump, 3 * len + 1);\n    }\n    if (!ifp->if_snd.queue->lockEnqueue(m)) {\n        freePacket(m);\n        ret = kIOReturnOutputDropped;\n    }\n    (*ifp->if_start)(ifp);\n    return ret;\n}\n\nconst OSString * AirportItlwm::newVendorString() const\n{\n    return OSString::withCString(\"Apple\");\n}\n\nconst OSString * AirportItlwm::newModelString() const\n{\n    return OSString::withCString(fHalService->getDriverInfo()->getFirmwareName());\n}\n\nIOReturn AirportItlwm::getHardwareAddress(IOEthernetAddress *addrP)\n{\n    if (IEEE80211_ADDR_EQ(etheranyaddr, fHalService->get80211Controller()->ic_myaddr))\n        return kIOReturnError;\n    else {\n        IEEE80211_ADDR_COPY(addrP, fHalService->get80211Controller()->ic_myaddr);\n        return kIOReturnSuccess;\n    }\n}\n\nIOReturn AirportItlwm::setHardwareAddress(const void *addrP, UInt32 addrBytes)\n{\n    if (!fNetIf || !addrP)\n        return kIOReturnError;\n    if_setlladdr(&fHalService->get80211Controller()->ic_ac.ac_if, (const UInt8 *)addrP);\n    if (fHalService->get80211Controller()->ic_state > IEEE80211_S_INIT) {\n        fHalService->disable(bsdInterface);\n        fHalService->enable(bsdInterface);\n    }\n    return kIOReturnSuccess;\n}\n\nUInt32 AirportItlwm::getFeatures() const\n{\n    return fHalService->getDriverInfo()->supportedFeatures();\n}\n\nIOReturn AirportItlwm::setPromiscuousMode(IOEnetPromiscuousMode mode)\n{\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::setMulticastMode(IOEnetMulticastMode mode)\n{\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::setMulticastList(IOEthernetAddress* addr, UInt32 len)\n{\n    return fHalService->getDriverController()->setMulticastList(addr, len);\n}\n\nIOReturn AirportItlwm::getPacketFilters(const OSSymbol *group, UInt32 *filters) const\n{\n    IOReturn    rtn = kIOReturnSuccess;\n    if (group == gIOEthernetWakeOnLANFilterGroup && magicPacketSupported)\n        *filters = kIOEthernetWakeOnMagicPacket;\n    else if (group == gIONetworkFilterGroup)\n        *filters = kIOPacketFilterMulticast | kIOPacketFilterPromiscuous;\n    else\n        rtn = IOEthernetController::getPacketFilters(group, filters);\n    return rtn;\n}\n\nSInt32 AirportItlwm::\nenableFeature(IO80211FeatureCode code, void *data)\n{\n    if (code == kIO80211Feature80211n) {\n        return 0;\n    }\n    return 102;\n}\n\nbool AirportItlwm::getLogPipes(CCPipe**logPipe, CCPipe**eventPipe, CCPipe**snapshotsPipe)\n{\n    bool ret = false;\n    if (logPipe) {\n        *logPipe = driverLogPipe;\n        ret = true;\n    }\n    if (eventPipe) {\n        *eventPipe = driverDataPathPipe;\n        ret = true;\n    }\n    if (snapshotsPipe) {\n        *snapshotsPipe = driverSnapshotsPipe;\n        ret = true;\n    }\n    return ret;\n}\n\n#define APPLE80211_CAPA_AWDL_FEATURE_AUTO_UNLOCK    0x00000004\n#define APPLE80211_CAPA_AWDL_FEATURE_WOW            0x00000080\n\nIOReturn AirportItlwm::\ngetCARD_CAPABILITIES(OSObject *object,\n                                     struct apple80211_capability_data *cd)\n{\n    uint32_t caps = fHalService->get80211Controller()->ic_caps;\n    memset(cd, 0, sizeof(struct apple80211_capability_data));\n    \n    if (caps & IEEE80211_C_WEP)\n        cd->capabilities[0] |= 1 << APPLE80211_CAP_WEP;\n    if (caps & IEEE80211_C_RSN)\n        cd->capabilities[0] |= 1 << APPLE80211_CAP_TKIP | 1 << APPLE80211_CAP_AES_CCM;\n    // Disable not implemented capabilities\n    // if (caps & IEEE80211_C_PMGT)\n    //     cd->capabilities[0] |= 1 << APPLE80211_CAP_PMGT;\n    // if (caps & IEEE80211_C_IBSS)\n    //     cd->capabilities[0] |= 1 << APPLE80211_CAP_IBSS;\n    // if (caps & IEEE80211_C_HOSTAP)\n    //     cd->capabilities[0] |= 1 << APPLE80211_CAP_HOSTAP;\n    // AES not enabled, like on Apple cards\n    \n    if (caps & IEEE80211_C_SHSLOT)\n        cd->capabilities[1] |= 1 << (APPLE80211_CAP_SHSLOT - 8);\n    if (caps & IEEE80211_C_SHPREAMBLE)\n        cd->capabilities[1] |= 1 << (APPLE80211_CAP_SHPREAMBLE - 8);\n    if (caps & IEEE80211_C_RSN)\n        cd->capabilities[1] |= 1 << (APPLE80211_CAP_WPA1 - 8) | 1 << (APPLE80211_CAP_WPA2 - 8) | 1 << (APPLE80211_CAP_TKIPMIC - 8);\n    // Disable not implemented capabilities\n    // if (caps & IEEE80211_C_TXPMGT)\n    //     cd->capabilities[1] |= 1 << (APPLE80211_CAP_TXPMGT - 8);\n    // if (caps & IEEE80211_C_MONITOR)\n    //     cd->capabilities[1] |= 1 << (APPLE80211_CAP_MONITOR - 8);\n    // WPA not enabled, like on Apple cards\n\n    cd->version = APPLE80211_VERSION;\n    cd->capabilities[2] = 0xFF; // BURST, WME, SHORT_GI_40MHZ, SHORT_GI_20MHZ, WOW, TSN, ?, ?\n    cd->capabilities[3] = 0x2B;\n    cd->capabilities[5] = 0x40;\n    cd->capabilities[6] = (\n//                           1 |    //MFP capable\n                           0x8 |\n                           0x4 |\n                           0x80\n                           );\n    *(uint16_t *)&cd->capabilities[8] = 0x201;\n//\n//    cd->capabilities[2] |= 0x10;\n//    cd->capabilities[5] |= 0x1;\n//\n//    cd->capabilities[2] |= 0x2;\n//\n//    cd->capabilities[3] |= 0x20;\n//\n//    cd->capabilities[0] |= 0x80;\n//\n//    cd->capabilities[3] |= 0x80;\n//    cd->capabilities[4] |= 0x4;\n//\n//    cd->capabilities[4] |= 0x1;\n//    cd->capabilities[3] |= 0x1;\n//    cd->capabilities[6] |= 0x8;\n//\n//    cd->capabilities[3] |= 3;\n//    cd->capabilities[4] |= 2;\n//    cd->capabilities[6] |= 0x10;\n//    cd->capabilities[5] |= 0x20;\n//    cd->capabilities[5] |= 0x80;\n//\n//    if (cd->capabilities[6] & 0x20) {\n//        cd->capabilities[2] |= 8;\n//    }\n//    cd->capabilities[5] |= 8;\n//    cd->capabilities[8] |= 2;\n//\n//    cd->capabilities[11] |= (2 | 4 | 8 | 0x10 | 0x20 | 0x40 | 0x80);\n    \n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetDRIVER_VERSION(OSObject *object,\n                                  struct apple80211_version_data *hv)\n{\n    if (!hv)\n        return kIOReturnError;\n    hv->version = APPLE80211_VERSION;\n    snprintf(hv->string, sizeof(hv->string), \"itlwm: %s%s fw: %s\", ITLWM_VERSION, GIT_COMMIT, fHalService->getDriverInfo()->getFirmwareVersion());\n    hv->string_len = strlen(hv->string);\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetHARDWARE_VERSION(OSObject *object,\n                                    struct apple80211_version_data *hv)\n{\n    if (!hv)\n        return kIOReturnError;\n    hv->version = APPLE80211_VERSION;\n    strncpy(hv->string, fHalService->getDriverInfo()->getFirmwareVersion(), sizeof(hv->string));\n    hv->string_len = strlen(fHalService->getDriverInfo()->getFirmwareVersion());\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetCOUNTRY_CODE(OSObject *object,\n                                struct apple80211_country_code_data *cd)\n{\n    char user_override_cc[3];\n    const char *cc_fw = fHalService->getDriverInfo()->getFirmwareCountryCode();\n    \n    if (!cd)\n        return kIOReturnError;\n    cd->version = APPLE80211_VERSION;\n    memset(user_override_cc, 0, sizeof(user_override_cc));\n    PE_parse_boot_argn(\"itlwm_cc\", user_override_cc, 3);\n    /* user_override_cc > firmware_cc > geo_location_cc */\n    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));\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\nsetCOUNTRY_CODE(OSObject *object, struct apple80211_country_code_data *data)\n{\n    XYLog(\"%s cc=%s\\n\", __FUNCTION__, data->cc);\n    if (data && data->cc[0] != 120 && data->cc[0] != 88) {\n        memcpy(geo_location_cc, data->cc, sizeof(geo_location_cc));\n        fNetIf->postMessage(APPLE80211_M_COUNTRY_CODE_CHANGED, NULL, 0, 0);\n    }\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetPOWER(OSObject *object,\n                         struct apple80211_power_data *pd)\n{\n    if (!pd)\n        return kIOReturnError;\n    pd->version = APPLE80211_VERSION;\n    pd->num_radios = 4;\n    pd->power_state[0] = power_state;\n    pd->power_state[1] = power_state;\n    pd->power_state[2] = power_state;\n    pd->power_state[3] = power_state;\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\nsetPOWER(OSObject *object,\n                         struct apple80211_power_data *pd)\n{\n    if (!pd)\n        return kIOReturnError;\n    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]);\n    if (pd->num_radios > 0) {\n        bool isRunning = (fHalService->get80211Controller()->ic_ac.ac_if.if_flags & (IFF_UP | IFF_RUNNING)) != 0;\n        if (pd->power_state[0] == 0) {\n            changePowerStateToPriv(1);\n            if (isRunning) {\n                net80211_ifstats(fHalService->get80211Controller());\n                disableAdapter(bsdInterface);\n            }\n        } else {\n            changePowerStateToPriv(2);\n            if (!isRunning)\n                enableAdapter(bsdInterface);\n        }\n        power_state = (pd->power_state[0]);\n    }\n    \n    return kIOReturnSuccess;\n}\n\nSInt32 AirportItlwm::apple80211_ioctl(IO80211SkywalkInterface *interface,unsigned long cmd,void *data, bool b1, bool b2)\n{\n    if (!ml_at_interrupt_context())\n        XYLog(\"%s cmd: %s b1: %d b2: %d\\n\", __FUNCTION__, convertApple80211IOCTLToString((unsigned int)cmd), b1, b2);\n    return super::apple80211_ioctl(interface, cmd, data, b1, b2);\n}\n\nSInt32 AirportItlwm::apple80211SkywalkRequest(UInt request,int cmd,IO80211SkywalkInterface *interface,void *data)\n{\n    if (!ml_at_interrupt_context())\n        XYLog(\"%s 1 cmd: %s request: %d\\n\", __FUNCTION__, convertApple80211IOCTLToString(cmd), request);\n    return kIOReturnUnsupported;\n}\n\nSInt32 AirportItlwm::apple80211SkywalkRequest(UInt request,int cmd,IO80211SkywalkInterface *interface,void *data,void *)\n{\n    if (!ml_at_interrupt_context())\n        XYLog(\"%s 2 cmd: %s request: %d\\n\", __FUNCTION__, convertApple80211IOCTLToString(cmd), request);\n    return kIOReturnUnsupported;\n}\n\nIOReturn AirportItlwm::enableAdapter(IONetworkInterface *netif)\n{\n    fHalService->enable(netif);\n    watchdogTimer->setTimeoutMS(kWatchDogTimerPeriod);\n    watchdogTimer->enable();\n    return kIOReturnSuccess;\n}\n\nvoid AirportItlwm::disableAdapter(IONetworkInterface *netif)\n{\n    watchdogTimer->cancelTimeout();\n    watchdogTimer->disable();\n    fHalService->disable(netif);\n}\n\nIOReturn AirportItlwm::\ntsleepHandler(OSObject* owner, void* arg0, void* arg1, void* arg2, void* arg3)\n{\n    AirportItlwm* dev = OSDynamicCast(AirportItlwm, owner);\n    if (dev == 0)\n        return kIOReturnError;\n    \n    if (arg1 == 0) {\n        if (_fCommandGate->commandSleep(arg0, THREAD_INTERRUPTIBLE) == THREAD_AWAKENED)\n            return kIOReturnSuccess;\n        else\n            return kIOReturnTimeout;\n    } else {\n        AbsoluteTime deadline;\n        clock_interval_to_deadline((*(int*)arg1), kNanosecondScale, reinterpret_cast<uint64_t*> (&deadline));\n        if (_fCommandGate->commandSleep(arg0, deadline, THREAD_INTERRUPTIBLE) == THREAD_AWAKENED)\n            return kIOReturnSuccess;\n        else\n            return kIOReturnTimeout;\n    }\n}\n\nbool AirportItlwm::initPCIPowerManagment(IOPCIDevice *provider)\n{\n    UInt16 reg16;\n\n    reg16 = provider->configRead16(kIOPCIConfigCommand);\n\n    reg16 |= ( kIOPCICommandBusMaster       |\n               kIOPCICommandMemorySpace     |\n               kIOPCICommandMemWrInvalidate );\n\n    reg16 &= ~kIOPCICommandIOSpace;  // disable I/O space\n\n    provider->configWrite16( kIOPCIConfigCommand, reg16 );\n    provider->findPCICapability(kIOPCIPowerManagementCapability,\n                                &pmPCICapPtr);\n    if (pmPCICapPtr) {\n        UInt16 pciPMCReg = provider->configRead32( pmPCICapPtr ) >> 16;\n        if (pciPMCReg & kPCIPMCPMESupportFromD3Cold)\n            magicPacketSupported = true;\n        provider->configWrite16((pmPCICapPtr + 4), 0x8000 );\n        IOSleep(10);\n    }\n    return true;\n}\n\nstatic IOPMPowerState powerStateArray[kPowerStateCount] =\n{\n    {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},\n    {1, kIOPMDeviceUsable, kIOPMPowerOn, kIOPMPowerOn, 0, 0, 0, 0, 0, 0, 0, 0}\n};\n\nvoid AirportItlwm::unregistPM()\n{\n    if (powerOffThreadCall) {\n        thread_call_free(powerOffThreadCall);\n        powerOffThreadCall = NULL;\n    }\n    if (powerOnThreadCall) {\n        thread_call_free(powerOnThreadCall);\n        powerOnThreadCall = NULL;\n    }\n}\n\nIOReturn AirportItlwm::setPowerState(unsigned long powerStateOrdinal, IOService *policyMaker)\n{\n    IOReturn result = IOPMAckImplied;\n    \n    if (pmPowerState == powerStateOrdinal)\n        return result;\n    switch (powerStateOrdinal) {\n        case kPowerStateOff:\n            if (powerOffThreadCall) {\n                retain();\n                if (thread_call_enter(powerOffThreadCall))\n                    release();\n                result = 5000000;\n            }\n            break;\n        case kPowerStateOn:\n            if (powerOnThreadCall) {\n                retain();\n                if (thread_call_enter(powerOnThreadCall))\n                    release();\n                result = 5000000;\n            }\n            break;\n            \n        default:\n            break;\n    }\n    return result;\n}\n\nIOReturn AirportItlwm::setWakeOnMagicPacket(bool active)\n{\n    magicPacketEnabled = active;\n    return kIOReturnSuccess;\n}\n\nstatic void handleSetPowerStateOff(thread_call_param_t param0,\n                             thread_call_param_t param1)\n{\n    AirportItlwm *self = (AirportItlwm *)param0;\n\n    if (param1 == 0)\n    {\n        self->getCommandGate()->runAction((IOCommandGate::Action)\n                                           handleSetPowerStateOff,\n                                           (void *) 1);\n    }\n    else\n    {\n        self->setPowerStateOff();\n        self->release();\n    }\n}\n\nstatic void handleSetPowerStateOn(thread_call_param_t param0,\n                            thread_call_param_t param1)\n{\n    AirportItlwm *self = (AirportItlwm *) param0;\n\n    if (param1 == 0)\n    {\n        self->getCommandGate()->runAction((IOCommandGate::Action)\n                                           handleSetPowerStateOn,\n                                           (void *) 1);\n    }\n    else\n    {\n        self->setPowerStateOn();\n        self->release();\n    }\n}\n\nIOReturn AirportItlwm::registerWithPolicyMaker(IOService *policyMaker)\n{\n    IOReturn ret;\n    \n    pmPowerState = kPowerStateOn;\n    pmPolicyMaker = policyMaker;\n    \n    powerOffThreadCall = thread_call_allocate(\n                                            (thread_call_func_t)handleSetPowerStateOff,\n                                            (thread_call_param_t)this);\n    powerOnThreadCall  = thread_call_allocate(\n                                            (thread_call_func_t)handleSetPowerStateOn,\n                                              (thread_call_param_t)this);\n    ret = pmPolicyMaker->registerPowerDriver(this,\n                                             powerStateArray,\n                                             kPowerStateCount);\n    return ret;\n}\n\nvoid AirportItlwm::setPowerStateOff()\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    pmPowerState = kPowerStateOff;\n    disableAdapter(bsdInterface);\n    pmPolicyMaker->acknowledgeSetPowerState();\n}\n\nvoid AirportItlwm::setPowerStateOn()\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    pmPowerState = kPowerStateOn;\n    pmPolicyMaker->acknowledgeSetPowerState();\n}\n"
  },
  {
    "path": "AirportItlwm/AirportItlwmV2.hpp",
    "content": "//\n//  AirportItlwmV2.hpp\n//  AirportItlwm-Sonoma\n//\n//  Created by qcwap on 2023/6/27.\n//  Copyright © 2023 钟先耀. All rights reserved.\n//\n\n#ifndef AirportItlwmV2_hpp\n#define AirportItlwmV2_hpp\n\n#include \"Apple80211.h\"\n\n#include \"IOKit/network/IOGatedOutputQueue.h\"\n#include <libkern/c++/OSString.h>\n#include <IOKit/IOService.h>\n#include <IOKit/pci/IOPCIDevice.h>\n#include <IOKit/IOLib.h>\n#include <libkern/OSKextLib.h>\n#include <libkern/c++/OSMetaClass.h>\n#include <IOKit/IOFilterInterruptEventSource.h>\n\n#include \"ItlIwm.hpp\"\n#include \"ItlIwx.hpp\"\n#include \"ItlIwn.hpp\"\n\n#include \"AirportItlwmEthernetInterface.hpp\"\n\nenum\n{\n    kPowerStateOff = 0,\n    kPowerStateOn,\n    kPowerStateCount\n};\n\n#define kWatchDogTimerPeriod 1000\n\nextern \"C\" {\nconst char *convertApple80211IOCTLToString(signed int cmd);\n}\n\nclass AirportItlwm : public IO80211Controller {\n    OSDeclareDefaultStructors(AirportItlwm)\n#define IOCTL(REQ_TYPE, REQ, DATA_TYPE) \\\nif (REQ_TYPE == SIOCGA80211) { \\\nret = get##REQ(interface, (struct DATA_TYPE* )data); \\\n} else { \\\nret = set##REQ(interface, (struct DATA_TYPE* )data); \\\n}\n    \n#define IOCTL_GET(REQ_TYPE, REQ, DATA_TYPE) \\\nif (REQ_TYPE == SIOCGA80211) { \\\nret = get##REQ(interface, (struct DATA_TYPE* )data); \\\n}\n#define IOCTL_SET(REQ_TYPE, REQ, DATA_TYPE) \\\nif (REQ_TYPE == SIOCSA80211) { \\\nret = set##REQ(interface, (struct DATA_TYPE* )data); \\\n}\n#define FUNC_IOCTL(REQ, DATA_TYPE) \\\nFUNC_IOCTL_GET(REQ, DATA_TYPE) \\\nFUNC_IOCTL_SET(REQ, DATA_TYPE)\n#define FUNC_IOCTL_GET(REQ, DATA_TYPE) \\\nIOReturn get##REQ(OSObject *object, struct DATA_TYPE *data);\n#define FUNC_IOCTL_SET(REQ, DATA_TYPE) \\\nIOReturn set##REQ(OSObject *object, struct DATA_TYPE *data);\n    \npublic:\n    virtual bool init(OSDictionary *properties) override;\n    virtual void free() override;\n    virtual IOService* probe(IOService* provider, SInt32* score) override;\n    virtual bool start(IOService *provider) override;\n    virtual void stop(IOService *provider) override;\n    virtual IOReturn enable(IO80211SkywalkInterface *netif) override;\n    virtual IOReturn disable(IO80211SkywalkInterface *netif) override;\n    virtual IOReturn setHardwareAddress(const void *addr, UInt32 addrBytes) override;\n    virtual IOReturn getHardwareAddress(IOEthernetAddress* addrP) override;\n    virtual IOReturn getPacketFilters(const OSSymbol *group, UInt32 *filters) const override;\n    virtual IOReturn setPromiscuousMode(IOEnetPromiscuousMode mode) override;\n    virtual IOReturn setMulticastMode(IOEnetMulticastMode mode) override;\n    virtual IOReturn setMulticastList(IOEthernetAddress* addr, UInt32 len) override;\n    virtual UInt32 getFeatures() const override;\n    virtual const OSString * newVendorString() const override;\n    virtual const OSString * newModelString() const override;\n    virtual IOReturn selectMedium(const IONetworkMedium *medium) override;\n    virtual bool createWorkQueue() override;\n    virtual IONetworkInterface * createInterface() override;\n    virtual bool configureInterface(IONetworkInterface *netif) override;\n    virtual UInt32 outputPacket(mbuf_t, void * param) override;\n#ifdef __PRIVATE_SPI__\n    virtual IOReturn outputStart(IONetworkInterface *interface, IOOptionBits options) override;\n    virtual IOReturn networkInterfaceNotification(\n                        IONetworkInterface * interface,\n                        uint32_t              type,\n                        void *                  argument ) override;\n#endif\n    virtual bool setLinkStatus(\n                               UInt32                  status,\n                               const IONetworkMedium * activeMedium = 0,\n                               UInt64                  speed        = 0,\n                               OSData *                data         = 0) override;\n    static IOReturn setLinkStateGated(OSObject *target, void *arg0, void *arg1, void *arg2, void *arg3);\n    \n    static IOReturn tsleepHandler(OSObject* owner, void* arg0 = 0, void* arg1 = 0, void* arg2 = 0, void* arg3 = 0);\n    static void eventHandler(struct ieee80211com *, int, void *);\n    IOReturn enableAdapter(IONetworkInterface *netif);\n    void disableAdapter(IONetworkInterface *netif);\n    bool initCCLogs();\n    \n    virtual IO80211WorkQueue *getWorkQueue() override;\n    virtual bool requiresExplicitMBufRelease() override {\n        return false;\n    }\n    virtual bool flowIdSupported() override {\n        return false;\n    }\n    virtual SInt32 monitorModeSetEnabled(bool, UInt) override {\n        return kIOReturnSuccess;\n    }\n    virtual IOReturn requestQueueSizeAndTimeout(unsigned short *queue, unsigned short *timeout) override {\n        XYLog(\"%s\\n\", __FUNCTION__);\n        return kIOReturnSuccess;\n    }\n    \n    virtual bool getLogPipes(CCPipe**, CCPipe**, CCPipe**) override;\n    \n    virtual void *getFaultReporterFromDriver() override;\n    \n    virtual SInt32 apple80211_ioctl(IO80211SkywalkInterface *,unsigned long,void *, bool, bool) override;\n    virtual SInt32 apple80211SkywalkRequest(UInt,int,IO80211SkywalkInterface *,void *) override;\n    virtual SInt32 apple80211SkywalkRequest(UInt,int,IO80211SkywalkInterface *,void *,void *) override;\n\n    bool createMediumTables(const IONetworkMedium **primary);\n    void releaseAll();\n    void watchdogAction(IOTimerEventSource *timer);\n    \n    virtual SInt32 enableFeature(IO80211FeatureCode, void*) override;\n    virtual bool isCommandProhibited(int command) override {\n//        if (!ml_at_interrupt_context())\n//            XYLog(\"%s %s\\n\", __FUNCTION__, convertApple80211IOCTLToString(command));\n        return false;\n    };\n    virtual SInt32 handleCardSpecific(IO80211SkywalkInterface *,unsigned long,void *,bool) override {\n        XYLog(\"%s\\n\", __FUNCTION__);\n        return 0;\n    };\n    virtual IOReturn getDRIVER_VERSION(IO80211SkywalkInterface *interface,apple80211_version_data *data) override {\n        XYLog(\"%s\\n\", __FUNCTION__);\n        return getDRIVER_VERSION((OSObject *)interface, data);\n    };\n    virtual IOReturn getHARDWARE_VERSION(IO80211SkywalkInterface *interface,apple80211_version_data *data) override {\n        XYLog(\"%s\\n\", __FUNCTION__);\n        return getHARDWARE_VERSION((OSObject *)interface, data);\n    };\n    virtual IOReturn getCARD_CAPABILITIES(IO80211SkywalkInterface *interface,apple80211_capability_data *data) override {\n//        XYLog(\"%s\\n\", __FUNCTION__);\n        return getCARD_CAPABILITIES((OSObject *)interface, data);\n    }\n    virtual IOReturn getPOWER(IO80211SkywalkInterface *interface,apple80211_power_data *data) override {\n//        XYLog(\"%s\\n\", __FUNCTION__);\n        return getPOWER((OSObject *)interface, data);\n    }\n    virtual IOReturn setPOWER(IO80211SkywalkInterface *interface,apple80211_power_data *data) override {\n//        XYLog(\"%s\\n\", __FUNCTION__);\n        return setPOWER((OSObject *)interface, data);\n    }\n    virtual IOReturn getCOUNTRY_CODE(IO80211SkywalkInterface *interface,apple80211_country_code_data *data) override {\n//        XYLog(\"%s\\n\", __FUNCTION__);\n        return getCOUNTRY_CODE((OSObject *)interface, data);\n    }\n    virtual IOReturn setCOUNTRY_CODE(IO80211SkywalkInterface *interface,apple80211_country_code_data *data) override {\n//        XYLog(\"%s\\n\", __FUNCTION__);\n        return setCOUNTRY_CODE((OSObject *)interface, data);\n    }\n    virtual IOReturn setGET_DEBUG_INFO(IO80211SkywalkInterface *interface,apple80211_debug_command *data) override {\n        XYLog(\"%s\\n\", __FUNCTION__);\n        return kIOReturnSuccess;\n    }\n    \n    //scan\n    static void fakeScanDone(OSObject *owner, IOTimerEventSource *sender);\n    \n    //-----------------------------------------------------------------------\n    // Power management support.\n    //-----------------------------------------------------------------------\n    virtual IOReturn registerWithPolicyMaker( IOService * policyMaker ) override;\n    virtual IOReturn setPowerState( unsigned long powerStateOrdinal,\n                                    IOService *   policyMaker) override;\n    virtual IOReturn setWakeOnMagicPacket( bool active ) override;\n    void setPowerStateOff(void);\n    void setPowerStateOn(void);\n    void unregistPM();\n    bool initPCIPowerManagment(IOPCIDevice *provider);\n\n    FUNC_IOCTL_GET(CARD_CAPABILITIES, apple80211_capability_data)\n    FUNC_IOCTL(POWER, apple80211_power_data)\n    FUNC_IOCTL_GET(DRIVER_VERSION, apple80211_version_data)\n    FUNC_IOCTL_GET(HARDWARE_VERSION, apple80211_version_data)\n    FUNC_IOCTL(COUNTRY_CODE, apple80211_country_code_data)\n    \npublic:\n    IOInterruptEventSource* fInterrupt;\n    IOTimerEventSource *watchdogTimer;\n    IOPCIDevice *pciNub;\n    IONetworkStats *fpNetStats;\n    AirportItlwmEthernetInterface *bsdInterface;\n    IO80211SkywalkInterface *fNetIf;\n    IOWorkLoop *fWatchdogWorkLoop;\n    ItlHalService *fHalService;\n    \n    //IO80211\n    uint8_t power_state;\n    struct ieee80211_node *fNextNodeToSend;\n    bool fScanResultWrapping;\n    IOTimerEventSource *scanSource;\n    \n    u_int32_t current_authtype_lower;\n    u_int32_t current_authtype_upper;\n    UInt64 currentSpeed;\n    UInt32 currentStatus;\n    bool disassocIsVoluntary;\n    char geo_location_cc[3];\n    \n    //pm\n    thread_call_t powerOnThreadCall;\n    thread_call_t powerOffThreadCall;\n    UInt32 pmPowerState;\n    IOService *pmPolicyMaker;\n    UInt8 pmPCICapPtr;\n    bool magicPacketEnabled;\n    bool magicPacketSupported;\n    \n    //AWDL\n    uint8_t *syncFrameTemplate;\n    uint32_t syncFrameTemplateLength;\n    uint8_t awdlBSSID[6];\n    uint32_t awdlSyncState;\n    uint32_t awdlElectionId;\n    uint32_t awdlPresenceMode;\n    uint16_t awdlMasterChannel;\n    uint16_t awdlSecondaryMasterChannel;\n    uint8_t *roamProfile;\n    struct apple80211_btc_profiles_data *btcProfile;\n    struct apple80211_btc_config_data btcConfig;\n    uint32_t btcMode;\n    uint32_t btcOptions;\n    bool awdlSyncEnable;\n    \n    CCPipe *driverLogPipe;\n    CCPipe *driverDataPathPipe;\n    CCPipe *driverSnapshotsPipe;\n    \n    CCStream *driverFaultReporter;\n};\n\n#endif /* AirportItlwmV2_hpp */\n"
  },
  {
    "path": "AirportItlwm/AirportSTAIOCTL.cpp",
    "content": "//\n//  AirportSTAIOCTL.cpp\n//  AirportItlwm\n//\n//  Created by qcwap on 2020/9/4.\n//  Copyright © 2020 钟先耀. All rights reserved.\n//\n\n#include \"AirportItlwm.hpp\"\n#include <sys/_netstat.h>\n\nextern IOCommandGate *_fCommandGate;\n\nconst char* hexdump(uint8_t *buf, size_t len);\n\nSInt32 AirportItlwm::apple80211Request(unsigned int request_type,\n                                       int request_number,\n                                       IO80211Interface *interface,\n                                       void *data)\n{\n    if (request_type != SIOCGA80211 && request_type != SIOCSA80211)\n        return kIOReturnError;\n    IOReturn ret = kIOReturnError;\n    \n    switch (request_number) {\n        case APPLE80211_IOC_SSID:  // 1\n            IOCTL(request_type, SSID, apple80211_ssid_data);\n            break;\n        case APPLE80211_IOC_AUTH_TYPE:  // 2\n            IOCTL(request_type, AUTH_TYPE, apple80211_authtype_data);\n            break;\n        case APPLE80211_IOC_CHANNEL:  // 4\n            IOCTL(request_type, CHANNEL, apple80211_channel_data);\n            break;\n        case APPLE80211_IOC_PROTMODE:\n            IOCTL(request_type, PROTMODE, apple80211_protmode_data);\n            break;\n        case APPLE80211_IOC_TXPOWER:  // 7\n            IOCTL_GET(request_type, TXPOWER, apple80211_txpower_data);\n            break;\n        case APPLE80211_IOC_RATE:  // 8\n            IOCTL_GET(request_type, RATE, apple80211_rate_data);\n            break;\n        case APPLE80211_IOC_BSSID:  // 9\n            IOCTL(request_type, BSSID, apple80211_bssid_data);\n            break;\n        case APPLE80211_IOC_SCAN_REQ:  // 10\n            IOCTL_SET(request_type, SCAN_REQ, apple80211_scan_data);\n            break;\n        case APPLE80211_IOC_SCAN_REQ_MULTIPLE:\n            IOCTL_SET(request_type, SCAN_REQ_MULTIPLE, apple80211_scan_multiple_data);\n            break;\n        case APPLE80211_IOC_SCAN_RESULT:  // 11\n            IOCTL_GET(request_type, SCAN_RESULT, apple80211_scan_result*);\n            break;\n        case APPLE80211_IOC_CARD_CAPABILITIES:  // 12\n            IOCTL_GET(request_type, CARD_CAPABILITIES, apple80211_capability_data);\n            break;\n        case APPLE80211_IOC_STATE:  // 13\n            IOCTL_GET(request_type, STATE, apple80211_state_data);\n            break;\n        case APPLE80211_IOC_PHY_MODE:  // 14\n            IOCTL_GET(request_type, PHY_MODE, apple80211_phymode_data);\n            break;\n        case APPLE80211_IOC_OP_MODE:  // 15\n            IOCTL_GET(request_type, OP_MODE, apple80211_opmode_data);\n            break;\n        case APPLE80211_IOC_RSSI:  // 16\n            IOCTL_GET(request_type, RSSI, apple80211_rssi_data);\n            break;\n        case APPLE80211_IOC_NOISE:  // 17\n            IOCTL_GET(request_type, NOISE, apple80211_noise_data);\n            break;\n        case APPLE80211_IOC_INT_MIT:  // 18\n            IOCTL_GET(request_type, INT_MIT, apple80211_intmit_data);\n            break;\n        case APPLE80211_IOC_POWER:  // 19\n            IOCTL(request_type, POWER, apple80211_power_data);\n            break;\n        case APPLE80211_IOC_ASSOCIATE:  // 20\n            IOCTL_SET(request_type, ASSOCIATE, apple80211_assoc_data);\n            break;\n        case APPLE80211_IOC_ASSOCIATE_RESULT: // 21\n            IOCTL_GET(request_type, ASSOCIATE_RESULT, apple80211_assoc_result_data);\n            break;\n        case APPLE80211_IOC_DISASSOCIATE: // 22\n            if (request_type == SIOCSA80211)\n                setDISASSOCIATE(interface);\n            break;\n        case APPLE80211_IOC_RATE_SET:\n            IOCTL_GET(request_type, RATE_SET, apple80211_rate_set_data);\n            break;\n        case APPLE80211_IOC_MCS_INDEX_SET:\n            IOCTL_GET(request_type, MCS_INDEX_SET, apple80211_mcs_index_set_data);\n            break;\n        case APPLE80211_IOC_VHT_MCS_INDEX_SET:\n            IOCTL_GET(request_type, VHT_MCS_INDEX_SET, apple80211_vht_mcs_index_set_data);\n            break;\n        case APPLE80211_IOC_MCS_VHT:\n            IOCTL(request_type, MCS_VHT, apple80211_mcs_vht_data);\n            break;\n        case APPLE80211_IOC_SUPPORTED_CHANNELS:  // 27\n        case APPLE80211_IOC_HW_SUPPORTED_CHANNELS:\n            IOCTL_GET(request_type, SUPPORTED_CHANNELS, apple80211_sup_channel_data);\n            break;\n        case APPLE80211_IOC_LOCALE:  // 28\n            IOCTL_GET(request_type, LOCALE, apple80211_locale_data);\n            break;\n        case APPLE80211_IOC_DEAUTH:\n            IOCTL(request_type, DEAUTH, apple80211_deauth_data);\n            break;\n        case APPLE80211_IOC_TX_ANTENNA:  // 37\n            IOCTL_GET(request_type, TX_ANTENNA, apple80211_antenna_data);\n            break;\n        case APPLE80211_IOC_ANTENNA_DIVERSITY:  // 39\n            IOCTL_GET(request_type, ANTENNA_DIVERSITY, apple80211_antenna_data);\n            break;\n        case APPLE80211_IOC_DRIVER_VERSION:  // 43\n            IOCTL_GET(request_type, DRIVER_VERSION, apple80211_version_data);\n            break;\n        case APPLE80211_IOC_HARDWARE_VERSION:  // 44\n            IOCTL_GET(request_type, HARDWARE_VERSION, apple80211_version_data);\n            break;\n        case APPLE80211_IOC_RSN_IE: // 46\n            IOCTL(request_type, RSN_IE, apple80211_rsn_ie_data);\n            break;\n        case APPLE80211_IOC_AP_IE_LIST: // 48\n            if (request_type != SIOCGA80211)\n                return kIOReturnError;\n            IOCTL_GET(request_type, AP_IE_LIST, apple80211_ap_ie_data);\n            break;\n        case APPLE80211_IOC_ASSOCIATION_STATUS:  // 50\n            IOCTL_GET(request_type, ASSOCIATION_STATUS, apple80211_assoc_status_data);\n            break;\n        case APPLE80211_IOC_COUNTRY_CODE:  // 51\n            IOCTL(request_type, COUNTRY_CODE, apple80211_country_code_data);\n            break;\n        case APPLE80211_IOC_RADIO_INFO:\n            IOCTL_GET(request_type, RADIO_INFO, apple80211_radio_info_data);\n            break;\n        case APPLE80211_IOC_MCS:  // 57\n            IOCTL_GET(request_type, MCS, apple80211_mcs_data);\n            break;\n        case APPLE80211_IOC_VIRTUAL_IF_CREATE: // 94\n            IOCTL_SET(request_type, VIRTUAL_IF_CREATE, apple80211_virt_if_create_data);\n            break;\n        case APPLE80211_IOC_VIRTUAL_IF_DELETE:\n            IOCTL_SET(request_type, VIRTUAL_IF_DELETE, apple80211_virt_if_delete_data);\n            break;\n        case APPLE80211_IOC_ROAM_THRESH:\n            IOCTL_GET(request_type, ROAM_THRESH, apple80211_roam_threshold_data);\n            break;\n        case APPLE80211_IOC_LINK_CHANGED_EVENT_DATA:\n            IOCTL_GET(request_type, LINK_CHANGED_EVENT_DATA, apple80211_link_changed_event_data);\n            break;\n        case APPLE80211_IOC_POWERSAVE:\n            IOCTL_GET(request_type, POWERSAVE, apple80211_powersave_data);\n            break;\n        case APPLE80211_IOC_CIPHER_KEY:\n            IOCTL_SET(request_type, CIPHER_KEY, apple80211_key);\n            break;\n        case APPLE80211_IOC_SCANCACHE_CLEAR:\n            IOCTL_SET(request_type, SCANCACHE_CLEAR, apple80211req);\n            break;\n        case APPLE80211_IOC_TX_NSS:\n            IOCTL(request_type, TX_NSS, apple80211_tx_nss_data);\n            break;\n        case APPLE80211_IOC_NSS:\n            IOCTL_GET(request_type, NSS, apple80211_nss_data);\n            break;\n        case APPLE80211_IOC_ROAM:\n            IOCTL_SET(request_type, ROAM, apple80211_sta_roam_data);\n            break;\n        case APPLE80211_IOC_ROAM_PROFILE:\n            IOCTL(request_type, ROAM_PROFILE, apple80211_roam_profile_band_data);\n            break;\n        case APPLE80211_IOC_WOW_PARAMETERS:\n            IOCTL(request_type, WOW_PARAMETERS, apple80211_wow_parameter_data);\n            break;\n        case APPLE80211_IOC_IE:\n            IOCTL(request_type, IE, apple80211_ie_data);\n            break;\n        case APPLE80211_IOC_P2P_LISTEN:\n            IOCTL_SET(request_type, P2P_LISTEN, apple80211_p2p_listen_data);\n            break;\n        case APPLE80211_IOC_P2P_SCAN:\n            IOCTL_SET(request_type, P2P_SCAN, apple80211_scan_data);\n            break;\n        case APPLE80211_IOC_P2P_GO_CONF:\n            IOCTL_SET(request_type, P2P_GO_CONF, apple80211_p2p_go_conf_data);\n            break;\n        case APPLE80211_IOC_BTCOEX_PROFILES:\n            IOCTL(request_type, BTCOEX_PROFILES, apple80211_btc_profiles_data);\n            break;\n        case APPLE80211_IOC_BTCOEX_CONFIG:\n            IOCTL(request_type, BTCOEX_CONFIG, apple80211_btc_config_data);\n            break;\n        case APPLE80211_IOC_BTCOEX_OPTIONS:\n            IOCTL(request_type, BTCOEX_OPTIONS, apple80211_btc_options_data);\n            break;\n        case APPLE80211_IOC_BTCOEX_MODE:\n            IOCTL(request_type, BTCOEX_MODE, apple80211_btc_mode_data);\n            break;\n        default:\n        unhandled:\n            if (!ml_at_interrupt_context()) {\n                XYLog(\"%s Unhandled IOCTL %s (%d) %s\\n\", __FUNCTION__, IOCTL_NAMES[request_number >= ARRAY_SIZE(IOCTL_NAMES) ? 0: request_number],\n                      request_number, request_type == SIOCGA80211 ? \"get\" : (request_type == SIOCSA80211 ? \"set\" : \"other\"));\n            }\n            break;\n    }\n    \n    return ret;\n}\n\nIOReturn AirportItlwm::\ngetSSID(OSObject *object,\n                        struct apple80211_ssid_data *sd)\n{\n    struct ieee80211com * ic = fHalService->get80211Controller();\n    if (ic->ic_state == IEEE80211_S_RUN) {\n        memset(sd, 0, sizeof(*sd));\n        sd->version = APPLE80211_VERSION;\n        memcpy(sd->ssid_bytes, ic->ic_des_essid, strlen((const char*)ic->ic_des_essid));\n        sd->ssid_len = (uint32_t)strlen((const char*)ic->ic_des_essid);\n        return kIOReturnSuccess;\n    }\n    return 6;\n}\n\nIOReturn AirportItlwm::\nsetSSID(OSObject *object, struct apple80211_ssid_data *sd)\n{\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetAUTH_TYPE(OSObject *object, struct apple80211_authtype_data *ad)\n{\n    ad->version = APPLE80211_VERSION;\n    ad->authtype_lower = current_authtype_lower;\n    ad->authtype_upper = current_authtype_upper;\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\nsetAUTH_TYPE(OSObject *object, struct apple80211_authtype_data *ad)\n{\n    current_authtype_lower = ad->authtype_lower;\n    current_authtype_upper = ad->authtype_upper;\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\nsetCIPHER_KEY(OSObject *object, struct apple80211_key *key)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    const char* keydump = hexdump(key->key, key->key_len);\n    const char* rscdump = hexdump(key->key_rsc, key->key_rsc_len);\n    const char* eadump = hexdump(key->key_ea.octet, APPLE80211_ADDR_LEN);\n    static_assert(__offsetof(struct apple80211_key, key_ea) == 92, \"struct corrupted\");\n    static_assert(__offsetof(struct apple80211_key, key_rsc_len) == 80, \"struct corrupted\");\n    static_assert(__offsetof(struct apple80211_key, wowl_kck_len) == 100, \"struct corrupted\");\n    static_assert(__offsetof(struct apple80211_key, wowl_kek_len) == 120, \"struct corrupted\");\n    static_assert(__offsetof(struct apple80211_key, wowl_kck_key) == 104, \"struct corrupted\");\n    if (keydump && rscdump && eadump)\n        XYLog(\"Set key request: len=%d cipher_type=%d flags=%d index=%d key=%s rsc_len=%d rsc=%s ea=%s\\n\",\n              key->key_len, key->key_cipher_type, key->key_flags, key->key_index, keydump, key->key_rsc_len, rscdump, eadump);\n    else\n        XYLog(\"Set key request, but failed to allocate memory for hexdump\\n\");\n    \n    if (keydump)\n        IOFree((void*)keydump, 3 * key->key_len + 1);\n    if (rscdump)\n        IOFree((void*)rscdump, 3 * key->key_rsc_len + 1);\n    if (eadump)\n        IOFree((void*)eadump, 3 * APPLE80211_ADDR_LEN + 1);\n    \n    switch (key->key_cipher_type) {\n        case APPLE80211_CIPHER_NONE:\n            // clear existing key\n//            XYLog(\"Setting NONE key is not supported\\n\");\n            break;\n        case APPLE80211_CIPHER_WEP_40:\n        case APPLE80211_CIPHER_WEP_104:\n            XYLog(\"Setting WEP key %d is not supported\\n\", key->key_index);\n            break;\n        case APPLE80211_CIPHER_TKIP:\n        case APPLE80211_CIPHER_AES_OCB:\n        case APPLE80211_CIPHER_AES_CCM:\n            switch (key->key_flags) {\n                case 4: // PTK\n                    setPTK(key->key, key->key_len);\n                    getNetworkInterface()->postMessage(APPLE80211_M_RSN_HANDSHAKE_DONE);\n                    break;\n                case 0: // GTK\n                    setGTK(key->key, key->key_len, key->key_index, key->key_rsc);\n                    getNetworkInterface()->postMessage(APPLE80211_M_RSN_HANDSHAKE_DONE);\n                    break;\n            }\n            break;\n        case APPLE80211_CIPHER_PMK:\n            XYLog(\"Setting WPA PMK is not supported\\n\");\n            break;\n        case APPLE80211_CIPHER_PMKSA:\n            XYLog(\"Setting WPA PMKSA is not supported\\n\");\n            break;\n    }\n    //fInterface->postMessage(APPLE80211_M_CIPHER_KEY_CHANGED);\n    return kIOReturnSuccess;\n}\n\n// From Ventura, airport/wifiagent seems that they don't like to accept extra channel flags in the scan result list,\n// if not, the exact behavior is that the wifi list on the control center/menu bar will not refresh after system boot.\n#if __IO80211_TARGET >= __MAC_13_0\nstatic int ieeeChanFlag2appleScanFlagVentura(int flags)\n{\n    int ret = 0;\n    if (flags & IEEE80211_CHAN_2GHZ)\n        ret |= APPLE80211_C_FLAG_2GHZ;\n    if (flags & IEEE80211_CHAN_5GHZ)\n        ret |= APPLE80211_C_FLAG_5GHZ;\n    ret |= (APPLE80211_C_FLAG_ACTIVE | APPLE80211_C_FLAG_20MHZ);\n    return ret;\n}\n#endif\n\nstatic int ieeeChanFlag2apple(int flags, int bw)\n{\n    int ret = 0;\n    if (flags & IEEE80211_CHAN_2GHZ)\n        ret |= APPLE80211_C_FLAG_2GHZ;\n    if (flags & IEEE80211_CHAN_5GHZ)\n        ret |= APPLE80211_C_FLAG_5GHZ;\n    if (!(flags & IEEE80211_CHAN_PASSIVE))\n        ret |= APPLE80211_C_FLAG_ACTIVE;\n    if (flags & IEEE80211_CHAN_DFS)\n        ret |= APPLE80211_C_FLAG_DFS;\n    if (bw == -1) {\n        if (flags & IEEE80211_CHAN_VHT) {\n            if ((flags & IEEE80211_CHAN_VHT160) || (flags & IEEE80211_CHAN_VHT80_80))\n                ret |= APPLE80211_C_FLAG_160MHZ;\n            if (flags & IEEE80211_CHAN_VHT80)\n                ret |= APPLE80211_C_FLAG_80MHZ;\n        } else if ((flags & IEEE80211_CHAN_HT40) && (flags & IEEE80211_CHAN_HT)) {\n            ret |= APPLE80211_C_FLAG_40MHZ;\n            if (flags & IEEE80211_CHAN_HT40U)\n                ret |= APPLE80211_C_FLAG_EXT_ABV;\n        } else if (flags & IEEE80211_CHAN_HT20)\n            ret |= APPLE80211_C_FLAG_20MHZ;\n        else if ((flags & IEEE80211_CHAN_CCK) || (flags & IEEE80211_CHAN_OFDM))\n            ret |= APPLE80211_C_FLAG_10MHZ;\n    } else {\n        switch (bw) {\n            case IEEE80211_CHAN_WIDTH_80P80:\n            case IEEE80211_CHAN_WIDTH_160:\n                ret |= APPLE80211_C_FLAG_160MHZ;\n                break;\n            case IEEE80211_CHAN_WIDTH_80:\n                ret |= APPLE80211_C_FLAG_80MHZ;\n                break;\n            case IEEE80211_CHAN_WIDTH_40:\n                ret |= APPLE80211_C_FLAG_40MHZ;\n                if (flags & IEEE80211_CHAN_HT40U)\n                    ret |= APPLE80211_C_FLAG_EXT_ABV;\n                break;\n            case IEEE80211_CHAN_WIDTH_20:\n                ret |= APPLE80211_C_FLAG_20MHZ;\n                break;\n            default:\n                if (flags & IEEE80211_CHAN_HT20)\n                    ret |= APPLE80211_C_FLAG_20MHZ;\n                else if ((flags & IEEE80211_CHAN_CCK) || (flags & IEEE80211_CHAN_OFDM))\n                    ret |= APPLE80211_C_FLAG_10MHZ;\n                break;\n        }\n    }\n    return ret;\n}\n\nIOReturn AirportItlwm::\ngetCHANNEL(OSObject *object,\n                           struct apple80211_channel_data *cd)\n{\n    struct ieee80211com * ic = fHalService->get80211Controller();\n    if (ic->ic_state == IEEE80211_S_RUN) {\n        memset(cd, 0, sizeof(apple80211_channel_data));\n        cd->version = APPLE80211_VERSION;\n        cd->channel.version = APPLE80211_VERSION;\n        cd->channel.channel = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan);\n        cd->channel.flags = ieeeChanFlag2apple(ic->ic_bss->ni_chan->ic_flags, ic->ic_bss->ni_chw);\n        return kIOReturnSuccess;\n    }\n    return 6;\n}\n\nIOReturn AirportItlwm::\nsetCHANNEL(OSObject *object, struct apple80211_channel_data *data)\n{\n    XYLog(\"%s channel=%d\\n\", __FUNCTION__, data->channel.channel);\n    return kIOReturnError;\n}\n\nIOReturn AirportItlwm::\ngetPROTMODE(OSObject *object, struct apple80211_protmode_data *pd)\n{\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    if (ic->ic_state == IEEE80211_S_RUN) {\n        memset(pd, 0, sizeof(*pd));\n        pd->version = APPLE80211_VERSION;\n        pd->threshold = 0;\n        pd->protmode = 0;\n        return kIOReturnSuccess;\n    }\n    return 6;\n}\n\nIOReturn AirportItlwm::\nsetPROTMODE(OSObject *object, struct apple80211_protmode_data *pd)\n{\n    return kIOReturnError;\n}\n\nIOReturn AirportItlwm::\ngetTXPOWER(OSObject *object,\n                           struct apple80211_txpower_data *txd)\n{\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    if (ic->ic_state == IEEE80211_S_RUN) {\n        memset(txd, 0, sizeof(*txd));\n        txd->version = APPLE80211_VERSION;\n        txd->txpower = ic->ic_txpower;\n        txd->txpower_unit = APPLE80211_UNIT_PERCENT;\n        return kIOReturnSuccess;\n    }\n    return 6;\n}\n\nIOReturn AirportItlwm::\ngetTX_NSS(OSObject *object, struct apple80211_tx_nss_data *data)\n{\n    memset(data, 0, sizeof(*data));\n    data->version = APPLE80211_VERSION;\n    data->nss = fHalService->getDriverInfo()->getTxNSS();\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetNSS(OSObject *object, struct apple80211_nss_data *data)\n{\n    memset(data, 0, sizeof(*data));\n    data->version = APPLE80211_VERSION;\n    data->nss = fHalService->getDriverInfo()->getTxNSS();\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\nsetTX_NSS(OSObject *object, struct apple80211_tx_nss_data *data)\n{\n    return kIOReturnError;\n}\n\nIOReturn AirportItlwm::\nsetROAM(OSObject *object, struct apple80211_sta_roam_data *data)\n{\n    XYLog(\"%s rcc_channels=%d unk=%d target_channel=%d target_bssid=%s\\n\", __FUNCTION__, data->rcc_channels, data->unk1, data->taget_channel, ether_sprintf(data->target_bssid));\n    return kIOReturnError;\n}\n\nIOReturn AirportItlwm::\ngetRATE(OSObject *object, struct apple80211_rate_data *rd)\n{\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    if (ic->ic_bss == NULL)\n        return 6;\n    int nss;\n    int sgi;\n    int index = 0;\n    if (ic->ic_state == IEEE80211_S_RUN) {\n        memset(rd, 0, sizeof(*rd));\n        rd->version = APPLE80211_VERSION;\n        rd->num_radios = 1;\n        sgi = ieee80211_node_supports_sgi(ic->ic_bss);\n        if (ic->ic_curmode == IEEE80211_MODE_11AC) {\n            if (sgi)\n                index += 1;\n            nss = fHalService->getDriverInfo()->getTxNSS();\n            switch (ic->ic_bss->ni_chw) {\n                case IEEE80211_CHAN_WIDTH_40:\n                    index += 4;\n                    break;\n                case IEEE80211_CHAN_WIDTH_80:\n                    index += 8;\n                    break;\n                case IEEE80211_CHAN_WIDTH_80P80:\n                case IEEE80211_CHAN_WIDTH_160:\n                    index += 12;\n                    break;\n\n                default:\n                    break;\n            }\n            index += 2 * (nss - 1);\n            const struct ieee80211_vht_rateset *rs = &ieee80211_std_ratesets_11ac[index];\n            rd->rate[0] = rs->rates[ic->ic_bss->ni_txmcs % rs->nrates] / 2;\n        } else if (ic->ic_curmode == IEEE80211_MODE_11N) {\n            int is_40mhz = ic->ic_bss->ni_chw == IEEE80211_CHAN_WIDTH_40;\n            if (sgi)\n                index += 1;\n            if (is_40mhz)\n                index += (IEEE80211_HT_RATESET_MIMO4_SGI + 1);\n            index += (ic->ic_bss->ni_txmcs / 16);\n            nss = ic->ic_bss->ni_txmcs / 8 + 1;\n            index += 2 * (nss - 1);\n            rd->rate[0] = ieee80211_std_ratesets_11n[index].rates[ic->ic_bss->ni_txmcs % 8] / 2;\n        } else\n            rd->rate[0] = ic->ic_bss->ni_rates.rs_rates[ic->ic_bss->ni_txrate];\n        return kIOReturnSuccess;\n    }\n    return 6;\n}\n\nIOReturn AirportItlwm::\ngetROAM_PROFILE(OSObject *object, struct apple80211_roam_profile_band_data *data)\n{\n    if (roamProfile == NULL) {\n        XYLog(\"%s no roam profile, return error\\n\", __FUNCTION__);\n        return kIOReturnError;\n    }\n    memcpy(data, roamProfile, sizeof(struct apple80211_roam_profile_band_data));\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\nsetROAM_PROFILE(OSObject *object, struct apple80211_roam_profile_band_data *data)\n{\n    XYLog(\"%s cnt=%d flags=%d\\n\", __FUNCTION__, data->profile_cnt, data->flags);\n#if 0\n    for (int i = 0; i < data->profile_cnt; i++) {\n        struct apple80211_roam_profile *bd = &data->profiles[i];\n        XYLog(\"%s %d ROAM_PROF_BACKOFF_MULTIPLIER: %d, ROAM_PROF_FULLSCAN_PERIOD: %d, ROAM_PROF_INIT_SCAN_PERIOD: %d, ROAM_PROF_MAX_SCAN_PERIOD: %d, ROAM_PROF_NFSCAN: %d, ROAM_PROF_ROAM_DELTA: %d, ROAM_PROF_ROAM_FLAGS:%d, ROAM_PROF_ROAM_TRIGGER: %d, ROAM_PROF_RSSI_BOOST_DELTA: %d, ROAM_PROF_RSSI_BOOST_THRESH: %d, ROAM_PROF_RSSI_LOWER: %d\\n\", __FUNCTION__, i, bd->backoff_multiplier, bd->full_scan_period, bd->init_scan_period, bd->max_scan_period, bd->nfscan, bd->delta, bd->flags, bd->trigger, bd->rssi_boost_delta, bd->rssi_boost_thresh, bd->rssi_lower);\n    }\n#endif\n    if (roamProfile != NULL)\n        IOFree(roamProfile, sizeof(struct apple80211_roam_profile_band_data));\n    roamProfile = (uint8_t *)IOMalloc(sizeof(struct apple80211_roam_profile_band_data));\n    memcpy(roamProfile, data, sizeof(struct apple80211_roam_profile_band_data));\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetBTCOEX_CONFIG(OSObject *object, struct apple80211_btc_config_data *data)\n{\n    if (!data)\n        return kIOReturnError;\n    memcpy(data, &btcConfig, sizeof(struct apple80211_btc_config_data));\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\nsetBTCOEX_CONFIG(OSObject *object, struct apple80211_btc_config_data *data)\n{\n    if (!data)\n        return kIOReturnError;\n    XYLog(\"%s Setting BTCoex Config: enable_2G:%d, profile_2g:%d, enable_5G:%d, profile_5G:%d\\n\", __FUNCTION__, data->enable_2G, data->profile_2g, data->enable_5G, data->profile_5G);\n    memcpy(&btcConfig, data, sizeof(struct apple80211_btc_config_data));\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetBTCOEX_MODE(OSObject *object, struct apple80211_btc_mode_data *data)\n{\n    if (!data)\n        return kIOReturnError;\n    data->version = APPLE80211_VERSION;\n    data->btc_mode = btcMode;\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\nsetBTCOEX_MODE(OSObject *object, struct apple80211_btc_mode_data *data)\n{\n    if (!data)\n        return kIOReturnError;\n    XYLog(\"%s mode: %d\\n\", __FUNCTION__, data->btc_mode);\n    btcMode = data->btc_mode;\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetBTCOEX_OPTIONS(OSObject *object, struct apple80211_btc_options_data *data)\n{\n    if (!data)\n        return kIOReturnError;\n    data->version = APPLE80211_VERSION;\n    data->btc_options = btcOptions;\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\nsetBTCOEX_OPTIONS(OSObject *object, struct apple80211_btc_options_data *data)\n{\n    if (!data)\n        return kIOReturnError;\n    XYLog(\"%s options: %d\\n\", __FUNCTION__, data->btc_options);\n    btcOptions = data->btc_options;\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetBTCOEX_PROFILES(OSObject *object, struct apple80211_btc_profiles_data *data)\n{\n    if (!data || !btcProfile)\n        return kIOReturnError;\n    memcpy(data, btcProfile, sizeof(struct apple80211_btc_profiles_data));\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\nsetBTCOEX_PROFILES(OSObject *object, struct apple80211_btc_profiles_data *data)\n{\n    if (!data)\n        return kIOReturnError;\n    XYLog(\"%s profiles: %d\\n\", __FUNCTION__, data->profile_cnt);\n    if (btcProfile)\n        IOFree(btcProfile, sizeof(struct apple80211_btc_profiles_data));\n    btcProfile = (struct apple80211_btc_profiles_data *)IOMalloc(sizeof(struct apple80211_btc_profiles_data));\n    memcpy(btcProfile, data, sizeof(struct apple80211_btc_profiles_data));\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetWOW_PARAMETERS(OSObject *object, struct apple80211_wow_parameter_data *data)\n{\n    return kIOReturnError;\n}\n\nIOReturn AirportItlwm::\nsetWOW_PARAMETERS(OSObject *object, struct apple80211_wow_parameter_data *data)\n{\n    XYLog(\"%s pattern_count=%d\\n\", __FUNCTION__, data->pattern_count);\n    return kIOReturnError;\n}\n\nIOReturn AirportItlwm::\ngetBSSID(OSObject *object,\n                         struct apple80211_bssid_data *bd)\n{\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    if (ic->ic_state == IEEE80211_S_RUN) {\n        memset(bd, 0, sizeof(*bd));\n        bd->version = APPLE80211_VERSION;\n        memcpy(bd->bssid.octet, ic->ic_bss->ni_bssid, APPLE80211_ADDR_LEN);\n        return kIOReturnSuccess;\n    }\n    return 6;\n}\n\nIOReturn AirportItlwm::\nsetBSSID(OSObject *object, struct apple80211_bssid_data *data)\n{\n    XYLog(\"%s bssid=%s\\n\", __FUNCTION__, ether_sprintf(data->bssid.octet));\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetCARD_CAPABILITIES(OSObject *object,\n                                     struct apple80211_capability_data *cd)\n{\n    uint32_t caps = fHalService->get80211Controller()->ic_caps;\n    memset(cd, 0, sizeof(struct apple80211_capability_data));\n    \n    if (caps & IEEE80211_C_WEP)\n        cd->capabilities[0] |= 1 << APPLE80211_CAP_WEP;\n    if (caps & IEEE80211_C_RSN)\n        cd->capabilities[0] |= 1 << APPLE80211_CAP_TKIP | 1 << APPLE80211_CAP_AES_CCM;\n    // Disable not implemented capabilities\n    // if (caps & IEEE80211_C_PMGT)\n    //     cd->capabilities[0] |= 1 << APPLE80211_CAP_PMGT;\n    // if (caps & IEEE80211_C_IBSS)\n    //     cd->capabilities[0] |= 1 << APPLE80211_CAP_IBSS;\n    // if (caps & IEEE80211_C_HOSTAP)\n    //     cd->capabilities[0] |= 1 << APPLE80211_CAP_HOSTAP;\n    // AES not enabled, like on Apple cards\n    \n    if (caps & IEEE80211_C_SHSLOT)\n        cd->capabilities[1] |= 1 << (APPLE80211_CAP_SHSLOT - 8);\n    if (caps & IEEE80211_C_SHPREAMBLE)\n        cd->capabilities[1] |= 1 << (APPLE80211_CAP_SHPREAMBLE - 8);\n    if (caps & IEEE80211_C_RSN)\n        cd->capabilities[1] |= 1 << (APPLE80211_CAP_WPA1 - 8) | 1 << (APPLE80211_CAP_WPA2 - 8) | 1 << (APPLE80211_CAP_TKIPMIC - 8);\n    // Disable not implemented capabilities\n    // if (caps & IEEE80211_C_TXPMGT)\n    //     cd->capabilities[1] |= 1 << (APPLE80211_CAP_TXPMGT - 8);\n    // if (caps & IEEE80211_C_MONITOR)\n    //     cd->capabilities[1] |= 1 << (APPLE80211_CAP_MONITOR - 8);\n    // WPA not enabled, like on Apple cards\n\n    cd->version = APPLE80211_VERSION;\n    cd->capabilities[2] = 0xFF; // BURST, WME, SHORT_GI_40MHZ, SHORT_GI_20MHZ, WOW, TSN, ?, ?\n    cd->capabilities[3] = 0x2B;\n    cd->capabilities[4] = 0xAD;\n    cd->capabilities[5] = 0x80;//isCntryDefaultSupported\n    cd->capabilities[5] |= 0x0C;\n    cd->capabilities[6] = (\n//                           1 |    //MFP capable\n                           0x8 |\n                           0x4 |\n                           0x80\n                           );\n    cd->capabilities[7] = 0x84; // This byte contains Apple Watch unlock\n    //cd->capabilities[8] = 0x40;\n    //cd->capabilities[8] |= 8;//dfs white list\n    //cd->capabilities[9] = 0x28;\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetSTATE(OSObject *object,\n                         struct apple80211_state_data *sd)\n{\n    memset(sd, 0, sizeof(*sd));\n    sd->version = APPLE80211_VERSION;\n    sd->state = fHalService->get80211Controller()->ic_state;\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetMCS_INDEX_SET(OSObject *object, struct apple80211_mcs_index_set_data *ad)\n{\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    if (ic->ic_state == IEEE80211_S_RUN) {\n        memset(ad, 0, sizeof(*ad));\n        ad->version = APPLE80211_VERSION;\n        size_t size = min(ARRAY_SIZE(ic->ic_bss->ni_rxmcs), ARRAY_SIZE(ad->mcs_set_map));\n        for (int i = 0; i < size; i++)\n            ad->mcs_set_map[i] = ic->ic_bss->ni_rxmcs[i];\n        return kIOReturnSuccess;\n    }\n    return 6;\n}\n\nIOReturn AirportItlwm::\ngetVHT_MCS_INDEX_SET(OSObject *object, struct apple80211_vht_mcs_index_set_data *data)\n{\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    if (ic->ic_bss == NULL || ic->ic_curmode < IEEE80211_MODE_11AC) {\n        return kIOReturnError;\n    }\n    memset(data, 0, sizeof(struct apple80211_vht_mcs_index_set_data));\n    data->version = APPLE80211_VERSION;\n    data->mcs_map = ic->ic_bss->ni_vht_mcsinfo.tx_mcs_map;\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetMCS_VHT(OSObject *object, struct apple80211_mcs_vht_data *data)\n{\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    if (ic->ic_bss == NULL || ic->ic_curmode < IEEE80211_MODE_11AC) {\n        return kIOReturnError;\n    }\n    memset(data, 0, sizeof(struct apple80211_mcs_vht_data));\n    data->version = APPLE80211_VERSION;\n    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;\n    data->index = ic->ic_bss->ni_txmcs;\n    data->nss = fHalService->getDriverInfo()->getTxNSS();\n    switch (ic->ic_bss->ni_chw) {\n        case IEEE80211_CHAN_WIDTH_40:\n            data->bw = 40;\n            break;\n        case IEEE80211_CHAN_WIDTH_80:\n            data->bw = 80;\n            break;\n        case IEEE80211_CHAN_WIDTH_80P80:\n        case IEEE80211_CHAN_WIDTH_160:\n            data->bw = 160;\n            break;\n            \n        default:\n            data->bw = 20;\n            break;\n    }\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\nsetMCS_VHT(OSObject *object, struct apple80211_mcs_vht_data *data)\n{\n    XYLog(\"%s gi=%d index=%d nss=%d bw=%d\\n\", __FUNCTION__, data->guard_interval, data->index, data->nss, data->bw);\n    return kIOReturnError;\n}\n\nIOReturn AirportItlwm::\ngetRATE_SET(OSObject *object, struct apple80211_rate_set_data *ad)\n{\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    if (ic->ic_state == IEEE80211_S_RUN) {\n        memset(ad, 0, sizeof(*ad));\n        ad->version = APPLE80211_VERSION;\n        ad->num_rates = ic->ic_bss->ni_rates.rs_nrates;\n        size_t size = min(ic->ic_bss->ni_rates.rs_nrates, ARRAY_SIZE(ad->rates));\n        for (int i=0; i < size; i++) {\n            struct apple80211_rate apple_rate = ad->rates[i];\n            apple_rate.version = APPLE80211_VERSION;\n            apple_rate.rate = ic->ic_bss->ni_rates.rs_rates[i];\n            apple_rate.flags = 0;\n        }\n        return kIOReturnSuccess;\n    }\n    return 6;\n}\n\nIOReturn AirportItlwm::\ngetPHY_MODE(OSObject *object,\n                            struct apple80211_phymode_data *pd)\n{\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    \n    pd->version = APPLE80211_VERSION;\n    pd->phy_mode = APPLE80211_MODE_11A\n    | APPLE80211_MODE_11B\n    | APPLE80211_MODE_11G\n    | APPLE80211_MODE_11N;\n    \n    if (ic->ic_flags & IEEE80211_F_VHTON)\n        pd->phy_mode |= APPLE80211_MODE_11AC;\n    \n    if (ic->ic_flags & IEEE80211_F_HEON)\n        pd->phy_mode |= APPLE80211_MODE_11AX;\n    \n    switch (fHalService->get80211Controller()->ic_curmode) {\n        case IEEE80211_MODE_AUTO:\n            pd->active_phy_mode = APPLE80211_MODE_AUTO;\n            break;\n        case IEEE80211_MODE_11A:\n            pd->active_phy_mode = APPLE80211_MODE_11A;\n            break;\n        case IEEE80211_MODE_11B:\n            pd->active_phy_mode = APPLE80211_MODE_11B;\n            break;\n        case IEEE80211_MODE_11G:\n            pd->active_phy_mode = APPLE80211_MODE_11G;\n            break;\n        case IEEE80211_MODE_11N:\n            pd->active_phy_mode = APPLE80211_MODE_11N;\n            break;\n        case IEEE80211_MODE_11AC:\n            pd->active_phy_mode = APPLE80211_MODE_11AC;\n            break;\n        case IEEE80211_MODE_11AX:\n            pd->active_phy_mode = APPLE80211_MODE_11AX;\n            break;\n            \n        default:\n            pd->active_phy_mode = APPLE80211_MODE_AUTO;\n            break;\n    }\n    \n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetOP_MODE(OSObject *object,\n                           struct apple80211_opmode_data *od)\n{\n    od->version = APPLE80211_VERSION;\n    od->op_mode = APPLE80211_M_STA;\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetRSSI(OSObject *object,\n                        struct apple80211_rssi_data *rd)\n{\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    if (ic->ic_state == IEEE80211_S_RUN) {\n        memset(rd, 0, sizeof(*rd));\n        rd->num_radios = 1;\n        rd->rssi_unit = APPLE80211_UNIT_DBM;\n        rd->rssi[0] = rd->aggregate_rssi\n        = rd->rssi_ext[0]\n        = rd->aggregate_rssi_ext\n        = -(0 - IWM_MIN_DBM - ic->ic_bss->ni_rssi);\n        return kIOReturnSuccess;\n    }\n    return 6;\n}\n\nIOReturn AirportItlwm::\ngetRSN_IE(OSObject *object, struct apple80211_rsn_ie_data *data)\n{\n#ifdef USE_APPLE_SUPPLICANT\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    if (ic->ic_bss == NULL || ic->ic_bss->ni_rsnie == NULL) {\n        return kIOReturnError;\n    }\n    data->version = APPLE80211_VERSION;\n    if (ic->ic_rsn_ie_override[1] > 0) {\n        data->len = 2 + ic->ic_rsn_ie_override[1];\n        memcpy(data->ie, ic->ic_rsn_ie_override, data->len);\n    }\n    else {\n        data->len = 2 + ic->ic_bss->ni_rsnie[1];\n        memcpy(data->ie, ic->ic_bss->ni_rsnie, data->len);\n    }\n    return kIOReturnSuccess;\n#else\n    return kIOReturnUnsupported;\n#endif\n}\n\nIOReturn AirportItlwm::\nsetRSN_IE(OSObject *object, struct apple80211_rsn_ie_data *data)\n{\n#ifdef USE_APPLE_SUPPLICANT\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    if (!data)\n        return kIOReturnError;\n    static_assert(sizeof(ic->ic_rsn_ie_override) == APPLE80211_MAX_RSN_IE_LEN, \"Max RSN IE length mismatch\");\n    memcpy(ic->ic_rsn_ie_override, data->ie, APPLE80211_MAX_RSN_IE_LEN);\n    if (ic->ic_state == IEEE80211_S_RUN && ic->ic_bss != nullptr)\n        ieee80211_save_ie(data->ie, &ic->ic_bss->ni_rsnie);\n    return kIOReturnSuccess;\n#else\n    return kIOReturnUnsupported;\n#endif\n}\n\nIOReturn AirportItlwm::\ngetAP_IE_LIST(OSObject *object, struct apple80211_ap_ie_data *data)\n{\n#ifdef USE_APPLE_SUPPLICANT\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    if (!data)\n        return kIOReturnError;\n    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)\n        return kIOReturnError;\n    data->version = APPLE80211_VERSION;\n    data->len = ic->ic_bss->ni_rsnie_tlv_len;\n    memcpy(data->ie_data, ic->ic_bss->ni_rsnie_tlv, data->len);\n    return kIOReturnSuccess;\n#else\n    return kIOReturnUnsupported;\n#endif\n}\n\nIOReturn AirportItlwm::\ngetNOISE(OSObject *object,\n                         struct apple80211_noise_data *nd)\n{\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    if (ic->ic_state == IEEE80211_S_RUN) {\n        memset(nd, 0, sizeof(*nd));\n        nd->version = APPLE80211_VERSION;\n        nd->num_radios = 1;\n        nd->noise[0]\n        = nd->aggregate_noise = -fHalService->getDriverInfo()->getBSSNoise();\n        nd->noise_unit = APPLE80211_UNIT_DBM;\n        return kIOReturnSuccess;\n    }\n    return 6;\n}\n\nIOReturn AirportItlwm::\ngetINT_MIT(OSObject *object, struct apple80211_intmit_data *imd)\n{\n    if (!imd)\n        return kIOReturnError;\n    imd->version = APPLE80211_VERSION;\n    imd->int_mit = APPLE80211_INT_MIT_AUTO;\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetPOWER(OSObject *object,\n                         struct apple80211_power_data *pd)\n{\n    if (!pd)\n        return kIOReturnError;\n    pd->version = APPLE80211_VERSION;\n    pd->num_radios = 4;\n    pd->power_state[0] = power_state;\n    pd->power_state[1] = power_state;\n    pd->power_state[2] = power_state;\n    pd->power_state[3] = power_state;\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetPOWERSAVE(OSObject *object, struct apple80211_powersave_data *pd)\n{\n    pd->version = APPLE80211_VERSION;\n    pd->powersave_level = APPLE80211_POWERSAVE_MODE_DISABLED;\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\nsetPOWER(OSObject *object,\n                         struct apple80211_power_data *pd)\n{\n    if (!pd)\n        return kIOReturnError;\n    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]);\n    if (pd->num_radios > 0) {\n        bool isRunning = (fHalService->get80211Controller()->ic_ac.ac_if.if_flags & (IFF_UP | IFF_RUNNING)) != 0;\n        if (pd->power_state[0] == 0) {\n            changePowerStateToPriv(1);\n            if (isRunning) {\n                net80211_ifstats(fHalService->get80211Controller());\n                disableAdapter(fNetIf);\n            }\n        } else {\n            changePowerStateToPriv(2);\n            if (!isRunning)\n                enableAdapter(fNetIf);\n        }\n        power_state = (pd->power_state[0]);\n    }\n    \n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\nsetASSOCIATE(OSObject *object,\n                             struct apple80211_assoc_data *ad)\n{\n    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,\n          (ad->ad_flags & 2) ? \", Instant Hotspot\" : \"\",\n          (ad->ad_flags & 4) ? \", Auto Instant Hotspot\" : \"\",\n          (ad->ad_rsn_ie[APPLE80211_MAX_RSN_IE_LEN] & 1) ? \", don't disassociate\" : \"\",\n          (ad->ad_rsn_ie[APPLE80211_MAX_RSN_IE_LEN] & 2) ? \", don't blacklist\" : \"\",\n          (ad->ad_rsn_ie[APPLE80211_MAX_RSN_IE_LEN] & 4) ? \", closed Network\" : \"\",\n          (ad->ad_rsn_ie[APPLE80211_MAX_RSN_IE_LEN] & 8) ? \", 802.1X\" : \"\",\n          (ad->ad_rsn_ie[APPLE80211_MAX_RSN_IE_LEN] & 0x20) ? \", force BSSID\" : \"\");\n    \n    struct apple80211_rsn_ie_data rsn_ie_data;\n    struct apple80211_authtype_data auth_type_data;\n    struct ieee80211com *ic = fHalService->get80211Controller();\n\n    if (!ad)\n        return kIOReturnError;\n    \n    if (ic->ic_state < IEEE80211_S_SCAN)\n        return kIOReturnSuccess;\n    \n    if (ic->ic_state == IEEE80211_S_ASSOC || ic->ic_state == IEEE80211_S_AUTH)\n        return kIOReturnSuccess;\n\n    if (ad->ad_mode != APPLE80211_AP_MODE_IBSS) {\n        disassocIsVoluntary = false;\n        auth_type_data.version = APPLE80211_VERSION;\n        auth_type_data.authtype_upper = ad->ad_auth_upper;\n        auth_type_data.authtype_lower = ad->ad_auth_lower;\n        setAUTH_TYPE(object, &auth_type_data);\n        rsn_ie_data.version = APPLE80211_VERSION;\n        rsn_ie_data.len = ad->ad_rsn_ie[1] + 2;\n        memcpy(rsn_ie_data.ie, ad->ad_rsn_ie, rsn_ie_data.len);\n        setRSN_IE(object, &rsn_ie_data);\n\n        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);\n    }\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetASSOCIATE_RESULT(OSObject *object, struct apple80211_assoc_result_data *ad)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    if (ad && ic->ic_state == IEEE80211_S_RUN) {\n        memset(ad, 0, sizeof(struct apple80211_assoc_result_data));\n        ad->version = APPLE80211_VERSION;\n        ad->result = APPLE80211_RESULT_SUCCESS;\n        return kIOReturnSuccess;\n    }\n    return kIOReturnError;\n}\n\nIOReturn AirportItlwm::setDISASSOCIATE(OSObject *object)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct ieee80211com *ic = fHalService->get80211Controller();\n\n    if (ic->ic_state < IEEE80211_S_SCAN)\n        return kIOReturnSuccess;\n    \n    if (ic->ic_state > IEEE80211_S_AUTH && ic->ic_bss != NULL)\n        IEEE80211_SEND_MGMT(ic, ic->ic_bss, IEEE80211_FC0_SUBTYPE_DEAUTH, IEEE80211_REASON_AUTH_LEAVE);\n    \n    if (ic->ic_state == IEEE80211_S_ASSOC || ic->ic_state == IEEE80211_S_AUTH)\n        return kIOReturnSuccess;\n    \n    disassocIsVoluntary = true;\n\n    ieee80211_del_ess(ic, nullptr, 0, 1);\n    ieee80211_deselect_ess(ic);\n#ifdef USE_APPLE_SUPPLICANT\n    ic->ic_rsn_ie_override[1] = 0;\n#endif\n    ic->ic_assoc_status = APPLE80211_STATUS_UNAVAILABLE;\n    ic->ic_deauth_reason = APPLE80211_REASON_ASSOC_LEAVING;\n    ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetSUPPORTED_CHANNELS(OSObject *object, struct apple80211_sup_channel_data *ad)\n{\n    if (!ad)\n        return kIOReturnError;\n    ad->version = APPLE80211_VERSION;\n    ad->num_channels = 0;\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    for (int i = 0; i < IEEE80211_CHAN_MAX; i++) {\n        if (ic->ic_channels[i].ic_freq != 0) {\n            ad->supported_channels[ad->num_channels].channel = ieee80211_chan2ieee(ic, &ic->ic_channels[i]);\n#if __IO80211_TARGET < __MAC_13_0\n            ad->supported_channels[ad->num_channels].flags = ieeeChanFlag2apple(ic->ic_channels[i].ic_flags, -1);\n#else\n            ad->supported_channels[ad->num_channels].flags = ieeeChanFlag2appleScanFlagVentura(ic->ic_channels[i].ic_flags);\n#endif\n            \n            ad->num_channels++;\n        }\n    }\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetLOCALE(OSObject *object,\n                          struct apple80211_locale_data *ld)\n{\n    if (!ld)\n        return kIOReturnError;\n    ld->version = APPLE80211_VERSION;\n    ld->locale  = APPLE80211_LOCALE_FCC;\n    \n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetDEAUTH(OSObject *object,\n                          struct apple80211_deauth_data *da)\n{\n    if (!da)\n        return kIOReturnError;\n    da->version = APPLE80211_VERSION;\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    da->deauth_reason = ic->ic_deauth_reason;\n//    XYLog(\"%s, %d\\n\", __FUNCTION__, da->deauth_reason);\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetASSOCIATION_STATUS(OSObject *object, struct apple80211_assoc_status_data *hv)\n{\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    \n    if (!hv)\n        return kIOReturnError;\n    memset(hv, 0, sizeof(*hv));\n    hv->version = APPLE80211_VERSION;\n    if (ic->ic_state == IEEE80211_S_RUN)\n        hv->status = APPLE80211_STATUS_SUCCESS;\n    else\n        hv->status = APPLE80211_STATUS_UNAVAILABLE;\n//    XYLog(\"%s, %d\\n\", __FUNCTION__, hv->status);\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\nsetSCANCACHE_CLEAR(OSObject *object, struct apple80211req *req)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    //if doing background or active scan, don't free nodes.\n    if ((ic->ic_flags & IEEE80211_F_BGSCAN) || (ic->ic_flags & IEEE80211_F_ASCAN))\n        return kIOReturnSuccess;\n    ieee80211_free_allnodes(ic, 0);\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\nsetDEAUTH(OSObject *object,\n                          struct apple80211_deauth_data *da)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    return kIOReturnSuccess;\n}\n\nvoid AirportItlwm::\neventHandler(struct ieee80211com *ic, int msgCode, void *data)\n{\n    IO80211Interface *interface = OSDynamicCast(IO80211Interface, ic->ic_ac.ac_if.iface);\n    if (!interface)\n        return;\n    switch (msgCode) {\n        case IEEE80211_EVT_COUNTRY_CODE_UPDATE:\n            interface->postMessage(APPLE80211_M_COUNTRY_CODE_CHANGED);\n            break;\n        case IEEE80211_EVT_STA_ASSOC_DONE:\n            interface->postMessage(APPLE80211_M_ASSOC_DONE);\n            break;\n        case IEEE80211_EVT_STA_DEAUTH:\n            interface->postMessage(APPLE80211_M_DEAUTH_RECEIVED);\n            break;\n#if 0\n        case IEEE80211_EVT_SCAN_DONE:\n            interface->postMessage(APPLE80211_M_SCAN_DONE);\n            break;\n#endif\n        default:\n            break;\n    }\n}\n\nIOReturn AirportItlwm::\ngetTX_ANTENNA(OSObject *object,\n                              apple80211_antenna_data *ad)\n{\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    if (ic->ic_state != IEEE80211_S_RUN ||  ic->ic_bss == NULL || !ad)\n        return kIOReturnError;\n    ad->version = APPLE80211_VERSION;\n    ad->num_radios = 1;\n    ad->antenna_index[0] = 1;\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetANTENNA_DIVERSITY(OSObject *object,\n                                     apple80211_antenna_data *ad)\n{\n    if (!ad)\n        return kIOReturnError;\n    ad->version = APPLE80211_VERSION;\n    ad->num_radios = 1;\n    ad->antenna_index[0] = 1;\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetDRIVER_VERSION(OSObject *object,\n                                  struct apple80211_version_data *hv)\n{\n    if (!hv)\n        return kIOReturnError;\n    hv->version = APPLE80211_VERSION;\n    snprintf(hv->string, sizeof(hv->string), \"itlwm: %s%s fw: %s\", ITLWM_VERSION, GIT_COMMIT, fHalService->getDriverInfo()->getFirmwareVersion());\n    hv->string_len = strlen(hv->string);\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetHARDWARE_VERSION(OSObject *object,\n                                    struct apple80211_version_data *hv)\n{\n    if (!hv)\n        return kIOReturnError;\n    hv->version = APPLE80211_VERSION;\n    strncpy(hv->string, fHalService->getDriverInfo()->getFirmwareVersion(), sizeof(hv->string));\n    hv->string_len = strlen(fHalService->getDriverInfo()->getFirmwareVersion());\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetCOUNTRY_CODE(OSObject *object,\n                                struct apple80211_country_code_data *cd)\n{\n    char user_override_cc[3];\n    const char *cc_fw = fHalService->getDriverInfo()->getFirmwareCountryCode();\n    \n    if (!cd)\n        return kIOReturnError;\n    cd->version = APPLE80211_VERSION;\n    memset(user_override_cc, 0, sizeof(user_override_cc));\n    PE_parse_boot_argn(\"itlwm_cc\", user_override_cc, 3);\n    /* user_override_cc > firmware_cc > geo_location_cc */\n    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));\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\nsetCOUNTRY_CODE(OSObject *object, struct apple80211_country_code_data *data)\n{\n    XYLog(\"%s cc=%s\\n\", __FUNCTION__, data->cc);\n    if (data && data->cc[0] != 120 && data->cc[0] != 88) {\n        memcpy(geo_location_cc, data->cc, sizeof(geo_location_cc));\n        fNetIf->postMessage(APPLE80211_M_COUNTRY_CODE_CHANGED);\n    }\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetMCS(OSObject *object, struct apple80211_mcs_data* md)\n{\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    if (ic->ic_state != IEEE80211_S_RUN ||  ic->ic_bss == NULL || !md)\n        return 6;\n    md->version = APPLE80211_VERSION;\n    md->index = ic->ic_bss->ni_txmcs;\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetROAM_THRESH(OSObject *object, struct apple80211_roam_threshold_data* md)\n{\n    if (!md)\n        return kIOReturnError;\n    md->threshold = 100;\n    md->count = 0;\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetRADIO_INFO(OSObject *object, struct apple80211_radio_info_data* md)\n{\n    if (!md)\n        return kIOReturnError;\n    md->version = APPLE80211_VERSION;\n    md->count = 1;\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\nsetSCAN_REQ(OSObject *object,\n                            struct apple80211_scan_data *sd)\n{\n    struct ieee80211com *ic = fHalService->get80211Controller();\n#if 0\n    XYLog(\"%s Type: %u BSS Type: %u PHY Mode: %u Dwell time: %u Rest time: %u Num channels: %u SSID: %s BSSID: %s\\n\",\n          __FUNCTION__,\n          sd->scan_type,\n          sd->bss_type,\n          sd->phy_mode,\n          sd->dwell_time,\n          sd->rest_time,\n          sd->num_channels,\n          sd->ssid,\n          ether_sprintf(sd->bssid.octet));\n#endif\n    if (fScanResultWrapping)\n        return 22;\n    if (ic->ic_state <= IEEE80211_S_INIT)\n        return 22;\n    if (sd->scan_type == APPLE80211_SCAN_TYPE_FAST || sd->scan_type == APPLE80211_SCAN_TYPE_PASSIVE) {\n        if (scanSource) {\n            scanSource->setTimeoutMS(100);\n            scanSource->enable();\n        }\n        return kIOReturnSuccess;\n    }\n    ieee80211_begin_cache_bgscan(&ic->ic_ac.ac_if);\n    if (scanSource) {\n        scanSource->setTimeoutMS(100);\n        scanSource->enable();\n    }\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\nsetSCAN_REQ_MULTIPLE(OSObject *object, struct apple80211_scan_multiple_data *sd)\n{\n    struct ieee80211com *ic = fHalService->get80211Controller();\n#if 0\n    int i;\n    XYLog(\"%s Type: %u SSID Count: %u BSSID Count: %u PHY Mode: %u Dwell time: %u Rest time: %u Num channels: %u Unk: %u\\n\",\n          __FUNCTION__,\n          sd->scan_type,\n          sd->ssid_count,\n          sd->bssid_count,\n          sd->phy_mode,\n          sd->dwell_time,\n          sd->rest_time,\n          sd->num_channels,\n          sd->unk_2);\n    for (i = 0; i < sd->ssid_count; i++)\n        XYLog(\"%s index=%d ssid=%s ssid_len=%d\\n\", __FUNCTION__, i, sd->ssids[i].ssid_bytes, sd->ssids[i].ssid_len);\n#endif\n    if (fScanResultWrapping)\n        return 22;\n    if (ic->ic_state <= IEEE80211_S_INIT)\n        return 22;\n    ieee80211_begin_cache_bgscan(&ic->ic_ac.ac_if);\n    if (scanSource) {\n        scanSource->setTimeoutMS(100);\n        scanSource->enable();\n    }\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetSCAN_RESULT(OSObject *object, struct apple80211_scan_result **sr)\n{\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    \n    if (fNextNodeToSend == NULL) {\n        if (fScanResultWrapping) {\n            fScanResultWrapping = false;\n            return 5;\n        } else {\n            fNextNodeToSend = RB_MIN(ieee80211_tree, &ic->ic_tree);\n            if (fNextNodeToSend == NULL)\n                return 12;\n        }\n    }\n//    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), 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);\n    apple80211_scan_result* result = (apple80211_scan_result* )fNextNodeToSend->verb;\n    bzero(result, sizeof(*result));\n    result->version = APPLE80211_VERSION;\n    if (fNextNodeToSend->ni_rsnie_tlv && fNextNodeToSend->ni_rsnie_tlv_len > 0) {\n        result->asr_ie_len = fNextNodeToSend->ni_rsnie_tlv_len;\n#if __IO80211_TARGET < __MAC_12_0\n        result->asr_ie_data = fNextNodeToSend->ni_rsnie_tlv;\n#else\n        memcpy(result->asr_ie_data, fNextNodeToSend->ni_rsnie_tlv, MIN(result->asr_ie_len, sizeof(result->asr_ie_data)));\n#endif\n    } else {\n        result->asr_ie_len = 0;\n#if __IO80211_TARGET < __MAC_12_0\n        result->asr_ie_data = NULL;\n#endif\n    }\n    result->asr_beacon_int = fNextNodeToSend->ni_intval;\n    for (int i = 0; i < result->asr_nrates; i++ )\n        result->asr_rates[i] = fNextNodeToSend->ni_rates.rs_rates[i];\n    result->asr_nrates = fNextNodeToSend->ni_rates.rs_nrates;\n    result->asr_age = (uint32_t)(airport_up_time() - fNextNodeToSend->ni_age_ts);\n    result->asr_cap = fNextNodeToSend->ni_capinfo;\n    result->asr_channel.version = APPLE80211_VERSION;\n    result->asr_channel.channel = ieee80211_chan2ieee(ic, fNextNodeToSend->ni_chan);\n#if __IO80211_TARGET < __MAC_13_0\n    result->asr_channel.flags = ieeeChanFlag2apple(fNextNodeToSend->ni_chan->ic_flags, -1);\n#else\n    result->asr_channel.flags = ieeeChanFlag2appleScanFlagVentura(fNextNodeToSend->ni_chan->ic_flags);\n#endif\n    result->asr_noise = -fHalService->getDriverInfo()->getBSSNoise();\n    result->asr_rssi = -(0 - IWM_MIN_DBM - fNextNodeToSend->ni_rssi);\n    memcpy(result->asr_bssid, fNextNodeToSend->ni_bssid, IEEE80211_ADDR_LEN);\n    result->asr_ssid_len = fNextNodeToSend->ni_esslen;\n    if (result->asr_ssid_len != 0)\n        memcpy(&result->asr_ssid, fNextNodeToSend->ni_essid, result->asr_ssid_len);\n\n    *sr = result;\n    \n    fNextNodeToSend = RB_NEXT(ieee80211_tree, &ic->ic_tree, fNextNodeToSend);\n    if (fNextNodeToSend == NULL)\n        fScanResultWrapping = true;\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\nsetVIRTUAL_IF_CREATE(OSObject *object, struct apple80211_virt_if_create_data* data)\n{\n    // From Ventura, the virtual interface sequence has channged, now temporary disabled the virtual interface creation because it is no functionality. This fix the issue of delaying start time of associating to AP.\n#if __IO80211_TARGET >= __MAC_13_0\n    return kIOReturnUnsupported;\n#else\n    struct ether_addr addr;\n    struct apple80211_channel chann;\n    XYLog(\"%s role=%d, bsd_name=%s, mac=%s, unk1=%d\\n\", __FUNCTION__, data->role, data->bsd_name,\n          ether_sprintf(data->mac), data->unk1);\n    if (data->role == APPLE80211_VIF_P2P_DEVICE) {\n        IO80211P2PInterface *inf = new IO80211P2PInterface;\n        if (inf == NULL)\n            return kIOReturnError;\n        memcpy(addr.octet, data->mac, 6);\n        inf->init(this, &addr, data->role, \"p2p\");\n        fP2PDISCInterface = inf;\n    } else if (data->role == APPLE80211_VIF_P2P_GO) {\n        IO80211P2PInterface *inf = new IO80211P2PInterface;\n        if (inf == NULL)\n            return kIOReturnError;\n        memcpy(addr.octet, data->mac, 6);\n        inf->init(this, &addr, data->role, \"p2p\");\n        fP2PGOInterface = inf;\n    } else if (data->role == APPLE80211_VIF_AWDL) {\n        if (fAWDLInterface != NULL && strncmp((const char *)data->bsd_name, \"awdl\", 4) == 0) {\n            XYLog(\"%s awdl interface already exists!\\n\", __FUNCTION__);\n            return kIOReturnSuccess;\n        }\n        IO80211P2PInterface *inf = new IO80211P2PInterface;\n        if (inf == NULL)\n            return kIOReturnError;\n        memcpy(addr.octet, data->mac, 6);\n        inf->init(this, &addr, data->role, \"awdl\");\n        chann.channel = 149;\n        chann.version = 1;\n        chann.flags = APPLE80211_C_FLAG_5GHZ | APPLE80211_C_FLAG_ACTIVE | APPLE80211_C_FLAG_80MHZ;\n        setInfraChannel(&chann);\n        fAWDLInterface = inf;\n    } else {\n        XYLog(\"%s unhandled virtual interface role type: %d\\n\", __FUNCTION__, data->role);\n        return kIOReturnError;\n    }\n    return kIOReturnSuccess;\n#endif\n}\n\nIOReturn AirportItlwm::\nsetVIRTUAL_IF_DELETE(OSObject *object, struct apple80211_virt_if_delete_data *data)\n{\n    XYLog(\"%s bsd_name=%s\\n\", __FUNCTION__, data->bsd_name);\n    //TODO find vif according to the bsd_name\n    IO80211VirtualInterface *vif = OSDynamicCast(IO80211VirtualInterface, object);\n    if (vif == NULL)\n        return kIOReturnError;\n    detachVirtualInterface(vif, false);\n    vif->release();\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetLINK_CHANGED_EVENT_DATA(OSObject *object, struct apple80211_link_changed_event_data *ed)\n{\n    if (ed == nullptr)\n        return 16;\n    \n    struct ieee80211com *ic = fHalService->get80211Controller();\n    \n    bzero(ed, sizeof(apple80211_link_changed_event_data));\n    ed->isLinkDown = !(currentStatus & kIONetworkLinkActive);\n    if (ed->isLinkDown) {\n        ed->voluntary = disassocIsVoluntary;\n        ed->reason = APPLE80211_LINK_DOWN_REASON_DEAUTH;\n    } else\n        ed->rssi = -(0 - IWM_MIN_DBM - ic->ic_bss->ni_rssi);\n    XYLog(\"Link %s, reason: %d, voluntary: %d\\n\", ed->isLinkDown ? \"down\" : \"up\", ed->reason, ed->voluntary);\n    return kIOReturnSuccess;\n}\n"
  },
  {
    "path": "AirportItlwm/AirportVirtualIOCTL.cpp",
    "content": "//\n//  AirportVirtualIOCTL.cpp\n//  AirportItlwm\n//\n//  Created by qcwap on 2020/9/4.\n//  Copyright © 2020 钟先耀. All rights reserved.\n//\n\n#include \"AirportItlwm.hpp\"\n\n\nSInt32 AirportItlwm::\napple80211VirtualRequest(UInt request_type, int request_number, IO80211VirtualInterface *interface, void *data)\n{\n    if (request_type != SIOCGA80211 && request_type != SIOCSA80211)\n        return kIOReturnError;\n    IOReturn ret = kIOReturnError;\n    \n    switch (request_number) {\n        case APPLE80211_IOC_CARD_CAPABILITIES:\n            IOCTL_GET(request_type, CARD_CAPABILITIES, apple80211_capability_data);\n            break;\n        case APPLE80211_IOC_POWER:\n            IOCTL_GET(request_type, POWER, apple80211_power_data);\n            break;\n        case APPLE80211_IOC_SUPPORTED_CHANNELS:\n            IOCTL_GET(request_type, SUPPORTED_CHANNELS, apple80211_sup_channel_data);\n            break;\n        case APPLE80211_IOC_DRIVER_VERSION:\n            IOCTL_GET(request_type, DRIVER_VERSION, apple80211_version_data);\n            break;\n        case APPLE80211_IOC_OP_MODE:\n            IOCTL_GET(request_type, OP_MODE, apple80211_opmode_data);\n            break;\n        case APPLE80211_IOC_PHY_MODE:\n            IOCTL_GET(request_type, PHY_MODE, apple80211_phymode_data);\n            break;\n        case APPLE80211_IOC_RSSI:\n            IOCTL_GET(request_type, RSSI, apple80211_rssi_data);\n            break;\n        case APPLE80211_IOC_STATE:\n            IOCTL_GET(request_type, STATE, apple80211_state_data);\n            break;\n        case APPLE80211_IOC_BSSID:\n            IOCTL(request_type, BSSID, apple80211_bssid_data);\n            break;\n        case APPLE80211_IOC_RATE:\n            IOCTL_GET(request_type, RATE, apple80211_rate_data);\n            break;\n        case APPLE80211_IOC_CHANNEL:\n            IOCTL(request_type, CHANNEL, apple80211_channel_data);\n            break;\n        case APPLE80211_IOC_AUTH_TYPE:\n            IOCTL(request_type, AUTH_TYPE, apple80211_authtype_data);\n            break;\n        case APPLE80211_IOC_ROAM_PROFILE:\n            IOCTL(request_type, ROAM_PROFILE, apple80211_roam_profile_band_data);\n            break;\n        case APPLE80211_IOC_SSID:\n            IOCTL(request_type, SSID, apple80211_ssid_data);\n            break;\n        case APPLE80211_IOC_AWDL_PEER_TRAFFIC_REGISTRATION:\n            IOCTL(request_type, AWDL_PEER_TRAFFIC_REGISTRATION, apple80211_awdl_peer_traffic_registration);\n            break;\n        case APPLE80211_IOC_AWDL_SYNC_ENABLED:\n            IOCTL(request_type, SYNC_ENABLED, apple80211_awdl_sync_enabled);\n            break;\n        case APPLE80211_IOC_AWDL_SYNC_FRAME_TEMPLATE:\n            IOCTL(request_type, SYNC_FRAME_TEMPLATE, apple80211_awdl_sync_frame_template);\n            break;\n        case APPLE80211_IOC_HT_CAPABILITY:\n            IOCTL_GET(request_type, AWDL_HT_CAPABILITY, apple80211_ht_capability);\n            break;\n        case APPLE80211_IOC_VHT_CAPABILITY:\n            IOCTL_GET(request_type, AWDL_VHT_CAPABILITY, apple80211_vht_capability);\n            break;\n        case APPLE80211_IOC_AWDL_ELECTION_METRIC:\n            IOCTL(request_type, AWDL_ELECTION_METRIC, apple80211_awdl_election_metric);\n            break;\n        case APPLE80211_IOC_AWDL_BSSID:\n            IOCTL(request_type, AWDL_BSSID, apple80211_awdl_bssid);\n            break;\n        case APPLE80211_IOC_CHANNELS_INFO:\n            IOCTL_GET(request_type, CHANNELS_INFO, apple80211_channels_info);\n            break;\n        case APPLE80211_IOC_PEER_CACHE_MAXIMUM_SIZE:\n            IOCTL(request_type, PEER_CACHE_MAXIMUM_SIZE, apple80211_peer_cache_maximum_size);\n            break;\n        case APPLE80211_IOC_AWDL_ELECTION_ID:\n            IOCTL(request_type, AWDL_ELECTION_ID, apple80211_awdl_election_id);            \n            break;\n        case APPLE80211_IOC_AWDL_MASTER_CHANNEL:\n            IOCTL(request_type, AWDL_MASTER_CHANNEL, apple80211_awdl_master_channel);\n            break;\n        case APPLE80211_IOC_AWDL_SECONDARY_MASTER_CHANNEL:\n            IOCTL(request_type, AWDL_SECONDARY_MASTER_CHANNEL, apple80211_awdl_secondary_master_channel);\n            break;\n        case APPLE80211_IOC_AWDL_MIN_RATE:\n            IOCTL(request_type, AWDL_MIN_RATE, apple80211_awdl_min_rate);\n            break;\n        case APPLE80211_IOC_AWDL_ELECTION_RSSI_THRESHOLDS:\n            IOCTL(request_type, AWDL_ELECTION_RSSI_THRESHOLDS, apple80211_awdl_election_rssi_thresholds);\n            break;\n        case APPLE80211_IOC_AWDL_SYNCHRONIZATION_CHANNEL_SEQUENCE:\n            IOCTL(request_type, AWDL_SYNCHRONIZATION_CHANNEL_SEQUENCE, apple80211_awdl_sync_channel_sequence);\n            break;\n        case APPLE80211_IOC_AWDL_PRESENCE_MODE:\n            IOCTL(request_type, AWDL_PRESENCE_MODE, apple80211_awdl_presence_mode);\n            break;\n        case APPLE80211_IOC_AWDL_EXTENSION_STATE_MACHINE_PARAMETERS:\n            IOCTL(request_type, AWDL_EXTENSION_STATE_MACHINE_PARAMETERS, apple80211_awdl_extension_state_machine_parameter);\n            break;\n        case APPLE80211_IOC_AWDL_SYNC_STATE:\n            IOCTL(request_type, AWDL_SYNC_STATE, apple80211_awdl_sync_state);\n            break;\n        case APPLE80211_IOC_AWDL_SYNC_PARAMS:\n            IOCTL(request_type, AWDL_SYNC_PARAMS, apple80211_awdl_sync_params);\n            break;\n        case APPLE80211_IOC_AWDL_CAPABILITIES:\n            IOCTL_GET(request_type, AWDL_CAPABILITIES, apple80211_awdl_cap);\n            break;\n        case APPLE80211_IOC_AWDL_AF_TX_MODE:\n            IOCTL(request_type, AWDL_AF_TX_MODE, apple80211_awdl_af_tx_mode);\n            break;\n        case APPLE80211_IOC_AWDL_OOB_AUTO_REQUEST:\n            IOCTL_SET(request_type, AWDL_OOB_AUTO_REQUEST, apple80211_awdl_oob_request);\n            break;\n        case APPLE80211_IOC_IE:\n            IOCTL(request_type, IE, apple80211_ie_data);\n            break;\n        case APPLE80211_IOC_P2P_LISTEN:\n            IOCTL_SET(request_type, P2P_LISTEN, apple80211_p2p_listen_data);\n            break;\n        case APPLE80211_IOC_P2P_SCAN:\n            IOCTL_SET(request_type, P2P_SCAN, apple80211_scan_data);\n            break;\n        case APPLE80211_IOC_P2P_GO_CONF:\n            IOCTL_SET(request_type, P2P_GO_CONF, apple80211_p2p_go_conf_data);\n            break;\n        default:\n        unhandled:\n            if (!ml_at_interrupt_context())\n                XYLog(\"%s Unhandled IOCTL %s (%d) %s\\n\", __FUNCTION__, IOCTL_NAMES[request_number >= ARRAY_SIZE(IOCTL_NAMES) ? 0: request_number],\n                      request_number, request_type == SIOCGA80211 ? \"get\" : (request_type == SIOCSA80211 ? \"set\" : \"other\"));\n            break;\n    }\n    \n    return ret;\n}\n\nIOReturn AirportItlwm::\nsetAWDL_PEER_TRAFFIC_REGISTRATION(OSObject *object, struct apple80211_awdl_peer_traffic_registration *data)\n{\n    char name[255];\n    if (data->name_len > 0 && data->name_len < 255) {\n        bzero(name, 255);\n        memcpy(name, data->name, data->name_len);\n    }\n    XYLog(\"%s name=%s, name_len=%d, active=%d\\n\", __FUNCTION__, name, data->name_len, data->active);\n    if (!strncmp(data->name, \"wifid-assisted-discovery\", data->name_len)) {\n        if (data->active) {\n            \n        } else {\n            \n        }\n    } else if (!strncmp(data->name, \"sidecar\", data->name_len)) {\n        \n    }\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetAWDL_PEER_TRAFFIC_REGISTRATION(OSObject *object, struct apple80211_awdl_peer_traffic_registration *)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    if (fAWDLInterface)\n        return 45;\n    return 22;\n}\n\nIOReturn AirportItlwm::\nsetAWDL_ELECTION_METRIC(OSObject *object, struct apple80211_awdl_election_metric *data)\n{\n    XYLog(\"%s metric=%d\\n\", __FUNCTION__, data->metric);\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetAWDL_ELECTION_METRIC(OSObject *object, struct apple80211_awdl_election_metric *data)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    return kIOReturnError;\n}\n\nIOReturn AirportItlwm::\ngetSYNC_ENABLED(OSObject *object, struct apple80211_awdl_sync_enabled *data)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    data->version = APPLE80211_VERSION;\n    data->enabled = this->awdlSyncEnable;\n    data->unk1 = 0;\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\nsetSYNC_ENABLED(OSObject *object, struct apple80211_awdl_sync_enabled *data)\n{\n    XYLog(\"%s sync_enabled=%d\\n\", __FUNCTION__, data->enabled);\n    this->awdlSyncEnable = data->enabled;\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetSYNC_FRAME_TEMPLATE(OSObject *object, struct apple80211_awdl_sync_frame_template *data)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    if (syncFrameTemplate == NULL || syncFrameTemplateLength == 0)\n        return kIOReturnError;\n    data->version = APPLE80211_VERSION;\n    data->payload_len = syncFrameTemplateLength;\n    memcpy(data->payload, syncFrameTemplate, syncFrameTemplateLength);\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\nsetSYNC_FRAME_TEMPLATE(OSObject *object, struct apple80211_awdl_sync_frame_template *data)\n{\n    XYLog(\"%s payload_len=%d\\n\", __FUNCTION__, data->payload_len);\n    if (data->payload_len <= 0)\n        return kIOReturnError;\n    if (syncFrameTemplate != NULL && syncFrameTemplateLength > 0) {\n        IOFree(syncFrameTemplate, syncFrameTemplateLength);\n        syncFrameTemplateLength = 0;\n        syncFrameTemplate = NULL;\n    }\n    syncFrameTemplate = (uint8_t *)IOMalloc(data->payload_len);\n    syncFrameTemplateLength = data->payload_len;\n    memset(syncFrameTemplate, 0, data->payload_len);\n    memcpy(syncFrameTemplate, data->payload, data->payload_len);\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetAWDL_HT_CAPABILITY(OSObject *object, struct apple80211_ht_capability *data)\n{\n    memset(data, 0, sizeof(*data));\n    data->version = APPLE80211_VERSION;\n    data->hc_id = IEEE80211_ELEMID_HTCAPS;\n    data->hc_cap = (IEEE80211_HTCAP_SGI20 | IEEE80211_HTCAP_CBW20_40 | IEEE80211_HTCAP_SGI40);\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetAWDL_VHT_CAPABILITY(OSObject *object, struct apple80211_vht_capability *data)\n{\n    memset(data, 0, sizeof(*data));\n    data->version = APPLE80211_VERSION;\n    data->cap = 3263;\n\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetAWDL_BSSID(OSObject *object, struct apple80211_awdl_bssid *data)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    data->version = APPLE80211_VERSION;\n    memcpy(data->bssid, awdlBSSID, 6);\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\nsetAWDL_BSSID(OSObject *object, struct apple80211_awdl_bssid *data)\n{\n    XYLog(\"%s bssid=%s unk_mac=%s\\n\", __FUNCTION__, ether_sprintf(data->bssid), ether_sprintf(data->unk_mac));\n    memcpy(awdlBSSID, data->bssid, 6);\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetCHANNELS_INFO(OSObject *object, struct apple80211_channels_info *data)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    memset(data, 0, sizeof(*data));\n    data->version = APPLE80211_VERSION;\n    for (int i = 0; i < IEEE80211_CHAN_MAX; i++) {\n        struct ieee80211_channel *channel = &ic->ic_channels[i];\n        if (channel->ic_freq != 0) {\n            int chanNum = ieee80211_chan2ieee(ic, channel);\n            data->chan_num[data->num_chan_specs] = chanNum;\n            data->support_80Mhz[data->num_chan_specs] = IEEE80211_IS_CHAN_VHT80(channel);\n            data->support_40Mhz[data->num_chan_specs] = IEEE80211_IS_CHAN_HT40(channel) || IEEE80211_IS_CHAN_VHT40(channel);\n            data->num_chan_specs++;\n            if (data->num_chan_specs >= APPLE80211_MAX_CHANNELS)\n                break;\n        }\n    }\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetAWDL_ELECTION_ID(OSObject *object, struct apple80211_awdl_election_id *data)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    data->version = APPLE80211_VERSION;\n    data->election_id = awdlElectionId;\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\nsetAWDL_ELECTION_ID(OSObject *object, struct apple80211_awdl_election_id *data)\n{\n    XYLog(\"%s election_id=%d\\n\", __FUNCTION__, data->election_id);\n    awdlElectionId = data->election_id;\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetPEER_CACHE_MAXIMUM_SIZE(OSObject *object, struct apple80211_peer_cache_maximum_size *data)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    data->version = APPLE80211_VERSION;\n    data->max_peers = 255;\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\nsetPEER_CACHE_MAXIMUM_SIZE(OSObject *object, struct apple80211_peer_cache_maximum_size *data)\n{\n    XYLog(\"%s max_peers=%d\\n\", __FUNCTION__, data->max_peers);\n    \n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetAWDL_MASTER_CHANNEL(OSObject *object, struct apple80211_awdl_master_channel *data)\n{\n    data->version = APPLE80211_VERSION;\n    data->master_channel = awdlMasterChannel;\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\nsetAWDL_MASTER_CHANNEL(OSObject *object, struct apple80211_awdl_master_channel *data)\n{\n    XYLog(\"%s master_channel=%d\\n\", __FUNCTION__, data->master_channel);\n    awdlMasterChannel = data->master_channel;\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetAWDL_SECONDARY_MASTER_CHANNEL(OSObject *object, struct apple80211_awdl_secondary_master_channel *data)\n{\n    XYLog(\"%s temporary return channel 0\\n\", __FUNCTION__);\n    data->version = APPLE80211_VERSION;\n    data->secondary_master_channel = awdlSecondaryMasterChannel;\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\nsetAWDL_SECONDARY_MASTER_CHANNEL(OSObject *object, struct apple80211_awdl_secondary_master_channel *data)\n{\n    XYLog(\"%s secondary_master_channel=%d\\n\", __FUNCTION__, data->secondary_master_channel);\n    awdlSecondaryMasterChannel = data->secondary_master_channel;\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\nsetAWDL_MIN_RATE(OSObject *object, struct apple80211_awdl_min_rate *data)\n{\n    XYLog(\"%s min_rate=%d plus=%d\\n\", __FUNCTION__, data->min_rate, 2 *data->min_rate);\n    \n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetAWDL_MIN_RATE(OSObject *object, struct apple80211_awdl_min_rate *data)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    data->version = APPLE80211_VERSION;\n    \n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetAWDL_ELECTION_RSSI_THRESHOLDS(OSObject *object, struct apple80211_awdl_election_rssi_thresholds *data)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    return kIOReturnError;\n}\n\nIOReturn AirportItlwm::\nsetAWDL_ELECTION_RSSI_THRESHOLDS(OSObject *object, struct apple80211_awdl_election_rssi_thresholds *data)\n{\n    XYLog(\"%s unk1=%d unk2=%d unk3=%d\\n\", __FUNCTION__, data->unk1, data->unk2, data->unk3);\n    \n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetAWDL_SYNCHRONIZATION_CHANNEL_SEQUENCE(OSObject *object, struct apple80211_awdl_sync_channel_sequence *data)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    data->version = APPLE80211_VERSION;\n    \n    return kIOReturnSuccess;\n}\n\n#if 0\nstatic void dumpAWDLChannelSeqs(struct apple80211_awdl_sync_channel_sequence *data)\n{\n    if (data == nullptr)\n        return;\n    XYLog(\"%s length %u step count %u duplicate %u fill %d encoding %u\\n\", __FUNCTION__, data->length, data->step_count, data->duplicate_count, data->fill_channel, data->encoding);\n    for (int i = 0; i < data->length; i++) {\n        struct apple80211_channel_sequence seq = data->seqs[i];\n        uint16_t band = seq.flags & 0xC00;\n        uint16_t channel = seq.flags & 0x300;\n\n        XYLog(\"%s %d 0x%04x=%d%s%s%s\\n\", __FUNCTION__, i, seq.flags, (uint8_t)seq.flags, band != 0x800 ? (band == 0xC00 ? \",20MHz\" : \",unknown\") : \",20MHz\", channel != 0x200 ? (channel == 0x100 ? \",-1\" : \",none\") : \",1\", (seq.flags & 0xF000) == 4096 ? \",5GHz\" : \",unknown\");\n    }\n}\n#endif\n\nIOReturn AirportItlwm::\nsetAWDL_SYNCHRONIZATION_CHANNEL_SEQUENCE(OSObject *object, struct apple80211_awdl_sync_channel_sequence *data)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n#if 0\n    dumpAWDLChannelSeqs(data);\n#endif\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetAWDL_PRESENCE_MODE(OSObject *object, struct apple80211_awdl_presence_mode *data)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    data->version = APPLE80211_VERSION;\n    data->mode = awdlPresenceMode;\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\nsetAWDL_PRESENCE_MODE(OSObject *object, struct apple80211_awdl_presence_mode *data)\n{\n    XYLog(\"%s mode=%d\\n\", __FUNCTION__, data->mode);\n    awdlPresenceMode = data->mode;\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetAWDL_EXTENSION_STATE_MACHINE_PARAMETERS(OSObject *object, struct apple80211_awdl_extension_state_machine_parameter *data)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    data->version = APPLE80211_VERSION;\n    \n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\nsetAWDL_EXTENSION_STATE_MACHINE_PARAMETERS(OSObject *object, struct apple80211_awdl_extension_state_machine_parameter *data)\n{\n    XYLog(\"%s unk1=%d unk2=%d unk3=%d unk4=%d\\n\", __FUNCTION__, data->unk1, data->unk2, data->unk3, data->unk4);\n    \n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetAWDL_SYNC_STATE(OSObject *object, struct apple80211_awdl_sync_state *data)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    data->version = APPLE80211_VERSION;\n    data->state = awdlSyncState;\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\nsetAWDL_SYNC_STATE(OSObject *object, struct apple80211_awdl_sync_state *data)\n{\n    XYLog(\"%s state=%d\\n\", __FUNCTION__, data->state);\n    awdlSyncState = data->state;\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetAWDL_SYNC_PARAMS(OSObject *object, struct apple80211_awdl_sync_params *data)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    data->version = APPLE80211_VERSION;\n\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\nsetAWDL_SYNC_PARAMS(OSObject *object, struct apple80211_awdl_sync_params *data)\n{\n    XYLog(\"%s availability_window_length=%d availability_window_period=%d extension_length=%d synchronization_frame_period=%d\\n\", __FUNCTION__, data->availability_window_length, data->availability_window_period, data->extension_length, data->synchronization_frame_period);\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetAWDL_CAPABILITIES(OSObject *object, struct apple80211_awdl_cap *data)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    data->version = APPLE80211_VERSION;\n    data->cap = APPLE80211_AWDL_CAP_CCA_STATS;\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\ngetAWDL_AF_TX_MODE(OSObject *object, struct apple80211_awdl_af_tx_mode *data)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    data->version = APPLE80211_VERSION;\n\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\nsetAWDL_AF_TX_MODE(OSObject *object, struct apple80211_awdl_af_tx_mode *data)\n{\n    XYLog(\"%s mode=%llu\\n\", __FUNCTION__, data->mode);\n\n    return kIOReturnSuccess;\n}\n\nIOReturn AirportItlwm::\nsetAWDL_OOB_AUTO_REQUEST(OSObject *object, struct apple80211_awdl_oob_request *data)\n{\n    XYLog(\"%s data_len=%d unk1=%d unk2=%d unk3=%d unk4=%d unk5=%d unk6=%d unk7=%d unk9=%d\\n\", __FUNCTION__, data->data_len, data->unk1, data->unk2, data->unk3, data->unk4, data->unk5, data->unk6, data->unk7, data->unk9);\n    return kIOReturnSuccess;\n}\n"
  },
  {
    "path": "AirportItlwm/IOPCIEDeviceWrapper.cpp",
    "content": "//\n//  IOPCIEDeviceWrapper.cpp\n//  AirportItlwm-Sonoma\n//\n//  Created by qcwap on 2023/6/27.\n//  Copyright © 2023 钟先耀. All rights reserved.\n//\n\n#include \"IOPCIEDeviceWrapper.hpp\"\n#include \"Apple80211.h\"\n\n#include \"ItlIwm.hpp\"\n#include \"ItlIwx.hpp\"\n#include \"ItlIwn.hpp\"\n\n#define super IOService\nOSDefineMetaClassAndStructors(IOPCIEDeviceWrapper, IOService);\n\n#define  PCI_MSI_FLAGS        2    /* Message Control */\n#define  PCI_CAP_ID_MSI        0x05    /* Message Signalled Interrupts */\n#define  PCI_MSIX_FLAGS        2    /* Message Control */\n#define  PCI_CAP_ID_MSIX    0x11    /* MSI-X */\n#define  PCI_MSIX_FLAGS_ENABLE    0x8000    /* MSI-X enable */\n#define  PCI_MSI_FLAGS_ENABLE    0x0001    /* MSI feature enabled */\n\nstatic IOPMPowerState powerStateArray[2] =\n{\n    {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},\n    {1, kIOPMDeviceUsable, kIOPMPowerOn, kIOPMPowerOn, 0, 0, 0, 0, 0, 0, 0, 0}\n};\n\nstatic void pciMsiSetEnable(IOPCIDevice *device, UInt8 msiCap, int enable)\n{\n    UInt16 control;\n    \n    control = device->configRead16(msiCap + PCI_MSI_FLAGS);\n    control &= ~PCI_MSI_FLAGS_ENABLE;\n    if (enable)\n        control |= PCI_MSI_FLAGS_ENABLE;\n    device->configWrite16(msiCap + PCI_MSI_FLAGS, control);\n}\n\nstatic void pciMsiXClearAndSet(IOPCIDevice *device, UInt8 msixCap, UInt16 clear, UInt16 set)\n{\n    UInt16 ctrl;\n    \n    ctrl = device->configRead16(msixCap + PCI_MSIX_FLAGS);\n    ctrl &= ~clear;\n    ctrl |= set;\n    device->configWrite16(msixCap + PCI_MSIX_FLAGS, ctrl);\n}\n\nextern IOWorkLoop *_fWorkloop;\n\nIOWorkLoop *IOPCIEDeviceWrapper::getWorkLoop() const\n{\n    return _fWorkloop;\n}\n\nIOService* IOPCIEDeviceWrapper::\nprobe(IOService *provider, SInt32 *score)\n{\n    XYLog(\"%s\\n\", __PRETTY_FUNCTION__);\n    bool isMatch = false;\n    super::probe(provider, score);\n    UInt8 msiCap;\n    UInt8 msixCap;\n    IOPCIDevice* device = OSDynamicCast(IOPCIDevice, provider);\n    if (!device)\n        return NULL;\n    if (ItlIwx::iwx_match(device)) {\n        isMatch = true;\n        fHalService = new ItlIwx;\n    }\n    if (!isMatch && ItlIwm::iwm_match(device)) {\n        isMatch = true;\n        fHalService = new ItlIwm;\n    }\n    if (!isMatch && ItlIwn::iwn_match(device)) {\n        isMatch = true;\n        fHalService = new ItlIwn;\n    }\n    if (isMatch) {\n        XYLog(\"%s Found\\n\", __FUNCTION__);\n        device->findPCICapability(PCI_CAP_ID_MSIX, &msixCap);\n        if (msixCap)\n            pciMsiXClearAndSet(device, msixCap, PCI_MSIX_FLAGS_ENABLE, 0);\n        device->findPCICapability(PCI_CAP_ID_MSI, &msiCap);\n        if (msiCap)\n            pciMsiSetEnable(device, msiCap, 1);\n        if (!msiCap && !msixCap) {\n            XYLog(\"%s No MSI cap\\n\", __FUNCTION__);\n            fHalService->release();\n            fHalService = NULL;\n            return NULL;\n        }\n        this->pciNub = device;\n        return this;\n    }\n    return NULL;\n}\n\nbool IOPCIEDeviceWrapper::\nstart(IOService *provider)\n{\n    XYLog(\"%s\\n\", __PRETTY_FUNCTION__);\n    _fWorkloop = IO80211WorkQueue::workQueue();\n    if (!super::start(provider)) {\n        return false;\n    }\n    IOLog(\"%s::super start succeed\\n\", getName());\n    UInt8 builtIn = 0;\n    setProperty(\"built-in\", OSData::withBytes(&builtIn, sizeof(builtIn)));\n    PMinit();\n    registerPowerDriver(this, powerStateArray, 2);\n    provider->joinPMtree(this);\n    registerService();\n    return true;\n}\n\nvoid IOPCIEDeviceWrapper::\nstop(IOService *provider)\n{\n    XYLog(\"%s\\n\", __PRETTY_FUNCTION__);\n    PMstop();\n    super::stop(provider);\n}\n\nIOReturn IOPCIEDeviceWrapper::\nsetPowerState(unsigned long powerStateOrdinal, IOService *whatDevice)\n{\n    return IOPMAckImplied;\n}\n"
  },
  {
    "path": "AirportItlwm/IOPCIEDeviceWrapper.hpp",
    "content": "//\n//  IOPCIEDeviceWrapper.hpp\n//  AirportItlwm-Sonoma\n//\n//  Created by qcwap on 2023/6/27.\n//  Copyright © 2023 钟先耀. All rights reserved.\n//\n\n#ifndef IOPCIEDeviceWrapper_hpp\n#define IOPCIEDeviceWrapper_hpp\n\n#include <IOKit/IOService.h>\n#include <IOKit/pci/IOPCIDevice.h>\n#include <IOKit/IOLib.h>\n#include <IOKit/IOTypes.h>\n\n#include <HAL/ItlHalService.hpp>\n\nclass IOPCIEDeviceWrapper : public IOService {\n    OSDeclareDefaultStructors(IOPCIEDeviceWrapper)\n    \npublic:\n    virtual IOService* probe(IOService* provider, SInt32* score) override;\n    virtual bool start(IOService *provider) override;\n    virtual void stop(IOService *provider) override;\n    virtual IOWorkLoop* getWorkLoop() const override;\n    virtual IOReturn setPowerState(\n        unsigned long powerStateOrdinal,\n                                   IOService *   whatDevice ) override;\n    \npublic:\n    ItlHalService *fHalService;\n    IOPCIDevice *pciNub;\n};\n\n#endif /* IOPCIEDeviceWrapper_hpp */\n"
  },
  {
    "path": "AirportItlwm/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>$(DEVELOPMENT_LANGUAGE)</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>$(MODULE_VERSION)</string>\n\t<key>CFBundleVersion</key>\n\t<string>$(MODULE_VERSION)</string>\n\t<key>IOKitPersonalities</key>\n\t<dict>\n\t\t<key>itlwm</key>\n\t\t<dict>\n\t\t\t<key>CFBundleIdentifier</key>\n\t\t\t<string>com.zxystd.AirportItlwm</string>\n\t\t\t<key>IOClass</key>\n\t\t\t<string>AirportItlwm</string>\n\t\t\t<key>IOMatchCategory</key>\n\t\t\t<string>IODefaultMatchCategory</string>\n\t\t\t<key>IOPCIMatch</key>\n\t\t\t<string>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</string>\n\t\t\t<key>IOProbeScore</key>\n\t\t\t<integer>2000</integer>\n\t\t\t<key>IOProviderClass</key>\n\t\t\t<string>IOPCIDevice</string>\n\t\t</dict>\n\t</dict>\n\t<key>NSHumanReadableCopyright</key>\n\t<string>Copyright © 2020 钟先耀. All rights reserved.</string>\n\t<key>OSBundleLibraries</key>\n\t<dict>\n\t\t<key>com.apple.iokit.IO80211Family</key>\n\t\t<string>1200.12.2b1</string>\n\t\t<key>com.apple.iokit.IONetworkingFamily</key>\n\t\t<string>3.2</string>\n\t\t<key>com.apple.iokit.IOPCIFamily</key>\n\t\t<string>2.9</string>\n\t\t<key>com.apple.kpi.bsd</key>\n\t\t<string>16.7</string>\n\t\t<key>com.apple.kpi.iokit</key>\n\t\t<string>16.7</string>\n\t\t<key>com.apple.kpi.libkern</key>\n\t\t<string>16.7</string>\n\t\t<key>com.apple.kpi.mach</key>\n\t\t<string>16.7</string>\n\t</dict>\n\t<key>OSBundleRequired</key>\n\t<string>Network-Root</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "LICENSE",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 2, June 1991\n\n Copyright (C) 1989, 1991 Free Software Foundation, Inc.,\n 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The licenses for most software are designed to take away your\nfreedom to share and change it.  By contrast, the GNU General Public\nLicense is intended to guarantee your freedom to share and change free\nsoftware--to make sure the software is free for all its users.  This\nGeneral Public License applies to most of the Free Software\nFoundation's software and to any other program whose authors commit to\nusing it.  (Some other Free Software Foundation software is covered by\nthe GNU Lesser General Public License instead.)  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthis service if you wish), that you receive source code or can get it\nif you want it, that you can change the software or use pieces of it\nin new free programs; and that you know you can do these things.\n\n  To protect your rights, we need to make restrictions that forbid\nanyone to deny you these rights or to ask you to surrender the rights.\nThese restrictions translate to certain responsibilities for you if you\ndistribute copies of the software, or if you modify it.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must give the recipients all the rights that\nyou have.  You must make sure that they, too, receive or can get the\nsource code.  And you must show them these terms so they know their\nrights.\n\n  We protect your rights with two steps: (1) copyright the software, and\n(2) offer you this license which gives you legal permission to copy,\ndistribute and/or modify the software.\n\n  Also, for each author's protection and ours, we want to make certain\nthat everyone understands that there is no warranty for this free\nsoftware.  If the software is modified by someone else and passed on, we\nwant its recipients to know that what they have is not the original, so\nthat any problems introduced by others will not reflect on the original\nauthors' reputations.\n\n  Finally, any free program is threatened constantly by software\npatents.  We wish to avoid the danger that redistributors of a free\nprogram will individually obtain patent licenses, in effect making the\nprogram proprietary.  To prevent this, we have made it clear that any\npatent must be licensed for everyone's free use or not licensed at all.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                    GNU GENERAL PUBLIC LICENSE\n   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n\n  0. This License applies to any program or other work which contains\na notice placed by the copyright holder saying it may be distributed\nunder the terms of this General Public License.  The \"Program\", below,\nrefers to any such program or work, and a \"work based on the Program\"\nmeans either the Program or any derivative work under copyright law:\nthat is to say, a work containing the Program or a portion of it,\neither verbatim or with modifications and/or translated into another\nlanguage.  (Hereinafter, translation is included without limitation in\nthe term \"modification\".)  Each licensee is addressed as \"you\".\n\nActivities other than copying, distribution and modification are not\ncovered by this License; they are outside its scope.  The act of\nrunning the Program is not restricted, and the output from the Program\nis covered only if its contents constitute a work based on the\nProgram (independent of having been made by running the Program).\nWhether that is true depends on what the Program does.\n\n  1. You may copy and distribute verbatim copies of the Program's\nsource code as you receive it, in any medium, provided that you\nconspicuously and appropriately publish on each copy an appropriate\ncopyright notice and disclaimer of warranty; keep intact all the\nnotices that refer to this License and to the absence of any warranty;\nand give any other recipients of the Program a copy of this License\nalong with the Program.\n\nYou may charge a fee for the physical act of transferring a copy, and\nyou may at your option offer warranty protection in exchange for a fee.\n\n  2. You may modify your copy or copies of the Program or any portion\nof it, thus forming a work based on the Program, and copy and\ndistribute such modifications or work under the terms of Section 1\nabove, provided that you also meet all of these conditions:\n\n    a) You must cause the modified files to carry prominent notices\n    stating that you changed the files and the date of any change.\n\n    b) You must cause any work that you distribute or publish, that in\n    whole or in part contains or is derived from the Program or any\n    part thereof, to be licensed as a whole at no charge to all third\n    parties under the terms of this License.\n\n    c) If the modified program normally reads commands interactively\n    when run, you must cause it, when started running for such\n    interactive use in the most ordinary way, to print or display an\n    announcement including an appropriate copyright notice and a\n    notice that there is no warranty (or else, saying that you provide\n    a warranty) and that users may redistribute the program under\n    these conditions, and telling the user how to view a copy of this\n    License.  (Exception: if the Program itself is interactive but\n    does not normally print such an announcement, your work based on\n    the Program is not required to print an announcement.)\n\nThese requirements apply to the modified work as a whole.  If\nidentifiable sections of that work are not derived from the Program,\nand can be reasonably considered independent and separate works in\nthemselves, then this License, and its terms, do not apply to those\nsections when you distribute them as separate works.  But when you\ndistribute the same sections as part of a whole which is a work based\non the Program, the distribution of the whole must be on the terms of\nthis License, whose permissions for other licensees extend to the\nentire whole, and thus to each and every part regardless of who wrote it.\n\nThus, it is not the intent of this section to claim rights or contest\nyour rights to work written entirely by you; rather, the intent is to\nexercise the right to control the distribution of derivative or\ncollective works based on the Program.\n\nIn addition, mere aggregation of another work not based on the Program\nwith the Program (or with a work based on the Program) on a volume of\na storage or distribution medium does not bring the other work under\nthe scope of this License.\n\n  3. You may copy and distribute the Program (or a work based on it,\nunder Section 2) in object code or executable form under the terms of\nSections 1 and 2 above provided that you also do one of the following:\n\n    a) Accompany it with the complete corresponding machine-readable\n    source code, which must be distributed under the terms of Sections\n    1 and 2 above on a medium customarily used for software interchange; or,\n\n    b) Accompany it with a written offer, valid for at least three\n    years, to give any third party, for a charge no more than your\n    cost of physically performing source distribution, a complete\n    machine-readable copy of the corresponding source code, to be\n    distributed under the terms of Sections 1 and 2 above on a medium\n    customarily used for software interchange; or,\n\n    c) Accompany it with the information you received as to the offer\n    to distribute corresponding source code.  (This alternative is\n    allowed only for noncommercial distribution and only if you\n    received the program in object code or executable form with such\n    an offer, in accord with Subsection b above.)\n\nThe source code for a work means the preferred form of the work for\nmaking modifications to it.  For an executable work, complete source\ncode means all the source code for all modules it contains, plus any\nassociated interface definition files, plus the scripts used to\ncontrol compilation and installation of the executable.  However, as a\nspecial exception, the source code distributed need not include\nanything that is normally distributed (in either source or binary\nform) with the major components (compiler, kernel, and so on) of the\noperating system on which the executable runs, unless that component\nitself accompanies the executable.\n\nIf distribution of executable or object code is made by offering\naccess to copy from a designated place, then offering equivalent\naccess to copy the source code from the same place counts as\ndistribution of the source code, even though third parties are not\ncompelled to copy the source along with the object code.\n\n  4. You may not copy, modify, sublicense, or distribute the Program\nexcept as expressly provided under this License.  Any attempt\notherwise to copy, modify, sublicense or distribute the Program is\nvoid, and will automatically terminate your rights under this License.\nHowever, parties who have received copies, or rights, from you under\nthis License will not have their licenses terminated so long as such\nparties remain in full compliance.\n\n  5. You are not required to accept this License, since you have not\nsigned it.  However, nothing else grants you permission to modify or\ndistribute the Program or its derivative works.  These actions are\nprohibited by law if you do not accept this License.  Therefore, by\nmodifying or distributing the Program (or any work based on the\nProgram), you indicate your acceptance of this License to do so, and\nall its terms and conditions for copying, distributing or modifying\nthe Program or works based on it.\n\n  6. Each time you redistribute the Program (or any work based on the\nProgram), the recipient automatically receives a license from the\noriginal licensor to copy, distribute or modify the Program subject to\nthese terms and conditions.  You may not impose any further\nrestrictions on the recipients' exercise of the rights granted herein.\nYou are not responsible for enforcing compliance by third parties to\nthis License.\n\n  7. If, as a consequence of a court judgment or allegation of patent\ninfringement or for any other reason (not limited to patent issues),\nconditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot\ndistribute so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you\nmay not distribute the Program at all.  For example, if a patent\nlicense would not permit royalty-free redistribution of the Program by\nall those who receive copies directly or indirectly through you, then\nthe only way you could satisfy both it and this License would be to\nrefrain entirely from distribution of the Program.\n\nIf any portion of this section is held invalid or unenforceable under\nany particular circumstance, the balance of the section is intended to\napply and the section as a whole is intended to apply in other\ncircumstances.\n\nIt is not the purpose of this section to induce you to infringe any\npatents or other property right claims or to contest validity of any\nsuch claims; this section has the sole purpose of protecting the\nintegrity of the free software distribution system, which is\nimplemented by public license practices.  Many people have made\ngenerous contributions to the wide range of software distributed\nthrough that system in reliance on consistent application of that\nsystem; it is up to the author/donor to decide if he or she is willing\nto distribute software through any other system and a licensee cannot\nimpose that choice.\n\nThis section is intended to make thoroughly clear what is believed to\nbe a consequence of the rest of this License.\n\n  8. If the distribution and/or use of the Program is restricted in\ncertain countries either by patents or by copyrighted interfaces, the\noriginal copyright holder who places the Program under this License\nmay add an explicit geographical distribution limitation excluding\nthose countries, so that distribution is permitted only in or among\ncountries not thus excluded.  In such case, this License incorporates\nthe limitation as if written in the body of this License.\n\n  9. The Free Software Foundation may publish revised and/or new versions\nof the General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\nEach version is given a distinguishing version number.  If the Program\nspecifies a version number of this License which applies to it and \"any\nlater version\", you have the option of following the terms and conditions\neither of that version or of any later version published by the Free\nSoftware Foundation.  If the Program does not specify a version number of\nthis License, you may choose any version ever published by the Free Software\nFoundation.\n\n  10. If you wish to incorporate parts of the Program into other free\nprograms whose distribution conditions are different, write to the author\nto ask for permission.  For software which is copyrighted by the Free\nSoftware Foundation, write to the Free Software Foundation; we sometimes\nmake exceptions for this.  Our decision will be guided by the two goals\nof preserving the free status of all derivatives of our free software and\nof promoting the sharing and reuse of software generally.\n\n                            NO WARRANTY\n\n  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\nFOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN\nOTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\nPROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\nOR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS\nTO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE\nPROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\nREPAIR OR CORRECTION.\n\n  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\nREDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\nINCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\nOUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\nTO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\nYOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\nPROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGES.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nconvey the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software; you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License along\n    with this program; if not, write to the Free Software Foundation, Inc.,\n    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n\nAlso add information on how to contact you by electronic and paper mail.\n\nIf the program is interactive, make it output a short notice like this\nwhen it starts in an interactive mode:\n\n    Gnomovision version 69, Copyright (C) year name of author\n    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, the commands you use may\nbe called something other than `show w' and `show c'; they could even be\nmouse-clicks or menu items--whatever suits your program.\n\nYou should also get your employer (if you work as a programmer) or your\nschool, if any, to sign a \"copyright disclaimer\" for the program, if\nnecessary.  Here is a sample; alter the names:\n\n  Yoyodyne, Inc., hereby disclaims all copyright interest in the program\n  `Gnomovision' (which makes passes at compilers) written by James Hacker.\n\n  <signature of Ty Coon>, 1 April 1989\n  Ty Coon, President of Vice\n\nThis General Public License does not permit incorporating your program into\nproprietary programs.  If your program is a subroutine library, you may\nconsider it more useful to permit linking proprietary applications with the\nlibrary.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.\n"
  },
  {
    "path": "README.md",
    "content": "# itlwm\n\n**An Intel Wi-Fi Adapter Kernel Extension for macOS, based on the OpenBSD Project.**\n\n## Documentation\n\nWe highly recommend exploring our documentation before using this Kernel Extension:\n\n- [Intro](https://OpenIntelWireless.github.io/itlwm)\n- [Compatibility](https://openintelwireless.github.io/itlwm/Compat)\n- [FAQ](https://openintelwireless.github.io/itlwm/FAQ)\n\n## Download\n\n[![Download from https://github.com/OpenIntelWireless/itlwm/releases](https://img.shields.io/github/v/release/OpenIntelWireless/itlwm?label=Download)](https://github.com/OpenIntelWireless/itlwm/releases)\n\n## Questions and Issues\n\nCheck out our [FAQ Page](https://openintelwireless.github.io/itlwm/FAQ) for more info.\n\nIf you have other questions or feedback, feel free to [![Join the chat at https://gitter.im/OpenIntelWireless/itlwm](https://badges.gitter.im/OpenIntelWireless/itlwm.svg)](https://gitter.im/OpenIntelWireless/itlwm?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge).\n\nWe only accept bug reports in GitHub Issues, before opening an issue, you're recommended to reconfirm it with us on [Gitter](https://gitter.im/OpenIntelWireless/itlwm); once it's confirmed, please use the provided issue template.\n\n## Credits\n\n- [Acidanthera](https://github.com/acidanthera) for [MacKernelSDK](https://github.com/acidanthera/MacKernelSDK)\n- [Apple](https://www.apple.com) for [macOS](https://www.apple.com/macos)\n- [AppleIntelWiFi](https://github.com/AppleIntelWiFi) for [Black80211-Catalina](https://github.com/AppleIntelWiFi/Black80211-Catalina)\n- [ErrorErrorError](https://github.com/ErrorErrorError) for UserClient bug fixes\n- [Intel](https://www.intel.com) for [Wireless Adapter Firmwares](https://www.intel.com/content/www/us/en/support/articles/000005511/network-and-io/wireless.html) and [iwlwifi](https://wireless.wiki.kernel.org/en/users/drivers/iwlwifi)\n- [Linux](https://www.kernel.org) for [iwlwifi](https://wireless.wiki.kernel.org/en/users/drivers/iwlwifi)\n- [mercurysquad](https://github.com/mercurysquad) for [Voodoo80211](https://github.com/mercurysquad/Voodoo80211)\n- [OpenBSD](https://openbsd.org) for [net80211, iwn, iwm, and iwx](https://github.com/openbsd/src)\n- [pigworlds](https://github.com/OpenIntelWireless/itlwm/commits?author=pigworlds) for DVM devices support, MIRA bug fixes, and Tx aggregation for MVM Gen 1 devices\n- [rpeshkov](https://github.com/rpeshkov) for [black80211](https://github.com/rpeshkov/black80211)\n- [usr-sse2](https://github.com/usr-sse2) for implementing the usage of Apple RSN Supplicant and bug fixes\n- [zxystd](https://github.com/zxystd) for developing [itlwm](https://github.com/OpenIntelWireless/itlwm)\n\n## Acknowledgements\n\n- [@penghubingzhou](https://github.com/startpenghubingzhou)\n- [@Bat.bat](https://github.com/williambj1)\n- [@iStarForever](https://github.com/XStar-Dev)\n- [@stevezhengshiqi](https://github.com/stevezhengshiqi)\n- [@DogAndPot](https://github.com/DogAndPot) for providing resources and help for system configuration\n- [@Daliansky](https://github.com/Daliansky) for providing Wi-Fi cards\n"
  },
  {
    "path": "include/Airport/Apple80211.h",
    "content": "//\n//  Apple80211.h\n//  itlwm\n//\n//  Created by qcwap on 2020/9/4.\n//  Copyright © 2020 钟先耀. All rights reserved.\n//\n\n#ifndef Apple80211_h\n#define Apple80211_h\n\n#include \"apple_private_spi.h\"\n#include \"debug.h\"\n#include \"IO80211WorkLoop.h\"\n#ifdef IO80211FAMILY_V2\n#include \"IO80211WorkQueue.h\"\n#include \"IO80211ControllerV2.h\"\n#include \"IO80211InfraInterface.h\"\n#include \"IO80211InfraProtocol.h\"\n#include \"IOSkywalkPacketBufferPool.h\"\n#include \"IOSkywalkLegacyEthernetInterface.h\"\n#include \"IO80211SkywalkInterface.h\"\n#else\n#include \"IO80211Controller.h\"\n#include \"IO80211Interface.h\"\n#include \"IO80211VirtualInterface.h\"\n#include \"IO80211P2PInterface.h\"\n#endif /* IO80211FAMILY_V2 */\n\n#endif /* Apple80211_h */\n"
  },
  {
    "path": "include/Airport/CCDataPipe.h",
    "content": "//\n//  CCDataPipe.h\n//  itlwm\n//\n//  Created by qcwap on 2023/6/14.\n//  Copyright © 2023 钟先耀. All rights reserved.\n//\n\n#ifndef CCDataPipe_h\n#define CCDataPipe_h\n\n#include \"CCPipe.h\"\n#include <IOKit/IOTimerEventSource.h>\n\nclass CCDataPipeBlob;\n\nclass CCDataPipe : public CCPipe {\n    OSDeclareDefaultStructors(CCDataPipe)\n    \npublic:\n    virtual void free() APPLE_KEXT_OVERRIDE;\n    virtual IOReturn configureReport(IOReportChannelList *,UInt,void *,void *) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn updateReport(IOReportChannelList *,UInt,void *,void *) APPLE_KEXT_OVERRIDE;\n    virtual bool start( IOService * provider ) APPLE_KEXT_OVERRIDE;\n    virtual void stop( IOService * provider ) APPLE_KEXT_OVERRIDE;\n    virtual void detach( IOService * provider ) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn newUserClient( task_t owningTask, void * securityID,\n    UInt32 type, OSDictionary * properties,\n    LIBKERN_RETURNS_RETAINED IOUserClient ** handler ) APPLE_KEXT_OVERRIDE;\n    virtual bool clientClose(void) APPLE_KEXT_OVERRIDE;\n    virtual void *getCoreCapturePipeReporter(void) APPLE_KEXT_OVERRIDE;\n    virtual bool isClientConnected(void) APPLE_KEXT_OVERRIDE;\n    virtual bool startPipe(void) APPLE_KEXT_OVERRIDE;\n    virtual void stopPipe(void) APPLE_KEXT_OVERRIDE;\n    virtual UInt generateStreamId(void) APPLE_KEXT_OVERRIDE;\n    virtual bool addInitCapture(void) APPLE_KEXT_OVERRIDE;\n    virtual void removeInitCapture(void) APPLE_KEXT_OVERRIDE;\n    virtual void removeCapture(void) APPLE_KEXT_OVERRIDE;\n    virtual bool profileLoaded(void) APPLE_KEXT_OVERRIDE;\n    virtual bool profileRemoved(void) APPLE_KEXT_OVERRIDE;\n    virtual bool capture(CCTimestamp *,char const*) APPLE_KEXT_OVERRIDE;\n    virtual bool capture(CCTimestamp,char const*) APPLE_KEXT_OVERRIDE;\n    virtual bool hasPrivilege(void) APPLE_KEXT_OVERRIDE;\n    virtual bool hasPrivilegeAdministrator(task_t) APPLE_KEXT_OVERRIDE;\n    virtual bool initWithOwnerNameCapacity(IOService *,char const*,char const*,CCPipeOptions const*) APPLE_KEXT_OVERRIDE;\n    virtual OSString *getClassName(void) APPLE_KEXT_OVERRIDE;\n    virtual void setCCaptureInRegistry(void) APPLE_KEXT_OVERRIDE;\n    virtual unsigned long getPipeSize(void) APPLE_KEXT_OVERRIDE;\n    virtual void setPipeSize(unsigned long) APPLE_KEXT_OVERRIDE;\n    virtual void freeCCCaptureObject(void) APPLE_KEXT_OVERRIDE;\n    virtual void *getPipeCallbacks(void) APPLE_KEXT_OVERRIDE;\n    virtual IOService *getProvider(void) APPLE_KEXT_OVERRIDE;\n    virtual void *getCurrentOptions(void) APPLE_KEXT_OVERRIDE;\n    virtual void *getDriverOptions(void) APPLE_KEXT_OVERRIDE;\n    virtual UInt getLoggingFlags(void) APPLE_KEXT_OVERRIDE;\n    virtual unsigned long getRingEntryMaxTimeMs(void) APPLE_KEXT_OVERRIDE;\n    virtual unsigned long getRingEntrySleepTimeMs(void) APPLE_KEXT_OVERRIDE;\n    virtual CCPipeStatistics *getStatistics(void) APPLE_KEXT_OVERRIDE;\n    virtual void setStatistics(CCPipeStatistics *) APPLE_KEXT_OVERRIDE;\n    virtual void publishStatistics(void) APPLE_KEXT_OVERRIDE;\n    virtual void updateStatistics(bool) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn configureAllReports(void) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn updateAllReports(void) APPLE_KEXT_OVERRIDE;\n    virtual void *createReportSet(void) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn enqueueBlob(CCDataPipeBlob *);\n    virtual bool dequeueBlob(CCDataPipeBlob **);\n    virtual void freeResources(void);\n    virtual void notifyTimeout(IOTimerEventSource *);\n    \npublic:\n    uint8_t filter[0x98];\n};\n\n#endif /* CCDataPipe_h */\n"
  },
  {
    "path": "include/Airport/CCLogPipe.h",
    "content": "//\n//  CCLogPipe.h\n//  itlwm\n//\n//  Created by qcwap on 2023/6/14.\n//  Copyright © 2023 钟先耀. All rights reserved.\n//\n\n#ifndef CCLogPipe_h\n#define CCLogPipe_h\n\n#include \"CCPipe.h\"\n#include \"CCLogStream.h\"\n#include <IOKit/IOTimerEventSource.h>\n\ntypedef int CCLogPolicy;\ntypedef int CCLogState;\nclass CCLogMetadata;\n\nclass CCLogPipe : public CCPipe {\n    OSDeclareDefaultStructors(CCLogPipe)\n    \npublic:\n    virtual void free() APPLE_KEXT_OVERRIDE;\n    virtual IOReturn configureReport(IOReportChannelList *,UInt,void *,void *) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn updateReport(IOReportChannelList *,UInt,void *,void *) APPLE_KEXT_OVERRIDE;\n    virtual bool start( IOService * provider ) APPLE_KEXT_OVERRIDE;\n    virtual void stop( IOService * provider ) APPLE_KEXT_OVERRIDE;\n    virtual void detach( IOService * provider ) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn newUserClient( task_t owningTask, void * securityID,\n    UInt32 type, OSDictionary * properties,\n    LIBKERN_RETURNS_RETAINED IOUserClient ** handler ) APPLE_KEXT_OVERRIDE;\n    virtual bool clientClose(void) APPLE_KEXT_OVERRIDE;\n    virtual void *getCoreCapturePipeReporter(void) APPLE_KEXT_OVERRIDE;\n    virtual bool isClientConnected(void) APPLE_KEXT_OVERRIDE;\n    virtual bool startPipe(void) APPLE_KEXT_OVERRIDE;\n    virtual void stopPipe(void) APPLE_KEXT_OVERRIDE;\n    virtual UInt generateStreamId(void) APPLE_KEXT_OVERRIDE;\n    virtual bool addInitCapture(void) APPLE_KEXT_OVERRIDE;\n    virtual void removeInitCapture(void) APPLE_KEXT_OVERRIDE;\n    virtual void removeCapture(void) APPLE_KEXT_OVERRIDE;\n    virtual bool profileLoaded(void) APPLE_KEXT_OVERRIDE;\n    virtual bool profileRemoved(void) APPLE_KEXT_OVERRIDE;\n    virtual bool capture(CCTimestamp *,char const*) APPLE_KEXT_OVERRIDE;\n    virtual bool capture(CCTimestamp,char const*) APPLE_KEXT_OVERRIDE;\n    virtual bool hasPrivilege(void) APPLE_KEXT_OVERRIDE;\n    virtual bool hasPrivilegeAdministrator(task_t) APPLE_KEXT_OVERRIDE;\n    virtual bool initWithOwnerNameCapacity(IOService *,char const*,char const*,CCPipeOptions const*) APPLE_KEXT_OVERRIDE;\n    virtual OSString *getClassName(void) APPLE_KEXT_OVERRIDE;\n    virtual void setCCaptureInRegistry(void) APPLE_KEXT_OVERRIDE;\n    virtual unsigned long getPipeSize(void) APPLE_KEXT_OVERRIDE;\n    virtual void setPipeSize(unsigned long) APPLE_KEXT_OVERRIDE;\n    virtual void freeCCCaptureObject(void) APPLE_KEXT_OVERRIDE;\n    virtual void *getPipeCallbacks(void) APPLE_KEXT_OVERRIDE;\n    virtual IOService *getProvider(void) APPLE_KEXT_OVERRIDE;\n    virtual void *getCurrentOptions(void) APPLE_KEXT_OVERRIDE;\n    virtual void *getDriverOptions(void) APPLE_KEXT_OVERRIDE;\n    virtual UInt getLoggingFlags(void) APPLE_KEXT_OVERRIDE;\n    virtual unsigned long getRingEntryMaxTimeMs(void) APPLE_KEXT_OVERRIDE;\n    virtual unsigned long getRingEntrySleepTimeMs(void) APPLE_KEXT_OVERRIDE;\n    virtual CCPipeStatistics *getStatistics(void) APPLE_KEXT_OVERRIDE;\n    virtual void setStatistics(CCPipeStatistics *) APPLE_KEXT_OVERRIDE;\n    virtual void publishStatistics(void) APPLE_KEXT_OVERRIDE;\n    virtual void updateStatistics(bool) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn configureAllReports(void) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn updateAllReports(void) APPLE_KEXT_OVERRIDE;\n    virtual void *createReportSet(void) APPLE_KEXT_OVERRIDE;\n    virtual void log(uint,CCStreamLogLevel,char const*,unsigned long long,bool,bool);\n    virtual void log(uint,char const*,unsigned long long,unsigned long long,unsigned long long);\n    virtual void log(uint,char const*,unsigned long long);\n    virtual bool unmapPipe(void);\n    virtual void setNotifyTimeout(uint);\n    virtual void setWatermarkLevelToNotify(unsigned long);\n    virtual bool getPolicy(CCLogPolicy *);\n    virtual void setPolicy(CCLogPolicy);\n    virtual void setStreamLogFlags(char const*,unsigned long long);\n    virtual void updateStreamLogFlags(char const*,char const*,uint);\n    virtual void setStreamLogLevel(char const*,CCStreamLogLevel);\n    virtual void setStreamConsoleLogFlags(char const*,unsigned long long);\n    virtual void setStreamConsoleLogLevel(char const*,CCStreamLogLevel);\n    virtual void updateStreamConsoleLogFlags(char const*,char const*,uint);\n    virtual IOReturn getUserSpaceNotificationPort(unsigned long long *);\n    virtual void notifyUserSpace(void);\n    virtual bool willDropMessage(uint);\n    virtual char *getScratchBuffer(unsigned long,unsigned long *,uint);\n    virtual void putScratchBuffer(char *,int);\n    virtual void resizeScratchBuffer(char *,unsigned long,unsigned long *);\n    virtual bool reserveRingEntry(unsigned long long,uint,int *);\n    virtual UInt getLogIdentifier(void);\n    virtual void freeResources(void);\n    virtual void notifyTimeout(IOTimerEventSource *);\n    virtual void log(CCStreamLogLevel,char const*,unsigned long long,unsigned long long,CCLogState);\n    virtual bool isValidCCLogMetaData(CCLogMetadata volatile*);\n    virtual bool isValidStreamLogLevel(CCStreamLogLevel);\n    virtual bool isPtrInRing(void *);\n    virtual void addOffset(uint volatile&,unsigned long,unsigned long);\n    virtual UInt calculateFreeBufferLength(uint,uint);\n    virtual void incrementRingPtr(unsigned char volatile*&,unsigned long);\n    virtual void decrementRingPtr(unsigned char volatile*&,unsigned long);\n    virtual void freeLogBuffer(unsigned long);\n    virtual const char *getLogLevelShortName(CCStreamLogLevel);\n    virtual CCLogStream *findStream(char const*);\n    virtual void releaseStream(CCLogStream *);\n    virtual void *findStreamEntry(char const*);\n    virtual bool initScratchBuffers(unsigned long,unsigned long);\n    virtual void freeScratchBuffers(void);\n    \npublic:\n    uint8_t filter[0x98];\n};\n\n#endif /* CCLogPipe_h */\n"
  },
  {
    "path": "include/Airport/CCLogStream.h",
    "content": "//\n//  CCLogStream.h\n//  itlwm\n//\n//  Created by qcwap on 2023/6/14.\n//  Copyright © 2023 钟先耀. All rights reserved.\n//\n\n#ifndef CCLogStream_h\n#define CCLogStream_h\n\n#include <IOKit/IOService.h>\n#include \"CCStream.h\"\n\nenum CCStreamLogLevel\n{\n    LEVEL_1,\n};\n\nclass CCLogStream : public CCStream {\n    OSDeclareDefaultStructors(CCLogStream)\n    \npublic:\n    virtual void free() APPLE_KEXT_OVERRIDE;\n    virtual bool init(OSDictionary *) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn configureReport(IOReportChannelList *,UInt,void *,void *) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn updateReport(IOReportChannelList *,UInt,void *,void *) APPLE_KEXT_OVERRIDE;\n    virtual bool start(IOService *) APPLE_KEXT_OVERRIDE;\n    virtual void stop(IOService *) APPLE_KEXT_OVERRIDE;\n    virtual bool attach( IOService * provider ) APPLE_KEXT_OVERRIDE;\n    virtual void detach( IOService * provider ) APPLE_KEXT_OVERRIDE;\n    virtual bool profileLoaded(void) APPLE_KEXT_OVERRIDE;\n    virtual bool profileRemoved(void) APPLE_KEXT_OVERRIDE;\n    virtual CCLogStream const *initWithPipeAndName(CCPipe *,char const*,CCStreamOptions const*) APPLE_KEXT_OVERRIDE;\n    virtual void setLevel(CCStreamLogLevel);\n    virtual CCStreamLogLevel getLevel(void);\n    virtual void setFlags(unsigned long long);\n    virtual unsigned long long getFlags(void);\n    virtual void setLogFlag(unsigned long long);\n    virtual void clearLogFlag(unsigned long long);\n    virtual void setConsoleLevel(CCStreamLogLevel);\n    virtual void setConsoleFlags(unsigned long long);\n    virtual unsigned long long getConsoleFlags(void);\n    virtual void setConsoleLogFlag(unsigned long long);\n    virtual void clearConsoleLogFlag(unsigned long long);\n    \npublic:\n    uint8_t filter[0x98];\n};\n\n#endif /* CCLogStream_h */\n\n"
  },
  {
    "path": "include/Airport/CCPipe.h",
    "content": "//\n//  CCPipe.h\n//  itlwm\n//\n//  Created by qcwap on 2023/6/14.\n//  Copyright © 2023 钟先耀. All rights reserved.\n//\n\n#ifndef CCPipe_h\n#define CCPipe_h\n\n#include <IOKit/IOService.h>\n\nclass CCTimestamp;\nclass CCPipeStatistics;\nstruct CCPipeOptions {\n    uint64_t pipe_type;  // 0x0\n    uint64_t log_data_type;  // 0x8\n    uint64_t pipe_size;  // 0x10\n    uint64_t min_log_size_notify;  // 0x18\n    uint32_t notify_threshold;  // 0x20\n    char     file_name[0x100];   // 0x24\n    char     name[0xF0];    // 0x124\n    char    pad8[0x10];     // 0x214\n    uint32_t    pad9;       // 0x224\n    uint32_t    pad10;     // 0x228\n    uint64_t    file_options;  // 0x230\n    uint64_t    log_policy;  // 0x238\n    uint32_t    pad13;\n    char    directory_name[0x100];   // 0x244\n    uint8_t pad[0xC];\n};\n\nstatic_assert(offsetof(CCPipeOptions, pipe_size) == 0x10, \"Invalid offset\");\nstatic_assert(offsetof(CCPipeOptions, file_name) == 0x24, \"Invalid offset\");\nstatic_assert(offsetof(CCPipeOptions, name) == 0x124, \"Invalid offset\");\nstatic_assert(offsetof(CCPipeOptions, pad9) == 0x224, \"Invalid offset\");\nstatic_assert(offsetof(CCPipeOptions, pad10) == 0x228, \"Invalid offset\");\nstatic_assert(offsetof(CCPipeOptions, file_options) == 0x230, \"Invalid offset\");\nstatic_assert(offsetof(CCPipeOptions, log_policy) == 0x238, \"Invalid offset\");\nstatic_assert(offsetof(CCPipeOptions, directory_name) == 0x244, \"Invalid offset\");\nstatic_assert(sizeof(CCPipeOptions) == 0x350, \"Invalid offset\");\n\n\nclass CCPipe : public IOService {\n    OSDeclareAbstractStructors(CCPipe)\n    \npublic:\n    virtual void free() APPLE_KEXT_OVERRIDE;\n    virtual IOReturn configureReport(IOReportChannelList *,UInt,void *,void *) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn updateReport(IOReportChannelList *,UInt,void *,void *) APPLE_KEXT_OVERRIDE;\n    virtual void detach( IOService * provider ) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn newUserClient( task_t owningTask, void * securityID,\n    UInt32 type, OSDictionary * properties,\n    LIBKERN_RETURNS_RETAINED IOUserClient ** handler ) = 0;\n    virtual bool clientClose(void) = 0;\n    virtual void *getCoreCapturePipeReporter(void);\n    virtual bool isClientConnected(void) = 0;\n    virtual bool startPipe(void);\n    virtual void stopPipe(void);\n    virtual UInt generateStreamId(void);\n    virtual bool addInitCapture(void);\n    virtual void removeInitCapture(void);\n    virtual void removeCapture(void);\n    virtual bool profileLoaded(void);\n    virtual bool profileRemoved(void);\n    virtual bool capture(CCTimestamp *,char const*) = 0;\n    virtual bool capture(CCTimestamp,char const*) = 0;\n    virtual bool hasPrivilege(void);\n    virtual bool hasPrivilegeAdministrator(task_t);\n    virtual bool initWithOwnerNameCapacity(IOService *,char const*,char const*,CCPipeOptions const*);\n    virtual OSString *getClassName(void);\n    virtual void setCCaptureInRegistry(void);\n    virtual unsigned long getPipeSize(void);\n    virtual void setPipeSize(unsigned long);\n    virtual void freeCCCaptureObject(void);\n    virtual void *getPipeCallbacks(void);\n    virtual IOService *getProvider(void);\n    virtual void *getCurrentOptions(void);\n    virtual void *getDriverOptions(void);\n    virtual UInt getLoggingFlags(void);\n    virtual unsigned long getRingEntryMaxTimeMs(void);\n    virtual unsigned long getRingEntrySleepTimeMs(void);\n    virtual CCPipeStatistics *getStatistics(void);\n    virtual void setStatistics(CCPipeStatistics *);\n    virtual void publishStatistics(void);\n    virtual void updateStatistics(bool);\n    virtual IOReturn configureAllReports(void);\n    virtual IOReturn updateAllReports(void);\n    virtual void *createReportSet(void);\n    \npublic:\n    static CCPipe *withOwnerNameCapacity(IOService *,char const*,char const*,CCPipeOptions const*);\n    \npublic:\n    uint8_t filter[0x90];\n};\n\n#endif /* CCPipe_h */\n"
  },
  {
    "path": "include/Airport/CCStream.h",
    "content": "//\n//  CCStream.h\n//  itlwm\n//\n//  Created by qcwap on 2023/6/14.\n//  Copyright © 2023 钟先耀. All rights reserved.\n//\n\n#ifndef CCStream_h\n#define CCStream_h\n\n#include <IOKit/IOService.h>\n#include \"CCPipe.h\"\n\nstruct CCStreamOptions {\n    uint64_t stream_type;\n    uint64_t console_level;\n    char pad[0x348];\n};\n\nclass CCStream : public IOService {\n    OSDeclareAbstractStructors(CCStream)\n    \npublic:\n    virtual void free() APPLE_KEXT_OVERRIDE;\n    virtual IOReturn configureReport(IOReportChannelList *,UInt,void *,void *) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn updateReport(IOReportChannelList *,UInt,void *,void *) APPLE_KEXT_OVERRIDE;\n    virtual bool attach( IOService * provider ) APPLE_KEXT_OVERRIDE;\n    virtual void detach( IOService * provider ) APPLE_KEXT_OVERRIDE;\n    virtual bool profileLoaded(void);\n    virtual bool profileRemoved(void);\n    virtual CCStream const *initWithPipeAndName(CCPipe *,char const*,CCStreamOptions const*);\n    \npublic:\n    static CCStream *withPipeAndName(CCPipe *,char const*,CCStreamOptions const*);\n    CCPipe *getPipe() const;\n    \npublic:\n    uint8_t filter[0x90];\n};\n\n#endif /* CCStream_h */\n\n"
  },
  {
    "path": "include/Airport/IO80211Controller.h",
    "content": "//\n//  IO80211Controller.h\n//  IO80211Family\n//\n\n#ifndef _IO80211CONTROLLER_H\n#define _IO80211CONTROLLER_H\n\n#if defined(KERNEL) && defined(__cplusplus)\n\n#include <Availability.h>\n#include <libkern/version.h>\n\n// This is necessary, because even the latest Xcode does not support properly targeting 11.0.\n#ifndef __IO80211_TARGET\n#error \"Please define __IO80211_TARGET to the requested version\"\n#endif\n\n#if VERSION_MAJOR > 8\n#define _MODERN_BPF\n#endif\n\n#include <sys/kpi_mbuf.h>\n\n#include <IOKit/network/IOEthernetController.h>\n\n#include <sys/param.h>\n#include <net/bpf.h>\n\n#include \"apple80211_ioctl.h\"\n#include \"IO80211WorkLoop.h\"\n\n#define AUTH_TIMEOUT            15    // seconds\n\n/*! @enum LinkSpeed.\n @abstract ???.\n @discussion ???.\n @constant LINK_SPEED_80211A 54 Mbps\n @constant LINK_SPEED_80211B 11 Mbps.\n @constant LINK_SPEED_80211G 54 Mbps.\n */\nenum {\n    LINK_SPEED_80211A    = 54000000ul,        // 54 Mbps\n    LINK_SPEED_80211B    = 11000000ul,        // 11 Mbps\n    LINK_SPEED_80211G    = 54000000ul,        // 54 Mbps\n    LINK_SPEED_80211N    = 300000000ul,        // 300 Mbps (MCS index 15, 400ns GI, 40 MHz channel)\n};\n\nenum IO80211CountryCodeOp\n{\n    kIO80211CountryCodeReset,                // Reset country code to world wide default, and start\n    // searching for 802.11d beacon\n};\ntypedef enum IO80211CountryCodeOp IO80211CountryCodeOp;\n\nenum IO80211SystemPowerState\n{\n    kIO80211SystemPowerStateUnknown,\n    kIO80211SystemPowerStateAwake,\n    kIO80211SystemPowerStateSleeping,\n};\ntypedef enum IO80211SystemPowerState IO80211SystemPowerState;\n\nenum IO80211FeatureCode\n{\n    kIO80211Feature80211n = 1,\n};\ntypedef enum IO80211FeatureCode IO80211FeatureCode;\n\n\nclass IOSkywalkInterface;\nclass IO80211ScanManager;\nenum CCStreamLogLevel\n{\n    LEVEL_1,\n};\n\nenum scanSource\n{\n    SOURCE_1,\n};\n\nenum joinStatus\n{\n    STATUS_1,\n};\n\nclass IO80211SkywalkInterface;\nclass IO80211Controller;\nclass IO80211Interface;\nclass IO82110WorkLoop;\nclass IO80211VirtualInterface;\nclass IO80211ControllerMonitor;\nclass CCLogPipe;\nclass CCIOReporterLogStream;\nclass CCLogStream;\nclass IO80211VirtualInterface;\nclass IO80211RangingManager;\nclass IO80211FlowQueue;\nclass IO80211FlowQueueLegacy;\nclass FlowIdMetadata;\nclass IOReporter;\n#if __IO80211_TARGET >= __MAC_11_0\nclass IO80211InfraInterface;\n#endif\nextern void IO80211VirtualInterfaceNamerRetain();\n\n\nstruct apple80211_hostap_state;\n\nstruct apple80211_awdl_sync_channel_sequence;\nstruct ieee80211_ht_capability_ie;\nstruct apple80211_channel_switch_announcement;\nstruct apple80211_beacon_period_data;\nstruct apple80211_power_debug_sub_info;\nstruct apple80211_stat_report;\nstruct apple80211_frame_counters;\nstruct apple80211_leaky_ap_event;\nstruct apple80211_chip_stats;\nstruct apple80211_extended_stats;\nstruct apple80211_ampdu_stat_report;\nstruct apple80211_btCoex_report;\nstruct apple80211_cca_report;\nclass CCPipe;\nstruct apple80211_lteCoex_report;\n\n//typedef int scanSource;\n//typedef int joinStatus;\n//typedef int CCStreamLogLevel;\ntypedef IOReturn (*IOCTL_FUNC)(IO80211Controller*, IO80211Interface*, IO80211VirtualInterface*, apple80211req*, bool);\nextern IOCTL_FUNC gGetHandlerTable[];\nextern IOCTL_FUNC gSetHandlerTable[];\n\nclass IO80211Controller : public IOEthernetController {\n    OSDeclareAbstractStructors(IO80211Controller)\n\npublic:\n\n    virtual void free() APPLE_KEXT_OVERRIDE;\n#if __IO80211_TARGET <= __MAC_10_15\n    virtual bool terminate(unsigned int) APPLE_KEXT_OVERRIDE;\n#endif\n    virtual bool init(OSDictionary *) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn configureReport(IOReportChannelList *,UInt,void *,void *) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn updateReport(IOReportChannelList *,UInt,void *,void *) APPLE_KEXT_OVERRIDE;\n    virtual bool start(IOService *) APPLE_KEXT_OVERRIDE;\n    virtual void stop(IOService *) APPLE_KEXT_OVERRIDE;\n    virtual IOService* getProvider(void) const APPLE_KEXT_OVERRIDE;\n    virtual IOWorkLoop* getWorkLoop(void) const APPLE_KEXT_OVERRIDE;\n    virtual const char* stringFromReturn(int) APPLE_KEXT_OVERRIDE;\n    virtual int errnoFromReturn(int) APPLE_KEXT_OVERRIDE;\n    virtual IOOutputQueue* getOutputQueue(void) const APPLE_KEXT_OVERRIDE;\n    virtual bool createWorkLoop(void) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn enable(IONetworkInterface *) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn disable(IONetworkInterface *) APPLE_KEXT_OVERRIDE;\n    virtual bool attachInterface(IONetworkInterface **, bool attach = true) APPLE_KEXT_OVERRIDE;\n#if __IO80211_TARGET >= __MAC_10_15\n    virtual void detachInterface(IONetworkInterface *, bool sync = false) APPLE_KEXT_OVERRIDE;\n#endif\n    virtual IONetworkInterface* createInterface(void) APPLE_KEXT_OVERRIDE;\n    virtual bool configureInterface(IONetworkInterface *) APPLE_KEXT_OVERRIDE;\n#ifdef __PRIVATE_SPI__\n    virtual IOReturn outputStart(IONetworkInterface *,UInt) APPLE_KEXT_OVERRIDE;\n#endif\n    virtual IOReturn getHardwareAddress(IOEthernetAddress *) APPLE_KEXT_OVERRIDE;\n    virtual void requestPacketTx(void*, UInt);\n    virtual IOReturn getHardwareAddressForInterface(IO80211Interface *,IOEthernetAddress *);\n    virtual void inputMonitorPacket(mbuf_t,UInt,void *,unsigned long);\n    virtual int outputRaw80211Packet(IO80211Interface *,mbuf_t);\n    virtual int outputActionFrame(IO80211Interface *,mbuf_t);\n    virtual int bpfOutputPacket(OSObject *,UInt,mbuf_t m);\n    virtual SInt32 monitorModeSetEnabled(IO80211Interface*, bool, UInt);\n    virtual IO80211Interface* getNetworkInterface(void);\n#if __IO80211_TARGET >= __MAC_10_15\n    virtual IO80211SkywalkInterface* getPrimarySkywalkInterface(void);\n#endif\n    virtual SInt32 apple80211_ioctl(IO80211Interface *, IO80211VirtualInterface*, ifnet_t,unsigned long,void *);\n#if __IO80211_TARGET >= __MAC_10_15\n    virtual SInt32 apple80211_ioctl(IO80211SkywalkInterface *,unsigned long,void *);\n#endif\n    virtual SInt32 apple80211_ioctl(IO80211Interface *interface, ifnet_t net,unsigned long id,void *data) {\n        return apple80211_ioctl(interface, NULL, net, id, data);\n    }\n    virtual SInt32 apple80211Request(unsigned int, int, IO80211Interface*, void*) = 0;\n    virtual SInt32 apple80211VirtualRequest(UInt,int,IO80211VirtualInterface *,void *);\n#if __IO80211_TARGET >= __MAC_10_15\n    virtual SInt32 apple80211SkywalkRequest(UInt,int,IO80211SkywalkInterface *,void *);\n#endif\n    virtual SInt32 stopDMA() = 0;\n    virtual UInt32 hardwareOutputQueueDepth(IO80211Interface*) = 0;\n    virtual SInt32 performCountryCodeOperation(IO80211Interface*, IO80211CountryCodeOp) = 0;\n    virtual bool useAppleRSNSupplicant(IO80211Interface *);\n    virtual bool useAppleRSNSupplicant(IO80211VirtualInterface *);\n    virtual void dataLinkLayerAttachComplete(IO80211Interface *);\n    virtual SInt32 enableFeature(IO80211FeatureCode, void*) = 0;\n    virtual SInt32 setVirtualHardwareAddress(IO80211VirtualInterface *,ether_addr *);\n    virtual SInt32 enableVirtualInterface(IO80211VirtualInterface *);\n    virtual SInt32 disableVirtualInterface(IO80211VirtualInterface *);\n    virtual bool requiresExplicitMBufRelease() {\n        return false;\n    }\n    virtual bool flowIdSupported() {\n        return false;\n    }\n    virtual IO80211FlowQueueLegacy* requestFlowQueue(FlowIdMetadata const*);\n    virtual void releaseFlowQueue(IO80211FlowQueue *);\n#if __IO80211_TARGET >= __MAC_10_15\n    virtual void getLogPipes(CCPipe**, CCPipe**, CCPipe**) {};\n#endif\n    virtual IOReturn enablePacketTimestamping(void) {\n        return kIOReturnUnsupported;\n    }\n    virtual IOReturn disablePacketTimestamping(void) {\n        return kIOReturnUnsupported;\n    }\n    virtual UInt32 selfDiagnosticsReport(int,char const*,UInt);\n    virtual UInt32 getDataQueueDepth(OSObject *);\n#if __IO80211_TARGET >= __MAC_11_0\n    virtual bool isAssociatedToMovingNetwork(void) { return false; }\n#endif\n    virtual mbuf_flags_t inputPacket(mbuf_t);\n    virtual SInt32 apple80211_ioctl_get(IO80211Interface *,IO80211VirtualInterface *,ifnet_t,void *);\n    \n    \n#if __IO80211_TARGET >= __MAC_10_15\n    virtual SInt32 apple80211_ioctl_get(IO80211SkywalkInterface *,void *);\n    virtual SInt32 apple80211_ioctl_set(IO80211Interface *,IO80211VirtualInterface *,IO80211SkywalkInterface *,void *);\n    virtual SInt32 apple80211_ioctl_set(IO80211SkywalkInterface *,void*);\n    virtual bool attachInterface(IOSkywalkInterface *,IOService *);\n#else\n    virtual SInt32 apple80211_ioctl_set(IO80211Interface *,IO80211VirtualInterface *,ifnet_t,void *);\n#endif\n    \n    \n#if __IO80211_TARGET >= __MAC_11_0\n    virtual bool detachInterface(IOSkywalkInterface *, bool);\n#endif\n    virtual IO80211VirtualInterface* createVirtualInterface(ether_addr *,UInt);\n    virtual bool attachVirtualInterface(IO80211VirtualInterface **,ether_addr *,UInt,bool);\n    virtual bool detachVirtualInterface(IO80211VirtualInterface *,bool);\n#if __IO80211_TARGET >= __MAC_10_15\n    virtual IOReturn enable(IO80211SkywalkInterface *);\n    virtual IOReturn disable(IO80211SkywalkInterface *);\n#endif\n    \npublic:\n#if __IO80211_TARGET >= __MAC_11_0\n    void setDisplayState(bool);\n    void resetIO80211ReporterHistory(void);\n    bool markInterfaceUnitUnused(char const*,UInt);\n    bool markInterfaceUnitUsed(char const*,UInt);\n    bool assignUnitNumber(char const*);\n#endif\n#if __IO80211_TARGET >= __MAC_10_15\n    IO80211SkywalkInterface* getInfraInterface(void);\n    IO80211ScanManager* getPrimaryInterfaceScanManager(void);\n    IO80211ControllerMonitor* getInterfaceMonitor(void);\n#endif\n    IOReturn addReporterLegend(IOService *,IOReporter *,char const*,char const*);\n    IOReturn removeReporterFromLegend(IOService *,IOReporter *,char const*,char const*);\n    IOReturn unlockIOReporterLegend(void);\n    void lockIOReporterLegend(void);// Suspected return type - int\n    IOReturn logIOReportLogStreamSubscription(unsigned long long);\n    IOReturn addIOReportLogStreamForProvider(IOService *,unsigned long long *);\n    IOReturn addSubscriptionForThisReporterFetchedOnTimer(IOReporter *,char const*,char const*,IOService *) ;\n    IOReturn addSubscriptionForProviderFetchedOnTimer(IOService *);\n    void handleIOReporterTimer(IOTimerEventSource *);\n    void setIOReportersStreamFlags(unsigned long long);\n    void updateIOReportersStreamFrequency(void); // Suspected return type - int\n    void setIOReportersStreamLevel(CCStreamLogLevel);\n    void powerChangeGated(OSObject *,void *,void *,void *,void *);\n    int copyOut(void const*,unsigned long long,unsigned long);\n#if __IO80211_TARGET >= __MAC_11_0\n    SInt32 getASSOCIATE_EXTENDED_RESULT(IO80211Interface *,IO80211VirtualInterface *,IO80211InfraInterface *,apple80211_assoc_result_data *);\n#endif\n    SInt32 getASSOCIATE_RESULT(IO80211Interface *,IO80211VirtualInterface *,IO80211SkywalkInterface *,apple80211_assoc_result_data *);\n    IOReturn copyIn(unsigned long long,void *,unsigned long);\n    void logIOCTL(apple80211req *);\n    bool isIOCTLLoggingRestricted(apple80211req *);\n    IOReturn setChanNoiseFloorLTE(apple80211_stat_report *,int);\n    IOReturn setChanNoiseFloor(apple80211_stat_report *,int);\n    IOReturn setChanCCA(apple80211_stat_report *,int);\n    IOReturn setChanExtendedCCA(apple80211_stat_report *,apple80211_cca_report *);\n    bool setLTECoexstat(apple80211_stat_report *,apple80211_lteCoex_report *);\n    bool setBTCoexstat(apple80211_stat_report *,apple80211_btCoex_report *);\n    bool setAMPDUstat(apple80211_stat_report *,apple80211_ampdu_stat_report *,apple80211_channel *);\n    UInt32 getCountryCode(apple80211_country_code_data *);\n    IOReturn setCountryCode(apple80211_country_code_data *);\n    bool getInfraExtendedStats(apple80211_extended_stats *);\n    bool getChipCounterStats(apple80211_chip_stats *);\n#if __IO80211_TARGET >= __MAC_10_15\n    bool setExtendedChipCounterStats(apple80211_stat_report *,void *);\n#endif\n    bool setChipCounterStats(apple80211_stat_report *,apple80211_chip_stats *,apple80211_channel *);\n    bool setLeakyAPStats(apple80211_leaky_ap_event *);\n    bool setFrameStats(apple80211_stat_report *,apple80211_frame_counters *,apple80211_channel *);\n    bool setPowerStats(apple80211_stat_report *,apple80211_power_debug_sub_info *);\n    bool getBeaconPeriod(apple80211_beacon_period_data *);\n    SInt32 apple80211VirtualRequestIoctl(unsigned int,int,IO80211VirtualInterface *,void *);\n    bool getBSSIDData(OSObject *,apple80211_bssid_data *);\n    bool getSSIDData(apple80211_ssid_data *);\n    bool inputInfraPacket(mbuf_t);\n#if __IO80211_TARGET >= __MAC_10_15\n    void notifyHostapState(apple80211_hostap_state *);\n#endif\n    bool isAwdlAssistedDiscoveryEnabled(void);\n    void joinDone(scanSource,joinStatus);\n    void joinStarted(scanSource,joinStatus);\n    void handleChannelSwitchAnnouncement(apple80211_channel_switch_announcement *);\n    void scanDone(scanSource,int);\n    void scanStarted(scanSource,apple80211_scan_data *);\n    void printChannels(void);\n#if __IO80211_TARGET >= __MAC_10_15\n    void updateInterfaceCoexRiskPct(unsigned long long);\n#endif\n    SInt32 getInfraChannel(apple80211_channel_data *);\n    void calculateInterfacesAvaiability(void); // Suspected return type - int\n    void setChannelSequenceList(apple80211_awdl_sync_channel_sequence *); // Suspected return type - int\n#if __IO80211_TARGET >= __MAC_10_15\n    void setPrimaryInterfaceDatapathState(bool);\n    UInt32 getPrimaryInterfaceLinkState(void);\n#endif\n    void setCurrentChannel(apple80211_channel *); // Suspected return type - int\n    void setHtCapability(ieee80211_ht_capability_ie *);\n    UInt32 getHtCapability(void);\n    UInt32 getHtCapabilityLength(void);\n    bool io80211isDebuggable(bool* enable);\n    void logDebug(unsigned long long,char const*,...); // Suspected return type - int\n    void vlogDebug(unsigned long long,char const*,va_list); // Suspected return type - char\n    void logDebug(char const*,...); // Suspected return type - int\n    bool calculateInterfacesCoex(void);\n    void setInfraChannel(apple80211_channel *);\n#if __IO80211_TARGET >= __MAC_10_15\n    void configureAntennae(void);\n#endif\n    SInt32 apple80211RequestIoctl(unsigned int,int,IO80211Interface *,void *);\n    UInt32 radioCountForInterface(IO80211Interface *);\n    void releaseIOReporters(void);\n#if __IO80211_TARGET >= __MAC_10_15\n    bool findAndAttachToFaultReporter(void);\n#endif\n    UInt32 setupControlPathLogging(void);\n    IOReturn createIOReporters(IOService *);\n    IOReturn powerChangeHandler(void *,void *,unsigned int,IOService *,void *,unsigned long);\n    \n    OSMetaClassDeclareReservedUnused( IO80211Controller,  0);\n    OSMetaClassDeclareReservedUnused( IO80211Controller,  1);\n    OSMetaClassDeclareReservedUnused( IO80211Controller,  2);\n    OSMetaClassDeclareReservedUnused( IO80211Controller,  3);\n    OSMetaClassDeclareReservedUnused( IO80211Controller,  4);\n    OSMetaClassDeclareReservedUnused( IO80211Controller,  5);\n    OSMetaClassDeclareReservedUnused( IO80211Controller,  6);\n    OSMetaClassDeclareReservedUnused( IO80211Controller,  7);\n    OSMetaClassDeclareReservedUnused( IO80211Controller,  8);\n    OSMetaClassDeclareReservedUnused( IO80211Controller,  9);\n    OSMetaClassDeclareReservedUnused( IO80211Controller, 10);\n    OSMetaClassDeclareReservedUnused( IO80211Controller, 11);\n    OSMetaClassDeclareReservedUnused( IO80211Controller, 12);\n    OSMetaClassDeclareReservedUnused( IO80211Controller, 13);\n    OSMetaClassDeclareReservedUnused( IO80211Controller, 14);\n    OSMetaClassDeclareReservedUnused( IO80211Controller, 15);\n\nprotected:\n    uint8_t  filler[0x500];\n};\n\n// 0x215: 1 byte, length of channel sequence, should be 16\n// 0x21c: channel sequence, should contain 16 elements of length 12, possibly apple80211_channel (but why 16?)\n// struct of three ints, last looks like flags, first unused\n\n/*\n void __thiscall\nsetChannelSequenceList(IO80211Controller *this,apple80211_awdl_sync_channel_sequence *param_1)\n\n{\n  _memcpy(this + 0x210,param_1,400);\n  calculateInterfacesAvaiability(this);\n  return;\n}\n*/\n\n\n#endif /* defined(KERNEL) && defined(__cplusplus) */\n\n#endif /* !_IO80211CONTROLLER_H */\n"
  },
  {
    "path": "include/Airport/IO80211ControllerV2.h",
    "content": "//\n//  IOSkywalkInterface.h\n//  itlwm\n//\n//  Created by qcwap on 2023/6/7.\n//  Copyright © 2023 钟先耀. All rights reserved.\n//\n\n#ifndef _IO80211CONTROLLER_H\n#define _IO80211CONTROLLER_H\n\n#if defined(KERNEL) && defined(__cplusplus)\n\n#include <Availability.h>\n#include <libkern/version.h>\n\n// This is necessary, because even the latest Xcode does not support properly targeting 11.0.\n#ifndef __IO80211_TARGET\n#error \"Please define __IO80211_TARGET to the requested version\"\n#endif\n\n#if VERSION_MAJOR > 8\n#define _MODERN_BPF\n#endif\n\n#include <sys/kpi_mbuf.h>\n\n#include <IOKit/network/IOEthernetController.h>\n\n#include <sys/param.h>\n#include <net/bpf.h>\n\n#include \"apple80211_ioctl.h\"\n#include \"IO80211SkywalkInterface.h\"\n#include \"IO80211WorkLoop.h\"\n#include \"IO80211WorkQueue.h\"\n#include \"CCStream.h\"\n#include \"CCDataPipe.h\"\n#include \"CCLogPipe.h\"\n#include \"CCLogStream.h\"\n\n#define AUTH_TIMEOUT            15    // seconds\n\n/*! @enum LinkSpeed.\n @abstract ???.\n @discussion ???.\n @constant LINK_SPEED_80211A 54 Mbps\n @constant LINK_SPEED_80211B 11 Mbps.\n @constant LINK_SPEED_80211G 54 Mbps.\n */\nenum {\n    LINK_SPEED_80211A    = 54000000ul,        // 54 Mbps\n    LINK_SPEED_80211B    = 11000000ul,        // 11 Mbps\n    LINK_SPEED_80211G    = 54000000ul,        // 54 Mbps\n    LINK_SPEED_80211N    = 300000000ul,        // 300 Mbps (MCS index 15, 400ns GI, 40 MHz channel)\n};\n\nenum IO80211CountryCodeOp\n{\n    kIO80211CountryCodeReset,                // Reset country code to world wide default, and start\n    // searching for 802.11d beacon\n};\ntypedef enum IO80211CountryCodeOp IO80211CountryCodeOp;\n\nenum IO80211SystemPowerState\n{\n    kIO80211SystemPowerStateUnknown,\n    kIO80211SystemPowerStateAwake,\n    kIO80211SystemPowerStateSleeping,\n};\ntypedef enum IO80211SystemPowerState IO80211SystemPowerState;\n\nenum IO80211FeatureCode\n{\n    kIO80211Feature80211n = 1,\n};\ntypedef enum IO80211FeatureCode IO80211FeatureCode;\n\n\nclass IOSkywalkInterface;\nclass IO80211ScanManager;\n\nenum scanSource\n{\n    SOURCE_1,\n};\n\nenum joinStatus\n{\n    STATUS_1,\n};\n\nclass IO80211Controller;\nclass IO80211Interface;\nclass IO82110WorkLoop;\nclass IO80211VirtualInterface;\nclass IO80211ControllerMonitor;\nclass CCLogPipe;\nclass CCIOReporterLogStream;\nclass CCLogStream;\nclass IO80211VirtualInterface;\nclass IO80211RangingManager;\nclass IO80211FlowQueue;\nclass IO80211FlowQueueLegacy;\nclass FlowIdMetadata;\nclass IOReporter;\nclass IO80211InfraInterface;\nextern void IO80211VirtualInterfaceNamerRetain();\n\n\nstruct apple80211_hostap_state;\n\nstruct apple80211_awdl_sync_channel_sequence;\nstruct ieee80211_ht_capability_ie;\nstruct apple80211_channel_switch_announcement;\nstruct apple80211_beacon_period_data;\nstruct apple80211_power_debug_sub_info;\nstruct apple80211_stat_report;\nstruct apple80211_frame_counters;\nstruct apple80211_leaky_ap_event;\nstruct apple80211_chip_stats;\nstruct apple80211_extended_stats;\nstruct apple80211_ampdu_stat_report;\nstruct apple80211_btCoex_report;\nstruct apple80211_cca_report;\nclass CCPipe;\nstruct apple80211_lteCoex_report;\n\n//typedef int scanSource;\n//typedef int joinStatus;\n//typedef int CCStreamLogLevel;\ntypedef IOReturn (*IOCTL_FUNC)(IO80211Controller*, IO80211Interface*, IO80211VirtualInterface*, apple80211req*, bool);\nextern IOCTL_FUNC gGetHandlerTable[];\nextern IOCTL_FUNC gSetHandlerTable[];\n\nclass IO80211InterfaceAVCAdvisory;\n\nclass IO80211Controller : public IOEthernetController {\n    OSDeclareAbstractStructors(IO80211Controller)\n\npublic:\n\n    virtual void free() APPLE_KEXT_OVERRIDE;\n    virtual bool init(OSDictionary *) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn configureReport(IOReportChannelList *,UInt,void *,void *) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn updateReport(IOReportChannelList *,UInt,void *,void *) APPLE_KEXT_OVERRIDE;\n    virtual bool start(IOService *) APPLE_KEXT_OVERRIDE;\n    virtual void stop(IOService *) APPLE_KEXT_OVERRIDE;\n    virtual IOWorkLoop* getWorkLoop(void) const APPLE_KEXT_OVERRIDE;\n    virtual const char* stringFromReturn(int) APPLE_KEXT_OVERRIDE;\n    virtual int errnoFromReturn(int) APPLE_KEXT_OVERRIDE;\n    virtual UInt32 getFeatures() const APPLE_KEXT_OVERRIDE;\n    virtual const OSString * newVendorString() const APPLE_KEXT_OVERRIDE;\n    virtual const OSString * newModelString() const APPLE_KEXT_OVERRIDE;\n    virtual bool createWorkLoop() APPLE_KEXT_OVERRIDE;\n    virtual IOReturn getHardwareAddress(IOEthernetAddress *) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn setHardwareAddress(const IOEthernetAddress * addrP) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn setMulticastMode(bool active) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn setPromiscuousMode(bool active) APPLE_KEXT_OVERRIDE;\n    virtual bool isCommandProhibited(int) = 0;\n    virtual bool createWorkQueue();\n    virtual IO80211WorkQueue *getWorkQueue();\n    virtual void requestPacketTx(void*, UInt);\n    virtual IOCommandGate *getIO80211CommandGate();\n    virtual IOReturn getHardwareAddressForInterface(IOEthernetAddress *);\n    virtual bool useAppleRSNSupplicant(IO80211VirtualInterface *);\n    virtual IO80211SkywalkInterface* getPrimarySkywalkInterface(void);\n    virtual int bpfOutputPacket(OSObject *,UInt,mbuf_t m);\n    virtual SInt32 monitorModeSetEnabled(bool, UInt);\n    virtual SInt32 apple80211_ioctl(IO80211SkywalkInterface *,unsigned long,void *, bool, bool);\n    virtual SInt32 apple80211VirtualRequest(UInt,int,IO80211VirtualInterface *,void *);\n    virtual SInt32 apple80211SkywalkRequest(UInt,int,IO80211SkywalkInterface *,void *);\n    virtual SInt32 apple80211SkywalkRequest(UInt,int,IO80211SkywalkInterface *,void *,void *);\n    \n    virtual SInt32 handleCardSpecific(IO80211SkywalkInterface *,unsigned long,void *,bool) = 0;\n    \n    virtual UInt32 hardwareOutputQueueDepth();\n    virtual SInt32 performCountryCodeOperation(IO80211CountryCodeOp);\n    \n    virtual void dataLinkLayerAttachComplete();\n    virtual SInt32 enableFeature(IO80211FeatureCode, void*) = 0;\n    \n    virtual IOReturn getDRIVER_VERSION(IO80211SkywalkInterface *,apple80211_version_data *) = 0;\n    virtual IOReturn getHARDWARE_VERSION(IO80211SkywalkInterface *,apple80211_version_data *) = 0;\n    virtual IOReturn getCARD_CAPABILITIES(IO80211SkywalkInterface *,apple80211_capability_data *) = 0;\n    virtual IOReturn getPOWER(IO80211SkywalkInterface *,apple80211_power_data *) = 0;\n    virtual IOReturn setPOWER(IO80211SkywalkInterface *,apple80211_power_data *) = 0;\n    virtual IOReturn getCOUNTRY_CODE(IO80211SkywalkInterface *,apple80211_country_code_data *) = 0;\n    virtual IOReturn setCOUNTRY_CODE(IO80211SkywalkInterface *,apple80211_country_code_data *) = 0;\n    virtual IOReturn setGET_DEBUG_INFO(IO80211SkywalkInterface *,apple80211_debug_command *) = 0;\n    \n    virtual SInt32 setVirtualHardwareAddress(IO80211VirtualInterface *,ether_addr *);\n    virtual SInt32 enableVirtualInterface(IO80211VirtualInterface *);\n    virtual SInt32 disableVirtualInterface(IO80211VirtualInterface *);\n    virtual bool requiresExplicitMBufRelease();\n    virtual bool flowIdSupported() {\n        return false;\n    }\n    virtual IO80211FlowQueueLegacy* requestFlowQueue(FlowIdMetadata const*);\n    virtual void releaseFlowQueue(IO80211FlowQueue *);\n    virtual bool getLogPipes(CCPipe**, CCPipe**, CCPipe**);\n    virtual void enableFeatureForLoggingFlags(unsigned long long) {};\n    virtual IOReturn requestQueueSizeAndTimeout(unsigned short *, unsigned short *) { return kIOReturnIOError; };\n    virtual IOReturn enablePacketTimestamping(void) {\n        return kIOReturnUnsupported;\n    }\n    virtual IOReturn disablePacketTimestamping(void) {\n        return kIOReturnUnsupported;\n    }\n    \n    virtual UInt getPacketTSCounter();\n    virtual void *getDriverTextLog();\n    \n    virtual UInt32 selfDiagnosticsReport(int,char const*,UInt);\n    \n    virtual void *getFaultReporterFromDriver();\n    \n    virtual UInt32 getDataQueueDepth(OSObject *);\n    virtual bool isAssociatedToMovingNetwork(void) { return false; }\n    virtual bool wasDynSARInFailSafeMode(void) { return false; }\n    virtual void updateAdvisoryScoresIfNeed(void);\n    virtual UInt64 getAVCAdvisoryInfo(IO80211InterfaceAVCAdvisory *);\n    virtual SInt32 apple80211_ioctl_get(IO80211SkywalkInterface *,void *, bool, bool);\n    virtual SInt32 apple80211_ioctl_set(IO80211SkywalkInterface *,void *, bool, bool);\n    virtual bool attachInterface(OSObject *,IOService *);\n    virtual SInt32 apple80211_ioctl_get(IO80211VirtualInterface *,void *,bool,bool);\n    virtual SInt32 apple80211_ioctl_set(IO80211VirtualInterface *,void *,bool,bool);\n    virtual void detachInterface(OSObject *,bool);\n    virtual IO80211VirtualInterface* createVirtualInterface(ether_addr *,UInt);\n    virtual bool attachVirtualInterface(IO80211VirtualInterface **,ether_addr *,UInt,bool);\n    virtual bool detachVirtualInterface(IO80211VirtualInterface *,bool);\n    virtual IOReturn enable(IO80211SkywalkInterface *);\n    virtual IOReturn disable(IO80211SkywalkInterface *);\n    \n    OSMetaClassDeclareReservedUnused( IO80211Controller,  0);\n    OSMetaClassDeclareReservedUnused( IO80211Controller,  1);\n    OSMetaClassDeclareReservedUnused( IO80211Controller,  2);\n    OSMetaClassDeclareReservedUnused( IO80211Controller,  3);\n    OSMetaClassDeclareReservedUnused( IO80211Controller,  4);\n    OSMetaClassDeclareReservedUnused( IO80211Controller,  5);\n    OSMetaClassDeclareReservedUnused( IO80211Controller,  6);\n    OSMetaClassDeclareReservedUnused( IO80211Controller,  7);\n    OSMetaClassDeclareReservedUnused( IO80211Controller,  8);\n    OSMetaClassDeclareReservedUnused( IO80211Controller,  9);\n    OSMetaClassDeclareReservedUnused( IO80211Controller, 10);\n    OSMetaClassDeclareReservedUnused( IO80211Controller, 11);\n    OSMetaClassDeclareReservedUnused( IO80211Controller, 12);\n    OSMetaClassDeclareReservedUnused( IO80211Controller, 13);\n    OSMetaClassDeclareReservedUnused( IO80211Controller, 14);\n    OSMetaClassDeclareReservedUnused( IO80211Controller, 15);\n    \n    virtual void postMessage(UInt,void *,unsigned long,UInt,void *);\n    virtual IOReturn setMulticastList(ether_addr const*, UInt);\n\nprotected:\n    uint8_t  filler[0x128];\n};\n\n#endif /* defined(KERNEL) && defined(__cplusplus) */\n\n#endif /* !_IO80211CONTROLLER_H */\n"
  },
  {
    "path": "include/Airport/IO80211InfraInterface.h",
    "content": "//\n//  IO80211InfraInterface.h\n//  itlwm\n//\n//  Created by qcwap on 2023/6/12.\n//  Copyright © 2023 钟先耀. All rights reserved.\n//\n\n#ifndef IO80211InfraInterface_h\n#define IO80211InfraInterface_h\n\nstruct apple80211_wcl_advisory_info;\nstruct apple80211_wcl_tx_rx_latency;\n\nclass IO80211InfraInterface : public IO80211SkywalkInterface {\n    OSDeclareAbstractStructors(IO80211InfraInterface)\n    \npublic:\n    virtual bool init() APPLE_KEXT_OVERRIDE;\n    virtual void free() APPLE_KEXT_OVERRIDE;\n    virtual IOReturn configureReport(IOReportChannelList *,UInt,void *,void *) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn updateReport(IOReportChannelList *,UInt,void *,void *) APPLE_KEXT_OVERRIDE;\n    virtual bool start(IOService *) APPLE_KEXT_OVERRIDE;\n    virtual SInt32 initBSDInterfaceParameters(ifnet_init_eparams *,sockaddr_dl **) APPLE_KEXT_OVERRIDE;\n    virtual bool prepareBSDInterface(ifnet_t, UInt) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn processBSDCommand(ifnet_t, UInt, void *) APPLE_KEXT_OVERRIDE;\n    virtual SInt32 setInterfaceEnable(bool) APPLE_KEXT_OVERRIDE;\n    virtual UInt getHardwareAssists(void) APPLE_KEXT_OVERRIDE;\n    virtual bool bpfTap(UInt,UInt) APPLE_KEXT_OVERRIDE;\n    virtual void getHardwareAddress(ether_addr *) APPLE_KEXT_OVERRIDE;\n    virtual void setHardwareAddress(ether_addr *) APPLE_KEXT_OVERRIDE;\n    virtual void postMessage(UInt,void *,unsigned long,bool) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn recordOutputPackets(TxSubmissionDequeueStats *,TxSubmissionDequeueStats *) APPLE_KEXT_OVERRIDE;\n    virtual void logTxPacket(IO80211NetworkPacket *,PacketSkywalkScratch *,apple80211_wme_ac,bool) APPLE_KEXT_OVERRIDE;\n    virtual void logTxCompletionPacket(IO80211NetworkPacket *,PacketSkywalkScratch *,unsigned char *,apple80211_wme_ac,int,UInt,bool) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn recordCompletionPackets(TxCompletionEnqueueStats *,TxCompletionEnqueueStats *) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn inputPacket(IO80211NetworkPacket *,packet_info_tag *,ether_header *,bool *) APPLE_KEXT_OVERRIDE;\n    virtual SInt64 pendingPackets(unsigned char) APPLE_KEXT_OVERRIDE;\n    virtual SInt64 packetSpace(unsigned char) APPLE_KEXT_OVERRIDE;\n    virtual bool isDebounceOnGoing(void) APPLE_KEXT_OVERRIDE;\n    virtual bool setLinkState(IO80211LinkState,UInt,bool debounceTimeout = 30,UInt code = 0) APPLE_KEXT_OVERRIDE;\n    virtual IO80211LinkState linkState(void) APPLE_KEXT_OVERRIDE;\n    virtual void setScanningState(UInt,bool,apple80211_scan_data *,int) APPLE_KEXT_OVERRIDE;\n    virtual void setDataPathState(bool) APPLE_KEXT_OVERRIDE;\n    virtual void *getScanManager(void) APPLE_KEXT_OVERRIDE;\n    virtual void updateLinkParameters(apple80211_interface_availability *) APPLE_KEXT_OVERRIDE;\n    virtual void updateInterfaceCoexRiskPct(unsigned long long) APPLE_KEXT_OVERRIDE;\n    virtual void setLQM(unsigned long long) APPLE_KEXT_OVERRIDE;\n    virtual void updateLinkStatus(void) APPLE_KEXT_OVERRIDE;\n    virtual void updateLinkStatusGated(void) APPLE_KEXT_OVERRIDE;\n    virtual void setInterfaceExtendedCCA(apple80211_channel,apple80211_cca_report *) APPLE_KEXT_OVERRIDE;\n    virtual void setInterfaceCCA(apple80211_channel,int) APPLE_KEXT_OVERRIDE;\n    virtual void setInterfaceNF(apple80211_channel,long long) APPLE_KEXT_OVERRIDE;\n    virtual void setInterfaceOFDMDesense(apple80211_channel,long long) APPLE_KEXT_OVERRIDE;\n    virtual void setDebugFlags(unsigned long long,UInt) APPLE_KEXT_OVERRIDE;\n    virtual SInt64 debugFlags(void) APPLE_KEXT_OVERRIDE;\n    virtual void setInterfaceChipCounters(apple80211_stat_report *,apple80211_chip_counters_tx *,apple80211_chip_error_counters_tx *,apple80211_chip_counters_rx *) APPLE_KEXT_OVERRIDE;\n    virtual void setInterfaceMIBdot11(apple80211_stat_report *,apple80211_ManagementInformationBasedot11_counters *) APPLE_KEXT_OVERRIDE;\n    virtual void setFrameStats(apple80211_stat_report *,apple80211_frame_counters *) APPLE_KEXT_OVERRIDE;\n#if __IO80211_TARGET >= __MAC_14_4\n    virtual void setInfraSpecificFrameStats(apple80211_stat_report *,apple80211_infra_specific_stats *) APPLE_KEXT_OVERRIDE;\n#endif\n    virtual SInt64 getWmeTxCounters(unsigned long long *) APPLE_KEXT_OVERRIDE;\n    virtual void setEnabledBySystem(bool) APPLE_KEXT_OVERRIDE;\n    virtual bool enabledBySystem(void) APPLE_KEXT_OVERRIDE;\n    virtual bool willRoam(ether_addr *,UInt) APPLE_KEXT_OVERRIDE;\n    virtual void setPeerManagerLogFlag(UInt,UInt,UInt) APPLE_KEXT_OVERRIDE;\n    virtual void setWoWEnabled(bool) APPLE_KEXT_OVERRIDE;\n    virtual bool wowEnabled(void) APPLE_KEXT_OVERRIDE;\n    virtual UInt64 createLinkQualityMonitor(IO80211Peer *,IOService *) APPLE_KEXT_OVERRIDE;\n    virtual void releaseLinkQualityMonitor(IO80211Peer *) APPLE_KEXT_OVERRIDE;\n    virtual int getAssocState(void) APPLE_KEXT_OVERRIDE;\n    virtual void *getLQMSummary(apple80211_lqm_summary *) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn setLinkStateInternal(IO80211LinkState,uint,bool,uint,apple80211_link_changed_event_data &);\n    virtual void setPoweredOnByUser(bool);\n    virtual void setCurrentBssid(ether_addr *);\n    virtual void setWCL_ADVISORTY_INFO(apple80211_wcl_advisory_info *);\n    virtual void *getWCL_TX_RX_LATENCY(apple80211_wcl_tx_rx_latency *);\n    \npublic:\n    char _data[0x120];\n};\n\n#endif /* IO80211InfraInterface_h */\n"
  },
  {
    "path": "include/Airport/IO80211InfraProtocol.h",
    "content": "//\n//  IO80211InfraProtocol.h\n//  itlwm\n//\n//  Created by qcwap on 2023/6/14.\n//  Copyright © 2023 钟先耀. All rights reserved.\n//\n\n#ifndef IO80211InfraProtocol_h\n#define IO80211InfraProtocol_h\n\n#include <IOKit/IOService.h>\n#include <Airport/apple80211_var.h>\n#include <Airport/apple80211_ioctl.h>\n\nstruct apple80211_sta_ie_data;\nstruct apple80211_sta_stats_data;\nstruct apple80211_rssi_bounds_data;\nstruct apple80211_rate_set_data;\nstruct apple80211_power_debug_info;\nstruct apple80211_bgscan_cached_network_data_list;\nstruct apple80211_private_mac_data;\nstruct apple80211_dbg_guard_time_params;\nstruct apple80211_ranging_enable_request_t;\nstruct apple80211_gas_result_t;\nstruct apple80211_ranging_start_request_t;\nstruct apple80211_leaky_ap_setting;\nstruct apple80211_rsdb_capability;\nstruct apple80211_tko_params;\nstruct apple80211_tko_dump;\nstruct apple80211_thermal_index_t;\nstruct apple80211_btcoex_max_nss_for_ap_data;\nstruct apple80211_btcoex_2g_chain_disable;\nstruct apple80211_power_budget_t;\nstruct apple80211_ranging_capabilities_t;\nstruct apple80211_suppress_scans_t;\nstruct apple80211_host_ap_mode_hidden_t;\nstruct apple80211_lqm_config_t;\nstruct apple80211_trap_mini_dump_data;\nstruct apple80211_beacon_info_t;\nstruct apple80211_softap_params;\nstruct apple80211_chip_power_limit;\nstruct apple80211_softap_stats;\nstruct apple80211_nss_data;\nstruct apple80211_hw_mac_address;\nstruct apple80211_he_mcs_index_set_data;\nstruct appl80211_chip_diags_data;\nstruct apple80211_hp2p_ctrl;\nstruct apple80211_assoc_ready;\nstruct apple80211_txrx_chain_info;\nstruct apple80211_mimo_status;\nstruct apple80211_dynsar_detail;\nstruct apple80211_mac_randomisation_status;\nstruct apple80211_colocated_network_scope_id\n{\n    uint32_t version;\n    uint32_t id1;\n    uint32_t id2;\n};\nstruct apple80211_slow_wifi_feature_enabled;\nstruct apple80211_interface_cca_data;\nstruct apple80211_timesync_info;\nstruct apple80211_sensing_data_t;\nstruct apple80211_country_band_support;\nstruct apple80211_fw_hot_channels;\nstruct apple80211_low_latency_info;\nstruct apple80211_beacon_msg;\nstruct apple80211_wcl_traffic_counters;\nstruct apple80211_ssid_transition_feature_enabled;\ntypedef enum {\n    \n} p2pStatusForScan;\nstruct apple80211ChannelInfo;\nstruct apple80211_p2p_steering_metrics;;\nstruct apple80211_rsn_xe_data;\nstruct apple80211_sib_coex_status;\nstruct apple80211_extended_bss_info;\nstruct apple80211_wcl_low_latency_stats;\nstruct apple80211_noise_per_ant_t;\nstruct apple80211_blocked_bands;\nstruct apple80211_disassoc_data;\nstruct apple80211_bgscan_data;\nstruct apple80211_sta_authorize_data;\nstruct apple80211_sta_disassoc_data;\nstruct apple80211_rsn_conf_data;\nstruct apple80211_country_channel_data;\nstruct apple80211_awdl_forced_roam_config;\nstruct apple80211_offload_arp_data;\nstruct apple80211_offload_ndp_data;\nstruct apple80211_offload_scan_data;\nstruct apple80211_gas_query_t;\nstruct apple80211_gas_peer_t;\nstruct apple80211_btcoex_profile;\nstruct apple80211_btcoex_profile_active_data;\nstruct apple80211_trap_info_data;\nstruct apple80211_he_capability;\nstruct apple80211_pmk;\nstruct apple80211_wow_test_data;\nstruct apple80211_reset_command;\nstruct apple80211_crash_command;\nstruct apple80211_ranging_authenticate_request_t;\nstruct apple80211_softap_csa_params;\nstruct apple80211_softap_wifi_network_info;\nstruct apple80211_scan_control_params;\nstruct apple80211_usb_host_notification_data;\nstruct apple80211_set_mac_address;\nstruct apple80211_abort_scan;\nstruct apple80211_set_property_unserialized_data;\nstruct apple80211_roam_cache_data;\nstruct apple80211_pm_mode;\nstruct apple80211_wifi_assertion_data;\nstruct apple80211_capture_debug_info_t;\nstruct apple80211_linkdown_debounce_status;\nstruct apple80211_softap_extended_capabilities_info;\nstruct apple80211_sensing_enable_t;\nstruct apple80211_sensing_disable_t;\nstruct apple80211_nan_link_association_info;\nstruct apple80211_6G_mode;\nstruct apple80211_leave_network;\nstruct apple80211_reassoc;\nstruct apple80211_set_roam_lock;\nstruct apple80211_roam_profile_config;\nstruct apple80211_roam_profile_configV1;\nstruct apple80211_user_roam_cache;\nstruct apple80211_set_multi_ap_env;\nstruct apple80211_wcl_real_time_mode;\nstruct apple80211_wcl_garp_mode;\nstruct triggerCC;\nstruct apple80211ScanRequest;\nstruct apple80211_assoc_candidates;\nstruct apple80211_wcl_protect_ip_mode;\nstruct scanHomeAndAwayTime;\nstruct apple80211_wcl_voluntary_network_disconnect;\nstruct apple80211_wcl_update_link_state;\nstruct apple80211_wcl_ulofdma_state;\nstruct apple80211_wcl_action_frame;\nstruct apple80211_wcl_real_time_policy;\nstruct apple80211_feature_flags;\nstruct apple80211_dhcp_renewal_data;\nstruct apple80211_network_flags;\nstruct apple80211_battery_ps_config;\nstruct apple80211_mimo_config;\nstruct apple80211_bg_motion_profile;\nstruct apple80211_bg_network;\nstruct apple80211_bg_scan;\nstruct apple80211_bg_params;\ntypedef UInt apple80211_offload_tcpka_enable_t;\n\nclass IO80211InfraProtocol : public IO80211InfraInterface {\n    OSDeclareAbstractStructors(IO80211InfraProtocol)\n    \npublic:\n    virtual IOReturn getSSID(apple80211_ssid_data *) = 0;\n    virtual IOReturn getAUTH_TYPE(apple80211_authtype_data *) = 0;\n    virtual IOReturn getCHANNEL(apple80211_channel_data *) = 0;\n    virtual IOReturn getPOWERSAVE(apple80211_powersave_data *) = 0;\n    virtual IOReturn getTXPOWER(apple80211_txpower_data *) = 0;\n    virtual IOReturn getRATE(apple80211_rate_data *) = 0;\n    virtual IOReturn getBSSID(apple80211_bssid_data *) = 0;\n    virtual IOReturn getSCAN_RESULT(apple80211_scan_result *) = 0;\n    virtual IOReturn getSTATE(apple80211_state_data *) = 0;\n    virtual IOReturn getPHY_MODE(apple80211_phymode_data *) = 0;\n    virtual IOReturn getOP_MODE(apple80211_opmode_data *) = 0;\n    virtual IOReturn getRSSI(apple80211_rssi_data *) = 0;\n    virtual IOReturn getNOISE(apple80211_noise_data *) = 0;\n    virtual IOReturn getSUPPORTED_CHANNELS(apple80211_sup_channel_data *) = 0;\n    virtual IOReturn getLOCALE(apple80211_locale_data *) = 0;\n    virtual IOReturn getDEAUTH(apple80211_deauth_data *) = 0;\n    virtual IOReturn getRATE_SET(apple80211_rate_set_data *) = 0;\n    virtual IOReturn getDTIM_INT(apple80211_dtim_int_data *) = 0;\n    virtual IOReturn getSTATION_LIST(apple80211_sta_data *) = 0;\n    virtual IOReturn getRSN_IE(apple80211_rsn_ie_data *) = 0;\n    virtual IOReturn getAP_IE_LIST(apple80211_ap_ie_data *) = 0;\n    virtual IOReturn getSTATS(apple80211_stats_data *) = 0;\n    virtual IOReturn getASSOCIATION_STATUS(apple80211_assoc_status_data *) = 0;\n    virtual IOReturn getGUARD_INTERVAL(apple80211_guard_interval_data *) = 0;\n    virtual IOReturn getMCS(apple80211_mcs_data *) = 0;\n    virtual IOReturn getMCS_INDEX_SET(apple80211_mcs_index_set_data *) = 0;\n    virtual IOReturn getWOW_PARAMETERS(apple80211_wow_parameter_data *) = 0;\n    virtual IOReturn getWOW_ENABLED(apple80211_state_data *) = 0;\n    virtual IOReturn getPID_LOCK(apple80211_state_data *) = 0;\n    virtual IOReturn getSTA_IE_LIST(apple80211_sta_ie_data *) = 0;\n    virtual IOReturn getSTA_STATS(apple80211_sta_stats_data *) = 0;\n    virtual IOReturn getBT_COEX_FLAGS(apple80211_state_data *) = 0;\n    virtual IOReturn getCURRENT_NETWORK(apple80211_scan_result *) = 0;\n    virtual IOReturn getRSSI_BOUNDS(apple80211_rssi_bounds_data *) = 0;\n    virtual IOReturn getPOWER_DEBUG_INFO(apple80211_power_debug_info *) = 0;\n    virtual IOReturn getHT_CAPABILITY(apple80211_ht_capability *) = 0;\n    virtual IOReturn getLINK_CHANGED_EVENT_DATA(apple80211_link_changed_event_data *) = 0;\n    virtual IOReturn getEXTENDED_STATS(apple80211_extended_stats *) = 0;\n    virtual IOReturn getBEACON_PERIOD(apple80211_beacon_period_data *) = 0;\n    virtual IOReturn getVHT_MCS_INDEX_SET(apple80211_vht_mcs_index_set_data *) = 0;\n    virtual IOReturn getMCS_VHT(apple80211_mcs_vht_data *) = 0;\n    virtual IOReturn getGAS_RESULTS(apple80211_gas_result_t *) = 0;\n    virtual IOReturn getCHANNELS_INFO(apple80211_channels_info *) = 0;\n    virtual IOReturn getVHT_CAPABILITY(apple80211_vht_capability *) = 0;\n    virtual IOReturn getBGSCAN_CACHE_RESULTS(apple80211_bgscan_cached_network_data_list *) = 0;\n    virtual IOReturn getROAM_PROFILE(apple80211_roam_profile_band_data *) = 0;\n    virtual IOReturn getCHIP_COUNTER_STATS(apple80211_chip_stats *) = 0;\n    virtual IOReturn getDBG_GUARD_TIME_PARAMS(apple80211_dbg_guard_time_params *) = 0;\n    virtual IOReturn getLEAKY_AP_STATS_MODE(apple80211_leaky_ap_setting *) = 0;\n    virtual IOReturn getCOUNTRY_CHANNELS(apple80211_country_channel_data *) = 0;\n    virtual IOReturn getPRIVATE_MAC(apple80211_private_mac_data *) = 0;\n    virtual IOReturn getRANGING_ENABLE(apple80211_ranging_enable_request_t *) = 0;\n    virtual IOReturn getRANGING_START(apple80211_ranging_start_request_t *) = 0;\n    virtual IOReturn getAWDL_RSDB_CAPS(apple80211_rsdb_capability *) = 0;\n    virtual IOReturn getTKO_PARAMS(apple80211_tko_params *) = 0;\n    virtual IOReturn getTKO_DUMP(apple80211_tko_dump *) = 0;\n    virtual IOReturn getHW_SUPPORTED_CHANNELS(apple80211_sup_channel_data *) = 0;\n    virtual IOReturn getBTCOEX_PROFILE(apple80211_btcoex_profile *) = 0;\n    virtual IOReturn getBTCOEX_PROFILE_ACTIVE(apple80211_btcoex_profile_active_data *) = 0;\n    virtual IOReturn getTRAP_INFO(apple80211_trap_info_data *) = 0;\n    virtual IOReturn getTHERMAL_INDEX(apple80211_thermal_index_t *) = 0;\n    virtual IOReturn getMAX_NSS_FOR_AP(apple80211_btcoex_max_nss_for_ap_data *) = 0;\n    virtual IOReturn getBTCOEX_2G_CHAIN_DISABLE(apple80211_btcoex_2g_chain_disable *) = 0;\n    virtual IOReturn getPOWER_BUDGET(apple80211_power_budget_t *) = 0;\n    virtual IOReturn getOFFLOAD_TCPKA_ENABLE(apple80211_offload_tcpka_enable_t *) = 0;\n    virtual IOReturn getRANGING_CAPS(apple80211_ranging_capabilities_t *) = 0;\n    virtual IOReturn getSUPPRESS_SCANS(apple80211_suppress_scans_t *) = 0;\n    virtual IOReturn getHOST_AP_MODE_HIDDEN(apple80211_host_ap_mode_hidden_t *) = 0;\n    virtual IOReturn getLQM_CONFIG(apple80211_lqm_config_t *) = 0;\n    virtual IOReturn getTRAP_CRASHTRACER_MINI_DUMP(apple80211_trap_mini_dump_data *) = 0;\n    virtual IOReturn getHE_CAPABILITY(apple80211_he_capability *) = 0;\n    virtual IOReturn getBEACON_INFO(apple80211_beacon_info_t *) = 0;\n    virtual IOReturn getSOFTAP_PARAMS(apple80211_softap_params *) = 0;\n    virtual IOReturn getCHIP_POWER_RANGE(apple80211_chip_power_limit *) = 0;\n    virtual IOReturn getSOFTAP_STATS(apple80211_softap_stats *) = 0;\n    virtual IOReturn getNSS(apple80211_nss_data *) = 0;\n    virtual IOReturn getHW_ADDR(apple80211_hw_mac_address *) = 0;\n    virtual IOReturn getHE_MCS_INDEX_SET(apple80211_he_mcs_index_set_data *) = 0;\n    virtual IOReturn getCHIP_DIAGS(appl80211_chip_diags_data *) = 0;\n    virtual IOReturn getHP2P_CTRL(apple80211_hp2p_ctrl *) = 0;\n    virtual IOReturn getREQUEST_BSS_BLACKLIST(void *) = 0;\n    virtual IOReturn getASSOC_READY_STATUS(apple80211_assoc_ready *) = 0;\n    virtual IOReturn getTXRX_CHAIN_INFO(apple80211_txrx_chain_info *) = 0;\n    virtual IOReturn getMIMO_STATUS(apple80211_mimo_status *) = 0;\n    virtual IOReturn getCUR_PMK(apple80211_pmk *) = 0;\n    virtual IOReturn getDYNSAR_DETAIL(apple80211_dynsar_detail *) = 0;\n    virtual IOReturn getRANDOMISATION_STATUS(apple80211_mac_randomisation_status *) = 0;\n    virtual IOReturn getCOUNTRY_CHANNELS_INFO(apple80211_channels_info *) = 0;\n    virtual IOReturn getLQM_SUMMARY(apple80211_lqm_summary *) = 0;\n    virtual IOReturn getCOLOCATED_NETWORK_SCOPE_ID(apple80211_colocated_network_scope_id *) = 0;\n    virtual IOReturn getBEACON_SCAN_CACHE_REQ(apple80211_scan_result *) = 0;\n    virtual IOReturn getSLOW_WIFI_FEATURE_ENABLED(apple80211_slow_wifi_feature_enabled *) = 0;\n    virtual IOReturn getCCA(apple80211_interface_cca_data *) = 0;\n    virtual IOReturn getRX_RATE(apple80211_rate_data *) = 0;\n    virtual IOReturn getTIMESYNC_INFO(apple80211_timesync_info *) = 0;\n    virtual IOReturn getSENSING_DATA(apple80211_sensing_data_t *) = 0;\n    virtual IOReturn getCOUNTRY_BAND_SUPPORT(apple80211_country_band_support *) = 0;\n    virtual IOReturn getWCL_FW_HOT_CHANNELS(apple80211_fw_hot_channels *) = 0;\n    virtual IOReturn getWCL_LOW_LATENCY_INFO(apple80211_low_latency_info *) = 0;\n    virtual IOReturn getWCL_BSS_INFO(apple80211_beacon_msg *) = 0;\n    virtual IOReturn getWCL_TRAFFIC_COUNTERS(apple80211_wcl_traffic_counters *) = 0;\n    virtual IOReturn getWCL_GET_TX_BLANKING_STATUS(uint *) = 0;\n    virtual IOReturn getSSID_TRANSITION_SUPPORT(apple80211_ssid_transition_feature_enabled *) = 0;\n    virtual IOReturn getWCL_VALID_CHANNEL_COUNT(unsigned long *) = 0;\n    virtual IOReturn getWCL_P2P_STATUS_FOR_SCAN(p2pStatusForScan *) = 0;\n    virtual IOReturn getWCL_CHANNELS_INFO(apple80211ChannelInfo *) = 0;\n    virtual IOReturn getP2P_STEERING_METRIC(apple80211_p2p_steering_metrics *) = 0;\n    virtual IOReturn getRSN_XE(apple80211_rsn_xe_data *) = 0;\n    virtual IOReturn getSIB_COEX_STATUS(apple80211_sib_coex_status *) = 0;\n    virtual IOReturn getWCL_EXTENDED_BSS_INFO(apple80211_extended_bss_info *) = 0;\n    virtual IOReturn getWCL_LOW_LATENCY_INFO_STATS(apple80211_wcl_low_latency_stats *) = 0;\n    virtual IOReturn getWCL_BGSCAN_CACHE_RESULT(apple80211_bgscan_cached_network_data_list *) = 0;\n    virtual IOReturn getWIFI_NOISE_PER_ANT(apple80211_noise_per_ant_t *) = 0;\n    virtual IOReturn getBLOCKED_BANDS(apple80211_blocked_bands *) = 0;\n    virtual IOReturn setSSID(apple80211_ssid_data *) = 0;\n    virtual IOReturn setAUTH_TYPE(apple80211_authtype_data *) = 0;\n    virtual IOReturn setCIPHER_KEY(apple80211_key *) = 0;\n    virtual IOReturn setCHANNEL(apple80211_channel_data *) = 0;\n    virtual IOReturn setPOWERSAVE(apple80211_powersave_data *) = 0;\n    virtual IOReturn setTXPOWER(apple80211_txpower_data *) = 0;\n    virtual IOReturn setRATE(apple80211_rate_data *) = 0;\n    virtual IOReturn setSCAN_REQ(apple80211_scan_data *) = 0;\n    virtual IOReturn setASSOCIATE(apple80211_assoc_data *) = 0;\n    virtual IOReturn setDISASSOCIATE(apple80211_disassoc_data *) = 0;\n    virtual IOReturn setIBSS_MODE(apple80211_network_data *) = 0;\n    virtual IOReturn setHOST_AP_MODE(apple80211_network_data *) = 0;\n    virtual IOReturn setAP_MODE(apple80211_apmode_data *) = 0;\n    virtual IOReturn setDEAUTH(apple80211_deauth_data *) = 0;\n    virtual IOReturn setTX_ANTENNA(void *) = 0;\n    virtual IOReturn setANTENNA_DIVERSITY(void *) = 0;\n    virtual IOReturn setRSN_IE(apple80211_rsn_ie_data *) = 0;\n    virtual IOReturn setBACKGROUND_SCAN(apple80211_bgscan_data *) = 0;\n    virtual IOReturn setWOW_PARAMETERS(apple80211_wow_parameter_data *) = 0;\n    virtual IOReturn setWOW_ENABLED(apple80211_state_data *) = 0;\n    virtual IOReturn setPID_LOCK(apple80211_state_data *) = 0;\n    virtual IOReturn setSTA_AUTHORIZE(apple80211_sta_authorize_data *) = 0;\n    virtual IOReturn setSTA_DISASSOCIATE(apple80211_sta_disassoc_data *) = 0;\n    virtual IOReturn setSTA_DEAUTH(apple80211_sta_disassoc_data *) = 0;\n    virtual IOReturn setRSN_CONF(apple80211_rsn_conf_data *) = 0;\n    virtual IOReturn setIE(apple80211_ie_data *) = 0;\n    virtual IOReturn setWOW_TEST(apple80211_wow_test_data *) = 0;\n    virtual IOReturn setSCANCACHE_CLEAR(void *) = 0;\n    virtual IOReturn setVIRTUAL_IF_CREATE(apple80211_virt_if_create_data *) = 0;\n    virtual IOReturn setBT_COEX_FLAGS(apple80211_state_data *) = 0;\n    virtual IOReturn setROAM(apple80211_sta_roam_data *) = 0;\n    virtual IOReturn setHT_CAPABILITY(apple80211_ht_capability *) = 0;\n    virtual IOReturn setAWDL_FORCED_ROAM_CONFIG(apple80211_awdl_forced_roam_config *) = 0;\n    virtual IOReturn setOFFLOAD_ARP(apple80211_offload_arp_data *) = 0;\n    virtual IOReturn setOFFLOAD_NDP(apple80211_offload_ndp_data *) = 0;\n    virtual IOReturn setOFFLOAD_SCAN(apple80211_offload_scan_data *) = 0;\n    virtual IOReturn setGAS_REQ(apple80211_gas_query_t *) = 0;\n    virtual IOReturn setGAS_START(apple80211_gas_query_t *) = 0;\n    virtual IOReturn setGAS_SET_PEER(apple80211_gas_peer_t *) = 0;\n    virtual IOReturn setVHT_CAPABILITY(apple80211_vht_capability *) = 0;\n    virtual IOReturn setROAM_PROFILE(apple80211_roam_profile_band_data *) = 0;\n    virtual IOReturn setAWDL_ENABLE_ROAMING(void *) = 0;\n    virtual IOReturn setDBG_GUARD_TIME_PARAMS(apple80211_dbg_guard_time_params *) = 0;\n    virtual IOReturn setLEAKY_AP_STATS_MODE(apple80211_leaky_ap_setting *) = 0;\n    virtual IOReturn setPRIVATE_MAC(apple80211_private_mac_data *) = 0;\n    virtual IOReturn setRESET_CHIP(apple80211_reset_command *) = 0;\n    virtual IOReturn setCRASH(apple80211_crash_command *) = 0;\n    virtual IOReturn setRANGING_ENABLE(apple80211_ranging_enable_request_t *) = 0;\n    virtual IOReturn setRANGING_START(apple80211_ranging_start_request_t *) = 0;\n    virtual IOReturn setRANGING_AUTHENTICATE(apple80211_ranging_authenticate_request_t *) = 0;\n    virtual IOReturn setTKO_PARAMS(apple80211_tko_params *) = 0;\n    virtual IOReturn setBTCOEX_PROFILE(apple80211_btcoex_profile *) = 0;\n    virtual IOReturn setBTCOEX_PROFILE_ACTIVE(apple80211_btcoex_profile_active_data *) = 0;\n    virtual IOReturn setTHERMAL_INDEX(apple80211_thermal_index_t *) = 0;\n    virtual IOReturn setBTCOEX_2G_CHAIN_DISABLE(apple80211_btcoex_2g_chain_disable *) = 0;\n    virtual IOReturn setPOWER_BUDGET(apple80211_power_budget_t *) = 0;\n    virtual IOReturn setOFFLOAD_TCPKA_ENABLE(apple80211_offload_tcpka_enable_t *) = 0;\n    virtual IOReturn setSUPPRESS_SCANS(apple80211_suppress_scans_t *) = 0;\n    virtual IOReturn setHOST_AP_MODE_HIDDEN(apple80211_host_ap_mode_hidden_t *) = 0;\n    virtual IOReturn setLQM_CONFIG(apple80211_lqm_config_t *) = 0;\n    virtual IOReturn setSOFTAP_PARAMS(apple80211_softap_params *) = 0;\n    virtual IOReturn setSOFTAP_TRIGGER_CSA(apple80211_softap_csa_params *) = 0;\n    virtual IOReturn setSOFTAP_WIFI_NETWORK_INFO_IE(apple80211_softap_wifi_network_info *) = 0;\n    virtual IOReturn setBTCOEX_DISABLE_ULOFDMA(uint *) = 0;\n    virtual IOReturn setSCAN_CONTROL(apple80211_scan_control_params *) = 0;\n    virtual IOReturn setUSB_HOST_NOTIFICATION(apple80211_usb_host_notification_data *) = 0;\n    virtual IOReturn setSET_MAC_ADDRESS(apple80211_set_mac_address *) = 0;\n    virtual IOReturn setHP2P_CTRL(apple80211_hp2p_ctrl *) = 0;\n    virtual IOReturn setABORT_SCAN(apple80211_abort_scan *) = 0;\n    virtual IOReturn setSET_PROPERTY(apple80211_set_property_unserialized_data *) = 0;\n    virtual IOReturn setROAM_CACHE_UPDATE(apple80211_roam_cache_data *) = 0;\n    virtual IOReturn setPM_MODE(apple80211_pm_mode *) = 0;\n    virtual IOReturn setSET_WIFI_ASSERTION_STATE(apple80211_wifi_assertion_data *) = 0;\n    virtual IOReturn setREASSOCIATE_WITH_CORECAPTURE(apple80211_capture_debug_info_t *) = 0;\n    virtual IOReturn setLINKDOWN_DEBOUNCE_STATUS(apple80211_linkdown_debounce_status *) = 0;\n    virtual IOReturn setSOFTAP_EXTENDED_CAPABILITIES_IE(apple80211_softap_extended_capabilities_info *) = 0;\n    virtual IOReturn setREALTIME_QOS_MSCS(apple80211_state_data *) = 0;\n    virtual IOReturn setSENSING_ENABLE(apple80211_sensing_enable_t *) = 0;\n    virtual IOReturn setSENSING_DISABLE(apple80211_sensing_disable_t *) = 0;\n    virtual IOReturn setNANPHS_ASSOCIATION(apple80211_nan_link_association_info *) = 0;\n    virtual IOReturn setNANPHS_TERMINATED(apple80211_nan_link_association_info *) = 0;\n    virtual IOReturn set6G_MODE(apple80211_6G_mode *) = 0;\n    virtual IOReturn setWCL_LEAVE_NETWORK(apple80211_leave_network *) = 0;\n    virtual IOReturn setWCL_REASSOC(apple80211_reassoc *) = 0;\n    virtual IOReturn setWCL_SET_ROAM_LOCK(apple80211_set_roam_lock *) = 0;\n    virtual IOReturn setWCL_ROAM_PROFILE_CONFIG(apple80211_roam_profile_config *) = 0;\n    virtual IOReturn setWCL_ROAM_PROFILE_CONFIGV1(apple80211_roam_profile_configV1 *) = 0;\n    virtual IOReturn setWCL_ROAM_USER_CACHE(apple80211_user_roam_cache *) = 0;\n    virtual IOReturn setWCL_SET_MULTI_AP_ENV(apple80211_set_multi_ap_env *) = 0;\n    virtual IOReturn setWCL_SCAN_ABORT(void *) = 0;\n    virtual IOReturn setWCL_REAL_TIME_MODE(apple80211_wcl_real_time_mode *) = 0;\n    virtual IOReturn setWCL_GARP_MODE(apple80211_wcl_garp_mode *) = 0;\n    virtual IOReturn setWCL_JOIN_ABORT(void *) = 0;\n    virtual IOReturn setWCL_TRIGGER_CC(triggerCC *) = 0;\n    virtual IOReturn setWCL_SCAN_REQ(apple80211ScanRequest *) = 0;\n    virtual IOReturn setWCL_ASSOCIATE(apple80211_assoc_candidates *) = 0;\n    virtual IOReturn setWCL_PROTECT_IP(apple80211_wcl_protect_ip_mode *) = 0;\n    virtual IOReturn setWCL_LINK_UP_DONE(void *) = 0;\n    virtual IOReturn setWCL_SET_SCAN_HOME_AWAY_TIME(scanHomeAndAwayTime *) = 0;\n    virtual IOReturn setWCL_VOLUNTARY_NETWORK_DISCONNECT(apple80211_wcl_voluntary_network_disconnect *) = 0;\n    virtual IOReturn setWCL_LINK_STATE_UPDATE(apple80211_wcl_update_link_state *) = 0;\n    virtual IOReturn setSLOW_WIFI_RECOVERY(void *) = 0;\n    virtual IOReturn setRSN_XE(apple80211_rsn_xe_data *) = 0;\n    virtual IOReturn setWCL_ULOFDMA_STATE(apple80211_wcl_ulofdma_state *) = 0;\n    virtual IOReturn setWCL_ACTION_FRAME(apple80211_wcl_action_frame *) = 0;\n    virtual IOReturn setWCL_REAL_TIME_POLICY(apple80211_wcl_real_time_policy *) = 0;\n    virtual IOReturn setGAS_ABORT(void *) = 0;\n    virtual IOReturn setOS_FEATURE_FLAGS(apple80211_feature_flags *) = 0;\n    virtual IOReturn setDHCP_RENEWAL_DATA(apple80211_dhcp_renewal_data *) = 0;\n    virtual IOReturn setMOVING_NETWORK(apple80211_network_flags *) = 0;\n    virtual IOReturn setBATTERY_POWERSAVE_CONFIG(apple80211_battery_ps_config *) = 0;\n    virtual IOReturn setMIMO_CONFIG(apple80211_mimo_config *) = 0;\n    virtual IOReturn setWCL_CONFIG_BG_MOTIONPROFILE(apple80211_bg_motion_profile *) = 0;\n    virtual IOReturn setWCL_CONFIG_BG_NETWORK(apple80211_bg_network *) = 0;\n    virtual IOReturn setWCL_CONFIG_BGSCAN(apple80211_bg_scan *) = 0;\n    virtual IOReturn setWCL_CONFIG_BG_PARAMS(apple80211_bg_params *) = 0;\n    virtual IOReturn setBLOCKED_BANDS(apple80211_blocked_bands *) = 0;\n    \npublic:\n    uint8_t filter[0x120];\n};\n\n#endif /* IO80211InfraProtocol_h */\n\n"
  },
  {
    "path": "include/Airport/IO80211Interface.h",
    "content": "#ifndef _IO80211INTERFACE_H\n#define _IO80211INTERFACE_H\n\n/*\n * Kernel\n */\n#if defined(KERNEL) && defined(__cplusplus)\n\n#include <Availability.h>\n#include <libkern/version.h>\n\n// This is necessary, because even the latest Xcode does not support properly targeting 11.0.\n#ifndef __IO80211_TARGET\n#error \"Please define __IO80211_TARGET to the requested version\"\n#endif\n\n#if VERSION_MAJOR > 8\n\t#define _MODERN_BPF\n#endif\n\n#include <IOKit/network/IOEthernetInterface.h>\n#include <net/if_var.h>\n#include <sys/queue.h>\n\ntypedef UInt kIO80211InterfaceType;\n\n/*!\t@defined kIO80211InterfaceClass\n\t@abstract The name of the IO80211Interface class.\n\t*/\n#define kIO80211InterfaceClass     \"IO80211Interface\"\n\ntypedef UInt64 IO80211FlowQueueHash;\nclass RSNSupplicant;\nclass IOTimerEventSource;\nclass IOGatedOutputQueue;\nclass IO80211Controller;\nclass IO80211Workloop;\nclass IO80211ScanManager;\nclass IO80211PeerManager;\nclass IO80211FlowQueueDatabase;\nclass IO80211InterfaceMonitor;\nclass IO80211AssociationJoinSnapshot;\n\nstruct apple80211_debug_command;\nstruct apple80211_txstats;\nstruct apple80211_chip_counters_tx;\nstruct apple80211_chip_error_counters_tx;\nstruct apple80211_chip_counters_rx;\nstruct apple80211_ManagementInformationBasedot11_counters;\nstruct apple80211_leaky_ap_stats;\nstruct apple80211_leaky_ap_ssid_metrics;\nstruct apple80211_interface_availability;\nstruct apple80211_pmk_cache_data;\nstruct apple80211_ap_cmp_data;\n\nstruct TxPacketRequest {\n    uint16_t    unk1;       // 0\n    uint16_t    t;       // 2\n    uint16_t    mU;       // 4\n    uint16_t    mM;       // 6\n    uint16_t    pkt_cnt;\n    uint16_t    unk2;\n    uint16_t    unk3;\n    uint16_t    unk4;\n    uint32_t    pad;\n    mbuf_t      bufs[8];    // 18\n    uint32_t    reqTx;\n};\n\nstatic_assert(sizeof(struct TxPacketRequest) == 0x60, \"TxPacketRequest size error\");\n\nstruct AWSRequest;\nstruct packet_info_tx;\nstruct userPrintCtx;\n\ntypedef int apple80211_postMessage_tlv_types;\n\nclass IO80211Interface : public IOEthernetInterface\n{\n    OSDeclareDefaultStructors( IO80211Interface );\n\npublic:\n    virtual void free() APPLE_KEXT_OVERRIDE;\n    virtual IOReturn configureReport(IOReportChannelList *,uint,void *,void *) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn updateReport(IOReportChannelList *,uint,void *,void *) APPLE_KEXT_OVERRIDE;\n    virtual bool terminate(unsigned int) APPLE_KEXT_OVERRIDE;\n    virtual bool attach(IOService*) APPLE_KEXT_OVERRIDE;\n    virtual void detach(IOService*) APPLE_KEXT_OVERRIDE;\n#if __IO80211_TARGET >= __MAC_10_15\n    virtual IOReturn newUserClient(task_t, void*, UInt32 type, OSDictionary*, IOUserClient**) APPLE_KEXT_OVERRIDE;\n#endif\n    virtual const char* stringFromReturn(int) APPLE_KEXT_OVERRIDE;\n    virtual int errnoFromReturn(int) APPLE_KEXT_OVERRIDE;\n    virtual bool init(IONetworkController*) APPLE_KEXT_OVERRIDE;\n    virtual UInt32 inputPacket(mbuf_t          packet,\n                               UInt32          length  = 0,\n                               IOOptionBits    options = 0,\n                               void *          param   = 0) APPLE_KEXT_OVERRIDE;\n    virtual bool inputEvent(unsigned int, void*) APPLE_KEXT_OVERRIDE;\n    virtual SInt32 performCommand(IONetworkController*, unsigned long, void*, void*) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn attachToDataLinkLayer(IOOptionBits, void*) APPLE_KEXT_OVERRIDE;\n    virtual void detachFromDataLinkLayer(unsigned int, void*) APPLE_KEXT_OVERRIDE;\n\n    virtual void setPoweredOnByUser(bool);\n    virtual void setEnabledBySystem(bool);\n\n    virtual bool setLinkState(IO80211LinkState, unsigned int);\n    virtual bool setLinkState(IO80211LinkState, int, unsigned int);\n    virtual UInt32 outputPacket(mbuf_t, void*);\n\n    virtual bool setLinkQualityMetric(int);\n    virtual void handleDebugCmd(apple80211_debug_command*);\n    OSMetaClassDeclareReservedUnused( IO80211Interface,  0);\n    OSMetaClassDeclareReservedUnused( IO80211Interface,  1);\n    OSMetaClassDeclareReservedUnused( IO80211Interface,  2);\n    OSMetaClassDeclareReservedUnused( IO80211Interface,  3);\n    OSMetaClassDeclareReservedUnused( IO80211Interface,  4);\n    OSMetaClassDeclareReservedUnused( IO80211Interface,  5);\n    OSMetaClassDeclareReservedUnused( IO80211Interface,  6);\n    OSMetaClassDeclareReservedUnused( IO80211Interface,  7);\n    OSMetaClassDeclareReservedUnused( IO80211Interface,  8);\n    OSMetaClassDeclareReservedUnused( IO80211Interface,  9);\n    OSMetaClassDeclareReservedUnused( IO80211Interface, 10);\n    OSMetaClassDeclareReservedUnused( IO80211Interface, 11);\n    OSMetaClassDeclareReservedUnused( IO80211Interface, 12);\n    OSMetaClassDeclareReservedUnused( IO80211Interface, 13);\n    OSMetaClassDeclareReservedUnused( IO80211Interface, 14);\n    OSMetaClassDeclareReservedUnused( IO80211Interface, 15);\npublic:\n    IOReturn IO80211InterfacePostMessage(UInt,void *,unsigned long);\n    struct apple80211_ap_cmp_data *apCompare(apple80211_ap_cmp_data *,apple80211_ap_cmp_data *);\n    void associateForNetBoot(IOService *);\n    IOReturn associateForNetBootGated(OSObject *,void *,void *,void *,void *);\n    bool authTimeout(void);\n    UInt32 awsRespond(mbuf_t,AWSRequest *,unsigned long,unsigned short);\n    IOReturn bpfAttach(UInt,UInt);\n    IOReturn bpfAttach(UInt,UInt,OSObject *,UInt (OSObject::*)(mbuf_t,void *),int (OSObject::*)(UInt,UInt),IOWorkLoop *);\n    IOReturn bpfOutput(UInt,mbuf_t);\n    UInt32 bpfOutputPacket(mbuf_t,void *);\n    void bpfTap(UInt,UInt);\n    UInt32 bpfTapInput(mbuf_t,UInt,void *,unsigned long);\n    UInt32 cachePMKSA(unsigned char *,unsigned long,ether_addr *);\n    UInt32 cachePMKSA(unsigned char *,unsigned long,ether_addr *,unsigned char *);\n    void clearAssocHistory(void);\n    void configureAntennae(void);\n    void configureBpfOutputQueues(bool);\n    IOReturn createAssocHistory(void);\n    UInt64 createIOReporters(IOService *);\n    UInt64 debugFlags(void);\n    mbuf_t dequeueTxPackets(TxPacketRequest *);\n    mbuf_t dequeueTxPackets(UInt,UInt);\n    void dropTxPacket(mbuf_t);\n    bool efiNVRAMPublished(void *,void *,IOService *,IONotifier *);\n    bool enabledBySystem(void);\n    IO80211FlowQueue *findExistingFlowQueue(IO80211FlowQueueHash);\n    IO80211FlowQueue *findOrCreateFlowQueue(IO80211FlowQueueHash);\n    void finishAttachToDataLinkLayer(void);\n    IOReturn finishAttachToDataLinkLayerGated(OSObject *,void *,void *,void *,void *);\n    void flushPacketQueues(void);\n    void freeBpf(void);\n    void freePMKSACache(void);\n    const char *getBSDName();\n    IO80211Controller *getController(void);\n    IO80211WorkLoop *getControllerWorkLoop(void);\n    bool getExtendedStats(apple80211_extended_stats *);\n    bool getLeakyApStats(apple80211_leaky_ap_stats const**);\n    IOOutputQueue *getOutputQueue(void);\n    IOOutputQueue *getOutputQueueForDLT(UInt);\n    void getPMKSAList(apple80211_pmk_cache_data *);\n    void getWmeTxCounters(unsigned long long *);\n    void handleLeakyApStatsModeTimer(IOTimerEventSource *);\n    void handleLeakyApStatsResetTimer(IOTimerEventSource *);\n    bool initSupplicant(unsigned char *,int);\n    UInt32 inputAWSPacket(mbuf_t);\n    IO80211LinkState linkState(void);\n    void logDebug(char const*, ...);\n    void logDebug(unsigned long long, char const*, ...);\n    void logDebugHex(void const*,unsigned long,char const*,...);\n    void logTxCompletionPacket(mbuf_t,int);\n    void logTxPacket(mbuf_t);\n    UInt32 monitorModeInputPacket(mbuf_t,UInt,void *,unsigned long);\n    IOReturn netBootThread(IOService *);\n    IOReturn netBootThreadGated(OSObject *,void *,void *,void *,void *);\n    bool netBooting(void);\n    UInt32 outputEAPOLFrame(mbuf_t);\n    void outputPreEnqueueHandler(void *,void *,mbuf_t);\n    IOReturn outputStart(UInt);\n    UInt64 packetSpace(unsigned char);\n    UInt64 pendingPackets(unsigned char);\n    IOReturn performCountryCodeOpGated(OSObject *,void *,void *,void *,void *);\n    IOReturn performGatedCommand(void *,void *,void *,void *,void *);\n    bool pidLocked(void);\n    UInt64 pmksaLookup(ether_addr *,unsigned char *);\n    void postMessage(unsigned int, void* data = NULL, unsigned long dataLen = 0);\n    IOReturn powerChangeHandler(void *,void *,UInt,IOService *,void *,unsigned long);\n    bool poweredOnByUser(void);\n    mbuf_t preQueuePacket(mbuf_t);\n    void printDataPath(userPrintCtx *);\n    void printPeers(UInt,UInt);\n    void purgePMKSACache(void);\n    UInt64 queueSize(unsigned char);\n    IOReturn queueWMEPacket(mbuf_t,void *);\n    void removePacketQueue(IO80211FlowQueueHash const*);\n    IOReturn reportDataPathEvents(UInt,void *,unsigned long);\n    IOReturn reportDataPathEventsGated(void *,void *,void *,void *,void *);\n    IOReturn reportDataTransferRates(void);\n    IOReturn reportDataTransferRatesGated(void);\n    IOReturn reportDataTransferRatesStatic(void *);\n    IOReturn reportTransmitCompletionStatus(mbuf_t,int,UInt,UInt,UInt);\n    void reportTransmitStatus(mbuf_t,int,packet_info_tx *);\n    void reportTxStatistics(apple80211_txstats *);\n    void resetLeakyApStats(void);\n    void resetSupplicant(void);\n#if __IO80211_TARGET >= __MAC_10_15\n    void resetUserClientReference(void);\n#endif\n#if __IO80211_TARGET >= __MAC_11_0\n    IOReturn resetUserClientReferenceGated(OSObject *,void *,void *,void *,void *);\n#endif\n    void setAuthTimeout(unsigned long);\n    bool setBTCoexWLANLostAntennaTime(unsigned long long,unsigned long long,bool,apple80211_btCoex_report *);\n    void setCountermeasuresTimer(IOTimerEventSource *);\n    void setDataPathState(bool);\n    IOReturn setDataPointerAndLengthForMessageType(apple80211_postMessage_tlv_types,void **,unsigned long *);\n    void setDebugFlags(unsigned long long,UInt);\n    bool setFrameStats(apple80211_stat_report *,apple80211_frame_counters *);\n    bool setInterfaceCCA(apple80211_channel,int);\n    bool setInterfaceChipCounters(apple80211_stat_report *,apple80211_chip_counters_tx *,apple80211_chip_error_counters_tx *,apple80211_chip_counters_rx *);\n    bool setInterfaceExtendedCCA(apple80211_channel,apple80211_cca_report *);\n    bool setInterfaceMIBdot11(apple80211_stat_report *,apple80211_ManagementInformationBasedot11_counters *);\n    IOReturn setLQM(unsigned long long);\n    IOReturn setLQMGated(long long);\n    IOReturn setLQMStatic(void *,void *);\n    bool setLeakyAPStats(apple80211_leaky_ap_event *);\n    bool setLeakyAPStatsMode(UInt);\n    bool setLeakyApSsidMetrics(apple80211_leaky_ap_ssid_metrics *);\n    void setNetBooting(bool);\n    bool setPMK(unsigned char *,unsigned char *);\n#if __IO80211_TARGET >= __MAC_10_15\n    bool setPSKPMK(unsigned char *);\n#endif\n    void setPeerManagerLogFlag(UInt,UInt,UInt);\n    bool setPidLock(bool);\n    void setScanningState(UInt,bool,apple80211_scan_data *,int);\n    void setWoWEnabled(bool);\n    bool shortGISupported20MHz(void);\n    bool shortGISupported40MHz(void);\n    bool shouldLog(unsigned long long);\n    bool shouldRoam(apple80211_scan_result *);\n#if __IO80211_TARGET >= __MAC_10_15\n    IOReturn startAsyncEventUserClientForTask(task *,kIO80211InterfaceType);\n#endif\n    void startOutputQueues();\n    void stopBpf(void);\n    void stopCountermeasures(OSObject *,IOTimerEventSource *);\n    void stopOutputQueues();\n    bool supplicantExchangeComplete(void);\n    bool supplicantInitialized(void);\n    void terminateSupplicant(void);\n    void togglePeerManagerLogFlag(UInt,UInt);\n    void updateBSSIDProperty(void);\n    void updateChannelProperty(void);\n    void updateChannelPropertyGated(void);\n    void updateChannelPropertyStatic(void *);\n    void updateCountryCodeProperty(bool);\n    bool updateInterfaceCoexRiskPct(unsigned long long);\n    void updateLinkParameters(apple80211_interface_availability *);\n    void updateLinkParametersGated(apple80211_interface_availability *);\n    void updateLinkParametersStatic(void *,void *);\n    bool updateLinkSpeed();\n    IOReturn updateLinkStatus(void);\n    IOReturn updateLinkStatusGated(void);\n    IOReturn updateLinkStatusStatic(void *);\n    void updateSSIDProperty(void);\n    void updateStaticProperties(void);\n    void vlogDebug(unsigned long long, char const*, va_list);\n    void vlogDebugBPF(unsigned long long,char const*,va_list);\n    void willRoam(ether_addr *,UInt);\n\nprotected:\n    u_int8_t dat[0x500];\n};\n\n#endif /* defined(KERNEL) && defined(__cplusplus) */\n\n#endif /* ! _IO80211INTERFACE_H */\n\n"
  },
  {
    "path": "include/Airport/IO80211P2PInterface.h",
    "content": "#ifndef IO80211P2PInterface_h\n#define IO80211P2PInterface_h\n\n#include \"IO80211VirtualInterface.h\"\n\nclass IO80211P2PInterface : public IO80211VirtualInterface {\n    OSDeclareDefaultStructors(IO80211P2PInterface)\n    \npublic:\n    virtual void free(void) APPLE_KEXT_OVERRIDE;\n#if __IO80211_TARGET >= __MAC_11_0\n    virtual bool willTerminate(IOService *,uint) APPLE_KEXT_OVERRIDE;\n#endif\n    virtual IOReturn configureReport(IOReportChannelList   *channels,\n                                     IOReportConfigureAction action,\n                                     void                  *result,\n                                     void                  *destination) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn updateReport(IOReportChannelList      *channels,\n                                  IOReportUpdateAction      action,\n                                  void                     *result,\n                                  void                     *destination) APPLE_KEXT_OVERRIDE;\n    \n    virtual bool terminate( IOOptionBits options = 0 ) APPLE_KEXT_OVERRIDE;\n    virtual bool attach(IOService *) APPLE_KEXT_OVERRIDE;\n    virtual void detach(IOService *) APPLE_KEXT_OVERRIDE;\n#if __IO80211_TARGET >= __MAC_10_15\n    virtual IOReturn newUserClient(task_t,void *,UInt,OSDictionary *,IOUserClient **) APPLE_KEXT_OVERRIDE;\n#endif\n    virtual const char * stringFromReturn( IOReturn rtn ) APPLE_KEXT_OVERRIDE;\n    virtual int errnoFromReturn( IOReturn rtn ) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn powerStateWillChangeTo(\n                                            IOPMPowerFlags  capabilities,\n                                            unsigned long   stateNumber,\n                                            IOService *     whatDevice ) APPLE_KEXT_OVERRIDE;\n\n    virtual IOReturn powerStateDidChangeTo(\n                                           IOPMPowerFlags  capabilities,\n                                           unsigned long   stateNumber,\n                                           IOService *     whatDevice ) APPLE_KEXT_OVERRIDE;\n    virtual bool init(IO80211Controller *,ether_addr *,uint,char const*) APPLE_KEXT_OVERRIDE;\n    virtual bool createPeerManager(ether_addr *,IO80211PeerManager **) APPLE_KEXT_OVERRIDE;\n    virtual IOMediumType getMediumType() APPLE_KEXT_OVERRIDE;\n    virtual void setLinkState(IO80211LinkState,uint) APPLE_KEXT_OVERRIDE;\n    virtual bool dequeueOutputPacketsWithServiceClass(uint,IOMbufServiceClass,mbuf_t*,mbuf_t*,UInt *,unsigned long long *) APPLE_KEXT_OVERRIDE;\n    virtual UInt32 outputPacket (mbuf_t m, void* param) APPLE_KEXT_OVERRIDE;\n    virtual void setEnabledBySystem(bool) APPLE_KEXT_OVERRIDE;\n    virtual void handleIoctl(unsigned long,void *) APPLE_KEXT_OVERRIDE;\n    virtual UInt32 inputPacket(mbuf_t,packet_info_tag *) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn controllerWillChangePowerState(IO80211Controller *,unsigned long,UInt,IOService *) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn controllerDidChangePowerState(IO80211Controller *,unsigned long,UInt,IOService *) APPLE_KEXT_OVERRIDE;\n    virtual bool handleDebugCmd(apple80211_debug_command *) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn postPeerPresence(ether_addr *,int,int,int,char *) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn postPeerAbsence(ether_addr *) APPLE_KEXT_OVERRIDE;\n#if __IO80211_TARGET >= __MAC_10_15\n    virtual IOReturn postPeerPresenceIPv6(ether_addr *,int,int,int,char *,unsigned char *) APPLE_KEXT_OVERRIDE;\n#endif\n    virtual void signalOutputThread() APPLE_KEXT_OVERRIDE;\n    virtual bool isOutputFlowControlled() APPLE_KEXT_OVERRIDE;\n    virtual void setOutputFlowControlled() APPLE_KEXT_OVERRIDE;\n    virtual void clearOutputFlowControlled() APPLE_KEXT_OVERRIDE;\n    virtual void outputStart(uint) APPLE_KEXT_OVERRIDE;\n    virtual UInt32 configureAQMOutput() APPLE_KEXT_OVERRIDE;\n    virtual void setUnitNumber(char const*) APPLE_KEXT_OVERRIDE;\n    virtual bool initIfnetEparams(ifnet_init_eparams *) APPLE_KEXT_OVERRIDE;\n    virtual bool attachToBpf() APPLE_KEXT_OVERRIDE;\n    virtual bool configureIfnet() APPLE_KEXT_OVERRIDE;\n    OSMetaClassDeclareReservedUnused( IO80211P2PInterface,  0);\n    OSMetaClassDeclareReservedUnused( IO80211P2PInterface,  1);\n    OSMetaClassDeclareReservedUnused( IO80211P2PInterface,  2);\n    OSMetaClassDeclareReservedUnused( IO80211P2PInterface,  3);\n    OSMetaClassDeclareReservedUnused( IO80211P2PInterface,  4);\n    OSMetaClassDeclareReservedUnused( IO80211P2PInterface,  5);\n    OSMetaClassDeclareReservedUnused( IO80211P2PInterface,  6);\n    OSMetaClassDeclareReservedUnused( IO80211P2PInterface,  7);\n    OSMetaClassDeclareReservedUnused( IO80211P2PInterface,  8);\n    OSMetaClassDeclareReservedUnused( IO80211P2PInterface,  9);\n    OSMetaClassDeclareReservedUnused( IO80211P2PInterface, 10);\n    OSMetaClassDeclareReservedUnused( IO80211P2PInterface, 11);\n    OSMetaClassDeclareReservedUnused( IO80211P2PInterface, 12);\n    OSMetaClassDeclareReservedUnused( IO80211P2PInterface, 13);\n    OSMetaClassDeclareReservedUnused( IO80211P2PInterface, 14);\n    OSMetaClassDeclareReservedUnused( IO80211P2PInterface, 15);\npublic:\n#if __IO80211_TARGET < __MAC_11_0\n    void setJoiningState(UInt,joinStatus,bool);\n    void setInfraChannel(apple80211_channel *);\n#endif\n    void p2pSetUnitNumber(char const*);\n    bool p2pCreatePeerManager(ether_addr *,IO80211PeerManager **);\n    bool p2pConfigureIfnet(void);\n    bool p2pAttachToBpf(void);\n#if __IO80211_TARGET < __MAC_11_0\n#if __IO80211_TARGET >= __MAC_10_15\n    void notifyHostapState(apple80211_hostap_state *);\n#endif\n    bool isAwdlAssistedDiscoveryEnabled(void);\n    void handleChannelSwitchAnnouncement(apple80211_channel_switch_announcement *);\n    void awdlSetUnitNumber(char const*);\n    void awdlInit(void);\n    void awdlFree(void);\n    bool awdlCreatePeerManager(ether_addr *,IO80211PeerManager **);\n    bool awdlConfigureIfnet(void);\n    bool awdlAttachToBpf(void);\n#endif\n#if __IO80211_TARGET >= __MAC_11_0\n    bool isP2P(void);\n    bool isAPSTA(void);\n#endif\n    errno_t apsta_if_output_pre_enqueue(ifnet_t, mbuf_t);\n    void apStaSetUnitNumber(char const*);\n    bool apStaInitIfnetEparams(ifnet_init_eparams *);\n    bool apStaCreatePeerManager(ether_addr *,IO80211PeerManager **);\n    bool apStaConfigureIfnet(void);\n    bool apStaAttachToBpf(void);\n\npublic:\n    char buf[0x300];\n};\n\n#endif /* IO80211P2PInterface_h */\n"
  },
  {
    "path": "include/Airport/IO80211SkywalkInterface.h",
    "content": "//\n//  IO80211SkywalkInterface.h\n//  IO80211Family\n//\n//  Created by 钟先耀 on 2019/10/18.\n//  Copyright © 2019 钟先耀. All rights reserved.\n//\n\n#ifndef _IO80211SKYWALK_H\n#define _IO80211SKYWALK_H\n\n#include <Availability.h>\n#include \"IOSkywalkEthernetInterface.h\"\n\n// This is necessary, because even the latest Xcode does not support properly targeting 11.0.\n#ifndef __IO80211_TARGET\n#error \"Please define __IO80211_TARGET to the requested version\"\n#endif\n\nclass TxSubmissionDequeueStats;\nclass TxCompletionEnqueueStats;\nclass IO80211NetworkPacket;\nclass PacketSkywalkScratch;\ntypedef UInt64 IO80211FlowQueueHash;\nclass IO80211Peer;\nclass CCPipe;\nclass IO80211APIUserClient;\nstruct apple80211_wme_ac;\nstruct apple80211_interface_availability;\nstruct apple80211_cca_report;\nstruct apple80211_stat_report;\nstruct apple80211_chip_counters_tx;\nstruct apple80211_chip_counters_rx;\nstruct apple80211_chip_error_counters_tx;\nstruct apple80211_ManagementInformationBasedot11_counters;\nstruct apple80211_lteCoex_report;\nstruct apple80211_frame_counters;\nstruct userPrintCtx;\nstruct apple80211_lqm_summary;\nstruct apple80211_infra_specific_stats;\n\nstruct TxPacketRequest {\n    uint16_t    unk1;       // 0\n    uint16_t    t;       // 2\n    uint16_t    mU;       // 4\n    uint16_t    mM;       // 6\n    uint16_t    pkt_cnt;\n    uint16_t    unk2;\n    uint16_t    unk3;\n    uint16_t    unk4;\n    uint32_t    pad;\n    mbuf_t      bufs[8];    // 18\n    uint32_t    reqTx;\n};\n\nstatic_assert(sizeof(struct TxPacketRequest) == 0x60, \"TxPacketRequest size error\");\n\nclass IO80211SkywalkInterface : public IOSkywalkEthernetInterface {\n    OSDeclareAbstractStructors(IO80211SkywalkInterface)\n\npublic:\n    \n    virtual bool init() APPLE_KEXT_OVERRIDE;\n    virtual void free() APPLE_KEXT_OVERRIDE;\n    virtual IOReturn configureReport(IOReportChannelList *,UInt,void *,void *) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn updateReport(IOReportChannelList *,UInt,void *,void *) APPLE_KEXT_OVERRIDE;\n    virtual bool start(IOService *) APPLE_KEXT_OVERRIDE;\n    virtual void stop(IOService *) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn setPowerState(\n        unsigned long powerStateOrdinal,\n        IOService *   whatDevice ) APPLE_KEXT_OVERRIDE;\n    virtual unsigned long maxCapabilityForDomainState( IOPMPowerFlags domainState ) APPLE_KEXT_OVERRIDE;\n    virtual unsigned long initialPowerStateForDomainState( IOPMPowerFlags domainState ) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn enable(UInt) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn disable(UInt) APPLE_KEXT_OVERRIDE;\n    virtual SInt32 initBSDInterfaceParameters(ifnet_init_eparams *,sockaddr_dl **) APPLE_KEXT_OVERRIDE;\n    virtual bool prepareBSDInterface(ifnet_t, UInt) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn processBSDCommand(ifnet_t, UInt, void *) APPLE_KEXT_OVERRIDE;\n    virtual SInt32 setInterfaceEnable(bool) APPLE_KEXT_OVERRIDE;\n    virtual SInt32 setRunningState(bool) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn handleChosenMedia(UInt) APPLE_KEXT_OVERRIDE;\n    virtual void *getSupportedMediaArray(UInt *,UInt *) APPLE_KEXT_OVERRIDE;\n    virtual UInt32 getFeatureFlags(void) APPLE_KEXT_OVERRIDE;\n    virtual const char *classNameOverride(void) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn setPromiscuousModeEnable(bool, UInt) APPLE_KEXT_OVERRIDE;\n    virtual void *createPeerManager(void);\n    virtual void postMessage(UInt,void *,unsigned long,bool);\n    virtual IOReturn reportDataPathEvents(UInt,void *,unsigned long,bool);\n    virtual IOReturn recordOutputPackets(TxSubmissionDequeueStats *,TxSubmissionDequeueStats *);\n    virtual IOReturn recordOutputPacket(apple80211_wme_ac,int,int);\n    virtual void logTxPacket(IO80211NetworkPacket *,PacketSkywalkScratch *,apple80211_wme_ac,bool);\n    virtual void logTxCompletionPacket(IO80211NetworkPacket *,PacketSkywalkScratch *,unsigned char *,apple80211_wme_ac,int,UInt,bool);\n    virtual IOReturn recordCompletionPackets(TxCompletionEnqueueStats *,TxCompletionEnqueueStats *);\n    virtual IOReturn inputPacket(IO80211NetworkPacket *,packet_info_tag *,ether_header *,bool *);\n    virtual IOReturn forwardInfraRelayPackets(IO80211NetworkPacket*, ether_header*);\n    virtual void logSkywalkTxReqPacket(IO80211NetworkPacket *,PacketSkywalkScratch *,unsigned char *,apple80211_wme_ac,bool);\n    virtual SInt64 pendingPackets(unsigned char);\n    virtual SInt64 packetSpace(unsigned char);\n    virtual bool isChipInterfaceReady(void);\n    virtual bool isDebounceOnGoing(void);\n    virtual bool setLinkState(IO80211LinkState,UInt,bool debounceTimeout = 30,UInt code = 0);\n    virtual IO80211LinkState linkState(void);\n    virtual void setScanningState(UInt,bool,apple80211_scan_data *,int);\n    virtual void setDataPathState(bool);\n    virtual void *getScanManager(void);\n    virtual void updateLinkParameters(apple80211_interface_availability *);\n    virtual void updateInterfaceCoexRiskPct(unsigned long long);\n    virtual void setLQM(unsigned long long);\n    virtual void updateLinkStatus(void);\n    virtual void updateLinkStatusGated(void);\n    virtual void setInterfaceExtendedCCA(apple80211_channel,apple80211_cca_report *);\n    virtual void setInterfaceCCA(apple80211_channel,int);\n    virtual void setInterfaceNF(apple80211_channel,long long);\n    virtual void setInterfaceOFDMDesense(apple80211_channel,long long);\n    virtual void removePacketQueue(IO80211FlowQueueHash *);\n    virtual void setDebugFlags(unsigned long long,UInt);\n    virtual SInt64 debugFlags(void);\n    virtual void setInterfaceChipCounters(apple80211_stat_report *,apple80211_chip_counters_tx *,apple80211_chip_error_counters_tx *,apple80211_chip_counters_rx *);\n    virtual void setInterfaceMIBdot11(apple80211_stat_report *,apple80211_ManagementInformationBasedot11_counters *);\n    virtual void setFrameStats(apple80211_stat_report *,apple80211_frame_counters *);\n#if __IO80211_TARGET >= __MAC_14_4\n    virtual void setInfraSpecificFrameStats(apple80211_stat_report *,apple80211_infra_specific_stats *);\n#endif\n    virtual SInt64 getWmeTxCounters(unsigned long long *);\n    virtual void setEnabledBySystem(bool);\n    virtual bool enabledBySystem(void);\n    virtual bool willRoam(ether_addr *,UInt);\n    virtual void setPeerManagerLogFlag(UInt,UInt,UInt);\n    virtual void setWoWEnabled(bool);\n    virtual bool wowEnabled(void);\n    virtual void printDataPath(userPrintCtx *);\n    virtual bool findOrCreateFlowQueue(IO80211FlowQueueHash);\n    virtual UInt64 findOrCreateFlowQueueWithCache(IO80211FlowQueueHash,bool *);\n    virtual UInt64 findExistingFlowQueue(IO80211FlowQueueHash);\n    virtual void removePacketQueue(IO80211FlowQueueHash const*);\n    virtual void flushPacketQueues(void);\n    virtual void cachePeer(ether_addr *,UInt *);\n    virtual bool shouldLog(unsigned long long);\n    virtual void vlogDebug(unsigned long long,char const*,va_list);\n    virtual void vlogDebugBPF(unsigned long long,char const*,va_list);\n    virtual UInt64 createLinkQualityMonitor(IO80211Peer *,IOService *);\n    virtual void releaseLinkQualityMonitor(IO80211Peer *);\n    virtual void *getP2PSkywalkPeerMgr(void);\n    virtual bool isCommandProhibited(int);\n    virtual void setNotificationProperty(OSSymbol const*,OSObject const*);\n    virtual void *getWorkerMatchingDict(OSString *);\n    virtual bool init(IOService *);\n    virtual bool isInterfaceEnabled(void);\n    virtual ether_addr *getSelfMacAddr(void);\n    virtual void setSelfMacAddr(ether_addr *);\n    virtual void *getPacketPool(OSString *);\n    virtual void *getLogger(void);\n    virtual IOReturn handleSIOCSIFADDR(void);\n    virtual IOReturn debugHandler(apple80211_debug_command *);\n    virtual void statsDump(void);\n    virtual void powerOnNotification(void);\n    virtual void powerOffNotification(void);\n    virtual UInt64 getTxQueueDepth(void);\n    virtual UInt64 getRxQueueCapacity(void);\n    virtual void updateRxCounter(unsigned long long);\n    virtual void *getMultiCastQueue(void);\n    virtual void *getCurrentBssid(void);\n    virtual int getAssocState(void);\n    virtual void notifyQueueState(apple80211_wme_ac,unsigned short);\n    virtual int getTxHeadroom(void);\n    virtual void *getRxCompQueue(void);\n    virtual void *getTxCompQueue(void);\n    virtual void *getTxSubQueue(apple80211_wme_ac);\n    virtual void *getTxPacketPool(void);\n    virtual void *getRxPacketPool(void);\n    virtual void enableDatapath(void);\n    virtual void disableDatapath(void);\n    virtual int getNumTxQueues(void);\n    virtual void *getLQMSummary(apple80211_lqm_summary *);\n    virtual int getEventPipeSize(void);\n    virtual UInt64 createEventPipe(IO80211APIUserClient *);\n    virtual void destroyEventPipe(IO80211APIUserClient *);\n    virtual void postMessageIOUC(char const*,UInt,void *,unsigned long);\n    virtual bool isIOUCPipeOpened(void);\n    virtual void *getRingMD(IO80211APIUserClient *,unsigned long long);\n    \npublic:\n    OSString *setInterfaceRole(UInt role);\n    void *setInterfaceId(UInt id);\n    int getInterfaceRole();\n    \npublic:\n    char _data[0x118];\n};\n\n#endif /* _IO80211SKYWALK_H */\n"
  },
  {
    "path": "include/Airport/IO80211VirtualInterface.h",
    "content": "#ifndef IO80211VirtualInterface_h\n#define IO80211VirtualInterface_h\n\n#include \"IO80211Interface.h\"\n#include \"apple_private_spi.h\"\n\ntypedef UInt64 IO80211FlowQueueHash;\ntypedef UInt kIO80211InterfaceType;\nclass IO80211PeerManager;\nclass RSNSupplicant;\n\nstruct TxPacketRequest;\nstruct ifmediareq;\nstruct realTimeServiceId;\nstruct apple80211_awdl_app_specific_info;\nstruct apple80211_awdl_statistics;\nstruct apple80211_lowlatency_peer_statistics_evevt;\nstruct apple80211_p2p_airplay_statistics;\nstruct apple80211_awdl_sidecar_statistics;\n\nclass IO80211VirtualInterface : public IOService {\n    OSDeclareDefaultStructors(IO80211VirtualInterface)\n    \npublic:\n    virtual void free(void) APPLE_KEXT_OVERRIDE;\n#if __IO80211_TARGET >= __MAC_11_0\n    virtual bool willTerminate( IOService * provider, IOOptionBits options ) APPLE_KEXT_OVERRIDE;\n#endif\n    virtual IOReturn configureReport(IOReportChannelList   *channels,\n                                     IOReportConfigureAction action,\n                                     void                  *result,\n                                     void                  *destination) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn updateReport(IOReportChannelList      *channels,\n                                  IOReportUpdateAction      action,\n                                  void                     *result,\n                                  void                     *destination) APPLE_KEXT_OVERRIDE;\n    virtual bool terminate( IOOptionBits options = 0 ) APPLE_KEXT_OVERRIDE;\n    virtual bool attach(IOService *) APPLE_KEXT_OVERRIDE;\n    virtual void detach(IOService *) APPLE_KEXT_OVERRIDE;\n#if __IO80211_TARGET >= __MAC_10_15\n    virtual IOReturn newUserClient(task_t,void *,UInt,OSDictionary *,IOUserClient **) APPLE_KEXT_OVERRIDE;\n#endif\n    virtual const char * stringFromReturn( IOReturn rtn ) APPLE_KEXT_OVERRIDE;\n    virtual int errnoFromReturn( IOReturn rtn ) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn powerStateWillChangeTo(\n                                            IOPMPowerFlags  capabilities,\n                                            unsigned long   stateNumber,\n                                            IOService *     whatDevice ) APPLE_KEXT_OVERRIDE;\n\n    virtual IOReturn powerStateDidChangeTo(\n                                           IOPMPowerFlags  capabilities,\n                                           unsigned long   stateNumber,\n                                           IOService *     whatDevice ) APPLE_KEXT_OVERRIDE;\n    virtual bool init(IO80211Controller *,ether_addr *,UInt,char const*);\n    virtual bool createPeerManager(ether_addr *,IO80211PeerManager **);\n    virtual IOMediumType getMediumType();\n    virtual void setLinkState(IO80211LinkState,UInt);\n    virtual bool dequeueOutputPacketsWithServiceClass(UInt,IOMbufServiceClass,mbuf_t*,mbuf_t*,UInt *,unsigned long long *);\n    virtual UInt32 outputPacket (mbuf_t m, void* param);\n    virtual void setEnabledBySystem(bool);\n    virtual void handleIoctl(unsigned long,void *);\n    virtual UInt32 inputPacket(mbuf_t,packet_info_tag *);\n    virtual IOReturn controllerWillChangePowerState(IO80211Controller *,unsigned long,UInt,IOService *);\n    virtual IOReturn controllerDidChangePowerState(IO80211Controller *,unsigned long,UInt,IOService *);\n    virtual bool handleDebugCmd(apple80211_debug_command *);\n    virtual IOReturn postPeerPresence(ether_addr *,int,int,int,char *);\n    virtual IOReturn postPeerAbsence(ether_addr *);\n#if __IO80211_TARGET >= __MAC_10_15\n    virtual IOReturn postPeerPresenceIPv6(ether_addr *,int,int,int,char *,unsigned char *);\n#endif\n    virtual void signalOutputThread();\n    virtual bool isOutputFlowControlled();\n    virtual void setOutputFlowControlled();\n    virtual void clearOutputFlowControlled();\n    virtual void outputStart(UInt);\n    virtual UInt32 configureAQMOutput();\n    virtual void setUnitNumber(char const*);\n    virtual bool initIfnetEparams(ifnet_init_eparams *);\n    virtual bool attachToBpf();\n    virtual bool configureIfnet();\n    OSMetaClassDeclareReservedUnused( IO80211VirtualInterface,  0);\n    OSMetaClassDeclareReservedUnused( IO80211VirtualInterface,  1);\n    OSMetaClassDeclareReservedUnused( IO80211VirtualInterface,  2);\n    OSMetaClassDeclareReservedUnused( IO80211VirtualInterface,  3);\n    OSMetaClassDeclareReservedUnused( IO80211VirtualInterface,  4);\n    OSMetaClassDeclareReservedUnused( IO80211VirtualInterface,  5);\n    OSMetaClassDeclareReservedUnused( IO80211VirtualInterface,  6);\n    OSMetaClassDeclareReservedUnused( IO80211VirtualInterface,  7);\n    OSMetaClassDeclareReservedUnused( IO80211VirtualInterface,  8);\n    OSMetaClassDeclareReservedUnused( IO80211VirtualInterface,  9);\n    OSMetaClassDeclareReservedUnused( IO80211VirtualInterface, 10);\n    OSMetaClassDeclareReservedUnused( IO80211VirtualInterface, 11);\n    OSMetaClassDeclareReservedUnused( IO80211VirtualInterface, 12);\n    OSMetaClassDeclareReservedUnused( IO80211VirtualInterface, 13);\n    OSMetaClassDeclareReservedUnused( IO80211VirtualInterface, 14);\n    OSMetaClassDeclareReservedUnused( IO80211VirtualInterface, 15);\npublic:\n    IOReturn IO80211InterfacePostMessage(UInt,void *,unsigned long);\n#if __IO80211_TARGET < __MAC_10_15\n    IOReturn _outputStart(OSObject *,void *,void *,void *,void *);\n    IOReturn _outputStartGated(UInt);\n    IOReturn _outputStartGatedNoPM(UInt);\n#endif\n    bool attachIfnet(ether_addr *,char const*);\n    bool authTimeout(void);\n    errno_t bpfAttach(UInt,UInt);\n    errno_t bpfAttach(UInt,UInt,OSObject *,UInt (OSObject::*)(mbuf_t,void *),int (OSObject::*)(UInt,UInt),IOWorkLoop *);\n    errno_t bpfAttachEN10MB(UInt);\n    UInt32 bpfOutput(UInt,mbuf_t);\n    UInt32 bpfOutputPacket(mbuf_t,void *);\n    UInt32 bpfTap(UInt,UInt);\n    void bpfTapInput(mbuf_t,UInt,void *,unsigned long);\n    UInt32 cachePMKSA(unsigned char *,unsigned long,ether_addr *);\n    UInt32 cachePMKSA(unsigned char *,unsigned long,ether_addr *,unsigned char *);\n    bool controllerLostPower(void);\n    UInt64 createIOReporters(IOService *);\n    UInt64 debugFlags(void);\n    mbuf_t dequeueTxPackets(TxPacketRequest *);\n    errno_t detachIfnet(void);\n    void dropTxPacket(mbuf_t);\n    bool dualBandCapable(void);\n    bool enabledBySystem(void);\n    IO80211FlowQueue *findExistingFlowQueue(IO80211FlowQueueHash);\n    IO80211FlowQueue *findOrCreateFlowQueue(IO80211FlowQueueHash);\n    void flushPacketQueues(void);\n    const char *getBSDName(void);\n    IO80211Controller *getController(void);\n    IOLock *getDetachLock(void);\n    ifnet_t getIfnet(void);\n#if __IO80211_TARGET >= __MAC_10_15\n    bool getInterfaceAddress(unsigned char *);\n#endif\n    UInt getInterfaceRole(void);\n    IOOutputQueue *getOutputQueueForDLT(UInt);\n    void getPMKSAList(apple80211_pmk_cache_data *);\n    void getWmeTxCounters(unsigned long long *);\n    IO80211WorkLoop *getWorkLoop(void);\n#if __IO80211_TARGET >= __MAC_11_0\n    void handleChannelSwitchAnnouncement(apple80211_channel_switch_announcement *);\n#endif\n    IOReturn handleIoctlGated(void *,void *,void *,void *,void *);\n    SInt32 handleSIOCGIFMEDIA(unsigned long,ifmediareq *);\n    SInt32 handleSIOCSIFADDR(void);\n    SInt32 handleSIOCSIFFLAGS(char const*);\n    static void ifnet_detach_callback(ifnet_t);\n    static void ifnet_ioctl_callback(ifnet_t,unsigned long,void *);\n    static void ifnet_start_callback(ifnet_t);\n    bool initSupplicant(unsigned char *,int);\n    void ioctl_internal(void *);\n    IOReturn ioctl_internal_gated(void *,void *,void *,void *,void *);\n#if __IO80211_TARGET >= __MAC_11_0\n    bool isAwdlAssistedDiscoveryEnabled(void);\n    bool isPeerToPeerInterface(void);\n#endif\n    IO80211LinkState linkState(void);\n    void logDebug(char const*,...);\n    void logDebug(unsigned long long,char const*,...);\n    void logTxCompletionPacket(mbuf_t,int);\n    void logTxPacket(mbuf_t);\n#if __IO80211_TARGET >= __MAC_11_0\n    void notifyHostapState(apple80211_hostap_state *);\n    void p2pDaemonExited(void);\n#endif\n    UInt64 packetSpace(unsigned char);\n#if __IO80211_TARGET >= __MAC_11_0\n    bool peerToPeerAttachToBpf(void);\n    errno_t peerToPeerConfigureIfnet(void);\n#endif\n    UInt64 pendingPackets(unsigned char);\n#if __IO80211_TARGET >= __MAC_10_15\n    void postAwdlAppSpecificInfo(apple80211_awdl_app_specific_info *);\n#endif\n#if __IO80211_TARGET >= __MAC_11_0\n    void postAwdlHppStatsEvent(realTimeServiceId);\n#else\n    void postAwdlSidecarStatistics(apple80211_awdl_sidecar_statistics *);\n#endif\n    void postAwdlStatistics(apple80211_awdl_statistics *);\n#if __IO80211_TARGET >= __MAC_11_0\n    void postHostapChannelChanged(apple80211_hostap_state *);\n    void postLowlatencyStatistics(apple80211_lowlatency_peer_statistics_evevt *);\n#endif\n    void postMessage(unsigned int, void* data = NULL, unsigned long dataLen = 0);\n    void postNewMasterElected(void);\n#if __IO80211_TARGET >= __MAC_11_0\n    void postP2PAirplayStatistics(apple80211_p2p_airplay_statistics *);\n#endif\n    void postServiceIndication(void);\n    void postSyncStateChanged(void);\n    IOReturn powerStateDidChangeToGated(void *,void *,void *,void *,void *);\n    IOReturn powerStateWillChangeToGated(void *,void *,void *,void *,void *);\n    mbuf_t preQueuePacket(mbuf_t);\n    void printDataPath(userPrintCtx *);\n    void pushPacket(mbuf_t);\n    UInt64 queueSize(unsigned char);\n    void removePacketQueue(IO80211FlowQueueHash const*);\n    IOReturn reportDataPathEvents(UInt,void *,unsigned long);\n    IOReturn reportDataPathEventsGated(void *,void *,void *,void *,void *);\n    IOReturn reportTransmitCompletionStatus(mbuf_t,int,UInt,UInt,UInt);\n    void reportTransmitStatus(mbuf_t,int,packet_info_tx *);\n    void resetSupplicant(void);\n#if __IO80211_TARGET >= __MAC_10_15\n    void resetUserClientReference(void);\n#endif\n#if __IO80211_TARGET >= __MAC_11_0\n    IOReturn resetUserClientReferenceGated(OSObject *,void *,void *,void *,void *);\n    void sendToBpfTap(mbuf_t,UInt,void *,unsigned long);\n    void setAMPDUstat(apple80211_stat_report *,apple80211_ampdu_stat_report *);\n#endif\n    void setAuthTimeout(unsigned long);\n    void setDebugFlags(unsigned long long,UInt);\n    bool setFrameStats(apple80211_stat_report *,apple80211_frame_counters *);\n#if __IO80211_TARGET >= __MAC_11_0\n    void setInfraChannel(apple80211_channel *);\n#endif\n    void setInfraTxState(bool);\n    bool setInterfaceCCA(apple80211_channel,int,apple80211_awdl_sync_channel_sequence *);\n    bool setInterfaceChipCounters(apple80211_stat_report *,apple80211_chip_counters_tx *,apple80211_chip_error_counters_tx *,apple80211_chip_counters_rx *);\n    bool setInterfaceExtendedCCA(apple80211_channel,apple80211_cca_report *,apple80211_awdl_sync_channel_sequence *);\n    bool setInterfaceMIBdot11(apple80211_stat_report *,apple80211_ManagementInformationBasedot11_counters *);\n    void setInterfaceRole(UInt);\n#if __IO80211_TARGET >= __MAC_11_0\n    void setJoiningState(UInt,joinStatus,bool);\n#endif\n    bool setPMK(unsigned char *);\n#if __IO80211_TARGET >= __MAC_10_15\n    bool setPSKPMK(unsigned char *);\n#endif\n    void setScanningState(UInt,bool,apple80211_scan_data *,int);\n    void setUnitNumber(char const*,UInt);\n    void setWaitingForDetach(bool);\n    void setWoWEnabled(bool);\n    bool shouldLog(unsigned long long);\n#if __IO80211_TARGET >= __MAC_10_15\n    IOReturn startAsyncEventUserClientForTask(task *,kIO80211InterfaceType);\n#endif\n    void startOutputQueues(void);\n#if __IO80211_TARGET >= __MAC_11_0\n    IOReturn startP2PDaemonUserClientForTask(task *);\n#endif\n    void stopOutputQueues(void);\n    bool supplicantExchangeComplete(void);\n    bool supplicantInitialized(void);\n    void terminateSupplicant(void);\n    void updateInterfaceCoexRiskPct(unsigned long long);\n    void updateLinkParameters(apple80211_interface_availability *);\n    void vlogDebug(unsigned long long,char const*,va_list);\n    void vlogDebugBPF(unsigned long long,char const*,va_list);\n\npublic:\n    char buf[0x300];\n};\n\n\n#endif /* IO80211VirtualInterface_h */\n"
  },
  {
    "path": "include/Airport/IO80211WorkLoop.h",
    "content": "/*\n *  IO80211WorkLoop.h\n *  IO80211Family\n *\n *  Created by Pete on 5/31/06.\n *  Copyright 2006 Apple Computer, Inc. All rights reserved.\n *\n */\n\n#ifndef _IO80211WORKLOOP_H\n#define _IO80211WORKLOOP_H\n\n#include <Availability.h>\n#include <IOKit/IOWorkLoop.h>\n\n// This is necessary, because even the latest Xcode does not support properly targeting 11.0.\n#ifndef __IO80211_TARGET\n#error \"Please define __IO80211_TARGET to the requested version\"\n#endif\n\nclass IO80211WorkLoop : public IOWorkLoop\n{\n    OSDeclareDefaultStructors( IO80211WorkLoop )\n\npublic:\n\n    static IO80211WorkLoop * workLoop();\n\n    virtual void openGate() APPLE_KEXT_OVERRIDE;\n    virtual void closeGate() APPLE_KEXT_OVERRIDE;\n    virtual int sleepGate( void * event, UInt32 interuptibleType ) APPLE_KEXT_OVERRIDE;\n    virtual int sleepGateDeadline( void * event, UInt32 interuptibleType, AbsoluteTime deadline );\n    virtual void wakeupGate( void * event, bool oneThread ) APPLE_KEXT_OVERRIDE;\n\n};\n\n#endif\n"
  },
  {
    "path": "include/Airport/IO80211WorkQueue.h",
    "content": "\n#ifndef _IO80211WORKQUEUE_H\n#define _IO80211WORKQUEUE_H\n\n#include <Availability.h>\n#include <IOKit/IOWorkLoop.h>\n\n// This is necessary, because even the latest Xcode does not support properly targeting 11.0.\n#ifndef __IO80211_TARGET\n#error \"Please define __IO80211_TARGET to the requested version\"\n#endif\n\nclass IO80211WorkQueue : public IOWorkLoop\n{\n    OSDeclareDefaultStructors( IO80211WorkQueue )\n\npublic:\n    \n    virtual IOThread getThread() const APPLE_KEXT_OVERRIDE;\n    virtual void enableAllInterrupts() const APPLE_KEXT_OVERRIDE;\n    virtual void disableAllInterrupts() const APPLE_KEXT_OVERRIDE;\n    virtual IOReturn runAction(Action action, OSObject *target,\n        void *arg0 = NULL, void *arg1 = NULL,\n        void *arg2 = NULL, void *arg3 = NULL) APPLE_KEXT_OVERRIDE;\n    virtual int commandSleep(void *,unsigned long long);\n    virtual void commandWakeup(void *);\n    \n    static IO80211WorkQueue * workQueue();\n    \npublic:\n    uint8_t filter[0x50];\n};\n\n#endif\n"
  },
  {
    "path": "include/Airport/IOSkywalkEthernetInterface.h",
    "content": "#ifndef IOSkywalkEthernetInterface_h\n#define IOSkywalkEthernetInterface_h\n\n#include \"IOSkywalkNetworkInterface.h\"\n\nstruct nicproxy_limits_info_s;\nstruct nicproxy_info_s;\n\nclass IOSkywalkEthernetInterface : public IOSkywalkNetworkInterface {\n    OSDeclareAbstractStructors( IOSkywalkEthernetInterface )\n    \npublic:\n    struct RegistrationInfo {\n        uint8_t pad[304];\n    } __attribute__((packed));\n    \npublic:\n    virtual void free() APPLE_KEXT_OVERRIDE;\n    virtual bool init(OSDictionary *) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn newUserClient( task_t owningTask, void * securityID,\n                                   UInt32 type, OSDictionary * properties,\n                                   LIBKERN_RETURNS_RETAINED IOUserClient ** handler ) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn setPowerState(\n                                   unsigned long powerStateOrdinal,\n                                   IOService *   whatDevice ) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn enable(UInt) APPLE_KEXT_OVERRIDE;\n    virtual SInt32 initBSDInterfaceParameters(ifnet_init_eparams *,sockaddr_dl **) APPLE_KEXT_OVERRIDE;\n    virtual bool prepareBSDInterface(ifnet_t,UInt) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn processBSDCommand(ifnet_t,UInt,void *) APPLE_KEXT_OVERRIDE;\n    virtual void *getPacketTapInfo(UInt *,UInt *) APPLE_KEXT_OVERRIDE;\n    virtual void enableNetworkWake(UInt) APPLE_KEXT_OVERRIDE;\n    virtual UInt getMaxTransferUnit(void) APPLE_KEXT_OVERRIDE;\n    virtual UInt getMinPacketSize(void) APPLE_KEXT_OVERRIDE;\n    virtual void *getInterfaceFamily(void) APPLE_KEXT_OVERRIDE;\n    virtual void *getInterfaceSubFamily(void) APPLE_KEXT_OVERRIDE;\n    virtual UInt getInitialMedia(void) APPLE_KEXT_OVERRIDE;\n    virtual const char *getBSDNamePrefix(void) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn registerNetworkInterfaceWithLogicalLink(IOSkywalkEthernetInterface::RegistrationInfo const*, IOSkywalkLogicalLink*, IOSkywalkPacketBufferPool*, IOSkywalkPacketBufferPool*, UInt);\n    virtual void getHardwareAddress(ether_addr *);\n    virtual void setHardwareAddress(ether_addr *);\n    virtual void setLinkLayerAddress(ether_addr *);\n    virtual bool configureMulticastFilter(UInt,ether_addr const*,UInt);\n    virtual bool setMulticastAddresses(ether_addr const*,UInt);\n    virtual void setAllMulticastModeEnable(bool);\n    virtual IOReturn setPromiscuousModeEnable(bool, UInt);\n    virtual void reportNicProxyLimits(nicproxy_limits_info_s);\n    virtual void hwConfigNicProxyData(nicproxy_info_s *);\n    OSMetaClassDeclareReservedUnused( IOSkywalkEthernetInterface,  0 );\n    OSMetaClassDeclareReservedUnused( IOSkywalkEthernetInterface,  1 );\n    OSMetaClassDeclareReservedUnused( IOSkywalkEthernetInterface,  2 );\n    OSMetaClassDeclareReservedUnused( IOSkywalkEthernetInterface,  3 );\n    OSMetaClassDeclareReservedUnused( IOSkywalkEthernetInterface,  4 );\n    OSMetaClassDeclareReservedUnused( IOSkywalkEthernetInterface,  5 );\n    OSMetaClassDeclareReservedUnused( IOSkywalkEthernetInterface,  6 );\n    OSMetaClassDeclareReservedUnused( IOSkywalkEthernetInterface,  7 );\n    OSMetaClassDeclareReservedUnused( IOSkywalkEthernetInterface,  8 );\n    OSMetaClassDeclareReservedUnused( IOSkywalkEthernetInterface,  9 );\n    OSMetaClassDeclareReservedUnused( IOSkywalkEthernetInterface, 10 );\n    \npublic:\n    bool initRegistrationInfo(IOSkywalkEthernetInterface::RegistrationInfo*, unsigned int, unsigned long);\n    bool registerEthernetInterface(IOSkywalkEthernetInterface::RegistrationInfo const*, IOSkywalkPacketQueue**, unsigned int, IOSkywalkPacketBufferPool*, IOSkywalkPacketBufferPool*, unsigned int);\n    \npublic:\n    void *vptr;\n    uint8_t pad1[0x30];\n    struct ExpansionData\n    {\n        RegistrationInfo *fRegistrationInfo;\n        ifnet_t fBSDInterface;\n    };\n    ExpansionData *mExpansionData2;\n};\n\nstatic_assert(__offsetof(IOSkywalkEthernetInterface, mExpansionData2) == 0x108, \"Invalid class size\");\n\nstatic_assert(sizeof(IOSkywalkEthernetInterface) == 0x110, \"Invalid class size\");\n\n#endif /* IOSkywalkEthernetInterface_h */\n"
  },
  {
    "path": "include/Airport/IOSkywalkInterface.h",
    "content": "//\n//  IOSkywalkInterface.h\n//  itlwm\n//\n//  Created by qcwap on 2023/6/7.\n//  Copyright © 2023 钟先耀. All rights reserved.\n//\n\n#ifndef IOSkywalkInterface_h\n#define IOSkywalkInterface_h\n\n\nclass IOSkywalkInterface : public IOService {\n    OSDeclareAbstractStructors(IOSkywalkInterface)\n    \npublic:\n    virtual void free() APPLE_KEXT_OVERRIDE;\n    virtual bool init(OSDictionary *) APPLE_KEXT_OVERRIDE;\n    virtual bool willTerminate( IOService * provider, IOOptionBits options ) APPLE_KEXT_OVERRIDE;\n    virtual bool didTerminate( IOService * provider, IOOptionBits options, bool * defer ) APPLE_KEXT_OVERRIDE;\n    virtual bool handleOpen(    IOService *   forClient,\n                            IOOptionBits      options,\n                            void *        arg ) APPLE_KEXT_OVERRIDE;\n    virtual void handleClose(   IOService *       forClient,\n                             IOOptionBits      options ) APPLE_KEXT_OVERRIDE;\n    virtual bool handleIsOpen(  const IOService * forClient ) const APPLE_KEXT_OVERRIDE;\n    virtual IOReturn enable( IOOptionBits options ) = 0;\n    virtual IOReturn disable( IOOptionBits options ) = 0;\n    virtual IOReturn clientConnectWithTask( task_t task, IOService * forClient, IOOptionBits options );\n    virtual void clientDisconnect( IOService * forClient, IOOptionBits options );\n    virtual bool isTerminating(void);\n    \n    OSMetaClassDeclareReservedUnused( IOSkywalkInterface,  0 );\n    OSMetaClassDeclareReservedUnused( IOSkywalkInterface,  1 );\n    OSMetaClassDeclareReservedUnused( IOSkywalkInterface,  2 );\n    OSMetaClassDeclareReservedUnused( IOSkywalkInterface,  3 );\n    OSMetaClassDeclareReservedUnused( IOSkywalkInterface,  4 );\n    OSMetaClassDeclareReservedUnused( IOSkywalkInterface,  5 );\n    OSMetaClassDeclareReservedUnused( IOSkywalkInterface,  6 );\n    OSMetaClassDeclareReservedUnused( IOSkywalkInterface,  7 );\n    OSMetaClassDeclareReservedUnused( IOSkywalkInterface,  8 );\n    OSMetaClassDeclareReservedUnused( IOSkywalkInterface,  9 );\n    OSMetaClassDeclareReservedUnused( IOSkywalkInterface, 10 );\n    \npublic:\n    uint8_t filter[0xB0 - 136];\n};\n\nstatic_assert(sizeof(IOSkywalkInterface) == 0xB0, \"Invalid class size\");\n\n#endif /* IOSkywalkInterface_h */\n"
  },
  {
    "path": "include/Airport/IOSkywalkLegacyEthernetInterface.h",
    "content": "//\n//  IOSkywalkLegacyEthernetInterface.h\n//  itlwm\n//\n//  Created by qcwap on 2023/6/19.\n//  Copyright © 2023 钟先耀. All rights reserved.\n//\n\n#ifndef IOSkywalkLegacyEthernetInterface_h\n#define IOSkywalkLegacyEthernetInterface_h\n\n#include <IOKit/IOService.h>\n#include <IOKit/network/IOEthernetInterface.h>\n\nclass IOSkywalkLegacyEthernetInterface : public IOEthernetInterface {\n    OSDeclareDefaultStructors(IOSkywalkLegacyEthernetInterface)\n    \npublic:\n    virtual void free() APPLE_KEXT_OVERRIDE;\n    virtual OSObject * getProperty( const OSSymbol * aKey) const APPLE_KEXT_OVERRIDE;\n    virtual OSObject * copyProperty( const OSSymbol * aKey) const APPLE_KEXT_OVERRIDE;\n    virtual bool serializeProperties( OSSerialize * serialize ) const APPLE_KEXT_OVERRIDE;\n    virtual IOReturn setProperties( OSObject * properties ) APPLE_KEXT_OVERRIDE;\n    virtual bool init( IONetworkController * controller ) APPLE_KEXT_OVERRIDE;\n    virtual const char * getNamePrefix() const APPLE_KEXT_OVERRIDE;\n    virtual bool controllerDidOpen(IONetworkController * controller) APPLE_KEXT_OVERRIDE;\n    virtual void controllerWillClose(IONetworkController * controller) APPLE_KEXT_OVERRIDE;\n    virtual ifnet_t  getIfnet( void ) const APPLE_KEXT_OVERRIDE;\n    virtual IOReturn attachToDataLinkLayer( IOOptionBits options, void *       parameter ) APPLE_KEXT_OVERRIDE;\n    virtual void     detachFromDataLinkLayer( IOOptionBits options,\n                                             void *       parameter ) APPLE_KEXT_OVERRIDE;\n    \npublic:\n    uint8_t filter[0x160];\n};\n\n#endif /* IOSkywalkLegacyEthernetInterface_h */\n\n"
  },
  {
    "path": "include/Airport/IOSkywalkLogicalLink.h",
    "content": "//\n//  IOSkywalkLogicalLink.h\n//  itlwm\n//\n//  Created by qcwap on 2023/6/12.\n//  Copyright © 2023 钟先耀. All rights reserved.\n//\n\n#ifndef IOSkywalkLogicalLink_h\n#define IOSkywalkLogicalLink_h\n\nclass IOSkywalkLogicalLink : public IOService {\n    OSDeclareAbstractStructors(IOSkywalkLogicalLink)\n    \npublic:\n    \npublic:\n};\n\n#endif /* IOSkywalkLogicalLink_h */\n"
  },
  {
    "path": "include/Airport/IOSkywalkNetworkInterface.h",
    "content": "//\n//  IOSkywalkNetworkInterface.h\n//  itlwm\n//\n//  Created by qcwap on 2023/6/7.\n//  Copyright © 2023 钟先耀. All rights reserved.\n//\n\n#ifndef IOSkywalkNetworkInterface_h\n#define IOSkywalkNetworkInterface_h\n\n#include <net/if.h>\n\n#include \"IOSkywalkInterface.h\"\n\ntypedef UInt if_link_status;\nclass IOSkywalkPacketQueue;\nclass IOSkywalkLogicalLink;\nclass IOSkywalkPacketBufferPool;\n\nclass IOSkywalkNetworkInterface : public IOSkywalkInterface {\n    OSDeclareAbstractStructors( IOSkywalkNetworkInterface )\n    \npublic:\n    struct RegistrationInfo {\n        uint8_t pad[304];\n    } __attribute__((packed));\n    struct IOSkywalkTSOOptions;\n    \npublic:\n    virtual void free() APPLE_KEXT_OVERRIDE;\n    virtual bool init(OSDictionary *) APPLE_KEXT_OVERRIDE;\n    virtual void stop(IOService *) APPLE_KEXT_OVERRIDE;\n    virtual void joinPMtree( IOService * driver ) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn setAggressiveness(\n                                       unsigned long type,\n                                       unsigned long newLevel ) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn enable(UInt) APPLE_KEXT_OVERRIDE;\n    virtual IOReturn disable(UInt) APPLE_KEXT_OVERRIDE;\n    virtual SInt32 initBSDInterfaceParameters(ifnet_init_eparams *,sockaddr_dl **) = 0;\n    virtual bool prepareBSDInterface(ifnet_t,UInt);\n    virtual void finalizeBSDInterface(ifnet_t,UInt);\n    virtual ifnet_t getBSDInterface(void);\n    virtual void setBSDName(char const*);\n    virtual const char *getBSDName(void);\n    virtual IOReturn processBSDCommand(ifnet_t,UInt,void *);\n    virtual IOReturn processInterfaceCommand(ifdrv *);\n    virtual IOReturn interfaceAdvisoryEnable(bool);\n    virtual SInt32 setInterfaceEnable(bool);\n    virtual SInt32 setRunningState(bool);\n    virtual IOReturn handleChosenMedia(UInt);\n    virtual void *getSupportedMediaArray(UInt *,UInt *);\n    virtual void *getPacketTapInfo(UInt *,UInt *);\n    virtual UInt getUnsentDataByteCount(UInt *,UInt *,UInt);\n    virtual UInt32 getSupportedWakeFlags(UInt *);\n    virtual void enableNetworkWake(UInt);\n    virtual void calculateRingSizeForQueue(IOSkywalkPacketQueue const*,UInt *);\n    virtual UInt getMaxTransferUnit(void);\n    virtual void setMaxTransferUnit(UInt);\n    virtual UInt getMinPacketSize(void);\n    virtual UInt getHardwareAssists(void);\n    virtual void setHardwareAssists(UInt,UInt);\n    virtual void *getInterfaceFamily(void);\n    virtual void *getInterfaceSubFamily(void);\n    virtual UInt getInitialMedia(void);\n    virtual UInt getFeatureFlags(void);\n    virtual UInt getTxDataOffset(void);\n    virtual UInt captureInterfaceState(UInt);\n    virtual void restoreInterfaceState(UInt);\n    virtual void setMTU(UInt);\n    virtual bool bpfTap(UInt,UInt);\n    virtual const char *getBSDNamePrefix(void);\n    virtual UInt getBSDUnitNumber(void);\n    virtual const char *classNameOverride(void);\n    virtual void deferBSDAttach(bool);\n    virtual void reportDetailedLinkStatus(if_link_status const*);\n    virtual IOReturn registerNetworkInterfaceWithLogicalLink(IOSkywalkNetworkInterface::RegistrationInfo const*,IOSkywalkLogicalLink *,IOSkywalkPacketBufferPool *,IOSkywalkPacketBufferPool *,UInt);\n    virtual IOReturn deregisterLogicalLink(void);\n    virtual UInt getTSOOptions(IOSkywalkNetworkInterface::IOSkywalkTSOOptions *);\n    OSMetaClassDeclareReservedUnused( IOSkywalkNetworkInterface,  0);\n    OSMetaClassDeclareReservedUnused( IOSkywalkNetworkInterface,  1);\n    OSMetaClassDeclareReservedUnused( IOSkywalkNetworkInterface,  2);\n    OSMetaClassDeclareReservedUnused( IOSkywalkNetworkInterface,  3);\n    OSMetaClassDeclareReservedUnused( IOSkywalkNetworkInterface,  4);\n    OSMetaClassDeclareReservedUnused( IOSkywalkNetworkInterface,  5);\n    OSMetaClassDeclareReservedUnused( IOSkywalkNetworkInterface,  6);\n    OSMetaClassDeclareReservedUnused( IOSkywalkNetworkInterface,  7);\n    OSMetaClassDeclareReservedUnused( IOSkywalkNetworkInterface,  8);\n    OSMetaClassDeclareReservedUnused( IOSkywalkNetworkInterface,  9);\n    \npublic:\n    void reportLinkStatus(unsigned int, unsigned int);\n    \npublic:\n    void *vptr;\n    struct ExpansionData\n    {\n        RegistrationInfo *fRegistrationInfo;\n        ifnet_t fBSDInterface;\n    };\n    ExpansionData *mExpansionData;\n    uint8_t pad[2 * 8];\n};\n\nstatic_assert(sizeof(IOSkywalkNetworkInterface) == 0xD0, \"Invalid class size\");\n\n#endif /* IOSkywalkNetworkInterface_h */\n"
  },
  {
    "path": "include/Airport/IOSkywalkNetworkPacket.h",
    "content": "//\n//  IOSkywalkNetworkPacket.h\n//  itlwm\n//\n//  Created by qcwap on 2023/6/13.\n//  Copyright © 2023 钟先耀. All rights reserved.\n//\n\n#ifndef IOSkywalkInterface_h\n#define IOSkywalkInterface_h\n\nclass IOSkywalkPacketBufferPool;\nclass IOSkywalkPacketDescriptor;\nclass IOSkywalkPacketBuffer;\nclass IOSkywalkPacketQueue;\n\nclass IOSkywalkNetworkPacket : public IOService {\n    OSDeclareAbstractStructors(IOSkywalkNetworkPacket)\n    \npublic:\n    virtual void free() APPLE_KEXT_OVERRIDE;\n    \n    virtual bool initWithPool(IOSkywalkPacketBufferPool *,IOSkywalkPacketDescriptor *,uint);\n    virtual void *getPacketBuffers(IOSkywalkPacketBuffer **,uint);\n    virtual UInt getPacketBufferCount(void);\n    virtual IOSkywalkPacketDescriptor *getMemoryDescriptor(void);\n    virtual void setDataLength(uint);\n    virtual UInt getDataLength(void);\n    virtual void setDataOffset(unsigned short);\n    virtual unsigned short getDataOffset(void);\n    virtual void setDataOffsetAndLength(unsigned short,uint);\n    virtual void setDataOff(long long);\n    virtual long long getDataOff(void);\n    virtual void setDataOffAndLen(long long,unsigned long);\n    virtual void *getDataVirtualAddress(void);\n    virtual void *getDataIOVirtualAddress(void);\n    virtual bool prepareWithQueue(IOSkywalkPacketQueue *,uint,uint);\n    virtual bool prepare(IOSkywalkPacketQueue *,unsigned long long,uint);\n    virtual void completeWithQueue(IOSkywalkPacketQueue *,uint,uint);\n    virtual void complete(IOSkywalkPacketQueue *,uint);\n    virtual UInt getPacketType(void);\n    virtual void setWakeFlag(void);\n    virtual UInt getTraceID(void);\n    virtual void setTraceID(UInt);\n    virtual void traceEvent(uint);\n    virtual void *generateTraceTag(IOSkywalkPacketQueue *);\n    virtual void *acquireWithPacketHandle(unsigned long long,uint);\n    virtual void disposePacket(void);\n    \npublic:\n    uint8_t filter[0x78];\n};\n\n#endif /* IOSkywalkInterface_h */\n"
  },
  {
    "path": "include/Airport/IOSkywalkPacketBufferPool.h",
    "content": "//\n//  IOSkywalkPacketBufferPool.h\n//  itlwm\n//\n//  Created by qcwap on 2023/6/15.\n//  Copyright © 2023 钟先耀. All rights reserved.\n//\n\n#ifndef IOSkywalkPacketBufferPool_h\n#define IOSkywalkPacketBufferPool_h\n\n#include <IOKit/IOService.h>\n\nclass IOSkywalkMemorySegment;\nclass IOSkywalkMemorySegmentDescriptor;\nclass IOSkywalkPacket;\nclass IOSkywalkPacketBuffer;\nclass IOSkywalkPacketDescriptor;\nclass IOSkywalkPacketBufferDescriptor;\n\nclass IOSkywalkPacketBufferPool : public OSObject {\n    OSDeclareDefaultStructors(IOSkywalkPacketBufferPool)\n    \npublic:\n    struct PoolOptions {\n        uint32_t packetCount;\n        uint32_t bufferCount;\n        uint32_t bufferSize;\n        uint32_t maxBuffersPerPacket;\n        uint32_t memorySegmentSize;\n        uint32_t poolFlags;\n        uint64_t pad;\n    };\n    \npublic:\n    virtual void free() APPLE_KEXT_OVERRIDE;\n    virtual bool initWithName(char const*,void *,uint,IOSkywalkPacketBufferPool::PoolOptions const*);\n    virtual bool initWithName(char const*,OSObject *,uint,IOSkywalkPacketBufferPool::PoolOptions const*);\n    virtual bool allocatePacket(IOSkywalkPacket **,uint);\n    virtual bool allocatePacket(uint,IOSkywalkPacket **,uint);\n    virtual bool allocatePackets(uint,uint *,IOSkywalkPacket **,uint);\n    virtual void deallocatePacket(IOSkywalkPacket *);\n    virtual void deallocatePackets(IOSkywalkPacket **,uint);\n    virtual void deallocatePacketList(IOSkywalkPacket *);\n    virtual void deallocatePacketChain(unsigned long long);\n    virtual bool allocatePacketBuffer(IOSkywalkPacketBuffer **,uint);\n    virtual bool allocatePacketBuffers(uint *,IOSkywalkPacketBuffer **,uint);\n    virtual void deallocatePacketBuffer(IOSkywalkPacketBuffer *);\n    virtual void deallocatePacketBuffers(IOSkywalkPacketBuffer **,uint);\n    virtual bool newPacket(IOSkywalkPacketDescriptor *,IOSkywalkPacket **);\n    virtual bool newPacketBuffer(IOSkywalkPacketBufferDescriptor *,IOSkywalkPacketBuffer **);\n    virtual bool newMemorySegment(IOSkywalkMemorySegmentDescriptor *,IOSkywalkMemorySegment **);\n    \npublic:\n    static IOSkywalkPacketBufferPool *withName(char const*,OSObject *,uint,IOSkywalkPacketBufferPool::PoolOptions const*);\n    \npublic:\n    uint8_t filter[0xB8];\n};\n\n#endif /* IOSkywalkPacketBufferPool_h */\n\n"
  },
  {
    "path": "include/Airport/apple80211_ioctl.h",
    "content": "/*\n * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.\n *\n * @APPLE_LICENSE_HEADER_START@\n *\n * The contents of this file constitute Original Code as defined in and\n * are subject to the Apple Public Source License Version 1.1 (the\n * \"License\").  You may not use this file except in compliance with the\n * License.  Please obtain a copy of the License at\n * http://www.apple.com/publicsource and read it before using this file.\n *\n * This Original Code and all software distributed under the License are\n * distributed on an \"AS IS\" basis, WITHOUT WARRANTY OF ANY KIND, EITHER\n * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,\n * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the\n * License for the specific language governing rights and limitations\n * under the License.\n *\n * @APPLE_LICENSE_HEADER_END@\n */\n#ifndef _APPLE80211_IOCTL_H_\n#define _APPLE80211_IOCTL_H_\n\n#include <Availability.h>\n#include <sys/socket.h>\n#include <net/if.h>\n#include <net/ethernet.h>\n#include <sys/param.h>\n#include <sys/ioctl.h>\n\n// This is necessary, because even the latest Xcode does not support properly targeting 11.0.\n#ifndef __IO80211_TARGET\n#error \"Please define __IO80211_TARGET to the requested version\"\n#endif\n\n#include \"apple80211_var.h\"\n\nstruct apple80211req\n{\n    char        req_if_name[IFNAMSIZ];    // 16 bytes\n    int         req_type;                 // 4 bytes\n    int         req_val;                  // 4 bytes\n    u_int32_t   req_len;                  // 4 bytes\n    void        *req_data;                // 4 bytes\n};\n\n#if __IO80211_TARGET >= __MAC_10_15\n#define SIOCSA80211 2150656456\n#define SIOCGA80211 3224398281\n#else\n#define SIOCSA80211 2150132168\n#define SIOCGA80211 3223873993\n#endif\n\n#define APPLE80211_AWDL_CAP_CCA_STATS   2\n#define APPLE80211_AWDL_CAP_SEC_PAYLOAD 0x100000000\n\n// req_type\n\n#define APPLE80211_IOC_SSID                     1    // req_type\n\n#define APPLE80211_IOC_AUTH_TYPE                2    // req_type\n#define     APPLE80211_AUTH_TYPE_UNICAST        1    // req_val, SIOCGA80211 only\n#define     APPLE80211_AUTH_TYPE_MULTICAST      2    // req_val, SIOCGA80211 only\n\n#define APPLE80211_IOC_CIPHER_KEY                3   // req_type\n#define     APPLE80211_CIPHER_KEY_UNICAST        1   // req_val\n#define     APPLE80211_CIPHER_KEY_MULICAST       2   // req_val\n\n#define APPLE80211_IOC_CHANNEL                   4   // req_type\n\n#define APPLE80211_IOC_POWERSAVE                 5   // req_type\n\n#define APPLE80211_IOC_PROTMODE                  6   // req_type\n\n#define APPLE80211_IOC_TXPOWER                   7   // req_type\n#define APPLE80211_IOC_RATE                      8   // req_type\n#define APPLE80211_IOC_BSSID                     9   // req_type\n\n#define APPLE80211_IOC_SCAN_REQ                 10   // req_type\n\n#define APPLE80211_IOC_SCAN_RESULT              11   // req_type\n\n#define APPLE80211_IOC_CARD_CAPABILITIES        12   // req_type\n\n#define APPLE80211_IOC_STATE                    13   // req_type (apple80211_state)\n#define APPLE80211_IOC_PHY_MODE                 14   // req_type (apple80211_phymode)\n\n#define APPLE80211_IOC_OP_MODE                  15   // req_type (apple80211_opmode)\n#define APPLE80211_IOC_RSSI                     16   // req_type\n#define APPLE80211_IOC_NOISE                    17   // req_type\n\n#define APPLE80211_IOC_INT_MIT                  18\n#define APPLE80211_IOC_INT_MIT_OFF               1   // req_val\n#define APPLE80211_IOC_INT_MIT_ON                2   // req_val\n\n// card power\n#define APPLE80211_IOC_POWER                    19   // req_type\n\n#define APPLE80211_IOC_ASSOCIATE                20   // req_type\n#define APPLE80211_IOC_ASSOCIATE_RESULT         21   // req_type\n#define APPLE80211_IOC_DISASSOCIATE             22   // req_type\n#define APPLE80211_IOC_STATUS_DEV_NAME          23   // req_type\n\n#define APPLE80211_IOC_IBSS_MODE                24   // req_type\n#define APPLE80211_IOC_IBSS_MODE_START           1   // req_val\n#define APPLE80211_IOC_IBSS_MODE_STOP            2   // req_val\n\n#define APPLE80211_IOC_HOST_AP_MODE             25   // req_type\n#define APPLE80211_IOC_HOST_AP_MODE_START        1   // req_val\n#define APPLE80211_IOC_HOST_AP_MODE_STOP         2   // req_val\n\n#define APPLE80211_IOC_AP_MODE                   26  // req_type (apple80211_apmode)\n#define APPLE80211_IOC_SUPPORTED_CHANNELS        27  // req_type\n#define APPLE80211_IOC_LOCALE                    28  // req_type\n#define APPLE80211_IOC_DEAUTH                    29  // req_type\n#define APPLE80211_IOC_COUNTERMEASURES           30  // req_type\n#define APPLE80211_IOC_FRAG_THRESHOLD            31  // req_type\n#define APPLE80211_IOC_RATE_SET                  32  // req_type\n#define APPLE80211_IOC_SHORT_SLOT                33  // req_type\n#define APPLE80211_IOC_MULTICAST_RATE            34  // req_type\n#define APPLE80211_IOC_SHORT_RETRY_LIMIT         35  // req_type\n#define APPLE80211_IOC_LONG_RETRY_LIMIT          36  // req_type\n#define APPLE80211_IOC_TX_ANTENNA                37  // req_type\n#define APPLE80211_IOC_RX_ANTENNA                38  // req_type\n#define APPLE80211_IOC_ANTENNA_DIVERSITY         39  // req_type\n#define APPLE80211_IOC_ROM                       40  // req_type\n#define APPLE80211_IOC_DTIM_INT                  41  // req_type\n#define APPLE80211_IOC_STATION_LIST              42  // req_type\n#define APPLE80211_IOC_DRIVER_VERSION            43  // req_type\n#define APPLE80211_IOC_HARDWARE_VERSION          44  // req_type\n#define APPLE80211_IOC_RAND                      45  // req_type\n#define APPLE80211_IOC_RSN_IE                    46  // req_type\n#define APPLE80211_IOC_BACKGROUND_SCAN           47  // req_type\n#define APPLE80211_IOC_AP_IE_LIST                48  // req_type\n#define APPLE80211_IOC_STATS                     49  // req_type\n#define APPLE80211_IOC_ASSOCIATION_STATUS        50  // req_type\n#define APPLE80211_IOC_COUNTRY_CODE              51  // req_type\n#define APPLE80211_IOC_DEBUG_FLAGS               52  // req_type\n#define APPLE80211_IOC_LAST_RX_PKT_DATA          53  // req_type\n#define APPLE80211_IOC_RADIO_INFO                54  // req_type\n#define APPLE80211_IOC_GUARD_INTERVAL            55  // req_type\n#define APPLE80211_IOC_MIMO_POWERSAVE            56  // req_type\n#define APPLE80211_IOC_MCS                       57  // req_type\n#define APPLE80211_IOC_RIFS                      58  // req_type\n#define APPLE80211_IOC_LDPC                      59  // req_type\n#define APPLE80211_IOC_MSDU                      60  // req_type\n#define APPLE80211_IOC_MPDU                      61  // req_type\n#define APPLE80211_IOC_BLOCK_ACK                 62  // req_type\n#define APPLE80211_IOC_PLS                       63  // req_type\n#define APPLE80211_IOC_PSMP                      64  // req_type\n#define APPLE80211_IOC_PHY_SUB_MODE              65  // req_type\n#define APPLE80211_IOC_MCS_INDEX_SET             66  // req_type\n#define APPLE80211_IOC_CACHE_THRESH_BCAST        67  // req_type\n#define APPLE80211_IOC_CACHE_THRESH_DIRECT       68  // req_type\n#define APPLE80211_IOC_WOW_PARAMETERS            69  // req_type\n#define APPLE80211_IOC_WOW_ENABLED               70  // req_type\n#define APPLE80211_IOC_40MHZ_INTOLERANT          71  // req_type\n#define APPLE80211_IOC_PID_LOCK                  72\n#define APPLE80211_IOC_STA_IE_LIST               73\n#define APPLE80211_IOC_STA_AUTHORIZE             74\n#define APPLE80211_IOC_STA_DISASSOCIATE          75\n#define APPLE80211_IOC_STA_DEAUTH                76\n#define APPLE80211_IOC_RSN_CONF                  77\n#define APPLE80211_IOC_KEY_RSC                   78\n#define APPLE80211_IOC_STA_STATS                 79\n#define APPLE80211_IOC_ROAM_THRESH               80\n#define APPLE80211_IOC_VENDOR_DBG_FLAGS          81\n#define APPLE80211_IOC_CACHE_AGE_THRESH          82\n#define APPLE80211_IOC_PMK_CACHE                 83\n#define APPLE80211_IOC_LINK_QUAL_EVENT_PARAMS    84\n#define APPLE80211_IOC_IE                        85\n#define APPLE80211_IOC_SCAN_REQ_MULTIPLE         86\n#define APPLE80211_IOC_BTCOEX_MODE               87\n#define APPLE80211_IOC_WOW_TEST                  88\n#define APPLE80211_IOC_CLEAR_PMK_CACHE           89\n#define APPLE80211_IOC_SCANCACHE_CLEAR           90\n#define APPLE80211_IOC_P2P_ENABLE                91\n#define APPLE80211_IOC_P2P_LISTEN                92\n#define APPLE80211_IOC_P2P_SCAN                  93\n#define APPLE80211_IOC_VIRTUAL_IF_CREATE         94\n#define APPLE80211_IOC_VIRTUAL_IF_DELETE         95\n#define APPLE80211_IOC_VIRTUAL_IF_ROLE           96\n#define APPLE80211_IOC_VIRTUAL_IF_PARENT         97\n#define APPLE80211_IOC_P2P_GO_CONF               98\n#define APPLE80211_IOC_P2P_NOA_LIST              99\n#define APPLE80211_IOC_P2P_OPP_PS                100\n#define APPLE80211_IOC_P2P_CT_WINDOW             101\n#define APPLE80211_IOC_BT_COEX_FLAGS             102\n#define APPLE80211_IOC_CURRENT_NETWORK           103\n#define APPLE80211_IOC_BT_POWER                  104\n#define APPLE80211_IOC_AVAILABILITY              105\n#define APPLE80211_IOC_RSSI_BOUNDS               106\n#define APPLE80211_IOC_ROAM                      107\n#define APPLE80211_IOC_TX_CHAIN_POWER            108\n#define APPLE80211_IOC_CDD_MODE                  109\n#define APPLE80211_IOC_LAST_BCAST_SCAN_TIME      110\n#define APPLE80211_IOC_THERMAL_THROTTLING        111\n#define APPLE80211_IOC_FACTORY_MODE              112\n#define APPLE80211_IOC_REASSOCIATE               113\n\n#define APPLE80211_IOC_POWER_DEBUG_INFO 115\n#define APPLE80211_IOC_AWDL_SYNC_PARAMS 116\n#define APPLE80211_IOC_AWDL_SYNC_ENABLED 117\n#define APPLE80211_IOC_AWDL_EXTENSION_STATE_MACHINE_PARAMETERS 118\n#define APPLE80211_IOC_AWDL_SERVICE_PARAMS 119\n#define APPLE80211_IOC_AWDL_PEER_SERVICE_REQUEST 120\n#define APPLE80211_IOC_AWDL_ELECTION_ALGORITHM_ENABLED 121\n#define APPLE80211_IOC_AWDL_ELECTION_ID 122\n#define APPLE80211_IOC_AWDL_MAX_TREE_DEPTH 123\n#define APPLE80211_IOC_AWDL_GUARD_TIME 124\n#define APPLE80211_IOC_AWDL_BSSID 125\n#define APPLE80211_IOC_AWDL_ELECTION_METRIC 126\n#define APPLE80211_IOC_AWDL_AVAILABILITY_WINDOW_AP_ALIGNMENT 127\n#define APPLE80211_IOC_AWDL_SYNC_FRAME_AP_BEACON_ALIGNMENT 128\n#define APPLE80211_IOC_AWDL_SYNCHRONIZATION_CHANNEL_SEQUENCE 129\n#define APPLE80211_IOC_PEER_CACHE_MAXIMUM_SIZE 130\n#define APPLE80211_IOC_AWDL_OUI 131\n#define APPLE80211_IOC_AWDL_MASTER_CHANNEL 132\n#define APPLE80211_IOC_AWDL_TOP_MASTER 133\n#define APPLE80211_IOC_AWDL_SYNC_STATE 134\n#define APPLE80211_IOC_AWDL_ELECTION_RSSI_THRESHOLDS 135\n#define APPLE80211_IOC_AWDL_PRESENCE_MODE 136\n#define APPLE80211_IOC_AWDL_ELECTION_MASTER_COUNTS 137\n#define APPLE80211_IOC_AWDL_PERIODIC_SYNC_FRAME_PACKET_LIFETIME 138\n#define APPLE80211_IOC_AWDL_MASTER_MODE_SYNC_FRAME_PERIOD 139\n#define APPLE80211_IOC_AWDL_NON_ELECTION_MASTER_MODE_SYNC_FRAME_PERIOD 140\n#define APPLE80211_IOC_AWDL_EXPLICIT_AVAILABILITY_WINDOW_EXTENSION_OPT_OUT 141\n#define APPLE80211_IOC_AWDL_GET_AWDL_MASTER_DATABASE 142\n#define APPLE80211_IOC_PEER_CACHE_CONTROL 143\n#define APPLE80211_IOC_AWDL_BATTERY_LEVEL 144\n#define APPLE80211_IOC_AWDL_BT_COEX_AW_PROTECTED_PERIOD_LENGTH 145\n#define APPLE80211_IOC_AWDL_BT_COEX_AGREEMENT 146\n#define APPLE80211_IOC_AWDL_BT_COEX_AGREEMENT_ENABLED 147\n#define APPLE80211_IOC_AWDL_STRATEGY 148\n#define APPLE80211_IOC_AWDL_OOB_REQUEST 149\n#define APPLE80211_IOC_AWDL_MAX_NO_MASTER_PERIODS 150\n#define APPLE80211_IOC_AWDL_SYNC_FRAME_TEMPLATE 151\n#define APPLE80211_IOC_LOG_FLAGS 152\n#define APPLE80211_IOC_PEER_STATS 153\n#define APPLE80211_IOC_HT_CAPABILITY 154\n#define APPLE80211_IOC_AWDL_ELECTION_PARAMS 155\n#define APPLE80211_IOC_LINK_CHANGED_EVENT_DATA 156\n#define APPLE80211_IOC_GET_DEBUG_INFO 157\n#define APPLE80211_IOC_AWDL_DEVICE_CAPABILITIES 158\n#define APPLE80211_IOC_AWDL_RSSI_MEASUREMENT_REQUEST 159\n#define APPLE80211_IOC_AWDL_AES_KEY 160\n#define APPLE80211_IOC_AWDL_SCAN_RESERVED_TIME 161\n#define APPLE80211_IOC_AWDL_CTL 162\n#define APPLE80211_IOC_AWDL_SOCIAL_TIME_SLOTS 163\n#define APPLE80211_IOC_AWDL_PEER_TRAFFIC_REGISTRATION 164\n#define APPLE80211_IOC_EXTENDED_STATS 165\n#define APPLE80211_IOC_BEACON_PERIOD 166\n#define APPLE80211_IOC_AWDL_FORCED_ROAM_CONFIG 167\n#define APPLE80211_IOC_AWDL_QUIET 168\n#define APPLE80211_IOC_ACL_POLICY 169\n#define APPLE80211_IOC_ACL_ADD 170\n#define APPLE80211_IOC_ACL_REMOVE 171\n#define APPLE80211_IOC_ACL_FLUSH 172\n#define APPLE80211_IOC_ACL_LIST 173\n#define APPLE80211_IOC_CHAIN_ACK 174\n#define APPLE80211_IOC_DESENSE 175\n#define APPLE80211_IOC_OFFLOAD_SCANNING 176\n#define APPLE80211_IOC_OFFLOAD_RSN 177\n#define APPLE80211_IOC_OFFLOAD_COUNTRY_CODE 178\n#define APPLE80211_IOC_OFFLOAD_KEEPALIVE_L2 179\n#define APPLE80211_IOC_OFFLOAD_ARP_NDP 180\n#define APPLE80211_IOC_VHT_MCS_INDEX_SET 181\n#define APPLE80211_IOC_DWDS 182\n#define APPLE80211_IOC_INTERRUPT_STATS 183\n#define APPLE80211_IOC_INTERRUPT_STATS_RESET 184\n#define APPLE80211_IOC_TIMER_STATS 185\n#define APPLE80211_IOC_TIMER_STATS_RESET 186\n#define APPLE80211_IOC_OFFLOAD_STATS 187\n#define APPLE80211_IOC_OFFLOAD_STATS_RESET 188\n#define APPLE80211_IOC_OFFLOAD_BEACONS 189\n#define APPLE80211_IOC_ROAMING 190\n#define APPLE80211_IOC_OFFLOAD_ARP 191\n#define APPLE80211_IOC_OFFLOAD_NDP 192\n#define APPLE80211_IOC_OFFLOAD_SCAN 193\n#define APPLE80211_IOC_DESENSE_LEVEL 194\n#define APPLE80211_IOC_MCS_VHT 195\n#define APPLE80211_IOC_TX_NSS 196\n#define APPLE80211_IOC_GAS_REQ 197\n#define APPLE80211_IOC_GAS_START 198\n#define APPLE80211_IOC_GAS_SET_PEER 199\n#define APPLE80211_IOC_GAS_RESULTS 200\n#define APPLE80211_IOC_AWDL_BTLE_PEER_INDICATION 201\n#define APPLE80211_IOC_AWDL_BTLE_STATE_PARAMS 202\n#define APPLE80211_IOC_AWDL_PEER_DATABASE 203\n#define APPLE80211_IOC_AWDL_BTLE_ENABLE_SYNC_WITH_PARAMS 204\n#define APPLE80211_IOC_AWDL_SECONDARY_MASTER_CHANNEL 205\n#define APPLE80211_IOC_PHY_STATS 206\n#define APPLE80211_IOC_CHANNELS_INFO 207\n#define APPLE80211_IOC_AWDL_AF_TX_MODE 208\n#define APPLE80211_IOC_ERROR_STRING 209\n#define APPLE80211_IOC_ERROR_NO 210\n#define APPLE80211_IOC_AWDL_PIGGYBACK_SCAN_REQ 211\n#define APPLE80211_IOC_AWDL_PRIVATE_ELECTION_ID 212\n#define APPLE80211_IOC_AWDL_MIN_RATE 213\n#define APPLE80211_IOC_VHT_CAPABILITY 214\n#define APPLE80211_IOC_BGSCAN_CACHE_RESULTS 215\n#define APPLE80211_IOC_ROAM_PROFILE 216\n#define APPLE80211_IOC_AWDL_OPER_MODE 217\n#define APPLE80211_IOC_RESTORE_DEFAULTS 218\n#define APPLE80211_IOC_AWDL_ENCRYPTION_KEYS 219\n#define APPLE80211_IOC_AWDL_ENCRYPTION_TYPE 220\n#define APPLE80211_IOC_BTCOEX_PROFILES 221\n#define APPLE80211_IOC_BTCOEX_CONFIG 222\n#define APPLE80211_IOC_AWDL_STATISTICS 223\n#define APPLE80211_IOC_AWDL_ENABLE_ROAMING 224\n#define APPLE80211_IOC_AWDL_OOB_AUTO_REQUEST 225\n#define APPLE80211_IOC_AWDL_TXCAL_PERIOD 226\n#define APPLE80211_IOC_CHIP_COUNTER_STATS 227\n#define APPLE80211_IOC_DBG_GUARD_TIME_PARAMS 228\n#define APPLE80211_IOC_AWDL_AWDL_ADVERTISERS 229\n#define APPLE80211_IOC_LEAKY_AP_STATS_MODE 230\n#define APPLE80211_IOC_CAPTURE 231\n#define APPLE80211_IOC_LEAKY_AP_STATS 232\n#define APPLE80211_IOC_AWDL_BLOCK_SET_COMMANDS 233\n#define APPLE80211_IOC_LEAKY_AP_AWD_MODE 234\n#define APPLE80211_IOC_BTCOEX_OPTIONS 235\n#define APPLE80211_IOC_FORCE_SYNC_TO_PEER 236\n#define APPLE80211_IOC_COUNTRY_CHANNELS 237\n#define APPLE80211_IOC_PRIVATE_MAC 238\n#define APPLE80211_IOC_RESET_CHIP 239\n#define APPLE80211_IOC_CRASH 240\n#define APPLE80211_IOC_RANGING_ENABLE 241\n#define APPLE80211_IOC_RANGING_START 242\n#define APPLE80211_IOC_RANGING_AUTHENTICATE 243\n#define APPLE80211_IOC_AWDL_PREFERRED_CHANNELS 244\n#define APPLE80211_IOC_LEAKY_AP_SSID_STATS 245\n#define APPLE80211_IOC_AWDL_RSDB_CAPS 246\n#define APPLE80211_IOC_AWDL_DEV_STATS 247\n#define APPLE80211_IOC_LAST_ASSOC_HISTORY 248\n#define APPLE80211_IOC_AWDL_COMMON_CHANNEL 249\n#define APPLE80211_IOC_AWDL_PEERS_INFO 250\n#define APPLE80211_IOC_TKO_PARAMS 251\n#define APPLE80211_IOC_TKO_DUMP 252\n#define APPLE80211_IOC_AWDL_NEARBY_LOG_TRIGGER 253\n#define APPLE80211_IOC_HW_SUPPORTED_CHANNELS 254\n#define APPLE80211_IOC_BTCOEX_PROFILE 255\n#define APPLE80211_IOC_BTCOEX_PROFILE_ACTIVE 256\n#define APPLE80211_IOC_TRAP_INFO 257\n#define APPLE80211_IOC_THERMAL_INDEX 258\n#define APPLE80211_IOC_MAX_NSS_FOR_AP 259\n#define APPLE80211_IOC_BTCOEX_2G_CHAIN_DISABLE 260\n#define APPLE80211_IOC_POWER_BUDGET 261\n#define APPLE80211_IOC_AWDL_DFSP_CONFIG 262\n#define APPLE80211_IOC_AWDL_DFSP_UCSA_CONFIG 263\n#define APPLE80211_IOC_SCAN_BACKOFF_REPORT 264\n#define APPLE80211_IOC_OFFLOAD_TCPKA_ENABLE 265\n#define APPLE80211_IOC_RANGING_CAPS 266\n#define APPLE80211_IOC_SUPPRESS_SCANS 267\n#define APPLE80211_IOC_HOST_AP_MODE_HIDDEN 336\n#define APPLE80211_IOC_LQM_CONFIG 337\n#define APPLE80211_IOC_AWDL_CCA 338\n#define APPLE80211_IOC_TRAP_CRASHTRACER_MINI_DUMP 339\n#define APPLE80211_IOC_AWDL_SIDECAR_STATISTICS 340\n#define APPLE80211_IOC_AWDL_CAPABILITIES    341\n#define APPLE80211_IOC_LLW_PARAMS 344\n#define APPLE80211_IOC_HE_CAPABILITY        345\n#define APPLE80211_IOC_SOFTAP_PARAMS        347\n#define APPLE80211_IOC_SOFTAP_TRIGGER_CSA   349\n#define APPLE80211_IOC_SOFTAP_STATS         350\n#define APPLE80211_IOC_AWDL_SIDECAR_DIAGNOSTICS 351\n#define APPLE80211_IOC_SOFTAP_WIFI_NETWORK_INFO_IE  352\n#define APPLE80211_IOC_NSS  353\n\n#define APPLE80211_IOC_CARD_SPECIFIC            0xffffffff    // req_type\n\n// Kernel interface\n\n// Bump this value when structures change\n#define APPLE80211_VERSION    1\n\nstruct apple80211_ssid_data\n{\n    u_int32_t    version;\n    u_int32_t    ssid_len;\n    u_int8_t     ssid_bytes[APPLE80211_MAX_SSID_LEN];\n};\n\nstruct apple80211_virt_if_create_data {\n    uint32_t    version;\n    uint8_t     mac[APPLE80211_ADDR_LEN];\n    uint16_t    unk1;\n    uint32_t    role;\n    uint8_t     bsd_name[IFNAMSIZ];\n} __attribute__((packed));\n\nstruct apple80211_virt_if_delete_data {\n    uint32_t    version;\n    uint8_t     bsd_name[IFNAMSIZ];\n} __attribute__((packed));\n\nstruct apple80211_ht_capability {\n    uint32_t    version;\n    uint8_t     hc_id;              /* element ID */\n    uint8_t     hc_len;             /* length in bytes */\n    uint16_t    hc_cap;             /* HT caps (see below) */\n    uint8_t     hc_param;           /* HT params (see below) */\n    uint8_t     hc_mcsset[16];      /* supported MCS set */\n    uint16_t    hc_extcap;          /* extended HT capabilities */\n    uint32_t    hc_txbf;            /* txbf capabilities */\n    uint8_t     hc_antenna;         /* antenna capabilities */\n} __attribute__((packed));\n\nstruct apple80211_vht_capability {\n    uint32_t    version;\n    uint16_t    cap;        // 4\n    uint32_t    unk1;       // 6\n    uint16_t    unk2;       // 10\n    uint16_t    unk3;       // 12\n    uint16_t    unk4;       // 14\n    uint16_t    unk5;       // 16\n    uint16_t    unk6;       // 18\n} __attribute__((packed));\n\nstruct apple80211_channel_data\n{\n    u_int32_t                    version;\n    struct apple80211_channel    channel;\n};\n\nstruct apple80211_bssid_data\n{\n    u_int32_t            version;\n    struct ether_addr    bssid;\n};\n\n#if __IO80211_TARGET >= __MAC_14_0\nstruct apple80211_capability_data\n{\n    u_int32_t    version;\n    u_int8_t     capabilities[14];\n};\n#else\nstruct apple80211_capability_data\n{\n    u_int32_t    version;\n    u_int8_t     capabilities[11];\n};\n#endif\n\nstruct apple80211_state_data\n{\n    u_int32_t    version;\n    u_int32_t    state;\n};\n\nstruct apple80211_rssi_data\n{\n    u_int32_t    version;\n    u_int32_t    num_radios;\n    u_int32_t    rssi_unit;\n    int32_t      rssi[APPLE80211_MAX_RADIO];        // control channel\n    int32_t      aggregate_rssi;                    // aggregate control channel rssi\n    int32_t      rssi_ext[APPLE80211_MAX_RADIO];    // extension channel rssi\n    int32_t      aggregate_rssi_ext;                // aggregate extension channel rssi\n};\n\nstruct apple80211_power_data\n{\n    u_int32_t    version;\n    u_int32_t    num_radios;\n    u_int32_t    power_state[APPLE80211_MAX_RADIO];\n};\n\nstruct apple80211_assoc_result_data\n{\n    u_int32_t    version;\n    u_int32_t    result;\n};\n\nstruct apple80211_assoc_status_data\n{\n    u_int32_t    version;\n    u_int32_t    status;\n};\n\nstruct apple80211_rate_data\n{\n    u_int32_t    version;\n    u_int32_t    num_radios;\n    u_int32_t    rate[APPLE80211_MAX_RADIO];\n};\n\nstruct apple80211_status_dev_data\n{\n    u_int32_t    version;\n    u_int8_t     dev_name[MAXPATHLEN];\n};\n\nstruct apple80211_powersave_data\n{\n    u_int32_t    version;\n    u_int32_t    powersave_level;\n};\n\nstruct apple80211_protmode_data\n{\n    u_int32_t    version;\n    u_int32_t    protmode;\n    u_int32_t    threshold;        // bytes\n};\n\nstruct apple80211_txpower_data\n{\n    u_int32_t    version;\n    u_int32_t    txpower_unit;\n    int32_t      txpower;\n};\n\nstruct apple80211_phymode_data\n{\n    u_int32_t    version;\n    u_int32_t    phy_mode;            // vector of supported phy modes\n    u_int32_t    active_phy_mode;     // current active phy mode\n};\n\nstruct apple80211_opmode_data\n{\n    u_int32_t    version;\n    u_int32_t    op_mode;\n};\n\nstruct apple80211_noise_data\n{\n    u_int32_t    version;\n    u_int32_t    num_radios;\n    u_int32_t    noise_unit;\n    int32_t      noise[APPLE80211_MAX_RADIO];        // control channel\n    int32_t      aggregate_noise;                    // aggregate control channel noise\n    int32_t      noise_ext[APPLE80211_MAX_RADIO];    // extension channel noise\n    int32_t      aggregate_noise_ext;                // aggregate extension channel noise\n};\n\nstruct apple80211_intmit_data\n{\n    u_int32_t    version;\n    u_int32_t    int_mit;\n};\n\nstruct apple80211_authtype_data\n{\n    u_int32_t    version;\n    u_int32_t    authtype_lower;    //    apple80211_authtype_lower\n    u_int32_t    authtype_upper;    //    apple80211_authtype_upper\n};\n\nstruct apple80211_sup_channel_data\n{\n    u_int32_t                    version;\n    u_int32_t                    num_channels;\n    struct apple80211_channel    supported_channels[APPLE80211_MAX_CHANNELS];\n};\n\n\nstruct apple80211_roam_threshold_data\n{\n    u_int32_t threshold;\n    u_int32_t count;\n};\n\nstruct apple80211_locale_data\n{\n    u_int32_t    version;\n    u_int32_t    locale;\n};\n\nstruct apple80211_scan_data\n{\n    u_int32_t                    version;\n    u_int32_t                    bss_type;                            // apple80211_apmode\n    struct ether_addr            bssid;                               // target BSSID\n    u_int32_t                    ssid_len;                            // length of the SSID\n    u_int8_t                     ssid[APPLE80211_MAX_SSID_LEN];       // direct scan ssid or AirDrop scan ssid like \"Air-xxxx\"\n    u_int32_t                    scan_type;                           // apple80211_scan_type\n    u_int32_t                    phy_mode;                            // apple80211_phymode vector\n    u_int16_t                    dwell_time;                          // time to spend on each channel (ms)\n    u_int32_t                    rest_time;                           // time between scanning each channel (ms)\n    u_int32_t                    num_channels;                        // 0 if not passing in channels\n    struct apple80211_channel    channels[APPLE80211_MAX_CHANNELS];   // channel list\n};\n\nstruct apple80211_scan_multiple_data\n{\n    uint32_t                  version;\n    uint32_t                  ap_mode; // apple80211_apmode\n    uint32_t                  ssid_count;\n    apple80211_ssid_data      ssids[10];\n    uint32_t                  bssid_count;\n    ether_addr                bssids[16];\n    uint32_t                  scan_type;\n    uint32_t                  phy_mode;\n    uint32_t                  dwell_time;\n    uint32_t                  rest_time;\n    uint32_t                  num_channels;\n    struct apple80211_channel channels[APPLE80211_MAX_CHANNELS];\n    uint16_t                  unk_2;\n};\n\nstatic_assert(__offsetof(struct apple80211_scan_multiple_data, bssid_count) == 0x19c, \"zxystd: BSSID offset invalid\");\n\nstruct apple80211_link_changed_event_data\n{\n    bool       isLinkDown; // 0\n    uint32_t   rssi;       // 4\n    uint16_t   snr;        // 8\n    uint16_t   nf;         // 10\n    char       cca;        // 12\n    bool       voluntary;  // 16\n    uint32_t   reason;     // 20\n};\n\nstruct apple80211_apmode_data\n{\n    u_int32_t    version;\n    u_int32_t    apmode;\n};\n\nstruct apple80211_assoc_data\n{\n    u_int32_t                version;\n    u_int16_t                ad_mode;          // apple80211_apmode\n    u_int16_t                ad_auth_lower;    // apple80211_authtype_lower\n    u_int16_t                ad_auth_upper;    // apple80211_authtype_upper\n    u_int32_t                ad_ssid_len;\n    u_int8_t                 ad_ssid[ APPLE80211_MAX_SSID_LEN ];\n    struct ether_addr        ad_bssid;         // prefer over ssid if not zeroed\n    struct apple80211_key    ad_key;\n    uint16_t                 ad_rsn_ie_len;\n    u_int8_t                 ad_rsn_ie[ APPLE80211_MAX_RSN_IE_LEN + 1 ];\n    u_int32_t                ad_flags;         // apple80211_assoc_flags\n};\n\nstatic_assert(offsetof(apple80211_assoc_data, ad_key) == 0x38, \"aaaa\");\n\nstatic_assert(offsetof(apple80211_assoc_data, ad_rsn_ie) == 206, \"offsetof(apple80211_assoc_data, ad_rsn_ie)\");\nstatic_assert(offsetof(apple80211_assoc_data, ad_flags) == 464, \"ad_flags offset error\");\n\nstruct apple80211_deauth_data\n{\n    u_int32_t            version;\n    u_int32_t            deauth_reason;    // reason code\n    struct ether_addr    deauth_ea;        // BSSID of AP\n};\n\nstruct apple80211_countermeasures_data\n{\n    u_int32_t    version;\n    u_int32_t    enabled;\n};\n\nstruct apple80211_frag_threshold_data\n{\n    u_int32_t    version;\n    u_int32_t    threshold;    // bytes\n};\n\nstruct apple80211_rate_set_data\n{\n    u_int32_t                version;\n    u_int16_t                num_rates;\n    struct apple80211_rate   rates[APPLE80211_MAX_RATES];\n};\n\nstruct apple80211_short_slot_data\n{\n    u_int32_t    version;\n    u_int8_t     mode;\n};\n\nstruct apple80211_retry_limit_data\n{\n    u_int32_t    version;\n    u_int32_t    limit;\n};\n\nstruct apple80211_antenna_data\n{\n    u_int32_t    version;\n    u_int32_t    num_radios;\n    int32_t      antenna_index[APPLE80211_MAX_RADIO];\n};\n\nstruct apple80211_dtim_int_data\n{\n    u_int32_t    version;\n    u_int32_t    interval;\n};\n\nstruct apple80211_sta_data\n{\n    u_int32_t                    version;\n    u_int32_t                    num_stations;\n    struct apple80211_station    station_list[APPLE80211_MAX_STATIONS];\n};\n\nstruct apple80211_version_data\n{\n    u_int32_t    version;\n    u_int16_t    string_len;\n    char         string[APPLE80211_MAX_VERSION_LEN];\n};\n\nstruct apple80211_rom_data\n{\n    u_int32_t    version;\n    u_int32_t    rom_len;\n    u_int8_t     rom[1];    // variable length\n};\n\nstruct apple80211_rand_data\n{\n    u_int32_t    version;\n    u_int32_t    rand;\n};\n\nstruct apple80211_rsn_ie_data\n{\n    u_int32_t    version;\n    u_int16_t    len;\n    u_int8_t     ie[ APPLE80211_MAX_RSN_IE_LEN ];\n};\n\nstruct apple80211_ap_ie_data\n{\n    u_int32_t    version;\n    u_int32_t    len;\n#if __IO80211_TARGET < __MAC_13_0\n    u_int8_t     *ie_data;\n#else\n    u_int8_t     ie_data[APPLE80211_NETWORK_DATA_MAX_IE_LEN];\n#endif\n};\n\nstruct apple80211_stats_data\n{\n    u_int32_t    version;\n    u_int32_t    tx_frame_count;\n    u_int32_t    tx_errors;\n    u_int32_t    rx_frame_count;\n    u_int32_t    rx_errors;\n};\n\nstruct apple80211_country_code_data\n{\n    u_int32_t    version;\n    u_int8_t     cc[APPLE80211_MAX_CC_LEN];\n};\n\nstruct apple80211_last_rx_pkt_data\n{\n    u_int32_t         version;\n    u_int32_t         rate;\n    int32_t           rssi;\n    u_int32_t         num_streams;    // number of spatial streams\n    struct ether_addr sa;             // source address\n};\n\nstruct apple80211_radio_info_data\n{\n    u_int32_t    version;\n    u_int32_t    count;        // number of rf chains\n};\n\nstruct apple80211_guard_interval_data\n{\n    u_int32_t    version;\n    u_int32_t    interval;    // apple80211_guard_interval\n};\n\nstruct apple80211_mcs_data\n{\n    u_int32_t    version;\n    u_int32_t    index;        // 0 to APPLE80211_MAX_MCS_INDEX\n};\n\nstruct apple80211_rifs_data\n{\n    u_int32_t    version;\n    u_int32_t    enabled;\n};\n\nstruct apple80211_ldpc_data\n{\n    u_int32_t    version;\n    u_int32_t    enabled;\n};\n\nstruct apple80211_msdu_data\n{\n    u_int32_t    version;\n    u_int32_t    max_length;        // 3839 or 7935 bytes\n};\n\nstruct apple80211_mpdu_data\n{\n    u_int32_t    version;\n    u_int32_t    max_factor;        // 0 - APPLE80211_MAX_MPDU_FACTOR\n    u_int32_t    max_density;       // 0 - APPLE80211_MAX_MPDU_DENSITY\n};\n\nstruct apple80211_block_ack_data\n{\n    u_int32_t   version;\n    u_int8_t    ba_enabled;             // block ack enabled\n    u_int8_t    immediate_ba_enabled;   // immediate block ack enabled\n    u_int8_t    cbba_enabled;           // compressed bitmap block ack enabled\n    u_int8_t    implicit_ba_enabled;    // implicit block ack enabled\n};\n\nstruct apple80211_pls_data\n{\n    u_int32_t    version;\n    u_int32_t    enabled;    // phy level spoofing enabled\n};\n\nstruct apple80211_psmp_data\n{\n    u_int32_t    version;\n    u_int32_t    enabled;\n};\n\nstruct apple80211_physubmode_data\n{\n    u_int32_t    version;\n    u_int32_t    phy_mode;       // one apple80211_phymode\n    u_int32_t    phy_submode;    // one apple80211_physubmode\n    u_int32_t    flags;          // apple80211_channel_flag vector\n};\n\nstruct apple80211_mcs_index_set_data\n{\n    u_int32_t   version;\n    u_int8_t    mcs_set_map[APPLE80211_MAP_SIZE( APPLE80211_MAX_MCS_INDEX + 1 )];\n};\n\nstruct apple80211_vht_mcs_index_set_data\n{\n    u_int32_t   version;\n    u_int16_t    mcs_map;\n} __attribute__((packed));\n\nstruct apple80211_mcs_vht_data \n{\n    u_int32_t   version;\n    u_int32_t   index;\n    u_int32_t   nss;\n    u_int32_t   bw;\n    u_int32_t   guard_interval;\n} __attribute__((packed));\n\nstruct apple80211_wow_parameter_data\n{\n    u_int32_t                     version;\n    u_int8_t                      wake_cond_map[APPLE80211_MAP_SIZE( APPLE80211_MAX_WAKE_COND + 1 )];\n    u_int32_t                     beacon_loss_time;\n    u_int32_t                     pattern_count;\n    struct apple80211_wow_pattern patterns[APPLE80211_MAX_WOW_PATTERNS];\n};\n\nstruct apple80211_40mhz_intolerant_data\n{\n    u_int32_t    version;\n    u_int32_t    enabled;    // bit enabled or not\n};\n\nstruct apple80211_tx_nss_data\n{\n    uint32_t    version;\n    uint8_t     nss;\n};\n\nstruct apple80211_nss_data\n{\n    uint32_t    version;\n    uint8_t     nss;\n};\n\nstruct apple80211_awdl_peer_traffic_registration\n{\n    uint32_t    version;\n    void        *addr;\n    uint32_t    name_len;\n    char        name[152];\n    uint32_t    active;\n} __attribute__((packed));\n\nstruct apple80211_awdl_election_metric\n{\n    uint32_t    version;\n    uint32_t    metric;\n} __attribute__((packed));\n\nstruct apple80211_awdl_sync_enabled\n{\n    uint32_t    version;\n    uint32_t    unk1;\n    uint32_t    enabled;\n} __attribute__((packed));\n\nstruct apple80211_awdl_sync_frame_template\n{\n    uint32_t    version;\n    uint32_t    payload_len;\n    void        *payload;\n} __attribute__((packed));\n\nstruct apple80211_awdl_bssid {\n    uint32_t    version;\n    uint8_t     bssid[APPLE80211_ADDR_LEN];\n    uint8_t     unk_mac[APPLE80211_ADDR_LEN];\n} __attribute__((packed));\n\nstruct apple80211_awdl_channel {\n    uint16_t    chan_spec;\n    uint8_t     chan_num;\n    uint8_t     indoor_restric;\n    uint8_t     radar_dfs;\n    uint8_t     passive;\n    uint8_t     support_40Mhz;\n    uint8_t     support_80Mhz;\n    uint8_t     z;\n    uint32_t    per_chan;\n    uint32_t    chan_bitmap;\n} __attribute__((packed));\n\nstruct apple80211_channels_info {\n    uint32_t    version;\n    uint32_t    unk1;\n    uint16_t    num_chan_specs;\n    uint16_t    chan_spec[APPLE80211_MAX_CHANNELS];\n    uint8_t     chan_num[APPLE80211_MAX_CHANNELS];\n    uint8_t     indoor_restric[APPLE80211_MAX_CHANNELS];\n    uint8_t     radar_dfs[APPLE80211_MAX_CHANNELS];\n    uint8_t     passive[APPLE80211_MAX_CHANNELS];\n    uint8_t     support_40Mhz[APPLE80211_MAX_CHANNELS];\n    uint8_t     support_80Mhz[APPLE80211_MAX_CHANNELS];\n    uint8_t     z[APPLE80211_MAX_CHANNELS];\n    uint8_t     pad[386];\n    uint32_t    per_chan[APPLE80211_MAX_CHANNELS];\n    uint32_t    chan_bitmap[APPLE80211_MAX_CHANNELS];\n} __attribute__((packed));\n\nstatic_assert(__offsetof(struct apple80211_channels_info, chan_num) == 0x10A, \"invalid offset\");   //wf_chspec_ctlchan\nstatic_assert(__offsetof(struct apple80211_channels_info, indoor_restric) == 0x18A, \"invalid offset\"); //wlc_restricted_chanspec\nstatic_assert(__offsetof(struct apple80211_channels_info, radar_dfs) == 0x20A, \"invalid offset\");  //wlc_radar_chanspec\nstatic_assert(__offsetof(struct apple80211_channels_info, passive) == 0x28A, \"invalid offset\");    //wlc_quiet_chanspec\nstatic_assert(__offsetof(struct apple80211_channels_info, support_40Mhz) == 0x30A, \"invalid offset\");\nstatic_assert(__offsetof(struct apple80211_channels_info, support_80Mhz) == 0x38A, \"invalid offset\");\nstatic_assert(__offsetof(struct apple80211_channels_info, per_chan) == 0x60C, \"invalid offset\");\n\nstruct apple80211_peer_cache_maximum_size {\n    uint32_t    version;\n    uint32_t    max_peers;\n} __attribute__((packed));\n\nstruct apple80211_awdl_election_id {\n    uint32_t    version;\n    uint32_t    election_id;\n} __attribute__((packed));\n\nstruct apple80211_awdl_master_channel {\n    uint32_t    version;\n    uint32_t    master_channel;\n} __attribute__((packed));\n\nstruct apple80211_awdl_secondary_master_channel {\n    uint32_t    version;\n    uint32_t    secondary_master_channel;\n} __attribute__((packed));\n\nstruct apple80211_awdl_min_rate {\n    uint32_t    version;\n    uint8_t    min_rate;\n} __attribute__((packed));\n\nstruct apple80211_awdl_election_rssi_thresholds {\n    uint32_t    version;\n    uint32_t    unk1;\n    uint32_t    unk2;\n    uint32_t    unk3;\n} __attribute__((packed));\n\nstruct apple80211_channel_sequence {\n    uint16_t    flags;\n    uint8_t     pad;\n} __attribute__((packed));\n\nstruct apple80211_awdl_sync_channel_sequence {\n    uint32_t    version;\n    uint8_t     pad1;\n    uint8_t     length;             // 5\n    uint8_t     encoding;           // 6\n    uint8_t     step_count;         // 7\n    uint8_t     duplicate_count;    // 8\n    uint8_t     fill_channel;       // 9\n    uint8_t     pad2[6];\n    struct apple80211_channel_sequence seqs[APPLE80211_MAX_CHANNELS];\n} __attribute__((packed));\n\nstatic_assert(__offsetof(apple80211_awdl_sync_channel_sequence, seqs) == 16, \"seqs offset error\");\n\nstatic_assert(sizeof(struct apple80211_awdl_sync_channel_sequence) == 0x190, \"apple80211_awdl_sync_channel_sequence struct corrupt\");\n\nstruct apple80211_awdl_presence_mode {\n    uint32_t    version;\n    uint32_t    mode;\n} __attribute__((packed));\n\nstruct apple80211_awdl_extension_state_machine_parameter {\n    uint32_t    version;\n    uint32_t    unk1;\n    uint32_t    unk2;\n    uint32_t    unk3;\n    uint32_t    unk4;\n} __attribute__((packed));\n\nstruct apple80211_awdl_sync_state {\n    uint32_t    version;\n    uint32_t    state;\n} __attribute__((packed));\n\nstruct apple80211_awdl_sync_params {\n    uint32_t    version;\n    uint32_t    availability_window_length;\n    uint32_t    availability_window_period;\n    uint32_t    extension_length;\n    uint32_t    synchronization_frame_period;\n} __attribute__((packed));\n\nstruct apple80211_awdl_cap {\n    uint32_t    version;\n    uint8_t     cap;\n} __attribute__((packed));\n\nstruct apple80211_awdl_af_tx_mode {\n    uint32_t    version;\n    uint64_t    mode;\n} __attribute__((packed));\n\n#define AWDL_OOB_AF_PARAMS_SIZE 38\n\nstruct apple80211_awdl_oob_request {\n    uint32_t    version;\n    uint32_t    unk1;               // 4\n    uint32_t    unk2;               // 8\n    uint32_t    unk3;               // 12\n    uint32_t    unk4;               // 16\n    uint16_t    pad1;\n    uint32_t    unk5;               // 22\n    uint16_t    unk6;               // 26\n    uint32_t    pad2;\n    uint32_t    unk7;               // 32\n    uint32_t    pad3;\n    uint16_t    data_len;           // 40\n    uint32_t    pad4;\n    uint16_t    unk9;               // 44\n    uint8_t     data[1782];         // 48\n} __attribute__((packed));\n\n//Roam: <airport[565]> DISABLED, 2.4GHz on awdl0 => {\n//    \"ROAM_PROF\" =     (\n//                {\n//            \"ROAM_PROF_BACKOFF_MULTIPLIER\" = 10;\n//            \"ROAM_PROF_FULLSCAN_PERIOD\" = 3000;\n//            \"ROAM_PROF_INIT_SCAN_PERIOD\" = 600;\n//            \"ROAM_PROF_MAX_SCAN_PERIOD\" = 60000;\n//            \"ROAM_PROF_NFSCAN\" = 1;\n//            \"ROAM_PROF_ROAM_DELTA\" = 50;\n//            \"ROAM_PROF_ROAM_FLAGS\" = 0;\n//            \"ROAM_PROF_ROAM_TRIGGER\" = \"-120\";\n//            \"ROAM_PROF_RSSI_BOOST_DELTA\" = 55;\n//            \"ROAM_PROF_RSSI_BOOST_THRESH\" = \"-68\";\n//            \"ROAM_PROF_RSSI_LOWER\" = \"-128\";\n//        }\n//    );\n//    \"ROAM_PROF_BAND\" = 4;\n//    \"ROAM_PROF_NUM\" = 1;\n//}\n//Roam: <airport[565]> SINGLE-BAND, SINGLE-AP, 2.4GHz on awdl0 => {\n//    \"ROAM_PROF\" =     (\n//                {\n//            \"ROAM_PROF_BACKOFF_MULTIPLIER\" = 2;\n//            \"ROAM_PROF_FULLSCAN_PERIOD\" = 3600;\n//            \"ROAM_PROF_INIT_SCAN_PERIOD\" = 60;\n//            \"ROAM_PROF_MAX_SCAN_PERIOD\" = 1200;\n//            \"ROAM_PROF_NFSCAN\" = 1;\n//            \"ROAM_PROF_ROAM_DELTA\" = 12;\n//            \"ROAM_PROF_ROAM_FLAGS\" = 0;\n//            \"ROAM_PROF_ROAM_TRIGGER\" = \"-80\";\n//            \"ROAM_PROF_RSSI_BOOST_DELTA\" = 55;\n//            \"ROAM_PROF_RSSI_BOOST_THRESH\" = \"-68\";\n//            \"ROAM_PROF_RSSI_LOWER\" = \"-128\";\n//        }\n//    );\n//    \"ROAM_PROF_BAND\" = 4;\n//    \"ROAM_PROF_NUM\" = 1;\n//}\n//Roam: <airport[565]> DUAL-BAND, SINGLE-AP, 2.4GHz on awdl0 => {\n//    \"ROAM_PROF\" =     (\n//                {\n//            \"ROAM_PROF_BACKOFF_MULTIPLIER\" = 2;\n//            \"ROAM_PROF_FULLSCAN_PERIOD\" = 300;\n//            \"ROAM_PROF_INIT_SCAN_PERIOD\" = 180;\n//            \"ROAM_PROF_MAX_SCAN_PERIOD\" = 180;\n//            \"ROAM_PROF_NFSCAN\" = 2;\n//            \"ROAM_PROF_ROAM_DELTA\" = 16;\n//            \"ROAM_PROF_ROAM_FLAGS\" = 1;\n//            \"ROAM_PROF_ROAM_TRIGGER\" = \"-10\";\n//            \"ROAM_PROF_RSSI_BOOST_DELTA\" = 55;\n//            \"ROAM_PROF_RSSI_BOOST_THRESH\" = \"-68\";\n//            \"ROAM_PROF_RSSI_LOWER\" = \"-75\";\n//        },\n//                {\n//            \"ROAM_PROF_BACKOFF_MULTIPLIER\" = 2;\n//            \"ROAM_PROF_FULLSCAN_PERIOD\" = 120;\n//            \"ROAM_PROF_INIT_SCAN_PERIOD\" = 20;\n//            \"ROAM_PROF_MAX_SCAN_PERIOD\" = 90;\n//            \"ROAM_PROF_NFSCAN\" = 2;\n//            \"ROAM_PROF_ROAM_DELTA\" = 12;\n//            \"ROAM_PROF_ROAM_FLAGS\" = 0;\n//            \"ROAM_PROF_ROAM_TRIGGER\" = \"-75\";\n//            \"ROAM_PROF_RSSI_BOOST_DELTA\" = 55;\n//            \"ROAM_PROF_RSSI_BOOST_THRESH\" = \"-68\";\n//            \"ROAM_PROF_RSSI_LOWER\" = \"-128\";\n//        }\n//    );\n//    \"ROAM_PROF_BAND\" = 4;\n//    \"ROAM_PROF_NUM\" = 2;\n//}\n//Roam: <airport[565]> MULTI-AP, 2.4GHz on awdl0 => {\n//    \"ROAM_PROF\" =     (\n//                {\n//            \"ROAM_PROF_BACKOFF_MULTIPLIER\" = 2;\n//            \"ROAM_PROF_FULLSCAN_PERIOD\" = 1200;\n//            \"ROAM_PROF_INIT_SCAN_PERIOD\" = 180;\n//            \"ROAM_PROF_MAX_SCAN_PERIOD\" = 600;\n//            \"ROAM_PROF_NFSCAN\" = 2;\n//            \"ROAM_PROF_ROAM_DELTA\" = 20;\n//            \"ROAM_PROF_ROAM_FLAGS\" = 1;\n//            \"ROAM_PROF_ROAM_TRIGGER\" = \"-10\";\n//            \"ROAM_PROF_RSSI_BOOST_DELTA\" = 55;\n//            \"ROAM_PROF_RSSI_BOOST_THRESH\" = \"-68\";\n//            \"ROAM_PROF_RSSI_LOWER\" = \"-50\";\n//        },\n//                {\n//            \"ROAM_PROF_BACKOFF_MULTIPLIER\" = 2;\n//            \"ROAM_PROF_FULLSCAN_PERIOD\" = 600;\n//            \"ROAM_PROF_INIT_SCAN_PERIOD\" = 180;\n//            \"ROAM_PROF_MAX_SCAN_PERIOD\" = 180;\n//            \"ROAM_PROF_NFSCAN\" = 2;\n//            \"ROAM_PROF_ROAM_DELTA\" = 16;\n//            \"ROAM_PROF_ROAM_FLAGS\" = 1;\n//            \"ROAM_PROF_ROAM_TRIGGER\" = \"-50\";\n//            \"ROAM_PROF_RSSI_BOOST_DELTA\" = 55;\n//            \"ROAM_PROF_RSSI_BOOST_THRESH\" = \"-68\";\n//            \"ROAM_PROF_RSSI_LOWER\" = \"-75\";\n//        },\n//                {\n//            \"ROAM_PROF_BACKOFF_MULTIPLIER\" = 1;\n//            \"ROAM_PROF_FULLSCAN_PERIOD\" = 120;\n//            \"ROAM_PROF_INIT_SCAN_PERIOD\" = 20;\n//            \"ROAM_PROF_MAX_SCAN_PERIOD\" = 90;\n//            \"ROAM_PROF_NFSCAN\" = 2;\n//            \"ROAM_PROF_ROAM_DELTA\" = 12;\n//            \"ROAM_PROF_ROAM_FLAGS\" = 0;\n//            \"ROAM_PROF_ROAM_TRIGGER\" = \"-75\";\n//            \"ROAM_PROF_RSSI_BOOST_DELTA\" = 55;\n//            \"ROAM_PROF_RSSI_BOOST_THRESH\" = \"-68\";\n//            \"ROAM_PROF_RSSI_LOWER\" = \"-128\";\n//        }\n//    );\n//    \"ROAM_PROF_BAND\" = 4;\n//    \"ROAM_PROF_NUM\" = 3;\n//}\n//Roam: <airport[565]> AC POWER, 2.4GHz on awdl0 => {\n//    \"ROAM_PROF\" =     (\n//                {\n//            \"ROAM_PROF_BACKOFF_MULTIPLIER\" = 2;\n//            \"ROAM_PROF_FULLSCAN_PERIOD\" = 120;\n//            \"ROAM_PROF_INIT_SCAN_PERIOD\" = 20;\n//            \"ROAM_PROF_MAX_SCAN_PERIOD\" = 90;\n//            \"ROAM_PROF_NFSCAN\" = 2;\n//            \"ROAM_PROF_ROAM_DELTA\" = 16;\n//            \"ROAM_PROF_ROAM_FLAGS\" = 1;\n//            \"ROAM_PROF_ROAM_TRIGGER\" = \"-10\";\n//            \"ROAM_PROF_RSSI_BOOST_DELTA\" = 55;\n//            \"ROAM_PROF_RSSI_BOOST_THRESH\" = \"-68\";\n//            \"ROAM_PROF_RSSI_LOWER\" = \"-75\";\n//        },\n//                {\n//            \"ROAM_PROF_BACKOFF_MULTIPLIER\" = 2;\n//            \"ROAM_PROF_FULLSCAN_PERIOD\" = 120;\n//            \"ROAM_PROF_INIT_SCAN_PERIOD\" = 20;\n//            \"ROAM_PROF_MAX_SCAN_PERIOD\" = 90;\n//            \"ROAM_PROF_NFSCAN\" = 2;\n//            \"ROAM_PROF_ROAM_DELTA\" = 12;\n//            \"ROAM_PROF_ROAM_FLAGS\" = 0;\n//            \"ROAM_PROF_ROAM_TRIGGER\" = \"-75\";\n//            \"ROAM_PROF_RSSI_BOOST_DELTA\" = 55;\n//            \"ROAM_PROF_RSSI_BOOST_THRESH\" = \"-68\";\n//            \"ROAM_PROF_RSSI_LOWER\" = \"-128\";\n//        }\n//    );\n//    \"ROAM_PROF_BAND\" = 4;\n//    \"ROAM_PROF_NUM\" = 2;\n//}\n//Roam: <airport[565]> DISABLED, 5GHz on awdl0 => {\n//    \"ROAM_PROF\" =     (\n//                {\n//            \"ROAM_PROF_BACKOFF_MULTIPLIER\" = 10;\n//            \"ROAM_PROF_FULLSCAN_PERIOD\" = 3000;\n//            \"ROAM_PROF_INIT_SCAN_PERIOD\" = 600;\n//            \"ROAM_PROF_MAX_SCAN_PERIOD\" = 60000;\n//            \"ROAM_PROF_NFSCAN\" = 1;\n//            \"ROAM_PROF_ROAM_DELTA\" = 50;\n//            \"ROAM_PROF_ROAM_FLAGS\" = 0;\n//            \"ROAM_PROF_ROAM_TRIGGER\" = \"-120\";\n//            \"ROAM_PROF_RSSI_BOOST_DELTA\" = 0;\n//            \"ROAM_PROF_RSSI_BOOST_THRESH\" = 0;\n//            \"ROAM_PROF_RSSI_LOWER\" = \"-128\";\n//        }\n//    );\n//    \"ROAM_PROF_BAND\" = 2;\n//    \"ROAM_PROF_NUM\" = 1;\n//}\n//Roam: <airport[565]> SINGLE-BAND, SINGLE-AP, 5GHz on awdl0 => {\n//    \"ROAM_PROF\" =     (\n//                {\n//            \"ROAM_PROF_BACKOFF_MULTIPLIER\" = 2;\n//            \"ROAM_PROF_FULLSCAN_PERIOD\" = 3600;\n//            \"ROAM_PROF_INIT_SCAN_PERIOD\" = 60;\n//            \"ROAM_PROF_MAX_SCAN_PERIOD\" = 1200;\n//            \"ROAM_PROF_NFSCAN\" = 1;\n//            \"ROAM_PROF_ROAM_DELTA\" = 12;\n//            \"ROAM_PROF_ROAM_FLAGS\" = 0;\n//            \"ROAM_PROF_ROAM_TRIGGER\" = \"-80\";\n//            \"ROAM_PROF_RSSI_BOOST_DELTA\" = 0;\n//            \"ROAM_PROF_RSSI_BOOST_THRESH\" = 0;\n//            \"ROAM_PROF_RSSI_LOWER\" = \"-128\";\n//        }\n//    );\n//    \"ROAM_PROF_BAND\" = 2;\n//    \"ROAM_PROF_NUM\" = 1;\n//}\n//Roam: <airport[565]> DUAL-BAND, SINGLE-AP, 5GHz on awdl0 => {\n//    \"ROAM_PROF\" =     (\n//                {\n//            \"ROAM_PROF_BACKOFF_MULTIPLIER\" = 2;\n//            \"ROAM_PROF_FULLSCAN_PERIOD\" = 120;\n//            \"ROAM_PROF_INIT_SCAN_PERIOD\" = 20;\n//            \"ROAM_PROF_MAX_SCAN_PERIOD\" = 90;\n//            \"ROAM_PROF_NFSCAN\" = 2;\n//            \"ROAM_PROF_ROAM_DELTA\" = 12;\n//            \"ROAM_PROF_ROAM_FLAGS\" = 0;\n//            \"ROAM_PROF_ROAM_TRIGGER\" = \"-75\";\n//            \"ROAM_PROF_RSSI_BOOST_DELTA\" = 0;\n//            \"ROAM_PROF_RSSI_BOOST_THRESH\" = 0;\n//            \"ROAM_PROF_RSSI_LOWER\" = \"-128\";\n//        }\n//    );\n//    \"ROAM_PROF_BAND\" = 2;\n//    \"ROAM_PROF_NUM\" = 1;\n//}\n//Roam: <airport[565]> MULTI-AP, 5GHz on awdl0 => {\n//    \"ROAM_PROF\" =     (\n//                {\n//            \"ROAM_PROF_BACKOFF_MULTIPLIER\" = 2;\n//            \"ROAM_PROF_FULLSCAN_PERIOD\" = 120;\n//            \"ROAM_PROF_INIT_SCAN_PERIOD\" = 20;\n//            \"ROAM_PROF_MAX_SCAN_PERIOD\" = 90;\n//            \"ROAM_PROF_NFSCAN\" = 2;\n//            \"ROAM_PROF_ROAM_DELTA\" = 12;\n//            \"ROAM_PROF_ROAM_FLAGS\" = 0;\n//            \"ROAM_PROF_ROAM_TRIGGER\" = \"-75\";\n//            \"ROAM_PROF_RSSI_BOOST_DELTA\" = 0;\n//            \"ROAM_PROF_RSSI_BOOST_THRESH\" = 0;\n//            \"ROAM_PROF_RSSI_LOWER\" = \"-128\";\n//        }\n//    );\n//    \"ROAM_PROF_BAND\" = 2;\n//    \"ROAM_PROF_NUM\" = 1;\n//}\n//Roam: <airport[565]> AC POWER, 5GHz on awdl0 => {\n//    \"ROAM_PROF\" =     (\n//                {\n//            \"ROAM_PROF_BACKOFF_MULTIPLIER\" = 2;\n//            \"ROAM_PROF_FULLSCAN_PERIOD\" = 120;\n//            \"ROAM_PROF_INIT_SCAN_PERIOD\" = 20;\n//            \"ROAM_PROF_MAX_SCAN_PERIOD\" = 90;\n//            \"ROAM_PROF_NFSCAN\" = 2;\n//            \"ROAM_PROF_ROAM_DELTA\" = 12;\n//            \"ROAM_PROF_ROAM_FLAGS\" = 0;\n//            \"ROAM_PROF_ROAM_TRIGGER\" = \"-75\";\n//            \"ROAM_PROF_RSSI_BOOST_DELTA\" = 0;\n//            \"ROAM_PROF_RSSI_BOOST_THRESH\" = 0;\n//            \"ROAM_PROF_RSSI_LOWER\" = \"-128\";\n//        }\n//    );\n//    \"ROAM_PROF_BAND\" = 2;\n//    \"ROAM_PROF_NUM\" = 1;\n//}\n\nstruct apple80211_roam_profile {\n    int8_t      flags;\n    int8_t      trigger;\n    int8_t      rssi_lower;\n    int8_t      rssi_boost_delta;\n    int8_t      rssi_boost_thresh;\n    int8_t      delta;\n    uint16_t    backoff_multiplier;\n    uint16_t    full_scan_period;\n    uint16_t    init_scan_period;\n    uint16_t    nfscan;\n    uint16_t    max_scan_period;\n} __attribute__((packed));\n\nstruct apple80211_roam_profile_band_data {\n    uint32_t    version;\n    uint32_t    flags;          // 4 (0x2, 0x4)\n    uint32_t    profile_cnt;    // 8\n    struct apple80211_roam_profile profiles[4];\n} __attribute__((packed));\n\nstatic_assert(sizeof(struct apple80211_roam_profile_band_data) == 76, \"roam data size error\");\n\nstruct apple80211_ie_data {\n    uint32_t    version;\n    uint32_t    frame_type_flags;   // 4\n    uint32_t    add;                // 8\n    uint32_t    signature_len;      // 12\n    uint32_t    ie_len;             // 16\n    uint32_t    pad1;               // 20\n    uint8_t     ie[2048];\n} __attribute__((packed));\n\nstruct apple80211_p2p_listen_data {\n    uint32_t    version;\n    uint32_t    pad1;\n    uint32_t    channel;        // 8\n    uint32_t    flags;          // 12\n    uint32_t    duration;       // 16\n} __attribute__((packed));\n\nstruct apple80211_p2p_go_conf_data {\n    uint32_t    version;\n    uint32_t    auth_upper;     // 4 should equal to 1\n    uint32_t    auth_lower;     // 6 should non zero\n    void        *dynbcn;        // 8\n    uint32_t    channel;        // 12\n    uint32_t    bcn_len;        // 16\n    uint32_t    ssid_len;       // 20\n    uint8_t     ssid[32];       // 24\n    uint32_t    suppress_beacon;// 56 security:1,4\n} __attribute__((packed));\n\nstruct apple80211_sta_roam_data {\n    uint32_t    version;\n    uint8_t     rcc_channels;\n    uint8_t     unk1;\n    uint8_t     taget_channel;\n    uint8_t     target_bssid[APPLE80211_ADDR_LEN];\n} __attribute__((packed));\n\nstruct apple80211_btc_profiles_data {\n    uint32_t    version;\n    uint32_t    profile_cnt;\n    uint8_t     profiles[141][4];\n} __attribute__((packed));\n\nstruct apple80211_btc_config_data {\n    uint32_t version;\n    uint32_t enable_2G;\n    uint32_t profile_2g;\n    uint32_t enable_5G;\n    uint32_t profile_5G;\n} __attribute__((packed));\n\nstruct apple80211_btc_mode_data {\n    uint32_t    version;\n    uint32_t    btc_mode;\n} __attribute__((packed));\n\nstruct apple80211_btc_options_data {\n    uint32_t    version;\n    uint32_t    btc_options;\n} __attribute__((packed));\n\nstruct apple80211_driver_available_data {\n    uint64_t event;\n    uint64_t avaliable;\n    uint32_t reason;\n    uint32_t sub_reason;\n    char pad[160];\n} __attribute__((packed));\n\nstatic_assert(sizeof(struct apple80211_driver_available_data) == 0xB8, \"invalid struct apple80211_driver_available_data\");\n\n#endif // _APPLE80211_IOCTL_H_\n\n"
  },
  {
    "path": "include/Airport/apple80211_var.h",
    "content": "/*\n * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.\n *\n * @APPLE_LICENSE_HEADER_START@\n *\n * The contents of this file constitute Original Code as defined in and\n * are subject to the Apple Public Source License Version 1.1 (the\n * \"License\").  You may not use this file except in compliance with the\n * License.  Please obtain a copy of the License at\n * http://www.apple.com/publicsource and read it before using this file.\n *\n * This Original Code and all software distributed under the License are\n * distributed on an \"AS IS\" basis, WITHOUT WARRANTY OF ANY KIND, EITHER\n * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,\n * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the\n * License for the specific language governing rights and limitations\n * under the License.\n *\n * @APPLE_LICENSE_HEADER_END@\n */\n\n#ifndef _APPLE80211_VAR_H_\n#define _APPLE80211_VAR_H_\n\n#include <Availability.h>\n#include <sys/types.h>\n#include <net/ethernet.h>\n#include <sys/param.h>\n\n// This is necessary, because even the latest Xcode does not support properly targeting 11.0.\n#ifndef __IO80211_TARGET\n#error \"Please define __IO80211_TARGET to the requested version\"\n#endif\n\n// Sizes and limits\n#define APPLE80211_ADDR_LEN            6\n#define APPLE80211_MAX_RATES           15\n#define APPLE80211_MAX_SSID_LEN        32\n#define APPLE80211_MAX_ANTENNAE        4\n#define APPLE80211_MAX_RADIO           4\n#define APPLE80211_MAX_CHANNELS        128\n#define APPLE80211_MAX_STATIONS        128\n#define APPLE80211_MAX_VERSION_LEN     256\n#define APPLE80211_MAX_ROM_SIZE        32768    // 32 KB\n#define APPLE80211_MAX_RSN_IE_LEN      257      // 255 + type and length bytes\n#define APPLE80211_MAX_CC_LEN          3\n#define APPLE80211_MAX_MCS_INDEX       76\n#define APPLE80211_MAX_MPDU_FACTOR     3\n#define APPLE80211_MAX_MPDU_DENSITY    7\n#define APPLE80211_MAX_WOW_PAT_LEN     1500    // Max wake on wireless pattern length\n#define APPLE80211_MAX_WOW_PATTERNS    12      // Arbitrary..this can change\n\n#define APPLE80211_MAP_SIZE( _bits ) (roundup( _bits, NBBY )/NBBY)\n\nenum apple80211_phymode {\n    APPLE80211_MODE_UNKNOWN            = 0,\n    APPLE80211_MODE_AUTO            = 0x1,                  // autoselect\n    APPLE80211_MODE_11A                = 2 << (1 - 1),      // 5GHz, OFDM\n    APPLE80211_MODE_11B                = 2 << (2 - 1),      // 2GHz, CCK\n    APPLE80211_MODE_11G                = 2 << (3 - 1),      // 2GHz, OFDM\n    APPLE80211_MODE_11N                = 2 << (4 - 1),      // 2GHz/5GHz, OFDM\n    APPLE80211_MODE_TURBO_A            = 2 << (5 - 1),      // 5GHz, OFDM, 2x clock\n    APPLE80211_MODE_TURBO_G            = 2 << (6 - 1),      // 2GHz, OFDM, 2x clock\n    APPLE80211_MODE_11AC               = 2 << (7 - 1),\n    APPLE80211_MODE_11AX               = 2 << (8 - 1),\n};\n\nenum apple80211_physubmode {\n    APPLE80211_SUBMODE_UNKNOWN           = 0x0,\n    APPLE80211_SUBMODE_11N_AUTO          = 0x1,    // 11n mode determined by AP capabilities\n    APPLE80211_SUBMODE_11N_LEGACY        = 0x2,    // legacy\n    APPLE80211_SUBMODE_11N_LEGACY_DUP    = 0x4,    // legacy duplicate\n    APPLE80211_SUBMODE_11N_HT            = 0x8,    // high throughput\n    APPLE80211_SUBMODE_11N_HT_DUP        = 0x10,   // high throughput duplicate\n    APPLE80211_SUBMODE_11N_GF            = 0x20,   // green field\n};\n\n// flags\nenum apple80211_opmode {\n    APPLE80211_M_NONE     = 0x0,\n    APPLE80211_M_STA      = 0x1,        // infrastructure station\n    APPLE80211_M_IBSS     = 0x2,        // IBSS (adhoc) station\n    APPLE80211_M_AHDEMO   = 0x4,        // Old lucent compatible adhoc demo\n    APPLE80211_M_HOSTAP   = 0x8,        // Software Access Point\n    APPLE80211_M_MONITOR  = 0x10        // Monitor mode\n};\n\nenum apple80211_apmode    {\n    APPLE80211_AP_MODE_UNKNOWN    = 0,\n    APPLE80211_AP_MODE_IBSS       = 1,        // IBSS (adhoc) station\n    APPLE80211_AP_MODE_INFRA      = 2,        // Access Point\n    APPLE80211_AP_MODE_ANY        = 3,        // Any supported mode\n};\n\nenum apple80211_state {\n    APPLE80211_S_INIT    = 0,            // default state\n    APPLE80211_S_SCAN    = 1,            // scanning\n    APPLE80211_S_AUTH    = 2,            // try to authenticate\n    APPLE80211_S_ASSOC   = 3,            // try to assoc\n    APPLE80211_S_RUN     = 4,            // associated\n};\n\nenum apple80211_protmode {\n    APPLE80211_PROTMODE_OFF            = 0,    // no protection\n    APPLE80211_PROTMODE_AUTO           = 1,    // auto\n    APPLE80211_PROTMODE_CTS            = 2,    // CTS to self\n    APPLE80211_PROTMODE_RTSCTS         = 3,    // RTS-CTS\n    APPLE80211_PROTMODE_DUAL_CTS       = 4,    // dual CTS\n};\n\nenum apple80211_cipher_type {\n    APPLE80211_CIPHER_NONE        = 0,        // open network\n    APPLE80211_CIPHER_WEP_40      = 1,        // 40 bit WEP\n    APPLE80211_CIPHER_WEP_104     = 2,        // 104 bit WEP\n    APPLE80211_CIPHER_TKIP        = 3,        // TKIP (WPA)\n    APPLE80211_CIPHER_AES_OCB     = 4,        // AES (OCB)\n    APPLE80211_CIPHER_AES_CCM     = 5,        // AES (CCM)\n    APPLE80211_CIPHER_PMK         = 6,        // PMK\n    APPLE80211_CIPHER_PMKSA       = 7,        // PMK obtained from pre-authentication\n    APPLE80211_CIPHER_SMS4        = 8,\n    APPLE80211_CIPHER_MSK         = 9,\n    APPLE80211_CIPHER_PWD         = 10,\n    APPLE80211_CIPHER_AES_GCM     = 11,\n    APPLE80211_CIPHER_AES_GCM256  = 12,\n};\n\nenum apple80211_cipher_key_type\n{\n    APPLE80211_CIPHER_KEY_TYPE_UNICAST   = 0,   // unicast cipher key\n    APPLE80211_CIPHER_KEY_TYPE_MULTICAST = 1    // multicast cipher key\n};\n\n// Low level 802.11 authentication types\n\nenum apple80211_authtype_lower\n{\n    APPLE80211_AUTHTYPE_OPEN          = 1,    // open\n    APPLE80211_AUTHTYPE_SHARED        = 2,    // shared key\n    APPLE80211_AUTHTYPE_CISCO         = 3,    // cisco net eap\n};\n\n// Higher level authentication used after 802.11 association complete\n\nenum apple80211_authtype_upper\n{\n    APPLE80211_AUTHTYPE_NONE         = 0,         //    No upper auth\n    APPLE80211_AUTHTYPE_WPA          = 1 << 0,    //    WPA\n    APPLE80211_AUTHTYPE_WPA_PSK      = 1 << 1,    //    WPA PSK\n    APPLE80211_AUTHTYPE_WPA2         = 1 << 2,    //    WPA2\n    APPLE80211_AUTHTYPE_WPA2_PSK     = 1 << 3,    //    WPA2 PSK\n    APPLE80211_AUTHTYPE_FT_PSK       = 1 << 4,    //\n    APPLE80211_AUTHTYPE_LEAP         = 1 << 5,    //    LEAP\n    APPLE80211_AUTHTYPE_WEP_8021X    = 1 << 6,    //    WEP 802.1x\n    APPLE80211_AUTHTYPE_FT_8021X     = 1 << 7,    //    802.1x\n    APPLE80211_AUTHTYPE_WPS          = 1 << 8,    //    WiFi Protected Setup\n    APPLE80211_AUTHTYPE_WAPI         = 1 << 9,\n    APPLE80211_AUTHTYPE_SHA256_PSK   = 1 << 10,\n    APPLE80211_AUTHTYPE_SHA256_8021X = 1 << 11,\n    APPLE80211_AUTHTYPE_WPA3_SAE     = 1 << 12,\n    APPLE80211_AUTHTYPE_WPA3_FT_SAE  = 1 << 13,\n    APPLE80211_AUTHTYPE_WPA3_ENTERPRISE = 1 << 14,\n    APPLE80211_AUTHTYPE_WPA3_FT_ENTERPRISE = 1 << 15,\n};\n\n// Unify association status code and deauth reason codes into a single enum describing\n// common error conditions\nenum apple80211_associate_result\n{\n    APPLE80211_RESULT_UNAVAILABLE                = 0,  // No association/authentication result ready\n    APPLE80211_RESULT_SUCCESS                    = 1,  // APPLE80211_STATUS_SUCCESS and no deauth\n    APPLE80211_RESULT_UNSPECIFIED_FAILURE        = 2,  // APPLE80211_STATUS_UNSPECIFIED_FAILURE\n    APPLE80211_RESULT_UNSUPPORTED_CAPAPBILITIES  = 3,  // APPLE80211_STATUS_UNSUPPORTED_CAPABILITIES\n    APPLE80211_RESULT_REASSOCIATION_DENIED       = 4,  // APPLE80211_STATUS_REASSOCIATION_DENIED\n    APPLE80211_RESULT_ASSOCIATION_DENIED         = 5,  // APPLE80211_STATUS_ASSOCIATION_DENIED\n    APPLE80211_RESULT_AUTH_ALG_UNSUPPORTED       = 6,  // APPLE80211_STATUS_AUTH_ALG_UNSUPPORTED\n    APPLE80211_RESULT_INVALID_AUTH_SEQ_NUM       = 7,  // APPLE80211_STATUS_INVALID_AUTH_SEQ_NUM\n    APPLE80211_RESULT_CHALLENGE_FAILURE          = 8,  // APPLE80211_STATUS_CHALLENGE_FAILURE\n    APPLE80211_RESULT_TIMEOUT                    = 9,  // APPLE80211_STATUS_TIMEOUT\n    APPLE80211_RESULT_AP_FULL                    = 10, // APPLE80211_STATUS_AP_FULL\n    APPLE80211_RESULT_UNSUPPORTED_RATE_SET       = 11, // APPLE80211_STATUS_UNSUPPORTED_RATE_SET\n    APPLE80211_RESULT_SHORT_SLOT_UNSUPPORTED     = 12, // APPLE80211_STATUS_SHORT_SLOT_UNSUPPORTED\n    APPLE80211_RESULT_DSSS_OFDM_UNSUPPORTED      = 13, // APPLE80211_STATUS_DSSS_OFDM_UNSUPPORTED\n    APPLE80211_RESULT_INVALID_IE                 = 14, // APPLE80211_STATUS_INVALID_IE\n    APPLE80211_RESULT_INVALID_GROUP_CIPHER       = 15, // APPLE80211_STATUS_INVALID_GROUP_CIPHER\n    APPLE80211_RESULT_INVALID_PAIRWISE_CIPHER    = 16, // APPLE80211_STATUS_INVALID_PAIRWISE_CIPHER\n    APPLE80211_RESULT_INVALID_AKMP               = 17, // APPLE80211_STATUS_INVALID_AKMP\n    APPLE80211_RESULT_UNSUPPORTED_RSN_VERSION    = 18, // APPLE80211_STATUS_UNSUPPORTED_RSN_VERSION\n    APPLE80211_RESULT_INVALID_RSN_CAPABILITIES   = 19, // APPLE80211_STATUS_INVALID_RSN_CAPABILITIES\n    APPLE80211_RESULT_CIPHER_SUITE_REJECTED      = 20, // APPLE80211_STATUS_CIPHER_SUIT_REJECTED\n    APPLE80211_RESULT_INVALID_PMK                = 21, // APPLE80211_REASON_PREV_AUTH_EXPIRED received\n    APPLE80211_RESULT_SUPPLICANT_TIMEOUT         = 22, // RSNSupplicant did not finish handshake\n    APPLE80211_RESULT_UNKNOWN                    = 0xffff // Unrecognized error condition\n};\n\nenum apple80211_link_down_reason\n{\n   APPLE80211_LINK_DOWN_REASON_INTERNAL_ERROR   = 0,\n   APPLE80211_LINK_DOWN_REASON_BEACONLOST       = 1,\n   APPLE80211_LINK_DOWN_REASON_DEAUTH           = 2,\n   APPLE80211_LINK_DOWN_REASON_INTERNAL_ERROR_2 = 3\n};\n\nenum apple80211_unit\n{\n    APPLE80211_UNIT_DBM        = 0,        // dBm\n    APPLE80211_UNIT_MW         = 1,        // milliwatts\n    APPLE80211_UNIT_PERCENT    = 2,        // value expressed as a percentage\n};\n\nenum apple80211_power_state\n{\n    APPLE80211_POWER_OFF       = 0,    //    Chain disabled\n    APPLE80211_POWER_ON        = 1,    //    Chain powered on for tx and rx\n    APPLE80211_POWER_TX        = 2,    //    Chain powered on for tx only\n    APPLE80211_POWER_RX        = 3,    //    Chain powered on for rx only\n};\n\nenum apple80211_locale\n{\n    APPLE80211_LOCALE_UNKNOWN    = 0,\n    APPLE80211_LOCALE_FCC        = 1,\n    APPLE80211_LOCALE_ETSI       = 2,\n    APPLE80211_LOCALE_JAPAN      = 3,\n    APPLE80211_LOCALE_KOREA      = 4,\n    APPLE80211_LOCALE_APAC       = 5,\n    APPLE80211_LOCALE_ROW        = 6,\n    APPLE80211_LOCALE_INDONESIA  = 7\n};\n\nenum apple80211_scan_type\n{\n    APPLE80211_SCAN_TYPE_NONE       = 0,\n    APPLE80211_SCAN_TYPE_ACTIVE     = 1,\n    APPLE80211_SCAN_TYPE_PASSIVE    = 2,\n    APPLE80211_SCAN_TYPE_FAST       = 3,    // Ok to return cached scan results\n    APPLE80211_SCAN_TYPE_BACKGROUND = 4,    // Initiate background scanning\n};\n\nenum apple80211_int_mit {\n    APPLE80211_INT_MIT_OFF    = 0,\n    APPLE80211_INT_MIT_AUTO   = 1,\n};\n\nenum apple80211_channel_flag\n{\n    APPLE80211_C_FLAG_NONE         = 0x0,   // no flags\n    APPLE80211_C_FLAG_10MHZ        = 0x1,   // 10 MHz wide\n    APPLE80211_C_FLAG_20MHZ        = 0x2,   // 20 MHz wide\n    APPLE80211_C_FLAG_40MHZ        = 0x4,   // 40 MHz wide\n    APPLE80211_C_FLAG_2GHZ         = 0x8,   // 2.4 GHz\n    APPLE80211_C_FLAG_5GHZ         = 0x10,  // 5 GHz\n    APPLE80211_C_FLAG_IBSS         = 0x20,  // IBSS supported\n    APPLE80211_C_FLAG_HOST_AP      = 0x40,  // HOST AP mode supported\n    APPLE80211_C_FLAG_ACTIVE       = 0x80,  // active scanning supported\n    APPLE80211_C_FLAG_DFS          = 0x100, // DFS required\n    APPLE80211_C_FLAG_EXT_ABV      = 0x200, // If 40 Mhz, extension channel above.\n    // If this flag is not set, then the\n    // extension channel is below.\n    APPLE80211_C_FLAG_80MHZ        = 0x400,  // name made up - set if channelWidth == 80 && 5ghz && AC\n    APPLE80211_C_FLAG_160MHZ       = 0x800,  // zxystd: Apple Broadcom not use it, but we can use!\n};\n\nenum apple80211_rate_flag\n{\n    APPLE80211_RATE_FLAG_NONE      = 0x0,   // no flags\n    APPLE80211_RATE_FLAG_BASIC     = 0x1,   // basic rate\n    APPLE80211_RATE_FLAG_HT        = 0x2,   // HT rate computed from MCS index\n};\n\nenum apple80211_short_slot_mode\n{\n    APPLE80211_SHORT_SLOT_MODE_AUTO     = 1,    // Default behavior\n    APPLE80211_SHORT_SLOT_MODE_LONG     = 2,    // long - short slot timing mode\n    APPLE80211_SHORT_SLOT_MODE_SHORT    = 3,    // short - short slot timing mode\n};\n\nenum apple80211_powersave_mode\n{\n    // Standard modes\n    APPLE80211_POWERSAVE_MODE_DISABLED       = 0,\n    APPLE80211_POWERSAVE_MODE_80211          = 1,\n    APPLE80211_POWERSAVE_MODE_VENDOR         = 2,    //    Vendor specific mode, there should be\n    //  more general apple modes in the future.\n    //  Vendor modes also likely require more info.\n    // Mimo modes\n    APPLE80211_POWERSAVE_MODE_MIMO_STATIC     = 3,\n    APPLE80211_POWERSAVE_MODE_MIMO_DYNAMIC    = 4,\n    APPLE80211_POWERSAVE_MODE_MIMO_MIMO       = 5,\n\n    // WOW\n    APPLE80211_POWERSAVE_MODE_WOW             = 6,\n\n    // Vendor specific powersave mode, throughput is maximized\n    APPLE80211_POWERSAVE_MODE_MAX_THROUGHPUT  = 7,\n\n    // Vendor specific powersave mode, power savings are maximized, possibly\n    // at the expense of throughput/latency.\n    APPLE80211_POWERSAVE_MODE_MAX_POWERSAVE   = 8,\n};\n\nenum apple80211_debug_flag\n{\n    APPLE80211_DEBUG_FLAG_NONE           = 0x0,    // No logging\n    APPLE80211_DEBUG_FLAG_INFORMATIVE    = 0x1,    // Log \"interesting\" events\n    APPLE80211_DEBUG_FLAG_ERROR          = 0x2,    // Log errors\n    APPLE80211_DEBUG_FLAG_RSN            = 0x4,    // Full RSN supplicant logging\n    APPLE80211_DEBUG_FLAG_SCAN           = 0x8,    // Scan events and information\n};\n\nenum apple80211_guard_interval\n{\n    APPLE80211_GI_SHORT    = 400,    // ns\n    APPLE80211_GI_LONG     = 800,    // ns\n};\n\n#define APPLE80211_RSC_LEN                 8\n#define APPLE80211_KEY_BUFF_LEN           32\n\n#define APPLE80211_KEY_FLAG_UNICAST       0x1\n#define APPLE80211_KEY_FLAG_MULTICAST     0x2\n#define APPLE80211_KEY_FLAG_TX            0x4\n#define APPLE80211_KEY_FLAG_RX            0x8\n\nstruct apple80211_key\n{\n    u_int32_t           version;\n    u_int32_t           key_len;\n    u_int32_t           key_cipher_type;                    // apple80211_cipher_type\n    u_int16_t           key_flags;\n    u_int16_t           key_index;\n    u_int8_t            key[ APPLE80211_KEY_BUFF_LEN ];\n    u_int8_t            pad[30];\n    u_int32_t           key_rsc_len;\n    u_int8_t            key_rsc[ APPLE80211_RSC_LEN ];    // receive sequence counter\n    struct ether_addr   key_ea;                           // key applies to this bssid\n    uint                wowl_kck_len;\n    uint8_t             wowl_kck_key[16];\n    uint                wowl_kek_len;\n    u_int8_t            wowl_kek_key[24];\n};\n\n// Changing this affects any structure that contains a channel\nstruct apple80211_channel\n{\n    u_int32_t    version;\n    u_int32_t    channel;    //    channel number\n    u_int32_t    flags;      //    apple80211_channel_flag vector\n};\n\nstruct apple80211_rate\n{\n    u_int32_t    version;\n    u_int32_t    rate;     // rate mbps\n    u_int32_t    flags;    // apple80211_rate_flag vector\n};\n\n// Probe response capability flags, IEEE 7.3.1.4\n#define APPLE80211_CAPINFO_ESS               0x0001\n#define APPLE80211_CAPINFO_IBSS              0x0002\n#define APPLE80211_CAPINFO_CF_POLLABLE       0x0004\n#define APPLE80211_CAPINFO_CF_POLLREQ        0x0008\n#define APPLE80211_CAPINFO_PRIVACY           0x0010\n#define APPLE80211_CAPINFO_SHORT_PREAMBLE    0x0020\n#define APPLE80211_CAPINFO_PBCC              0x0040\n#define APPLE80211_CAPINFO_AGILITY           0x0080\n// 0x0100, 0x0200 reserved\n#define APPLE80211_CAPINFO_SHORT_SLOT_TIME   0x0400\n// 0x0800, 0x1000 reserved\n#define APPLE80211_CAPINFO_DSSS_OFDM         0x2000\n// 0x4000, 0x8000 reserved\n\n// Reason codes IEEE 7.3.1.7\n#define APPLE80211_REASON_UNSPECIFIED                1\n#define APPLE80211_REASON_PREV_AUTH_EXPIRED          2\n#define APPLE80211_REASON_AUTH_LEAVING               3\n#define APPLE80211_REASON_INACTIVE                   4\n#define APPLE80211_REASON_AP_OVERLOAD                5\n#define APPLE80211_REASON_NOT_AUTHED                 6\n#define APPLE80211_REASON_NOT_ASSOCED                7\n#define APPLE80211_REASON_ASSOC_LEAVING              8\n#define APPLE80211_REASON_ASSOC_NOT_AUTHED           9\n#define APPLE80211_REASON_POWER_CAP                  10\n#define APPLE80211_REASON_SUPPORTED_CHANS            11\n\n#define APPLE80211_REASON_INVALID_IE                 13\n#define APPLE80211_REASON_MIC_FAILURE                14\n#define APPLE80211_REASON_4_WAY_TIMEOUT              15\n#define APPLE80211_REASON_GROUP_KEY_TIMEOUT          16\n#define APPLE80211_REASON_DIFF_IE                    17\n#define APPLE80211_REASON_INVALID_GROUP_KEY          18\n#define APPLE80211_REASON_INVALID_PAIR_KEY           19\n#define APPLE80211_REASON_INVALID_AKMP               20\n#define APPLE80211_REASON_UNSUPP_RSN_VER             21\n#define APPLE80211_REASON_INVALID_RSN_CAPS           22\n#define APPLE80211_REASON_8021X_AUTH_FAILED          23\n\n// Status codes IEEE 7.3.1.9\n#define APPLE80211_STATUS_SUCCESS                     0\n#define APPLE80211_STATUS_UNSPECIFIED_FAILURE         1\n// 2-9 reserved\n#define APPLE80211_STATUS_UNSUPPORTED_CAPABILITIES   10\n#define APPLE80211_STATUS_REASSOCIATION_DENIED       11\n#define APPLE80211_STATUS_ASSOCIATION_DENIED         12\n#define APPLE80211_STATUS_AUTH_ALG_UNSUPPORTED       13\n#define APPLE80211_STATUS_INVALID_AUTH_SEQ_NUM       14\n#define APPLE80211_STATUS_CHALLENGE_FAILURE          15\n#define APPLE80211_STATUS_TIMEOUT                    16\n#define APPLE80211_STATUS_AP_FULL                    17\n#define APPLE80211_STATUS_UNSUPPORTED_RATE_SET       18\n// 22-24 reserved\n#define APPLE80211_STATUS_SHORT_SLOT_UNSUPPORTED     25\n#define APPLE80211_STATUS_DSSS_OFDM_UNSUPPORTED      26\n// 27-39 reserved\n#define APPLE80211_STATUS_INVALID_IE                 40\n#define APPLE80211_STATUS_INVALID_GROUP_CIPHER       41\n#define APPLE80211_STATUS_INVALID_PAIRWISE_CIPHER    42\n#define APPLE80211_STATUS_INVALID_AKMP               43\n#define APPLE80211_STATUS_UNSUPPORTED_RSN_VERSION    44\n#define APPLE80211_STATUS_INVALID_RSN_CAPABILITIES   45\n#define APPLE80211_STATUS_CIPHER_SUITE_REJECTED      46\n// 47 - 65535 reserved\n#define APPLE80211_STATUS_UNAVAILABLE                0xffff\n\n// If mcs index is set to APPLE80211_MCS_INDEX_AUTO, the interface\n// should go to auto rate selection, and abandon any previously\n// configured static MCS indices\n#define APPLE80211_MCS_INDEX_AUTO    0xffffffff\n\n/*\n DSCP TOS/Traffic class values for WME access categories taken from\n WiFi WMM Test Plan v 1.3.1 Appendix C.\n \n TOS/Traffic class field looks like:\n \n 0   1   2   3   4   5   6   7\n +---+---+---+---+---+---+---+---+\n |          DSCP         |  ECN  |\n +---+---+---+---+---+---+---+---+\n \n These bits are numbered according to rfc 2474, but might be misleading.\n It looks like bit 0 is actually the high order bit.\n */\n\n#define APPLE80211_DSCP_WME_BE    0x00\n#define APPLE80211_DSCP_WME_BK    0x08\n#define APPLE80211_DSCP_WME_VI    0x28\n#define APPLE80211_DSCP_WME_VO    0x38\n\n// Access category values set in the mbuf\n#define APPLE80211_WME_AC_BE    0\n#define APPLE80211_WME_AC_BK    1\n#define APPLE80211_WME_AC_VI    2\n#define APPLE80211_WME_AC_VO    3\n\n// Working within the limitations of the kpi mbuf routines, the receive interface pointer\n// is the best place to put this for now since it is not used on the output path. The mbuf\n// kpi doesn't allow us to access unused flags, or I would put the WME AC in there like\n// everyone else.\n\n#define APPLE80211_MBUF_SET_WME_AC( m, ac ) mbuf_pkthdr_setrcvif( m, (ifnet_t)ac )\n#define APPLE80211_MBUF_WME_AC( m ) (int)mbuf_pkthdr_rcvif( m )\n\n// FIXME: seems that rates array starts at 0x24, immediately after\nstruct apple80211_scan_result\n{\n    u_int32_t             version;        // 0x00 - 0x03\n    apple80211_channel    asr_channel;    // 0x04 - 0x0f\n\n    int16_t               asr_unk;        // 0x10 - 0x11\n\n    int16_t               asr_noise;      // 0x12 - 0x13\n    int16_t               asr_snr;        // 0x14 - 0x15\n    int16_t               asr_rssi;       // 0x16 - 0x17\n    int16_t               asr_beacon_int; // 0x18 - 0x19\n\n    int16_t               asr_cap;        // 0x1a - 0x1b (capabilities)\n\n    u_int8_t              asr_bssid[ APPLE80211_ADDR_LEN ]; // 0x1c 0x1d 0x1e 0x1f 0x20 0x21\n    u_int8_t              asr_nrates;     // 0x22\n    u_int8_t              asr_nr_unk;     // 0x23\n    u_int32_t             asr_rates[ APPLE80211_MAX_RATES ]; // 0x24 - 0x5f\n    u_int8_t              asr_ssid_len;   // 0x60\n    u_int8_t              asr_ssid[ APPLE80211_MAX_SSID_LEN ]; // 0x61 - 0x80\n    int16_t               unk;\n    uint8_t               unk2;\n    u_int32_t             asr_age;        // (ms) non-zero for cached scan result // 0x84\n\n    u_int16_t             unk3;             // 0x88\n    int16_t               asr_ie_len;       // 0x8A\n#if __IO80211_TARGET < __MAC_12_0\n    uint32_t              asr_unk3;         // 0x8C\n    void*                 asr_ie_data;      // 90\n#else\n    uint8_t               asr_ie_data[1024];    // 0x8C\n#endif\n} __attribute__((packed));\n\nstruct apple80211_network_data\n{\n    u_int32_t                   version;\n    u_int16_t                   nd_mode;              // apple80211_apmode\n    u_int16_t                   nd_auth_lower;        // apple80211_authtype_lower\n    u_int16_t                   nd_auth_upper;        // apple80211_authtype_upper\n    struct apple80211_channel   nd_channel;\n    u_int32_t                   nd_ssid_len;\n    u_int8_t                    nd_ssid[ APPLE80211_MAX_SSID_LEN ];\n    struct apple80211_key       nd_key;\n    u_int32_t                   nd_ie_len;\n    void                        *nd_ie_data;\n};\n\n#define APPLE80211_NETWORK_DATA_MAX_IE_LEN 1024\n\n// As hostap support improves, this will grow\nstruct apple80211_station\n{\n    u_int32_t            version;\n    struct ether_addr    sta_mac;\n    int32_t              sta_rssi;\n};\n\n// WOW structures and defines\n\nstruct apple80211_wow_pattern\n{\n    size_t      len;\n    u_int8_t    *pattern;\n};\n\nenum apple80211_wake_condition\n{\n    APPLE80211_WAKE_COND_MAGIC_PATTERN  = 0,\n    APPLE80211_WAKE_COND_NET_PATTERN    = 1,\n    APPLE80211_WAKE_COND_DISASSOCIATED  = 2,\n    APPLE80211_WAKE_COND_DEAUTHED       = 3,\n    APPLE80211_WAKE_COND_RETROGRADE_TSF = 4,\n    APPLE80211_WAKE_COND_BEACON_LOSS    = 5,\n};\n\n#define APPLE80211_MAX_WAKE_COND 5\n\nenum apple80211_card_capability\n{\n    APPLE80211_CAP_WEP             = 0,    // CAPABILITY: WEP available\n    APPLE80211_CAP_TKIP            = 1,    // CAPABILITY: TKIP available\n    APPLE80211_CAP_AES             = 2,    // CAPABILITY: AES OCB avail\n    APPLE80211_CAP_AES_CCM         = 3,    // CAPABILITY: AES CCM avail\n    APPLE80211_CAP_CKIP            = 4,    // CAPABILITY: CKIP available\n    APPLE80211_CAP_IBSS            = 5,    // CAPABILITY: IBSS available\n    APPLE80211_CAP_PMGT            = 6,    // CAPABILITY: Power mgmt\n    APPLE80211_CAP_HOSTAP          = 7,    // CAPABILITY: HOSTAP avail\n    APPLE80211_CAP_TXPMGT          = 8,    // CAPABILITY: tx power mgmt\n    APPLE80211_CAP_SHSLOT          = 9,    // CAPABILITY: short slottime\n    APPLE80211_CAP_SHPREAMBLE      = 10,   // CAPABILITY: short preamble\n    APPLE80211_CAP_MONITOR         = 11,   // CAPABILITY: monitor mode\n    APPLE80211_CAP_TKIPMIC         = 12,   // CAPABILITY: TKIP MIC avail\n    APPLE80211_CAP_WPA1            = 13,   // CAPABILITY: WPA1 avail\n    APPLE80211_CAP_WPA2            = 14,   // CAPABILITY: WPA2 avail\n    APPLE80211_CAP_WPA             = 15,   // CAPABILITY: WPA1+WPA2 avail\n    APPLE80211_CAP_BURST           = 16,   // CAPABILITY: frame bursting\n    APPLE80211_CAP_WME             = 17,   // CAPABILITY: WME avail\n    APPLE80211_CAP_SHORT_GI_40MHZ  = 18,   // CAPABILITY: Short guard interval in 40 MHz\n    APPLE80211_CAP_SHORT_GI_20MHZ  = 19,   // CAPABILITY: Short guard interval in 20 MHz\n    APPLE80211_CAP_WOW             = 20,   // CAPABILITY: Wake on wireless\n    APPLE80211_CAP_TSN             = 21,   // CAPABILITY: WPA with WEP group key\n};\n#define APPLE80211_CAP_MAX    63\n\nenum apple80211_virtual_interface_type\n{\n#if __IO80211_TARGET < __MAC_13_0\n    APPLE80211_VIF_P2P_DEVICE   = 1,\n#else\n    APPLE80211_VIF_P2P_DEVICE   = 3,\n#endif\n    APPLE80211_VIF_P2P_CLIENT,\n    APPLE80211_VIF_P2P_GO,\n    APPLE80211_VIF_AWDL,\n    APPLE80211_VIF_SOFT_AP,\n    \n    APPLE80211_VIF_MAX\n};\n\nenum apple80211_ie_type\n{\n    APPLE80211_IE_FLAG_PROBE_REQ     = (1 << 0),\n    APPLE80211_IE_FLAG_PROBE_RESP    = (1 << 1),\n    APPLE80211_IE_FLAG_ASSOC_REQ     = (1 << 2),\n    APPLE80211_IE_FLAG_ASSOC_RESP    = (1 << 3),\n    APPLE80211_IE_FLAG_BEACON        = (1 << 4),\n};\n\nenum apple80211_assoc_flags {\n    APPLE80211_ASSOC_F_CLOSED    = 1,    // flag: scan was directed, needed to remember closed networks\n};\n\nenum IO80211LinkState\n{\n    kIO80211NetworkLinkUndefined,            // Starting link state when an interface is created\n    kIO80211NetworkLinkDown,                // Interface not capable of transmitting packets\n    kIO80211NetworkLinkUp,                    // Interface capable of transmitting packets\n};\ntypedef enum IO80211LinkState IO80211LinkState;\n\n// Kernel messages\n\nstruct apple80211_status_msg_hdr\n{\n    u_int32_t    msg_type;        //    type of message\n    u_int32_t    msg_len;         //  length of data (not including msg_type and msg_len)\n    \n    // data follows\n};\n\n#define APPLE80211_M_MAX_LEN                2048\n\n#define APPLE80211_M_POWER_CHANGED           1\n#define APPLE80211_M_SSID_CHANGED            2\n#define APPLE80211_M_BSSID_CHANGED           3\n#define APPLE80211_M_LINK_CHANGED            4\n#define APPLE80211_M_MIC_ERROR_UCAST         5\n#define APPLE80211_M_MIC_ERROR_MCAST         6\n#define APPLE80211_M_INT_MIT_CHANGED         7\n#define APPLE80211_M_MODE_CHANGED            8\n#define APPLE80211_M_ASSOC_DONE              9\n#define APPLE80211_M_SCAN_DONE               10\n#define APPLE80211_M_COUNTRY_CODE_CHANGED    11\n#define APPLE80211_M_STA_ARRIVE              12\n#define APPLE80211_M_STA_LEAVE               13\n#define APPLE80211_M_DECRYPTION_FAILURE      14\n#define APPLE80211_M_SCAN_CACHE_UPDATED      15\n#define APPLE80211_M_INTERNAL_SCAN_DONE      16\n#define APPLE80211_M_LINK_QUALITY            17\n#define APPLE80211_M_IBSS_PEER_ARRIVED       18\n#define APPLE80211_M_IBSS_PEER_LEFT          19\n#define APPLE80211_M_RSN_HANDSHAKE_DONE      20\n#define APPLE80211_M_BT_COEX_CHANGED         21\n#define APPLE80211_M_P2P_PEER_DETECTED       22\n#define APPLE80211_M_P2P_LISTEN_COMPLETE     23\n#define APPLE80211_M_P2P_SCAN_COMPLETE       24\n#define APPLE80211_M_P2P_LISTEN_STARTED      25\n#define APPLE80211_M_P2P_SCAN_STARTED        26\n#define APPLE80211_M_P2P_INTERFACE_CREATED   27\n#define APPLE80211_M_P2P_GROUP_STARTED       28\n#define APPLE80211_M_BGSCAN_NET_DISCOVERED   29\n#define APPLE80211_M_ROAMED                  30\n#define APPLE80211_M_ACT_FRM_TX_COMPLETE     31\n#define APPLE80211_M_DEAUTH_RECEIVED         32\n#define APPLE80211_M_RSSI_CHANGED            39\n#define APPLE80211_M_PEER_STATE              40\n#define APPLE80211_M_AWDL_AVAILABILITY_WINDOW_START 42\n#define APPLE80211_M_AWDL_AVAILABILITY_WINDOW_EXTENSIONS_END    43\n#define APPLE80211_M_AWDL_SYNC_STATE_CHANGED 46\n#define APPLE80211_M_AWDL_PEER_PRESENCE      47\n#define APPLE80211_M_RESET_INTERFACE         49\n#define APPLE80211_M_PEER_CREDIT_GRANT       50\n#define APPLE80211_M_CHANNEL_SWITCH          54\n#define APPLE80211_M_DRIVER_AVAILABLE        55\n#define APPLE80211_M_INTERFACE_STATE         58\n#define APPLE80211_M_LINK_ADDRESS_CHANGED    59\n#define APPLE80211_M_BGSCAN_CACHED_NETWORK_AVAILABLE    63\n#define APPLE80211_M_AWDL_STATISTICS         65\n#define APPLE80211_M_AWDL_REALTIME_MODE_START   67\n#define APPLE80211_M_AWDL_REALTIME_MODE_END  68\n#define APPLE80211_M_ROAM_START              70\n#define APPLE80211_M_ROAM_END                71\n#define APPLE80211_M_DUMP_LOGS               79\n#define APPLE80211_M_LEAKY_AP_STATISTICS     81\n#define APPLE80211_M_RANGING_MEASUREMENT_DONE   83\n#define APPLE80211_M_AWDL_DFS_CSA            88\n#define APPLE80211_M_TCPKA_TIMEOUT           91\n#define APPLE80211_M_AWDL_DFS_CSA_COMPLETE   94\n#define APPLE80211_M_BSS_STEERING_REQUEST_EVENT 140\n#define APPLE80211_M_AWDL_HPP_STATISTICS     142\n#define APPLE80211_M_ACTION_FRAME            143\n#define APPLE80211_M_AWDL_APP_SPECIFIC_INFO  144\n#define APPLE80211_M_WSEC_NOTIFICATION       146\n\n\n#define APPLE80211_M_MAX                     170\n#define APPLE80211_M_BUFF_SIZE               APPLE80211_MAP_SIZE( APPLE80211_M_MAX )\n\n// Registry Information\n#define APPLE80211_REGKEY_HARDWARE_VERSION    \"IO80211HardwareVersion\"\n// #define APPLE80211_REG_FIRMWARE_VERSION    \"IO80211FirmwareVersion\"\n#define APPLE80211_REGKEY_DRIVER_VERSION      \"IO80211DriverVersion\"\n#define APPLE80211_REGKEY_LOCALE              \"IO80211Locale\"\n#define APPLE80211_REGKEY_SSID                \"IO80211SSID\"\n#define APPLE80211_REGKEY_CHANNEL             \"IO80211Channel\"\n#define APPLE80211_REGKEY_EXT_CHANNEL         \"IO80211ExtensionChannel\"\n#define APPLE80211_REGKEY_BAND                \"IO80211Band\"\n#define APPLE80211_BAND_2GHZ                  \"2 GHz\"\n#define APPLE80211_BAND_5GHZ                  \"5 GHz\"\n#define APPLE80211_REGKEY_COUNTRY_CODE        \"IO80211CountryCode\"\n\n// Userland messages\n#define APPLE80211_M_RSN_AUTH_SUCCESS            254\n#define APPLE80211_M_RSN_AUTH_SUCCESS_TEMPLATE   \"com.apple.rsn.%s.auth.success\"    // string is interface name\n\n#define APPLE80211_M_RSN_AUTH_TIMEOUT            255\n#define APPLE80211_M_RSN_AUTH_TIMEOUT_TEMPLATE   \"com.apple.rsn.%s.auth.timeout\"    // string is interface name\n\n#define APPLE80211_M_RSN_MSG_MAX                 2\n\n#endif // _APPLE80211_VAR_H_\n\n"
  },
  {
    "path": "include/Airport/apple80211_wps.h",
    "content": "//\n//  wps_eap.h\n//  IO80211Family\n//\n//  Created by Pete on 6/20/06.\n//  Copyright 2006 Apple Computer, Inc. All rights reserved.\n//\n\n#ifndef _APPLE80211_WPS_H_\n#define _APPLE80211_WPS_H_\n\n#include <Availability.h>\n#include <sys/types.h>\n#include <net/ethernet.h>\n\n// This is necessary, because even the latest Xcode does not support properly targeting 11.0.\n#ifndef __IO80211_TARGET\n#error \"Please define __IO80211_TARGET to the requested version\"\n#endif\n\n#define WPS_HANDSHAKE_TIMEOUT      120 /* seconds */\n#define WPS_RETRANSMIT_TIMEOUT     5\n#define WPS_MAX_RETRIES            3\n\n#define WPS_IDENTITY_STR                \"WFA-SimpleConfig-Enrollee-1-0\"\n#define WPS_IDENTITY_STR_LEN            29\n#define WPS_PERSONALIZATION_STRING      \"Wi-Fi Easy and Secure Key Derivation\"\n#define WPS_PERSONALIZATION_STRING_LEN  ( sizeof( WPS_PERSONALIZATION_STRING ) - 1 )\n#define WPS_KDF_KEY_BITS                640\n\n#define WPS_DISPLAY_PIN_LEN    8\n\n#define EAP_TYPE_ID            1\n#define WPS_EAP_METHOD_TYPE    254\n\n#define WPS_VENDOR_ID_BYTES    0x00, 0x37, 0x2A\n#define WPS_VENDOR_TYPE        0x00000001\n\n#define WPS_OP_START           0x01\n#define WPS_OP_ACK             0x02\n#define WPS_OP_NACK            0x03\n#define WPS_OP_MSG             0x04\n#define WPS_OP_DONE            0x05\n\n#define WPS_FLAG_MF            0x01    /* more fragments */\n#define WPS_FLAG_LF            0x02    /* length field in use */\n\n#define WPS_MAX_MSG_LEN UINT16_MAX    /* max frag len, my limit */\n\n#define PACKED __attribute__((packed))\n\nstruct wps_eap_hdr\n{\n    u_int8_t    code;\n    u_int8_t    identifier;\n    u_int16_t    length;\n    u_int8_t    type;\n    u_int8_t    vendor_id[3];\n    u_int32_t    vendor_type;\n    u_int8_t    op_code;\n    u_int8_t    flags;\n    u_int16_t    msg_length;\n    //    u_int8_t    msg[1];        /* data follows */\n} PACKED;\n\n#define WPS_EAP_HDR_LEN( _whdr ) ( ( _whdr->flags & WPS_FLAG_LF ) ? sizeof( struct wps_eap_hdr ) : sizeof( struct wps_eap_hdr ) - sizeof( u_int16_t ) )\n\n// Messages elements\n\n#define BUF_SIZE_64_BITS    8\n#define BUF_SIZE_128_BITS   16\n#define BUF_SIZE_160_BITS   20\n#define BUF_SIZE_256_BITS   32\n#define BUF_SIZE_512_BITS   64\n#define BUF_SIZE_1024_BITS  128\n#define BUF_SIZE_1536_BITS  192\n\nstruct wps_msg_elem_hdr\n{\n    u_int16_t    elem_id;\n    u_int16_t    elem_len;\n} PACKED;\n\n#define WPS_ELEM_SET_HEADER( elem, id, len ) (elem)->hdr.elem_id = htons( id ); (elem)->hdr.elem_len = htons( len )\n\nstruct wps_dev_type\n{\n    u_int16_t    category;\n    u_int8_t    oui[4];\n    u_int16_t    sub_category;\n} PACKED;\n\n#define WIFI_DEV_TYPE_OUI_BYTES    0x00, 0x50, 0xf2, 0x04\n\n#define DEFINE_WPS_ELEMENT( name, param ) \\\ntypedef struct {                          \\\n  struct wps_msg_elem_hdr hdr;            \\\n  param;                                  \\\n} PACKED name\n\n\n#define WPS_VERSION 0x10\nDEFINE_WPS_ELEMENT( wps_elem_ap_channel_t, u_int16_t channel );\nDEFINE_WPS_ELEMENT( wps_elem_assoc_state_t, u_int16_t assoc_state );\nDEFINE_WPS_ELEMENT( wps_elem_auth_type_t, u_int16_t auth_type );\nDEFINE_WPS_ELEMENT( wps_elem_auth_type_flags_t, u_int16_t auth_flags );\n#define AUTHENTICATOR_MSG_SIZE ( sizeof( struct wps_msg_elem_hdr ) + 8 )\nDEFINE_WPS_ELEMENT( wps_elem_authenticator_t, u_int8_t authenticator[8] );\nDEFINE_WPS_ELEMENT( wps_elem_config_methods_t, u_int16_t config_methods );\nDEFINE_WPS_ELEMENT( wps_elem_config_error_t, u_int16_t error );\nDEFINE_WPS_ELEMENT( wps_elem_confirm_url4_t, u_int16_t url4[1] ); // <= 64B\nDEFINE_WPS_ELEMENT( wps_elem_confirm_url6_t, u_int16_t url6[1] ); // <= 76B\nDEFINE_WPS_ELEMENT( wps_elem_conn_type_t, u_int8_t conn_type );\nDEFINE_WPS_ELEMENT( wps_elem_conn_type_flags_t, u_int8_t conn_type_flags );\nDEFINE_WPS_ELEMENT( wps_elem_credential_t, u_int8_t cred[1] );    // <= ???\nDEFINE_WPS_ELEMENT( wps_elem_dev_name_t, u_int8_t dev_name[1] ); // <= 32B\nDEFINE_WPS_ELEMENT( wps_elem_dev_pw_id_t, u_int16_t dev_pw_id );\nDEFINE_WPS_ELEMENT( wps_elem_e_hash1_t, u_int8_t e_hash1[BUF_SIZE_256_BITS] );\nDEFINE_WPS_ELEMENT( wps_elem_e_hash2_t, u_int8_t e_hash2[BUF_SIZE_256_BITS] );\nDEFINE_WPS_ELEMENT( wps_elem_e_snonce1_t, u_int8_t e_snonce1[BUF_SIZE_128_BITS] );\nDEFINE_WPS_ELEMENT( wps_elem_e_snonce2_t, u_int8_t e_snonce2[BUF_SIZE_128_BITS] );\nDEFINE_WPS_ELEMENT( wps_elem_ecrypt_settings_t, u_int8_t settings[1] );    // no limit defined\nDEFINE_WPS_ELEMENT( wps_elem_encrypt_type_t, u_int16_t encrypt_type );\nDEFINE_WPS_ELEMENT( wps_elem_encrypt_type_flags_t, u_int16_t encrypt_type_flags );\nDEFINE_WPS_ELEMENT( wps_elem_enrl_nonce_t, u_int8_t nonce[BUF_SIZE_128_BITS] );\nDEFINE_WPS_ELEMENT( wps_elem_feature_id_t, u_int32_t feature_id );\nDEFINE_WPS_ELEMENT( wps_elem_identity_t, u_int8_t identity[1] ); // <= 80\n// identity proof?\nDEFINE_WPS_ELEMENT( wps_elem_iv_t, u_int8_t iv[BUF_SIZE_256_BITS] );\nDEFINE_WPS_ELEMENT( wps_elem_key_wrap_authenticator_t, u_int8_t key_wrap_authenticator[8] );\nDEFINE_WPS_ELEMENT( wps_elem_key_id_t, u_int8_t key_id[16] );\nDEFINE_WPS_ELEMENT( wps_elem_mac_addr_t, u_int8_t mac[ETHER_ADDR_LEN] );\nDEFINE_WPS_ELEMENT( wps_elem_manufacturer_t, u_int8_t manufacturer[1] ); // <= 64\nDEFINE_WPS_ELEMENT( wps_elem_msg_type_t, u_int8_t msg_type  );\nDEFINE_WPS_ELEMENT( wps_elem_model_name_t, u_int8_t model_name[1] ); // <= 32B\nDEFINE_WPS_ELEMENT( wps_elem_model_number_t, u_int8_t model_number[1] ); // <= 32B\nDEFINE_WPS_ELEMENT( wps_elem_network_index_t, u_int8_t network_index );\nDEFINE_WPS_ELEMENT( wps_elem_network_key_t, u_int8_t network_key[1] ); // <= 64B\nDEFINE_WPS_ELEMENT( wps_elem_network_key_index_t, u_int8_t network_key_index );\nDEFINE_WPS_ELEMENT( wps_elem_new_dev_name_t, u_int8_t new_dev_name[1] ); // <= 32B\nDEFINE_WPS_ELEMENT( wps_elem_new_pw_t, u_int8_t new_pw[1] ); // <= 64\n// oob device password?\nDEFINE_WPS_ELEMENT( wps_elem_os_version_t, u_int32_t os_version );\nDEFINE_WPS_ELEMENT( wps_elem_power_level_t, u_int8_t power_level );\nDEFINE_WPS_ELEMENT( wps_elem_psk_current_t, u_int8_t psk_current );\nDEFINE_WPS_ELEMENT( wps_elem_psk_max_t, u_int8_t psk_max );\nDEFINE_WPS_ELEMENT( wps_elem_public_key_t, u_int8_t key[BUF_SIZE_1536_BITS] );\nDEFINE_WPS_ELEMENT( wps_elem_radio_enabled_t, u_int8_t radio_enabled ); // bool?\nDEFINE_WPS_ELEMENT( wps_elem_reboot_t, u_int8_t reboot ); // bool?\nDEFINE_WPS_ELEMENT( wps_elem_reg_current_t, u_int8_t reg_current );\nDEFINE_WPS_ELEMENT( wps_elem_reg_established_t, u_int8_t reg_established ); // bool?\nDEFINE_WPS_ELEMENT( wps_elem_reg_list_t, u_int8_t reg_list[1] ); // <= 512B\nDEFINE_WPS_ELEMENT( wps_elem_reg_max_t, u_int8_t reg_max );\nDEFINE_WPS_ELEMENT( wps_elem_reg_nonce_t, u_int8_t nonce[BUF_SIZE_128_BITS] );\nDEFINE_WPS_ELEMENT( wps_elem_req_type_t, u_int8_t req_type );\nDEFINE_WPS_ELEMENT( wps_elem_resp_type_t, u_int8_t resp_type );\nDEFINE_WPS_ELEMENT( wps_elem_rf_band_t, u_int8_t rf_band );\nDEFINE_WPS_ELEMENT( wps_elem_r_hash1, u_int8_t r_hash1[BUF_SIZE_256_BITS] );\nDEFINE_WPS_ELEMENT( wps_elem_r_hash2, u_int8_t r_hash2[BUF_SIZE_256_BITS] );\nDEFINE_WPS_ELEMENT( wps_elem_r_snonce1, u_int8_t r_snonce1[BUF_SIZE_128_BITS] );\nDEFINE_WPS_ELEMENT( wps_elem_r_snonce2, u_int8_t r_snonce2[BUF_SIZE_128_BITS] );\nDEFINE_WPS_ELEMENT( wps_elem_selected_reg_t, u_int8_t selected_reg );    // bool?\nDEFINE_WPS_ELEMENT( wps_elem_serial_number_t, u_int8_t serial_number[1] ); // <= 32B\nDEFINE_WPS_ELEMENT( wps_elem_simple_config_state_t, u_int8_t simple_config_state );\nDEFINE_WPS_ELEMENT( wps_elem_ssid_t, u_int8_t ssid[32] );\nDEFINE_WPS_ELEMENT( wps_elem_total_networks_t, u_int8_t total_networks );\nDEFINE_WPS_ELEMENT( wps_elem_uuid_e_t, u_int8_t uuid_e[16] );\nDEFINE_WPS_ELEMENT( wps_elem_uuid_r_t, u_int8_t uuid_r[16] );\nDEFINE_WPS_ELEMENT( wps_elem_vendor_ext_t, u_int8_t vendor_ext[1] ); // <= 1024\nDEFINE_WPS_ELEMENT( wps_elem_version_t, u_int8_t version  ); // int?\nDEFINE_WPS_ELEMENT( wps_elem_x_509_cert_req_t, u_int8_t cert_req[1] );    // limit?\nDEFINE_WPS_ELEMENT( wps_elem_x_509_cert_t, u_int8_t cert[1] );    // limit?\nDEFINE_WPS_ELEMENT( wps_elem_eap_id_t, u_int8_t eap_id[1] ); // <= 64\nDEFINE_WPS_ELEMENT( wps_elem_msg_counter_t, u_int8_t msg_counter[8] );\nDEFINE_WPS_ELEMENT( wps_elem_public_key_hash_t, u_int8_t public_key_hash[BUF_SIZE_160_BITS] );\nDEFINE_WPS_ELEMENT( wps_elem_rekey_key_t, u_int8_t rekey_key[32] );\nDEFINE_WPS_ELEMENT( wps_elem_key_lifetime_t, u_int32_t key_lifetime );\nDEFINE_WPS_ELEMENT( wps_elem_permitted_config_methods_t, u_int16_t permitted_config_methods );\nDEFINE_WPS_ELEMENT( wps_elem_sel_reg_config_methods_t, u_int8_t sel_reg_config_methods );\nDEFINE_WPS_ELEMENT( wps_elem_primary_dev_type_t, struct wps_dev_type prime_dev_type );\nDEFINE_WPS_ELEMENT( wps_elem_secondary_dev_type_list_t, u_int8_t secondary_dev_type_list[1] ); // <= 128B\nDEFINE_WPS_ELEMENT( wps_elem_portable_dev_t, u_int8_t portable_dev );    // bool?\nDEFINE_WPS_ELEMENT( wps_elem_ap_setup_locked_t, u_int8_t ap_setup_locked ); // bool?\nDEFINE_WPS_ELEMENT( wps_elem_app_list_t, u_int8_t app_list[1] ); // <= 512B\nDEFINE_WPS_ELEMENT( wps_elem_eap_type_t, u_int8_t eap_type[1] ); // <= 8B\n\n#define WPS_NEXT_ELEMENT( cast, cur_elm, len ) (cast)( (UInt8 *)(cur_elm) + sizeof( struct wps_msg_elem_hdr ) + ntohs( cur_elm->hdr.elem_len ) );    \\\nlen+=( sizeof( struct wps_msg_elem_hdr ) + ntohs( cur_elm->hdr.elem_len ) )\n#define WPS_NEXT_ELEMENT_IE( cast, cur_elm, len ) (cast)( (UInt8 *)(cur_elm) + sizeof( struct wps_msg_elem_hdr ) + ntohs( cur_elm->hdr.elem_len ) );    \\\nlen-=( sizeof( struct wps_msg_elem_hdr ) + ntohs( cur_elm->hdr.elem_len ) );\n#define WPS_ELEMENT_IS( elem, id ) ( ntohs( elem->hdr.elem_id ) == id )\n#define WPS_ELEMENT_LEN_VAR( elem )    ( sizeof( struct wps_msg_elem_hdr ) + ntohs( elem->hdr.elem_len ) )\n#define WPS_ELEMENT_LEN_FIXED( fixed ) ( sizeof( struct wps_msg_elem_hdr ) + sizeof( fixed ) )\n#define WPS_ELEMENT_PARAM_LEN( elem ) ( ntohs( elem->hdr.elem_len ) )\n\n// Messages\n#define WPS_MBUF_GET_MSG_PTR( m, type ) (type *)( (UInt8 *)mbuf_data( m ) + sizeof( struct ether_header ) + sizeof( struct wps_eap_hdr ) )\n\nstruct wps_msg_nack\n{\n    wps_elem_version_t        version;\n    wps_elem_msg_type_t        msg_type;\n    wps_elem_enrl_nonce_t    enrl_nonce;\n    wps_elem_reg_nonce_t    reg_nonce;\n    wps_elem_config_error_t error;\n}PACKED;\n\nstruct wps_msg_ack\n{\n    wps_elem_version_t        version;\n    wps_elem_msg_type_t        msg_type;\n    wps_elem_enrl_nonce_t    enrl_nonce;\n    wps_elem_reg_nonce_t    reg_nonce;\n}PACKED;\n\nstruct wps_msg_done\n{\n    wps_elem_version_t        version;\n    wps_elem_msg_type_t        msg_type;\n};\n\n// From RFC 3748 section 4.1 for identity\nstruct wps_identity_msg\n{\n    u_int8_t    code;\n    u_int8_t    id;\n    u_int16_t    length;\n    u_int8_t    type;\n    //    u_int8_t    type_data[1];    /* data follows */\n} PACKED;\n\n#define WPS_EAP_TYPE_IDENTITY    1\n\n// Data Element Definitions\n#define WPS_ID_AP_CHANNEL         0x1001\n#define WPS_ID_ASSOC_STATE        0x1002\n#define WPS_ID_AUTH_TYPE          0x1003\n#define WPS_ID_AUTH_TYPE_FLAGS    0x1004\n#define WPS_ID_AUTHENTICATOR      0x1005\n#define WPS_ID_CONFIG_METHODS     0x1008\n#define WPS_ID_CONFIG_ERROR       0x1009\n#define WPS_ID_CONF_URL4          0x100A\n#define WPS_ID_CONF_URL6          0x100B\n#define WPS_ID_CONN_TYPE          0x100C\n#define WPS_ID_CONN_TYPE_FLAGS    0x100D\n#define WPS_ID_CREDENTIAL         0x100E\n#define WPS_ID_DEVICE_NAME        0x1011\n#define WPS_ID_DEVICE_PWD_ID      0x1012\n#define WPS_ID_E_HASH1            0x1014\n#define WPS_ID_E_HASH2            0x1015\n#define WPS_ID_E_SNONCE1          0x1016\n#define WPS_ID_E_SNONCE2          0x1017\n#define WPS_ID_ENCR_SETTINGS      0x1018\n#define WPS_ID_ENCR_TYPE          0x100F\n#define WPS_ID_ENCR_TYPE_FLAGS    0x1010\n#define WPS_ID_ENROLLEE_NONCE     0x101A\n#define WPS_ID_FEATURE_ID         0x101B\n#define WPS_ID_IDENTITY           0x101C\n#define WPS_ID_IDENTITY_PROOF     0x101D\n#define WPS_ID_INIT_VECTOR        0x104B //this becomes 0x1060 later\n//#define WPS_ID_KEY_WRAP_AUTH      WPS_ID_AUTHENTICATOR //this becomes 0x101E later\n#define WPS_ID_KEY_WRAP_AUTH      0x101E // HH changed for MS beta 2 testing\n#define WPS_ID_KEY_IDENTIFIER     0x101F\n#define WPS_ID_MAC_ADDR           0x1020\n#define WPS_ID_MANUFACTURER       0x1021\n#define WPS_ID_MSG_TYPE           0x1022\n#define WPS_ID_MODEL_NAME         0x1023\n#define WPS_ID_MODEL_NUMBER       0x1024\n#define WPS_ID_NW_INDEX           0x1026\n#define WPS_ID_NW_KEY             0x1027\n#define WPS_ID_NW_KEY_INDEX       0x1028\n#define WPS_ID_NEW_DEVICE_NAME    0x1029\n#define WPS_ID_NEW_PWD            0x102A\n#define WPS_ID_OOB_DEV_PWD        0x102C\n#define WPS_ID_OS_VERSION         0x102D\n#define WPS_ID_POWER_LEVEL        0x102F\n#define WPS_ID_PSK_CURRENT        0x1030\n#define WPS_ID_PSK_MAX            0x1031\n#define WPS_ID_PUBLIC_KEY         0x1032\n#define WPS_ID_RADIO_ENABLED      0x1033\n#define WPS_ID_REBOOT             0x1034\n#define WPS_ID_REGISTRAR_CURRENT  0x1035\n#define WPS_ID_REGISTRAR_ESTBLSHD 0x1036\n#define WPS_ID_REGISTRAR_LIST     0x1037\n#define WPS_ID_REGISTRAR_MAX      0x1038\n#define WPS_ID_REGISTRAR_NONCE    0x1039\n#define WPS_ID_REQ_TYPE           0x103A\n#define WPS_ID_RESP_TYPE          0x103B\n#define WPS_ID_RF_BAND            0x103C\n#define WPS_ID_R_HASH1            0x103D\n#define WPS_ID_R_HASH2            0x103E\n#define WPS_ID_R_SNONCE1          0x103F\n#define WPS_ID_R_SNONCE2          0x1040\n#define WPS_ID_SEL_REGISTRAR      0x1041\n#define WPS_ID_SERIAL_NUM         0x1042\n#define WPS_ID_SC_STATE           0x1044\n#define WPS_ID_SSID               0x1045\n#define WPS_ID_TOT_NETWORKS       0x1046\n#define WPS_ID_UUID_E             0x1047\n#define WPS_ID_UUID_R             0x1048\n#define WPS_ID_VENDOR_EXT         0x1049\n#define WPS_ID_VERSION            0x104A\n#define WPS_ID_X509_CERT_REQ      0x104B\n#define WPS_ID_X509_CERT          0x104C\n#define WPS_ID_EAP_IDENTITY       0x104D\n#define WPS_ID_MSG_COUNTER        0x104E\n#define WPS_ID_PUBKEY_HASH        0x104F\n#define WPS_ID_REKEY_KEY          0x1050\n#define WPS_ID_KEY_LIFETIME       0x1051\n#define WPS_ID_PERM_CFG_METHODS   0x1052\n#define WPS_ID_SEL_REG_CFG_METHODS_ORIGINAL 0x0153    // This was the original val in the spec, we must support both\n#define WPS_ID_SEL_REG_CFG_METHODS 0x1053\n#define WPS_ID_PRIM_DEV_TYPE      0x1054\n#define WPS_ID_SEC_DEV_TYPE_LIST  0x1055\n#define WPS_ID_PORTABLE_DEVICE    0x1056\n#define WPS_ID_AP_SETUP_LOCKED    0x1057\n#define WPS_ID_APP_LIST           0x1058\n#define WPS_ID_EAP_TYPE           0x1059\n\n// Association states\n#define WPS_ASSOC_NOT_ASSOCIATED  0\n#define WPS_ASSOC_CONN_SUCCESS    1\n#define WPS_ASSOC_CONFIG_FAIL     2\n#define WPS_ASSOC_ASSOC_FAIL      3\n#define WPS_ASSOC_IP_FAIL         4\n\n// Authentication types\n#define WPS_AUTHTYPE_OPEN        0x0001\n#define WPS_AUTHTYPE_WPAPSK      0x0002\n#define WPS_AUTHTYPE_SHARED      0x0004\n#define WPS_AUTHTYPE_WPA         0x0008\n#define WPS_AUTHTYPE_WPA2        0x0010\n#define WPS_AUTHTYPE_WPA2PSK     0x0020\n\n// Config methods\n#define WPS_CONFMET_USBA            0x0001\n#define WPS_CONFMET_ETHERNET        0x0002\n#define WPS_CONFMET_LABEL           0x0004\n#define WPS_CONFMET_DISPLAY         0x0008\n#define WPS_CONFMET_EXT_NFC_TOK     0x0010\n#define WPS_CONFMET_INT_NFC_TOK     0x0020\n#define WPS_CONFMET_NFC_INTF        0x0040\n#define WPS_CONFMET_PBC             0x0080\n#define WPS_CONFMET_KEYPAD          0x0100\n\n// WPS error messages\n#define WPS_ERROR_NO_ERROR                0\n#define WPS_ERROR_OOB_INT_READ_ERR        1\n#define WPS_ERROR_DECRYPT_CRC_FAIL        2\n#define WPS_ERROR_CHAN24_NOT_SUPP         3\n#define WPS_ERROR_CHAN50_NOT_SUPP         4\n#define WPS_ERROR_SIGNAL_WEAK             5\n#define WPS_ERROR_NW_AUTH_FAIL            6\n#define WPS_ERROR_NW_ASSOC_FAIL           7\n#define WPS_ERROR_NO_DHCP_RESP            8\n#define WPS_ERROR_FAILED_DHCP_CONF        9\n#define WPS_ERROR_IP_ADDR_CONFLICT        10\n#define WPS_ERROR_FAIL_CONN_REGISTRAR     11\n#define WPS_ERROR_MULTI_PBC_DETECTED      12\n#define WPS_ERROR_ROGUE_SUSPECTED         13\n#define WPS_ERROR_DEVICE_BUSY             14\n#define WPS_ERROR_SETUP_LOCKED            15\n#define WPS_ERROR_MSG_TIMEOUT             16\n#define WPS_ERROR_REG_SESSION_TIMEOUT     17\n#define WPS_ERROR_DEV_PWD_AUTH_FAIL       18\n\n#define WPS_ERROR_MAX                      WPS_ERROR_DEV_PWD_AUTH_FAIL\n\n// Connection types\n#define WPS_CONNTYPE_ESS    0x01\n#define WPS_CONNTYPE_IBSS   0x02\n\n// Device password ID\n#define WPS_DEVICEPWDID_DEFAULT          0x0000\n#define WPS_DEVICEPWDID_USER_SPEC        0x0001\n#define WPS_DEVICEPWDID_MACHINE_SPEC     0x0002\n#define WPS_DEVICEPWDID_REKEY            0x0003\n#define WPS_DEVICEPWDID_PUSH_BTN         0x0004\n#define WPS_DEVICEPWDID_REG_SPEC         0x0005\n\n/*\n // Device type\n #define WPS_DEVICETYPE_COMPUTER            \"Computer\"\n #define WPS_DEVICETYPE_AP                  \"Access_Point\"\n #define WPS_DEVICETYPE_ROUTER_AP           \"Router_AP\"\n #define WPS_DEVICETYPE_PRINTER             \"Printer\"\n #define WPS_DEVICETYPE_PRINTER_BRIDGE      \"Printer_Brigde\"\n #define WPS_DEVICETYPE_ELECT_PIC_FRAME     \"Electronic_Picture_Frame\"\n #define WPS_DEVICETYPE_DIG_AUDIO_RECV      \"Digital_Audio_Receiver\"\n #define WPS_DEVICETYPE_WIN_MCE             \"Windows_Media_Center_Extender\"\n #define WPS_DEVICETYPE_WIN_MOBILE          \"Windows_Mobile\"\n #define WPS_DEVICETYPE_PVR                 \"Personal_Video_Recorder\"\n #define WPS_DEVICETYPE_VIDEO_STB           \"Video_STB\"\n #define WPS_DEVICETYPE_PROJECTOR           \"Projector\"\n #define WPS_DEVICETYPE_IP_TV               \"IP_TV\"\n #define WPS_DEVICETYPE_DIG_STILL_CAM       \"Digital_Still_Camera\"\n #define WPS_DEVICETYPE_PHONE               \"Phone\"\n #define WPS_DEVICETYPE_VOID_PHONE          \"VoIP_Phone\"\n #define WPS_DEVICETYPE_GAME_CONSOLE        \"Game_console\"\n #define WPS_DEVICETYPE_OTHER               \"Other\"\n */\n\n// Encryption type\n#define WPS_ENCRTYPE_NONE    0x0001\n#define WPS_ENCRTYPE_WEP     0x0002\n#define WPS_ENCRTYPE_TKIP    0x0004\n#define WPS_ENCRTYPE_AES     0x0008\n\n\n// WPS Message Types\n#define WPS_ID_BEACON            0x01\n#define WPS_ID_PROBE_REQ         0x02\n#define WPS_ID_PROBE_RESP        0x03\n#define WPS_ID_MESSAGE_M1        0x04\n#define WPS_ID_MESSAGE_M2        0x05\n#define WPS_ID_MESSAGE_M2D       0x06\n#define WPS_ID_MESSAGE_M3        0x07\n#define WPS_ID_MESSAGE_M4        0x08\n#define WPS_ID_MESSAGE_M5        0x09\n#define WPS_ID_MESSAGE_M6        0x0A\n#define WPS_ID_MESSAGE_M7        0x0B\n#define WPS_ID_MESSAGE_M8        0x0C\n#define WPS_ID_MESSAGE_ACK       0x0D\n#define WPS_ID_MESSAGE_NACK      0x0E\n#define WPS_ID_MESSAGE_DONE      0x0F\n\n//Device Type categories for primary and secondary device types\n#define WPS_DEVICE_TYPE_CAT_COMPUTER        1\n#define WPS_DEVICE_TYPE_CAT_INPUT_DEVICE    2\n#define WPS_DEVICE_TYPE_CAT_PRINTER         3\n#define WPS_DEVICE_TYPE_CAT_CAMERA          4\n#define WPS_DEVICE_TYPE_CAT_STORAGE         5\n#define WPS_DEVICE_TYPE_CAT_NW_INFRA        6\n#define WPS_DEVICE_TYPE_CAT_DISPLAYS        7\n#define WPS_DEVICE_TYPE_CAT_MM_DEVICES      8\n#define WPS_DEVICE_TYPE_CAT_GAME_DEVICES    9\n#define WPS_DEVICE_TYPE_CAT_TELEPHONE       10\n\n//Device Type sub categories for primary and secondary device types\n#define WPS_DEVICE_TYPE_SUB_CAT_COMP_PC         1\n#define WPS_DEVICE_TYPE_SUB_CAT_COMP_SERVER     2\n#define WPS_DEVICE_TYPE_SUB_CAT_COMP_MEDIA_CTR  3\n#define WPS_DEVICE_TYPE_SUB_CAT_PRTR_PRINTER    1\n#define WPS_DEVICE_TYPE_SUB_CAT_PRTR_SCANNER    2\n#define WPS_DEVICE_TYPE_SUB_CAT_CAM_DGTL_STILL  1\n#define WPS_DEVICE_TYPE_SUB_CAT_STOR_NAS        1\n#define WPS_DEVICE_TYPE_SUB_CAT_NW_AP           1\n#define WPS_DEVICE_TYPE_SUB_CAT_NW_ROUTER       2\n#define WPS_DEVICE_TYPE_SUB_CAT_NW_SWITCH       3\n#define WPS_DEVICE_TYPE_SUB_CAT_DISP_TV         1\n#define WPS_DEVICE_TYPE_SUB_CAT_DISP_PIC_FRAME  2\n#define WPS_DEVICE_TYPE_SUB_CAT_DISP_PROJECTOR  3\n#define WPS_DEVICE_TYPE_SUB_CAT_MM_DAR          1\n#define WPS_DEVICE_TYPE_SUB_CAT_MM_PVR          2\n#define WPS_DEVICE_TYPE_SUB_CAT_MM_MCX          3\n#define WPS_DEVICE_TYPE_SUB_CAT_GAM_XBOX        1\n#define WPS_DEVICE_TYPE_SUB_CAT_GAM_XBOX_360    2\n#define WPS_DEVICE_TYPE_SUB_CAT_GAM_PS          3\n#define WPS_DEVICE_TYPE_SUB_CAT_PHONE_WM        1\n\n// Device request/response type\n#define WPS_MSGTYPE_ENROLLEE_INFO_ONLY    0x00\n#define WPS_MSGTYPE_ENROLLEE_OPEN_8021X   0x01\n#define WPS_MSGTYPE_REGISTRAR             0x02\n#define WPS_MSGTYPE_AP_WLAN_MGR           0x03\n\n// RF Band\n#define WPS_RFBAND_24GHZ    0x01\n#define WPS_RFBAND_50GHZ    0x02\n\n// Simple Config state\n#define WPS_SCSTATE_UNCONFIGURED    0x01\n#define WPS_SCSTATE_CONFIGURED      0x02\n\n// State business\n#define WPS_RETRY_INTERVAL    5    /* seconds */\n#define WPS_PACKET_TIMEOUT    15    /* seconds */\n\n#define WPS_TIMEOUT_SECS 1\n\nenum WPSSupplicantState\n{\n    WPS_S_INIT,\n    WPS_S_EAPOL_START_TX,\n    WPS_S_EAPOL_START_RX,\n    WPS_S_IDENT_REQ_TX,\n    WPS_S_IDENT_REQ_RX,\n    WPS_S_IDENT_RESP_TX,\n    WPS_S_IDENT_RESP_RX,\n    WPS_S_START_TX,\n    WPS_S_START_RX,\n    WPS_S_M1_TX,\n    WPS_S_M1_RX,\n    WPS_S_M2_TX,\n    WPS_S_M2_RX,\n    WPS_S_M3_TX,\n    WPS_S_M3_RX,\n    WPS_S_M4_TX,\n    WPS_S_M4_RX,\n    WPS_S_M5_TX,\n    WPS_S_M5_RX,\n    WPS_S_M6_TX,\n    WPS_S_M6_RX,\n    WPS_S_M7_TX,\n    WPS_S_M7_RX,\n    WPS_S_M8_TX,\n    WPS_S_M8_RX,\n    WPS_S_DONE_TX,\n    WPS_S_DONE_RX,\n    WPS_S_FAIL_TX,\n    WPS_S_FAIL_RX,\n    WPS_S_MSG_TIMEOUT,\n    WPS_S_SESSION_TIMEOUT,\n};\ntypedef enum WPSSupplicantState WPSSupplicantState;\n\n// Apple specific error codes\n\n#define WPSE_NOERR                     0        // no error\n#define WPSE_ERR                      -1        // general error code\n#define    WPSE_PROTO_ERR             -2        // Problem with EAPOL handshake\n#define    WPSE_IE_NOT_PRESENT        -3        // No WPS IE present in IE list for ssid\n#define    WPSE_IE_MALFORMED          -4        // WPS IS missing required (for Apple) fields\n#define    WPSE_SCAN_ERR              -5        // Scan failed\n#define    WPSE_NO_PIN_AT_REG         -6        // No PIN configured at registrar\n#define WPSE_NO_PIN_AT_CLIENT         -7        // No PIN configured at client\n#define    WPSE_SSID_NOT_FOUND        -8        // Scan did not find SSID\n#define    WPSE_UNSUPPORTED_PW_ID     -9        // Registrar reports that it is using an unsupported PW ID\n#define    WPSE_ASSOC_FAILED          -10       // Association attempt failed\n#define WPSE_API_REQ                  -11       // An apple80211 ioctl request failed\n#define WPSE_NOMEM                    -12       // memory error\n#define WPSE_WPA_RSN_NOT_SUP          -13       // WPA/RSN not supported\n#define WPSE_TIMEOUT                  -14       // EAPOL timed out\n#define WPSE_NACKED                   -15       // NACKED by registrar\n#define WPSE_FAIL                     -16       // unexpected EAP-FAIL received\n\n#endif /* _APPLE80211_WPS_H_ */\n"
  },
  {
    "path": "include/Airport/apple_private_spi.h",
    "content": "/*\n* Copyright (c) 1998-2016 Apple Inc. All rights reserved.\n*\n* @APPLE_OSREFERENCE_LICENSE_HEADER_START@\n*\n* This file contains Original Code and/or Modifications of Original Code\n* as defined in and that are subject to the Apple Public Source License\n* Version 2.0 (the 'License'). You may not use this file except in\n* compliance with the License. The rights granted to you under the License\n* may not be used to create, or enable the creation or redistribution of,\n* unlawful or unlicensed copies of an Apple operating system, or to\n* circumvent, violate, or enable the circumvention or violation of, any\n* terms of an Apple operating system software license agreement.\n*\n* Please obtain a copy of the License at\n* http://www.opensource.apple.com/apsl/ and read it before using this file.\n*\n* The Original Code and all software distributed under the License are\n* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER\n* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,\n* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,\n* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.\n* Please see the License for the specific language governing rights and\n* limitations under the License.\n*\n* @APPLE_OSREFERENCE_LICENSE_HEADER_END@\n*/\n\n#ifndef apple_private_spi_h\n#define apple_private_spi_h\n\n#ifndef __PRIVATE_SPI__\n\n/*! @enum IOMbufServiceClass\n    @discussion Service class of a mbuf packet.\n    @constant kIOMbufServiceClassBKSYS Background System-Initiated.\n    @constant kIOMbufServiceClassBK  Background.\n    @constant kIOMbufServiceClassBE  Best Effort.\n    @constant kIOMbufServiceClassRD  Responsive Data.\n    @constant kIOMbufServiceClassOAM Operations, Administration, and Management.\n    @constant kIOMbufServiceClassAV  Multimedia Audio/Video Streaming.\n    @constant kIOMbufServiceClassRV  Responsive Multimedia Audio/Video.\n    @constant kIOMbufServiceClassVI  Interactive Video.\n    @constant kIOMbufServiceClassVO  Interactive Voice.\n    @constant kIOMbufServiceClassCTL Network Control.\n*/\nenum IOMbufServiceClass {\n    kIOMbufServiceClassBKSYS    = 100,\n    kIOMbufServiceClassBK       = 200,\n    kIOMbufServiceClassBE       = 0,\n    kIOMbufServiceClassRD       = 300,\n    kIOMbufServiceClassOAM      = 400,\n    kIOMbufServiceClassAV       = 500,\n    kIOMbufServiceClassRV       = 600,\n    kIOMbufServiceClassVI       = 700,\n    kIOMbufServiceClassVO       = 800,\n    kIOMbufServiceClassCTL      = 900\n};\n\n#endif\n\nstruct packet_info_tag {\n    \n};\n\nstruct apple80211_debug_command {\n    \n};\n\nstruct ifnet_init_eparams {\n    \n};\n\n#endif /* apple_private_spi_h */\n"
  },
  {
    "path": "include/Airport/debug.h",
    "content": "//\n//  debug.h\n//  Black80211_HighSierra\n//\n//  Created by Roman Peshkov on 05/07/2018.\n//  Copyright © 2018 Roman Peshkov. All rights reserved.\n//\n\n#ifndef debug_h\n#define debug_h\n\nstatic const char* IOCTL_NAMES[] = {\n     \"UNKNOWN\",\n     \"SSID\",\n     \"AUTH_TYPE\",\n     \"CIPHER_KEY\",\n     \"CHANNEL\",\n     \"POWERSAVE\",\n     \"PROTMODE\",\n     \"TXPOWER\",\n     \"RATE\",\n     \"BSSID\",\n     \"SCAN_REQ\",\n     \"SCAN_RESULT\",\n     \"CARD_CAPABILITIES\",\n     \"STATE\",\n     \"PHY_MODE\",\n     \"OP_MODE\",\n     \"RSSI\",\n     \"NOISE\",\n     \"INT_MIT\",\n     \"POWER\",\n     \"ASSOCIATE\",\n     \"ASSOCIATE_RESULT\",\n     \"DISASSOCIATE\",\n     \"STATUS_DEV_NAME\",\n     \"IBSS_MODE\",\n     \"HOST_AP_MODE\",\n     \"AP_MODE\",\n     \"SUPPORTED_CHANNELS\",\n     \"LOCALE\",\n     \"DEAUTH\",\n     \"COUNTERMEASURES\",\n     \"FRAG_THRESHOLD\",\n     \"RATE_SET\",\n     \"SHORT_SLOT\",\n     \"MULTICAST_RATE\",\n     \"SHORT_RETRY_LIMIT\",\n     \"LONG_RETRY_LIMIT\",\n     \"TX_ANTENNA\",\n     \"RX_ANTENNA\",\n     \"ANTENNA_DIVERSITY\",\n     \"ROM\",\n     \"DTIM_INT\",\n     \"STATION_LIST\",\n     \"DRIVER_VERSION\",\n     \"HARDWARE_VERSION\",\n     \"RAND\",\n     \"RSN_IE\",\n     \"BACKGROUND_SCAN\",\n     \"AP_IE_LIST\",\n     \"STATS\",\n     \"ASSOCIATION_STATUS\",\n     \"COUNTRY_CODE\",\n     \"DEBUG_FLAGS\",\n     \"LAST_RX_PKT_DATA\",\n     \"RADIO_INFO\",\n     \"GUARD_INTERVAL\",\n     \"MIMO_POWERSAVE\",\n     \"MCS\",\n     \"RIFS\",\n     \"LDPC\",\n     \"MSDU\",\n     \"MPDU\",\n     \"BLOCK_ACK\",\n     \"PLS\",\n     \"PSMP\",\n     \"PHY_SUB_MODE\",\n     \"MCS_INDEX_SET\",\n     \"CACHE_THRESH_BCAST\",\n     \"CACHE_THRESH_DIRECT\",\n     \"WOW_PARAMETERS\",\n     \"WOW_ENABLED\",\n     \"40MHZ_INTOLERANT\",\n     \"PID_LOCK\",\n     \"STA_IE_LIST\",\n     \"STA_AUTHORIZE\",\n     \"STA_DISASSOCIATE\",\n     \"STA_DEAUTH\",\n     \"RSN_CONF\",\n     \"KEY_RSC\",\n     \"STA_STATS\",\n     \"ROAM_THRESH\",\n     \"VENDOR_DBG_FLAGS\",\n     \"CACHE_AGE_THRESH\",\n     \"PMK_CACHE\",\n     \"LINK_QUAL_EVENT_PARAMS\",\n     \"IE\",\n     \"SCAN_REQ_MULTIPLE\",\n     \"BTCOEX_MODE\",\n     \"WOW_TEST\",\n     \"CLEAR_PMK_CACHE\",\n     \"SCANCACHE_CLEAR\",\n     \"P2P_ENABLE\",\n     \"P2P_LISTEN\",\n     \"P2P_SCAN\",\n     \"VIRTUAL_IF_CREATE\",\n     \"VIRTUAL_IF_DELETE\",\n     \"VIRTUAL_IF_ROLE\",\n     \"VIRTUAL_IF_PARENT\",\n     \"P2P_GO_CONF\",\n     \"P2P_NOA_LIST\",\n     \"P2P_OPP_PS\",\n     \"P2P_CT_WINDOW\",\n     \"BT_COEX_FLAGS\",\n     \"CURRENT_NETWORK\",\n     \"BT_POWER\",\n     \"AVAILABILITY\",\n     \"RSSI_BOUNDS\",\n     \"ROAM\",\n     \"TX_CHAIN_POWER\",\n     \"CDD_MODE\",\n     \"LAST_BCAST_SCAN_TIME\",\n     \"THERMAL_THROTTLING\",\n     \"FACTORY_MODE\",\n     \"REASSOCIATE\",\n     \"???MISSING???\",\n     \"POWER_DEBUG_INFO\",\n     \"AWDL_SYNC_PARAMS\",\n     \"AWDL_SYNC_ENABLED\",\n     \"AWDL_EXTENSION_STATE_MACHINE_PARAMETERS\",\n     \"AWDL_SERVICE_PARAMS\",\n     \"AWDL_PEER_SERVICE_REQUEST\",\n     \"AWDL_ELECTION_ALGORITHM_ENABLED\",\n     \"AWDL_ELECTION_ID\",\n     \"AWDL_MAX_TREE_DEPTH\",\n     \"AWDL_GUARD_TIME\",\n     \"AWDL_BSSID\",\n     \"AWDL_ELECTION_METRIC\",\n     \"AWDL_AVAILABILITY_WINDOW_AP_ALIGNMENT\",\n     \"AWDL_SYNC_FRAME_AP_BEACON_ALIGNMENT\",\n     \"AWDL_SYNCHRONIZATION_CHANNEL_SEQUENCE\",\n     \"PEER_CACHE_MAXIMUM_SIZE\",\n     \"AWDL_OUI\",\n     \"AWDL_MASTER_CHANNEL\",\n     \"AWDL_TOP_MASTER\",\n     \"AWDL_SYNC_STATE\",\n     \"AWDL_ELECTION_RSSI_THRESHOLDS\",\n     \"AWDL_PRESENCE_MODE\",\n     \"AWDL_ELECTION_MASTER_COUNTS\",\n     \"AWDL_PERIODIC_SYNC_FRAME_PACKET_LIFETIME\",\n     \"AWDL_MASTER_MODE_SYNC_FRAME_PERIOD\",\n     \"AWDL_NON_ELECTION_MASTER_MODE_SYNC_FRAME_PERIOD\",\n     \"AWDL_EXPLICIT_AVAILABILITY_WINDOW_EXTENSION_OPT_OUT\",\n     \"AWDL_GET_AWDL_MASTER_DATABASE\",\n     \"PEER_CACHE_CONTROL\",\n     \"AWDL_BATTERY_LEVEL\",\n     \"AWDL_BT_COEX_AW_PROTECTED_PERIOD_LENGTH\",\n     \"AWDL_BT_COEX_AGREEMENT\",\n     \"AWDL_BT_COEX_AGREEMENT_ENABLED\",\n     \"AWDL_STRATEGY\",\n     \"AWDL_OOB_REQUEST\",\n     \"AWDL_MAX_NO_MASTER_PERIODS\",\n     \"AWDL_SYNC_FRAME_TEMPLATE\",\n     \"LOG_FLAGS\",\n     \"PEER_STATS\",\n     \"HT_CAPABILITY\",\n     \"AWDL_ELECTION_PARAMS\",\n     \"LINK_CHANGED_EVENT_DATA\",\n     \"GET_DEBUG_INFO\",\n     \"AWDL_DEVICE_CAPABILITIES\",\n     \"AWDL_RSSI_MEASUREMENT_REQUEST\",\n     \"AWDL_AES_KEY\",\n     \"AWDL_SCAN_RESERVED_TIME\",\n     \"AWDL_CTL\",\n     \"AWDL_SOCIAL_TIME_SLOTS\",\n     \"AWDL_PEER_TRAFFIC_REGISTRATION\",\n     \"EXTENDED_STATS\",\n     \"BEACON_PERIOD\",\n     \"AWDL_FORCED_ROAM_CONFIG\",\n     \"AWDL_QUIET\",\n     \"ACL_POLICY\",\n     \"ACL_ADD\",\n     \"ACL_REMOVE\",\n     \"ACL_FLUSH\",\n     \"ACL_LIST\",\n     \"CHAIN_ACK\",\n     \"DESENSE\",\n     \"OFFLOAD_SCANNING\",\n     \"OFFLOAD_RSN\",\n     \"OFFLOAD_COUNTRY_CODE\",\n     \"OFFLOAD_KEEPALIVE_L2\",\n     \"OFFLOAD_ARP_NDP\",\n     \"VHT_MCS_INDEX_SET\",\n     \"DWDS\",\n     \"INTERRUPT_STATS\",\n     \"INTERRUPT_STATS_RESET\",\n     \"TIMER_STATS\",\n     \"TIMER_STATS_RESET\",\n     \"OFFLOAD_STATS\",\n     \"OFFLOAD_STATS_RESET\",\n     \"OFFLOAD_BEACONS\",\n     \"ROAMING\",\n     \"OFFLOAD_ARP\",\n     \"OFFLOAD_NDP\",\n     \"OFFLOAD_SCAN\",\n     \"DESENSE_LEVEL\",\n     \"MCS_VHT\",\n     \"TX_NSS\",\n     \"GAS_REQ\",\n     \"GAS_START\",\n     \"GAS_SET_PEER\",\n     \"GAS_RESULTS\",\n     \"AWDL_BTLE_PEER_INDICATION\",\n     \"AWDL_BTLE_STATE_PARAMS\",\n     \"AWDL_PEER_DATABASE\",\n     \"AWDL_BTLE_ENABLE_SYNC_WITH_PARAMS\",\n     \"AWDL_SECONDARY_MASTER_CHANNEL\",\n     \"PHY_STATS\",\n     \"CHANNELS_INFO\",\n     \"AWDL_AF_TX_MODE\",\n     \"ERROR_STRING\",\n     \"ERROR_NO\",\n     \"AWDL_PIGGYBACK_SCAN_REQ\",\n     \"AWDL_PRIVATE_ELECTION_ID\",\n     \"AWDL_MIN_RATE\",\n     \"VHT_CAPABILITY\",\n     \"BGSCAN_CACHE_RESULTS\",\n     \"ROAM_PROFILE\",\n     \"AWDL_OPER_MODE\",\n     \"RESTORE_DEFAULTS\",\n     \"AWDL_ENCRYPTION_KEYS\",\n     \"AWDL_ENCRYPTION_TYPE\",\n     \"BTCOEX_PROFILES\",\n     \"BTCOEX_CONFIG\",\n     \"AWDL_STATISTICS\",\n     \"AWDL_ENABLE_ROAMING\",\n     \"AWDL_OOB_AUTO_REQUEST\",\n     \"AWDL_TXCAL_PERIOD\",\n     \"CHIP_COUNTER_STATS\",\n     \"DBG_GUARD_TIME_PARAMS\",\n     \"AWDL_AWDL_ADVERTISERS\",\n     \"LEAKY_AP_STATS_MODE\",\n     \"CAPTURE\",\n     \"LEAKY_AP_STATS\",\n     \"AWDL_BLOCK_SET_COMMANDS\",\n     \"LEAKY_AP_AWD_MODE\",\n     \"BTCOEX_OPTIONS\",\n     \"FORCE_SYNC_TO_PEER\",\n     \"COUNTRY_CHANNELS\",\n     \"PRIVATE_MAC\",\n     \"RESET_CHIP\",\n     \"CRASH\",\n     \"RANGING_ENABLE\",\n     \"RANGING_START\",\n     \"RANGING_AUTHENTICATE\",\n     \"AWDL_PREFERRED_CHANNELS\",\n     \"LEAKY_AP_SSID_STATS\",\n     \"AWDL_RSDB_CAPS\",\n     \"AWDL_DEV_STATS\",\n     \"LAST_ASSOC_HISTORY\",\n     \"AWDL_COMMON_CHANNEL\",\n     \"AWDL_PEERS_INFO\",\n     \"TKO_PARAMS\",\n     \"TKO_DUMP\",\n     \"AWDL_NEARBY_LOG_TRIGGER\",\n     \"HW_SUPPORTED_CHANNELS\",\n     \"BTCOEX_PROFILE\",\n     \"BTCOEX_PROFILE_ACTIVE\",\n     \"TRAP_INFO\",\n     \"THERMAL_INDEX\",\n     \"MAX_NSS_FOR_AP\",\n     \"BTCOEX_2G_CHAIN_DISABLE\",\n     \"POWER_BUDGET\",\n     \"AWDL_DFSP_CONFIG\",\n     \"AWDL_DFSP_UCSA_CONFIG\",\n     \"SCAN_BACKOFF_REPORT\",\n     \"OFFLOAD_TCPKA_ENABLE\",\n     \"RANGING_CAPS\",\n     \"PER_CORE_RSSI_REPORT/SUPPRESS_SCANS\",\n};\n\n#endif /* debug_h */\n"
  },
  {
    "path": "include/ClientKit/Common.h",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n\n#ifndef Common_h\n#define Common_h\n\n#include \"IoctlId.h\"\n\n#define IOCTL_MASK 0x800000\n#define IOCTL_VERSION 1\n#define NWID_LEN 32\n#define WPA_KEY_LEN 128\n\n#define kIONoScanResult 20008\n\nstruct ioctl_driver_info {\n    unsigned int version;\n    char fw_version[32];    //firmware version string\n    char driver_version[32];    //driver version string\n    char bsd_name[32];  //interface bsd name, eg. en1\n};\n\nenum itl_phy_mode {\n    ITL80211_MODE_11A,\n    ITL80211_MODE_11B,\n    ITL80211_MODE_11G,\n    ITL80211_MODE_11N,\n    ITL80211_MODE_11AC,\n    ITL80211_MODE_11AX\n};\n\nstruct ioctl_sta_info {\n    unsigned int version;\n    enum itl_phy_mode op_mode;\n    int max_mcs;\n    int cur_mcs;\n    uint channel;\n    uint16_t band_width;//20 40 80 160\n    int16_t rssi;\n    int16_t noise;\n    uint rate;\n    unsigned char ssid[NWID_LEN];\n    uint8_t bssid[ETHER_ADDR_LEN];\n};\n\nstruct ioctl_power {\n    unsigned int version;\n    unsigned int enabled;    //1 == on, 0 == off\n    unsigned int maxsleep;   //max sleep in ms\n};\n\nenum itl_80211_state {\n    ITL80211_S_INIT    = 0,    /* default state */\n    ITL80211_S_SCAN    = 1,    /* scanning */\n    ITL80211_S_AUTH    = 2,    /* try to authenticate */\n    ITL80211_S_ASSOC    = 3,    /* try to assoc */\n    ITL80211_S_RUN        = 4    /* associated */\n};\n\nstruct ioctl_state {\n    unsigned int version;\n    int state; //itl_80211_state\n};\n\nstruct ioctl_nw_id {\n    unsigned int version;\n    unsigned int len;\n    char nwid[NWID_LEN];\n};\n\nstruct ioctl_nw_bssid {\n    unsigned int version;\n    char bssid[ETHER_ADDR_LEN];\n};\n\nstruct ioctl_wpa_key {\n    unsigned int version;\n    unsigned int len;\n    char key[WPA_KEY_LEN];\n};\n\nstruct ioctl_associate {\n    unsigned int version;\n    struct ioctl_nw_id nwid;\n    struct ioctl_wpa_key wpa_key;\n};\n\nstruct ioctl_disassociate {\n    unsigned int version;\n    unsigned char ssid[NWID_LEN];\n};\n\nstruct ioctl_join {\n    unsigned int version;\n    struct ioctl_nw_id nwid;\n    struct ioctl_wpa_key wpa_key;\n};\n\nstruct ioctl_scan {\n    unsigned int version;\n};\n\nstruct ioctl_scan_result {\n    unsigned int version;\n};\n\nstruct ioctl_tx_power {\n    unsigned int version;\n};\n\n/*\n * 802.11 ciphers.\n */\nenum itl80211_cipher {\n    ITL80211_CIPHER_NONE        = 0x00000000,\n    ITL80211_CIPHER_USEGROUP    = 0x00000001,\n    ITL80211_CIPHER_WEP40        = 0x00000002,\n    ITL80211_CIPHER_TKIP        = 0x00000004,\n    ITL80211_CIPHER_CCMP        = 0x00000008,\n    ITL80211_CIPHER_WEP104        = 0x00000010,\n    ITL80211_CIPHER_BIP        = 0x00000020    /* 11w */\n};\n\nenum itl80211_wpa_proto {\n    ITL80211_WPA_PROTO_WPA1 = 0x01,\n    ITL80211_WPA_PROTO_WPA2 = 0x02\n};\n\nenum itl80211_proto {\n    ITL80211_PROTO_NONE = 0,\n    ITL80211_PROTO_RSN = 1 << 0,\n    ITL80211_PROTO_WPA = 1 << 1\n};\n\n/*\n * 802.11 Authentication and Key Management Protocols.\n */\nenum itl80211_akm {\n    ITL80211_AKM_NONE        = 0x00000000,\n    ITL80211_AKM_8021X        = 0x00000001,\n    ITL80211_AKM_PSK        = 0x00000002,\n    ITL80211_AKM_SHA256_8021X    = 0x00000004,    /* 11w */\n    ITL80211_AKM_SHA256_PSK    = 0x00000008    /* 11w */\n};\n\nstruct ioctl_network_info {\n    unsigned char ssid[NWID_LEN];\n    int16_t noise;\n    int16_t rssi;\n    uint8_t bssid[ETHER_ADDR_LEN];\n    uint32_t channel;\n    unsigned int supported_rsnprotos;   //itl80211_proto\n    unsigned int rsn_protos;    //itl80211_wpa_proto\n    unsigned int supported_rsnakms; //itl80211_akm\n    unsigned int rsn_akms;  //rsn_akms\n    unsigned int rsn_ciphers;\n    enum itl80211_cipher    rsn_groupcipher;\n    enum itl80211_cipher    rsn_groupmgmtcipher;\n    u_int16_t        ni_rsncaps;\n    enum itl80211_cipher    ni_rsncipher;\n    uint32_t recv_timestamp;\n};\n\n#endif /* Common_h */\n"
  },
  {
    "path": "include/ClientKit/IoctlId.h",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n\n#ifndef IoctlId_h\n#define IoctlId_h\n\nenum IOCTL_IDS {\n    IOCTL_80211_DRIVER_INFO,\n    IOCTL_80211_STA_INFO,\n    IOCTL_80211_POWER,\n    IOCTL_80211_STATE,\n    IOCTL_80211_NW_ID,\n    IOCTL_80211_WPA_KEY,\n    IOCTL_80211_ASSOCIATE,\n    IOCTL_80211_DISASSOCIATE,\n    IOCTL_80211_JOIN,\n    IOCTL_80211_SCAN,\n    IOCTL_80211_SCAN_RESULT,\n    IOCTL_80211_TX_POWER_LEVEL,\n    IOCTL_80211_NW_BSSID,\n    \n    IOCTL_ID_MAX\n};\n\n#endif /* IoctlId_h */\n"
  },
  {
    "path": "include/FwData.h",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n\n#ifndef FwData_h\n#define FwData_h\n\n#include <string.h>\n#include <libkern/c++/OSData.h>\n#include <libkern/zlib.h>\n#include <zutil.h>\n\nstruct FwDesc {\n    const char *name;\n    const unsigned char *var;\n    const int size;\n};\n\n#define IWL_FW(fw_name, fw_var, fw_size) \\\n    .name = fw_name, .var = fw_var, .size = fw_size\n\n\nextern const struct FwDesc fwList[];\nextern const int fwNumber;\n\nstatic inline OSData *getFWDescByName(const char* name) {\n    for (int i = 0; i < fwNumber; i++) {\n        if (strcmp(fwList[i].name, name) == 0) {\n            FwDesc desc = fwList[i];\n            return OSData::withBytes(desc.var, desc.size);\n        }\n    }\n    return NULL;\n}\n\nstatic inline bool uncompressFirmware(unsigned char *dest, uint *destLen, unsigned char *source, uint sourceLen)\n{\n    z_stream stream;\n    int err;\n    \n    stream.next_in = source;\n    stream.avail_in = sourceLen;\n    stream.next_out = dest;\n    stream.avail_out = *destLen;\n    stream.zalloc = zcalloc;\n    stream.zfree = zcfree;\n    err = inflateInit(&stream);\n    if (err != Z_OK) {\n        return false;\n    }\n    err = inflate(&stream, Z_FINISH);\n    if (err != Z_STREAM_END) {\n        inflateEnd(&stream);\n        return false;\n    }\n    *destLen = (uint)stream.total_out;\n\n    err = inflateEnd(&stream);\n    return err == Z_OK;\n}\n\n#endif /* FwData_h */\n"
  },
  {
    "path": "include/HAL/ItlDriverController.hpp",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n\n#ifndef ItlDriverController_h\n#define ItlDriverController_h\n\nclass ItlDriverController {\n    \npublic:\n    \n    virtual void clearScanningFlags() = 0;\n    \n    virtual IOReturn setMulticastList(IOEthernetAddress *addr, int count) = 0;\n};\n\n#endif /* ItlDriverController_h */\n"
  },
  {
    "path": "include/HAL/ItlDriverInfo.hpp",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n\n#ifndef ItlDriverInfo_h\n#define ItlDriverInfo_h\n\nclass ItlDriverInfo {\n    \npublic:\n    \n    virtual const char *getFirmwareVersion() = 0;\n    \n    virtual int16_t getBSSNoise() = 0;\n    \n    virtual bool is5GBandSupport() = 0;\n    \n    virtual int getTxNSS() = 0;\n    \n    virtual const char *getFirmwareName() = 0;\n    \n    virtual UInt32 supportedFeatures() = 0;\n\n    virtual const char *getFirmwareCountryCode() = 0;\n\n    virtual uint32_t getTxQueueSize() = 0;\n};\n\n#endif /* ItlDriverInfo_h */\n"
  },
  {
    "path": "include/HAL/ItlHalService.cpp",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n\n#include \"ItlHalService.hpp\"\n\n#define super OSObject\nOSDefineMetaClassAndAbstractStructors(ItlHalService, OSObject)\n\nbool ItlHalService::\ninitWithController(IOEthernetController *controller, IOWorkLoop *workloop, IOCommandGate *commandGate)\n{\n    this->controller = controller;\n    this->controller->retain();\n    this->mainWorkLoop = workloop;\n    this->mainWorkLoop->retain();\n    this->mainCommandGate = commandGate;\n    this->mainCommandGate->retain();\n    this->inner_attr = lck_attr_alloc_init();\n    this->inner_gp_attr = lck_grp_attr_alloc_init();\n    this->inner_gp = lck_grp_alloc_init(\"itlwm_tsleep\", this->inner_gp_attr);\n    this->inner_lock = lck_mtx_alloc_init(this->inner_gp, this->inner_attr);\n    return true;\n}\n\nIOEthernetController *ItlHalService::\ngetController()\n{\n    return this->controller;\n}\n\nIOCommandGate *ItlHalService::\ngetMainCommandGate()\n{\n    return this->mainCommandGate;\n}\n\nIOWorkLoop *ItlHalService::\ngetMainWorkLoop()\n{\n    return this->mainWorkLoop;\n}\n\nvoid ItlHalService::\nwakeupOn(void *ident)\n{\n//    XYLog(\"%s\\n\", __FUNCTION__);\n    wakeup(ident);\n}\n\nint ItlHalService::\ntsleep_nsec(void *ident, int priority, const char *wmesg, int timo)\n{\n//    XYLog(\"%s %s\\n\", __FUNCTION__, wmesg);\n    struct timespec ts;\n    int err;\n    memset(&ts, 0, sizeof(struct timespec));\n    ts.tv_nsec = timo;\n    lck_mtx_lock(this->inner_lock);\n    err = msleep(ident, this->inner_lock, priority, wmesg, &ts);\n    lck_mtx_unlock(this->inner_lock);\n    return err;\n}\n\nvoid ItlHalService::\nfree()\n{\n    XYLog(\"%s\\n\", __PRETTY_FUNCTION__);\n    if (this->mainWorkLoop) {\n        this->mainWorkLoop->release();\n    }\n    this->mainWorkLoop = NULL;\n    if (this->mainCommandGate) {\n        this->mainCommandGate->release();\n    }\n    this->mainCommandGate = NULL;\n    if (this->controller) {\n        this->controller->release();\n    }\n    if (this->inner_lock) {\n        lck_attr_free(this->inner_attr);\n        lck_mtx_free(this->inner_lock, this->inner_gp);\n        lck_grp_free(this->inner_gp);\n        lck_grp_attr_free(this->inner_gp_attr);\n        this->inner_lock = NULL;\n    }\n    this->controller = NULL;\n    super::free();\n}\n"
  },
  {
    "path": "include/HAL/ItlHalService.hpp",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n\n#ifndef ItlHalService_hpp\n#define ItlHalService_hpp\n\n#include <libkern/c++/OSObject.h>\n#include <IOKit/IOLib.h>\n#include <IOKit/IOService.h>\n#include <IOKit/IOCommandGate.h>\n#include <IOKit/IOWorkLoop.h>\n#include <IOKit/pci/IOPCIDevice.h>\n#include <IOKit/network/IOEthernetController.h>\n#include <IOKit/network/IOEthernetInterface.h>\n\n#include \"ItlDriverInfo.hpp\"\n#include \"ItlDriverController.hpp\"\n\n#include <net80211/ieee80211_var.h>\n\nclass ItlHalService : public OSObject {\n    OSDeclareAbstractStructors(ItlHalService)\n    \npublic:\n    \n    virtual bool attach(IOPCIDevice *device) = 0;\n    \n    virtual void detach(IOPCIDevice *device) = 0;\n    \n    virtual IOReturn enable(IONetworkInterface *interface) = 0;\n    \n    virtual IOReturn disable(IONetworkInterface *interface) = 0;\n    \n    virtual struct ieee80211com *get80211Controller() = 0;\n    \n    virtual ItlDriverInfo *getDriverInfo() = 0;\n    \n    virtual ItlDriverController *getDriverController() = 0;\n    \n    virtual void free() override;\n\npublic:\n    virtual bool initWithController(IOEthernetController *controller, IOWorkLoop *workloop, IOCommandGate *commandGate);\n    \nprotected:\n    \n    int tsleep_nsec(void *ident, int priority, const char *wmesg, int timo);\n    \n    void wakeupOn(void* ident);\n    \n    IOEthernetController *getController();\n    \n    IOCommandGate *getMainCommandGate();\n    \n    IOWorkLoop *getMainWorkLoop();\n    \nprivate:\n    IOEthernetController *controller;\n    IOCommandGate *mainCommandGate;\n    IOWorkLoop *mainWorkLoop;\n\n    lck_grp_t *inner_gp;\n    lck_grp_attr_t *inner_gp_attr;\n    lck_attr_t *inner_attr;\n    lck_mtx_t *inner_lock;\n};\n\n#endif /* ItlHalService_hpp */\n"
  },
  {
    "path": "itl80211/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>$(DEVELOPMENT_LANGUAGE)</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0</string>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n\t<key>IOKitPersonalities</key>\n\t<dict/>\n\t<key>NSHumanReadableCopyright</key>\n\t<string>Copyright © 2020 钟先耀. All rights reserved.</string>\n\t<key>OSBundleLibraries</key>\n\t<dict/>\n</dict>\n</plist>\n"
  },
  {
    "path": "itl80211/compat.cpp",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n//\n//  compat.cpp\n//  net80211\n//\n//  Copyright (c) 2012 Prashant Vaibhav. All rights reserved.\n//\n\n#include \"compat.h\"\n#include <sys/random.h>\n#include <sys/param.h>\n#include <sys/proc.h>\n\nOSDefineMetaClassAndStructors(pci_intr_handle, OSObject)\n\nint pci_get_capability(pci_chipset_tag_t chipsettag, pcitag_t pcitag, int capid, int *offsetp, pcireg_t *valuep) {\n\tuint8_t offset;\n\tUInt32 value = pcitag->findPCICapability(capid, &offset);\n\tif (valuep)\n\t\t*valuep = (pcireg_t)value;\n\tif (offsetp)\n\t\t*offsetp = offset;\n\tif (value == 0)\n\t\treturn 0;\n\telse\n\t\treturn 1;\n}\n\npcireg_t pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg) {\n\treturn tag->configRead32(reg);\n}\n\nvoid pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t val) {\n\ttag->configWrite32(reg, val);\n}\n\npcireg_t pci_mapreg_type(pci_chipset_tag_t pc, pcitag_t tag, int reg) {\n\treturn 0; // XXX this is not needed on OS X, will always be memorymap\n}\n\nint pci_mapreg_map(const struct pci_attach_args *pa, int reg, pcireg_t type, int busflags, bus_space_tag_t *tagp,\n\t\t   bus_space_handle_t *handlep, bus_addr_t *basep, bus_size_t *sizep, bus_size_t maxsize)\n{\t\n\tIOMemoryMap* map = pa->pa_tag->mapDeviceMemoryWithRegister(reg);\n\tif (map == 0)\n\t\treturn kIOReturnError;\n\t\n\t*handlep = reinterpret_cast<caddr_t>(map->getVirtualAddress());\n\t\n\tif (tagp)\n\t\t*tagp = map;\n\tif (basep)\n\t\t*basep = map->getVirtualAddress();\n\tif (sizep)\n\t\t*sizep = map->getSize();\n\t\n\treturn 0;\n}\n\nint\npci_intr_map_msix(struct pci_attach_args *pa, int vec, pci_intr_handle_t *ihp)\n{\n    pci_chipset_tag_t pc = pa->pa_pc;\n    pcitag_t tag = pa->pa_tag;\n    pcireg_t reg;\n\n    KASSERT(PCI_MSIX_VEC(vec) == vec, \"PCI_MSIX_VEC(vec) == vec\");\n\n    if (pci_get_capability(pc, tag, PCI_CAP_MSIX, NULL, &reg) == 0)\n        return 1;\n\n    if (vec > PCI_MSIX_MC_TBLSZ(reg))\n        return 1;\n    \n    return pci_intr_map_msi(pa, ihp);\n}\n\nint pci_intr_map_msi(struct pci_attach_args *paa, pci_intr_handle_t *ih) {\n\tif (paa == 0 || ih == 0)\n\t\treturn 1;\n\t\n\t*ih = new pci_intr_handle();\n\t\n\tif (*ih == 0)\n\t\treturn 1;\n\t\n\t(*ih)->dev = paa->pa_tag;  // pci device reference\n\t\n\t(*ih)->workloop = paa->workloop;\n\t\n\treturn 0; // XXX not required on OS X\n}\n\nint pci_intr_map(struct pci_attach_args *paa, pci_intr_handle_t *ih) {\n\treturn pci_intr_map_msi(paa, ih);\n}\n\nvoid interruptTrampoline(OSObject *ih, IOInterruptEventSource *, int count);\nvoid interruptTrampoline(OSObject *ih, IOInterruptEventSource *, int count) {\n\tpci_intr_handle* _ih = OSDynamicCast(pci_intr_handle, ih);\n\tif (_ih == 0)\n\t\treturn;\n\t_ih->func(_ih->arg); // jump to actual interrupt handler\n}\n\nvoid* pci_intr_establish(pci_chipset_tag_t pc, pci_intr_handle_t ih, int level, int (*handler)(void *), void *arg) {\n\tih->arg = arg;\n\tih->intr = IOInterruptEventSource::interruptEventSource(ih, &interruptTrampoline, ih->dev);\n\t\n\tif (ih->intr == 0)\n\t\treturn 0;\n\tif (ih->workloop->addEventSource(ih->intr) != kIOReturnSuccess)\n\t\treturn 0;\n\t\n\tih->intr->enable();\n\treturn ih;\n}\n\nvoid pci_intr_disestablish(pci_chipset_tag_t pc, void *ih) {\n\tpci_intr_handle_t intr = (pci_intr_handle_t) ih;\n\t\n\tintr->workloop->removeEventSource(intr->intr);\n\t\n\tintr->intr->release();\n\tintr->intr = 0;\n\t\n\tintr->dev->release();\n\tintr->dev = 0;\n\t\n\tintr->workloop->release();\n\tintr->workloop = 0;\n\t\n\tintr->arg = 0;\n\tintr->release();\n\tintr = 0;\n\tih = 0;\n}\n\nuint64_t bus_space_read_8(bus_space_tag_t space, bus_space_handle_t handle, bus_size_t offset) {\n    return *((uint64_t*)(handle + offset));\n}\n\nvoid bus_space_write_8(bus_space_tag_t space, bus_space_handle_t handle, bus_size_t offset, uint64_t value) {\n    *((uint64_t*)(handle + offset)) = value;\n}\n\nuint32_t bus_space_read_4(bus_space_tag_t space, bus_space_handle_t handle, bus_size_t offset) {\n\treturn *((uint32_t*)(handle + offset));\n}\n\nvoid bus_space_write_1(bus_space_tag_t space, bus_space_handle_t handle, bus_size_t offset, uint8_t value) {\n    *((uint8_t*)(handle + offset)) = value;\n}\n\nvoid bus_space_write_4(bus_space_tag_t space, bus_space_handle_t handle, bus_size_t offset, uint32_t value) {\n\t*((uint32_t*)(handle + offset)) = value;\n}\n\nvoid bus_space_barrier(bus_space_tag_t space, bus_space_handle_t handle, bus_size_t offset, bus_size_t length, int flags) {\n\treturn; // In OSX device memory access is always uncached and serialized (afaik!)\n}\n\nint bus_dmamap_create(bus_dma_tag_t tag, bus_size_t size, int nsegments, bus_size_t maxsegsz, bus_size_t boundary, int flags, bus_dmamap_t *dmamp) {\n\tif (dmamp == 0)\n\t\treturn 1;\n\t*dmamp = new bus_dmamap;\n\t(*dmamp)->cursor = IOMbufNaturalMemoryCursor::withSpecification(maxsegsz, nsegments);\n\tif ((*dmamp)->cursor == 0)\n\t\treturn 1;\n\telse\n\t\treturn 0;\n}\n\nIOBufferMemoryDescriptor* alloc_dma_memory(size_t size, mach_vm_address_t alignment,/* void** vaddr, mach_vm_address_t* paddr, */IOOptionBits opts);\nIOBufferMemoryDescriptor* alloc_dma_memory(size_t size, mach_vm_address_t alignment,/* void** vaddr, mach_vm_address_t* paddr, */IOOptionBits opts = kIOMemoryPhysicallyContiguous | kIOMapInhibitCache)\n{\n\tsize_t\t\treqsize;\n\tuint64_t\tphymask;\n\tint\t\ti;\n\t/*\n\tif (alignment <= PAGE_SIZE) {\n\t\treqsize = size;\n\t\tphymask = 0x00000000ffffffffull & (~(alignment - 1));\n\t} else {\n\t\treqsize = size + alignment;\n\t\tphymask = 0x00000000fffff000ull; /* page-aligned \n\t}*/\n\t\n\tphymask = 0x00000000ffffffffull & (~(alignment - 1));\n\treqsize = size;\n\t\n\tIOBufferMemoryDescriptor* mem = 0;\n\tmem = IOBufferMemoryDescriptor::inTaskWithPhysicalMask(kernel_task, opts, reqsize, phymask);\n\tif (!mem)\n\t\treturn 0;\n\n\tmem->prepare();\n\t/*\n\tif (paddr)\n\t\t*paddr = mem->getPhysicalAddress();\n\tif (vaddr)\n\t\t*vaddr = mem->getBytesNoCopy();\n\t\n\t/*\n\t * Check the alignment and increment by 4096 until we get the\n\t * requested alignment. Fail if can't obtain the alignment\n\t * we requested.\n\t \n\tif ((*paddr & (alignment - 1)) != 0) {\n\t\tfor (i = 0; i < alignment / 4096; i++) {\n\t\t\tif ((*paddr & (alignment - 1 )) == 0)\n\t\t\t\tbreak;\n\t\t\t*paddr += 4096;\n\t\t\t*vaddr = ((uint8_t*) *vaddr) + 4096;\n\t\t}\n\t\tif (i == alignment / 4096) {\n\t\t\tmem->complete();\n\t\t\tmem->release();\n\t\t\treturn 0;\n\t\t}\n\t}*/\n\treturn mem;\n}\n\n\nint bus_dmamem_alloc(bus_dma_tag_t tag, bus_size_t size, bus_size_t alignment, bus_size_t boundary, bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags) {\n\t// Ignore flags and don't pass in the number of segments, it's not used in the driver (always 1 anyway)\n\tif (segs == 0)\n\t\treturn 1;\n\t*segs = alloc_dma_memory(size, alignment);\n\tif (*segs == 0)\n\t\treturn 1;\n\telse\n\t\treturn 0;\n}\n\nint bus_dmamem_map(bus_dma_tag_t tag, bus_dma_segment_t *segs, int nsegs, size_t size, void **kvap, int flags) {\n\t// ignore flags, the memory is already mapped as one segment by the call to bus_dmamem_alloc so just return the virtual address\n\tif (*segs == 0 || kvap == 0)\n\t\treturn 1;\n\t*kvap = (*segs)->getBytesNoCopy();\n\treturn 0;\n}\n\nbus_addr_t bus_dmamap_get_paddr(bus_dma_segment_t seg) {\n\tif (seg == 0)\n\t\treturn 0;\n\telse\n\t\treturn seg->getPhysicalAddress();\n}\n\nvoid bus_dmamap_sync(bus_dma_tag_t tag, bus_dmamap_t dmam, bus_addr_t offset, bus_size_t len, int ops) {\n\treturn; // no syncing, we mapped the memory with cache inhibition so pray it works\n}\n\nvoid bus_dmamem_unmap(bus_dma_segment_t seg) {\n\tif (seg == 0)\n\t\treturn;\n\tseg->complete();\n}\n\nvoid bus_dmamem_free(bus_dma_tag_t tag, bus_dma_segment_t *segs, int nsegs) {\n\tif (segs == 0)\n\t\treturn;\n\tif (*segs == 0)\n\t\treturn;\n\t(*segs)->release();\n\t*segs = 0;\n}\n\nvoid bus_dmamap_destroy(bus_dma_tag_t tag, bus_dmamap_t dmam) {\n\tif (dmam == 0)\n\t\treturn;\n\tif (dmam->cursor == 0)\n\t\treturn;\n\tdmam->cursor->release();\n\tdmam->cursor = 0;\n\tdelete dmam;\n}\n\nint bus_dmamap_load(bus_dmamap_t map, mbuf_t mb) {\n\tif (map == 0 || mb == 0)\n\t\treturn 1;\n\tmap->dm_nsegs = map->cursor->getPhysicalSegmentsWithCoalesce(mb, map->dm_segs, 1);\n\tif (map->dm_nsegs == 0)\n\t\treturn 1;\n\telse\n\t\treturn 0;\n}\n"
  },
  {
    "path": "itl80211/compat.h",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n//\n//  compat.h\n//  net80211\n//\n//  Copyright (c) 2012 Prashant Vaibhav. All rights reserved.\n//\n\n#ifndef net80211_compat_h\n#define net80211_compat_h\n\n// BSD compatibility definitions\n\n#include <IOKit/pci/IOPCIDevice.h>\n#include <IOKit/IOWorkLoop.h>\n#include <IOKit/IOInterruptEventSource.h>\n#include <IOKit/IOBufferMemoryDescriptor.h>\n#include <sys/kpi_mbuf.h>\n#include <IOKit/network/IOMbufMemoryCursor.h>\n#include <net80211/ieee80211_var.h>\n#include <net80211/ieee80211_mira.h>\n#include <net80211/ieee80211_amrr.h>\n#include <sys/pcireg.h>\n\n// the following isn't actually used\n#define BUS_SPACE_BARRIER_READ\t0\n#define BUS_SPACE_BARRIER_WRITE\t0\n#define BUS_DMA_NOWAIT\t\t0\n#define BUS_DMA_ZERO\t\t0\n#define BUS_DMA_COHERENT\t0\n#define BUS_DMA_READ\t\t0\n\nstatic inline void\nUSEC_TO_TIMEVAL(uint64_t us, struct timeval *tv)\n{\n    tv->tv_sec = us / 1000000;\n    tv->tv_usec = us % 1000000;\n}\n\nstatic inline void\nNSEC_TO_TIMEVAL(uint64_t ns, struct timeval *tv)\n{\n    tv->tv_sec = ns / 1000000000L;\n    tv->tv_usec = (ns % 1000000000L) / 1000;\n}\n\nstatic inline uint64_t\nTIMEVAL_TO_NSEC(const struct timeval *tv)\n{\n    uint64_t nsecs;\n\n    if (tv->tv_sec > UINT64_MAX / 1000000000ULL)\n        return UINT64_MAX;\n    nsecs = tv->tv_sec * 1000000000ULL;\n    if (tv->tv_usec * 1000ULL > UINT64_MAX - nsecs)\n        return UINT64_MAX;\n    return nsecs + tv->tv_usec * 1000ULL;\n}\n\nstatic inline void\nNSEC_TO_TIMESPEC(uint64_t ns, struct timespec *ts)\n{\n    ts->tv_sec = ns / 1000000000L;\n    ts->tv_nsec = ns % 1000000000L;\n}\n\nstatic inline uint64_t\nSEC_TO_NSEC(uint64_t seconds)\n{\n    if (seconds > UINT64_MAX / 1000000000ULL)\n        return UINT64_MAX;\n    return seconds * 1000000000ULL;\n}\n\nstatic inline uint64_t\nMSEC_TO_NSEC(uint64_t milliseconds)\n{\n    if (milliseconds > UINT64_MAX / 1000000ULL)\n        return UINT64_MAX;\n    return milliseconds * 1000000ULL;\n}\n\nstatic inline uint64_t\nUSEC_TO_NSEC(uint64_t microseconds)\n{\n    if (microseconds > UINT64_MAX / 1000ULL)\n        return UINT64_MAX;\n    return microseconds * 1000ULL;\n}\n\nstatic inline uint64_t\nTIMESPEC_TO_NSEC(const struct timespec *ts)\n{\n    if (ts->tv_sec > (UINT64_MAX - ts->tv_nsec) / 1000000000ULL)\n        return UINT64_MAX;\n    return ts->tv_sec * 1000000000ULL + ts->tv_nsec;\n}\n\n#define MHLEN mbuf_get_mhlen()\n#define M_DONTWAIT MBUF_DONTWAIT\n#define M_EXT MBUF_EXT\n#define m_freem mbuf_freem\n#define m_free mbuf_free\n#define m_copydata mbuf_copydata\n\nstatic inline int\nflsl(long mask)\n{\n    int bit;\n\n    if (mask == 0)\n        return (0);\n    for (bit = 1; mask != 1; bit++)\n        mask = (unsigned long)mask >> 1;\n    return (bit);\n}\n\n/*\n * Find Last Set bit\n */\nstatic inline int\n_fls(int mask)\n{\n    int bit;\n\n    if (mask == 0)\n        return (0);\n    for (bit = 1; mask != 1; bit++)\n        mask = (unsigned int)mask >> 1;\n    return (bit);\n}\n\nenum {\n\tBUS_DMASYNC_PREREAD,\n\tBUS_DMASYNC_PREWRITE,\n\tBUS_DMASYNC_POSTREAD,\n\tBUS_DMASYNC_POSTWRITE\n};\n\ntypedef int\t\t\t\tbus_dma_tag_t;\ntypedef IOBufferMemoryDescriptor*\tbus_dma_segment_t;\ntypedef caddr_t\t\t\t\tbus_space_handle_t; // pointer to device memory\ntypedef int\t\t\t\tpci_chipset_tag_t;\ntypedef mach_vm_address_t\t\tbus_addr_t;\ntypedef u_int32_t\t\t\tbus_size_t;\ntypedef IOMemoryMap*\t\t\tbus_space_tag_t;\ntypedef IOPCIDevice*\t\t\tpcitag_t;\ntypedef uint32_t\t\t\tpcireg_t;\n\nclass pci_intr_handle : public OSObject {\n\tOSDeclareDefaultStructors(pci_intr_handle)\npublic:\n\tIOWorkLoop*\t\tworkloop;\n\tIOInterruptEventSource*\tintr;\n\tIOPCIDevice*\t\tdev;\n\tvoid (*func)(void* arg);\n\tvoid* arg;\n};\ntypedef pci_intr_handle* pci_intr_handle_t;\n\n/*\n * Actions for ca_activate.\n */\n#define    DVACT_DEACTIVATE    1    /* deactivate the device */\n#define    DVACT_QUIESCE        2    /* warn the device about suspend */\n#define    DVACT_SUSPEND        3    /* suspend the device */\n#define    DVACT_RESUME        4    /* resume the device */\n#define    DVACT_WAKEUP        5    /* tell device to recover after resume */\n#define    DVACT_POWERDOWN        6    /* power device down */\n\nstruct device {\n    IOService *provider;\n    void *_data;\n\tchar dv_xname[16];\n};\n\nstruct workq_task {\n\tint blah;\n};\n\nstruct pci_attach_args {\n\tIOWorkLoop*\t\tworkloop;\n\tpci_chipset_tag_t\tpa_pc;\n\tpcitag_t\t\tpa_tag;\n\tbus_dma_tag_t\t\tpa_dmat;\n};\n\nstruct bus_dmamap {\n\tIOMbufNaturalMemoryCursor*\tcursor;\n\tint\t\t\t\tdm_nsegs;\n\tIOPhysicalSegment\t\tdm_segs[23]; // reserve space for 8 segments\n};\ntypedef struct bus_dmamap* bus_dmamap_t;\n\n/* max bufs per tfd the driver will use */\n#define IWM_MAX_CMD_TBS_PER_TFD 2\n\n#define IWM_TX_RING_COUNT    256\n#define IWM_TX_RING_LOMARK    192\n#define IWM_TX_RING_HIMARK    224\n\nstruct pci_matchid {\n    int     pm_vid;\n    int     pm_pid;\n    int     pm_sub_dev;\n    int     pm_sub_vid;\n    void    *drv_data;\n};\n\n#define PCI_ANY_ID 0xffff\n\nstatic inline int\npci_matchbyid(int vid, int pid, const struct pci_matchid *ids, int nent)\n{\n    const struct pci_matchid *pm;\n    int i;\n\n    for (i = 0, pm = ids; i < nent; i++, pm++)\n        if (vid == pm->pm_vid &&\n            pid == pm->pm_pid)\n            return (1);\n    return (0);\n}\n\nstatic inline int\npci_match(int vid, int pid, int sub_vid, int sub_dev, const struct pci_matchid *ids, int nent, void **drv_data)\n{\n    const struct pci_matchid *pm;\n    int i;\n\n    for (i = 0, pm = ids; i < nent; i++, pm++) {\n        if (vid == pm->pm_vid && pid == pm->pm_pid) {\n            if (pm->pm_sub_dev != PCI_ANY_ID && sub_dev != pm->pm_sub_dev) {\n                return 0;\n            }\n            if (pm->pm_sub_vid != PCI_ANY_ID && sub_vid != pm->pm_sub_vid) {\n                return 0;\n            }\n            if (drv_data) {\n                *drv_data = pm->drv_data;\n            }\n            return 1;\n        }\n    }\n    return 0;\n}\n\n/*\n * DMA glue is from iwn\n */\n\nchar*\t\tether_sprintf(const u_char *ap);\nint\t\tpci_get_capability(pci_chipset_tag_t chipsettag, pcitag_t pcitag, int capid, int *offsetp, pcireg_t *valuep);\npcireg_t\tpci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg);\nvoid\t\tpci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t val);\npcireg_t\tpci_mapreg_type(pci_chipset_tag_t pc, pcitag_t tag, int reg);\nint\t\tpci_mapreg_map(const struct pci_attach_args *pa, int reg, pcireg_t type, int busflags, bus_space_tag_t *tagp,\n\t\t\t       bus_space_handle_t *handlep, bus_addr_t *basep, bus_size_t *sizep, bus_size_t maxsize);\nint     pci_intr_map_msix(struct pci_attach_args *pa, int vec, pci_intr_handle_t *ihp);\nint\t\tpci_intr_map_msi(struct pci_attach_args *paa, pci_intr_handle_t *ih);\nint\t\tpci_intr_map(struct pci_attach_args *paa, pci_intr_handle_t *ih);\nvoid*\t\tpci_intr_establish(pci_chipset_tag_t pc, pci_intr_handle_t ih, int level, int (*handler)(void *), void *arg);\nvoid\t\tpci_intr_disestablish(pci_chipset_tag_t pc, void *ih);\n\nuint64_t    bus_space_read_8(bus_space_tag_t space, bus_space_handle_t handle, bus_size_t offset);\nvoid        bus_space_write_8(bus_space_tag_t space, bus_space_handle_t handle, bus_size_t offset, uint64_t value);\nuint32_t\tbus_space_read_4(bus_space_tag_t space, bus_space_handle_t handle, bus_size_t offset);\nvoid\t\tbus_space_write_4(bus_space_tag_t space, bus_space_handle_t handle, bus_size_t offset, uint32_t value);\nvoid bus_space_write_1(bus_space_tag_t space, bus_space_handle_t handle, bus_size_t offset, uint8_t value);\nvoid\t\tbus_space_barrier(bus_space_tag_t space, bus_space_handle_t handle, bus_size_t offset, bus_size_t length, int flags);\n\nint\t\tbus_dmamap_create(bus_dma_tag_t tag, bus_size_t size, int nsegments, bus_size_t maxsegsz, bus_size_t boundary, int flags, bus_dmamap_t *dmamp);\nint\t\tbus_dmamem_alloc(bus_dma_tag_t tag, bus_size_t size, bus_size_t alignment, bus_size_t boundary, bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags);\nint\t\tbus_dmamem_map(bus_dma_tag_t tag, bus_dma_segment_t *segs, int nsegs, size_t size, void **kvap, int flags);\nbus_addr_t\tbus_dmamap_get_paddr(bus_dma_segment_t seg); // XXX new\nvoid\t\tbus_dmamap_sync(bus_dma_tag_t tag, bus_dmamap_t dmam, bus_addr_t offset, bus_size_t len, int ops);\nvoid\t\tbus_dmamem_unmap(bus_dma_segment_t seg); // XXX changed args\nvoid\t\tbus_dmamem_free(bus_dma_tag_t tag, bus_dma_segment_t *segs, int nsegs);\nvoid\t\tbus_dmamap_destroy(bus_dma_tag_t tag, bus_dmamap_t dmam);\nint\t\tbus_dmamap_load(bus_dmamap_t map, mbuf_t m);\n#define bus_dmamap_load_mbuf bus_dmamap_load\n\n#endif\n"
  },
  {
    "path": "itl80211/linux/bitfield.h",
    "content": "//\n//  bitfield.h\n//  AppleIntelWifiAdapter\n//\n//  Created by qcwap on 2020/1/5.\n//  Copyright © 2020 钟先耀. All rights reserved.\n//\n\n/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n\n#ifndef bitfield_h\n#define bitfield_h\n\n#include <libkern/OSTypes.h>\n#include <libkern/OSAtomic.h>\n\n#define BITS_PER_LONG 64\n\n#define BITS_PER_LONG_LONG 64\n\n#define BIT(nr)            (1UL << (nr))\n#define BIT_ULL(nr)        (1ULL << (nr))\n#define BIT_MASK(nr)        (1UL << ((nr) % BITS_PER_LONG))\n#define BIT_WORD(nr)        ((nr) / BITS_PER_LONG)\n#define BIT_ULL_MASK(nr)    (1ULL << ((nr) % BITS_PER_LONG_LONG))\n#define BIT_ULL_WORD(nr)    ((nr) / BITS_PER_LONG_LONG)\n#define BITS_PER_BYTE        8\n#define BITS_TO_LONGS(nr)    DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))\n#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))\n#define __bf_shf(x) (__builtin_ffsll(x) - 1)\n#define FIELD_PREP(_mask, _val)                        \\\n({                                \\\n((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask);    \\\n})\n\nstatic inline int\nfind_first_zero_bit(volatile void *p, int max)\n{\n    int b;\n    volatile u_int *ptr = (volatile u_int *)p;\n\n    for (b = 0; b < max; b += 32) {\n        if (ptr[b >> 5] != ~0) {\n            for (;;) {\n                if ((ptr[b >> 5] & (1 << (b & 0x1f))) == 0)\n                    return b;\n                b++;\n            }\n        }\n    }\n    return max;\n}\n\nstatic inline int\nfind_next_zero_bit(volatile void *p, int max, int b)\n{\n    volatile u_int *ptr = (volatile u_int *)p;\n\n    for (; b < max; b += 32) {\n        if (ptr[b >> 5] != ~0) {\n            for (;;) {\n                if ((ptr[b >> 5] & (1 << (b & 0x1f))) == 0)\n                    return b;\n                b++;\n            }\n        }\n    }\n    return max;\n}\n\nstatic inline int\nfind_first_bit(volatile void *p, int max)\n{\n    int b;\n    volatile u_int *ptr = (volatile u_int *)p;\n\n    for (b = 0; b < max; b += 32) {\n        if (ptr[b >> 5] != 0) {\n            for (;;) {\n                if (ptr[b >> 5] & (1 << (b & 0x1f)))\n                    return b;\n                b++;\n            }\n        }\n    }\n    return max;\n}\n\nstatic inline int\nfind_next_bit(volatile void *p, int max, int b)\n{\n    volatile u_int *ptr = (volatile u_int *)p;\n\n    for (; b < max; b+= 32) {\n        if (ptr[b >> 5] != 0) {\n            for (;;) {\n                if (ptr[b >> 5] & (1 << (b & 0x1f)))\n                    return b;\n                b++;\n            }\n        }\n    }\n    return max;\n}\n\nstatic inline int\nfind_last_bit(volatile void *p, int max)\n{\n    int b;\n    volatile u_int *ptr = (volatile u_int *)p;\n\n    for (b = max; b > 0; b -= 32) {\n        if (ptr[b >> 5] != 0) {\n            for (;;) {\n                if (ptr[b >> 5] & (1 << (b & 0x1f)))\n                    return b;\n                b--;\n            }\n        }\n    }\n    return max;\n}\n\n#define for_each_set_bit(bit, addr, size) \\\n        for ((bit) = find_first_bit((addr), (size));        \\\n            (bit) < (size);                    \\\n            (bit) = find_next_bit((addr), (size), (bit) + 1))\n\n#define GENMASK(h, l) \\\n    (((~(0UL)) - ((1UL) << (l)) + 1) & \\\n     (~(0UL) >> (BITS_PER_LONG - 1 - (h))))\n\n#define GENMASK_ULL(h, l) \\\n    (((~(0ULL)) - ((1ULL) << (l)) + 1) & \\\n     (~(0ULL) >> (BITS_PER_LONG_LONG - 1 - (h))))\n\nstatic inline UInt64 OSBitwiseAtomic64(unsigned long and_mask, unsigned long or_mask, unsigned long xor_mask, unsigned long * value)\n{\n    unsigned long    oldValue;\n    unsigned long    newValue;\n\n    do {\n        oldValue = *value;\n        newValue = ((oldValue & and_mask) | or_mask) ^ xor_mask;\n    } while (! OSCompareAndSwap64(oldValue, newValue, value));\n    \n    return oldValue;\n}\n\nstatic inline unsigned long OSBitAndAtomic64(unsigned long mask, unsigned long * value)\n{\n    return OSBitwiseAtomic64(mask, 0, 0, value);\n}\n\nstatic inline unsigned long OSBitOrAtomic64(unsigned long mask, unsigned long * value)\n{\n    return OSBitwiseAtomic64(-1, mask, 0, value);\n}\n\nstatic inline void set_bit(int nr, volatile unsigned long *addr)\n{\n    unsigned long mask = BIT_MASK(nr);\n    unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);\n    OSBitOrAtomic64(mask, p);\n}\n\nstatic inline void clear_bit(int nr, volatile unsigned long *addr)\n{\n    unsigned long mask = BIT_MASK(nr);\n    unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);\n    OSBitAndAtomic64(~mask, p);\n}\n\nstatic inline int test_and_set_bit(int nr, volatile unsigned long *addr)\n{\n    unsigned long mask = BIT_MASK(nr);\n    unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);\n    unsigned long old;\n    \n    old = *p;\n    *p = old | mask;\n    \n    return (old & mask) != 0;\n}\n\nstatic inline int test_and_clear_bit(int nr, volatile unsigned long *addr)\n{\n    unsigned long mask = BIT_MASK(nr);\n    unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);\n    unsigned long old;\n    \n    old = *p;\n    *p = old & ~mask;\n    \n    return (old & mask) != 0;\n}\n\nstatic inline int\ntest_bit(int nr, const volatile unsigned long *addr)\n{\n    return (OSAddAtomic(0, addr) & (1 << nr)) != 0;\n}\n\nstatic inline int linux_fls(int x)\n{\n    int r = 32;\n    \n    if (!x)\n        return 0;\n    if (!(x & 0xffff0000u)) {\n        x <<= 16;\n        r -= 16;\n    }\n    if (!(x & 0xff000000u)) {\n        x <<= 8;\n        r -= 8;\n    }\n    if (!(x & 0xf0000000u)) {\n        x <<= 4;\n        r -= 4;\n    }\n    if (!(x & 0xc0000000u)) {\n        x <<= 2;\n        r -= 2;\n    }\n    if (!(x & 0x80000000u)) {\n        x <<= 1;\n        r -= 1;\n    }\n    return r;\n}\n\n#endif /* bitfield_h */\n"
  },
  {
    "path": "itl80211/linux/kernel.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0 */\n\n#ifndef kernel_h\n#define kernel_h\n\n#include <linux/types.h>\n\n#include <sys/errno.h>\n#include <libkern/OSTypes.h>\n#include <IOKit/IOLib.h>\n\n#define ERFKILL        132    /* Operation not possible due to RF-kill */\n\n#define EHWPOISON    133    /* Memory page has hardware error */\n\n\n/* Defined for the NFSv3 protocol */\n#define EBADHANDLE    521    /* Illegal NFS file handle */\n#define ENOTSYNC    522    /* Update synchronization mismatch */\n#define EBADCOOKIE    523    /* Cookie is stale */\n#define ENOTSUPP    524    /* Operation is not supported */\n#define ETOOSMALL    525    /* Buffer or request is too small */\n#define ESERVERFAULT    526    /* An untranslatable error occurred */\n#define EBADTYPE    527    /* Type not supported by server */\n#define EJUKEBOX    528    /* Request initiated, but will not complete before timeout */\n#define EIOCBQUEUED    529    /* iocb queued, will get completion event */\n#define ERECALLCONFLICT    530    /* conflict with recalled state */\n\n\n#define min_t(type,x,y) \\\n({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })\n\n#define max_t(type, x, y) \\\n({ type __x = (x); type __y = (y); __x > __y ? __x: __y; })\n\n\n\n#define OS_EXPECT(x, v) __builtin_expect((x), (v))\n\n#define likely(x)       OS_EXPECT(!!(x), 1)\n#define unlikely(x)     ({ \\\n                            OS_EXPECT(!!(x), 0); \\\n                            !!(x); \\\n                        })\n\n# define do_div(n,base) ({                    \\\nuint32_t __base = (base);                \\\nuint32_t __rem;                        \\\n__rem = ((uint64_t)(n)) % __base;            \\\n(n) = ((uint64_t)(n)) / __base;                \\\n__rem;                            \\\n})\n\n#define MAX_ERRNO 4095\n\n//判断x是不是在（0xfffff000，0xffffffff)之间，注意这里用unlikely()的用意\n#define IS_ERR_VALUE(x) unlikely((x) >= (unsigned long)-MAX_ERRNO)\n  \n//由错误码求指针，-1 -> 0xFFFFFFFF\nstatic inline void *ERR_PTR(long error)\n{\n    return (void *) error;\n}\n\n//由指针求错误码，0xFFFFFFFF -> -1 ,依次类推\nstatic inline long PTR_ERR(const void *ptr)\n{\n    return (long) ptr;\n}\n  \n//判断x是不是在（0xfffff000，0xffffffff)之间，x是不是一个有效的指针\n static inline long IS_ERR(const void *ptr)\n{\n    return IS_ERR_VALUE((unsigned long)ptr);\n}\n\nstatic inline int fls64(UInt64 x)\n{\n    int bitpos = -1;\n    /*\n     * AMD64 says BSRQ won't clobber the dest reg if x==0; Intel64 says the\n     * dest reg is undefined if x==0, but their CPU architect says its\n     * value is written to set it to the same as before.\n     */\n    asm(\"bsrq %1,%q0\"\n        : \"+r\" (bitpos)\n        : \"rm\" (x));\n    return bitpos + 1;\n}\n\nstatic inline const char *reverse_strchr(const char *s, int c)\n{\n    char *find = NULL;\n    const char *ss = s;\n    \n    while (*ss != '\\0' && (find = strchr(ss, c))) {\n        ss = ++find;\n    }\n    return ss;\n}\n\n#ifndef strrchr\n#define strrchr(x, y) reverse_strchr((x), (y))\n#endif\n\n/*\n * Runtime evaluation of get_order()\n */\nstatic inline\nint __get_order(unsigned long size)\n{\n    int order;\n    \n    size--;\n    size >>= PAGE_SHIFT;\n#if BITS_PER_LONG == 32\n    order = linux_fls(size);\n#else\n    order = fls64(size);\n#endif\n    return order;\n}\n\n/**\n * get_order - Determine the allocation order of a memory size\n * @size: The size for which to get the order\n *\n * Determine the allocation order of a particular sized block of memory.  This\n * is on a logarithmic scale, where:\n *\n *    0 -> 2^0 * PAGE_SIZE and below\n *    1 -> 2^1 * PAGE_SIZE to 2^0 * PAGE_SIZE + 1\n *    2 -> 2^2 * PAGE_SIZE to 2^1 * PAGE_SIZE + 1\n *    3 -> 2^3 * PAGE_SIZE to 2^2 * PAGE_SIZE + 1\n *    4 -> 2^4 * PAGE_SIZE to 2^3 * PAGE_SIZE + 1\n *    ...\n *\n * The order returned is used to find the smallest allocation granule required\n * to hold an object of the specified size.\n *\n * The result is undefined if the size is 0.\n *\n * This function may be used to initialise variables with compile time\n * evaluations of constants.\n */\n#define get_order(n)                        \\\n(                                \\\n__builtin_constant_p(n) ? (                \\\n((n) == 0UL) ? BITS_PER_LONG - PAGE_SHIFT :    \\\n(((n) < (1UL << PAGE_SHIFT)) ? 0 :        \\\nilog2((n) - 1) - PAGE_SHIFT + 1)        \\\n) :                            \\\n__get_order(n)                        \\\n)\n\n/**\n * container_of - cast a member of a structure out to the containing structure\n * @ptr:    the pointer to the member.\n * @type:    the type of the container struct this is embedded in.\n * @member:    the name of the member within the struct.\n *\n */\n#define container_of(ptr, type, member) ({                \\\npointer_t __mptr = (pointer_t)(ptr);                    \\\n((type *)(__mptr - offsetof(type, member))); })\n\n\n/*\n * This looks more complex than it should be. But we need to\n * get the type for the ~ right in round_down (it needs to be\n * as wide as the result!), and we want to evaluate the macro\n * arguments just once each.\n */\n#define __round_mask(x, y) ((__typeof__(x))((y)-1))\n#define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1)\n#define round_down(x, y) ((x) & ~__round_mask(x, y))\n\n#define jiffies                         \\\n({                                      \\\n    uint64_t m,f;                       \\\n    clock_get_uptime(&m);               \\\n    absolutetime_to_nanoseconds(m,&f);  \\\n    ((f * HZ) / 1000000000);            \\\n})\n\n#define time_after(a,b)    \\\n((long)(b) - (long)(a) < 0)\n#define time_is_before_jiffies(a) time_after(ticks, a)\n\n#define DMA_BIT_MASK(n)    (((n) == 64) ? ~0ULL : ((1ULL<<(n))-1))\n\n#define struct_size(x, y, l) (sizeof(*x) + sizeof(*y) * l)\n\n// log2.h\n/*\n *  Determine whether some value is a power of two, where zero is\n * *not* considered a power of two.\n */\n\nstatic inline __attribute__((const))\nbool is_power_of_2(unsigned long n)\n{\n    return (n != 0 && ((n & (n - 1)) == 0));\n}\n\n/**\n * kmemdup - duplicate region of memory\n *\n * @src: memory region to duplicate\n * @len: memory region length\n * @gfp: GFP mask to use\n */\nstatic inline void *kmemdup(const void *src, size_t len) {\n    void *p;\n    p = IOMalloc(len);\n    if (p)\n        memcpy(p, src, len);\n    return p;\n}\n\nstatic inline void* kcalloc(size_t n, size_t size)\n{\n    if (size != 0 && n > SIZE_MAX / size) {\n        return NULL;\n    }\n    void *ret = IOMalloc(n * size);\n    if (ret) {\n        bzero(ret, n * size);\n    }\n    return ret;\n}\n\nstatic inline void* kzalloc(size_t size)\n{\n    void *ret = IOMalloc(size);\n    if (ret) {\n        bzero(ret, size);\n    }\n    return ret;\n}\n\n\n\nstatic inline int atomic_dec_and_test(volatile SInt32 * addr)\n{\n    return ((OSDecrementAtomic(addr) == 1) ? 1 : 0);\n}\n\nstatic inline int atomic_inc_and_test(volatile SInt32 * addr)\n{\n    return ((OSIncrementAtomic(addr) == -1) ? 1 : 0);\n}\n\n#define atomic_inc(v) OSIncrementAtomic(v)\n#define atomic_dec(v) OSDecrementAtomic(v)\n\n#if __has_builtin(__builtin_abs)\n#define abs(N) __builtin_abs((N))\n#else\n#define abs(N) (((N)<0)?-(N):(N))\n#endif /* __has_builtin(__builtin_abs) */\n\n#endif /* kernel_h */\n"
  },
  {
    "path": "itl80211/linux/random.h",
    "content": "//\n//  random.h\n//  AppleIntelWifiAdapter\n//\n//  Created by 钟先耀 on 2020/1/22.\n//  Copyright © 2020 钟先耀. All rights reserved.\n//\n\n/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n\n#ifndef random_h\n#define random_h\n\n#include <libkern/crypto/rand.h>\n\nstatic inline void get_random_bytes(void *buf, int nbytes)\n{\n    random_buf(buf, nbytes);\n}\n\n#endif /* random_h */\n"
  },
  {
    "path": "itl80211/linux/types.h",
    "content": "//\n//  types.h\n//  AppleIntelWifiAdapter\n//\n//  Created by qcwap on 2020/1/5.\n//  Copyright © 2020 钟先耀. All rights reserved.\n//\n\n/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n\n#ifndef types_h\n#define types_h\n\n#include <IOKit/IOTypes.h>\n#include <libkern/OSAtomic.h>\n#include <linux/bitfield.h>\n\n#define local_bh_disable()\n#define local_bh_enable()\n\n#define NUM_DEFAULT_KEYS 4\n#define NUM_DEFAULT_MGMT_KEYS 2\n\n#define gfp_t int\n\n#define __packed __attribute__((packed)) __attribute__((aligned(1)))\n#define __aligned(x)        __attribute__((aligned(x)))\n#define __must_check        __attribute__((warn_unused_result))\n\n/*\n#define MODULE_FIRMWARE(fw)\n#define MODULE_DESCRIPTION(x)\n#define MODULE_AUTHOR(x)\n#define MODULE_LICENSE(x)\n \n\n#define __init\n#define __exit\n\n\n#define module_init(x)\n#define module_exit(x)\n */\n\n#define pr_info(x)\n\n#define __rcu\n\n# define __acquires(x)\n# define __releases(x)\n# define __acquire(x) (void)0\n# define __release(x) (void)0\n\n#define might_sleep()\n\n#define __bitwise\n#define __force\n\n#define list_head       queue_entry\n\n#ifndef __WARN_printf\n/*\n * To port this properly we'd have to port warn_slowpath_null(),\n * which I'm lazy to do so just do a regular print for now. If you\n * want to port this read kernel/panic.c\n */\n#define __WARN_printf(func, line, arg...)   do { IOLog(\"(AppleIntelWifiAdapter) (%s:%d) WARN\", func, line);} while (0);\n#endif\n\n#ifndef unlikely\n#include <linux/kernel.h>\n#endif\n\n#ifndef WARN_ON_ONCE\n#define WARN_ON_ONCE(condition, fmt...) ({ \\\n    static int __warned; \\\n    int __ret_warn_once = !!(condition); \\\n        \\\n    if(unlikely(__ret_warn_once)) \\\n        if(WARN_ON(!__warned, fmt...)) \\\n            __warned = 1;    \\\n    unlikely(__ret_warn_once); \\\n    (bool)__ret_warn_once; \\\n})\n#endif\n\n#ifndef WARN_ON\n#define WARN_ON(condition, fmt...) ({ \\\n    int __ret_warn_on = !!(condition); \\\n    if(unlikely(__ret_warn_on)) \\\n        __WARN_printf(__FUNCTION__, __LINE__, fmt...) \\\n    unlikely(__ret_warn_on); \\\n    (bool)(__ret_warn_on);\\\n})\n#endif\n\n#define __stringify OS_STRINGIFY\n\n#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))\n\n#define XYLog(fmt, x...)\\\ndo\\\n{\\\nkprintf(\"%s: \" fmt, \"itlwm\", ##x);\\\n}while(0)\n\ntypedef UInt8  u8;\ntypedef UInt16 u16;\ntypedef UInt32 u32;\ntypedef UInt64 u64;\n\ntypedef u8 __u8;\ntypedef u16 __u16;\ntypedef u32 __u32;\ntypedef u64 __u64;\n\ntypedef  SInt16 __be16;\ntypedef  SInt32 __be32;\ntypedef  SInt64 __be64;\ntypedef  SInt16 __le16;\ntypedef  SInt32 __le32;\ntypedef  SInt64 __le64;\n\ntypedef SInt8  s8;\ntypedef SInt16 s16;\ntypedef SInt32 s32;\ntypedef SInt64 s64;\n\ntypedef s8  __s8;\ntypedef s16 __s16;\ntypedef s32 __s32;\ntypedef s64 __s64;\n\ntypedef UInt16 __sum16;\n\ntypedef u64 dma_addr_t;\n\n#define U8_MAX        ((u8)~0U)\n#define S8_MAX        ((s8)(U8_MAX >> 1))\n#define S8_MIN        ((s8)(-S8_MAX - 1))\n\n#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))\n\n#define upper_32_bits(n) ((u32)(((n) >> 16) >> 16))\n\n#define lower_32_bits(n) ((u32)(n))\n\n#define __cpu_to_le64(x) ((__force __le64)(__u64)(x))\n#define __le64_to_cpu(x) ((__force __u64)(__le64)(x))\n#define __cpu_to_le32(x) ((__force __le32)(__u32)(x))\n#define __le32_to_cpu(x) ((__force __u32)(__le32)(x))\n#define __cpu_to_le16(x) ((__force __le16)(__u16)(x))\n#define __le16_to_cpu(x) ((__force __u16)(__le16)(x))\n#define __cpu_to_be64(x) ((__force __be64)__swab64((x)))\n#define __be64_to_cpu(x) __swab64((__force __u64)(__be64)(x))\n#define __cpu_to_be32(x) ((__force __be32)__swab32((x)))\n#define __be32_to_cpu(x) __swab32((__force __u32)(__be32)(x))\n#define __cpu_to_be16(x) ((__force __be16)__swab16((x)))\n#define __be16_to_cpu(x) __swab16((__force __u16)(__be16)(x))\n\n#define cpu_to_le64 __cpu_to_le64\n#define le64_to_cpu __le64_to_cpu\n#define cpu_to_le32 __cpu_to_le32\n#define le32_to_cpu __le32_to_cpu\n#define cpu_to_le16 __cpu_to_le16\n#define le16_to_cpu __le16_to_cpu\n#define cpu_to_be64 OSSwapHostToBigInt64\n#define be64_to_cpu OSSwapBigToHostInt64\n#define cpu_to_be32 OSSwapHostToBigInt32\n#define be32_to_cpu OSSwapBigToHostInt32\n#define cpu_to_be16 OSSwapHostToBigInt16\n#define be16_to_cpu OSSwapBigToHostInt16\n\nstatic inline __u16 __be16_to_cpup(const __be16 *p)\n{\n    return (__force __u16)*p;\n}\n\nstatic inline __u32 __be32_to_cpup(const __be32 *p)\n{\n    return (__force __u32)*p;\n}\n\nstatic inline __be32 __cpu_to_be32p(const __u32 *p)\n{\n    return (__force __be32)*p;\n}\n\nstatic inline __u64 __be64_to_cpup(const __be64 *p)\n{\n    return (__force __u64)*p;\n}\n\nstatic inline __be64 __cpu_to_be64p(const __u64 *p)\n{\n    return (__force __be64)*p;\n}\n\nstatic inline __u32 __le32_to_cpup(const __le32 *p)\n{\n    return (__force __u32)*p;\n}\n\nstatic inline __u16 __le16_to_cpup(const __le16 *p)\n{\n    return (__force __u16)*p;\n}\n\n#define le16_to_cpup(_a_) ((__uint16_t)(*(const uint16_t *)(_a_)))\n#define le32_to_cpup(_a_) ((__uint32_t)(*(const uint32_t *)(_a_)))\n\nstatic inline u32 get_unaligned_le32(const void *p)\n{\n    return le32_to_cpup((__le32 *)p);\n}\n\nstatic inline u32 get_unaligned_le16(const void *p)\n{\n    return le16_to_cpup((__le16 *)p);\n}\n\nstatic inline void put_unaligned_le32(u32 val, void *p)\n{\n    *((__le32 *)p) = cpu_to_le32(val);\n}\n\nstatic inline unsigned int hweight8(unsigned int w)\n{\n    unsigned int res = w - ((w >> 1) & 0x55);\n    res = (res & 0x33) + ((res >> 2) & 0x33);\n    return (res + (res >> 4)) & 0x0F;\n}\n\nstatic inline unsigned int hweight16(unsigned int w)\n{\n    unsigned int res = w - ((w >> 1) & 0x5555);\n    res = (res & 0x3333) + ((res >> 2) & 0x3333);\n    res = (res + (res >> 4)) & 0x0F0F;\n    return (res + (res >> 8)) & 0x00FF;\n}\n\nstatic inline unsigned int hweight32(unsigned int w)\n{\n    unsigned int res = w - ((w >> 1) & 0x55555555);\n    res = (res & 0x33333333) + ((res >> 2) & 0x33333333);\n    res = (res + (res >> 4)) & 0x0F0F0F0F;\n    res = res + (res >> 8);\n    return (res + (res >> 16)) & 0x000000FF;\n}\n\nstatic inline unsigned long hweight64(uint64_t w)\n{\n    uint64_t res = w - ((w >> 1) & 0x5555555555555555ul);\n    res = (res & 0x3333333333333333ul) + ((res >> 2) & 0x3333333333333333ul);\n    res = (res + (res >> 4)) & 0x0F0F0F0F0F0F0F0Ful;\n    res = res + (res >> 8);\n    res = res + (res >> 16);\n    return (res + (res >> 32)) & 0x00000000000000FFul;\n}\n\nstatic inline uint64_t field_multiplier(uint64_t field)\n{\n    return field & -field;\n}\n\nstatic inline uint64_t field_mask(uint64_t field)\n{\n    return field / field_multiplier(field);\n}\n\n/**\n * sizeof_field(TYPE, MEMBER)\n *\n * @TYPE: The structure containing the field of interest\n * @MEMBER: The field to return the size of\n */\n#define sizeof_field(TYPE, MEMBER) sizeof((((TYPE *)0)->MEMBER))\n\n/**\n * offsetofend(TYPE, MEMBER)\n *\n * @TYPE: The type of the structure\n * @MEMBER: The member within the structure to get the end offset of\n */\n#define offsetofend(TYPE, MEMBER) \\\n    (offsetof(TYPE, MEMBER)    + sizeof_field(TYPE, MEMBER))\n\n#define ____MAKE_OP(type,base,to,from)                    \\\nstatic inline __##type type##_encode_bits(base v, base field)    \\\n{                                    \\\n    return to((v & field_mask(field)) * field_multiplier(field));    \\\n}                                    \\\nstatic inline __##type type##_replace_bits(__##type old,    \\\n                    base val, base field)        \\\n{                                    \\\n    return (old & ~to(field)) | type##_encode_bits(val, field);    \\\n}                                    \\\nstatic inline void type##p_replace_bits(__##type *p,        \\\n                    base val, base field)        \\\n{                                    \\\n    *p = (*p & ~to(field)) | type##_encode_bits(val, field);    \\\n}                                    \\\nstatic inline base type##_get_bits(__##type v, base field)    \\\n{                                    \\\n    return (from(v) & field)/field_multiplier(field);        \\\n}\n#define __MAKE_OP(size)                            \\\n    ____MAKE_OP(le##size,u##size,cpu_to_le##size,le##size##_to_cpu)    \\\n    ____MAKE_OP(be##size,u##size,cpu_to_be##size,be##size##_to_cpu)    \\\n    ____MAKE_OP(u##size,u##size,,)\n____MAKE_OP(u8,u8,,)\n__MAKE_OP(16)\n__MAKE_OP(32)\n__MAKE_OP(64)\n#undef __MAKE_OP\n#undef ____MAKE_OP\n\n#define atomic_t    volatile SInt32\n#define atomic64_t  volatile SInt64\n\n#define ETHTOOL_FWVERS_LEN    32\n\n\n#define RT_ALIGN_T(u, uAlignment, type) ( ((type)(u) + ((uAlignment) - 1)) & ~(type)((uAlignment) - 1) )\n#define RT_ALIGN_Z(cb, uAlignment)              RT_ALIGN_T(cb, uAlignment, size_t)\n#define LNX_ALIGN RT_ALIGN_Z\n\n#define ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask))\n#define _ALIGN(x, a)         ALIGN_MASK(x, (typeof(x))(a) - 1)\n\n#define _usec_delay(x)           IODelay(x)\n#define _msec_delay(x)           IOSleep(x)\n#define _udelay(x)               IODelay(x)\n#define _mdelay(x)               IODelay(1000*(x))\n#define _msleep(x)               IOSleep(x)\n\n#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))\n#define usleep_range(min, max)    _msleep(DIV_ROUND_UP(min, 1000))\n\n#endif /* types_h */\n"
  },
  {
    "path": "itl80211/openbsd/crypto/aes.c",
    "content": "/*\n * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>\n *\n * Modified for OpenBSD by Thomas Pornin and Mike Belopuhov.\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the\n * \"Software\"), to deal in the Software without restriction, including\n * without limitation the rights to use, copy, modify, merge, publish,\n * distribute, sublicense, and/or sell copies of the Software, and to\n * permit persons to whom the Software is furnished to do so, subject to\n * the following conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\n * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\n * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n#include <sys/types.h>\n#include <sys/systm.h>\n#include <IOKit/IOLib.h>\n\n#include \"aes.h\"\n\nstatic inline void\nenc32le(void *dst, uint32_t x)\n{\n\tunsigned char *buf = (unsigned char *)dst;\n\n\tbuf[0] = (unsigned char)x;\n\tbuf[1] = (unsigned char)(x >> 8);\n\tbuf[2] = (unsigned char)(x >> 16);\n\tbuf[3] = (unsigned char)(x >> 24);\n}\n\nstatic inline uint32_t\ndec32le(const void *src)\n{\n\tconst unsigned char *buf = (const unsigned char *)src;\n\n\treturn (uint32_t)buf[0]\n\t\t| ((uint32_t)buf[1] << 8)\n\t\t| ((uint32_t)buf[2] << 16)\n\t\t| ((uint32_t)buf[3] << 24);\n}\n\n/*\n * This constant-time implementation is \"bitsliced\": the 128-bit state is\n * split over eight 32-bit words q* in the following way:\n *\n * -- Input block consists in 16 bytes:\n *    a00 a10 a20 a30 a01 a11 a21 a31 a02 a12 a22 a32 a03 a13 a23 a33\n * In the terminology of FIPS 197, this is a 4x4 matrix which is read\n * column by column.\n *\n * -- Each byte is split into eight bits which are distributed over the\n * eight words, at the same rank. Thus, for a byte x at rank k, bit 0\n * (least significant) of x will be at rank k in q0 (if that bit is b,\n * then it contributes \"b << k\" to the value of q0), bit 1 of x will be\n * at rank k in q1, and so on.\n *\n * -- Ranks given to bits are in \"row order\" and are either all even, or\n * all odd. Two independent AES states are thus interleaved, one using\n * the even ranks, the other the odd ranks. Row order means:\n *    a00 a01 a02 a03 a10 a11 a12 a13 a20 a21 a22 a23 a30 a31 a32 a33\n *\n * Converting input bytes from two AES blocks to bitslice representation\n * is done in the following way:\n * -- Decode first block into the four words q0 q2 q4 q6, in that order,\n * using little-endian convention.\n * -- Decode second block into the four words q1 q3 q5 q7, in that order,\n * using little-endian convention.\n * -- Call aes_ct_ortho().\n *\n * Converting back to bytes is done by using the reverse operations. Note\n * that aes_ct_ortho() is its own inverse.\n */\n\n/*\n * The AES S-box, as a bitsliced constant-time version. The input array\n * consists in eight 32-bit words; 32 S-box instances are computed in\n * parallel. Bits 0 to 7 of each S-box input (bit 0 is least significant)\n * are spread over the words 0 to 7, at the same rank.\n */\nstatic void\naes_ct_bitslice_Sbox(uint32_t *q)\n{\n\t/*\n\t * This S-box implementation is a straightforward translation of\n\t * the circuit described by Boyar and Peralta in \"A new\n\t * combinational logic minimization technique with applications\n\t * to cryptology\" (https://eprint.iacr.org/2009/191.pdf).\n\t *\n\t * Note that variables x* (input) and s* (output) are numbered\n\t * in \"reverse\" order (x0 is the high bit, x7 is the low bit).\n\t */\n\n\tuint32_t x0, x1, x2, x3, x4, x5, x6, x7;\n\tuint32_t y1, y2, y3, y4, y5, y6, y7, y8, y9;\n\tuint32_t y10, y11, y12, y13, y14, y15, y16, y17, y18, y19;\n\tuint32_t y20, y21;\n\tuint32_t z0, z1, z2, z3, z4, z5, z6, z7, z8, z9;\n\tuint32_t z10, z11, z12, z13, z14, z15, z16, z17;\n\tuint32_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9;\n\tuint32_t t10, t11, t12, t13, t14, t15, t16, t17, t18, t19;\n\tuint32_t t20, t21, t22, t23, t24, t25, t26, t27, t28, t29;\n\tuint32_t t30, t31, t32, t33, t34, t35, t36, t37, t38, t39;\n\tuint32_t t40, t41, t42, t43, t44, t45, t46, t47, t48, t49;\n\tuint32_t t50, t51, t52, t53, t54, t55, t56, t57, t58, t59;\n\tuint32_t t60, t61, t62, t63, t64, t65, t66, t67;\n\tuint32_t s0, s1, s2, s3, s4, s5, s6, s7;\n\n\tx0 = q[7];\n\tx1 = q[6];\n\tx2 = q[5];\n\tx3 = q[4];\n\tx4 = q[3];\n\tx5 = q[2];\n\tx6 = q[1];\n\tx7 = q[0];\n\n\t/*\n\t * Top linear transformation.\n\t */\n\ty14 = x3 ^ x5;\n\ty13 = x0 ^ x6;\n\ty9 = x0 ^ x3;\n\ty8 = x0 ^ x5;\n\tt0 = x1 ^ x2;\n\ty1 = t0 ^ x7;\n\ty4 = y1 ^ x3;\n\ty12 = y13 ^ y14;\n\ty2 = y1 ^ x0;\n\ty5 = y1 ^ x6;\n\ty3 = y5 ^ y8;\n\tt1 = x4 ^ y12;\n\ty15 = t1 ^ x5;\n\ty20 = t1 ^ x1;\n\ty6 = y15 ^ x7;\n\ty10 = y15 ^ t0;\n\ty11 = y20 ^ y9;\n\ty7 = x7 ^ y11;\n\ty17 = y10 ^ y11;\n\ty19 = y10 ^ y8;\n\ty16 = t0 ^ y11;\n\ty21 = y13 ^ y16;\n\ty18 = x0 ^ y16;\n\n\t/*\n\t * Non-linear section.\n\t */\n\tt2 = y12 & y15;\n\tt3 = y3 & y6;\n\tt4 = t3 ^ t2;\n\tt5 = y4 & x7;\n\tt6 = t5 ^ t2;\n\tt7 = y13 & y16;\n\tt8 = y5 & y1;\n\tt9 = t8 ^ t7;\n\tt10 = y2 & y7;\n\tt11 = t10 ^ t7;\n\tt12 = y9 & y11;\n\tt13 = y14 & y17;\n\tt14 = t13 ^ t12;\n\tt15 = y8 & y10;\n\tt16 = t15 ^ t12;\n\tt17 = t4 ^ t14;\n\tt18 = t6 ^ t16;\n\tt19 = t9 ^ t14;\n\tt20 = t11 ^ t16;\n\tt21 = t17 ^ y20;\n\tt22 = t18 ^ y19;\n\tt23 = t19 ^ y21;\n\tt24 = t20 ^ y18;\n\n\tt25 = t21 ^ t22;\n\tt26 = t21 & t23;\n\tt27 = t24 ^ t26;\n\tt28 = t25 & t27;\n\tt29 = t28 ^ t22;\n\tt30 = t23 ^ t24;\n\tt31 = t22 ^ t26;\n\tt32 = t31 & t30;\n\tt33 = t32 ^ t24;\n\tt34 = t23 ^ t33;\n\tt35 = t27 ^ t33;\n\tt36 = t24 & t35;\n\tt37 = t36 ^ t34;\n\tt38 = t27 ^ t36;\n\tt39 = t29 & t38;\n\tt40 = t25 ^ t39;\n\n\tt41 = t40 ^ t37;\n\tt42 = t29 ^ t33;\n\tt43 = t29 ^ t40;\n\tt44 = t33 ^ t37;\n\tt45 = t42 ^ t41;\n\tz0 = t44 & y15;\n\tz1 = t37 & y6;\n\tz2 = t33 & x7;\n\tz3 = t43 & y16;\n\tz4 = t40 & y1;\n\tz5 = t29 & y7;\n\tz6 = t42 & y11;\n\tz7 = t45 & y17;\n\tz8 = t41 & y10;\n\tz9 = t44 & y12;\n\tz10 = t37 & y3;\n\tz11 = t33 & y4;\n\tz12 = t43 & y13;\n\tz13 = t40 & y5;\n\tz14 = t29 & y2;\n\tz15 = t42 & y9;\n\tz16 = t45 & y14;\n\tz17 = t41 & y8;\n\n\t/*\n\t * Bottom linear transformation.\n\t */\n\tt46 = z15 ^ z16;\n\tt47 = z10 ^ z11;\n\tt48 = z5 ^ z13;\n\tt49 = z9 ^ z10;\n\tt50 = z2 ^ z12;\n\tt51 = z2 ^ z5;\n\tt52 = z7 ^ z8;\n\tt53 = z0 ^ z3;\n\tt54 = z6 ^ z7;\n\tt55 = z16 ^ z17;\n\tt56 = z12 ^ t48;\n\tt57 = t50 ^ t53;\n\tt58 = z4 ^ t46;\n\tt59 = z3 ^ t54;\n\tt60 = t46 ^ t57;\n\tt61 = z14 ^ t57;\n\tt62 = t52 ^ t58;\n\tt63 = t49 ^ t58;\n\tt64 = z4 ^ t59;\n\tt65 = t61 ^ t62;\n\tt66 = z1 ^ t63;\n\ts0 = t59 ^ t63;\n\ts6 = t56 ^ ~t62;\n\ts7 = t48 ^ ~t60;\n\tt67 = t64 ^ t65;\n\ts3 = t53 ^ t66;\n\ts4 = t51 ^ t66;\n\ts5 = t47 ^ t65;\n\ts1 = t64 ^ ~s3;\n\ts2 = t55 ^ ~t67;\n\n\tq[7] = s0;\n\tq[6] = s1;\n\tq[5] = s2;\n\tq[4] = s3;\n\tq[3] = s4;\n\tq[2] = s5;\n\tq[1] = s6;\n\tq[0] = s7;\n}\n\n/*\n * Perform bytewise orthogonalization of eight 32-bit words. Bytes\n * of q0..q7 are spread over all words: for a byte x that occurs\n * at rank i in q[j] (byte x uses bits 8*i to 8*i+7 in q[j]), the bit\n * of rank k in x (0 <= k <= 7) goes to q[k] at rank 8*i+j.\n *\n * This operation is an involution.\n */\nstatic void\naes_ct_ortho(uint32_t *q)\n{\n#define SWAPN(cl, ch, s, x, y)   do { \\\n\t\tuint32_t a, b; \\\n\t\ta = (x); \\\n\t\tb = (y); \\\n\t\t(x) = (a & (uint32_t)cl) | ((b & (uint32_t)cl) << (s)); \\\n\t\t(y) = ((a & (uint32_t)ch) >> (s)) | (b & (uint32_t)ch); \\\n\t} while (0)\n\n#define SWAP2(x, y)   SWAPN(0x55555555, 0xAAAAAAAA, 1, x, y)\n#define SWAP4(x, y)   SWAPN(0x33333333, 0xCCCCCCCC, 2, x, y)\n#define SWAP8(x, y)   SWAPN(0x0F0F0F0F, 0xF0F0F0F0, 4, x, y)\n\n\tSWAP2(q[0], q[1]);\n\tSWAP2(q[2], q[3]);\n\tSWAP2(q[4], q[5]);\n\tSWAP2(q[6], q[7]);\n\n\tSWAP4(q[0], q[2]);\n\tSWAP4(q[1], q[3]);\n\tSWAP4(q[4], q[6]);\n\tSWAP4(q[5], q[7]);\n\n\tSWAP8(q[0], q[4]);\n\tSWAP8(q[1], q[5]);\n\tSWAP8(q[2], q[6]);\n\tSWAP8(q[3], q[7]);\n}\n\nstatic inline uint32_t\nsub_word(uint32_t x)\n{\n\tuint32_t q[8];\n\tint i;\n\n\tfor (i = 0; i < 8; i ++) {\n\t\tq[i] = x;\n\t}\n\taes_ct_ortho(q);\n\taes_ct_bitslice_Sbox(q);\n\taes_ct_ortho(q);\n\treturn q[0];\n}\n\nstatic const unsigned char Rcon[] = {\n\t0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36\n};\n\n/*\n * Base key schedule code. The function sub_word() must be defined\n * below. Subkeys are produced in little-endian convention (but not\n * bitsliced). Key length is expressed in bytes.\n */\nstatic unsigned\naes_keysched_base(uint32_t *skey, const void *key, size_t key_len)\n{\n\tunsigned num_rounds;\n\tint i, j, k, nk, nkf;\n\tuint32_t tmp;\n\n\tswitch (key_len) {\n\tcase 16:\n\t\tnum_rounds = 10;\n\t\tbreak;\n\tcase 24:\n\t\tnum_rounds = 12;\n\t\tbreak;\n\tcase 32:\n\t\tnum_rounds = 14;\n\t\tbreak;\n\tdefault:\n\t\treturn 0;\n\t}\n\tnk = (int)(key_len >> 2);\n\tnkf = (int)((num_rounds + 1) << 2);\n\tfor (i = 0; i < nk; i ++) {\n\t\ttmp = dec32le((const unsigned char *)key + (i << 2));\n\t\tskey[i] = tmp;\n\t}\n\ttmp = skey[(key_len >> 2) - 1];\n\tfor (i = nk, j = 0, k = 0; i < nkf; i ++) {\n\t\tif (j == 0) {\n\t\t\ttmp = (tmp << 24) | (tmp >> 8);\n\t\t\ttmp = sub_word(tmp) ^ Rcon[k];\n\t\t} else if (nk > 6 && j == 4) {\n\t\t\ttmp = sub_word(tmp);\n\t\t}\n\t\ttmp ^= skey[i - nk];\n\t\tskey[i] = tmp;\n\t\tif (++ j == nk) {\n\t\t\tj = 0;\n\t\t\tk ++;\n\t\t}\n\t}\n\treturn num_rounds;\n}\n\n/*\n * AES key schedule, constant-time version. skey[] is filled with n+1\n * 128-bit subkeys, where n is the number of rounds (10 to 14, depending\n * on key size). The number of rounds is returned. If the key size is\n * invalid (not 16, 24 or 32), then 0 is returned.\n */\nunsigned\naes_ct_keysched(uint32_t *comp_skey, const void *key, size_t key_len)\n{\n\tuint32_t skey[60];\n\tunsigned u, num_rounds;\n\n\tnum_rounds = aes_keysched_base(skey, key, key_len);\n\tfor (u = 0; u <= num_rounds; u ++) {\n\t\tuint32_t q[8];\n\n\t\tq[0] = q[1] = skey[(u << 2) + 0];\n\t\tq[2] = q[3] = skey[(u << 2) + 1];\n\t\tq[4] = q[5] = skey[(u << 2) + 2];\n\t\tq[6] = q[7] = skey[(u << 2) + 3];\n\t\taes_ct_ortho(q);\n\t\tcomp_skey[(u << 2) + 0] =\n\t\t\t(q[0] & 0x55555555) | (q[1] & 0xAAAAAAAA);\n\t\tcomp_skey[(u << 2) + 1] =\n\t\t\t(q[2] & 0x55555555) | (q[3] & 0xAAAAAAAA);\n\t\tcomp_skey[(u << 2) + 2] =\n\t\t\t(q[4] & 0x55555555) | (q[5] & 0xAAAAAAAA);\n\t\tcomp_skey[(u << 2) + 3] =\n\t\t\t(q[6] & 0x55555555) | (q[7] & 0xAAAAAAAA);\n\t}\n\treturn num_rounds;\n}\n\n/*\n * Expand AES subkeys as produced by aes_ct_keysched(), into\n * a larger array suitable for aes_ct_bitslice_encrypt() and\n * aes_ct_bitslice_decrypt().\n */\nvoid\naes_ct_skey_expand(uint32_t *skey,\n\tunsigned num_rounds, const uint32_t *comp_skey)\n{\n\tunsigned u, v, n;\n\n\tn = (num_rounds + 1) << 2;\n\tfor (u = 0, v = 0; u < n; u ++, v += 2) {\n\t\tuint32_t x, y;\n\n\t\tx = y = comp_skey[u];\n\t\tx &= 0x55555555;\n\t\tskey[v + 0] = x | (x << 1);\n\t\ty &= 0xAAAAAAAA;\n\t\tskey[v + 1] = y | (y >> 1);\n\t}\n}\n\nstatic inline void\nadd_round_key(uint32_t *q, const uint32_t *sk)\n{\n\tq[0] ^= sk[0];\n\tq[1] ^= sk[1];\n\tq[2] ^= sk[2];\n\tq[3] ^= sk[3];\n\tq[4] ^= sk[4];\n\tq[5] ^= sk[5];\n\tq[6] ^= sk[6];\n\tq[7] ^= sk[7];\n}\n\nstatic inline void\nshift_rows(uint32_t *q)\n{\n\tint i;\n\n\tfor (i = 0; i < 8; i ++) {\n\t\tuint32_t x;\n\n\t\tx = q[i];\n\t\tq[i] = (x & 0x000000FF)\n\t\t\t| ((x & 0x0000FC00) >> 2) | ((x & 0x00000300) << 6)\n\t\t\t| ((x & 0x00F00000) >> 4) | ((x & 0x000F0000) << 4)\n\t\t\t| ((x & 0xC0000000) >> 6) | ((x & 0x3F000000) << 2);\n\t}\n}\n\nstatic inline uint32_t\nrotr16(uint32_t x)\n{\n\treturn (x << 16) | (x >> 16);\n}\n\nstatic inline void\nmix_columns(uint32_t *q)\n{\n\tuint32_t q0, q1, q2, q3, q4, q5, q6, q7;\n\tuint32_t r0, r1, r2, r3, r4, r5, r6, r7;\n\n\tq0 = q[0];\n\tq1 = q[1];\n\tq2 = q[2];\n\tq3 = q[3];\n\tq4 = q[4];\n\tq5 = q[5];\n\tq6 = q[6];\n\tq7 = q[7];\n\tr0 = (q0 >> 8) | (q0 << 24);\n\tr1 = (q1 >> 8) | (q1 << 24);\n\tr2 = (q2 >> 8) | (q2 << 24);\n\tr3 = (q3 >> 8) | (q3 << 24);\n\tr4 = (q4 >> 8) | (q4 << 24);\n\tr5 = (q5 >> 8) | (q5 << 24);\n\tr6 = (q6 >> 8) | (q6 << 24);\n\tr7 = (q7 >> 8) | (q7 << 24);\n\n\tq[0] = q7 ^ r7 ^ r0 ^ rotr16(q0 ^ r0);\n\tq[1] = q0 ^ r0 ^ q7 ^ r7 ^ r1 ^ rotr16(q1 ^ r1);\n\tq[2] = q1 ^ r1 ^ r2 ^ rotr16(q2 ^ r2);\n\tq[3] = q2 ^ r2 ^ q7 ^ r7 ^ r3 ^ rotr16(q3 ^ r3);\n\tq[4] = q3 ^ r3 ^ q7 ^ r7 ^ r4 ^ rotr16(q4 ^ r4);\n\tq[5] = q4 ^ r4 ^ r5 ^ rotr16(q5 ^ r5);\n\tq[6] = q5 ^ r5 ^ r6 ^ rotr16(q6 ^ r6);\n\tq[7] = q6 ^ r6 ^ r7 ^ rotr16(q7 ^ r7);\n}\n\n/*\n * Compute AES encryption on bitsliced data. Since input is stored on\n * eight 32-bit words, two block encryptions are actually performed\n * in parallel.\n */\nvoid\naes_ct_bitslice_encrypt(unsigned num_rounds,\n\tconst uint32_t *skey, uint32_t *q)\n{\n\tunsigned u;\n\n\tadd_round_key(q, skey);\n\tfor (u = 1; u < num_rounds; u ++) {\n\t\taes_ct_bitslice_Sbox(q);\n\t\tshift_rows(q);\n\t\tmix_columns(q);\n\t\tadd_round_key(q, skey + (u << 3));\n\t}\n\taes_ct_bitslice_Sbox(q);\n\tshift_rows(q);\n\tadd_round_key(q, skey + (num_rounds << 3));\n}\n\n/*\n * Like aes_ct_bitslice_Sbox(), but for the inverse S-box.\n */\nvoid\naes_ct_bitslice_invSbox(uint32_t *q)\n{\n\t/*\n\t * AES S-box is:\n\t *   S(x) = A(I(x)) ^ 0x63\n\t * where I() is inversion in GF(256), and A() is a linear\n\t * transform (0 is formally defined to be its own inverse).\n\t * Since inversion is an involution, the inverse S-box can be\n\t * computed from the S-box as:\n\t *   iS(x) = B(S(B(x ^ 0x63)) ^ 0x63)\n\t * where B() is the inverse of A(). Indeed, for any y in GF(256):\n\t *   iS(S(y)) = B(A(I(B(A(I(y)) ^ 0x63 ^ 0x63))) ^ 0x63 ^ 0x63) = y\n\t *\n\t * Note: we reuse the implementation of the forward S-box,\n\t * instead of duplicating it here, so that total code size is\n\t * lower. By merging the B() transforms into the S-box circuit\n\t * we could make faster CBC decryption, but CBC decryption is\n\t * already quite faster than CBC encryption because we can\n\t * process two blocks in parallel.\n\t */\n\tuint32_t q0, q1, q2, q3, q4, q5, q6, q7;\n\n\tq0 = ~q[0];\n\tq1 = ~q[1];\n\tq2 = q[2];\n\tq3 = q[3];\n\tq4 = q[4];\n\tq5 = ~q[5];\n\tq6 = ~q[6];\n\tq7 = q[7];\n\tq[7] = q1 ^ q4 ^ q6;\n\tq[6] = q0 ^ q3 ^ q5;\n\tq[5] = q7 ^ q2 ^ q4;\n\tq[4] = q6 ^ q1 ^ q3;\n\tq[3] = q5 ^ q0 ^ q2;\n\tq[2] = q4 ^ q7 ^ q1;\n\tq[1] = q3 ^ q6 ^ q0;\n\tq[0] = q2 ^ q5 ^ q7;\n\n\taes_ct_bitslice_Sbox(q);\n\n\tq0 = ~q[0];\n\tq1 = ~q[1];\n\tq2 = q[2];\n\tq3 = q[3];\n\tq4 = q[4];\n\tq5 = ~q[5];\n\tq6 = ~q[6];\n\tq7 = q[7];\n\tq[7] = q1 ^ q4 ^ q6;\n\tq[6] = q0 ^ q3 ^ q5;\n\tq[5] = q7 ^ q2 ^ q4;\n\tq[4] = q6 ^ q1 ^ q3;\n\tq[3] = q5 ^ q0 ^ q2;\n\tq[2] = q4 ^ q7 ^ q1;\n\tq[1] = q3 ^ q6 ^ q0;\n\tq[0] = q2 ^ q5 ^ q7;\n}\n\nstatic inline void\ninv_shift_rows(uint32_t *q)\n{\n\tint i;\n\n\tfor (i = 0; i < 8; i ++) {\n\t\tuint32_t x;\n\n\t\tx = q[i];\n\t\tq[i] = (x & 0x000000FF)\n\t\t\t| ((x & 0x00003F00) << 2) | ((x & 0x0000C000) >> 6)\n\t\t\t| ((x & 0x000F0000) << 4) | ((x & 0x00F00000) >> 4)\n\t\t\t| ((x & 0x03000000) << 6) | ((x & 0xFC000000) >> 2);\n\t}\n}\n\nstatic void\ninv_mix_columns(uint32_t *q)\n{\n\tuint32_t q0, q1, q2, q3, q4, q5, q6, q7;\n\tuint32_t r0, r1, r2, r3, r4, r5, r6, r7;\n\n\tq0 = q[0];\n\tq1 = q[1];\n\tq2 = q[2];\n\tq3 = q[3];\n\tq4 = q[4];\n\tq5 = q[5];\n\tq6 = q[6];\n\tq7 = q[7];\n\tr0 = (q0 >> 8) | (q0 << 24);\n\tr1 = (q1 >> 8) | (q1 << 24);\n\tr2 = (q2 >> 8) | (q2 << 24);\n\tr3 = (q3 >> 8) | (q3 << 24);\n\tr4 = (q4 >> 8) | (q4 << 24);\n\tr5 = (q5 >> 8) | (q5 << 24);\n\tr6 = (q6 >> 8) | (q6 << 24);\n\tr7 = (q7 >> 8) | (q7 << 24);\n\n\tq[0] = q5 ^ q6 ^ q7 ^ r0 ^ r5 ^ r7 ^ rotr16(q0 ^ q5 ^ q6 ^ r0 ^ r5);\n\tq[1] = q0 ^ q5 ^ r0 ^ r1 ^ r5 ^ r6 ^ r7 ^ rotr16(q1 ^ q5 ^ q7 ^ r1 ^ r5 ^ r6);\n\tq[2] = q0 ^ q1 ^ q6 ^ r1 ^ r2 ^ r6 ^ r7 ^ rotr16(q0 ^ q2 ^ q6 ^ r2 ^ r6 ^ r7);\n\tq[3] = q0 ^ q1 ^ q2 ^ q5 ^ q6 ^ r0 ^ r2 ^ r3 ^ r5 ^ rotr16(q0 ^ q1 ^ q3 ^ q5 ^ q6 ^ q7 ^ r0 ^ r3 ^ r5 ^ r7);\n\tq[4] = q1 ^ q2 ^ q3 ^ q5 ^ r1 ^ r3 ^ r4 ^ r5 ^ r6 ^ r7 ^ rotr16(q1 ^ q2 ^ q4 ^ q5 ^ q7 ^ r1 ^ r4 ^ r5 ^ r6);\n\tq[5] = q2 ^ q3 ^ q4 ^ q6 ^ r2 ^ r4 ^ r5 ^ r6 ^ r7 ^ rotr16(q2 ^ q3 ^ q5 ^ q6 ^ r2 ^ r5 ^ r6 ^ r7);\n\tq[6] = q3 ^ q4 ^ q5 ^ q7 ^ r3 ^ r5 ^ r6 ^ r7 ^ rotr16(q3 ^ q4 ^ q6 ^ q7 ^ r3 ^ r6 ^ r7);\n\tq[7] = q4 ^ q5 ^ q6 ^ r4 ^ r6 ^ r7 ^ rotr16(q4 ^ q5 ^ q7 ^ r4 ^ r7);\n}\n\n/*\n * Compute AES decryption on bitsliced data. Since input is stored on\n * eight 32-bit words, two block decryptions are actually performed\n * in parallel.\n */\nvoid\naes_ct_bitslice_decrypt(unsigned num_rounds,\n\tconst uint32_t *skey, uint32_t *q)\n{\n\tunsigned u;\n\n\tadd_round_key(q, skey + (num_rounds << 3));\n\tfor (u = num_rounds - 1; u > 0; u --) {\n\t\tinv_shift_rows(q);\n\t\taes_ct_bitslice_invSbox(q);\n\t\tadd_round_key(q, skey + (u << 3));\n\t\tinv_mix_columns(q);\n\t}\n\tinv_shift_rows(q);\n\taes_ct_bitslice_invSbox(q);\n\tadd_round_key(q, skey);\n}\n\n\nint\nAES_Setkey(AES_CTX *ctx, const uint8_t *key, int len)\n{\n\tctx->num_rounds = aes_ct_keysched(ctx->sk, key, len);\n\tif (ctx->num_rounds == 0)\n\t\treturn -1;\n\taes_ct_skey_expand(ctx->sk_exp, ctx->num_rounds, ctx->sk);\n\treturn 0;\n}\n\nvoid\nAES_Encrypt_ECB(AES_CTX *ctx, const uint8_t *src,\n\tuint8_t *dst, size_t num_blocks)\n{\n\twhile (num_blocks > 0) {\n\t\tuint32_t q[8];\n\n\t\tq[0] = dec32le(src);\n\t\tq[2] = dec32le(src + 4);\n\t\tq[4] = dec32le(src + 8);\n\t\tq[6] = dec32le(src + 12);\n\t\tif (num_blocks > 1) {\n\t\t\tq[1] = dec32le(src + 16);\n\t\t\tq[3] = dec32le(src + 20);\n\t\t\tq[5] = dec32le(src + 24);\n\t\t\tq[7] = dec32le(src + 28);\n\t\t} else {\n\t\t\tq[1] = 0;\n\t\t\tq[3] = 0;\n\t\t\tq[5] = 0;\n\t\t\tq[7] = 0;\n\t\t}\n\t\taes_ct_ortho(q);\n\t\taes_ct_bitslice_encrypt(ctx->num_rounds, ctx->sk_exp, q);\n\t\taes_ct_ortho(q);\n\t\tenc32le(dst, q[0]);\n\t\tenc32le(dst + 4, q[2]);\n\t\tenc32le(dst + 8, q[4]);\n\t\tenc32le(dst + 12, q[6]);\n\t\tif (num_blocks > 1) {\n\t\t\tenc32le(dst + 16, q[1]);\n\t\t\tenc32le(dst + 20, q[3]);\n\t\t\tenc32le(dst + 24, q[5]);\n\t\t\tenc32le(dst + 28, q[7]);\n\t\t\tsrc += 32;\n\t\t\tdst += 32;\n\t\t\tnum_blocks -= 2;\n\t\t} else {\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nvoid\nAES_Decrypt_ECB(AES_CTX *ctx, const uint8_t *src,\n\tuint8_t *dst, size_t num_blocks)\n{\n\twhile (num_blocks > 0) {\n\t\tuint32_t q[8];\n\n\t\tq[0] = dec32le(src);\n\t\tq[2] = dec32le(src + 4);\n\t\tq[4] = dec32le(src + 8);\n\t\tq[6] = dec32le(src + 12);\n\t\tif (num_blocks > 1) {\n\t\t\tq[1] = dec32le(src + 16);\n\t\t\tq[3] = dec32le(src + 20);\n\t\t\tq[5] = dec32le(src + 24);\n\t\t\tq[7] = dec32le(src + 28);\n\t\t} else {\n\t\t\tq[1] = 0;\n\t\t\tq[3] = 0;\n\t\t\tq[5] = 0;\n\t\t\tq[7] = 0;\n\t\t}\n\t\taes_ct_ortho(q);\n\t\taes_ct_bitslice_decrypt(ctx->num_rounds, ctx->sk_exp, q);\n\t\taes_ct_ortho(q);\n\t\tenc32le(dst, q[0]);\n\t\tenc32le(dst + 4, q[2]);\n\t\tenc32le(dst + 8, q[4]);\n\t\tenc32le(dst + 12, q[6]);\n\t\tif (num_blocks > 1) {\n\t\t\tenc32le(dst + 16, q[1]);\n\t\t\tenc32le(dst + 20, q[3]);\n\t\t\tenc32le(dst + 24, q[5]);\n\t\t\tenc32le(dst + 28, q[7]);\n\t\t\tsrc += 32;\n\t\t\tdst += 32;\n\t\t\tnum_blocks -= 2;\n\t\t} else {\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nvoid\nAES_Encrypt(AES_CTX *ctx, const uint8_t *src, uint8_t *dst)\n{\n\tAES_Encrypt_ECB(ctx, src, dst, 1);\n}\n\nvoid\nAES_Decrypt(AES_CTX *ctx, const uint8_t *src, uint8_t *dst)\n{\n\tAES_Decrypt_ECB(ctx, src, dst, 1);\n}\n\nint\nAES_KeySetup_Encrypt(uint32_t *skey, const uint8_t *key, int len)\n{\n\tunsigned r, u;\n\tuint32_t tkey[60];\n\n\tr = aes_keysched_base(tkey, key, len);\n\tif (r == 0) {\n\t\treturn 0;\n\t}\n\tfor (u = 0; u < ((r + 1) << 2); u ++) {\n\t\tuint32_t w;\n\n\t\tw = tkey[u];\n\t\tskey[u] = (w << 24)\n\t\t\t| ((w & 0x0000FF00) << 8)\n\t\t\t| ((w & 0x00FF0000) >> 8)\n\t\t\t| (w >> 24);\n\t}\n\treturn r;\n}\n\n/*\n * Reduce value x modulo polynomial x^8+x^4+x^3+x+1. This works as\n * long as x fits on 12 bits at most.\n */\nstatic inline uint32_t\nredgf256(uint32_t x)\n{\n\tuint32_t h;\n\n\th = x >> 8;\n\treturn (x ^ h ^ (h << 1) ^ (h << 3) ^ (h << 4)) & 0xFF;\n}\n\n/*\n * Multiplication by 0x09 in GF(256).\n */\nstatic inline uint32_t\nmul9(uint32_t x)\n{\n\treturn redgf256(x ^ (x << 3));\n}\n\n/*\n * Multiplication by 0x0B in GF(256).\n */\nstatic inline uint32_t\nmulb(uint32_t x)\n{\n\treturn redgf256(x ^ (x << 1) ^ (x << 3));\n}\n\n/*\n * Multiplication by 0x0D in GF(256).\n */\nstatic inline uint32_t\nmuld(uint32_t x)\n{\n\treturn redgf256(x ^ (x << 2) ^ (x << 3));\n}\n\n/*\n * Multiplication by 0x0E in GF(256).\n */\nstatic inline uint32_t\nmule(uint32_t x)\n{\n\treturn redgf256((x << 1) ^ (x << 2) ^ (x << 3));\n}\n\nint\nAES_KeySetup_Decrypt(uint32_t *skey, const uint8_t *key, int len)\n{\n\tunsigned r, u;\n\tuint32_t tkey[60];\n\n\t/*\n\t * Compute encryption subkeys. We get them in big-endian\n\t * notation.\n\t */\n\tr = AES_KeySetup_Encrypt(tkey, key, len);\n\tif (r == 0) {\n\t\treturn 0;\n\t}\n\n\t/*\n\t * Copy the subkeys in reverse order. Also, apply InvMixColumns()\n\t * on the subkeys (except first and last).\n\t */\n\tmemcpy(skey + (r << 2), tkey, 4 * sizeof(uint32_t));\n\tmemcpy(skey, tkey + (r << 2), 4 * sizeof(uint32_t));\n\tfor (u = 4; u < (r << 2); u ++) {\n\t\tuint32_t sk, sk0, sk1, sk2, sk3;\n\t\tuint32_t tk, tk0, tk1, tk2, tk3;\n\n\t\tsk = tkey[u];\n\t\tsk0 = sk >> 24;\n\t\tsk1 = (sk >> 16) & 0xFF;\n\t\tsk2 = (sk >> 8) & 0xFF;\n\t\tsk3 = sk & 0xFF;\n\t\ttk0 = mule(sk0) ^ mulb(sk1) ^ muld(sk2) ^ mul9(sk3);\n\t\ttk1 = mul9(sk0) ^ mule(sk1) ^ mulb(sk2) ^ muld(sk3);\n\t\ttk2 = muld(sk0) ^ mul9(sk1) ^ mule(sk2) ^ mulb(sk3);\n\t\ttk3 = mulb(sk0) ^ muld(sk1) ^ mul9(sk2) ^ mule(sk3);\n\t\ttk = (tk0 << 24) ^ (tk1 << 16) ^ (tk2 << 8) ^ tk3;\n\t\tskey[((r - (u >> 2)) << 2) + (u & 3)] = tk;\n\t}\n\n\treturn r;\n}\n"
  },
  {
    "path": "itl80211/openbsd/crypto/aes.h",
    "content": "/*\n * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>\n * Copyright (c) 2016 Mike Belopuhov\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the\n * \"Software\"), to deal in the Software without restriction, including\n * without limitation the rights to use, copy, modify, merge, publish,\n * distribute, sublicense, and/or sell copies of the Software, and to\n * permit persons to whom the Software is furnished to do so, subject to\n * the following conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\n * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\n * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n#ifndef _AES_H_\n#define _AES_H_\n\n#ifndef AES_MAXROUNDS\n#define AES_MAXROUNDS\t(14)\n#endif\n\ntypedef struct aes_ctx {\n\tuint32_t sk[60];\n\tuint32_t sk_exp[120];\n\n\tunsigned num_rounds;\n} AES_CTX;\n\nint\tAES_Setkey(AES_CTX *, const uint8_t *, int);\nvoid\tAES_Encrypt(AES_CTX *, const uint8_t *, uint8_t *);\nvoid\tAES_Decrypt(AES_CTX *, const uint8_t *, uint8_t *);\nvoid\tAES_Encrypt_ECB(AES_CTX *, const uint8_t *, uint8_t *, size_t);\nvoid\tAES_Decrypt_ECB(AES_CTX *, const uint8_t *, uint8_t *, size_t);\n\nint\tAES_KeySetup_Encrypt(uint32_t *, const uint8_t *, int);\nint\tAES_KeySetup_Decrypt(uint32_t *, const uint8_t *, int);\n\n#endif\t/* _AES_H_ */\n"
  },
  {
    "path": "itl80211/openbsd/crypto/arc4.c",
    "content": "/*\t$OpenBSD: arc4.c,v 1.3 2007/09/11 12:07:05 djm Exp $\t*/\n/*\n * Copyright (c) 2003 Markus Friedl <markus@openbsd.org>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n#include <sys/types.h>                                                         \n\n#include <crypto/arc4.h> \n\n#define RC4SWAP(x,y) \\\n\tdo { \\\n\t\tu_int8_t t = ctx->state[x];  \\\n\t\tctx->state[x] = ctx->state[y]; \\\n\t\tctx->state[y] = t; \\\n\t} while(0)\n\nvoid\nrc4_keysetup(struct rc4_ctx *ctx, u_char *key, u_int32_t klen)\n{\n\tu_int8_t x, y;\n\tu_int32_t i;\n\n\tx = y = 0;\n\tfor (i = 0; i < RC4STATE; i++)\n\t\tctx->state[i] = i;\n\tfor (i = 0; i < RC4STATE; i++) {\n\t\ty = (key[x] + ctx->state[i] + y) & (RC4STATE - 1);\n\t\tRC4SWAP(i, y);\n\t\tx = (x + 1) % klen;\n\t}\n\tctx->x = ctx->y = 0;\n}\n\nvoid\nrc4_crypt(struct rc4_ctx *ctx, u_char *src, u_char *dst,\n    u_int32_t len)\n{\n\tu_int32_t i;\n\n\tfor (i = 0; i < len; i++) {\n\t\tctx->x = (ctx->x + 1) & (RC4STATE - 1);\n\t\tctx->y = (ctx->state[ctx->x] + ctx->y) & (RC4STATE - 1);\n\t\tRC4SWAP(ctx->x, ctx->y);\n\t\tdst[i] = src[i] ^ ctx->state[\n\t\t   (ctx->state[ctx->x] + ctx->state[ctx->y]) & (RC4STATE - 1)];\n\t}\n}\n\nvoid\nrc4_getbytes(struct rc4_ctx *ctx, u_char *dst, u_int32_t len)\n{\n\tu_int32_t i;\n\n\tfor (i = 0; i < len; i++) {\n\t\tctx->x = (ctx->x + 1) & (RC4STATE - 1);\n\t\tctx->y = (ctx->state[ctx->x] + ctx->y) & (RC4STATE - 1);\n\t\tRC4SWAP(ctx->x, ctx->y);\n\t\tdst[i] = ctx->state[\n\t\t   (ctx->state[ctx->x] + ctx->state[ctx->y]) & (RC4STATE - 1)];\n\t}\n}\n\nvoid\nrc4_skip(struct rc4_ctx *ctx, u_int32_t len)\n{\n\tfor (; len > 0; len--) {\n\t\tctx->x = (ctx->x + 1) & (RC4STATE - 1);\n\t\tctx->y = (ctx->state[ctx->x] + ctx->y) & (RC4STATE - 1);\n\t\tRC4SWAP(ctx->x, ctx->y);\n\t}\n}\n"
  },
  {
    "path": "itl80211/openbsd/crypto/arc4.h",
    "content": "/*\t$OpenBSD: arc4.h,v 1.3 2007/09/11 12:07:05 djm Exp $\t*/\n/*\n * Copyright (c) 2003 Markus Friedl <markus@openbsd.org>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n#define RC4STATE 256\n#define RC4KEYLEN 16\n\nstruct rc4_ctx {\n\tu_int8_t x, y;\n\tu_int8_t state[RC4STATE];\n};\n\nvoid\trc4_keysetup(struct rc4_ctx *, u_char *, u_int32_t)\n    __attribute__((__bounded__(__buffer__,2,3)));\nvoid\trc4_crypt(struct rc4_ctx *, u_char *, u_char *, u_int32_t)\n    __attribute__((__bounded__(__buffer__,2,4)))\n    __attribute__((__bounded__(__buffer__,3,4)));\nvoid\trc4_getbytes(struct rc4_ctx *, u_char *, u_int32_t)\n    __attribute__((__bounded__(__buffer__,2,3)));\nvoid\trc4_skip(struct rc4_ctx *, u_int32_t);\n"
  },
  {
    "path": "itl80211/openbsd/crypto/blf.c",
    "content": "/*\t$OpenBSD: blf.c,v 1.7 2007/11/26 09:28:34 martynas Exp $\t*/\n\n/*\n * Blowfish block cipher for OpenBSD\n * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>\n * All rights reserved.\n *\n * Implementation advice by David Mazieres <dm@lcs.mit.edu>.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *      This product includes software developed by Niels Provos.\n * 4. The name of the author may not be used to endorse or promote products\n *    derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*\n * This code is derived from section 14.3 and the given source\n * in section V of Applied Cryptography, second edition.\n * Blowfish is an unpatented fast block cipher designed by\n * Bruce Schneier.\n */\n\n#include <sys/param.h>\n#include <sys/systm.h>\n\n#include <crypto/blf.h>\n\n#undef inline\n#ifdef __GNUC__\n#define inline __inline\n#else\t\t\t\t/* !__GNUC__ */\n#define inline\n#endif\t\t\t\t/* !__GNUC__ */\n\n/* Function for Feistel Networks */\n\n#define F(s, x) ((((s)[        (((x)>>24)&0xFF)]  \\\n\t\t + (s)[0x100 + (((x)>>16)&0xFF)]) \\\n\t\t ^ (s)[0x200 + (((x)>> 8)&0xFF)]) \\\n\t\t + (s)[0x300 + ( (x)     &0xFF)])\n\n#define BLFRND(s,p,i,j,n) (i ^= F(s,j) ^ (p)[n])\n\nvoid\nBlowfish_encipher(blf_ctx *c, u_int32_t *x)\n{\n\tu_int32_t Xl;\n\tu_int32_t Xr;\n\tu_int32_t *s = c->S[0];\n\tu_int32_t *p = c->P;\n\n\tXl = x[0];\n\tXr = x[1];\n\n\tXl ^= p[0];\n\tBLFRND(s, p, Xr, Xl, 1); BLFRND(s, p, Xl, Xr, 2);\n\tBLFRND(s, p, Xr, Xl, 3); BLFRND(s, p, Xl, Xr, 4);\n\tBLFRND(s, p, Xr, Xl, 5); BLFRND(s, p, Xl, Xr, 6);\n\tBLFRND(s, p, Xr, Xl, 7); BLFRND(s, p, Xl, Xr, 8);\n\tBLFRND(s, p, Xr, Xl, 9); BLFRND(s, p, Xl, Xr, 10);\n\tBLFRND(s, p, Xr, Xl, 11); BLFRND(s, p, Xl, Xr, 12);\n\tBLFRND(s, p, Xr, Xl, 13); BLFRND(s, p, Xl, Xr, 14);\n\tBLFRND(s, p, Xr, Xl, 15); BLFRND(s, p, Xl, Xr, 16);\n\n\tx[0] = Xr ^ p[17];\n\tx[1] = Xl;\n}\n\nvoid\nBlowfish_decipher(blf_ctx *c, u_int32_t *x)\n{\n\tu_int32_t Xl;\n\tu_int32_t Xr;\n\tu_int32_t *s = c->S[0];\n\tu_int32_t *p = c->P;\n\n\tXl = x[0];\n\tXr = x[1];\n\n\tXl ^= p[17];\n\tBLFRND(s, p, Xr, Xl, 16); BLFRND(s, p, Xl, Xr, 15);\n\tBLFRND(s, p, Xr, Xl, 14); BLFRND(s, p, Xl, Xr, 13);\n\tBLFRND(s, p, Xr, Xl, 12); BLFRND(s, p, Xl, Xr, 11);\n\tBLFRND(s, p, Xr, Xl, 10); BLFRND(s, p, Xl, Xr, 9);\n\tBLFRND(s, p, Xr, Xl, 8); BLFRND(s, p, Xl, Xr, 7);\n\tBLFRND(s, p, Xr, Xl, 6); BLFRND(s, p, Xl, Xr, 5);\n\tBLFRND(s, p, Xr, Xl, 4); BLFRND(s, p, Xl, Xr, 3);\n\tBLFRND(s, p, Xr, Xl, 2); BLFRND(s, p, Xl, Xr, 1);\n\n\tx[0] = Xr ^ p[0];\n\tx[1] = Xl;\n}\n\nvoid\nBlowfish_initstate(blf_ctx *c)\n{\n\t/* P-box and S-box tables initialized with digits of Pi */\n\n\tstatic const blf_ctx initstate =\n\n\t{ {\n\t\t{\n\t\t\t0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,\n\t\t\t0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,\n\t\t\t0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,\n\t\t\t0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,\n\t\t\t0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,\n\t\t\t0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,\n\t\t\t0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,\n\t\t\t0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,\n\t\t\t0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,\n\t\t\t0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,\n\t\t\t0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,\n\t\t\t0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,\n\t\t\t0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,\n\t\t\t0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,\n\t\t\t0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,\n\t\t\t0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,\n\t\t\t0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,\n\t\t\t0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,\n\t\t\t0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,\n\t\t\t0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,\n\t\t\t0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,\n\t\t\t0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,\n\t\t\t0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,\n\t\t\t0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,\n\t\t\t0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,\n\t\t\t0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,\n\t\t\t0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,\n\t\t\t0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,\n\t\t\t0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,\n\t\t\t0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,\n\t\t\t0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,\n\t\t\t0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,\n\t\t\t0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,\n\t\t\t0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,\n\t\t\t0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,\n\t\t\t0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,\n\t\t\t0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,\n\t\t\t0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,\n\t\t\t0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,\n\t\t\t0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,\n\t\t\t0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,\n\t\t\t0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,\n\t\t\t0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,\n\t\t\t0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,\n\t\t\t0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,\n\t\t\t0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,\n\t\t\t0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,\n\t\t\t0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,\n\t\t\t0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,\n\t\t\t0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,\n\t\t\t0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,\n\t\t\t0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,\n\t\t\t0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,\n\t\t\t0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,\n\t\t\t0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,\n\t\t\t0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,\n\t\t\t0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,\n\t\t\t0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,\n\t\t\t0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,\n\t\t\t0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,\n\t\t\t0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,\n\t\t\t0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,\n\t\t\t0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,\n\t\t0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a},\n\t\t{\n\t\t\t0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,\n\t\t\t0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,\n\t\t\t0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,\n\t\t\t0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,\n\t\t\t0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,\n\t\t\t0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,\n\t\t\t0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,\n\t\t\t0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,\n\t\t\t0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,\n\t\t\t0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,\n\t\t\t0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,\n\t\t\t0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,\n\t\t\t0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,\n\t\t\t0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,\n\t\t\t0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,\n\t\t\t0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,\n\t\t\t0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,\n\t\t\t0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,\n\t\t\t0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,\n\t\t\t0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,\n\t\t\t0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,\n\t\t\t0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,\n\t\t\t0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,\n\t\t\t0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,\n\t\t\t0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,\n\t\t\t0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,\n\t\t\t0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,\n\t\t\t0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,\n\t\t\t0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,\n\t\t\t0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,\n\t\t\t0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,\n\t\t\t0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,\n\t\t\t0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,\n\t\t\t0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,\n\t\t\t0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,\n\t\t\t0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,\n\t\t\t0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,\n\t\t\t0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,\n\t\t\t0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,\n\t\t\t0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,\n\t\t\t0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,\n\t\t\t0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,\n\t\t\t0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,\n\t\t\t0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,\n\t\t\t0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,\n\t\t\t0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,\n\t\t\t0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,\n\t\t\t0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,\n\t\t\t0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,\n\t\t\t0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,\n\t\t\t0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,\n\t\t\t0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,\n\t\t\t0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,\n\t\t\t0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,\n\t\t\t0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,\n\t\t\t0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,\n\t\t\t0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,\n\t\t\t0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,\n\t\t\t0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,\n\t\t\t0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,\n\t\t\t0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,\n\t\t\t0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,\n\t\t\t0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,\n\t\t0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7},\n\t\t{\n\t\t\t0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,\n\t\t\t0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,\n\t\t\t0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,\n\t\t\t0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,\n\t\t\t0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,\n\t\t\t0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,\n\t\t\t0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,\n\t\t\t0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,\n\t\t\t0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,\n\t\t\t0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,\n\t\t\t0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,\n\t\t\t0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,\n\t\t\t0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,\n\t\t\t0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,\n\t\t\t0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,\n\t\t\t0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,\n\t\t\t0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,\n\t\t\t0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,\n\t\t\t0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,\n\t\t\t0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,\n\t\t\t0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,\n\t\t\t0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,\n\t\t\t0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,\n\t\t\t0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,\n\t\t\t0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,\n\t\t\t0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,\n\t\t\t0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,\n\t\t\t0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,\n\t\t\t0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,\n\t\t\t0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,\n\t\t\t0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,\n\t\t\t0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,\n\t\t\t0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,\n\t\t\t0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,\n\t\t\t0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,\n\t\t\t0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,\n\t\t\t0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,\n\t\t\t0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,\n\t\t\t0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,\n\t\t\t0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,\n\t\t\t0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,\n\t\t\t0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,\n\t\t\t0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,\n\t\t\t0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,\n\t\t\t0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,\n\t\t\t0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,\n\t\t\t0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,\n\t\t\t0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,\n\t\t\t0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,\n\t\t\t0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,\n\t\t\t0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,\n\t\t\t0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,\n\t\t\t0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,\n\t\t\t0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,\n\t\t\t0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,\n\t\t\t0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,\n\t\t\t0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,\n\t\t\t0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,\n\t\t\t0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,\n\t\t\t0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,\n\t\t\t0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,\n\t\t\t0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,\n\t\t\t0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,\n\t\t0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0},\n\t\t{\n\t\t\t0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,\n\t\t\t0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,\n\t\t\t0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,\n\t\t\t0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,\n\t\t\t0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,\n\t\t\t0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,\n\t\t\t0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,\n\t\t\t0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,\n\t\t\t0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,\n\t\t\t0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,\n\t\t\t0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,\n\t\t\t0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,\n\t\t\t0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,\n\t\t\t0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,\n\t\t\t0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,\n\t\t\t0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,\n\t\t\t0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,\n\t\t\t0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,\n\t\t\t0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,\n\t\t\t0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,\n\t\t\t0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,\n\t\t\t0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,\n\t\t\t0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,\n\t\t\t0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,\n\t\t\t0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,\n\t\t\t0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,\n\t\t\t0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,\n\t\t\t0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,\n\t\t\t0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,\n\t\t\t0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,\n\t\t\t0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,\n\t\t\t0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,\n\t\t\t0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,\n\t\t\t0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,\n\t\t\t0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,\n\t\t\t0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,\n\t\t\t0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,\n\t\t\t0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,\n\t\t\t0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,\n\t\t\t0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,\n\t\t\t0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,\n\t\t\t0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,\n\t\t\t0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,\n\t\t\t0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,\n\t\t\t0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,\n\t\t\t0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,\n\t\t\t0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,\n\t\t\t0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,\n\t\t\t0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,\n\t\t\t0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,\n\t\t\t0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,\n\t\t\t0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,\n\t\t\t0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,\n\t\t\t0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,\n\t\t\t0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,\n\t\t\t0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,\n\t\t\t0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,\n\t\t\t0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,\n\t\t\t0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,\n\t\t\t0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,\n\t\t\t0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,\n\t\t\t0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,\n\t\t\t0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,\n\t\t0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6}\n\t},\n\t{\n\t\t0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,\n\t\t0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,\n\t\t0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,\n\t\t0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,\n\t\t0x9216d5d9, 0x8979fb1b\n\t} };\n\n\t*c = initstate;\n}\n\nu_int32_t\nBlowfish_stream2word(const u_int8_t *data, u_int16_t databytes,\n    u_int16_t *current)\n{\n\tu_int8_t i;\n\tu_int16_t j;\n\tu_int32_t temp;\n\n\ttemp = 0x00000000;\n\tj = *current;\n\n\tfor (i = 0; i < 4; i++, j++) {\n\t\tif (j >= databytes)\n\t\t\tj = 0;\n\t\ttemp = (temp << 8) | data[j];\n\t}\n\n\t*current = j;\n\treturn temp;\n}\n\nvoid\nBlowfish_expand0state(blf_ctx *c, const u_int8_t *key, u_int16_t keybytes)\n{\n\tu_int16_t i;\n\tu_int16_t j;\n\tu_int16_t k;\n\tu_int32_t temp;\n\tu_int32_t data[2];\n\n\tj = 0;\n\tfor (i = 0; i < BLF_N + 2; i++) {\n\t\t/* Extract 4 int8 to 1 int32 from keystream */\n\t\ttemp = Blowfish_stream2word(key, keybytes, &j);\n\t\tc->P[i] = c->P[i] ^ temp;\n\t}\n\n\tj = 0;\n\tdata[0] = 0x00000000;\n\tdata[1] = 0x00000000;\n\tfor (i = 0; i < BLF_N + 2; i += 2) {\n\t\tBlowfish_encipher(c, data);\n\n\t\tc->P[i] = data[0];\n\t\tc->P[i + 1] = data[1];\n\t}\n\n\tfor (i = 0; i < 4; i++) {\n\t\tfor (k = 0; k < 256; k += 2) {\n\t\t\tBlowfish_encipher(c, data);\n\n\t\t\tc->S[i][k] = data[0];\n\t\t\tc->S[i][k + 1] = data[1];\n\t\t}\n\t}\n}\n\n\nvoid\nBlowfish_expandstate(blf_ctx *c, const u_int8_t *data, u_int16_t databytes,\n    const u_int8_t *key, u_int16_t keybytes)\n{\n\tu_int16_t i;\n\tu_int16_t j;\n\tu_int16_t k;\n\tu_int32_t temp;\n\tu_int32_t d[2];\n\n\tj = 0;\n\tfor (i = 0; i < BLF_N + 2; i++) {\n\t\t/* Extract 4 int8 to 1 int32 from keystream */\n\t\ttemp = Blowfish_stream2word(key, keybytes, &j);\n\t\tc->P[i] = c->P[i] ^ temp;\n\t}\n\n\tj = 0;\n\td[0] = 0x00000000;\n\td[1] = 0x00000000;\n\tfor (i = 0; i < BLF_N + 2; i += 2) {\n\t\td[0] ^= Blowfish_stream2word(data, databytes, &j);\n\t\td[1] ^= Blowfish_stream2word(data, databytes, &j);\n\t\tBlowfish_encipher(c, d);\n\n\t\tc->P[i] = d[0];\n\t\tc->P[i + 1] = d[1];\n\t}\n\n\tfor (i = 0; i < 4; i++) {\n\t\tfor (k = 0; k < 256; k += 2) {\n\t\t\td[0]^= Blowfish_stream2word(data, databytes, &j);\n\t\t\td[1] ^= Blowfish_stream2word(data, databytes, &j);\n\t\t\tBlowfish_encipher(c, d);\n\n\t\t\tc->S[i][k] = d[0];\n\t\t\tc->S[i][k + 1] = d[1];\n\t\t}\n\t}\n\n}\n\nvoid\nblf_key(blf_ctx *c, const u_int8_t *k, u_int16_t len)\n{\n\t/* Initialize S-boxes and subkeys with Pi */\n\tBlowfish_initstate(c);\n\n\t/* Transform S-boxes and subkeys with key */\n\tBlowfish_expand0state(c, k, len);\n}\n\nvoid\nblf_enc(blf_ctx *c, u_int32_t *data, u_int16_t blocks)\n{\n\tu_int32_t *d;\n\tu_int16_t i;\n\n\td = data;\n\tfor (i = 0; i < blocks; i++) {\n\t\tBlowfish_encipher(c, d);\n\t\td += 2;\n\t}\n}\n\nvoid\nblf_dec(blf_ctx *c, u_int32_t *data, u_int16_t blocks)\n{\n\tu_int32_t *d;\n\tu_int16_t i;\n\n\td = data;\n\tfor (i = 0; i < blocks; i++) {\n\t\tBlowfish_decipher(c, d);\n\t\td += 2;\n\t}\n}\n\nvoid\nblf_ecb_encrypt(blf_ctx *c, u_int8_t *data, u_int32_t len)\n{\n\tu_int32_t l, r, d[2];\n\tu_int32_t i;\n\n\tfor (i = 0; i < len; i += 8) {\n\t\tl = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];\n\t\tr = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];\n\t\td[0] = l;\n\t\td[1] = r;\n\t\tBlowfish_encipher(c, d);\n\t\tl = d[0];\n\t\tr = d[1];\n\t\tdata[0] = l >> 24 & 0xff;\n\t\tdata[1] = l >> 16 & 0xff;\n\t\tdata[2] = l >> 8 & 0xff;\n\t\tdata[3] = l & 0xff;\n\t\tdata[4] = r >> 24 & 0xff;\n\t\tdata[5] = r >> 16 & 0xff;\n\t\tdata[6] = r >> 8 & 0xff;\n\t\tdata[7] = r & 0xff;\n\t\tdata += 8;\n\t}\n}\n\nvoid\nblf_ecb_decrypt(blf_ctx *c, u_int8_t *data, u_int32_t len)\n{\n\tu_int32_t l, r, d[2];\n\tu_int32_t i;\n\n\tfor (i = 0; i < len; i += 8) {\n\t\tl = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];\n\t\tr = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];\n\t\td[0] = l;\n\t\td[1] = r;\n\t\tBlowfish_decipher(c, d);\n\t\tl = d[0];\n\t\tr = d[1];\n\t\tdata[0] = l >> 24 & 0xff;\n\t\tdata[1] = l >> 16 & 0xff;\n\t\tdata[2] = l >> 8 & 0xff;\n\t\tdata[3] = l & 0xff;\n\t\tdata[4] = r >> 24 & 0xff;\n\t\tdata[5] = r >> 16 & 0xff;\n\t\tdata[6] = r >> 8 & 0xff;\n\t\tdata[7] = r & 0xff;\n\t\tdata += 8;\n\t}\n}\n\nvoid\nblf_cbc_encrypt(blf_ctx *c, u_int8_t *iv, u_int8_t *data, u_int32_t len)\n{\n\tu_int32_t l, r, d[2];\n\tu_int32_t i, j;\n\n\tfor (i = 0; i < len; i += 8) {\n\t\tfor (j = 0; j < 8; j++)\n\t\t\tdata[j] ^= iv[j];\n\t\tl = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];\n\t\tr = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];\n\t\td[0] = l;\n\t\td[1] = r;\n\t\tBlowfish_encipher(c, d);\n\t\tl = d[0];\n\t\tr = d[1];\n\t\tdata[0] = l >> 24 & 0xff;\n\t\tdata[1] = l >> 16 & 0xff;\n\t\tdata[2] = l >> 8 & 0xff;\n\t\tdata[3] = l & 0xff;\n\t\tdata[4] = r >> 24 & 0xff;\n\t\tdata[5] = r >> 16 & 0xff;\n\t\tdata[6] = r >> 8 & 0xff;\n\t\tdata[7] = r & 0xff;\n\t\tiv = data;\n\t\tdata += 8;\n\t}\n}\n\nvoid\nblf_cbc_decrypt(blf_ctx *c, u_int8_t *iva, u_int8_t *data, u_int32_t len)\n{\n\tu_int32_t l, r, d[2];\n\tu_int8_t *iv;\n\tu_int32_t i, j;\n\n\tiv = data + len - 16;\n\tdata = data + len - 8;\n\tfor (i = len - 8; i >= 8; i -= 8) {\n\t\tl = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];\n\t\tr = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];\n\t\td[0] = l;\n\t\td[1] = r;\n\t\tBlowfish_decipher(c, d);\n\t\tl = d[0];\n\t\tr = d[1];\n\t\tdata[0] = l >> 24 & 0xff;\n\t\tdata[1] = l >> 16 & 0xff;\n\t\tdata[2] = l >> 8 & 0xff;\n\t\tdata[3] = l & 0xff;\n\t\tdata[4] = r >> 24 & 0xff;\n\t\tdata[5] = r >> 16 & 0xff;\n\t\tdata[6] = r >> 8 & 0xff;\n\t\tdata[7] = r & 0xff;\n\t\tfor (j = 0; j < 8; j++)\n\t\t\tdata[j] ^= iv[j];\n\t\tiv -= 8;\n\t\tdata -= 8;\n\t}\n\tl = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];\n\tr = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];\n\td[0] = l;\n\td[1] = r;\n\tBlowfish_decipher(c, d);\n\tl = d[0];\n\tr = d[1];\n\tdata[0] = l >> 24 & 0xff;\n\tdata[1] = l >> 16 & 0xff;\n\tdata[2] = l >> 8 & 0xff;\n\tdata[3] = l & 0xff;\n\tdata[4] = r >> 24 & 0xff;\n\tdata[5] = r >> 16 & 0xff;\n\tdata[6] = r >> 8 & 0xff;\n\tdata[7] = r & 0xff;\n\tfor (j = 0; j < 8; j++)\n\t\tdata[j] ^= iva[j];\n}\n"
  },
  {
    "path": "itl80211/openbsd/crypto/blf.h",
    "content": "/*\t$OpenBSD: blf.h,v 1.6 2007/02/21 19:25:40 grunk Exp $\t*/\n\n/*\n * Blowfish - a fast block cipher designed by Bruce Schneier\n *\n * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *      This product includes software developed by Niels Provos.\n * 4. The name of the author may not be used to endorse or promote products\n *    derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef _BLF_H_\n#define _BLF_H_\n\n/* Schneier states the maximum key length to be 56 bytes.\n * The way how the subkeys are initialized by the key up\n * to (N+2)*4 i.e. 72 bytes are utilized.\n * Warning: For normal blowfish encryption only 56 bytes\n * of the key affect all cipherbits.\n */\n\n#define BLF_N\t16\t\t\t/* Number of Subkeys */\n#define BLF_MAXKEYLEN ((BLF_N-2)*4)\t/* 448 bits */\n#define BLF_MAXUTILIZED ((BLF_N+2)*4)\t/* 576 bits */\n\n/* Blowfish context */\ntypedef struct BlowfishContext {\n\tu_int32_t S[4][256];\t/* S-Boxes */\n\tu_int32_t P[BLF_N + 2];\t/* Subkeys */\n} blf_ctx;\n\n/* Raw access to customized Blowfish\n *\tblf_key is just:\n *\tBlowfish_initstate( state )\n *\tBlowfish_expand0state( state, key, keylen )\n */\n\nvoid Blowfish_encipher(blf_ctx *, u_int32_t *);\nvoid Blowfish_decipher(blf_ctx *, u_int32_t *);\nvoid Blowfish_initstate(blf_ctx *);\nvoid Blowfish_expand0state(blf_ctx *, const u_int8_t *, u_int16_t);\nvoid Blowfish_expandstate(blf_ctx *, const u_int8_t *, u_int16_t, const u_int8_t *, u_int16_t);\n\n/* Standard Blowfish */\n\nvoid blf_key(blf_ctx *, const u_int8_t *, u_int16_t);\nvoid blf_enc(blf_ctx *, u_int32_t *, u_int16_t);\nvoid blf_dec(blf_ctx *, u_int32_t *, u_int16_t);\n\n/* Converts u_int8_t to u_int32_t */\nu_int32_t Blowfish_stream2word(const u_int8_t *, u_int16_t ,\n\t\t\t\t    u_int16_t *);\n\nvoid blf_ecb_encrypt(blf_ctx *, u_int8_t *, u_int32_t);\nvoid blf_ecb_decrypt(blf_ctx *, u_int8_t *, u_int32_t);\n\nvoid blf_cbc_encrypt(blf_ctx *, u_int8_t *, u_int8_t *, u_int32_t);\nvoid blf_cbc_decrypt(blf_ctx *, u_int8_t *, u_int8_t *, u_int32_t);\n#endif\n"
  },
  {
    "path": "itl80211/openbsd/crypto/cast.c",
    "content": "/*      $OpenBSD: cast.c,v 1.4 2012/04/25 04:12:27 matthew Exp $       */\n\n/*\n *\tCAST-128 in C\n *\tWritten by Steve Reid <sreid@sea-to-sky.net>\n *\t100% Public Domain - no warranty\n *\tReleased 1997.10.11\n */\n\n#include <sys/types.h>\n#include <sys/systm.h>\n#include <crypto/cast.h>\n#include <crypto/castsb.h>\n\n/* Macros to access 8-bit bytes out of a 32-bit word */\n#define U_INT8_Ta(x) ( (u_int8_t) (x>>24) )\n#define U_INT8_Tb(x) ( (u_int8_t) ((x>>16)&255) )\n#define U_INT8_Tc(x) ( (u_int8_t) ((x>>8)&255) )\n#define U_INT8_Td(x) ( (u_int8_t) ((x)&255) )\n\n/* Circular left shift */\n#define ROL(x, n) ( ((x)<<(n)) | ((x)>>(32-(n))) )\n\n/* CAST-128 uses three different round functions */\n#define F1(l, r, i) \\\n\tt = ROL(key->xkey[i] + r, key->xkey[i+16]); \\\n\tl ^= ((cast_sbox1[U_INT8_Ta(t)] ^ cast_sbox2[U_INT8_Tb(t)]) - \\\n\t cast_sbox3[U_INT8_Tc(t)]) + cast_sbox4[U_INT8_Td(t)];\n#define F2(l, r, i) \\\n\tt = ROL(key->xkey[i] ^ r, key->xkey[i+16]); \\\n\tl ^= ((cast_sbox1[U_INT8_Ta(t)] - cast_sbox2[U_INT8_Tb(t)]) + \\\n\t cast_sbox3[U_INT8_Tc(t)]) ^ cast_sbox4[U_INT8_Td(t)];\n#define F3(l, r, i) \\\n\tt = ROL(key->xkey[i] - r, key->xkey[i+16]); \\\n\tl ^= ((cast_sbox1[U_INT8_Ta(t)] + cast_sbox2[U_INT8_Tb(t)]) ^ \\\n\t cast_sbox3[U_INT8_Tc(t)]) - cast_sbox4[U_INT8_Td(t)];\n\n\n/***** Encryption Function *****/\n\nvoid\ncast_encrypt(cast_key *key, u_int8_t *inblock, u_int8_t *outblock)\n{\n\tu_int32_t t, l, r;\n\n\t/* Get inblock into l,r */\n\tl = ((u_int32_t)inblock[0] << 24) | ((u_int32_t)inblock[1] << 16) |\n\t    ((u_int32_t)inblock[2] << 8) | (u_int32_t)inblock[3];\n\tr = ((u_int32_t)inblock[4] << 24) | ((u_int32_t)inblock[5] << 16) |\n\t    ((u_int32_t)inblock[6] << 8) | (u_int32_t)inblock[7];\n\t/* Do the work */\n\tF1(l, r,  0);\n\tF2(r, l,  1);\n\tF3(l, r,  2);\n\tF1(r, l,  3);\n\tF2(l, r,  4);\n\tF3(r, l,  5);\n\tF1(l, r,  6);\n\tF2(r, l,  7);\n\tF3(l, r,  8);\n\tF1(r, l,  9);\n\tF2(l, r, 10);\n\tF3(r, l, 11);\n\t/* Only do full 16 rounds if key length > 80 bits */\n\tif (key->rounds > 12) {\n\t\tF1(l, r, 12);\n\t\tF2(r, l, 13);\n\t\tF3(l, r, 14);\n\t\tF1(r, l, 15);\n\t}\n\t/* Put l,r into outblock */\n\toutblock[0] = U_INT8_Ta(r);\n\toutblock[1] = U_INT8_Tb(r);\n\toutblock[2] = U_INT8_Tc(r);\n\toutblock[3] = U_INT8_Td(r);\n\toutblock[4] = U_INT8_Ta(l);\n\toutblock[5] = U_INT8_Tb(l);\n\toutblock[6] = U_INT8_Tc(l);\n\toutblock[7] = U_INT8_Td(l);\n\t/* Wipe clean */\n\tt = l = r = 0;\n}\n\n\n/***** Decryption Function *****/\n\nvoid\ncast_decrypt(cast_key *key, u_int8_t *inblock, u_int8_t *outblock)\n{\n\tu_int32_t t, l, r;\n\n\t/* Get inblock into l,r */\n\tr = ((u_int32_t)inblock[0] << 24) | ((u_int32_t)inblock[1] << 16) |\n\t    ((u_int32_t)inblock[2] << 8) | (u_int32_t)inblock[3];\n\tl = ((u_int32_t)inblock[4] << 24) | ((u_int32_t)inblock[5] << 16) |\n\t    ((u_int32_t)inblock[6] << 8) | (u_int32_t)inblock[7];\n\t/* Do the work */\n\t/* Only do full 16 rounds if key length > 80 bits */\n\tif (key->rounds > 12) {\n\t\tF1(r, l, 15);\n\t\tF3(l, r, 14);\n\t\tF2(r, l, 13);\n\t\tF1(l, r, 12);\n\t}\n\tF3(r, l, 11);\n\tF2(l, r, 10);\n\tF1(r, l,  9);\n\tF3(l, r,  8);\n\tF2(r, l,  7);\n\tF1(l, r,  6);\n\tF3(r, l,  5);\n\tF2(l, r,  4);\n\tF1(r, l,  3);\n\tF3(l, r,  2);\n\tF2(r, l,  1);\n\tF1(l, r,  0);\n\t/* Put l,r into outblock */\n\toutblock[0] = U_INT8_Ta(l);\n\toutblock[1] = U_INT8_Tb(l);\n\toutblock[2] = U_INT8_Tc(l);\n\toutblock[3] = U_INT8_Td(l);\n\toutblock[4] = U_INT8_Ta(r);\n\toutblock[5] = U_INT8_Tb(r);\n\toutblock[6] = U_INT8_Tc(r);\n\toutblock[7] = U_INT8_Td(r);\n\t/* Wipe clean */\n\tt = l = r = 0;\n}\n\n\n/***** Key Schedule *****/\n\nvoid\ncast_setkey(cast_key *key, u_int8_t *rawkey, int keybytes)\n{\n\tu_int32_t t[4], z[4], x[4];\n\tint i;\n\n\t/* Set number of rounds to 12 or 16, depending on key length */\n\tkey->rounds = (keybytes <= 10 ? 12 : 16);\n\n\t/* Copy key to workspace x */\n\tfor (i = 0; i < 4; i++) {\n\t\tx[i] = 0;\n\t\tif ((i*4+0) < keybytes) x[i] = (u_int32_t)rawkey[i*4+0] << 24;\n\t\tif ((i*4+1) < keybytes) x[i] |= (u_int32_t)rawkey[i*4+1] << 16;\n\t\tif ((i*4+2) < keybytes) x[i] |= (u_int32_t)rawkey[i*4+2] << 8;\n\t\tif ((i*4+3) < keybytes) x[i] |= (u_int32_t)rawkey[i*4+3];\n\t}\n\t/* Generate 32 subkeys, four at a time */\n\tfor (i = 0; i < 32; i+=4) {\n\t\tswitch (i & 4) {\n\t\tcase 0:\n\t\t\tt[0] = z[0] = x[0] ^ cast_sbox5[U_INT8_Tb(x[3])] ^\n\t\t\t    cast_sbox6[U_INT8_Td(x[3])] ^\n\t\t\t    cast_sbox7[U_INT8_Ta(x[3])] ^\n\t\t\t    cast_sbox8[U_INT8_Tc(x[3])] ^\n\t\t\t    cast_sbox7[U_INT8_Ta(x[2])];\n\t\t\tt[1] = z[1] = x[2] ^ cast_sbox5[U_INT8_Ta(z[0])] ^\n\t\t\t    cast_sbox6[U_INT8_Tc(z[0])] ^\n\t\t\t    cast_sbox7[U_INT8_Tb(z[0])] ^\n\t\t\t    cast_sbox8[U_INT8_Td(z[0])] ^\n\t\t\t    cast_sbox8[U_INT8_Tc(x[2])];\n\t\t\tt[2] = z[2] = x[3] ^ cast_sbox5[U_INT8_Td(z[1])] ^\n\t\t\t    cast_sbox6[U_INT8_Tc(z[1])] ^\n\t\t\t    cast_sbox7[U_INT8_Tb(z[1])] ^\n\t\t\t    cast_sbox8[U_INT8_Ta(z[1])] ^\n\t\t\t    cast_sbox5[U_INT8_Tb(x[2])];\n\t\t\tt[3] = z[3] = x[1] ^ cast_sbox5[U_INT8_Tc(z[2])] ^\n\t\t\t    cast_sbox6[U_INT8_Tb(z[2])] ^\n\t\t\t    cast_sbox7[U_INT8_Td(z[2])] ^\n\t\t\t    cast_sbox8[U_INT8_Ta(z[2])] ^\n\t\t\t    cast_sbox6[U_INT8_Td(x[2])];\n\t\t\tbreak;\n\t\t case 4:\n\t\t\tt[0] = x[0] = z[2] ^ cast_sbox5[U_INT8_Tb(z[1])] ^\n\t\t\t    cast_sbox6[U_INT8_Td(z[1])] ^\n\t\t\t    cast_sbox7[U_INT8_Ta(z[1])] ^\n\t\t\t    cast_sbox8[U_INT8_Tc(z[1])] ^\n\t\t\t    cast_sbox7[U_INT8_Ta(z[0])];\n\t\t\tt[1] = x[1] = z[0] ^ cast_sbox5[U_INT8_Ta(x[0])] ^\n\t\t\t    cast_sbox6[U_INT8_Tc(x[0])] ^\n\t\t\t    cast_sbox7[U_INT8_Tb(x[0])] ^\n\t\t\t    cast_sbox8[U_INT8_Td(x[0])] ^\n\t\t\t    cast_sbox8[U_INT8_Tc(z[0])];\n\t\t\tt[2] = x[2] = z[1] ^ cast_sbox5[U_INT8_Td(x[1])] ^\n\t\t\t    cast_sbox6[U_INT8_Tc(x[1])] ^\n\t\t\t    cast_sbox7[U_INT8_Tb(x[1])] ^\n\t\t\t    cast_sbox8[U_INT8_Ta(x[1])] ^\n\t\t\t    cast_sbox5[U_INT8_Tb(z[0])];\n\t\t\tt[3] = x[3] = z[3] ^ cast_sbox5[U_INT8_Tc(x[2])] ^\n\t\t\t    cast_sbox6[U_INT8_Tb(x[2])] ^\n\t\t\t    cast_sbox7[U_INT8_Td(x[2])] ^\n\t\t\t    cast_sbox8[U_INT8_Ta(x[2])] ^\n\t\t\t    cast_sbox6[U_INT8_Td(z[0])];\n\t\t\tbreak;\n\t\t}\n\t\tswitch (i & 12) {\n\t\tcase 0:\n\t\tcase 12:\n\t\t\tkey->xkey[i+0] = cast_sbox5[U_INT8_Ta(t[2])] ^\n\t\t\t    cast_sbox6[U_INT8_Tb(t[2])] ^\n\t\t\t    cast_sbox7[U_INT8_Td(t[1])] ^\n\t\t\t    cast_sbox8[U_INT8_Tc(t[1])];\n\t\t\tkey->xkey[i+1] = cast_sbox5[U_INT8_Tc(t[2])] ^\n\t\t\t    cast_sbox6[U_INT8_Td(t[2])] ^\n\t\t\t    cast_sbox7[U_INT8_Tb(t[1])] ^\n\t\t\t    cast_sbox8[U_INT8_Ta(t[1])];\n\t\t\tkey->xkey[i+2] = cast_sbox5[U_INT8_Ta(t[3])] ^\n\t\t\t    cast_sbox6[U_INT8_Tb(t[3])] ^\n\t\t\t    cast_sbox7[U_INT8_Td(t[0])] ^\n\t\t\t    cast_sbox8[U_INT8_Tc(t[0])];\n\t\t\tkey->xkey[i+3] = cast_sbox5[U_INT8_Tc(t[3])] ^\n\t\t\t    cast_sbox6[U_INT8_Td(t[3])] ^\n\t\t\t    cast_sbox7[U_INT8_Tb(t[0])] ^\n\t\t\t    cast_sbox8[U_INT8_Ta(t[0])];\n\t\t\tbreak;\n\t\tcase 4:\n\t\tcase 8:\n\t\t\tkey->xkey[i+0] = cast_sbox5[U_INT8_Td(t[0])] ^\n\t\t\t    cast_sbox6[U_INT8_Tc(t[0])] ^\n\t\t\t    cast_sbox7[U_INT8_Ta(t[3])] ^\n\t\t\t    cast_sbox8[U_INT8_Tb(t[3])];\n\t\t\tkey->xkey[i+1] = cast_sbox5[U_INT8_Tb(t[0])] ^\n\t\t\t    cast_sbox6[U_INT8_Ta(t[0])] ^\n\t\t\t    cast_sbox7[U_INT8_Tc(t[3])] ^\n\t\t\t    cast_sbox8[U_INT8_Td(t[3])];\n\t\t\tkey->xkey[i+2] = cast_sbox5[U_INT8_Td(t[1])] ^\n\t\t\t    cast_sbox6[U_INT8_Tc(t[1])] ^\n\t\t\t    cast_sbox7[U_INT8_Ta(t[2])] ^\n\t\t\t    cast_sbox8[U_INT8_Tb(t[2])];\n\t\t\tkey->xkey[i+3] = cast_sbox5[U_INT8_Tb(t[1])] ^\n\t\t\t    cast_sbox6[U_INT8_Ta(t[1])] ^\n\t\t\t    cast_sbox7[U_INT8_Tc(t[2])] ^\n\t\t\t    cast_sbox8[U_INT8_Td(t[2])];\n\t\t\tbreak;\n\t\t}\n\t\tswitch (i & 12) {\n\t\tcase 0:\n\t\t\tkey->xkey[i+0] ^= cast_sbox5[U_INT8_Tc(z[0])];\n\t\t\tkey->xkey[i+1] ^= cast_sbox6[U_INT8_Tc(z[1])];\n\t\t\tkey->xkey[i+2] ^= cast_sbox7[U_INT8_Tb(z[2])];\n\t\t\tkey->xkey[i+3] ^= cast_sbox8[U_INT8_Ta(z[3])];\n\t\t\tbreak;\n\t\tcase 4:\n\t\t\tkey->xkey[i+0] ^= cast_sbox5[U_INT8_Ta(x[2])];\n\t\t\tkey->xkey[i+1] ^= cast_sbox6[U_INT8_Tb(x[3])];\n\t\t\tkey->xkey[i+2] ^= cast_sbox7[U_INT8_Td(x[0])];\n\t\t\tkey->xkey[i+3] ^= cast_sbox8[U_INT8_Td(x[1])];\n\t\t\tbreak;\n\t\tcase 8:\n\t\t\tkey->xkey[i+0] ^= cast_sbox5[U_INT8_Tb(z[2])];\n\t\t\tkey->xkey[i+1] ^= cast_sbox6[U_INT8_Ta(z[3])];\n\t\t\tkey->xkey[i+2] ^= cast_sbox7[U_INT8_Tc(z[0])];\n\t\t\tkey->xkey[i+3] ^= cast_sbox8[U_INT8_Tc(z[1])];\n\t\t\tbreak;\n\t\tcase 12:\n\t\t\tkey->xkey[i+0] ^= cast_sbox5[U_INT8_Td(x[0])];\n\t\t\tkey->xkey[i+1] ^= cast_sbox6[U_INT8_Td(x[1])];\n\t\t\tkey->xkey[i+2] ^= cast_sbox7[U_INT8_Ta(x[2])];\n\t\t\tkey->xkey[i+3] ^= cast_sbox8[U_INT8_Tb(x[3])];\n\t\t\tbreak;\n\t\t}\n\t\tif (i >= 16) {\n\t\t\tkey->xkey[i+0] &= 31;\n\t\t\tkey->xkey[i+1] &= 31;\n\t\t\tkey->xkey[i+2] &= 31;\n\t\t\tkey->xkey[i+3] &= 31;\n\t\t}\n\t}\n\t/* Wipe clean */\n\tmemset(t, 0, sizeof(t));\n\tmemset(x, 0, sizeof(x));\n\tmemset(z, 0, sizeof(z));\n}\n\n/* Made in Canada */\n"
  },
  {
    "path": "itl80211/openbsd/crypto/cast.h",
    "content": "/*      $OpenBSD: cast.h,v 1.2 2002/03/14 01:26:51 millert Exp $       */\n\n/*\n *\tCAST-128 in C\n *\tWritten by Steve Reid <sreid@sea-to-sky.net>\n *\t100% Public Domain - no warranty\n *\tReleased 1997.10.11\n */\n\n#ifndef _CAST_H_\n#define _CAST_H_\n\ntypedef struct {\n\tu_int32_t\txkey[32];\t/* Key, after expansion */\n\tint\t\trounds;\t\t/* Number of rounds to use, 12 or 16 */\n} cast_key;\n\nvoid cast_setkey(cast_key * key, u_int8_t * rawkey, int keybytes);\nvoid cast_encrypt(cast_key * key, u_int8_t * inblock, u_int8_t * outblock);\nvoid cast_decrypt(cast_key * key, u_int8_t * inblock, u_int8_t * outblock);\n\n#endif /* ifndef _CAST_H_ */\n"
  },
  {
    "path": "itl80211/openbsd/crypto/castsb.h",
    "content": "/*      $OpenBSD: castsb.h,v 1.1 2000/02/28 23:13:04 deraadt Exp $       */\n/*\n *\tCAST-128 in C\n *\tWritten by Steve Reid <sreid@sea-to-sky.net>\n *\t100% Public Domain - no warranty\n *\tReleased 1997.10.11\n */\n\nstatic const u_int32_t cast_sbox1[256] = {\n\t0x30FB40D4, 0x9FA0FF0B, 0x6BECCD2F, 0x3F258C7A,\n\t0x1E213F2F, 0x9C004DD3, 0x6003E540, 0xCF9FC949,\n\t0xBFD4AF27, 0x88BBBDB5, 0xE2034090, 0x98D09675,\n\t0x6E63A0E0, 0x15C361D2, 0xC2E7661D, 0x22D4FF8E,\n\t0x28683B6F, 0xC07FD059, 0xFF2379C8, 0x775F50E2,\n\t0x43C340D3, 0xDF2F8656, 0x887CA41A, 0xA2D2BD2D,\n\t0xA1C9E0D6, 0x346C4819, 0x61B76D87, 0x22540F2F,\n\t0x2ABE32E1, 0xAA54166B, 0x22568E3A, 0xA2D341D0,\n\t0x66DB40C8, 0xA784392F, 0x004DFF2F, 0x2DB9D2DE,\n\t0x97943FAC, 0x4A97C1D8, 0x527644B7, 0xB5F437A7,\n\t0xB82CBAEF, 0xD751D159, 0x6FF7F0ED, 0x5A097A1F,\n\t0x827B68D0, 0x90ECF52E, 0x22B0C054, 0xBC8E5935,\n\t0x4B6D2F7F, 0x50BB64A2, 0xD2664910, 0xBEE5812D,\n\t0xB7332290, 0xE93B159F, 0xB48EE411, 0x4BFF345D,\n\t0xFD45C240, 0xAD31973F, 0xC4F6D02E, 0x55FC8165,\n\t0xD5B1CAAD, 0xA1AC2DAE, 0xA2D4B76D, 0xC19B0C50,\n\t0x882240F2, 0x0C6E4F38, 0xA4E4BFD7, 0x4F5BA272,\n\t0x564C1D2F, 0xC59C5319, 0xB949E354, 0xB04669FE,\n\t0xB1B6AB8A, 0xC71358DD, 0x6385C545, 0x110F935D,\n\t0x57538AD5, 0x6A390493, 0xE63D37E0, 0x2A54F6B3,\n\t0x3A787D5F, 0x6276A0B5, 0x19A6FCDF, 0x7A42206A,\n\t0x29F9D4D5, 0xF61B1891, 0xBB72275E, 0xAA508167,\n\t0x38901091, 0xC6B505EB, 0x84C7CB8C, 0x2AD75A0F,\n\t0x874A1427, 0xA2D1936B, 0x2AD286AF, 0xAA56D291,\n\t0xD7894360, 0x425C750D, 0x93B39E26, 0x187184C9,\n\t0x6C00B32D, 0x73E2BB14, 0xA0BEBC3C, 0x54623779,\n\t0x64459EAB, 0x3F328B82, 0x7718CF82, 0x59A2CEA6,\n\t0x04EE002E, 0x89FE78E6, 0x3FAB0950, 0x325FF6C2,\n\t0x81383F05, 0x6963C5C8, 0x76CB5AD6, 0xD49974C9,\n\t0xCA180DCF, 0x380782D5, 0xC7FA5CF6, 0x8AC31511,\n\t0x35E79E13, 0x47DA91D0, 0xF40F9086, 0xA7E2419E,\n\t0x31366241, 0x051EF495, 0xAA573B04, 0x4A805D8D,\n\t0x548300D0, 0x00322A3C, 0xBF64CDDF, 0xBA57A68E,\n\t0x75C6372B, 0x50AFD341, 0xA7C13275, 0x915A0BF5,\n\t0x6B54BFAB, 0x2B0B1426, 0xAB4CC9D7, 0x449CCD82,\n\t0xF7FBF265, 0xAB85C5F3, 0x1B55DB94, 0xAAD4E324,\n\t0xCFA4BD3F, 0x2DEAA3E2, 0x9E204D02, 0xC8BD25AC,\n\t0xEADF55B3, 0xD5BD9E98, 0xE31231B2, 0x2AD5AD6C,\n\t0x954329DE, 0xADBE4528, 0xD8710F69, 0xAA51C90F,\n\t0xAA786BF6, 0x22513F1E, 0xAA51A79B, 0x2AD344CC,\n\t0x7B5A41F0, 0xD37CFBAD, 0x1B069505, 0x41ECE491,\n\t0xB4C332E6, 0x032268D4, 0xC9600ACC, 0xCE387E6D,\n\t0xBF6BB16C, 0x6A70FB78, 0x0D03D9C9, 0xD4DF39DE,\n\t0xE01063DA, 0x4736F464, 0x5AD328D8, 0xB347CC96,\n\t0x75BB0FC3, 0x98511BFB, 0x4FFBCC35, 0xB58BCF6A,\n\t0xE11F0ABC, 0xBFC5FE4A, 0xA70AEC10, 0xAC39570A,\n\t0x3F04442F, 0x6188B153, 0xE0397A2E, 0x5727CB79,\n\t0x9CEB418F, 0x1CACD68D, 0x2AD37C96, 0x0175CB9D,\n\t0xC69DFF09, 0xC75B65F0, 0xD9DB40D8, 0xEC0E7779,\n\t0x4744EAD4, 0xB11C3274, 0xDD24CB9E, 0x7E1C54BD,\n\t0xF01144F9, 0xD2240EB1, 0x9675B3FD, 0xA3AC3755,\n\t0xD47C27AF, 0x51C85F4D, 0x56907596, 0xA5BB15E6,\n\t0x580304F0, 0xCA042CF1, 0x011A37EA, 0x8DBFAADB,\n\t0x35BA3E4A, 0x3526FFA0, 0xC37B4D09, 0xBC306ED9,\n\t0x98A52666, 0x5648F725, 0xFF5E569D, 0x0CED63D0,\n\t0x7C63B2CF, 0x700B45E1, 0xD5EA50F1, 0x85A92872,\n\t0xAF1FBDA7, 0xD4234870, 0xA7870BF3, 0x2D3B4D79,\n\t0x42E04198, 0x0CD0EDE7, 0x26470DB8, 0xF881814C,\n\t0x474D6AD7, 0x7C0C5E5C, 0xD1231959, 0x381B7298,\n\t0xF5D2F4DB, 0xAB838653, 0x6E2F1E23, 0x83719C9E,\n\t0xBD91E046, 0x9A56456E, 0xDC39200C, 0x20C8C571,\n\t0x962BDA1C, 0xE1E696FF, 0xB141AB08, 0x7CCA89B9,\n\t0x1A69E783, 0x02CC4843, 0xA2F7C579, 0x429EF47D,\n\t0x427B169C, 0x5AC9F049, 0xDD8F0F00, 0x5C8165BF\n};\n\nstatic const u_int32_t cast_sbox2[256] = {\n\t0x1F201094, 0xEF0BA75B, 0x69E3CF7E, 0x393F4380,\n\t0xFE61CF7A, 0xEEC5207A, 0x55889C94, 0x72FC0651,\n\t0xADA7EF79, 0x4E1D7235, 0xD55A63CE, 0xDE0436BA,\n\t0x99C430EF, 0x5F0C0794, 0x18DCDB7D, 0xA1D6EFF3,\n\t0xA0B52F7B, 0x59E83605, 0xEE15B094, 0xE9FFD909,\n\t0xDC440086, 0xEF944459, 0xBA83CCB3, 0xE0C3CDFB,\n\t0xD1DA4181, 0x3B092AB1, 0xF997F1C1, 0xA5E6CF7B,\n\t0x01420DDB, 0xE4E7EF5B, 0x25A1FF41, 0xE180F806,\n\t0x1FC41080, 0x179BEE7A, 0xD37AC6A9, 0xFE5830A4,\n\t0x98DE8B7F, 0x77E83F4E, 0x79929269, 0x24FA9F7B,\n\t0xE113C85B, 0xACC40083, 0xD7503525, 0xF7EA615F,\n\t0x62143154, 0x0D554B63, 0x5D681121, 0xC866C359,\n\t0x3D63CF73, 0xCEE234C0, 0xD4D87E87, 0x5C672B21,\n\t0x071F6181, 0x39F7627F, 0x361E3084, 0xE4EB573B,\n\t0x602F64A4, 0xD63ACD9C, 0x1BBC4635, 0x9E81032D,\n\t0x2701F50C, 0x99847AB4, 0xA0E3DF79, 0xBA6CF38C,\n\t0x10843094, 0x2537A95E, 0xF46F6FFE, 0xA1FF3B1F,\n\t0x208CFB6A, 0x8F458C74, 0xD9E0A227, 0x4EC73A34,\n\t0xFC884F69, 0x3E4DE8DF, 0xEF0E0088, 0x3559648D,\n\t0x8A45388C, 0x1D804366, 0x721D9BFD, 0xA58684BB,\n\t0xE8256333, 0x844E8212, 0x128D8098, 0xFED33FB4,\n\t0xCE280AE1, 0x27E19BA5, 0xD5A6C252, 0xE49754BD,\n\t0xC5D655DD, 0xEB667064, 0x77840B4D, 0xA1B6A801,\n\t0x84DB26A9, 0xE0B56714, 0x21F043B7, 0xE5D05860,\n\t0x54F03084, 0x066FF472, 0xA31AA153, 0xDADC4755,\n\t0xB5625DBF, 0x68561BE6, 0x83CA6B94, 0x2D6ED23B,\n\t0xECCF01DB, 0xA6D3D0BA, 0xB6803D5C, 0xAF77A709,\n\t0x33B4A34C, 0x397BC8D6, 0x5EE22B95, 0x5F0E5304,\n\t0x81ED6F61, 0x20E74364, 0xB45E1378, 0xDE18639B,\n\t0x881CA122, 0xB96726D1, 0x8049A7E8, 0x22B7DA7B,\n\t0x5E552D25, 0x5272D237, 0x79D2951C, 0xC60D894C,\n\t0x488CB402, 0x1BA4FE5B, 0xA4B09F6B, 0x1CA815CF,\n\t0xA20C3005, 0x8871DF63, 0xB9DE2FCB, 0x0CC6C9E9,\n\t0x0BEEFF53, 0xE3214517, 0xB4542835, 0x9F63293C,\n\t0xEE41E729, 0x6E1D2D7C, 0x50045286, 0x1E6685F3,\n\t0xF33401C6, 0x30A22C95, 0x31A70850, 0x60930F13,\n\t0x73F98417, 0xA1269859, 0xEC645C44, 0x52C877A9,\n\t0xCDFF33A6, 0xA02B1741, 0x7CBAD9A2, 0x2180036F,\n\t0x50D99C08, 0xCB3F4861, 0xC26BD765, 0x64A3F6AB,\n\t0x80342676, 0x25A75E7B, 0xE4E6D1FC, 0x20C710E6,\n\t0xCDF0B680, 0x17844D3B, 0x31EEF84D, 0x7E0824E4,\n\t0x2CCB49EB, 0x846A3BAE, 0x8FF77888, 0xEE5D60F6,\n\t0x7AF75673, 0x2FDD5CDB, 0xA11631C1, 0x30F66F43,\n\t0xB3FAEC54, 0x157FD7FA, 0xEF8579CC, 0xD152DE58,\n\t0xDB2FFD5E, 0x8F32CE19, 0x306AF97A, 0x02F03EF8,\n\t0x99319AD5, 0xC242FA0F, 0xA7E3EBB0, 0xC68E4906,\n\t0xB8DA230C, 0x80823028, 0xDCDEF3C8, 0xD35FB171,\n\t0x088A1BC8, 0xBEC0C560, 0x61A3C9E8, 0xBCA8F54D,\n\t0xC72FEFFA, 0x22822E99, 0x82C570B4, 0xD8D94E89,\n\t0x8B1C34BC, 0x301E16E6, 0x273BE979, 0xB0FFEAA6,\n\t0x61D9B8C6, 0x00B24869, 0xB7FFCE3F, 0x08DC283B,\n\t0x43DAF65A, 0xF7E19798, 0x7619B72F, 0x8F1C9BA4,\n\t0xDC8637A0, 0x16A7D3B1, 0x9FC393B7, 0xA7136EEB,\n\t0xC6BCC63E, 0x1A513742, 0xEF6828BC, 0x520365D6,\n\t0x2D6A77AB, 0x3527ED4B, 0x821FD216, 0x095C6E2E,\n\t0xDB92F2FB, 0x5EEA29CB, 0x145892F5, 0x91584F7F,\n\t0x5483697B, 0x2667A8CC, 0x85196048, 0x8C4BACEA,\n\t0x833860D4, 0x0D23E0F9, 0x6C387E8A, 0x0AE6D249,\n\t0xB284600C, 0xD835731D, 0xDCB1C647, 0xAC4C56EA,\n\t0x3EBD81B3, 0x230EABB0, 0x6438BC87, 0xF0B5B1FA,\n\t0x8F5EA2B3, 0xFC184642, 0x0A036B7A, 0x4FB089BD,\n\t0x649DA589, 0xA345415E, 0x5C038323, 0x3E5D3BB9,\n\t0x43D79572, 0x7E6DD07C, 0x06DFDF1E, 0x6C6CC4EF,\n\t0x7160A539, 0x73BFBE70, 0x83877605, 0x4523ECF1\n};\n\nstatic const u_int32_t cast_sbox3[256] = {\n\t0x8DEFC240, 0x25FA5D9F, 0xEB903DBF, 0xE810C907,\n\t0x47607FFF, 0x369FE44B, 0x8C1FC644, 0xAECECA90,\n\t0xBEB1F9BF, 0xEEFBCAEA, 0xE8CF1950, 0x51DF07AE,\n\t0x920E8806, 0xF0AD0548, 0xE13C8D83, 0x927010D5,\n\t0x11107D9F, 0x07647DB9, 0xB2E3E4D4, 0x3D4F285E,\n\t0xB9AFA820, 0xFADE82E0, 0xA067268B, 0x8272792E,\n\t0x553FB2C0, 0x489AE22B, 0xD4EF9794, 0x125E3FBC,\n\t0x21FFFCEE, 0x825B1BFD, 0x9255C5ED, 0x1257A240,\n\t0x4E1A8302, 0xBAE07FFF, 0x528246E7, 0x8E57140E,\n\t0x3373F7BF, 0x8C9F8188, 0xA6FC4EE8, 0xC982B5A5,\n\t0xA8C01DB7, 0x579FC264, 0x67094F31, 0xF2BD3F5F,\n\t0x40FFF7C1, 0x1FB78DFC, 0x8E6BD2C1, 0x437BE59B,\n\t0x99B03DBF, 0xB5DBC64B, 0x638DC0E6, 0x55819D99,\n\t0xA197C81C, 0x4A012D6E, 0xC5884A28, 0xCCC36F71,\n\t0xB843C213, 0x6C0743F1, 0x8309893C, 0x0FEDDD5F,\n\t0x2F7FE850, 0xD7C07F7E, 0x02507FBF, 0x5AFB9A04,\n\t0xA747D2D0, 0x1651192E, 0xAF70BF3E, 0x58C31380,\n\t0x5F98302E, 0x727CC3C4, 0x0A0FB402, 0x0F7FEF82,\n\t0x8C96FDAD, 0x5D2C2AAE, 0x8EE99A49, 0x50DA88B8,\n\t0x8427F4A0, 0x1EAC5790, 0x796FB449, 0x8252DC15,\n\t0xEFBD7D9B, 0xA672597D, 0xADA840D8, 0x45F54504,\n\t0xFA5D7403, 0xE83EC305, 0x4F91751A, 0x925669C2,\n\t0x23EFE941, 0xA903F12E, 0x60270DF2, 0x0276E4B6,\n\t0x94FD6574, 0x927985B2, 0x8276DBCB, 0x02778176,\n\t0xF8AF918D, 0x4E48F79E, 0x8F616DDF, 0xE29D840E,\n\t0x842F7D83, 0x340CE5C8, 0x96BBB682, 0x93B4B148,\n\t0xEF303CAB, 0x984FAF28, 0x779FAF9B, 0x92DC560D,\n\t0x224D1E20, 0x8437AA88, 0x7D29DC96, 0x2756D3DC,\n\t0x8B907CEE, 0xB51FD240, 0xE7C07CE3, 0xE566B4A1,\n\t0xC3E9615E, 0x3CF8209D, 0x6094D1E3, 0xCD9CA341,\n\t0x5C76460E, 0x00EA983B, 0xD4D67881, 0xFD47572C,\n\t0xF76CEDD9, 0xBDA8229C, 0x127DADAA, 0x438A074E,\n\t0x1F97C090, 0x081BDB8A, 0x93A07EBE, 0xB938CA15,\n\t0x97B03CFF, 0x3DC2C0F8, 0x8D1AB2EC, 0x64380E51,\n\t0x68CC7BFB, 0xD90F2788, 0x12490181, 0x5DE5FFD4,\n\t0xDD7EF86A, 0x76A2E214, 0xB9A40368, 0x925D958F,\n\t0x4B39FFFA, 0xBA39AEE9, 0xA4FFD30B, 0xFAF7933B,\n\t0x6D498623, 0x193CBCFA, 0x27627545, 0x825CF47A,\n\t0x61BD8BA0, 0xD11E42D1, 0xCEAD04F4, 0x127EA392,\n\t0x10428DB7, 0x8272A972, 0x9270C4A8, 0x127DE50B,\n\t0x285BA1C8, 0x3C62F44F, 0x35C0EAA5, 0xE805D231,\n\t0x428929FB, 0xB4FCDF82, 0x4FB66A53, 0x0E7DC15B,\n\t0x1F081FAB, 0x108618AE, 0xFCFD086D, 0xF9FF2889,\n\t0x694BCC11, 0x236A5CAE, 0x12DECA4D, 0x2C3F8CC5,\n\t0xD2D02DFE, 0xF8EF5896, 0xE4CF52DA, 0x95155B67,\n\t0x494A488C, 0xB9B6A80C, 0x5C8F82BC, 0x89D36B45,\n\t0x3A609437, 0xEC00C9A9, 0x44715253, 0x0A874B49,\n\t0xD773BC40, 0x7C34671C, 0x02717EF6, 0x4FEB5536,\n\t0xA2D02FFF, 0xD2BF60C4, 0xD43F03C0, 0x50B4EF6D,\n\t0x07478CD1, 0x006E1888, 0xA2E53F55, 0xB9E6D4BC,\n\t0xA2048016, 0x97573833, 0xD7207D67, 0xDE0F8F3D,\n\t0x72F87B33, 0xABCC4F33, 0x7688C55D, 0x7B00A6B0,\n\t0x947B0001, 0x570075D2, 0xF9BB88F8, 0x8942019E,\n\t0x4264A5FF, 0x856302E0, 0x72DBD92B, 0xEE971B69,\n\t0x6EA22FDE, 0x5F08AE2B, 0xAF7A616D, 0xE5C98767,\n\t0xCF1FEBD2, 0x61EFC8C2, 0xF1AC2571, 0xCC8239C2,\n\t0x67214CB8, 0xB1E583D1, 0xB7DC3E62, 0x7F10BDCE,\n\t0xF90A5C38, 0x0FF0443D, 0x606E6DC6, 0x60543A49,\n\t0x5727C148, 0x2BE98A1D, 0x8AB41738, 0x20E1BE24,\n\t0xAF96DA0F, 0x68458425, 0x99833BE5, 0x600D457D,\n\t0x282F9350, 0x8334B362, 0xD91D1120, 0x2B6D8DA0,\n\t0x642B1E31, 0x9C305A00, 0x52BCE688, 0x1B03588A,\n\t0xF7BAEFD5, 0x4142ED9C, 0xA4315C11, 0x83323EC5,\n\t0xDFEF4636, 0xA133C501, 0xE9D3531C, 0xEE353783\n};\n\nstatic const u_int32_t cast_sbox4[256] = {\n\t0x9DB30420, 0x1FB6E9DE, 0xA7BE7BEF, 0xD273A298,\n\t0x4A4F7BDB, 0x64AD8C57, 0x85510443, 0xFA020ED1,\n\t0x7E287AFF, 0xE60FB663, 0x095F35A1, 0x79EBF120,\n\t0xFD059D43, 0x6497B7B1, 0xF3641F63, 0x241E4ADF,\n\t0x28147F5F, 0x4FA2B8CD, 0xC9430040, 0x0CC32220,\n\t0xFDD30B30, 0xC0A5374F, 0x1D2D00D9, 0x24147B15,\n\t0xEE4D111A, 0x0FCA5167, 0x71FF904C, 0x2D195FFE,\n\t0x1A05645F, 0x0C13FEFE, 0x081B08CA, 0x05170121,\n\t0x80530100, 0xE83E5EFE, 0xAC9AF4F8, 0x7FE72701,\n\t0xD2B8EE5F, 0x06DF4261, 0xBB9E9B8A, 0x7293EA25,\n\t0xCE84FFDF, 0xF5718801, 0x3DD64B04, 0xA26F263B,\n\t0x7ED48400, 0x547EEBE6, 0x446D4CA0, 0x6CF3D6F5,\n\t0x2649ABDF, 0xAEA0C7F5, 0x36338CC1, 0x503F7E93,\n\t0xD3772061, 0x11B638E1, 0x72500E03, 0xF80EB2BB,\n\t0xABE0502E, 0xEC8D77DE, 0x57971E81, 0xE14F6746,\n\t0xC9335400, 0x6920318F, 0x081DBB99, 0xFFC304A5,\n\t0x4D351805, 0x7F3D5CE3, 0xA6C866C6, 0x5D5BCCA9,\n\t0xDAEC6FEA, 0x9F926F91, 0x9F46222F, 0x3991467D,\n\t0xA5BF6D8E, 0x1143C44F, 0x43958302, 0xD0214EEB,\n\t0x022083B8, 0x3FB6180C, 0x18F8931E, 0x281658E6,\n\t0x26486E3E, 0x8BD78A70, 0x7477E4C1, 0xB506E07C,\n\t0xF32D0A25, 0x79098B02, 0xE4EABB81, 0x28123B23,\n\t0x69DEAD38, 0x1574CA16, 0xDF871B62, 0x211C40B7,\n\t0xA51A9EF9, 0x0014377B, 0x041E8AC8, 0x09114003,\n\t0xBD59E4D2, 0xE3D156D5, 0x4FE876D5, 0x2F91A340,\n\t0x557BE8DE, 0x00EAE4A7, 0x0CE5C2EC, 0x4DB4BBA6,\n\t0xE756BDFF, 0xDD3369AC, 0xEC17B035, 0x06572327,\n\t0x99AFC8B0, 0x56C8C391, 0x6B65811C, 0x5E146119,\n\t0x6E85CB75, 0xBE07C002, 0xC2325577, 0x893FF4EC,\n\t0x5BBFC92D, 0xD0EC3B25, 0xB7801AB7, 0x8D6D3B24,\n\t0x20C763EF, 0xC366A5FC, 0x9C382880, 0x0ACE3205,\n\t0xAAC9548A, 0xECA1D7C7, 0x041AFA32, 0x1D16625A,\n\t0x6701902C, 0x9B757A54, 0x31D477F7, 0x9126B031,\n\t0x36CC6FDB, 0xC70B8B46, 0xD9E66A48, 0x56E55A79,\n\t0x026A4CEB, 0x52437EFF, 0x2F8F76B4, 0x0DF980A5,\n\t0x8674CDE3, 0xEDDA04EB, 0x17A9BE04, 0x2C18F4DF,\n\t0xB7747F9D, 0xAB2AF7B4, 0xEFC34D20, 0x2E096B7C,\n\t0x1741A254, 0xE5B6A035, 0x213D42F6, 0x2C1C7C26,\n\t0x61C2F50F, 0x6552DAF9, 0xD2C231F8, 0x25130F69,\n\t0xD8167FA2, 0x0418F2C8, 0x001A96A6, 0x0D1526AB,\n\t0x63315C21, 0x5E0A72EC, 0x49BAFEFD, 0x187908D9,\n\t0x8D0DBD86, 0x311170A7, 0x3E9B640C, 0xCC3E10D7,\n\t0xD5CAD3B6, 0x0CAEC388, 0xF73001E1, 0x6C728AFF,\n\t0x71EAE2A1, 0x1F9AF36E, 0xCFCBD12F, 0xC1DE8417,\n\t0xAC07BE6B, 0xCB44A1D8, 0x8B9B0F56, 0x013988C3,\n\t0xB1C52FCA, 0xB4BE31CD, 0xD8782806, 0x12A3A4E2,\n\t0x6F7DE532, 0x58FD7EB6, 0xD01EE900, 0x24ADFFC2,\n\t0xF4990FC5, 0x9711AAC5, 0x001D7B95, 0x82E5E7D2,\n\t0x109873F6, 0x00613096, 0xC32D9521, 0xADA121FF,\n\t0x29908415, 0x7FBB977F, 0xAF9EB3DB, 0x29C9ED2A,\n\t0x5CE2A465, 0xA730F32C, 0xD0AA3FE8, 0x8A5CC091,\n\t0xD49E2CE7, 0x0CE454A9, 0xD60ACD86, 0x015F1919,\n\t0x77079103, 0xDEA03AF6, 0x78A8565E, 0xDEE356DF,\n\t0x21F05CBE, 0x8B75E387, 0xB3C50651, 0xB8A5C3EF,\n\t0xD8EEB6D2, 0xE523BE77, 0xC2154529, 0x2F69EFDF,\n\t0xAFE67AFB, 0xF470C4B2, 0xF3E0EB5B, 0xD6CC9876,\n\t0x39E4460C, 0x1FDA8538, 0x1987832F, 0xCA007367,\n\t0xA99144F8, 0x296B299E, 0x492FC295, 0x9266BEAB,\n\t0xB5676E69, 0x9BD3DDDA, 0xDF7E052F, 0xDB25701C,\n\t0x1B5E51EE, 0xF65324E6, 0x6AFCE36C, 0x0316CC04,\n\t0x8644213E, 0xB7DC59D0, 0x7965291F, 0xCCD6FD43,\n\t0x41823979, 0x932BCDF6, 0xB657C34D, 0x4EDFD282,\n\t0x7AE5290C, 0x3CB9536B, 0x851E20FE, 0x9833557E,\n\t0x13ECF0B0, 0xD3FFB372, 0x3F85C5C1, 0x0AEF7ED2\n};\n\nstatic const u_int32_t cast_sbox5[256] = {\n\t0x7EC90C04, 0x2C6E74B9, 0x9B0E66DF, 0xA6337911,\n\t0xB86A7FFF, 0x1DD358F5, 0x44DD9D44, 0x1731167F,\n\t0x08FBF1FA, 0xE7F511CC, 0xD2051B00, 0x735ABA00,\n\t0x2AB722D8, 0x386381CB, 0xACF6243A, 0x69BEFD7A,\n\t0xE6A2E77F, 0xF0C720CD, 0xC4494816, 0xCCF5C180,\n\t0x38851640, 0x15B0A848, 0xE68B18CB, 0x4CAADEFF,\n\t0x5F480A01, 0x0412B2AA, 0x259814FC, 0x41D0EFE2,\n\t0x4E40B48D, 0x248EB6FB, 0x8DBA1CFE, 0x41A99B02,\n\t0x1A550A04, 0xBA8F65CB, 0x7251F4E7, 0x95A51725,\n\t0xC106ECD7, 0x97A5980A, 0xC539B9AA, 0x4D79FE6A,\n\t0xF2F3F763, 0x68AF8040, 0xED0C9E56, 0x11B4958B,\n\t0xE1EB5A88, 0x8709E6B0, 0xD7E07156, 0x4E29FEA7,\n\t0x6366E52D, 0x02D1C000, 0xC4AC8E05, 0x9377F571,\n\t0x0C05372A, 0x578535F2, 0x2261BE02, 0xD642A0C9,\n\t0xDF13A280, 0x74B55BD2, 0x682199C0, 0xD421E5EC,\n\t0x53FB3CE8, 0xC8ADEDB3, 0x28A87FC9, 0x3D959981,\n\t0x5C1FF900, 0xFE38D399, 0x0C4EFF0B, 0x062407EA,\n\t0xAA2F4FB1, 0x4FB96976, 0x90C79505, 0xB0A8A774,\n\t0xEF55A1FF, 0xE59CA2C2, 0xA6B62D27, 0xE66A4263,\n\t0xDF65001F, 0x0EC50966, 0xDFDD55BC, 0x29DE0655,\n\t0x911E739A, 0x17AF8975, 0x32C7911C, 0x89F89468,\n\t0x0D01E980, 0x524755F4, 0x03B63CC9, 0x0CC844B2,\n\t0xBCF3F0AA, 0x87AC36E9, 0xE53A7426, 0x01B3D82B,\n\t0x1A9E7449, 0x64EE2D7E, 0xCDDBB1DA, 0x01C94910,\n\t0xB868BF80, 0x0D26F3FD, 0x9342EDE7, 0x04A5C284,\n\t0x636737B6, 0x50F5B616, 0xF24766E3, 0x8ECA36C1,\n\t0x136E05DB, 0xFEF18391, 0xFB887A37, 0xD6E7F7D4,\n\t0xC7FB7DC9, 0x3063FCDF, 0xB6F589DE, 0xEC2941DA,\n\t0x26E46695, 0xB7566419, 0xF654EFC5, 0xD08D58B7,\n\t0x48925401, 0xC1BACB7F, 0xE5FF550F, 0xB6083049,\n\t0x5BB5D0E8, 0x87D72E5A, 0xAB6A6EE1, 0x223A66CE,\n\t0xC62BF3CD, 0x9E0885F9, 0x68CB3E47, 0x086C010F,\n\t0xA21DE820, 0xD18B69DE, 0xF3F65777, 0xFA02C3F6,\n\t0x407EDAC3, 0xCBB3D550, 0x1793084D, 0xB0D70EBA,\n\t0x0AB378D5, 0xD951FB0C, 0xDED7DA56, 0x4124BBE4,\n\t0x94CA0B56, 0x0F5755D1, 0xE0E1E56E, 0x6184B5BE,\n\t0x580A249F, 0x94F74BC0, 0xE327888E, 0x9F7B5561,\n\t0xC3DC0280, 0x05687715, 0x646C6BD7, 0x44904DB3,\n\t0x66B4F0A3, 0xC0F1648A, 0x697ED5AF, 0x49E92FF6,\n\t0x309E374F, 0x2CB6356A, 0x85808573, 0x4991F840,\n\t0x76F0AE02, 0x083BE84D, 0x28421C9A, 0x44489406,\n\t0x736E4CB8, 0xC1092910, 0x8BC95FC6, 0x7D869CF4,\n\t0x134F616F, 0x2E77118D, 0xB31B2BE1, 0xAA90B472,\n\t0x3CA5D717, 0x7D161BBA, 0x9CAD9010, 0xAF462BA2,\n\t0x9FE459D2, 0x45D34559, 0xD9F2DA13, 0xDBC65487,\n\t0xF3E4F94E, 0x176D486F, 0x097C13EA, 0x631DA5C7,\n\t0x445F7382, 0x175683F4, 0xCDC66A97, 0x70BE0288,\n\t0xB3CDCF72, 0x6E5DD2F3, 0x20936079, 0x459B80A5,\n\t0xBE60E2DB, 0xA9C23101, 0xEBA5315C, 0x224E42F2,\n\t0x1C5C1572, 0xF6721B2C, 0x1AD2FFF3, 0x8C25404E,\n\t0x324ED72F, 0x4067B7FD, 0x0523138E, 0x5CA3BC78,\n\t0xDC0FD66E, 0x75922283, 0x784D6B17, 0x58EBB16E,\n\t0x44094F85, 0x3F481D87, 0xFCFEAE7B, 0x77B5FF76,\n\t0x8C2302BF, 0xAAF47556, 0x5F46B02A, 0x2B092801,\n\t0x3D38F5F7, 0x0CA81F36, 0x52AF4A8A, 0x66D5E7C0,\n\t0xDF3B0874, 0x95055110, 0x1B5AD7A8, 0xF61ED5AD,\n\t0x6CF6E479, 0x20758184, 0xD0CEFA65, 0x88F7BE58,\n\t0x4A046826, 0x0FF6F8F3, 0xA09C7F70, 0x5346ABA0,\n\t0x5CE96C28, 0xE176EDA3, 0x6BAC307F, 0x376829D2,\n\t0x85360FA9, 0x17E3FE2A, 0x24B79767, 0xF5A96B20,\n\t0xD6CD2595, 0x68FF1EBF, 0x7555442C, 0xF19F06BE,\n\t0xF9E0659A, 0xEEB9491D, 0x34010718, 0xBB30CAB8,\n\t0xE822FE15, 0x88570983, 0x750E6249, 0xDA627E55,\n\t0x5E76FFA8, 0xB1534546, 0x6D47DE08, 0xEFE9E7D4\n};\n\nstatic const u_int32_t cast_sbox6[256] = {\n\t0xF6FA8F9D, 0x2CAC6CE1, 0x4CA34867, 0xE2337F7C,\n\t0x95DB08E7, 0x016843B4, 0xECED5CBC, 0x325553AC,\n\t0xBF9F0960, 0xDFA1E2ED, 0x83F0579D, 0x63ED86B9,\n\t0x1AB6A6B8, 0xDE5EBE39, 0xF38FF732, 0x8989B138,\n\t0x33F14961, 0xC01937BD, 0xF506C6DA, 0xE4625E7E,\n\t0xA308EA99, 0x4E23E33C, 0x79CBD7CC, 0x48A14367,\n\t0xA3149619, 0xFEC94BD5, 0xA114174A, 0xEAA01866,\n\t0xA084DB2D, 0x09A8486F, 0xA888614A, 0x2900AF98,\n\t0x01665991, 0xE1992863, 0xC8F30C60, 0x2E78EF3C,\n\t0xD0D51932, 0xCF0FEC14, 0xF7CA07D2, 0xD0A82072,\n\t0xFD41197E, 0x9305A6B0, 0xE86BE3DA, 0x74BED3CD,\n\t0x372DA53C, 0x4C7F4448, 0xDAB5D440, 0x6DBA0EC3,\n\t0x083919A7, 0x9FBAEED9, 0x49DBCFB0, 0x4E670C53,\n\t0x5C3D9C01, 0x64BDB941, 0x2C0E636A, 0xBA7DD9CD,\n\t0xEA6F7388, 0xE70BC762, 0x35F29ADB, 0x5C4CDD8D,\n\t0xF0D48D8C, 0xB88153E2, 0x08A19866, 0x1AE2EAC8,\n\t0x284CAF89, 0xAA928223, 0x9334BE53, 0x3B3A21BF,\n\t0x16434BE3, 0x9AEA3906, 0xEFE8C36E, 0xF890CDD9,\n\t0x80226DAE, 0xC340A4A3, 0xDF7E9C09, 0xA694A807,\n\t0x5B7C5ECC, 0x221DB3A6, 0x9A69A02F, 0x68818A54,\n\t0xCEB2296F, 0x53C0843A, 0xFE893655, 0x25BFE68A,\n\t0xB4628ABC, 0xCF222EBF, 0x25AC6F48, 0xA9A99387,\n\t0x53BDDB65, 0xE76FFBE7, 0xE967FD78, 0x0BA93563,\n\t0x8E342BC1, 0xE8A11BE9, 0x4980740D, 0xC8087DFC,\n\t0x8DE4BF99, 0xA11101A0, 0x7FD37975, 0xDA5A26C0,\n\t0xE81F994F, 0x9528CD89, 0xFD339FED, 0xB87834BF,\n\t0x5F04456D, 0x22258698, 0xC9C4C83B, 0x2DC156BE,\n\t0x4F628DAA, 0x57F55EC5, 0xE2220ABE, 0xD2916EBF,\n\t0x4EC75B95, 0x24F2C3C0, 0x42D15D99, 0xCD0D7FA0,\n\t0x7B6E27FF, 0xA8DC8AF0, 0x7345C106, 0xF41E232F,\n\t0x35162386, 0xE6EA8926, 0x3333B094, 0x157EC6F2,\n\t0x372B74AF, 0x692573E4, 0xE9A9D848, 0xF3160289,\n\t0x3A62EF1D, 0xA787E238, 0xF3A5F676, 0x74364853,\n\t0x20951063, 0x4576698D, 0xB6FAD407, 0x592AF950,\n\t0x36F73523, 0x4CFB6E87, 0x7DA4CEC0, 0x6C152DAA,\n\t0xCB0396A8, 0xC50DFE5D, 0xFCD707AB, 0x0921C42F,\n\t0x89DFF0BB, 0x5FE2BE78, 0x448F4F33, 0x754613C9,\n\t0x2B05D08D, 0x48B9D585, 0xDC049441, 0xC8098F9B,\n\t0x7DEDE786, 0xC39A3373, 0x42410005, 0x6A091751,\n\t0x0EF3C8A6, 0x890072D6, 0x28207682, 0xA9A9F7BE,\n\t0xBF32679D, 0xD45B5B75, 0xB353FD00, 0xCBB0E358,\n\t0x830F220A, 0x1F8FB214, 0xD372CF08, 0xCC3C4A13,\n\t0x8CF63166, 0x061C87BE, 0x88C98F88, 0x6062E397,\n\t0x47CF8E7A, 0xB6C85283, 0x3CC2ACFB, 0x3FC06976,\n\t0x4E8F0252, 0x64D8314D, 0xDA3870E3, 0x1E665459,\n\t0xC10908F0, 0x513021A5, 0x6C5B68B7, 0x822F8AA0,\n\t0x3007CD3E, 0x74719EEF, 0xDC872681, 0x073340D4,\n\t0x7E432FD9, 0x0C5EC241, 0x8809286C, 0xF592D891,\n\t0x08A930F6, 0x957EF305, 0xB7FBFFBD, 0xC266E96F,\n\t0x6FE4AC98, 0xB173ECC0, 0xBC60B42A, 0x953498DA,\n\t0xFBA1AE12, 0x2D4BD736, 0x0F25FAAB, 0xA4F3FCEB,\n\t0xE2969123, 0x257F0C3D, 0x9348AF49, 0x361400BC,\n\t0xE8816F4A, 0x3814F200, 0xA3F94043, 0x9C7A54C2,\n\t0xBC704F57, 0xDA41E7F9, 0xC25AD33A, 0x54F4A084,\n\t0xB17F5505, 0x59357CBE, 0xEDBD15C8, 0x7F97C5AB,\n\t0xBA5AC7B5, 0xB6F6DEAF, 0x3A479C3A, 0x5302DA25,\n\t0x653D7E6A, 0x54268D49, 0x51A477EA, 0x5017D55B,\n\t0xD7D25D88, 0x44136C76, 0x0404A8C8, 0xB8E5A121,\n\t0xB81A928A, 0x60ED5869, 0x97C55B96, 0xEAEC991B,\n\t0x29935913, 0x01FDB7F1, 0x088E8DFA, 0x9AB6F6F5,\n\t0x3B4CBF9F, 0x4A5DE3AB, 0xE6051D35, 0xA0E1D855,\n\t0xD36B4CF1, 0xF544EDEB, 0xB0E93524, 0xBEBB8FBD,\n\t0xA2D762CF, 0x49C92F54, 0x38B5F331, 0x7128A454,\n\t0x48392905, 0xA65B1DB8, 0x851C97BD, 0xD675CF2F\n};\n\nstatic const u_int32_t cast_sbox7[256] = {\n\t0x85E04019, 0x332BF567, 0x662DBFFF, 0xCFC65693,\n\t0x2A8D7F6F, 0xAB9BC912, 0xDE6008A1, 0x2028DA1F,\n\t0x0227BCE7, 0x4D642916, 0x18FAC300, 0x50F18B82,\n\t0x2CB2CB11, 0xB232E75C, 0x4B3695F2, 0xB28707DE,\n\t0xA05FBCF6, 0xCD4181E9, 0xE150210C, 0xE24EF1BD,\n\t0xB168C381, 0xFDE4E789, 0x5C79B0D8, 0x1E8BFD43,\n\t0x4D495001, 0x38BE4341, 0x913CEE1D, 0x92A79C3F,\n\t0x089766BE, 0xBAEEADF4, 0x1286BECF, 0xB6EACB19,\n\t0x2660C200, 0x7565BDE4, 0x64241F7A, 0x8248DCA9,\n\t0xC3B3AD66, 0x28136086, 0x0BD8DFA8, 0x356D1CF2,\n\t0x107789BE, 0xB3B2E9CE, 0x0502AA8F, 0x0BC0351E,\n\t0x166BF52A, 0xEB12FF82, 0xE3486911, 0xD34D7516,\n\t0x4E7B3AFF, 0x5F43671B, 0x9CF6E037, 0x4981AC83,\n\t0x334266CE, 0x8C9341B7, 0xD0D854C0, 0xCB3A6C88,\n\t0x47BC2829, 0x4725BA37, 0xA66AD22B, 0x7AD61F1E,\n\t0x0C5CBAFA, 0x4437F107, 0xB6E79962, 0x42D2D816,\n\t0x0A961288, 0xE1A5C06E, 0x13749E67, 0x72FC081A,\n\t0xB1D139F7, 0xF9583745, 0xCF19DF58, 0xBEC3F756,\n\t0xC06EBA30, 0x07211B24, 0x45C28829, 0xC95E317F,\n\t0xBC8EC511, 0x38BC46E9, 0xC6E6FA14, 0xBAE8584A,\n\t0xAD4EBC46, 0x468F508B, 0x7829435F, 0xF124183B,\n\t0x821DBA9F, 0xAFF60FF4, 0xEA2C4E6D, 0x16E39264,\n\t0x92544A8B, 0x009B4FC3, 0xABA68CED, 0x9AC96F78,\n\t0x06A5B79A, 0xB2856E6E, 0x1AEC3CA9, 0xBE838688,\n\t0x0E0804E9, 0x55F1BE56, 0xE7E5363B, 0xB3A1F25D,\n\t0xF7DEBB85, 0x61FE033C, 0x16746233, 0x3C034C28,\n\t0xDA6D0C74, 0x79AAC56C, 0x3CE4E1AD, 0x51F0C802,\n\t0x98F8F35A, 0x1626A49F, 0xEED82B29, 0x1D382FE3,\n\t0x0C4FB99A, 0xBB325778, 0x3EC6D97B, 0x6E77A6A9,\n\t0xCB658B5C, 0xD45230C7, 0x2BD1408B, 0x60C03EB7,\n\t0xB9068D78, 0xA33754F4, 0xF430C87D, 0xC8A71302,\n\t0xB96D8C32, 0xEBD4E7BE, 0xBE8B9D2D, 0x7979FB06,\n\t0xE7225308, 0x8B75CF77, 0x11EF8DA4, 0xE083C858,\n\t0x8D6B786F, 0x5A6317A6, 0xFA5CF7A0, 0x5DDA0033,\n\t0xF28EBFB0, 0xF5B9C310, 0xA0EAC280, 0x08B9767A,\n\t0xA3D9D2B0, 0x79D34217, 0x021A718D, 0x9AC6336A,\n\t0x2711FD60, 0x438050E3, 0x069908A8, 0x3D7FEDC4,\n\t0x826D2BEF, 0x4EEB8476, 0x488DCF25, 0x36C9D566,\n\t0x28E74E41, 0xC2610ACA, 0x3D49A9CF, 0xBAE3B9DF,\n\t0xB65F8DE6, 0x92AEAF64, 0x3AC7D5E6, 0x9EA80509,\n\t0xF22B017D, 0xA4173F70, 0xDD1E16C3, 0x15E0D7F9,\n\t0x50B1B887, 0x2B9F4FD5, 0x625ABA82, 0x6A017962,\n\t0x2EC01B9C, 0x15488AA9, 0xD716E740, 0x40055A2C,\n\t0x93D29A22, 0xE32DBF9A, 0x058745B9, 0x3453DC1E,\n\t0xD699296E, 0x496CFF6F, 0x1C9F4986, 0xDFE2ED07,\n\t0xB87242D1, 0x19DE7EAE, 0x053E561A, 0x15AD6F8C,\n\t0x66626C1C, 0x7154C24C, 0xEA082B2A, 0x93EB2939,\n\t0x17DCB0F0, 0x58D4F2AE, 0x9EA294FB, 0x52CF564C,\n\t0x9883FE66, 0x2EC40581, 0x763953C3, 0x01D6692E,\n\t0xD3A0C108, 0xA1E7160E, 0xE4F2DFA6, 0x693ED285,\n\t0x74904698, 0x4C2B0EDD, 0x4F757656, 0x5D393378,\n\t0xA132234F, 0x3D321C5D, 0xC3F5E194, 0x4B269301,\n\t0xC79F022F, 0x3C997E7E, 0x5E4F9504, 0x3FFAFBBD,\n\t0x76F7AD0E, 0x296693F4, 0x3D1FCE6F, 0xC61E45BE,\n\t0xD3B5AB34, 0xF72BF9B7, 0x1B0434C0, 0x4E72B567,\n\t0x5592A33D, 0xB5229301, 0xCFD2A87F, 0x60AEB767,\n\t0x1814386B, 0x30BCC33D, 0x38A0C07D, 0xFD1606F2,\n\t0xC363519B, 0x589DD390, 0x5479F8E6, 0x1CB8D647,\n\t0x97FD61A9, 0xEA7759F4, 0x2D57539D, 0x569A58CF,\n\t0xE84E63AD, 0x462E1B78, 0x6580F87E, 0xF3817914,\n\t0x91DA55F4, 0x40A230F3, 0xD1988F35, 0xB6E318D2,\n\t0x3FFA50BC, 0x3D40F021, 0xC3C0BDAE, 0x4958C24C,\n\t0x518F36B2, 0x84B1D370, 0x0FEDCE83, 0x878DDADA,\n\t0xF2A279C7, 0x94E01BE8, 0x90716F4B, 0x954B8AA3\n};\n\nstatic const u_int32_t cast_sbox8[256] = {\n\t0xE216300D, 0xBBDDFFFC, 0xA7EBDABD, 0x35648095,\n\t0x7789F8B7, 0xE6C1121B, 0x0E241600, 0x052CE8B5,\n\t0x11A9CFB0, 0xE5952F11, 0xECE7990A, 0x9386D174,\n\t0x2A42931C, 0x76E38111, 0xB12DEF3A, 0x37DDDDFC,\n\t0xDE9ADEB1, 0x0A0CC32C, 0xBE197029, 0x84A00940,\n\t0xBB243A0F, 0xB4D137CF, 0xB44E79F0, 0x049EEDFD,\n\t0x0B15A15D, 0x480D3168, 0x8BBBDE5A, 0x669DED42,\n\t0xC7ECE831, 0x3F8F95E7, 0x72DF191B, 0x7580330D,\n\t0x94074251, 0x5C7DCDFA, 0xABBE6D63, 0xAA402164,\n\t0xB301D40A, 0x02E7D1CA, 0x53571DAE, 0x7A3182A2,\n\t0x12A8DDEC, 0xFDAA335D, 0x176F43E8, 0x71FB46D4,\n\t0x38129022, 0xCE949AD4, 0xB84769AD, 0x965BD862,\n\t0x82F3D055, 0x66FB9767, 0x15B80B4E, 0x1D5B47A0,\n\t0x4CFDE06F, 0xC28EC4B8, 0x57E8726E, 0x647A78FC,\n\t0x99865D44, 0x608BD593, 0x6C200E03, 0x39DC5FF6,\n\t0x5D0B00A3, 0xAE63AFF2, 0x7E8BD632, 0x70108C0C,\n\t0xBBD35049, 0x2998DF04, 0x980CF42A, 0x9B6DF491,\n\t0x9E7EDD53, 0x06918548, 0x58CB7E07, 0x3B74EF2E,\n\t0x522FFFB1, 0xD24708CC, 0x1C7E27CD, 0xA4EB215B,\n\t0x3CF1D2E2, 0x19B47A38, 0x424F7618, 0x35856039,\n\t0x9D17DEE7, 0x27EB35E6, 0xC9AFF67B, 0x36BAF5B8,\n\t0x09C467CD, 0xC18910B1, 0xE11DBF7B, 0x06CD1AF8,\n\t0x7170C608, 0x2D5E3354, 0xD4DE495A, 0x64C6D006,\n\t0xBCC0C62C, 0x3DD00DB3, 0x708F8F34, 0x77D51B42,\n\t0x264F620F, 0x24B8D2BF, 0x15C1B79E, 0x46A52564,\n\t0xF8D7E54E, 0x3E378160, 0x7895CDA5, 0x859C15A5,\n\t0xE6459788, 0xC37BC75F, 0xDB07BA0C, 0x0676A3AB,\n\t0x7F229B1E, 0x31842E7B, 0x24259FD7, 0xF8BEF472,\n\t0x835FFCB8, 0x6DF4C1F2, 0x96F5B195, 0xFD0AF0FC,\n\t0xB0FE134C, 0xE2506D3D, 0x4F9B12EA, 0xF215F225,\n\t0xA223736F, 0x9FB4C428, 0x25D04979, 0x34C713F8,\n\t0xC4618187, 0xEA7A6E98, 0x7CD16EFC, 0x1436876C,\n\t0xF1544107, 0xBEDEEE14, 0x56E9AF27, 0xA04AA441,\n\t0x3CF7C899, 0x92ECBAE6, 0xDD67016D, 0x151682EB,\n\t0xA842EEDF, 0xFDBA60B4, 0xF1907B75, 0x20E3030F,\n\t0x24D8C29E, 0xE139673B, 0xEFA63FB8, 0x71873054,\n\t0xB6F2CF3B, 0x9F326442, 0xCB15A4CC, 0xB01A4504,\n\t0xF1E47D8D, 0x844A1BE5, 0xBAE7DFDC, 0x42CBDA70,\n\t0xCD7DAE0A, 0x57E85B7A, 0xD53F5AF6, 0x20CF4D8C,\n\t0xCEA4D428, 0x79D130A4, 0x3486EBFB, 0x33D3CDDC,\n\t0x77853B53, 0x37EFFCB5, 0xC5068778, 0xE580B3E6,\n\t0x4E68B8F4, 0xC5C8B37E, 0x0D809EA2, 0x398FEB7C,\n\t0x132A4F94, 0x43B7950E, 0x2FEE7D1C, 0x223613BD,\n\t0xDD06CAA2, 0x37DF932B, 0xC4248289, 0xACF3EBC3,\n\t0x5715F6B7, 0xEF3478DD, 0xF267616F, 0xC148CBE4,\n\t0x9052815E, 0x5E410FAB, 0xB48A2465, 0x2EDA7FA4,\n\t0xE87B40E4, 0xE98EA084, 0x5889E9E1, 0xEFD390FC,\n\t0xDD07D35B, 0xDB485694, 0x38D7E5B2, 0x57720101,\n\t0x730EDEBC, 0x5B643113, 0x94917E4F, 0x503C2FBA,\n\t0x646F1282, 0x7523D24A, 0xE0779695, 0xF9C17A8F,\n\t0x7A5B2121, 0xD187B896, 0x29263A4D, 0xBA510CDF,\n\t0x81F47C9F, 0xAD1163ED, 0xEA7B5965, 0x1A00726E,\n\t0x11403092, 0x00DA6D77, 0x4A0CDD61, 0xAD1F4603,\n\t0x605BDFB0, 0x9EEDC364, 0x22EBE6A8, 0xCEE7D28A,\n\t0xA0E736A0, 0x5564A6B9, 0x10853209, 0xC7EB8F37,\n\t0x2DE705CA, 0x8951570F, 0xDF09822B, 0xBD691A6C,\n\t0xAA12E4F2, 0x87451C0F, 0xE0F6A27A, 0x3ADA4819,\n\t0x4CF1764F, 0x0D771C2B, 0x67CDB156, 0x350D8384,\n\t0x5938FA0F, 0x42399EF3, 0x36997B07, 0x0E84093D,\n\t0x4AA93E61, 0x8360D87B, 0x1FA98B0C, 0x1149382C,\n\t0xE97625A5, 0x0614D1B7, 0x0E25244B, 0x0C768347,\n\t0x589E8D82, 0x0D2059D1, 0xA466BB1E, 0xF8DA0A82,\n\t0x04F19130, 0xBA6E4EC0, 0x99265164, 0x1EE7230D,\n\t0x50B2AD80, 0xEAEE6801, 0x8DB2A283, 0xEA8BF59E\n};\n\n"
  },
  {
    "path": "itl80211/openbsd/crypto/chacha_private.h",
    "content": "/*\nchacha-merged.c version 20080118\nD. J. Bernstein\nPublic domain.\n*/\n\ntypedef unsigned char u8;\ntypedef unsigned int u32;\n\ntypedef struct\n{\n  u32 input[16]; /* could be compressed */\n} chacha_ctx;\n\n#define U8C(v) (v##U)\n#define U32C(v) (v##U)\n\n#define U8V(v) ((u8)(v) & U8C(0xFF))\n#define U32V(v) ((u32)(v) & U32C(0xFFFFFFFF))\n\n#define ROTL32(v, n) \\\n  (U32V((v) << (n)) | ((v) >> (32 - (n))))\n\n#define U8TO32_LITTLE(p) \\\n  (((u32)((p)[0])      ) | \\\n   ((u32)((p)[1]) <<  8) | \\\n   ((u32)((p)[2]) << 16) | \\\n   ((u32)((p)[3]) << 24))\n\n#define U32TO8_LITTLE(p, v) \\\n  do { \\\n    (p)[0] = U8V((v)      ); \\\n    (p)[1] = U8V((v) >>  8); \\\n    (p)[2] = U8V((v) >> 16); \\\n    (p)[3] = U8V((v) >> 24); \\\n  } while (0)\n\n#define ROTATE(v,c) (ROTL32(v,c))\n#define XOR(v,w) ((v) ^ (w))\n#define PLUS(v,w) (U32V((v) + (w)))\n#define PLUSONE(v) (PLUS((v),1))\n\n#define QUARTERROUND(a,b,c,d) \\\n  a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \\\n  c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \\\n  a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \\\n  c = PLUS(c,d); b = ROTATE(XOR(b,c), 7);\n\nstatic const char sigma[32] = \"expand 32-byte k\";\nstatic const char tau[32] = \"expand 16-byte k\";\n\nstatic void\nchacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits)\n{\n  const char *constants;\n\n  x->input[4] = U8TO32_LITTLE(k + 0);\n  x->input[5] = U8TO32_LITTLE(k + 4);\n  x->input[6] = U8TO32_LITTLE(k + 8);\n  x->input[7] = U8TO32_LITTLE(k + 12);\n  if (kbits == 256) { /* recommended */\n    k += 16;\n    constants = sigma;\n  } else { /* kbits == 128 */\n    constants = tau;\n  }\n  x->input[8] = U8TO32_LITTLE(k + 0);\n  x->input[9] = U8TO32_LITTLE(k + 4);\n  x->input[10] = U8TO32_LITTLE(k + 8);\n  x->input[11] = U8TO32_LITTLE(k + 12);\n  x->input[0] = U8TO32_LITTLE(constants + 0);\n  x->input[1] = U8TO32_LITTLE(constants + 4);\n  x->input[2] = U8TO32_LITTLE(constants + 8);\n  x->input[3] = U8TO32_LITTLE(constants + 12);\n}\n\nstatic void\nchacha_ivsetup(chacha_ctx *x, const u8 *iv, const u8 *counter)\n{\n  x->input[12] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 0);\n  x->input[13] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 4);\n  x->input[14] = U8TO32_LITTLE(iv + 0);\n  x->input[15] = U8TO32_LITTLE(iv + 4);\n}\n\nstatic void\nchacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 *c,u32 bytes)\n{\n  u32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;\n  u32 j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;\n  u8 *ctarget = NULL;\n  u8 tmp[64];\n  u_int i;\n\n  if (!bytes) return;\n\n  j0 = x->input[0];\n  j1 = x->input[1];\n  j2 = x->input[2];\n  j3 = x->input[3];\n  j4 = x->input[4];\n  j5 = x->input[5];\n  j6 = x->input[6];\n  j7 = x->input[7];\n  j8 = x->input[8];\n  j9 = x->input[9];\n  j10 = x->input[10];\n  j11 = x->input[11];\n  j12 = x->input[12];\n  j13 = x->input[13];\n  j14 = x->input[14];\n  j15 = x->input[15];\n\n  for (;;) {\n    if (bytes < 64) {\n      for (i = 0;i < bytes;++i) tmp[i] = m[i];\n      m = tmp;\n      ctarget = c;\n      c = tmp;\n    }\n    x0 = j0;\n    x1 = j1;\n    x2 = j2;\n    x3 = j3;\n    x4 = j4;\n    x5 = j5;\n    x6 = j6;\n    x7 = j7;\n    x8 = j8;\n    x9 = j9;\n    x10 = j10;\n    x11 = j11;\n    x12 = j12;\n    x13 = j13;\n    x14 = j14;\n    x15 = j15;\n    for (i = 20;i > 0;i -= 2) {\n      QUARTERROUND( x0, x4, x8,x12)\n      QUARTERROUND( x1, x5, x9,x13)\n      QUARTERROUND( x2, x6,x10,x14)\n      QUARTERROUND( x3, x7,x11,x15)\n      QUARTERROUND( x0, x5,x10,x15)\n      QUARTERROUND( x1, x6,x11,x12)\n      QUARTERROUND( x2, x7, x8,x13)\n      QUARTERROUND( x3, x4, x9,x14)\n    }\n    x0 = PLUS(x0,j0);\n    x1 = PLUS(x1,j1);\n    x2 = PLUS(x2,j2);\n    x3 = PLUS(x3,j3);\n    x4 = PLUS(x4,j4);\n    x5 = PLUS(x5,j5);\n    x6 = PLUS(x6,j6);\n    x7 = PLUS(x7,j7);\n    x8 = PLUS(x8,j8);\n    x9 = PLUS(x9,j9);\n    x10 = PLUS(x10,j10);\n    x11 = PLUS(x11,j11);\n    x12 = PLUS(x12,j12);\n    x13 = PLUS(x13,j13);\n    x14 = PLUS(x14,j14);\n    x15 = PLUS(x15,j15);\n\n#ifndef KEYSTREAM_ONLY\n    x0 = XOR(x0,U8TO32_LITTLE(m + 0));\n    x1 = XOR(x1,U8TO32_LITTLE(m + 4));\n    x2 = XOR(x2,U8TO32_LITTLE(m + 8));\n    x3 = XOR(x3,U8TO32_LITTLE(m + 12));\n    x4 = XOR(x4,U8TO32_LITTLE(m + 16));\n    x5 = XOR(x5,U8TO32_LITTLE(m + 20));\n    x6 = XOR(x6,U8TO32_LITTLE(m + 24));\n    x7 = XOR(x7,U8TO32_LITTLE(m + 28));\n    x8 = XOR(x8,U8TO32_LITTLE(m + 32));\n    x9 = XOR(x9,U8TO32_LITTLE(m + 36));\n    x10 = XOR(x10,U8TO32_LITTLE(m + 40));\n    x11 = XOR(x11,U8TO32_LITTLE(m + 44));\n    x12 = XOR(x12,U8TO32_LITTLE(m + 48));\n    x13 = XOR(x13,U8TO32_LITTLE(m + 52));\n    x14 = XOR(x14,U8TO32_LITTLE(m + 56));\n    x15 = XOR(x15,U8TO32_LITTLE(m + 60));\n#endif\n\n    j12 = PLUSONE(j12);\n    if (!j12) {\n      j13 = PLUSONE(j13);\n      /* stopping at 2^70 bytes per nonce is user's responsibility */\n    }\n\n    U32TO8_LITTLE(c + 0,x0);\n    U32TO8_LITTLE(c + 4,x1);\n    U32TO8_LITTLE(c + 8,x2);\n    U32TO8_LITTLE(c + 12,x3);\n    U32TO8_LITTLE(c + 16,x4);\n    U32TO8_LITTLE(c + 20,x5);\n    U32TO8_LITTLE(c + 24,x6);\n    U32TO8_LITTLE(c + 28,x7);\n    U32TO8_LITTLE(c + 32,x8);\n    U32TO8_LITTLE(c + 36,x9);\n    U32TO8_LITTLE(c + 40,x10);\n    U32TO8_LITTLE(c + 44,x11);\n    U32TO8_LITTLE(c + 48,x12);\n    U32TO8_LITTLE(c + 52,x13);\n    U32TO8_LITTLE(c + 56,x14);\n    U32TO8_LITTLE(c + 60,x15);\n\n    if (bytes <= 64) {\n      if (bytes < 64) {\n        for (i = 0;i < bytes;++i) ctarget[i] = c[i];\n      }\n      x->input[12] = j12;\n      x->input[13] = j13;\n      return;\n    }\n    bytes -= 64;\n    c += 64;\n#ifndef KEYSTREAM_ONLY\n    m += 64;\n#endif\n  }\n}\n"
  },
  {
    "path": "itl80211/openbsd/crypto/chachapoly.c",
    "content": "/*\n * Copyright (c) 2015 Mike Belopuhov\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n#include <sys/param.h>\n#include <sys/systm.h>\n\n#include <crypto/chacha_private.h>\n#include <crypto/poly1305.h>\n#include <crypto/chachapoly.h>\n\nint\nchacha20_setkey(void *sched, u_int8_t *key, int len)\n{\n\tstruct chacha20_ctx *ctx = (struct chacha20_ctx *)sched;\n\n\tif (len != CHACHA20_KEYSIZE + CHACHA20_SALT)\n\t\treturn (-1);\n\n\t/* initial counter is 1 */\n\tctx->nonce[0] = 1;\n\tmemcpy(ctx->nonce + CHACHA20_CTR, key + CHACHA20_KEYSIZE,\n\t    CHACHA20_SALT);\n\tchacha_keysetup((chacha_ctx *)&ctx->block, key, CHACHA20_KEYSIZE * 8);\n\treturn (0);\n}\n\nvoid\nchacha20_reinit(caddr_t key, u_int8_t *iv)\n{\n\tstruct chacha20_ctx *ctx = (struct chacha20_ctx *)key;\n\n\tchacha_ivsetup((chacha_ctx *)ctx->block, iv, ctx->nonce);\n}\n\nvoid\nchacha20_crypt(caddr_t key, u_int8_t *data)\n{\n\tstruct chacha20_ctx *ctx = (struct chacha20_ctx *)key;\n\n\tchacha_encrypt_bytes((chacha_ctx *)ctx->block, data, data,\n\t    CHACHA20_BLOCK_LEN);\n}\n\nvoid\nChacha20_Poly1305_Init(void *xctx)\n{\n\tCHACHA20_POLY1305_CTX *ctx = (CHACHA20_POLY1305_CTX *)xctx;\n\n\tmemset(ctx, 0, sizeof(*ctx));\n}\n\nvoid\nChacha20_Poly1305_Setkey(void *xctx, const uint8_t *key, uint16_t klen)\n{\n\tCHACHA20_POLY1305_CTX *ctx = (CHACHA20_POLY1305_CTX *)xctx;\n\n\t/* salt is provided with the key material */\n\tmemcpy(ctx->nonce + CHACHA20_CTR, key + CHACHA20_KEYSIZE,\n\t    CHACHA20_SALT);\n\tchacha_keysetup((chacha_ctx *)&ctx->chacha, key, CHACHA20_KEYSIZE * 8);\n}\n\nvoid\nChacha20_Poly1305_Reinit(void *xctx, const uint8_t *iv, uint16_t ivlen)\n{\n\tCHACHA20_POLY1305_CTX *ctx = (CHACHA20_POLY1305_CTX *)xctx;\n\n\t/* initial counter is 0 */\n\tchacha_ivsetup((chacha_ctx *)&ctx->chacha, iv, ctx->nonce);\n\tchacha_encrypt_bytes((chacha_ctx *)&ctx->chacha, ctx->key, ctx->key,\n\t    POLY1305_KEYLEN);\n\tpoly1305_init((poly1305_state *)&ctx->poly, ctx->key);\n}\n\nint\nChacha20_Poly1305_Update(void *xctx, const uint8_t *data, uint16_t len)\n{\n    static const char zeroes[POLY1305_BLOCK_LEN] = {0};\n\tCHACHA20_POLY1305_CTX *ctx = (CHACHA20_POLY1305_CTX *)xctx;\n\tsize_t rem;\n\n\tpoly1305_update((poly1305_state *)&ctx->poly, data, len);\n\n\t/* number of bytes in the last 16 byte block */\n\trem = (len + POLY1305_BLOCK_LEN) & (POLY1305_BLOCK_LEN - 1);\n\tif (rem > 0)\n\t\tpoly1305_update((poly1305_state *)&ctx->poly, (const unsigned char *)zeroes,\n\t\t    (size_t)(POLY1305_BLOCK_LEN - rem));\n\treturn (0);\n}\n\nvoid\nChacha20_Poly1305_Final(uint8_t tag[POLY1305_TAGLEN], void *xctx)\n{\n\tCHACHA20_POLY1305_CTX *ctx = (CHACHA20_POLY1305_CTX *)xctx;\n\n\tpoly1305_finish((poly1305_state *)&ctx->poly, tag);\n\tmemset(ctx, 0, sizeof(*ctx));\n}\n"
  },
  {
    "path": "itl80211/openbsd/crypto/chachapoly.h",
    "content": "/*\n * Copyright (c) 2015 Mike Belopuhov\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n#ifndef _CHACHAPOLY_H_\n#define _CHACHAPOLY_H_\n\n#define CHACHA20_KEYSIZE\t32\n#define CHACHA20_CTR\t\t4\n#define CHACHA20_SALT\t\t4\n#define CHACHA20_NONCE\t\t8\n#define CHACHA20_BLOCK_LEN\t64\n\nstruct chacha20_ctx {\n\tuint8_t\t\t\tblock[CHACHA20_BLOCK_LEN];\n\tuint8_t\t\t\tnonce[CHACHA20_NONCE];\n};\n\nint\tchacha20_setkey(void *, u_int8_t *, int);\nvoid\tchacha20_reinit(caddr_t, u_int8_t *);\nvoid\tchacha20_crypt(caddr_t, u_int8_t *);\n\n\n#define POLY1305_KEYLEN\t\t32\n#define POLY1305_TAGLEN\t\t16\n#define POLY1305_BLOCK_LEN\t16\n\nstruct poly1305_ctx {\n\t/* r, h, pad, leftover */\n\tunsigned long\t\tstate[5+5+4];\n\tsize_t\t\t\tleftover;\n\tunsigned char\t\tbuffer[POLY1305_BLOCK_LEN];\n\tunsigned char\t\tfinal;\n};\n\ntypedef struct {\n\tuint8_t\t\t\tkey[POLY1305_KEYLEN];\n\t/* counter, salt */\n\tuint8_t\t\t\tnonce[CHACHA20_NONCE];\n\tstruct chacha20_ctx\tchacha;\n\tstruct poly1305_ctx\tpoly;\n} CHACHA20_POLY1305_CTX;\n\nvoid\tChacha20_Poly1305_Init(void *);\nvoid\tChacha20_Poly1305_Setkey(void *, const uint8_t *, uint16_t);\nvoid\tChacha20_Poly1305_Reinit(void *, const uint8_t *, uint16_t);\nint\tChacha20_Poly1305_Update(void *, const uint8_t *, uint16_t);\nvoid\tChacha20_Poly1305_Final(uint8_t[POLY1305_TAGLEN], void *);\n\n#endif\t/* _CHACHAPOLY_H_ */\n"
  },
  {
    "path": "itl80211/openbsd/crypto/cmac.c",
    "content": "/*\t$OpenBSD: cmac.c,v 1.3 2017/05/02 17:07:06 mikeb Exp $\t*/\n\n/*-\n * Copyright (c) 2008 Damien Bergamini <damien.bergamini@free.fr>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n/*\n * This code implements the CMAC (Cipher-based Message Authentication)\n * algorithm described in FIPS SP800-38B using the AES-128 cipher.\n */\n\n#include <sys/param.h>\n#include <sys/systm.h>\n\n#include <crypto/aes.h>\n#include <crypto/cmac.h>\n\n#define LSHIFT(v, r) do {\t\t\t\t\t\\\n\tint i;\t\t\t\t\t\t\t\\\n\tfor (i = 0; i < 15; i++)\t\t\t\t\\\n\t\t(r)[i] = (v)[i] << 1 | (v)[i + 1] >> 7;\t\t\\\n\t(r)[15] = (v)[15] << 1;\t\t\t\t\t\\\n} while (0)\n\n#define XOR(v, r) do {\t\t\t\t\t\t\\\n\tint i;\t\t\t\t\t\t\t\\\n\tfor (i = 0; i < 16; i++)\t\t\t\t\\\n\t\t(r)[i] ^= (v)[i];\t\t\t\t\\\n} while (0)\n\nvoid\nAES_CMAC_Init(AES_CMAC_CTX *ctx)\n{\n\tmemset(ctx->X, 0, sizeof ctx->X);\n\tctx->M_n = 0;\n}\n\nvoid\nAES_CMAC_SetKey(AES_CMAC_CTX *ctx, const u_int8_t key[AES_CMAC_KEY_LENGTH])\n{\n\tAES_Setkey(&ctx->aesctx, key, 16);\n}\n\nvoid\nAES_CMAC_Update(AES_CMAC_CTX *ctx, const u_int8_t *data, u_int len)\n{\n\tu_int mlen;\n\n\tif (ctx->M_n > 0) {\n\t\tmlen = MIN(16 - ctx->M_n, len);\n\t\tmemcpy(ctx->M_last + ctx->M_n, data, mlen);\n\t\tctx->M_n += mlen;\n\t\tif (ctx->M_n < 16 || len == mlen)\n\t\t\treturn;\n\t\tXOR(ctx->M_last, ctx->X);\n\t\tAES_Encrypt(&ctx->aesctx, ctx->X, ctx->X);\n\t\tdata += mlen;\n\t\tlen -= mlen;\n\t}\n\twhile (len > 16) {\t/* not last block */\n\t\tXOR(data, ctx->X);\n\t\tAES_Encrypt(&ctx->aesctx, ctx->X, ctx->X);\n\t\tdata += 16;\n\t\tlen -= 16;\n\t}\n\t/* potential last block, save it */\n\tmemcpy(ctx->M_last, data, len);\n\tctx->M_n = len;\n}\n\nvoid\nAES_CMAC_Final(u_int8_t digest[AES_CMAC_DIGEST_LENGTH], AES_CMAC_CTX *ctx)\n{\n\tu_int8_t K[16];\n\n\t/* generate subkey K1 */\n\tmemset(K, 0, sizeof K);\n\tAES_Encrypt(&ctx->aesctx, K, K);\n\n\tif (K[0] & 0x80) {\n\t\tLSHIFT(K, K);\n\t\tK[15] ^= 0x87;\n\t} else\n\t\tLSHIFT(K, K);\n\n\tif (ctx->M_n == 16) {\n\t\t/* last block was a complete block */\n\t\tXOR(K, ctx->M_last);\n\t} else {\n\t\t/* generate subkey K2 */\n\t\tif (K[0] & 0x80) {\n\t\t\tLSHIFT(K, K);\n\t\t\tK[15] ^= 0x87;\n\t\t} else\n\t\t\tLSHIFT(K, K);\n\n\t\t/* padding(M_last) */\n\t\tctx->M_last[ctx->M_n] = 0x80;\n\t\twhile (++ctx->M_n < 16)\n\t\t\tctx->M_last[ctx->M_n] = 0;\n\n\t\tXOR(K, ctx->M_last);\n\t}\n\tXOR(ctx->M_last, ctx->X);\n\tAES_Encrypt(&ctx->aesctx, ctx->X, digest);\n\n\tmemset(K, 0, sizeof K);\n}\n"
  },
  {
    "path": "itl80211/openbsd/crypto/cmac.h",
    "content": "/*\t$OpenBSD: cmac.h,v 1.3 2017/05/02 17:07:06 mikeb Exp $\t*/\n\n/*-\n * Copyright (c) 2008 Damien Bergamini <damien.bergamini@free.fr>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n#ifndef _CMAC_H_\n#define _CMAC_H_\n\n#define AES_CMAC_KEY_LENGTH\t16\n#define AES_CMAC_DIGEST_LENGTH\t16\n\ntypedef struct _AES_CMAC_CTX {\n\tAES_CTX\t\taesctx;\n\tu_int8_t\tX[16];\n\tu_int8_t\tM_last[16];\n\tu_int\t\tM_n;\n} AES_CMAC_CTX;\n\n//__BEGIN_DECLS\nvoid\t AES_CMAC_Init(AES_CMAC_CTX *);\nvoid\t AES_CMAC_SetKey(AES_CMAC_CTX *, const u_int8_t [AES_CMAC_KEY_LENGTH]);\nvoid\t AES_CMAC_Update(AES_CMAC_CTX *, const u_int8_t *, u_int)\n\t\t__attribute__((__bounded__(__string__,2,3)));\nvoid\t AES_CMAC_Final(u_int8_t [AES_CMAC_DIGEST_LENGTH], AES_CMAC_CTX *)\n\t\t__attribute__((__bounded__(__minbytes__,1,AES_CMAC_DIGEST_LENGTH)));\n//__END_DECLS\n\n#endif /* _CMAC_H_ */\n"
  },
  {
    "path": "itl80211/openbsd/crypto/cryptodev.h",
    "content": "/*\t$OpenBSD: cryptodev.h,v 1.71 2017/08/10 18:57:20 tedu Exp $\t*/\n\n/*\n * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu)\n *\n * This code was written by Angelos D. Keromytis in Athens, Greece, in\n * February 2000. Network Security Technologies Inc. (NSTI) kindly\n * supported the development of this code.\n *\n * Copyright (c) 2000 Angelos D. Keromytis\n *\n * Permission to use, copy, and modify this software with or without fee\n * is hereby granted, provided that this entire notice is included in\n * all source code copies of any software which is or includes a copy or\n * modification of this software.\n *\n * THIS SOFTWARE IS BEING PROVIDED \"AS IS\", WITHOUT ANY EXPRESS OR\n * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY\n * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE\n * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR\n * PURPOSE.\n *\n * Copyright (c) 2001 Theo de Raadt\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * Effort sponsored in part by the Defense Advanced Research Projects\n * Agency (DARPA) and Air Force Research Laboratory, Air Force\n * Materiel Command, USAF, under agreement number F30602-01-2-0537.\n *\n */\n\n#ifndef _CRYPTO_CRYPTO_H_\n#define _CRYPTO_CRYPTO_H_\n\n#include <IOKit/IOLib.h>\n\n/* Some initial values */\n#define CRYPTO_DRIVERS_INITIAL\t4\n#define CRYPTO_DRIVERS_MAX\t128\n#define CRYPTO_SW_SESSIONS\t32\n\n/* HMAC values */\n#define HMAC_MD5_BLOCK_LEN\t64\n#define HMAC_SHA1_BLOCK_LEN\t64\n#define HMAC_RIPEMD160_BLOCK_LEN 64\n#define HMAC_SHA2_256_BLOCK_LEN\t64\n#define HMAC_SHA2_384_BLOCK_LEN\t128\n#define HMAC_SHA2_512_BLOCK_LEN\t128\n#define HMAC_MAX_BLOCK_LEN\tHMAC_SHA2_512_BLOCK_LEN\t/* keep in sync */\n#define HMAC_IPAD_VAL\t\t0x36\n#define HMAC_OPAD_VAL\t\t0x5C\n\n/* Encryption algorithm block sizes */\n#define DES3_BLOCK_LEN\t\t8\n#define BLOWFISH_BLOCK_LEN\t8\n#define CAST128_BLOCK_LEN\t8\n#define RIJNDAEL128_BLOCK_LEN\t16\n#define CHACHA20_BLOCK_LEN\t64\n#define EALG_MAX_BLOCK_LEN\t64 /* Keep this updated */\n\n/* Maximum hash algorithm result length */\n#define AALG_MAX_RESULT_LEN\t64 /* Keep this updated */\n\n#define CRYPTO_3DES_CBC\t\t1\n#define CRYPTO_BLF_CBC\t\t2\n#define CRYPTO_CAST_CBC\t\t3\n#define CRYPTO_MD5_HMAC\t\t4\n#define CRYPTO_SHA1_HMAC\t5\n#define CRYPTO_RIPEMD160_HMAC\t6\n#define CRYPTO_RIJNDAEL128_CBC\t7  /* 128 bit blocksize */\n#define CRYPTO_AES_CBC\t\t7  /* 128 bit blocksize -- the same as above */\n#define CRYPTO_DEFLATE_COMP\t8  /* Deflate compression algorithm */\n#define CRYPTO_NULL\t\t9\n#define CRYPTO_LZS_COMP\t\t10 /* LZS compression algorithm */\n#define CRYPTO_SHA2_256_HMAC\t11\n#define CRYPTO_SHA2_384_HMAC\t12\n#define CRYPTO_SHA2_512_HMAC\t13\n#define CRYPTO_AES_CTR\t\t14\n#define CRYPTO_AES_XTS\t\t15\n#define CRYPTO_AES_GCM_16\t16\n#define CRYPTO_AES_128_GMAC\t17\n#define CRYPTO_AES_192_GMAC\t18\n#define CRYPTO_AES_256_GMAC\t19\n#define CRYPTO_AES_GMAC\t\t20\n#define CRYPTO_CHACHA20_POLY1305\t21\n#define CRYPTO_CHACHA20_POLY1305_MAC\t22\n#define CRYPTO_ESN\t\t23 /* Support for Extended Sequence Numbers */\n#define CRYPTO_ALGORITHM_MAX\t23 /* Keep updated */\n\n/* Algorithm flags */\n#define\tCRYPTO_ALG_FLAG_SUPPORTED\t0x01 /* Algorithm is supported */\n\n/* Standard initialization structure beginning */\nstruct cryptoini {\n\tint\t\tcri_alg;\t/* Algorithm to use */\n\tint\t\tcri_klen;\t/* Key length, in bits */\n\tint\t\tcri_rnd;\t/* Algorithm rounds, where relevant */\n\tcaddr_t\t\tcri_key;\t/* key to use */\n\tunion {\n\t\tu_int8_t\tiv[EALG_MAX_BLOCK_LEN];\t/* IV to use */\n\t\tu_int8_t\tesn[4];\t\t\t/* high-order ESN */\n\t} u;\n#define cri_iv\t\tu.iv\n#define cri_esn\t\tu.esn\n\tstruct cryptoini *cri_next;\n};\n\n/* Describe boundaries of a single crypto operation */\nstruct cryptodesc {\n\tint\t\tcrd_skip;\t/* How many bytes to ignore from start */\n\tint\t\tcrd_len;\t/* How many bytes to process */\n\tint\t\tcrd_inject;\t/* Where to inject results, if applicable */\n\tint\t\tcrd_flags;\n\n#define\tCRD_F_ENCRYPT\t\t0x01\t/* Set when doing encryption */\n#define\tCRD_F_IV_PRESENT\t0x02\t/* When encrypting, IV is already in\n\t\t\t\t\t   place, so don't copy. */\n#define\tCRD_F_IV_EXPLICIT\t0x04\t/* IV explicitly provided */\n#define CRD_F_COMP\t\t0x10    /* Set when doing compression */\n#define CRD_F_ESN\t\t0x20\t/* Set when ESN field is provided */\n\n\tstruct cryptoini\tCRD_INI; /* Initialization/context data */\n#define crd_esn\t\tCRD_INI.cri_esn\n#define crd_iv\t\tCRD_INI.cri_iv\n#define crd_key\t\tCRD_INI.cri_key\n#define crd_rnd\t\tCRD_INI.cri_rnd\n#define crd_alg\t\tCRD_INI.cri_alg\n#define crd_klen\tCRD_INI.cri_klen\n};\n\n/* Structure describing complete operation */\nstruct cryptop {\n\tstruct task\tcrp_task;\n\n\tu_int64_t\tcrp_sid;\t/* Session ID */\n\tint\t\tcrp_ilen;\t/* Input data total length */\n\tint\t\tcrp_olen;\t/* Result total length */\n\tint\t\tcrp_alloctype;\t/* Type of buf to allocate if needed */\n\n\tint\t\tcrp_etype;\t/*\n\t\t\t\t\t * Error type (zero means no error).\n\t\t\t\t\t * All error codes except EAGAIN\n\t\t\t\t\t * indicate possible data corruption (as in,\n\t\t\t\t\t * the data have been touched). On all\n\t\t\t\t\t * errors, the crp_sid may have changed\n\t\t\t\t\t * (reset to a new one), so the caller\n\t\t\t\t\t * should always check and use the new\n\t\t\t\t\t * value on future requests.\n\t\t\t\t\t */\n\tint\t\tcrp_flags;\n\n#define CRYPTO_F_IMBUF\t0x0001\t/* Input/output are mbuf chains, otherwise contig */\n#define CRYPTO_F_IOV\t0x0002\t/* Input/output are uio */\n#define CRYPTO_F_NOQUEUE\t0x0008\t/* Don't use crypto queue/thread */\n#define CRYPTO_F_DONE\t0x0010\t/* request completed */\n\n\tvoid \t\t*crp_buf;\t/* Data to be processed */\n\tvoid \t\t*crp_opaque;\t/* Opaque pointer, passed along */\n\n\tstruct cryptodesc *crp_desc;\t/* List of processing descriptors */\n\tstruct cryptodesc crp_sdesc[2];\t/* Static array for small ops */\n\tint\t\t crp_ndesc;\t/* Amount of descriptors to use */\n\tint\t\t crp_ndescalloc;/* Amount of descriptors allocated */\n\n\tvoid (*crp_callback)(struct cryptop *); /* Callback function */\n\n\tcaddr_t\t\tcrp_mac;\n};\n\n#define CRYPTO_BUF_IOV\t\t0x1\n#define CRYPTO_BUF_MBUF\t\t0x2\n\n#define CRYPTO_OP_DECRYPT\t0x0\n#define CRYPTO_OP_ENCRYPT\t0x1\n\n/* Crypto capabilities structure */\nstruct cryptocap {\n\tu_int64_t\tcc_operations;\t/* Counter of how many ops done */\n\tu_int64_t\tcc_bytes;\t/* Counter of how many bytes done */\n\tu_int64_t\tcc_koperations;\t/* How many PK ops done */\n\n\tu_int32_t\tcc_sessions;\t/* How many sessions allocated */\n\n\t/* Symmetric/hash algorithms supported */\n\tint\t\tcc_alg[CRYPTO_ALGORITHM_MAX + 1];\n\n\tint\t\tcc_queued;\t/* Operations queued */\n\n\tu_int8_t\tcc_flags;\n#define CRYPTOCAP_F_CLEANUP     0x01\n#define CRYPTOCAP_F_SOFTWARE    0x02\n#define CRYPTOCAP_F_MPSAFE      0x04\n\n\tint\t\t(*cc_newsession) (u_int32_t *, struct cryptoini *);\n\tint\t\t(*cc_process) (struct cryptop *);\n\tint\t\t(*cc_freesession) (u_int64_t);\n};\n\n\nint\tcrypto_newsession(u_int64_t *, struct cryptoini *, int);\nint\tcrypto_freesession(u_int64_t);\nint\tcrypto_dispatch(struct cryptop *);\nint\tcrypto_register(u_int32_t, int *,\n\t    int (*)(u_int32_t *, struct cryptoini *), int (*)(u_int64_t),\n\t    int (*)(struct cryptop *));\nint\tcrypto_unregister(u_int32_t, int);\nint32_t\tcrypto_get_driverid(u_int8_t);\nint\tcrypto_invoke(struct cryptop *);\nvoid\tcrypto_done(struct cryptop *);\n\nvoid\tcuio_copydata(struct uio *, int, int, caddr_t);\nvoid\tcuio_copyback(struct uio *, int, int, const void *);\nint\tcuio_getptr(struct uio *, int, int *);\nint\tcuio_apply(struct uio *, int, int,\n\t    int (*f)(caddr_t, caddr_t, unsigned int), caddr_t);\n\nstruct\tcryptop *crypto_getreq(int);\nvoid\tcrypto_freereq(struct cryptop *);\n#endif /* _CRYPTO_CRYPTO_H_ */\n"
  },
  {
    "path": "itl80211/openbsd/crypto/des_locl.h",
    "content": "/*\t$OpenBSD: des_locl.h,v 1.7 2015/12/10 21:00:51 naddy Exp $\t*/\n\n/* lib/des/des_locl.h */\n/* Copyright (C) 1995 Eric Young (eay@mincom.oz.au)\n * All rights reserved.\n * \n * This file is part of an SSL implementation written\n * by Eric Young (eay@mincom.oz.au).\n * The implementation was written so as to conform with Netscapes SSL\n * specification.  This library and applications are\n * FREE FOR COMMERCIAL AND NON-COMMERCIAL USE\n * as long as the following conditions are aheared to.\n * \n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.  If this code is used in a product,\n * Eric Young should be given attribution as the author of the parts used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    This product includes software developed by Eric Young (eay@mincom.oz.au)\n * \n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n * \n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n\n#ifndef HEADER_DES_LOCL_H\n#define HEADER_DES_LOCL_H\n\n#include <sys/types.h>\n#include <sys/systm.h>\n\ntypedef unsigned char des_cblock[8];\ntypedef struct des_ks_struct\n\t{\n\tunion\t{\n\t\tdes_cblock cblock;\n\t\t/* make sure things are correct size on machines with\n\t\t * 8 byte longs */\n\t\tint32_t pad[2];\n\t\t} ks;\n\t} des_key_schedule[16];\n\n#define DES_KEY_SZ \t(sizeof(des_cblock))\n#define DES_SCHEDULE_SZ (sizeof(des_key_schedule))\n\n\nvoid des_encrypt2(u_int32_t *data,des_key_schedule ks, int enc);\n\n\n#define ITERATIONS 16\n#define HALF_ITERATIONS 8\n\n\n#define c2l(c,l)\t(l =((u_int32_t)(*((c)++)))    , \\\n\t\t\t l|=((u_int32_t)(*((c)++)))<< 8L, \\\n\t\t\t l|=((u_int32_t)(*((c)++)))<<16L, \\\n\t\t\t l|=((u_int32_t)(*((c)++)))<<24L)\n\n#define l2c(l,c)\t(*((c)++)=(unsigned char)(((l)     )&0xff), \\\n\t\t\t *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \\\n\t\t\t *((c)++)=(unsigned char)(((l)>>16L)&0xff), \\\n\t\t\t *((c)++)=(unsigned char)(((l)>>24L)&0xff))\n\n#define D_ENCRYPT(Q,R,S) {\\\n\tu=(R^s[S  ]); \\\n\tt=R^s[S+1]; \\\n\tt=((t>>4L)+(t<<28L)); \\\n\tQ^=\tdes_SPtrans[1][(t     )&0x3f]| \\\n\t\tdes_SPtrans[3][(t>> 8L)&0x3f]| \\\n\t\tdes_SPtrans[5][(t>>16L)&0x3f]| \\\n\t\tdes_SPtrans[7][(t>>24L)&0x3f]| \\\n\t\tdes_SPtrans[0][(u     )&0x3f]| \\\n\t\tdes_SPtrans[2][(u>> 8L)&0x3f]| \\\n\t\tdes_SPtrans[4][(u>>16L)&0x3f]| \\\n\t\tdes_SPtrans[6][(u>>24L)&0x3f]; }\n\n\t/* IP and FP\n\t * The problem is more of a geometric problem that random bit fiddling.\n\t 0  1  2  3  4  5  6  7      62 54 46 38 30 22 14  6\n\t 8  9 10 11 12 13 14 15      60 52 44 36 28 20 12  4\n\t16 17 18 19 20 21 22 23      58 50 42 34 26 18 10  2\n\t24 25 26 27 28 29 30 31  to  56 48 40 32 24 16  8  0\n\n\t32 33 34 35 36 37 38 39      63 55 47 39 31 23 15  7\n\t40 41 42 43 44 45 46 47      61 53 45 37 29 21 13  5\n\t48 49 50 51 52 53 54 55      59 51 43 35 27 19 11  3\n\t56 57 58 59 60 61 62 63      57 49 41 33 25 17  9  1\n\n\tThe output has been subject to swaps of the form\n\t0 1 -> 3 1 but the odd and even bits have been put into\n\t2 3    2 0\n\tdifferent words.  The main trick is to remember that\n\tt=((l>>size)^r)&(mask);\n\tr^=t;\n\tl^=(t<<size);\n\tcan be used to swap and move bits between words.\n\n\tSo l =  0  1  2  3  r = 16 17 18 19\n\t        4  5  6  7      20 21 22 23\n\t        8  9 10 11      24 25 26 27\n\t       12 13 14 15      28 29 30 31\n\tbecomes (for size == 2 and mask == 0x3333)\n\t   t =   2^16  3^17 -- --   l =  0  1 16 17  r =  2  3 18 19\n\t\t 6^20  7^21 -- --        4  5 20 21       6  7 22 23\n\t\t10^24 11^25 -- --        8  9 24 25      10 11 24 25\n\t\t14^28 15^29 -- --       12 13 28 29      14 15 28 29\n\n\tThanks for hints from Richard Outerbridge - he told me IP&FP\n\tcould be done in 15 xor, 10 shifts and 5 ands.\n\tWhen I finally started to think of the problem in 2D\n\tI first got ~42 operations without xors.  When I remembered\n\thow to use xors :-) I got it to its final state.\n\t*/\n#define PERM_OP(a,b,t,n,m) ((t)=((((a)>>(n))^(b))&(m)),\\\n\t(b)^=(t),\\\n\t(a)^=((t)<<(n)))\n\n#define IP(l,r) \\\n\t{ \\\n\tregister u_int32_t tt; \\\n\tPERM_OP(r,l,tt, 4,0x0f0f0f0fL); \\\n\tPERM_OP(l,r,tt,16,0x0000ffffL); \\\n\tPERM_OP(r,l,tt, 2,0x33333333L); \\\n\tPERM_OP(l,r,tt, 8,0x00ff00ffL); \\\n\tPERM_OP(r,l,tt, 1,0x55555555L); \\\n\t}\n\n#define FP(l,r) \\\n\t{ \\\n\tregister u_int32_t tt; \\\n\tPERM_OP(l,r,tt, 1,0x55555555L); \\\n\tPERM_OP(r,l,tt, 8,0x00ff00ffL); \\\n\tPERM_OP(l,r,tt, 2,0x33333333L); \\\n\tPERM_OP(r,l,tt,16,0x0000ffffL); \\\n\tPERM_OP(l,r,tt, 4,0x0f0f0f0fL); \\\n\t}\n#endif\n"
  },
  {
    "path": "itl80211/openbsd/crypto/ecb3_enc.c",
    "content": "/*\t$OpenBSD: ecb3_enc.c,v 1.3 2013/11/18 18:49:53 brad Exp $\t*/\n\n/* lib/des/ecb3_enc.c */\n/* Copyright (C) 1995 Eric Young (eay@mincom.oz.au)\n * All rights reserved.\n * \n * This file is part of an SSL implementation written\n * by Eric Young (eay@mincom.oz.au).\n * The implementation was written so as to conform with Netscapes SSL\n * specification.  This library and applications are\n * FREE FOR COMMERCIAL AND NON-COMMERCIAL USE\n * as long as the following conditions are aheared to.\n * \n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.  If this code is used in a product,\n * Eric Young should be given attribution as the author of the parts used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    This product includes software developed by Eric Young (eay@mincom.oz.au)\n * \n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n * \n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n\n#include \"des_locl.h\"\n\nvoid\ndes_ecb3_encrypt(des_cblock (*input), des_cblock (*output),\n    des_key_schedule ks1, des_key_schedule ks2, des_key_schedule ks3,\n    int encrypt)\n{\n\tregister u_int32_t l0, l1;\n\tregister unsigned char *in, *out;\n\tu_int32_t ll[2];\n\n\tin = (unsigned char *) input;\n\tout = (unsigned char *) output;\n\tc2l(in, l0);\n\tc2l(in, l1);\n\tIP(l0, l1);\n\tll[0] = l0;\n\tll[1] = l1;\n\tdes_encrypt2(ll, ks1, encrypt);\n\tdes_encrypt2(ll, ks2, !encrypt);\n\tdes_encrypt2(ll, ks3, encrypt);\n\tl0 = ll[0];\n\tl1 = ll[1];\n\tFP(l1, l0);\n\tl2c(l0, out);\n\tl2c(l1, out);\n}\n"
  },
  {
    "path": "itl80211/openbsd/crypto/ecb_enc.c",
    "content": "/*\t$OpenBSD: ecb_enc.c,v 1.6 2015/12/10 21:00:51 naddy Exp $\t*/\n\n/* lib/des/ecb_enc.c */\n/* Copyright (C) 1995 Eric Young (eay@mincom.oz.au)\n * All rights reserved.\n * \n * This file is part of an SSL implementation written\n * by Eric Young (eay@mincom.oz.au).\n * The implementation was written so as to conform with Netscapes SSL\n * specification.  This library and applications are\n * FREE FOR COMMERCIAL AND NON-COMMERCIAL USE\n * as long as the following conditions are aheared to.\n * \n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.  If this code is used in a product,\n * Eric Young should be given attribution as the author of the parts used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    This product includes software developed by Eric Young (eay@mincom.oz.au)\n * \n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n * \n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n\n#include \"des_locl.h\"\n#include \"spr.h\"\n\nvoid\ndes_encrypt2(u_int32_t *data, des_key_schedule ks, int encrypt)\n{\n\tregister u_int32_t l, r, t, u;\n#ifdef DES_USE_PTR\n\tregister unsigned char *des_SP=(unsigned char *)des_SPtrans;\n#endif\n\tregister int i;\n\tregister u_int32_t *s;\n\n\tu = data[0];\n\tr = data[1];\n\n\t/* Things have been modified so that the initial rotate is\n\t * done outside the loop.  This required the\n\t * des_SPtrans values in sp.h to be rotated 1 bit to the right.\n\t * One perl script later and things have a 5% speed up on a sparc2.\n\t * Thanks to Richard Outerbridge <71755.204@CompuServe.COM>\n\t * for pointing this out. */\n\tl = (r << 1) | (r >> 31);\n\tr = (u << 1) | (u >> 31);\n\n\t/* clear the top bits on machines with 8byte longs */\n\tl &= 0xffffffffL;\n\tr &= 0xffffffffL;\n\n\ts = (u_int32_t *) ks;\n\t/* I don't know if it is worth the effort of loop unrolling the\n\t * inner loop */\n\tif (encrypt) {\n\t\tfor (i = 0; i < 32; i += 4) {\n\t\t\tD_ENCRYPT(l, r, i + 0); /*  1 */\n\t\t\tD_ENCRYPT(r, l, i + 2); /*  2 */\n\t\t}\n\t} else {\n\t\tfor (i = 30; i > 0; i -= 4) {\n\t\t\tD_ENCRYPT(l, r, i - 0); /* 16 */\n\t\t\tD_ENCRYPT(r, l, i - 2); /* 15 */\n\t\t}\n\t}\n\tl = (l >> 1) | (l << 31);\n\tr = (r >> 1) | (r << 31);\n\t/* clear the top bits on machines with 8byte longs */\n\tl &= 0xffffffffL;\n\tr &= 0xffffffffL;\n\n\tdata[0] = l;\n\tdata[1] = r;\n\tl = r = t = u = 0;\n}\n"
  },
  {
    "path": "itl80211/openbsd/crypto/gmac.c",
    "content": "/*\t$OpenBSD: gmac.c,v 1.10 2017/05/02 11:44:32 mikeb Exp $\t*/\n\n/*\n * Copyright (c) 2010 Mike Belopuhov\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n/*\n * This code implements the Message Authentication part of the\n * Galois/Counter Mode (as being described in the RFC 4543) using\n * the AES cipher.  FIPS SP 800-38D describes the algorithm details.\n */\n\n#include <sys/param.h>\n#include <sys/systm.h>\n\n#include <crypto/aes.h>\n#include <crypto/gmac.h>\n#include <sys/endian.h>\n\nvoid\tghash_gfmul(uint32_t *, uint32_t *, uint32_t *);\nvoid\tghash_update_mi(GHASH_CTX *, uint8_t *, size_t);\n\n/* Allow overriding with optimized MD function */\nvoid\t(*ghash_update)(GHASH_CTX *, uint8_t *, size_t) = ghash_update_mi;\n\n/* Computes a block multiplication in the GF(2^128) */\nvoid\nghash_gfmul(uint32_t *X, uint32_t *Y, uint32_t *product)\n{\n\tuint32_t\tv[4];\n\tuint32_t\tz[4] = { 0, 0, 0, 0};\n\tuint8_t\t\t*x = (uint8_t *)X;\n\tuint32_t\tmask;\n\tint\t\ti;\n\n\tv[0] = betoh32(Y[0]);\n\tv[1] = betoh32(Y[1]);\n\tv[2] = betoh32(Y[2]);\n\tv[3] = betoh32(Y[3]);\n\n\tfor (i = 0; i < GMAC_BLOCK_LEN * 8; i++) {\n\t\t/* update Z */\n\t\tmask = !!(x[i >> 3] & (1 << (~i & 7)));\n\t\tmask = ~(mask - 1);\n\t\tz[0] ^= v[0] & mask;\n\t\tz[1] ^= v[1] & mask;\n\t\tz[2] ^= v[2] & mask;\n\t\tz[3] ^= v[3] & mask;\n\n\t\t/* update V */\n\t\tmask = ~((v[3] & 1) - 1);\n\t\tv[3] = (v[2] << 31) | (v[3] >> 1);\n\t\tv[2] = (v[1] << 31) | (v[2] >> 1);\n\t\tv[1] = (v[0] << 31) | (v[1] >> 1);\n\t\tv[0] = (v[0] >> 1) ^ (0xe1000000 & mask);\n\t}\n\n\tproduct[0] = htobe32(z[0]);\n\tproduct[1] = htobe32(z[1]);\n\tproduct[2] = htobe32(z[2]);\n\tproduct[3] = htobe32(z[3]);\n}\n\nvoid\nghash_update_mi(GHASH_CTX *ctx, uint8_t *X, size_t len)\n{\n\tuint32_t\t*x = (uint32_t *)X;\n\tuint32_t\t*s = (uint32_t *)ctx->S;\n\tuint32_t\t*y = (uint32_t *)ctx->Z;\n\tint\t\ti;\n\n\tfor (i = 0; i < len / GMAC_BLOCK_LEN; i++) {\n\t\ts[0] = y[0] ^ x[0];\n\t\ts[1] = y[1] ^ x[1];\n\t\ts[2] = y[2] ^ x[2];\n\t\ts[3] = y[3] ^ x[3];\n\n\t\tghash_gfmul((uint32_t *)ctx->S, (uint32_t *)ctx->H,\n\t\t    (uint32_t *)ctx->S);\n\n\t\ty = s;\n\t\tx += 4;\n\t}\n\n\tbcopy(ctx->S, ctx->Z, GMAC_BLOCK_LEN);\n}\n\n#define AESCTR_NONCESIZE\t4\n\nvoid\nAES_GMAC_Init(void *xctx)\n{\n\tAES_GMAC_CTX\t*ctx = (AES_GMAC_CTX    *)xctx;\n\n\tbzero(ctx->ghash.H, GMAC_BLOCK_LEN);\n\tbzero(ctx->ghash.S, GMAC_BLOCK_LEN);\n\tbzero(ctx->ghash.Z, GMAC_BLOCK_LEN);\n\tbzero(ctx->J, GMAC_BLOCK_LEN);\n}\n\nvoid\nAES_GMAC_Setkey(void *xctx, const uint8_t *key, uint16_t klen)\n{\n\tAES_GMAC_CTX\t*ctx = (AES_GMAC_CTX    *)xctx;\n\n\tAES_Setkey(&ctx->K, key, klen - AESCTR_NONCESIZE);\n\t/* copy out salt to the counter block */\n\tbcopy(key + klen - AESCTR_NONCESIZE, ctx->J, AESCTR_NONCESIZE);\n\t/* prepare a hash subkey */\n\tAES_Encrypt(&ctx->K, ctx->ghash.H, ctx->ghash.H);\n}\n\nvoid\nAES_GMAC_Reinit(void *xctx, const uint8_t *iv, uint16_t ivlen)\n{\n\tAES_GMAC_CTX\t*ctx = (AES_GMAC_CTX    *)xctx;\n\n\t/* copy out IV to the counter block */\n\tbcopy(iv, ctx->J + AESCTR_NONCESIZE, ivlen);\n}\n\nint\nAES_GMAC_Update(void *xctx, const uint8_t *data, uint16_t len)\n{\n\tAES_GMAC_CTX\t*ctx = (AES_GMAC_CTX    *)xctx;\n\tuint32_t\tblk[4] = { 0, 0, 0, 0 };\n\tint\t\tplen;\n\n\tif (len > 0) {\n\t\tplen = len % GMAC_BLOCK_LEN;\n\t\tif (len >= GMAC_BLOCK_LEN)\n\t\t\t(*ghash_update)(&ctx->ghash, (uint8_t *)data,\n\t\t\t    len - plen);\n\t\tif (plen) {\n\t\t\tmemcpy((uint8_t *)blk, (uint8_t *)data + (len - plen),\n\t\t\t    plen);\n\t\t\t(*ghash_update)(&ctx->ghash, (uint8_t *)blk,\n\t\t\t    GMAC_BLOCK_LEN);\n\t\t}\n\t}\n\treturn (0);\n}\n\nvoid\nAES_GMAC_Final(uint8_t digest[GMAC_DIGEST_LEN], void *xctx)\n{\n\tAES_GMAC_CTX\t*ctx = (AES_GMAC_CTX    *)xctx;\n\tuint8_t\t\tkeystream[GMAC_BLOCK_LEN];\n\tint\t\ti;\n\n\t/* do one round of GCTR */\n\tctx->J[GMAC_BLOCK_LEN - 1] = 1;\n\tAES_Encrypt(&ctx->K, ctx->J, keystream);\n\tfor (i = 0; i < GMAC_DIGEST_LEN; i++)\n\t\tdigest[i] = ctx->ghash.S[i] ^ keystream[i];\n\tmemset(keystream, 0, sizeof(keystream));\n}\n"
  },
  {
    "path": "itl80211/openbsd/crypto/gmac.h",
    "content": "/*\t$OpenBSD: gmac.h,v 1.6 2017/05/02 11:44:32 mikeb Exp $\t*/\n\n/*\n * Copyright (c) 2010 Mike Belopuhov\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n#ifndef _GMAC_H_\n#define _GMAC_H_\n\n#include <crypto/aes.h>\n\n#define GMAC_BLOCK_LEN\t\t16\n#define GMAC_DIGEST_LEN\t\t16\n\ntypedef struct _GHASH_CTX {\n\tuint8_t\t\tH[GMAC_BLOCK_LEN];\t\t/* hash subkey */\n\tuint8_t\t\tS[GMAC_BLOCK_LEN];\t\t/* state */\n\tuint8_t\t\tZ[GMAC_BLOCK_LEN];\t\t/* initial state */\n} GHASH_CTX;\n\ntypedef struct _AES_GMAC_CTX {\n\tGHASH_CTX\tghash;\n\tAES_CTX\t\tK;\n\tuint8_t\t\tJ[GMAC_BLOCK_LEN];\t\t/* counter block */\n} AES_GMAC_CTX;\n\n//__BEGIN_DECLS\nextern void (*ghash_update)(GHASH_CTX *, uint8_t *, size_t);\n\nvoid\tAES_GMAC_Init(void *);\nvoid\tAES_GMAC_Setkey(void *, const uint8_t *, uint16_t);\nvoid\tAES_GMAC_Reinit(void *, const uint8_t *, uint16_t);\nint\tAES_GMAC_Update(void *, const uint8_t *, uint16_t);\nvoid\tAES_GMAC_Final(uint8_t [GMAC_DIGEST_LEN], void *);\n//__END_DECLS\n\n#endif /* _GMAC_H_ */\n"
  },
  {
    "path": "itl80211/openbsd/crypto/hmac.c",
    "content": "/*\t$OpenBSD: hmac.c,v 1.4 2016/09/19 18:09:40 tedu Exp $\t*/\n\n/*-\n * Copyright (c) 2008 Damien Bergamini <damien.bergamini@free.fr>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n/*\n * This code implements the HMAC algorithm described in RFC 2104 using\n * the MD5, SHA1 and SHA-256 hash functions.\n */\n\n#include <sys/param.h>\n#include <sys/systm.h>\n\n#include <crypto/md5.h>\n#include <crypto/sha1.h>\n#include <crypto/sha2.h>\n#include <crypto/hmac.h>\n\nvoid\nHMAC_MD5_Init(HMAC_MD5_CTX *ctx, const u_int8_t *key, u_int key_len)\n{\n\tu_int8_t k_ipad[MD5_BLOCK_LENGTH];\n\tint i;\n\n\tif (key_len > MD5_BLOCK_LENGTH) {\n\t\tMD5Init(&ctx->ctx);\n\t\tMD5Update(&ctx->ctx, key, key_len);\n\t\tMD5Final(ctx->key, &ctx->ctx);\n\t\tctx->key_len = MD5_DIGEST_LENGTH;\n\t} else {\n\t\tbcopy(key, ctx->key, key_len);\n\t\tctx->key_len = key_len;\n\t}\n\n\tbzero(k_ipad, MD5_BLOCK_LENGTH);\n\tmemcpy(k_ipad, ctx->key, ctx->key_len);\n\tfor (i = 0; i < MD5_BLOCK_LENGTH; i++)\n\t\tk_ipad[i] ^= 0x36;\n\n\tMD5Init(&ctx->ctx);\n\tMD5Update(&ctx->ctx, k_ipad, MD5_BLOCK_LENGTH);\n\n\tmemset(k_ipad, 0, sizeof k_ipad);\n}\n\nvoid\nHMAC_MD5_Update(HMAC_MD5_CTX *ctx, const u_int8_t *data, u_int len)\n{\n\tMD5Update(&ctx->ctx, data, len);\n}\n\nvoid\nHMAC_MD5_Final(u_int8_t digest[MD5_DIGEST_LENGTH], HMAC_MD5_CTX *ctx)\n{\n\tu_int8_t k_opad[MD5_BLOCK_LENGTH];\n\tint i;\n\n\tMD5Final(digest, &ctx->ctx);\n\n\tbzero(k_opad, MD5_BLOCK_LENGTH);\n\tmemcpy(k_opad, ctx->key, ctx->key_len);\n\tfor (i = 0; i < MD5_BLOCK_LENGTH; i++)\n\t\tk_opad[i] ^= 0x5c;\n\n\tMD5Init(&ctx->ctx);\n\tMD5Update(&ctx->ctx, k_opad, MD5_BLOCK_LENGTH);\n\tMD5Update(&ctx->ctx, digest, MD5_DIGEST_LENGTH);\n\tMD5Final(digest, &ctx->ctx);\n\n\tmemset(k_opad, 0, sizeof k_opad);\n}\n\nvoid\nHMAC_SHA1_Init(HMAC_SHA1_CTX *ctx, const u_int8_t *key, u_int key_len)\n{\n\tu_int8_t k_ipad[SHA1_BLOCK_LENGTH];\n\tint i;\n\n\tif (key_len > SHA1_BLOCK_LENGTH) {\n\t\tSHA1Init(&ctx->ctx);\n\t\tSHA1Update(&ctx->ctx, key, key_len);\n\t\tSHA1Final(ctx->key, &ctx->ctx);\n\t\tctx->key_len = SHA1_DIGEST_LENGTH;\n\t} else {\n\t\tbcopy(key, ctx->key, key_len);\n\t\tctx->key_len = key_len;\n\t}\n\n\tbzero(k_ipad, SHA1_BLOCK_LENGTH);\n\tmemcpy(k_ipad, ctx->key, ctx->key_len);\n\tfor (i = 0; i < SHA1_BLOCK_LENGTH; i++)\n\t\tk_ipad[i] ^= 0x36;\n\n\tSHA1Init(&ctx->ctx);\n\tSHA1Update(&ctx->ctx, k_ipad, SHA1_BLOCK_LENGTH);\n\n\tmemset(k_ipad, 0, sizeof k_ipad);\n}\n\nvoid\nHMAC_SHA1_Update(HMAC_SHA1_CTX *ctx, const u_int8_t *data, u_int len)\n{\n\tSHA1Update(&ctx->ctx, data, len);\n}\n\nvoid\nHMAC_SHA1_Final(u_int8_t digest[SHA1_DIGEST_LENGTH], HMAC_SHA1_CTX *ctx)\n{\n\tu_int8_t k_opad[SHA1_BLOCK_LENGTH];\n\tint i;\n\n\tSHA1Final(digest, &ctx->ctx);\n\n\tbzero(k_opad, SHA1_BLOCK_LENGTH);\n\tmemcpy(k_opad, ctx->key, ctx->key_len);\n\tfor (i = 0; i < SHA1_BLOCK_LENGTH; i++)\n\t\tk_opad[i] ^= 0x5c;\n\n\tSHA1Init(&ctx->ctx);\n\tSHA1Update(&ctx->ctx, k_opad, SHA1_BLOCK_LENGTH);\n\tSHA1Update(&ctx->ctx, digest, SHA1_DIGEST_LENGTH);\n\tSHA1Final(digest, &ctx->ctx);\n\n\tmemset(k_opad, 0, sizeof k_opad);\n}\n\nvoid\nHMAC_SHA256_Init(HMAC_SHA256_CTX *ctx, const u_int8_t *key, u_int key_len)\n{\n\tu_int8_t k_ipad[SHA256_BLOCK_LENGTH];\n\tint i;\n\n\tif (key_len > SHA256_BLOCK_LENGTH) {\n\t\tSHA256Init(&ctx->ctx);\n\t\tSHA256Update(&ctx->ctx, key, key_len);\n\t\tSHA256Final(ctx->key, &ctx->ctx);\n\t\tctx->key_len = SHA256_DIGEST_LENGTH;\n\t} else {\n\t\tbcopy(key, ctx->key, key_len);\n\t\tctx->key_len = key_len;\n\t}\n\n\tbzero(k_ipad, SHA256_BLOCK_LENGTH);\n\tmemcpy(k_ipad, ctx->key, ctx->key_len);\n\tfor (i = 0; i < SHA256_BLOCK_LENGTH; i++)\n\t\tk_ipad[i] ^= 0x36;\n\n\tSHA256Init(&ctx->ctx);\n\tSHA256Update(&ctx->ctx, k_ipad, SHA256_BLOCK_LENGTH);\n\n\tmemset(k_ipad, 0, sizeof k_ipad);\n}\n\nvoid\nHMAC_SHA256_Update(HMAC_SHA256_CTX *ctx, const u_int8_t *data, u_int len)\n{\n\tSHA256Update(&ctx->ctx, data, len);\n}\n\nvoid\nHMAC_SHA256_Final(u_int8_t digest[SHA256_DIGEST_LENGTH], HMAC_SHA256_CTX *ctx)\n{\n\tu_int8_t k_opad[SHA256_BLOCK_LENGTH];\n\tint i;\n\n\tSHA256Final(digest, &ctx->ctx);\n\n\tbzero(k_opad, SHA256_BLOCK_LENGTH);\n\tmemcpy(k_opad, ctx->key, ctx->key_len);\n\tfor (i = 0; i < SHA256_BLOCK_LENGTH; i++)\n\t\tk_opad[i] ^= 0x5c;\n\n\tSHA256Init(&ctx->ctx);\n\tSHA256Update(&ctx->ctx, k_opad, SHA256_BLOCK_LENGTH);\n\tSHA256Update(&ctx->ctx, digest, SHA256_DIGEST_LENGTH);\n\tSHA256Final(digest, &ctx->ctx);\n\n\tmemset(k_opad, 0, sizeof k_opad);\n}\n"
  },
  {
    "path": "itl80211/openbsd/crypto/hmac.h",
    "content": "/*\t$OpenBSD: hmac.h,v 1.3 2012/12/05 23:20:15 deraadt Exp $\t*/\n\n/*-\n * Copyright (c) 2008 Damien Bergamini <damien.bergamini@free.fr>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n#ifndef _HMAC_H_\n#define _HMAC_H_\n\n#include \"sha2.h\"\n#include \"md5.h\"\n\ntypedef struct _HMAC_MD5_CTX {\n\tMD5_CTX\t\tctx;\n\tu_int8_t\tkey[MD5_BLOCK_LENGTH];\n\tu_int\t\tkey_len;\n} HMAC_MD5_CTX;\n\ntypedef struct _HMAC_SHA1_CTX {\n\tSHA1_CTX\tctx;\n\tu_int8_t\tkey[SHA1_BLOCK_LENGTH];\n\tu_int\t\tkey_len;\n} HMAC_SHA1_CTX;\n\ntypedef struct _HMAC_SHA256_CTX {\n\tSHA2_CTX\tctx;\n\tu_int8_t\tkey[SHA256_BLOCK_LENGTH];\n\tu_int\t\tkey_len;\n} HMAC_SHA256_CTX;\n\n//__BEGIN_DECLS\n\nvoid\t HMAC_MD5_Init(HMAC_MD5_CTX *, const u_int8_t *, u_int)\n\t\t__attribute__((__bounded__(__string__,2,3)));\nvoid\t HMAC_MD5_Update(HMAC_MD5_CTX *, const u_int8_t *, u_int)\n\t\t__attribute__((__bounded__(__string__,2,3)));\nvoid\t HMAC_MD5_Final(u_int8_t [MD5_DIGEST_LENGTH], HMAC_MD5_CTX *)\n\t\t__attribute__((__bounded__(__minbytes__,1,MD5_DIGEST_LENGTH)));\n\nvoid\t HMAC_SHA1_Init(HMAC_SHA1_CTX *, const u_int8_t *, u_int)\n\t\t__attribute__((__bounded__(__string__,2,3)));\nvoid\t HMAC_SHA1_Update(HMAC_SHA1_CTX *, const u_int8_t *, u_int)\n\t\t__attribute__((__bounded__(__string__,2,3)));\nvoid\t HMAC_SHA1_Final(u_int8_t [SHA1_DIGEST_LENGTH], HMAC_SHA1_CTX *)\n\t\t__attribute__((__bounded__(__minbytes__,1,SHA1_DIGEST_LENGTH)));\n\nvoid\t HMAC_SHA256_Init(HMAC_SHA256_CTX *, const u_int8_t *, u_int)\n\t\t__attribute__((__bounded__(__string__,2,3)));\nvoid\t HMAC_SHA256_Update(HMAC_SHA256_CTX *, const u_int8_t *, u_int)\n\t\t__attribute__((__bounded__(__string__,2,3)));\nvoid\t HMAC_SHA256_Final(u_int8_t [SHA256_DIGEST_LENGTH], HMAC_SHA256_CTX *)\n\t\t__attribute__((__bounded__(__minbytes__,1,SHA256_DIGEST_LENGTH)));\n\n//__END_DECLS\n\n#endif\t/* _HMAC_H_ */\n"
  },
  {
    "path": "itl80211/openbsd/crypto/idgen.c",
    "content": "/*\n * Copyright (c) 2008 Damien Miller <djm@mindrot.org>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n/*\n * IDGEN32: non-repeating ID generation covering an almost maximal 32-bit\n * range.\n *\n * IDGEN32 is based on public domain SKIP32 by Greg Rose.\n */\n\n#include <sys/types.h>\n#include <sys/systm.h>\n#include <sys/time.h>\n#include <sys/_arc4random.h>\n\n#include <crypto/idgen.h>\n\n#define time_second 20\n\nstatic const u_int8_t idgen32_ftable[256] = { \n\t0xa3, 0xd7, 0x09, 0x83, 0xf8, 0x48, 0xf6, 0xf4,\n\t0xb3, 0x21, 0x15, 0x78, 0x99, 0xb1, 0xaf, 0xf9,\n\t0xe7, 0x2d, 0x4d, 0x8a, 0xce, 0x4c, 0xca, 0x2e,\n\t0x52, 0x95, 0xd9, 0x1e, 0x4e, 0x38, 0x44, 0x28,\n\t0x0a, 0xdf, 0x02, 0xa0, 0x17, 0xf1, 0x60, 0x68,\n\t0x12, 0xb7, 0x7a, 0xc3, 0xe9, 0xfa, 0x3d, 0x53,\n\t0x96, 0x84, 0x6b, 0xba, 0xf2, 0x63, 0x9a, 0x19,\n\t0x7c, 0xae, 0xe5, 0xf5, 0xf7, 0x16, 0x6a, 0xa2,\n\t0x39, 0xb6, 0x7b, 0x0f, 0xc1, 0x93, 0x81, 0x1b,\n\t0xee, 0xb4, 0x1a, 0xea, 0xd0, 0x91, 0x2f, 0xb8,\n\t0x55, 0xb9, 0xda, 0x85, 0x3f, 0x41, 0xbf, 0xe0,\n\t0x5a, 0x58, 0x80, 0x5f, 0x66, 0x0b, 0xd8, 0x90,\n\t0x35, 0xd5, 0xc0, 0xa7, 0x33, 0x06, 0x65, 0x69,\n\t0x45, 0x00, 0x94, 0x56, 0x6d, 0x98, 0x9b, 0x76,\n\t0x97, 0xfc, 0xb2, 0xc2, 0xb0, 0xfe, 0xdb, 0x20,\n\t0xe1, 0xeb, 0xd6, 0xe4, 0xdd, 0x47, 0x4a, 0x1d,\n\t0x42, 0xed, 0x9e, 0x6e, 0x49, 0x3c, 0xcd, 0x43,\n\t0x27, 0xd2, 0x07, 0xd4, 0xde, 0xc7, 0x67, 0x18,\n\t0x89, 0xcb, 0x30, 0x1f, 0x8d, 0xc6, 0x8f, 0xaa,\n\t0xc8, 0x74, 0xdc, 0xc9, 0x5d, 0x5c, 0x31, 0xa4,\n\t0x70, 0x88, 0x61, 0x2c, 0x9f, 0x0d, 0x2b, 0x87,\n\t0x50, 0x82, 0x54, 0x64, 0x26, 0x7d, 0x03, 0x40,\n\t0x34, 0x4b, 0x1c, 0x73, 0xd1, 0xc4, 0xfd, 0x3b,\n\t0xcc, 0xfb, 0x7f, 0xab, 0xe6, 0x3e, 0x5b, 0xa5,\n\t0xad, 0x04, 0x23, 0x9c, 0x14, 0x51, 0x22, 0xf0,\n\t0x29, 0x79, 0x71, 0x7e, 0xff, 0x8c, 0x0e, 0xe2,\n\t0x0c, 0xef, 0xbc, 0x72, 0x75, 0x6f, 0x37, 0xa1,\n\t0xec, 0xd3, 0x8e, 0x62, 0x8b, 0x86, 0x10, 0xe8,\n\t0x08, 0x77, 0x11, 0xbe, 0x92, 0x4f, 0x24, 0xc5,\n\t0x32, 0x36, 0x9d, 0xcf, 0xf3, 0xa6, 0xbb, 0xac,\n\t0x5e, 0x6c, 0xa9, 0x13, 0x57, 0x25, 0xb5, 0xe3,\n\t0xbd, 0xa8, 0x3a, 0x01, 0x05, 0x59, 0x2a, 0x46\n};\n\nstatic u_int16_t\nidgen32_g(u_int8_t *key, int k, u_int16_t w)\n{\n\tu_int8_t g1, g2, g3, g4, g5, g6;\n\tu_int o = k * 4;\n\n\tg1 = (w >> 8) & 0xff;\n\tg2 = w & 0xff;\n\n\tg3 = idgen32_ftable[g2 ^ key[o++ & (IDGEN32_KEYLEN - 1)]] ^ g1;\n\tg4 = idgen32_ftable[g3 ^ key[o++ & (IDGEN32_KEYLEN - 1)]] ^ g2;\n\tg5 = idgen32_ftable[g4 ^ key[o++ & (IDGEN32_KEYLEN - 1)]] ^ g3;\n\tg6 = idgen32_ftable[g5 ^ key[o++ & (IDGEN32_KEYLEN - 1)]] ^ g4;\n\n\treturn (g5 << 8) | g6;\n}\n\nstatic u_int32_t\nidgen32_permute(struct idgen32_ctx *ctx, u_int32_t in)\n{\n\tu_int i, r;\n\tu_int16_t wl, wr;\n\n\twl = (in >> 16) & 0x7fff;\n\twr = in & 0xffff;\n\n\t/* Doubled up rounds, with an odd round at the end to swap */\n\tfor (i = r = 0; i < IDGEN32_ROUNDS / 2; ++i) {\n\t\twr ^= (idgen32_g(ctx->id32_key, r, wl) ^ r);\n\t\tr++;\n\t\twl ^= (idgen32_g(ctx->id32_key, r, wr) ^ r) & 0x7fff;\n\t\tr++;\n\t}\n\twr ^= (idgen32_g(ctx->id32_key, r, wl) ^ r);\n\n\treturn (wl << 16) | wr;\n}\n\nstatic void\nidgen32_rekey(struct idgen32_ctx *ctx)\n{\n\tctx->id32_counter = 0;\n\tctx->id32_hibit ^= 0x80000000;\n\tctx->id32_offset = arc4random();\n\tarc4random_buf(ctx->id32_key, sizeof(ctx->id32_key));\n\tctx->id32_rekey_time = time_second + IDGEN32_REKEY_TIME;\n}\n\nvoid\nidgen32_init(struct idgen32_ctx *ctx)\n{\n\tbzero(ctx, sizeof(*ctx));\n\tctx->id32_hibit = arc4random() & 0x80000000;\n\tidgen32_rekey(ctx);\n}\n\nu_int32_t\nidgen32(struct idgen32_ctx *ctx)\n{\n\tu_int32_t ret;\n\n\tdo {\n\t\t/* Rekey a little early to avoid \"card counting\" attack */\n\t\tif (ctx->id32_counter > IDGEN32_REKEY_LIMIT ||\n\t\t    ctx->id32_rekey_time < time_second)\n\t\t\tidgen32_rekey(ctx);\n\t\tret = ctx->id32_hibit | idgen32_permute(ctx,\n\t\t    (ctx->id32_offset + ctx->id32_counter++) & 0x7fffffff);\n\t} while (ret == 0); /* Zero IDs are often special, so avoid */\n\n\treturn ret;\n}\n\n"
  },
  {
    "path": "itl80211/openbsd/crypto/idgen.h",
    "content": "/*\t$OpenBSD: idgen.h,v 1.3 2013/06/05 05:45:54 djm Exp $\t*/\n/*\n * Copyright (c) 2008 Damien Miller <djm@mindrot.org>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n#define IDGEN32_ROUNDS\t\t31\n#define IDGEN32_KEYLEN\t\t32\n#define IDGEN32_REKEY_LIMIT\t0x60000000\n#define IDGEN32_REKEY_TIME\t600\n\nstruct idgen32_ctx {\n\tu_int32_t id32_counter;\n\tu_int32_t id32_offset;\n\tu_int32_t id32_hibit;\n\tu_int8_t id32_key[IDGEN32_KEYLEN];\n\ttime_t id32_rekey_time;\n};\n\nvoid idgen32_init(struct idgen32_ctx *);\nu_int32_t idgen32(struct idgen32_ctx *);\n\n"
  },
  {
    "path": "itl80211/openbsd/crypto/key_wrap.c",
    "content": "/*\t$OpenBSD: key_wrap.c,v 1.5 2017/05/02 17:07:06 mikeb Exp $\t*/\n\n/*-\n * Copyright (c) 2008 Damien Bergamini <damien.bergamini@free.fr>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n/*\n * This code implements the AES Key Wrap algorithm described in RFC 3394.\n */\n\n#include <sys/param.h>\n#include <sys/systm.h>\n#include <sys/endian.h>\n\n#include <crypto/aes.h>\n#include <crypto/key_wrap.h>\n\nstatic const u_int8_t IV[8] =\n\t{ 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6 };\n\nvoid\naes_key_wrap_set_key(aes_key_wrap_ctx *ctx, const u_int8_t *K, size_t K_len)\n{\n\tAES_Setkey(&ctx->ctx, K, K_len);\n}\n\nvoid\naes_key_wrap_set_key_wrap_only(aes_key_wrap_ctx *ctx, const u_int8_t *K,\n    size_t K_len)\n{\n\tAES_Setkey(&ctx->ctx, K, K_len);\n}\n\nvoid\naes_key_wrap(aes_key_wrap_ctx *ctx, const u_int8_t *P, size_t n, u_int8_t *C)\n{\n\tu_int64_t B[2], t;\n\tu_int8_t *A, *R;\n\tsize_t i;\n\tint j;\n\n\tmemmove(C + 8, P, n * 8);\t/* P and C may overlap */\n\tA = C;\t\t\t\t/* A points to C[0] */\n\tmemcpy(A, IV, 8);\t\t/* A = IV, an initial value */\n\n\tfor (j = 0, t = 1; j <= 5; j++) {\n\t\tR = C + 8;\n\t\tfor (i = 1; i <= n; i++, t++) {\n\t\t\t/* B = A | R[i] */\n\t\t\tmemcpy(&B[0], A, 8);\n\t\t\tmemcpy(&B[1], R, 8);\n\t\t\t/* B = AES(K, B) */\n\t\t\tAES_Encrypt(&ctx->ctx, (const uint8_t *)(caddr_t)B, (uint8_t *)(caddr_t)B);\n\t\t\t/* MSB(64, B) = MSB(64, B) ^ t */\n\t\t\tB[0] ^= htobe64(t);\n\t\t\t/* A = MSB(64, B) */\n\t\t\tmemcpy(A, &B[0], 8);\n\t\t\t/* R[i] = LSB(64, B) */\n\t\t\tmemcpy(R, &B[1], 8);\n\n\t\t\tR += 8;\n\t\t}\n\t}\n\tmemset(B, 0, sizeof B);\n}\n\nint\naes_key_unwrap(aes_key_wrap_ctx *ctx, const u_int8_t *C, u_int8_t *P, size_t n)\n{\n\tu_int64_t B[2], t;\n\tu_int8_t A[8], *R;\n\tsize_t i;\n\tint j;\n\n\tmemcpy(A, C, 8);\t\t/* A = C[0] */\n\tmemmove(P, C + 8, n * 8);\t/* P and C may overlap */\n\n\tfor (j = 5, t = 6 * n; j >= 0; j--) {\n\t\tR = P + (n - 1) * 8;\n\t\tfor (i = n; i >= 1; i--, t--) {\n\t\t\t/* MSB(64, B) = A */\n\t\t\tmemcpy(&B[0], A, 8);\n\t\t\t/* MSB(64, B) = MSB(64, B) ^ t */\n\t\t\tB[0] ^= htobe64(t);\n\t\t\t/* B = MSB(64, B) | R[i] */\n\t\t\tmemcpy(&B[1], R, 8);\n\t\t\t/* B = AES-1(K, B) */\n\t\t\tAES_Decrypt(&ctx->ctx, (const uint8_t *)(caddr_t)B, (uint8_t *)(caddr_t)B);\n\t\t\t/* A = MSB(64, B) */\n\t\t\tmemcpy(A, &B[0], 8);\n\t\t\t/* R[i] = LSB(64, B) */\n\t\t\tmemcpy(R, &B[1], 8);\n\n\t\t\tR -= 8;\n\t\t}\n\t}\n\tmemset(B, 0, sizeof B);\n\n\t/* check that A is an appropriate initial value */\n\treturn timingsafe_bcmp(A, IV, 8) != 0;\n}\n"
  },
  {
    "path": "itl80211/openbsd/crypto/key_wrap.h",
    "content": "/*\t$OpenBSD: key_wrap.h,v 1.3 2017/05/02 17:07:06 mikeb Exp $\t*/\n\n/*-\n * Copyright (c) 2008 Damien Bergamini <damien.bergamini@free.fr>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n#ifndef _KEY_WRAP_H_\n#define _KEY_WRAP_H_\n\nextern int timingsafe_bcmp(const void *b1, const void *b2, size_t n);\n\ntypedef struct _aes_key_wrap_ctx {\n\tAES_CTX\t\tctx;\n} aes_key_wrap_ctx;\n\n//__BEGIN_DECLS\n\nvoid\taes_key_wrap_set_key(aes_key_wrap_ctx *, const u_int8_t *, size_t);\nvoid\taes_key_wrap_set_key_wrap_only(aes_key_wrap_ctx *, const u_int8_t *,\n\t    size_t);\nvoid\taes_key_wrap(aes_key_wrap_ctx *, const u_int8_t *, size_t, u_int8_t *);\nint\taes_key_unwrap(aes_key_wrap_ctx *, const u_int8_t *, u_int8_t *,\n\t    size_t);\n//__END_DECLS\n\n#endif /* _KEY_WRAP_H_ */\n"
  },
  {
    "path": "itl80211/openbsd/crypto/md5.c",
    "content": "/*\t$OpenBSD: md5.c,v 1.4 2014/12/28 10:04:35 tedu Exp $\t*/\n\n/*\n * This code implements the MD5 message-digest algorithm.\n * The algorithm is due to Ron Rivest.\tThis code was\n * written by Colin Plumb in 1993, no copyright is claimed.\n * This code is in the public domain; do with it what you wish.\n *\n * Equivalent code is available from RSA Data Security, Inc.\n * This code has been tested against that, and is equivalent,\n * except that you don't need to include two pages of legalese\n * with every copy.\n *\n * To compute the message digest of a chunk of bytes, declare an\n * MD5Context structure, pass it to MD5Init, call MD5Update as\n * needed on buffers full of bytes, and then call MD5Final, which\n * will fill a supplied 16-byte array with the digest.\n */\n\n#include <sys/param.h>\n#include <sys/systm.h>\n#include <crypto/md5.h>\n\n#define PUT_64BIT_LE(cp, value) do {\t\t\t\t\t\\\n\t(cp)[7] = (value) >> 56;\t\t\t\t\t\\\n\t(cp)[6] = (value) >> 48;\t\t\t\t\t\\\n\t(cp)[5] = (value) >> 40;\t\t\t\t\t\\\n\t(cp)[4] = (value) >> 32;\t\t\t\t\t\\\n\t(cp)[3] = (value) >> 24;\t\t\t\t\t\\\n\t(cp)[2] = (value) >> 16;\t\t\t\t\t\\\n\t(cp)[1] = (value) >> 8;\t\t\t\t\t\t\\\n\t(cp)[0] = (value); } while (0)\n\n#define PUT_32BIT_LE(cp, value) do {\t\t\t\t\t\\\n\t(cp)[3] = (value) >> 24;\t\t\t\t\t\\\n\t(cp)[2] = (value) >> 16;\t\t\t\t\t\\\n\t(cp)[1] = (value) >> 8;\t\t\t\t\t\t\\\n\t(cp)[0] = (value); } while (0)\n\nstatic u_int8_t PADDING[MD5_BLOCK_LENGTH] = {\n\t0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\n};\n\n/*\n * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious\n * initialization constants.\n */\nvoid\nMD5Init(MD5_CTX *ctx)\n{\n\tctx->count = 0;\n\tctx->state[0] = 0x67452301;\n\tctx->state[1] = 0xefcdab89;\n\tctx->state[2] = 0x98badcfe;\n\tctx->state[3] = 0x10325476;\n}\n\n/*\n * Update context to reflect the concatenation of another buffer full\n * of bytes.\n */\nvoid\nMD5Update(MD5_CTX *ctx, const void *inputptr, size_t len)\n{\n\tconst uint8_t *input = (const uint8_t *)inputptr;\n\tsize_t have, need;\n\n\t/* Check how many bytes we already have and how many more we need. */\n\thave = (size_t)((ctx->count >> 3) & (MD5_BLOCK_LENGTH - 1));\n\tneed = MD5_BLOCK_LENGTH - have;\n\n\t/* Update bitcount */\n\tctx->count += (u_int64_t)len << 3;\n\n\tif (len >= need) {\n\t\tif (have != 0) {\n\t\t\tmemcpy(ctx->buffer + have, input, need);\n\t\t\tMD5Transform(ctx->state, ctx->buffer);\n\t\t\tinput += need;\n\t\t\tlen -= need;\n\t\t\thave = 0;\n\t\t}\n\n\t\t/* Process data in MD5_BLOCK_LENGTH-byte chunks. */\n\t\twhile (len >= MD5_BLOCK_LENGTH) {\n\t\t\tMD5Transform(ctx->state, input);\n\t\t\tinput += MD5_BLOCK_LENGTH;\n\t\t\tlen -= MD5_BLOCK_LENGTH;\n\t\t}\n\t}\n\n\t/* Handle any remaining bytes of data. */\n\tif (len != 0)\n\t\tmemcpy(ctx->buffer + have, input, len);\n}\n\n/*\n * Final wrapup - pad to 64-byte boundary with the bit pattern\n * 1 0* (64-bit count of bits processed, MSB-first)\n */\nvoid\nMD5Final(unsigned char digest[MD5_DIGEST_LENGTH], MD5_CTX *ctx)\n{\n\tu_int8_t count[8];\n\tsize_t padlen;\n\tint i;\n\n\t/* Convert count to 8 bytes in little endian order. */\n\tPUT_64BIT_LE(count, ctx->count);\n\n\t/* Pad out to 56 mod 64. */\n\tpadlen = MD5_BLOCK_LENGTH -\n\t    ((ctx->count >> 3) & (MD5_BLOCK_LENGTH - 1));\n\tif (padlen < 1 + 8)\n\t\tpadlen += MD5_BLOCK_LENGTH;\n\tMD5Update(ctx, PADDING, padlen - 8);\t\t/* padlen - 8 <= 64 */\n\tMD5Update(ctx, count, 8);\n\n\tfor (i = 0; i < 4; i++)\n\t\tPUT_32BIT_LE(digest + i * 4, ctx->state[i]);\n\tmemset(ctx, 0, sizeof(*ctx));\t/* in case it's sensitive */\n}\n\n\n/* The four core functions - F1 is optimized somewhat */\n\n/* #define F1(x, y, z) (x & y | ~x & z) */\n#define F1(x, y, z) (z ^ (x & (y ^ z)))\n#define F2(x, y, z) F1(z, x, y)\n#define F3(x, y, z) (x ^ y ^ z)\n#define F4(x, y, z) (y ^ (x | ~z))\n\n/* This is the central step in the MD5 algorithm. */\n#define MD5STEP(f, w, x, y, z, data, s) \\\n\t( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )\n\n/*\n * The core of the MD5 algorithm, this alters an existing MD5 hash to\n * reflect the addition of 16 longwords of new data.  MD5Update blocks\n * the data and converts bytes into longwords for this routine.\n */\nvoid\nMD5Transform(u_int32_t state[4], const u_int8_t block[MD5_BLOCK_LENGTH])\n{\n\tu_int32_t a, b, c, d, in[MD5_BLOCK_LENGTH / 4];\n\n#if BYTE_ORDER == LITTLE_ENDIAN\n\tmemcpy(in, block, sizeof(in));\n#else\n\tfor (a = 0; a < MD5_BLOCK_LENGTH / 4; a++) {\n\t\tin[a] = (u_int32_t)(\n\t\t    (u_int32_t)(block[a * 4 + 0]) |\n\t\t    (u_int32_t)(block[a * 4 + 1]) <<  8 |\n\t\t    (u_int32_t)(block[a * 4 + 2]) << 16 |\n\t\t    (u_int32_t)(block[a * 4 + 3]) << 24);\n\t}\n#endif\n\n\ta = state[0];\n\tb = state[1];\n\tc = state[2];\n\td = state[3];\n\n\tMD5STEP(F1, a, b, c, d, in[ 0] + 0xd76aa478,  7);\n\tMD5STEP(F1, d, a, b, c, in[ 1] + 0xe8c7b756, 12);\n\tMD5STEP(F1, c, d, a, b, in[ 2] + 0x242070db, 17);\n\tMD5STEP(F1, b, c, d, a, in[ 3] + 0xc1bdceee, 22);\n\tMD5STEP(F1, a, b, c, d, in[ 4] + 0xf57c0faf,  7);\n\tMD5STEP(F1, d, a, b, c, in[ 5] + 0x4787c62a, 12);\n\tMD5STEP(F1, c, d, a, b, in[ 6] + 0xa8304613, 17);\n\tMD5STEP(F1, b, c, d, a, in[ 7] + 0xfd469501, 22);\n\tMD5STEP(F1, a, b, c, d, in[ 8] + 0x698098d8,  7);\n\tMD5STEP(F1, d, a, b, c, in[ 9] + 0x8b44f7af, 12);\n\tMD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);\n\tMD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);\n\tMD5STEP(F1, a, b, c, d, in[12] + 0x6b901122,  7);\n\tMD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);\n\tMD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);\n\tMD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);\n\n\tMD5STEP(F2, a, b, c, d, in[ 1] + 0xf61e2562,  5);\n\tMD5STEP(F2, d, a, b, c, in[ 6] + 0xc040b340,  9);\n\tMD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);\n\tMD5STEP(F2, b, c, d, a, in[ 0] + 0xe9b6c7aa, 20);\n\tMD5STEP(F2, a, b, c, d, in[ 5] + 0xd62f105d,  5);\n\tMD5STEP(F2, d, a, b, c, in[10] + 0x02441453,  9);\n\tMD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);\n\tMD5STEP(F2, b, c, d, a, in[ 4] + 0xe7d3fbc8, 20);\n\tMD5STEP(F2, a, b, c, d, in[ 9] + 0x21e1cde6,  5);\n\tMD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6,  9);\n\tMD5STEP(F2, c, d, a, b, in[ 3] + 0xf4d50d87, 14);\n\tMD5STEP(F2, b, c, d, a, in[ 8] + 0x455a14ed, 20);\n\tMD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905,  5);\n\tMD5STEP(F2, d, a, b, c, in[ 2] + 0xfcefa3f8,  9);\n\tMD5STEP(F2, c, d, a, b, in[ 7] + 0x676f02d9, 14);\n\tMD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);\n\n\tMD5STEP(F3, a, b, c, d, in[ 5] + 0xfffa3942,  4);\n\tMD5STEP(F3, d, a, b, c, in[ 8] + 0x8771f681, 11);\n\tMD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);\n\tMD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);\n\tMD5STEP(F3, a, b, c, d, in[ 1] + 0xa4beea44,  4);\n\tMD5STEP(F3, d, a, b, c, in[ 4] + 0x4bdecfa9, 11);\n\tMD5STEP(F3, c, d, a, b, in[ 7] + 0xf6bb4b60, 16);\n\tMD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);\n\tMD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6,  4);\n\tMD5STEP(F3, d, a, b, c, in[ 0] + 0xeaa127fa, 11);\n\tMD5STEP(F3, c, d, a, b, in[ 3] + 0xd4ef3085, 16);\n\tMD5STEP(F3, b, c, d, a, in[ 6] + 0x04881d05, 23);\n\tMD5STEP(F3, a, b, c, d, in[ 9] + 0xd9d4d039,  4);\n\tMD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);\n\tMD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);\n\tMD5STEP(F3, b, c, d, a, in[2 ] + 0xc4ac5665, 23);\n\n\tMD5STEP(F4, a, b, c, d, in[ 0] + 0xf4292244,  6);\n\tMD5STEP(F4, d, a, b, c, in[7 ] + 0x432aff97, 10);\n\tMD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);\n\tMD5STEP(F4, b, c, d, a, in[5 ] + 0xfc93a039, 21);\n\tMD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3,  6);\n\tMD5STEP(F4, d, a, b, c, in[3 ] + 0x8f0ccc92, 10);\n\tMD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);\n\tMD5STEP(F4, b, c, d, a, in[1 ] + 0x85845dd1, 21);\n\tMD5STEP(F4, a, b, c, d, in[8 ] + 0x6fa87e4f,  6);\n\tMD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);\n\tMD5STEP(F4, c, d, a, b, in[6 ] + 0xa3014314, 15);\n\tMD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);\n\tMD5STEP(F4, a, b, c, d, in[4 ] + 0xf7537e82,  6);\n\tMD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);\n\tMD5STEP(F4, c, d, a, b, in[2 ] + 0x2ad7d2bb, 15);\n\tMD5STEP(F4, b, c, d, a, in[9 ] + 0xeb86d391, 21);\n\n\tstate[0] += a;\n\tstate[1] += b;\n\tstate[2] += c;\n\tstate[3] += d;\n}\n"
  },
  {
    "path": "itl80211/openbsd/crypto/md5.h",
    "content": "/*\t$OpenBSD: md5.h,v 1.3 2014/11/16 17:39:09 tedu Exp $\t*/\n\n/*\n * This code implements the MD5 message-digest algorithm.\n * The algorithm is due to Ron Rivest.  This code was\n * written by Colin Plumb in 1993, no copyright is claimed.\n * This code is in the public domain; do with it what you wish.\n *\n * Equivalent code is available from RSA Data Security, Inc.\n * This code has been tested against that, and is equivalent,\n * except that you don't need to include two pages of legalese\n * with every copy.\n */\n\n#ifndef _MD5_H_\n#define _MD5_H_\n\n#define\tMD5_BLOCK_LENGTH\t\t64\n#define\tMD5_DIGEST_LENGTH\t\t16\n\ntypedef struct MD5Context {\n\tu_int32_t state[4];\t\t\t/* state */\n\tu_int64_t count;\t\t\t/* number of bits, mod 2^64 */\n\tu_int8_t buffer[MD5_BLOCK_LENGTH];\t/* input buffer */\n} MD5_CTX;\n\n//__BEGIN_DECLS\nvoid\t MD5Init(MD5_CTX *);\nvoid\t MD5Update(MD5_CTX *, const void *, size_t)\n\t\t__attribute__((__bounded__(__string__,2,3)));\nvoid\t MD5Final(u_int8_t [MD5_DIGEST_LENGTH], MD5_CTX *)\n\t\t__attribute__((__bounded__(__minbytes__,1,MD5_DIGEST_LENGTH)));\nvoid\t MD5Transform(u_int32_t [4], const u_int8_t [MD5_BLOCK_LENGTH])\n\t\t__attribute__((__bounded__(__minbytes__,1,4)))\n\t\t__attribute__((__bounded__(__minbytes__,2,MD5_BLOCK_LENGTH)));\n//__END_DECLS\n\n#endif /* _MD5_H_ */\n"
  },
  {
    "path": "itl80211/openbsd/crypto/michael.c",
    "content": "/*\t$OpenBSD: michael.c,v 1.2 2008/07/21 19:52:45 damien Exp $\t*/\n\n/*\n * Copyright (c) 2005, 2006 Reyk Floeter <reyk@openbsd.org>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n/*\n * Implementation of the Michael MIC as defined in IEEE 802.11i for TKIP.\n * The MIC generates a 64bit digest, which shouldn't be used for any other\n * applications except TKIP.\n */\n\n#include <sys/param.h>\n#include <sys/systm.h>\n\n#include <crypto/michael.h>\n\n#define ROL(n, x)\t(((x) << (n)) | ((x) >> (32 - (n))))\n#define ROR(n, x)\t(((x) >> (n)) | ((x) << (32 - (n))))\n#define XSWAP(x)\t(((x) & 0xff00ff00UL) >> 8 | ((x) & 0x00ff00ffUL) << 8)\n\n#if defined(__STRICT_ALIGNMENT) || _BYTE_ORDER != _LITTLE_ENDIAN\n#define GETLE32(x)\t((x)[0] | (x)[1] << 8 | (x)[2] << 16 | (x)[3] << 24)\n#define PUTLE32(x, v)\t((x)[0] = (u_int8_t)(v),\t\t\t\\\n\t\t\t (x)[1] = (u_int8_t)((v) >> 8),\t\t\t\\\n\t\t\t (x)[2] = (u_int8_t)((v) >> 16),\t\t\\\n\t\t\t (x)[3] = (u_int8_t)((v) >> 24))\n#else\n#define GETLE32(x)\t(*((u_int32_t *)(x)))\n#define PUTLE32(x, v)\t(*((u_int32_t *)(x)) = (v))\n#endif\n\n#define MICHAEL_BLOCK(l, r) do {\t\t\t\t\t\\\n\tr ^= ROL(17, l);\t\t\t\t\t\t\\\n\tl += r;\t\t\t\t\t\t\t\t\\\n\tr ^= XSWAP(l);\t\t\t\t\t\t\t\\\n\tl += r;\t\t\t\t\t\t\t\t\\\n\tr ^= ROL(3, l);\t\t\t\t\t\t\t\\\n\tl += r;\t\t\t\t\t\t\t\t\\\n\tr ^= ROR(2, l);\t\t\t\t\t\t\t\\\n\tl += r;\t\t\t\t\t\t\t\t\\\n} while (0)\n\nvoid\nmichael_init(MICHAEL_CTX *ctx)\n{\n\tbzero(ctx, sizeof(MICHAEL_CTX));\n}\n\nvoid\nmichael_update(MICHAEL_CTX *ctx, const u_int8_t *data, u_int len)\n{\n\tint i;\n\n\tfor (i = 0; i < len; i++) {\n\t\tctx->michael_state |= data[i] << (ctx->michael_count << 3);\n\t\tctx->michael_count++;\n\n\t\tif (ctx->michael_count >= MICHAEL_RAW_BLOCK_LENGTH) {\n\t\t\tctx->michael_l ^= ctx->michael_state;\n\t\t\tMICHAEL_BLOCK(ctx->michael_l, ctx->michael_r);\n\t\t\tctx->michael_state = ctx->michael_count = 0;\n\t\t}\n\t}\n}\n\nvoid\nmichael_final(u_int8_t digest[MICHAEL_DIGEST_LENGTH], MICHAEL_CTX *ctx)\n{\n\tstatic const u_int8_t pad[] =\n\t    { 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };\n\n\tmichael_update(ctx, pad, sizeof(pad));\n\n\tPUTLE32(digest, ctx->michael_l);\n\tPUTLE32(digest + MICHAEL_RAW_BLOCK_LENGTH, ctx->michael_r);\n}\n\nvoid\nmichael_key(const u_int8_t *key, MICHAEL_CTX *ctx)\n{\n\tctx->michael_l = ctx->michael_key[0] =\n\t    GETLE32(key);\n\tctx->michael_r = ctx->michael_key[1] =\n\t    GETLE32(key + MICHAEL_RAW_BLOCK_LENGTH);\n}\n"
  },
  {
    "path": "itl80211/openbsd/crypto/michael.h",
    "content": "/*\t$OpenBSD: michael.h,v 1.2 2012/12/05 23:20:15 deraadt Exp $\t*/\n\n/*\n * Copyright (c) 2005, 2006 Reyk Floeter <reyk@openbsd.org>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n#ifndef _MICHAEL_H_\n#define _MICHAEL_H_\n\n#define\tMICHAEL_BLOCK_LENGTH\t\t8\n#define MICHAEL_RAW_BLOCK_LENGTH\t4\n#define\tMICHAEL_DIGEST_LENGTH\t\t8\n\ntypedef struct michael_context {\n\tu_int32_t\tmichael_key[2];\n\tu_int32_t\tmichael_l, michael_r;\n\tu_int32_t\tmichael_state;\n\tu_int\t\tmichael_count;\n} MICHAEL_CTX;\n\n//__BEGIN_DECLS\nvoid\t michael_init(MICHAEL_CTX *);\nvoid\t michael_update(MICHAEL_CTX *, const u_int8_t *, u_int)\n\t    __attribute__((__bounded__(__buffer__, 2, 3)));\nvoid\t michael_final(u_int8_t [MICHAEL_DIGEST_LENGTH], MICHAEL_CTX *)\n\t    __attribute__((__bounded__(__minbytes__, 1,\n\t    MICHAEL_DIGEST_LENGTH)));\nvoid\t michael_key(const u_int8_t *, MICHAEL_CTX *)\n\t    __attribute__((__bounded__(__minbytes__, 1,\n\t    MICHAEL_BLOCK_LENGTH)));\n//__END_DECLS\n\n#endif /* _MICHAEL_H_ */\n"
  },
  {
    "path": "itl80211/openbsd/crypto/podd.h",
    "content": "/*\t$OpenBSD: podd.h,v 1.1 2000/02/28 23:13:05 deraadt Exp $\t*/\n\n/* lib/des/podd.h */\n/* Copyright (C) 1995 Eric Young (eay@mincom.oz.au)\n * All rights reserved.\n * \n * This file is part of an SSL implementation written\n * by Eric Young (eay@mincom.oz.au).\n * The implementation was written so as to conform with Netscapes SSL\n * specification.  This library and applications are\n * FREE FOR COMMERCIAL AND NON-COMMERCIAL USE\n * as long as the following conditions are aheared to.\n * \n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.  If this code is used in a product,\n * Eric Young should be given attribution as the author of the parts used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    This product includes software developed by Eric Young (eay@mincom.oz.au)\n * \n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n * \n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n\nstatic const unsigned char odd_parity[256]={\n  1,  1,  2,  2,  4,  4,  7,  7,  8,  8, 11, 11, 13, 13, 14, 14,\n 16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28, 31, 31,\n 32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44, 44, 47, 47,\n 49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59, 61, 61, 62, 62,\n 64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74, 74, 76, 76, 79, 79,\n 81, 81, 82, 82, 84, 84, 87, 87, 88, 88, 91, 91, 93, 93, 94, 94,\n 97, 97, 98, 98,100,100,103,103,104,104,107,107,109,109,110,110,\n112,112,115,115,117,117,118,118,121,121,122,122,124,124,127,127,\n128,128,131,131,133,133,134,134,137,137,138,138,140,140,143,143,\n145,145,146,146,148,148,151,151,152,152,155,155,157,157,158,158,\n161,161,162,162,164,164,167,167,168,168,171,171,173,173,174,174,\n176,176,179,179,181,181,182,182,185,185,186,186,188,188,191,191,\n193,193,194,194,196,196,199,199,200,200,203,203,205,205,206,206,\n208,208,211,211,213,213,214,214,217,217,218,218,220,220,223,223,\n224,224,227,227,229,229,230,230,233,233,234,234,236,236,239,239,\n241,241,242,242,244,244,247,247,248,248,251,251,253,253,254,254};\n"
  },
  {
    "path": "itl80211/openbsd/crypto/poly1305.c",
    "content": "/*\n * Public Domain poly1305 from Andrew Moon\n * Based on poly1305-donna.c, poly1305-donna-32.h and poly1305-donna.h from:\n *   https://github.com/floodyberry/poly1305-donna\n */\n\n#include <sys/types.h>\n#include <sys/systm.h>\n\n#include \"poly1305.h\"\n\n/*\n * poly1305 implementation using 32 bit * 32 bit = 64 bit multiplication\n * and 64 bit addition.\n */\n\n/* interpret four 8 bit unsigned integers as a 32 bit unsigned integer in little endian */\nstatic unsigned long\nU8TO32(const unsigned char *p)\n{\n\treturn (((unsigned long)(p[0] & 0xff)) |\n\t    ((unsigned long)(p[1] & 0xff) <<  8) |\n\t    ((unsigned long)(p[2] & 0xff) << 16) |\n\t    ((unsigned long)(p[3] & 0xff) << 24));\n}\n\n/* store a 32 bit unsigned integer as four 8 bit unsigned integers in little endian */\nstatic void\nU32TO8(unsigned char *p, unsigned long v)\n{\n\tp[0] = (v) & 0xff;\n\tp[1] = (v >>  8) & 0xff;\n\tp[2] = (v >> 16) & 0xff;\n\tp[3] = (v >> 24) & 0xff;\n}\n\nvoid\npoly1305_init(poly1305_state *st, const unsigned char key[32])\n{\n\t/* r &= 0xffffffc0ffffffc0ffffffc0fffffff */\n\tst->r[0] = (U8TO32(&key[0])) & 0x3ffffff;\n\tst->r[1] = (U8TO32(&key[3]) >> 2) & 0x3ffff03;\n\tst->r[2] = (U8TO32(&key[6]) >> 4) & 0x3ffc0ff;\n\tst->r[3] = (U8TO32(&key[9]) >> 6) & 0x3f03fff;\n\tst->r[4] = (U8TO32(&key[12]) >> 8) & 0x00fffff;\n\n\t/* h = 0 */\n\tst->h[0] = 0;\n\tst->h[1] = 0;\n\tst->h[2] = 0;\n\tst->h[3] = 0;\n\tst->h[4] = 0;\n\n\t/* save pad for later */\n\tst->pad[0] = U8TO32(&key[16]);\n\tst->pad[1] = U8TO32(&key[20]);\n\tst->pad[2] = U8TO32(&key[24]);\n\tst->pad[3] = U8TO32(&key[28]);\n\n\tst->leftover = 0;\n\tst->final = 0;\n}\n\nstatic void\npoly1305_blocks(poly1305_state *st, const unsigned char *m, size_t bytes)\n{\n\tconst unsigned long hibit = (st->final) ? 0 : (1 << 24); /* 1 << 128 */\n\tunsigned long r0, r1, r2, r3, r4;\n\tunsigned long s1, s2, s3, s4;\n\tunsigned long h0, h1, h2, h3, h4;\n\tunsigned long long d0, d1, d2, d3, d4;\n\tunsigned long c;\n\n\tr0 = st->r[0];\n\tr1 = st->r[1];\n\tr2 = st->r[2];\n\tr3 = st->r[3];\n\tr4 = st->r[4];\n\n\ts1 = r1 * 5;\n\ts2 = r2 * 5;\n\ts3 = r3 * 5;\n\ts4 = r4 * 5;\n\n\th0 = st->h[0];\n\th1 = st->h[1];\n\th2 = st->h[2];\n\th3 = st->h[3];\n\th4 = st->h[4];\n\n\twhile (bytes >= poly1305_block_size) {\n\t\t/* h += m[i] */\n\t\th0 += (U8TO32(m + 0)) & 0x3ffffff;\n\t\th1 += (U8TO32(m + 3) >> 2) & 0x3ffffff;\n\t\th2 += (U8TO32(m + 6) >> 4) & 0x3ffffff;\n\t\th3 += (U8TO32(m + 9) >> 6) & 0x3ffffff;\n\t\th4 += (U8TO32(m + 12) >> 8) | hibit;\n\n\t\t/* h *= r */\n\t\td0 = ((unsigned long long)h0 * r0) +\n\t\t    ((unsigned long long)h1 * s4) +\n\t\t    ((unsigned long long)h2 * s3) +\n\t\t    ((unsigned long long)h3 * s2) +\n\t\t    ((unsigned long long)h4 * s1);\n\t\td1 = ((unsigned long long)h0 * r1) +\n\t\t    ((unsigned long long)h1 * r0) +\n\t\t    ((unsigned long long)h2 * s4) +\n\t\t    ((unsigned long long)h3 * s3) +\n\t\t    ((unsigned long long)h4 * s2);\n\t\td2 = ((unsigned long long)h0 * r2) +\n\t\t    ((unsigned long long)h1 * r1) +\n\t\t    ((unsigned long long)h2 * r0) +\n\t\t    ((unsigned long long)h3 * s4) +\n\t\t    ((unsigned long long)h4 * s3);\n\t\td3 = ((unsigned long long)h0 * r3) +\n\t\t    ((unsigned long long)h1 * r2) +\n\t\t    ((unsigned long long)h2 * r1) +\n\t\t    ((unsigned long long)h3 * r0) +\n\t\t    ((unsigned long long)h4 * s4);\n\t\td4 = ((unsigned long long)h0 * r4) +\n\t\t    ((unsigned long long)h1 * r3) +\n\t\t    ((unsigned long long)h2 * r2) +\n\t\t    ((unsigned long long)h3 * r1) +\n\t\t    ((unsigned long long)h4 * r0);\n\n\t\t/* (partial) h %= p */\n\t\tc = (unsigned long)(d0 >> 26);\n\t\th0 = (unsigned long)d0 & 0x3ffffff;\n\t\td1 += c;\n\t\tc = (unsigned long)(d1 >> 26);\n\t\th1 = (unsigned long)d1 & 0x3ffffff;\n\t\td2 += c;\n\t\tc = (unsigned long)(d2 >> 26);\n\t\th2 = (unsigned long)d2 & 0x3ffffff;\n\t\td3 += c;\n\t\tc = (unsigned long)(d3 >> 26);\n\t\th3 = (unsigned long)d3 & 0x3ffffff;\n\t\td4 += c;\n\t\tc = (unsigned long)(d4 >> 26);\n\t\th4 = (unsigned long)d4 & 0x3ffffff;\n\t\th0 += c * 5;\n\t\tc = (h0 >> 26);\n\t\th0 = h0 & 0x3ffffff;\n\t\th1 += c;\n\n\t\tm += poly1305_block_size;\n\t\tbytes -= poly1305_block_size;\n\t}\n\n\tst->h[0] = h0;\n\tst->h[1] = h1;\n\tst->h[2] = h2;\n\tst->h[3] = h3;\n\tst->h[4] = h4;\n}\n\nvoid\npoly1305_update(poly1305_state *st, const unsigned char *m, size_t bytes)\n{\n\tsize_t i;\n\n\t/* handle leftover */\n\tif (st->leftover) {\n\t\tsize_t want = (poly1305_block_size - st->leftover);\n\t\tif (want > bytes)\n\t\t\twant = bytes;\n\t\tfor (i = 0; i < want; i++)\n\t\t\tst->buffer[st->leftover + i] = m[i];\n\t\tbytes -= want;\n\t\tm += want;\n\t\tst->leftover += want;\n\t\tif (st->leftover < poly1305_block_size)\n\t\t\treturn;\n\t\tpoly1305_blocks(st, st->buffer, poly1305_block_size);\n\t\tst->leftover = 0;\n\t}\n\n\t/* process full blocks */\n\tif (bytes >= poly1305_block_size) {\n\t\tsize_t want = (bytes & ~(poly1305_block_size - 1));\n\t\tpoly1305_blocks(st, m, want);\n\t\tm += want;\n\t\tbytes -= want;\n\t}\n\n\t/* store leftover */\n\tif (bytes) {\n\t\tfor (i = 0; i < bytes; i++)\n\t\t\tst->buffer[st->leftover + i] = m[i];\n\t\tst->leftover += bytes;\n\t}\n}\n\nvoid\npoly1305_finish(poly1305_state *st, unsigned char mac[16])\n{\n\tunsigned long h0, h1, h2, h3, h4, c;\n\tunsigned long g0, g1, g2, g3, g4;\n\tunsigned long long f;\n\tunsigned long mask;\n\n\t/* process the remaining block */\n\tif (st->leftover) {\n\t\tsize_t i = st->leftover;\n\t\tst->buffer[i++] = 1;\n\t\tfor (; i < poly1305_block_size; i++)\n\t\t\tst->buffer[i] = 0;\n\t\tst->final = 1;\n\t\tpoly1305_blocks(st, st->buffer, poly1305_block_size);\n\t}\n\n\t/* fully carry h */\n\th0 = st->h[0];\n\th1 = st->h[1];\n\th2 = st->h[2];\n\th3 = st->h[3];\n\th4 = st->h[4];\n\n\tc = h1 >> 26;\n\th1 = h1 & 0x3ffffff;\n\th2 += c;\n\tc = h2 >> 26;\n\th2 = h2 & 0x3ffffff;\n\th3 += c;\n\tc = h3 >> 26;\n\th3 = h3 & 0x3ffffff;\n\th4 += c;\n\tc = h4 >> 26;\n\th4 = h4 & 0x3ffffff;\n\th0 += c * 5;\n\tc = h0 >> 26;\n\th0 = h0 & 0x3ffffff;\n\th1 += c;\n\n\t/* compute h + -p */\n\tg0 = h0 + 5;\n\tc = g0 >> 26;\n\tg0 &= 0x3ffffff;\n\tg1 = h1 + c;\n\tc = g1 >> 26;\n\tg1 &= 0x3ffffff;\n\tg2 = h2 + c;\n\tc = g2 >> 26;\n\tg2 &= 0x3ffffff;\n\tg3 = h3 + c;\n\tc = g3 >> 26;\n\tg3 &= 0x3ffffff;\n\tg4 = h4 + c - (1 << 26);\n\n\t/* select h if h < p, or h + -p if h >= p */\n\tmask = (g4 >> ((sizeof(unsigned long) * 8) - 1)) - 1;\n\tg0 &= mask;\n\tg1 &= mask;\n\tg2 &= mask;\n\tg3 &= mask;\n\tg4 &= mask;\n\tmask = ~mask;\n\th0 = (h0 & mask) | g0;\n\th1 = (h1 & mask) | g1;\n\th2 = (h2 & mask) | g2;\n\th3 = (h3 & mask) | g3;\n\th4 = (h4 & mask) | g4;\n\n\t/* h = h % (2^128) */\n\th0 = ((h0) | (h1 << 26)) & 0xffffffff;\n\th1 = ((h1 >>  6) | (h2 << 20)) & 0xffffffff;\n\th2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffff;\n\th3 = ((h3 >> 18) | (h4 <<  8)) & 0xffffffff;\n\n\t/* mac = (h + pad) % (2^128) */\n\tf = (unsigned long long)h0 + st->pad[0];\n\th0 = (unsigned long)f;\n\tf = (unsigned long long)h1 + st->pad[1] + (f >> 32);\n\th1 = (unsigned long)f;\n\tf = (unsigned long long)h2 + st->pad[2] + (f >> 32);\n\th2 = (unsigned long)f;\n\tf = (unsigned long long)h3 + st->pad[3] + (f >> 32);\n\th3 = (unsigned long)f;\n\n\tU32TO8(mac +  0, h0);\n\tU32TO8(mac +  4, h1);\n\tU32TO8(mac +  8, h2);\n\tU32TO8(mac + 12, h3);\n\n\t/* zero out the state */\n\tst->h[0] = 0;\n\tst->h[1] = 0;\n\tst->h[2] = 0;\n\tst->h[3] = 0;\n\tst->h[4] = 0;\n\tst->r[0] = 0;\n\tst->r[1] = 0;\n\tst->r[2] = 0;\n\tst->r[3] = 0;\n\tst->r[4] = 0;\n\tst->pad[0] = 0;\n\tst->pad[1] = 0;\n\tst->pad[2] = 0;\n\tst->pad[3] = 0;\n}\n"
  },
  {
    "path": "itl80211/openbsd/crypto/poly1305.h",
    "content": "/*\n * Public Domain poly1305 from Andrew Moon\n *\n * poly1305 implementation using 32 bit * 32 bit = 64 bit multiplication\n * and 64 bit addition from https://github.com/floodyberry/poly1305-donna\n */\n\n#ifndef _POLY1305_H_\n#define _POLY1305_H_\n\n#define poly1305_block_size 16\n\ntypedef struct poly1305_state {\n\tunsigned long r[5];\n\tunsigned long h[5];\n\tunsigned long pad[4];\n\tsize_t leftover;\n\tunsigned char buffer[poly1305_block_size];\n\tunsigned char final;\n} poly1305_state;\n\nvoid\tpoly1305_init(poly1305_state *, const unsigned char[32]);\nvoid\tpoly1305_update(poly1305_state *, const unsigned char *, size_t);\nvoid\tpoly1305_finish(poly1305_state *, unsigned char[16]);\n\n#endif\t/* _POLY1305_H_ */\n"
  },
  {
    "path": "itl80211/openbsd/crypto/rijndael.c",
    "content": "/*\t$OpenBSD: rijndael.c,v 1.20 2014/11/17 12:27:47 mikeb Exp $ */\n\n/**\n * rijndael-alg-fst.c\n *\n * @version 3.0 (December 2000)\n *\n * Optimised ANSI C code for the Rijndael cipher (now AES)\n *\n * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>\n * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>\n * @author Paulo Barreto <paulo.barreto@terra.com.br>\n *\n * This code is hereby placed in the public domain.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS\n * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR\n * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE\n * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\n * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <sys/param.h>\n#include <sys/systm.h>\n\n#include <crypto/rijndael.h>\n\n#undef FULL_UNROLL\n\n/*\nTe0[x] = S [x].[02, 01, 01, 03];\nTe1[x] = S [x].[03, 02, 01, 01];\nTe2[x] = S [x].[01, 03, 02, 01];\nTe3[x] = S [x].[01, 01, 03, 02];\n\nTd0[x] = Si[x].[0e, 09, 0d, 0b];\nTd1[x] = Si[x].[0b, 0e, 09, 0d];\nTd2[x] = Si[x].[0d, 0b, 0e, 09];\nTd3[x] = Si[x].[09, 0d, 0b, 0e];\nTd4[x] = Si[x].[01];\n*/\n\nstatic const u32 Te0[256] = {\n    0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU,\n    0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U,\n    0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU,\n    0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU,\n    0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U,\n    0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU,\n    0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU,\n    0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU,\n    0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU,\n    0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU,\n    0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U,\n    0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU,\n    0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU,\n    0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U,\n    0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU,\n    0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU,\n    0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU,\n    0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU,\n    0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU,\n    0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U,\n    0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU,\n    0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU,\n    0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU,\n    0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU,\n    0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U,\n    0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U,\n    0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U,\n    0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U,\n    0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU,\n    0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U,\n    0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U,\n    0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU,\n    0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU,\n    0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U,\n    0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U,\n    0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U,\n    0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU,\n    0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U,\n    0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU,\n    0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U,\n    0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU,\n    0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U,\n    0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U,\n    0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU,\n    0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U,\n    0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U,\n    0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U,\n    0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U,\n    0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U,\n    0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U,\n    0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U,\n    0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U,\n    0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU,\n    0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U,\n    0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U,\n    0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U,\n    0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U,\n    0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U,\n    0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U,\n    0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU,\n    0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U,\n    0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U,\n    0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U,\n    0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU,\n};\nstatic const u32 Te1[256] = {\n    0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU,\n    0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U,\n    0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU,\n    0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U,\n    0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU,\n    0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U,\n    0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU,\n    0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U,\n    0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U,\n    0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU,\n    0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U,\n    0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U,\n    0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U,\n    0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU,\n    0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U,\n    0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U,\n    0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU,\n    0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U,\n    0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U,\n    0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U,\n    0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU,\n    0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU,\n    0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U,\n    0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU,\n    0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU,\n    0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U,\n    0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU,\n    0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U,\n    0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU,\n    0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U,\n    0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U,\n    0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U,\n    0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU,\n    0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U,\n    0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU,\n    0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U,\n    0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU,\n    0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U,\n    0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U,\n    0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU,\n    0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU,\n    0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU,\n    0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U,\n    0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U,\n    0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU,\n    0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U,\n    0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU,\n    0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U,\n    0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU,\n    0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U,\n    0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU,\n    0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU,\n    0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U,\n    0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU,\n    0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U,\n    0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU,\n    0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U,\n    0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U,\n    0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U,\n    0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU,\n    0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU,\n    0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U,\n    0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU,\n    0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U,\n};\nstatic const u32 Te2[256] = {\n    0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU,\n    0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U,\n    0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU,\n    0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U,\n    0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU,\n    0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U,\n    0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU,\n    0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U,\n    0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U,\n    0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU,\n    0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U,\n    0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U,\n    0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U,\n    0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU,\n    0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U,\n    0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U,\n    0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU,\n    0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U,\n    0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U,\n    0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U,\n    0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU,\n    0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU,\n    0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U,\n    0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU,\n    0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU,\n    0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U,\n    0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU,\n    0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U,\n    0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU,\n    0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U,\n    0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U,\n    0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U,\n    0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU,\n    0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U,\n    0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU,\n    0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U,\n    0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU,\n    0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U,\n    0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U,\n    0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU,\n    0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU,\n    0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU,\n    0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U,\n    0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U,\n    0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU,\n    0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U,\n    0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU,\n    0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U,\n    0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU,\n    0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U,\n    0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU,\n    0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU,\n    0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U,\n    0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU,\n    0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U,\n    0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU,\n    0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U,\n    0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U,\n    0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U,\n    0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU,\n    0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU,\n    0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U,\n    0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU,\n    0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U,\n};\nstatic const u32 Te3[256] = {\n    0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U,\n    0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U,\n    0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U,\n    0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU,\n    0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU,\n    0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU,\n    0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U,\n    0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU,\n    0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU,\n    0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U,\n    0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U,\n    0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU,\n    0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU,\n    0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU,\n    0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU,\n    0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU,\n    0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U,\n    0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU,\n    0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU,\n    0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U,\n    0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U,\n    0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U,\n    0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U,\n    0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U,\n    0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU,\n    0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U,\n    0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU,\n    0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU,\n    0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U,\n    0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U,\n    0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U,\n    0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU,\n    0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U,\n    0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU,\n    0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU,\n    0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U,\n    0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U,\n    0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU,\n    0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U,\n    0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU,\n    0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U,\n    0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U,\n    0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U,\n    0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U,\n    0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU,\n    0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U,\n    0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU,\n    0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U,\n    0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU,\n    0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U,\n    0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU,\n    0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU,\n    0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU,\n    0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU,\n    0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U,\n    0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U,\n    0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U,\n    0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U,\n    0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U,\n    0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U,\n    0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU,\n    0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U,\n    0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU,\n    0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU,\n};\nstatic const u32 Td0[256] = {\n    0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U,\n    0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U,\n    0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U,\n    0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU,\n    0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U,\n    0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U,\n    0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU,\n    0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U,\n    0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU,\n    0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U,\n    0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U,\n    0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U,\n    0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U,\n    0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU,\n    0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U,\n    0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU,\n    0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U,\n    0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU,\n    0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U,\n    0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U,\n    0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U,\n    0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU,\n    0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U,\n    0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU,\n    0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U,\n    0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU,\n    0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U,\n    0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU,\n    0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU,\n    0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U,\n    0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU,\n    0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U,\n    0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU,\n    0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U,\n    0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U,\n    0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U,\n    0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU,\n    0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U,\n    0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U,\n    0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU,\n    0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U,\n    0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U,\n    0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U,\n    0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U,\n    0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U,\n    0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU,\n    0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U,\n    0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U,\n    0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U,\n    0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U,\n    0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U,\n    0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU,\n    0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU,\n    0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU,\n    0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU,\n    0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U,\n    0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U,\n    0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU,\n    0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU,\n    0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U,\n    0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU,\n    0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U,\n    0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U,\n    0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U,\n};\nstatic const u32 Td1[256] = {\n    0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU,\n    0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U,\n    0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU,\n    0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U,\n    0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U,\n    0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U,\n    0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U,\n    0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U,\n    0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U,\n    0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU,\n    0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU,\n    0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU,\n    0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U,\n    0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU,\n    0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U,\n    0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U,\n    0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U,\n    0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU,\n    0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU,\n    0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U,\n    0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU,\n    0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U,\n    0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU,\n    0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU,\n    0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U,\n    0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U,\n    0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U,\n    0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU,\n    0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U,\n    0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU,\n    0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U,\n    0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U,\n    0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U,\n    0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU,\n    0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U,\n    0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U,\n    0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U,\n    0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U,\n    0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U,\n    0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U,\n    0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU,\n    0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU,\n    0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U,\n    0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU,\n    0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U,\n    0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU,\n    0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU,\n    0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U,\n    0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU,\n    0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U,\n    0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U,\n    0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U,\n    0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U,\n    0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U,\n    0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U,\n    0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U,\n    0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU,\n    0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U,\n    0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U,\n    0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU,\n    0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U,\n    0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U,\n    0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U,\n    0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U,\n};\nstatic const u32 Td2[256] = {\n    0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U,\n    0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U,\n    0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U,\n    0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U,\n    0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU,\n    0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U,\n    0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U,\n    0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U,\n    0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U,\n    0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU,\n    0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U,\n    0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U,\n    0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU,\n    0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U,\n    0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U,\n    0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U,\n    0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U,\n    0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U,\n    0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U,\n    0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU,\n    0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U,\n    0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U,\n    0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U,\n    0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U,\n    0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U,\n    0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU,\n    0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU,\n    0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U,\n    0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU,\n    0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U,\n    0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU,\n    0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU,\n    0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU,\n    0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU,\n    0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U,\n    0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U,\n    0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U,\n    0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U,\n    0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U,\n    0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U,\n    0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U,\n    0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU,\n    0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU,\n    0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U,\n    0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U,\n    0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU,\n    0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU,\n    0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U,\n    0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U,\n    0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U,\n    0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U,\n    0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U,\n    0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U,\n    0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U,\n    0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU,\n    0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U,\n    0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U,\n    0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U,\n    0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U,\n    0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U,\n    0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U,\n    0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU,\n    0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U,\n    0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U,\n};\nstatic const u32 Td3[256] = {\n    0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU,\n    0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU,\n    0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U,\n    0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U,\n    0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU,\n    0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU,\n    0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U,\n    0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU,\n    0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U,\n    0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU,\n    0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U,\n    0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U,\n    0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U,\n    0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U,\n    0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U,\n    0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU,\n    0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU,\n    0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U,\n    0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U,\n    0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU,\n    0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU,\n    0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U,\n    0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U,\n    0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U,\n    0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U,\n    0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU,\n    0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U,\n    0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U,\n    0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU,\n    0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU,\n    0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U,\n    0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U,\n    0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U,\n    0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU,\n    0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U,\n    0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U,\n    0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U,\n    0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U,\n    0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U,\n    0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U,\n    0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U,\n    0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU,\n    0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U,\n    0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U,\n    0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU,\n    0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU,\n    0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U,\n    0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU,\n    0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U,\n    0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U,\n    0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U,\n    0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U,\n    0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U,\n    0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U,\n    0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU,\n    0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU,\n    0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU,\n    0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU,\n    0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U,\n    0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U,\n    0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U,\n    0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU,\n    0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U,\n    0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U,\n};\nstatic const u8 Td4[256] = {\n    0x52U, 0x09U, 0x6aU, 0xd5U, 0x30U, 0x36U, 0xa5U, 0x38U,\n    0xbfU, 0x40U, 0xa3U, 0x9eU, 0x81U, 0xf3U, 0xd7U, 0xfbU,\n    0x7cU, 0xe3U, 0x39U, 0x82U, 0x9bU, 0x2fU, 0xffU, 0x87U,\n    0x34U, 0x8eU, 0x43U, 0x44U, 0xc4U, 0xdeU, 0xe9U, 0xcbU,\n    0x54U, 0x7bU, 0x94U, 0x32U, 0xa6U, 0xc2U, 0x23U, 0x3dU,\n    0xeeU, 0x4cU, 0x95U, 0x0bU, 0x42U, 0xfaU, 0xc3U, 0x4eU,\n    0x08U, 0x2eU, 0xa1U, 0x66U, 0x28U, 0xd9U, 0x24U, 0xb2U,\n    0x76U, 0x5bU, 0xa2U, 0x49U, 0x6dU, 0x8bU, 0xd1U, 0x25U,\n    0x72U, 0xf8U, 0xf6U, 0x64U, 0x86U, 0x68U, 0x98U, 0x16U,\n    0xd4U, 0xa4U, 0x5cU, 0xccU, 0x5dU, 0x65U, 0xb6U, 0x92U,\n    0x6cU, 0x70U, 0x48U, 0x50U, 0xfdU, 0xedU, 0xb9U, 0xdaU,\n    0x5eU, 0x15U, 0x46U, 0x57U, 0xa7U, 0x8dU, 0x9dU, 0x84U,\n    0x90U, 0xd8U, 0xabU, 0x00U, 0x8cU, 0xbcU, 0xd3U, 0x0aU,\n    0xf7U, 0xe4U, 0x58U, 0x05U, 0xb8U, 0xb3U, 0x45U, 0x06U,\n    0xd0U, 0x2cU, 0x1eU, 0x8fU, 0xcaU, 0x3fU, 0x0fU, 0x02U,\n    0xc1U, 0xafU, 0xbdU, 0x03U, 0x01U, 0x13U, 0x8aU, 0x6bU,\n    0x3aU, 0x91U, 0x11U, 0x41U, 0x4fU, 0x67U, 0xdcU, 0xeaU,\n    0x97U, 0xf2U, 0xcfU, 0xceU, 0xf0U, 0xb4U, 0xe6U, 0x73U,\n    0x96U, 0xacU, 0x74U, 0x22U, 0xe7U, 0xadU, 0x35U, 0x85U,\n    0xe2U, 0xf9U, 0x37U, 0xe8U, 0x1cU, 0x75U, 0xdfU, 0x6eU,\n    0x47U, 0xf1U, 0x1aU, 0x71U, 0x1dU, 0x29U, 0xc5U, 0x89U,\n    0x6fU, 0xb7U, 0x62U, 0x0eU, 0xaaU, 0x18U, 0xbeU, 0x1bU,\n    0xfcU, 0x56U, 0x3eU, 0x4bU, 0xc6U, 0xd2U, 0x79U, 0x20U,\n    0x9aU, 0xdbU, 0xc0U, 0xfeU, 0x78U, 0xcdU, 0x5aU, 0xf4U,\n    0x1fU, 0xddU, 0xa8U, 0x33U, 0x88U, 0x07U, 0xc7U, 0x31U,\n    0xb1U, 0x12U, 0x10U, 0x59U, 0x27U, 0x80U, 0xecU, 0x5fU,\n    0x60U, 0x51U, 0x7fU, 0xa9U, 0x19U, 0xb5U, 0x4aU, 0x0dU,\n    0x2dU, 0xe5U, 0x7aU, 0x9fU, 0x93U, 0xc9U, 0x9cU, 0xefU,\n    0xa0U, 0xe0U, 0x3bU, 0x4dU, 0xaeU, 0x2aU, 0xf5U, 0xb0U,\n    0xc8U, 0xebU, 0xbbU, 0x3cU, 0x83U, 0x53U, 0x99U, 0x61U,\n    0x17U, 0x2bU, 0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U,\n    0xe1U, 0x69U, 0x14U, 0x63U, 0x55U, 0x21U, 0x0cU, 0x7dU,\n};\nstatic const u32 rcon[] = {\n\t0x01000000, 0x02000000, 0x04000000, 0x08000000,\n\t0x10000000, 0x20000000, 0x40000000, 0x80000000,\n\t0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */\n};\n\n#define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] <<  8) ^ ((u32)(pt)[3]))\n#define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >>  8); (ct)[3] = (u8)(st); }\n\n/**\n * Expand the cipher key into the encryption key schedule.\n *\n * @return\tthe number of rounds for the given cipher key size.\n */\nint\nrijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits)\n{\n   \tint i = 0;\n\tu32 temp;\n\n\trk[0] = GETU32(cipherKey     );\n\trk[1] = GETU32(cipherKey +  4);\n\trk[2] = GETU32(cipherKey +  8);\n\trk[3] = GETU32(cipherKey + 12);\n\tif (keyBits == 128) {\n\t\tfor (;;) {\n\t\t\ttemp  = rk[3];\n\t\t\trk[4] = rk[0] ^\n\t\t\t\t(Te2[(temp >> 16) & 0xff] & 0xff000000) ^\n\t\t\t\t(Te3[(temp >>  8) & 0xff] & 0x00ff0000) ^\n\t\t\t\t(Te0[(temp      ) & 0xff] & 0x0000ff00) ^\n\t\t\t\t(Te1[(temp >> 24)       ] & 0x000000ff) ^\n\t\t\t\trcon[i];\n\t\t\trk[5] = rk[1] ^ rk[4];\n\t\t\trk[6] = rk[2] ^ rk[5];\n\t\t\trk[7] = rk[3] ^ rk[6];\n\t\t\tif (++i == 10) {\n\t\t\t\treturn 10;\n\t\t\t}\n\t\t\trk += 4;\n\t\t}\n\t}\n\trk[4] = GETU32(cipherKey + 16);\n\trk[5] = GETU32(cipherKey + 20);\n\tif (keyBits == 192) {\n\t\tfor (;;) {\n\t\t\ttemp = rk[ 5];\n\t\t\trk[ 6] = rk[ 0] ^\n\t\t\t\t(Te2[(temp >> 16) & 0xff] & 0xff000000) ^\n\t\t\t\t(Te3[(temp >>  8) & 0xff] & 0x00ff0000) ^\n\t\t\t\t(Te0[(temp      ) & 0xff] & 0x0000ff00) ^\n\t\t\t\t(Te1[(temp >> 24)       ] & 0x000000ff) ^\n\t\t\t\trcon[i];\n\t\t\trk[ 7] = rk[ 1] ^ rk[ 6];\n\t\t\trk[ 8] = rk[ 2] ^ rk[ 7];\n\t\t\trk[ 9] = rk[ 3] ^ rk[ 8];\n\t\t\tif (++i == 8) {\n\t\t\t\treturn 12;\n\t\t\t}\n\t\t\trk[10] = rk[ 4] ^ rk[ 9];\n\t\t\trk[11] = rk[ 5] ^ rk[10];\n\t\t\trk += 6;\n\t\t}\n\t}\n\trk[6] = GETU32(cipherKey + 24);\n\trk[7] = GETU32(cipherKey + 28);\n\tif (keyBits == 256) {\n\t\tfor (;;) {\n\t\t\ttemp = rk[ 7];\n\t\t\trk[ 8] = rk[ 0] ^\n\t\t\t\t(Te2[(temp >> 16) & 0xff] & 0xff000000) ^\n\t\t\t\t(Te3[(temp >>  8) & 0xff] & 0x00ff0000) ^\n\t\t\t\t(Te0[(temp      ) & 0xff] & 0x0000ff00) ^\n\t\t\t\t(Te1[(temp >> 24)       ] & 0x000000ff) ^\n\t\t\t\trcon[i];\n\t\t\trk[ 9] = rk[ 1] ^ rk[ 8];\n\t\t\trk[10] = rk[ 2] ^ rk[ 9];\n\t\t\trk[11] = rk[ 3] ^ rk[10];\n\t\t\tif (++i == 7) {\n\t\t\t\treturn 14;\n\t\t\t}\n\t\t\ttemp = rk[11];\n\t\t\trk[12] = rk[ 4] ^\n\t\t\t\t(Te2[(temp >> 24)       ] & 0xff000000) ^\n\t\t\t\t(Te3[(temp >> 16) & 0xff] & 0x00ff0000) ^\n\t\t\t\t(Te0[(temp >>  8) & 0xff] & 0x0000ff00) ^\n\t\t\t\t(Te1[(temp      ) & 0xff] & 0x000000ff);\n\t\t\trk[13] = rk[ 5] ^ rk[12];\n\t\t\trk[14] = rk[ 6] ^ rk[13];\n\t\t     \trk[15] = rk[ 7] ^ rk[14];\n\t\t\trk += 8;\n\t\t}\n\t}\n\treturn 0;\n}\n\n/**\n * Expand the cipher key into the decryption key schedule.\n *\n * @return\tthe number of rounds for the given cipher key size.\n */\nint\nrijndaelKeySetupDec(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits)\n{\n\tint Nr, i, j;\n\tu32 temp;\n\n\t/* expand the cipher key: */\n\tNr = rijndaelKeySetupEnc(rk, cipherKey, keyBits);\n\n\t/* invert the order of the round keys: */\n\tfor (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) {\n\t\ttemp = rk[i    ]; rk[i    ] = rk[j    ]; rk[j    ] = temp;\n\t\ttemp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp;\n\t\ttemp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp;\n\t\ttemp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp;\n\t}\n\t/* apply the inverse MixColumn transform to all round keys but the first and the last: */\n\tfor (i = 1; i < Nr; i++) {\n\t\trk += 4;\n\t\trk[0] =\n\t\t\tTd0[Te1[(rk[0] >> 24)       ] & 0xff] ^\n\t\t\tTd1[Te1[(rk[0] >> 16) & 0xff] & 0xff] ^\n\t\t\tTd2[Te1[(rk[0] >>  8) & 0xff] & 0xff] ^\n\t\t\tTd3[Te1[(rk[0]      ) & 0xff] & 0xff];\n\t\trk[1] =\n\t\t\tTd0[Te1[(rk[1] >> 24)       ] & 0xff] ^\n\t\t\tTd1[Te1[(rk[1] >> 16) & 0xff] & 0xff] ^\n\t\t\tTd2[Te1[(rk[1] >>  8) & 0xff] & 0xff] ^\n\t\t\tTd3[Te1[(rk[1]      ) & 0xff] & 0xff];\n\t\trk[2] =\n\t\t\tTd0[Te1[(rk[2] >> 24)       ] & 0xff] ^\n\t\t\tTd1[Te1[(rk[2] >> 16) & 0xff] & 0xff] ^\n\t\t\tTd2[Te1[(rk[2] >>  8) & 0xff] & 0xff] ^\n\t\t\tTd3[Te1[(rk[2]      ) & 0xff] & 0xff];\n\t\trk[3] =\n\t\t\tTd0[Te1[(rk[3] >> 24)       ] & 0xff] ^\n\t\t\tTd1[Te1[(rk[3] >> 16) & 0xff] & 0xff] ^\n\t\t\tTd2[Te1[(rk[3] >>  8) & 0xff] & 0xff] ^\n\t\t\tTd3[Te1[(rk[3]      ) & 0xff] & 0xff];\n\t}\n\treturn Nr;\n}\n\nvoid\nrijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16],\n    u8 ct[16])\n{\n\tu32 s0, s1, s2, s3, t0, t1, t2, t3;\n#ifndef FULL_UNROLL\n    int r;\n#endif /* ?FULL_UNROLL */\n\n    /*\n\t * map byte array block to cipher state\n\t * and add initial round key:\n\t */\n\ts0 = GETU32(pt     ) ^ rk[0];\n\ts1 = GETU32(pt +  4) ^ rk[1];\n\ts2 = GETU32(pt +  8) ^ rk[2];\n\ts3 = GETU32(pt + 12) ^ rk[3];\n#ifdef FULL_UNROLL\n    /* round 1: */\n   \tt0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4];\n   \tt1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5];\n   \tt2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6];\n   \tt3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7];\n   \t/* round 2: */\n   \ts0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8];\n   \ts1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9];\n   \ts2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10];\n   \ts3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11];\n    /* round 3: */\n   \tt0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12];\n   \tt1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13];\n   \tt2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14];\n   \tt3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15];\n   \t/* round 4: */\n   \ts0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16];\n   \ts1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17];\n   \ts2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18];\n   \ts3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19];\n    /* round 5: */\n   \tt0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20];\n   \tt1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21];\n   \tt2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22];\n   \tt3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23];\n   \t/* round 6: */\n   \ts0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24];\n   \ts1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25];\n   \ts2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26];\n   \ts3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27];\n    /* round 7: */\n   \tt0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28];\n   \tt1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29];\n   \tt2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30];\n   \tt3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31];\n   \t/* round 8: */\n   \ts0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32];\n   \ts1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33];\n   \ts2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34];\n   \ts3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35];\n    /* round 9: */\n   \tt0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36];\n   \tt1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37];\n   \tt2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38];\n   \tt3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39];\n    if (Nr > 10) {\n\t/* round 10: */\n\ts0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40];\n\ts1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[41];\n\ts2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[42];\n\ts3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[43];\n\t/* round 11: */\n\tt0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[44];\n\tt1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[45];\n\tt2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[46];\n\tt3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[47];\n\tif (Nr > 12) {\n\t    /* round 12: */\n\t    s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[48];\n\t    s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[49];\n\t    s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[50];\n\t    s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[51];\n\t    /* round 13: */\n\t    t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[52];\n\t    t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[53];\n\t    t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[54];\n\t    t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[55];\n\t}\n    }\n    rk += Nr << 2;\n#else  /* !FULL_UNROLL */\n    /*\n\t * Nr - 1 full rounds:\n\t */\n    r = Nr >> 1;\n    for (;;) {\n\tt0 =\n\t    Te0[(s0 >> 24)       ] ^\n\t    Te1[(s1 >> 16) & 0xff] ^\n\t    Te2[(s2 >>  8) & 0xff] ^\n\t    Te3[(s3      ) & 0xff] ^\n\t    rk[4];\n\tt1 =\n\t    Te0[(s1 >> 24)       ] ^\n\t    Te1[(s2 >> 16) & 0xff] ^\n\t    Te2[(s3 >>  8) & 0xff] ^\n\t    Te3[(s0      ) & 0xff] ^\n\t    rk[5];\n\tt2 =\n\t    Te0[(s2 >> 24)       ] ^\n\t    Te1[(s3 >> 16) & 0xff] ^\n\t    Te2[(s0 >>  8) & 0xff] ^\n\t    Te3[(s1      ) & 0xff] ^\n\t    rk[6];\n\tt3 =\n\t    Te0[(s3 >> 24)       ] ^\n\t    Te1[(s0 >> 16) & 0xff] ^\n\t    Te2[(s1 >>  8) & 0xff] ^\n\t    Te3[(s2      ) & 0xff] ^\n\t    rk[7];\n\n\trk += 8;\n\tif (--r == 0) {\n\t    break;\n\t}\n\n\ts0 =\n\t    Te0[(t0 >> 24)       ] ^\n\t    Te1[(t1 >> 16) & 0xff] ^\n\t    Te2[(t2 >>  8) & 0xff] ^\n\t    Te3[(t3      ) & 0xff] ^\n\t    rk[0];\n\ts1 =\n\t    Te0[(t1 >> 24)       ] ^\n\t    Te1[(t2 >> 16) & 0xff] ^\n\t    Te2[(t3 >>  8) & 0xff] ^\n\t    Te3[(t0      ) & 0xff] ^\n\t    rk[1];\n\ts2 =\n\t    Te0[(t2 >> 24)       ] ^\n\t    Te1[(t3 >> 16) & 0xff] ^\n\t    Te2[(t0 >>  8) & 0xff] ^\n\t    Te3[(t1      ) & 0xff] ^\n\t    rk[2];\n\ts3 =\n\t    Te0[(t3 >> 24)       ] ^\n\t    Te1[(t0 >> 16) & 0xff] ^\n\t    Te2[(t1 >>  8) & 0xff] ^\n\t    Te3[(t2      ) & 0xff] ^\n\t    rk[3];\n    }\n#endif /* ?FULL_UNROLL */\n    /*\n\t * apply last round and\n\t * map cipher state to byte array block:\n\t */\n\ts0 =\n\t\t(Te2[(t0 >> 24)       ] & 0xff000000) ^\n\t\t(Te3[(t1 >> 16) & 0xff] & 0x00ff0000) ^\n\t\t(Te0[(t2 >>  8) & 0xff] & 0x0000ff00) ^\n\t\t(Te1[(t3      ) & 0xff] & 0x000000ff) ^\n\t\trk[0];\n\tPUTU32(ct     , s0);\n\ts1 =\n\t\t(Te2[(t1 >> 24)       ] & 0xff000000) ^\n\t\t(Te3[(t2 >> 16) & 0xff] & 0x00ff0000) ^\n\t\t(Te0[(t3 >>  8) & 0xff] & 0x0000ff00) ^\n\t\t(Te1[(t0      ) & 0xff] & 0x000000ff) ^\n\t\trk[1];\n\tPUTU32(ct +  4, s1);\n\ts2 =\n\t\t(Te2[(t2 >> 24)       ] & 0xff000000) ^\n\t\t(Te3[(t3 >> 16) & 0xff] & 0x00ff0000) ^\n\t\t(Te0[(t0 >>  8) & 0xff] & 0x0000ff00) ^\n\t\t(Te1[(t1      ) & 0xff] & 0x000000ff) ^\n\t\trk[2];\n\tPUTU32(ct +  8, s2);\n\ts3 =\n\t\t(Te2[(t3 >> 24)       ] & 0xff000000) ^\n\t\t(Te3[(t0 >> 16) & 0xff] & 0x00ff0000) ^\n\t\t(Te0[(t1 >>  8) & 0xff] & 0x0000ff00) ^\n\t\t(Te1[(t2      ) & 0xff] & 0x000000ff) ^\n\t\trk[3];\n\tPUTU32(ct + 12, s3);\n}\n\nstatic void\nrijndaelDecrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16],\n    u8 pt[16])\n{\n\tu32 s0, s1, s2, s3, t0, t1, t2, t3;\n#ifndef FULL_UNROLL\n    int r;\n#endif /* ?FULL_UNROLL */\n\n    /*\n\t * map byte array block to cipher state\n\t * and add initial round key:\n\t */\n    s0 = GETU32(ct     ) ^ rk[0];\n    s1 = GETU32(ct +  4) ^ rk[1];\n    s2 = GETU32(ct +  8) ^ rk[2];\n    s3 = GETU32(ct + 12) ^ rk[3];\n#ifdef FULL_UNROLL\n    /* round 1: */\n    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[ 4];\n    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[ 5];\n    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[ 6];\n    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[ 7];\n    /* round 2: */\n    s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[ 8];\n    s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[ 9];\n    s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[10];\n    s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[11];\n    /* round 3: */\n    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[12];\n    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[13];\n    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[14];\n    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[15];\n    /* round 4: */\n    s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[16];\n    s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[17];\n    s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[18];\n    s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[19];\n    /* round 5: */\n    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[20];\n    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[21];\n    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[22];\n    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[23];\n    /* round 6: */\n    s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[24];\n    s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[25];\n    s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[26];\n    s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[27];\n    /* round 7: */\n    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[28];\n    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[29];\n    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[30];\n    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[31];\n    /* round 8: */\n    s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[32];\n    s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[33];\n    s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[34];\n    s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[35];\n    /* round 9: */\n    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[36];\n    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[37];\n    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[38];\n    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[39];\n    if (Nr > 10) {\n\t/* round 10: */\n\ts0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[40];\n\ts1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[41];\n\ts2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[42];\n\ts3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[43];\n\t/* round 11: */\n\tt0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[44];\n\tt1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[45];\n\tt2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[46];\n\tt3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[47];\n\tif (Nr > 12) {\n\t    /* round 12: */\n\t    s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[48];\n\t    s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[49];\n\t    s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[50];\n\t    s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[51];\n\t    /* round 13: */\n\t    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[52];\n\t    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[53];\n\t    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[54];\n\t    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[55];\n\t}\n    }\n\trk += Nr << 2;\n#else  /* !FULL_UNROLL */\n    /*\n     * Nr - 1 full rounds:\n     */\n    r = Nr >> 1;\n    for (;;) {\n\tt0 =\n\t    Td0[(s0 >> 24)       ] ^\n\t    Td1[(s3 >> 16) & 0xff] ^\n\t    Td2[(s2 >>  8) & 0xff] ^\n\t    Td3[(s1      ) & 0xff] ^\n\t    rk[4];\n\tt1 =\n\t    Td0[(s1 >> 24)       ] ^\n\t    Td1[(s0 >> 16) & 0xff] ^\n\t    Td2[(s3 >>  8) & 0xff] ^\n\t    Td3[(s2      ) & 0xff] ^\n\t    rk[5];\n\tt2 =\n\t    Td0[(s2 >> 24)       ] ^\n\t    Td1[(s1 >> 16) & 0xff] ^\n\t    Td2[(s0 >>  8) & 0xff] ^\n\t    Td3[(s3      ) & 0xff] ^\n\t    rk[6];\n\tt3 =\n\t    Td0[(s3 >> 24)       ] ^\n\t    Td1[(s2 >> 16) & 0xff] ^\n\t    Td2[(s1 >>  8) & 0xff] ^\n\t    Td3[(s0      ) & 0xff] ^\n\t    rk[7];\n\n\trk += 8;\n\tif (--r == 0) {\n\t    break;\n\t}\n\n\ts0 =\n\t    Td0[(t0 >> 24)       ] ^\n\t    Td1[(t3 >> 16) & 0xff] ^\n\t    Td2[(t2 >>  8) & 0xff] ^\n\t    Td3[(t1      ) & 0xff] ^\n\t    rk[0];\n\ts1 =\n\t    Td0[(t1 >> 24)       ] ^\n\t    Td1[(t0 >> 16) & 0xff] ^\n\t    Td2[(t3 >>  8) & 0xff] ^\n\t    Td3[(t2      ) & 0xff] ^\n\t    rk[1];\n\ts2 =\n\t    Td0[(t2 >> 24)       ] ^\n\t    Td1[(t1 >> 16) & 0xff] ^\n\t    Td2[(t0 >>  8) & 0xff] ^\n\t    Td3[(t3      ) & 0xff] ^\n\t    rk[2];\n\ts3 =\n\t    Td0[(t3 >> 24)       ] ^\n\t    Td1[(t2 >> 16) & 0xff] ^\n\t    Td2[(t1 >>  8) & 0xff] ^\n\t    Td3[(t0      ) & 0xff] ^\n\t    rk[3];\n    }\n#endif /* ?FULL_UNROLL */\n    /*\n\t * apply last round and\n\t * map cipher state to byte array block:\n\t */\n   \ts0 =\n   \t\t(Td4[(t0 >> 24)       ] << 24) ^\n   \t\t(Td4[(t3 >> 16) & 0xff] << 16) ^\n   \t\t(Td4[(t2 >>  8) & 0xff] <<  8) ^\n   \t\t(Td4[(t1      ) & 0xff])       ^\n   \t\trk[0];\n\tPUTU32(pt     , s0);\n   \ts1 =\n   \t\t(Td4[(t1 >> 24)       ] << 24) ^\n   \t\t(Td4[(t0 >> 16) & 0xff] << 16) ^\n   \t\t(Td4[(t3 >>  8) & 0xff] <<  8) ^\n   \t\t(Td4[(t2      ) & 0xff])       ^\n   \t\trk[1];\n\tPUTU32(pt +  4, s1);\n   \ts2 =\n   \t\t(Td4[(t2 >> 24)       ] << 24) ^\n   \t\t(Td4[(t1 >> 16) & 0xff] << 16) ^\n   \t\t(Td4[(t0 >>  8) & 0xff] <<  8) ^\n   \t\t(Td4[(t3      ) & 0xff])       ^\n   \t\trk[2];\n\tPUTU32(pt +  8, s2);\n   \ts3 =\n   \t\t(Td4[(t3 >> 24)       ] << 24) ^\n   \t\t(Td4[(t2 >> 16) & 0xff] << 16) ^\n   \t\t(Td4[(t1 >>  8) & 0xff] <<  8) ^\n   \t\t(Td4[(t0      ) & 0xff])       ^\n   \t\trk[3];\n\tPUTU32(pt + 12, s3);\n}\n\n/* setup key context for encryption only */\nint\nrijndael_set_key_enc_only(rijndael_ctx *ctx, const u_char *key, int bits)\n{\n\tint rounds;\n\n\trounds = rijndaelKeySetupEnc(ctx->ek, key, bits);\n\tif (rounds == 0)\n\t\treturn -1;\n\n\tctx->Nr = rounds;\n\tctx->enc_only = 1;\n\n\treturn 0;\n}\n\n/* setup key context for both encryption and decryption */\nint\nrijndael_set_key(rijndael_ctx *ctx, const u_char *key, int bits)\n{\n\tint rounds;\n\n\trounds = rijndaelKeySetupEnc(ctx->ek, key, bits);\n\tif (rounds == 0)\n\t\treturn -1;\n\tif (rijndaelKeySetupDec(ctx->dk, key, bits) != rounds)\n\t\treturn -1;\n\n\tctx->Nr = rounds;\n\tctx->enc_only = 0;\n\n\treturn 0;\n}\n\nvoid\nrijndael_decrypt(rijndael_ctx *ctx, const u_char *src, u_char *dst)\n{\n\trijndaelDecrypt(ctx->dk, ctx->Nr, src, dst);\n}\n\nvoid\nrijndael_encrypt(rijndael_ctx *ctx, const u_char *src, u_char *dst)\n{\n\trijndaelEncrypt(ctx->ek, ctx->Nr, src, dst);\n}\n"
  },
  {
    "path": "itl80211/openbsd/crypto/rijndael.h",
    "content": "/*\t$OpenBSD: rijndael.h,v 1.13 2008/06/09 07:49:45 djm Exp $ */\n\n/**\n * rijndael-alg-fst.h\n *\n * @version 3.0 (December 2000)\n *\n * Optimised ANSI C code for the Rijndael cipher (now AES)\n *\n * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>\n * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>\n * @author Paulo Barreto <paulo.barreto@terra.com.br>\n *\n * This code is hereby placed in the public domain.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS\n * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR\n * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE\n * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\n * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#ifndef __RIJNDAEL_H\n#define __RIJNDAEL_H\n\n#define AES_MAXKEYBITS\t(256)\n#define AES_MAXKEYBYTES\t(AES_MAXKEYBITS/8)\n/* for 256-bit keys, fewer for less */\n#define AES_MAXROUNDS\t14\n\ntypedef unsigned char\tu8;\ntypedef unsigned short\tu16;\ntypedef unsigned int\tu32;\n\n/*  The structure for key information */\ntypedef struct {\n\tint\tenc_only;\t\t/* context contains only encrypt schedule */\n\tint\tNr;\t\t\t/* key-length-dependent number of rounds */\n\tu32\tek[4*(AES_MAXROUNDS + 1)];\t/* encrypt key schedule */\n\tu32\tdk[4*(AES_MAXROUNDS + 1)];\t/* decrypt key schedule */\n} rijndael_ctx;\n\nint\t rijndael_set_key(rijndael_ctx *, const u_char *, int);\nint\t rijndael_set_key_enc_only(rijndael_ctx *, const u_char *, int);\nvoid\t rijndael_decrypt(rijndael_ctx *, const u_char *, u_char *);\nvoid\t rijndael_encrypt(rijndael_ctx *, const u_char *, u_char *);\n\nint\trijndaelKeySetupEnc(unsigned int [], const unsigned char [], int);\nint\trijndaelKeySetupDec(unsigned int [], const unsigned char [], int);\nvoid\trijndaelEncrypt(const unsigned int [], int, const unsigned char [],\n\t    unsigned char []);\n\n#endif /* __RIJNDAEL_H */\n"
  },
  {
    "path": "itl80211/openbsd/crypto/rmd160.c",
    "content": "/*\t$OpenBSD: rmd160.c,v 1.5 2011/01/11 15:42:05 deraadt Exp $\t*/\n/*\n * Copyright (c) 2001 Markus Friedl.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n/*\n * Preneel, Bosselaers, Dobbertin, \"The Cryptographic Hash Function RIPEMD-160\",\n * RSA Laboratories, CryptoBytes, Volume 3, Number 2, Autumn 1997,\n * ftp://ftp.rsasecurity.com/pub/cryptobytes/crypto3n2.pdf\n */\n#include <sys/param.h>\n#include <sys/systm.h>\n#include <sys/endian.h>\n#include <crypto/rmd160.h>\n\n#define PUT_64BIT_LE(cp, value) do { \\\n\t(cp)[7] = (value) >> 56; \\\n\t(cp)[6] = (value) >> 48; \\\n\t(cp)[5] = (value) >> 40; \\\n\t(cp)[4] = (value) >> 32; \\\n\t(cp)[3] = (value) >> 24; \\\n\t(cp)[2] = (value) >> 16; \\\n\t(cp)[1] = (value) >> 8; \\\n\t(cp)[0] = (value); } while (0)\n\n#define PUT_32BIT_LE(cp, value) do { \\\n\t(cp)[3] = (value) >> 24; \\\n\t(cp)[2] = (value) >> 16; \\\n\t(cp)[1] = (value) >> 8; \\\n\t(cp)[0] = (value); } while (0)\n\n#define\tH0\t0x67452301U\n#define\tH1\t0xEFCDAB89U\n#define\tH2\t0x98BADCFEU\n#define\tH3\t0x10325476U\n#define\tH4\t0xC3D2E1F0U\n\n#define\tK0\t0x00000000U\n#define\tK1\t0x5A827999U\n#define\tK2\t0x6ED9EBA1U\n#define\tK3\t0x8F1BBCDCU\n#define\tK4\t0xA953FD4EU\n\n#define\tKK0\t0x50A28BE6U\n#define\tKK1\t0x5C4DD124U\n#define\tKK2\t0x6D703EF3U\n#define\tKK3\t0x7A6D76E9U\n#define\tKK4\t0x00000000U\n\n/* rotate x left n bits.  */\n#define ROL(n, x) (((x) << (n)) | ((x) >> (32-(n))))\n\n#define F0(x, y, z) ((x) ^ (y) ^ (z))\n#define F1(x, y, z) (((x) & (y)) | ((~x) & (z)))\n#define F2(x, y, z) (((x) | (~y)) ^ (z))\n#define F3(x, y, z) (((x) & (z)) | ((y) & (~z)))\n#define F4(x, y, z) ((x) ^ ((y) | (~z)))\n\n#define R(a, b, c, d, e, Fj, Kj, sj, rj) \\\n\tdo { \\\n\t\ta = ROL(sj, a + Fj(b,c,d) + X(rj) + Kj) + e; \\\n\t\tc = ROL(10, c); \\\n\t} while(0)\n\n#define X(i)\tx[i]\n\nstatic u_char PADDING[64] = {\n\t0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\n};\n\nvoid\nRMD160Init(RMD160_CTX *ctx)\n{\n\tctx->count = 0;\n\tctx->state[0] = H0;\n\tctx->state[1] = H1;\n\tctx->state[2] = H2;\n\tctx->state[3] = H3;\n\tctx->state[4] = H4;\n}\n\nvoid\nRMD160Update(RMD160_CTX *ctx, const u_char *input, u_int32_t len)\n{\n\tu_int32_t have, off, need;\n\n\thave = (ctx->count/8) % 64;\n\tneed = 64 - have;\n\tctx->count += 8 * len;\n\toff = 0;\n\n\tif (len >= need) {\n\t\tif (have) {\n\t\t\tmemcpy(ctx->buffer + have, input, need);\n\t\t\tRMD160Transform(ctx->state, ctx->buffer);\n\t\t\toff = need;\n\t\t\thave = 0;\n\t\t}\n\t\t/* now the buffer is empty */\n\t\twhile (off + 64 <= len) {\n\t\t\tRMD160Transform(ctx->state, input+off);\n\t\t\toff += 64;\n\t\t}\n\t}\n\tif (off < len)\n\t\tmemcpy(ctx->buffer + have, input+off, len-off);\n}\n\nvoid\nRMD160Final(u_char digest[20], RMD160_CTX *ctx)\n{\n\tint i;\n\tu_char size[8];\n\tu_int32_t padlen;\n\n\tPUT_64BIT_LE(size, ctx->count);\n\n\t/*\n\t * pad to 64 byte blocks, at least one byte from PADDING plus 8 bytes\n\t * for the size\n\t */\n\tpadlen = 64 - ((ctx->count/8) % 64);\n\tif (padlen < 1 + 8)\n\t\tpadlen += 64;\n\tRMD160Update(ctx, PADDING, padlen - 8);\t\t/* padlen - 8 <= 64 */\n\tRMD160Update(ctx, size, 8);\n\n\tif (digest != NULL)\n\t\tfor (i = 0; i < 5; i++)\n\t\t\tPUT_32BIT_LE(digest + i*4, ctx->state[i]);\n\n\tmemset(ctx, 0, sizeof (*ctx));\n}\n\nvoid\nRMD160Transform(u_int32_t state[5], const u_char block[64])\n{\n\tu_int32_t a, b, c, d, e, aa, bb, cc, dd, ee, t, x[16];\n\n#if BYTE_ORDER == LITTLE_ENDIAN\n\tmemcpy(x, block, 64);\n#else\n\tint i;\n\n\tfor (i = 0; i < 16; i++)\n\t\tx[i] = (u_int32_t)(\n\t\t    (u_int32_t)(block[i*4 + 0]) |\n\t\t    (u_int32_t)(block[i*4 + 1]) <<  8 |\n\t\t    (u_int32_t)(block[i*4 + 2]) << 16 |\n\t\t    (u_int32_t)(block[i*4 + 3]) << 24);\n#endif\n\n\ta = state[0];\n\tb = state[1];\n\tc = state[2];\n\td = state[3];\n\te = state[4];\n\n\t/* Round 1 */\n\tR(a, b, c, d, e, F0, K0, 11,  0);\n\tR(e, a, b, c, d, F0, K0, 14,  1);\n\tR(d, e, a, b, c, F0, K0, 15,  2);\n\tR(c, d, e, a, b, F0, K0, 12,  3);\n\tR(b, c, d, e, a, F0, K0,  5,  4);\n\tR(a, b, c, d, e, F0, K0,  8,  5);\n\tR(e, a, b, c, d, F0, K0,  7,  6);\n\tR(d, e, a, b, c, F0, K0,  9,  7);\n\tR(c, d, e, a, b, F0, K0, 11,  8);\n\tR(b, c, d, e, a, F0, K0, 13,  9);\n\tR(a, b, c, d, e, F0, K0, 14, 10);\n\tR(e, a, b, c, d, F0, K0, 15, 11);\n\tR(d, e, a, b, c, F0, K0,  6, 12);\n\tR(c, d, e, a, b, F0, K0,  7, 13);\n\tR(b, c, d, e, a, F0, K0,  9, 14);\n\tR(a, b, c, d, e, F0, K0,  8, 15); /* #15 */\n\t/* Round 2 */\n\tR(e, a, b, c, d, F1, K1,  7,  7);\n\tR(d, e, a, b, c, F1, K1,  6,  4);\n\tR(c, d, e, a, b, F1, K1,  8, 13);\n\tR(b, c, d, e, a, F1, K1, 13,  1);\n\tR(a, b, c, d, e, F1, K1, 11, 10);\n\tR(e, a, b, c, d, F1, K1,  9,  6);\n\tR(d, e, a, b, c, F1, K1,  7, 15);\n\tR(c, d, e, a, b, F1, K1, 15,  3);\n\tR(b, c, d, e, a, F1, K1,  7, 12);\n\tR(a, b, c, d, e, F1, K1, 12,  0);\n\tR(e, a, b, c, d, F1, K1, 15,  9);\n\tR(d, e, a, b, c, F1, K1,  9,  5);\n\tR(c, d, e, a, b, F1, K1, 11,  2);\n\tR(b, c, d, e, a, F1, K1,  7, 14);\n\tR(a, b, c, d, e, F1, K1, 13, 11);\n\tR(e, a, b, c, d, F1, K1, 12,  8); /* #31 */\n\t/* Round 3 */\n\tR(d, e, a, b, c, F2, K2, 11,  3);\n\tR(c, d, e, a, b, F2, K2, 13, 10);\n\tR(b, c, d, e, a, F2, K2,  6, 14);\n\tR(a, b, c, d, e, F2, K2,  7,  4);\n\tR(e, a, b, c, d, F2, K2, 14,  9);\n\tR(d, e, a, b, c, F2, K2,  9, 15);\n\tR(c, d, e, a, b, F2, K2, 13,  8);\n\tR(b, c, d, e, a, F2, K2, 15,  1);\n\tR(a, b, c, d, e, F2, K2, 14,  2);\n\tR(e, a, b, c, d, F2, K2,  8,  7);\n\tR(d, e, a, b, c, F2, K2, 13,  0);\n\tR(c, d, e, a, b, F2, K2,  6,  6);\n\tR(b, c, d, e, a, F2, K2,  5, 13);\n\tR(a, b, c, d, e, F2, K2, 12, 11);\n\tR(e, a, b, c, d, F2, K2,  7,  5);\n\tR(d, e, a, b, c, F2, K2,  5, 12); /* #47 */\n\t/* Round 4 */\n\tR(c, d, e, a, b, F3, K3, 11,  1);\n\tR(b, c, d, e, a, F3, K3, 12,  9);\n\tR(a, b, c, d, e, F3, K3, 14, 11);\n\tR(e, a, b, c, d, F3, K3, 15, 10);\n\tR(d, e, a, b, c, F3, K3, 14,  0);\n\tR(c, d, e, a, b, F3, K3, 15,  8);\n\tR(b, c, d, e, a, F3, K3,  9, 12);\n\tR(a, b, c, d, e, F3, K3,  8,  4);\n\tR(e, a, b, c, d, F3, K3,  9, 13);\n\tR(d, e, a, b, c, F3, K3, 14,  3);\n\tR(c, d, e, a, b, F3, K3,  5,  7);\n\tR(b, c, d, e, a, F3, K3,  6, 15);\n\tR(a, b, c, d, e, F3, K3,  8, 14);\n\tR(e, a, b, c, d, F3, K3,  6,  5);\n\tR(d, e, a, b, c, F3, K3,  5,  6);\n\tR(c, d, e, a, b, F3, K3, 12,  2); /* #63 */\n\t/* Round 5 */\n\tR(b, c, d, e, a, F4, K4,  9,  4);\n\tR(a, b, c, d, e, F4, K4, 15,  0);\n\tR(e, a, b, c, d, F4, K4,  5,  5);\n\tR(d, e, a, b, c, F4, K4, 11,  9);\n\tR(c, d, e, a, b, F4, K4,  6,  7);\n\tR(b, c, d, e, a, F4, K4,  8, 12);\n\tR(a, b, c, d, e, F4, K4, 13,  2);\n\tR(e, a, b, c, d, F4, K4, 12, 10);\n\tR(d, e, a, b, c, F4, K4,  5, 14);\n\tR(c, d, e, a, b, F4, K4, 12,  1);\n\tR(b, c, d, e, a, F4, K4, 13,  3);\n\tR(a, b, c, d, e, F4, K4, 14,  8);\n\tR(e, a, b, c, d, F4, K4, 11, 11);\n\tR(d, e, a, b, c, F4, K4,  8,  6);\n\tR(c, d, e, a, b, F4, K4,  5, 15);\n\tR(b, c, d, e, a, F4, K4,  6, 13); /* #79 */\n\n\taa = a ; bb = b; cc = c; dd = d; ee = e;\n\n\ta = state[0];\n\tb = state[1];\n\tc = state[2];\n\td = state[3];\n\te = state[4];\n\n\t/* Parallel round 1 */\n\tR(a, b, c, d, e, F4, KK0,  8,  5);\n\tR(e, a, b, c, d, F4, KK0,  9, 14);\n\tR(d, e, a, b, c, F4, KK0,  9,  7);\n\tR(c, d, e, a, b, F4, KK0, 11,  0);\n\tR(b, c, d, e, a, F4, KK0, 13,  9);\n\tR(a, b, c, d, e, F4, KK0, 15,  2);\n\tR(e, a, b, c, d, F4, KK0, 15, 11);\n\tR(d, e, a, b, c, F4, KK0,  5,  4);\n\tR(c, d, e, a, b, F4, KK0,  7, 13);\n\tR(b, c, d, e, a, F4, KK0,  7,  6);\n\tR(a, b, c, d, e, F4, KK0,  8, 15);\n\tR(e, a, b, c, d, F4, KK0, 11,  8);\n\tR(d, e, a, b, c, F4, KK0, 14,  1);\n\tR(c, d, e, a, b, F4, KK0, 14, 10);\n\tR(b, c, d, e, a, F4, KK0, 12,  3);\n\tR(a, b, c, d, e, F4, KK0,  6, 12); /* #15 */\n\t/* Parallel round 2 */\n\tR(e, a, b, c, d, F3, KK1,  9,  6);\n\tR(d, e, a, b, c, F3, KK1, 13, 11);\n\tR(c, d, e, a, b, F3, KK1, 15,  3);\n\tR(b, c, d, e, a, F3, KK1,  7,  7);\n\tR(a, b, c, d, e, F3, KK1, 12,  0);\n\tR(e, a, b, c, d, F3, KK1,  8, 13);\n\tR(d, e, a, b, c, F3, KK1,  9,  5);\n\tR(c, d, e, a, b, F3, KK1, 11, 10);\n\tR(b, c, d, e, a, F3, KK1,  7, 14);\n\tR(a, b, c, d, e, F3, KK1,  7, 15);\n\tR(e, a, b, c, d, F3, KK1, 12,  8);\n\tR(d, e, a, b, c, F3, KK1,  7, 12);\n\tR(c, d, e, a, b, F3, KK1,  6,  4);\n\tR(b, c, d, e, a, F3, KK1, 15,  9);\n\tR(a, b, c, d, e, F3, KK1, 13,  1);\n\tR(e, a, b, c, d, F3, KK1, 11,  2); /* #31 */\n\t/* Parallel round 3 */\n\tR(d, e, a, b, c, F2, KK2,  9, 15);\n\tR(c, d, e, a, b, F2, KK2,  7,  5);\n\tR(b, c, d, e, a, F2, KK2, 15,  1);\n\tR(a, b, c, d, e, F2, KK2, 11,  3);\n\tR(e, a, b, c, d, F2, KK2,  8,  7);\n\tR(d, e, a, b, c, F2, KK2,  6, 14);\n\tR(c, d, e, a, b, F2, KK2,  6,  6);\n\tR(b, c, d, e, a, F2, KK2, 14,  9);\n\tR(a, b, c, d, e, F2, KK2, 12, 11);\n\tR(e, a, b, c, d, F2, KK2, 13,  8);\n\tR(d, e, a, b, c, F2, KK2,  5, 12);\n\tR(c, d, e, a, b, F2, KK2, 14,  2);\n\tR(b, c, d, e, a, F2, KK2, 13, 10);\n\tR(a, b, c, d, e, F2, KK2, 13,  0);\n\tR(e, a, b, c, d, F2, KK2,  7,  4);\n\tR(d, e, a, b, c, F2, KK2,  5, 13); /* #47 */\n\t/* Parallel round 4 */\n\tR(c, d, e, a, b, F1, KK3, 15,  8);\n\tR(b, c, d, e, a, F1, KK3,  5,  6);\n\tR(a, b, c, d, e, F1, KK3,  8,  4);\n\tR(e, a, b, c, d, F1, KK3, 11,  1);\n\tR(d, e, a, b, c, F1, KK3, 14,  3);\n\tR(c, d, e, a, b, F1, KK3, 14, 11);\n\tR(b, c, d, e, a, F1, KK3,  6, 15);\n\tR(a, b, c, d, e, F1, KK3, 14,  0);\n\tR(e, a, b, c, d, F1, KK3,  6,  5);\n\tR(d, e, a, b, c, F1, KK3,  9, 12);\n\tR(c, d, e, a, b, F1, KK3, 12,  2);\n\tR(b, c, d, e, a, F1, KK3,  9, 13);\n\tR(a, b, c, d, e, F1, KK3, 12,  9);\n\tR(e, a, b, c, d, F1, KK3,  5,  7);\n\tR(d, e, a, b, c, F1, KK3, 15, 10);\n\tR(c, d, e, a, b, F1, KK3,  8, 14); /* #63 */\n\t/* Parallel round 5 */\n\tR(b, c, d, e, a, F0, KK4,  8, 12);\n\tR(a, b, c, d, e, F0, KK4,  5, 15);\n\tR(e, a, b, c, d, F0, KK4, 12, 10);\n\tR(d, e, a, b, c, F0, KK4,  9,  4);\n\tR(c, d, e, a, b, F0, KK4, 12,  1);\n\tR(b, c, d, e, a, F0, KK4,  5,  5);\n\tR(a, b, c, d, e, F0, KK4, 14,  8);\n\tR(e, a, b, c, d, F0, KK4,  6,  7);\n\tR(d, e, a, b, c, F0, KK4,  8,  6);\n\tR(c, d, e, a, b, F0, KK4, 13,  2);\n\tR(b, c, d, e, a, F0, KK4,  6, 13);\n\tR(a, b, c, d, e, F0, KK4,  5, 14);\n\tR(e, a, b, c, d, F0, KK4, 15,  0);\n\tR(d, e, a, b, c, F0, KK4, 13,  3);\n\tR(c, d, e, a, b, F0, KK4, 11,  9);\n\tR(b, c, d, e, a, F0, KK4, 11, 11); /* #79 */\n\n\tt =        state[1] + cc + d;\n\tstate[1] = state[2] + dd + e;\n\tstate[2] = state[3] + ee + a;\n\tstate[3] = state[4] + aa + b;\n\tstate[4] = state[0] + bb + c;\n\tstate[0] = t;\n}\n"
  },
  {
    "path": "itl80211/openbsd/crypto/rmd160.h",
    "content": "/*\t$OpenBSD: rmd160.h,v 1.5 2009/07/05 19:33:46 millert Exp $\t*/\n/*\n * Copyright (c) 2001 Markus Friedl.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#ifndef  _RMD160_H\n#define  _RMD160_H\n\n#define RMD160_BLOCK_LENGTH\t\t64\n#define RMD160_DIGEST_LENGTH\t\t20\n\n/* RMD160 context. */\ntypedef struct RMD160Context {\n\tu_int32_t state[5];\t\t\t/* state */\n\tu_int64_t count;\t\t\t/* number of bits, mod 2^64 */\n\tu_char buffer[RMD160_BLOCK_LENGTH];\t/* input buffer */\n} RMD160_CTX;\n\n//__BEGIN_DECLS\nvoid\t RMD160Init(RMD160_CTX *);\nvoid\t RMD160Transform(u_int32_t [5], const u_char [RMD160_BLOCK_LENGTH])\n\t     __attribute__((__bounded__(__minbytes__,1,5)))\n\t     __attribute__((__bounded__(__minbytes__,2,RMD160_BLOCK_LENGTH)));\nvoid\t RMD160Update(RMD160_CTX *, const u_char *, u_int32_t)\n\t     __attribute__((__bounded__(__string__,2,3)));\nvoid\t RMD160Final(u_char [RMD160_DIGEST_LENGTH], RMD160_CTX *)\n\t     __attribute__((__bounded__(__minbytes__,1,RMD160_DIGEST_LENGTH)));\n//__END_DECLS\n\n#endif  /* _RMD160_H */\n"
  },
  {
    "path": "itl80211/openbsd/crypto/set_key.c",
    "content": "/*\t$OpenBSD: set_key.c,v 1.4 2015/12/10 21:00:51 naddy Exp $\t*/\n\n/* lib/des/set_key.c */\n/* Copyright (C) 1995 Eric Young (eay@mincom.oz.au)\n * All rights reserved.\n * \n * This file is part of an SSL implementation written\n * by Eric Young (eay@mincom.oz.au).\n * The implementation was written so as to conform with Netscapes SSL\n * specification.  This library and applications are\n * FREE FOR COMMERCIAL AND NON-COMMERCIAL USE\n * as long as the following conditions are aheared to.\n * \n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.  If this code is used in a product,\n * Eric Young should be given attribution as the author of the parts used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    This product includes software developed by Eric Young (eay@mincom.oz.au)\n * \n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n * \n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n\n/* set_key.c v 1.4 eay 24/9/91\n * 1.4 Speed up by 400% :-)\n * 1.3 added register declarations.\n * 1.2 unrolled make_key_sched a bit more\n * 1.1 added norm_expand_bits\n * 1.0 First working version\n */\n#include \"des_locl.h\"\n#include \"podd.h\"\n#include \"sk.h\"\n\nstatic int check_parity(des_cblock (*key));\n\nint des_check_key=0;\n\nstatic int\ncheck_parity(des_cblock (*key))\n{\n\tint i;\n\n\tfor (i = 0; i < DES_KEY_SZ; i++) {\n\t\tif ((*key)[i] != odd_parity[(*key)[i]])\n\t\t\treturn(0);\n\t}\n\treturn (1);\n}\n\n/* Weak and semi week keys as take from\n * %A D.W. Davies\n * %A W.L. Price\n * %T Security for Computer Networks\n * %I John Wiley & Sons\n * %D 1984\n * Many thanks to smb@ulysses.att.com (Steven Bellovin) for the reference\n * (and actual cblock values).\n */\n#define NUM_WEAK_KEY\t16\nstatic des_cblock weak_keys[NUM_WEAK_KEY]={\n\t/* weak keys */\n\t{0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01},\n\t{0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE},\n\t{0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F},\n\t{0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0},\n\t/* semi-weak keys */\n\t{0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE},\n\t{0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01},\n\t{0x1F,0xE0,0x1F,0xE0,0x0E,0xF1,0x0E,0xF1},\n\t{0xE0,0x1F,0xE0,0x1F,0xF1,0x0E,0xF1,0x0E},\n\t{0x01,0xE0,0x01,0xE0,0x01,0xF1,0x01,0xF1},\n\t{0xE0,0x01,0xE0,0x01,0xF1,0x01,0xF1,0x01},\n\t{0x1F,0xFE,0x1F,0xFE,0x0E,0xFE,0x0E,0xFE},\n\t{0xFE,0x1F,0xFE,0x1F,0xFE,0x0E,0xFE,0x0E},\n\t{0x01,0x1F,0x01,0x1F,0x01,0x0E,0x01,0x0E},\n\t{0x1F,0x01,0x1F,0x01,0x0E,0x01,0x0E,0x01},\n\t{0xE0,0xFE,0xE0,0xFE,0xF1,0xFE,0xF1,0xFE},\n\t{0xFE,0xE0,0xFE,0xE0,0xFE,0xF1,0xFE,0xF1}};\n\nint\ndes_is_weak_key(des_cblock (*key))\n{\n\tint i;\n\n\tfor (i = 0; i < NUM_WEAK_KEY; i++) {\n\t\t/* Added == 0 to comparision, I obviously don't run\n\t\t * this section very often :-(, thanks to\n\t\t * engineering@MorningStar.Com for the fix\n\t\t * eay 93/06/29 */\n\t\tif (bcmp(weak_keys[i], key, sizeof(des_cblock)) == 0)\n\t\t\treturn (1);\n\t}\n\treturn (0);\n}\n\n/* NOW DEFINED IN des_local.h\n * See ecb_encrypt.c for a pseudo description of these macros. \n * #define PERM_OP(a, b, t, n, m) ((t) = ((((a) >> (n))^(b)) & (m)),\\\n * \t(b)^=(t),\\\n * \t(a) = ((a)^((t) << (n))))\n */\n\n#define HPERM_OP(a, t, n, m) ((t) = ((((a) << (16 - (n)))^(a)) & (m)),\\\n\t(a) = (a)^(t)^(t >> (16 - (n))))\n\nstatic int shifts2[16]={0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0};\n\n/* return 0 if key parity is odd (correct),\n * return -1 if key parity error,\n * return -2 if illegal weak key.\n */\nint\ndes_set_key(des_cblock (*key), des_key_schedule schedule)\n{\n\tregister u_int32_t c, d, t, s;\n\tregister unsigned char *in;\n\tregister u_int32_t *k;\n\tregister int i;\n\n\tif (des_check_key) {\n\t\tif (!check_parity(key))\n\t\t\treturn(-1);\n\n\t\tif (des_is_weak_key(key))\n\t\t\treturn(-2);\n\t}\n\n\tk = (u_int32_t *) schedule;\n\tin = (unsigned char *) key;\n\n\tc2l(in, c);\n\tc2l(in, d);\n\n\t/* do PC1 in 60 simple operations */ \n/*\tPERM_OP(d, c, t, 4, 0x0f0f0f0fL);\n\tHPERM_OP(c, t, -2, 0xcccc0000L);\n\tHPERM_OP(c, t, -1, 0xaaaa0000L);\n\tHPERM_OP(c, t, 8, 0x00ff0000L);\n\tHPERM_OP(c, t, -1, 0xaaaa0000L);\n\tHPERM_OP(d, t, -8, 0xff000000L);\n\tHPERM_OP(d, t, 8, 0x00ff0000L);\n\tHPERM_OP(d, t, 2, 0x33330000L);\n\td = ((d & 0x00aa00aaL) << 7L) | ((d & 0x55005500L) >> 7L) | (d & 0xaa55aa55L);\n\td = (d >> 8) | ((c & 0xf0000000L) >> 4);\n\tc &= 0x0fffffffL; */\n\n\t/* I now do it in 47 simple operations :-)\n\t * Thanks to John Fletcher (john_fletcher@lccmail.ocf.llnl.gov)\n\t * for the inspiration. :-) */\n\tPERM_OP (d, c, t, 4, 0x0f0f0f0fL);\n\tHPERM_OP(c, t, -2, 0xcccc0000L);\n\tHPERM_OP(d, t, -2, 0xcccc0000L);\n\tPERM_OP (d, c, t, 1, 0x55555555L);\n\tPERM_OP (c, d, t, 8, 0x00ff00ffL);\n\tPERM_OP (d, c, t, 1, 0x55555555L);\n\td = (((d & 0x000000ffL) << 16L) | (d & 0x0000ff00L) |\n\t     ((d & 0x00ff0000L) >> 16L) | ((c & 0xf0000000L) >> 4L));\n\tc &= 0x0fffffffL;\n\n\tfor (i = 0; i < ITERATIONS; i++) {\n\t\tif (shifts2[i])\n\t\t\t{ c = ((c >> 2L) | (c << 26L)); d = ((d >> 2L) | (d << 26L)); }\n\t\telse\n\t\t\t{ c = ((c >> 1L) | (c << 27L)); d = ((d >> 1L) | (d << 27L)); }\n\t\tc &= 0x0fffffffL;\n\t\td &= 0x0fffffffL;\n\t\t/* could be a few less shifts but I am to lazy at this\n\t\t * point in time to investigate */\n\t\ts = des_skb[0][ (c    ) & 0x3f                ]|\n\t\t    des_skb[1][((c >> 6) & 0x03) | ((c >> 7L) & 0x3c)]|\n\t\t    des_skb[2][((c >> 13) & 0x0f) | ((c >> 14L) & 0x30)]|\n\t\t    des_skb[3][((c >> 20) & 0x01) | ((c >> 21L) & 0x06) |\n\t\t\t\t\t\t  ((c >> 22L) & 0x38)];\n\t\tt = des_skb[4][ (d    ) & 0x3f                ]|\n\t\t    des_skb[5][((d >> 7L) & 0x03) | ((d >> 8L) & 0x3c)]|\n\t\t    des_skb[6][ (d >> 15L) & 0x3f                ]|\n\t\t    des_skb[7][((d >> 21L) & 0x0f) | ((d >> 22L) & 0x30)];\n\n\t\t/* table contained 0213 4657 */\n\t\t*(k++) = ((t << 16L) | (s & 0x0000ffffL)) & 0xffffffffL;\n\t\ts = ((s >> 16L) | (t & 0xffff0000L));\n\t\t\n\t\ts = (s << 4L) | (s >> 28L);\n\t\t*(k++) = s & 0xffffffffL;\n\t}\n\treturn (0);\n}\n"
  },
  {
    "path": "itl80211/openbsd/crypto/sha1-pbkdf2.c",
    "content": "/*\n * SHA1-based key derivation function (PBKDF2) for IEEE 802.11i\n * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>\n *\n * This software may be distributed under the terms of the BSD license.\n * See README for more details.\n */\n\n#include \"sha1.h\"\n#include \"hmac.h\"\n\nstatic int openssl_hmac_vector(const u8 *key,\n                   size_t key_len, size_t num_elem,\n                   const u8 *addr[], const size_t *len, u8 *mac,\n                   unsigned int mdlen)\n{\n    HMAC_SHA1_CTX ctx;\n    size_t i;\n    u_int8_t digest[SHA1_DIGEST_LENGTH];\n\n    HMAC_SHA1_Init(&ctx, key, key_len);\n\n    for (i = 0; i < num_elem; i++)\n        HMAC_SHA1_Update(&ctx, addr[i], len[i]);\n\n    HMAC_SHA1_Final(digest, &ctx);\n    memcpy(mac, digest, sizeof(digest));\n\n    return 0;\n}\n\nint hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,\n             const u8 *addr[], const size_t *len, u8 *mac)\n{\n    return openssl_hmac_vector(key, key_len, num_elem, addr,\n                   len, mac, 20);\n}\n\n\nint hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len,\n           u8 *mac)\n{\n    return hmac_sha1_vector(key, key_len, 1, &data, &data_len, mac);\n}\n\nstatic int pbkdf2_sha1_f(const char *passphrase, const u8 *ssid,\n\t\t\t size_t ssid_len, int iterations, unsigned int count,\n\t\t\t u8 *digest)\n{\n\tunsigned char tmp[SHA1_MAC_LEN], tmp2[SHA1_MAC_LEN];\n\tint i, j;\n\tunsigned char count_buf[4];\n\tconst u8 *addr[2];\n\tsize_t len[2];\n\tsize_t passphrase_len = strlen(passphrase);\n\n\taddr[0] = ssid;\n\tlen[0] = ssid_len;\n\taddr[1] = count_buf;\n\tlen[1] = 4;\n\n\t/* F(P, S, c, i) = U1 xor U2 xor ... Uc\n\t * U1 = PRF(P, S || i)\n\t * U2 = PRF(P, U1)\n\t * Uc = PRF(P, Uc-1)\n\t */\n\n\tcount_buf[0] = (count >> 24) & 0xff;\n\tcount_buf[1] = (count >> 16) & 0xff;\n\tcount_buf[2] = (count >> 8) & 0xff;\n\tcount_buf[3] = count & 0xff;\n\tif (hmac_sha1_vector((u8 *) passphrase, passphrase_len, 2, addr, len,\n\t\t\t     tmp))\n\t\treturn -1;\n\tmemcpy(digest, tmp, SHA1_MAC_LEN);\n\n\tfor (i = 1; i < iterations; i++) {\n\t\tif (hmac_sha1((u8 *) passphrase, passphrase_len, tmp,\n\t\t\t      SHA1_MAC_LEN, tmp2))\n\t\t\treturn -1;\n\t\tmemcpy(tmp, tmp2, SHA1_MAC_LEN);\n\t\tfor (j = 0; j < SHA1_MAC_LEN; j++)\n\t\t\tdigest[j] ^= tmp2[j];\n\t}\n\n\treturn 0;\n}\n\n\n/**\n * pbkdf2_sha1 - SHA1-based key derivation function (PBKDF2) for IEEE 802.11i\n * @passphrase: ASCII passphrase\n * @ssid: SSID\n * @ssid_len: SSID length in bytes\n * @iterations: Number of iterations to run\n * @buf: Buffer for the generated key\n * @buflen: Length of the buffer in bytes\n * Returns: 0 on success, -1 of failure\n *\n * This function is used to derive PSK for WPA-PSK. For this protocol,\n * iterations is set to 4096 and buflen to 32. This function is described in\n * IEEE Std 802.11-2004, Clause H.4. The main construction is from PKCS#5 v2.0.\n */\nint pbkdf2_sha1(const char *passphrase, const u8 *ssid, size_t ssid_len,\n\t\tint iterations, u8 *buf, size_t buflen)\n{\n\tunsigned int count = 0;\n\tunsigned char *pos = buf;\n\tsize_t left = buflen, plen;\n\tunsigned char digest[SHA1_MAC_LEN];\n\n\twhile (left > 0) {\n\t\tcount++;\n\t\tif (pbkdf2_sha1_f(passphrase, ssid, ssid_len, iterations,\n\t\t\t\t  count, digest))\n\t\t\treturn -1;\n\t\tplen = left > SHA1_MAC_LEN ? SHA1_MAC_LEN : left;\n\t\tmemcpy(pos, digest, plen);\n\t\tpos += plen;\n\t\tleft -= plen;\n\t}\n\n\treturn 0;\n}\n"
  },
  {
    "path": "itl80211/openbsd/crypto/sha1.c",
    "content": "/*\t$OpenBSD: sha1.c,v 1.11 2014/12/28 10:04:35 tedu Exp $\t*/\n\n/*\n * SHA-1 in C\n * By Steve Reid <steve@edmweb.com>\n * 100% Public Domain\n * \n * Test Vectors (from FIPS PUB 180-1)\n * \"abc\"\n *   A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D\n * \"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq\"\n *   84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1\n * A million repetitions of \"a\"\n *   34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F\n*/\n\n/* #define LITTLE_ENDIAN * This should be #define'd already, if true. */\n/* #define SHA1HANDSOFF * Copies data before messing with it. */\n\n#define SHA1HANDSOFF\n\n#include <sys/param.h>\n#include <sys/systm.h>\n\n#include <crypto/sha1.h>\n\n#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))\n\n/* blk0() and blk() perform the initial expand. */\n/* I got the idea of expanding during the round function from SSLeay */\n#if BYTE_ORDER == LITTLE_ENDIAN\n#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \\\n    |(rol(block->l[i],8)&0x00FF00FF))\n#else\n#define blk0(i) block->l[i]\n#endif\n#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \\\n    ^block->l[(i+2)&15]^block->l[i&15],1))\n\n/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */\n#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);\n#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);\n#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);\n#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);\n#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);\n\n/* Hash a single 512-bit block. This is the core of the algorithm. */\n\nvoid\nSHA1Transform(u_int32_t state[5], const unsigned char buffer[SHA1_BLOCK_LENGTH])\n{\n    u_int32_t a, b, c, d, e;\n    typedef union {\n        unsigned char c[64];\n        unsigned int l[16];\n    } CHAR64LONG16;\n    CHAR64LONG16* block;\n#ifdef SHA1HANDSOFF\n    unsigned char workspace[SHA1_BLOCK_LENGTH];\n\n    block = (CHAR64LONG16 *)workspace;\n    memcpy(block, buffer, SHA1_BLOCK_LENGTH);\n#else\n    block = (CHAR64LONG16 *)buffer;\n#endif\n    /* Copy context->state[] to working vars */\n    a = state[0];\n    b = state[1];\n    c = state[2];\n    d = state[3];\n    e = state[4];\n\n    /* 4 rounds of 20 operations each. Loop unrolled. */\n    R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);\n    R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);\n    R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);\n    R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);\n    R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);\n    R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);\n    R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);\n    R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);\n    R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);\n    R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);\n    R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);\n    R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);\n    R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);\n    R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);\n    R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);\n    R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);\n    R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);\n    R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);\n    R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);\n    R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);\n\n    /* Add the working vars back into context.state[] */\n    state[0] += a;\n    state[1] += b;\n    state[2] += c;\n    state[3] += d;\n    state[4] += e;\n    /* Wipe variables */\n    a = b = c = d = e = 0;\n}\n\n\n/* SHA1Init - Initialize new context */\n\nvoid\nSHA1Init(SHA1_CTX *context)\n{\n    /* SHA1 initialization constants */\n    context->count = 0;\n    context->state[0] = 0x67452301;\n    context->state[1] = 0xEFCDAB89;\n    context->state[2] = 0x98BADCFE;\n    context->state[3] = 0x10325476;\n    context->state[4] = 0xC3D2E1F0;\n}\n\n\n/* Run your data through this. */\n\nvoid\nSHA1Update(SHA1_CTX *context, const void *dataptr, unsigned int len)\n{\n    const uint8_t *data = (const uint8_t *)dataptr;\n    unsigned int i;\n    unsigned int j;\n\n    j = (u_int32_t)((context->count >> 3) & 63);\n    context->count += (len << 3);\n    if ((j + len) > 63) {\n        memcpy(&context->buffer[j], data, (i = 64 - j));\n        SHA1Transform(context->state, context->buffer);\n        for ( ; i + 63 < len; i += 64) {\n            SHA1Transform(context->state, &data[i]);\n        }\n        j = 0;\n    }\n    else i = 0;\n    memcpy(&context->buffer[j], &data[i], len - i);\n}\n\n\n/* Add padding and return the message digest. */\n\nvoid\nSHA1Final(unsigned char digest[SHA1_DIGEST_LENGTH], SHA1_CTX *context)\n{\n    unsigned int i;\n    unsigned char finalcount[8];\n\n    for (i = 0; i < 8; i++) {\n        finalcount[i] = (unsigned char)((context->count >>\n            ((7 - (i & 7)) * 8)) & 255);  /* Endian independent */\n    }\n    SHA1Update(context, \"\\200\", 1);\n    while ((context->count & 504) != 448) {\n        SHA1Update(context, \"\\0\", 1);\n    }\n    SHA1Update(context, finalcount, 8);  /* Should cause a SHA1Transform() */\n\n    for (i = 0; i < SHA1_DIGEST_LENGTH; i++) {\n        digest[i] = (unsigned char)((context->state[i >> 2] >>\n            ((3 - (i & 3)) * 8)) & 255);\n    }\n    memset(&finalcount, 0, sizeof(finalcount));\n    memset(context, 0, sizeof(*context));\n}\n"
  },
  {
    "path": "itl80211/openbsd/crypto/sha1.h",
    "content": "/*\t$OpenBSD: sha1.h,v 1.6 2014/11/16 17:39:09 tedu Exp $\t*/\n\n/*\n * SHA-1 in C\n * By Steve Reid <steve@edmweb.com>\n * 100% Public Domain\n */\n\n#ifndef _SHA1_H_\n#define _SHA1_H_\n\n#include \"types.h\"\n\n#define SHA1_MAC_LEN 20\n\n#define\tSHA1_BLOCK_LENGTH\t\t64\n#define\tSHA1_DIGEST_LENGTH\t\t20\n\ntypedef struct {\n\tu_int32_t\tstate[5];\n\tu_int64_t\tcount;\n\tunsigned char\tbuffer[SHA1_BLOCK_LENGTH];\n} SHA1_CTX;\n\nvoid SHA1Init(SHA1_CTX * context);\nvoid SHA1Transform(u_int32_t state[5], const unsigned char buffer[SHA1_BLOCK_LENGTH]);\nvoid SHA1Update(SHA1_CTX *context, const void *data, unsigned int len);\nvoid SHA1Final(unsigned char digest[SHA1_DIGEST_LENGTH], SHA1_CTX *context);\n\nint hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,\n             const u8 *addr[], const size_t *len, u8 *mac);\nint hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len,\n           u8 *mac);\nint pbkdf2_sha1(const char *passphrase, const u8 *ssid, size_t ssid_len,\n                int iterations, u8 *buf, size_t buflen);\n#endif /* _SHA1_H_ */\n"
  },
  {
    "path": "itl80211/openbsd/crypto/sha2.c",
    "content": "/*\t$OpenBSD: sha2.c,v 1.18 2015/03/14 03:38:46 jsg Exp $\t*/\n\n/*\n * FILE:\tsha2.c\n * AUTHOR:\tAaron D. Gifford <me@aarongifford.com>\n * \n * Copyright (c) 2000-2001, Aaron D. Gifford\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the copyright holder nor the names of contributors\n *    may be used to endorse or promote products derived from this software\n *    without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * $From: sha2.c,v 1.1 2001/11/08 00:01:51 adg Exp adg $\n */\n\n#include <sys/time.h>\n#include <sys/systm.h>\n#include <crypto/sha2.h>\n#include <sys/_endian.h>\n\n/*\n * UNROLLED TRANSFORM LOOP NOTE:\n * You can define SHA2_UNROLL_TRANSFORM to use the unrolled transform\n * loop version for the hash transform rounds (defined using macros\n * later in this file).  Either define on the command line, for example:\n *\n *   cc -DSHA2_UNROLL_TRANSFORM -o sha2 sha2.c sha2prog.c\n *\n * or define below:\n *\n *   #define SHA2_UNROLL_TRANSFORM\n *\n */\n#ifndef SMALL_KERNEL\n#if defined(__amd64__) || defined(__i386__)\n#define SHA2_UNROLL_TRANSFORM\n#endif\n#endif\n\n/*** SHA-256/384/512 Machine Architecture Definitions *****************/\n/*\n * BYTE_ORDER NOTE:\n *\n * Please make sure that your system defines BYTE_ORDER.  If your\n * architecture is little-endian, make sure it also defines\n * LITTLE_ENDIAN and that the two (BYTE_ORDER and LITTLE_ENDIAN) are\n * equivilent.\n *\n * If your system does not define the above, then you can do so by\n * hand like this:\n *\n *   #define LITTLE_ENDIAN 1234\n *   #define BIG_ENDIAN    4321\n *\n * And for little-endian machines, add:\n *\n *   #define BYTE_ORDER LITTLE_ENDIAN \n *\n * Or for big-endian machines:\n *\n *   #define BYTE_ORDER BIG_ENDIAN\n *\n * The FreeBSD machine this was written on defines BYTE_ORDER\n * appropriately by including <sys/types.h> (which in turn includes\n * <machine/endian.h> where the appropriate definitions are actually\n * made).\n */\n#if !defined(BYTE_ORDER) || (BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN)\n#error Define BYTE_ORDER to be equal to either LITTLE_ENDIAN or BIG_ENDIAN\n#endif\n\n\n/*** SHA-256/384/512 Various Length Definitions ***********************/\n/* NOTE: Most of these are in sha2.h */\n#define SHA256_SHORT_BLOCK_LENGTH\t(SHA256_BLOCK_LENGTH - 8)\n#define SHA384_SHORT_BLOCK_LENGTH\t(SHA384_BLOCK_LENGTH - 16)\n#define SHA512_SHORT_BLOCK_LENGTH\t(SHA512_BLOCK_LENGTH - 16)\n\n/*\n * Macro for incrementally adding the unsigned 64-bit integer n to the\n * unsigned 128-bit integer (represented using a two-element array of\n * 64-bit words):\n */\n#define ADDINC128(w,n)\t{ \\\n\t(w)[0] += (u_int64_t)(n); \\\n\tif ((w)[0] < (n)) { \\\n\t\t(w)[1]++; \\\n\t} \\\n}\n\n/*** THE SIX LOGICAL FUNCTIONS ****************************************/\n/*\n * Bit shifting and rotation (used by the six SHA-XYZ logical functions:\n *\n *   NOTE:  The naming of R and S appears backwards here (R is a SHIFT and\n *   S is a ROTATION) because the SHA-256/384/512 description document\n *   (see http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf) uses this\n *   same \"backwards\" definition.\n */\n/* Shift-right (used in SHA-256, SHA-384, and SHA-512): */\n#define R(b,x) \t\t((x) >> (b))\n/* 32-bit Rotate-right (used in SHA-256): */\n#define S32(b,x)\t(((x) >> (b)) | ((x) << (32 - (b))))\n/* 64-bit Rotate-right (used in SHA-384 and SHA-512): */\n#define S64(b,x)\t(((x) >> (b)) | ((x) << (64 - (b))))\n\n/* Two of six logical functions used in SHA-256, SHA-384, and SHA-512: */\n#define Ch(x,y,z)\t(((x) & (y)) ^ ((~(x)) & (z)))\n#define Maj(x,y,z)\t(((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))\n\n/* Four of six logical functions used in SHA-256: */\n#define Sigma0_256(x)\t(S32(2,  (x)) ^ S32(13, (x)) ^ S32(22, (x)))\n#define Sigma1_256(x)\t(S32(6,  (x)) ^ S32(11, (x)) ^ S32(25, (x)))\n#define sigma0_256(x)\t(S32(7,  (x)) ^ S32(18, (x)) ^ R(3 ,   (x)))\n#define sigma1_256(x)\t(S32(17, (x)) ^ S32(19, (x)) ^ R(10,   (x)))\n\n/* Four of six logical functions used in SHA-384 and SHA-512: */\n#define Sigma0_512(x)\t(S64(28, (x)) ^ S64(34, (x)) ^ S64(39, (x)))\n#define Sigma1_512(x)\t(S64(14, (x)) ^ S64(18, (x)) ^ S64(41, (x)))\n#define sigma0_512(x)\t(S64( 1, (x)) ^ S64( 8, (x)) ^ R( 7,   (x)))\n#define sigma1_512(x)\t(S64(19, (x)) ^ S64(61, (x)) ^ R( 6,   (x)))\n\n/*** INTERNAL FUNCTION PROTOTYPES *************************************/\n/* NOTE: These should not be accessed directly from outside this\n * library -- they are intended for private internal visibility/use\n * only.\n */\nvoid SHA512Last(SHA2_CTX *);\nvoid SHA256Transform(u_int32_t *, const u_int8_t *);\nvoid SHA512Transform(u_int64_t *, const u_int8_t *);\n\n\n/*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/\n/* Hash constant words K for SHA-256: */\nconst static u_int32_t K256[64] = {\n\t0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,\n\t0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,\n\t0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL,\n\t0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,\n\t0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,\n\t0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,\n\t0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL,\n\t0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,\n\t0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL,\n\t0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,\n\t0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL,\n\t0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,\n\t0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL,\n\t0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,\n\t0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,\n\t0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL\n};\n\n/* Initial hash value H for SHA-256: */\nconst static u_int32_t sha256_initial_hash_value[8] = {\n\t0x6a09e667UL,\n\t0xbb67ae85UL,\n\t0x3c6ef372UL,\n\t0xa54ff53aUL,\n\t0x510e527fUL,\n\t0x9b05688cUL,\n\t0x1f83d9abUL,\n\t0x5be0cd19UL\n};\n\n/* Hash constant words K for SHA-384 and SHA-512: */\nconst static u_int64_t K512[80] = {\n\t0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,\n\t0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,\n\t0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,\n\t0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,\n\t0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,\n\t0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,\n\t0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,\n\t0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,\n\t0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,\n\t0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,\n\t0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,\n\t0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,\n\t0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,\n\t0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,\n\t0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,\n\t0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,\n\t0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,\n\t0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,\n\t0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,\n\t0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,\n\t0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,\n\t0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,\n\t0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,\n\t0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,\n\t0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,\n\t0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,\n\t0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,\n\t0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,\n\t0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,\n\t0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,\n\t0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,\n\t0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,\n\t0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,\n\t0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,\n\t0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,\n\t0x113f9804bef90daeULL, 0x1b710b35131c471bULL,\n\t0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,\n\t0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,\n\t0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,\n\t0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL\n};\n\n/* Initial hash value H for SHA-384 */\nconst static u_int64_t sha384_initial_hash_value[8] = {\n\t0xcbbb9d5dc1059ed8ULL,\n\t0x629a292a367cd507ULL,\n\t0x9159015a3070dd17ULL,\n\t0x152fecd8f70e5939ULL,\n\t0x67332667ffc00b31ULL,\n\t0x8eb44a8768581511ULL,\n\t0xdb0c2e0d64f98fa7ULL,\n\t0x47b5481dbefa4fa4ULL\n};\n\n/* Initial hash value H for SHA-512 */\nconst static u_int64_t sha512_initial_hash_value[8] = {\n\t0x6a09e667f3bcc908ULL,\n\t0xbb67ae8584caa73bULL,\n\t0x3c6ef372fe94f82bULL,\n\t0xa54ff53a5f1d36f1ULL,\n\t0x510e527fade682d1ULL,\n\t0x9b05688c2b3e6c1fULL,\n\t0x1f83d9abfb41bd6bULL,\n\t0x5be0cd19137e2179ULL\n};\n\n\n/*** SHA-256: *********************************************************/\nvoid\nSHA256Init(SHA2_CTX *context)\n{\n\tmemcpy(context->state.st32, sha256_initial_hash_value,\n\t    SHA256_DIGEST_LENGTH);\n\tmemset(context->buffer, 0, SHA256_BLOCK_LENGTH);\n\tcontext->bitcount[0] = 0;\n}\n\n#ifdef SHA2_UNROLL_TRANSFORM\n\n/* Unrolled SHA-256 round macros: */\n\n#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) do {\t\t\t\t    \\\n\tW256[j] = (u_int32_t)data[3] | ((u_int32_t)data[2] << 8) |\t    \\\n\t    ((u_int32_t)data[1] << 16) | ((u_int32_t)data[0] << 24);\t    \\\n\tdata += 4;\t\t\t\t\t\t\t    \\\n\tT1 = (h) + Sigma1_256((e)) + Ch((e), (f), (g)) + K256[j] + W256[j]; \\\n\t(d) += T1;\t\t\t\t\t\t\t    \\\n\t(h) = T1 + Sigma0_256((a)) + Maj((a), (b), (c));\t\t    \\\n\tj++;\t\t\t\t\t\t\t\t    \\\n} while(0)\n\n#define ROUND256(a,b,c,d,e,f,g,h) do {\t\t\t\t\t    \\\n\ts0 = W256[(j+1)&0x0f];\t\t\t\t\t\t    \\\n\ts0 = sigma0_256(s0);\t\t\t\t\t\t    \\\n\ts1 = W256[(j+14)&0x0f];\t\t\t\t\t\t    \\\n\ts1 = sigma1_256(s1);\t\t\t\t\t\t    \\\n\tT1 = (h) + Sigma1_256((e)) + Ch((e), (f), (g)) + K256[j] +\t    \\\n\t     (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0);\t\t    \\\n\t(d) += T1;\t\t\t\t\t\t\t    \\\n\t(h) = T1 + Sigma0_256((a)) + Maj((a), (b), (c));\t\t    \\\n\tj++;\t\t\t\t\t\t\t\t    \\\n} while(0)\n\nvoid\nSHA256Transform(u_int32_t *state, const u_int8_t *data)\n{\n\tu_int32_t\ta, b, c, d, e, f, g, h, s0, s1;\n\tu_int32_t\tT1, W256[16];\n\tint\t\tj;\n\n\t/* Initialize registers with the prev. intermediate value */\n\ta = state[0];\n\tb = state[1];\n\tc = state[2];\n\td = state[3];\n\te = state[4];\n\tf = state[5];\n\tg = state[6];\n\th = state[7];\n\n\tj = 0;\n\tdo {\n\t\t/* Rounds 0 to 15 (unrolled): */\n\t\tROUND256_0_TO_15(a,b,c,d,e,f,g,h);\n\t\tROUND256_0_TO_15(h,a,b,c,d,e,f,g);\n\t\tROUND256_0_TO_15(g,h,a,b,c,d,e,f);\n\t\tROUND256_0_TO_15(f,g,h,a,b,c,d,e);\n\t\tROUND256_0_TO_15(e,f,g,h,a,b,c,d);\n\t\tROUND256_0_TO_15(d,e,f,g,h,a,b,c);\n\t\tROUND256_0_TO_15(c,d,e,f,g,h,a,b);\n\t\tROUND256_0_TO_15(b,c,d,e,f,g,h,a);\n\t} while (j < 16);\n\n\t/* Now for the remaining rounds to 64: */\n\tdo {\n\t\tROUND256(a,b,c,d,e,f,g,h);\n\t\tROUND256(h,a,b,c,d,e,f,g);\n\t\tROUND256(g,h,a,b,c,d,e,f);\n\t\tROUND256(f,g,h,a,b,c,d,e);\n\t\tROUND256(e,f,g,h,a,b,c,d);\n\t\tROUND256(d,e,f,g,h,a,b,c);\n\t\tROUND256(c,d,e,f,g,h,a,b);\n\t\tROUND256(b,c,d,e,f,g,h,a);\n\t} while (j < 64);\n\n\t/* Compute the current intermediate hash value */\n\tstate[0] += a;\n\tstate[1] += b;\n\tstate[2] += c;\n\tstate[3] += d;\n\tstate[4] += e;\n\tstate[5] += f;\n\tstate[6] += g;\n\tstate[7] += h;\n\n\t/* Clean up */\n\ta = b = c = d = e = f = g = h = T1 = 0;\n}\n\n#else /* SHA2_UNROLL_TRANSFORM */\n\nvoid\nSHA256Transform(u_int32_t *state, const u_int8_t *data)\n{\n\tu_int32_t\ta, b, c, d, e, f, g, h, s0, s1;\n\tu_int32_t\tT1, T2, W256[16];\n\tint\t\tj;\n\n\t/* Initialize registers with the prev. intermediate value */\n\ta = state[0];\n\tb = state[1];\n\tc = state[2];\n\td = state[3];\n\te = state[4];\n\tf = state[5];\n\tg = state[6];\n\th = state[7];\n\n\tj = 0;\n\tdo {\n\t\tW256[j] = (u_int32_t)data[3] | ((u_int32_t)data[2] << 8) |\n\t\t    ((u_int32_t)data[1] << 16) | ((u_int32_t)data[0] << 24);\n\t\tdata += 4;\n\t\t/* Apply the SHA-256 compression function to update a..h */\n\t\tT1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j];\n\t\tT2 = Sigma0_256(a) + Maj(a, b, c);\n\t\th = g;\n\t\tg = f;\n\t\tf = e;\n\t\te = d + T1;\n\t\td = c;\n\t\tc = b;\n\t\tb = a;\n\t\ta = T1 + T2;\n\n\t\tj++;\n\t} while (j < 16);\n\n\tdo {\n\t\t/* Part of the message block expansion: */\n\t\ts0 = W256[(j+1)&0x0f];\n\t\ts0 = sigma0_256(s0);\n\t\ts1 = W256[(j+14)&0x0f];\t\n\t\ts1 = sigma1_256(s1);\n\n\t\t/* Apply the SHA-256 compression function to update a..h */\n\t\tT1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + \n\t\t     (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0);\n\t\tT2 = Sigma0_256(a) + Maj(a, b, c);\n\t\th = g;\n\t\tg = f;\n\t\tf = e;\n\t\te = d + T1;\n\t\td = c;\n\t\tc = b;\n\t\tb = a;\n\t\ta = T1 + T2;\n\n\t\tj++;\n\t} while (j < 64);\n\n\t/* Compute the current intermediate hash value */\n\tstate[0] += a;\n\tstate[1] += b;\n\tstate[2] += c;\n\tstate[3] += d;\n\tstate[4] += e;\n\tstate[5] += f;\n\tstate[6] += g;\n\tstate[7] += h;\n\n\t/* Clean up */\n\ta = b = c = d = e = f = g = h = T1 = T2 = 0;\n}\n\n#endif /* SHA2_UNROLL_TRANSFORM */\n\nvoid\nSHA256Update(SHA2_CTX *context, const void *dataptr, size_t len)\n{\n\tconst uint8_t *data = (const uint8_t *)dataptr;\n\tsize_t\tfreespace, usedspace;\n\n\t/* Calling with no data is valid (we do nothing) */\n\tif (len == 0)\n\t\treturn;\n\n\tusedspace = (context->bitcount[0] >> 3) % SHA256_BLOCK_LENGTH;\n\tif (usedspace > 0) {\n\t\t/* Calculate how much free space is available in the buffer */\n\t\tfreespace = SHA256_BLOCK_LENGTH - usedspace;\n\n\t\tif (len >= freespace) {\n\t\t\t/* Fill the buffer completely and process it */\n\t\t\tmemcpy(&context->buffer[usedspace], data, freespace);\n\t\t\tcontext->bitcount[0] += freespace << 3;\n\t\t\tlen -= freespace;\n\t\t\tdata += freespace;\n\t\t\tSHA256Transform(context->state.st32, context->buffer);\n\t\t} else {\n\t\t\t/* The buffer is not yet full */\n\t\t\tmemcpy(&context->buffer[usedspace], data, len);\n\t\t\tcontext->bitcount[0] += len << 3;\n\t\t\t/* Clean up: */\n\t\t\tusedspace = freespace = 0;\n\t\t\treturn;\n\t\t}\n\t}\n\twhile (len >= SHA256_BLOCK_LENGTH) {\n\t\t/* Process as many complete blocks as we can */\n\t\tSHA256Transform(context->state.st32, data);\n\t\tcontext->bitcount[0] += SHA256_BLOCK_LENGTH << 3;\n\t\tlen -= SHA256_BLOCK_LENGTH;\n\t\tdata += SHA256_BLOCK_LENGTH;\n\t}\n\tif (len > 0) {\n\t\t/* There's left-overs, so save 'em */\n\t\tmemcpy(context->buffer, data, len);\n\t\tcontext->bitcount[0] += len << 3;\n\t}\n\t/* Clean up: */\n\tusedspace = freespace = 0;\n}\n\nvoid\nSHA256Final(u_int8_t digest[], SHA2_CTX *context)\n{\n\tunsigned int\tusedspace;\n\n\tusedspace = (context->bitcount[0] >> 3) % SHA256_BLOCK_LENGTH;\n#if BYTE_ORDER == LITTLE_ENDIAN\n\t/* Convert FROM host byte order */\n\tcontext->bitcount[0] = _OSSwapInt64(context->bitcount[0]);\n#endif\n\tif (usedspace > 0) {\n\t\t/* Begin padding with a 1 bit: */\n\t\tcontext->buffer[usedspace++] = 0x80;\n\n\t\tif (usedspace <= SHA256_SHORT_BLOCK_LENGTH) {\n\t\t\t/* Set-up for the last transform: */\n\t\t\tmemset(&context->buffer[usedspace], 0,\n\t\t\t    SHA256_SHORT_BLOCK_LENGTH - usedspace);\n\t\t} else {\n\t\t\tif (usedspace < SHA256_BLOCK_LENGTH) {\n\t\t\t\tmemset(&context->buffer[usedspace], 0,\n\t\t\t\t    SHA256_BLOCK_LENGTH - usedspace);\n\t\t\t}\n\t\t\t/* Do second-to-last transform: */\n\t\t\tSHA256Transform(context->state.st32, context->buffer);\n\n\t\t\t/* And set-up for the last transform: */\n\t\t\tmemset(context->buffer, 0,\n\t\t\t    SHA256_SHORT_BLOCK_LENGTH);\n\t\t}\n\t} else {\n\t\t/* Set-up for the last transform: */\n\t\tmemset(context->buffer, 0, SHA256_SHORT_BLOCK_LENGTH);\n\n\t\t/* Begin padding with a 1 bit: */\n\t\t*context->buffer = 0x80;\n\t}\n\t/* Set the bit count: */\n\t*(u_int64_t *)&context->buffer[SHA256_SHORT_BLOCK_LENGTH] = context->bitcount[0];\n\n\t/* Final transform: */\n\tSHA256Transform(context->state.st32, context->buffer);\n\n#if BYTE_ORDER == LITTLE_ENDIAN\n\t{\n\t\t/* Convert TO host byte order */\n\t\tint\tj;\n\t\tfor (j = 0; j < 8; j++) {\n\t\t\tcontext->state.st32[j] = _OSSwapInt32(context->state.st32[j]);\n\t\t}\n\t}\n#endif\n\tmemcpy(digest, context->state.st32, SHA256_DIGEST_LENGTH);\n\t/* Clean up state data: */\n\tmemset(context, 0, sizeof(*context));\n\tusedspace = 0;\n}\n\n\n/*** SHA-512: *********************************************************/\nvoid\nSHA512Init(SHA2_CTX *context)\n{\n\tmemcpy(context->state.st64, sha512_initial_hash_value,\n\t    SHA512_DIGEST_LENGTH);\n\tmemset(context->buffer, 0, SHA512_BLOCK_LENGTH);\n\tcontext->bitcount[0] = context->bitcount[1] =  0;\n}\n\n#ifdef SHA2_UNROLL_TRANSFORM\n\n/* Unrolled SHA-512 round macros: */\n\n#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) do {\t\t\t\t    \\\n\tW512[j] = (u_int64_t)data[7] | ((u_int64_t)data[6] << 8) |\t    \\\n\t    ((u_int64_t)data[5] << 16) | ((u_int64_t)data[4] << 24) |\t    \\\n\t    ((u_int64_t)data[3] << 32) | ((u_int64_t)data[2] << 40) |\t    \\\n\t    ((u_int64_t)data[1] << 48) | ((u_int64_t)data[0] << 56);\t    \\\n\tdata += 8;\t\t\t\t\t\t\t    \\\n\tT1 = (h) + Sigma1_512((e)) + Ch((e), (f), (g)) + K512[j] + W512[j]; \\\n\t(d) += T1;\t\t\t\t\t\t\t    \\\n\t(h) = T1 + Sigma0_512((a)) + Maj((a), (b), (c));\t\t    \\\n\tj++;\t\t\t\t\t\t\t\t    \\\n} while(0)\n\n\n#define ROUND512(a,b,c,d,e,f,g,h) do {\t\t\t\t\t    \\\n\ts0 = W512[(j+1)&0x0f];\t\t\t\t\t\t    \\\n\ts0 = sigma0_512(s0);\t\t\t\t\t\t    \\\n\ts1 = W512[(j+14)&0x0f];\t\t\t\t\t\t    \\\n\ts1 = sigma1_512(s1);\t\t\t\t\t\t    \\\n\tT1 = (h) + Sigma1_512((e)) + Ch((e), (f), (g)) + K512[j] +\t    \\\n             (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0);\t\t    \\\n\t(d) += T1;\t\t\t\t\t\t\t    \\\n\t(h) = T1 + Sigma0_512((a)) + Maj((a), (b), (c));\t\t    \\\n\tj++;\t\t\t\t\t\t\t\t    \\\n} while(0)\n\nvoid\nSHA512Transform(u_int64_t *state, const u_int8_t *data)\n{\n\tu_int64_t\ta, b, c, d, e, f, g, h, s0, s1;\n\tu_int64_t\tT1, W512[16];\n\tint\t\tj;\n\n\t/* Initialize registers with the prev. intermediate value */\n\ta = state[0];\n\tb = state[1];\n\tc = state[2];\n\td = state[3];\n\te = state[4];\n\tf = state[5];\n\tg = state[6];\n\th = state[7];\n\n\tj = 0;\n\tdo {\n\t\tROUND512_0_TO_15(a,b,c,d,e,f,g,h);\n\t\tROUND512_0_TO_15(h,a,b,c,d,e,f,g);\n\t\tROUND512_0_TO_15(g,h,a,b,c,d,e,f);\n\t\tROUND512_0_TO_15(f,g,h,a,b,c,d,e);\n\t\tROUND512_0_TO_15(e,f,g,h,a,b,c,d);\n\t\tROUND512_0_TO_15(d,e,f,g,h,a,b,c);\n\t\tROUND512_0_TO_15(c,d,e,f,g,h,a,b);\n\t\tROUND512_0_TO_15(b,c,d,e,f,g,h,a);\n\t} while (j < 16);\n\n\t/* Now for the remaining rounds up to 79: */\n\tdo {\n\t\tROUND512(a,b,c,d,e,f,g,h);\n\t\tROUND512(h,a,b,c,d,e,f,g);\n\t\tROUND512(g,h,a,b,c,d,e,f);\n\t\tROUND512(f,g,h,a,b,c,d,e);\n\t\tROUND512(e,f,g,h,a,b,c,d);\n\t\tROUND512(d,e,f,g,h,a,b,c);\n\t\tROUND512(c,d,e,f,g,h,a,b);\n\t\tROUND512(b,c,d,e,f,g,h,a);\n\t} while (j < 80);\n\n\t/* Compute the current intermediate hash value */\n\tstate[0] += a;\n\tstate[1] += b;\n\tstate[2] += c;\n\tstate[3] += d;\n\tstate[4] += e;\n\tstate[5] += f;\n\tstate[6] += g;\n\tstate[7] += h;\n\n\t/* Clean up */\n\ta = b = c = d = e = f = g = h = T1 = 0;\n}\n\n#else /* SHA2_UNROLL_TRANSFORM */\n\nvoid\nSHA512Transform(u_int64_t *state, const u_int8_t *data)\n{\n\tu_int64_t\ta, b, c, d, e, f, g, h, s0, s1;\n\tu_int64_t\tT1, T2, W512[16];\n\tint\t\tj;\n\n\t/* Initialize registers with the prev. intermediate value */\n\ta = state[0];\n\tb = state[1];\n\tc = state[2];\n\td = state[3];\n\te = state[4];\n\tf = state[5];\n\tg = state[6];\n\th = state[7];\n\n\tj = 0;\n\tdo {\n\t\tW512[j] = (u_int64_t)data[7] | ((u_int64_t)data[6] << 8) |\n\t\t    ((u_int64_t)data[5] << 16) | ((u_int64_t)data[4] << 24) |\n\t\t    ((u_int64_t)data[3] << 32) | ((u_int64_t)data[2] << 40) |\n\t\t    ((u_int64_t)data[1] << 48) | ((u_int64_t)data[0] << 56);\n\t\tdata += 8;\n\t\t/* Apply the SHA-512 compression function to update a..h */\n\t\tT1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + W512[j];\n\t\tT2 = Sigma0_512(a) + Maj(a, b, c);\n\t\th = g;\n\t\tg = f;\n\t\tf = e;\n\t\te = d + T1;\n\t\td = c;\n\t\tc = b;\n\t\tb = a;\n\t\ta = T1 + T2;\n\n\t\tj++;\n\t} while (j < 16);\n\n\tdo {\n\t\t/* Part of the message block expansion: */\n\t\ts0 = W512[(j+1)&0x0f];\n\t\ts0 = sigma0_512(s0);\n\t\ts1 = W512[(j+14)&0x0f];\n\t\ts1 =  sigma1_512(s1);\n\n\t\t/* Apply the SHA-512 compression function to update a..h */\n\t\tT1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] +\n\t\t     (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0);\n\t\tT2 = Sigma0_512(a) + Maj(a, b, c);\n\t\th = g;\n\t\tg = f;\n\t\tf = e;\n\t\te = d + T1;\n\t\td = c;\n\t\tc = b;\n\t\tb = a;\n\t\ta = T1 + T2;\n\n\t\tj++;\n\t} while (j < 80);\n\n\t/* Compute the current intermediate hash value */\n\tstate[0] += a;\n\tstate[1] += b;\n\tstate[2] += c;\n\tstate[3] += d;\n\tstate[4] += e;\n\tstate[5] += f;\n\tstate[6] += g;\n\tstate[7] += h;\n\n\t/* Clean up */\n\ta = b = c = d = e = f = g = h = T1 = T2 = 0;\n}\n\n#endif /* SHA2_UNROLL_TRANSFORM */\n\nvoid\nSHA512Update(SHA2_CTX *context, const void *dataptr, size_t len)\n{\n\tconst uint8_t *data = (const uint8_t *)dataptr;\n\tsize_t\tfreespace, usedspace;\n\n\t/* Calling with no data is valid (we do nothing) */\n\tif (len == 0)\n\t\treturn;\n\n\tusedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH;\n\tif (usedspace > 0) {\n\t\t/* Calculate how much free space is available in the buffer */\n\t\tfreespace = SHA512_BLOCK_LENGTH - usedspace;\n\n\t\tif (len >= freespace) {\n\t\t\t/* Fill the buffer completely and process it */\n\t\t\tmemcpy(&context->buffer[usedspace], data, freespace);\n\t\t\tADDINC128(context->bitcount, freespace << 3);\n\t\t\tlen -= freespace;\n\t\t\tdata += freespace;\n\t\t\tSHA512Transform(context->state.st64, context->buffer);\n\t\t} else {\n\t\t\t/* The buffer is not yet full */\n\t\t\tmemcpy(&context->buffer[usedspace], data, len);\n\t\t\tADDINC128(context->bitcount, len << 3);\n\t\t\t/* Clean up: */\n\t\t\tusedspace = freespace = 0;\n\t\t\treturn;\n\t\t}\n\t}\n\twhile (len >= SHA512_BLOCK_LENGTH) {\n\t\t/* Process as many complete blocks as we can */\n\t\tSHA512Transform(context->state.st64, data);\n\t\tADDINC128(context->bitcount, SHA512_BLOCK_LENGTH << 3);\n\t\tlen -= SHA512_BLOCK_LENGTH;\n\t\tdata += SHA512_BLOCK_LENGTH;\n\t}\n\tif (len > 0) {\n\t\t/* There's left-overs, so save 'em */\n\t\tmemcpy(context->buffer, data, len);\n\t\tADDINC128(context->bitcount, len << 3);\n\t}\n\t/* Clean up: */\n\tusedspace = freespace = 0;\n}\n\nvoid\nSHA512Last(SHA2_CTX *context)\n{\n\tunsigned int\tusedspace;\n\n\tusedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH;\n#if BYTE_ORDER == LITTLE_ENDIAN\n\t/* Convert FROM host byte order */\n\tcontext->bitcount[0] = _OSSwapInt64(context->bitcount[0]);\n\tcontext->bitcount[1] = _OSSwapInt64(context->bitcount[1]);\n#endif\n\tif (usedspace > 0) {\n\t\t/* Begin padding with a 1 bit: */\n\t\tcontext->buffer[usedspace++] = 0x80;\n\n\t\tif (usedspace <= SHA512_SHORT_BLOCK_LENGTH) {\n\t\t\t/* Set-up for the last transform: */\n\t\t\tmemset(&context->buffer[usedspace], 0,\n\t\t\t    SHA512_SHORT_BLOCK_LENGTH - usedspace);\n\t\t} else {\n\t\t\tif (usedspace < SHA512_BLOCK_LENGTH) {\n\t\t\t\tmemset(&context->buffer[usedspace], 0,\n\t\t\t\t    SHA512_BLOCK_LENGTH - usedspace);\n\t\t\t}\n\t\t\t/* Do second-to-last transform: */\n\t\t\tSHA512Transform(context->state.st64, context->buffer);\n\n\t\t\t/* And set-up for the last transform: */\n\t\t\tmemset(context->buffer, 0, SHA512_BLOCK_LENGTH - 2);\n\t\t}\n\t} else {\n\t\t/* Prepare for final transform: */\n\t\tmemset(context->buffer, 0, SHA512_SHORT_BLOCK_LENGTH);\n\n\t\t/* Begin padding with a 1 bit: */\n\t\t*context->buffer = 0x80;\n\t}\n\t/* Store the length of input data (in bits): */\n\t*(u_int64_t *)&context->buffer[SHA512_SHORT_BLOCK_LENGTH] = context->bitcount[1];\n\t*(u_int64_t *)&context->buffer[SHA512_SHORT_BLOCK_LENGTH+8] = context->bitcount[0];\n\n\t/* Final transform: */\n\tSHA512Transform(context->state.st64, context->buffer);\n}\n\nvoid\nSHA512Final(u_int8_t digest[], SHA2_CTX *context)\n{\n\n\tSHA512Last(context);\n\n\t/* Save the hash data for output: */\n#if BYTE_ORDER == LITTLE_ENDIAN\n\t{\n\t\t/* Convert TO host byte order */\n\t\tint\tj;\n\t\tfor (j = 0; j < 8; j++) {\n\t\t\tcontext->state.st64[j] = _OSSwapInt64(context->state.st64[j]);\n\t\t}\n\t}\n#endif\n\tmemcpy(digest, context->state.st64, SHA512_DIGEST_LENGTH);\n\n\t/* Zero out state data */\n\tmemset(context, 0, sizeof(*context));\n}\n\n\n/*** SHA-384: *********************************************************/\nvoid\nSHA384Init(SHA2_CTX *context)\n{\n\tmemcpy(context->state.st64, sha384_initial_hash_value,\n\t    SHA512_DIGEST_LENGTH);\n\tmemset(context->buffer, 0, SHA384_BLOCK_LENGTH);\n\tcontext->bitcount[0] = context->bitcount[1] = 0;\n}\n\nvoid\nSHA384Update(SHA2_CTX *context, const void *data, size_t len)\n{\n\tSHA512Update(context, data, len);\n}\n\nvoid\nSHA384Final(u_int8_t digest[], SHA2_CTX *context)\n{\n\n\tSHA512Last(context);\n\n\t/* Save the hash data for output: */\n#if BYTE_ORDER == LITTLE_ENDIAN\n\t{\n\t\t/* Convert TO host byte order */\n\t\tint\tj;\n\t\tfor (j = 0; j < 6; j++) {\n\t\t\tcontext->state.st64[j] = _OSSwapInt64(context->state.st64[j]);\n\t\t}\n\t}\n#endif\n\tmemcpy(digest, context->state.st64, SHA384_DIGEST_LENGTH);\n\t/* Zero out state data */\n\tmemset(context, 0, sizeof(*context));\n}\n"
  },
  {
    "path": "itl80211/openbsd/crypto/sha2.h",
    "content": "/*\t$OpenBSD: sha2.h,v 1.5 2014/11/16 17:39:09 tedu Exp $\t*/\n\n/*\n * FILE:\tsha2.h\n * AUTHOR:\tAaron D. Gifford <me@aarongifford.com>\n * \n * Copyright (c) 2000-2001, Aaron D. Gifford\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the copyright holder nor the names of contributors\n *    may be used to endorse or promote products derived from this software\n *    without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * $From: sha2.h,v 1.1 2001/11/08 00:02:01 adg Exp adg $\n */\n\n#ifndef _SHA2_H\n#define _SHA2_H\n\n\n/*** SHA-256/384/512 Various Length Definitions ***********************/\n#define SHA256_BLOCK_LENGTH\t\t64\n#define SHA256_DIGEST_LENGTH\t\t32\n#define SHA256_DIGEST_STRING_LENGTH\t(SHA256_DIGEST_LENGTH * 2 + 1)\n#define SHA384_BLOCK_LENGTH\t\t128\n#define SHA384_DIGEST_LENGTH\t\t48\n#define SHA384_DIGEST_STRING_LENGTH\t(SHA384_DIGEST_LENGTH * 2 + 1)\n#define SHA512_BLOCK_LENGTH\t\t128\n#define SHA512_DIGEST_LENGTH\t\t64\n#define SHA512_DIGEST_STRING_LENGTH\t(SHA512_DIGEST_LENGTH * 2 + 1)\n\n\n/*** SHA-256/384/512 Context Structure *******************************/\ntypedef struct _SHA2_CTX {\n\tunion {\n\t\tu_int32_t\tst32[8];\n\t\tu_int64_t\tst64[8];\n\t} state;\n\tu_int64_t\tbitcount[2];\n\tu_int8_t\tbuffer[SHA512_BLOCK_LENGTH];\n} SHA2_CTX;\n\n//__BEGIN_DECLS\nvoid SHA256Init(SHA2_CTX *);\nvoid SHA256Update(SHA2_CTX *, const void *, size_t)\n\t__attribute__((__bounded__(__string__,2,3)));\nvoid SHA256Final(u_int8_t[SHA256_DIGEST_LENGTH], SHA2_CTX *)\n\t__attribute__((__bounded__(__minbytes__,1,SHA256_DIGEST_LENGTH)));\n\nvoid SHA384Init(SHA2_CTX *);\nvoid SHA384Update(SHA2_CTX *, const void *, size_t)\n\t__attribute__((__bounded__(__string__,2,3)));\nvoid SHA384Final(u_int8_t[SHA384_DIGEST_LENGTH], SHA2_CTX *)\n\t__attribute__((__bounded__(__minbytes__,1,SHA384_DIGEST_LENGTH)));\n\nvoid SHA512Init(SHA2_CTX *);\nvoid SHA512Update(SHA2_CTX *, const void *, size_t)\n\t__attribute__((__bounded__(__string__,2,3)));\nvoid SHA512Final(u_int8_t[SHA512_DIGEST_LENGTH], SHA2_CTX *)\n\t__attribute__((__bounded__(__minbytes__,1,SHA512_DIGEST_LENGTH)));\n//__END_DECLS\n\n#endif /* _SHA2_H */\n"
  },
  {
    "path": "itl80211/openbsd/crypto/sk.h",
    "content": "/*\t$OpenBSD: sk.h,v 1.2 2002/10/27 13:24:26 miod Exp $\t*/\n\n/* lib/des/sk.h */\n/* Copyright (C) 1995 Eric Young (eay@mincom.oz.au)\n * All rights reserved.\n * \n * This file is part of an SSL implementation written\n * by Eric Young (eay@mincom.oz.au).\n * The implementation was written so as to conform with Netscapes SSL\n * specification.  This library and applications are\n * FREE FOR COMMERCIAL AND NON-COMMERCIAL USE\n * as long as the following conditions are aheared to.\n * \n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.  If this code is used in a product,\n * Eric Young should be given attribution as the author of the parts used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    This product includes software developed by Eric Young (eay@mincom.oz.au)\n * \n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n * \n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n\nstatic const u_int32_t des_skb[8][64]={\n{\n/* for C bits (numbered as per FIPS 46) 1 2 3 4 5 6 */\n0x00000000L,0x00000010L,0x20000000L,0x20000010L,\n0x00010000L,0x00010010L,0x20010000L,0x20010010L,\n0x00000800L,0x00000810L,0x20000800L,0x20000810L,\n0x00010800L,0x00010810L,0x20010800L,0x20010810L,\n0x00000020L,0x00000030L,0x20000020L,0x20000030L,\n0x00010020L,0x00010030L,0x20010020L,0x20010030L,\n0x00000820L,0x00000830L,0x20000820L,0x20000830L,\n0x00010820L,0x00010830L,0x20010820L,0x20010830L,\n0x00080000L,0x00080010L,0x20080000L,0x20080010L,\n0x00090000L,0x00090010L,0x20090000L,0x20090010L,\n0x00080800L,0x00080810L,0x20080800L,0x20080810L,\n0x00090800L,0x00090810L,0x20090800L,0x20090810L,\n0x00080020L,0x00080030L,0x20080020L,0x20080030L,\n0x00090020L,0x00090030L,0x20090020L,0x20090030L,\n0x00080820L,0x00080830L,0x20080820L,0x20080830L,\n0x00090820L,0x00090830L,0x20090820L,0x20090830L,\n},{\n/* for C bits (numbered as per FIPS 46) 7 8 10 11 12 13 */\n0x00000000L,0x02000000L,0x00002000L,0x02002000L,\n0x00200000L,0x02200000L,0x00202000L,0x02202000L,\n0x00000004L,0x02000004L,0x00002004L,0x02002004L,\n0x00200004L,0x02200004L,0x00202004L,0x02202004L,\n0x00000400L,0x02000400L,0x00002400L,0x02002400L,\n0x00200400L,0x02200400L,0x00202400L,0x02202400L,\n0x00000404L,0x02000404L,0x00002404L,0x02002404L,\n0x00200404L,0x02200404L,0x00202404L,0x02202404L,\n0x10000000L,0x12000000L,0x10002000L,0x12002000L,\n0x10200000L,0x12200000L,0x10202000L,0x12202000L,\n0x10000004L,0x12000004L,0x10002004L,0x12002004L,\n0x10200004L,0x12200004L,0x10202004L,0x12202004L,\n0x10000400L,0x12000400L,0x10002400L,0x12002400L,\n0x10200400L,0x12200400L,0x10202400L,0x12202400L,\n0x10000404L,0x12000404L,0x10002404L,0x12002404L,\n0x10200404L,0x12200404L,0x10202404L,0x12202404L,\n},{\n/* for C bits (numbered as per FIPS 46) 14 15 16 17 19 20 */\n0x00000000L,0x00000001L,0x00040000L,0x00040001L,\n0x01000000L,0x01000001L,0x01040000L,0x01040001L,\n0x00000002L,0x00000003L,0x00040002L,0x00040003L,\n0x01000002L,0x01000003L,0x01040002L,0x01040003L,\n0x00000200L,0x00000201L,0x00040200L,0x00040201L,\n0x01000200L,0x01000201L,0x01040200L,0x01040201L,\n0x00000202L,0x00000203L,0x00040202L,0x00040203L,\n0x01000202L,0x01000203L,0x01040202L,0x01040203L,\n0x08000000L,0x08000001L,0x08040000L,0x08040001L,\n0x09000000L,0x09000001L,0x09040000L,0x09040001L,\n0x08000002L,0x08000003L,0x08040002L,0x08040003L,\n0x09000002L,0x09000003L,0x09040002L,0x09040003L,\n0x08000200L,0x08000201L,0x08040200L,0x08040201L,\n0x09000200L,0x09000201L,0x09040200L,0x09040201L,\n0x08000202L,0x08000203L,0x08040202L,0x08040203L,\n0x09000202L,0x09000203L,0x09040202L,0x09040203L,\n},{\n/* for C bits (numbered as per FIPS 46) 21 23 24 26 27 28 */\n0x00000000L,0x00100000L,0x00000100L,0x00100100L,\n0x00000008L,0x00100008L,0x00000108L,0x00100108L,\n0x00001000L,0x00101000L,0x00001100L,0x00101100L,\n0x00001008L,0x00101008L,0x00001108L,0x00101108L,\n0x04000000L,0x04100000L,0x04000100L,0x04100100L,\n0x04000008L,0x04100008L,0x04000108L,0x04100108L,\n0x04001000L,0x04101000L,0x04001100L,0x04101100L,\n0x04001008L,0x04101008L,0x04001108L,0x04101108L,\n0x00020000L,0x00120000L,0x00020100L,0x00120100L,\n0x00020008L,0x00120008L,0x00020108L,0x00120108L,\n0x00021000L,0x00121000L,0x00021100L,0x00121100L,\n0x00021008L,0x00121008L,0x00021108L,0x00121108L,\n0x04020000L,0x04120000L,0x04020100L,0x04120100L,\n0x04020008L,0x04120008L,0x04020108L,0x04120108L,\n0x04021000L,0x04121000L,0x04021100L,0x04121100L,\n0x04021008L,0x04121008L,0x04021108L,0x04121108L,\n},{\n/* for D bits (numbered as per FIPS 46) 1 2 3 4 5 6 */\n0x00000000L,0x10000000L,0x00010000L,0x10010000L,\n0x00000004L,0x10000004L,0x00010004L,0x10010004L,\n0x20000000L,0x30000000L,0x20010000L,0x30010000L,\n0x20000004L,0x30000004L,0x20010004L,0x30010004L,\n0x00100000L,0x10100000L,0x00110000L,0x10110000L,\n0x00100004L,0x10100004L,0x00110004L,0x10110004L,\n0x20100000L,0x30100000L,0x20110000L,0x30110000L,\n0x20100004L,0x30100004L,0x20110004L,0x30110004L,\n0x00001000L,0x10001000L,0x00011000L,0x10011000L,\n0x00001004L,0x10001004L,0x00011004L,0x10011004L,\n0x20001000L,0x30001000L,0x20011000L,0x30011000L,\n0x20001004L,0x30001004L,0x20011004L,0x30011004L,\n0x00101000L,0x10101000L,0x00111000L,0x10111000L,\n0x00101004L,0x10101004L,0x00111004L,0x10111004L,\n0x20101000L,0x30101000L,0x20111000L,0x30111000L,\n0x20101004L,0x30101004L,0x20111004L,0x30111004L,\n},{\n/* for D bits (numbered as per FIPS 46) 8 9 11 12 13 14 */\n0x00000000L,0x08000000L,0x00000008L,0x08000008L,\n0x00000400L,0x08000400L,0x00000408L,0x08000408L,\n0x00020000L,0x08020000L,0x00020008L,0x08020008L,\n0x00020400L,0x08020400L,0x00020408L,0x08020408L,\n0x00000001L,0x08000001L,0x00000009L,0x08000009L,\n0x00000401L,0x08000401L,0x00000409L,0x08000409L,\n0x00020001L,0x08020001L,0x00020009L,0x08020009L,\n0x00020401L,0x08020401L,0x00020409L,0x08020409L,\n0x02000000L,0x0A000000L,0x02000008L,0x0A000008L,\n0x02000400L,0x0A000400L,0x02000408L,0x0A000408L,\n0x02020000L,0x0A020000L,0x02020008L,0x0A020008L,\n0x02020400L,0x0A020400L,0x02020408L,0x0A020408L,\n0x02000001L,0x0A000001L,0x02000009L,0x0A000009L,\n0x02000401L,0x0A000401L,0x02000409L,0x0A000409L,\n0x02020001L,0x0A020001L,0x02020009L,0x0A020009L,\n0x02020401L,0x0A020401L,0x02020409L,0x0A020409L,\n},{\n/* for D bits (numbered as per FIPS 46) 16 17 18 19 20 21 */\n0x00000000L,0x00000100L,0x00080000L,0x00080100L,\n0x01000000L,0x01000100L,0x01080000L,0x01080100L,\n0x00000010L,0x00000110L,0x00080010L,0x00080110L,\n0x01000010L,0x01000110L,0x01080010L,0x01080110L,\n0x00200000L,0x00200100L,0x00280000L,0x00280100L,\n0x01200000L,0x01200100L,0x01280000L,0x01280100L,\n0x00200010L,0x00200110L,0x00280010L,0x00280110L,\n0x01200010L,0x01200110L,0x01280010L,0x01280110L,\n0x00000200L,0x00000300L,0x00080200L,0x00080300L,\n0x01000200L,0x01000300L,0x01080200L,0x01080300L,\n0x00000210L,0x00000310L,0x00080210L,0x00080310L,\n0x01000210L,0x01000310L,0x01080210L,0x01080310L,\n0x00200200L,0x00200300L,0x00280200L,0x00280300L,\n0x01200200L,0x01200300L,0x01280200L,0x01280300L,\n0x00200210L,0x00200310L,0x00280210L,0x00280310L,\n0x01200210L,0x01200310L,0x01280210L,0x01280310L,\n},{\n/* for D bits (numbered as per FIPS 46) 22 23 24 25 27 28 */\n0x00000000L,0x04000000L,0x00040000L,0x04040000L,\n0x00000002L,0x04000002L,0x00040002L,0x04040002L,\n0x00002000L,0x04002000L,0x00042000L,0x04042000L,\n0x00002002L,0x04002002L,0x00042002L,0x04042002L,\n0x00000020L,0x04000020L,0x00040020L,0x04040020L,\n0x00000022L,0x04000022L,0x00040022L,0x04040022L,\n0x00002020L,0x04002020L,0x00042020L,0x04042020L,\n0x00002022L,0x04002022L,0x00042022L,0x04042022L,\n0x00000800L,0x04000800L,0x00040800L,0x04040800L,\n0x00000802L,0x04000802L,0x00040802L,0x04040802L,\n0x00002800L,0x04002800L,0x00042800L,0x04042800L,\n0x00002802L,0x04002802L,0x00042802L,0x04042802L,\n0x00000820L,0x04000820L,0x00040820L,0x04040820L,\n0x00000822L,0x04000822L,0x00040822L,0x04040822L,\n0x00002820L,0x04002820L,0x00042820L,0x04042820L,\n0x00002822L,0x04002822L,0x00042822L,0x04042822L,\n}};\n"
  },
  {
    "path": "itl80211/openbsd/crypto/spr.h",
    "content": "/*\t$OpenBSD: spr.h,v 1.2 2002/10/27 13:24:26 miod Exp $\t*/\n\n/* lib/des/spr.h */\n/* Copyright (C) 1995 Eric Young (eay@mincom.oz.au)\n * All rights reserved.\n * \n * This file is part of an SSL implementation written\n * by Eric Young (eay@mincom.oz.au).\n * The implementation was written so as to conform with Netscapes SSL\n * specification.  This library and applications are\n * FREE FOR COMMERCIAL AND NON-COMMERCIAL USE\n * as long as the following conditions are aheared to.\n * \n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.  If this code is used in a product,\n * Eric Young should be given attribution as the author of the parts used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    This product includes software developed by Eric Young (eay@mincom.oz.au)\n * \n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n * \n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n\nstatic const u_int32_t des_SPtrans[8][64]={\n{\n/* nibble 0 */\n0x00820200L, 0x00020000L, 0x80800000L, 0x80820200L,\n0x00800000L, 0x80020200L, 0x80020000L, 0x80800000L,\n0x80020200L, 0x00820200L, 0x00820000L, 0x80000200L,\n0x80800200L, 0x00800000L, 0x00000000L, 0x80020000L,\n0x00020000L, 0x80000000L, 0x00800200L, 0x00020200L,\n0x80820200L, 0x00820000L, 0x80000200L, 0x00800200L,\n0x80000000L, 0x00000200L, 0x00020200L, 0x80820000L,\n0x00000200L, 0x80800200L, 0x80820000L, 0x00000000L,\n0x00000000L, 0x80820200L, 0x00800200L, 0x80020000L,\n0x00820200L, 0x00020000L, 0x80000200L, 0x00800200L,\n0x80820000L, 0x00000200L, 0x00020200L, 0x80800000L,\n0x80020200L, 0x80000000L, 0x80800000L, 0x00820000L,\n0x80820200L, 0x00020200L, 0x00820000L, 0x80800200L,\n0x00800000L, 0x80000200L, 0x80020000L, 0x00000000L,\n0x00020000L, 0x00800000L, 0x80800200L, 0x00820200L,\n0x80000000L, 0x80820000L, 0x00000200L, 0x80020200L,\n},{\n/* nibble 1 */\n0x10042004L, 0x00000000L, 0x00042000L, 0x10040000L,\n0x10000004L, 0x00002004L, 0x10002000L, 0x00042000L,\n0x00002000L, 0x10040004L, 0x00000004L, 0x10002000L,\n0x00040004L, 0x10042000L, 0x10040000L, 0x00000004L,\n0x00040000L, 0x10002004L, 0x10040004L, 0x00002000L,\n0x00042004L, 0x10000000L, 0x00000000L, 0x00040004L,\n0x10002004L, 0x00042004L, 0x10042000L, 0x10000004L,\n0x10000000L, 0x00040000L, 0x00002004L, 0x10042004L,\n0x00040004L, 0x10042000L, 0x10002000L, 0x00042004L,\n0x10042004L, 0x00040004L, 0x10000004L, 0x00000000L,\n0x10000000L, 0x00002004L, 0x00040000L, 0x10040004L,\n0x00002000L, 0x10000000L, 0x00042004L, 0x10002004L,\n0x10042000L, 0x00002000L, 0x00000000L, 0x10000004L,\n0x00000004L, 0x10042004L, 0x00042000L, 0x10040000L,\n0x10040004L, 0x00040000L, 0x00002004L, 0x10002000L,\n0x10002004L, 0x00000004L, 0x10040000L, 0x00042000L,\n},{\n/* nibble 2 */\n0x41000000L, 0x01010040L, 0x00000040L, 0x41000040L,\n0x40010000L, 0x01000000L, 0x41000040L, 0x00010040L,\n0x01000040L, 0x00010000L, 0x01010000L, 0x40000000L,\n0x41010040L, 0x40000040L, 0x40000000L, 0x41010000L,\n0x00000000L, 0x40010000L, 0x01010040L, 0x00000040L,\n0x40000040L, 0x41010040L, 0x00010000L, 0x41000000L,\n0x41010000L, 0x01000040L, 0x40010040L, 0x01010000L,\n0x00010040L, 0x00000000L, 0x01000000L, 0x40010040L,\n0x01010040L, 0x00000040L, 0x40000000L, 0x00010000L,\n0x40000040L, 0x40010000L, 0x01010000L, 0x41000040L,\n0x00000000L, 0x01010040L, 0x00010040L, 0x41010000L,\n0x40010000L, 0x01000000L, 0x41010040L, 0x40000000L,\n0x40010040L, 0x41000000L, 0x01000000L, 0x41010040L,\n0x00010000L, 0x01000040L, 0x41000040L, 0x00010040L,\n0x01000040L, 0x00000000L, 0x41010000L, 0x40000040L,\n0x41000000L, 0x40010040L, 0x00000040L, 0x01010000L,\n},{\n/* nibble 3 */\n0x00100402L, 0x04000400L, 0x00000002L, 0x04100402L,\n0x00000000L, 0x04100000L, 0x04000402L, 0x00100002L,\n0x04100400L, 0x04000002L, 0x04000000L, 0x00000402L,\n0x04000002L, 0x00100402L, 0x00100000L, 0x04000000L,\n0x04100002L, 0x00100400L, 0x00000400L, 0x00000002L,\n0x00100400L, 0x04000402L, 0x04100000L, 0x00000400L,\n0x00000402L, 0x00000000L, 0x00100002L, 0x04100400L,\n0x04000400L, 0x04100002L, 0x04100402L, 0x00100000L,\n0x04100002L, 0x00000402L, 0x00100000L, 0x04000002L,\n0x00100400L, 0x04000400L, 0x00000002L, 0x04100000L,\n0x04000402L, 0x00000000L, 0x00000400L, 0x00100002L,\n0x00000000L, 0x04100002L, 0x04100400L, 0x00000400L,\n0x04000000L, 0x04100402L, 0x00100402L, 0x00100000L,\n0x04100402L, 0x00000002L, 0x04000400L, 0x00100402L,\n0x00100002L, 0x00100400L, 0x04100000L, 0x04000402L,\n0x00000402L, 0x04000000L, 0x04000002L, 0x04100400L,\n},{\n/* nibble 4 */\n0x02000000L, 0x00004000L, 0x00000100L, 0x02004108L,\n0x02004008L, 0x02000100L, 0x00004108L, 0x02004000L,\n0x00004000L, 0x00000008L, 0x02000008L, 0x00004100L,\n0x02000108L, 0x02004008L, 0x02004100L, 0x00000000L,\n0x00004100L, 0x02000000L, 0x00004008L, 0x00000108L,\n0x02000100L, 0x00004108L, 0x00000000L, 0x02000008L,\n0x00000008L, 0x02000108L, 0x02004108L, 0x00004008L,\n0x02004000L, 0x00000100L, 0x00000108L, 0x02004100L,\n0x02004100L, 0x02000108L, 0x00004008L, 0x02004000L,\n0x00004000L, 0x00000008L, 0x02000008L, 0x02000100L,\n0x02000000L, 0x00004100L, 0x02004108L, 0x00000000L,\n0x00004108L, 0x02000000L, 0x00000100L, 0x00004008L,\n0x02000108L, 0x00000100L, 0x00000000L, 0x02004108L,\n0x02004008L, 0x02004100L, 0x00000108L, 0x00004000L,\n0x00004100L, 0x02004008L, 0x02000100L, 0x00000108L,\n0x00000008L, 0x00004108L, 0x02004000L, 0x02000008L,\n},{\n/* nibble 5 */\n0x20000010L, 0x00080010L, 0x00000000L, 0x20080800L,\n0x00080010L, 0x00000800L, 0x20000810L, 0x00080000L,\n0x00000810L, 0x20080810L, 0x00080800L, 0x20000000L,\n0x20000800L, 0x20000010L, 0x20080000L, 0x00080810L,\n0x00080000L, 0x20000810L, 0x20080010L, 0x00000000L,\n0x00000800L, 0x00000010L, 0x20080800L, 0x20080010L,\n0x20080810L, 0x20080000L, 0x20000000L, 0x00000810L,\n0x00000010L, 0x00080800L, 0x00080810L, 0x20000800L,\n0x00000810L, 0x20000000L, 0x20000800L, 0x00080810L,\n0x20080800L, 0x00080010L, 0x00000000L, 0x20000800L,\n0x20000000L, 0x00000800L, 0x20080010L, 0x00080000L,\n0x00080010L, 0x20080810L, 0x00080800L, 0x00000010L,\n0x20080810L, 0x00080800L, 0x00080000L, 0x20000810L,\n0x20000010L, 0x20080000L, 0x00080810L, 0x00000000L,\n0x00000800L, 0x20000010L, 0x20000810L, 0x20080800L,\n0x20080000L, 0x00000810L, 0x00000010L, 0x20080010L,\n},{\n/* nibble 6 */\n0x00001000L, 0x00000080L, 0x00400080L, 0x00400001L,\n0x00401081L, 0x00001001L, 0x00001080L, 0x00000000L,\n0x00400000L, 0x00400081L, 0x00000081L, 0x00401000L,\n0x00000001L, 0x00401080L, 0x00401000L, 0x00000081L,\n0x00400081L, 0x00001000L, 0x00001001L, 0x00401081L,\n0x00000000L, 0x00400080L, 0x00400001L, 0x00001080L,\n0x00401001L, 0x00001081L, 0x00401080L, 0x00000001L,\n0x00001081L, 0x00401001L, 0x00000080L, 0x00400000L,\n0x00001081L, 0x00401000L, 0x00401001L, 0x00000081L,\n0x00001000L, 0x00000080L, 0x00400000L, 0x00401001L,\n0x00400081L, 0x00001081L, 0x00001080L, 0x00000000L,\n0x00000080L, 0x00400001L, 0x00000001L, 0x00400080L,\n0x00000000L, 0x00400081L, 0x00400080L, 0x00001080L,\n0x00000081L, 0x00001000L, 0x00401081L, 0x00400000L,\n0x00401080L, 0x00000001L, 0x00001001L, 0x00401081L,\n0x00400001L, 0x00401080L, 0x00401000L, 0x00001001L,\n},{\n/* nibble 7 */\n0x08200020L, 0x08208000L, 0x00008020L, 0x00000000L,\n0x08008000L, 0x00200020L, 0x08200000L, 0x08208020L,\n0x00000020L, 0x08000000L, 0x00208000L, 0x00008020L,\n0x00208020L, 0x08008020L, 0x08000020L, 0x08200000L,\n0x00008000L, 0x00208020L, 0x00200020L, 0x08008000L,\n0x08208020L, 0x08000020L, 0x00000000L, 0x00208000L,\n0x08000000L, 0x00200000L, 0x08008020L, 0x08200020L,\n0x00200000L, 0x00008000L, 0x08208000L, 0x00000020L,\n0x00200000L, 0x00008000L, 0x08000020L, 0x08208020L,\n0x00008020L, 0x08000000L, 0x00000000L, 0x00208000L,\n0x08200020L, 0x08008020L, 0x08008000L, 0x00200020L,\n0x08208000L, 0x00000020L, 0x00200020L, 0x08008000L,\n0x08208020L, 0x00200000L, 0x08200000L, 0x08000020L,\n0x00208000L, 0x00008020L, 0x08008020L, 0x08200000L,\n0x00000020L, 0x08208000L, 0x00208020L, 0x00000000L,\n0x08000000L, 0x08200020L, 0x00008000L, 0x00208020L,\n}};\n"
  },
  {
    "path": "itl80211/openbsd/net80211/CTimeout.cpp",
    "content": "//\n//  CTimeout.cpp\n//  AppleIntelWifiAdapter\n//\n//  Created by 钟先耀 on 2020/1/30.\n//  Copyright © 2020 钟先耀. All rights reserved.\n//\n\n/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n\n#include <sys/CTimeout.hpp>\n\nvoid CTimeout::timeoutOccurred(OSObject* owner, IOTimerEventSource* timer)\n{\n//    IOLog(\"itlwm %s\\n\", __FUNCTION__);\n    if (owner == NULL) {\n        IOLog(\"itlwm tm owner == NULL!!!\\n\");\n    }\n    CTimeout *tm = OSDynamicCast(CTimeout, owner);\n    if (tm == NULL) {\n        IOLog(\"itlwm tm == NULL!!!\\n\");\n        return;\n    }\n    //callback\n    tm->isPending = false;\n    tm->to_func(tm->to_arg);\n}\n\nIOReturn CTimeout::timeout_add_msec(OSObject *target, void *arg0, void *arg1, void *arg2, void *arg3)\n{\n    IOWorkLoop *wl = (IOWorkLoop*)arg1;\n    int msecs = *(int*)arg2;\n    CTimeout **ccto = (CTimeout **)arg0;\n    \n    if (ccto == NULL || *ccto == NULL) {\n        return kIOReturnError;\n    }\n    CTimeout *cto = *ccto;\n    if (cto->tm == NULL) {\n        cto->tm = IOTimerEventSource::timerEventSource(cto, &CTimeout::timeoutOccurred);\n        if (cto->tm == NULL) {\n            return kIOReturnError;\n        }\n        cto->tm->enable();\n        wl->addEventSource(cto->tm);\n    }\n    cto->tm->setTimeoutMS(msecs);\n    cto->isPending = true;\n    return kIOReturnSuccess;\n}\n\nIOReturn CTimeout::timeout_del(OSObject *target, void *arg0, void *arg1, void *arg2, void *arg3)\n{\n    CTimeout **ccto = (CTimeout **)arg0;\n    if (ccto == NULL || *ccto == NULL) {\n        return kIOReturnSuccess;\n    }\n    CTimeout *cto = *ccto;\n    if (cto->tm == NULL || !cto->isPending) {\n        return kIOReturnSuccess;\n    }\n    cto->tm->cancelTimeout();\n    cto->isPending = false;\n    return kIOReturnSuccess;\n}\n\nIOReturn CTimeout::timeout_free(OSObject *target, void *arg0, void *arg1, void *arg2, void *arg3)\n{\n    CTimeout **cto = (CTimeout **)arg0;\n    IOWorkLoop *wl = (IOWorkLoop*)arg1;\n    if (cto == NULL || *cto == NULL) {\n        return kIOReturnSuccess;\n    }\n    CTimeout *tm = *cto;\n    if (tm->tm != NULL) {\n        wl->removeEventSource(tm->tm);\n        tm->tm->release();\n        tm->tm = NULL;\n    }\n    tm->release();\n    *cto = NULL;\n    return kIOReturnSuccess;\n}\n\ntypedef void (*callback)(void *);\n\nIOReturn CTimeout::timeout_set(OSObject *target, void *arg0, void *arg1, void *arg2, void *arg3)\n{\n    CTimeout *tm;\n    CTimeout **cto = (CTimeout **)arg0;\n    if (cto == NULL) {\n        return kIOReturnError;\n    }\n    if ((*cto) == NULL) {\n        *cto = new CTimeout;\n    }\n    tm = *cto;\n    tm->isPending = false;\n    tm->to_func = (callback)arg1;\n    tm->to_arg = arg2;\n    return kIOReturnSuccess;\n}\n\nIOReturn CTimeout::timeout_pending(OSObject *target, void *arg0, void *arg1, void *arg2, void *arg3)\n{\n    CTimeout **cto = (CTimeout **)arg0;\n    CTimeout *tm;\n    if (cto == NULL) {\n        return kIOReturnError;\n    }\n    tm = *cto;\n    if (tm != NULL && tm->isPending) {\n        return kIOReturnSuccess;\n    }\n    return kIOReturnError;\n}\n"
  },
  {
    "path": "itl80211/openbsd/net80211/_string.c",
    "content": "//\n//  _string.h\n//  AppleIntelWifiAdapter\n//\n//  Created by 钟先耀 on 2020/1/30.\n//  Copyright © 2020 钟先耀. All rights reserved.\n//\n\n/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n\n#ifndef _string_c\n#define _string_c\n\n#include <string.h>\n#include <sys/syslog.h>\n#include <IOKit/IOLib.h>\n\nint timingsafe_bcmp(const void *b1, const void *b2, size_t n)\n{\n    const unsigned char *p1 = (const unsigned char *)b1, *p2 = (const unsigned char *)b2;\n    int ret = 0;\n\n    for (; n > 0; n--)\n        ret |= *p1++ ^ *p2++;\n    return (ret != 0);\n}\n\n\n\n\n#endif /* _string_c */\n"
  },
  {
    "path": "itl80211/openbsd/net80211/ieee80211.c",
    "content": "/*\n * Copyright (C) 2020  钟先耀\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n */\n/*    $OpenBSD: ieee80211.c,v 1.83 2020/04/08 09:34:29 stsp Exp $    */\n/*    $NetBSD: ieee80211.c,v 1.19 2004/06/06 05:45:29 dyoung Exp $    */\n\n/*-\n * Copyright (c) 2001 Atsushi Onoe\n * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. The name of the author may not be used to endorse or promote products\n *    derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*\n * IEEE 802.11 generic handler\n */\n\n#include <sys/param.h>\n#include <sys/systm.h>\n#include <sys/mbuf.h>\n#include <sys/kernel.h>\n#include <sys/socket.h>\n#include <sys/sockio.h>\n#include <sys/endian.h>\n#include <sys/errno.h>\n#include <sys/sysctl.h>\n\n#include <net/if.h>\n#include <net/if_dl.h>\n#include <sys/_if_media.h>\n\n#if NBPFILTER > 0\n#include <net/bpf.h>\n#endif\n\n#include <netinet/in.h>\n#include <netinet/if_ether.h>\n\n#include <net80211/ieee80211_var.h>\n#include <net80211/ieee80211_priv.h>\n\n#ifdef IEEE80211_DEBUG\nint\tieee80211_debug = 0;\n#endif\n\n///compat for undefined symbols\nint _stop(struct kmod_info*, void*) {\n    IOLog(\"_stop(struct kmod_info*, void*) has been invoked\\n\");\n    return 0;\n};\nint _start(struct kmod_info*, void*) {\n    IOLog(\"_start(struct kmod_info*, void*) has been invoked\\n\");\n    return 0;\n};\n///\n\nint ieee80211_cache_size = IEEE80211_CACHE_SIZE;\n\nvoid ieee80211_setbasicrates(struct ieee80211com *);\nint ieee80211_findrate(struct ieee80211com *, enum ieee80211_phymode, int);\nvoid ieee80211_configure_ampdu_tx(struct ieee80211com *, int);\n\nvoid\nieee80211_begin_bgscan(struct _ifnet *ifp)\n{\n    struct ieee80211com *ic = (struct ieee80211com *)ifp;\n    \n    if (ic->ic_state != IEEE80211_S_RUN || ic->ic_mgt_timer != 0)\n        return;\n    \n    if ((ic->ic_flags & IEEE80211_F_RSNON) && !ic->ic_bss->ni_port_valid)\n        return;\n    \n    if ((ic->ic_flags & IEEE80211_F_BGSCAN)) {\n        //clear disable flag, because we need to switch a better wifi now.\n        ic->ic_flags &= ~IEEE80211_F_DISABLE_BG_AUTO_CONNECT;\n        return;\n    }\n    \n    if (ic->ic_bgscan_start != NULL && ic->ic_bgscan_start(ic) == 0) {\n        /*\n         * Free the nodes table to ensure we get an up-to-date view\n         * of APs around us. In particular, we need to kick out the\n         * AP we are associated to. Otherwise, our current AP might\n         * stay cached if it is turned off while we are scanning, and\n         * we could end up picking a now non-existent AP over and over.\n         */\n        ieee80211_free_allnodes(ic, 0 /* keep ic->ic_bss */);\n        \n        ic->ic_flags |= IEEE80211_F_BGSCAN;\n        ic->ic_flags &= ~IEEE80211_F_DISABLE_BG_AUTO_CONNECT;\n        if (ifp->if_flags & IFF_DEBUG)\n            XYLog(\"%s: begin background scan\\n\", ifp->if_xname);\n        \n        /* Driver calls ieee80211_end_scan() when done. */\n    }\n}\n\nvoid\nieee80211_begin_cache_bgscan(struct _ifnet *ifp)\n{\n    struct ieee80211com *ic = (struct ieee80211com *)ifp;\n    struct timeval tv;\n    \n    if ((ic->ic_flags & IEEE80211_F_BGSCAN) ||\n        ic->ic_state != IEEE80211_S_RUN || ic->ic_mgt_timer != 0)\n        return;\n    \n    if ((ic->ic_flags & IEEE80211_F_RSNON) && !ic->ic_bss->ni_port_valid)\n        return;\n    \n    ic->ic_flags |= IEEE80211_F_DISABLE_BG_AUTO_CONNECT;\n    \n    //if last cache scan is 5 minutes ago, clear the nodes and rescan.\n    microtime(&tv);\n    if (ic->ic_last_cache_scan_ts > 0 && tv.tv_sec - ic->ic_last_cache_scan_ts > 5 * 60) {\n        ieee80211_free_allnodes(ic, 0);\n    }\n    ic->ic_last_cache_scan_ts = tv.tv_sec;\n    \n    if (ic->ic_bgscan_start != NULL && ic->ic_bgscan_start(ic) == 0) {\n        ic->ic_flags |= IEEE80211_F_BGSCAN;\n        DPRINTF((\"%s: begin cache background scan\\n\", ifp->if_xname));\n    }\n}\n\nvoid\nieee80211_bgscan_timeout(void *arg)\n{\n    struct _ifnet *ifp = (struct _ifnet *)arg;\n    \n    ieee80211_begin_bgscan(ifp);\n}\n\nvoid\nieee80211_channel_init(struct _ifnet *ifp)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct ieee80211com *ic = (struct ieee80211com *)ifp;\n    struct ieee80211_channel *c;\n    int i;\n    \n    /*\n     * Fill in 802.11 available channel set, mark\n     * all available channels as active, and pick\n     * a default channel if not already specified.\n     */\n    memset(ic->ic_chan_avail, 0, sizeof(ic->ic_chan_avail));\n    ic->ic_modecaps |= 1<<IEEE80211_MODE_AUTO;\n    for (i = 0; i <= IEEE80211_CHAN_MAX; i++) {\n        c = &ic->ic_channels[i];\n        if (c->ic_flags) {\n            /*\n             * Verify driver passed us valid data.\n             */\n            if (i != ieee80211_chan2ieee(ic, c)) {\n                XYLog(\"%s: bad channel ignored; \"\n                      \"freq %u flags %x number %u\\n\",\n                      ifp->if_xname, c->ic_freq, c->ic_flags,\n                      i);\n                c->ic_flags = 0;    /* NB: remove */\n                continue;\n            }\n            setbit(ic->ic_chan_avail, i);\n            /*\n             * Identify mode capabilities.\n             */\n            if (IEEE80211_IS_CHAN_A(c))\n                ic->ic_modecaps |= 1<<IEEE80211_MODE_11A;\n            if (IEEE80211_IS_CHAN_B(c))\n                ic->ic_modecaps |= 1<<IEEE80211_MODE_11B;\n            if (IEEE80211_IS_CHAN_PUREG(c))\n                ic->ic_modecaps |= 1<<IEEE80211_MODE_11G;\n            if (IEEE80211_IS_CHAN_N(c))\n                ic->ic_modecaps |= 1<<IEEE80211_MODE_11N;\n            if (IEEE80211_IS_CHAN_AC(c))\n                ic->ic_modecaps |= 1<<IEEE80211_MODE_11AC | 1<<IEEE80211_MODE_11AX;\n        }\n    }\n    /* validate ic->ic_curmode */\n    if ((ic->ic_modecaps & (1<<ic->ic_curmode)) == 0)\n        ic->ic_curmode = IEEE80211_MODE_AUTO;\n    ic->ic_des_chan = IEEE80211_CHAN_ANYC;    /* any channel is ok */\n}\n\nvoid\nieee80211_ifattach(struct _ifnet *ifp, IOEthernetController *controller)\n{\n    IOLog(\"ieee80211_ifattach\\n\");\n    struct ieee80211com *ic = (struct ieee80211com *)ifp;\n    \n    ifp->controller = controller;\n    ifq_init(&ifp->if_snd, ifp, 2048);\n    memcpy(((struct arpcom *)ifp)->ac_enaddr, ic->ic_myaddr,\n           ETHER_ADDR_LEN);\n    if (ifp->if_sadl) {\n        ::free(ifp->if_sadl);\n    }\n    ifp->if_sadl = (struct sockaddr_dl *)::malloc(sizeof(struct sockaddr_dl), 0, 0);\n    memcpy(LLADDR(ifp->if_sadl), ic->ic_myaddr, ETHER_ADDR_LEN);\n    \n    ifp->if_output = ieee80211_output;\n    \n#if NBPFILTER > 0\n    bpfattach(&ic->ic_rawbpf, ifp, DLT_IEEE802_11,\n              sizeof(struct ieee80211_frame_addr4));\n#endif\n    ieee80211_crypto_attach(ifp);\n    \n    ieee80211_channel_init(ifp);\n    \n    /* IEEE 802.11 defines a MTU >= 2290 */\n    //\tifp->if_capabilities |= IFCAP_VLAN_MTU;\n    \n    ieee80211_setbasicrates(ic);\n    (void)ieee80211_setmode(ic, (enum ieee80211_phymode)ic->ic_curmode);\n    \n    if (ic->ic_lintval == 0)\n        ic->ic_lintval = 100;\t\t/* default sleep */\n    ic->ic_bmissthres = IEEE80211_BEACON_MISS_THRES;\n    ic->ic_dtim_period = 1;\t/* all TIMs are DTIMs */\n    \n    ieee80211_node_attach(ifp);\n    ieee80211_proto_attach(ifp);\n    \n    //\tif_addgroup(ifp, \"wlan\");\n    //\tifp->if_priority = IF_WIRELESS_DEFAULT_PRIORITY;\n    \n    ieee80211_set_link_state(ic, LINK_STATE_DOWN);\n    \n    timeout_set(&ic->ic_bgscan_timeout, ieee80211_bgscan_timeout, ifp);\n}\n\nvoid\nieee80211_ifdetach(struct _ifnet *ifp)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct ieee80211com *ic = (struct ieee80211com *)ifp;\n    \n    timeout_del(&ic->ic_bgscan_timeout);\n    timeout_free(&ic->ic_bgscan_timeout);\n    ieee80211_proto_detach(ifp);\n    ieee80211_crypto_detach(ifp);\n    ieee80211_node_detach(ifp);\n    ifmedia_delete_instance(&ic->ic_media, IFM_INST_ANY);\n    ifq_destroy(&ifp->if_snd);\n    if (ifp->if_slowtimo) {\n        ifp->if_slowtimo->release();\n        ifp->if_slowtimo = NULL;\n    }\n    if (ifp->if_sadl) {\n        ::free(ifp->if_sadl);\n        ifp->if_sadl = NULL;\n    }\n    ifp->netStat = NULL;\n    ifp->controller = NULL;\n    ifp->iface = NULL;\n}\n\n/*\n * Convert MHz frequency to IEEE channel number.\n */\nu_int\nieee80211_mhz2ieee(u_int freq, u_int flags)\n{\n    if (flags & IEEE80211_CHAN_2GHZ) {    /* 2GHz band */\n        if (freq == 2484)\n            return 14;\n        if (freq < 2484)\n            return (freq - 2407) / 5;\n        else\n            return 15 + ((freq - 2512) / 20);\n    } else if (flags & IEEE80211_CHAN_5GHZ) {    /* 5GHz band */\n        return (freq - 5000) / 5;\n    } else {                /* either, guess */\n        if (freq == 2484)\n            return 14;\n        if (freq < 2484)\n            return (freq - 2407) / 5;\n        if (freq < 5000)\n            return 15 + ((freq - 2512) / 20);\n        return (freq - 5000) / 5;\n    }\n}\n\n/*\n * Convert channel to IEEE channel number.\n */\nu_int\nieee80211_chan2ieee(struct ieee80211com *ic, const struct ieee80211_channel *c)\n{\n    struct _ifnet *ifp = &ic->ic_if;\n    if (ic->ic_channels <= c && c <= &ic->ic_channels[IEEE80211_CHAN_MAX])\n        return c - ic->ic_channels;\n    else if (c == IEEE80211_CHAN_ANYC)\n        return IEEE80211_CHAN_ANY;\n    \n    XYLog(\"严重%s: bogus channel pointer\", ifp->if_xname);\n    return 1;\n}\n\n/*\n * Convert IEEE channel number to MHz frequency.\n */\nu_int\nieee80211_ieee2mhz(u_int chan, u_int flags)\n{\n    if (flags & IEEE80211_CHAN_2GHZ) {    /* 2GHz band */\n        if (chan == 14)\n            return 2484;\n        if (chan < 14)\n            return 2407 + chan*5;\n        else\n            return 2512 + ((chan-15)*20);\n    } else if (flags & IEEE80211_CHAN_5GHZ) {/* 5GHz band */\n        return 5000 + (chan*5);\n    } else {                /* either, guess */\n        if (chan == 14)\n            return 2484;\n        if (chan < 14)            /* 0-13 */\n            return 2407 + chan*5;\n        if (chan < 27)            /* 15-26 */\n            return 2512 + ((chan-15)*20);\n        return 5000 + (chan*5);\n    }\n}\n\nvoid\nieee80211_configure_ampdu_tx(struct ieee80211com *ic, int enable)\n{\n    if ((ic->ic_caps & IEEE80211_C_TX_AMPDU) == 0)\n        return;\n    \n    /* Sending AMPDUs requires QoS support. */\n    if ((ic->ic_caps & IEEE80211_C_QOS) == 0)\n        return;\n    \n    if (enable)\n        ic->ic_flags |= IEEE80211_F_QOS;\n    else\n        ic->ic_flags &= ~IEEE80211_F_QOS;\n}\n\n/*\n * Setup the media data structures according to the channel and\n * rate tables.  This must be called by the driver after\n * ieee80211_attach and before most anything else.\n */\nvoid\nieee80211_media_init(struct _ifnet *ifp)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n#define    ADD(_ic, _s, _o) \\\nifmedia_add(&(_ic)->ic_media, \\\nIFM_MAKEWORD(IFM_IEEE80211, (_s), (_o), 0), 0, NULL)\n    struct ieee80211com *ic = (struct ieee80211com *)ifp;\n    struct ifmediareq imr;\n    int i, j, mode, rate, maxrate, r;\n    uint64_t mword, mopt;\n    const struct ieee80211_rateset *rs;\n    struct ieee80211_rateset allrates;\n    \n    /*\n     * Do late attach work that must wait for any subclass\n     * (i.e. driver) work such as overriding methods.\n     */\n    ieee80211_node_lateattach(ifp);\n    \n    /*\n     * Fill in media characteristics.\n     */\n    ifmedia_init(&ic->ic_media, 0);\n    maxrate = 0;\n    memset(&allrates, 0, sizeof(allrates));\n    for (mode = IEEE80211_MODE_AUTO; mode <= IEEE80211_MODE_11G; mode++) {\n        static const uint64_t mopts[] = {\n            IFM_AUTO,\n            IFM_IEEE80211_11A,\n            IFM_IEEE80211_11B,\n            IFM_IEEE80211_11G,\n        };\n        if ((ic->ic_modecaps & (1<<mode)) == 0)\n            continue;\n        mopt = mopts[mode];\n        ADD(ic, IFM_AUTO, mopt);    /* e.g. 11a auto */\n#ifndef IEEE80211_STA_ONLY\n        if (ic->ic_caps & IEEE80211_C_IBSS)\n            ADD(ic, IFM_AUTO, mopt | IFM_IEEE80211_IBSS);\n        if (ic->ic_caps & IEEE80211_C_HOSTAP)\n            ADD(ic, IFM_AUTO, mopt | IFM_IEEE80211_HOSTAP);\n        if (ic->ic_caps & IEEE80211_C_AHDEMO)\n            ADD(ic, IFM_AUTO, mopt | IFM_IEEE80211_ADHOC);\n#endif\n        if (ic->ic_caps & IEEE80211_C_MONITOR)\n            ADD(ic, IFM_AUTO, mopt | IFM_IEEE80211_MONITOR);\n        if (mode == IEEE80211_MODE_AUTO)\n            continue;\n        rs = &ic->ic_sup_rates[mode];\n        for (i = 0; i < rs->rs_nrates; i++) {\n            rate = rs->rs_rates[i];\n            mword = ieee80211_rate2media(ic, rate, (enum ieee80211_phymode)mode);\n            if (mword == 0)\n                continue;\n            ADD(ic, mword, mopt);\n#ifndef IEEE80211_STA_ONLY\n            if (ic->ic_caps & IEEE80211_C_IBSS)\n                ADD(ic, mword, mopt | IFM_IEEE80211_IBSS);\n            if (ic->ic_caps & IEEE80211_C_HOSTAP)\n                ADD(ic, mword, mopt | IFM_IEEE80211_HOSTAP);\n            if (ic->ic_caps & IEEE80211_C_AHDEMO)\n                ADD(ic, mword, mopt | IFM_IEEE80211_ADHOC);\n#endif\n            if (ic->ic_caps & IEEE80211_C_MONITOR)\n                ADD(ic, mword, mopt | IFM_IEEE80211_MONITOR);\n            /*\n             * Add rate to the collection of all rates.\n             */\n            r = rate & IEEE80211_RATE_VAL;\n            for (j = 0; j < allrates.rs_nrates; j++)\n                if (allrates.rs_rates[j] == r)\n                    break;\n            if (j == allrates.rs_nrates) {\n                /* unique, add to the set */\n                allrates.rs_rates[j] = r;\n                allrates.rs_nrates++;\n            }\n            rate = (rate & IEEE80211_RATE_VAL) / 2;\n            if (rate > maxrate)\n                maxrate = rate;\n        }\n    }\n    for (i = 0; i < allrates.rs_nrates; i++) {\n        mword = ieee80211_rate2media(ic, allrates.rs_rates[i],\n                                     IEEE80211_MODE_AUTO);\n        if (mword == 0)\n            continue;\n        mword = IFM_SUBTYPE(mword);    /* remove media options */\n        ADD(ic, mword, 0);\n#ifndef IEEE80211_STA_ONLY\n        if (ic->ic_caps & IEEE80211_C_IBSS)\n            ADD(ic, mword, IFM_IEEE80211_IBSS);\n        if (ic->ic_caps & IEEE80211_C_HOSTAP)\n            ADD(ic, mword, IFM_IEEE80211_HOSTAP);\n        if (ic->ic_caps & IEEE80211_C_AHDEMO)\n            ADD(ic, mword, IFM_IEEE80211_ADHOC);\n#endif\n        if (ic->ic_caps & IEEE80211_C_MONITOR)\n            ADD(ic, mword, IFM_IEEE80211_MONITOR);\n    }\n    \n    if (ic->ic_modecaps & (1 << IEEE80211_MODE_11N)) {\n        mopt = IFM_IEEE80211_11N;\n        ADD(ic, IFM_AUTO, mopt);\n#ifndef IEEE80211_STA_ONLY\n        if (ic->ic_caps & IEEE80211_C_IBSS)\n            ADD(ic, IFM_AUTO, mopt | IFM_IEEE80211_IBSS);\n        if (ic->ic_caps & IEEE80211_C_HOSTAP)\n            ADD(ic, IFM_AUTO, mopt | IFM_IEEE80211_HOSTAP);\n#endif\n        if (ic->ic_caps & IEEE80211_C_MONITOR)\n            ADD(ic, IFM_AUTO, mopt | IFM_IEEE80211_MONITOR);\n        for (i = 0; i < IEEE80211_HT_NUM_MCS; i++) {\n            if (!isset(ic->ic_sup_mcs, i))\n                continue;\n            ADD(ic, IFM_IEEE80211_HT_MCS0 + i, mopt);\n#ifndef IEEE80211_STA_ONLY\n            if (ic->ic_caps & IEEE80211_C_IBSS)\n                ADD(ic, IFM_IEEE80211_HT_MCS0 + i,\n                    mopt | IFM_IEEE80211_IBSS);\n            if (ic->ic_caps & IEEE80211_C_HOSTAP)\n                ADD(ic, IFM_IEEE80211_HT_MCS0 + i,\n                    mopt | IFM_IEEE80211_HOSTAP);\n#endif\n            if (ic->ic_caps & IEEE80211_C_MONITOR)\n                ADD(ic, IFM_IEEE80211_HT_MCS0 + i,\n                    mopt | IFM_IEEE80211_MONITOR);\n        }\n        ic->ic_flags |= IEEE80211_F_HTON; /* enable 11n by default */\n        ieee80211_configure_ampdu_tx(ic, 1);\n    }\n    \n    if (ic->ic_modecaps & (1 << IEEE80211_MODE_11AC)) {\n        mopt = IFM_IEEE80211_11AC;\n        ADD(ic, IFM_AUTO, mopt);\n#ifndef IEEE80211_STA_ONLY\n        if (ic->ic_caps & IEEE80211_C_IBSS)\n            ADD(ic, IFM_AUTO, mopt | IFM_IEEE80211_IBSS);\n        if (ic->ic_caps & IEEE80211_C_HOSTAP)\n            ADD(ic, IFM_AUTO, mopt | IFM_IEEE80211_HOSTAP);\n#endif\n        if (ic->ic_caps & IEEE80211_C_MONITOR)\n            ADD(ic, IFM_AUTO, mopt | IFM_IEEE80211_MONITOR);\n        for (i = 0; i < IEEE80211_VHT_NUM_MCS; i++) {\n#if 0\n            /* TODO: Obtain VHT MCS information from VHT CAP IE. */\n            if (!vht_mcs_supported)\n                continue;\n#endif\n            ADD(ic, IFM_IEEE80211_VHT_MCS0 + i, mopt);\n#ifndef IEEE80211_STA_ONLY\n            if (ic->ic_caps & IEEE80211_C_IBSS)\n                ADD(ic, IFM_IEEE80211_VHT_MCS0 + i,\n                    mopt | IFM_IEEE80211_IBSS);\n            if (ic->ic_caps & IEEE80211_C_HOSTAP)\n                ADD(ic, IFM_IEEE80211_VHT_MCS0 + i,\n                    mopt | IFM_IEEE80211_HOSTAP);\n#endif\n            if (ic->ic_caps & IEEE80211_C_MONITOR)\n                ADD(ic, IFM_IEEE80211_VHT_MCS0 + i,\n                    mopt | IFM_IEEE80211_MONITOR);\n        }\n        ieee80211_configure_ampdu_tx(ic, 1);\n    }\n    if (ic->ic_modecaps & (1 << IEEE80211_MODE_11AX)) {\n        mopt = IFM_IEEE80211_11AX;\n        ADD(ic, IFM_AUTO, mopt);\n        for (i = 0; i < IEEE80211_VHT_NUM_MCS; i++) {\n#if 0\n            /* TODO: Obtain VHT MCS information from VHT CAP IE. */\n            if (!vht_mcs_supported)\n                continue;\n#endif\n            ADD(ic, IFM_IEEE80211_VHT_MCS0 + i, mopt);\n#ifndef IEEE80211_STA_ONLY\n            if (ic->ic_caps & IEEE80211_C_IBSS)\n                ADD(ic, IFM_IEEE80211_VHT_MCS0 + i,\n                    mopt | IFM_IEEE80211_IBSS);\n            if (ic->ic_caps & IEEE80211_C_HOSTAP)\n                ADD(ic, IFM_IEEE80211_VHT_MCS0 + i,\n                    mopt | IFM_IEEE80211_HOSTAP);\n#endif\n            if (ic->ic_caps & IEEE80211_C_MONITOR)\n                ADD(ic, IFM_IEEE80211_VHT_MCS0 + i,\n                    mopt | IFM_IEEE80211_MONITOR);\n        }\n        ieee80211_configure_ampdu_tx(ic, 1);\n    }\n    \n    ieee80211_media_status(ifp, &imr);\n    ifmedia_set(&ic->ic_media, imr.ifm_active);\n    \n    //\tif (maxrate)\n    //\t\tifp->if_baudrate = IF_Mbps(maxrate);\n    \n    \n#undef ADD\n}\n\nint\nieee80211_findrate(struct ieee80211com *ic, enum ieee80211_phymode mode,\n                   int rate)\n{\n#define    IEEERATE(_ic,_m,_i) \\\n((_ic)->ic_sup_rates[_m].rs_rates[_i] & IEEE80211_RATE_VAL)\n    int i, nrates = ic->ic_sup_rates[mode].rs_nrates;\n    for (i = 0; i < nrates; i++)\n        if (IEEERATE(ic, mode, i) == rate)\n            return i;\n    return -1;\n#undef IEEERATE\n}\n\n/*\n * Handle a media change request.\n */\nint\nieee80211_media_change(struct _ifnet *ifp)\n{\n    struct ieee80211com *ic = (struct ieee80211com *)ifp;\n    struct ifmedia_entry *ime;\n    enum ieee80211_opmode newopmode;\n    enum ieee80211_phymode newphymode;\n    int i, j, newrate, error = 0;\n    \n    ime = ic->ic_media.ifm_cur;\n    /*\n     * First, identify the phy mode.\n     */\n    switch (IFM_MODE(ime->ifm_media)) {\n        case IFM_IEEE80211_11A:\n            newphymode = IEEE80211_MODE_11A;\n            break;\n        case IFM_IEEE80211_11B:\n            newphymode = IEEE80211_MODE_11B;\n            break;\n        case IFM_IEEE80211_11G:\n            newphymode = IEEE80211_MODE_11G;\n            break;\n        case IFM_IEEE80211_11N:\n            newphymode = IEEE80211_MODE_11N;\n            break;\n        case IFM_IEEE80211_11AC:\n            newphymode = IEEE80211_MODE_11AC;\n            break;\n        case IFM_IEEE80211_11AX:\n            newphymode = IEEE80211_MODE_11AX;\n            break;\n        case IFM_AUTO:\n            newphymode = IEEE80211_MODE_AUTO;\n            break;\n        default:\n            return EINVAL;\n    }\n    \n    /*\n     * Validate requested mode is available.\n     */\n    if ((ic->ic_modecaps & (1<<newphymode)) == 0)\n        return EINVAL;\n    \n    /*\n     * Next, the fixed/variable rate.\n     */\n    i = -1;\n    if (IFM_SUBTYPE(ime->ifm_media) >= IFM_IEEE80211_VHT_MCS0 &&\n        IFM_SUBTYPE(ime->ifm_media) <= IFM_IEEE80211_VHT_MCS9) {\n        if (((ic->ic_modecaps & (1 << IEEE80211_MODE_11AC)) == 0) && ((ic->ic_modecaps & (1 << IEEE80211_MODE_11AX)) == 0))\n            return EINVAL;\n        if (newphymode != IEEE80211_MODE_AUTO &&\n            newphymode != IEEE80211_MODE_11AC &&\n            newphymode != IEEE80211_MODE_11AX)\n            return EINVAL;\n        i = ieee80211_media2mcs(ime->ifm_media);\n        /* TODO: Obtain VHT MCS information from VHT CAP IE. */\n        if (i == -1 /* || !vht_mcs_supported */)\n            return EINVAL;\n    } else if (IFM_SUBTYPE(ime->ifm_media) >= IFM_IEEE80211_HT_MCS0 &&\n               IFM_SUBTYPE(ime->ifm_media) <= IFM_IEEE80211_HT_MCS76) {\n        if ((ic->ic_modecaps & (1 << IEEE80211_MODE_11N)) == 0)\n            return EINVAL;\n        if (newphymode != IEEE80211_MODE_AUTO &&\n            newphymode != IEEE80211_MODE_11N)\n            return EINVAL;\n        i = ieee80211_media2mcs(ime->ifm_media);\n        if (i == -1 || isclr(ic->ic_sup_mcs, i))\n            return EINVAL;\n    } else if (IFM_SUBTYPE(ime->ifm_media) != IFM_AUTO) {\n        /*\n         * Convert media subtype to rate.\n         */\n        newrate = ieee80211_media2rate(ime->ifm_media);\n        if (newrate == 0)\n            return EINVAL;\n        /*\n         * Check the rate table for the specified/current phy.\n         */\n        if (newphymode == IEEE80211_MODE_AUTO) {\n            /*\n             * In autoselect mode search for the rate.\n             */\n            for (j = IEEE80211_MODE_11A;\n                 j < IEEE80211_MODE_MAX; j++) {\n                if ((ic->ic_modecaps & (1<<j)) == 0)\n                    continue;\n                i = ieee80211_findrate(ic, (enum ieee80211_phymode)j, newrate);\n                if (i != -1) {\n                    /* lock mode too */\n                    newphymode = (enum ieee80211_phymode)j;\n                    break;\n                }\n            }\n        } else {\n            i = ieee80211_findrate(ic, newphymode, newrate);\n        }\n        if (i == -1)            /* mode/rate mismatch */\n            return EINVAL;\n    }\n    /* NB: defer rate setting to later */\n    \n    /*\n     * Deduce new operating mode but don't install it just yet.\n     */\n#ifndef IEEE80211_STA_ONLY\n    if (ime->ifm_media & IFM_IEEE80211_ADHOC)\n        newopmode = IEEE80211_M_AHDEMO;\n    else if (ime->ifm_media & IFM_IEEE80211_HOSTAP)\n        newopmode = IEEE80211_M_HOSTAP;\n    else if (ime->ifm_media & IFM_IEEE80211_IBSS)\n        newopmode = IEEE80211_M_IBSS;\n    else\n#endif\n        if (ime->ifm_media & IFM_IEEE80211_MONITOR)\n            newopmode = IEEE80211_M_MONITOR;\n        else\n            newopmode = IEEE80211_M_STA;\n    \n#ifndef IEEE80211_STA_ONLY\n    /*\n     * Autoselect doesn't make sense when operating as an AP.\n     * If no phy mode has been selected, pick one and lock it\n     * down so rate tables can be used in forming beacon frames\n     * and the like.\n     */\n    if (newopmode == IEEE80211_M_HOSTAP &&\n        newphymode == IEEE80211_MODE_AUTO) {\n        if (ic->ic_modecaps & (1 << IEEE80211_MODE_11AX))\n            newphymode = IEEE80211_MODE_11AX;\n        if (ic->ic_modecaps & (1 << IEEE80211_MODE_11AC))\n            newphymode = IEEE80211_MODE_11AC;\n        else if (ic->ic_modecaps & (1 << IEEE80211_MODE_11N))\n            newphymode = IEEE80211_MODE_11N;\n        else if (ic->ic_modecaps & (1 << IEEE80211_MODE_11A))\n            newphymode = IEEE80211_MODE_11A;\n        else if (ic->ic_modecaps & (1 << IEEE80211_MODE_11G))\n            newphymode = IEEE80211_MODE_11G;\n        else\n            newphymode = IEEE80211_MODE_11B;\n    }\n#endif\n    \n    /*\n     * Handle phy mode change.\n     */\n    if (ic->ic_curmode != newphymode) {        /* change phy mode */\n        error = ieee80211_setmode(ic, newphymode);\n        if (error != 0)\n            return error;\n        error = ENETRESET;\n    }\n    \n    /*\n     * Committed to changes, install the MCS/rate setting.\n     */\n    ic->ic_flags &= ~(IEEE80211_F_HTON | IEEE80211_F_VHTON);\n    ieee80211_configure_ampdu_tx(ic, 0);\n    if ((ic->ic_modecaps & (1 << IEEE80211_MODE_11AX)) &&\n        (newphymode == IEEE80211_MODE_AUTO ||\n         newphymode == IEEE80211_MODE_11AX)) {\n        ic->ic_flags |= IEEE80211_F_HEON;\n        ieee80211_configure_ampdu_tx(ic, 1);\n    } else if ((ic->ic_modecaps & (1 << IEEE80211_MODE_11AC)) &&\n        (newphymode == IEEE80211_MODE_AUTO ||\n         newphymode == IEEE80211_MODE_11AC)) {\n        ic->ic_flags |= IEEE80211_F_VHTON;\n        ieee80211_configure_ampdu_tx(ic, 1);\n    } else if ((ic->ic_modecaps & (1 << IEEE80211_MODE_11N)) &&\n               (newphymode == IEEE80211_MODE_AUTO ||\n                newphymode == IEEE80211_MODE_11N)) {\n        ic->ic_flags |= IEEE80211_F_HTON;\n        ieee80211_configure_ampdu_tx(ic, 1);\n    }\n    if ((ic->ic_flags & (IEEE80211_F_HTON | IEEE80211_F_VHTON)) == 0) {\n        ic->ic_fixed_mcs = -1;\n        if (ic->ic_fixed_rate != i) {\n            ic->ic_fixed_rate = i;        /* set fixed tx rate */\n            error = ENETRESET;\n        }\n    } else {\n        ic->ic_fixed_rate = -1;\n        if (ic->ic_fixed_mcs != i) {\n            ic->ic_fixed_mcs = i;        /* set fixed mcs */\n            error = ENETRESET;\n        }\n    }\n    \n    /*\n     * Handle operating mode change.\n     */\n    if (ic->ic_opmode != newopmode) {\n        ic->ic_opmode = newopmode;\n#ifndef IEEE80211_STA_ONLY\n        switch (newopmode) {\n            case IEEE80211_M_AHDEMO:\n            case IEEE80211_M_HOSTAP:\n            case IEEE80211_M_STA:\n            case IEEE80211_M_MONITOR:\n                ic->ic_flags &= ~IEEE80211_F_IBSSON;\n                break;\n            case IEEE80211_M_IBSS:\n                ic->ic_flags |= IEEE80211_F_IBSSON;\n                break;\n        }\n#endif\n        /*\n         * Yech, slot time may change depending on the\n         * operating mode so reset it to be sure everything\n         * is setup appropriately.\n         */\n        ieee80211_reset_erp(ic);\n        error = ENETRESET;\n    }\n#ifdef notdef\n    if (error == 0)\n        ifp->if_baudrate = ifmedia_baudrate(ime->ifm_media);\n#endif\n    return error;\n}\n\nvoid\nieee80211_media_status(struct _ifnet *ifp, struct ifmediareq *imr)\n{\n    struct ieee80211com *ic = (struct ieee80211com *)ifp;\n    const struct ieee80211_node *ni = NULL;\n    \n    imr->ifm_status = IFM_AVALID;\n    imr->ifm_active = IFM_IEEE80211;\n    if (ic->ic_state == IEEE80211_S_RUN &&\n        (ic->ic_opmode != IEEE80211_M_STA ||\n         !(ic->ic_flags & IEEE80211_F_RSNON) ||\n         ic->ic_bss->ni_port_valid))\n        imr->ifm_status |= IFM_ACTIVE;\n    imr->ifm_active |= IFM_AUTO;\n    switch (ic->ic_opmode) {\n        case IEEE80211_M_STA:\n            ni = ic->ic_bss;\n            if (ic->ic_curmode == IEEE80211_MODE_11N ||\n                ic->ic_curmode == IEEE80211_MODE_11AC ||\n                ic->ic_curmode == IEEE80211_MODE_11AX)\n                imr->ifm_active |= ieee80211_mcs2media(ic,\n                                                       ni->ni_txmcs, (enum ieee80211_phymode)ic->ic_curmode);\n            else if (ni->ni_flags & IEEE80211_NODE_HE) /* in MODE_AUTO */\n                imr->ifm_active |= ieee80211_mcs2media(ic,\n                                                       ni->ni_txmcs, IEEE80211_MODE_11AX);\n            else if (ni->ni_flags & IEEE80211_NODE_VHT) /* in MODE_AUTO */\n                imr->ifm_active |= ieee80211_mcs2media(ic,\n                                                       ni->ni_txmcs, IEEE80211_MODE_11AC);\n            else if (ni->ni_flags & IEEE80211_NODE_HT) /* in MODE_AUTO */\n                imr->ifm_active |= ieee80211_mcs2media(ic,\n                                                       ni->ni_txmcs, IEEE80211_MODE_11N);\n            else\n            /* calculate rate subtype */\n                imr->ifm_active |= ieee80211_rate2media(ic,\n                                                        ni->ni_rates.rs_rates[ni->ni_txrate],\n                                                        (enum ieee80211_phymode)ic->ic_curmode);\n            break;\n#ifndef IEEE80211_STA_ONLY\n        case IEEE80211_M_IBSS:\n            imr->ifm_active |= IFM_IEEE80211_IBSS;\n            break;\n        case IEEE80211_M_AHDEMO:\n            imr->ifm_active |= IFM_IEEE80211_ADHOC;\n            break;\n        case IEEE80211_M_HOSTAP:\n            imr->ifm_active |= IFM_IEEE80211_HOSTAP;\n            break;\n#endif\n        case IEEE80211_M_MONITOR:\n            imr->ifm_active |= IFM_IEEE80211_MONITOR;\n            break;\n        default:\n            break;\n    }\n    switch (ic->ic_curmode) {\n        case IEEE80211_MODE_11A:\n            imr->ifm_active |= IFM_IEEE80211_11A;\n            break;\n        case IEEE80211_MODE_11B:\n            imr->ifm_active |= IFM_IEEE80211_11B;\n            break;\n        case IEEE80211_MODE_11G:\n            imr->ifm_active |= IFM_IEEE80211_11G;\n            break;\n        case IEEE80211_MODE_11N:\n            imr->ifm_active |= IFM_IEEE80211_11N;\n            break;\n        case IEEE80211_MODE_11AC:\n            imr->ifm_active |= IFM_IEEE80211_11AC;\n            break;\n        case IEEE80211_MODE_11AX:\n            imr->ifm_active |= IFM_IEEE80211_11AX;\n            break;\n    }\n}\n\nvoid\nieee80211_watchdog(struct _ifnet *ifp)\n{\n    struct ieee80211com *ic = (struct ieee80211com *)ifp;\n    \n    if (ic->ic_mgt_timer && --ic->ic_mgt_timer == 0) {\n        if (ic->ic_opmode == IEEE80211_M_STA &&\n            (ic->ic_state == IEEE80211_S_AUTH ||\n             ic->ic_state == IEEE80211_S_ASSOC)) {\n            struct ieee80211_node *ni;\n            if (ifp->if_flags & IFF_DEBUG)\n                XYLog(\"%s: %s timed out for %s\\n\",\n                      ifp->if_xname,\n                      ic->ic_state == IEEE80211_S_ASSOC ?\n                      \"association\" : \"authentication\",\n                      ether_sprintf(ic->ic_bss->ni_macaddr));\n            ni = ieee80211_find_node(ic, ic->ic_bss->ni_macaddr);\n            if (ni)\n                ni->ni_fails++;\n            /* Try more times to join, some drivers will timeout when doing auth/assoc */\n            if (ic->ic_state == IEEE80211_S_AUTH && ni && ni->ni_fails < 3) {\n                ieee80211_node_join_bss(ic, ni);\n                goto done;\n            }\n            if (ISSET(ic->ic_flags, IEEE80211_F_AUTO_JOIN))\n                ieee80211_deselect_ess(ic);\n        }\n        ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);\n    }\n    \ndone:\n    if (ic->ic_mgt_timer != 0)\n        ifp->if_timer = 1;\n}\n\nconst struct ieee80211_rateset ieee80211_std_rateset_11a =\n{ 8, { 12, 18, 24, 36, 48, 72, 96, 108 } };\n\nconst struct ieee80211_rateset ieee80211_std_rateset_11b =\n{ 4, { 2, 4, 11, 22 } };\n\nconst struct ieee80211_rateset ieee80211_std_rateset_11g =\n{ 12, { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 } };\n\nconst struct ieee80211_ht_rateset ieee80211_std_ratesets_11n[] = {\n    /* MCS 0-7, 20MHz channel, no SGI */\n    { 8, { 13, 26, 39, 52, 78, 104, 117, 130 }, 0x000000ff, 0, 7, 0},\n    \n    /* MCS 0-7, 20MHz channel, SGI */\n    { 8, { 14, 29, 43, 58, 87, 116, 130, 144 }, 0x000000ff, 0, 7, 1 },\n    \n    /* MCS 8-15, 20MHz channel, no SGI */\n    { 8, { 26, 52, 78, 104, 156, 208, 234, 260 }, 0x0000ff00, 8, 15, 0 },\n    \n    /* MCS 8-15, 20MHz channel, SGI */\n    { 8, { 29, 58, 87, 116, 173, 231, 261, 289 }, 0x0000ff00, 8, 15, 1 },\n    \n    /* MCS 16-23, 20MHz channel, no SGI */\n    { 8, { 39, 78, 117, 156, 234, 312, 351, 390 }, 0x00ff0000, 16, 23, 0 },\n    \n    /* MCS 16-23, 20MHz channel, SGI */\n    { 8, { 43, 87, 130, 173, 260, 347, 390, 433 }, 0x00ff0000, 16, 23, 1 },\n    \n    /* MCS 24-31, 20MHz channel, no SGI */\n    { 8, { 52, 104, 156, 208, 312, 416, 468, 520 }, 0xff000000, 24, 31, 0 },\n    \n    /* MCS 24-31, 20MHz channel, SGI */\n    { 8, { 58, 116, 173, 231, 347, 462, 520, 578 }, 0xff000000, 24, 31, 1 },\n    \n    /* MCS 0-7, 40MHz channel, no SGI */\n    { 8, { 27, 54, 81, 108, 162, 216, 243, 270 }, 0x000000ff, 0, 7, 0},\n    \n    /* MCS 0-7, 40MHz channel, SGI */\n    { 8, { 30, 60, 90, 120, 180, 240, 270, 300 }, 0x000000ff, 0, 7, 1 },\n    \n    /* MCS 8-15, 40MHz channel, no SGI */\n    { 8, { 54, 108, 162, 216, 324, 432, 486, 540 }, 0x0000ff00, 8, 15, 0 },\n    \n    /* MCS 8-15, 40MHz channel, SGI */\n    { 8, { 60, 120, 180, 240, 360, 480, 540, 600 }, 0x0000ff00, 8, 15, 1 },\n    \n    /* MCS 16-23, 40MHz channel, no SGI */\n    { 8, { 81, 162, 243, 324, 486, 648, 729, 810 }, 0x00ff0000, 16, 23, 0 },\n    \n    /* MCS 16-23, 40MHz channel, SGI */\n    { 8, { 90, 180, 270, 360, 540, 720, 810, 900 }, 0x00ff0000, 16, 23, 1 },\n    \n    /* MCS 24-31, 40MHz channel, no SGI */\n    { 8, { 108, 216, 324, 432, 648, 864, 972, 1080 }, 0xff000000, 24, 31, 0 },\n    \n    /* MCS 24-31, 40MHz channel, SGI */\n    { 8, { 120, 240, 360, 480, 720, 960, 1080, 1200 }, 0xff000000, 24, 31, 1 },\n};\n\nconst struct ieee80211_vht_rateset ieee80211_std_ratesets_11ac[] = {\n    /* MCS 0-8 (MCS 9 N/A), 1 SS, 20MHz channel, no SGI */\n    { 9, { 13, 26, 39, 52, 78, 104, 117, 130, 156 }, 1, 0 },\n    \n    /* MCS 0-8 (MCS 9 N/A), 1 SS, 20MHz channel, SGI */\n    { 9, { 14, 29, 43, 58, 87, 116, 130, 144, 174 }, 1, 1 },\n    \n    /* MCS 0-8 (MCS 9 N/A), 2 SS, 20MHz channel, no SGI */\n    { 9, { 26, 52, 78, 104, 156, 208, 234, 260, 312 }, 2, 0 },\n    \n    /* MCS 0-8 (MCS 9 N/A), 2 SS, 20MHz channel, SGI */\n    { 9, { 29, 58, 87, 116, 173, 231, 261, 289, 347 }, 2, 1 },\n    \n    /* MCS 0-9, 1 SS, 40MHz channel, no SGI */\n    { 10, { 27, 54, 81, 108, 162, 216, 243, 270, 324, 360 }, 1, 0 },\n    \n    /* MCS 0-9, 1 SS, 40MHz channel, SGI */\n    { 10, { 30, 60, 90, 120, 180, 240, 270, 300, 360, 400 }, 1, 1 },\n    \n    /* MCS 0-9, 2 SS, 40MHz channel, no SGI */\n    { 10, { 54, 108, 162, 216, 324, 432, 486, 540, 648, 720 }, 2, 0 },\n    \n    /* MCS 0-9, 2 SS, 40MHz channel, SGI */\n    { 10, { 60, 120, 180, 240, 360, 480, 540, 600, 720, 800 }, 2, 1 },\n    \n    /* MCS 0-9, 1 SS, 80MHz channel, no SGI */\n    { 10, { 59, 117, 176, 234, 351, 468, 527, 585, 702, 780 }, 1, 0 },\n    \n    /* MCS 0-9, 1 SS, 80MHz channel, SGI */\n    { 10, { 65, 130, 195, 260, 390, 520, 585, 650, 780, 867 }, 1, 1 },\n    \n    /* MCS 0-9, 2 SS, 80MHz channel, no SGI */\n    { 10, { 117, 234, 351, 468, 702, 936, 1053, 1404, 1560 }, 2, 0 },\n    \n    /* MCS 0-9, 2 SS, 80MHz channel, SGI */\n    { 10, { 130, 260, 390, 520, 780, 1040, 1170, 1300, 1560, 1734 }, 2, 1 },\n    \n    /* MCS 0-9, 1 SS, 160MHz channel, no SGI */\n    { 10, { 117, 234, 351, 468, 702, 936, 1053, 1170, 1404, 1560 }, 1, 0 },\n    \n    /* MCS 0-9, 1 SS, 160MHz channel, SGI */\n    { 10, { 130, 260, 390, 520, 780, 1040, 1170, 1300, 1560, 1734 }, 1, 1 },\n    \n    /* MCS 0-9, 2 SS, 160MHz channel, no SGI */\n    { 10, { 234, 468, 702, 936, 1404, 1872, 2106, 2340, 2808 }, 2, 0 },\n    \n    /* MCS 0-9, 2 SS, 160MHz channel, SGI */\n    { 10, { 260, 520, 780, 1040, 1560, 2080, 2340, 2600, 3120, 3464 }, 2, 1 },\n};\n\nconst struct ieee80211_he_rateset ieee80211_std_ratesets_11ax[] = {\n    /* MCS 0-11 1 SS, 20MHz channel */\n    { 12, { 17, 34, 52, 69, 103, 138, 155, 172, 206, 230, 258, 287 }, 1 },\n    \n    /* MCS 0-11 2 SS, 20MHz channel */\n    { 12, { 34, 69, 103, 138, 206, 275, 310, 344, 413, 459, 516, 574 }, 2 },\n    \n    /* MCS 0-11 1 SS, 40MHz channel */\n    { 12, { 34, 69, 103, 138, 206, 275, 310, 344, 413, 459, 516, 574 }, 1 },\n    \n    /* MCS 0-11 2 SS, 40MHz channel */\n    { 12, { 69, 138, 206, 275, 413, 551, 619, 688, 826, 918, 1032, 1147 }, 2 },\n    \n    /* MCS 0-11 1 SS, 80MHz channel */\n    { 12, { 72, 144, 216, 288, 432, 577, 649, 721, 865, 961, 1081, 1201 }, 1 },\n    \n    /* MCS 0-11 2 SS, 80MHz channel */\n    { 12, { 288, 577, 865, 1153, 1729, 2306, 2594, 2882, 3459, 3843, 4324, 4804 }, 2},\n    \n    /* MCS 0-11 1 SS, 160MHz channel */\n    { 12, { 144, 288, 432, 564, 865, 1152, 1298, 1442, 1730, 1922, 2162, 2402 }, 1 },\n    \n    /* MCS 0-11 2 SS, 160MHz channel */\n    { 12, { 576, 1154, 1730, 2306, 3458, 4612, 5188, 5764, 6918, 7686, 8648, 9608 }, 2 },\n};\n\n/*\n * Mark the basic rates for the 11g rate table based on the\n * operating mode.  For real 11g we mark all the 11b rates\n * and 6, 12, and 24 OFDM.  For 11b compatibility we mark only\n * 11b rates.  There's also a pseudo 11a-mode used to mark only\n * the basic OFDM rates.\n */\nvoid\nieee80211_setbasicrates(struct ieee80211com *ic)\n{\n    static const struct ieee80211_rateset basic[] = {\n        { 0 },                /* IEEE80211_MODE_AUTO */\n        { 3, { 12, 24, 48 } },        /* IEEE80211_MODE_11A */\n        { 2, { 2, 4 } },            /* IEEE80211_MODE_11B */\n        { 4, { 2, 4, 11, 22 } },        /* IEEE80211_MODE_11G */\n        { 0 },                /* IEEE80211_MODE_11N    */\n        { 0 },                /* IEEE80211_MODE_11AC    */\n        { 0 },                /* IEEE80211_MODE_11AX    */\n    };\n    int mode;\n    struct ieee80211_rateset *rs;\n    int i, j;\n    \n    for (mode = 0; mode < IEEE80211_MODE_MAX; mode++) {\n        rs = &ic->ic_sup_rates[mode];\n        for (i = 0; i < rs->rs_nrates; i++) {\n            rs->rs_rates[i] &= IEEE80211_RATE_VAL;\n            for (j = 0; j < basic[mode].rs_nrates; j++) {\n                if (basic[mode].rs_rates[j] ==\n                    rs->rs_rates[i]) {\n                    rs->rs_rates[i] |=\n                    IEEE80211_RATE_BASIC;\n                    break;\n                }\n            }\n        }\n    }\n}\n\nint\nieee80211_min_basic_rate(struct ieee80211com *ic)\n{\n    struct ieee80211_rateset *rs = &ic->ic_bss->ni_rates;\n    int i, min, rval;\n    \n    min = -1;\n    \n    for (i = 0; i < rs->rs_nrates; i++) {\n        if ((rs->rs_rates[i] & IEEE80211_RATE_BASIC) == 0)\n            continue;\n        rval = (rs->rs_rates[i] & IEEE80211_RATE_VAL);\n        if (min == -1)\n            min = rval;\n        else if (rval < min)\n            min = rval;\n    }\n    \n    /* Default to 1 Mbit/s on 2GHz and 6 Mbit/s on 5GHz. */\n    if (min == -1)\n        min = IEEE80211_IS_CHAN_2GHZ(ic->ic_bss->ni_chan) ? 2 : 12;\n    \n    return min;\n}\n\nint\nieee80211_max_basic_rate(struct ieee80211com *ic)\n{\n    struct ieee80211_rateset *rs = &ic->ic_bss->ni_rates;\n    int i, max, rval;\n    \n    /* Default to 1 Mbit/s on 2GHz and 6 Mbit/s on 5GHz. */\n    max = IEEE80211_IS_CHAN_2GHZ(ic->ic_bss->ni_chan) ? 2 : 12;\n    \n    for (i = 0; i < rs->rs_nrates; i++) {\n        if ((rs->rs_rates[i] & IEEE80211_RATE_BASIC) == 0)\n            continue;\n        rval = (rs->rs_rates[i] & IEEE80211_RATE_VAL);\n        if (rval > max)\n            max = rval;\n    }\n    \n    return max;\n}\n\n/*\n * Set the current phy mode and recalculate the active channel\n * set based on the available channels for this mode.  Also\n * select a new default/current channel if the current one is\n * inappropriate for this mode.\n */\nint\nieee80211_setmode(struct ieee80211com *ic, enum ieee80211_phymode mode)\n{\n    struct _ifnet *ifp = &ic->ic_if;\n    static const u_int chanflags[] = {\n        0,            /* IEEE80211_MODE_AUTO */\n        IEEE80211_CHAN_A,    /* IEEE80211_MODE_11A */\n        IEEE80211_CHAN_B,    /* IEEE80211_MODE_11B */\n        IEEE80211_CHAN_PUREG,    /* IEEE80211_MODE_11G */\n        IEEE80211_CHAN_HT,    /* IEEE80211_MODE_11N */\n        IEEE80211_CHAN_VHT | IEEE80211_CHAN_HT,    /* IEEE80211_MODE_11AC */\n        IEEE80211_CHAN_VHT | IEEE80211_CHAN_HT,    /* IEEE80211_MODE_11AX */\n    };\n    const struct ieee80211_channel *c;\n    u_int modeflags;\n    int i;\n    \n    /* validate new mode */\n    if ((ic->ic_modecaps & (1<<mode)) == 0) {\n        DPRINTF((\"mode %u not supported (caps 0x%x)\\n\",\n                 mode, ic->ic_modecaps));\n        return EINVAL;\n    }\n    \n    /*\n     * Verify at least one channel is present in the available\n     * channel list before committing to the new mode.\n     */\n    if (mode >= nitems(chanflags))\n        panic(\"%s: unexpected mode %u\", __func__, mode);\n    modeflags = chanflags[mode];\n    for (i = 0; i <= IEEE80211_CHAN_MAX; i++) {\n        c = &ic->ic_channels[i];\n        if (mode == IEEE80211_MODE_AUTO) {\n            if (c->ic_flags != 0)\n                break;\n        } else if ((c->ic_flags & modeflags) != 0)\n            break;\n    }\n    if (i > IEEE80211_CHAN_MAX) {\n        DPRINTF((\"no channels found for mode %u\\n\", mode));\n        return EINVAL;\n    }\n    \n    /*\n     * Calculate the active channel set.\n     */\n    memset(ic->ic_chan_active, 0, sizeof(ic->ic_chan_active));\n    for (i = 0; i <= IEEE80211_CHAN_MAX; i++) {\n        c = &ic->ic_channels[i];\n        if (mode == IEEE80211_MODE_AUTO) {\n            if (c->ic_flags != 0)\n                setbit(ic->ic_chan_active, i);\n        } else if ((c->ic_flags & modeflags) != 0)\n            setbit(ic->ic_chan_active, i);\n    }\n    /*\n     * If no current/default channel is setup or the current\n     * channel is wrong for the mode then pick the first\n     * available channel from the active list.  This is likely\n     * not the right one.\n     */\n    if (ic->ic_ibss_chan == NULL || isclr(ic->ic_chan_active,\n                                          ieee80211_chan2ieee(ic, ic->ic_ibss_chan))) {\n        for (i = 0; i <= IEEE80211_CHAN_MAX; i++)\n            if (isset(ic->ic_chan_active, i)) {\n                ic->ic_ibss_chan = &ic->ic_channels[i];\n                break;\n            }\n        if ((ic->ic_ibss_chan == NULL) || isclr(ic->ic_chan_active,\n                                                ieee80211_chan2ieee(ic, ic->ic_ibss_chan)))\n            panic(\"Bad IBSS channel %u\",\n                  ieee80211_chan2ieee(ic, ic->ic_ibss_chan));\n    }\n    \n    /*\n     * Reset the scan state for the new mode. This avoids scanning\n     * of invalid channels, ie. 5GHz channels in 11b mode.\n     */\n    ieee80211_reset_scan(ifp);\n    \n    ic->ic_curmode = mode;\n    ieee80211_reset_erp(ic);    /* reset ERP state */\n    \n    return 0;\n}\n\nenum ieee80211_phymode\nieee80211_next_mode(struct _ifnet *ifp)\n{\n    struct ieee80211com *ic = (struct ieee80211com *)ifp;\n    uint16_t mode;\n    \n    /*\n     * Indicate a wrap-around if we're running in a fixed, user-specified\n     * phy mode.\n     */\n    if (IFM_MODE(ic->ic_media.ifm_cur->ifm_media) != IFM_AUTO)\n        return (IEEE80211_MODE_AUTO);\n    \n    /*\n     * Always scan in AUTO mode if the driver scans all bands.\n     * The current mode might have changed during association\n     * so we must reset it here.\n     */\n    if (ic->ic_caps & IEEE80211_C_SCANALLBAND) {\n        ieee80211_setmode(ic, IEEE80211_MODE_AUTO);\n        return (enum ieee80211_phymode)(ic->ic_curmode);\n    }\n    \n    /*\n     * Get the next supported mode; effectively, this alternates between\n     * the 11a (5GHz) and 11b/g (2GHz) modes. What matters is that each\n     * supported channel gets scanned.\n     */\n    for (mode = ic->ic_curmode + 1; mode <= IEEE80211_MODE_MAX; mode++) {\n        /*\n         * Skip over 11n mode. Its set of channels is the superset\n         * of all channels supported by the other modes.\n         */\n        if (mode == IEEE80211_MODE_11N)\n            continue;\n        /*\n         * Skip over 11ac mode. Its set of channels is the set\n         * of all channels supported by 11a.\n         */\n        if (mode == IEEE80211_MODE_11AC)\n            continue;\n        \n        /*\n         * Skip over 11ax mode. Its set of channels is the set\n         * of all channels supported by 11a.\n         */\n        if (mode == IEEE80211_MODE_11AX)\n            continue;\n        \n        /* Start over if we have already tried all modes. */\n        if (mode == IEEE80211_MODE_MAX) {\n            mode = IEEE80211_MODE_AUTO;\n            break;\n        }\n        \n        if (ic->ic_modecaps & (1 << mode))\n            break;\n    }\n    \n    if (mode != ic->ic_curmode)\n        ieee80211_setmode(ic, (enum ieee80211_phymode)mode);\n    \n    return (enum ieee80211_phymode)(ic->ic_curmode);\n}\n\n/*\n * Return the phy mode for with the specified channel so the\n * caller can select a rate set.  This is problematic and the\n * work here assumes how things work elsewhere in this code.\n *\n * Because the result of this function is ultimately used to select a\n * rate from the rate set of the returned mode, it must return one of the\n * legacy 11a/b/g modes; 11n and 11ac modes use MCS instead of rate sets.\n */\nenum ieee80211_phymode\nieee80211_chan2mode(struct ieee80211com *ic,\n                    const struct ieee80211_channel *chan)\n{\n    /*\n     * Are we fixed in 11a/b/g mode?\n     * NB: this assumes the channel would not be supplied to us\n     *     unless it was already compatible with the current mode.\n     */\n    if (ic->ic_curmode == IEEE80211_MODE_11A ||\n        ic->ic_curmode == IEEE80211_MODE_11B ||\n        ic->ic_curmode == IEEE80211_MODE_11G)\n        return (enum ieee80211_phymode)ic->ic_curmode;\n    \n    /* If no channel was provided, return the most suitable legacy mode. */\n    if (chan == IEEE80211_CHAN_ANYC) {\n        switch (ic->ic_curmode) {\n            case IEEE80211_MODE_AUTO:\n            case IEEE80211_MODE_11N:\n                if (ic->ic_modecaps & (1 << IEEE80211_MODE_11A))\n                    return IEEE80211_MODE_11A;\n                if (ic->ic_modecaps & (1 << IEEE80211_MODE_11G))\n                    return IEEE80211_MODE_11G;\n                return IEEE80211_MODE_11B;\n            case IEEE80211_MODE_11AC:\n            case IEEE80211_MODE_11AX:\n                return IEEE80211_MODE_11A;\n            default:\n                return (enum ieee80211_phymode)ic->ic_curmode;\n        }\n    }\n    \n    /* Deduce a legacy mode based on the channel characteristics. */\n    if (IEEE80211_IS_CHAN_5GHZ(chan))\n        return IEEE80211_MODE_11A;\n    else if (chan->ic_flags & (IEEE80211_CHAN_OFDM|IEEE80211_CHAN_DYN))\n        return IEEE80211_MODE_11G;\n    else\n        return IEEE80211_MODE_11B;\n}\n\n/*\n * Convert IEEE80211 MCS index to ifmedia subtype.\n */\nuint64_t\nieee80211_mcs2media(struct ieee80211com *ic, int mcs,\n                    enum ieee80211_phymode mode)\n{\n    switch (mode) {\n        case IEEE80211_MODE_11A:\n        case IEEE80211_MODE_11B:\n        case IEEE80211_MODE_11G:\n            /* these modes use rates, not MCS */\n            panic(\"%s: unexpected mode %d\", __func__, mode);\n            break;\n        case IEEE80211_MODE_11N:\n            if (mcs >= 0 && mcs < IEEE80211_HT_NUM_MCS)\n                return (IFM_IEEE80211_11N |\n                        (IFM_IEEE80211_HT_MCS0 + mcs));\n            break;\n        case IEEE80211_MODE_11AC:\n            if (mcs >= 0 && mcs < IEEE80211_VHT_NUM_MCS)\n                return (IFM_IEEE80211_11AC |\n                        (IFM_IEEE80211_VHT_MCS0 + mcs));\n            break;\n        case IEEE80211_MODE_11AX:\n            if (mcs >= 0 && mcs < IEEE80211_VHT_NUM_MCS)\n                return (IFM_IEEE80211_11AX |\n                        (IFM_IEEE80211_VHT_MCS0 + mcs));\n            break;\n        case IEEE80211_MODE_AUTO:\n            break;\n    }\n    \n    return IFM_AUTO;\n}\n\n/*\n * Convert ifmedia subtype to IEEE80211 MCS index.\n */\nint\nieee80211_media2mcs(uint64_t mword)\n{\n    uint64_t subtype;\n    \n    subtype = IFM_SUBTYPE(mword);\n    \n    if (subtype == IFM_AUTO)\n        return -1;\n    else if (subtype == IFM_MANUAL || subtype == IFM_NONE)\n        return 0;\n    \n    if (subtype >= IFM_IEEE80211_HT_MCS0 &&\n        subtype <= IFM_IEEE80211_HT_MCS76)\n        return (int)(subtype - IFM_IEEE80211_HT_MCS0);\n    \n    if (subtype >= IFM_IEEE80211_VHT_MCS0 &&\n        subtype <= IFM_IEEE80211_VHT_MCS9)\n        return (int)(subtype - IFM_IEEE80211_VHT_MCS0);\n    \n    return -1;\n}\n\n/*\n * convert IEEE80211 rate value to ifmedia subtype.\n * ieee80211 rate is in unit of 0.5Mbps.\n */\nuint64_t\nieee80211_rate2media(struct ieee80211com *ic, int rate,\n                     enum ieee80211_phymode mode)\n{\n    static const struct {\n        uint64_t    m;    /* rate + mode */\n        uint64_t    r;    /* if_media rate */\n    } rates[] = {\n        {   2 | IFM_IEEE80211_11B, IFM_IEEE80211_DS1 },\n        {   4 | IFM_IEEE80211_11B, IFM_IEEE80211_DS2 },\n        {  11 | IFM_IEEE80211_11B, IFM_IEEE80211_DS5 },\n        {  22 | IFM_IEEE80211_11B, IFM_IEEE80211_DS11 },\n        {  44 | IFM_IEEE80211_11B, IFM_IEEE80211_DS22 },\n        {  12 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM6 },\n        {  18 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM9 },\n        {  24 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM12 },\n        {  36 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM18 },\n        {  48 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM24 },\n        {  72 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM36 },\n        {  96 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM48 },\n        { 108 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM54 },\n        {   2 | IFM_IEEE80211_11G, IFM_IEEE80211_DS1 },\n        {   4 | IFM_IEEE80211_11G, IFM_IEEE80211_DS2 },\n        {  11 | IFM_IEEE80211_11G, IFM_IEEE80211_DS5 },\n        {  22 | IFM_IEEE80211_11G, IFM_IEEE80211_DS11 },\n        {  12 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM6 },\n        {  18 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM9 },\n        {  24 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM12 },\n        {  36 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM18 },\n        {  48 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM24 },\n        {  72 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM36 },\n        {  96 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM48 },\n        { 108 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM54 },\n        /* NB: OFDM72 doesn't really exist so we don't handle it */\n    };\n    uint64_t mask;\n    int i;\n    \n    mask = rate & IEEE80211_RATE_VAL;\n    switch (mode) {\n        case IEEE80211_MODE_11A:\n            mask |= IFM_IEEE80211_11A;\n            break;\n        case IEEE80211_MODE_11B:\n            mask |= IFM_IEEE80211_11B;\n            break;\n        case IEEE80211_MODE_AUTO:\n            /* NB: hack, 11g matches both 11b+11a rates */\n            /* FALLTHROUGH */\n        case IEEE80211_MODE_11G:\n            mask |= IFM_IEEE80211_11G;\n            break;\n        case IEEE80211_MODE_11N:\n        case IEEE80211_MODE_11AC:\n        case IEEE80211_MODE_11AX:\n            /* 11n/11ac/11ax uses MCS, not rates. */\n            panic(\"%s: unexpected mode %d\", __func__, mode);\n            break;\n    }\n    for (i = 0; i < nitems(rates); i++)\n        if (rates[i].m == mask)\n            return rates[i].r;\n    return IFM_AUTO;\n}\n\nint\nieee80211_media2rate(uint64_t mword)\n{\n    int i;\n    static const struct {\n        uint64_t subtype;\n        int rate;\n    } ieeerates[] = {\n        { IFM_AUTO,        -1    },\n        { IFM_MANUAL,        0    },\n        { IFM_NONE,        0    },\n        { IFM_IEEE80211_DS1,    2    },\n        { IFM_IEEE80211_DS2,    4    },\n        { IFM_IEEE80211_DS5,    11    },\n        { IFM_IEEE80211_DS11,    22    },\n        { IFM_IEEE80211_DS22,    44    },\n        { IFM_IEEE80211_OFDM6,    12    },\n        { IFM_IEEE80211_OFDM9,    18    },\n        { IFM_IEEE80211_OFDM12,    24    },\n        { IFM_IEEE80211_OFDM18,    36    },\n        { IFM_IEEE80211_OFDM24,    48    },\n        { IFM_IEEE80211_OFDM36,    72    },\n        { IFM_IEEE80211_OFDM48,    96    },\n        { IFM_IEEE80211_OFDM54,    108    },\n        { IFM_IEEE80211_OFDM72,    144    },\n    };\n    for (i = 0; i < nitems(ieeerates); i++) {\n        if (ieeerates[i].subtype == IFM_SUBTYPE(mword))\n            return ieeerates[i].rate;\n    }\n    return 0;\n}\n\n/*\n * Convert bit rate (in 0.5Mbps units) to PLCP signal (R4-R1) and vice versa.\n */\nu_int8_t\nieee80211_rate2plcp(u_int8_t rate, enum ieee80211_phymode mode)\n{\n    rate &= IEEE80211_RATE_VAL;\n    \n    if (mode == IEEE80211_MODE_11B) {\n        /* IEEE Std 802.11b-1999 page 15, subclause 18.2.3.3 */\n        switch (rate) {\n            case 2:        return 10;\n            case 4:        return 20;\n            case 11:    return 55;\n            case 22:    return 110;\n                /* IEEE Std 802.11g-2003 page 19, subclause 19.3.2.1 */\n            case 44:    return 220;\n        }\n    } else if (mode == IEEE80211_MODE_11G || mode == IEEE80211_MODE_11A) {\n        /* IEEE Std 802.11a-1999 page 14, subclause 17.3.4.1 */\n        switch (rate) {\n            case 12:    return 0x0b;\n            case 18:    return 0x0f;\n            case 24:    return 0x0a;\n            case 36:    return 0x0e;\n            case 48:    return 0x09;\n            case 72:    return 0x0d;\n            case 96:    return 0x08;\n            case 108:    return 0x0c;\n        }\n    } else\n        panic(\"%s: unexpected mode %u\", __func__, mode);\n    \n    DPRINTF((\"unsupported rate %u\\n\", rate));\n    \n    return 0;\n}\n\nu_int8_t\nieee80211_plcp2rate(u_int8_t plcp, enum ieee80211_phymode mode)\n{\n    if (mode == IEEE80211_MODE_11B) {\n        /* IEEE Std 802.11g-2003 page 19, subclause 19.3.2.1 */\n        switch (plcp) {\n            case 10:    return 2;\n            case 20:    return 4;\n            case 55:    return 11;\n            case 110:    return 22;\n                /* IEEE Std 802.11g-2003 page 19, subclause 19.3.2.1 */\n            case 220:    return 44;\n        }\n    } else if (mode == IEEE80211_MODE_11G || mode == IEEE80211_MODE_11A) {\n        /* IEEE Std 802.11a-1999 page 14, subclause 17.3.4.1 */\n        switch (plcp) {\n            case 0x0b:    return 12;\n            case 0x0f:    return 18;\n            case 0x0a:    return 24;\n            case 0x0e:    return 36;\n            case 0x09:    return 48;\n            case 0x0d:    return 72;\n            case 0x08:    return 96;\n            case 0x0c:    return 108;\n        }\n    } else\n        panic(\"%s: unexpected mode %u\", __func__, mode);\n    \n    DPRINTF((\"unsupported plcp %u\\n\", plcp));\n    \n    return 0;\n}\n"
  },
  {
    "path": "itl80211/openbsd/net80211/ieee80211.h",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n/*\t$OpenBSD: ieee80211.h,v 1.62 2019/02/19 08:12:30 stsp Exp $\t*/\n/*\t$NetBSD: ieee80211.h,v 1.6 2004/04/30 23:51:53 dyoung Exp $\t*/\n\n/*-\n * Copyright (c) 2001 Atsushi Onoe\n * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#ifndef _NET80211_IEEE80211_H_\n#define _NET80211_IEEE80211_H_\n\n/*\n * 802.11 protocol definitions.\n */\n\n#include <sys/endian.h>\n#include <sys/_clock.h>\n\n#define IEEE80211_ADDR_LEN\t6\t/* size of 802.11 address */\n/* is 802.11 address multicast/broadcast? */\n#define IEEE80211_IS_MULTICAST(_a)\t(*(_a) & 0x01)\n\n/*\n * Generic definitions for IEEE 802.11 frames.\n */\nstruct ieee80211_frame {\n\tu_int8_t\ti_fc[2];\n\tu_int8_t\ti_dur[2];\n\tu_int8_t\ti_addr1[IEEE80211_ADDR_LEN];\n\tu_int8_t\ti_addr2[IEEE80211_ADDR_LEN];\n\tu_int8_t\ti_addr3[IEEE80211_ADDR_LEN];\n\tu_int8_t\ti_seq[2];\n} __packed;\n\nstruct ieee80211_qosframe {\n\tu_int8_t\ti_fc[2];\n\tu_int8_t\ti_dur[2];\n\tu_int8_t\ti_addr1[IEEE80211_ADDR_LEN];\n\tu_int8_t\ti_addr2[IEEE80211_ADDR_LEN];\n\tu_int8_t\ti_addr3[IEEE80211_ADDR_LEN];\n\tu_int8_t\ti_seq[2];\n\tu_int8_t\ti_qos[2];\n} __packed;\n\nstruct ieee80211_htframe {\t\t/* 11n */\n\tu_int8_t\ti_fc[2];\n\tu_int8_t\ti_dur[2];\n\tu_int8_t\ti_addr1[IEEE80211_ADDR_LEN];\n\tu_int8_t\ti_addr2[IEEE80211_ADDR_LEN];\n\tu_int8_t\ti_addr3[IEEE80211_ADDR_LEN];\n\tu_int8_t\ti_seq[2];\n\tu_int8_t\ti_qos[2];\n\tu_int8_t\ti_ht[4];\n} __packed;\n\nstruct ieee80211_frame_addr4 {\n\tu_int8_t\ti_fc[2];\n\tu_int8_t\ti_dur[2];\n\tu_int8_t\ti_addr1[IEEE80211_ADDR_LEN];\n\tu_int8_t\ti_addr2[IEEE80211_ADDR_LEN];\n\tu_int8_t\ti_addr3[IEEE80211_ADDR_LEN];\n\tu_int8_t\ti_seq[2];\n\tu_int8_t\ti_addr4[IEEE80211_ADDR_LEN];\n} __packed;\n\nstruct ieee80211_qosframe_addr4 {\n\tu_int8_t\ti_fc[2];\n\tu_int8_t\ti_dur[2];\n\tu_int8_t\ti_addr1[IEEE80211_ADDR_LEN];\n\tu_int8_t\ti_addr2[IEEE80211_ADDR_LEN];\n\tu_int8_t\ti_addr3[IEEE80211_ADDR_LEN];\n\tu_int8_t\ti_seq[2];\n\tu_int8_t\ti_addr4[IEEE80211_ADDR_LEN];\n\tu_int8_t\ti_qos[2];\n} __packed;\n\nstruct ieee80211_htframe_addr4 {\t/* 11n */\n\tu_int8_t\ti_fc[2];\n\tu_int8_t\ti_dur[2];\n\tu_int8_t\ti_addr1[IEEE80211_ADDR_LEN];\n\tu_int8_t\ti_addr2[IEEE80211_ADDR_LEN];\n\tu_int8_t\ti_addr3[IEEE80211_ADDR_LEN];\n\tu_int8_t\ti_seq[2];\n\tu_int8_t\ti_addr4[IEEE80211_ADDR_LEN];\n\tu_int8_t\ti_qos[2];\n\tu_int8_t\ti_ht[4];\n} __packed;\n\n/**\n * enum ieee80211_chan_width - channel width definitions\n *\n * @IEEE80211_CHAN_WIDTH_20_NOHT: 20 MHz, non-HT channel\n * @IEEE80211_CHAN_WIDTH_20: 20 MHz HT channel\n * @IEEE80211_CHAN_WIDTH_40: 40 MHz channel, the %NL80211_ATTR_CENTER_FREQ1\n *    attribute must be provided as well\n * @IEEE80211_CHAN_WIDTH_80: 80 MHz channel, the %NL80211_ATTR_CENTER_FREQ1\n *    attribute must be provided as well\n * @IEEE80211_CHAN_WIDTH_80P80: 80+80 MHz channel, the %NL80211_ATTR_CENTER_FREQ1\n *    and %NL80211_ATTR_CENTER_FREQ2 attributes must be provided as well\n * @IEEE80211_CHAN_WIDTH_160: 160 MHz channel, the %NL80211_ATTR_CENTER_FREQ1\n *    attribute must be provided as well\n * @IEEE80211_CHAN_WIDTH_5: 5 MHz OFDM channel\n * @IEEE80211_CHAN_WIDTH_10: 10 MHz OFDM channel\n * @IEEE80211_CHAN_WIDTH_1: 1 MHz OFDM channel\n * @IEEE80211_CHAN_WIDTH_2: 2 MHz OFDM channel\n * @IEEE80211_CHAN_WIDTH_4: 4 MHz OFDM channel\n * @IEEE80211_CHAN_WIDTH_8: 8 MHz OFDM channel\n * @IEEE80211_CHAN_WIDTH_16: 16 MHz OFDM channel\n */\nenum ieee80211_chan_width {\n    IEEE80211_CHAN_WIDTH_20_NOHT,\n    IEEE80211_CHAN_WIDTH_20,\n    IEEE80211_CHAN_WIDTH_40,\n    IEEE80211_CHAN_WIDTH_80,\n    IEEE80211_CHAN_WIDTH_80P80,\n    IEEE80211_CHAN_WIDTH_160,\n    IEEE80211_CHAN_WIDTH_5,\n    IEEE80211_CHAN_WIDTH_10,\n    IEEE80211_CHAN_WIDTH_1,\n    IEEE80211_CHAN_WIDTH_2,\n    IEEE80211_CHAN_WIDTH_4,\n    IEEE80211_CHAN_WIDTH_8,\n    IEEE80211_CHAN_WIDTH_16,\n};\n\nconst char * const ieee80211_chan_width_name[] = {\n    \"20\",\n    \"20\",\n    \"40\",\n    \"80\",\n    \"80P80\",\n    \"160\",\n    \"5\",\n    \"10\",\n    \"1\",\n    \"2\",\n    \"4\",\n    \"8\",\n    \"16\",\n};\n\n#define\tIEEE80211_FC0_VERSION_MASK\t\t0x03\n#define\tIEEE80211_FC0_VERSION_SHIFT\t\t0\n#define\tIEEE80211_FC0_VERSION_0\t\t\t0x00\n#define\tIEEE80211_FC0_TYPE_MASK\t\t\t0x0c\n#define\tIEEE80211_FC0_TYPE_SHIFT\t\t2\n#define\tIEEE80211_FC0_TYPE_MGT\t\t\t0x00\n#define\tIEEE80211_FC0_TYPE_CTL\t\t\t0x04\n#define\tIEEE80211_FC0_TYPE_DATA\t\t\t0x08\n#define IEEE80211_FC0_TYPE_ORDER        0x8000\n\n#define\tIEEE80211_FC0_SUBTYPE_MASK\t\t0xf0\n#define\tIEEE80211_FC0_SUBTYPE_SHIFT\t\t4\n/* for TYPE_MGT */\n#define\tIEEE80211_FC0_SUBTYPE_ASSOC_REQ\t\t0x00\n#define\tIEEE80211_FC0_SUBTYPE_ASSOC_RESP\t0x10\n#define\tIEEE80211_FC0_SUBTYPE_REASSOC_REQ\t0x20\n#define\tIEEE80211_FC0_SUBTYPE_REASSOC_RESP\t0x30\n#define\tIEEE80211_FC0_SUBTYPE_PROBE_REQ\t\t0x40\n#define\tIEEE80211_FC0_SUBTYPE_PROBE_RESP\t0x50\n#define\tIEEE80211_FC0_SUBTYPE_BEACON\t\t0x80\n#define\tIEEE80211_FC0_SUBTYPE_ATIM\t\t0x90\n#define\tIEEE80211_FC0_SUBTYPE_DISASSOC\t\t0xa0\n#define\tIEEE80211_FC0_SUBTYPE_AUTH\t\t0xb0\n#define\tIEEE80211_FC0_SUBTYPE_DEAUTH\t\t0xc0\n#define IEEE80211_FC0_SUBTYPE_ACTION\t\t0xd0\n#define IEEE80211_FC0_SUBTYPE_ACTION_NOACK\t0xe0\t/* 11n */\n/* for TYPE_CTL */\n#define IEEE80211_FC0_SUBTYPE_WRAPPER\t\t0x70\t/* 11n */\n#define IEEE80211_FC0_SUBTYPE_BAR\t\t0x80\n#define IEEE80211_FC0_SUBTYPE_BA\t\t0x90\n#define\tIEEE80211_FC0_SUBTYPE_PS_POLL\t\t0xa0\n#define\tIEEE80211_FC0_SUBTYPE_RTS\t\t0xb0\n#define\tIEEE80211_FC0_SUBTYPE_CTS\t\t0xc0\n#define\tIEEE80211_FC0_SUBTYPE_ACK\t\t0xd0\n#define\tIEEE80211_FC0_SUBTYPE_CF_END\t\t0xe0\n#define\tIEEE80211_FC0_SUBTYPE_CF_END_ACK\t0xf0\n/* for TYPE_DATA (bit combination) */\n#define\tIEEE80211_FC0_SUBTYPE_DATA\t\t0x00\n#define\tIEEE80211_FC0_SUBTYPE_DATA_CF_ACK\t0x10\n#define\tIEEE80211_FC0_SUBTYPE_DATA_CF_POLL\t0x20\n#define\tIEEE80211_FC0_SUBTYPE_DATA_CF_ACKPOLL\t0x30\n#define\tIEEE80211_FC0_SUBTYPE_NODATA\t\t0x40\n#define\tIEEE80211_FC0_SUBTYPE_NODATA_CF_ACK\t0x50\n#define\tIEEE80211_FC0_SUBTYPE_NODATA_CF_POLL\t0x60\n#define\tIEEE80211_FC0_SUBTYPE_NODATA_CF_ACKPOLL\t0x70\n#define\tIEEE80211_FC0_SUBTYPE_QOS\t\t0x80\n\n#define\tIEEE80211_FC1_DIR_MASK\t\t\t0x03\n#define\tIEEE80211_FC1_DIR_NODS\t\t\t0x00\t/* STA->STA */\n#define\tIEEE80211_FC1_DIR_TODS\t\t\t0x01\t/* STA->AP  */\n#define\tIEEE80211_FC1_DIR_FROMDS\t\t0x02\t/* AP ->STA */\n#define\tIEEE80211_FC1_DIR_DSTODS\t\t0x03\t/* AP ->AP  */\n\n#define\tIEEE80211_FC1_MORE_FRAG\t\t\t0x04\n#define\tIEEE80211_FC1_RETRY\t\t\t0x08\n#define\tIEEE80211_FC1_PWR_MGT\t\t\t0x10\n#define\tIEEE80211_FC1_MORE_DATA\t\t\t0x20\n#define\tIEEE80211_FC1_PROTECTED\t\t\t0x40\n#define\tIEEE80211_FC1_WEP\t\t\t0x40\t/* pre-RSNA compat */\n#define\tIEEE80211_FC1_ORDER\t\t\t0x80\n#define IEEE80211_FC1_BITS\t\t\t\t\t\\\n\t\"\\20\\03MORE_FRAG\\04RETRY\\05PWR_MGT\\06MORE_DATA\"\t\t\\\n\t\"\\07PROTECTED\\08ORDER\"\n\n/*\n * Sequence Control field (see 802.11-2012 8.2.4.4).\n */\n#define\tIEEE80211_SEQ_FRAG_MASK\t\t\t0x000f\n#define\tIEEE80211_SEQ_FRAG_SHIFT\t\t0\n#define\tIEEE80211_SEQ_SEQ_MASK\t\t\t0xfff0\n#define\tIEEE80211_SEQ_SEQ_SHIFT\t\t\t4\n\n#define\tIEEE80211_NWID_LEN\t\t\t32\n#define IEEE80211_MMIE_LEN\t\t\t18\t/* 11w */\n\n/*\n * QoS Control field (see 802.11-2012 8.2.4.5).\n */\n#define IEEE80211_QOS_TXOP\t\t\t0xff00\n#define IEEE80211_QOS_AMSDU\t\t\t0x0080\t/* 11n */\n#define IEEE80211_QOS_ACK_POLICY_NORMAL\t\t0x0000\n#define IEEE80211_QOS_ACK_POLICY_NOACK\t\t0x0020\n#define IEEE80211_QOS_ACK_POLICY_NOEXPLACK\t0x0040\n#define IEEE80211_QOS_ACK_POLICY_BA\t\t0x0060\n#define IEEE80211_QOS_ACK_POLICY_MASK\t\t0x0060\n#define IEEE80211_QOS_ACK_POLICY_SHIFT\t\t5\n#define IEEE80211_QOS_EOSP\t\t\t0x0010\n#define IEEE80211_QOS_TID\t\t\t0x000f\n\n/*\n * Control frames.\n */\nstruct ieee80211_frame_min {\n\tu_int8_t\ti_fc[2];\n\tu_int8_t\ti_dur[2];\n\tu_int8_t\ti_addr1[IEEE80211_ADDR_LEN];\n\tu_int8_t\ti_addr2[IEEE80211_ADDR_LEN];\n\t/* FCS */\n} __packed;\n\nstruct ieee80211_frame_rts {\n\tu_int8_t\ti_fc[2];\n\tu_int8_t\ti_dur[2];\n\tu_int8_t\ti_ra[IEEE80211_ADDR_LEN];\n\tu_int8_t\ti_ta[IEEE80211_ADDR_LEN];\n\t/* FCS */\n} __packed;\n\nstruct ieee80211_frame_cts {\n\tu_int8_t\ti_fc[2];\n\tu_int8_t\ti_dur[2];\n\tu_int8_t\ti_ra[IEEE80211_ADDR_LEN];\n\t/* FCS */\n} __packed;\n\nstruct ieee80211_frame_ack {\n\tu_int8_t\ti_fc[2];\n\tu_int8_t\ti_dur[2];\n\tu_int8_t\ti_ra[IEEE80211_ADDR_LEN];\n\t/* FCS */\n} __packed;\n\nstruct ieee80211_frame_pspoll {\n\tu_int8_t\ti_fc[2];\n\tu_int8_t\ti_aid[2];\n\tu_int8_t\ti_bssid[IEEE80211_ADDR_LEN];\n\tu_int8_t\ti_ta[IEEE80211_ADDR_LEN];\n\t/* FCS */\n} __packed;\n\nstruct ieee80211_frame_cfend {\t\t/* NB: also CF-End+CF-Ack */\n\tu_int8_t\ti_fc[2];\n\tu_int8_t\ti_dur[2];\t/* should be zero */\n\tu_int8_t\ti_ra[IEEE80211_ADDR_LEN];\n\tu_int8_t\ti_bssid[IEEE80211_ADDR_LEN];\n\t/* FCS */\n} __packed;\n\n#ifdef _KERNEL\nstatic __inline int\nieee80211_has_seq(const struct ieee80211_frame *wh)\n{\n\treturn (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) !=\n\t    IEEE80211_FC0_TYPE_CTL;\n}\n\nstatic __inline int\nieee80211_has_addr4(const struct ieee80211_frame *wh)\n{\n\treturn (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) ==\n\t    IEEE80211_FC1_DIR_DSTODS;\n}\n\nstatic __inline int\nieee80211_has_qos(const struct ieee80211_frame *wh)\n{\n\treturn (wh->i_fc[0] &\n\t    (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_QOS)) ==\n\t    (IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_QOS);\n}\n\nstatic __inline int\nieee80211_has_htc(const struct ieee80211_frame *wh)\n{\n\treturn (wh->i_fc[1] & IEEE80211_FC1_ORDER) &&\n\t    (ieee80211_has_qos(wh) ||\n\t     (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==\n\t     IEEE80211_FC0_TYPE_MGT);\n}\n\nstatic __inline u_int16_t\nieee80211_get_qos(const struct ieee80211_frame *wh)\n{\n\tconst u_int8_t *frm;\n\n\tif (ieee80211_has_addr4(wh))\n\t\tfrm = ((const struct ieee80211_qosframe_addr4 *)wh)->i_qos;\n\telse\n\t\tfrm = ((const struct ieee80211_qosframe *)wh)->i_qos;\n\n\treturn letoh16(*(const u_int16_t *)frm);\n}\n\nstatic __inline int\nieee80211_is_ctl(uint16_t fc)\n{\n    return (fc & htole16(IEEE80211_FC0_TYPE_MASK)) ==\n            htole16(IEEE80211_FC0_TYPE_CTL);\n}\n\nstatic __inline int\nieee80211_is_data(uint16_t fc)\n{\n    return (fc & htole16(IEEE80211_FC0_TYPE_MASK)) ==\n            htole16(IEEE80211_FC0_TYPE_DATA);\n}\n\nstatic __inline int\nieee80211_is_mgmt(uint16_t fc)\n{\n    return (fc & htole16(IEEE80211_FC0_TYPE_MASK)) ==\n           htole16(IEEE80211_FC0_TYPE_MGT);\n}\n\nstatic __inline int\nieee80211_is_data_qos(uint16_t fc)\n{\n    /*\n     * mask with QOS_DATA rather than IEEE80211_FCTL_STYPE as we just need\n     * to check the one bit\n     */\n    return (fc & htole16(IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_QOS)) ==\n           htole16(IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_QOS);\n}\n\nstatic __inline int\nieee80211_is_qos_nullfunc(const struct ieee80211_frame *wh)\n{\n    return (wh->i_fc[0] & (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) ==\n           (IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_CTS);\n}\n\nstatic __inline int\nieee80211_has_order(const struct ieee80211_frame *wh)\n{\n    return (wh->i_fc[0] & IEEE80211_FC0_TYPE_ORDER) != 0;\n}\n\n#endif\t/* _KERNEL */\n\n/*\n * Capability Information field (see 802.11-2012 8.4.1.4).\n */\n#define\tIEEE80211_CAPINFO_ESS\t\t\t0x0001\n#define\tIEEE80211_CAPINFO_IBSS\t\t\t0x0002\n#define\tIEEE80211_CAPINFO_CF_POLLABLE\t\t0x0004\n#define\tIEEE80211_CAPINFO_CF_POLLREQ\t\t0x0008\n#define\tIEEE80211_CAPINFO_PRIVACY\t\t0x0010\n#define\tIEEE80211_CAPINFO_SHORT_PREAMBLE\t0x0020\n#define\tIEEE80211_CAPINFO_PBCC\t\t\t0x0040\n#define\tIEEE80211_CAPINFO_CHNL_AGILITY\t\t0x0080\n#define IEEE80211_CAPINFO_SPECTRUM_MGMT\t\t0x0100\n#define IEEE80211_CAPINFO_QOS\t\t\t0x0200\n#define\tIEEE80211_CAPINFO_SHORT_SLOTTIME\t0x0400\n#define\tIEEE80211_CAPINFO_APSD\t\t\t0x0800\n#define\tIEEE80211_CAPINFO_RADIO_MEASUREMENT\t0x1000\n#define\tIEEE80211_CAPINFO_DSSSOFDM\t\t0x2000\n#define IEEE80211_CAPINFO_DELAYED_B_ACK\t\t0x4000\n#define IEEE80211_CAPINFO_IMMEDIATE_B_ACK\t0x8000\n#define IEEE80211_CAPINFO_BITS\t\t\t\t\t\\\n\t\"\\10\\01ESS\\02IBSS\\03CF_POLLABLE\\04CF_POLLREQ\"\t\t\\\n\t\"\\05PRIVACY\\06SHORT_PREAMBLE\\07PBCC\\10CHNL_AGILITY\"\t\\\n\t\"\\11SPECTRUM_MGMT\\12QOS\\13SHORT_SLOTTIME\\14APSD\"\t\\\n\t\"\\15RADIO_MEASUREMENT\\16DSSSOFDM\\17DELAYED_B_ACK\\20IMMEDIATE_B_ACK\"\n\n/*\n * Information element IDs (see 802.11-2012 Table 8.4.2).\n */\nenum {\n\tIEEE80211_ELEMID_SSID\t\t\t= 0,\n\tIEEE80211_ELEMID_RATES\t\t\t= 1,\n\tIEEE80211_ELEMID_FHPARMS\t\t= 2,\n\tIEEE80211_ELEMID_DSPARMS\t\t= 3,\n\tIEEE80211_ELEMID_CFPARMS\t\t= 4,\n\tIEEE80211_ELEMID_TIM\t\t\t= 5,\n\tIEEE80211_ELEMID_IBSSPARMS\t\t= 6,\n\tIEEE80211_ELEMID_COUNTRY\t\t= 7,\n\tIEEE80211_ELEMID_HOPPING_PARMS\t\t= 8,\n\tIEEE80211_ELEMID_HOPPING_PATTERN\t= 9,\n\tIEEE80211_ELEMID_REQUEST\t\t= 10,\n\tIEEE80211_ELEMID_QBSS_LOAD\t\t= 11,\n\tIEEE80211_ELEMID_EDCAPARMS\t\t= 12,\n\tIEEE80211_ELEMID_TSPEC\t\t\t= 13,\n\tIEEE80211_ELEMID_TCLASS\t\t\t= 14,\n\tIEEE80211_ELEMID_SCHEDULE\t\t= 15,\n\tIEEE80211_ELEMID_CHALLENGE\t\t= 16,\n\t/* 17-31 reserved for challenge text extension */\n\tIEEE80211_ELEMID_POWER_CONSTRAINT\t= 32,\n\tIEEE80211_ELEMID_POWER_CAP\t\t= 33,\n\tIEEE80211_ELEMID_TPC_REQUEST\t\t= 34,\n\tIEEE80211_ELEMID_TPC_REPORT\t\t= 35,\n\tIEEE80211_ELEMID_SUPP_CHNLS\t\t= 35,\n\tIEEE80211_ELEMID_CSA\t\t\t= 37,\t/* 11h */\n\tIEEE80211_ELEMID_MEASUREMENT_REQUEST\t= 38,\t/* DFS */\n\tIEEE80211_ELEMID_MEASUREMENT_REPORT\t= 39,\t/* DFS */\n\tIEEE80211_ELEMID_QUIET\t\t\t= 40,\n\tIEEE80211_ELEMID_IBSS_DFS\t\t= 41,\n\tIEEE80211_ELEMID_ERP\t\t\t= 42,\n\tIEEE80211_ELEMID_TS_DELAY\t\t= 43,\n\tIEEE80211_ELEMID_TCLAS\t\t\t= 44,\n\tIEEE80211_ELEMID_HTCAPS\t\t\t= 45,\t/* 11n */\n\tIEEE80211_ELEMID_QOS_CAP\t\t= 46,\n\t/* 47 reserved for Broadcom */\n\tIEEE80211_ELEMID_RSN\t\t\t= 48,\n\tIEEE80211_ELEMID_802_15_COEX    = 49,\n\tIEEE80211_ELEMID_XRATES\t\t\t= 50,\n\tIEEE80211_ELEMID_AP_CHNL_REPORT\t\t= 51,\n\tIEEE80211_ELEMID_NBR_REPORT\t\t= 52,\n\tIEEE80211_ELEMID_RCPI\t\t\t= 53,\n\tIEEE80211_ELEMID_MDE\t\t\t= 54,\n\tIEEE80211_ELEMID_FTE\t\t\t= 55,\n\tIEEE80211_ELEMID_TIE\t\t\t= 56,\t/* 11r */\n\tIEEE80211_ELEMID_RDE\t\t\t= 57,\n\tIEEE80211_ELEMID_DSE\t\t\t= 58,\n\tIEEE80211_ELEMID_SUPP_OPCLASS\t\t= 59,\n\tIEEE80211_ELEMID_XCSA\t\t\t= 60,\n\tIEEE80211_ELEMID_HTOP\t\t\t= 61,\t/* 11n */\n\tIEEE80211_ELEMID_SECONDARY_CHANL_OFFSET\t= 62,\t/* 11n */\n\tIEEE80211_ELEMID_AVG_ACCESS_DELAY\t= 63,\n\tIEEE80211_ELEMID_ANTENNA\t\t= 64,\n\tIEEE80211_ELEMID_RSNI\t\t\t= 65,\n\tIEEE80211_ELEMID_MEASUREMENT_PILOT_TX\t= 66,\n\tIEEE80211_ELEMID_AVAIL_CAPACITY\t\t= 67,\n\tIEEE80211_ELEMID_AC_ACCESS_DELAY\t= 68,\n\tIEEE80211_ELEMID_TIME_ADVERT\t\t= 69,\n\tIEEE80211_ELEMID_RM\t\t\t= 70,\n\tIEEE80211_ELEMID_MULTI_BSSID\t\t= 71,\n\tIEEE80211_ELEMID_20_40_CBW_COEX\t\t= 72,\t/* 11n */\n\tIEEE80211_ELEMID_20_40_CBW_INTOLERANT\t= 73,\t/* 11n */\n\tIEEE80211_ELEMID_SCAN_PARAM_OVERLAP\t= 74,\n\tIEEE80211_ELEMID_RIC\t\t\t= 75,\n\tIEEE80211_ELEMID_MMIE\t\t\t= 76,\t/* 11w */\n\tIEEE80211_ELEMID_EVENT_REQUEST\t\t= 78,\n\tIEEE80211_ELEMID_EVENT_REPORT\t\t= 79,\n\tIEEE80211_ELEMID_DIAG_REQUEST\t\t= 80,\n\tIEEE80211_ELEMID_DIAG_REPORT\t\t= 81,\n\tIEEE80211_ELEMID_LOCATION_PARMS\t\t= 82,\n\tIEEE80211_ELEMID_NONTX_BSSID\t\t= 83,\n\tIEEE80211_ELEMID_SSID_LIST\t\t= 84,\n\tIEEE80211_ELEMID_MULTI_BSSID_IDX\t= 85,\n\tIEEE80211_ELEMID_FMS_DESC\t\t= 86,\n\tIEEE80211_ELEMID_FMS_REQUEST\t\t= 87,\n\tIEEE80211_ELEMID_FMS_RESPONSE\t\t= 88,\n\tIEEE80211_ELEMID_QOS_TRAFFIC_CAP\t= 89,\n\tIEEE80211_ELEMID_MAX_IDLE_PERIOD\t= 90,\n\tIEEE80211_ELEMID_TFS_REQUEST\t\t= 91,\n\tIEEE80211_ELEMID_TFS_RESPONSE\t\t= 92,\n\tIEEE80211_ELEMID_WNM_SLEEP\t\t= 93,\n\tIEEE80211_ELEMID_TIM_BCAST_REQUEST\t= 94,\n\tIEEE80211_ELEMID_TIM_BCAST_RESPONSE\t= 95,\n\tIEEE80211_ELEMID_INTERFERENCE_REPORT\t= 96,\n\tIEEE80211_ELEMID_CHNL_USAGE\t\t= 97,\n\tIEEE80211_ELEMID_TIME_ZONE\t\t= 98,\n\tIEEE80211_ELEMID_DMS_REQUEST\t\t= 99,\n\tIEEE80211_ELEMID_DMS_RESPONSE\t\t= 100,\n\tIEEE80211_ELEMID_LINK_ID\t\t= 101,\n\tIEEE80211_ELEMID_WAKE_SCHED\t\t= 102,\n\t/* 103 undefined */\n\tIEEE80211_ELEMID_CHNL_SWITCH_TIMING\t= 104,\n\tIEEE80211_ELEMID_PTI_CTRL\t\t= 105,\n\tIEEE80211_ELEMID_TPU_BUF_STATUS\t\t= 106,\n\tIEEE80211_ELEMID_INTERWORKING\t\t= 107,\n\tIEEE80211_ELEMID_ADVERT_PROTOCOL\t= 108,\n\tIEEE80211_ELEMID_EXPEDITED_BW_REQUEST\t= 109,\n\tIEEE80211_ELEMID_QOS_MAP_SET\t\t= 110,\n\tIEEE80211_ELEMID_ROAMING_CONSORTIUM\t= 111,\n\tIEEE80211_ELEMID_EMERGENCY_ALERT_ID\t= 112,\n\tIEEE80211_ELEMID_MESHCONF\t\t= 113,\n\tIEEE80211_ELEMID_MESHID\t\t\t= 114,\n\tIEEE80211_ELEMID_MESHLINK\t\t= 115,\n\tIEEE80211_ELEMID_MESHCNGST\t\t= 116,\n\tIEEE80211_ELEMID_MESHPEER\t\t= 117,\n\tIEEE80211_ELEMID_MESHCSA\t\t= 118,\n\tIEEE80211_ELEMID_MESHAWAKEW\t\t= 119,\n\tIEEE80211_ELEMID_MESHBEACONT\t\t= 120,\n\tIEEE80211_ELEMID_MCCAOP_SETUP_REQUEST\t= 121,\n\tIEEE80211_ELEMID_MCCAOP_SETUP_REPLY\t= 122,\n\tIEEE80211_ELEMID_MCCAOP_ADVERT\t\t= 123,\n\tIEEE80211_ELEMID_MCCAOP_TEARDOWN\t= 124,\n\tIEEE80211_ELEMID_MESHGANN\t\t= 125,\n\tIEEE80211_ELEMID_MESHRANN\t\t= 126,\n\tIEEE80211_ELEMID_XCAPS\t\t\t= 127,\n\t/* 128-129 reserved for Agere */\n\tIEEE80211_ELEMID_MESHPREQ\t\t= 130,\n\tIEEE80211_ELEMID_MESHPREP\t\t= 131,\n\tIEEE80211_ELEMID_MESHPERR\t\t= 132,\n\t/* 133-136 reserved for Cisco */\n\tIEEE80211_ELEMID_MESHPXU\t\t= 137,\n\tIEEE80211_ELEMID_MESHPXUC\t\t= 138,\n\tIEEE80211_ELEMID_AUTH_MESH_PEERING_XCHG\t= 139,\n\tIEEE80211_ELEMID_MIC\t\t\t= 140,\n\tIEEE80211_ELEMID_DEST_URI\t\t= 141,\n\tIEEE80211_ELEMID_U_APSD_COEX\t\t= 142,\n\t/* 143-174 reserved */\n    IEEE80211_ELEMID_WAKEUP_SCHEDULE    = 143,\n    IEEE80211_ELEMID_EXT_SCHEDULE       = 144,\n    IEEE80211_ELEMID_STA_AVAILABILITY   = 145,\n    IEEE80211_ELEMID_DMG_TSPEC          = 146,\n    IEEE80211_ELEMID_DMG_AT             = 147,\n    IEEE80211_ELEMID_DMG_CAP            = 148,\n    /* 149 reserved for Cisco */\n    IEEE80211_ELEMID_CISCO_VENDOR_SPECIFIC  = 150,\n    IEEE80211_ELEMID_DMG_OPERATION          = 151,\n    IEEE80211_ELEMID_DMG_BSS_PARAM_CHANGE   = 152,\n    IEEE80211_ELEMID_DMG_BEAM_REFINEMENT    = 153,\n    IEEE80211_ELEMID_CHANNEL_MEASURE_FEEDBACK = 154,\n    /* 155-156 reserved for Cisco */\n    IEEE80211_ELEMID_AWAKE_WINDOW           = 157,\n    IEEE80211_ELEMID_MULTI_BAND             = 158,\n    IEEE80211_ELEMID_ADDBA_EXT              = 159,\n    IEEE80211_ELEMID_NEXT_PCP_LIST          = 160,\n    IEEE80211_ELEMID_PCP_HANDOVER           = 161,\n    IEEE80211_ELEMID_DMG_LINK_MARGIN        = 162,\n    IEEE80211_ELEMID_SWITCHING_STREAM       = 163,\n    IEEE80211_ELEMID_SESSION_TRANSITION     = 164,\n    IEEE80211_ELEMID_DYN_TONE_PAIRING_REPORT = 165,\n    IEEE80211_ELEMID_CLUSTER_REPORT         = 166,\n    IEEE80211_ELEMID_RELAY_CAP              = 167,\n    IEEE80211_ELEMID_RELAY_XFER_PARAM_SET   = 168,\n    IEEE80211_ELEMID_BEAM_LINK_MAINT        = 169,\n    IEEE80211_ELEMID_MULTIPLE_MAC_ADDR      = 170,\n    IEEE80211_ELEMID_U_PID                  = 171,\n    IEEE80211_ELEMID_DMG_LINK_ADAPT_ACK     = 172,\n    /* 173 reserved for Symbol */\n\tIEEE80211_ELEMID_MCCAOP_ADVERT_OVIEW\t= 174,\n    IEEE80211_ELEMID_QUIET_PERIOD_REQ       = 175,\n    /* 176 reserved for Symbol */\n    IEEE80211_ELEMID_QUIET_PERIOD_RESP      = 177,\n\t/* 178-179 reserved for Symbol */\n    /* 180 reserved for ISO/IEC 20011 */\n    IEEE80211_ELEMID_EPAC_POLICY            = 182,\n    IEEE80211_ELEMID_CLISTER_TIME_OFF       = 183,\n    IEEE80211_ELEMID_INTER_AC_PRIO          = 184,\n    IEEE80211_ELEMID_SCS_DESCRIPTOR         = 185,\n    IEEE80211_ELEMID_QLOAD_REPORT           = 186,\n    IEEE80211_ELEMID_HCCA_TXOP_UPDATE_COUNT = 187,\n    IEEE80211_ELEMID_HL_STREAM_ID           = 188,\n    IEEE80211_ELEMID_GCR_GROUP_ADDR         = 189,\n    IEEE80211_ELEMID_ANTENNA_SECTOR_ID_PATTERN = 190,\n    /* 802.11ac */\n    IEEE80211_ELEMID_VHT_CAP    = 191,\n    IEEE80211_ELEMID_VHT_OPMODE    = 192,\n    IEEE80211_ELEMID_EXTENDED_BSS_LOAD = 193,\n    IEEE80211_ELEMID_WIDE_BW_CHANNEL_SWITCH = 194,\n    IEEE80211_ELEMID_VHT_PWR_ENV    = 195,\n    IEEE80211_ELEMID_CHANNEL_SWITCH_WRAPPER = 196,\n    IEEE80211_ELEMID_AID            = 197,\n    IEEE80211_ELEMID_QUIET_CHANNEL  = 198,\n    IEEE80211_ELEMID_OPMODE_NOTIF   = 199,\n\tIEEE80211_ELEMID_VENDOR\t\t\t= 221,\t/* vendor private */\n    IEEE80211_ELEMID_QOS_PARAMETER  = 222,\n    IEEE80211_ELEMID_CAG_NUMBER     = 237,\n    IEEE80211_ELEMID_AP_CSN         = 239,\n    IEEE80211_ELEMID_FILS_INDICATION = 240,\n    IEEE80211_ELEMID_DILS           = 241,\n    IEEE80211_ELEMID_FRAGMENT       = 242,\n    IEEE80211_ELEMID_EXTENSION      = 255,\n};\n\n/* Element ID Extensions for Element ID 255 */\nenum ieee80211_eid_ext {\n    IEEE80211_ELEMID_EXT_ASSOC_DELAY_INFO = 1,\n    IEEE80211_ELEMID_EXT_FILS_REQ_PARAMS = 2,\n    IEEE80211_ELEMID_EXT_FILS_KEY_CONFIRM = 3,\n    IEEE80211_ELEMID_EXT_FILS_SESSION = 4,\n    IEEE80211_ELEMID_EXT_FILS_HLP_CONTAINER = 5,\n    IEEE80211_ELEMID_EXT_FILS_IP_ADDR_ASSIGN = 6,\n    IEEE80211_ELEMID_EXT_KEY_DELIVERY = 7,\n    IEEE80211_ELEMID_EXT_FILS_WRAPPED_DATA = 8,\n    IEEE80211_ELEMID_EXT_FILS_PUBLIC_KEY = 12,\n    IEEE80211_ELEMID_EXT_FILS_NONCE = 13,\n    IEEE80211_ELEMID_EXT_FUTURE_CHAN_GUIDANCE = 14,\n    IEEE80211_ELEMID_EXT_HE_CAPABILITY = 35,\n    IEEE80211_ELEMID_EXT_HE_OPERATION = 36,\n    IEEE80211_ELEMID_EXT_UORA = 37,\n    IEEE80211_ELEMID_EXT_HE_MU_EDCA = 38,\n    IEEE80211_ELEMID_EXT_HE_SPR = 39,\n    IEEE80211_ELEMID_EXT_NDP_FEEDBACK_REPORT_PARAMSET = 41,\n    IEEE80211_ELEMID_EXT_BSS_COLOR_CHG_ANN = 42,\n    IEEE80211_ELEMID_EXT_QUIET_TIME_PERIOD_SETUP = 43,\n    IEEE80211_ELEMID_EXT_ESS_REPORT = 45,\n    IEEE80211_ELEMID_EXT_OPS = 46,\n    IEEE80211_ELEMID_EXT_HE_BSS_LOAD = 47,\n    IEEE80211_ELEMID_EXT_MAX_CHANNEL_SWITCH_TIME = 52,\n    IEEE80211_ELEMID_EXT_MULTIPLE_BSSID_CONFIGURATION = 55,\n    IEEE80211_ELEMID_EXT_NON_INHERITANCE = 56,\n    IEEE80211_ELEMID_EXT_KNOWN_BSSID = 57,\n    IEEE80211_ELEMID_EXT_SHORT_SSID_LIST = 58,\n    IEEE80211_ELEMID_EXT_HE_6GHZ_CAPA = 59,\n    IEEE80211_ELEMID_EXT_UL_MU_POWER_CAPA = 60,\n};\n\n/*\n * Action field category values (see 802.11-2012 8.4.1.11 Table 8-38).\n */\nenum {\n\tIEEE80211_CATEG_SPECTRUM\t\t= 0,\n\tIEEE80211_CATEG_QOS\t\t\t= 1,\n\tIEEE80211_CATEG_DLS\t\t\t= 2,\n\tIEEE80211_CATEG_BA\t\t\t= 3,\n\tIEEE80211_CATEG_PUB\t\t\t= 4,\n\tIEEE80211_CATEG_RADIO_MSRMNT\t\t= 5,\n\tIEEE80211_CATEG_FAST_BSS_TRANS\t\t= 6,\n\tIEEE80211_CATEG_HT\t\t\t= 7,\t/* 11n */\n\tIEEE80211_CATEG_SA_QUERY\t\t= 8,\t/* 11w */\n\tIEEE80211_CATEG_PROT_DUAL_PUBLIC_ACTION\t= 9,\n\tIEEE80211_CATEG_WNM\t\t\t= 10,\n\tIEEE80211_CATEG_UNPROT_WNM\t\t= 11,\n\tIEEE80211_CATEG_TDLS\t\t\t= 12,\n\tIEEE80211_CATEG_MESH\t\t\t= 13,\n\tIEEE80211_CATEG_MULTIHOP\t\t= 14,\n\tIEEE80211_CATEG_SELF_PROT\t\t= 15,\n\t/* 16-125 reserved */\n\tIEEE80211_CATEG_PROT_VENDOR\t\t= 126,\n\tIEEE80211_CATEG_VENDOR\t\t\t= 127\n\t/* 128-255 error */\n};\n\n/*\n * Block Ack Action field values (see 802.11-2012 8.5.5 Table 8-202).\n */\n#define IEEE80211_ACTION_ADDBA_REQ\t0\n#define IEEE80211_ACTION_ADDBA_RESP\t1\n#define IEEE80211_ACTION_DELBA\t\t2\n/* 3-255 reserved */\n\n/*\n * SA Query Action field values (see 802.11-2012 8.5.10 Table 8-227).\n */\n#define IEEE80211_ACTION_SA_QUERY_REQ\t0\n#define IEEE80211_ACTION_SA_QUERY_RESP\t1\n\n/*\n * HT Action field values (see 802.11-2012 8.5.12 Table 8-229).\n */\n#define IEEE80211_ACTION_NOTIFYCW\t\t0\n#define IEEE80211_ACTION_SM_PWRSAVE\t\t1\n#define IEEE80211_ACTION_PSMP\t\t\t2\n#define IEEE80211_ACTION_SET_PCO_PHASE\t\t3\n#define IEEE80211_ACTION_CSI\t\t\t4\n#define IEEE80211_ACTION_NONCOMPRESSED_BF\t5\n#define IEEE80211_ACTION_COMPRESSED_BF\t\t6\n#define IEEE80211_ACTION_ASEL_IDX_FEEDBACK\t7\n/* 8-255 reserved */\n\n#define\tIEEE80211_RATE_BASIC\t\t\t0x80\n#define\tIEEE80211_RATE_VAL\t\t\t0x7f\n#define\tIEEE80211_RATE_SIZE\t\t\t8\t/* 802.11 standard */\n#define\tIEEE80211_RATE_MAXSIZE\t\t\t15\t/* max rates we'll handle */\n\n#define\tIEEE80211_HT_NUM_MCS\t\t\t77\n#define\tIEEE80211_VHT_NUM_MCS\t\t\t10\n\n/*\n * BlockAck/BlockAckReq Control field (see 802.11-2012 8.3.1.9 Figure 8-25).\n */\n#define IEEE80211_BA_ACK_POLICY\t\t0x0001\n#define IEEE80211_BA_MULTI_TID\t\t0x0002\n#define IEEE80211_BA_COMPRESSED\t\t0x0004\n#define IEEE80211_BA_TID_INFO_MASK\t0xf000\n#define IEEE80211_BA_TID_INFO_SHIFT\t12\n\n/*\n * ADDBA Parameter Set field (see 802.11-2012 8.4.1.14 Figure 8-48).\n */\n#define IEEE80211_ADDBA_AMSDU\t\t0x0001 /* A-MSDU in A-MPDU supported */\n#define IEEE80211_ADDBA_BA_POLICY\t0x0002 /* 1=immediate BA 0=delayed BA */\n#define IEEE80211_ADDBA_TID_MASK\t0x003c\n#define IEEE80211_ADDBA_TID_SHIFT\t2\n#define IEEE80211_ADDBA_BUFSZ_MASK\t0xffc0\n#define IEEE80211_ADDBA_BUFSZ_SHIFT\t6\n\n/*\n * DELBA Parameter Set field (see 802.11-2012 8.4.1.16 Figure 8-50).\n */\n#define IEEE80211_DELBA_INITIATOR\t0x0800\n#define IEEE80211_DELBA_TID_INFO_MASK\t0xf000\n#define IEEE80211_DELBA_TID_INFO_SHIFT\t12\n\n/*\n * ERP information element parameters (see 802.11-2012 8.4.2.14 Figure 8-95).\n */\n#define\tIEEE80211_ERP_NON_ERP_PRESENT\t\t0x01\n#define\tIEEE80211_ERP_USE_PROTECTION\t\t0x02\n#define\tIEEE80211_ERP_BARKER_MODE\t\t0x04\n\n/*\n * RSN capabilities (see 802.11-2012 8.4.2.27.4).\n */\n#define IEEE80211_RSNCAP_PREAUTH\t\t0x0001\n#define IEEE80211_RSNCAP_NOPAIRWISE\t\t0x0002\n#define IEEE80211_RSNCAP_PTKSA_RCNT_MASK\t0x000c\n#define IEEE80211_RSNCAP_PTKSA_RCNT_SHIFT\t2\n#define IEEE80211_RSNCAP_GTKSA_RCNT_MASK\t0x0030\n#define IEEE80211_RSNCAP_GTKSA_RCNT_SHIFT\t4\n#define IEEE80211_RSNCAP_RCNT1\t\t\t0\n#define IEEE80211_RSNCAP_RCNT2\t\t\t1\n#define IEEE80211_RSNCAP_RCNT4\t\t\t2\n#define IEEE80211_RSNCAP_RCNT16\t\t\t3\n#define IEEE80211_RSNCAP_MFPR\t\t\t0x0040\t/* 11w */\n#define IEEE80211_RSNCAP_MFPC\t\t\t0x0080\t/* 11w */\n#define IEEE80211_RSNCAP_PEERKEYENA\t\t0x0200\n#define IEEE80211_RSNCAP_SPPAMSDUC\t\t0x0400\t/* 11n */\n#define IEEE80211_RSNCAP_SPPAMSDUR\t\t0x0800\t/* 11n */\n#define IEEE80211_RSNCAP_PBAC\t\t\t0x1000\t/* 11n */\n#define IEEE80211_RSNCAP_EXTENDED_KEYID\t\t0x2000\n\n/*\n * HT Capabilities Info (see 802.11-2012 8.4.2.58.2).\n */\n#define IEEE80211_HTCAP_LDPC\t\t0x00000001\n#define IEEE80211_HTCAP_CBW20_40\t0x00000002\n#define IEEE80211_HTCAP_SMPS_MASK\t0x0000000c\n#define IEEE80211_HTCAP_SMPS_SHIFT\t2\n#define IEEE80211_HTCAP_SMPS_STA\t0\n#define IEEE80211_HTCAP_SMPS_DYN\t1\n#define IEEE80211_HTCAP_SMPS_DIS\t3\n#define IEEE80211_HTCAP_GF\t\t0x00000010\n#define IEEE80211_HTCAP_SGI20\t\t0x00000020\n#define IEEE80211_HTCAP_SGI40\t\t0x00000040\n#define IEEE80211_HTCAP_TXSTBC\t\t0x00000080\n#define IEEE80211_HTCAP_RXSTBC_MASK\t0x00000300\n#define IEEE80211_HTCAP_RXSTBC_SHIFT\t8\n#define IEEE80211_HTCAP_DELAYEDBA\t0x00000400\n#define IEEE80211_HTCAP_AMSDU7935\t0x00000800\n#define IEEE80211_HTCAP_DSSSCCK40\t0x00001000\n#define IEEE80211_HTCAP_PSMP\t\t0x00002000\n#define IEEE80211_HTCAP_40INTOLERANT\t0x00004000\n#define IEEE80211_HTCAP_LSIGTXOPPROT\t0x00008000\n\n/*\n * HT A-MPDU parameters (see 802.11-2012 8.4.2.58.3).\n */\n#define IEEE80211_AMPDU_PARAM_LE\t0x03\n#define IEEE80211_AMPDU_PARAM_SS\t0x1c\n#define IEEE80211_AMPDU_PARAM_SS_NONE\t(0 << 2)\n#define IEEE80211_AMPDU_PARAM_SS_0_25\t(1 << 2)\n#define IEEE80211_AMPDU_PARAM_SS_0_5\t(2 << 2)\n#define IEEE80211_AMPDU_PARAM_SS_1\t(3 << 2)\n#define IEEE80211_AMPDU_PARAM_SS_2\t(4 << 2)\n#define IEEE80211_AMPDU_PARAM_SS_4\t(5 << 2)\n#define IEEE80211_AMPDU_PARAM_SS_8\t(6 << 2)\n#define IEEE80211_AMPDU_PARAM_SS_16\t(7 << 2)\n/* bits 5-7 reserved */\n\n/*\n * HT Supported MCS Set (see 802.11-2012 8.4.2.58.4).\n * This field is 16 bytes in size. Bitmasks given below\n * operate on 8 or 16 bit integer subsets of this field\n * for use with ieee80211com and ieee80211_node.\n */\n/* Bits 0-76: Supported Rx MCS bitmask */\n/* Bits 77-79: Reserved */\n/* Bits 80-89: Highest Rx rate in units of 1MB/s */\n#define IEEE80211_MCS_RX_RATE_HIGH\t0x03ff\n/* Bits 90-95: Reserved */\n/* Bits 96-100: Tx MCS set */\n#define IEEE80211_TX_MCS_SET_DEFINED\t\t0x01\n#define IEEE80211_TX_RX_MCS_NOT_EQUAL\t\t0x02\n#define IEEE80211_TX_SPATIAL_STREAMS\t\t0x0c\n#define IEEE80211_TX_UNEQUAL_MODULATION\t\t0x10\n/* Bits 101-127: Reserved */\n\n/*\n * HT Extended Capabilities (see 802.11-2012 8.4.2.58.5).\n */\n#define IEEE80211_HTXCAP_PCO\t\t0x0001\n#define IEEE80211_HTXCAP_PCOTT_MASK\t0x0006\n#define IEEE80211_HTXCAP_PCOTT_SHIFT\t1\n#define IEEE80211_HTXCAP_PCOTT_400\t1\n#define IEEE80211_HTXCAP_PCOTT_1500\t2\n#define IEEE80211_HTXCAP_PCOTT_5000\t3\n/* Bits 3-7 are reserved. */\n#define IEEE80211_HTXCAP_MFB_MASK\t0x0300\n#define IEEE80211_HTXCAP_MFB_SHIFT\t8\n#define IEEE80211_HTXCAP_MFB_NONE\t0\n#define IEEE80211_HTXCAP_MFB_UNSOL\t2\n#define IEEE80211_HTXCAP_MFB_BOTH\t3\n#define IEEE80211_HTXCAP_HTC\t\t0x0400\n#define IEEE80211_HTXCAP_RDRESP\t\t0x0800\n/* Bits 12-15 are reserved. */\n\n/*\n * Transmit Beamforming (TxBF) Capabilities (see 802.11-2012 8.4.2.58.6).\n */\n#define IEEE80211_TXBFCAP_IMPLICIT_RX\t\t\t0x00000001\n#define IEEE80211_TXBFCAP_RSSC\t\t\t\t0x00000002\n#define IEEE80211_TXBFCAP_TSSC\t\t\t\t0x00000004\n#define IEEE80211_TXBFCAP_RNDP\t\t\t\t0x00000008\n#define IEEE80211_TXBFCAP_TNDP\t\t\t\t0x00000010\n#define IEEE80211_TXBFCAP_IMPLICIT_TX\t\t\t0x00000020\n#define IEEE80211_TXBFCAP_CALIB_MASK\t\t\t0x000000c0\n#define IEEE80211_TXBFCAP_CALIB_SHIFT\t\t\t6\n#define IEEE80211_TXBFCAP_TX_CSI\t\t\t0x00000100\n#define IEEE80211_TXBFCAP_EXPLICIT_NSC\t\t\t0x00000200\n#define IEEE80211_TXBFCAP_EXPLICIT_CSC\t\t\t0x00000400\n#define IEEE80211_TXBFCAP_CSI_FB_DELAYED\t\t0x00000800\n#define IEEE80211_TXBFCAP_CSI_FB_IMMEDIATE\t\t0x00001000\n#define IEEE80211_TXBFCAP_EXPLICIT_NB_FB_DELAYED\t0x00002000\n#define IEEE80211_TXBFCAP_EXPLICIT_NB_FB_IMMEDIATE\t0x00004000\n#define IEEE80211_TXBFCAP_EXPLICIT_CB_FB_DELAYED\t0x00008000\n#define IEEE80211_TXBFCAP_EXPLICIT_CB_FB_IMMEDIATE\t0x00010000\n#define IEEE80211_TXBFCAP_MINIMAL_GROUPING_1_2\t\t0x00020000\n#define IEEE80211_TXBFCAP_MINIMAL_GROUPING_1_4\t\t0x00040000\n#define IEEE80211_TXBFCAP_CSI_NUM_ANT_MASK\t\t0x00180000\n#define IEEE80211_TXBFCAP_CSI_NUM_ANT_SHIFT\t\t19\n#define IEEE80211_TXBFCAP_NS_NUM_ANT_MASK\t\t0x00600000\n#define IEEE80211_TXBFCAP_NS_NUM_ANT_SHIFT\t\t21\n#define IEEE80211_TXBFCAP_CS_NUM_ANT_MASK\t\t0x01800000\n#define IEEE80211_TXBFCAP_CS_NUM_ANT_SHIFT\t\t23\n#define IEEE80211_TXBFCAP_CSI_NUM_ROWS_MASK\t\t0x06000000\n#define IEEE80211_TXBFCAP_CSI_NUM_ROWS_SHIFT\t\t25\n#define IEEE80211_TXBFCAP_CHANL_ESTIMATE_MASK\t\t0x18000000\n#define IEEE80211_TXBFCAP_CHANL_ESTIMATE_SHIFT\t\t27\n\n/*\n * Antenna Selection (ASEL) Capability (see 802.11-2012 8.4.2.58.7).\n */\n#define IEEE80211_ASELCAP_ASEL\t\t0x01\n#define IEEE80211_ASELCAP_CSIFB_TX\t0x02\n#define IEEE80211_ASELCAP_ANT_IDX_FB_TX\t0x04\n#define IEEE80211_ASELCAP_CSIFB\t\t0x08\n#define IEEE80211_ASELCAP_ANT_IDX_FB\t0x10\n#define IEEE80211_ASELCAP_ASEL_RX\t0x20\n#define IEEE80211_ASELCAP_TX_SOUND_PPDU\t0x20\n/* Bit 7 is reserved. */\n\n/*\n * HT Operation element (see 802.11-2012 8.4.2.59).\n */\n/* Byte 0 contains primary channel number. */\n/* Byte 1. */\n#define IEEE80211_HTOP0_SCO_MASK\t0x03\n#define IEEE80211_HTOP0_SCO_SHIFT\t0\n#define IEEE80211_HTOP0_SCO_SCN\t\t0\n#define IEEE80211_HTOP0_SCO_SCA\t\t1\n#define IEEE80211_HTOP0_SCO_SCB\t\t3\n#define IEEE80211_HTOP0_CHW\t\t0x04\n#define IEEE80211_HTOP0_RIFS\t\t0x08\n/* bits 4-7 reserved */\n/* Bytes 2-3. */\n#define IEEE80211_HTOP1_PROT_MASK\t0x0003\n#define IEEE80211_HTOP1_PROT_SHIFT\t0\n#define IEEE80211_HTOP1_NONGF_STA\t0x0004\n/* Bit 3 is reserved. */\n#define IEEE80211_HTOP1_OBSS_NONHT_STA\t0x0010\n/* Bits 5-15 are reserved. */\n#define IEEE80211_HT_OP_MODE_CCFS2_SHIFT        5\n#define IEEE80211_HT_OP_MODE_CCFS2_MASK            0x1fe0\n/* Bytes 4-5. */\n/* Bits 0-5 are reserved. */\n#define IEEE80211_HTOP2_DUALBEACON\t0x0040\n#define IEEE80211_HTOP2_DUALCTSPROT\t0x0080\n#define IEEE80211_HTOP2_STBCBEACON\t0x0100\n#define IEEE80211_HTOP2_LSIGTXOP\t0x0200\n#define IEEE80211_HTOP2_PCOACTIVE\t0x0400\n#define IEEE80211_HTOP2_PCOPHASE40\t0x0800\n/* Bits 12-15 are reserved. */\n\n/*\n * EDCA Access Categories.\n */\nenum ieee80211_edca_ac {\n\tEDCA_AC_BK  = 1,\t/* Background */\n\tEDCA_AC_BE  = 0,\t/* Best Effort */\n\tEDCA_AC_VI  = 2,\t/* Video */\n\tEDCA_AC_VO  = 3\t\t/* Voice */\n};\n#define EDCA_NUM_AC\t4\n\n/* number of TID values (traffic identifier) */\n#define IEEE80211_NUM_TID\t16\n\n/* Atheros private advanced capabilities info */\n#define\tATHEROS_CAP_TURBO_PRIME\t\t\t0x01\n#define\tATHEROS_CAP_COMPRESSION\t\t\t0x02\n#define\tATHEROS_CAP_FAST_FRAME\t\t\t0x04\n/* bits 3-6 reserved */\n#define\tATHEROS_CAP_BOOST\t\t\t0x80\n\n/*-\n * Organizationally Unique Identifiers.\n * See http://standards.ieee.org/regauth/oui/oui.txt for a list.\n */\n#define ATHEROS_OUI\t((const u_int8_t[]){ 0x00, 0x03, 0x7f })\n#define BROADCOM_OUI\t((const u_int8_t[]){ 0x00, 0x90, 0x4c })\n#define IEEE80211_OUI\t((const u_int8_t[]){ 0x00, 0x0f, 0xac })\n#define MICROSOFT_OUI\t((const u_int8_t[]){ 0x00, 0x50, 0xf2 })\n\n#define\tIEEE80211_AUTH_ALGORITHM(auth) \\\n\t((auth)[0] | ((auth)[1] << 8))\n#define\tIEEE80211_AUTH_TRANSACTION(auth) \\\n\t((auth)[2] | ((auth)[3] << 8))\n#define\tIEEE80211_AUTH_STATUS(auth) \\\n\t((auth)[4] | ((auth)[5] << 8))\n\n/*\n * Authentication Algorithm Number field (see 7.3.1.1).\n */\n#define IEEE80211_AUTH_ALG_OPEN\t\t\t0x0000\n#define IEEE80211_AUTH_ALG_SHARED\t\t0x0001\n#define IEEE80211_AUTH_ALG_LEAP\t\t\t0x0080\n\n/*\n * 802.11n HT Capability IE\n * NB: these reflect D1.10\n */\nstruct ieee80211_ie_htcap {\n    uint8_t        hc_id;            /* element ID */\n    uint8_t        hc_len;            /* length in bytes */\n    uint16_t    hc_cap;            /* HT caps (see below) */\n    uint8_t        hc_param;        /* HT params (see below) */\n    uint8_t     hc_mcsset[16];         /* supported MCS set */\n    uint16_t    hc_extcap;        /* extended HT capabilities */\n    uint32_t    hc_txbf;        /* txbf capabilities */\n    uint8_t        hc_antenna;        /* antenna capabilities */\n} __packed;\n\n/*\n * Authentication Transaction Sequence Number field (see 7.3.1.2).\n */\nenum {\n\tIEEE80211_AUTH_OPEN_REQUEST\t\t= 1,\n\tIEEE80211_AUTH_OPEN_RESPONSE\t\t= 2\n};\nenum {\n\tIEEE80211_AUTH_SHARED_REQUEST\t\t= 1,\n\tIEEE80211_AUTH_SHARED_CHALLENGE\t\t= 2,\n\tIEEE80211_AUTH_SHARED_RESPONSE\t\t= 3,\n\tIEEE80211_AUTH_SHARED_PASS\t\t= 4\n};\n\n/*\n * Reason codes (see Table 22).\n */\nenum {\n\tIEEE80211_REASON_UNSPECIFIED\t\t= 1,\n\tIEEE80211_REASON_AUTH_EXPIRE\t\t= 2,\n\tIEEE80211_REASON_AUTH_LEAVE\t\t= 3,\n\tIEEE80211_REASON_ASSOC_EXPIRE\t\t= 4,\n\tIEEE80211_REASON_ASSOC_TOOMANY\t\t= 5,\n\tIEEE80211_REASON_NOT_AUTHED\t\t= 6,\n\tIEEE80211_REASON_NOT_ASSOCED\t\t= 7,\n\tIEEE80211_REASON_ASSOC_LEAVE\t\t= 8,\n\tIEEE80211_REASON_ASSOC_NOT_AUTHED\t= 9,\n\n\t/* XXX the following two reason codes are not correct */\n\tIEEE80211_REASON_RSN_REQUIRED\t\t= 11,\n\tIEEE80211_REASON_RSN_INCONSISTENT\t= 12,\n\n\tIEEE80211_REASON_IE_INVALID\t\t= 13,\n\tIEEE80211_REASON_MIC_FAILURE\t\t= 14,\n\tIEEE80211_REASON_4WAY_TIMEOUT\t\t= 15,\n\tIEEE80211_REASON_GROUP_TIMEOUT\t\t= 16,\n\tIEEE80211_REASON_RSN_DIFFERENT_IE\t= 17,\n\tIEEE80211_REASON_BAD_GROUP_CIPHER\t= 18,\n\tIEEE80211_REASON_BAD_PAIRWISE_CIPHER\t= 19,\n\tIEEE80211_REASON_BAD_AKMP\t\t= 20,\n\tIEEE80211_REASON_RSN_IE_VER_UNSUP\t= 21,\n\tIEEE80211_REASON_RSN_IE_BAD_CAP\t\t= 22,\n\n\tIEEE80211_REASON_CIPHER_REJ_POLICY\t= 24,\n\n\tIEEE80211_REASON_SETUP_REQUIRED\t\t= 38,\n\tIEEE80211_REASON_TIMEOUT\t\t= 39\n};\n\n/*\n * Status codes (see Table 23).\n */\nenum {\n\tIEEE80211_STATUS_SUCCESS\t\t= 0,\n\tIEEE80211_STATUS_UNSPECIFIED\t\t= 1,\n\tIEEE80211_STATUS_CAPINFO\t\t= 10,\n\tIEEE80211_STATUS_NOT_ASSOCED\t\t= 11,\n\tIEEE80211_STATUS_OTHER\t\t\t= 12,\n\tIEEE80211_STATUS_ALG\t\t\t= 13,\n\tIEEE80211_STATUS_SEQUENCE\t\t= 14,\n\tIEEE80211_STATUS_CHALLENGE\t\t= 15,\n\tIEEE80211_STATUS_TIMEOUT\t\t= 16,\n\tIEEE80211_STATUS_TOOMANY\t\t= 17,\n\tIEEE80211_STATUS_BASIC_RATE\t\t= 18,\n\tIEEE80211_STATUS_SP_REQUIRED\t\t= 19,\n\tIEEE80211_STATUS_PBCC_REQUIRED\t\t= 20,\n\tIEEE80211_STATUS_CA_REQUIRED\t\t= 21,\n\tIEEE80211_STATUS_TOO_MANY_STATIONS\t= 22,\n\tIEEE80211_STATUS_RATES\t\t\t= 23,\n\tIEEE80211_STATUS_SHORTSLOT_REQUIRED\t= 25,\n\tIEEE80211_STATUS_DSSSOFDM_REQUIRED\t= 26,\n\n\tIEEE80211_STATUS_TRY_AGAIN_LATER\t= 30,\n\tIEEE80211_STATUS_MFP_POLICY\t\t= 31,\n\n\tIEEE80211_STATUS_REFUSED\t\t= 37,\n\tIEEE80211_STATUS_INVALID_PARAM\t\t= 38,\n\n\tIEEE80211_STATUS_IE_INVALID\t\t= 40,\n\tIEEE80211_STATUS_BAD_GROUP_CIPHER\t= 41,\n\tIEEE80211_STATUS_BAD_PAIRWISE_CIPHER\t= 42,\n\tIEEE80211_STATUS_BAD_AKMP\t\t= 43,\n\tIEEE80211_STATUS_RSN_IE_VER_UNSUP\t= 44,\n\n\tIEEE80211_STATUS_CIPHER_REJ_POLICY\t= 46\n};\n\n#define\tIEEE80211_WEP_KEYLEN\t\t\t5\t/* 40bit */\n#define\tIEEE80211_WEP_NKID\t\t\t4\t/* number of key ids */\n#define IEEE80211_CHALLENGE_LEN\t\t\t128\n\n/* WEP header constants */\n#define\tIEEE80211_WEP_IVLEN\t\t\t3\t/* 24bit */\n#define\tIEEE80211_WEP_KIDLEN\t\t\t1\t/* 1 octet */\n#define\tIEEE80211_WEP_CRCLEN\t\t\t4\t/* CRC-32 */\n#define\tIEEE80211_CRC_LEN\t\t\t4\n#define\tIEEE80211_WEP_TOTLEN\t\t(IEEE80211_WEP_IVLEN + \\\n\t\t\t\t\t IEEE80211_WEP_KIDLEN + \\\n\t\t\t\t\t IEEE80211_WEP_CRCLEN)\n\n/*\n * 802.11i defines an extended IV for use with non-WEP ciphers.\n * When the EXTIV bit is set in the key id byte an additional\n * 4 bytes immediately follow the IV for TKIP.  For CCMP the\n * EXTIV bit is likewise set but the 8 bytes represent the\n * CCMP header rather than IV+extended-IV.\n */\n#define\tIEEE80211_WEP_EXTIV\t\t0x20\n#define\tIEEE80211_WEP_EXTIVLEN\t\t4\t/* extended IV length */\n#define\tIEEE80211_WEP_MICLEN\t\t8\t/* trailing MIC */\n\n/*\n * Maximum acceptable MTU is:\n *\tIEEE80211_MAX_LEN - WEP overhead - CRC -\n *\t\tQoS overhead - RSN/WPA overhead\n * Min is arbitrarily chosen > IEEE80211_MIN_LEN.  The default\n * mtu is Ethernet-compatible; it's set by ether_ifattach.\n */\n#define\tIEEE80211_MTU_MAX\t\t\t2290\n#define\tIEEE80211_MTU_MIN\t\t\t32\n\n#define\tIEEE80211_MAX_LEN\t\t\t(2300 + IEEE80211_CRC_LEN + \\\n    (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN))\n#define\tIEEE80211_ACK_LEN \\\n\t(sizeof(struct ieee80211_frame_ack) + IEEE80211_CRC_LEN)\n#define\tIEEE80211_MIN_LEN \\\n\t(sizeof(struct ieee80211_frame_min) + IEEE80211_CRC_LEN)\n\n/* Maximal size of an A-MSDU that can be transported in a HT BA session */\n#define IEEE80211_MAX_MPDU_LEN_HT_BA        4095\n\n/* Maximal size of an A-MSDU */\n#define IEEE80211_MAX_MPDU_LEN_HT_3839        3839\n#define IEEE80211_MAX_MPDU_LEN_HT_7935        7935\n\n#define IEEE80211_MAX_MPDU_LEN_VHT_3895        3895\n#define IEEE80211_MAX_MPDU_LEN_VHT_7991        7991\n#define IEEE80211_MAX_MPDU_LEN_VHT_11454    11454\n\n/*\n * The 802.11 spec says at most 2007 stations may be\n * associated at once.  For most AP's this is way more\n * than is feasible so we use a default of 1800. This\n * number may be overridden by the driver and/or by\n * user configuration.\n */\n#define\tIEEE80211_AID_MAX\t2007\n#define\tIEEE80211_AID_DEF\t1800\n#define IEEE80211_AID(b)\t((b) &~ 0xc000)\n\n/*\n * RTS frame length parameters.  The default is specified in\n * the 802.11 spec.  The max may be wrong for jumbo frames.\n */\n#define\tIEEE80211_RTS_DEFAULT\t\t\t512\n#define\tIEEE80211_RTS_MIN\t\t\t1\n#define\tIEEE80211_RTS_MAX\t\t\tIEEE80211_MAX_LEN\n\n#define IEEE80211_PLCP_SERVICE\t\t0x00\n#define IEEE80211_PLCP_SERVICE_PBCC\t0x08\t/* PBCC encoded */\n#define IEEE80211_PLCP_SERVICE_LENEXT\t0x80\t/* length extension bit */\n\n/* One Time Unit (TU) is 1Kus = 1024 microseconds. */\n#define IEEE80211_DUR_TU\t\t1024\n\n/* IEEE 802.11b durations for DSSS PHY in microseconds */\n#define IEEE80211_DUR_DS_LONG_PREAMBLE\t144\n#define IEEE80211_DUR_DS_SHORT_PREAMBLE\t72\n#define\tIEEE80211_DUR_DS_PREAMBLE_DIFFERENCE\t\\\n    (IEEE80211_DUR_DS_LONG_PREAMBLE - IEEE80211_DUR_DS_SHORT_PREAMBLE)\n#define IEEE80211_DUR_DS_FAST_PLCPHDR\t24\n#define IEEE80211_DUR_DS_SLOW_PLCPHDR\t48\n#define\tIEEE80211_DUR_DS_PLCPHDR_DIFFERENCE\t\\\n    (IEEE80211_DUR_DS_SLOW_PLCPHDR - IEEE80211_DUR_DS_FAST_PLCPHDR)\n#define IEEE80211_DUR_DS_SLOW_ACK\t112\n#define IEEE80211_DUR_DS_FAST_ACK\t56\n#define IEEE80211_DUR_DS_SLOW_CTS\t112\n#define IEEE80211_DUR_DS_FAST_CTS\t56\n#define IEEE80211_DUR_DS_SLOT\t\t20\n#define IEEE80211_DUR_DS_SHSLOT\t\t9\n#define IEEE80211_DUR_DS_SIFS\t\t10\n#define IEEE80211_DUR_DS_PIFS\t(IEEE80211_DUR_DS_SIFS + IEEE80211_DUR_DS_SLOT)\n#define IEEE80211_DUR_DS_DIFS\t(IEEE80211_DUR_DS_SIFS + \\\n\t\t\t\t 2 * IEEE80211_DUR_DS_SLOT)\n#define IEEE80211_DUR_DS_EIFS\t(IEEE80211_DUR_DS_SIFS + \\\n\t\t\t\t IEEE80211_DUR_DS_SLOW_ACK + \\\n\t\t\t\t IEEE80211_DUR_DS_LONG_PREAMBLE + \\\n\t\t\t\t IEEE80211_DUR_DS_SLOW_PLCPHDR + \\\n\t\t\t\t IEEE80211_DUR_DIFS)\n\n/*\n * The RSNA key descriptor used by IEEE 802.11 does not use the IEEE 802.1X\n * key descriptor.  Instead, it uses the key descriptor described in 8.5.2.\n */\n#define EAPOL_KEY_NONCE_LEN\t32\n#define EAPOL_KEY_IV_LEN\t16\n#define EAPOL_KEY_MIC_LEN\t16\n\nstruct ieee80211_eapol_key {\n\tu_int8_t\tversion;\n#define EAPOL_VERSION\t1\n\n\tu_int8_t\ttype;\n/* IEEE Std 802.1X-2004, 7.5.4 (only type EAPOL-Key is used here) */\n#define EAP_PACKET\t0\n#define EAPOL_START\t1\n#define EAPOL_LOGOFF\t2\n#define EAPOL_KEY\t3\n#define EAPOL_ASF_ALERT\t4\n\n\tu_int8_t\tlen[2];\n\tu_int8_t\tdesc;\n/* IEEE Std 802.1X-2004, 7.6.1 */\n#define EAPOL_KEY_DESC_RC4\t\t  1\t/* deprecated */\n#define EAPOL_KEY_DESC_IEEE80211\t  2\n#define EAPOL_KEY_DESC_WPA\t\t254\t/* non-standard WPA */\n\n\tu_int8_t\tinfo[2];\n#define EAPOL_KEY_VERSION_MASK\t0x7\n#define EAPOL_KEY_DESC_V1\t1\n#define EAPOL_KEY_DESC_V2\t2\n#define EAPOL_KEY_DESC_V3\t3\t\t/* 11r */\n#define EAPOL_KEY_PAIRWISE\t(1 <<  3)\n#define EAPOL_KEY_INSTALL\t(1 <<  6)\t/* I */\n#define EAPOL_KEY_KEYACK\t(1 <<  7)\t/* A */\n#define EAPOL_KEY_KEYMIC\t(1 <<  8)\t/* M */\n#define EAPOL_KEY_SECURE\t(1 <<  9)\t/* S */\n#define EAPOL_KEY_ERROR\t\t(1 << 10)\n#define EAPOL_KEY_REQUEST\t(1 << 11)\n#define EAPOL_KEY_ENCRYPTED\t(1 << 12)\n#define EAPOL_KEY_SMK\t\t(1 << 13)\n/* WPA compatibility */\n#define EAPOL_KEY_WPA_KID_MASK\t0x3\n#define EAPOL_KEY_WPA_KID_SHIFT\t4\n#define EAPOL_KEY_WPA_TX\tEAPOL_KEY_INSTALL\n\n\tu_int8_t\tkeylen[2];\n\tu_int8_t\treplaycnt[8];\n\tu_int8_t\tnonce[EAPOL_KEY_NONCE_LEN];\n\tu_int8_t\tiv[EAPOL_KEY_IV_LEN];\n\tu_int8_t\trsc[8];\n\tu_int8_t\treserved[8];\n\tu_int8_t\tmic[EAPOL_KEY_MIC_LEN];\n\tu_int8_t\tpaylen[2];\n} __packed;\n\n/* Pairwise Transient Key (see 8.5.1.2) */\nstruct ieee80211_ptk {\n\tu_int8_t\tkck[16];\t/* Key Confirmation Key */\n\tu_int8_t\tkek[16];\t/* Key Encryption Key */\n\tu_int8_t\ttk[32];\t\t/* Temporal Key */\n} __packed;\n\n#define IEEE80211_PMKID_LEN\t16\n#define IEEE80211_SMKID_LEN\t16\n\n/*\n * Key Data Encapsulation (see Table 62).\n */\nenum {\n\tIEEE80211_KDE_GTK\t= 1,\n\tIEEE80211_KDE_MACADDR\t= 3,\n\tIEEE80211_KDE_PMKID\t= 4,\n\tIEEE80211_KDE_SMK\t= 5,\n\tIEEE80211_KDE_NONCE\t= 6,\n\tIEEE80211_KDE_LIFETIME\t= 7,\n\tIEEE80211_KDE_ERROR\t= 8,\n\tIEEE80211_KDE_IGTK\t= 9\t/* 11w */\n};\n\n/*\n * HT protection modes (see 802.11-2012 8.4.2.59)\n */\nenum ieee80211_htprot {\n\tIEEE80211_HTPROT_NONE = 0,\t/* only 20/40MHz HT STAs exist */\n\tIEEE80211_HTPROT_NONMEMBER,\t/* non-HT STA overlaps our channel */ \n\tIEEE80211_HTPROT_20MHZ,\t\t/* 20MHz HT STA on a 40MHz channel */\n\tIEEE80211_HTPROT_NONHT_MIXED\t/* non-HT STA associated to our BSS */\n};\n\n/*\n * 802.11ac definitions - 802.11ac-2013 .\n */\n\n/*\n * Maximum length of A-MPDU that the STA can RX in VHT.\n * Length = 2 ^ (13 + max_ampdu_length_exp) - 1 (octets)\n */\n#define    IEEE80211_VHTCAP_MAX_AMPDU_8K        0\n#define    IEEE80211_VHTCAP_MAX_AMPDU_16K        1\n#define    IEEE80211_VHTCAP_MAX_AMPDU_32K        2\n#define    IEEE80211_VHTCAP_MAX_AMPDU_64K        3\n#define    IEEE80211_VHTCAP_MAX_AMPDU_128K        4\n#define    IEEE80211_VHTCAP_MAX_AMPDU_256K        5\n#define    IEEE80211_VHTCAP_MAX_AMPDU_512K        6\n#define    IEEE80211_VHTCAP_MAX_AMPDU_1024K    7\n\n/*\n * VHT MCS information.\n * + rx_highest/tx_highest: optional; maximum long GI VHT PPDU\n *    data rate.  1Mbit/sec units.\n * + rx_mcs_map/tx_mcs_map: bitmap of per-stream supported MCS;\n *    2 bits each.\n */\n#define    IEEE80211_VHT_MCS_SUPPORT_0_7        0    /* MCS0-7 */\n#define    IEEE80211_VHT_MCS_SUPPORT_0_8        1    /* MCS0-8 */\n#define    IEEE80211_VHT_MCS_SUPPORT_0_9        2    /* MCS0-9 */\n#define    IEEE80211_VHT_MCS_NOT_SUPPORTED        3    /* not supported */\n\nstruct ieee80211_vht_mcs_info {\n    uint16_t rx_mcs_map;\n    uint16_t rx_highest;\n    uint16_t tx_mcs_map;\n    uint16_t tx_highest;\n} __packed;\n\n/* for rx_highest */\n#define IEEE80211_VHT_MAX_NSTS_TOTAL_SHIFT    13\n#define IEEE80211_VHT_MAX_NSTS_TOTAL_MASK    (7 << IEEE80211_VHT_MAX_NSTS_TOTAL_SHIFT)\n\n/* for tx_highest */\n#define IEEE80211_VHT_EXT_NSS_BW_CAPABLE    (1 << 13)\n\n/* VHT capabilities element: 802.11ac-2013 8.4.2.160 */\nstruct ieee80211_ie_vhtcap {\n    uint8_t ie;\n    uint8_t len;\n    uint32_t vht_cap_info;\n    struct ieee80211_vht_mcs_info supp_mcs;\n} __packed;\n\n/* VHT operation mode subfields - 802.11ac-2013 Table 8.183x */\n#define    IEEE80211_VHT_CHANWIDTH_USE_HT        0    /* Use HT IE for chw */\n#define    IEEE80211_VHT_CHANWIDTH_80MHZ        1    /* 80MHz */\n#define    IEEE80211_VHT_CHANWIDTH_160MHZ        2    /* 160MHz */\n#define    IEEE80211_VHT_CHANWIDTH_80P80MHZ    3    /* 80+80MHz */\n\n/* VHT operation IE - 802.11ac-2013 8.4.2.161 */\nstruct ieee80211_ie_vht_operation {\n    uint8_t ie;\n    uint8_t len;\n    uint8_t chan_width;\n    uint8_t center_freq_seg1_idx;\n    uint8_t center_freq_seg2_idx;\n    uint16_t basic_mcs_set;\n} __packed;\n\n/* 802.11ac VHT Capabilities */\n#define    IEEE80211_VHTCAP_MAX_MPDU_LENGTH_3895    0x00000000\n#define    IEEE80211_VHTCAP_MAX_MPDU_LENGTH_7991    0x00000001\n#define    IEEE80211_VHTCAP_MAX_MPDU_LENGTH_11454    0x00000002\n#define    IEEE80211_VHTCAP_MAX_MPDU_MASK        0x00000003\n#define    IEEE80211_VHTCAP_MAX_MPDU_MASK_S    0\n\n#define    IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_MASK    0x0000000C\n#define    IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_MASK_S    2\n#define    IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_NONE        0\n#define    IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_160MHZ        4\n#define    IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_160_80P80MHZ    8\n\n#define    IEEE80211_VHTCAP_RXLDPC        0x00000010\n#define    IEEE80211_VHTCAP_RXLDPC_S    4\n\n#define    IEEE80211_VHTCAP_SHORT_GI_80        0x00000020\n#define    IEEE80211_VHTCAP_SHORT_GI_80_S        5\n\n#define    IEEE80211_VHTCAP_SHORT_GI_160        0x00000040\n#define    IEEE80211_VHTCAP_SHORT_GI_160_S        6\n\n#define    IEEE80211_VHTCAP_TXSTBC        0x00000080\n#define    IEEE80211_VHTCAP_TXSTBC_S    7\n\n#define    IEEE80211_VHTCAP_RXSTBC_1        0x00000100\n#define    IEEE80211_VHTCAP_RXSTBC_2        0x00000200\n#define    IEEE80211_VHTCAP_RXSTBC_3        0x00000300\n#define    IEEE80211_VHTCAP_RXSTBC_4        0x00000400\n#define    IEEE80211_VHTCAP_RXSTBC_MASK        0x00000700\n#define    IEEE80211_VHTCAP_RXSTBC_MASK_S        8\n\n#define    IEEE80211_VHTCAP_SU_BEAMFORMER_CAPABLE    0x00000800\n#define    IEEE80211_VHTCAP_SU_BEAMFORMER_CAPABLE_S    11\n\n#define    IEEE80211_VHTCAP_SU_BEAMFORMEE_CAPABLE    0x00001000\n#define    IEEE80211_VHTCAP_SU_BEAMFORMEE_CAPABLE_S    12\n\n#define    IEEE80211_VHTCAP_BEAMFORMEE_STS_SHIFT    13\n#define    IEEE80211_VHTCAP_BEAMFORMEE_STS_MASK \\\n        (7 << IEEE80211_VHTCAP_BEAMFORMEE_STS_SHIFT)\n#define    IEEE80211_VHTCAP_BEAMFORMEE_STS_MASK_S    13\n\n#define    IEEE80211_VHTCAP_SOUNDING_DIMENSIONS_SHIFT    16\n#define    IEEE80211_VHTCAP_SOUNDING_DIMENSIONS_MASK \\\n        (7 << IEEE80211_VHTCAP_SOUNDING_DIMENSIONS_SHIFT)\n#define    IEEE80211_VHTCAP_SOUNDING_DIMENSIONS_MASK_S    16\n\n#define    IEEE80211_VHTCAP_MU_BEAMFORMER_CAPABLE    0x00080000\n#define    IEEE80211_VHTCAP_MU_BEAMFORMER_CAPABLE_S    19\n#define    IEEE80211_VHTCAP_MU_BEAMFORMEE_CAPABLE    0x00100000\n#define    IEEE80211_VHTCAP_MU_BEAMFORMEE_CAPABLE_S    20\n#define    IEEE80211_VHTCAP_VHT_TXOP_PS        0x00200000\n#define    IEEE80211_VHTCAP_VHT_TXOP_PS_S        21\n#define    IEEE80211_VHTCAP_HTC_VHT        0x00400000\n#define    IEEE80211_VHTCAP_HTC_VHT_S        22\n\n#define    IEEE80211_VHTCAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT    23\n#define    IEEE80211_VHTCAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK \\\n        (7 << IEEE80211_VHTCAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT)\n#define    IEEE80211_VHTCAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK_S    23\n\n#define    IEEE80211_VHTCAP_VHT_LINK_ADAPTATION_VHT_MASK    0x0c000000\n#define    IEEE80211_VHTCAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB    0x08000000\n#define    IEEE80211_VHTCAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB    0x0c000000\n#define    IEEE80211_VHTCAP_VHT_LINK_ADAPTATION_VHT_MASK_S    26\n\n#define    IEEE80211_VHTCAP_RX_ANTENNA_PATTERN    0x10000000\n#define    IEEE80211_VHTCAP_RX_ANTENNA_PATTERN_S    28\n#define    IEEE80211_VHTCAP_TX_ANTENNA_PATTERN    0x20000000\n#define    IEEE80211_VHTCAP_TX_ANTENNA_PATTERN_S    29\n\n#define IEEE80211_VHTCAP_EXT_NSS_BW_SHIFT            30\n#define IEEE80211_VHTCAP_EXT_NSS_BW_MASK            0xc0000000\n\n/*\n * XXX TODO: add the rest of the bits\n */\n#define    IEEE80211_VHTCAP_BITS \\\n    \"\\20\\1MPDU7991\\2MPDU11454\\3CHAN160\\4CHAN8080\\5RXLDPC\\6SHORTGI80\" \\\n    \"\\7SHORTGI160\\10RXSTBC1\\11RXSTBC2\\12RXSTBC3\\13RXSTBC4\\14BFERCAP\" \\\n    \"\\15BFEECAP\\27VHT\\37RXANTPTN\\40TXANTPTN\"\n\n/*\n * VHT Transmit Power Envelope element - 802.11ac-2013 8.4.2.164\n *\n * This defines the maximum transmit power for various bandwidths.\n */\n/*\n * Count is how many elements follow and what they're for:\n *\n * 0 - 20 MHz\n * 1 - 20+40 MHz\n * 2 - 20+40+80 MHz\n * 3 - 20+40+80+(160, 80+80) MHz\n */\n#define    IEEE80211_VHT_TXPWRENV_INFO_COUNT_SHIFT    0\n#define    IEEE80211_VHT_TXPWRENV_INFO_COUNT_MASK    0x07\n\n/*\n * Unit is the tx power representation.  It should be EIRP for now;\n * other values are reserved.\n */\n#define    IEEE80211_VHT_TXPWRENV_UNIT_MASK    0x38\n#define    IEEE80211_VHT_TXPWRENV_UNIT_SHIFT    3\n\n/* This value is within the unit mask/shift above */\n#define    IEEE80211_VHT_TXPWRENV_UNIT_EIRP    0\n\nstruct ieee80211_ie_vht_txpwrenv {\n    uint8_t ie;\n    uint8_t len;\n    uint8_t tx_info;\n    int8_t tx_elem[0];    /* TX power elements, 1/2 dB, signed */\n};\n\n/* VHT action codes */\n#define    WLAN_ACTION_VHT_COMPRESSED_BF        0\n#define    WLAN_ACTION_VHT_GROUPID_MGMT        1\n#define    WLAN_ACTION_VHT_OPMODE_NOTIF        2\n\n#define IEEE80211_EXTCAP_CMS            (1ULL <<  0) /* 20/40 BSS coexistence management support */\n#define IEEE80211_EXTCAP_RSVD_1            (1ULL <<  1)\n#define IEEE80211_EXTCAP_ECS            (1ULL <<  2) /* extended channel switching */\n#define IEEE80211_EXTCAP_RSVD_3            (1ULL <<  3)\n#define IEEE80211_EXTCAP_PSMP_CAP        (1ULL <<  4) /* PSMP capability */\n#define IEEE80211_EXTCAP_RSVD_5            (1ULL <<  5)\n#define IEEE80211_EXTCAP_S_PSMP_SUPP        (1ULL <<  6)\n#define IEEE80211_EXTCAP_EVENT            (1ULL <<  7)\n#define IEEE80211_EXTCAP_DIAGNOSTICS        (1ULL <<  8)\n#define IEEE80211_EXTCAP_MCAST_DIAG        (1ULL <<  9)\n#define IEEE80211_EXTCAP_LOC_TRACKING        (1ULL << 10)\n#define IEEE80211_EXTCAP_FMS            (1ULL << 11)\n#define IEEE80211_EXTCAP_PROXY_ARP        (1ULL << 12)\n#define IEEE80211_EXTCAP_CIR            (1ULL << 13) /* collocated interference reporting */\n#define IEEE80211_EXTCAP_CIVIC_LOC        (1ULL << 14)\n#define IEEE80211_EXTCAP_GEOSPATIAL_LOC        (1ULL << 15)\n#define IEEE80211_EXTCAP_TFS            (1ULL << 16)\n#define IEEE80211_EXTCAP_WNM_SLEEPMODE        (1ULL << 17)\n#define IEEE80211_EXTCAP_TIM_BROADCAST        (1ULL << 18)\n#define IEEE80211_EXTCAP_BSS_TRANSITION        (1ULL << 19)\n#define IEEE80211_EXTCAP_QOS_TRAF_CAP        (1ULL << 20)\n#define IEEE80211_EXTCAP_AC_STA_COUNT        (1ULL << 21)\n#define IEEE80211_EXTCAP_M_BSSID        (1ULL << 22) /* multiple BSSID field */\n#define IEEE80211_EXTCAP_TIMING_MEAS        (1ULL << 23)\n#define IEEE80211_EXTCAP_CHAN_USAGE        (1ULL << 24)\n#define IEEE80211_EXTCAP_SSID_LIST        (1ULL << 25)\n#define IEEE80211_EXTCAP_DMS            (1ULL << 26)\n#define IEEE80211_EXTCAP_UTC_TSF_OFFSET        (1ULL << 27)\n#define IEEE80211_EXTCAP_TLDS_BUF_STA_SUPP    (1ULL << 28) /* TDLS peer U-APSP buffer STA support */\n#define IEEE80211_EXTCAP_TLDS_PPSM_SUPP        (1ULL << 29) /* TDLS peer PSM support */\n#define IEEE80211_EXTCAP_TLDS_CH_SW        (1ULL << 30) /* TDLS channel switching */\n#define IEEE80211_EXTCAP_INTERWORKING        (1ULL << 31)\n#define IEEE80211_EXTCAP_QOSMAP            (1ULL << 32)\n#define IEEE80211_EXTCAP_EBR            (1ULL << 33)\n#define IEEE80211_EXTCAP_SSPN_IF        (1ULL << 34)\n#define IEEE80211_EXTCAP_RSVD_35        (1ULL << 35)\n#define IEEE80211_EXTCAP_MSGCF_CAP        (1ULL << 36)\n#define IEEE80211_EXTCAP_TLDS_SUPP        (1ULL << 37)\n#define IEEE80211_EXTCAP_TLDS_PROHIB        (1ULL << 38)\n#define IEEE80211_EXTCAP_TLDS_CH_SW_PROHIB    (1ULL << 39) /* TDLS channel switching prohibited */\n#define IEEE80211_EXTCAP_RUF            (1ULL << 40) /* reject unadmitted frame */\n/* service interval granularity */\n#define IEEE80211_EXTCAP_SIG \\\n                ((1ULL << 41) | (1ULL << 42) | (1ULL << 43))\n#define IEEE80211_EXTCAP_ID_LOC            (1ULL << 44)\n#define IEEE80211_EXTCAP_U_APSD_COEX        (1ULL << 45)\n#define IEEE80211_EXTCAP_WNM_NOTIFICATION    (1ULL << 46)\n#define IEEE80211_EXTCAP_RSVD_47        (1ULL << 47)\n#define IEEE80211_EXTCAP_SSID            (1ULL << 48) /* UTF-8 SSID */\n/* bits 49-n are reserved */\n\nstruct ieee80211_extcap_ie {\n    uint8_t        ie;\n    uint8_t        len;\n} __packed;\n\n/*\n * 802.11h Quiet Time Element.\n */\nstruct ieee80211_quiet_ie {\n    uint8_t        quiet_ie;        /* IEEE80211_ELEMID_QUIET */\n    uint8_t        len;\n    uint8_t        tbttcount;        /* quiet start */\n    uint8_t        period;            /* beacon intervals between quiets */\n    uint16_t    duration;        /* TUs of each quiet*/\n    uint16_t    offset;            /* TUs of from TBTT of quiet start */\n} __packed;\n\n/*\n * 802.11h Channel Switch Announcement (CSA).\n */\nstruct ieee80211_csa_ie {\n    uint8_t        csa_ie;        /* IEEE80211_ELEMID_CHANSWITCHANN */\n    uint8_t        csa_len;\n    uint8_t        csa_mode;        /* Channel Switch Mode */\n    uint8_t        csa_newchan;        /* New Channel Number */\n    uint8_t        csa_count;        /* Channel Switch Count */\n} __packed;\n\n/**\n * struct ieee80211_vht_operation - VHT operation IE\n *\n * This structure is the \"VHT operation element\" as\n * described in 802.11ac D3.0 8.4.2.161\n * @chan_width: Operating channel width\n * @center_freq_seg0_idx: center freq segment 0 index\n * @center_freq_seg1_idx: center freq segment 1 index\n * @basic_mcs_set: VHT Basic MCS rate set\n */\nstruct ieee80211_vht_operation {\n    uint8_t chan_width;\n    uint8_t center_freq_seg0_idx;\n    uint8_t center_freq_seg1_idx;\n    uint16_t basic_mcs_set;\n} __packed;\n\n#define IEEE80211_HE_PPE_THRES_MAX_LEN        25\n\n/**\n * struct ieee80211_he_cap_elem - HE capabilities element\n *\n * This structure is the \"HE capabilities element\" fixed fields as\n * described in P802.11ax_D4.0 section 9.4.2.242.2 and 9.4.2.242.3\n */\nstruct ieee80211_he_cap_elem {\n    uint8_t mac_cap_info[6];\n    uint8_t phy_cap_info[11];\n} __packed;\n\n#define IEEE80211_TX_RX_MCS_NSS_DESC_MAX_LEN    5\n\n/**\n * enum ieee80211_he_mcs_support - HE MCS support definitions\n * @IEEE80211_HE_MCS_SUPPORT_0_7: MCSes 0-7 are supported for the\n *    number of streams\n * @IEEE80211_HE_MCS_SUPPORT_0_9: MCSes 0-9 are supported\n * @IEEE80211_HE_MCS_SUPPORT_0_11: MCSes 0-11 are supported\n * @IEEE80211_HE_MCS_NOT_SUPPORTED: This number of streams isn't supported\n *\n * These definitions are used in each 2-bit subfield of the rx_mcs_*\n * and tx_mcs_* fields of &struct ieee80211_he_mcs_nss_supp, which are\n * both split into 8 subfields by number of streams. These values indicate\n * which MCSes are supported for the number of streams the value appears\n * for.\n */\nenum ieee80211_he_mcs_support {\n    IEEE80211_HE_MCS_SUPPORT_0_7    = 0,\n    IEEE80211_HE_MCS_SUPPORT_0_9    = 1,\n    IEEE80211_HE_MCS_SUPPORT_0_11    = 2,\n    IEEE80211_HE_MCS_NOT_SUPPORTED    = 3,\n};\n\n/**\n * struct ieee80211_he_mcs_nss_supp - HE Tx/Rx HE MCS NSS Support Field\n *\n * This structure holds the data required for the Tx/Rx HE MCS NSS Support Field\n * described in P802.11ax_D2.0 section 9.4.2.237.4\n *\n * @rx_mcs_80: Rx MCS map 2 bits for each stream, total 8 streams, for channel\n *     widths less than 80MHz.\n * @tx_mcs_80: Tx MCS map 2 bits for each stream, total 8 streams, for channel\n *     widths less than 80MHz.\n * @rx_mcs_160: Rx MCS map 2 bits for each stream, total 8 streams, for channel\n *     width 160MHz.\n * @tx_mcs_160: Tx MCS map 2 bits for each stream, total 8 streams, for channel\n *     width 160MHz.\n * @rx_mcs_80p80: Rx MCS map 2 bits for each stream, total 8 streams, for\n *     channel width 80p80MHz.\n * @tx_mcs_80p80: Tx MCS map 2 bits for each stream, total 8 streams, for\n *     channel width 80p80MHz.\n */\nstruct ieee80211_he_mcs_nss_supp {\n    uint16_t rx_mcs_80;\n    uint16_t tx_mcs_80;\n    uint16_t rx_mcs_160;\n    uint16_t tx_mcs_160;\n    uint16_t rx_mcs_80p80;\n    uint16_t tx_mcs_80p80;\n} __packed;\n\n/**\n * struct ieee80211_he_operation - HE capabilities element\n *\n * This structure is the \"HE operation element\" fields as\n * described in P802.11ax_D4.0 section 9.4.2.243\n */\nstruct ieee80211_he_operation {\n    uint32_t he_oper_params;\n    uint16_t he_mcs_nss_set;\n    /* Optional 0,1,3,4,5,7 or 8 bytes: depends on @he_oper_params */\n    uint8_t optional[];\n} __packed;\n\n/**\n * struct ieee80211_he_spr - HE spatial reuse element\n *\n * This structure is the \"HE spatial reuse element\" element as\n * described in P802.11ax_D4.0 section 9.4.2.241\n */\nstruct ieee80211_he_spr {\n    uint8_t he_sr_control;\n    /* Optional 0 to 19 bytes: depends on @he_sr_control */\n    uint8_t optional[];\n} __packed;\n\n/**\n * struct ieee80211_he_mu_edca_param_ac_rec - MU AC Parameter Record field\n *\n * This structure is the \"MU AC Parameter Record\" fields as\n * described in P802.11ax_D4.0 section 9.4.2.245\n */\nstruct ieee80211_he_mu_edca_param_ac_rec {\n    uint8_t aifsn;\n    uint8_t ecw_min_max;\n    uint8_t mu_edca_timer;\n} __packed;\n\n/**\n * struct ieee80211_mu_edca_param_set - MU EDCA Parameter Set element\n *\n * This structure is the \"MU EDCA Parameter Set element\" fields as\n * described in P802.11ax_D4.0 section 9.4.2.245\n */\nstruct ieee80211_mu_edca_param_set {\n    uint8_t mu_qos_info;\n    struct ieee80211_he_mu_edca_param_ac_rec ac_be;\n    struct ieee80211_he_mu_edca_param_ac_rec ac_bk;\n    struct ieee80211_he_mu_edca_param_ac_rec ac_vi;\n    struct ieee80211_he_mu_edca_param_ac_rec ac_vo;\n} __packed;\n\n/* 802.11ax HE MAC capabilities */\n#define IEEE80211_HE_MAC_CAP0_HTC_HE                0x01\n#define IEEE80211_HE_MAC_CAP0_TWT_REQ                0x02\n#define IEEE80211_HE_MAC_CAP0_TWT_RES                0x04\n#define IEEE80211_HE_MAC_CAP0_DYNAMIC_FRAG_NOT_SUPP        0x00\n#define IEEE80211_HE_MAC_CAP0_DYNAMIC_FRAG_LEVEL_1        0x08\n#define IEEE80211_HE_MAC_CAP0_DYNAMIC_FRAG_LEVEL_2        0x10\n#define IEEE80211_HE_MAC_CAP0_DYNAMIC_FRAG_LEVEL_3        0x18\n#define IEEE80211_HE_MAC_CAP0_DYNAMIC_FRAG_MASK            0x18\n#define IEEE80211_HE_MAC_CAP0_MAX_NUM_FRAG_MSDU_1        0x00\n#define IEEE80211_HE_MAC_CAP0_MAX_NUM_FRAG_MSDU_2        0x20\n#define IEEE80211_HE_MAC_CAP0_MAX_NUM_FRAG_MSDU_4        0x40\n#define IEEE80211_HE_MAC_CAP0_MAX_NUM_FRAG_MSDU_8        0x60\n#define IEEE80211_HE_MAC_CAP0_MAX_NUM_FRAG_MSDU_16        0x80\n#define IEEE80211_HE_MAC_CAP0_MAX_NUM_FRAG_MSDU_32        0xa0\n#define IEEE80211_HE_MAC_CAP0_MAX_NUM_FRAG_MSDU_64        0xc0\n#define IEEE80211_HE_MAC_CAP0_MAX_NUM_FRAG_MSDU_UNLIMITED    0xe0\n#define IEEE80211_HE_MAC_CAP0_MAX_NUM_FRAG_MSDU_MASK        0xe0\n\n#define IEEE80211_HE_MAC_CAP1_MIN_FRAG_SIZE_UNLIMITED        0x00\n#define IEEE80211_HE_MAC_CAP1_MIN_FRAG_SIZE_128            0x01\n#define IEEE80211_HE_MAC_CAP1_MIN_FRAG_SIZE_256            0x02\n#define IEEE80211_HE_MAC_CAP1_MIN_FRAG_SIZE_512            0x03\n#define IEEE80211_HE_MAC_CAP1_MIN_FRAG_SIZE_MASK        0x03\n#define IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_0US        0x00\n#define IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_8US        0x04\n#define IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US        0x08\n#define IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_MASK        0x0c\n#define IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_1        0x00\n#define IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_2        0x10\n#define IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_3        0x20\n#define IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_4        0x30\n#define IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_5        0x40\n#define IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_6        0x50\n#define IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_7        0x60\n#define IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_8        0x70\n#define IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_MASK        0x70\n\n/* Link adaptation is split between byte HE_MAC_CAP1 and\n * HE_MAC_CAP2. It should be set only if IEEE80211_HE_MAC_CAP0_HTC_HE\n * in which case the following values apply:\n * 0 = No feedback.\n * 1 = reserved.\n * 2 = Unsolicited feedback.\n * 3 = both\n */\n#define IEEE80211_HE_MAC_CAP1_LINK_ADAPTATION            0x80\n\n#define IEEE80211_HE_MAC_CAP2_LINK_ADAPTATION            0x01\n#define IEEE80211_HE_MAC_CAP2_ALL_ACK                0x02\n#define IEEE80211_HE_MAC_CAP2_TRS                0x04\n#define IEEE80211_HE_MAC_CAP2_BSR                0x08\n#define IEEE80211_HE_MAC_CAP2_BCAST_TWT                0x10\n#define IEEE80211_HE_MAC_CAP2_32BIT_BA_BITMAP            0x20\n#define IEEE80211_HE_MAC_CAP2_MU_CASCADING            0x40\n#define IEEE80211_HE_MAC_CAP2_ACK_EN                0x80\n\n#define IEEE80211_HE_MAC_CAP3_OMI_CONTROL            0x02\n#define IEEE80211_HE_MAC_CAP3_OFDMA_RA                0x04\n\n/* The maximum length of an A-MDPU is defined by the combination of the Maximum\n * A-MDPU Length Exponent field in the HT capabilities, VHT capabilities and the\n * same field in the HE capabilities.\n */\n#define IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_USE_VHT    0x00\n#define IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_VHT_1        0x08\n#define IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_VHT_2        0x10\n#define IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_RESERVED    0x18\n#define IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_MASK        0x18\n#define IEEE80211_HE_MAC_CAP3_AMSDU_FRAG            0x20\n#define IEEE80211_HE_MAC_CAP3_FLEX_TWT_SCHED            0x40\n#define IEEE80211_HE_MAC_CAP3_RX_CTRL_FRAME_TO_MULTIBSS        0x80\n\n#define IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_SHIFT        3\n\n#define IEEE80211_HE_MAC_CAP4_BSRP_BQRP_A_MPDU_AGG        0x01\n#define IEEE80211_HE_MAC_CAP4_QTP                0x02\n#define IEEE80211_HE_MAC_CAP4_BQR                0x04\n#define IEEE80211_HE_MAC_CAP4_SRP_RESP                0x08\n#define IEEE80211_HE_MAC_CAP4_NDP_FB_REP            0x10\n#define IEEE80211_HE_MAC_CAP4_OPS                0x20\n#define IEEE80211_HE_MAC_CAP4_AMDSU_IN_AMPDU            0x40\n/* Multi TID agg TX is split between byte #4 and #5\n * The value is a combination of B39,B40,B41\n */\n#define IEEE80211_HE_MAC_CAP4_MULTI_TID_AGG_TX_QOS_B39        0x80\n\n#define IEEE80211_HE_MAC_CAP5_MULTI_TID_AGG_TX_QOS_B40        0x01\n#define IEEE80211_HE_MAC_CAP5_MULTI_TID_AGG_TX_QOS_B41        0x02\n#define IEEE80211_HE_MAC_CAP5_SUBCHAN_SELECVITE_TRANSMISSION    0x04\n#define IEEE80211_HE_MAC_CAP5_UL_2x996_TONE_RU            0x08\n#define IEEE80211_HE_MAC_CAP5_OM_CTRL_UL_MU_DATA_DIS_RX        0x10\n#define IEEE80211_HE_MAC_CAP5_HE_DYNAMIC_SM_PS            0x20\n#define IEEE80211_HE_MAC_CAP5_PUNCTURED_SOUNDING        0x40\n#define IEEE80211_HE_MAC_CAP5_HT_VHT_TRIG_FRAME_RX        0x80\n\n#define IEEE80211_HE_VHT_MAX_AMPDU_FACTOR    20\n#define IEEE80211_HE_HT_MAX_AMPDU_FACTOR    16\n\n/* 802.11ax HE PHY capabilities */\n#define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G        0x02\n#define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G    0x04\n#define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G        0x08\n#define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G    0x10\n#define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_2G    0x20\n#define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_5G    0x40\n#define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_MASK            0xfe\n\n#define IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_80MHZ_ONLY_SECOND_20MHZ    0x01\n#define IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_80MHZ_ONLY_SECOND_40MHZ    0x02\n#define IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_160MHZ_ONLY_SECOND_20MHZ    0x04\n#define IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_160MHZ_ONLY_SECOND_40MHZ    0x08\n#define IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_MASK            0x0f\n#define IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A                0x10\n#define IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD            0x20\n#define IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US        0x40\n/* Midamble RX/TX Max NSTS is split between byte #2 and byte #3 */\n#define IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_TX_MAX_NSTS            0x80\n\n#define IEEE80211_HE_PHY_CAP2_MIDAMBLE_RX_TX_MAX_NSTS            0x01\n#define IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US            0x02\n#define IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ            0x04\n#define IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ            0x08\n#define IEEE80211_HE_PHY_CAP2_DOPPLER_TX                0x10\n#define IEEE80211_HE_PHY_CAP2_DOPPLER_RX                0x20\n\n/* Note that the meaning of UL MU below is different between an AP and a non-AP\n * sta, where in the AP case it indicates support for Rx and in the non-AP sta\n * case it indicates support for Tx.\n */\n#define IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO            0x40\n#define IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO            0x80\n\n#define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_NO_DCM            0x00\n#define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_BPSK            0x01\n#define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_QPSK            0x02\n#define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_16_QAM            0x03\n#define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_MASK            0x03\n#define IEEE80211_HE_PHY_CAP3_DCM_MAX_TX_NSS_1                0x00\n#define IEEE80211_HE_PHY_CAP3_DCM_MAX_TX_NSS_2                0x04\n#define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_NO_DCM            0x00\n#define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_BPSK            0x08\n#define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_QPSK            0x10\n#define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_16_QAM            0x18\n#define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_MASK            0x18\n#define IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_1                0x00\n#define IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_2                0x20\n#define IEEE80211_HE_PHY_CAP3_RX_HE_MU_PPDU_FROM_NON_AP_STA        0x40\n#define IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER                0x80\n\n#define IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE                0x01\n#define IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER                0x02\n\n/* Minimal allowed value of Max STS under 80MHz is 3 */\n#define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_4        0x0c\n#define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_5        0x10\n#define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_6        0x14\n#define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_7        0x18\n#define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_8        0x1c\n#define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_MASK    0x1c\n\n/* Minimal allowed value of Max STS above 80MHz is 3 */\n#define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_4        0x60\n#define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_5        0x80\n#define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_6        0xa0\n#define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_7        0xc0\n#define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_8        0xe0\n#define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_MASK    0xe0\n\n#define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_1    0x00\n#define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_2    0x01\n#define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_3    0x02\n#define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_4    0x03\n#define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_5    0x04\n#define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_6    0x05\n#define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_7    0x06\n#define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_8    0x07\n#define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK    0x07\n\n#define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_1    0x00\n#define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_2    0x08\n#define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_3    0x10\n#define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_4    0x18\n#define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_5    0x20\n#define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_6    0x28\n#define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_7    0x30\n#define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_8    0x38\n#define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_MASK    0x38\n\n#define IEEE80211_HE_PHY_CAP5_NG16_SU_FEEDBACK                0x40\n#define IEEE80211_HE_PHY_CAP5_NG16_MU_FEEDBACK                0x80\n\n#define IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU            0x01\n#define IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU            0x02\n#define IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMER_FB            0x04\n#define IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMER_FB            0x08\n#define IEEE80211_HE_PHY_CAP6_TRIG_CQI_FB                0x10\n#define IEEE80211_HE_PHY_CAP6_PARTIAL_BW_EXT_RANGE            0x20\n#define IEEE80211_HE_PHY_CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO        0x40\n#define IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT            0x80\n\n#define IEEE80211_HE_PHY_CAP7_SRP_BASED_SR                0x01\n#define IEEE80211_HE_PHY_CAP7_POWER_BOOST_FACTOR_AR            0x02\n#define IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI        0x04\n#define IEEE80211_HE_PHY_CAP7_MAX_NC_1                    0x08\n#define IEEE80211_HE_PHY_CAP7_MAX_NC_2                    0x10\n#define IEEE80211_HE_PHY_CAP7_MAX_NC_3                    0x18\n#define IEEE80211_HE_PHY_CAP7_MAX_NC_4                    0x20\n#define IEEE80211_HE_PHY_CAP7_MAX_NC_5                    0x28\n#define IEEE80211_HE_PHY_CAP7_MAX_NC_6                    0x30\n#define IEEE80211_HE_PHY_CAP7_MAX_NC_7                    0x38\n#define IEEE80211_HE_PHY_CAP7_MAX_NC_MASK                0x38\n#define IEEE80211_HE_PHY_CAP7_STBC_TX_ABOVE_80MHZ            0x40\n#define IEEE80211_HE_PHY_CAP7_STBC_RX_ABOVE_80MHZ            0x80\n\n#define IEEE80211_HE_PHY_CAP8_HE_ER_SU_PPDU_4XLTF_AND_08_US_GI        0x01\n#define IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G        0x02\n#define IEEE80211_HE_PHY_CAP8_20MHZ_IN_160MHZ_HE_PPDU            0x04\n#define IEEE80211_HE_PHY_CAP8_80MHZ_IN_160MHZ_HE_PPDU            0x08\n#define IEEE80211_HE_PHY_CAP8_HE_ER_SU_1XLTF_AND_08_US_GI        0x10\n#define IEEE80211_HE_PHY_CAP8_MIDAMBLE_RX_TX_2X_AND_1XLTF        0x20\n#define IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_242                0x00\n#define IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_484                0x40\n#define IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_996                0x80\n#define IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_2x996                0xc0\n#define IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_MASK                0xc0\n\n#define IEEE80211_HE_PHY_CAP9_LONGER_THAN_16_SIGB_OFDM_SYM        0x01\n#define IEEE80211_HE_PHY_CAP9_NON_TRIGGERED_CQI_FEEDBACK        0x02\n#define IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU        0x04\n#define IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU        0x08\n#define IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB    0x10\n#define IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB    0x20\n#define IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_0US            0x00\n#define IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_8US            0x40\n#define IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_16US            0x80\n#define IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_RESERVED        0xc0\n#define IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_MASK            0xc0\n\n/* 802.11ax HE TX/RX MCS NSS Support  */\n#define IEEE80211_TX_RX_MCS_NSS_SUPP_HIGHEST_MCS_POS            (3)\n#define IEEE80211_TX_RX_MCS_NSS_SUPP_TX_BITMAP_POS            (6)\n#define IEEE80211_TX_RX_MCS_NSS_SUPP_RX_BITMAP_POS            (11)\n#define IEEE80211_TX_RX_MCS_NSS_SUPP_TX_BITMAP_MASK            0x07c0\n#define IEEE80211_TX_RX_MCS_NSS_SUPP_RX_BITMAP_MASK            0xf800\n\n/* TX/RX HE MCS Support field Highest MCS subfield encoding */\nenum ieee80211_he_highest_mcs_supported_subfield_enc {\n    HIGHEST_MCS_SUPPORTED_MCS7 = 0,\n    HIGHEST_MCS_SUPPORTED_MCS8,\n    HIGHEST_MCS_SUPPORTED_MCS9,\n    HIGHEST_MCS_SUPPORTED_MCS10,\n    HIGHEST_MCS_SUPPORTED_MCS11,\n};\n\n/* Calculate 802.11ax HE capabilities IE Tx/Rx HE MCS NSS Support Field size */\nstatic inline uint8_t\nieee80211_he_mcs_nss_size(const struct ieee80211_he_cap_elem *he_cap)\n{\n    uint8_t count = 4;\n\n    if (he_cap->phy_cap_info[0] &\n        IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G)\n        count += 4;\n\n    if (he_cap->phy_cap_info[0] &\n        IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)\n        count += 4;\n\n    return count;\n}\n\n/* 802.11ax HE PPE Thresholds */\n#define IEEE80211_PPE_THRES_NSS_SUPPORT_2NSS            (1)\n#define IEEE80211_PPE_THRES_NSS_POS                (0)\n#define IEEE80211_PPE_THRES_NSS_MASK                (7)\n#define IEEE80211_PPE_THRES_RU_INDEX_BITMASK_2x966_AND_966_RU    \\\n    ((1 << 5) | (1 << 6))\n#define IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK        0x78\n#define IEEE80211_PPE_THRES_RU_INDEX_BITMASK_POS        (3)\n#define IEEE80211_PPE_THRES_INFO_PPET_SIZE            (3)\n\n/* HE Operation defines */\n#define IEEE80211_HE_OPERATION_DFLT_PE_DURATION_MASK        0x00000007\n#define IEEE80211_HE_OPERATION_TWT_REQUIRED            0x00000008\n#define IEEE80211_HE_OPERATION_RTS_THRESHOLD_MASK        0x00003ff0\n#define IEEE80211_HE_OPERATION_RTS_THRESHOLD_OFFSET        4\n#define IEEE80211_HE_OPERATION_VHT_OPER_INFO            0x00004000\n#define IEEE80211_HE_OPERATION_CO_HOSTED_BSS            0x00008000\n#define IEEE80211_HE_OPERATION_ER_SU_DISABLE            0x00010000\n#define IEEE80211_HE_OPERATION_6GHZ_OP_INFO            0x00020000\n#define IEEE80211_HE_OPERATION_BSS_COLOR_MASK            0x3f000000\n#define IEEE80211_HE_OPERATION_BSS_COLOR_OFFSET            24\n#define IEEE80211_HE_OPERATION_PARTIAL_BSS_COLOR        0x40000000\n#define IEEE80211_HE_OPERATION_BSS_COLOR_DISABLED        0x80000000\n\n/*\n * Calculate 802.11ax HE capabilities IE PPE field size\n * Input: Header byte of ppe_thres (first byte), and HE capa IE's PHY cap u8*\n */\nstatic inline uint8_t\nieee80211_he_ppe_size(uint8_t ppe_thres_hdr, const uint8_t *phy_cap_info)\n{\n    uint8_t n;\n\n    if ((phy_cap_info[6] &\n         IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) == 0)\n        return 0;\n\n    n = hweight8(ppe_thres_hdr &\n             IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK);\n    n *= (1 + ((ppe_thres_hdr & IEEE80211_PPE_THRES_NSS_MASK) >>\n           IEEE80211_PPE_THRES_NSS_POS));\n\n    /*\n     * Each pair is 6 bits, and we need to add the 7 \"header\" bits to the\n     * total size.\n     */\n    n = (n * IEEE80211_PPE_THRES_INFO_PPET_SIZE * 2) + 7;\n    n = DIV_ROUND_UP(n, 8);\n\n    return n;\n}\n\n/**\n * ieee80211_he_6ghz_oper - HE 6 GHz operation Information field\n * @primary: primary channel\n * @control: control flags\n * @ccfs0: channel center frequency segment 0\n * @ccfs1: channel center frequency segment 1\n * @minrate: minimum rate (in 1 Mbps units)\n */\nstruct ieee80211_he_6ghz_oper {\n    uint8_t primary;\n#define IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH    0x3\n#define        IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_20MHZ    0\n#define        IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_40MHZ    1\n#define        IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_80MHZ    2\n#define        IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_160MHZ    3\n#define IEEE80211_HE_6GHZ_OPER_CTRL_DUP_BEACON    0x4\n    uint8_t control;\n    uint8_t ccfs0;\n    uint8_t ccfs1;\n    uint8_t minrate;\n} __packed;\n\n/*\n * ieee80211_he_oper_size - calculate 802.11ax HE Operations IE size\n * @he_oper_ie: byte data of the He Operations IE, stating from the byte\n *    after the ext ID byte. It is assumed that he_oper_ie has at least\n *    sizeof(struct ieee80211_he_operation) bytes, the caller must have\n *    validated this.\n * @return the actual size of the IE data (not including header), or 0 on error\n */\nstatic inline uint8_t\nieee80211_he_oper_size(const uint8_t *he_oper_ie)\n{\n    struct ieee80211_he_operation *he_oper = (struct ieee80211_he_operation *)he_oper_ie;\n    uint8_t oper_len = sizeof(struct ieee80211_he_operation);\n    uint32_t he_oper_params;\n\n    /* Make sure the input is not NULL */\n    if (!he_oper_ie)\n        return 0;\n\n    /* Calc required length */\n    he_oper_params = le32toh(he_oper->he_oper_params);\n    if (he_oper_params & IEEE80211_HE_OPERATION_VHT_OPER_INFO)\n        oper_len += 3;\n    if (he_oper_params & IEEE80211_HE_OPERATION_CO_HOSTED_BSS)\n        oper_len++;\n    if (he_oper_params & IEEE80211_HE_OPERATION_6GHZ_OP_INFO)\n        oper_len += sizeof(struct ieee80211_he_6ghz_oper);\n\n    /* Add the first byte (extension ID) to the total length */\n    oper_len++;\n\n    return oper_len;\n}\n\n/**\n * ieee80211_he_6ghz_oper - obtain 6 GHz operation field\n * @he_oper: HE operation element (must be pre-validated for size)\n *    but may be %NULL\n *\n * Return: a pointer to the 6 GHz operation field, or %NULL\n */\nstatic inline const struct ieee80211_he_6ghz_oper *\nieee80211_he_6ghz_oper(const struct ieee80211_he_operation *he_oper)\n{\n    const uint8_t *ret = (const uint8_t *)&he_oper->optional;\n    uint32_t he_oper_params;\n\n    if (!he_oper)\n        return NULL;\n\n    he_oper_params = le32toh(he_oper->he_oper_params);\n\n    if (!(he_oper_params & IEEE80211_HE_OPERATION_6GHZ_OP_INFO))\n        return NULL;\n    if (he_oper_params & IEEE80211_HE_OPERATION_VHT_OPER_INFO)\n        ret += 3;\n    if (he_oper_params & IEEE80211_HE_OPERATION_CO_HOSTED_BSS)\n        ret++;\n\n    return (struct ieee80211_he_6ghz_oper *)ret;\n}\n\n/* HE Spatial Reuse defines */\n#define IEEE80211_HE_SPR_PSR_DISALLOWED                (1 << 0)\n#define IEEE80211_HE_SPR_NON_SRG_OBSS_PD_SR_DISALLOWED        (1 << 1)\n#define IEEE80211_HE_SPR_NON_SRG_OFFSET_PRESENT            (1 << 2)\n#define IEEE80211_HE_SPR_SRG_INFORMATION_PRESENT        (1 << 3)\n#define IEEE80211_HE_SPR_HESIGA_SR_VAL15_ALLOWED        (1 << 4)\n\n/*\n * ieee80211_he_spr_size - calculate 802.11ax HE Spatial Reuse IE size\n * @he_spr_ie: byte data of the He Spatial Reuse IE, stating from the byte\n *    after the ext ID byte. It is assumed that he_spr_ie has at least\n *    sizeof(struct ieee80211_he_spr) bytes, the caller must have validated\n *    this\n * @return the actual size of the IE data (not including header), or 0 on error\n */\nstatic inline uint8_t\nieee80211_he_spr_size(const uint8_t *he_spr_ie)\n{\n    struct ieee80211_he_spr *he_spr = (struct ieee80211_he_spr *)he_spr_ie;\n    uint8_t spr_len = sizeof(struct ieee80211_he_spr);\n    uint8_t he_spr_params;\n\n    /* Make sure the input is not NULL */\n    if (!he_spr_ie)\n        return 0;\n\n    /* Calc required length */\n    he_spr_params = he_spr->he_sr_control;\n    if (he_spr_params & IEEE80211_HE_SPR_NON_SRG_OFFSET_PRESENT)\n        spr_len++;\n    if (he_spr_params & IEEE80211_HE_SPR_SRG_INFORMATION_PRESENT)\n        spr_len += 18;\n\n    /* Add the first byte (extension ID) to the total length */\n    spr_len++;\n\n    return spr_len;\n}\n\n/*\n * Note the min acceptable CSA count is used to guard against\n * malicious CSA injection in station mode.  Defining this value\n * as other than 0 violates the 11h spec.\n */\n#define    IEEE80211_CSA_COUNT_MIN    2\n#define    IEEE80211_CSA_COUNT_MAX    255\n\n#define    IEEE80211_IS_CHAN_HT(_c) \\\n    (((_c)->ic_flags & IEEE80211_CHAN_HT) != 0)\n#define    IEEE80211_IS_CHAN_HT20(_c) \\\n    (((_c)->ic_flags & IEEE80211_CHAN_HT20) != 0)\n#define    IEEE80211_IS_CHAN_HT40(_c) \\\n    (((_c)->ic_flags & IEEE80211_CHAN_HT40) != 0)\n#define    IEEE80211_IS_CHAN_HT40U(_c) \\\n    (((_c)->ic_flags & IEEE80211_CHAN_HT40U) != 0)\n#define    IEEE80211_IS_CHAN_HT40D(_c) \\\n    (((_c)->ic_flags & IEEE80211_CHAN_HT40D) != 0)\n\n#define    IEEE80211_IS_CHAN_VHT(_c) \\\n    (((_c)->ic_flags & IEEE80211_CHAN_VHT) != 0)\n#define    IEEE80211_IS_CHAN_VHT_2GHZ(_c) \\\n    (IEEE80211_IS_CHAN_2GHZ(_c) && \\\n     ((_c)->ic_flags & IEEE80211_CHAN_VHT) != 0)\n#define    IEEE80211_IS_CHAN_VHT_5GHZ(_c) \\\n    (IEEE80211_IS_CHAN_5GHZ(_c) && \\\n     ((_c)->ic_flags & IEEE80211_CHAN_VHT) != 0)\n#define    IEEE80211_IS_CHAN_VHT20(_c) \\\n    (((_c)->ic_flags & IEEE80211_CHAN_VHT20) != 0)\n#define    IEEE80211_IS_CHAN_VHT40(_c) \\\n    (((_c)->ic_flags & IEEE80211_CHAN_VHT40) != 0)\n#define    IEEE80211_IS_CHAN_VHT40U(_c) \\\n    (((_c)->ic_flags & IEEE80211_CHAN_VHT40U) != 0)\n#define    IEEE80211_IS_CHAN_VHT40D(_c) \\\n    (((_c)->ic_flags & IEEE80211_CHAN_VHT40D) != 0)\n#define    IEEE80211_IS_CHAN_VHTA(_c) \\\n    (IEEE80211_IS_CHAN_5GHZ(_c) && \\\n     ((_c)->ic_flags & IEEE80211_CHAN_VHT) != 0)\n#define    IEEE80211_IS_CHAN_VHTG(_c) \\\n    (IEEE80211_IS_CHAN_2GHZ(_c) && \\\n     ((_c)->ic_flags & IEEE80211_CHAN_VHT) != 0)\n#define    IEEE80211_IS_CHAN_VHT80(_c) \\\n    (((_c)->ic_flags & IEEE80211_CHAN_VHT80) != 0)\n#define    IEEE80211_IS_CHAN_VHT80_80(_c) \\\n    (((_c)->ic_flags & IEEE80211_CHAN_VHT80_80) != 0)\n#define    IEEE80211_IS_CHAN_VHT160(_c) \\\n    (((_c)->ic_flags & IEEE80211_CHAN_VHT160) != 0)\n\n#define    WME_OUI            0xf25000\n#define    WME_OUI_TYPE        0x02\n#define    WME_INFO_OUI_SUBTYPE    0x00\n#define    WME_PARAM_OUI_SUBTYPE    0x01\n#define    WME_VERSION        1\n\n/* WME stream classes */\n#define    WME_AC_BE    0        /* best effort */\n#define    WME_AC_BK    1        /* background */\n#define    WME_AC_VI    2        /* video */\n#define    WME_AC_VO    3        /* voice */\n\n/*\n * WME/802.11e information element.\n */\nstruct ieee80211_wme_info {\n    uint8_t        wme_id;        /* IEEE80211_ELEMID_VENDOR */\n    uint8_t        wme_len;    /* length in bytes */\n    uint8_t        wme_oui[3];    /* 0x00, 0x50, 0xf2 */\n    uint8_t        wme_type;    /* OUI type */\n    uint8_t        wme_subtype;    /* OUI subtype */\n    uint8_t        wme_version;    /* spec revision */\n    uint8_t        wme_info;    /* QoS info */\n} __packed;\n\n#ifdef AIRPORT\nstatic inline uint64_t airport_up_time()\n{\n    struct timeval tv;\n    microuptime(&tv);\n    return tv.tv_sec * 1000 + tv.tv_usec / 1000;\n}\n#endif\n\n#endif /* _NET80211_IEEE80211_H_ */\n\n\n"
  },
  {
    "path": "itl80211/openbsd/net80211/ieee80211_amrr.c",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n/*    $OpenBSD: ieee80211_amrr.c,v 1.12 2019/02/24 09:36:28 stsp Exp $    */\n\n/*-\n * Copyright (c) 2006\n *    Damien Bergamini <damien.bergamini@free.fr>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n#include <sys/param.h>\n#include <sys/systm.h>\n#include <sys/kernel.h>\n#include <sys/socket.h>\n\n#include <net/if.h>\n#include <net/if_media.h>\n\n#include <netinet/in.h>\n#include <netinet/if_ether.h>\n\n#include <net80211/ieee80211_var.h>\n#include <net80211/ieee80211_priv.h>\n#include <net80211/ieee80211_amrr.h>\n\n#define is_success(amn)    \\\n    ((amn)->amn_retrycnt < (amn)->amn_txcnt / 10)\n#define is_failure(amn)    \\\n    ((amn)->amn_retrycnt > (amn)->amn_txcnt / 3)\n#define is_enough(amn)        \\\n    ((amn)->amn_txcnt > 10)\n#define reset_cnt(amn)        \\\n    do { (amn)->amn_txcnt = (amn)->amn_retrycnt = 0; } while (0)\n\nstatic inline int\nis_min_rate(struct ieee80211_node *ni)\n{\n    return (ni->ni_txrate == 0);\n}\n\nstatic inline int\nis_max_rate(struct ieee80211_node *ni)\n{\n    return (ni->ni_txrate == ni->ni_rates.rs_nrates - 1);\n}\n\nstatic inline void\nincrease_rate(struct ieee80211_node *ni)\n{\n    ni->ni_txrate++;\n}\n\nstatic inline void\ndecrease_rate(struct ieee80211_node *ni)\n{\n    ni->ni_txrate--;\n}\n\nvoid\nieee80211_amrr_node_init(const struct ieee80211_amrr *amrr,\n    struct ieee80211_amrr_node *amn)\n{\n    amn->amn_success = 0;\n    amn->amn_recovery = 0;\n    amn->amn_txcnt = amn->amn_retrycnt = 0;\n    amn->amn_success_threshold = amrr->amrr_min_success_threshold;\n}\n\n/*\n * Update ni->ni_txrate.\n */\nvoid\nieee80211_amrr_choose(struct ieee80211_amrr *amrr, struct ieee80211_node *ni,\n    struct ieee80211_amrr_node *amn)\n{\n#define RV(rate)    ((rate) & IEEE80211_RATE_VAL)\n    int need_change = 0;\n\n    if (is_success(amn) && is_enough(amn)) {\n        amn->amn_success++;\n        if (amn->amn_success >= amn->amn_success_threshold &&\n            !is_max_rate(ni)) {\n            amn->amn_recovery = 1;\n            amn->amn_success = 0;\n            increase_rate(ni);\n            DPRINTF((\"increase rate=%d,#tx=%d,#retries=%d\\n\",\n                RV(ni->ni_rates.rs_rates[ni->ni_txrate]),\n                amn->amn_txcnt, amn->amn_retrycnt));\n            need_change = 1;\n        } else {\n            amn->amn_recovery = 0;\n        }\n    } else if (is_failure(amn)) {\n        amn->amn_success = 0;\n        if (!is_min_rate(ni)) {\n            if (amn->amn_recovery) {\n                amn->amn_success_threshold *= 2;\n                if (amn->amn_success_threshold >\n                    amrr->amrr_max_success_threshold)\n                    amn->amn_success_threshold =\n                        amrr->amrr_max_success_threshold;\n            } else {\n                amn->amn_success_threshold =\n                    amrr->amrr_min_success_threshold;\n            }\n            decrease_rate(ni);\n            DPRINTF((\"decrease rate=%d,#tx=%d,#retries=%d\\n\",\n                RV(ni->ni_rates.rs_rates[ni->ni_txrate]),\n                amn->amn_txcnt, amn->amn_retrycnt));\n            need_change = 1;\n        }\n        amn->amn_recovery = 0;\n    }\n\n    if (is_enough(amn) || need_change)\n        reset_cnt(amn);\n#undef RV\n}\n"
  },
  {
    "path": "itl80211/openbsd/net80211/ieee80211_amrr.h",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n/*\t$OpenBSD: ieee80211_amrr.h,v 1.4 2007/06/16 13:17:05 damien Exp $\t*/\n\n/*-\n * Copyright (c) 2006\n *\tDamien Bergamini <damien.bergamini@free.fr>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n#ifndef _NET80211_IEEE80211_AMRR_H_\n#define _NET80211_IEEE80211_AMRR_H_\n\n/*-\n * Naive implementation of the Adaptive Multi Rate Retry algorithm:\n *\n * \"IEEE 802.11 Rate Adaptation: A Practical Approach\"\n *  Mathieu Lacage, Hossein Manshaei, Thierry Turletti\n *  INRIA Sophia - Projet Planete\n *  http://www-sop.inria.fr/rapports/sophia/RR-5208.html\n */\n\n/*\n * Rate control settings.\n */\nstruct ieee80211_amrr {\n\tu_int\tamrr_min_success_threshold;\n\tu_int\tamrr_max_success_threshold;\n};\n\n#define IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD\t 1\n#define IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD\t15\n\n/*\n * Rate control state for a given node.\n */\nstruct ieee80211_amrr_node {\n\tu_int\tamn_success;\n\tu_int\tamn_recovery;\n\tu_int\tamn_success_threshold;\n\tu_int\tamn_txcnt;\n\tu_int\tamn_retrycnt;\n};\n\nvoid\tieee80211_amrr_node_init(const struct ieee80211_amrr *,\n\t    struct ieee80211_amrr_node *);\nvoid\tieee80211_amrr_choose(struct ieee80211_amrr *, struct ieee80211_node *,\n\t    struct ieee80211_amrr_node *);\n\n#endif /* _NET80211_IEEE80211_AMRR_H_ */\n"
  },
  {
    "path": "itl80211/openbsd/net80211/ieee80211_crypto.c",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n/*    $OpenBSD: ieee80211_crypto.c,v 1.75 2019/08/16 19:53:32 procter Exp $    */\n\n/*-\n * Copyright (c) 2008 Damien Bergamini <damien.bergamini@free.fr>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n#include <sys/param.h>\n#include <sys/systm.h>\n#include <sys/mbuf.h>\n#include <sys/malloc.h>\n#include <sys/kernel.h>\n#include <sys/socket.h>\n#include <sys/sockio.h>\n#include <sys/endian.h>\n#include <sys/errno.h>\n#include <sys/sysctl.h>\n\n#include <net/if.h>\n#include <net/if_dl.h>\n#include <net/if_media.h>\n\n#include <netinet/in.h>\n#include <netinet/if_ether.h>\n\n#include <net80211/ieee80211_var.h>\n#include <net80211/ieee80211_priv.h>\n\n#include <crypto/arc4.h>\n#include <crypto/md5.h>\n#include <crypto/sha1.h>\n#include <crypto/sha2.h>\n#include <crypto/hmac.h>\n#include <crypto/aes.h>\n#include <crypto/cmac.h>\n#include <crypto/key_wrap.h>\n\nvoid    ieee80211_prf(const u_int8_t *, size_t, const u_int8_t *, size_t,\n        const u_int8_t *, size_t, u_int8_t *, size_t);\nvoid    ieee80211_kdf(const u_int8_t *, size_t, const u_int8_t *, size_t,\n        const u_int8_t *, size_t, u_int8_t *, size_t);\nvoid    ieee80211_derive_pmkid(enum ieee80211_akm, const u_int8_t *,\n        const u_int8_t *, const u_int8_t *, u_int8_t *);\n\nvoid\nieee80211_crypto_attach(struct _ifnet *ifp)\n{\n    struct ieee80211com *ic = (struct ieee80211com *)ifp;\n\n    TAILQ_INIT(&ic->ic_pmksa);\n    if (ic->ic_caps & IEEE80211_C_RSN) {\n        ic->ic_rsnprotos = IEEE80211_PROTO_RSN;\n        ic->ic_rsnakms = IEEE80211_AKM_PSK;\n        ic->ic_rsnciphers = IEEE80211_CIPHER_CCMP;\n        ic->ic_rsngroupcipher = IEEE80211_CIPHER_CCMP;\n        ic->ic_rsngroupmgmtcipher = IEEE80211_CIPHER_BIP;\n    }\n    ic->ic_set_key = ieee80211_set_key;\n    ic->ic_delete_key = ieee80211_delete_key;\n#ifndef IEEE80211_STA_ONLY\n    timeout_set(&ic->ic_tkip_micfail_timeout,\n        ieee80211_michael_mic_failure_timeout, ic);\n#endif\n}\n\nvoid\nieee80211_crypto_detach(struct _ifnet *ifp)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n\tstruct ieee80211com *ic = (struct ieee80211com *)ifp;\n\tstruct ieee80211_pmk *pmk;\n\n\t/* purge the PMKSA cache */\n\twhile ((pmk = TAILQ_FIRST(&ic->ic_pmksa)) != NULL) {\n\t\tTAILQ_REMOVE(&ic->ic_pmksa, pmk, pmk_next);\n\t\texplicit_bzero(pmk, sizeof(*pmk));\n\t\tfree(pmk);\n\t}\n\n\t/* clear all group keys from memory */\n\tieee80211_crypto_clear_groupkeys(ic);\n\n\t/* clear pre-shared key from memory */\n\texplicit_bzero(ic->ic_psk, IEEE80211_PMK_LEN);\n\n#ifndef IEEE80211_STA_ONLY\n\ttimeout_del(&ic->ic_tkip_micfail_timeout);\n    timeout_free(&ic->ic_tkip_micfail_timeout);\n#endif\n}\n\nvoid\nieee80211_crypto_clear_groupkeys(struct ieee80211com *ic)\n{\n\tint i;\n\n\tfor (i = 0; i < IEEE80211_GROUP_NKID; i++) {\n        struct ieee80211_key *k = &ic->ic_nw_keys[i];\n        if (k->k_cipher != IEEE80211_CIPHER_NONE)\n            (*ic->ic_delete_key)(ic, NULL, k);\n        explicit_bzero(k, sizeof(*k));\n    }\n}\n\n/*\n * Return the length in bytes of a cipher suite key (see Table 60).\n */\nint\nieee80211_cipher_keylen(enum ieee80211_cipher cipher)\n{\n\tswitch (cipher) {\n\tcase IEEE80211_CIPHER_WEP40:\n\t\treturn 5;\n\tcase IEEE80211_CIPHER_TKIP:\n\t\treturn 32;\n\tcase IEEE80211_CIPHER_CCMP:\n\t\treturn 16;\n\tcase IEEE80211_CIPHER_WEP104:\n\t\treturn 13;\n\tcase IEEE80211_CIPHER_BIP:\n\t\treturn 16;\n\tdefault:\t/* unknown cipher */\n\t\treturn 0;\n\t}\n}\n\nint\nieee80211_set_key(struct ieee80211com *ic, struct ieee80211_node *ni,\n    struct ieee80211_key *k)\n{\n\tint error;\n\n\tswitch (k->k_cipher) {\n    case IEEE80211_CIPHER_WEP40:\n    case IEEE80211_CIPHER_WEP104:\n        error = ieee80211_wep_set_key(ic, k);\n        break;\n    case IEEE80211_CIPHER_TKIP:\n        error = ieee80211_tkip_set_key(ic, k);\n        break;\n    case IEEE80211_CIPHER_CCMP:\n        error = ieee80211_ccmp_set_key(ic, k);\n        break;\n    case IEEE80211_CIPHER_BIP:\n        error = ieee80211_bip_set_key(ic, k);\n        break;\n    default:\n        /* should not get there */\n        error = EINVAL;\n    }\n\n    if (error == 0)\n        k->k_flags |= IEEE80211_KEY_SWCRYPTO;\n    \n    XYLog(\"%s kid=%d cipher=%d, error=%d\\n\", __FUNCTION__, k->k_id, k->k_cipher, error);\n\n    return error;\n}\n\nvoid\nieee80211_delete_key(struct ieee80211com *ic, struct ieee80211_node *ni,\n    struct ieee80211_key *k)\n{\n\tswitch (k->k_cipher) {\n    case IEEE80211_CIPHER_WEP40:\n    case IEEE80211_CIPHER_WEP104:\n        ieee80211_wep_delete_key(ic, k);\n        break;\n    case IEEE80211_CIPHER_TKIP:\n        ieee80211_tkip_delete_key(ic, k);\n        break;\n    case IEEE80211_CIPHER_CCMP:\n        ieee80211_ccmp_delete_key(ic, k);\n        break;\n    case IEEE80211_CIPHER_BIP:\n        ieee80211_bip_delete_key(ic, k);\n        break;\n    default:\n        /* should not get there */\n        break;\n    }\n    explicit_bzero(k, sizeof(*k));\n}\n\nstruct ieee80211_key *\nieee80211_get_txkey(struct ieee80211com *ic, const struct ieee80211_frame *wh,\n    struct ieee80211_node *ni)\n{\n\tint kid;\n\n\tif ((ic->ic_flags & IEEE80211_F_RSNON) &&\n        !IEEE80211_IS_MULTICAST(wh->i_addr1) &&\n        ni->ni_rsncipher != IEEE80211_CIPHER_USEGROUP)\n        return &ni->ni_pairwise_key;\n\n    /* All other cases (including WEP) use a group key. */\n    if (ni->ni_flags & IEEE80211_NODE_MFP)\n        kid = ic->ic_igtk_kid;\n    else\n        kid = ic->ic_def_txkey;\n\n    return &ic->ic_nw_keys[kid];\n}\n\nstruct ieee80211_key *\nieee80211_get_rxkey(struct ieee80211com *ic, mbuf_t m,\n    struct ieee80211_node *ni)\n{\n   struct ieee80211_key *k = NULL;\n   struct ieee80211_frame *wh;\n   u_int16_t kid;\n   u_int8_t *ivp, *mmie;\n   int hdrlen;\n\n   wh = mtod(m, struct ieee80211_frame *);\n   if ((ic->ic_flags & IEEE80211_F_RSNON) &&\n       !IEEE80211_IS_MULTICAST(wh->i_addr1) &&\n       ni->ni_rsncipher != IEEE80211_CIPHER_USEGROUP) {\n       k = &ni->ni_pairwise_key;\n   } else if (!IEEE80211_IS_MULTICAST(wh->i_addr1) ||\n       (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) !=\n       IEEE80211_FC0_TYPE_MGT) {\n       /* retrieve group data key id from IV field */\n       hdrlen = ieee80211_get_hdrlen(wh);\n       /* check that IV field is present */\n       if (mbuf_len(m) < hdrlen + 4)\n           return NULL;\n       ivp = (u_int8_t *)wh + hdrlen;\n       kid = ivp[3] >> 6;\n       k = &ic->ic_nw_keys[kid];\n   } else {\n       /* retrieve integrity group key id from MMIE */\n       if (mbuf_len(m) < sizeof(*wh) + IEEE80211_MMIE_LEN)\n           return NULL;\n       /* it is assumed management frames are contiguous */\n       mmie = (u_int8_t *)wh + mbuf_len(m) - IEEE80211_MMIE_LEN;\n       /* check that MMIE is valid */\n       if (mmie[0] != IEEE80211_ELEMID_MMIE || mmie[1] != 16)\n           return NULL;\n       kid = LE_READ_2(&mmie[2]);\n       if (kid != 4 && kid != 5)\n           return NULL;\n       k = &ic->ic_nw_keys[kid];\n   }\n\n   return k;\n}\n\nmbuf_t\nieee80211_encrypt(struct ieee80211com *ic, mbuf_t m0,\n    struct ieee80211_key *k)\n{\n    if ((k->k_flags & IEEE80211_KEY_SWCRYPTO) == 0) {\n\t\tXYLog(\"%s: BUG! key unset for sw crypto. k_id: %d k_cipher: %d k_flags: %d\\n\", __FUNCTION__, k->k_id, k->k_cipher, k->k_flags);\n        mbuf_freem(m0);\n        return NULL;\n    }\n    \n    XYLog(\"%s kid=%d cipher=%d\\n\", __FUNCTION__, k->k_id, k->k_cipher);\n\n\tswitch (k->k_cipher) {\n\tcase IEEE80211_CIPHER_WEP40:\n\tcase IEEE80211_CIPHER_WEP104:\n\t\tm0 = ieee80211_wep_encrypt(ic, m0, k);\n\t\tbreak;\n\tcase IEEE80211_CIPHER_TKIP:\n\t\tm0 = ieee80211_tkip_encrypt(ic, m0, k);\n\t\tbreak;\n\tcase IEEE80211_CIPHER_CCMP:\n\t\tm0 = ieee80211_ccmp_encrypt(ic, m0, k);\n\t\tbreak;\n\tcase IEEE80211_CIPHER_BIP:\n\t\tm0 = ieee80211_bip_encap(ic, m0, k);\n\t\tbreak;\n\tdefault:\n\t\t/* should not get there */\n\t\tpanic(\"invalid key cipher 0x%x\", k->k_cipher);\n\t}\n\treturn m0;\n}\n\nmbuf_t\nieee80211_decrypt(struct ieee80211com *ic, mbuf_t m0,\n    struct ieee80211_node *ni)\n{\n\tstruct ieee80211_key *k;\n\n\t/* find key for decryption */\n    k = ieee80211_get_rxkey(ic, m0, ni);\n    if (k == NULL || (k->k_flags & IEEE80211_KEY_SWCRYPTO) == 0) {\n        mbuf_freem(m0);\n        return NULL;\n    }\n\n    switch (k->k_cipher) {\n    case IEEE80211_CIPHER_WEP40:\n    case IEEE80211_CIPHER_WEP104:\n        m0 = ieee80211_wep_decrypt(ic, m0, k);\n        break;\n    case IEEE80211_CIPHER_TKIP:\n        m0 = ieee80211_tkip_decrypt(ic, m0, k);\n        break;\n    case IEEE80211_CIPHER_CCMP:\n        m0 = ieee80211_ccmp_decrypt(ic, m0, k);\n        break;\n    case IEEE80211_CIPHER_BIP:\n        m0 = ieee80211_bip_decap(ic, m0, k);\n        break;\n    default:\n        /* key not defined */\n        mbuf_freem(m0);\n        m0 = NULL;\n    }\n    return m0;\n}\n\n/*\n * SHA1-based Pseudo-Random Function (see 8.5.1.1).\n */\nvoid\nieee80211_prf(const u_int8_t *key, size_t key_len, const u_int8_t *label,\n    size_t label_len, const u_int8_t *context, size_t context_len,\n    u_int8_t *output, size_t len)\n{\n\tHMAC_SHA1_CTX ctx;\n    u_int8_t digest[SHA1_DIGEST_LENGTH];\n    u_int8_t count;\n\n    for (count = 0; len != 0; count++) {\n        HMAC_SHA1_Init(&ctx, key, key_len);\n        HMAC_SHA1_Update(&ctx, label, label_len);\n        HMAC_SHA1_Update(&ctx, context, context_len);\n        HMAC_SHA1_Update(&ctx, &count, 1);\n        if (len < SHA1_DIGEST_LENGTH) {\n            HMAC_SHA1_Final(digest, &ctx);\n            /* truncate HMAC-SHA1 to len bytes */\n            memcpy(output, digest, len);\n            break;\n        }\n        HMAC_SHA1_Final(output, &ctx);\n        output += SHA1_DIGEST_LENGTH;\n        len -= SHA1_DIGEST_LENGTH;\n    }\n}\n\n/*\n * SHA256-based Key Derivation Function (see 8.5.1.5.2).\n */\nvoid\nieee80211_kdf(const u_int8_t *key, size_t key_len, const u_int8_t *label,\n    size_t label_len, const u_int8_t *context, size_t context_len,\n    u_int8_t *output, size_t len)\n{\n\tHMAC_SHA256_CTX ctx;\n    u_int8_t digest[SHA256_DIGEST_LENGTH];\n    u_int16_t i, iter, length;\n\n    length = htole16(len * NBBY);\n    for (i = 1; len != 0; i++) {\n        HMAC_SHA256_Init(&ctx, key, key_len);\n        iter = htole16(i);\n        HMAC_SHA256_Update(&ctx, (u_int8_t *)&iter, sizeof iter);\n        HMAC_SHA256_Update(&ctx, label, label_len);\n        HMAC_SHA256_Update(&ctx, context, context_len);\n        HMAC_SHA256_Update(&ctx, (u_int8_t *)&length, sizeof length);\n        if (len < SHA256_DIGEST_LENGTH) {\n            HMAC_SHA256_Final(digest, &ctx);\n            /* truncate HMAC-SHA-256 to len bytes */\n            memcpy(output, digest, len);\n            break;\n        }\n        HMAC_SHA256_Final(output, &ctx);\n        output += SHA256_DIGEST_LENGTH;\n        len -= SHA256_DIGEST_LENGTH;\n    }\n}\n\n/*\n * Derive Pairwise Transient Key (PTK) (see 8.5.1.2).\n */\nvoid\nieee80211_derive_ptk(enum ieee80211_akm akm, const u_int8_t *pmk,\n    const u_int8_t *aa, const u_int8_t *spa, const u_int8_t *anonce,\n    const u_int8_t *snonce, struct ieee80211_ptk *ptk)\n{\n\tvoid (*kdf)(const u_int8_t *, size_t, const u_int8_t *, size_t,\n        const u_int8_t *, size_t, u_int8_t *, size_t);\n    u_int8_t buf[2 * IEEE80211_ADDR_LEN + 2 * EAPOL_KEY_NONCE_LEN];\n    int ret;\n\n    /* Min(AA,SPA) || Max(AA,SPA) */\n    ret = memcmp(aa, spa, IEEE80211_ADDR_LEN) < 0;\n    memcpy(&buf[ 0], ret ? aa : spa, IEEE80211_ADDR_LEN);\n    memcpy(&buf[ 6], ret ? spa : aa, IEEE80211_ADDR_LEN);\n\n    /* Min(ANonce,SNonce) || Max(ANonce,SNonce) */\n    ret = memcmp(anonce, snonce, EAPOL_KEY_NONCE_LEN) < 0;\n    memcpy(&buf[12], ret ? anonce : snonce, EAPOL_KEY_NONCE_LEN);\n    memcpy(&buf[44], ret ? snonce : anonce, EAPOL_KEY_NONCE_LEN);\n\n    kdf = ieee80211_is_sha256_akm(akm) ? ieee80211_kdf : ieee80211_prf;\n    (*kdf)(pmk, IEEE80211_PMK_LEN, (const u_int8_t *)\"Pairwise key expansion\", 23,\n        buf, sizeof buf, (u_int8_t *)ptk, sizeof(*ptk));\n}\n\nstatic void\nieee80211_pmkid_sha1(const u_int8_t *pmk, const u_int8_t *aa,\n    const u_int8_t *spa, u_int8_t *pmkid)\n{\n\tHMAC_SHA1_CTX ctx;\n\tu_int8_t digest[SHA1_DIGEST_LENGTH];\n\n\tHMAC_SHA1_Init(&ctx, pmk, IEEE80211_PMK_LEN);\n\tHMAC_SHA1_Update(&ctx, (const u_int8_t *)\"PMK Name\", 8);\n\tHMAC_SHA1_Update(&ctx, aa, IEEE80211_ADDR_LEN);\n\tHMAC_SHA1_Update(&ctx, spa, IEEE80211_ADDR_LEN);\n\tHMAC_SHA1_Final(digest, &ctx);\n\t/* use the first 128 bits of HMAC-SHA1 */\n\tmemcpy(pmkid, digest, IEEE80211_PMKID_LEN);\n}\n\nstatic void\nieee80211_pmkid_sha256(const u_int8_t *pmk, const u_int8_t *aa,\n    const u_int8_t *spa, u_int8_t *pmkid)\n{\n\tHMAC_SHA256_CTX ctx;\n\tu_int8_t digest[SHA256_DIGEST_LENGTH];\n\n\tHMAC_SHA256_Init(&ctx, pmk, IEEE80211_PMK_LEN);\n\tHMAC_SHA256_Update(&ctx, (uint8_t *)\"PMK Name\", 8);\n\tHMAC_SHA256_Update(&ctx, aa, IEEE80211_ADDR_LEN);\n\tHMAC_SHA256_Update(&ctx, spa, IEEE80211_ADDR_LEN);\n\tHMAC_SHA256_Final(digest, &ctx);\n\t/* use the first 128 bits of HMAC-SHA-256 */\n\tmemcpy(pmkid, digest, IEEE80211_PMKID_LEN);\n}\n\n/*\n * Derive Pairwise Master Key Identifier (PMKID) (see 8.5.1.2).\n */\nvoid\nieee80211_derive_pmkid(enum ieee80211_akm akm, const u_int8_t *pmk,\n    const u_int8_t *aa, const u_int8_t *spa, u_int8_t *pmkid)\n{\n\tif (ieee80211_is_sha256_akm(akm))\n\t\tieee80211_pmkid_sha256(pmk, aa, spa, pmkid);\n\telse\n\t\tieee80211_pmkid_sha1(pmk, aa, spa, pmkid);\n}\n\ntypedef union _ANY_CTX {\n\tHMAC_MD5_CTX\tmd5;\n\tHMAC_SHA1_CTX\tsha1;\n\tAES_CMAC_CTX\tcmac;\n} ANY_CTX;\n\n/*\n * Compute the Key MIC field of an EAPOL-Key frame using the specified Key\n * Confirmation Key (KCK).  The hash function can be HMAC-MD5, HMAC-SHA1\n * or AES-128-CMAC depending on the EAPOL-Key Key Descriptor Version.\n */\nvoid\nieee80211_eapol_key_mic(struct ieee80211_eapol_key *key, const u_int8_t *kck)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n\tu_int8_t digest[SHA1_DIGEST_LENGTH];\n\tANY_CTX ctx;\t/* XXX off stack? */\n\tu_int len;\n\n\tlen = BE_READ_2(key->len) + 4;\n\n    switch (BE_READ_2(key->info) & EAPOL_KEY_VERSION_MASK) {\n    case EAPOL_KEY_DESC_V1:\n        HMAC_MD5_Init(&ctx.md5, kck, 16);\n        HMAC_MD5_Update(&ctx.md5, (u_int8_t *)key, len);\n        HMAC_MD5_Final(key->mic, &ctx.md5);\n        break;\n    case EAPOL_KEY_DESC_V2:\n        HMAC_SHA1_Init(&ctx.sha1, kck, 16);\n        HMAC_SHA1_Update(&ctx.sha1, (u_int8_t *)key, len);\n        HMAC_SHA1_Final(digest, &ctx.sha1);\n        /* truncate HMAC-SHA1 to its 128 MSBs */\n        memcpy(key->mic, digest, EAPOL_KEY_MIC_LEN);\n        break;\n    case EAPOL_KEY_DESC_V3:\n        AES_CMAC_Init(&ctx.cmac);\n        AES_CMAC_SetKey(&ctx.cmac, kck);\n        AES_CMAC_Update(&ctx.cmac, (u_int8_t *)key, len);\n        AES_CMAC_Final(key->mic, &ctx.cmac);\n        break;\n    }\n}\n\n/*\n * Check the MIC of a received EAPOL-Key frame using the specified Key\n * Confirmation Key (KCK).\n */\nint\nieee80211_eapol_key_check_mic(struct ieee80211_eapol_key *key,\n    const u_int8_t *kck)\n{\n\tu_int8_t mic[EAPOL_KEY_MIC_LEN];\n\n    memcpy(mic, key->mic, EAPOL_KEY_MIC_LEN);\n    memset(key->mic, 0, EAPOL_KEY_MIC_LEN);\n    ieee80211_eapol_key_mic(key, kck);\n\n    return timingsafe_bcmp(key->mic, mic, EAPOL_KEY_MIC_LEN) != 0;\n}\n\n#ifndef IEEE80211_STA_ONLY\n/*\n * Encrypt the Key Data field of an EAPOL-Key frame using the specified Key\n * Encryption Key (KEK).  The encryption algorithm can be either ARC4 or\n * AES Key Wrap depending on the EAPOL-Key Key Descriptor Version.\n */\nvoid\nieee80211_eapol_key_encrypt(struct ieee80211com *ic,\n    struct ieee80211_eapol_key *key, const u_int8_t *kek)\n{\n\tunion {\n\t\tstruct rc4_ctx rc4;\n\t\taes_key_wrap_ctx aes;\n\t} ctx;\t/* XXX off stack? */\n\tu_int8_t keybuf[EAPOL_KEY_IV_LEN + 16];\n\tu_int16_t len, info;\n\tu_int8_t *data;\n\tint n;\n\n\tlen  = BE_READ_2(key->paylen);\n    info = BE_READ_2(key->info);\n    data = (u_int8_t *)(key + 1);\n\n    switch (info & EAPOL_KEY_VERSION_MASK) {\n    case EAPOL_KEY_DESC_V1:\n        /* set IV to the lower 16 octets of our global key counter */\n        memcpy(key->iv, ic->ic_globalcnt + 16, 16);\n        /* increment our global key counter (256-bit, big-endian) */\n        for (n = 31; n >= 0 && ++ic->ic_globalcnt[n] == 0; n--);\n\n        /* concatenate the EAPOL-Key IV field and the KEK */\n        memcpy(keybuf, key->iv, EAPOL_KEY_IV_LEN);\n        memcpy(keybuf + EAPOL_KEY_IV_LEN, kek, 16);\n\n        rc4_keysetup(&ctx.rc4, keybuf, sizeof keybuf);\n        /* discard the first 256 octets of the ARC4 key stream */\n        rc4_skip(&ctx.rc4, RC4STATE);\n        rc4_crypt(&ctx.rc4, data, data, len);\n        break;\n    case EAPOL_KEY_DESC_V2:\n    case EAPOL_KEY_DESC_V3:\n        if (len < 16 || (len & 7) != 0) {\n            /* insert padding */\n            n = (len < 16) ? 16 - len : 8 - (len & 7);\n            data[len++] = IEEE80211_ELEMID_VENDOR;\n            memset(&data[len], 0, n - 1);\n            len += n - 1;\n        }\n        aes_key_wrap_set_key_wrap_only(&ctx.aes, kek, 16);\n        aes_key_wrap(&ctx.aes, data, len / 8, data);\n        len += 8;    /* AES Key Wrap adds 8 bytes */\n        /* update key data length */\n        BE_WRITE_2(key->paylen, len);\n        /* update packet body length */\n        BE_WRITE_2(key->len, sizeof(*key) + len - 4);\n        break;\n    }\n}\n#endif\t/* IEEE80211_STA_ONLY */\n\n/*\n * Decrypt the Key Data field of an EAPOL-Key frame using the specified Key\n * Encryption Key (KEK).  The encryption algorithm can be either ARC4 or\n * AES Key Wrap depending on the EAPOL-Key Key Descriptor Version.\n */\nint\nieee80211_eapol_key_decrypt(struct ieee80211_eapol_key *key,\n    const u_int8_t *kek)\n{\n\tunion {\n        struct rc4_ctx rc4;\n        aes_key_wrap_ctx aes;\n    } ctx;    /* XXX off stack? */\n    u_int8_t keybuf[EAPOL_KEY_IV_LEN + 16];\n    u_int16_t len, info;\n    u_int8_t *data;\n\n    len  = BE_READ_2(key->paylen);\n    info = BE_READ_2(key->info);\n    data = (u_int8_t *)(key + 1);\n\n    switch (info & EAPOL_KEY_VERSION_MASK) {\n    case EAPOL_KEY_DESC_V1:\n        /* concatenate the EAPOL-Key IV field and the KEK */\n        memcpy(keybuf, key->iv, EAPOL_KEY_IV_LEN);\n        memcpy(keybuf + EAPOL_KEY_IV_LEN, kek, 16);\n\n        rc4_keysetup(&ctx.rc4, keybuf, sizeof keybuf);\n        /* discard the first 256 octets of the ARC4 key stream */\n        rc4_skip(&ctx.rc4, RC4STATE);\n        rc4_crypt(&ctx.rc4, data, data, len);\n        return 0;\n    case EAPOL_KEY_DESC_V2:\n    case EAPOL_KEY_DESC_V3:\n        /* Key Data Length must be a multiple of 8 */\n        if (len < 16 + 8 || (len & 7) != 0)\n            return 1;\n        len -= 8;    /* AES Key Wrap adds 8 bytes */\n        aes_key_wrap_set_key(&ctx.aes, kek, 16);\n        return aes_key_unwrap(&ctx.aes, data, data, len / 8);\n    }\n\n    return 1;    /* unknown Key Descriptor Version */\n}\n\n/*\n * Add a PMK entry to the PMKSA cache.\n */\nstruct ieee80211_pmk *\nieee80211_pmksa_add(struct ieee80211com *ic, enum ieee80211_akm akm,\n    const u_int8_t *macaddr, const u_int8_t *key, u_int32_t lifetime)\n{\n\tstruct ieee80211_pmk *pmk;\n\n\t/* check if an entry already exists for this (STA,AKMP) */\n\tTAILQ_FOREACH(pmk, &ic->ic_pmksa, pmk_next) {\n\t\tif (pmk->pmk_akm == akm &&\n\t\t    IEEE80211_ADDR_EQ(pmk->pmk_macaddr, macaddr))\n\t\t\tbreak;\n\t}\n\tif (pmk == NULL) {\n\t\t/* allocate a new PMKSA entry */\n\t\tif ((pmk = (struct ieee80211_pmk *)malloc(sizeof(*pmk), 0, 0)) == NULL)\n\t\t\treturn NULL;\n\t\tpmk->pmk_akm = akm;\n\t\tIEEE80211_ADDR_COPY(pmk->pmk_macaddr, macaddr);\n\t\tTAILQ_INSERT_TAIL(&ic->ic_pmksa, pmk, pmk_next);\n\t}\n\tmemcpy(pmk->pmk_key, key, IEEE80211_PMK_LEN);\n\tpmk->pmk_lifetime = lifetime;\t/* XXX not used yet */\n#ifndef IEEE80211_STA_ONLY\n\tif (ic->ic_opmode == IEEE80211_M_HOSTAP) {\n\t\tieee80211_derive_pmkid(pmk->pmk_akm, pmk->pmk_key,\n\t\t    ic->ic_myaddr, macaddr, pmk->pmk_pmkid);\n\t} else\n#endif\n\t{\n\t\tieee80211_derive_pmkid(pmk->pmk_akm, pmk->pmk_key,\n\t\t    macaddr, ic->ic_myaddr, pmk->pmk_pmkid);\n\t}\n\treturn pmk;\n}\n\n/*\n * Check if we have a cached PMK entry for the specified node and PMKID.\n */\nstruct ieee80211_pmk *\nieee80211_pmksa_find(struct ieee80211com *ic, struct ieee80211_node *ni,\n    const u_int8_t *pmkid)\n{\n\tstruct ieee80211_pmk *pmk;\n\n\tTAILQ_FOREACH(pmk, &ic->ic_pmksa, pmk_next) {\n        if (pmk->pmk_akm == ni->ni_rsnakms &&\n            IEEE80211_ADDR_EQ(pmk->pmk_macaddr, ni->ni_macaddr) &&\n            (pmkid == NULL ||\n             memcmp(pmk->pmk_pmkid, pmkid, IEEE80211_PMKID_LEN) == 0))\n            break;\n    }\n\treturn pmk;\n}\n"
  },
  {
    "path": "itl80211/openbsd/net80211/ieee80211_crypto.h",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n/*\t$OpenBSD: ieee80211_crypto.h,v 1.26 2019/08/16 19:53:32 procter Exp $\t*/\n\n/*-\n * Copyright (c) 2007,2008 Damien Bergamini <damien.bergamini@free.fr>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n#ifndef _NET80211_IEEE80211_CRYPTO_H_\n#define _NET80211_IEEE80211_CRYPTO_H_\n\n/*\n * 802.11 protocol crypto-related definitions.\n */\n\n#define _KERNEL\n\n/*\n * 802.11 ciphers.\n */\nenum ieee80211_cipher {\n\tIEEE80211_CIPHER_NONE\t\t= 0x00000000,\n\tIEEE80211_CIPHER_USEGROUP\t= 0x00000001,\n\tIEEE80211_CIPHER_WEP40\t\t= 0x00000002,\n\tIEEE80211_CIPHER_TKIP\t\t= 0x00000004,\n\tIEEE80211_CIPHER_CCMP\t\t= 0x00000008,\n\tIEEE80211_CIPHER_WEP104\t\t= 0x00000010,\n\tIEEE80211_CIPHER_BIP\t\t= 0x00000020\t/* 11w */\n};\n\n/*\n * 802.11 Authentication and Key Management Protocols.\n */\nenum ieee80211_akm {\n\tIEEE80211_AKM_NONE\t\t= 0x00000000,\n\tIEEE80211_AKM_8021X\t\t= 0x00000001,\n\tIEEE80211_AKM_PSK\t\t= 0x00000002,\n\tIEEE80211_AKM_SHA256_8021X\t= 0x00000004,\t/* 11w */\n\tIEEE80211_AKM_SHA256_PSK\t= 0x00000008\t/* 11w */\n};\n\n#define IEEE80211_TKIP_HDRLEN\t8\n#define IEEE80211_TKIP_MICLEN\t8\n#define IEEE80211_CCMP_HDRLEN\t8\n#define IEEE80211_CCMP_MICLEN\t8\n#define IEEE80211_WEP_IVLEN        4\n#define IEEE80211_WEP_ICVLEN        4\n#define IEEE80211_CCMP_PNLEN        6\n#define IEEE80211_CCMP_256_HDRLEN    8\n#define IEEE80211_CCMP_256_MICLEN    16\n#define IEEE80211_CCMP_256_PNLEN    6\n#define IEEE80211_TKIP_IVLEN        8\n#define IEEE80211_TKIP_ICVLEN        4\n#define IEEE80211_CMAC_PNLEN        6\n#define IEEE80211_GMAC_PNLEN        6\n#define IEEE80211_GCMP_HDRLEN        8\n#define IEEE80211_GCMP_MICLEN        16\n#define IEEE80211_GCMP_PNLEN        6\n\n#define IEEE80211_PMK_LEN\t32\n\n#ifdef _KERNEL \n\nstatic __inline int\nieee80211_is_8021x_akm(enum ieee80211_akm akm)\n{\n\treturn akm == IEEE80211_AKM_8021X ||\n\t    akm == IEEE80211_AKM_SHA256_8021X;\n}\n\nstatic __inline int\nieee80211_is_sha256_akm(enum ieee80211_akm akm)\n{\n\treturn akm == IEEE80211_AKM_SHA256_8021X ||\n\t    akm == IEEE80211_AKM_SHA256_PSK;\n}\n\nstruct ieee80211_key {\n\tu_int8_t\t\tk_id;\t\t/* identifier (0-5) */\n\tenum ieee80211_cipher\tk_cipher;\n\tu_int\t\t\tk_flags;\n#define IEEE80211_KEY_GROUP\t0x00000001\t/* group data key */\n#define IEEE80211_KEY_TX\t0x00000002\t/* Tx+Rx */\n#define IEEE80211_KEY_IGTK\t0x00000004\t/* integrity group key */\n#define IEEE80211_KEY_SWCRYPTO\t0x00000080\t/* loaded for software crypto */\n\n\tu_int\t\t\tk_len;\n\tu_int64_t\t\tk_rsc[IEEE80211_NUM_TID];\n\tu_int64_t\t\tk_mgmt_rsc;\n\tu_int64_t\t\tk_tsc;\n\tu_int8_t\t\tk_key[32];\n\tvoid\t\t\t*k_priv;\n};\n\n#define IEEE80211_KEYBUF_SIZE\t16\n\n/*\n * Entry in the PMKSA cache.\n */\nstruct ieee80211_pmk {\n\tenum ieee80211_akm\tpmk_akm;\n\tu_int32_t\t\tpmk_lifetime;\n#define IEEE80211_PMK_INFINITE\t0\n\n\tu_int8_t\t\tpmk_pmkid[IEEE80211_PMKID_LEN];\n\tu_int8_t\t\tpmk_macaddr[IEEE80211_ADDR_LEN];\n\tu_int8_t\t\tpmk_key[IEEE80211_PMK_LEN];\n\n\tTAILQ_ENTRY(ieee80211_pmk) pmk_next;\n};\n\n/* forward references */\nstruct\tieee80211com;\nstruct\tieee80211_node;\n\nvoid\tieee80211_crypto_attach(struct _ifnet *);\nvoid\tieee80211_crypto_detach(struct _ifnet *);\n\nvoid\tieee80211_crypto_clear_groupkeys(struct ieee80211com *);\nstruct\tieee80211_key *ieee80211_get_txkey(struct ieee80211com *,\n\t    const struct ieee80211_frame *, struct ieee80211_node *);\nstruct\tieee80211_key *ieee80211_get_rxkey(struct ieee80211com *,\n\t    mbuf_t, struct ieee80211_node *);\nmbuf_t ieee80211_encrypt(struct ieee80211com *, mbuf_t,\n\t    struct ieee80211_key *);\nmbuf_t ieee80211_decrypt(struct ieee80211com *, mbuf_t,\n\t    struct ieee80211_node *);\n\nint\tieee80211_set_key(struct ieee80211com *, struct ieee80211_node *,\n\t    struct ieee80211_key *);\nvoid\tieee80211_delete_key(struct ieee80211com *, struct ieee80211_node *,\n\t    struct ieee80211_key *);\n\nvoid\tieee80211_eapol_key_mic(struct ieee80211_eapol_key *,\n\t    const u_int8_t *);\nint\tieee80211_eapol_key_check_mic(struct ieee80211_eapol_key *,\n\t    const u_int8_t *);\n#ifndef IEEE80211_STA_ONLY\nvoid\tieee80211_eapol_key_encrypt(struct ieee80211com *,\n\t    struct ieee80211_eapol_key *, const u_int8_t *);\n#endif\nint\tieee80211_eapol_key_decrypt(struct ieee80211_eapol_key *,\n\t    const u_int8_t *);\n\nstruct\tieee80211_pmk *ieee80211_pmksa_add(struct ieee80211com *,\n\t    enum ieee80211_akm, const u_int8_t *, const u_int8_t *, u_int32_t);\nstruct\tieee80211_pmk *ieee80211_pmksa_find(struct ieee80211com *,\n\t    struct ieee80211_node *, const u_int8_t *);\nvoid\tieee80211_derive_ptk(enum ieee80211_akm, const u_int8_t *,\n\t    const u_int8_t *, const u_int8_t *, const u_int8_t *,\n\t    const u_int8_t *, struct ieee80211_ptk *);\nint\tieee80211_cipher_keylen(enum ieee80211_cipher);\n\nint\tieee80211_wep_set_key(struct ieee80211com *, struct ieee80211_key *);\nvoid\tieee80211_wep_delete_key(struct ieee80211com *,\n\t    struct ieee80211_key *);\nmbuf_t ieee80211_wep_encrypt(struct ieee80211com *, mbuf_t,\n\t    struct ieee80211_key *);\nmbuf_t ieee80211_wep_decrypt(struct ieee80211com *, mbuf_t,\n\t    struct ieee80211_key *);\n\nint\tieee80211_tkip_set_key(struct ieee80211com *, struct ieee80211_key *);\nvoid\tieee80211_tkip_delete_key(struct ieee80211com *,\n\t    struct ieee80211_key *);\nmbuf_t ieee80211_tkip_encrypt(struct ieee80211com *,\n\t    mbuf_t, struct ieee80211_key *);\nint    ieee80211_tkip_get_tsc(uint64_t *, uint64_t **, mbuf_t,\n                              struct ieee80211_key *);\nmbuf_t ieee80211_tkip_decrypt(struct ieee80211com *,\n\t    mbuf_t, struct ieee80211_key *);\nvoid\tieee80211_tkip_mic(mbuf_t, int, const u_int8_t *,\n\t    u_int8_t[IEEE80211_TKIP_MICLEN]);\nvoid\tieee80211_michael_mic_failure(struct ieee80211com *, u_int64_t);\n#ifndef IEEE80211_STA_ONLY\nvoid\tieee80211_michael_mic_failure_timeout(void *);\n#endif\n\nint\tieee80211_ccmp_set_key(struct ieee80211com *, struct ieee80211_key *);\nvoid\tieee80211_ccmp_delete_key(struct ieee80211com *,\n\t    struct ieee80211_key *);\nmbuf_t ieee80211_ccmp_encrypt(struct ieee80211com *, mbuf_t,\n\t    struct ieee80211_key *);\nint    ieee80211_ccmp_get_pn(uint64_t *, uint64_t **, mbuf_t,\n                             struct ieee80211_key *);\nmbuf_t ieee80211_ccmp_decrypt(struct ieee80211com *, mbuf_t,\n\t    struct ieee80211_key *);\n\nint\tieee80211_bip_set_key(struct ieee80211com *, struct ieee80211_key *);\nvoid\tieee80211_bip_delete_key(struct ieee80211com *,\n\t    struct ieee80211_key *);\nmbuf_t ieee80211_bip_encap(struct ieee80211com *, mbuf_t,\n\t    struct ieee80211_key *);\nmbuf_t ieee80211_bip_decap(struct ieee80211com *, mbuf_t,\n\t    struct ieee80211_key *);\n\n#endif /* _KERNEL */\n#endif /* _NET80211_IEEE80211_CRYPTO_H_ */\n"
  },
  {
    "path": "itl80211/openbsd/net80211/ieee80211_crypto_bip.c",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n/*\t$OpenBSD: ieee80211_crypto_bip.c,v 1.10 2018/11/09 14:14:31 claudio Exp $\t*/\n\n/*-\n * Copyright (c) 2008 Damien Bergamini <damien.bergamini@free.fr>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n/*\n * This code implements the Broadcast/Multicast Integrity Protocol (BIP)\n * defined in IEEE P802.11w/D7.0 section 8.3.4.\n */\n\n#include <sys/param.h>\n#include <sys/systm.h>\n#include <sys/mbuf.h>\n#include <sys/malloc.h>\n#include <sys/kernel.h>\n#include <sys/socket.h>\n#include <sys/endian.h>\n\n#include <net/if.h>\n#include <net/if_dl.h>\n#include <net/if_media.h>\n\n#include <netinet/in.h>\n#include <netinet/if_ether.h>\n\n#include <net80211/ieee80211_var.h>\n#include <net80211/ieee80211_crypto.h>\n#include <net80211/ieee80211_priv.h>\n\n#include <crypto/aes.h>\n#include <crypto/cmac.h>\n\n/* BIP software crypto context */\nstruct ieee80211_bip_ctx {\n\tAES_CMAC_CTX\tcmac;\n};\n\n/*\n * Initialize software crypto context.  This function can be overridden\n * by drivers doing hardware crypto.\n */\nint\nieee80211_bip_set_key(struct ieee80211com *ic, struct ieee80211_key *k)\n{\n\tstruct ieee80211_bip_ctx *ctx;\n\n\tctx = (struct ieee80211_bip_ctx *)malloc(sizeof(*ctx), 0, 0);\n\tif (ctx == NULL)\n\t\treturn ENOMEM;\n\tAES_CMAC_SetKey(&ctx->cmac, k->k_key);\n\tk->k_priv = ctx;\n\treturn 0;\n}\n\nvoid\nieee80211_bip_delete_key(struct ieee80211com *ic, struct ieee80211_key *k)\n{\n\tif (k->k_priv != NULL) {\n\t\texplicit_bzero(k->k_priv, sizeof(struct ieee80211_bip_ctx));\n\t\tfree(k->k_priv);\n\t}\n\tk->k_priv = NULL;\n}\n\n/* pseudo-header used for BIP MIC computation */\nstruct ieee80211_bip_frame {\n\tu_int8_t\ti_fc[2];\n\tu_int8_t\ti_addr1[IEEE80211_ADDR_LEN];\n\tu_int8_t\ti_addr2[IEEE80211_ADDR_LEN];\n\tu_int8_t\ti_addr3[IEEE80211_ADDR_LEN];\n} __packed;\n\nmbuf_t\nieee80211_bip_encap(struct ieee80211com *ic, mbuf_t m0,\n    struct ieee80211_key *k)\n{\n\tstruct ieee80211_bip_ctx *ctx = (struct ieee80211_bip_ctx *)k->k_priv;\n\tstruct ieee80211_bip_frame aad;\n\tstruct ieee80211_frame *wh;\n\tu_int8_t *mmie, mic[AES_CMAC_DIGEST_LENGTH];\n\tmbuf_t m;\n    mbuf_t temp;\n\n\twh = mtod(m0, struct ieee80211_frame *);\n\t_KASSERT((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==\n\t    IEEE80211_FC0_TYPE_MGT);\n\t/* clear Protected bit from group management frames */\n\twh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED;\n\n\t/* construct AAD (additional authenticated data) */\n\taad.i_fc[0] = wh->i_fc[0];\n\taad.i_fc[1] = wh->i_fc[1] & ~(IEEE80211_FC1_RETRY |\n\t    IEEE80211_FC1_PWR_MGT | IEEE80211_FC1_MORE_DATA);\n\t/* XXX 11n may require clearing the Order bit too */\n\tIEEE80211_ADDR_COPY(aad.i_addr1, wh->i_addr1);\n\tIEEE80211_ADDR_COPY(aad.i_addr2, wh->i_addr2);\n\tIEEE80211_ADDR_COPY(aad.i_addr3, wh->i_addr3);\n\n\tAES_CMAC_Init(&ctx->cmac);\n\tAES_CMAC_Update(&ctx->cmac, (u_int8_t *)&aad, sizeof aad);\n\tAES_CMAC_Update(&ctx->cmac, (u_int8_t *)&wh[1],\n\t    mbuf_len(m0) - sizeof(*wh));\n\n\tm = m0;\n\t/* reserve trailing space for MMIE */\n\tif (mbuf_trailingspace(m) < IEEE80211_MMIE_LEN) {\n        temp = NULL;\n        mbuf_mclget(MBUF_DONTWAIT, mbuf_type(m), &temp);\n\t\tif (temp == NULL)\n\t\t\tgoto nospace;\n        mbuf_setnext(m, temp);\n\t\tm = temp;\n        mbuf_setlen(m, 0);\n\t}\n\n\t/* construct Management MIC IE */\n\tmmie = mtod(m, u_int8_t *) + mbuf_len(m);\n\tmmie[0] = IEEE80211_ELEMID_MMIE;\n\tmmie[1] = 16;\n\tLE_WRITE_2(&mmie[2], k->k_id);\n\tLE_WRITE_6(&mmie[4], k->k_tsc);\n\tmemset(&mmie[10], 0, 8);\t/* MMIE MIC field set to 0 */\n\n\tAES_CMAC_Update(&ctx->cmac, mmie, IEEE80211_MMIE_LEN);\n\tAES_CMAC_Final(mic, &ctx->cmac);\n\t/* truncate AES-128-CMAC to 64-bit */\n\tmemcpy(&mmie[10], mic, 8);\n\n    mbuf_setlen(m, mbuf_len(m) + IEEE80211_MMIE_LEN);\n    mbuf_pkthdr_setlen(m0, mbuf_pkthdr_len(m0) + IEEE80211_MMIE_LEN);\n\n\tk->k_tsc++;\n\n\treturn m0;\n nospace:\n\tic->ic_stats.is_tx_nombuf++;\n\tmbuf_freem(m0);\n\treturn NULL;\n}\n\nmbuf_t\nieee80211_bip_decap(struct ieee80211com *ic, mbuf_t m0,\n    struct ieee80211_key *k)\n{\n\tstruct ieee80211_bip_ctx *ctx = (struct ieee80211_bip_ctx *)k->k_priv;\n\tstruct ieee80211_frame *wh;\n\tstruct ieee80211_bip_frame aad;\n\tu_int8_t *mmie, mic0[8], mic[AES_CMAC_DIGEST_LENGTH];\n\tu_int64_t ipn;\n\n\twh = mtod(m0, struct ieee80211_frame *);\n\t_KASSERT((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==\n\t    IEEE80211_FC0_TYPE_MGT);\n\n\t/*\n\t * It is assumed that management frames are contiguous and that\n\t * the mbuf length has already been checked to contain at least\n\t * a header and a MMIE (checked in ieee80211_decrypt()).\n\t */\n\t_KASSERT(m0->m_len >= sizeof(*wh) + IEEE80211_MMIE_LEN);\n\tmmie = mtod(m0, u_int8_t *) + mbuf_len(m0) - IEEE80211_MMIE_LEN;\n\n\tipn = LE_READ_6(&mmie[4]);\n\tif (ipn <= k->k_mgmt_rsc) {\n\t\t/* replayed frame, discard */\n\t\tic->ic_stats.is_cmac_replays++;\n\t\tmbuf_freem(m0);\n\t\treturn NULL;\n\t}\n\n\t/* save and mask MMIE MIC field to 0 */\n\tmemcpy(mic0, &mmie[10], 8);\n\tmemset(&mmie[10], 0, 8);\n\n\t/* construct AAD (additional authenticated data) */\n\taad.i_fc[0] = wh->i_fc[0];\n\taad.i_fc[1] = wh->i_fc[1] & ~(IEEE80211_FC1_RETRY |\n\t    IEEE80211_FC1_PWR_MGT | IEEE80211_FC1_MORE_DATA);\n\t/* XXX 11n may require clearing the Order bit too */\n\tIEEE80211_ADDR_COPY(aad.i_addr1, wh->i_addr1);\n\tIEEE80211_ADDR_COPY(aad.i_addr2, wh->i_addr2);\n\tIEEE80211_ADDR_COPY(aad.i_addr3, wh->i_addr3);\n\n\t/* compute MIC */\n\tAES_CMAC_Init(&ctx->cmac);\n\tAES_CMAC_Update(&ctx->cmac, (u_int8_t *)&aad, sizeof aad);\n\tAES_CMAC_Update(&ctx->cmac, (u_int8_t *)&wh[1],\n\t    mbuf_len(m0) - sizeof(*wh));\n\tAES_CMAC_Final(mic, &ctx->cmac);\n\n\t/* check that MIC matches the one in MMIE */\n\tif (timingsafe_bcmp(mic, mic0, 8) != 0) {\n\t\tic->ic_stats.is_cmac_icv_errs++;\n\t\tmbuf_freem(m0);\n\t\treturn NULL;\n\t}\n\t/*\n\t * There is no need to trim the MMIE from the mbuf since it is\n\t * an information element and will be ignored by upper layers.\n\t * We do it anyway as it is cheap to do it here and because it\n\t * may be confused with fixed fields by upper layers.\n\t */\n\tmbuf_adj(m0, -IEEE80211_MMIE_LEN);\n\n\t/* update last seen packet number (MIC is validated) */\n\tk->k_mgmt_rsc = ipn;\n\n\treturn m0;\n}\n"
  },
  {
    "path": "itl80211/openbsd/net80211/ieee80211_crypto_ccmp.c",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n/*\t$OpenBSD: ieee80211_crypto_ccmp.c,v 1.21 2018/11/09 14:14:31 claudio Exp $\t*/\n\n/*-\n * Copyright (c) 2008 Damien Bergamini <damien.bergamini@free.fr>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n/*\n * This code implements the CTR with CBC-MAC protocol (CCMP) defined in\n * IEEE Std 802.11-2007 section 8.3.3.\n */\n\n#include <sys/param.h>\n#include <sys/systm.h>\n#include <sys/mbuf.h>\n#include <sys/malloc.h>\n#include <sys/kernel.h>\n#include <sys/socket.h>\n#include <sys/endian.h>\n\n#include <net/if.h>\n#include <net/if_dl.h>\n#include <net/if_media.h>\n\n#include <netinet/in.h>\n#include <netinet/if_ether.h>\n\n#include <net80211/ieee80211_var.h>\n#include <net80211/ieee80211_crypto.h>\n\n#include <crypto/aes.h>\n\n/* CCMP software crypto context */\nstruct ieee80211_ccmp_ctx {\n\tAES_CTX\t\taesctx;\n};\n\n/*\n * Initialize software crypto context.  This function can be overridden\n * by drivers doing hardware crypto.\n */\nint\nieee80211_ccmp_set_key(struct ieee80211com *ic, struct ieee80211_key *k)\n{\n\tstruct ieee80211_ccmp_ctx *ctx;\n\n\tctx = (struct ieee80211_ccmp_ctx *)malloc(sizeof(*ctx), 0, 0);\n\tif (ctx == NULL)\n\t\treturn ENOMEM;\n\tAES_Setkey(&ctx->aesctx, k->k_key, 16);\n\tk->k_priv = ctx;\n\treturn 0;\n}\n\nvoid\nieee80211_ccmp_delete_key(struct ieee80211com *ic, struct ieee80211_key *k)\n{\n\tif (k->k_priv != NULL) {\n\t\texplicit_bzero(k->k_priv, sizeof(struct ieee80211_ccmp_ctx));\n\t\tfree(k->k_priv);\n\t}\n\tk->k_priv = NULL;\n}\n\n/*-\n * Counter with CBC-MAC (CCM) - see RFC3610.\n * CCMP uses the following CCM parameters: M = 8, L = 2\n */\nstatic void\nieee80211_ccmp_phase1(AES_CTX *ctx, const struct ieee80211_frame *wh,\n    u_int64_t pn, int lm, u_int8_t b[16], u_int8_t a[16], u_int8_t s0[16])\n{\n\tu_int8_t auth[32], nonce[13];\n\tu_int8_t *aad;\n\tu_int8_t tid = 0;\n\tint la, i;\n\n\t/* construct AAD (additional authenticated data) */\n\taad = &auth[2];\t/* skip l(a), will be filled later */\n\t*aad = wh->i_fc[0];\n\t/* 11w: conditionally mask subtype field */\n\tif ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==\n\t    IEEE80211_FC0_TYPE_DATA)\n\t\t*aad &= ~IEEE80211_FC0_SUBTYPE_MASK |\n\t\t   IEEE80211_FC0_SUBTYPE_QOS;\n\taad++;\n\t/* protected bit is already set in wh */\n\t*aad = wh->i_fc[1];\n\t*aad &= ~(IEEE80211_FC1_RETRY | IEEE80211_FC1_PWR_MGT |\n\t    IEEE80211_FC1_MORE_DATA);\n\t/* 11n: conditionally mask order bit */\n\tif (ieee80211_has_qos(wh))\n\t\t*aad &= ~IEEE80211_FC1_ORDER;\n\taad++;\n\tIEEE80211_ADDR_COPY(aad, wh->i_addr1); aad += IEEE80211_ADDR_LEN;\n\tIEEE80211_ADDR_COPY(aad, wh->i_addr2); aad += IEEE80211_ADDR_LEN;\n\tIEEE80211_ADDR_COPY(aad, wh->i_addr3); aad += IEEE80211_ADDR_LEN;\n\t*aad++ = wh->i_seq[0] & ~0xf0;\n\t*aad++ = 0;\n\tif (ieee80211_has_addr4(wh)) {\n\t\tIEEE80211_ADDR_COPY(aad,\n\t\t    ((const struct ieee80211_frame_addr4 *)wh)->i_addr4);\n\t\taad += IEEE80211_ADDR_LEN;\n\t}\n\tif (ieee80211_has_qos(wh)) {\n\t\t/* \n\t\t * XXX 802.11-2012 11.4.3.3.3 g says the A-MSDU present bit\n\t\t * must be set here if both STAs are SPP A-MSDU capable.\n\t\t */\n\t\t*aad++ = tid = ieee80211_get_qos(wh) & IEEE80211_QOS_TID;\n\t\t*aad++ = 0;\n\t}\n\n\t/* construct CCM nonce */\n\tnonce[ 0] = tid;\n\tif ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==\n\t    IEEE80211_FC0_TYPE_MGT)\n\t\tnonce[0] |= 1 << 4;\t/* 11w: set management bit */\n\tIEEE80211_ADDR_COPY(&nonce[1], wh->i_addr2);\n\tnonce[ 7] = pn >> 40;\t/* PN5 */\n\tnonce[ 8] = pn >> 32;\t/* PN4 */\n\tnonce[ 9] = pn >> 24;\t/* PN3 */\n\tnonce[10] = pn >> 16;\t/* PN2 */\n\tnonce[11] = pn >> 8;\t/* PN1 */\n\tnonce[12] = pn;\t\t/* PN0 */\n\n\t/* add 2 authentication blocks (including l(a) and padded AAD) */\n\tla = aad - &auth[2];\t\t/* fill l(a) */\n\tauth[0] = la >> 8;\n\tauth[1] = la & 0xff;\n\tmemset(aad, 0, 30 - la);\t/* pad AAD with zeros */\n\n\t/* construct first block B_0 */\n\tb[ 0] = 89;\t/* Flags = 64*Adata + 8*((M-2)/2) + (L-1) */\n\tmemcpy(&b[1], nonce, 13);\n\tb[14] = lm >> 8;\n\tb[15] = lm & 0xff;\n\tAES_Encrypt(ctx, b, b);\n\n\tfor (i = 0; i < 16; i++)\n\t\tb[i] ^= auth[i];\n\tAES_Encrypt(ctx, b, b);\n\tfor (i = 0; i < 16; i++)\n\t\tb[i] ^= auth[16 + i];\n\tAES_Encrypt(ctx, b, b);\n\n\t/* construct S_0 */\n\ta[ 0] = 1;\t/* Flags = L' = (L-1) */\n\tmemcpy(&a[1], nonce, 13);\n\ta[14] = a[15] = 0;\n\tAES_Encrypt(ctx, a, s0);\n}\n\nmbuf_t\nieee80211_ccmp_encrypt(struct ieee80211com *ic, mbuf_t m0,\n    struct ieee80211_key *k)\n{\n\tstruct ieee80211_ccmp_ctx *ctx = (struct ieee80211_ccmp_ctx *)k->k_priv;\n\tconst struct ieee80211_frame *wh;\n\tconst u_int8_t *src;\n\tu_int8_t *ivp, *mic, *dst;\n\tu_int8_t a[16], b[16], s0[16], s[16];\n\tmbuf_t n0, m, n;\n\tint hdrlen, left, moff, noff, len;\n\tu_int16_t ctr;\n\tint i, j;\n    mbuf_t temp;\n    unsigned int max_chunks = 1;\n\n    mbuf_get(MBUF_DONTWAIT, mbuf_type(m0), &n0);\n\tif (n0 == NULL)\n\t\tgoto nospace;\n\tif (m_dup_pkthdr(n0, m0, MBUF_DONTWAIT))\n\t\tgoto nospace;\n    mbuf_pkthdr_setlen(n0, mbuf_pkthdr_len(n0) + IEEE80211_CCMP_HDRLEN);\n    mbuf_setlen(n0, mbuf_get_mhlen());\n\tif (mbuf_pkthdr_len(n0) >= mbuf_get_minclsize() - IEEE80211_CCMP_MICLEN) {\n        mbuf_mclget(MBUF_DONTWAIT, mbuf_type(n0), &n0);\n\t\tif (mbuf_flags(n0) & MBUF_EXT)\n            mbuf_setlen(n0, MCLBYTES);\n\t}\n\tif (mbuf_len(n0) > mbuf_pkthdr_len(n0))\n        mbuf_setlen(n0, mbuf_pkthdr_len(n0));\n\n\t/* copy 802.11 header */\n\twh = mtod(m0, struct ieee80211_frame *);\n\thdrlen = ieee80211_get_hdrlen(wh);\n\tmemcpy(mtod(n0, caddr_t), wh, hdrlen);\n\n\tk->k_tsc++;\t/* increment the 48-bit PN */\n\n\t/* construct CCMP header */\n\tivp = mtod(n0, u_int8_t *) + hdrlen;\n\tivp[0] = k->k_tsc;\t\t/* PN0 */\n\tivp[1] = k->k_tsc >> 8;\t\t/* PN1 */\n\tivp[2] = 0;\t\t\t/* Rsvd */\n\tivp[3] = k->k_id << 6 | IEEE80211_WEP_EXTIV;\t/* KeyID | ExtIV */\n\tivp[4] = k->k_tsc >> 16;\t/* PN2 */\n\tivp[5] = k->k_tsc >> 24;\t/* PN3 */\n\tivp[6] = k->k_tsc >> 32;\t/* PN4 */\n\tivp[7] = k->k_tsc >> 40;\t/* PN5 */\n\n\t/* construct initial B, A and S_0 blocks */\n\tieee80211_ccmp_phase1(&ctx->aesctx, wh, k->k_tsc,\n\t    mbuf_pkthdr_len(m0) - hdrlen, b, a, s0);\n\n\t/* construct S_1 */\n\tctr = 1;\n\ta[14] = ctr >> 8;\n\ta[15] = ctr & 0xff;\n\tAES_Encrypt(&ctx->aesctx, a, s);\n\n\t/* encrypt frame body and compute MIC */\n\tj = 0;\n\tm = m0;\n\tn = n0;\n\tmoff = hdrlen;\n\tnoff = hdrlen + IEEE80211_CCMP_HDRLEN;\n\tleft = mbuf_pkthdr_len(m0) - moff;\n\twhile (left > 0) {\n\t\tif (moff == mbuf_len(m)) {\n\t\t\t/* nothing left to copy from m */\n\t\t\tm = mbuf_next(m);\n\t\t\tmoff = 0;\n\t\t}\n\t\tif (noff == mbuf_len(n)) {\n\t\t\t/* n is full and there's more data to copy */\n            temp = NULL;\n            mbuf_get(MBUF_DONTWAIT, mbuf_type(n), &temp);\n\t\t\tif (temp == NULL)\n\t\t\t\tgoto nospace;\n            mbuf_setnext(n, temp);\n\t\t\tn = mbuf_next(n);\n            mbuf_setlen(n, mbuf_get_mlen());\n\t\t\tif (left >= mbuf_get_minclsize() - IEEE80211_CCMP_MICLEN) {\n                mbuf_mclget(MBUF_DONTWAIT, mbuf_type(n), &n);\n\t\t\t\tif (mbuf_flags(n) & MBUF_EXT)\n                    mbuf_setlen(n, MCLBYTES);\n\t\t\t}\n\t\t\tif (mbuf_len(n) > left)\n                mbuf_setlen(n, left);\n\t\t\tnoff = 0;\n\t\t}\n\t\tlen = min(mbuf_len(m) - moff, mbuf_len(n) - noff);\n\n\t\tsrc = mtod(m, u_int8_t *) + moff;\n\t\tdst = mtod(n, u_int8_t *) + noff;\n\t\tfor (i = 0; i < len; i++) {\n\t\t\t/* update MIC with clear text */\n\t\t\tb[j] ^= src[i];\n\t\t\t/* encrypt message */\n\t\t\tdst[i] = src[i] ^ s[j];\n\t\t\tif (++j < 16)\n\t\t\t\tcontinue;\n\t\t\t/* we have a full block, encrypt MIC */\n\t\t\tAES_Encrypt(&ctx->aesctx, b, b);\n\t\t\t/* construct a new S_ctr block */\n\t\t\tctr++;\n\t\t\ta[14] = ctr >> 8;\n\t\t\ta[15] = ctr & 0xff;\n\t\t\tAES_Encrypt(&ctx->aesctx, a, s);\n\t\t\tj = 0;\n\t\t}\n\n\t\tmoff += len;\n\t\tnoff += len;\n\t\tleft -= len;\n\t}\n\tif (j != 0)\t/* partial block, encrypt MIC */\n\t\tAES_Encrypt(&ctx->aesctx, b, b);\n\n\t/* reserve trailing space for MIC */\n\tif (mbuf_trailingspace(n) < IEEE80211_CCMP_MICLEN) {\n        temp = NULL;\n        mbuf_get(MBUF_DONTWAIT, mbuf_type(n), &temp);\n\t\tif (temp == NULL)\n\t\t\tgoto nospace;\n        mbuf_setnext(n, temp);\n\t\tn = mbuf_next(n);\n        mbuf_setlen(n, 0);\n\t}\n\t/* finalize MIC, U := T XOR first-M-bytes( S_0 ) */\n\tmic = mtod(n, u_int8_t *) + mbuf_len(n);\n\tfor (i = 0; i < IEEE80211_CCMP_MICLEN; i++)\n\t\tmic[i] = b[i] ^ s0[i];\n    mbuf_setlen(n, mbuf_len(n) + IEEE80211_CCMP_MICLEN);\n    mbuf_pkthdr_setlen(n0, mbuf_pkthdr_len(n0) + IEEE80211_CCMP_MICLEN);\n\n\tmbuf_freem(m0);\n\treturn n0;\n nospace:\n\tic->ic_stats.is_tx_nombuf++;\n\tmbuf_freem(m0);\n\tmbuf_freem(n0);\n\treturn NULL;\n}\n\nint\nieee80211_ccmp_get_pn(uint64_t *pn, uint64_t **prsc, mbuf_t m,\n    struct ieee80211_key *k)\n{\n   struct ieee80211_frame *wh;\n   int hdrlen;\n   const u_int8_t *ivp;\n\n   wh = mtod(m, struct ieee80211_frame *);\n   hdrlen = ieee80211_get_hdrlen(wh);\n   if (mbuf_pkthdr_len(m) < hdrlen + IEEE80211_CCMP_HDRLEN)\n       return EINVAL;\n\n   ivp = (u_int8_t *)wh + hdrlen;\n\n   /* check that ExtIV bit is set */\n   if (!(ivp[3] & IEEE80211_WEP_EXTIV))\n       return EINVAL;\n\n   /* retrieve last seen packet number for this frame type/priority */\n   if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==\n       IEEE80211_FC0_TYPE_DATA) {\n       u_int8_t tid = ieee80211_has_qos(wh) ?\n           ieee80211_get_qos(wh) & IEEE80211_QOS_TID : 0;\n       *prsc = &k->k_rsc[tid];\n   } else    /* 11w: management frames have their own counters */\n       *prsc = &k->k_mgmt_rsc;\n\n   /* extract the 48-bit PN from the CCMP header */\n   *pn = (u_int64_t)ivp[0]      |\n        (u_int64_t)ivp[1] <<  8 |\n        (u_int64_t)ivp[4] << 16 |\n        (u_int64_t)ivp[5] << 24 |\n        (u_int64_t)ivp[6] << 32 |\n        (u_int64_t)ivp[7] << 40;\n\n   return 0;\n}\n\nmbuf_t\nieee80211_ccmp_decrypt(struct ieee80211com *ic, mbuf_t m0,\n    struct ieee80211_key *k)\n{\n\tstruct ieee80211_ccmp_ctx *ctx = (struct ieee80211_ccmp_ctx *)k->k_priv;\n\tstruct ieee80211_frame *wh;\n\tu_int64_t pn, *prsc;\n    const u_int8_t *src;\n\tu_int8_t *dst;\n\tu_int8_t mic0[IEEE80211_CCMP_MICLEN];\n\tu_int8_t a[16], b[16], s0[16], s[16];\n\tmbuf_t n0, m, n;\n\tint hdrlen, left, moff, noff, len;\n\tu_int16_t ctr;\n\tint i, j;\n    mbuf_t temp;\n    unsigned int max_chunks = 1;\n\n\twh = mtod(m0, struct ieee80211_frame *);\n    hdrlen = ieee80211_get_hdrlen(wh);\n    if (mbuf_pkthdr_len(m0) < hdrlen + IEEE80211_CCMP_HDRLEN +\n        IEEE80211_CCMP_MICLEN) {\n        mbuf_freem(m0);\n        return NULL;\n    }\n    \n    /*\n     * Get the frame's Packet Number (PN) and a pointer to our last-seen\n     * Receive Sequence Counter (RSC) which we can use to detect replays.\n     */\n    if (ieee80211_ccmp_get_pn(&pn, &prsc, m0, k) != 0) {\n        mbuf_freem(m0);\n        return NULL;\n    }\n\n\tif (pn <= *prsc) {\n\t\t/* replayed frame, discard */\n\t\tic->ic_stats.is_ccmp_replays++;\n\t\tmbuf_freem(m0);\n\t\treturn NULL;\n\t}\n\n    mbuf_get(MBUF_DONTWAIT, mbuf_type(m0), &n0);\n\tif (n0 == NULL)\n\t\tgoto nospace;\n\tif (m_dup_pkthdr(n0, m0, MBUF_DONTWAIT))\n\t\tgoto nospace;\n    \n    mbuf_pkthdr_setlen(n0, mbuf_pkthdr_len(n0) - (IEEE80211_CCMP_HDRLEN + IEEE80211_CCMP_MICLEN));\n    mbuf_setlen(n0, mbuf_get_mhlen());\n\tif (mbuf_pkthdr_len(n0) >= mbuf_get_minclsize()) {\n        mbuf_mclget(MBUF_DONTWAIT, mbuf_type(n0), &n0);\n\t\tif (mbuf_flags(n0) & MBUF_EXT)\n            mbuf_setlen(n0, MCLBYTES);\n\t}\n\tif (mbuf_len(n0) > mbuf_pkthdr_len(n0))\n        mbuf_setlen(n0, mbuf_pkthdr_len(n0));\n\n\t/* construct initial B, A and S_0 blocks */\n\tieee80211_ccmp_phase1(&ctx->aesctx, wh, pn,\n\t    mbuf_pkthdr_len(n0) - hdrlen, b, a, s0);\n\n\t/* copy 802.11 header and clear protected bit */\n\tmemcpy(mtod(n0, caddr_t), wh, hdrlen);\n\twh = mtod(n0, struct ieee80211_frame *);\n\twh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED;\n\n\t/* construct S_1 */\n\tctr = 1;\n\ta[14] = ctr >> 8;\n\ta[15] = ctr & 0xff;\n\tAES_Encrypt(&ctx->aesctx, a, s);\n\n\t/* decrypt frame body and compute MIC */\n\tj = 0;\n\tm = m0;\n\tn = n0;\n\tmoff = hdrlen + IEEE80211_CCMP_HDRLEN;\n\tnoff = hdrlen;\n\tleft = mbuf_pkthdr_len(n0) - noff;\n\twhile (left > 0) {\n\t\tif (moff == mbuf_len(m)) {\n\t\t\t/* nothing left to copy from m */\n\t\t\tm = mbuf_next(m);\n\t\t\tmoff = 0;\n\t\t}\n\t\tif (noff == mbuf_len(n)) {\n\t\t\t/* n is full and there's more data to copy */\n            temp = NULL;\n            mbuf_get(MBUF_DONTWAIT, mbuf_type(n), &temp);\n\t\t\tif (temp == NULL)\n\t\t\t\tgoto nospace;\n            mbuf_setnext(n, temp);\n\t\t\tn = mbuf_next(n);\n            mbuf_setlen(n, mbuf_get_mlen());\n\t\t\tif (left >= mbuf_get_minclsize()) {\n                mbuf_mclget(MBUF_DONTWAIT, mbuf_type(n), &n);\n\t\t\t\tif (mbuf_flags(n) & MBUF_EXT)\n                    mbuf_setlen(n, MCLBYTES);\n\t\t\t}\n\t\t\tif (mbuf_len(n) > left)\n                mbuf_setlen(n, left);\n\t\t\tnoff = 0;\n\t\t}\n\t\tlen = min(mbuf_len(m) - moff, mbuf_len(n) - noff);\n\n\t\tsrc = mtod(m, u_int8_t *) + moff;\n\t\tdst = mtod(n, u_int8_t *) + noff;\n\t\tfor (i = 0; i < len; i++) {\n\t\t\t/* decrypt message */\n\t\t\tdst[i] = src[i] ^ s[j];\n\t\t\t/* update MIC with clear text */\n\t\t\tb[j] ^= dst[i];\n\t\t\tif (++j < 16)\n\t\t\t\tcontinue;\n\t\t\t/* we have a full block, encrypt MIC */\n\t\t\tAES_Encrypt(&ctx->aesctx, b, b);\n\t\t\t/* construct a new S_ctr block */\n\t\t\tctr++;\n\t\t\ta[14] = ctr >> 8;\n\t\t\ta[15] = ctr & 0xff;\n\t\t\tAES_Encrypt(&ctx->aesctx, a, s);\n\t\t\tj = 0;\n\t\t}\n\n\t\tmoff += len;\n\t\tnoff += len;\n\t\tleft -= len;\n\t}\n\tif (j != 0)\t/* partial block, encrypt MIC */\n\t\tAES_Encrypt(&ctx->aesctx, b, b);\n\n\t/* finalize MIC, U := T XOR first-M-bytes( S_0 ) */\n\tfor (i = 0; i < IEEE80211_CCMP_MICLEN; i++)\n\t\tb[i] ^= s0[i];\n\n\t/* check that it matches the MIC in received frame */\n\tmbuf_copydata(m, moff, IEEE80211_CCMP_MICLEN, mic0);\n\tif (timingsafe_bcmp(mic0, b, IEEE80211_CCMP_MICLEN) != 0) {\n\t\tic->ic_stats.is_ccmp_dec_errs++;\n\t\tmbuf_freem(m0);\n\t\tmbuf_freem(n0);\n\t\treturn NULL;\n\t}\n\n\t/* update last seen packet number (MIC is validated) */\n\t*prsc = pn;\n\n\tmbuf_freem(m0);\n\treturn n0;\n nospace:\n\tic->ic_stats.is_rx_nombuf++;\n\tmbuf_freem(m0);\n\tmbuf_freem(n0);\n\treturn NULL;\n}\n"
  },
  {
    "path": "itl80211/openbsd/net80211/ieee80211_crypto_tkip.c",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n/*\t$OpenBSD: ieee80211_crypto_tkip.c,v 1.30 2018/11/09 14:14:31 claudio Exp $\t*/\n\n/*-\n * Copyright (c) 2008 Damien Bergamini <damien.bergamini@free.fr>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n/*\n * This code implements the Temporal Key Integrity Protocol (TKIP) defined\n * in IEEE Std 802.11-2007 section 8.3.2.\n */\n\n#include <sys/param.h>\n#include <sys/systm.h>\n#include <sys/mbuf.h>\n#include <sys/malloc.h>\n#include <sys/kernel.h>\n#include <sys/socket.h>\n#include <sys/endian.h>\n#include <sys/syslog.h>\n\n#include <net/if.h>\n#include <net/if_dl.h>\n#include <net/if_media.h>\n#include <sys/_arc4random.h>\n\n#include <netinet/in.h>\n#include <netinet/if_ether.h>\n\n#include <net80211/ieee80211_var.h>\n#include <net80211/ieee80211_crypto.h>\n\n#include <crypto/arc4.h>\n#include <crypto/michael.h>\n\ntypedef u_int8_t  byte;\t/* 8-bit byte (octet) */\ntypedef u_int16_t u16b;\t/* 16-bit unsigned word */\ntypedef u_int32_t u32b;\t/* 32-bit unsigned word */\n\nstatic void\tPhase1(u16b *, const byte *, const byte *, u32b);\nstatic void\tPhase2(byte *, const byte *, const u16b *, u16b);\n\n/* TKIP software crypto context */\nstruct ieee80211_tkip_ctx {\n\tstruct rc4_ctx\trc4;\n\tconst u_int8_t\t*txmic;\n\tconst u_int8_t\t*rxmic;\n\tu_int16_t\ttxttak[5];\n\tu_int16_t\trxttak[5];\n\tu_int8_t\ttxttak_ok;\n\tu_int8_t\trxttak_ok;\n};\n\n/*\n * Initialize software crypto context.  This function can be overridden\n * by drivers doing hardware crypto.\n */\nint\nieee80211_tkip_set_key(struct ieee80211com *ic, struct ieee80211_key *k)\n{\n\tstruct ieee80211_tkip_ctx *ctx;\n\n\tctx = (struct ieee80211_tkip_ctx *)malloc(sizeof(*ctx), 0, 0);\n\tif (ctx == NULL)\n\t\treturn ENOMEM;\n\t/*\n\t * Use bits 128-191 as the Michael key for AA->SPA and bits\n\t * 192-255 as the Michael key for SPA->AA.\n\t */\n#ifndef IEEE80211_STA_ONLY\n\tif (ic->ic_opmode == IEEE80211_M_HOSTAP) {\n\t\tctx->txmic = &k->k_key[16];\n\t\tctx->rxmic = &k->k_key[24];\n\t} else\n#endif\n\t{\n#ifdef USE_APPLE_SUPPLICANT\n        ctx->txmic = &k->k_key[16];\n        ctx->rxmic = &k->k_key[24];\n#else\n\t\tctx->rxmic = &k->k_key[16];\n\t\tctx->txmic = &k->k_key[24];\n#endif\n\t}\n\tk->k_priv = ctx;\n    XYLog(\"%s kid=%d klen=%d key=%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X \\n\", __FUNCTION__, k->k_id, k->k_len, k->k_key[0], k->k_key[1], k->k_key[2], k->k_key[3], k->k_key[4], k->k_key[5], k->k_key[6], k->k_key[7], k->k_key[8], k->k_key[9], k->k_key[10], k->k_key[11], k->k_key[12], k->k_key[13], k->k_key[14], k->k_key[15], k->k_key[16], k->k_key[17], k->k_key[18], k->k_key[19], k->k_key[20], k->k_key[21], k->k_key[22], k->k_key[23], k->k_key[24], k->k_key[25], k->k_key[26], k->k_key[27], k->k_key[28], k->k_key[29], k->k_key[30], k->k_key[31]);\n    XYLog(\"%s rxmic=%02X %02X %02X %02X %02X %02X %02X %02X txmic=%02X %02X %02X %02X %02X %02X %02X %02X \", __FUNCTION__, ctx->rxmic[0], ctx->rxmic[1], ctx->rxmic[2], ctx->rxmic[3], ctx->rxmic[4], ctx->rxmic[5], ctx->rxmic[6], ctx->rxmic[7], ctx->txmic[0], ctx->txmic[1], ctx->txmic[2], ctx->txmic[3], ctx->txmic[4], ctx->txmic[5], ctx->txmic[6], ctx->txmic[7]);\n\treturn 0;\n}\n\nvoid\nieee80211_tkip_delete_key(struct ieee80211com *ic, struct ieee80211_key *k)\n{\n\tif (k->k_priv != NULL) {\n\t\texplicit_bzero(k->k_priv, sizeof(struct ieee80211_tkip_ctx));\n\t\tfree(k->k_priv);\n\t}\n\tk->k_priv = NULL;\n}\n\n/* pseudo-header used for TKIP MIC computation */\nstruct ieee80211_tkip_frame {\n\tu_int8_t\ti_da[IEEE80211_ADDR_LEN];\n\tu_int8_t\ti_sa[IEEE80211_ADDR_LEN];\n\tu_int8_t\ti_pri;\n\tu_int8_t\ti_pad[3];\n} __packed;\n\n/*\n * Compute TKIP MIC over an mbuf chain starting \"off\" bytes from the\n * beginning.  This function should be kept independant from the software\n * TKIP crypto code so that drivers doing hardware crypto but not MIC can\n * call it without a software crypto context.\n */\nvoid\nieee80211_tkip_mic(mbuf_t m0, int off, const u_int8_t *key,\n    u_int8_t mic[IEEE80211_TKIP_MICLEN])\n{\n\tconst struct ieee80211_frame *wh;\n\tstruct ieee80211_tkip_frame wht;\n\tMICHAEL_CTX ctx;\t/* small enough */\n\tmbuf_t m;\n\tcaddr_t pos;\n\tint len;\n\n\t/* assumes 802.11 header is contiguous */\n\twh = mtod(m0, struct ieee80211_frame *);\n\n\t/* construct pseudo-header for TKIP MIC computation */\n\tswitch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) {\n\tcase IEEE80211_FC1_DIR_NODS:\n\t\tIEEE80211_ADDR_COPY(wht.i_da, wh->i_addr1);\n\t\tIEEE80211_ADDR_COPY(wht.i_sa, wh->i_addr2);\n\t\tbreak;\n\tcase IEEE80211_FC1_DIR_TODS:\n\t\tIEEE80211_ADDR_COPY(wht.i_da, wh->i_addr3);\n\t\tIEEE80211_ADDR_COPY(wht.i_sa, wh->i_addr2);\n\t\tbreak;\n\tcase IEEE80211_FC1_DIR_FROMDS:\n\t\tIEEE80211_ADDR_COPY(wht.i_da, wh->i_addr1);\n\t\tIEEE80211_ADDR_COPY(wht.i_sa, wh->i_addr3);\n\t\tbreak;\n\tcase IEEE80211_FC1_DIR_DSTODS:\n\t\tIEEE80211_ADDR_COPY(wht.i_da, wh->i_addr3);\n\t\tIEEE80211_ADDR_COPY(wht.i_sa,\n\t\t    ((const struct ieee80211_frame_addr4 *)wh)->i_addr4);\n\t\tbreak;\n\t}\n\tif (ieee80211_has_qos(wh))\n\t\twht.i_pri = ieee80211_get_qos(wh) & IEEE80211_QOS_TID;\n\telse\n\t\twht.i_pri = 0;\n\twht.i_pad[0] = wht.i_pad[1] = wht.i_pad[2] = 0;\n\n\tmichael_init(&ctx);\n\tmichael_key(key, &ctx);\n\n\tmichael_update((MICHAEL_CTX *)&ctx, (const u_int8_t *)&wht, sizeof(wht));\n\n\tm = m0;\n\t/* assumes the first \"off\" bytes are contiguous */\n\tpos = mtod(m, caddr_t) + off;\n\tlen = mbuf_len(m) - off;\n\tfor (;;) {\n\t\tmichael_update(&ctx, (const u_int8_t *)pos, len);\n\t\tif ((m = mbuf_next(m)) == NULL)\n\t\t\tbreak;\n\t\tpos = mtod(m, caddr_t);\n\t\tlen = mbuf_len(m);\n\t}\n\n\tmichael_final(mic, &ctx);\n}\n\n/* shortcuts */\n#define IEEE80211_TKIP_TAILLEN\t\\\n\t(IEEE80211_TKIP_MICLEN + IEEE80211_WEP_CRCLEN)\n#define IEEE80211_TKIP_OVHD\t\\\n\t(IEEE80211_TKIP_HDRLEN + IEEE80211_TKIP_TAILLEN)\n\nmbuf_t\nieee80211_tkip_encrypt(struct ieee80211com *ic, mbuf_t m0,\n    struct ieee80211_key *k)\n{\n\tstruct ieee80211_tkip_ctx *ctx = (struct ieee80211_tkip_ctx *)k->k_priv;\n\tu_int16_t wepseed[8];\t/* needs to be 16-bit aligned for Phase2 */\n\tconst struct ieee80211_frame *wh;\n\tu_int8_t *ivp, *mic, *icvp;\n\tmbuf_t n0, m, n;\n\tu_int32_t crc;\n\tint left, moff, noff, len, hdrlen;\n    mbuf_t temp;\n    unsigned int max_chunks = 1;\n    struct _ifnet *ifp = &ic->ic_ac.ac_if;\n\n    if (m0 == NULL) {\n        XYLog(\"%s, m0==NULL\\n\", __FUNCTION__);\n        return NULL;\n    }\n    mbuf_get(MBUF_DONTWAIT, mbuf_type(m0), &n0);\n\tif (n0 == NULL)\n\t\tgoto nospace;\n\tif (m_dup_pkthdr(n0, m0, MBUF_DONTWAIT))\n\t\tgoto nospace;\n    mbuf_pkthdr_setlen(n0, mbuf_pkthdr_len(n0) + IEEE80211_TKIP_HDRLEN);\n    mbuf_setlen(n0, mbuf_get_mhlen());\n\tif (mbuf_pkthdr_len(n0) >= mbuf_get_minclsize() - IEEE80211_TKIP_TAILLEN) {\n        mbuf_mclget(MBUF_DONTWAIT, mbuf_type(n0), &n0);\n        if (mbuf_flags(n0) & MBUF_EXT)\n            mbuf_setlen(n0, MCLBYTES);\n\t}\n\tif (mbuf_len(n0) > mbuf_pkthdr_len(n0))\n        mbuf_setlen(n0, mbuf_pkthdr_len(n0));\n\n\t/* copy 802.11 header */\n\twh = mtod(m0, struct ieee80211_frame *);\n\thdrlen = ieee80211_get_hdrlen(wh);\n\tmemcpy(mtod(n0, caddr_t), wh, hdrlen);\n\n\tk->k_tsc++;\t/* increment the 48-bit TSC */\n\n\t/* construct TKIP header */\n\tivp = mtod(n0, u_int8_t *) + hdrlen;\n\tivp[0] = k->k_tsc >> 8;\t\t/* TSC1 */\n\t/* WEP Seed = (TSC1 | 0x20) & 0x7f (see 8.3.2.2) */\n\tivp[1] = (ivp[0] | 0x20) & 0x7f;\n\tivp[2] = k->k_tsc;\t\t/* TSC0 */\n\tivp[3] = k->k_id << 6 | IEEE80211_WEP_EXTIV;\t/* KeyID | ExtIV */\n\tivp[4] = k->k_tsc >> 16;\t/* TSC2 */\n\tivp[5] = k->k_tsc >> 24;\t/* TSC3 */\n\tivp[6] = k->k_tsc >> 32;\t/* TSC4 */\n\tivp[7] = k->k_tsc >> 40;\t/* TSC5 */\n\n\t/* compute WEP seed */\n\tif (!ctx->txttak_ok || (k->k_tsc & 0xffff) == 0) {\n\t\tPhase1(ctx->txttak, k->k_key, wh->i_addr2, k->k_tsc >> 16);\n\t\tctx->txttak_ok = 1;\n\t}\n\tPhase2((u_int8_t *)wepseed, k->k_key, ctx->txttak, k->k_tsc & 0xffff);\n\trc4_keysetup(&ctx->rc4, (u_int8_t *)wepseed, 16);\n\texplicit_bzero(wepseed, sizeof(wepseed));\n\n\t/* encrypt frame body and compute WEP ICV */\n\tm = m0;\n\tn = n0;\n\tmoff = hdrlen;\n\tnoff = hdrlen + IEEE80211_TKIP_HDRLEN;\n\tleft = mbuf_pkthdr_len(m0) - moff;\n\tcrc = ~0;\n\twhile (left > 0) {\n\t\tif (moff == mbuf_len(m)) {\n\t\t\t/* nothing left to copy from m */\n\t\t\tm = mbuf_next(m);\n\t\t\tmoff = 0;\n\t\t}\n\t\tif (noff == mbuf_len(n)) {\n\t\t\t/* n is full and there's more data to copy */\n            temp = NULL;\n            mbuf_get(MBUF_DONTWAIT, mbuf_type(n), &temp);\n\t\t\tif (temp == NULL)\n\t\t\t\tgoto nospace;\n            mbuf_setnext(n, temp);\n\t\t\tn = mbuf_next(n);\n            mbuf_setlen(n, mbuf_get_mlen());\n\t\t\tif (left >= mbuf_get_minclsize() - IEEE80211_TKIP_TAILLEN) {\n                mbuf_mclget(MBUF_DONTWAIT, mbuf_type(n), &n);\n\t\t\t\tif (mbuf_flags(n) & MBUF_EXT)\n                    mbuf_setlen(n, MCLBYTES);\n\t\t\t}\n\t\t\tif (mbuf_len(n) > left)\n                mbuf_setlen(n, left);\n\t\t\tnoff = 0;\n\t\t}\n\t\tlen = min(mbuf_len(m) - moff, mbuf_len(n) - noff);\n\n\t\tcrc = ether_crc32_le_update(crc, mtod(m, const u_int8_t *) + moff, len);\n\t\trc4_crypt(&ctx->rc4, mtod(m, u_char*) + moff,\n\t\t    mtod(n, u_char*) + noff, len);\n\n\t\tmoff += len;\n\t\tnoff += len;\n\t\tleft -= len;\n\t}\n\n\t/* reserve trailing space for TKIP MIC and WEP ICV */\n\tif (mbuf_trailingspace(n) < IEEE80211_TKIP_TAILLEN) {\n        temp = NULL;\n        mbuf_get(MBUF_DONTWAIT, mbuf_type(n), &temp);\n\t\tif (temp == NULL)\n\t\t\tgoto nospace;\n        mbuf_setnext(n, temp);\n\t\tn = mbuf_next(n);\n        mbuf_setlen(n, 0);\n\t}\n\n\t/* compute TKIP MIC over clear text */\n\tmic = mtod(n, uint8_t*) + mbuf_len(n);\n\tieee80211_tkip_mic(m0, hdrlen, ctx->txmic, mic);\n\tcrc = ether_crc32_le_update(crc, mic, IEEE80211_TKIP_MICLEN);\n\trc4_crypt(&ctx->rc4, mic, mic, IEEE80211_TKIP_MICLEN);\n    mbuf_setlen(n, mbuf_len(n) + IEEE80211_TKIP_MICLEN);\n\n\t/* finalize WEP ICV */\n\ticvp = mtod(n, uint8_t*) + mbuf_len(n);\n\tcrc = ~crc;\n\ticvp[0] = crc;\n\ticvp[1] = crc >> 8;\n\ticvp[2] = crc >> 16;\n\ticvp[3] = crc >> 24;\n\trc4_crypt(&ctx->rc4, icvp, icvp, IEEE80211_WEP_CRCLEN);\n    mbuf_setlen(n, mbuf_len(n) + IEEE80211_WEP_CRCLEN);\n    mbuf_pkthdr_setlen(n0, mbuf_pkthdr_len(n0) + IEEE80211_TKIP_TAILLEN);\n\n\tmbuf_freem(m0);\n\treturn n0;\n nospace:\n\tic->ic_stats.is_tx_nombuf++;\n\tmbuf_freem(m0);\n\tmbuf_freem(n0);\n\treturn NULL;\n}\n\nint\nieee80211_tkip_get_tsc(uint64_t *tsc, uint64_t **prsc, mbuf_t m,\n    struct ieee80211_key *k)\n{\n   struct ieee80211_frame *wh;\n   int hdrlen;\n   u_int8_t tid;\n   const u_int8_t *ivp;\n\n   wh = mtod(m, struct ieee80211_frame *);\n   hdrlen = ieee80211_get_hdrlen(wh);\n\n   if (mbuf_pkthdr_len(m) < hdrlen + IEEE80211_TKIP_HDRLEN)\n       return EINVAL;\n\n   ivp = (u_int8_t *)wh + hdrlen;\n   /* check that ExtIV bit is set */\n   if (!(ivp[3] & IEEE80211_WEP_EXTIV))\n       return EINVAL;\n\n   /* Retrieve last seen packet number for this frame priority. */\n   tid = ieee80211_has_qos(wh) ?\n       ieee80211_get_qos(wh) & IEEE80211_QOS_TID : 0;\n   *prsc = &k->k_rsc[tid];\n\n   /* extract the 48-bit TSC from the TKIP header */\n   *tsc = (u_int64_t)ivp[2]      |\n         (u_int64_t)ivp[0] <<  8 |\n         (u_int64_t)ivp[4] << 16 |\n         (u_int64_t)ivp[5] << 24 |\n         (u_int64_t)ivp[6] << 32 |\n         (u_int64_t)ivp[7] << 40;\n\n   return 0;\n}\n\nmbuf_t\nieee80211_tkip_decrypt(struct ieee80211com *ic, mbuf_t m0,\n    struct ieee80211_key *k)\n{\n\tstruct ieee80211_tkip_ctx *ctx = (struct ieee80211_tkip_ctx *)k->k_priv;\n\tstruct ieee80211_frame *wh;\n\tu_int16_t wepseed[8];\t/* needs to be 16-bit aligned for Phase2 */\n\tu_int8_t buf[IEEE80211_TKIP_MICLEN + IEEE80211_WEP_CRCLEN];\n\tu_int8_t mic[IEEE80211_TKIP_MICLEN];\n\tu_int64_t tsc, *prsc;\n\tu_int32_t crc, crc0;\n\tu_int8_t *mic0;\n\tmbuf_t n0, m, n;\n\tint hdrlen, left, moff, noff, len;\n    mbuf_t temp;\n    unsigned int max_chunks = 1;\n    struct _ifnet *ifp = &ic->ic_ac.ac_if;\n\n\twh = mtod(m0, struct ieee80211_frame *);\n\thdrlen = ieee80211_get_hdrlen(wh);\n\n\tif (mbuf_pkthdr_len(m0) < hdrlen + IEEE80211_TKIP_OVHD) {\n\t\tmbuf_freem(m0);\n\t\treturn NULL;\n\t}\n\n    /*\n     * Get the frame's Tansmit Sequence Counter (TSC), and a pointer to\n     * our last-seen Receive Sequence Counter (RSC) with which we can\n     * detect replays.\n     */\n    if (ieee80211_tkip_get_tsc(&tsc, &prsc, m0, k) != 0) {\n        mbuf_freem(m0);\n        return NULL;\n    }\n\n\tif (tsc <= *prsc) {\n\t\t/* replayed frame, discard */\n\t\tic->ic_stats.is_tkip_replays++;\n\t\tmbuf_freem(m0);\n\t\treturn NULL;\n\t}\n\n    mbuf_get(MBUF_DONTWAIT, mbuf_type(m0), &n0);\n\tif (n0 == NULL)\n\t\tgoto nospace;\n\tif (m_dup_pkthdr(n0, m0, MBUF_DONTWAIT))\n\t\tgoto nospace;\n    mbuf_pkthdr_setlen(n0, mbuf_pkthdr_len(n0) - IEEE80211_TKIP_OVHD);\n    mbuf_setlen(n0, mbuf_get_mhlen());\n\tif (mbuf_pkthdr_len(n0) >= mbuf_get_minclsize()) {\n        mbuf_mclget(MBUF_DONTWAIT, mbuf_type(n0), &n0);\n\t\tif (mbuf_flags(n0) & MBUF_EXT)\n            mbuf_setlen(n0, MCLBYTES);\n\t}\n\tif (mbuf_len(n0) > mbuf_pkthdr_len(n0))\n        mbuf_setlen(n0, mbuf_pkthdr_len(n0));\n\n\t/* copy 802.11 header and clear protected bit */\n\tmemcpy(mtod(n0, caddr_t), wh, hdrlen);\n\twh = mtod(n0, struct ieee80211_frame *);\n\twh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED;\n\n\t/* compute WEP seed */\n\tif (!ctx->rxttak_ok || (tsc >> 16) != (*prsc >> 16)) {\n\t\tctx->rxttak_ok = 0;\t/* invalidate cached TTAK (if any) */\n\t\tPhase1(ctx->rxttak, k->k_key, wh->i_addr2, tsc >> 16);\n\t}\n\tPhase2((u_int8_t *)wepseed, k->k_key, ctx->rxttak, tsc & 0xffff);\n\trc4_keysetup(&ctx->rc4, (u_int8_t *)wepseed, 16);\n\texplicit_bzero(wepseed, sizeof(wepseed));\n\n\t/* decrypt frame body and compute WEP ICV */\n\tm = m0;\n\tn = n0;\n\tmoff = hdrlen + IEEE80211_TKIP_HDRLEN;\n\tnoff = hdrlen;\n\tleft = mbuf_pkthdr_len(n0) - noff;\n\tcrc = ~0;\n\twhile (left > 0) {\n\t\tif (moff == mbuf_len(m)) {\n\t\t\t/* nothing left to copy from m */\n\t\t\tm = mbuf_next(m);\n\t\t\tmoff = 0;\n\t\t}\n\t\tif (noff == mbuf_len(n)) {\n\t\t\t/* n is full and there's more data to copy */\n            temp = NULL;\n            mbuf_get(MBUF_DONTWAIT, mbuf_type(n), &temp);\n\t\t\tif (temp == NULL)\n\t\t\t\tgoto nospace;\n            mbuf_setnext(n, temp);\n\t\t\tn = mbuf_next(n);\n            mbuf_setlen(n, mbuf_get_mlen());\n\t\t\tif (left >= mbuf_get_minclsize()) {\n                mbuf_mclget(MBUF_DONTWAIT, mbuf_type(n), &n);\n\t\t\t\tif (mbuf_flags(n) & MBUF_EXT)\n                    mbuf_setlen(n, MCLBYTES);\n\t\t\t}\n\t\t\tif (mbuf_len(n) > left)\n                mbuf_setlen(n, left);\n\t\t\tnoff = 0;\n\t\t}\n\t\tlen = min(mbuf_len(m) - moff, mbuf_len(n) - noff);\n\n\t\trc4_crypt(&ctx->rc4, mtod(m, u_char*) + moff,\n\t\t    mtod(n, u_char*) + noff, len);\n\t\tcrc = ether_crc32_le_update(crc, mtod(n, const uint8_t*) + noff, len);\n\n\t\tmoff += len;\n\t\tnoff += len;\n\t\tleft -= len;\n\t}\n\n\t/* extract and decrypt TKIP MIC and WEP ICV from m0's tail */\n\tmbuf_copydata(m, moff, IEEE80211_TKIP_TAILLEN, buf);\n\trc4_crypt(&ctx->rc4, buf, buf, IEEE80211_TKIP_TAILLEN);\n\n\t/* include TKIP MIC in WEP ICV */\n\tmic0 = buf;\n\tcrc = ether_crc32_le_update(crc, mic0, IEEE80211_TKIP_MICLEN);\n\tcrc = ~crc;\n\n\t/* decrypt ICV and compare it with calculated ICV */\n\tcrc0 = *(u_int32_t *)(buf + IEEE80211_TKIP_MICLEN);\n\tif (crc != letoh32(crc0)) {\n\t\tic->ic_stats.is_tkip_icv_errs++;\n\t\tmbuf_freem(m0);\n\t\tmbuf_freem(n0);\n\t\treturn NULL;\n\t}\n\n\t/* compute TKIP MIC over decrypted message */\n\tieee80211_tkip_mic(n0, hdrlen, ctx->rxmic, mic);\n\t/* check that it matches the MIC in received frame */\n\tif (timingsafe_bcmp(mic0, mic, IEEE80211_TKIP_MICLEN) != 0) {\n\t\tmbuf_freem(m0);\n\t\tmbuf_freem(n0);\n\t\tic->ic_stats.is_rx_locmicfail++;\n\t\tieee80211_michael_mic_failure(ic, tsc);\n\t\treturn NULL;\n\t}\n\n\t/* update last seen packet number (MIC is validated) */\n\t*prsc = tsc;\n\t/* mark cached TTAK as valid */\n\tctx->rxttak_ok = 1;\n\n\tmbuf_freem(m0);\n\treturn n0;\n nospace:\n\tic->ic_stats.is_rx_nombuf++;\n\tmbuf_freem(m0);\n\tmbuf_freem(n0);\n\treturn NULL;\n}\n\n#ifndef IEEE80211_STA_ONLY\n/*\n * This function is called in HostAP mode to deauthenticate all STAs using\n * TKIP as their pairwise or group cipher (as part of TKIP countermeasures).\n */\nstatic void\nieee80211_tkip_deauth(void *arg, struct ieee80211_node *ni)\n{\n\tstruct ieee80211com *ic = (struct ieee80211com *)arg;\n\n\tif (ni->ni_state == IEEE80211_STA_ASSOC &&\n\t    (ic->ic_bss->ni_rsngroupcipher == IEEE80211_CIPHER_TKIP ||\n\t     ni->ni_rsncipher == IEEE80211_CIPHER_TKIP)) {\n\t\t/* deauthenticate STA */\n\t\tIEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DEAUTH,\n\t\t    IEEE80211_REASON_MIC_FAILURE);\n\t\tieee80211_node_leave(ic, ni);\n\t}\n}\n\nvoid\nieee80211_michael_mic_failure_timeout(void *arg)\n{\n\tstruct ieee80211com *ic = (struct ieee80211com *)arg;\n\n\t/* Disable TKIP countermeasures. */\n\tic->ic_flags &= ~IEEE80211_F_COUNTERM;\n}\n#endif\t/* IEEE80211_STA_ONLY */\n\n/*\n * This function can be called by the software TKIP crypto code or by the\n * drivers when their hardware crypto engines detect a Michael MIC failure.\n */\nvoid\nieee80211_michael_mic_failure(struct ieee80211com *ic, u_int64_t tsc)\n{\n#ifndef IEEE80211_STA_ONLY\n\tint sec;\n#endif\n\n\tif (ic->ic_flags & IEEE80211_F_COUNTERM)\n\t\treturn;\t/* countermeasures already active */\n\n\t//log(LOG_WARNING, \"%s: Michael MIC failure\\n\", ic->ic_if.if_xname);\n\n\t/*\n\t * NB. do not send Michael MIC Failure reports as recommended since\n\t * these may be used as an oracle to verify CRC guesses as described\n\t * in Beck, M. and Tews S. \"Practical attacks against WEP and WPA\"\n\t * http://dl.aircrack-ng.org/breakingwepandwpa.pdf\n\t */\n\n\t/*\n\t * Activate TKIP countermeasures (see 802.11-2012 11.4.2.4) if less than\n\t * 60 seconds have passed since the most recent previous MIC failure.\n\t */\n\tif (ic->ic_tkip_micfail == 0 ||\n\t    ticks - (ic->ic_tkip_micfail + 60 * hz) >= 0) {\n\t\tic->ic_tkip_micfail = ticks;\n\t\tic->ic_tkip_micfail_last_tsc = tsc;\n\t\treturn;\n\t}\n\n\tswitch (ic->ic_opmode) {\n#ifndef IEEE80211_STA_ONLY\n\tcase IEEE80211_M_HOSTAP:\n\t\t/* refuse new TKIP associations for at least 60 seconds */\n\t\tic->ic_flags |= IEEE80211_F_COUNTERM;\n\t\tsec = 60 + arc4random_uniform(30);\n\t\t//log(LOG_WARNING, \"%s: HostAP will be disabled for %d seconds \"\n\t\t//    \"as a countermeasure against TKIP key cracking attempts\\n\",\n\t\t//    ic->ic_if.if_xname, sec);\n\t\ttimeout_add_sec(&ic->ic_tkip_micfail_timeout, sec);\n\n\t\t/* deauthenticate all currently associated STAs using TKIP */\n\t\tieee80211_iterate_nodes(ic, ieee80211_tkip_deauth, ic);\n\n\t\t/* schedule a GTK change */\n\t\ttimeout_add_sec(&ic->ic_rsn_timeout, 1);\n\t\tbreak;\n#endif\n\tcase IEEE80211_M_STA:\n\t\t/*\n\t\t * Notify the AP of MIC failures: send two Michael\n\t\t * MIC Failure Report frames back-to-back to trigger\n\t\t * countermeasures at the AP end.\n\t\t */\n\t\t(void)ieee80211_send_eapol_key_req(ic, ic->ic_bss,\n\t\t    EAPOL_KEY_KEYMIC | EAPOL_KEY_ERROR | EAPOL_KEY_SECURE,\n\t\t    ic->ic_tkip_micfail_last_tsc);\n\t\t(void)ieee80211_send_eapol_key_req(ic, ic->ic_bss,\n\t\t    EAPOL_KEY_KEYMIC | EAPOL_KEY_ERROR | EAPOL_KEY_SECURE,\n\t\t    tsc);\n\n\t\t/* deauthenticate from the AP.. */\n\t\tIEEE80211_SEND_MGMT(ic, ic->ic_bss,\n\t\t    IEEE80211_FC0_SUBTYPE_DEAUTH,\n\t\t    IEEE80211_REASON_MIC_FAILURE);\n\t\t/* ..and find another one */\n\t\tieee80211_new_state(ic, IEEE80211_S_SCAN, -1);\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n\n\tic->ic_tkip_micfail = ticks;\n\tic->ic_tkip_micfail_last_tsc = tsc;\n}\n\n/***********************************************************************\n   Contents:    Generate IEEE 802.11 per-frame RC4 key hash test vectors\n   Date:        April 19, 2002\n   Notes:\n   This code is written for pedagogical purposes, NOT for performance.\n************************************************************************/\n\n/* macros for extraction/creation of byte/u16b values */\n#define RotR1(v16)\t((((v16) >> 1) & 0x7FFF) ^ (((v16) & 1) << 15))\n#define   Lo8(v16)\t((byte)( (v16)       & 0x00FF))\n#define   Hi8(v16)\t((byte)(((v16) >> 8) & 0x00FF))\n#define Lo16(v32)\t((u16b)( (v32)       & 0xFFFF))\n#define Hi16(v32)\t((u16b)(((v32) >>16) & 0xFFFF))\n#define Mk16(hi,lo)\t((lo) ^ (((u16b)(hi)) << 8))\n\n/* select the Nth 16-bit word of the Temporal Key byte array TK[] */\n#define TK16(N)\t\tMk16(TK[2 * (N) + 1], TK[2 * (N)])\n\n/* S-box lookup: 16 bits --> 16 bits */\n#define _S_(v16)\t(Sbox[Lo8(v16)] ^ swap16(Sbox[Hi8(v16)]))\n\n/* fixed algorithm \"parameters\" */\n#define PHASE1_LOOP_CNT\t 8\t/* this needs to be \"big enough\"     */\n#define TA_SIZE\t\t 6\t/* 48-bit transmitter address        */\n#define TK_SIZE\t\t16\t/* 128-bit Temporal Key              */\n#define P1K_SIZE\t10\t/* 80-bit Phase1 key                 */\n#define RC4_KEY_SIZE\t16\t/* 128-bit RC4KEY (104 bits unknown) */\n\n/* 2-byte by 2-byte subset of the full AES S-box table */\nstatic const u16b Sbox[256]=\t/* Sbox for hash */\n{\n\t0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,\n\t0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A,\n\t0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B,\n\t0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B,\n\t0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F,\n\t0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F,\n\t0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5,\n\t0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F,\n\t0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB,\n\t0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397,\n\t0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED,\n\t0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A,\n\t0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194,\n\t0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3,\n\t0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104,\n\t0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D,\n\t0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39,\n\t0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695,\n\t0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83,\n\t0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76,\n\t0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4,\n\t0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B,\n\t0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0,\n\t0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018,\n\t0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751,\n\t0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85,\n\t0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12,\n\t0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9,\n\t0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7,\n\t0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A,\n\t0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8,\n\t0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A\n};\n\n/*\n **********************************************************************\n * Routine: Phase 1 -- generate P1K, given TA, TK, IV32\n *\n * Inputs:\n *     TK[]      = Temporal Key                         [128 bits]\n *     TA[]      = transmitter's MAC address            [ 48 bits]\n *     IV32      = upper 32 bits of IV                  [ 32 bits]\n * Output:\n *     P1K[]     = Phase 1 key                          [ 80 bits]\n *\n * Note:\n *     This function only needs to be called every 2**16 frames,\n *     although in theory it could be called every frame.\n *\n **********************************************************************\n */\nstatic void\nPhase1(u16b *P1K, const byte *TK, const byte *TA, u32b IV32)\n{\n\tint i;\n\n\t/* Initialize the 80 bits of P1K[] from IV32 and TA[0..5] */\n\tP1K[0] = Lo16(IV32);\n\tP1K[1] = Hi16(IV32);\n\tP1K[2] = Mk16(TA[1], TA[0]);\t/* use TA[] as little-endian */\n\tP1K[3] = Mk16(TA[3], TA[2]);\n\tP1K[4] = Mk16(TA[5], TA[4]);\n\n\t/* Now compute an unbalanced Feistel cipher with 80-bit block */\n\t/* size on the 80-bit block P1K[], using the 128-bit key TK[] */\n\tfor (i = 0; i < PHASE1_LOOP_CNT; i++) {\n\t\t/* Each add operation here is mod 2**16 */\n\t\tP1K[0] += _S_(P1K[4] ^ TK16((i & 1) + 0));\n\t\tP1K[1] += _S_(P1K[0] ^ TK16((i & 1) + 2));\n\t\tP1K[2] += _S_(P1K[1] ^ TK16((i & 1) + 4));\n\t\tP1K[3] += _S_(P1K[2] ^ TK16((i & 1) + 6));\n\t\tP1K[4] += _S_(P1K[3] ^ TK16((i & 1) + 0));\n\t\tP1K[4] += i;\t/* avoid \"slide attacks\" */\n\t}\n}\n\n/*\n **********************************************************************\n * Routine: Phase 2 -- generate RC4KEY, given TK, P1K, IV16\n *\n * Inputs:\n *     TK[]      = Temporal Key                         [128 bits]\n *     P1K[]     = Phase 1 output key                   [ 80 bits]\n *     IV16      = low 16 bits of IV counter            [ 16 bits]\n * Output:\n *     RC4KEY[] = the key used to encrypt the frame     [128 bits]\n *\n * Note:\n *     The value {TA,IV32,IV16} for Phase1/Phase2 must be unique\n *     across all frames using the same key TK value. Then, for a\n *     given value of TK[], this TKIP48 construction guarantees that\n *     the final RC4KEY value is unique across all frames.\n *\n **********************************************************************\n */\nstatic void\nPhase2(byte *RC4KEY, const byte *TK, const u16b *P1K, u16b IV16)\n{\n\tu16b *PPK;\t/* temporary key for mixing */\n\tint i;\n\n\t/*\n\t * Suggested implementation optimization: if PPK[] is \"overlaid\"\n\t * appropriately on RC4KEY[], there is no need for the final for\n\t * loop that copies the PPK[] result into RC4KEY[].\n\t */\n\tPPK = (u16b *)&RC4KEY[4];\n\n\t/* all adds in the PPK[] equations below are mod 2**16 */\n\tfor (i = 0; i < 5; i++)\n\t\tPPK[i] = P1K[i];\t/* first, copy P1K to PPK */\n\tPPK[5] = P1K[4] + IV16;\t\t/* next, add in IV16 */\n\n\t/* Bijective non-linear mixing of the 96 bits of PPK[0..5] */\n\tPPK[0] += _S_(PPK[5] ^ TK16(0)); /* Mix key in each \"round\" */\n\tPPK[1] += _S_(PPK[0] ^ TK16(1));\n\tPPK[2] += _S_(PPK[1] ^ TK16(2));\n\tPPK[3] += _S_(PPK[2] ^ TK16(3));\n\tPPK[4] += _S_(PPK[3] ^ TK16(4));\n\tPPK[5] += _S_(PPK[4] ^ TK16(5)); /* Total # S-box lookups == 6 */\n\n\t/* Final sweep: bijective, linear. Rotates kill LSB correlations */\n\tPPK[0] += RotR1(PPK[5] ^ TK16(6));\n\tPPK[1] += RotR1(PPK[0] ^ TK16(7)); /* Use all of TK[] in Phase2 */\n\tPPK[2] += RotR1(PPK[1]);\n\tPPK[3] += RotR1(PPK[2]);\n\tPPK[4] += RotR1(PPK[3]);\n\tPPK[5] += RotR1(PPK[4]);\n\n\t/* At this point, for a given key TK[0..15], the 96-bit output */\n\t/* value PPK[0..5] is guaranteed to be unique, as a function */\n\t/* of the 96-bit \"input\" value   {TA,IV32,IV16}. That is, P1K */\n\t/* is now a keyed permutation of {TA,IV32,IV16}. */\n\t/* Set RC4KEY[0..3], which includes cleartext portion of RC4 key  */\n\tRC4KEY[0] = Hi8(IV16);\t/* RC4KEY[0..2] is the WEP IV */\n\tRC4KEY[1] =(Hi8(IV16) | 0x20) & 0x7F; /* Help avoid FMS weak keys */\n\tRC4KEY[2] = Lo8(IV16);\n\tRC4KEY[3] = Lo8((PPK[5] ^ TK16(0)) >> 1);\n\n#if BYTE_ORDER == BIG_ENDIAN\n\t/* Copy 96 bits of PPK[0..5] to RC4KEY[4..15] (little-endian) */\n\tfor (i = 0; i < 6; i++)\n\t\tPPK[i] = swap16(PPK[i]);\n#endif\n}\n"
  },
  {
    "path": "itl80211/openbsd/net80211/ieee80211_crypto_wep.c",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n/*\t$OpenBSD: ieee80211_crypto_wep.c,v 1.17 2018/11/09 14:14:31 claudio Exp $\t*/\n\n/*-\n * Copyright (c) 2008 Damien Bergamini <damien.bergamini@free.fr>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n/*\n * This code implements Wired Equivalent Privacy (WEP) defined in\n * IEEE Std 802.11-2007 section 8.2.1.\n */\n\n#include <sys/param.h>\n#include <sys/systm.h>\n#include <sys/mbuf.h>\n#include <sys/malloc.h>\n#include <sys/kernel.h>\n#include <sys/socket.h>\n#include <sys/endian.h>\n\n#include <net/if.h>\n#include <net/if_dl.h>\n#include <net/if_media.h>\n\n#include <netinet/in.h>\n#include <netinet/if_ether.h>\n\n#include <net80211/ieee80211_var.h>\n#include <net80211/ieee80211_crypto.h>\n\n#include <crypto/arc4.h>\n#include <sys/_arc4random.h>\n\n/* WEP software crypto context */\nstruct ieee80211_wep_ctx {\n\tstruct rc4_ctx\trc4;\n\tu_int32_t\tiv;\n};\n\n/*\n * Initialize software crypto context.  This function can be overridden\n * by drivers doing hardware crypto.\n */\nint\nieee80211_wep_set_key(struct ieee80211com *ic, struct ieee80211_key *k)\n{\n\tstruct ieee80211_wep_ctx *ctx;\n\n\tctx = (struct ieee80211_wep_ctx *)malloc(sizeof(*ctx), 0, 0);\n\tif (ctx == NULL)\n\t\treturn ENOMEM;\n\tk->k_priv = ctx;\n\treturn 0;\n}\n\nvoid\nieee80211_wep_delete_key(struct ieee80211com *ic, struct ieee80211_key *k)\n{\n\tif (k->k_priv != NULL) {\n\t\texplicit_bzero(k->k_priv, sizeof(struct ieee80211_wep_ctx));\n\t\tfree(k->k_priv);\n\t}\n\tk->k_priv = NULL;\n}\n\n/* shortcut */\n#define IEEE80211_WEP_HDRLEN\t\\\n\t(IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN)\n\nmbuf_t\nieee80211_wep_encrypt(struct ieee80211com *ic, mbuf_t m0,\n    struct ieee80211_key *k)\n{\n\tstruct ieee80211_wep_ctx *ctx = (struct ieee80211_wep_ctx *)k->k_priv;\n\tu_int8_t wepseed[16];\n\tconst struct ieee80211_frame *wh;\n\tmbuf_t n0, m, n;\n\tu_int8_t *ivp, *icvp;\n\tu_int32_t iv, crc;\n\tint left, moff, noff, len, hdrlen;\n    mbuf_t temp;\n\n    mbuf_get(MBUF_DONTWAIT, mbuf_type(m0), &n0);\n\tif (n0 == NULL)\n\t\tgoto nospace;\n\tif (m_dup_pkthdr(n0, m0, MBUF_DONTWAIT))\n\t\tgoto nospace;\n    mbuf_pkthdr_setlen(n0, mbuf_pkthdr_len(n0) + IEEE80211_WEP_HDRLEN);\n    mbuf_setlen(n0, mbuf_get_mhlen());\n\tif (mbuf_pkthdr_len(n0) >= mbuf_get_minclsize() - IEEE80211_WEP_CRCLEN) {\n        mbuf_mclget(MBUF_DONTWAIT, mbuf_type(n0), &n0);\n\t\tif (mbuf_flags(n0) & MBUF_EXT)\n            mbuf_setlen(n0, MCLBYTES);\n\t}\n\tif (mbuf_len(n0) > mbuf_pkthdr_len(n0))\n        mbuf_setlen(n0, mbuf_pkthdr_len(n0));\n\n\t/* copy 802.11 header */\n\twh = mtod(m0, struct ieee80211_frame *);\n\thdrlen = ieee80211_get_hdrlen(wh);\n\tmemcpy(mtod(n0, caddr_t), wh, hdrlen);\n\n\t/* select a new IV for every MPDU */\n\tiv = (ctx->iv != 0) ? ctx->iv : arc4random();\n\t/* skip weak IVs from Fluhrer/Mantin/Shamir */\n\tif (iv >= 0x03ff00 && (iv & 0xf8ff00) == 0x00ff00)\n\t\tiv += 0x000100;\n\tctx->iv = iv + 1;\n\tivp = mtod(n0, u_int8_t *) + hdrlen;\n\tivp[0] = iv;\n\tivp[1] = iv >> 8;\n\tivp[2] = iv >> 16;\n\tivp[3] = k->k_id << 6;\n\n\t/* compute WEP seed: concatenate IV and WEP Key */\n\tmemcpy(wepseed, ivp, IEEE80211_WEP_IVLEN);\n\tmemcpy(wepseed + IEEE80211_WEP_IVLEN, k->k_key, k->k_len);\n\trc4_keysetup(&ctx->rc4, wepseed, IEEE80211_WEP_IVLEN + k->k_len);\n\texplicit_bzero(wepseed, sizeof(wepseed));\n\n\t/* encrypt frame body and compute WEP ICV */\n\tm = m0;\n\tn = n0;\n\tmoff = hdrlen;\n\tnoff = hdrlen + IEEE80211_WEP_HDRLEN;\n\tleft = mbuf_pkthdr_len(m0)- moff;\n\tcrc = ~0;\n\twhile (left > 0) {\n\t\tif (moff == mbuf_len(m)) {\n\t\t\t/* nothing left to copy from m */\n\t\t\tm = mbuf_next(m);\n\t\t\tmoff = 0;\n\t\t}\n\t\tif (noff == mbuf_len(n)) {\n\t\t\t/* n is full and there's more data to copy */\n            temp = NULL;\n\t\t\tmbuf_get(MBUF_DONTWAIT, mbuf_type(n), &temp);\n\t\t\tif (temp == NULL)\n\t\t\t\tgoto nospace;\n            mbuf_setnext(n, temp);\n\t\t\tn = mbuf_next(n);\n            mbuf_setlen(n, mbuf_get_mlen());\n\t\t\tif (left >= mbuf_get_minclsize() - IEEE80211_WEP_CRCLEN) {\n                mbuf_mclget(MBUF_DONTWAIT, mbuf_type(n), &n);\n//\t\t\t\tMCLGET(n, MBUF_DONTWAIT);\n\t\t\t\tif (mbuf_flags(n) & MBUF_EXT)\n                    mbuf_setlen(n, MCLBYTES);\n\t\t\t}\n\t\t\tif (mbuf_len(n) > left)\n                mbuf_setlen(n, left);\n\t\t\tnoff = 0;\n\t\t}\n\t\tlen = min(mbuf_len(m) - moff, mbuf_len(n) - noff);\n\n\t\tcrc = ether_crc32_le_update(crc, mtod(m, const u_int8_t *) + moff, len);\n\t\trc4_crypt(&ctx->rc4, mtod(m, u_char *) + moff,\n\t\t    mtod(n, u_char *) + noff, len);\n\n\t\tmoff += len;\n\t\tnoff += len;\n\t\tleft -= len;\n\t}\n\n\t/* reserve trailing space for WEP ICV */\n\tif (mbuf_trailingspace(n) < IEEE80211_WEP_CRCLEN) {\n        temp = NULL;\n        mbuf_get(MBUF_DONTWAIT, mbuf_type(n), &temp);\n\t\tif (temp == NULL)\n\t\t\tgoto nospace;\n        mbuf_setnext(n, temp);\n\t\tn = mbuf_next(n);\n        mbuf_setlen(n, 0);\n\t}\n\n\t/* finalize WEP ICV */\n\ticvp = mtod(n, uint8_t *) + mbuf_len(n);\n\tcrc = ~crc;\n\ticvp[0] = crc;\n\ticvp[1] = crc >> 8;\n\ticvp[2] = crc >> 16;\n\ticvp[3] = crc >> 24;\n\trc4_crypt(&ctx->rc4, icvp, icvp, IEEE80211_WEP_CRCLEN);\n    mbuf_setlen(n, mbuf_len(n) + IEEE80211_WEP_CRCLEN);\n    mbuf_pkthdr_setlen(n0, mbuf_pkthdr_len(n0) + IEEE80211_WEP_CRCLEN);\n\n\tmbuf_freem(m0);\n\treturn n0;\n nospace:\n\tic->ic_stats.is_tx_nombuf++;\n\tmbuf_freem(m0);\n\tmbuf_freem(n0);\n\treturn NULL;\n}\n\nmbuf_t\nieee80211_wep_decrypt(struct ieee80211com *ic, mbuf_t m0,\n    struct ieee80211_key *k)\n{\n\tstruct ieee80211_wep_ctx *ctx = (struct ieee80211_wep_ctx *)k->k_priv;\n\tstruct ieee80211_frame *wh;\n\tu_int8_t wepseed[16];\n\tu_int32_t crc, crc0;\n\tu_int8_t *ivp;\n\tmbuf_t n0, m, n;\n\tint hdrlen, left, moff, noff, len;\n    mbuf_t temp;\n\n\twh = mtod(m0, struct ieee80211_frame *);\n\thdrlen = ieee80211_get_hdrlen(wh);\n\n\tif (mbuf_pkthdr_len(m0) < hdrlen + IEEE80211_WEP_TOTLEN) {\n\t\tmbuf_freem(m0);\n\t\treturn NULL;\n\t}\n\n\t/* concatenate IV and WEP Key */\n\tivp = (u_int8_t *)wh + hdrlen;\n\tmemcpy(wepseed, ivp, IEEE80211_WEP_IVLEN);\n\tmemcpy(wepseed + IEEE80211_WEP_IVLEN, k->k_key, k->k_len);\n\trc4_keysetup((struct rc4_ctx *)&ctx->rc4, (u_char*)wepseed, (uint32_t)(IEEE80211_WEP_IVLEN + k->k_len));\n\texplicit_bzero(wepseed, sizeof(wepseed));\n\n    mbuf_get(MBUF_DONTWAIT, mbuf_type(m0), &n0);\n\tif (n0 == NULL)\n\t\tgoto nospace;\n\tif (m_dup_pkthdr(n0, m0, MBUF_DONTWAIT))\n\t\tgoto nospace;\n    mbuf_pkthdr_setlen(n0, mbuf_pkthdr_len(n0) - IEEE80211_WEP_TOTLEN);\n\tmbuf_setlen(n0, mbuf_get_mhlen());\n\tif (mbuf_pkthdr_len(n0) >= mbuf_get_minclsize()) {\n        mbuf_mclget(MBUF_DONTWAIT, mbuf_type(n0), &n0);\n//\t\tMCLGET(n0, MBUF_DONTWAIT);\n\t\tif (mbuf_flags(n0) & MBUF_EXT)\n            mbuf_setlen(n0, MCLBYTES);\n//\t\t\tn0->m_len = n0->m_ext.ext_size;\n\t}\n\tif (mbuf_len(n0) > mbuf_pkthdr_len(n0))\n        mbuf_setlen(n0, mbuf_pkthdr_len(n0));\n\n\t/* copy 802.11 header and clear protected bit */\n\tmemcpy(mtod(n0, caddr_t), wh, hdrlen);\n\twh = mtod(n0, struct ieee80211_frame *);\n\twh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED;\n\n\t/* decrypt frame body and compute WEP ICV */\n\tm = m0;\n\tn = n0;\n\tmoff = hdrlen + IEEE80211_WEP_HDRLEN;\n\tnoff = hdrlen;\n\tleft = mbuf_pkthdr_len(n0) - noff;\n\tcrc = ~0;\n\twhile (left > 0) {\n\t\tif (moff == mbuf_len(m)) {\n\t\t\t/* nothing left to copy from m */\n\t\t\tm = mbuf_next(m);\n\t\t\tmoff = 0;\n\t\t}\n\t\tif (noff == mbuf_len(n)) {\n\t\t\t/* n is full and there's more data to copy */\n            temp = NULL;\n            mbuf_get(MBUF_DONTWAIT, mbuf_type(n), &temp);\n\t\t\tif (temp == NULL)\n\t\t\t\tgoto nospace;\n            mbuf_setnext(n, temp);\n\t\t\tn = mbuf_next(n);\n\t\t\tmbuf_setlen(n, mbuf_get_mlen());\n\t\t\tif (left >= mbuf_get_minclsize()) {\n                mbuf_mclget(MBUF_DONTWAIT, mbuf_type(n), &n);\n\t\t\t\tif (mbuf_flags(n) & MBUF_EXT)\n\t\t\t\t\tmbuf_setlen(n, MCLBYTES);\n\t\t\t}\n\t\t\tif (mbuf_len(n) > left)\n                mbuf_setlen(n, left);\n\t\t\tnoff = 0;\n\t\t}\n\t\tlen = min(mbuf_len(m) - moff, mbuf_len(n) - noff);\n\n\t\trc4_crypt(&ctx->rc4, mtod(m, u_char*) + moff,\n\t\t    mtod(n, u_char*) + noff, len);\n\t\tcrc = ether_crc32_le_update(crc, mtod(n, const u_int8_t *) + noff, len);\n\n\t\tmoff += len;\n\t\tnoff += len;\n\t\tleft -= len;\n\t}\n\n\t/* decrypt ICV and compare it with calculated ICV */\n\tmbuf_copydata(m, moff, IEEE80211_WEP_CRCLEN, (caddr_t)&crc0);\n\trc4_crypt(&ctx->rc4, (u_char*)&crc0, (u_char*)&crc0,\n\t    IEEE80211_WEP_CRCLEN);\n\tcrc = ~crc;\n\tif (crc != letoh32(crc0)) {\n\t\tic->ic_stats.is_rx_decryptcrc++;\n\t\tmbuf_freem(m0);\n\t\tmbuf_freem(n0);\n\t\treturn NULL;\n\t}\n\n\tmbuf_freem(m0);\n\treturn n0;\n nospace:\n\tic->ic_stats.is_rx_nombuf++;\n\tmbuf_freem(m0);\n\tmbuf_freem(n0);\n\treturn NULL;\n}\n"
  },
  {
    "path": "itl80211/openbsd/net80211/ieee80211_input.c",
    "content": "/*\n * Copyright (C) 2020  钟先耀\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n */\n/*    $OpenBSD: ieee80211_input.c,v 1.235 2021/05/17 08:02:20 stsp Exp $    */\n\n/*-\n * Copyright (c) 2001 Atsushi Onoe\n * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting\n * Copyright (c) 2007-2009 Damien Bergamini\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. The name of the author may not be used to endorse or promote products\n *    derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <sys/param.h>\n#include <sys/systm.h>\n#include <sys/mbuf.h>\n#include <sys/malloc.h>\n#include <sys/kernel.h>\n#include <sys/socket.h>\n#include <sys/sockio.h>\n#include <sys/endian.h>\n#include <sys/errno.h>\n#include <sys/sysctl.h>\n\n#include <net/if.h>\n#include <net/if_dl.h>\n#include <net/if_media.h>\n#include <net/if_llc.h>\n\n#if NBPFILTER > 0\n#include <net/bpf.h>\n#endif\n\n#include <netinet/in.h>\n#include <netinet/if_ether.h>\n\n#include <net80211/ieee80211_var.h>\n#include <net80211/ieee80211_priv.h>\n\nmbuf_t ieee80211_input_hwdecrypt(struct ieee80211com *,\n                                 struct ieee80211_node *, mbuf_t,\n                                 struct ieee80211_rxinfo *rxi);\nmbuf_t ieee80211_defrag(struct ieee80211com *, mbuf_t, int);\nvoid    ieee80211_defrag_timeout(void *);\nvoid    ieee80211_input_ba(struct ieee80211com *, mbuf_t,\n                           struct ieee80211_node *, int, struct ieee80211_rxinfo *,\n                           struct mbuf_list *);\nvoid    ieee80211_input_ba_flush(struct ieee80211com *, struct ieee80211_node *,\n                                 struct ieee80211_rx_ba *, struct mbuf_list *);\nint\t   ieee80211_input_ba_gap_skip(struct ieee80211_rx_ba *);\nvoid    ieee80211_input_ba_gap_timeout(void *arg);\nvoid    ieee80211_ba_move_window(struct ieee80211com *,\n                                 struct ieee80211_node *, u_int8_t, u_int16_t, struct mbuf_list *);\nvoid    ieee80211_input_ba_seq(struct ieee80211com *,\n                               struct ieee80211_node *, uint8_t, uint16_t, struct mbuf_list *);\nmbuf_t ieee80211_align_mbuf(mbuf_t);\nvoid    ieee80211_decap(struct ieee80211com *, mbuf_t,\n                        struct ieee80211_node *, int, struct mbuf_list *);\nint    ieee80211_amsdu_decap_validate(struct ieee80211com *, mbuf_t,\n                                      struct ieee80211_node *);\nvoid    ieee80211_amsdu_decap(struct ieee80211com *, mbuf_t,\n                              struct ieee80211_node *, int, struct mbuf_list *);\nvoid    ieee80211_enqueue_data(struct ieee80211com *, mbuf_t*,\n                               struct ieee80211_node *, int, struct mbuf_list *);\nint    ieee80211_parse_edca_params_body(struct ieee80211com *,\n                                        const u_int8_t *);\nint    ieee80211_parse_edca_params(struct ieee80211com *, const u_int8_t *);\nint    ieee80211_parse_wmm_params(struct ieee80211com *, const u_int8_t *);\nenum    ieee80211_cipher ieee80211_parse_rsn_cipher(const u_int8_t[]);\nenum    ieee80211_akm ieee80211_parse_rsn_akm(const u_int8_t[]);\nint    ieee80211_parse_rsn_body(struct ieee80211com *, const u_int8_t *,\n                                u_int, struct ieee80211_rsnparams *);\nint    ieee80211_save_ie(const u_int8_t *, u_int8_t **);\nvoid    ieee80211_recv_probe_resp(struct ieee80211com *, mbuf_t,\n                                  struct ieee80211_node *, struct ieee80211_rxinfo *, int);\n#ifndef IEEE80211_STA_ONLY\nvoid    ieee80211_recv_probe_req(struct ieee80211com *, mbuf_t,\n                                 struct ieee80211_node *, struct ieee80211_rxinfo *);\n#endif\nvoid    ieee80211_recv_auth(struct ieee80211com *, mbuf_t,\n                            struct ieee80211_node *, struct ieee80211_rxinfo *);\n#ifndef IEEE80211_STA_ONLY\nvoid    ieee80211_recv_assoc_req(struct ieee80211com *, mbuf_t,\n                                 struct ieee80211_node *, struct ieee80211_rxinfo *, int);\n#endif\nvoid    ieee80211_recv_assoc_resp(struct ieee80211com *, mbuf_t,\n                                  struct ieee80211_node *, int);\nvoid    ieee80211_recv_deauth(struct ieee80211com *, mbuf_t,\n                              struct ieee80211_node *);\nvoid    ieee80211_recv_disassoc(struct ieee80211com *, mbuf_t,\n                                struct ieee80211_node *);\nvoid    ieee80211_recv_addba_req(struct ieee80211com *, mbuf_t,\n                                 struct ieee80211_node *);\nvoid    ieee80211_recv_addba_resp(struct ieee80211com *, mbuf_t,\n                                  struct ieee80211_node *);\nvoid    ieee80211_recv_delba(struct ieee80211com *, mbuf_t,\n                             struct ieee80211_node *);\nvoid    ieee80211_recv_sa_query_req(struct ieee80211com *, mbuf_t,\n                                    struct ieee80211_node *);\n#ifndef IEEE80211_STA_ONLY\nvoid    ieee80211_recv_sa_query_resp(struct ieee80211com *, mbuf_t,\n                                     struct ieee80211_node *);\n#endif\nvoid    ieee80211_recv_action(struct ieee80211com *, mbuf_t,\n                              struct ieee80211_node *);\n#ifndef IEEE80211_STA_ONLY\nvoid    ieee80211_recv_pspoll(struct ieee80211com *, mbuf_t,\n                              struct ieee80211_node *);\n#endif\nvoid    ieee80211_recv_bar(struct ieee80211com *, mbuf_t,\n                           struct ieee80211_node *);\nvoid    ieee80211_bar_tid(struct ieee80211com *, struct ieee80211_node *,\n                          u_int8_t, u_int16_t);\n\n\n/*\n * Retrieve the length in bytes of an 802.11 header.\n */\nu_int\nieee80211_get_hdrlen(const struct ieee80211_frame *wh)\n{\n    u_int size = sizeof(*wh);\n    \n    /* NB: does not work with control frames */\n    _KASSERT(ieee80211_has_seq(wh));\n    \n    if (ieee80211_has_addr4(wh))\n        size += IEEE80211_ADDR_LEN;    /* i_addr4 */\n    if (ieee80211_has_qos(wh))\n        size += sizeof(u_int16_t);    /* i_qos */\n    if (ieee80211_has_htc(wh))\n        size += sizeof(u_int32_t);    /* i_ht */\n    return size;\n}\n\n/* Post-processing for drivers which perform decryption in hardware. */\nmbuf_t\nieee80211_input_hwdecrypt(struct ieee80211com *ic, struct ieee80211_node *ni,\n    mbuf_t m, struct ieee80211_rxinfo *rxi)\n{\n   struct ieee80211_key *k;\n   struct ieee80211_frame *wh;\n   uint64_t pn, *prsc;\n   int hdrlen;\n\n   k = ieee80211_get_rxkey(ic, m, ni);\n   if (k == NULL)\n       return NULL;\n\n   wh = mtod(m, struct ieee80211_frame *);\n   hdrlen = ieee80211_get_hdrlen(wh);\n\n   /*\n    * Update the last-seen packet number (PN) for drivers using hardware\n    * crypto offloading. This cannot be done by drivers because A-MPDU\n    * reordering needs to occur before a valid lower bound can be\n    * determined for the PN. Drivers will read the PN we write here and\n    * are expected to discard replayed frames based on it.\n    * Drivers are expected to leave the IV of decrypted frames intact\n    * so we can update the last-seen PN and strip the IV here.\n    */\n   switch (k->k_cipher) {\n   case IEEE80211_CIPHER_CCMP:\n       if (!(wh->i_fc[1] & IEEE80211_FC1_PROTECTED)) {\n           /*\n            * If the protected bit is clear then hardware has\n            * stripped the IV and we must trust that it handles\n            * replay detection correctly.\n            */\n           break;\n       }\n           if (ieee80211_ccmp_get_pn(&pn, &prsc, m, k) != 0)\n               return NULL;\n           if (rxi->rxi_flags & IEEE80211_RXI_HWDEC_SAME_PN) {\n               if (pn < *prsc) {\n                   ic->ic_stats.is_ccmp_replays++;\n                   return NULL;\n               }\n           } else if (pn <= *prsc) {\n               ic->ic_stats.is_ccmp_replays++;\n               return NULL;\n           }\n\n       /* Update last-seen packet number. */\n       *prsc = pn;\n\n       /* Clear Protected bit and strip IV. */\n       wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED;\n       memmove(mtod(m, caddr_t) + IEEE80211_CCMP_HDRLEN, wh, hdrlen);\n       mbuf_adj(m, IEEE80211_CCMP_HDRLEN);\n       /* Drivers are expected to strip the MIC. */\n       break;\n    case IEEE80211_CIPHER_TKIP:\n       if (!(wh->i_fc[1] & IEEE80211_FC1_PROTECTED)) {\n           /*\n            * If the protected bit is clear then hardware has\n            * stripped the IV and we must trust that it handles\n            * replay detection correctly.\n            */\n           break;\n       }\n       if (ieee80211_tkip_get_tsc(&pn, &prsc, m, k) != 0)\n           return NULL;\n\n       if (rxi->rxi_flags & IEEE80211_RXI_HWDEC_SAME_PN) {\n           if (pn < *prsc) {\n               ic->ic_stats.is_tkip_replays++;\n               return NULL;\n               }\n           } else if (pn <= *prsc) {\n           ic->ic_stats.is_tkip_replays++;\n           return NULL;\n       }\n\n       /* Update last-seen packet number. */\n       *prsc = pn;\n\n       /* Clear Protected bit and strip IV. */\n       wh = mtod(m, struct ieee80211_frame *);\n       wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED;\n       memmove(mtod(m, caddr_t) + IEEE80211_TKIP_HDRLEN, wh, hdrlen);\n       mbuf_adj(m, IEEE80211_TKIP_HDRLEN);\n       /* Drivers are expected to strip the MIC. */\n       break;\n   default:\n       break;\n   }\n\n   return m;\n}\n\n/*\n * Process a received frame.  The node associated with the sender\n * should be supplied.  If nothing was found in the node table then\n * the caller is assumed to supply a reference to ic_bss instead.\n * The RSSI and a timestamp are also supplied.  The RSSI data is used\n * during AP scanning to select a AP to associate with; it can have\n * any units so long as values have consistent units and higher values\n * mean ``better signal''.  The receive timestamp is currently not used\n * by the 802.11 layer.\n *\n * This function acts on management frames immediately and queues data frames\n * on the specified mbuf list. Delivery of queued data frames to upper layers\n * must be triggered with if_input(). Drivers should call if_input() only once\n * per Rx interrupt to avoid triggering the input ifq pressure drop mechanism\n * unnecessarily.\n */\nvoid\nieee80211_inputm(struct _ifnet *ifp, mbuf_t m, struct ieee80211_node *ni,\n                 struct ieee80211_rxinfo *rxi, struct mbuf_list *ml)\n{\n    struct ieee80211com *ic = (struct ieee80211com *)ifp;\n    struct ieee80211_frame *wh;\n    u_int16_t *orxseq, nrxseq, qos;\n    u_int8_t dir, type, subtype, tid;\n    int hdrlen, hasqos;\n    \n    _KASSERT(ni != NULL);\n    \n    /* in monitor mode, send everything directly to bpf */\n    if (ic->ic_opmode == IEEE80211_M_MONITOR)\n        goto out;\n    \n    /*\n     * Do not process frames without an Address 2 field any further.\n     * Only CTS and ACK control frames do not have this field.\n     */\n    if (mbuf_len(m) < sizeof(struct ieee80211_frame_min)) {\n        DPRINTF((\"frame too short, len %u\\n\", mbuf_len(m)));\n        ic->ic_stats.is_rx_tooshort++;\n        goto out;\n    }\n    \n    wh = mtod(m, struct ieee80211_frame *);\n    if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) !=\n        IEEE80211_FC0_VERSION_0) {\n        DPRINTF((\"frame with wrong version: %x\\n\", wh->i_fc[0]));\n        ic->ic_stats.is_rx_badversion++;\n        goto err;\n    }\n    \n    dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK;\n    type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;\n    subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;\n    \n    if (type != IEEE80211_FC0_TYPE_CTL) {\n        hdrlen = ieee80211_get_hdrlen(wh);\n        if (mbuf_len(m) < hdrlen) {\n            DPRINTF((\"frame too short, len %u\\n\", mbuf_len(m)));\n            ic->ic_stats.is_rx_tooshort++;\n            goto err;\n        }\n    } else\n        hdrlen = 0;\n    if ((hasqos = ieee80211_has_qos(wh))) {\n        qos = ieee80211_get_qos(wh);\n        tid = qos & IEEE80211_QOS_TID;\n    } else {\n        qos = 0;\n        tid = 0;\n    }\n    \n    if (ic->ic_state == IEEE80211_S_RUN &&\n        type == IEEE80211_FC0_TYPE_DATA && hasqos &&\n        (subtype & IEEE80211_FC0_SUBTYPE_NODATA) == 0 &&\n        !(rxi->rxi_flags & IEEE80211_RXI_AMPDU_DONE)\n#ifndef IEEE80211_STA_ONLY\n        && (ic->ic_opmode == IEEE80211_M_STA || ni != ic->ic_bss)\n#endif\n        ) {\n        int ba_state = ni->ni_rx_ba[tid].ba_state;\n        \n#ifndef IEEE80211_STA_ONLY\n        if (ic->ic_opmode == IEEE80211_M_HOSTAP) {\n            if (!IEEE80211_ADDR_EQ(wh->i_addr1,\n                                   ic->ic_bss->ni_bssid)) {\n                ic->ic_stats.is_rx_wrongbss++;\n                goto err;\n            }\n            if (ni->ni_state != IEEE80211_S_ASSOC) {\n                ic->ic_stats.is_rx_notassoc++;\n                goto err;\n            }\n        }\n#endif\n        /*\n         * If Block Ack was explicitly requested, check\n         * if we have a BA agreement for this RA/TID.\n         */\n        if ((qos & IEEE80211_QOS_ACK_POLICY_MASK) ==\n            IEEE80211_QOS_ACK_POLICY_BA &&\n            ba_state != IEEE80211_BA_AGREED) {\n            DPRINTF((\"no BA agreement for %s, TID %d\\n\",\n                     ether_sprintf(ni->ni_macaddr), tid));\n            /* send a DELBA with reason code UNKNOWN-BA */\n            IEEE80211_SEND_ACTION(ic, ni,\n                                  IEEE80211_CATEG_BA, IEEE80211_ACTION_DELBA,\n                                  IEEE80211_REASON_SETUP_REQUIRED << 16 | tid);\n            goto err;\n        }\n        \n        /*\n         * Check if we have an explicit or implicit\n         * Block Ack Request for a valid BA agreement.\n         */\n        if (ba_state == IEEE80211_BA_AGREED &&\n            ((qos & IEEE80211_QOS_ACK_POLICY_MASK) ==\n             IEEE80211_QOS_ACK_POLICY_BA ||\n             (qos & IEEE80211_QOS_ACK_POLICY_MASK) ==\n             IEEE80211_QOS_ACK_POLICY_NORMAL)) {\n            /* go through A-MPDU reordering */\n            ieee80211_input_ba(ic, m, ni, tid, rxi, ml);\n            return;    /* don't free m! */\n        } else if (ba_state == IEEE80211_BA_REQUESTED &&\n            (qos & IEEE80211_QOS_ACK_POLICY_MASK) ==\n            IEEE80211_QOS_ACK_POLICY_NORMAL) {\n            /*\n             * Apparently, qos frames for a tid where a\n             * block ack agreement was requested but not\n             * yet confirmed by us should still contribute\n             * to the sequence number for this tid.\n             */\n            ieee80211_input_ba(ic, m, ni, tid, rxi, ml);\n            return;    /* don't free m! */\n        }\n    }\n    \n    /*\n     * We do not yet support fragments. Drop any fragmented packets.\n     * Counter-measure against attacks where an arbitrary packet is\n     * injected via a fragment with attacker-controlled content.\n     * See https://papers.mathyvanhoef.com/usenix2021.pdf\n     * Section 6.8 \"Treating fragments as full frames\"\n     */\n    if (ieee80211_has_seq(wh)) {\n        uint16_t rxseq = letoh16(*(const u_int16_t *)wh->i_seq);\n        if ((wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG) ||\n            (rxseq & IEEE80211_SEQ_FRAG_MASK))\n            goto err;\n    }\n    \n    /* duplicate detection (see 9.2.9) */\n    if (ieee80211_has_seq(wh) &&\n        ic->ic_state != IEEE80211_S_SCAN) {\n        nrxseq = letoh16(*(u_int16_t *)wh->i_seq) >>\n        IEEE80211_SEQ_SEQ_SHIFT;\n        if (hasqos)\n            orxseq = &ni->ni_qos_rxseqs[tid];\n        else\n            orxseq = &ni->ni_rxseq;\n        if (rxi->rxi_flags & IEEE80211_RXI_SAME_SEQ) {\n            if (nrxseq != *orxseq) {\n                /* duplicate, silently discarded */\n                ic->ic_stats.is_rx_dup++;\n                goto out;\n            }\n        } else if ((wh->i_fc[1] & IEEE80211_FC1_RETRY) &&\n                   nrxseq == *orxseq) {\n            /* duplicate, silently discarded */\n            ic->ic_stats.is_rx_dup++;\n            goto out;\n        }\n        *orxseq = nrxseq;\n    }\n    if (ic->ic_state > IEEE80211_S_SCAN) {\n        ni->ni_rssi = rxi->rxi_rssi;\n        ni->ni_rstamp = rxi->rxi_tstamp;\n        ni->ni_inact = 0;\n        \n        if (ic->ic_state == IEEE80211_S_RUN && ic->ic_bgscan_start) {\n            /* Cancel or start background scan based on RSSI. */\n            if ((*ic->ic_node_checkrssi)(ic, ni))\n                timeout_del(&ic->ic_bgscan_timeout);\n            else if (!timeout_pending(&ic->ic_bgscan_timeout) &&\n                     (ic->ic_flags & IEEE80211_F_BGSCAN) == 0 &&\n                     (ic->ic_flags & IEEE80211_F_DESBSSID) == 0)\n                timeout_add_msec(&ic->ic_bgscan_timeout,\n                                 500 * (ic->ic_bgscan_fail + 1));\n        }\n    }\n    \n#ifndef IEEE80211_STA_ONLY\n    if (ic->ic_opmode == IEEE80211_M_HOSTAP &&\n        (ic->ic_caps & IEEE80211_C_APPMGT) &&\n        ni->ni_state == IEEE80211_STA_ASSOC) {\n        if (wh->i_fc[1] & IEEE80211_FC1_PWR_MGT) {\n            if (ni->ni_pwrsave == IEEE80211_PS_AWAKE) {\n                /* turn on PS mode */\n                ni->ni_pwrsave = IEEE80211_PS_DOZE;\n                DPRINTF((\"PS mode on for %s\\n\",\n                         ether_sprintf(wh->i_addr2)));\n            }\n        } else if (ni->ni_pwrsave == IEEE80211_PS_DOZE) {\n            mbuf_t m;\n            \n            /* turn off PS mode */\n            ni->ni_pwrsave = IEEE80211_PS_AWAKE;\n            DPRINTF((\"PS mode off for %s\\n\",\n                     ether_sprintf(wh->i_addr2)));\n            \n            (*ic->ic_set_tim)(ic, ni->ni_associd, 0);\n            \n            /* dequeue buffered unicast frames */\n            while ((m = mq_dequeue(&ni->ni_savedq)) != NULL) {\n                mq_enqueue(&ic->ic_pwrsaveq, m);\n                ifp->if_start(ifp);\n            }\n        }\n    }\n#endif\n    switch (type) {\n        case IEEE80211_FC0_TYPE_DATA:\n            switch (ic->ic_opmode) {\n                case IEEE80211_M_STA:\n                    if (dir != IEEE80211_FC1_DIR_FROMDS) {\n                        ic->ic_stats.is_rx_wrongdir++;\n                        goto out;\n                    }\n                    if (ic->ic_state != IEEE80211_S_SCAN &&\n                        !IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_bssid)) {\n                        /* Source address is not our BSS. */\n                        DPRINTF((\"discard frame from SA %s\\n\",\n                                 ether_sprintf(wh->i_addr2)));\n                        ic->ic_stats.is_rx_wrongbss++;\n                        goto out;\n                    }\n                    if ((ifp->if_flags & IFF_SIMPLEX) &&\n                        IEEE80211_IS_MULTICAST(wh->i_addr1) &&\n                        IEEE80211_ADDR_EQ(wh->i_addr3, ic->ic_myaddr)) {\n                        /*\n                         * In IEEE802.11 network, multicast frame\n                         * sent from me is broadcasted from AP.\n                         * It should be silently discarded for\n                         * SIMPLEX interface.\n                         */\n                        ic->ic_stats.is_rx_mcastecho++;\n                        goto out;\n                    }\n                    break;\n#ifndef IEEE80211_STA_ONLY\n                case IEEE80211_M_IBSS:\n                case IEEE80211_M_AHDEMO:\n                    if (dir != IEEE80211_FC1_DIR_NODS) {\n                        ic->ic_stats.is_rx_wrongdir++;\n                        goto out;\n                    }\n                    if (ic->ic_state != IEEE80211_S_SCAN &&\n                        !IEEE80211_ADDR_EQ(wh->i_addr3,\n                                           ic->ic_bss->ni_bssid) &&\n                        !IEEE80211_ADDR_EQ(wh->i_addr3,\n                                           etherbroadcastaddr)) {\n                        /* Destination is not our BSS or broadcast. */\n                        DPRINTF((\"discard data frame to DA %s\\n\",\n                                 ether_sprintf(wh->i_addr3)));\n                        ic->ic_stats.is_rx_wrongbss++;\n                        goto out;\n                    }\n                    break;\n                case IEEE80211_M_HOSTAP:\n                    if (dir != IEEE80211_FC1_DIR_TODS) {\n                        ic->ic_stats.is_rx_wrongdir++;\n                        goto out;\n                    }\n                    if (ic->ic_state != IEEE80211_S_SCAN &&\n                        !IEEE80211_ADDR_EQ(wh->i_addr1,\n                                           ic->ic_bss->ni_bssid) &&\n                        !IEEE80211_ADDR_EQ(wh->i_addr1,\n                                           etherbroadcastaddr)) {\n                        /* BSS is not us or broadcast. */\n                        DPRINTF((\"discard data frame to BSS %s\\n\",\n                                 ether_sprintf(wh->i_addr1)));\n                        ic->ic_stats.is_rx_wrongbss++;\n                        goto out;\n                    }\n                    /* check if source STA is associated */\n                    if (ni == ic->ic_bss) {\n                        DPRINTF((\"data from unknown src %s\\n\",\n                                 ether_sprintf(wh->i_addr2)));\n                        /* NB: caller deals with reference */\n                        ni = ieee80211_find_node(ic, wh->i_addr2);\n                        if (ni == NULL)\n                            ni = ieee80211_dup_bss(ic, wh->i_addr2);\n                        if (ni != NULL) {\n                            IEEE80211_SEND_MGMT(ic, ni,\n                                                IEEE80211_FC0_SUBTYPE_DEAUTH,\n                                                IEEE80211_REASON_NOT_AUTHED);\n                        }\n                        ic->ic_stats.is_rx_notassoc++;\n                        goto err;\n                    }\n                    if (ni->ni_state != IEEE80211_STA_ASSOC) {\n                        DPRINTF((\"data from unassoc src %s\\n\",\n                                 ether_sprintf(wh->i_addr2)));\n                        IEEE80211_SEND_MGMT(ic, ni,\n                                            IEEE80211_FC0_SUBTYPE_DISASSOC,\n                                            IEEE80211_REASON_NOT_ASSOCED);\n                        ic->ic_stats.is_rx_notassoc++;\n                        goto err;\n                    }\n                    break;\n#endif    /* IEEE80211_STA_ONLY */\n                default:\n                    /* can't get there */\n                    goto out;\n            }\n            \n            /* Do not process \"no data\" frames any further. */\n            if (subtype & IEEE80211_FC0_SUBTYPE_NODATA) {\n#if NBPFILTER > 0\n                if (ic->ic_rawbpf)\n                    bpf_mtap(ic->ic_rawbpf, m, BPF_DIRECTION_IN);\n#endif\n                goto out;\n            }\n            \n            if ((ic->ic_flags & IEEE80211_F_WEPON) ||\n                ((ic->ic_flags & IEEE80211_F_RSNON) &&\n                 (ni->ni_flags & IEEE80211_NODE_RXPROT))) {\n                /* protection is on for Rx */\n                if (!(rxi->rxi_flags & IEEE80211_RXI_HWDEC)) {\n                    if (!(wh->i_fc[1] & IEEE80211_FC1_PROTECTED)) {\n                        /* drop unencrypted */\n                        ic->ic_stats.is_rx_unencrypted++;\n                        goto err;\n                    }\n                    /* do software decryption */\n                    m = ieee80211_decrypt(ic, m, ni);\n                    if (m == NULL) {\n                        ic->ic_stats.is_rx_wepfail++;\n                        goto err;\n                    }\n                } else {\n                    m = ieee80211_input_hwdecrypt(ic, ni, m, rxi);\n                    if (m == NULL)\n                        goto err;\n                }\n                wh = mtod(m, struct ieee80211_frame *);\n            } else if ((wh->i_fc[1] & IEEE80211_FC1_PROTECTED) ||\n                       (rxi->rxi_flags & IEEE80211_RXI_HWDEC)) {\n                /* frame encrypted but protection off for Rx */\n                ic->ic_stats.is_rx_nowep++;\n                goto out;\n            }\n            \n#if NBPFILTER > 0\n            /* copy to listener after decrypt */\n            if (ic->ic_rawbpf)\n                bpf_mtap(ic->ic_rawbpf, m, BPF_DIRECTION_IN);\n#endif\n            \n            if ((ni->ni_flags & IEEE80211_NODE_HT) &&\n                hasqos && (qos & IEEE80211_QOS_AMSDU))\n                ieee80211_amsdu_decap(ic, m, ni, hdrlen, ml);\n            else\n                ieee80211_decap(ic, m, ni, hdrlen, ml);\n            return;\n            \n        case IEEE80211_FC0_TYPE_MGT:\n            if (dir != IEEE80211_FC1_DIR_NODS) {\n                ic->ic_stats.is_rx_wrongdir++;\n                goto err;\n            }\n#ifndef IEEE80211_STA_ONLY\n            if (ic->ic_opmode == IEEE80211_M_AHDEMO) {\n                ic->ic_stats.is_rx_ahdemo_mgt++;\n                goto out;\n            }\n#endif\n            /* drop frames without interest */\n            if (ic->ic_state == IEEE80211_S_SCAN) {\n                if (subtype != IEEE80211_FC0_SUBTYPE_BEACON &&\n                    subtype != IEEE80211_FC0_SUBTYPE_PROBE_RESP) {\n                    ic->ic_stats.is_rx_mgtdiscard++;\n                    goto out;\n                }\n            }\n            \n            if (ni->ni_flags & IEEE80211_NODE_RXMGMTPROT) {\n                /* MMPDU protection is on for Rx */\n                if (subtype == IEEE80211_FC0_SUBTYPE_DISASSOC ||\n                    subtype == IEEE80211_FC0_SUBTYPE_DEAUTH ||\n                    subtype == IEEE80211_FC0_SUBTYPE_ACTION) {\n                    if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&\n                        !(wh->i_fc[1] & IEEE80211_FC1_PROTECTED)) {\n                        /* unicast mgmt not encrypted */\n                        goto out;\n                    }\n                    /* do software decryption */\n                    m = ieee80211_decrypt(ic, m, ni);\n                    if (m == NULL) {\n                        /* XXX stats */\n                        goto out;\n                    }\n                    wh = mtod(m, struct ieee80211_frame *);\n                }\n            } else if ((ic->ic_flags & IEEE80211_F_RSNON) &&\n                       (wh->i_fc[1] & IEEE80211_FC1_PROTECTED)) {\n                /* encrypted but MMPDU Rx protection off for TA */\n                goto out;\n            }\n            \n#if NBPFILTER > 0\n            if (bpf_mtap(ic->ic_rawbpf, m, BPF_DIRECTION_IN) != 0) {\n                /*\n                 * Drop mbuf if it was filtered by bpf. Normally,\n                 * this is done in ether_input() but IEEE 802.11\n                 * management frames are a special case.\n                 */\n                mbuf_freem(m);\n                return;\n            }\n#endif\n            (*ic->ic_recv_mgmt)(ic, m, ni, rxi, subtype);\n            mbuf_freem(m);\n            return;\n            \n        case IEEE80211_FC0_TYPE_CTL:\n            switch (subtype) {\n#ifndef IEEE80211_STA_ONLY\n                case IEEE80211_FC0_SUBTYPE_PS_POLL:\n                    ieee80211_recv_pspoll(ic, m, ni);\n                    break;\n#endif\n                case IEEE80211_FC0_SUBTYPE_BAR:\n                    ieee80211_recv_bar(ic, m, ni);\n                    break;\n                default:\n                    ic->ic_stats.is_rx_ctl++;\n                    break;\n            }\n            goto out;\n            \n        default:\n            DPRINTF((\"bad frame type %x\\n\", type));\n            /* should not come here */\n            break;\n    }\nerr:\n    ifp->netStat->inputErrors++;\nout:\n    if (m != NULL) {\n#if NBPFILTER > 0\n        if (ic->ic_rawbpf)\n            bpf_mtap(ic->ic_rawbpf, m, BPF_DIRECTION_IN);\n#endif\n        mbuf_freem(m);\n    }\n}\n\n/* Input handler for drivers which only receive one frame per interrupt. */\nvoid\nieee80211_input(struct _ifnet *ifp, mbuf_t m, struct ieee80211_node *ni,\n                struct ieee80211_rxinfo *rxi)\n{\n    struct mbuf_list ml = MBUF_LIST_INITIALIZER();\n    \n    ieee80211_inputm(ifp, m, ni, rxi, &ml);\n    if_input(ifp, &ml);\n}\n\n#ifdef notyet\n/*\n * Handle defragmentation (see 9.5 and Annex C).  We support the concurrent\n * reception of fragments of three fragmented MSDUs or MMPDUs.\n */\nmbuf_t\nieee80211_defrag(struct ieee80211com *ic, mbuf_t m, int hdrlen)\n{\n    const struct ieee80211_frame *owh, *wh;\n    struct ieee80211_defrag *df;\n    u_int16_t rxseq, seq;\n    u_int8_t frag;\n    int i;\n    \n    wh = mtod(m, struct ieee80211_frame *);\n    rxseq = letoh16(*(const u_int16_t *)wh->i_seq);\n    seq = rxseq >> IEEE80211_SEQ_SEQ_SHIFT;\n    frag = rxseq & IEEE80211_SEQ_FRAG_MASK;\n    \n    if (frag == 0 && !(wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG))\n        return m;\t/* not fragmented */\n    \n    if (frag == 0) {\n        /* first fragment, setup entry in the fragment cache */\n        if (++ic->ic_defrag_cur == IEEE80211_DEFRAG_SIZE)\n            ic->ic_defrag_cur = 0;\n        df = &ic->ic_defrag[ic->ic_defrag_cur];\n        mbuf_freem(df->df_m);\t/* discard old entry */\n        df->df_seq = seq;\n        df->df_frag = 0;\n        df->df_m = m;\n        /* start receive MSDU timer of aMaxReceiveLifetime */\n        timeout_add_sec(&df->df_to, 1);\n        return NULL;\t/* MSDU or MMPDU not yet complete */\n    }\n    \n    /* find matching entry in the fragment cache */\n    for (i = 0; i < IEEE80211_DEFRAG_SIZE; i++) {\n        df = &ic->ic_defrag[i];\n        if (df->df_m == NULL)\n            continue;\n        if (df->df_seq != seq || df->df_frag + 1 != frag)\n            continue;\n        owh = mtod(df->df_m, struct ieee80211_frame *);\n        /* frame type, source and destination must match */\n        if (((wh->i_fc[0] ^ owh->i_fc[0]) & IEEE80211_FC0_TYPE_MASK) ||\n            !IEEE80211_ADDR_EQ(wh->i_addr1, owh->i_addr1) ||\n            !IEEE80211_ADDR_EQ(wh->i_addr2, owh->i_addr2))\n            continue;\n        /* matching entry found */\n        break;\n    }\n    if (i == IEEE80211_DEFRAG_SIZE) {\n        /* no matching entry found, discard fragment */\n        ic->ic_if.netStat->inputErrors++;\n        mbuf_freem(m);\n        return NULL;\n    }\n    \n    df->df_frag = frag;\n    /* strip 802.11 header and concatenate fragment */\n    mbuf_adj(m, hdrlen);\n    m_cat(df->df_m, m);\n    mbuf_pkthdr_setlen(df->df_m, mbuf_pkthdr_len(df->df_m) + mbuf_pkthdr_len(m));\n    \n    if (wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG)\n        return NULL;\t/* MSDU or MMPDU not yet complete */\n    \n    /* MSDU or MMPDU complete */\n    timeout_del(&df->df_to);\n    m = df->df_m;\n    df->df_m = NULL;\n    return m;\n}\n\n/*\n * Receive MSDU defragmentation timer exceeds aMaxReceiveLifetime.\n */\nvoid\nieee80211_defrag_timeout(void *arg)\n{\n    struct ieee80211_defrag *df = (struct ieee80211_defrag *)arg;\n    int s = splnet();\n    \n    /* discard all received fragments */\n    mbuf_freem(df->df_m);\n    df->df_m = NULL;\n    \n    splx(s);\n}\n#endif\n\n/*\n * Process a received data MPDU related to a specific HT-immediate Block Ack\n * agreement (see 9.10.7.6).\n */\nvoid\nieee80211_input_ba(struct ieee80211com *ic, mbuf_t m,\n                   struct ieee80211_node *ni, int tid, struct ieee80211_rxinfo *rxi,\n                   struct mbuf_list *ml)\n{\n    struct _ifnet *ifp = &ic->ic_if;\n    struct ieee80211_rx_ba *ba = &ni->ni_rx_ba[tid];\n    struct ieee80211_frame *wh;\n    int idx, count;\n    u_int16_t sn;\n    \n    wh = mtod(m, struct ieee80211_frame *);\n    sn = letoh16(*(u_int16_t *)wh->i_seq) >> IEEE80211_SEQ_SEQ_SHIFT;\n    \n    /* reset Block Ack inactivity timer */\n    if (ba->ba_timeout_val != 0)\n        timeout_add_usec(&ba->ba_to, ba->ba_timeout_val);\n    \n    if (SEQ_LT(sn, ba->ba_winstart)) {\t/* SN < WinStartB */\n        ic->ic_stats.is_ht_rx_frame_below_ba_winstart++;\n        mbuf_freem(m);\t/* discard the MPDU */\n        return;\n    }\n    if (ba->ba_buf == NULL) {\n        XYLog(\"SEVERE !!!! %s %d ba->ba_buf == NULL\\n\", __FUNCTION__, __LINE__);\n        ifp->netStat->inputErrors++;\n        ic->ic_stats.is_ht_rx_ba_no_buf++;\n        mbuf_freem(m);\n        return;\n    }\n    if (SEQ_LT(ba->ba_winend, sn)) {\t/* WinEndB < SN */\n        ic->ic_stats.is_ht_rx_frame_above_ba_winend++;\n        count = (sn - ba->ba_winend) & 0xfff;\n        if (count > ba->ba_winsize) {\n            /*\n             * Check whether we're consistently behind the window,\n             * and let the window move forward if neccessary.\n             */\n            if (ba->ba_winmiss < IEEE80211_BA_MAX_WINMISS) {\n                if (ba->ba_missedsn == ((sn - 1) & 0xfff))\n                    ba->ba_winmiss++;\n                else\n                    ba->ba_winmiss = 0;\n                ba->ba_missedsn = sn;\n                ifp->netStat->inputErrors++;\n                mbuf_freem(m);\t/* discard the MPDU */\n                return;\n            }\n            \n            /* It appears the window has moved for real. */\n            ic->ic_stats.is_ht_rx_ba_window_jump++;\n            ba->ba_winmiss = 0;\n            ba->ba_missedsn = 0;\n            ieee80211_ba_move_window(ic, ni, tid, sn, ml);\n        } else {\n            ic->ic_stats.is_ht_rx_ba_window_slide++;\n            ieee80211_input_ba_seq(ic, ni, tid,\n                                   (ba->ba_winstart + count) & 0xfff, ml);\n            ieee80211_input_ba_flush(ic, ni, ba, ml);\n        }\n    }\n    /* WinStartB <= SN <= WinEndB */\n    \n    ba->ba_winmiss = 0;\n    ba->ba_missedsn = 0;\n    idx = (sn - ba->ba_winstart) & 0xfff;\n    idx = (ba->ba_head + idx) % IEEE80211_BA_MAX_WINSZ;\n    /* store the received MPDU in the buffer */\n    if (ba->ba_buf[idx].m != NULL) {\n        ifp->netStat->inputErrors++;\n        ic->ic_stats.is_ht_rx_ba_no_buf++;\n        mbuf_freem(m);\n        return;\n    }\n    ba->ba_buf[idx].m = m;\n    /* store Rx meta-data too */\n    rxi->rxi_flags |= IEEE80211_RXI_AMPDU_DONE;\n    ba->ba_buf[idx].rxi = *rxi;\n    ba->ba_gapwait++;\n\n    if (ba->ba_buf[ba->ba_head].m == NULL && ba->ba_gapwait == 1)\n        timeout_add_msec(&ba->ba_gap_to, IEEE80211_BA_GAP_TIMEOUT);\n    \n    ieee80211_input_ba_flush(ic, ni, ba, ml);\n}\n\n/* \n * Forward buffered frames with sequence number lower than max_seq.\n * See 802.11-2012 9.21.7.6.2 b.\n */\nvoid\nieee80211_input_ba_seq(struct ieee80211com *ic, struct ieee80211_node *ni,\n                       uint8_t tid, uint16_t max_seq, struct mbuf_list *ml)\n{\n    struct _ifnet *ifp = &ic->ic_if;\n    struct ieee80211_rx_ba *ba = &ni->ni_rx_ba[tid];\n    struct ieee80211_frame *wh;\n    uint16_t seq;\n    int i = 0;\n    \n    while (i++ < ba->ba_winsize) {\n        /* gaps may exist */\n        if (ba->ba_buf[ba->ba_head].m != NULL) {\n            wh = mtod(ba->ba_buf[ba->ba_head].m,\n                      struct ieee80211_frame *);\n            _KASSERT(ieee80211_has_seq(wh));\n            seq = letoh16(*(u_int16_t *)wh->i_seq) >>\n            IEEE80211_SEQ_SEQ_SHIFT;\n            if (!SEQ_LT(seq, max_seq))\n                break;\n            ieee80211_inputm(ifp, ba->ba_buf[ba->ba_head].m,\n                             ni, &ba->ba_buf[ba->ba_head].rxi, ml);\n            ba->ba_buf[ba->ba_head].m = NULL;\n            ba->ba_gapwait--;\n        } else\n            ic->ic_stats.is_ht_rx_ba_frame_lost++;\n        ba->ba_head = (ba->ba_head + 1) % IEEE80211_BA_MAX_WINSZ;\n        /* move window forward */\n        ba->ba_winstart = (ba->ba_winstart + 1) & 0xfff;\n    }\n    ba->ba_winend = (ba->ba_winstart + ba->ba_winsize - 1) & 0xfff;\n}\n\n/* Flush a consecutive sequence of frames from the reorder buffer. */\nvoid\nieee80211_input_ba_flush(struct ieee80211com *ic, struct ieee80211_node *ni,\n                         struct ieee80211_rx_ba *ba, struct mbuf_list *ml)\n\n{\n    struct _ifnet *ifp = &ic->ic_if;\n    \n    /* Do not re-arm the gap timeout if we made no progress. */\n    if (ba->ba_buf[ba->ba_head].m == NULL)\n        return;\n    \n    /* pass reordered MPDUs up to the next MAC process */\n    while (ba->ba_buf[ba->ba_head].m != NULL) {\n        ieee80211_inputm(ifp, ba->ba_buf[ba->ba_head].m, ni,\n                         &ba->ba_buf[ba->ba_head].rxi, ml);\n        ba->ba_buf[ba->ba_head].m = NULL;\n        ba->ba_gapwait--;\n        \n        ba->ba_head = (ba->ba_head + 1) % IEEE80211_BA_MAX_WINSZ;\n        /* move window forward */\n        ba->ba_winstart = (ba->ba_winstart + 1) & 0xfff;\n    }\n    ba->ba_winend = (ba->ba_winstart + ba->ba_winsize - 1) & 0xfff;\n    \n    if (timeout_pending(&ba->ba_gap_to))\n        timeout_del(&ba->ba_gap_to);\n    if (ba->ba_gapwait)\n        timeout_add_msec(&ba->ba_gap_to, IEEE80211_BA_GAP_TIMEOUT);\n}\n\n/* \n * Forcibly move the BA window forward to remove a leading gap which has\n * been causing frames to linger in the reordering buffer for too long.\n * A leading gap will occur if a particular A-MPDU subframe never arrives\n * or if a bug in the sender causes sequence numbers to jump forward by > 1.\n */\nint\nieee80211_input_ba_gap_skip(struct ieee80211_rx_ba *ba)\n{\n    int skipped = 0;\n\n    while (skipped < ba->ba_winsize && ba->ba_buf[ba->ba_head].m == NULL) {\n        /* move window forward */\n        ba->ba_head = (ba->ba_head + 1) % IEEE80211_BA_MAX_WINSZ;\n        ba->ba_winstart = (ba->ba_winstart + 1) & 0xfff;\n        skipped++;\n    }\n    if (skipped > 0)\n        ba->ba_winend = (ba->ba_winstart + ba->ba_winsize - 1) & 0xfff;\n\n    return skipped;\n}\n\nvoid\nieee80211_input_ba_gap_timeout(void *arg)\n{\n    struct ieee80211_rx_ba *ba = (struct ieee80211_rx_ba *)arg;\n    struct ieee80211_node *ni = ba->ba_ni;\n    struct ieee80211com *ic = ni->ni_ic;\n    int s, skipped;\n    \n    ic->ic_stats.is_ht_rx_ba_window_gap_timeout++;\n    \n    s = splnet();\n    \n    skipped = ieee80211_input_ba_gap_skip(ba);\n    ic->ic_stats.is_ht_rx_ba_frame_lost += skipped;\n    if (skipped) {\n        struct mbuf_list ml = MBUF_LIST_INITIALIZER();\n        ieee80211_input_ba_flush(ic, ni, ba, &ml);\n        if_input(&ic->ic_if, &ml);\n    }\n    \n    splx(s);\n}\n\n\n/*\n * Change the value of WinStartB (move window forward) upon reception of a\n * BlockAckReq frame or an ADDBA Request (PBAC).\n */\nvoid\nieee80211_ba_move_window(struct ieee80211com *ic, struct ieee80211_node *ni,\n                         u_int8_t tid, u_int16_t ssn, struct mbuf_list *ml)\n{\n    struct _ifnet *ifp = &ic->ic_if;\n    struct ieee80211_rx_ba *ba = &ni->ni_rx_ba[tid];\n    int count;\n    \n    /* assert(WinStartB <= SSN) */\n    \n    count = (ssn - ba->ba_winstart) & 0xfff;\n    if (count > ba->ba_winsize)    /* no overlap */\n        count = ba->ba_winsize;\n    while (count-- > 0) {\n        /* gaps may exist */\n        if (ba->ba_buf[ba->ba_head].m != NULL) {\n            ieee80211_inputm(ifp, ba->ba_buf[ba->ba_head].m, ni,\n                             &ba->ba_buf[ba->ba_head].rxi, ml);\n            ba->ba_buf[ba->ba_head].m = NULL;\n            ba->ba_gapwait--;\n        } else\n            ic->ic_stats.is_ht_rx_ba_frame_lost++;\n        ba->ba_head = (ba->ba_head + 1) % IEEE80211_BA_MAX_WINSZ;\n    }\n    /* move window forward */\n    ba->ba_winstart = ssn;\n    ba->ba_winend = (ba->ba_winstart + ba->ba_winsize - 1) & 0xfff;\n    \n    ieee80211_input_ba_flush(ic, ni, ba, ml);\n}\n\nvoid\nieee80211_enqueue_data(struct ieee80211com *ic, mbuf_t m,\n                       struct ieee80211_node *ni, int mcast, struct mbuf_list *ml)\n{\n    struct _ifnet *ifp = &ic->ic_if;\n    struct ether_header *eh;\n    mbuf_t m1;\n    mbuf_t m2;\n    \n    eh = mtod(m, struct ether_header *);\n    \n    if ((ic->ic_flags & IEEE80211_F_RSNON) && !ni->ni_port_valid &&\n        eh->ether_type != htons(ETHERTYPE_PAE)) {\n        DPRINTF((\"port not valid: %s\\n\",\n                 ether_sprintf(eh->ether_dhost)));\n        ic->ic_stats.is_rx_unauth++;\n        mbuf_freem(m);\n        return;\n    }\n    \n    /*\n     * Perform as a bridge within the AP.  Notice that we do not\n     * bridge EAPOL frames as suggested in C.1.1 of IEEE Std 802.1X.\n     * And we do not forward unicast frames received on a multicast address.\n     */\n    m1 = NULL;\n#ifndef IEEE80211_STA_ONLY\n    if (ic->ic_opmode == IEEE80211_M_HOSTAP &&\n        !(ic->ic_userflags & IEEE80211_F_NOBRIDGE) &&\n        eh->ether_type != htons(ETHERTYPE_PAE)) {\n        struct ieee80211_node *ni1;\n        \n        if (ETHER_IS_MULTICAST(eh->ether_dhost)) {\n            m1 = m_dup_pkt(m, ETHER_ALIGN, MBUF_DONTWAIT);\n            if (m1 == NULL) {\n                XYLog(\"%s %d OUTPUT_ERROR\\n\", __FUNCTION__, __LINE__);\n                ifp->netStat->outputErrors++;\n            }\n            else\n                mbuf_setflags(m1, mbuf_flags(m1) | MBUF_MCAST);\n        } else if (!mcast) {\n            ni1 = ieee80211_find_node(ic, eh->ether_dhost);\n            if (ni1 != NULL &&\n                ni1->ni_state == IEEE80211_STA_ASSOC) {\n                m1 = m;\n                m = NULL;\n            }\n        }\n        if (m1 != NULL) {\n            if (if_enqueue(ifp, m1)) {\n                XYLog(\"%s %d OUTPUT_ERROR\\n\", __FUNCTION__, __LINE__);\n                ifp->netStat->outputErrors++;\n            }\n        }\n    }\n#endif\n    if (m != NULL) {\n        if ((ic->ic_flags & IEEE80211_F_RSNON) &&\n            eh->ether_type == htons(ETHERTYPE_PAE)) {\n            ifp->netStat->inputPackets++;\n#if NBPFILTER > 0\n            /*\n             * If we forward frame into transmitter of the AP,\n             * we don't need to duplicate for DLT_EN10MB.\n             */\n            if (ifp->if_bpf && m1 == NULL)\n                bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);\n#endif\n#ifdef USE_APPLE_SUPPLICANT\n            ml_enqueue(ml, m);\n#else\n#ifdef IO80211FAMILY_V2\n            if (ieee80211_is_8021x_akm((enum ieee80211_akm)ni->ni_rsnakms)) {\n                XYLog(\"%s Duplicate EAPOL packet to user space\\n\", __FUNCTION__);\n                mbuf_dup(m, MBUF_DONTWAIT, &m2);\n                if (m2 != NULL)\n                    ifp->iface->inputPacket(m2, mbuf_len(m2));\n            }\n#endif\n            ieee80211_eapol_key_input(ic, m, ni);\n#endif\n        } else {\n            ml_enqueue(ml, m);\n        }\n    }\n}\n\nvoid\nieee80211_decap(struct ieee80211com *ic, mbuf_t m,\n                struct ieee80211_node *ni, int hdrlen, struct mbuf_list *ml)\n{\n    struct ether_header eh;\n    struct ieee80211_frame *wh;\n    struct llc *llc;\n    int mcast;\n    \n    if (mbuf_len(m) < hdrlen + LLC_SNAPFRAMELEN &&\n        mbuf_pullup(&m, hdrlen + LLC_SNAPFRAMELEN)) {\n        ic->ic_stats.is_rx_decap++;\n        return;\n    }\n    wh = mtod(m, struct ieee80211_frame *);\n    mcast = IEEE80211_IS_MULTICAST(wh->i_addr1);\n    switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) {\n        case IEEE80211_FC1_DIR_NODS:\n            IEEE80211_ADDR_COPY(eh.ether_dhost, wh->i_addr1);\n            IEEE80211_ADDR_COPY(eh.ether_shost, wh->i_addr2);\n            break;\n        case IEEE80211_FC1_DIR_TODS:\n            IEEE80211_ADDR_COPY(eh.ether_dhost, wh->i_addr3);\n            IEEE80211_ADDR_COPY(eh.ether_shost, wh->i_addr2);\n            break;\n        case IEEE80211_FC1_DIR_FROMDS:\n            IEEE80211_ADDR_COPY(eh.ether_dhost, wh->i_addr1);\n            IEEE80211_ADDR_COPY(eh.ether_shost, wh->i_addr3);\n            break;\n        case IEEE80211_FC1_DIR_DSTODS:\n            IEEE80211_ADDR_COPY(eh.ether_dhost, wh->i_addr3);\n            IEEE80211_ADDR_COPY(eh.ether_shost,\n                                ((struct ieee80211_frame_addr4 *)wh)->i_addr4);\n            break;\n    }\n    llc = (struct llc *)((caddr_t)wh + hdrlen);\n    if (llc->llc_dsap == LLC_SNAP_LSAP &&\n        llc->llc_ssap == LLC_SNAP_LSAP &&\n        llc->llc_control == LLC_UI &&\n        llc->llc_snap.org_code[0] == 0 &&\n        llc->llc_snap.org_code[1] == 0 &&\n        llc->llc_snap.org_code[2] == 0) {\n        eh.ether_type = llc->llc_snap.ether_type;\n        mbuf_adj(m, hdrlen + LLC_SNAPFRAMELEN - ETHER_HDR_LEN);\n    } else {\n        eh.ether_type = htons(mbuf_pkthdr_len(m) - hdrlen);\n        mbuf_adj(m, hdrlen - ETHER_HDR_LEN);\n    }\n    memcpy(mtod(m, caddr_t), &eh, ETHER_HDR_LEN);\n    if (!ALIGNED_POINTER(mtod(m, caddr_t) + ETHER_HDR_LEN, u_int32_t)) {\n        mbuf_t m0 = m;\n        m = m_dup_pkt(m0, ETHER_ALIGN, M_NOWAIT);\n        mbuf_freem(m0);\n        if (m == NULL) {\n            ic->ic_stats.is_rx_decap++;\n            return;\n        }\n    }\n    ieee80211_enqueue_data(ic, m, ni, mcast, ml);\n}\n\nint\nieee80211_amsdu_decap_validate(struct ieee80211com *ic, mbuf_t m,\n                               struct ieee80211_node *ni)\n{\n    struct ether_header *eh = mtod(m, struct ether_header *);\n    const uint8_t llc_hdr_mac[ETHER_ADDR_LEN] = {\n        /* MAC address matching the 802.2 LLC header. */\n        LLC_SNAP_LSAP, LLC_SNAP_LSAP, LLC_UI, 0, 0, 0\n    }; \n    \n    /*\n     * We are sorry, but this particular MAC address cannot be used.\n     * This mitigates an attack where a single 802.11 frame is interpreted\n     * as an A-MSDU because of a forged AMSDU-present bit in the 802.11\n     * QoS frame header: https://papers.mathyvanhoef.com/usenix2021.pdf\n     * See Section 7.2, 'Countermeasures for the design flaws'\n     */\n    if (ETHER_IS_EQ(eh->ether_dhost, llc_hdr_mac))\n        return 1;\n    \n    switch (ic->ic_opmode) {\n#ifndef IEEE80211_STA_ONLY\n        case IEEE80211_M_HOSTAP:\n            /*\n             * Subframes must use the source address of the node which\n             * transmitted the A-MSDU. Prevents MAC spoofing.\n             */\n            if (!ETHER_IS_EQ(ni->ni_macaddr, eh->ether_shost))\n                return 1;\n            break;\n#endif\n        case IEEE80211_M_STA:\n            /* Subframes must be addressed to me. */\n            if (!ETHER_IS_EQ(ic->ic_myaddr, eh->ether_dhost))\n                return 1;\n            break;\n        default:\n            /* Ignore MONITOR/IBSS modes for now. */\n            break;\n    }\n    \n    return 0;\n}\n\n/*\n * Decapsulate an Aggregate MSDU (see 7.2.2.2).\n */\nvoid\nieee80211_amsdu_decap(struct ieee80211com *ic, mbuf_t m,\n                      struct ieee80211_node *ni, int hdrlen, struct mbuf_list *ml)\n{\n    mbuf_t n;\n    struct ether_header *eh;\n    struct llc *llc;\n    int len, pad, mcast;\n    struct ieee80211_frame *wh;\n    struct mbuf_list subframes = MBUF_LIST_INITIALIZER();\n    \n    wh = mtod(m, struct ieee80211_frame *);\n    mcast = IEEE80211_IS_MULTICAST(wh->i_addr1);\n    \n    /* strip 802.11 header */\n    mbuf_adj(m, hdrlen);\n    \n    while (mbuf_pkthdr_len(m) >= ETHER_HDR_LEN + LLC_SNAPFRAMELEN) {\n        /* process an A-MSDU subframe */\n        mbuf_pullup(&m, ETHER_HDR_LEN + LLC_SNAPFRAMELEN);\n        if (m == NULL)\n            break;\n        eh = mtod(m, struct ether_header *);\n        /* examine 802.3 header */\n        len = ntohs(eh->ether_type);\n        if (len < LLC_SNAPFRAMELEN) {\n            DPRINTF((\"A-MSDU subframe too short (%d)\\n\", len));\n            /* stop processing A-MSDU subframes */\n            ic->ic_stats.is_rx_decap++;\n            ml_purge(&subframes);\n            mbuf_freem(m);\n            return;\n        }\n        llc = (struct llc *)&eh[1];\n        /* Examine the 802.2 LLC header after the A-MSDU header. */\n        if (llc->llc_dsap == LLC_SNAP_LSAP &&\n            llc->llc_ssap == LLC_SNAP_LSAP &&\n            llc->llc_control == LLC_UI &&\n            llc->llc_snap.org_code[0] == 0 &&\n            llc->llc_snap.org_code[1] == 0 &&\n            llc->llc_snap.org_code[2] == 0) {\n            /* convert to Ethernet II header */\n            eh->ether_type = llc->llc_snap.ether_type;\n            /* strip LLC+SNAP headers */\n            memmove((u_int8_t *)eh + LLC_SNAPFRAMELEN, eh,\n                    ETHER_HDR_LEN);\n            mbuf_adj(m, LLC_SNAPFRAMELEN);\n            len -= LLC_SNAPFRAMELEN;\n        }\n        len += ETHER_HDR_LEN;\n        if (len > mbuf_pkthdr_len(m)) {\n            /* stop processing A-MSDU subframes */\n            DPRINTF((\"A-MSDU subframe too long (%d)\\n\", len));\n            ic->ic_stats.is_rx_decap++;\n            ml_purge(&subframes);\n            mbuf_freem(m);\n            return;\n        }\n        \n        /* \"detach\" our A-MSDU subframe from the others */\n        mbuf_split(m, len, MBUF_DONTWAIT, &n);\n        if (n == NULL) {\n            /* stop processing A-MSDU subframes */\n            ic->ic_stats.is_rx_decap++;\n            ml_purge(&subframes);\n            mbuf_freem(m);\n            return;\n        }\n        \n        if (ieee80211_amsdu_decap_validate(ic, m, ni)) {\n            /* stop processing A-MSDU subframes */\n            ic->ic_stats.is_rx_decap++;\n            ml_purge(&subframes);\n            mbuf_freem(m);\n            return;\n        }\n        \n        ml_enqueue(&subframes, m);\n        \n        m = n;\n        /* remove padding */\n        pad = ((len + 3) & ~3) - len;\n        mbuf_adj(m, pad);\n    }\n    \n    while ((n = ml_dequeue(&subframes)) != NULL)\n        ieee80211_enqueue_data(ic, n, ni, mcast, ml);\n    \n    mbuf_freem(m);\n}\n\n/*\n * Parse an EDCA Parameter Set element (see 7.3.2.27).\n */\nint\nieee80211_parse_edca_params_body(struct ieee80211com *ic, const u_int8_t *frm)\n{\n    u_int updtcount;\n    int aci;\n    \n    /*\n     * Check if EDCA parameters have changed XXX if we miss more than\n     * 15 consecutive beacons, we might not detect changes to EDCA\n     * parameters due to wraparound of the 4-bit Update Count field.\n     */\n    updtcount = frm[0] & 0xf;\n    if (updtcount == ic->ic_edca_updtcount)\n        return 0;    /* no changes to EDCA parameters, ignore */\n    ic->ic_edca_updtcount = updtcount;\n    \n    frm += 2;    /* skip QoS Info & Reserved fields */\n    \n    /* parse AC Parameter Records */\n    for (aci = 0; aci < EDCA_NUM_AC; aci++) {\n        struct ieee80211_edca_ac_params *ac = &ic->ic_edca_ac[aci];\n        \n        ac->ac_acm       = (frm[0] >> 4) & 0x1;\n        ac->ac_aifsn     = frm[0] & 0xf;\n        ac->ac_ecwmin    = frm[1] & 0xf;\n        ac->ac_ecwmax    = frm[1] >> 4;\n        ac->ac_txoplimit = LE_READ_2(frm + 2);\n        frm += 4;\n    }\n    /* give drivers a chance to update their settings */\n    if ((ic->ic_flags & IEEE80211_F_QOS) && ic->ic_updateedca != NULL)\n        (*ic->ic_updateedca)(ic);\n    \n    return 0;\n}\n\nint\nieee80211_parse_edca_params(struct ieee80211com *ic, const u_int8_t *frm)\n{\n    if (frm[1] < 18) {\n        ic->ic_stats.is_rx_elem_toosmall++;\n        return IEEE80211_REASON_IE_INVALID;\n    }\n    return ieee80211_parse_edca_params_body(ic, frm + 2);\n}\n\nint\nieee80211_parse_wmm_params(struct ieee80211com *ic, const u_int8_t *frm)\n{\n    if (frm[1] < 24) {\n        ic->ic_stats.is_rx_elem_toosmall++;\n        return IEEE80211_REASON_IE_INVALID;\n    }\n    return ieee80211_parse_edca_params_body(ic, frm + 8);\n}\n\nenum ieee80211_cipher\nieee80211_parse_rsn_cipher(const u_int8_t selector[4])\n{\n    if (memcmp(selector, MICROSOFT_OUI, 3) == 0) {    /* WPA */\n        switch (selector[3]) {\n            case 0:    /* use group data cipher suite */\n                return IEEE80211_CIPHER_USEGROUP;\n            case 1:    /* WEP-40 */\n                return IEEE80211_CIPHER_WEP40;\n            case 2:    /* TKIP */\n                return IEEE80211_CIPHER_TKIP;\n            case 4:    /* CCMP (RSNA default) */\n                return IEEE80211_CIPHER_CCMP;\n            case 5:    /* WEP-104 */\n                return IEEE80211_CIPHER_WEP104;\n        }\n    } else if (memcmp(selector, IEEE80211_OUI, 3) == 0) {    /* RSN */\n        /* see 802.11-2012 Table 8-99 */\n        switch (selector[3]) {\n            case 0:    /* use group data cipher suite */\n                return IEEE80211_CIPHER_USEGROUP;\n            case 1:    /* WEP-40 */\n                return IEEE80211_CIPHER_WEP40;\n            case 2:    /* TKIP */\n                return IEEE80211_CIPHER_TKIP;\n            case 4:    /* CCMP (RSNA default) */\n                return IEEE80211_CIPHER_CCMP;\n            case 5:    /* WEP-104 */\n                return IEEE80211_CIPHER_WEP104;\n            case 6:    /* BIP */\n                return IEEE80211_CIPHER_BIP;\n        }\n    }\n    return IEEE80211_CIPHER_NONE;    /* ignore unknown ciphers */\n}\n\nenum ieee80211_akm\nieee80211_parse_rsn_akm(const u_int8_t selector[4])\n{\n    if (memcmp(selector, MICROSOFT_OUI, 3) == 0) {    /* WPA */\n        switch (selector[3]) {\n            case 1:    /* IEEE 802.1X (RSNA default) */\n                return IEEE80211_AKM_8021X;\n            case 2:    /* PSK */\n                return IEEE80211_AKM_PSK;\n        }\n    } else if (memcmp(selector, IEEE80211_OUI, 3) == 0) {    /* RSN */\n        /* from IEEE Std 802.11i-2004 - Table 20dc */\n        switch (selector[3]) {\n            case 1:    /* IEEE 802.1X (RSNA default) */\n                return IEEE80211_AKM_8021X;\n            case 2:    /* PSK */\n                return IEEE80211_AKM_PSK;\n            case 5:    /* IEEE 802.1X with SHA256 KDF */\n                return IEEE80211_AKM_SHA256_8021X;\n            case 6:    /* PSK with SHA256 KDF */\n                return IEEE80211_AKM_SHA256_PSK;\n        }\n    }\n    return IEEE80211_AKM_NONE;    /* ignore unknown AKMs */\n}\n\n/*\n * Parse an RSN element (see 802.11-2012 8.4.2.27)\n */\nint\nieee80211_parse_rsn_body(struct ieee80211com *ic, const u_int8_t *frm,\n                         u_int len, struct ieee80211_rsnparams *rsn)\n{\n    const u_int8_t *efrm;\n    u_int16_t m, n, s;\n    \n    efrm = frm + len;\n    \n    /* check Version field */\n    if (LE_READ_2(frm) != 1)\n        return IEEE80211_STATUS_RSN_IE_VER_UNSUP;\n    frm += 2;\n    \n    /* all fields after the Version field are optional */\n    \n    /* if Cipher Suite missing, default to CCMP */\n    rsn->rsn_groupcipher = IEEE80211_CIPHER_CCMP;\n    rsn->rsn_nciphers = 1;\n    rsn->rsn_ciphers = IEEE80211_CIPHER_CCMP;\n    /* if Group Management Cipher Suite missing, defaut to BIP */\n    rsn->rsn_groupmgmtcipher = IEEE80211_CIPHER_BIP;\n    /* if AKM Suite missing, default to 802.1X */\n    rsn->rsn_nakms = 1;\n    rsn->rsn_akms = IEEE80211_AKM_8021X;\n    /* if RSN capabilities missing, default to 0 */\n    rsn->rsn_caps = 0;\n    rsn->rsn_npmkids = 0;\n    \n    /* read Group Data Cipher Suite field */\n    if (frm + 4 > efrm)\n        return 0;\n    rsn->rsn_groupcipher = ieee80211_parse_rsn_cipher(frm);\n    if (rsn->rsn_groupcipher == IEEE80211_CIPHER_NONE ||\n        rsn->rsn_groupcipher == IEEE80211_CIPHER_USEGROUP ||\n        rsn->rsn_groupcipher == IEEE80211_CIPHER_BIP)\n        return IEEE80211_STATUS_BAD_GROUP_CIPHER;\n    frm += 4;\n    \n    /* read Pairwise Cipher Suite Count field */\n    if (frm + 2 > efrm)\n        return 0;\n    m = rsn->rsn_nciphers = LE_READ_2(frm);\n    frm += 2;\n    \n    /* read Pairwise Cipher Suite List */\n    if (frm + m * 4 > efrm)\n        return IEEE80211_STATUS_IE_INVALID;\n    rsn->rsn_ciphers = IEEE80211_CIPHER_NONE;\n    while (m-- > 0) {\n        rsn->rsn_ciphers |= ieee80211_parse_rsn_cipher(frm);\n        frm += 4;\n    }\n    if (rsn->rsn_ciphers & IEEE80211_CIPHER_USEGROUP) {\n        if (rsn->rsn_ciphers != IEEE80211_CIPHER_USEGROUP)\n            return IEEE80211_STATUS_BAD_PAIRWISE_CIPHER;\n        if (rsn->rsn_groupcipher == IEEE80211_CIPHER_CCMP)\n            return IEEE80211_STATUS_BAD_PAIRWISE_CIPHER;\n    }\n    \n    /* read AKM Suite List Count field */\n    if (frm + 2 > efrm)\n        return 0;\n    n = rsn->rsn_nakms = LE_READ_2(frm);\n    frm += 2;\n    \n    /* read AKM Suite List */\n    if (frm + n * 4 > efrm)\n        return IEEE80211_STATUS_IE_INVALID;\n    rsn->rsn_akms = IEEE80211_AKM_NONE;\n    while (n-- > 0) {\n        rsn->rsn_akms |= ieee80211_parse_rsn_akm(frm);\n        frm += 4;\n    }\n    \n    /* read RSN Capabilities field */\n    if (frm + 2 > efrm)\n        return 0;\n    rsn->rsn_caps = LE_READ_2(frm);\n    frm += 2;\n    \n    /* read PMKID Count field */\n    if (frm + 2 > efrm)\n        return 0;\n    s = rsn->rsn_npmkids = LE_READ_2(frm);\n    frm += 2;\n    \n    /* read PMKID List */\n    if (frm + s * IEEE80211_PMKID_LEN > efrm)\n        return IEEE80211_STATUS_IE_INVALID;\n    if (s != 0) {\n        rsn->rsn_pmkids = frm;\n        frm += s * IEEE80211_PMKID_LEN;\n    }\n    \n    /* read Group Management Cipher Suite field */\n    if (frm + 4 > efrm)\n        return 0;\n    rsn->rsn_groupmgmtcipher = ieee80211_parse_rsn_cipher(frm);\n    if (rsn->rsn_groupmgmtcipher != IEEE80211_CIPHER_BIP)\n        return IEEE80211_STATUS_BAD_GROUP_CIPHER;\n    \n    return IEEE80211_STATUS_SUCCESS;\n}\n\nint\nieee80211_parse_rsn(struct ieee80211com *ic, const u_int8_t *frm,\n                    struct ieee80211_rsnparams *rsn)\n{\n    if (frm[1] < 2) {\n        ic->ic_stats.is_rx_elem_toosmall++;\n        return IEEE80211_STATUS_IE_INVALID;\n    }\n    return ieee80211_parse_rsn_body(ic, frm + 2, frm[1], rsn);\n}\n\nint\nieee80211_parse_wpa(struct ieee80211com *ic, const u_int8_t *frm,\n                    struct ieee80211_rsnparams *rsn)\n{\n    if (frm[1] < 6) {\n        ic->ic_stats.is_rx_elem_toosmall++;\n        return IEEE80211_STATUS_IE_INVALID;\n    }\n    return ieee80211_parse_rsn_body(ic, frm + 6, frm[1] - 4, rsn);\n}\n\n/*\n * Create (or update) a copy of an information element.\n */\nint\nieee80211_save_ie(const u_int8_t *frm, u_int8_t **ie)\n{\n    int olen = *ie ? 2 + (*ie)[1] : 0;\n    int len = 2 + frm[1];\n    \n    if (*ie == NULL || olen != len) {\n        if (*ie != NULL)\n            free(*ie);\n        *ie = (u_int8_t *)malloc(len, 0, 0);\n        if (*ie == NULL)\n            return ENOMEM;\n    }\n    memcpy(*ie, frm, len);\n    return 0;\n}\n\n/*\n * zxy, save tlv ie for Apple80211\n */\nint\nieee80211_save_ie_tlv(const u_int8_t *frm, u_int8_t **ie, uint32_t *accept_len, uint32_t len)\n{\n    int olen = *accept_len;\n    \n    if (*ie == NULL || olen != len) {\n        if (*ie != NULL && *accept_len > 0)\n            free(*ie);\n        *ie = (u_int8_t *)malloc(len, 1, 1);\n        if (*ie == NULL)\n            return ENOMEM;\n    }\n    *accept_len = len;\n    memcpy(*ie, frm, len);\n    return 0;\n}\n\n/*-\n * Beacon/Probe response frame format:\n * [8]   Timestamp\n * [2]   Beacon interval\n * [2]   Capability\n * [tlv] Service Set Identifier (SSID)\n * [tlv] Supported rates\n * [tlv] DS Parameter Set (802.11g)\n * [tlv] ERP Information (802.11g)\n * [tlv] Extended Supported Rates (802.11g)\n * [tlv] RSN (802.11i)\n * [tlv] EDCA Parameter Set (802.11e)\n * [tlv] QoS Capability (Beacon only, 802.11e)\n * [tlv] HT Capabilities (802.11n)\n * [tlv] HT Operation (802.11n)\n */\nvoid\nieee80211_recv_probe_resp(struct ieee80211com *ic, mbuf_t m,\n                          struct ieee80211_node *rni, struct ieee80211_rxinfo *rxi, int isprobe)\n{\n    struct ieee80211_node *ni = NULL;\n    const struct ieee80211_frame *wh;\n    const u_int8_t *frm, *efrm;\n    const u_int8_t *tstamp, *ssid, *rates, *xrates, *edcaie, *wmmie;\n    const u_int8_t *rsnie, *wpaie, *htcaps, *htop;\n    const uint8_t *csa;\n    const uint8_t *vhtcap;\n    const uint8_t *vhtopmode;\n    const uint8_t *hecap;\n    const uint8_t *heopmode;\n    u_int16_t capinfo, bintval;\n    u_int8_t chan, bchan, erp, dtim_count, dtim_period;\n    int is_new;\n    \n    /*\n     * We process beacon/probe response frames for:\n     *    o station mode: to collect state\n     *      updates such as 802.11g slot time and for passive\n     *      scanning of APs\n     *    o adhoc mode: to discover neighbors\n     *    o hostap mode: for passive scanning of neighbor APs\n     *    o when scanning\n     * In other words, in all modes other than monitor (which\n     * does not process incoming frames) and adhoc-demo (which\n     * does not use management frames at all).\n     */\n#ifdef DIAGNOSTIC\n    if (ic->ic_opmode != IEEE80211_M_STA &&\n#ifndef IEEE80211_STA_ONLY\n        ic->ic_opmode != IEEE80211_M_IBSS &&\n        ic->ic_opmode != IEEE80211_M_HOSTAP &&\n#endif\n        ic->ic_state != IEEE80211_S_SCAN) {\n        panic(\"%s: impossible operating mode\", __func__);\n    }\n#endif\n    /* make sure all mandatory fixed fields are present */\n    if (mbuf_len(m) < sizeof(*wh) + 12) {\n        DPRINTF((\"frame too short\\n\"));\n        return;\n    }\n    wh = mtod(m, struct ieee80211_frame *);\n    frm = (const u_int8_t *)&wh[1];\n    efrm = mtod(m, u_int8_t *) + mbuf_len(m);\n    \n    tstamp  = frm; frm += 8;\n    bintval = LE_READ_2(frm); frm += 2;\n    capinfo = LE_READ_2(frm); frm += 2;\n    \n    ssid = rates = xrates = edcaie = wmmie = rsnie = wpaie = csa = vhtcap = vhtopmode = hecap = heopmode = NULL;\n    htcaps = htop = NULL;\n    if (rxi->rxi_chan)\n         bchan = rxi->rxi_chan;\n     else\n         bchan = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan);\n    chan = bchan;\n    erp = 0;\n    dtim_count = dtim_period = 0;\n    while (frm + 2 <= efrm) {\n        if (frm + 2 + frm[1] > efrm) {\n            ic->ic_stats.is_rx_elem_toosmall++;\n            break;\n        }\n        switch (frm[0]) {\n            case IEEE80211_ELEMID_SSID:\n                ssid = frm;\n                break;\n            case IEEE80211_ELEMID_CSA:\n                csa = frm;\n                break;\n            case IEEE80211_ELEMID_RATES:\n                rates = frm;\n                break;\n            case IEEE80211_ELEMID_DSPARMS:\n                if (frm[1] < 1) {\n                    ic->ic_stats.is_rx_elem_toosmall++;\n                    break;\n                }\n                chan = frm[2];\n                break;\n            case IEEE80211_ELEMID_XRATES:\n                xrates = frm;\n                break;\n            case IEEE80211_ELEMID_ERP:\n                if (frm[1] < 1) {\n                    ic->ic_stats.is_rx_elem_toosmall++;\n                    break;\n                }\n                erp = frm[2];\n                break;\n            case IEEE80211_ELEMID_VHT_CAP:\n                vhtcap = frm;\n                break;\n            case IEEE80211_ELEMID_VHT_OPMODE:\n                vhtopmode = frm;\n                break;\n            case IEEE80211_ELEMID_RSN:\n                rsnie = frm;\n                break;\n            case IEEE80211_ELEMID_EDCAPARMS:\n                edcaie = frm;\n                break;\n            case IEEE80211_ELEMID_HTCAPS:\n                htcaps = frm;\n                break;\n            case IEEE80211_ELEMID_HTOP:\n                htop = frm;\n                break;\n            case IEEE80211_ELEMID_TIM:\n                if (frm[1] > 3) {\n                    dtim_count = frm[2];\n                    dtim_period = frm[3];\n                }\n                break;\n            case IEEE80211_ELEMID_VENDOR:\n                if (frm[1] < 4) {\n                    ic->ic_stats.is_rx_elem_toosmall++;\n                    break;\n                }\n                if (memcmp(frm + 2, MICROSOFT_OUI, 3) == 0) {\n                    if (frm[5] == 1)\n                        wpaie = frm;\n                    else if (frm[1] >= 5 &&\n                             frm[5] == 2 && frm[6] == 1)\n                        wmmie = frm;\n                }\n                break;\n            case IEEE80211_ELEMID_EXTENSION:\n                switch (frm[2]) {\n                    case IEEE80211_ELEMID_EXT_HE_MU_EDCA:\n                        break;\n                    case IEEE80211_ELEMID_EXT_HE_CAPABILITY:\n                        hecap = frm;\n                        break;\n                    case IEEE80211_ELEMID_EXT_HE_OPERATION:\n                        heopmode = frm;\n                        break;\n                    case IEEE80211_ELEMID_EXT_UORA:\n                        break;\n                    case IEEE80211_ELEMID_EXT_MAX_CHANNEL_SWITCH_TIME:\n                        break;\n                    case IEEE80211_ELEMID_EXT_MULTIPLE_BSSID_CONFIGURATION:\n                        break;\n                    case IEEE80211_ELEMID_EXT_HE_SPR:\n                        break;\n                    case IEEE80211_ELEMID_EXT_HE_6GHZ_CAPA:\n                        break;\n                }\n                break;\n        }\n        frm += 2 + frm[1];\n    }\n    /* supported rates element is mandatory */\n    if (rates == NULL || rates[1] > IEEE80211_RATE_MAXSIZE) {\n        DPRINTF((\"invalid supported rates element\\n\"));\n        return;\n    }\n    /* SSID element is mandatory */\n    if (ssid == NULL || ssid[1] > IEEE80211_NWID_LEN) {\n        DPRINTF((\"invalid SSID element\\n\"));\n        return;\n    }\n    if (csa != NULL && csa[1] < 3 * sizeof(uint8_t)) {\n        DPRINTF((\"csa ie too short, got %d, expected %lu\\n\", csa[1], 3 * sizeof(uint8_t)));\n        csa = NULL;\n    }\n    if (vhtcap != NULL && vhtcap[1] < sizeof(struct ieee80211_ie_vhtcap) - 2) {\n        DPRINTF((\"vhtcap ie too short, got %d, expected %lu\\n\", vhtcap[1], sizeof(struct ieee80211_ie_vhtcap) - 2));\n        vhtcap = NULL;\n    }\n    if (vhtopmode != NULL && vhtopmode[1] < sizeof(struct ieee80211_ie_vht_operation) - 2) {\n        DPRINTF((\"vhtopmode ie too short, got %d, expected %lu\\n\", vhtopmode[1], sizeof(struct ieee80211_ie_vht_operation) - 2));\n        vhtopmode = NULL;\n    }\n    if (\n#if IEEE80211_CHAN_MAX < 255\n        chan > IEEE80211_CHAN_MAX ||\n#endif\n        (isclr(ic->ic_chan_active, chan) &&\n         ((ic->ic_caps & IEEE80211_C_SCANALL) == 0 ||\n          (ic->ic_flags & IEEE80211_F_BGSCAN) == 0))) {\n        DPRINTF((\"ignore %s with invalid channel %u\\n\",\n                 isprobe ? \"probe response\" : \"beacon\", chan));\n        ic->ic_stats.is_rx_badchan++;\n        return;\n    }\n    if ((rxi->rxi_chan != 0 && chan != rxi->rxi_chan) ||\n        ((ic->ic_state != IEEE80211_S_SCAN ||\n         !(ic->ic_caps & IEEE80211_C_SCANALL)) &&\n        chan != bchan)) {\n        /*\n         * Frame was received on a channel different from the\n         * one indicated in the DS params element id;\n         * silently discard it.\n         *\n         * NB: this can happen due to signal leakage.\n         */\n        DPRINTF((\"ignore %s on channel %u marked for channel %u\\n\",\n                 isprobe ? \"probe response\" : \"beacon\", bchan, chan));\n        ic->ic_stats.is_rx_chanmismatch++;\n        return;\n    }\n    \n#ifdef IEEE80211_DEBUG\n    if (ieee80211_debug > 1 &&\n        (ni == NULL || ic->ic_state == IEEE80211_S_SCAN ||\n         (ic->ic_flags & IEEE80211_F_BGSCAN))) {\n        XYLog(\"%s: %s%s on chan %u (bss chan %u) \",\n              __func__, (ni == NULL ? \"new \" : \"\"),\n              isprobe ? \"probe response\" : \"beacon\",\n              chan, bchan);\n        ieee80211_print_essid(ssid + 2, ssid[1]);\n        XYLog(\" from %s\\n\", ether_sprintf((u_int8_t *)wh->i_addr2));\n        XYLog(\"%s: caps 0x%x bintval %u erp 0x%x\\n\",\n              __func__, capinfo, bintval, erp);\n    }\n#endif\n    \n    if ((ni = ieee80211_find_node(ic, wh->i_addr2)) == NULL) {\n        ni = ieee80211_alloc_node(ic, wh->i_addr2);\n        if (ni == NULL)\n            return;\n        is_new = 1;\n    } else\n        is_new = 0;\n    \n    ni->ni_chan = &ic->ic_channels[chan];\n    \n    if (htcaps)\n        ieee80211_setup_htcaps(ni, htcaps + 2, htcaps[1]);\n    if (htop && !ieee80211_setup_htop(ni, htop + 2, htop[1], 1))\n        htop = NULL; /* invalid HTOP */\n    \n    if (vhtcap != NULL && vhtopmode != NULL) {\n        ieee80211_setup_vhtcaps(ic, ni, vhtcap);\n        ieee80211_setup_vhtopmode(ni, vhtopmode);\n    }\n    if (hecap != NULL && heopmode != NULL) {\n        ieee80211_setup_hecaps(ni, hecap + 3, hecap[1] - 1);\n        ieee80211_setup_heop(ni, heopmode + 3, heopmode[1] - 1);\n    }\n    \n    ni->ni_dtimcount = dtim_count;\n    ni->ni_dtimperiod = dtim_period;\n#ifdef AIRPORT\n    ni->ni_age_ts = airport_up_time();\n#endif\n    \n    /*\n     * When operating in station mode, check for state updates\n     * while we're associated.\n     */\n    if (ic->ic_opmode == IEEE80211_M_STA &&\n        ic->ic_state == IEEE80211_S_RUN &&\n        ni->ni_state == IEEE80211_STA_BSS) {\n        int updateprot = 0;\n        /*\n         * Check if protection mode has changed since last beacon.\n         */\n        if (ni->ni_erp != erp) {\n            DPRINTF((\"[%s] erp change: was 0x%x, now 0x%x\\n\",\n                     ether_sprintf((u_int8_t *)wh->i_addr2),\n                     ni->ni_erp, erp));\n            if ((ic->ic_curmode == IEEE80211_MODE_11G ||\n                 (ic->ic_curmode == IEEE80211_MODE_11N &&\n                  IEEE80211_IS_CHAN_2GHZ(ni->ni_chan))) &&\n                (erp & IEEE80211_ERP_USE_PROTECTION))\n                ic->ic_flags |= IEEE80211_F_USEPROT;\n            else\n                ic->ic_flags &= ~IEEE80211_F_USEPROT;\n            ic->ic_bss->ni_erp = erp;\n            updateprot = 1;\n        }\n        if (htop && (ic->ic_bss->ni_flags & IEEE80211_NODE_HT)) {\n            enum ieee80211_htprot htprot_last, htprot;\n            htprot_last =\n            (enum ieee80211_htprot)((ic->ic_bss->ni_htop1 & IEEE80211_HTOP1_PROT_MASK)\n                                    >> IEEE80211_HTOP1_PROT_SHIFT);\n            htprot = (enum ieee80211_htprot)((ni->ni_htop1 & IEEE80211_HTOP1_PROT_MASK) >>\n                                             IEEE80211_HTOP1_PROT_SHIFT);\n            if (htprot_last != htprot) {\n                DPRINTF((\"[%s] htprot change: was %d, now %d\\n\",\n                         ether_sprintf((u_int8_t *)wh->i_addr2),\n                         htprot_last, htprot));\n                ic->ic_stats.is_ht_prot_change++;\n                ic->ic_bss->ni_htop1 = ni->ni_htop1;\n                updateprot = 1;\n            }\n        }\n        if (updateprot && ic->ic_updateprot != NULL)\n            ic->ic_updateprot(ic);\n\n        /*\n         * Check if 40MHz channel mode has changed since last beacon.\n         */\n        if (htop && !(ic->ic_bss->ni_flags & IEEE80211_NODE_VHT) &&\n            !(ic->ic_bss->ni_flags & IEEE80211_NODE_HE) &&\n            (ic->ic_bss->ni_flags & IEEE80211_NODE_HT) &&\n            (ic->ic_htcaps & IEEE80211_HTCAP_CBW20_40)) {\n            uint8_t chw_last, chw, sco_last, sco;\n            chw_last = (ic->ic_bss->ni_htop0 & IEEE80211_HTOP0_CHW);\n            chw = (ni->ni_htop0 & IEEE80211_HTOP0_CHW);\n            sco_last =\n            ((ic->ic_bss->ni_htop0 & IEEE80211_HTOP0_SCO_MASK)\n             >> IEEE80211_HTOP0_SCO_SHIFT);\n            sco = ((ni->ni_htop0 & IEEE80211_HTOP0_SCO_MASK) >>\n                   IEEE80211_HTOP0_SCO_SHIFT);\n            ic->ic_bss->ni_htop0 = ni->ni_htop0;\n            if (chw_last != chw || sco_last != sco) {\n                XYLog(\"[%s] channel mode change: was %d, now %d, sco was: %d, now: %d\\n\",\n                      ether_sprintf((u_int8_t *)wh->i_addr2),\n                      chw_last, chw, sco_last, sco);\n                if (ic->ic_update_chw != NULL)\n                    ic->ic_update_chw(ic);\n            }\n        } else if (htop)\n            ic->ic_bss->ni_htop0 = ni->ni_htop0;\n        \n        /*\n         * Check if AP short slot time setting has changed\n         * since last beacon and give the driver a chance to\n         * update the hardware.\n         */\n        if ((ni->ni_capinfo ^ capinfo) &\n            IEEE80211_CAPINFO_SHORT_SLOTTIME) {\n            ieee80211_set_shortslottime(ic,\n                                        ic->ic_curmode == IEEE80211_MODE_11A ||\n                                        (capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME));\n        }\n        \n        if (!ic->ic_bss->ni_dtimperiod) {\n            ic->ic_bss->ni_dtimcount = ni->ni_dtimcount;\n            ic->ic_bss->ni_dtimperiod = ni->ni_dtimperiod ?: 1;\n            \n            if (ic->ic_updatedtim != NULL)\n                ic->ic_updatedtim(ic);\n        }\n        \n        /*\n         * Reset management timer. If it is non-zero in RUN state, the\n         * driver sent a probe request after a missed beacon event.\n         * This probe response indicates the AP is still serving us\n         * so don't allow ieee80211_watchdog() to move us into SCAN.\n         */\n        if ((ic->ic_flags & IEEE80211_F_BGSCAN) == 0)\n            ic->ic_mgt_timer = 0;\n    }\n    /*\n     * We do not try to update EDCA parameters if QoS was not negotiated\n     * with the AP at association time.\n     */\n    if (ni->ni_flags & IEEE80211_NODE_QOS) {\n        /* always prefer EDCA IE over Wi-Fi Alliance WMM IE */\n        if ((edcaie != NULL &&\n             ieee80211_parse_edca_params(ic, edcaie) == 0) ||\n            (wmmie != NULL &&\n             ieee80211_parse_wmm_params(ic, wmmie) == 0))\n            ni->ni_flags |= IEEE80211_NODE_QOS;\n        else\n            ni->ni_flags &= ~IEEE80211_NODE_QOS;\n    }\n    \n    if (ic->ic_state == IEEE80211_S_SCAN ||\n        (ic->ic_flags & IEEE80211_F_BGSCAN)) {\n        struct ieee80211_rsnparams rsn, wpa;\n        \n        uint32_t tlv_len = (mtod(m, u_int8_t *) + mbuf_len(m)) - (u_int8_t *)&wh[1] + 1 - 8 - 2 - 2;\n        ieee80211_save_ie_tlv(((u_int8_t *)&wh[1]) + 8 + 2 + 2, &ni->ni_rsnie_tlv, &ni->ni_rsnie_tlv_len, tlv_len);\n        ni->ni_rsnprotos = IEEE80211_PROTO_NONE;\n        ni->ni_supported_rsnprotos = IEEE80211_PROTO_NONE;\n        ni->ni_rsnakms = 0;\n        ni->ni_supported_rsnakms = 0;\n        ni->ni_rsnciphers = 0;\n        ni->ni_rsngroupcipher = (enum ieee80211_cipher)0;\n        ni->ni_rsngroupmgmtcipher = (enum ieee80211_cipher)0;\n        ni->ni_rsncaps = 0;\n        \n        if (rsnie != NULL &&\n            ieee80211_parse_rsn(ic, rsnie, &rsn) == 0) {\n            ni->ni_supported_rsnprotos |= IEEE80211_PROTO_RSN;\n            ni->ni_supported_rsnakms |= rsn.rsn_akms;\n        }\n        if (wpaie != NULL &&\n            ieee80211_parse_wpa(ic, wpaie, &wpa) == 0) {\n            ni->ni_supported_rsnprotos |= IEEE80211_PROTO_WPA;\n            ni->ni_supported_rsnakms |= wpa.rsn_akms;\n        }\n        \n        /*\n         * If the AP advertises both WPA and RSN IEs (WPA1+WPA2),\n         * we only use the highest protocol version we support.\n         */\n        if (rsnie != NULL &&\n            (ni->ni_supported_rsnprotos & IEEE80211_PROTO_RSN) &&\n            (ic->ic_caps & IEEE80211_C_RSN)) {\n            if (ieee80211_save_ie(rsnie, &ni->ni_rsnie) == 0\n#ifndef IEEE80211_STA_ONLY\n                && ic->ic_opmode != IEEE80211_M_HOSTAP\n#endif\n                ) {\n                ni->ni_rsnprotos = IEEE80211_PROTO_RSN;\n                ni->ni_rsnakms = rsn.rsn_akms;\n                ni->ni_rsnciphers = rsn.rsn_ciphers;\n                ni->ni_rsngroupcipher = rsn.rsn_groupcipher;\n                ni->ni_rsngroupmgmtcipher =\n                rsn.rsn_groupmgmtcipher;\n                ni->ni_rsncaps = rsn.rsn_caps;\n            }\n        } else if (wpaie != NULL &&\n                   (ni->ni_supported_rsnprotos & IEEE80211_PROTO_WPA) &&\n                   (ic->ic_caps & IEEE80211_C_RSN)) {\n            if (ieee80211_save_ie(wpaie, &ni->ni_rsnie) == 0\n#ifndef IEEE80211_STA_ONLY\n                && ic->ic_opmode != IEEE80211_M_HOSTAP\n#endif\n                ) {\n                ni->ni_rsnprotos = IEEE80211_PROTO_WPA;\n                ni->ni_rsnakms = wpa.rsn_akms;\n                ni->ni_rsnciphers = wpa.rsn_ciphers;\n                ni->ni_rsngroupcipher = wpa.rsn_groupcipher;\n                ni->ni_rsngroupmgmtcipher =\n                wpa.rsn_groupmgmtcipher;\n                ni->ni_rsncaps = wpa.rsn_caps;\n            }\n        }\n    }\n    \n    /*\n     * Set our SSID if we do not know it yet.\n     * If we are doing a directed scan for an AP with a hidden SSID\n     * we must collect the SSID from a probe response to override\n     * a non-zero-length SSID filled with zeroes that we may have\n     * received earlier in a beacon.\n     */\n    if (ssid[1] != 0 && ni->ni_essid[0] == '\\0') {\n        ni->ni_esslen = ssid[1];\n        memset(ni->ni_essid, 0, sizeof(ni->ni_essid));\n        /* we know that ssid[1] <= IEEE80211_NWID_LEN */\n        memcpy(ni->ni_essid, &ssid[2], ssid[1]);\n    }\n    IEEE80211_ADDR_COPY(ni->ni_bssid, wh->i_addr3);\n    if (ic->ic_state == IEEE80211_S_SCAN &&\n        IEEE80211_IS_CHAN_5GHZ(ni->ni_chan)) {\n        /*\n         * During a scan on 5Ghz, prefer RSSI measured for probe\n         * response frames. i.e. don't allow beacons to lower the\n         * measured RSSI. Some 5GHz APs send beacons with much\n         * less Tx power than they use for probe responses.\n         */\n        if (isprobe || ni->ni_rssi == 0)\n            ni->ni_rssi = rxi->rxi_rssi;\n        else if (ni->ni_rssi < rxi->rxi_rssi)\n            ni->ni_rssi = rxi->rxi_rssi;\n    } else\n        ni->ni_rssi = rxi->rxi_rssi;\n    ni->ni_rstamp = rxi->rxi_tstamp;\n    memcpy(ni->ni_tstamp, tstamp, sizeof(ni->ni_tstamp));\n    ni->ni_intval = bintval;\n    ni->ni_capinfo = capinfo;\n    ni->ni_erp = erp;\n    /* NB: must be after ni_chan is setup */\n    ieee80211_setup_rates(ic, ni, rates, xrates, IEEE80211_F_DOSORT);\n#ifndef IEEE80211_STA_ONLY\n    if (ic->ic_opmode == IEEE80211_M_IBSS && is_new && isprobe) {\n        /*\n         * Fake an association so the driver can setup it's\n         * private state.  The rate set has been setup above;\n         * there is no handshake as in ap/station operation.\n         */\n        if (ic->ic_newassoc)\n            (*ic->ic_newassoc)(ic, ni, 1);\n    }\n#endif\n}\n\n#ifndef IEEE80211_STA_ONLY\n/*-\n * Probe request frame format:\n * [tlv] SSID\n * [tlv] Supported rates\n * [tlv] Extended Supported Rates (802.11g)\n * [tlv] HT Capabilities (802.11n)\n */\nvoid\nieee80211_recv_probe_req(struct ieee80211com *ic, mbuf_t m,\n                         struct ieee80211_node *ni, struct ieee80211_rxinfo *rxi)\n{\n    const struct ieee80211_frame *wh;\n    const u_int8_t *frm, *efrm;\n    const u_int8_t *ssid, *rates, *xrates, *htcaps;\n    u_int8_t rate;\n    \n    if (ic->ic_opmode == IEEE80211_M_STA ||\n        ic->ic_state != IEEE80211_S_RUN)\n        return;\n    \n    wh = mtod(m, struct ieee80211_frame *);\n    frm = (const u_int8_t *)&wh[1];\n    efrm = mtod(m, u_int8_t *) + mbuf_len(m);\n    \n    ssid = rates = xrates = htcaps = NULL;\n    while (frm + 2 <= efrm) {\n        if (frm + 2 + frm[1] > efrm) {\n            ic->ic_stats.is_rx_elem_toosmall++;\n            break;\n        }\n        switch (frm[0]) {\n            case IEEE80211_ELEMID_SSID:\n                ssid = frm;\n                break;\n            case IEEE80211_ELEMID_RATES:\n                rates = frm;\n                break;\n            case IEEE80211_ELEMID_XRATES:\n                xrates = frm;\n                break;\n            case IEEE80211_ELEMID_HTCAPS:\n                htcaps = frm;\n                break;\n        }\n        frm += 2 + frm[1];\n    }\n    /* supported rates element is mandatory */\n    if (rates == NULL || rates[1] > IEEE80211_RATE_MAXSIZE) {\n        DPRINTF((\"invalid supported rates element\\n\"));\n        return;\n    }\n    /* SSID element is mandatory */\n    if (ssid == NULL || ssid[1] > IEEE80211_NWID_LEN) {\n        DPRINTF((\"invalid SSID element\\n\"));\n        return;\n    }\n    /* check that the specified SSID (if not wildcard) matches ours */\n    if (ssid[1] != 0 && (ssid[1] != ic->ic_bss->ni_esslen ||\n                         memcmp(&ssid[2], ic->ic_bss->ni_essid, ic->ic_bss->ni_esslen))) {\n        DPRINTF((\"SSID mismatch\\n\"));\n        ic->ic_stats.is_rx_ssidmismatch++;\n        return;\n    }\n    /* refuse wildcard SSID if we're hiding our SSID in beacons */\n    if (ssid[1] == 0 && (ic->ic_userflags & IEEE80211_F_HIDENWID)) {\n        DPRINTF((\"wildcard SSID rejected\"));\n        ic->ic_stats.is_rx_ssidmismatch++;\n        return;\n    }\n    \n    if (ni == ic->ic_bss) {\n        ni = ieee80211_find_node(ic, wh->i_addr2);\n        if (ni == NULL)\n            ni = ieee80211_dup_bss(ic, wh->i_addr2);\n        if (ni == NULL)\n            return;\n        DPRINTF((\"new probe req from %s\\n\",\n                 ether_sprintf((u_int8_t *)wh->i_addr2)));\n    }\n    ni->ni_rssi = rxi->rxi_rssi;\n    ni->ni_rstamp = rxi->rxi_tstamp;\n    rate = ieee80211_setup_rates(ic, ni, rates, xrates,\n                                 IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE | IEEE80211_F_DONEGO |\n                                 IEEE80211_F_DODEL);\n    if (rate & IEEE80211_RATE_BASIC) {\n        DPRINTF((\"rate mismatch for %s\\n\",\n                 ether_sprintf((u_int8_t *)wh->i_addr2)));\n        return;\n    }\n    if (htcaps)\n        ieee80211_setup_htcaps(ni, htcaps + 2, htcaps[1]);\n    else\n        ieee80211_clear_htcaps(ni);\n    IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_PROBE_RESP, 0);\n}\n#endif\t/* IEEE80211_STA_ONLY */\n\n/*-\n * Authentication frame format:\n * [2] Authentication algorithm number\n * [2] Authentication transaction sequence number\n * [2] Status code\n */\nvoid\nieee80211_recv_auth(struct ieee80211com *ic, mbuf_t m,\n                    struct ieee80211_node *ni, struct ieee80211_rxinfo *rxi)\n{\n    const struct ieee80211_frame *wh;\n    const u_int8_t *frm;\n    u_int16_t algo, seq, status;\n    \n    /* make sure all mandatory fixed fields are present */\n    if (mbuf_len(m) < sizeof(*wh) + 6) {\n        DPRINTF((\"frame too short\\n\"));\n        return;\n    }\n    wh = mtod(m, struct ieee80211_frame *);\n    frm = (const u_int8_t *)&wh[1];\n    \n    algo   = LE_READ_2(frm); frm += 2;\n    seq    = LE_READ_2(frm); frm += 2;\n    status = LE_READ_2(frm); frm += 2;\n    DPRINTF((\"auth %d seq %d from %s\\n\", algo, seq,\n             ether_sprintf((u_int8_t *)wh->i_addr2)));\n    \n    /* only \"open\" auth mode is supported */\n    if (algo != IEEE80211_AUTH_ALG_OPEN) {\n        DPRINTF((\"unsupported auth algorithm %d from %s\\n\",\n                 algo, ether_sprintf((u_int8_t *)wh->i_addr2)));\n        ic->ic_stats.is_rx_auth_unsupported++;\n#ifndef IEEE80211_STA_ONLY\n        if (ic->ic_opmode == IEEE80211_M_HOSTAP) {\n            /* XXX hack to workaround calling convention */\n            IEEE80211_SEND_MGMT(ic, ni,\n                                IEEE80211_FC0_SUBTYPE_AUTH,\n                                IEEE80211_STATUS_ALG << 16 | ((seq + 1) & 0xfff));\n        }\n#endif\n        return;\n    }\n    ic->ic_deauth_reason = IEEE80211_REASON_UNSPECIFIED;\n    ic->ic_assoc_status = 0xffff;\n    ieee80211_auth_open(ic, wh, ni, rxi, seq, status);\n}\n\n#ifndef IEEE80211_STA_ONLY\n/*-\n * (Re)Association request frame format:\n * [2]   Capability information\n * [2]   Listen interval\n * [6*]  Current AP address (Reassociation only)\n * [tlv] SSID\n * [tlv] Supported rates\n * [tlv] Extended Supported Rates (802.11g)\n * [tlv] RSN (802.11i)\n * [tlv] QoS Capability (802.11e)\n * [tlv] HT Capabilities (802.11n)\n */\nvoid\nieee80211_recv_assoc_req(struct ieee80211com *ic, mbuf_t m,\n                         struct ieee80211_node *ni, struct ieee80211_rxinfo *rxi, int reassoc)\n{\n    const struct ieee80211_frame *wh;\n    const u_int8_t *frm, *efrm;\n    const u_int8_t *ssid, *rates, *xrates, *rsnie, *wpaie, *wmeie, *htcaps;\n    u_int16_t capinfo, bintval;\n    int resp, status = 0;\n    struct ieee80211_rsnparams rsn;\n    u_int8_t rate;\n    const u_int8_t *saveie = NULL;\n    \n    if (ic->ic_opmode != IEEE80211_M_HOSTAP ||\n        ic->ic_state != IEEE80211_S_RUN)\n        return;\n    \n    /* make sure all mandatory fixed fields are present */\n    if (mbuf_len(m) < sizeof(*wh) + (reassoc ? 10 : 4)) {\n        DPRINTF((\"frame too short\\n\"));\n        return;\n    }\n    wh = mtod(m, struct ieee80211_frame *);\n    frm = (const u_int8_t *)&wh[1];\n    efrm = mtod(m, u_int8_t *) + mbuf_len(m);\n    \n    if (!IEEE80211_ADDR_EQ(wh->i_addr3, ic->ic_bss->ni_bssid)) {\n        DPRINTF((\"ignore other bss from %s\\n\",\n                 ether_sprintf((u_int8_t *)wh->i_addr2)));\n        ic->ic_stats.is_rx_assoc_bss++;\n        return;\n    }\n    capinfo = LE_READ_2(frm); frm += 2;\n    bintval = LE_READ_2(frm); frm += 2;\n//    uint32_t tlv_len = (mtod(m, u_int8_t *) + mbuf_len(m)) - (u_int8_t *)&wh[1] + 1 - 2 - 2;\n//    ieee80211_save_ie_tlv(frm, &ni->ni_rsnie_tlv, &ni->ni_rsnie_tlv_len, tlv_len);\n    if (reassoc) {\n        frm += IEEE80211_ADDR_LEN;    /* skip current AP address */\n        resp = IEEE80211_FC0_SUBTYPE_REASSOC_RESP;\n    } else\n        resp = IEEE80211_FC0_SUBTYPE_ASSOC_RESP;\n    \n    ssid = rates = xrates = rsnie = wpaie = wmeie = htcaps = NULL;\n    while (frm + 2 <= efrm) {\n        if (frm + 2 + frm[1] > efrm) {\n            ic->ic_stats.is_rx_elem_toosmall++;\n            break;\n        }\n        switch (frm[0]) {\n            case IEEE80211_ELEMID_SSID:\n                ssid = frm;\n                break;\n            case IEEE80211_ELEMID_RATES:\n                rates = frm;\n                break;\n            case IEEE80211_ELEMID_XRATES:\n                xrates = frm;\n                break;\n            case IEEE80211_ELEMID_RSN:\n                rsnie = frm;\n                break;\n            case IEEE80211_ELEMID_QOS_CAP:\n                break;\n            case IEEE80211_ELEMID_HTCAPS:\n                htcaps = frm;\n                break;\n            case IEEE80211_ELEMID_VENDOR:\n                if (frm[1] < 4) {\n                    ic->ic_stats.is_rx_elem_toosmall++;\n                    break;\n                }\n                if (memcmp(frm + 2, MICROSOFT_OUI, 3) == 0) {\n                    if (frm[5] == 1)\n                        wpaie = frm;\n                    /* WME info IE: len=7 type=2 subtype=0 */\n                    if (frm[1] == 7 && frm[5] == 2 && frm[6] == 0)\n                        wmeie = frm;\n                }\n                break;\n        }\n        frm += 2 + frm[1];\n    }\n    /* supported rates element is mandatory */\n    if (rates == NULL || rates[1] > IEEE80211_RATE_MAXSIZE) {\n        DPRINTF((\"invalid supported rates element\\n\"));\n        return;\n    }\n    /* SSID element is mandatory */\n    if (ssid == NULL || ssid[1] > IEEE80211_NWID_LEN) {\n        DPRINTF((\"invalid SSID element\\n\"));\n        return;\n    }\n    /* check that the specified SSID matches ours */\n    if (ssid[1] != ic->ic_bss->ni_esslen ||\n        memcmp(&ssid[2], ic->ic_bss->ni_essid, ic->ic_bss->ni_esslen)) {\n        DPRINTF((\"SSID mismatch\\n\"));\n        ic->ic_stats.is_rx_ssidmismatch++;\n        return;\n    }\n    \n    if (ni->ni_state != IEEE80211_STA_AUTH &&\n        ni->ni_state != IEEE80211_STA_ASSOC) {\n        DPRINTF((\"deny %sassoc from %s, not authenticated\\n\",\n                 reassoc ? \"re\" : \"\",\n                 ether_sprintf((u_int8_t *)wh->i_addr2)));\n        ni = ieee80211_find_node(ic, wh->i_addr2);\n        if (ni == NULL)\n            ni = ieee80211_dup_bss(ic, wh->i_addr2);\n        if (ni != NULL) {\n            IEEE80211_SEND_MGMT(ic, ni,\n                                IEEE80211_FC0_SUBTYPE_DEAUTH,\n                                IEEE80211_REASON_ASSOC_NOT_AUTHED);\n        }\n        ic->ic_stats.is_rx_assoc_notauth++;\n        return;\n    }\n    \n    if (ni->ni_state == IEEE80211_STA_ASSOC &&\n        (ni->ni_flags & IEEE80211_NODE_MFP)) {\n        if (ni->ni_flags & IEEE80211_NODE_SA_QUERY_FAILED) {\n            /* send a protected Disassociate frame */\n            IEEE80211_SEND_MGMT(ic, ni,\n                                IEEE80211_FC0_SUBTYPE_DISASSOC,\n                                IEEE80211_REASON_AUTH_EXPIRE);\n            /* terminate the old SA */\n            ieee80211_node_leave(ic, ni);\n        } else {\n            /* reject the (Re)Association Request temporarily */\n            IEEE80211_SEND_MGMT(ic, ni, resp,\n                                IEEE80211_STATUS_TRY_AGAIN_LATER);\n            /* start SA Query procedure if not already engaged */\n            if (!(ni->ni_flags & IEEE80211_NODE_SA_QUERY))\n                ieee80211_sa_query_request(ic, ni);\n            /* do not modify association state */\n        }\n        return;\n    }\n    \n    if (!(capinfo & IEEE80211_CAPINFO_ESS)) {\n        ic->ic_stats.is_rx_assoc_capmismatch++;\n        status = IEEE80211_STATUS_CAPINFO;\n        goto end;\n    }\n    rate = ieee80211_setup_rates(ic, ni, rates, xrates,\n                                 IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE | IEEE80211_F_DONEGO |\n                                 IEEE80211_F_DODEL);\n    if (rate & IEEE80211_RATE_BASIC) {\n        ic->ic_stats.is_rx_assoc_norate++;\n        status = IEEE80211_STATUS_BASIC_RATE;\n        goto end;\n    }\n    \n    ni->ni_rsnprotos = IEEE80211_PROTO_NONE;\n    ni->ni_supported_rsnprotos = IEEE80211_PROTO_NONE;\n    ni->ni_rsnakms = 0;\n    ni->ni_supported_rsnakms = 0;\n    ni->ni_rsnciphers = 0;\n    ni->ni_rsngroupcipher = (enum ieee80211_cipher)0;\n    ni->ni_rsngroupmgmtcipher = (enum ieee80211_cipher)0;\n    ni->ni_rsncaps = 0;\n    \n    /*\n     * A station should never include both a WPA and an RSN IE\n     * in its (Re)Association Requests, but if it does, we only\n     * consider the IE of the highest version of the protocol\n     * that is allowed (ie RSN over WPA).\n     */\n    if (rsnie != NULL) {\n        status = ieee80211_parse_rsn(ic, rsnie, &rsn);\n        if (status != 0)\n            goto end;\n        ni->ni_supported_rsnprotos = IEEE80211_PROTO_RSN;\n        ni->ni_supported_rsnakms = rsn.rsn_akms;\n        if ((ic->ic_flags & IEEE80211_F_RSNON) &&\n            (ic->ic_rsnprotos & IEEE80211_PROTO_RSN)) {\n            ni->ni_rsnprotos = IEEE80211_PROTO_RSN;\n            saveie = rsnie;\n        }\n    } else if (wpaie != NULL) {\n        status = ieee80211_parse_wpa(ic, wpaie, &rsn);\n        if (status != 0)\n            goto end;\n        ni->ni_supported_rsnprotos = IEEE80211_PROTO_WPA;\n        ni->ni_supported_rsnakms = rsn.rsn_akms;\n        if ((ic->ic_flags & IEEE80211_F_RSNON) &&\n            (ic->ic_rsnprotos & IEEE80211_PROTO_WPA)) {\n            ni->ni_rsnprotos = IEEE80211_PROTO_WPA;\n            saveie = wpaie;\n        }\n    }\n    \n    if (ic->ic_flags & IEEE80211_F_QOS) {\n        if (wmeie != NULL)\n            ni->ni_flags |= IEEE80211_NODE_QOS;\n        else    /* for Reassociation */\n            ni->ni_flags &= ~IEEE80211_NODE_QOS;\n    }\n    \n    if (ic->ic_flags & IEEE80211_F_RSNON) {\n        if (ni->ni_rsnprotos == IEEE80211_PROTO_NONE) {\n            /*\n             * In an RSN, an AP shall not associate with STAs\n             * that fail to include the RSN IE in the\n             * (Re)Association Request.\n             */\n            status = IEEE80211_STATUS_IE_INVALID;\n            goto end;\n        }\n        /*\n         * The initiating STA's RSN IE shall include one authentication\n         * and pairwise cipher suite among those advertised by the\n         * targeted AP.  It shall also specify the group cipher suite\n         * specified by the targeted AP.\n         */\n        if (rsn.rsn_nakms != 1 ||\n            !(rsn.rsn_akms & ic->ic_bss->ni_rsnakms)) {\n            status = IEEE80211_STATUS_BAD_AKMP;\n            ni->ni_rsnprotos = IEEE80211_PROTO_NONE;\n            goto end;\n        }\n        if (rsn.rsn_nciphers != 1 ||\n            !(rsn.rsn_ciphers & ic->ic_bss->ni_rsnciphers)) {\n            status = IEEE80211_STATUS_BAD_PAIRWISE_CIPHER;\n            ni->ni_rsnprotos = IEEE80211_PROTO_NONE;\n            goto end;\n        }\n        if (rsn.rsn_groupcipher != ic->ic_bss->ni_rsngroupcipher) {\n            status = IEEE80211_STATUS_BAD_GROUP_CIPHER;\n            ni->ni_rsnprotos = IEEE80211_PROTO_NONE;\n            goto end;\n        }\n        \n        if ((ic->ic_bss->ni_rsncaps & IEEE80211_RSNCAP_MFPR) &&\n            !(rsn.rsn_caps & IEEE80211_RSNCAP_MFPC)) {\n            status = IEEE80211_STATUS_MFP_POLICY;\n            ni->ni_rsnprotos = IEEE80211_PROTO_NONE;\n            goto end;\n        }\n        if ((ic->ic_bss->ni_rsncaps & IEEE80211_RSNCAP_MFPC) &&\n            (rsn.rsn_caps & (IEEE80211_RSNCAP_MFPC |\n                             IEEE80211_RSNCAP_MFPR)) == IEEE80211_RSNCAP_MFPR) {\n            /* STA advertises an invalid setting */\n            status = IEEE80211_STATUS_MFP_POLICY;\n            ni->ni_rsnprotos = IEEE80211_PROTO_NONE;\n            goto end;\n        }\n        /*\n         * A STA that has associated with Management Frame Protection\n         * enabled shall not use cipher suite pairwise selector WEP40,\n         * WEP104, TKIP, or \"Use Group cipher suite\".\n         */\n        if ((rsn.rsn_caps & IEEE80211_RSNCAP_MFPC) &&\n            (rsn.rsn_ciphers != IEEE80211_CIPHER_CCMP ||\n             rsn.rsn_groupmgmtcipher !=\n             ic->ic_bss->ni_rsngroupmgmtcipher)) {\n            status = IEEE80211_STATUS_MFP_POLICY;\n            ni->ni_rsnprotos = IEEE80211_PROTO_NONE;\n            goto end;\n        }\n        \n        /*\n         * Disallow new associations using TKIP if countermeasures\n         * are active.\n         */\n        if ((ic->ic_flags & IEEE80211_F_COUNTERM) &&\n            (rsn.rsn_ciphers == IEEE80211_CIPHER_TKIP ||\n             rsn.rsn_groupcipher == IEEE80211_CIPHER_TKIP)) {\n            status = IEEE80211_STATUS_CIPHER_REJ_POLICY;\n            ni->ni_rsnprotos = IEEE80211_PROTO_NONE;\n            goto end;\n        }\n        \n        /* everything looks fine, save IE and parameters */\n        if (saveie == NULL ||\n            ieee80211_save_ie(saveie, &ni->ni_rsnie) != 0) {\n            status = IEEE80211_STATUS_TOOMANY;\n            ni->ni_rsnprotos = IEEE80211_PROTO_NONE;\n            goto end;\n        }\n        ni->ni_rsnakms = rsn.rsn_akms;\n        ni->ni_rsnciphers = rsn.rsn_ciphers;\n        ni->ni_rsngroupcipher = ic->ic_bss->ni_rsngroupcipher;\n        ni->ni_rsngroupmgmtcipher = ic->ic_bss->ni_rsngroupmgmtcipher;\n        ni->ni_rsncaps = rsn.rsn_caps;\n        \n        if (ieee80211_is_8021x_akm((enum ieee80211_akm)ni->ni_rsnakms)) {\n            struct ieee80211_pmk *pmk = NULL;\n            const u_int8_t *pmkid = rsn.rsn_pmkids;\n            /*\n             * Check if we have a cached PMK entry matching one\n             * of the PMKIDs specified in the RSN IE.\n             */\n            while (rsn.rsn_npmkids-- > 0) {\n                pmk = ieee80211_pmksa_find(ic, ni, pmkid);\n                if (pmk != NULL)\n                    break;\n                pmkid += IEEE80211_PMKID_LEN;\n            }\n            if (pmk != NULL) {\n                memcpy(ni->ni_pmk, pmk->pmk_key,\n                       IEEE80211_PMK_LEN);\n                memcpy(ni->ni_pmkid, pmk->pmk_pmkid,\n                       IEEE80211_PMKID_LEN);\n                ni->ni_flags |= IEEE80211_NODE_PMK;\n            }\n        }\n    }\n    \n    ni->ni_rssi = rxi->rxi_rssi;\n    ni->ni_rstamp = rxi->rxi_tstamp;\n    ni->ni_intval = bintval;\n    ni->ni_capinfo = capinfo;\n    ni->ni_chan = ic->ic_bss->ni_chan;\n    if (htcaps)\n        ieee80211_setup_htcaps(ni, htcaps + 2, htcaps[1]);\n    else\n        ieee80211_clear_htcaps(ni);\nend:\n    if (status != 0) {\n        IEEE80211_SEND_MGMT(ic, ni, resp, status);\n        ieee80211_node_leave(ic, ni);\n    } else\n        ieee80211_node_join(ic, ni, resp);\n}\n#endif\t/* IEEE80211_STA_ONLY */\n\n/*-\n * (Re)Association response frame format:\n * [2]   Capability information\n * [2]   Status code\n * [2]   Association ID (AID)\n * [tlv] Supported rates\n * [tlv] Extended Supported Rates (802.11g)\n * [tlv] EDCA Parameter Set (802.11e)\n * [tlv] HT Capabilities (802.11n)\n * [tlv] HT Operation (802.11n)\n */\nvoid\nieee80211_recv_assoc_resp(struct ieee80211com *ic, mbuf_t m,\n                          struct ieee80211_node *ni, int reassoc)\n{\n    XYLog(\"%s reassoc=%d\\n\", __FUNCTION__, reassoc);\n    struct _ifnet *ifp = &ic->ic_if;\n    const struct ieee80211_frame *wh;\n    const u_int8_t *frm, *efrm;\n    const u_int8_t *rates, *xrates, *edcaie, *wmmie, *htcaps, *htop;\n    const uint8_t *vhtcap;\n    const uint8_t *vhtopmode;\n    const uint8_t *hecap;\n    const uint8_t *heopmode;\n    u_int16_t capinfo, status, associd;\n    u_int8_t rate;\n    \n    if (ic->ic_opmode != IEEE80211_M_STA ||\n        ic->ic_state != IEEE80211_S_ASSOC) {\n        ic->ic_stats.is_rx_mgtdiscard++;\n        return;\n    }\n    \n    /* make sure all mandatory fixed fields are present */\n    if (mbuf_len(m) < sizeof(*wh) + 6) {\n        DPRINTF((\"frame too short\\n\"));\n        return;\n    }\n    wh = mtod(m, struct ieee80211_frame *);\n    frm = (const u_int8_t *)&wh[1];\n    efrm = mtod(m, u_int8_t *) + mbuf_len(m);\n    \n    capinfo = LE_READ_2(frm); frm += 2;\n    status =  LE_READ_2(frm); frm += 2;\n\n    ic->ic_assoc_status = status;\n    if (status == IEEE80211_STATUS_SUCCESS) {\n        if (ic->ic_event_handler) {\n            (*ic->ic_event_handler)(ic, IEEE80211_EVT_STA_ASSOC_DONE, NULL);\n        }\n    }\n    \n    if (status != IEEE80211_STATUS_SUCCESS) {\n        if (ifp->if_flags & IFF_DEBUG)\n            XYLog(\"%s: %sassociation failed (status %d)\"\n                  \" for %s\\n\", ifp->if_xname,\n                  reassoc ?  \"re\" : \"\",\n                  status, ether_sprintf((u_int8_t *)wh->i_addr3));\n        if (ni != ic->ic_bss)\n            ni->ni_fails++;\n        ic->ic_stats.is_rx_auth_fail++;\n        return;\n    }\n    associd = LE_READ_2(frm); frm += 2;\n    \n    rates = xrates = edcaie = wmmie = htcaps = htop = vhtcap = vhtopmode = hecap = heopmode = NULL;\n    while (frm + 2 <= efrm) {\n        if (frm + 2 + frm[1] > efrm) {\n            ic->ic_stats.is_rx_elem_toosmall++;\n            break;\n        }\n        switch (frm[0]) {\n            case IEEE80211_ELEMID_RATES:\n                rates = frm;\n                break;\n            case IEEE80211_ELEMID_XRATES:\n                xrates = frm;\n                break;\n            case IEEE80211_ELEMID_EDCAPARMS:\n                edcaie = frm;\n                break;\n            case IEEE80211_ELEMID_HTCAPS:\n                htcaps = frm;\n                break;\n            case IEEE80211_ELEMID_HTOP:\n                htop = frm;\n                break;\n            case IEEE80211_ELEMID_VHT_CAP:\n                vhtcap = frm;\n                break;\n            case IEEE80211_ELEMID_VHT_OPMODE:\n                vhtopmode = frm;\n                break;\n            case IEEE80211_ELEMID_VENDOR:\n                if (frm[1] < 4) {\n                    ic->ic_stats.is_rx_elem_toosmall++;\n                    break;\n                }\n                if (memcmp(frm + 2, MICROSOFT_OUI, 3) == 0) {\n                    if (frm[1] >= 5 && frm[5] == 2 && frm[6] == 1)\n                        wmmie = frm;\n                }\n                break;\n            case IEEE80211_ELEMID_EXTENSION:\n                switch (frm[2]) {\n                    case IEEE80211_ELEMID_EXT_HE_MU_EDCA:\n                        break;\n                    case IEEE80211_ELEMID_EXT_HE_CAPABILITY:\n                        hecap = frm;\n                        break;\n                    case IEEE80211_ELEMID_EXT_HE_OPERATION:\n                        heopmode = frm;\n                        break;\n                    case IEEE80211_ELEMID_EXT_UORA:\n                        break;\n                    case IEEE80211_ELEMID_EXT_MAX_CHANNEL_SWITCH_TIME:\n                        break;\n                    case IEEE80211_ELEMID_EXT_MULTIPLE_BSSID_CONFIGURATION:\n                        break;\n                    case IEEE80211_ELEMID_EXT_HE_SPR:\n                        break;\n                    case IEEE80211_ELEMID_EXT_HE_6GHZ_CAPA:\n                        break;\n                }\n                break;\n        }\n        frm += 2 + frm[1];\n    }\n    /* supported rates element is mandatory */\n    if (rates == NULL || rates[1] > IEEE80211_RATE_MAXSIZE) {\n        DPRINTF((\"invalid supported rates element\\n\"));\n        return;\n    }\n    rate = ieee80211_setup_rates(ic, ni, rates, xrates,\n                                 IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE | IEEE80211_F_DONEGO |\n                                 IEEE80211_F_DODEL);\n    if (rate & IEEE80211_RATE_BASIC) {\n        DPRINTF((\"rate mismatch for %s\\n\",\n                 ether_sprintf((u_int8_t *)wh->i_addr2)));\n        ic->ic_stats.is_rx_assoc_norate++;\n        return;\n    }\n    ni->ni_capinfo = capinfo;\n    ni->ni_associd = associd;\n    if (edcaie != NULL || wmmie != NULL) {\n        /* force update of EDCA parameters */\n        ic->ic_edca_updtcount = -1;\n        \n        if ((edcaie != NULL &&\n             ieee80211_parse_edca_params(ic, edcaie) == 0) ||\n            (wmmie != NULL &&\n             ieee80211_parse_wmm_params(ic, wmmie) == 0))\n            ni->ni_flags |= IEEE80211_NODE_QOS;\n        else    /* for Reassociation */\n            ni->ni_flags &= ~IEEE80211_NODE_QOS;\n    }\n    if (htcaps)\n        ieee80211_setup_htcaps(ni, htcaps + 2, htcaps[1]);\n    if (htop)\n        ieee80211_setup_htop(ni, htop + 2, htop[1], 0);\n    if (vhtcap != NULL && vhtopmode != NULL) {\n        ieee80211_setup_vhtcaps(ic, ni, vhtcap);\n        ieee80211_setup_vhtopmode(ni, vhtopmode);\n    }\n    if (hecap != NULL && heopmode != NULL) {\n        ieee80211_setup_hecaps(ni, hecap + 3, hecap[1] - 1);\n        ieee80211_setup_heop(ni, heopmode + 3, heopmode[1] - 1);\n    }\n\n    ieee80211_ht_negotiate(ic, ni);\n    ieee80211_vht_negotiate(ic, ni);\n    if (hecap != NULL && heopmode != NULL) {\n        ieee80211_he_negotiate(ic, ni);\n    }\n    \n    /* Hop into 11n/11ac/11ax mode after associating to an HT AP in a legacy mode. */\n    if (ni->ni_flags & IEEE80211_NODE_HE)\n        ieee80211_setmode(ic, IEEE80211_MODE_11AX);\n    else if (ni->ni_flags & IEEE80211_NODE_VHT)\n        ieee80211_setmode(ic, IEEE80211_MODE_11AC);\n    else if (ni->ni_flags & IEEE80211_NODE_HT)\n        ieee80211_setmode(ic, IEEE80211_MODE_11N);\n    else\n        ieee80211_setmode(ic, ieee80211_chan2mode(ic, ni->ni_chan));\n    \n    ieee80211_sta_set_rx_nss(ic, ni);\n    /*\n     * Reset the erp state (mostly the slot time) now that\n     * our operating mode has been nailed down.\n     */\n    ieee80211_reset_erp(ic);\n    \n    /*\n     * Configure state now that we are associated.\n     */\n    if (ic->ic_curmode == IEEE80211_MODE_11A ||\n        (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE))\n        ic->ic_flags |= IEEE80211_F_SHPREAMBLE;\n    else\n        ic->ic_flags &= ~IEEE80211_F_SHPREAMBLE;\n    \n    ieee80211_set_shortslottime(ic,\n                                ic->ic_curmode == IEEE80211_MODE_11A ||\n                                (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME));\n    /*\n     * Honor ERP protection.\n     */\n    if ((ic->ic_curmode == IEEE80211_MODE_11G ||\n         (ic->ic_curmode == IEEE80211_MODE_11N &&\n          IEEE80211_IS_CHAN_2GHZ(ni->ni_chan))) &&\n        (ni->ni_erp & IEEE80211_ERP_USE_PROTECTION))\n        ic->ic_flags |= IEEE80211_F_USEPROT;\n    else\n        ic->ic_flags &= ~IEEE80211_F_USEPROT;\n    /*\n     * If not an RSNA, mark the port as valid, otherwise wait for\n     * 802.1X authentication and 4-way handshake to complete..\n     */\n    if (ic->ic_flags & IEEE80211_F_RSNON) {\n        /* XXX ic->ic_mgt_timer = 5; */\n        ni->ni_rsn_supp_state = RSNA_SUPP_PTKSTART;\n    } else if (ic->ic_flags & IEEE80211_F_WEPON)\n        ni->ni_flags |= IEEE80211_NODE_TXRXPROT;\n    \n    ieee80211_new_state(ic, IEEE80211_S_RUN,\n                        IEEE80211_FC0_SUBTYPE_ASSOC_RESP);\n}\n\n/*-\n * Deauthentication frame format:\n * [2] Reason code\n */\nvoid\nieee80211_recv_deauth(struct ieee80211com *ic, mbuf_t m,\n                      struct ieee80211_node *ni)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    const struct ieee80211_frame *wh;\n    const u_int8_t *frm;\n    u_int16_t reason;\n    \n    /* make sure all mandatory fixed fields are present */\n    if (mbuf_len(m) < sizeof(*wh) + 2) {\n        DPRINTF((\"frame too short\\n\"));\n        return;\n    }\n    wh = mtod(m, struct ieee80211_frame *);\n    frm = (const u_int8_t *)&wh[1];\n    \n    reason = LE_READ_2(frm);\n\n    XYLog(\"Deauth received, reason %d\\n\", reason);\n    ic->ic_deauth_reason = reason;\n    if (ic->ic_event_handler) {\n        (*ic->ic_event_handler)(ic, IEEE80211_EVT_STA_DEAUTH, NULL);\n    }\n    \n    ic->ic_stats.is_rx_deauth++;\n    switch (ic->ic_opmode) {\n        case IEEE80211_M_STA: {\n            int bgscan = ((ic->ic_flags & IEEE80211_F_BGSCAN) &&\n                          ic->ic_state == IEEE80211_S_RUN);\n            int roamscan = bgscan &&\n                        (ic->ic_flags & IEEE80211_F_DISABLE_BG_AUTO_CONNECT) == 0;\n            int stay_auth = ((ic->ic_userflags & IEEE80211_F_STAYAUTH) &&\n                             ic->ic_state >= IEEE80211_S_AUTH);\n            if (!(roamscan || stay_auth))\n                ieee80211_new_state(ic, IEEE80211_S_AUTH,\n                                    IEEE80211_FC0_SUBTYPE_DEAUTH);\n        }\n            break;\n#ifndef IEEE80211_STA_ONLY\n        case IEEE80211_M_HOSTAP:\n            if (ni != ic->ic_bss) {\n                int stay_auth =\n                ((ic->ic_userflags & IEEE80211_F_STAYAUTH) &&\n                 (ni->ni_state == IEEE80211_STA_AUTH ||\n                  ni->ni_state == IEEE80211_STA_ASSOC));\n                if (ic->ic_if.if_flags & IFF_DEBUG)\n                    XYLog(\"%s: station %s deauthenticated \"\n                          \"by peer (reason %d)\\n\",\n                          ic->ic_if.if_xname,\n                          ether_sprintf(ni->ni_macaddr),\n                          reason);\n                if (!stay_auth)\n                    ieee80211_node_leave(ic, ni);\n            }\n            break;\n#endif\n        default:\n            break;\n    }\n}\n\n/*-\n * Disassociation frame format:\n * [2] Reason code\n */\nvoid\nieee80211_recv_disassoc(struct ieee80211com *ic, mbuf_t m,\n                        struct ieee80211_node *ni)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    const struct ieee80211_frame *wh;\n    const u_int8_t *frm;\n    u_int16_t reason;\n    \n    /* make sure all mandatory fixed fields are present */\n    if (mbuf_len(m) < sizeof(*wh) + 2) {\n        DPRINTF((\"frame too short\\n\"));\n        return;\n    }\n    wh = mtod(m, struct ieee80211_frame *);\n    frm = (const u_int8_t *)&wh[1];\n    \n    reason = LE_READ_2(frm);\n    \n    XYLog(\"Disassoc received, reason %d\\n\", reason);\n    \n    ic->ic_stats.is_rx_disassoc++;\n    switch (ic->ic_opmode) {\n        case IEEE80211_M_STA: {\n            int bgscan = ((ic->ic_flags & IEEE80211_F_BGSCAN) &&\n                          ic->ic_state == IEEE80211_S_RUN);\n            int roamscan = bgscan &&\n                        (ic->ic_flags & IEEE80211_F_DISABLE_BG_AUTO_CONNECT) == 0;\n            if (!roamscan) /* ignore disassoc during bgscan */\n                ieee80211_new_state(ic, IEEE80211_S_ASSOC,\n                                    IEEE80211_FC0_SUBTYPE_DISASSOC);\n        }\n            break;\n#ifndef IEEE80211_STA_ONLY\n        case IEEE80211_M_HOSTAP:\n            if (ni != ic->ic_bss) {\n                if (ic->ic_if.if_flags & IFF_DEBUG)\n                    XYLog(\"%s: station %s disassociated \"\n                          \"by peer (reason %d)\\n\",\n                          ic->ic_if.if_xname,\n                          ether_sprintf(ni->ni_macaddr),\n                          reason);\n                ieee80211_node_leave(ic, ni);\n            }\n            break;\n#endif\n        default:\n            break;\n    }\n}\n\n/*-\n * ADDBA Request frame format:\n * [1] Category\n * [1] Action\n * [1] Dialog Token\n * [2] Block Ack Parameter Set\n * [2] Block Ack Timeout Value\n * [2] Block Ack Starting Sequence Control\n */\nvoid\nieee80211_recv_addba_req(struct ieee80211com *ic, mbuf_t m,\n                         struct ieee80211_node *ni)\n{\n    const struct ieee80211_frame *wh;\n    const u_int8_t *frm;\n    struct ieee80211_rx_ba *ba;\n    u_int16_t params, ssn, bufsz, timeout;\n    u_int8_t token, tid;\n    int err = 0;\n    \n    /* Ignore if we are not ready to receive data frames. */\n    if (ic->ic_state != IEEE80211_S_RUN ||\n        ((ic->ic_flags & IEEE80211_F_RSNON) && !ni->ni_port_valid))\n        return;\n    \n    if (!(ni->ni_flags & IEEE80211_NODE_HT)) {\n        DPRINTF((\"received ADDBA req from non-HT STA %s\\n\",\n                 ether_sprintf(ni->ni_macaddr)));\n        return;\n    }\n    if (mbuf_len(m) < sizeof(*wh) + 9) {\n        DPRINTF((\"frame too short\\n\"));\n        return;\n    }\n    \n    /* MLME-ADDBA.indication */\n    wh = mtod(m, struct ieee80211_frame *);\n    frm = (const u_int8_t *)&wh[1];\n    \n    token = frm[2];\n    params = LE_READ_2(&frm[3]);\n    tid = ((params & IEEE80211_ADDBA_TID_MASK) >>\n           IEEE80211_ADDBA_TID_SHIFT);\n    bufsz = (params & IEEE80211_ADDBA_BUFSZ_MASK) >>\n    IEEE80211_ADDBA_BUFSZ_SHIFT;\n    timeout = LE_READ_2(&frm[5]);\n    ssn = LE_READ_2(&frm[7]) >> 4;\n    \n    ba = &ni->ni_rx_ba[tid];\n    /* The driver is still processing an ADDBA request for this tid. */\n    if (ba->ba_state == IEEE80211_BA_REQUESTED)\n        return;\n    /* If we are in the process of roaming between APs, ignore. */\n    if ((ic->ic_flags & IEEE80211_F_BGSCAN) &&\n        ((ic->ic_flags & IEEE80211_F_DISABLE_BG_AUTO_CONNECT) == 0) &&\n        (ic->ic_xflags & IEEE80211_F_TX_MGMT_ONLY))\n        return;\n    /* check if we already have a Block Ack agreement for this RA/TID */\n    if (ba->ba_state == IEEE80211_BA_AGREED) {\n        /* XXX should we update the timeout value? */\n        /* reset Block Ack inactivity timer */\n        if (ba->ba_timeout_val != 0)\n            timeout_add_usec(&ba->ba_to, ba->ba_timeout_val);\n        \n        /* check if it's a Protected Block Ack agreement */\n        if (!(ni->ni_flags & IEEE80211_NODE_MFP) ||\n            !(ni->ni_rsncaps & IEEE80211_RSNCAP_PBAC))\n            return;    /* not a PBAC, ignore */\n        \n        /* PBAC: treat the ADDBA Request like a BlockAckReq */\n        if (SEQ_LT(ba->ba_winstart, ssn)) {\n            struct mbuf_list ml = MBUF_LIST_INITIALIZER();\n            ieee80211_ba_move_window(ic, ni, tid, ssn, &ml);\n            if_input(&ic->ic_if, &ml);\n        }\n        return;\n    }\n    \n    /* if PBAC required but RA does not support it, refuse request */\n    if ((ic->ic_flags & IEEE80211_F_PBAR) &&\n        (!(ni->ni_flags & IEEE80211_NODE_MFP) ||\n         !(ni->ni_rsncaps & IEEE80211_RSNCAP_PBAC)))\n        goto refuse;\n    /*\n     * If the TID for which the Block Ack agreement is requested is\n     * configured with a no-ACK policy, refuse the agreement.\n     */\n    if (ic->ic_tid_noack & (1 << tid))\n        goto refuse;\n    \n    /* check that we support the requested Block Ack Policy */\n    if (!(ic->ic_htcaps & IEEE80211_HTCAP_DELAYEDBA) &&\n        !(params & IEEE80211_ADDBA_BA_POLICY))\n        goto refuse;\n    \n    /* setup Block Ack agreement */\n    ba->ba_state = IEEE80211_BA_REQUESTED;\n    ba->ba_timeout_val = timeout * IEEE80211_DUR_TU;\n    ba->ba_ni = ni;\n    ba->ba_token = token;\n    timeout_set(&ba->ba_to, ieee80211_rx_ba_timeout, ba);\n    timeout_set(&ba->ba_gap_to, ieee80211_input_ba_gap_timeout, ba);\n    ba->ba_gapwait = 0;\n    ba->ba_winsize = bufsz;\n    if (ba->ba_winsize == 0 || ba->ba_winsize > IEEE80211_BA_MAX_WINSZ)\n        ba->ba_winsize = IEEE80211_BA_MAX_WINSZ;\n    ba->ba_params = (params & IEEE80211_ADDBA_BA_POLICY);\n    ba->ba_params |= ((ba->ba_winsize << IEEE80211_ADDBA_BUFSZ_SHIFT) |\n                      (tid << IEEE80211_ADDBA_TID_SHIFT));\n    if (ic->ic_caps & IEEE80211_C_AMSDU_IN_AMPDU) {\n        ba->ba_params |= IEEE80211_ADDBA_AMSDU;\n    }\n    ba->ba_winstart = ssn;\n    ba->ba_winend = (ba->ba_winstart + ba->ba_winsize - 1) & 0xfff;\n    /* allocate and setup our reordering buffer */\n    ba->ba_buf = (struct ieee80211_ba_buf*)malloc(IEEE80211_BA_MAX_WINSZ * sizeof(struct ieee80211_ba_buf), 0, 0);\n    if (ba->ba_buf == NULL)\n        goto refuse;\n    \n    ba->ba_head = 0;\n    \n    /* notify drivers of this new Block Ack agreement */\n    if (ic->ic_ampdu_rx_start != NULL)\n        err = ic->ic_ampdu_rx_start(ic, ni, tid);\n    if (err == EBUSY) {\n        /* driver will accept or refuse agreement when done */\n        return;\n    } else if (err) {\n        /* driver failed to setup, rollback */\n        ieee80211_addba_req_refuse(ic, ni, tid);\n    } else\n        ieee80211_addba_req_accept(ic, ni, tid);\n    return;\n    \nrefuse:\n    /* MLME-ADDBA.response */\n    IEEE80211_SEND_ACTION(ic, ni, IEEE80211_CATEG_BA,\n                          IEEE80211_ACTION_ADDBA_RESP,\n                          IEEE80211_STATUS_REFUSED << 16 | token << 8 | tid);\n}\n\nvoid\nieee80211_addba_req_accept(struct ieee80211com *ic, struct ieee80211_node *ni,\n                           uint8_t tid)\n{\n    struct ieee80211_rx_ba *ba = &ni->ni_rx_ba[tid];\n    \n    ba->ba_state = IEEE80211_BA_AGREED;\n    ic->ic_stats.is_ht_rx_ba_agreements++;\n    /* start Block Ack inactivity timer */\n    if (ba->ba_timeout_val != 0)\n        timeout_add_usec(&ba->ba_to, ba->ba_timeout_val);\n    \n    /* MLME-ADDBA.response */\n    IEEE80211_SEND_ACTION(ic, ni, IEEE80211_CATEG_BA,\n                          IEEE80211_ACTION_ADDBA_RESP,\n                          IEEE80211_STATUS_SUCCESS << 16 | ba->ba_token << 8 | tid);\n}\n\nvoid\nieee80211_addba_req_refuse(struct ieee80211com *ic, struct ieee80211_node *ni,\n                           uint8_t tid)\n{\n    struct ieee80211_rx_ba *ba = &ni->ni_rx_ba[tid];\n    \n    free(ba->ba_buf);\n    ba->ba_buf = NULL;\n    ba->ba_state = IEEE80211_BA_INIT;\n    \n    /* MLME-ADDBA.response */\n    IEEE80211_SEND_ACTION(ic, ni, IEEE80211_CATEG_BA,\n                          IEEE80211_ACTION_ADDBA_RESP,\n                          IEEE80211_STATUS_REFUSED << 16 | ba->ba_token << 8 | tid);\n}\n\n/*-\n * ADDBA Response frame format:\n * [1] Category\n * [1] Action\n * [1] Dialog Token\n * [2] Status Code\n * [2] Block Ack Parameter Set\n * [2] Block Ack Timeout Value\n */\nvoid\nieee80211_recv_addba_resp(struct ieee80211com *ic, mbuf_t m,\n                          struct ieee80211_node *ni)\n{\n    const struct ieee80211_frame *wh;\n    const u_int8_t *frm;\n    struct ieee80211_tx_ba *ba;\n    u_int16_t status, params, bufsz, timeout;\n    u_int8_t token, tid;\n    int err = 0;\n    \n    if (mbuf_len(m) < sizeof(*wh) + 9) {\n        DPRINTF((\"frame too short\\n\"));\n        return;\n    }\n    wh = mtod(m, struct ieee80211_frame *);\n    frm = (const u_int8_t *)&wh[1];\n    \n    token = frm[2];\n    status = LE_READ_2(&frm[3]);\n    params = LE_READ_2(&frm[5]);\n    tid = (params >> 2) & 0xf;\n    bufsz = (params >> 6) & 0x3ff;\n    timeout = LE_READ_2(&frm[7]);\n    \n    DPRINTF((\"received ADDBA resp from %s, TID %d, status %d\\n\",\n             ether_sprintf(ni->ni_macaddr), tid, status));\n    \n    /*\n     * Ignore if no ADDBA request has been sent for this RA/TID or\n     * if we already have a Block Ack agreement.\n     */\n    ba = &ni->ni_tx_ba[tid];\n    if (ba->ba_state != IEEE80211_BA_REQUESTED) {\n        DPRINTF((\"no matching ADDBA req found\\n\"));\n        return;\n    }\n    if (token != ba->ba_token) {\n        DPRINTF((\"ignoring ADDBA resp from %s: token %x!=%x\\n\",\n                 ether_sprintf(ni->ni_macaddr), token, ba->ba_token));\n        return;\n    }\n    /* we got an ADDBA Response matching our request, stop timeout */\n    timeout_del(&ba->ba_to);\n    \n    if (status != IEEE80211_STATUS_SUCCESS) {\n        if (ni->ni_addba_req_intval[tid] <\n            IEEE80211_ADDBA_REQ_INTVAL_MAX)\n            ni->ni_addba_req_intval[tid]++;\n        \n        ieee80211_addba_resp_refuse(ic, ni, tid, status);\n        \n        /*\n         * In case the peer believes there is an existing\n         * block ack agreement with us, try to delete it.\n         */\n        IEEE80211_SEND_ACTION(ic, ni, IEEE80211_CATEG_BA,\n                              IEEE80211_ACTION_DELBA,\n                              IEEE80211_REASON_SETUP_REQUIRED << 16 | 1 << 8 | tid);\n        return;\n    }\n    \n    /* notify drivers of this new Block Ack agreement */\n    if (ic->ic_ampdu_tx_start != NULL)\n        err = ic->ic_ampdu_tx_start(ic, ni, tid);\n    \n    if (err == EBUSY) {\n        /* driver will accept or refuse agreement when done */\n        return;\n    } else if (err) {\n        /* driver failed to setup, rollback */\n        ieee80211_addba_resp_refuse(ic, ni, tid,\n                                    IEEE80211_STATUS_UNSPECIFIED);\n    } else\n        ieee80211_addba_resp_accept(ic, ni, tid);\n}\n\nvoid\nieee80211_addba_resp_accept(struct ieee80211com *ic,\n                            struct ieee80211_node *ni, uint8_t tid)\n{\n    struct ieee80211_tx_ba *ba = &ni->ni_tx_ba[tid];\n    \n    /* MLME-ADDBA.confirm(Success) */\n    ba->ba_state = IEEE80211_BA_AGREED;\n    ic->ic_stats.is_ht_tx_ba_agreements++;\n    \n    ni->ni_qos_txseqs[tid] = ba->ba_winstart;\n    \n    /* Reset ADDBA request interval. */\n    ni->ni_addba_req_intval[tid] = 1;\n    \n    /* start Block Ack inactivity timeout */\n    if (ba->ba_timeout_val != 0)\n        timeout_add_usec(&ba->ba_to, ba->ba_timeout_val);\n}\n\nvoid\nieee80211_addba_resp_refuse(struct ieee80211com *ic,\n                            struct ieee80211_node *ni, uint8_t tid, uint16_t status)\n{\n    struct ieee80211_tx_ba *ba = &ni->ni_tx_ba[tid];\n    \n    /* MLME-ADDBA.confirm(Failure) */\n    ba->ba_state = IEEE80211_BA_INIT;\n}\n\n/*-\n * DELBA frame format:\n * [1] Category\n * [1] Action\n * [2] DELBA Parameter Set\n * [2] Reason Code\n */\nvoid\nieee80211_recv_delba(struct ieee80211com *ic, mbuf_t m,\n                     struct ieee80211_node *ni)\n{\n    const struct ieee80211_frame *wh;\n    const u_int8_t *frm;\n    u_int16_t params, reason;\n    u_int8_t tid;\n    int i;\n    \n    if (mbuf_len(m) < sizeof(*wh) + 6) {\n        DPRINTF((\"frame too short\\n\"));\n        return;\n    }\n    wh = mtod(m, struct ieee80211_frame *);\n    frm = (const u_int8_t *)&wh[1];\n    \n    params = LE_READ_2(&frm[2]);\n    reason = LE_READ_2(&frm[4]);\n    tid = params >> 12;\n    \n    XYLog(\"received DELBA from %s, TID %d, reason %d\\n\",\n             ether_sprintf(ni->ni_macaddr), tid, reason);\n    \n    if (params & IEEE80211_DELBA_INITIATOR) {\n        /* MLME-DELBA.indication(Originator) */\n        struct ieee80211_rx_ba *ba = &ni->ni_rx_ba[tid];\n        \n        if (ba->ba_state != IEEE80211_BA_AGREED) {\n            DPRINTF((\"no matching Block Ack agreement\\n\"));\n            return;\n        }\n        /* notify drivers of the end of the Block Ack agreement */\n        if (ic->ic_ampdu_rx_stop != NULL)\n            ic->ic_ampdu_rx_stop(ic, ni, tid);\n        \n        ba->ba_state = IEEE80211_BA_INIT;\n        /* stop Block Ack inactivity timer */\n        timeout_del(&ba->ba_to);\n        timeout_del(&ba->ba_gap_to);\n        ba->ba_gapwait = 0;\n        \n        if (ba->ba_buf != NULL) {\n            /* free all MSDUs stored in reordering buffer */\n            for (i = 0; i < IEEE80211_BA_MAX_WINSZ; i++)\n                mbuf_freem(ba->ba_buf[i].m);\n            /* free reordering buffer */\n            free(ba->ba_buf);\n            ba->ba_buf = NULL;\n        }\n    } else {\n        /* MLME-DELBA.indication(Recipient) */\n        struct ieee80211_tx_ba *ba = &ni->ni_tx_ba[tid];\n        \n        if (ba->ba_state != IEEE80211_BA_AGREED) {\n            DPRINTF((\"no matching Block Ack agreement\\n\"));\n            return;\n        }\n        /* notify drivers of the end of the Block Ack agreement */\n        if (ic->ic_ampdu_tx_stop != NULL)\n            ic->ic_ampdu_tx_stop(ic, ni, tid);\n        \n        ba->ba_state = IEEE80211_BA_INIT;\n        /* stop Block Ack inactivity timer */\n        timeout_del(&ba->ba_to);\n    }\n}\n\n/*-\n * SA Query Request frame format:\n * [1] Category\n * [1] Action\n * [2] Transaction Identifier\n */\nvoid\nieee80211_recv_sa_query_req(struct ieee80211com *ic, mbuf_t m,\n                            struct ieee80211_node *ni)\n{\n    const struct ieee80211_frame *wh;\n    const u_int8_t *frm;\n    \n    if (ic->ic_opmode != IEEE80211_M_STA ||\n        !(ni->ni_flags & IEEE80211_NODE_MFP)) {\n        DPRINTF((\"unexpected SA Query req from %s\\n\",\n                 ether_sprintf(ni->ni_macaddr)));\n        return;\n    }\n    if (mbuf_len(m) < sizeof(*wh) + 4) {\n        DPRINTF((\"frame too short\\n\"));\n        return;\n    }\n    wh = mtod(m, struct ieee80211_frame *);\n    frm = (const u_int8_t *)&wh[1];\n    \n    /* MLME-SAQuery.indication */\n    \n    /* save Transaction Identifier for SA Query Response */\n    ni->ni_sa_query_trid = LE_READ_2(&frm[2]);\n    \n    /* MLME-SAQuery.response */\n    IEEE80211_SEND_ACTION(ic, ni, IEEE80211_CATEG_SA_QUERY,\n                          IEEE80211_ACTION_SA_QUERY_RESP, 0);\n}\n\n#ifndef IEEE80211_STA_ONLY\n/*-\n * SA Query Response frame format:\n * [1] Category\n * [1] Action\n * [2] Transaction Identifier\n */\nvoid\nieee80211_recv_sa_query_resp(struct ieee80211com *ic, mbuf_t m,\n                             struct ieee80211_node *ni)\n{\n    const struct ieee80211_frame *wh;\n    const u_int8_t *frm;\n    \n    /* ignore if we're not engaged in an SA Query with that STA */\n    if (!(ni->ni_flags & IEEE80211_NODE_SA_QUERY)) {\n        DPRINTF((\"unexpected SA Query resp from %s\\n\",\n                 ether_sprintf(ni->ni_macaddr)));\n        return;\n    }\n    if (mbuf_len(m) < sizeof(*wh) + 4) {\n        DPRINTF((\"frame too short\\n\"));\n        return;\n    }\n    wh = mtod(m, struct ieee80211_frame *);\n    frm = (const u_int8_t *)&wh[1];\n    \n    /* check that Transaction Identifier matches */\n    if (ni->ni_sa_query_trid != LE_READ_2(&frm[2])) {\n        DPRINTF((\"transaction identifier does not match\\n\"));\n        return;\n    }\n    /* MLME-SAQuery.confirm */\n    timeout_del(&ni->ni_sa_query_to);\n    ni->ni_flags &= ~IEEE80211_NODE_SA_QUERY;\n}\n#endif\n\n/*-\n * Action frame format:\n * [1] Category\n * [1] Action\n */\nvoid\nieee80211_recv_action(struct ieee80211com *ic, mbuf_t m,\n                      struct ieee80211_node *ni)\n{\n    const struct ieee80211_frame *wh;\n    const u_int8_t *frm;\n    \n    if (mbuf_len(m) < sizeof(*wh) + 2) {\n        DPRINTF((\"frame too short\\n\"));\n        return;\n    }\n    wh = mtod(m, struct ieee80211_frame *);\n    frm = (const u_int8_t *)&wh[1];\n    \n    switch (frm[0]) {\n        case IEEE80211_CATEG_BA:\n            switch (frm[1]) {\n                case IEEE80211_ACTION_ADDBA_REQ:\n                    ieee80211_recv_addba_req(ic, m, ni);\n                    break;\n                case IEEE80211_ACTION_ADDBA_RESP:\n                    ieee80211_recv_addba_resp(ic, m, ni);\n                    break;\n                case IEEE80211_ACTION_DELBA:\n                    ieee80211_recv_delba(ic, m, ni);\n                    break;\n            }\n            break;\n        case IEEE80211_CATEG_SA_QUERY:\n            switch (frm[1]) {\n                case IEEE80211_ACTION_SA_QUERY_REQ:\n                    ieee80211_recv_sa_query_req(ic, m, ni);\n                    break;\n#ifndef IEEE80211_STA_ONLY\n                case IEEE80211_ACTION_SA_QUERY_RESP:\n                    ieee80211_recv_sa_query_resp(ic, m, ni);\n                    break;\n#endif\n            }\n            break;\n        default:\n            DPRINTF((\"action frame category %d not handled\\n\", frm[0]));\n            break;\n    }\n}\n\nvoid\nieee80211_recv_mgmt(struct ieee80211com *ic, mbuf_t m,\n                    struct ieee80211_node *ni, struct ieee80211_rxinfo *rxi, int subtype)\n{\n    switch (subtype) {\n        case IEEE80211_FC0_SUBTYPE_BEACON:\n            ieee80211_recv_probe_resp(ic, m, ni, rxi, 0);\n            break;\n        case IEEE80211_FC0_SUBTYPE_PROBE_RESP:\n            ieee80211_recv_probe_resp(ic, m, ni, rxi, 1);\n            break;\n#ifndef IEEE80211_STA_ONLY\n        case IEEE80211_FC0_SUBTYPE_PROBE_REQ:\n            ieee80211_recv_probe_req(ic, m, ni, rxi);\n            break;\n#endif\n        case IEEE80211_FC0_SUBTYPE_AUTH:\n            ieee80211_recv_auth(ic, m, ni, rxi);\n            break;\n#ifndef IEEE80211_STA_ONLY\n        case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:\n            ieee80211_recv_assoc_req(ic, m, ni, rxi, 0);\n            break;\n        case IEEE80211_FC0_SUBTYPE_REASSOC_REQ:\n            ieee80211_recv_assoc_req(ic, m, ni, rxi, 1);\n            break;\n#endif\n        case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:\n            ieee80211_recv_assoc_resp(ic, m, ni, 0);\n            break;\n        case IEEE80211_FC0_SUBTYPE_REASSOC_RESP:\n            ieee80211_recv_assoc_resp(ic, m, ni, 1);\n            break;\n        case IEEE80211_FC0_SUBTYPE_DEAUTH:\n            ieee80211_recv_deauth(ic, m, ni);\n            break;\n        case IEEE80211_FC0_SUBTYPE_DISASSOC:\n            ieee80211_recv_disassoc(ic, m, ni);\n            break;\n        case IEEE80211_FC0_SUBTYPE_ACTION:\n            ieee80211_recv_action(ic, m, ni);\n            break;\n        default:\n            DPRINTF((\"mgmt frame with subtype 0x%x not handled\\n\",\n                     subtype));\n            ic->ic_stats.is_rx_badsubtype++;\n            break;\n    }\n}\n\n#ifndef IEEE80211_STA_ONLY\n/*\n * Process an incoming PS-Poll control frame (see 11.2).\n */\nvoid\nieee80211_recv_pspoll(struct ieee80211com *ic, mbuf_t m,\n                      struct ieee80211_node *ni)\n{\n    struct _ifnet *ifp = &ic->ic_if;\n    struct ieee80211_frame_pspoll *psp;\n    struct ieee80211_frame *wh;\n    u_int16_t aid;\n    \n    if (ic->ic_opmode != IEEE80211_M_HOSTAP ||\n        !(ic->ic_caps & IEEE80211_C_APPMGT) ||\n        ni->ni_state != IEEE80211_STA_ASSOC)\n        return;\n    \n    if (mbuf_len(m) < sizeof(*psp)) {\n        DPRINTF((\"frame too short, len %u\\n\", mbuf_len(m)));\n        ic->ic_stats.is_rx_tooshort++;\n        return;\n    }\n    psp = mtod(m, struct ieee80211_frame_pspoll *);\n    if (!IEEE80211_ADDR_EQ(psp->i_bssid, ic->ic_bss->ni_bssid)) {\n        DPRINTF((\"discard pspoll frame to BSS %s\\n\",\n                 ether_sprintf(psp->i_bssid)));\n        ic->ic_stats.is_rx_wrongbss++;\n        return;\n    }\n    aid = letoh16(*(u_int16_t *)psp->i_aid);\n    if (aid != ni->ni_associd) {\n        DPRINTF((\"invalid pspoll aid %x from %s\\n\", aid,\n                 ether_sprintf(psp->i_ta)));\n        return;\n    }\n    \n    /* take the first queued frame and put it out.. */\n    m = mq_dequeue(&ni->ni_savedq);\n    if (m == NULL)\n        return;\n    if (mq_empty(&ni->ni_savedq)) {\n        /* last queued frame, turn off the TIM bit */\n        (*ic->ic_set_tim)(ic, ni->ni_associd, 0);\n    } else {\n        /* more queued frames, set the more data bit */\n        wh = mtod(m, struct ieee80211_frame *);\n        wh->i_fc[1] |= IEEE80211_FC1_MORE_DATA;\n    }\n    mq_enqueue(&ic->ic_pwrsaveq, m);\n    ifp->if_start(ifp);\n}\n#endif\t/* IEEE80211_STA_ONLY */\n\n/*\n * Process an incoming BlockAckReq control frame (see 7.2.1.7).\n */\nvoid\nieee80211_recv_bar(struct ieee80211com *ic, mbuf_t m,\n                   struct ieee80211_node *ni)\n{\n    const struct ieee80211_frame_min *wh;\n    const u_int8_t *frm;\n    u_int16_t ctl, ssn;\n    u_int8_t tid, ntids;\n    \n    if (!(ni->ni_flags & IEEE80211_NODE_HT)) {\n        DPRINTF((\"received BlockAckReq from non-HT STA %s\\n\",\n                 ether_sprintf(ni->ni_macaddr)));\n        return;\n    }\n    if (mbuf_len(m) < sizeof(*wh) + 4) {\n        DPRINTF((\"frame too short\\n\"));\n        return;\n    }\n    wh = mtod(m, struct ieee80211_frame_min *);\n    frm = (const u_int8_t *)&wh[1];\n    \n    /* read BlockAckReq Control field */\n    ctl = LE_READ_2(&frm[0]);\n    tid = ctl >> 12;\n    \n    /* determine BlockAckReq frame variant */\n    if (ctl & IEEE80211_BA_MULTI_TID) {\n        /* Multi-TID BlockAckReq variant (PSMP only) */\n        ntids = tid + 1;\n        \n        if (mbuf_len(m) < sizeof(*wh) + 2 + 4 * ntids) {\n            DPRINTF((\"MTBAR frame too short\\n\"));\n            return;\n        }\n        frm += 2;    /* skip BlockAckReq Control field */\n        while (ntids-- > 0) {\n            /* read MTBAR Information field */\n            tid = LE_READ_2(&frm[0]) >> 12;\n            ssn = LE_READ_2(&frm[2]) >> 4;\n            ieee80211_bar_tid(ic, ni, tid, ssn);\n            frm += 4;\n        }\n    } else {\n        /* Basic or Compressed BlockAckReq variants */\n        ssn = LE_READ_2(&frm[2]) >> 4;\n        ieee80211_bar_tid(ic, ni, tid, ssn);\n    }\n}\n\n/*\n * Process a BlockAckReq for a specific TID (see 9.10.7.6.3).\n * This is the common back-end for all BlockAckReq frame variants.\n */\nvoid\nieee80211_bar_tid(struct ieee80211com *ic, struct ieee80211_node *ni,\n                  u_int8_t tid, u_int16_t ssn)\n{\n    struct ieee80211_rx_ba *ba = &ni->ni_rx_ba[tid];\n    \n    /* check if we have a Block Ack agreement for RA/TID */\n    if (ba->ba_state != IEEE80211_BA_AGREED) {\n        /* XXX not sure in PBAC case */\n        /* send a DELBA with reason code UNKNOWN-BA */\n        IEEE80211_SEND_ACTION(ic, ni, IEEE80211_CATEG_BA,\n                              IEEE80211_ACTION_DELBA,\n                              IEEE80211_REASON_SETUP_REQUIRED << 16 | tid);\n        return;\n    }\n    /* check if it is a Protected Block Ack agreement */\n    if ((ni->ni_flags & IEEE80211_NODE_MFP) &&\n        (ni->ni_rsncaps & IEEE80211_RSNCAP_PBAC)) {\n        /* ADDBA Requests must be used in PBAC case */\n        if (SEQ_LT(ssn, ba->ba_winstart) ||\n            SEQ_LT(ba->ba_winend, ssn))\n            ic->ic_stats.is_pbac_errs++;\n        return;    /* PBAC, do not move window */\n    }\n    /* reset Block Ack inactivity timer */\n    if (ba->ba_timeout_val != 0)\n        timeout_add_usec(&ba->ba_to, ba->ba_timeout_val);\n    \n    if (SEQ_LT(ba->ba_winstart, ssn)) {\n        struct mbuf_list ml = MBUF_LIST_INITIALIZER();\n        ieee80211_ba_move_window(ic, ni, tid, ssn, &ml);\n        if_input(&ic->ic_if, &ml);\n    }\n}\n"
  },
  {
    "path": "itl80211/openbsd/net80211/ieee80211_ioctl.c",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n/*\t$OpenBSD: ieee80211_ioctl.c,v 1.75 2019/09/02 12:54:21 stsp Exp $\t*/\n/*\t$NetBSD: ieee80211_ioctl.c,v 1.15 2004/05/06 02:58:16 dyoung Exp $\t*/\n\n/*-\n * Copyright (c) 2001 Atsushi Onoe\n * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. The name of the author may not be used to endorse or promote products\n *    derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*\n * IEEE 802.11 ioctl support\n */\n\n#include <sys/param.h>\n#include <sys/kernel.h>\n#include <sys/socket.h>\n#include <sys/sockio.h>\n#include <sys/systm.h>\n#include <sys/endian.h>\n#include <sys/tree.h>\n\n#include <net/if.h>\n#include <net/if_media.h>\n\n#include <netinet/in.h>\n#include <netinet/if_ether.h>\n\n#include <net80211/ieee80211_var.h>\n#include <net80211/ieee80211_crypto.h>\n#include <net80211/ieee80211_ioctl.h>\n\nvoid\t ieee80211_node2req(struct ieee80211com *,\n\t    const struct ieee80211_node *, struct ieee80211_nodereq *);\nvoid\t ieee80211_req2node(struct ieee80211com *,\n\t    const struct ieee80211_nodereq *, struct ieee80211_node *);\n\nstatic int kernel_copyin(const user_addr_t dest, void *src, size_t len)\n{\n    memcpy(src, (void *)dest, len);\n    return 0;\n}\n\nstatic int kernel_copyout(void *src, const user_addr_t dest, size_t len)\n{\n    memcpy((void *)dest, src, len);\n    return 0;\n}\n\nvoid\nieee80211_node2req(struct ieee80211com *ic, const struct ieee80211_node *ni,\n    struct ieee80211_nodereq *nr)\n{\n\tuint8_t rssi;\n\n\tmemset(nr, 0, sizeof(*nr));\n\n\tstrlcpy(nr->nr_ifname, ic->ic_if.if_xname, sizeof(nr->nr_ifname));\n\n\t/* Node address and name information */\n\tIEEE80211_ADDR_COPY(nr->nr_macaddr, ni->ni_macaddr);\n\tIEEE80211_ADDR_COPY(nr->nr_bssid, ni->ni_bssid);\n\tnr->nr_nwid_len = ni->ni_esslen;\n\tbcopy(ni->ni_essid, nr->nr_nwid, IEEE80211_NWID_LEN);\n\n\t/* Channel and rates */\n\tnr->nr_channel = ieee80211_chan2ieee(ic, ni->ni_chan);\n\tif (ni->ni_chan != IEEE80211_CHAN_ANYC)\n        nr->nr_chan_flags = ni->ni_chan->ic_flags;\n\tif (ic->ic_curmode != IEEE80211_MODE_11N)\n\t\tnr->nr_chan_flags &= ~IEEE80211_CHAN_HT;\n\tnr->nr_nrates = ni->ni_rates.rs_nrates;\n\tbcopy(ni->ni_rates.rs_rates, nr->nr_rates, IEEE80211_RATE_MAXSIZE);\n\n\t/* Node status information */\n\trssi = (*ic->ic_node_getrssi)(ic, ni);\n\tif (ic->ic_max_rssi) {\n\t\t/* Driver reports RSSI relative to ic_max_rssi. */\n\t\tnr->nr_rssi = rssi;\n\t} else {\n\t\t/*\n\t\t * Driver reports RSSI value in dBm.\n\t\t * Convert from unsigned to signed.\n\t\t * Some drivers report a negative value, some don't.\n\t\t * Reasonable range is -20dBm to -80dBm.\n\t\t */\n\t\tnr->nr_rssi = (rssi < 128) ? -rssi : rssi;\n\t}\n\tnr->nr_max_rssi = ic->ic_max_rssi;\n\tbcopy(ni->ni_tstamp, nr->nr_tstamp, sizeof(nr->nr_tstamp));\n\tnr->nr_intval = ni->ni_intval;\n\tnr->nr_capinfo = ni->ni_capinfo;\n\tnr->nr_erp = ni->ni_erp;\n\tnr->nr_pwrsave = ni->ni_pwrsave;\n\tnr->nr_associd = ni->ni_associd;\n\tnr->nr_txseq = ni->ni_txseq;\n\tnr->nr_rxseq = ni->ni_rxseq;\n\tnr->nr_fails = ni->ni_fails;\n\tnr->nr_assoc_fail = ni->ni_assoc_fail; /* flag values are the same */\n\tnr->nr_inact = ni->ni_inact;\n\tnr->nr_txrate = ni->ni_txrate;\n\tnr->nr_state = ni->ni_state;\n\n\t/* RSN */\n\tnr->nr_rsnciphers = ni->ni_rsnciphers;\n\tnr->nr_rsnakms = 0;\n\tnr->nr_rsnprotos = 0;\n\tif (ni->ni_supported_rsnprotos & IEEE80211_PROTO_RSN)\n\t\tnr->nr_rsnprotos |= IEEE80211_WPA_PROTO_WPA2;\n\tif (ni->ni_supported_rsnprotos & IEEE80211_PROTO_WPA)\n\t\tnr->nr_rsnprotos |= IEEE80211_WPA_PROTO_WPA1;\n\tif (ni->ni_supported_rsnakms & IEEE80211_AKM_8021X)\n\t\tnr->nr_rsnakms |= IEEE80211_WPA_AKM_8021X;\n\tif (ni->ni_supported_rsnakms & IEEE80211_AKM_PSK)\n\t\tnr->nr_rsnakms |= IEEE80211_WPA_AKM_PSK;\n\tif (ni->ni_supported_rsnakms & IEEE80211_AKM_SHA256_8021X)\n\t\tnr->nr_rsnakms |= IEEE80211_WPA_AKM_SHA256_8021X;\n\tif (ni->ni_supported_rsnakms & IEEE80211_AKM_SHA256_PSK)\n\t\tnr->nr_rsnakms |= IEEE80211_WPA_AKM_SHA256_PSK;\n\n\t/* Node flags */\n\tnr->nr_flags = 0;\n\tif (bcmp(nr->nr_macaddr, nr->nr_bssid, IEEE80211_ADDR_LEN) == 0)\n\t\tnr->nr_flags |= IEEE80211_NODEREQ_AP;\n\tif (ni == ic->ic_bss)\n\t\tnr->nr_flags |= IEEE80211_NODEREQ_AP_BSS;\n\n\t/* HT */\n\tnr->nr_htcaps = ni->ni_htcaps;\n\tmemcpy(nr->nr_rxmcs, ni->ni_rxmcs, sizeof(nr->nr_rxmcs));\n\tnr->nr_max_rxrate = ni->ni_max_rxrate;\n\tnr->nr_tx_mcs_set = ni->ni_tx_mcs_set;\n\tif (ni->ni_flags & IEEE80211_NODE_HT)\n\t\tnr->nr_flags |= IEEE80211_NODEREQ_HT;\n\n\t/* HT / VHT */\n\tnr->nr_txmcs = ni->ni_txmcs;\n\n\t/* VHT */\n\tnr->nr_vht_ss = ni->ni_vht_ss;\n\tif (ni->ni_flags & IEEE80211_NODE_VHT)\n\t\tnr->nr_flags |= IEEE80211_NODEREQ_VHT;\n}\n\nvoid\nieee80211_req2node(struct ieee80211com *ic, const struct ieee80211_nodereq *nr,\n    struct ieee80211_node *ni)\n{\n\t/* Node address and name information */\n\tIEEE80211_ADDR_COPY(ni->ni_macaddr, nr->nr_macaddr);\n\tIEEE80211_ADDR_COPY(ni->ni_bssid, nr->nr_bssid);\n\tni->ni_esslen = nr->nr_nwid_len;\n\tbcopy(nr->nr_nwid, ni->ni_essid, IEEE80211_NWID_LEN);\n\n\t/* Rates */\n\tni->ni_rates.rs_nrates = nr->nr_nrates;\n\tbcopy(nr->nr_rates, ni->ni_rates.rs_rates, IEEE80211_RATE_MAXSIZE);\n\n\t/* Node information */\n\tni->ni_intval = nr->nr_intval;\n\tni->ni_capinfo = nr->nr_capinfo;\n\tni->ni_erp = nr->nr_erp;\n\tni->ni_pwrsave = nr->nr_pwrsave;\n\tni->ni_associd = nr->nr_associd;\n\tni->ni_txseq = nr->nr_txseq;\n\tni->ni_rxseq = nr->nr_rxseq;\n\tni->ni_fails = nr->nr_fails;\n\tni->ni_inact = nr->nr_inact;\n\tni->ni_txrate = nr->nr_txrate;\n\tni->ni_state = nr->nr_state;\n}\n\nvoid\nieee80211_disable_wep(struct ieee80211com *ic)\n{\n\tstruct ieee80211_key *k;\n\tint i;\n\t\n\tfor (i = 0; i < IEEE80211_WEP_NKID; i++) {\n\t\tk = &ic->ic_nw_keys[i];\n\t\tif (k->k_cipher != IEEE80211_CIPHER_NONE)\n\t\t\t(*ic->ic_delete_key)(ic, NULL, k);\n\t\tmemset(k, 0, sizeof(*k));\n\t}\n\tic->ic_flags &= ~IEEE80211_F_WEPON;\n}\n\nvoid\nieee80211_disable_rsn(struct ieee80211com *ic)\n{\n\tic->ic_flags &= ~(IEEE80211_F_PSK | IEEE80211_F_RSNON);\n\tmemset(ic->ic_psk, 0, sizeof(ic->ic_psk));\n\tic->ic_rsnprotos = 0;\n\tic->ic_rsnakms = 0;\n\tic->ic_rsngroupcipher = (enum ieee80211_cipher)0;\n\tic->ic_rsnciphers = 0;\n}\n\n/* Keep in sync with ieee80211_node.c:ieee80211_ess_setnwkeys() */\nint\nieee80211_ioctl_setnwkeys(struct ieee80211com *ic,\n    const struct ieee80211_nwkey *nwkey)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n\tstruct ieee80211_key *k;\n\tint error, i;\n\n\tif (!(ic->ic_caps & IEEE80211_C_WEP))\n\t\treturn ENODEV;\n\n\tif (nwkey->i_wepon == IEEE80211_NWKEY_OPEN) {\n\t\tif (!(ic->ic_flags & IEEE80211_F_WEPON))\n\t\t\treturn 0;\n\t\tic->ic_flags &= ~IEEE80211_F_WEPON;\n\t\treturn ENETRESET;\n\t}\n\tif (nwkey->i_defkid < 1 || nwkey->i_defkid > IEEE80211_WEP_NKID)\n\t\treturn EINVAL;\n\n\tfor (i = 0; i < IEEE80211_WEP_NKID; i++) {\n\t\tif (nwkey->i_key[i].i_keylen == 0 ||\n\t\t    nwkey->i_key[i].i_keydat == NULL)\n\t\t\tcontinue;\t/* entry not set */\n\t\tif (nwkey->i_key[i].i_keylen > IEEE80211_KEYBUF_SIZE)\n\t\t\treturn EINVAL;\n\n\t\t/* map wep key to ieee80211_key */\n\t\tk = &ic->ic_nw_keys[i];\n\t\tif (k->k_cipher != IEEE80211_CIPHER_NONE)\n\t\t\t(*ic->ic_delete_key)(ic, NULL, k);\n\t\tmemset(k, 0, sizeof(*k));\n\t\tif (nwkey->i_key[i].i_keylen <= 5)\n\t\t\tk->k_cipher = IEEE80211_CIPHER_WEP40;\n\t\telse\n\t\t\tk->k_cipher = IEEE80211_CIPHER_WEP104;\n\t\tk->k_len = ieee80211_cipher_keylen(k->k_cipher);\n\t\tk->k_flags = IEEE80211_KEY_GROUP | IEEE80211_KEY_TX;\n\t\terror = kernel_copyin((const user_addr_t)nwkey->i_key[i].i_keydat, k->k_key, k->k_len);\n\t\tif (error != 0)\n\t\t\treturn error;\n        error = (*ic->ic_set_key)(ic, NULL, k);\n        switch (error) {\n            case 0:\n            case EBUSY:\n                break;\n            default:\n                return error;\n        }\n\t}\n\n\tic->ic_def_txkey = nwkey->i_defkid - 1;\n\tic->ic_flags |= IEEE80211_F_WEPON;\n\tif (ic->ic_flags & IEEE80211_F_RSNON)\n\t\tieee80211_disable_rsn(ic);\n\n\treturn ENETRESET;\n}\n\nstatic int\nieee80211_ioctl_getnwkeys(struct ieee80211com *ic,\n    struct ieee80211_nwkey *nwkey)\n{\n\tint i;\n\n\tif (ic->ic_flags & IEEE80211_F_WEPON)\n\t\tnwkey->i_wepon = IEEE80211_NWKEY_WEP;\n\telse\n\t\tnwkey->i_wepon = IEEE80211_NWKEY_OPEN;\n\n\tnwkey->i_defkid = ic->ic_wep_txkey + 1;\n\n\tfor (i = 0; i < IEEE80211_WEP_NKID; i++) {\n\t\tif (nwkey->i_key[i].i_keydat == NULL)\n\t\t\tcontinue;\n\t\t/* do not show any keys to userland */\n\t\treturn EPERM;\n\t}\n\treturn 0;\n}\n\n/* Keep in sync with ieee80211_node.c:ieee80211_ess_setwpaparms() */\nint\nieee80211_ioctl_setwpaparms(struct ieee80211com *ic,\n    const struct ieee80211_wpaparams *wpa)\n{\n\tif (!(ic->ic_caps & IEEE80211_C_RSN))\n\t\treturn ENODEV;\n\n\tif (!wpa->i_enabled) {\n\t\tif (!(ic->ic_flags & IEEE80211_F_RSNON))\n\t\t\treturn 0;\n\t\tic->ic_flags &= ~IEEE80211_F_RSNON;\n\t\tic->ic_rsnprotos = 0;\n\t\tic->ic_rsnakms = 0;\n\t\tic->ic_rsngroupcipher = (enum ieee80211_cipher)0;\n\t\tic->ic_rsnciphers = 0;\n\t\treturn ENETRESET;\n\t}\n\n\tic->ic_rsnprotos = 0;\n\tif (wpa->i_protos & IEEE80211_WPA_PROTO_WPA1)\n\t\tic->ic_rsnprotos |= IEEE80211_PROTO_WPA;\n\tif (wpa->i_protos & IEEE80211_WPA_PROTO_WPA2)\n\t\tic->ic_rsnprotos |= IEEE80211_PROTO_RSN;\n\tif (ic->ic_rsnprotos == 0)\t/* set to default (RSN) */\n\t\tic->ic_rsnprotos = IEEE80211_PROTO_RSN;\n\n\tic->ic_rsnakms = 0;\n\tif (wpa->i_akms & IEEE80211_WPA_AKM_PSK)\n\t\tic->ic_rsnakms |= IEEE80211_AKM_PSK;\n\tif (wpa->i_akms & IEEE80211_WPA_AKM_SHA256_PSK)\n\t\tic->ic_rsnakms |= IEEE80211_AKM_SHA256_PSK;\n\tif (wpa->i_akms & IEEE80211_WPA_AKM_8021X)\n\t\tic->ic_rsnakms |= IEEE80211_AKM_8021X;\n\tif (wpa->i_akms & IEEE80211_WPA_AKM_SHA256_8021X)\n\t\tic->ic_rsnakms |= IEEE80211_AKM_SHA256_8021X;\n\tif (ic->ic_rsnakms == 0)\t/* set to default (PSK) */\n\t\tic->ic_rsnakms = IEEE80211_AKM_PSK;\n\n\tif (wpa->i_groupcipher == IEEE80211_WPA_CIPHER_WEP40)\n\t\tic->ic_rsngroupcipher = IEEE80211_CIPHER_WEP40;\n\telse if (wpa->i_groupcipher == IEEE80211_WPA_CIPHER_TKIP)\n\t\tic->ic_rsngroupcipher = IEEE80211_CIPHER_TKIP;\n\telse if (wpa->i_groupcipher == IEEE80211_WPA_CIPHER_CCMP)\n\t\tic->ic_rsngroupcipher = IEEE80211_CIPHER_CCMP;\n\telse if (wpa->i_groupcipher == IEEE80211_WPA_CIPHER_WEP104)\n\t\tic->ic_rsngroupcipher = IEEE80211_CIPHER_WEP104;\n\telse  {\t/* set to default */\n\t\tif (ic->ic_rsnprotos & IEEE80211_PROTO_WPA)\n\t\t\tic->ic_rsngroupcipher = IEEE80211_CIPHER_TKIP;\n\t\telse\n\t\t\tic->ic_rsngroupcipher = IEEE80211_CIPHER_CCMP;\n\t}\n\n\tic->ic_rsnciphers = 0;\n\tif (wpa->i_ciphers & IEEE80211_WPA_CIPHER_TKIP)\n\t\tic->ic_rsnciphers |= IEEE80211_CIPHER_TKIP;\n\tif (wpa->i_ciphers & IEEE80211_WPA_CIPHER_CCMP)\n\t\tic->ic_rsnciphers |= IEEE80211_CIPHER_CCMP;\n\tif (wpa->i_ciphers & IEEE80211_WPA_CIPHER_USEGROUP)\n\t\tic->ic_rsnciphers = IEEE80211_CIPHER_USEGROUP;\n\tif (ic->ic_rsnciphers == 0) { /* set to default (CCMP, TKIP if WPA1) */\n\t\tic->ic_rsnciphers = IEEE80211_CIPHER_CCMP;\n\t\tif (ic->ic_rsnprotos & IEEE80211_PROTO_WPA)\n\t\t\tic->ic_rsnciphers |= IEEE80211_CIPHER_TKIP;\n\t}\n\n\tic->ic_flags |= IEEE80211_F_RSNON;\n\n\treturn ENETRESET;\n}\n\nint\nieee80211_ioctl_getwpaparms(struct ieee80211com *ic,\n    struct ieee80211_wpaparams *wpa)\n{\n\twpa->i_enabled = (ic->ic_flags & IEEE80211_F_RSNON) ? 1 : 0;\n\n\twpa->i_protos = 0;\n\tif (ic->ic_rsnprotos & IEEE80211_PROTO_WPA)\n\t\twpa->i_protos |= IEEE80211_WPA_PROTO_WPA1;\n\tif (ic->ic_rsnprotos & IEEE80211_PROTO_RSN)\n\t\twpa->i_protos |= IEEE80211_WPA_PROTO_WPA2;\n\n\twpa->i_akms = 0;\n\tif (ic->ic_rsnakms & IEEE80211_AKM_PSK)\n\t\twpa->i_akms |= IEEE80211_WPA_AKM_PSK;\n\tif (ic->ic_rsnakms & IEEE80211_AKM_SHA256_PSK)\n\t\twpa->i_akms |= IEEE80211_WPA_AKM_SHA256_PSK;\n\tif (ic->ic_rsnakms & IEEE80211_AKM_8021X)\n\t\twpa->i_akms |= IEEE80211_WPA_AKM_8021X;\n\tif (ic->ic_rsnakms & IEEE80211_AKM_SHA256_8021X)\n\t\twpa->i_akms |= IEEE80211_WPA_AKM_SHA256_8021X;\n\n\tif (ic->ic_rsngroupcipher == IEEE80211_CIPHER_WEP40)\n\t\twpa->i_groupcipher = IEEE80211_WPA_CIPHER_WEP40;\n\telse if (ic->ic_rsngroupcipher == IEEE80211_CIPHER_TKIP)\n\t\twpa->i_groupcipher = IEEE80211_WPA_CIPHER_TKIP;\n\telse if (ic->ic_rsngroupcipher == IEEE80211_CIPHER_CCMP)\n\t\twpa->i_groupcipher = IEEE80211_WPA_CIPHER_CCMP;\n\telse if (ic->ic_rsngroupcipher == IEEE80211_CIPHER_WEP104)\n\t\twpa->i_groupcipher = IEEE80211_WPA_CIPHER_WEP104;\n\telse\n\t\twpa->i_groupcipher = IEEE80211_WPA_CIPHER_NONE;\n\n\twpa->i_ciphers = 0;\n\tif (ic->ic_rsnciphers & IEEE80211_CIPHER_TKIP)\n\t\twpa->i_ciphers |= IEEE80211_WPA_CIPHER_TKIP;\n\tif (ic->ic_rsnciphers & IEEE80211_CIPHER_CCMP)\n\t\twpa->i_ciphers |= IEEE80211_WPA_CIPHER_CCMP;\n\tif (ic->ic_rsnciphers & IEEE80211_CIPHER_USEGROUP)\n\t\twpa->i_ciphers = IEEE80211_WPA_CIPHER_USEGROUP;\n\n\treturn 0;\n}\n\nvoid\nieee80211_ess_getwpaparms(struct ieee80211_ess *ess,\n    struct ieee80211_wpaparams *wpa)\n{\n\twpa->i_enabled = (ess->flags & IEEE80211_F_RSNON) ? 1 : 0;\n\n\twpa->i_protos = 0;\n\tif (ess->rsnprotos & IEEE80211_PROTO_WPA)\n\t\twpa->i_protos |= IEEE80211_WPA_PROTO_WPA1;\n\tif (ess->rsnprotos & IEEE80211_PROTO_RSN)\n\t\twpa->i_protos |= IEEE80211_WPA_PROTO_WPA2;\n\n\twpa->i_akms = 0;\n\tif (ess->rsnakms & IEEE80211_AKM_PSK)\n\t\twpa->i_akms |= IEEE80211_WPA_AKM_PSK;\n\tif (ess->rsnakms & IEEE80211_AKM_SHA256_PSK)\n\t\twpa->i_akms |= IEEE80211_WPA_AKM_SHA256_PSK;\n\tif (ess->rsnakms & IEEE80211_AKM_8021X)\n\t\twpa->i_akms |= IEEE80211_WPA_AKM_8021X;\n\tif (ess->rsnakms & IEEE80211_AKM_SHA256_8021X)\n\t\twpa->i_akms |= IEEE80211_WPA_AKM_SHA256_8021X;\n\n\tif (ess->rsngroupcipher == IEEE80211_CIPHER_WEP40)\n\t\twpa->i_groupcipher = IEEE80211_WPA_CIPHER_WEP40;\n\telse if (ess->rsngroupcipher == IEEE80211_CIPHER_TKIP)\n\t\twpa->i_groupcipher = IEEE80211_WPA_CIPHER_TKIP;\n\telse if (ess->rsngroupcipher == IEEE80211_CIPHER_CCMP)\n\t\twpa->i_groupcipher = IEEE80211_WPA_CIPHER_CCMP;\n\telse if (ess->rsngroupcipher == IEEE80211_CIPHER_WEP104)\n\t\twpa->i_groupcipher = IEEE80211_WPA_CIPHER_WEP104;\n\telse\n\t\twpa->i_groupcipher = IEEE80211_WPA_CIPHER_NONE;\n\n\twpa->i_ciphers = 0;\n\tif (ess->rsnciphers & IEEE80211_CIPHER_TKIP)\n\t\twpa->i_ciphers |= IEEE80211_WPA_CIPHER_TKIP;\n\tif (ess->rsnciphers & IEEE80211_CIPHER_CCMP)\n\t\twpa->i_ciphers |= IEEE80211_WPA_CIPHER_CCMP;\n\tif (ess->rsnciphers & IEEE80211_CIPHER_USEGROUP)\n\t\twpa->i_ciphers = IEEE80211_WPA_CIPHER_USEGROUP;\n}\n\nint\nieee80211_ioctl(struct _ifnet *ifp, u_long cmd, caddr_t data)\n{\n\tstruct ieee80211com *ic = (struct ieee80211com *)ifp;\n\tstruct ifreq *ifr = (struct ifreq *)data;\n\tint i, error = 0;\n\tsize_t len;\n\tstruct ieee80211_nwid nwid;\n\tstruct ieee80211_join join;\n\tstruct ieee80211_joinreq_all *ja;\n\tstruct ieee80211_ess *ess;\n\tstruct ieee80211_wpapsk *psk;\n\tstruct ieee80211_keyavail *ka;\n\tstruct ieee80211_keyrun *kr;\n\tstruct ieee80211_power *power;\n\tstruct ieee80211_bssid *bssid;\n\tstruct ieee80211chanreq *chanreq;\n\tstruct ieee80211_channel *chan;\n\tstruct ieee80211_txpower *txpower;\n\tstatic const u_int8_t empty_macaddr[IEEE80211_ADDR_LEN] = {\n\t\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00\n\t};\n\tstruct ieee80211_nodereq *nr, nrbuf;\n\tstruct ieee80211_nodereq_all *na;\n\tstruct ieee80211_node *ni;\n\tu_int32_t flags;\n\n\tswitch (cmd) {\n//\tcase SIOCSIFMEDIA:\n//\tcase SIOCGIFMEDIA:\n//\t\terror = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);\n//\t\tbreak;\n\tcase SIOCS80211NWID:\n//\t\tif ((error = suser(curproc)) != 0)\n//\t\t\tbreak;\n\t\tif ((error = kernel_copyin((const user_addr_t)ifr->ifr_data, &nwid, sizeof(nwid))) != 0)\n\t\t\tbreak;\n\t\tif (nwid.i_len > IEEE80211_NWID_LEN) {\n\t\t\terror = EINVAL;\n\t\t\tbreak;\n\t\t}\n\t\tmemset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN);\n\t\tic->ic_des_esslen = nwid.i_len;\n\t\tmemcpy(ic->ic_des_essid, nwid.i_nwid, nwid.i_len);\n\t\tif (ic->ic_des_esslen > 0) {\n\t\t\t/* 'nwid' disables auto-join magic */\n\t\t\tic->ic_flags &= ~IEEE80211_F_AUTO_JOIN;\n\t\t} else if (!TAILQ_EMPTY(&ic->ic_ess)) {\n\t\t\t/* '-nwid' re-enables auto-join */\n\t\t\tic->ic_flags |= IEEE80211_F_AUTO_JOIN;\n\t\t}\n\t\t/* disable WPA/WEP */\n\t\tieee80211_disable_rsn(ic);\n\t\tieee80211_disable_wep(ic);\n\t\terror = ENETRESET;\n\t\tbreak;\n\tcase SIOCG80211NWID:\n\t\tmemset(&nwid, 0, sizeof(nwid));\n\t\tswitch (ic->ic_state) {\n\t\tcase IEEE80211_S_INIT:\n\t\tcase IEEE80211_S_SCAN:\n\t\t\tnwid.i_len = ic->ic_des_esslen;\n\t\t\tmemcpy(nwid.i_nwid, ic->ic_des_essid, nwid.i_len);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tnwid.i_len = ic->ic_bss->ni_esslen;\n\t\t\tmemcpy(nwid.i_nwid, ic->ic_bss->ni_essid, nwid.i_len);\n\t\t\tbreak;\n\t\t}\n\t\terror = kernel_copyout((void *)&nwid, (user_addr_t)ifr->ifr_data, sizeof(nwid));\n\t\tbreak;\n\tcase SIOCS80211JOIN:\n//\t\tif ((error = suser(curproc)) != 0)\n//\t\t\tbreak;\n\t\tif ((error = kernel_copyin((user_addr_t)ifr->ifr_data, &join, sizeof(join))) != 0)\n\t\t\tbreak;\n\t\tif (join.i_len > IEEE80211_NWID_LEN) {\n\t\t\terror = EINVAL;\n\t\t\tbreak;\n\t\t}\n\t\tif (join.i_flags & IEEE80211_JOIN_DEL) {\n\t\t\tint update_ic = 0;\n\t\t\tif (ic->ic_des_esslen == join.i_len &&\n\t\t\t    memcmp(join.i_nwid, ic->ic_des_essid,\n\t\t\t    join.i_len) == 0)\n\t\t\t\tupdate_ic = 1;\n\t\t\tif (join.i_flags & IEEE80211_JOIN_DEL_ALL &&\n\t\t\t    ieee80211_get_ess(ic, (const char *)ic->ic_des_essid,\n\t\t\t    ic->ic_des_esslen) != NULL)\n\t\t\t\tupdate_ic = 1;\n\t\t\tieee80211_del_ess(ic, (char *)join.i_nwid, join.i_len,\n\t\t\t    join.i_flags & IEEE80211_JOIN_DEL_ALL ? 1 : 0);\n\t\t\tif (update_ic == 1) {\n\t\t\t\t/* Unconfigure this essid */\n\t\t\t\tmemset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN);\n\t\t\t\tic->ic_des_esslen = 0;\n\t\t\t\t/* disable WPA/WEP */\n\t\t\t\tieee80211_disable_rsn(ic);\n\t\t\t\tieee80211_disable_wep(ic);\n\t\t\t\terror = ENETRESET;\n\t\t\t}\n\t\t} else {\n            if (ic->ic_des_esslen == join.i_len &&\n                memcmp(join.i_nwid, ic->ic_des_essid,\n                       join.i_len) == 0) {\n                struct ieee80211_node *ni;\n                \n                ieee80211_deselect_ess(ic);\n                ni = ieee80211_find_node(ic,\n                    ic->ic_bss->ni_bssid);\n                if (ni != NULL)\n                    ieee80211_free_node(ic, ni);\n                error = ENETRESET;\n            }\n\t\t\t/* save nwid for auto-join */\n\t\t\tif (ieee80211_add_ess(ic, &join) == 0)\n\t\t\t\tic->ic_flags |= IEEE80211_F_AUTO_JOIN;\n\t\t}\n\t\tbreak;\n\tcase SIOCG80211JOIN:\n\t\tmemset(&join, 0, sizeof(join));\n\t\terror = ENOENT;\n\t\tif (ic->ic_bss == NULL)\n\t\t\tbreak;\n\t\tTAILQ_FOREACH(ess, &ic->ic_ess, ess_next) {\n\t\t\tif (memcmp(ess->essid, ic->ic_bss->ni_essid,\n\t\t\t    IEEE80211_NWID_LEN) == 0) {\n\t\t\t\tjoin.i_len = ic->ic_bss->ni_esslen;\n\t\t\t\tmemcpy(join.i_nwid, ic->ic_bss->ni_essid,\n\t\t\t\t    join.i_len);\n\t\t\t\tif (ic->ic_flags & IEEE80211_F_AUTO_JOIN)\n\t\t\t\t\tjoin.i_flags = IEEE80211_JOIN_FOUND;\n\t\t\t\terror = kernel_copyout(&join, (user_addr_t)ifr->ifr_data,\n\t\t\t\t    sizeof(join));\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tbreak;\n\tcase SIOCG80211JOINALL:\n\t\tja = (struct ieee80211_joinreq_all *)data;\n\t\tja->ja_nodes = len = 0;\n\t\tTAILQ_FOREACH(ess, &ic->ic_ess, ess_next) {\n\t\t\tif (len + sizeof(ja->ja_node[0]) >= ja->ja_size) {\n\t\t\t\terror = E2BIG;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tmemset(&join, 0, sizeof(join));\n\t\t\tjoin.i_len = ess->esslen;\n\t\t\tmemcpy(&join.i_nwid, ess->essid, join.i_len);\n\t\t\tif (ess->flags & IEEE80211_F_RSNON)\n\t\t\t\tjoin.i_flags |= IEEE80211_JOIN_WPA;\n\t\t\tif (ess->flags & IEEE80211_F_PSK)\n\t\t\t\tjoin.i_flags |= IEEE80211_JOIN_WPAPSK;\n\t\t\tif (ess->flags & IEEE80211_JOIN_8021X)\n\t\t\t\tjoin.i_flags |= IEEE80211_JOIN_8021X;\n\t\t\tif (ess->flags & IEEE80211_F_WEPON)\n\t\t\t\tjoin.i_flags |= IEEE80211_JOIN_NWKEY;\n\t\t\tif (ess->flags & IEEE80211_JOIN_ANY)\n\t\t\t\tjoin.i_flags |= IEEE80211_JOIN_ANY;\n\t\t\tieee80211_ess_getwpaparms(ess, &join.i_wpaparams);\n\t\t\terror = kernel_copyout(&join, (user_addr_t)&ja->ja_node[ja->ja_nodes],\n\t\t\t    sizeof(ja->ja_node[0]));\n\t\t\tif (error)\n\t\t\t\tbreak;\n\t\t\tlen += sizeof(join);\n\t\t\tja->ja_nodes++;\n\t\t}\n\t\tbreak;\n\tcase SIOCS80211NWKEY:\n//\t\tif ((error = suser(curproc)) != 0)\n//\t\t\tbreak;\n\t\terror = ieee80211_ioctl_setnwkeys(ic, (const struct ieee80211_nwkey *)data);\n\t\tbreak;\n\tcase SIOCG80211NWKEY:\n\t\terror = ieee80211_ioctl_getnwkeys(ic, (struct ieee80211_nwkey *)data);\n\t\tbreak;\n\tcase SIOCS80211WPAPARMS:\n//\t\tif ((error = suser(curproc)) != 0)\n//\t\t\tbreak;\n\t\terror = ieee80211_ioctl_setwpaparms(ic, (const struct ieee80211_wpaparams *)data);\n\t\tbreak;\n\tcase SIOCG80211WPAPARMS:\n\t\terror = ieee80211_ioctl_getwpaparms(ic, (struct ieee80211_wpaparams *)data);\n\t\tbreak;\n\tcase SIOCS80211WPAPSK:\n//\t\tif ((error = suser(curproc)) != 0)\n//\t\t\tbreak;\n\t\tpsk = (struct ieee80211_wpapsk *)data;\n\t\tif (psk->i_enabled) {\n\t\t\tic->ic_flags |= IEEE80211_F_PSK;\n\t\t\tmemcpy(ic->ic_psk, psk->i_psk, sizeof(ic->ic_psk));\n\t\t\tif (ic->ic_flags & IEEE80211_F_WEPON)\n\t\t\t\tieee80211_disable_wep(ic);\n\t\t} else {\n\t\t\tic->ic_flags &= ~IEEE80211_F_PSK;\n\t\t\tmemset(ic->ic_psk, 0, sizeof(ic->ic_psk));\n\t\t}\n\t\terror = ENETRESET;\n\t\tbreak;\n\tcase SIOCG80211WPAPSK:\n\t\tpsk = (struct ieee80211_wpapsk *)data;\n\t\tif (ic->ic_flags & IEEE80211_F_PSK) {\n\t\t\t/* do not show any keys to userland */\n\t\t\tpsk->i_enabled = 2;\n\t\t\tmemset(psk->i_psk, 0, sizeof(psk->i_psk));\n\t\t\tbreak;\t/* return ok but w/o key */\n\t\t} else\n\t\t\tpsk->i_enabled = 0;\n\t\tbreak;\n\tcase SIOCS80211KEYAVAIL:\n//\t\tif ((error = suser(curproc)) != 0)\n//\t\t\tbreak;\n\t\tka = (struct ieee80211_keyavail *)data;\n\t\t(void)ieee80211_pmksa_add(ic, IEEE80211_AKM_8021X,\n\t\t    ka->i_macaddr, ka->i_key, ka->i_lifetime);\n\t\tbreak;\n\tcase SIOCS80211KEYRUN:\n//\t\tif ((error = suser(curproc)) != 0)\n//\t\t\tbreak;\n\t\tkr = (struct ieee80211_keyrun *)data;\n\t\terror = ieee80211_keyrun(ic, kr->i_macaddr);\n\t\tif (error == 0 && (ic->ic_flags & IEEE80211_F_WEPON))\n\t\t\tieee80211_disable_wep(ic);\n\t\tbreak;\n\tcase SIOCS80211POWER:\n//\t\tif ((error = suser(curproc)) != 0)\n//\t\t\tbreak;\n\t\tpower = (struct ieee80211_power *)data;\n\t\tic->ic_lintval = power->i_maxsleep;\n\t\tif (power->i_enabled != 0) {\n\t\t\tif ((ic->ic_caps & IEEE80211_C_PMGT) == 0)\n\t\t\t\terror = EINVAL;\n\t\t\telse if ((ic->ic_flags & IEEE80211_F_PMGTON) == 0) {\n\t\t\t\tic->ic_flags |= IEEE80211_F_PMGTON;\n\t\t\t\terror = ENETRESET;\n\t\t\t}\n\t\t} else {\n\t\t\tif (ic->ic_flags & IEEE80211_F_PMGTON) {\n\t\t\t\tic->ic_flags &= ~IEEE80211_F_PMGTON;\n\t\t\t\terror = ENETRESET;\n\t\t\t}\n\t\t}\n\t\tbreak;\n\tcase SIOCG80211POWER:\n\t\tpower = (struct ieee80211_power *)data;\n\t\tpower->i_enabled = (ic->ic_flags & IEEE80211_F_PMGTON) ? 1 : 0;\n\t\tpower->i_maxsleep = ic->ic_lintval;\n\t\tbreak;\n\tcase SIOCS80211BSSID:\n//\t\tif ((error = suser(curproc)) != 0)\n//\t\t\tbreak;\n\t\tbssid = (struct ieee80211_bssid *)data;\n\t\tif (IEEE80211_ADDR_EQ(bssid->i_bssid, empty_macaddr))\n\t\t\tic->ic_flags &= ~IEEE80211_F_DESBSSID;\n\t\telse {\n\t\t\tic->ic_flags |= IEEE80211_F_DESBSSID;\n\t\t\tIEEE80211_ADDR_COPY(ic->ic_des_bssid, bssid->i_bssid);\n\t\t}\n#ifndef IEEE80211_STA_ONLY\n\t\tif (ic->ic_opmode == IEEE80211_M_HOSTAP)\n\t\t\tbreak;\n#endif\n\t\tswitch (ic->ic_state) {\n\t\tcase IEEE80211_S_INIT:\n\t\tcase IEEE80211_S_SCAN:\n\t\t\terror = ENETRESET;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tif ((ic->ic_flags & IEEE80211_F_DESBSSID) &&\n\t\t\t    !IEEE80211_ADDR_EQ(ic->ic_des_bssid,\n\t\t\t    ic->ic_bss->ni_bssid))\n\t\t\t\terror = ENETRESET;\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\tcase SIOCG80211BSSID:\n\t\tbssid = (struct ieee80211_bssid *)data;\n\t\tswitch (ic->ic_state) {\n\t\tcase IEEE80211_S_INIT:\n\t\tcase IEEE80211_S_SCAN:\n#ifndef IEEE80211_STA_ONLY\n\t\t\tif (ic->ic_opmode == IEEE80211_M_HOSTAP)\n\t\t\t\tIEEE80211_ADDR_COPY(bssid->i_bssid,\n\t\t\t\t    ic->ic_myaddr);\n\t\t\telse\n#endif\n\t\t\tif (ic->ic_flags & IEEE80211_F_DESBSSID)\n\t\t\t\tIEEE80211_ADDR_COPY(bssid->i_bssid,\n\t\t\t\t    ic->ic_des_bssid);\n\t\t\telse\n\t\t\t\tmemset(bssid->i_bssid, 0, IEEE80211_ADDR_LEN);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tIEEE80211_ADDR_COPY(bssid->i_bssid,\n\t\t\t    ic->ic_bss->ni_bssid);\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\tcase SIOCS80211CHANNEL:\n//\t\tif ((error = suser(curproc)) != 0)\n//\t\t\tbreak;\n\t\tchanreq = (struct ieee80211chanreq *)data;\n\t\tif (chanreq->i_channel == IEEE80211_CHAN_ANY)\n\t\t\tic->ic_des_chan = IEEE80211_CHAN_ANYC;\n\t\telse if (chanreq->i_channel > IEEE80211_CHAN_MAX ||\n\t\t    isclr(ic->ic_chan_active, chanreq->i_channel)) {\n\t\t\terror = EINVAL;\n\t\t\tbreak;\n\t\t} else\n\t\t\tic->ic_ibss_chan = ic->ic_des_chan =\n\t\t\t    &ic->ic_channels[chanreq->i_channel];\n\t\tswitch (ic->ic_state) {\n\t\tcase IEEE80211_S_INIT:\n\t\tcase IEEE80211_S_SCAN:\n\t\t\terror = ENETRESET;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tif (ic->ic_opmode == IEEE80211_M_STA) {\n\t\t\t\tif (ic->ic_des_chan != IEEE80211_CHAN_ANYC &&\n\t\t\t\t    ic->ic_bss->ni_chan != ic->ic_des_chan)\n\t\t\t\t\terror = ENETRESET;\n\t\t\t} else {\n\t\t\t\tif (ic->ic_bss->ni_chan != ic->ic_ibss_chan)\n\t\t\t\t\terror = ENETRESET;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\tcase SIOCG80211CHANNEL:\n\t\tchanreq = (struct ieee80211chanreq *)data;\n\t\tswitch (ic->ic_state) {\n\t\tcase IEEE80211_S_INIT:\n\t\tcase IEEE80211_S_SCAN:\n\t\t\tif (ic->ic_opmode == IEEE80211_M_STA)\n\t\t\t\tchan = ic->ic_des_chan;\n\t\t\telse\n\t\t\t\tchan = ic->ic_ibss_chan;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tchan = ic->ic_bss->ni_chan;\n\t\t\tbreak;\n\t\t}\n\t\tchanreq->i_channel = ieee80211_chan2ieee(ic, chan);\n\t\tbreak;\n\tcase SIOCG80211ALLCHANS:\n\t\terror = kernel_copyout(ic->ic_channels,\n\t\t    (user_addr_t)((struct ieee80211_chanreq_all *)data)->i_chans,\n\t\t    sizeof(ic->ic_channels));\n\t\tbreak;\n#if 0\n\tcase SIOCG80211ZSTATS:\n#endif\n\tcase SIOCG80211STATS:\n\t\tifr = (struct ifreq *)data;\n\t\terror = kernel_copyout(&ic->ic_stats, (user_addr_t)ifr->ifr_data,\n\t\t    sizeof(ic->ic_stats));\n#if 0\n\t\tif (cmd == SIOCG80211ZSTATS)\n\t\t\tmemset(&ic->ic_stats, 0, sizeof(ic->ic_stats));\n#endif\n\t\tbreak;\n\tcase SIOCS80211TXPOWER:\n//\t\tif ((error = suser(curproc)) != 0)\n//\t\t\tbreak;\n\t\ttxpower = (struct ieee80211_txpower *)data;\n\t\tif ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0) {\n\t\t\terror = EINVAL;\n\t\t\tbreak;\n\t\t}\n\t\tif (!(IEEE80211_TXPOWER_MIN <= txpower->i_val &&\n\t\t\ttxpower->i_val <= IEEE80211_TXPOWER_MAX)) {\n\t\t\terror = EINVAL;\n\t\t\tbreak;\n\t\t}\n\t\tic->ic_txpower = txpower->i_val;\n\t\terror = ENETRESET;\n\t\tbreak;\n\tcase SIOCG80211TXPOWER:\n\t\ttxpower = (struct ieee80211_txpower *)data;\n\t\tif ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0)\n\t\t\terror = EINVAL;\n\t\telse\n\t\t\ttxpower->i_val = ic->ic_txpower;\n\t\tbreak;\n\tcase SIOCSIFMTU:\n//\t\tifr = (struct ifreq *)data;\n//\t\tif (!(IEEE80211_MTU_MIN <= ifr->ifr_mtu &&\n//\t\t    ifr->ifr_mtu <= IEEE80211_MTU_MAX))\n//\t\t\terror = EINVAL;\n//\t\telse\n//\t\t\tifp->if_mtu = ifr->ifr_mtu;\n\t\tbreak;\n\tcase SIOCS80211SCAN:\n\t\t/* Disabled. SIOCG80211ALLNODES is enough. */\n\t\tbreak;\n\tcase SIOCG80211NODE:\n\t\tnr = (struct ieee80211_nodereq *)data;\n\t\tif (ic->ic_bss &&\n\t\t    IEEE80211_ADDR_EQ(nr->nr_macaddr, ic->ic_bss->ni_macaddr))\n\t\t\tni = ic->ic_bss;\n\t\telse\n\t\t\tni = ieee80211_find_node(ic, nr->nr_macaddr);\n\t\tif (ni == NULL) {\n\t\t\terror = ENOENT;\n\t\t\tbreak;\n\t\t}\n\t\tieee80211_node2req(ic, ni, nr);\n\t\tbreak;\n\tcase SIOCS80211NODE:\n//\t\tif ((error = suser(curproc)) != 0)\n//\t\t\tbreak;\n#ifndef IEEE80211_STA_ONLY\n\t\tif (ic->ic_opmode == IEEE80211_M_HOSTAP) {\n\t\t\terror = EINVAL;\n\t\t\tbreak;\n\t\t}\n#endif\n\t\tnr = (struct ieee80211_nodereq *)data;\n\n\t\tni = ieee80211_find_node(ic, nr->nr_macaddr);\n\t\tif (ni == NULL)\n\t\t\tni = ieee80211_alloc_node(ic, nr->nr_macaddr);\n\t\tif (ni == NULL) {\n\t\t\terror = ENOENT;\n\t\t\tbreak;\n\t\t}\n\n\t\tif (nr->nr_flags & IEEE80211_NODEREQ_COPY)\n\t\t\tieee80211_req2node(ic, nr, ni);\n\t\tbreak;\n#ifndef IEEE80211_STA_ONLY\n\tcase SIOCS80211DELNODE:\n//\t\tif ((error = suser(curproc)) != 0)\n//\t\t\tbreak;\n\t\tnr = (struct ieee80211_nodereq *)data;\n\t\tni = ieee80211_find_node(ic, nr->nr_macaddr);\n\t\tif (ni == NULL)\n\t\t\terror = ENOENT;\n\t\telse if (ni == ic->ic_bss)\n\t\t\terror = EPERM;\n\t\telse {\n\t\t\tif (ni->ni_state == IEEE80211_STA_COLLECT)\n\t\t\t\tbreak;\n\n\t\t\t/* Disassociate station. */\n\t\t\tif (ni->ni_state == IEEE80211_STA_ASSOC)\n\t\t\t\tIEEE80211_SEND_MGMT(ic, ni,\n\t\t\t\t    IEEE80211_FC0_SUBTYPE_DISASSOC,\n\t\t\t\t    IEEE80211_REASON_ASSOC_LEAVE);\n\n\t\t\t/* Deauth station. */\n\t\t\tif (ni->ni_state >= IEEE80211_STA_AUTH)\n\t\t\t\tIEEE80211_SEND_MGMT(ic, ni,\n\t\t\t\t    IEEE80211_FC0_SUBTYPE_DEAUTH,\n\t\t\t\t    IEEE80211_REASON_AUTH_LEAVE);\n\n\t\t\tieee80211_node_leave(ic, ni);\n\t\t}\n\t\tbreak;\n#endif\n\tcase SIOCG80211ALLNODES:\n\t\tif ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) !=\n\t\t    (IFF_UP | IFF_RUNNING)) {\n\t\t\terror = ENETDOWN;\n\t\t\tbreak;\n\t\t}\n\n\t\tna = (struct ieee80211_nodereq_all *)data;\n\t\tna->na_nodes = i = 0;\n\t\tni = RB_MIN(ieee80211_tree, &ic->ic_tree);\n\t\twhile (ni && na->na_size >=\n\t\t    i + sizeof(struct ieee80211_nodereq)) {\n\t\t\tieee80211_node2req(ic, ni, &nrbuf);\n\t\t\terror = kernel_copyout(&nrbuf, (user_addr_t)(caddr_t)na->na_node + i,\n\t\t\t    sizeof(struct ieee80211_nodereq));\n\t\t\tif (error)\n\t\t\t\tbreak;\n\t\t\ti += sizeof(struct ieee80211_nodereq);\n\t\t\tna->na_nodes++;\n\t\t\tni = RB_NEXT(ieee80211_tree, &ic->ic_tree, ni);\n\t\t}\n\t\tbreak;\n\tcase SIOCG80211FLAGS:\n\t\tflags = ic->ic_userflags;\n#ifndef IEEE80211_STA_ONLY\n\t\tif (ic->ic_opmode != IEEE80211_M_HOSTAP)\n#endif\n\t\t\tflags &= ~IEEE80211_F_HOSTAPMASK;\n\t\tifr->ifr_flags = flags;\n\t\tbreak;\n\tcase SIOCS80211FLAGS:\n//\t\tif ((error = suser(curproc)) != 0)\n//\t\t\tbreak;\n\t\tflags = ifr->ifr_flags;\n\t\tif (\n#ifndef IEEE80211_STA_ONLY\n\t\t    ic->ic_opmode != IEEE80211_M_HOSTAP &&\n#endif\n\t\t    (flags & IEEE80211_F_HOSTAPMASK)) {\n\t\t\terror = EINVAL;\n\t\t\tbreak;\n\t\t}\n\t\tic->ic_userflags = flags;\n\t\terror = ENETRESET;\n\t\tbreak;\n//\tcase SIOCADDMULTI:\n//\tcase SIOCDELMULTI:\n//\t\terror = (cmd == SIOCADDMULTI) ?\n//\t\t    ether_addmulti(ifr, &ic->ic_ac) :\n//\t\t    ether_delmulti(ifr, &ic->ic_ac);\n//\t\tif (error == ENETRESET)\n//\t\t\terror = 0;\n//\t\tbreak;\n\tdefault:\n//\t\terror = ether_ioctl(ifp, &ic->ic_ac, cmd, data);\n        break;\n\t}\n\n\treturn error;\n}\n"
  },
  {
    "path": "itl80211/openbsd/net80211/ieee80211_ioctl.h",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n/*\t$OpenBSD: ieee80211_ioctl.h,v 1.41 2020/10/06 07:23:15 gerhard Exp $\t*/\n/*\t$NetBSD: ieee80211_ioctl.h,v 1.7 2004/04/30 22:51:04 dyoung Exp $\t*/\n\n/*-\n * Copyright (c) 2001 Atsushi Onoe\n * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. The name of the author may not be used to endorse or promote products\n *    derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * $FreeBSD: src/sys/net80211/ieee80211_ioctl.h,v 1.5 2004/03/30 22:57:57 sam Exp $\n */\n#ifndef _NET80211_IEEE80211_IOCTL_H_\n#define _NET80211_IEEE80211_IOCTL_H_\n\n/*\n * IEEE 802.11 ioctls.\n */\n\n/* per-interface statistics */\nstruct ieee80211_stats {\n\tu_int32_t\tis_rx_badversion;\t/* rx frame with bad version */\n\tu_int32_t\tis_rx_tooshort;\t\t/* rx frame too short */\n\tu_int32_t\tis_rx_wrongbss;\t\t/* rx from wrong bssid */\n\tu_int32_t\tis_rx_dup;\t\t/* rx discard 'cuz dup */\n\tu_int32_t\tis_rx_wrongdir;\t\t/* rx w/ wrong direction */\n\tu_int32_t\tis_rx_mcastecho;\t/* rx discard 'cuz mcast echo */\n\tu_int32_t\tis_rx_notassoc;\t\t/* rx discard 'cuz sta !assoc */\n\tu_int32_t\tis_rx_nowep;\t\t/* rx w/ wep but wep !config */\n\tu_int32_t\tis_rx_unencrypted;\t/* rx w/o wep but wep config */\n\tu_int32_t\tis_rx_wepfail;\t\t/* rx wep processing failed */\n\tu_int32_t\tis_rx_decap;\t\t/* rx decapsulation failed */\n\tu_int32_t\tis_rx_mgtdiscard;\t/* rx discard mgt frames */\n\tu_int32_t\tis_rx_ctl;\t\t/* rx discard ctrl frames */\n\tu_int32_t\tis_rx_rstoobig;\t\t/* rx rate set truncated */\n\tu_int32_t\tis_rx_elem_missing;\t/* rx required element missing*/\n\tu_int32_t\tis_rx_elem_toobig;\t/* rx element too big */\n\tu_int32_t\tis_rx_elem_toosmall;\t/* rx element too small */\n\tu_int32_t\tis_rx_badchan;\t\t/* rx frame w/ invalid chan */\n\tu_int32_t\tis_rx_chanmismatch;\t/* rx frame chan mismatch */\n\tu_int32_t\tis_rx_nodealloc;\t/* rx frame dropped */\n\tu_int32_t\tis_rx_ssidmismatch;\t/* rx frame ssid mismatch  */\n\tu_int32_t\tis_rx_auth_unsupported;\t/* rx w/ unsupported auth alg */\n\tu_int32_t\tis_rx_auth_fail;\t/* rx sta auth failure */\n\tu_int32_t\tis_rx_assoc_bss;\t/* rx assoc from wrong bssid */\n\tu_int32_t\tis_rx_assoc_notauth;\t/* rx assoc w/o auth */\n\tu_int32_t\tis_rx_assoc_capmismatch;/* rx assoc w/ cap mismatch */\n\tu_int32_t\tis_rx_assoc_norate;\t/* rx assoc w/ no rate match */\n\tu_int32_t\tis_rx_deauth;\t\t/* rx deauthentication */\n\tu_int32_t\tis_rx_disassoc;\t\t/* rx disassociation */\n\tu_int32_t\tis_rx_badsubtype;\t/* rx frame w/ unknown subtype*/\n\tu_int32_t\tis_rx_nombuf;\t\t/* rx failed for lack of mbuf */\n\tu_int32_t\tis_rx_decryptcrc;\t/* rx decrypt failed on crc */\n\tu_int32_t\tis_rx_ahdemo_mgt;\t/* rx discard ahdemo mgt frame*/\n\tu_int32_t\tis_rx_bad_auth;\t\t/* rx bad auth request */\n\tu_int32_t\tis_tx_nombuf;\t\t/* tx failed for lack of mbuf */\n\tu_int32_t\tis_tx_nonode;\t\t/* tx failed for no node */\n\tu_int32_t\tis_tx_unknownmgt;\t/* tx of unknown mgt frame */\n\tu_int32_t\tis_scan_active;\t\t/* active scans started */\n\tu_int32_t\tis_scan_passive;\t/* passive scans started */\n\tu_int32_t\tis_node_timeout;\t/* nodes timed out inactivity */\n\tu_int32_t\tis_crypto_nomem;\t/* no memory for crypto ctx */\n\tu_int32_t\tis_rx_assoc_badrsnie;\t/* rx assoc w/ bad RSN IE */\n\tu_int32_t\tis_rx_unauth;\t\t/* rx port not valid */\n\tu_int32_t\tis_tx_noauth;\t\t/* tx port not valid */\n\tu_int32_t\tis_rx_eapol_key;\t/* rx eapol-key frames */\n\tu_int32_t\tis_rx_eapol_replay;\t/* rx replayed eapol frames */\n\tu_int32_t\tis_rx_eapol_badmic;\t/* rx eapol frames w/ bad mic */\n\tu_int32_t\tis_rx_remmicfail;\t/* rx tkip remote mic fails */\n\tu_int32_t\tis_rx_locmicfail;\t/* rx tkip local mic fails */\n\tu_int32_t\tis_tkip_replays;\n\tu_int32_t\tis_tkip_icv_errs;\n\tu_int32_t\tis_ccmp_replays;\n\tu_int32_t\tis_ccmp_dec_errs;\n\tu_int32_t\tis_cmac_replays;\n\tu_int32_t\tis_cmac_icv_errs;\n\tu_int32_t\tis_pbac_errs;\n\tu_int32_t\tis_ht_nego_no_mandatory_mcs;\n\tu_int32_t\tis_ht_nego_no_basic_mcs;\n\tu_int32_t\tis_ht_nego_bad_crypto;\n\tu_int32_t\tis_ht_prot_change;\n\tu_int32_t\tis_ht_rx_ba_agreements;\n\tu_int32_t\tis_ht_tx_ba_agreements;\n\tu_int32_t\tis_ht_rx_frame_below_ba_winstart;\n\tu_int32_t\tis_ht_rx_frame_above_ba_winend;\n\tu_int32_t\tis_ht_rx_ba_window_slide;\n\tu_int32_t\tis_ht_rx_ba_window_jump;\n\tu_int32_t\tis_ht_rx_ba_no_buf;\n\tu_int32_t\tis_ht_rx_ba_frame_lost;\n\tu_int32_t\tis_ht_rx_ba_window_gap_timeout;\n\tu_int32_t\tis_ht_rx_ba_timeout;\n\tu_int32_t\tis_ht_tx_ba_timeout;\n    u_int32_t   is_vht_nego_no_mandatory_mcs;\n    u_int32_t   is_vht_nego_bad_crypto;\n};\n\n#define\tSIOCG80211STATS\t\t_IOWR('i', 242, struct ifreq)\n\n/* network identifier (ESSID), nwid is pointed at by ifr.ifr_data */\nstruct ieee80211_nwid {\n\tu_int8_t\ti_len;\n\tu_int8_t\ti_nwid[IEEE80211_NWID_LEN];\n};\n\n#define\tSIOCS80211NWID\t\t_IOWR('i', 230, struct ifreq)\n#define\tSIOCG80211NWID\t\t_IOWR('i', 231, struct ifreq)\n\n/* network key (WEP), the first member must be matched with struct ifreq */\nstruct ieee80211_nwkey {\n\tchar\t\ti_name[IFNAMSIZ];\t/* if_name, e.g. \"wi0\" */\n\tint\t\ti_wepon;\t\t/* wep enabled flag */\n\tint\t\ti_defkid;\t\t/* default encrypt key id */\n\tstruct {\n\t\tint\t\ti_keylen;\n\t\tu_int8_t\t*i_keydat;\n\t}\t\ti_key[IEEE80211_WEP_NKID];\n};\n\n#define\tIEEE80211_NWKEY_OPEN\t0\t\t/* No privacy */\n#define\tIEEE80211_NWKEY_WEP\t1\t\t/* WEP enabled */\n#define\tIEEE80211_NWKEY_EAP\t2\t\t/* EAP enabled */\n#define\tIEEE80211_NWKEY_PERSIST\t0x100\t\t/* designate persist keyset */\n\n#define\tSIOCS80211NWKEY\t\t _IOW('i', 232, struct ieee80211_nwkey)\n#define\tSIOCG80211NWKEY\t\t_IOWR('i', 233, struct ieee80211_nwkey)\n\n/* power management parameters */\nstruct ieee80211_power {\n\tchar\t\ti_name[IFNAMSIZ];\t/* if_name, e.g. \"wi0\" */\n\tint\t\ti_enabled;\t\t/* 1 == on, 0 == off */\n\tint\t\ti_maxsleep;\t\t/* max sleep in ms */\n};\n#define\tSIOCS80211POWER\t\t _IOW('i', 234, struct ieee80211_power)\n#define\tSIOCG80211POWER\t\t_IOWR('i', 235, struct ieee80211_power)\n\n#define\tIEEE80211_AUTH_NONE\t0\n#define\tIEEE80211_AUTH_OPEN\t1\n#define\tIEEE80211_AUTH_SHARED\t2\n\n/* channel request */\nstruct ieee80211chanreq {\n\tchar\t\ti_name[IFNAMSIZ];\t/* if_name, e.g. \"wi0\" */\n\tu_int16_t\ti_channel;\n};\n\n#ifndef _KERNEL\n/*\n * Channels are specified by frequency and attributes.\n */\nstruct ieee80211_channel {\n\tu_int16_t\tic_freq;\t/* setting in MHz */\n\tu_int16_t\tic_flags;\t/* see below */\n};\n\n/*\n * Channel attributes (XXX must keep in sync with radiotap flags).\n */\n#define IEEE80211_CHAN_CCK\t0x0020\t/* CCK channel */\n#define IEEE80211_CHAN_OFDM\t0x0040\t/* OFDM channel */\n#define IEEE80211_CHAN_2GHZ\t0x0080\t/* 2 GHz spectrum channel */\n#define IEEE80211_CHAN_5GHZ\t0x0100\t/* 5 GHz spectrum channel */\n#define IEEE80211_CHAN_PASSIVE\t0x0200\t/* Only passive scan allowed */\n#define IEEE80211_CHAN_DYN\t0x0400\t/* Dynamic CCK-OFDM channel */\n#define IEEE80211_CHAN_XR\t0x1000\t/* Extended range OFDM channel */\n#define IEEE80211_CHAN_HT\t0x2000\t/* 11n/HT channel */\n#endif\t/* !_KERNEL */\n\nstruct ieee80211_chanreq_all {\n\tchar\t\ti_name[IFNAMSIZ];\t/* if_name, e.g. \"wi0\" */\n\tstruct ieee80211_channel *i_chans;\n};\n\n#ifndef IEEE80211_CHAN_ANY\n#define\tIEEE80211_CHAN_ANY\t0xffff\n#endif\n\n#define\tSIOCS80211CHANNEL\t _IOW('i', 238, struct ieee80211chanreq)\n#define\tSIOCG80211CHANNEL\t_IOWR('i', 239, struct ieee80211chanreq)\n#define\tSIOCG80211ALLCHANS\t_IOWR('i', 215, struct ieee80211_chanreq_all)\n\n/* BSS identifier */\nstruct ieee80211_bssid {\n\tchar\t\ti_name[IFNAMSIZ];\t/* if_name, e.g. \"wi0\" */\n\tu_int8_t\ti_bssid[IEEE80211_ADDR_LEN];\n};\n\n#define\tSIOCS80211BSSID\t\t _IOW('i', 240, struct ieee80211_bssid)\n#define\tSIOCG80211BSSID\t\t_IOWR('i', 241, struct ieee80211_bssid)\n\n/* transmit power */\nstruct ieee80211_txpower {\n\tchar\t\ti_name[IFNAMSIZ];\t/* if_name, e.g. \"wi0\" */\n\tint\t\ti_mode;\t\t\t/* auto, manual */\n\tint16_t\t\ti_val;\t\t\t/* dBm */\n};\n\n#define\tSIOCS80211TXPOWER\t _IOW('i', 243, struct ieee80211_txpower)\n#define\tSIOCG80211TXPOWER\t_IOWR('i', 244, struct ieee80211_txpower)\n\n#define IEEE80211_TXPOWER_MODE_FIXED\t0\t/* fixed tx power value */\n#define IEEE80211_TXPOWER_MODE_AUTO\t1\t/* auto level control */\n\nstruct ieee80211_wpapsk {\n\tchar\t\ti_name[IFNAMSIZ];\t/* if_name, e.g. \"wi0\" */\n\tint\t\ti_enabled;\n\tu_int8_t\ti_psk[32];\n};\n\n#define SIOCS80211WPAPSK\t _IOW('i', 245, struct ieee80211_wpapsk)\n#define SIOCG80211WPAPSK\t_IOWR('i', 246, struct ieee80211_wpapsk)\n\n#define IEEE80211_WPA_PROTO_WPA1\t0x01\n#define IEEE80211_WPA_PROTO_WPA2\t0x02\n\n#define IEEE80211_WPA_CIPHER_NONE\t0x00\n#define IEEE80211_WPA_CIPHER_USEGROUP\t0x01\n#define IEEE80211_WPA_CIPHER_WEP40\t0x02\n#define IEEE80211_WPA_CIPHER_TKIP\t0x04\n#define IEEE80211_WPA_CIPHER_CCMP\t0x08\n#define IEEE80211_WPA_CIPHER_WEP104\t0x10\n#define IEEE80211_WPA_CIPHER_BIP\t0x20\n\n#define IEEE80211_WPA_AKM_PSK\t\t0x01\n#define IEEE80211_WPA_AKM_8021X\t\t0x02\n#define IEEE80211_WPA_AKM_SHA256_PSK\t0x04\n#define IEEE80211_WPA_AKM_SHA256_8021X\t0x08\n\nstruct ieee80211_wpaparams {\n\tchar\ti_name[IFNAMSIZ];\t\t/* if_name, e.g. \"wi0\" */\n\tint\ti_enabled;\n\tu_int\ti_protos;\n\tu_int\ti_akms;\n\tu_int\ti_ciphers;\n\tu_int\ti_groupcipher;\n};\n\n#define SIOCS80211WPAPARMS\t _IOW('i', 247, struct ieee80211_wpaparams)\n#define SIOCG80211WPAPARMS\t_IOWR('i', 248, struct ieee80211_wpaparams)\n\nstruct ieee80211_keyavail {\n\tchar\t\ti_name[IFNAMSIZ];\t/* if_name, e.g. \"wi0\" */\n\tu_int8_t\ti_macaddr[IEEE80211_ADDR_LEN];\n\tu_int8_t\ti_key[32];\n\tu_int32_t\ti_lifetime;\n};\n\nstruct ieee80211_keyrun {\n\tchar\t\ti_name[IFNAMSIZ];\t/* if_name, e.g. \"wi0\" */\n\tu_int8_t\ti_macaddr[IEEE80211_ADDR_LEN];\n};\n\n#define SIOCS80211KEYAVAIL\t _IOW('i', 251, struct ieee80211_keyavail)\n#define SIOCS80211KEYRUN\t _IOW('i', 252, struct ieee80211_keyrun)\n\n/* scan request (will block) */\n#define IEEE80211_SCAN_TIMEOUT\t30\t/* timeout in seconds */\n\n#define SIOCS80211SCAN\t\t _IOW('i', 210, struct ifreq)\n\n#define\tSIOCG80211JOINALL\t_IOWR('i', 218, struct ieee80211_joinreq_all)\n#define\tSIOCS80211JOIN\t\t_IOWR('i', 255, struct ifreq)\n#define\tSIOCG80211JOIN\t\t_IOWR('i', 0, struct ifreq)\n\n/* join is pointed at by ifr.ifr_data */\nstruct ieee80211_join {\n\tu_int8_t\ti_len;\t/* length of i_nwid */\n\tu_int8_t\ti_nwid[IEEE80211_NWID_LEN];\n\tu_int32_t\ti_flags;\n\n\tstruct ieee80211_wpaparams\t i_wpaparams;\n\tstruct ieee80211_wpapsk\t\t i_wpapsk;\n\tstruct ieee80211_nwkey\t\t i_nwkey;\n};\n\nstruct ieee80211_joinreq_all {\n\tchar\t\t\t ja_ifname[IFNAMSIZ];\n\tint\t\t\t ja_nodes; /* returned count */\n\tsize_t\t\t\t ja_size;  /* size of node buffer */\n\tstruct ieee80211_join\t*ja_node;  /* allocated node buffer */\n};\n\n\n#define IEEE80211_JOIN_SHOW\t0x01\n#define IEEE80211_JOIN_FOUND\t0x02\n#define IEEE80211_JOIN_DEL\t0x04\n#define IEEE80211_JOIN_NWKEY\t0x08\n#define IEEE80211_JOIN_WPA\t0x10\n#define IEEE80211_JOIN_WPAPSK\t0x20\n#define IEEE80211_JOIN_8021X\t0x40\n#define IEEE80211_JOIN_ANY\t0x80\n#define IEEE80211_JOIN_DEL_ALL\t0x100\n\n/* node and requests */\nstruct ieee80211_nodereq {\n\tchar\t\tnr_ifname[IFNAMSIZ];\t\t/* e.g. \"ath0\" */\n\n\t/* Node address and name information */\n\tu_int8_t\tnr_macaddr[IEEE80211_ADDR_LEN];\t/* node lladdr */\n\tu_int8_t\tnr_bssid[IEEE80211_ADDR_LEN];\t/* bssid */\n\tu_int8_t\tnr_nwid_len;\t\t\t/* ESSID length */\n\tu_int8_t\tnr_nwid[IEEE80211_NWID_LEN];\t/* ESSID */\n\n\t/* Channel and rates */\n\tu_int16_t\tnr_channel;\t\t\t/* last channel */\n\tu_int32_t\tnr_chan_flags;\t\t/* channel flags */\n\tu_int8_t\tnr_nrates;\t\t\t/* rate count */\n\tu_int8_t\tnr_rates[IEEE80211_RATE_MAXSIZE];\t/* rate set */\n\n\t/* Node status information */\n\tint8_t\t\tnr_rssi;\t/* received signal strength */\n\tint8_t\t\tnr_max_rssi;\t/* maximum rssi */\n\tu_int8_t\tnr_tstamp[8];\t/* from last received beacon */\n\tu_int16_t\tnr_intval;\t/* beacon interval */\n\tu_int16_t\tnr_capinfo;\t/* capabilities */\n\tu_int8_t\tnr_erp;\t\t/* 11g only */\n\tu_int8_t\tnr_pwrsave;\t/* power saving mode */\n\tu_int16_t\tnr_associd;\t/* assoc response */\n\tu_int16_t\tnr_txseq;\t/* seq to be transmitted */\n\tu_int16_t\tnr_rxseq;\t/* seq previous received */\n\tu_int32_t\tnr_fails;\t/* failure count to associate */\n\tu_int32_t\tnr_inact;\t/* inactivity mark count */\n\tu_int8_t\tnr_txrate;\t/* index to nr_rates[] */\n\tu_int16_t\tnr_state;\t/* node state in the cache */\n\n\t/* RSN */\n\tu_int\t\tnr_rsnprotos;\n\tu_int\t\tnr_rsnciphers;\n\tu_int\t\tnr_rsnakms;\n\n\t/* Node flags */\n\tu_int8_t\tnr_flags;\n\n\t/* HT */\n\tuint16_t\t\tnr_htcaps;\n\tuint8_t\t\t\tnr_rxmcs[howmany(80,NBBY)];\n\tuint16_t\t\tnr_max_rxrate;\t/* in Mb/s, 0 <= rate <= 1023 */\n\tuint8_t\t\t\tnr_tx_mcs_set;\n\n\t/* HT / VHT */\n\tuint8_t\t\t\tnr_txmcs;\n\n\t/* VHT */\n\tuint8_t\t\t\tnr_vht_ss;\n\n\tu_int32_t\tnr_assoc_fail;\t/* association failure reasons */\n};\n\n#define IEEE80211_NODEREQ_STATE(_s)\t(1 << _s)\n#define IEEE80211_NODEREQ_STATE_BITS\t\t\t\t\t\\\n\t\"\\20\\01CACHE\\02BSS\\03AUTH\\04ASSOC\\05COLLECT\"\n\n#define IEEE80211_NODEREQ_RSSI(_nr)\t\t\t\t\t\\\n\t((u_int)(((float)(_nr)->nr_rssi / (_nr)->nr_max_rssi) * 100))\n\n#define IEEE80211_NODEREQ_STA\t\t0x00\t/* station */\n#define IEEE80211_NODEREQ_AP\t\t0x01\t/* access point */\n#define IEEE80211_NODEREQ_AP_BSS\t0x02\t/* current bss access point */\n#define IEEE80211_NODEREQ_COPY\t\t0x04\t/* add node with flags */\n#define IEEE80211_NODEREQ_HT\t\t0x08\t/* HT negotiated */\n#define IEEE80211_NODEREQ_VHT\t\t0x10\t/* VHT negotiated */\n\n#define SIOCG80211NODE\t\t_IOWR('i', 211, struct ieee80211_nodereq)\n#define SIOCS80211NODE\t\t _IOW('i', 212, struct ieee80211_nodereq)\n#define SIOCS80211DELNODE\t _IOW('i', 213, struct ieee80211_nodereq)\n\n#define IEEE80211_NODEREQ_ASSOCFAIL_CHAN\t0x01\n#define IEEE80211_NODEREQ_ASSOCFAIL_IBSS\t0x02\n#define IEEE80211_NODEREQ_ASSOCFAIL_PRIVACY\t0x04\n#define IEEE80211_NODEREQ_ASSOCFAIL_BASIC_RATE\t0x08\n#define IEEE80211_NODEREQ_ASSOCFAIL_ESSID\t0x10\n#define IEEE80211_NODEREQ_ASSOCFAIL_BSSID\t0x20\n#define IEEE80211_NODEREQ_ASSOCFAIL_WPA_PROTO\t0x40\n#define IEEE80211_NODEREQ_ASSOCFAIL_WPA_KEY\t0x80\n#define IEEE80211_NODEREQ_ASSOCFAIL_BITS\t\\\n\t\"\\20\\1!CHAN\\2!IBSS\\3!PRIVACY\\4!BASICRATE\\5!ESSID\\6!BSSID\\7!WPAPROTO\" \\\n\t\"\\10!WPAKEY\"\n\n/* get the entire node cache */\nstruct ieee80211_nodereq_all {\n\tchar\t\t\t\tna_ifname[IFNAMSIZ];\t/* e.g. \"ath0\" */\n\n\tint\t\t\t\tna_nodes;\t/* returned count */\n\tsize_t\t\t\t\tna_size;\t/* size of node buffer */\n\tstruct ieee80211_nodereq\t*na_node;\t/* allocated node buffer */\n\n\t/* Match nodes by flag */\n\tu_int8_t\t\t\tna_flags;\t/* IEEE80211_NODEREQ_* */\n};\n\n#define SIOCG80211ALLNODES\t_IOWR('i', 214, struct ieee80211_nodereq_all)\n\n/* net80211 specific interface flags */\n#define IEEE80211_F_HIDENWID\t0x00000001\t/* CONF: hidden ssid mode */\n#define IEEE80211_F_NOBRIDGE\t0x00000002\t/* CONF: no internal bridging */\n#define IEEE80211_F_HOSTAPMASK\t0x00000003\n#define IEEE80211_F_STAYAUTH\t0x00000004\t/* CONF: ignore deauth */\n#define IEEE80211_F_NOMIMO    0x00000008    /* CONF: disable MIMO */\n#define IEEE80211_F_NOVHT       0x00000010  /* CONF: disable 11ac */\n#define IEEE80211_F_NOHT40      0x00000020  /* CONF: disable 40mhz on 2.4Ghz channel */\n#define IEEE80211_F_USERBITS    \"\\20\\01HIDENWID\\02NOBRIDGE\\03STAYAUTH\\04NOMIMO\"\n\nstruct ieee80211_flags {\n\tconst char\t\t*f_name;\n\tu_int\t\t\tf_flag;\n};\n\n#define IEEE80211_FLAGS\t{\t\t\t\\\n\t{ \"hidenwid\", IEEE80211_F_HIDENWID },\t\\\n\t{ \"nobridge\", IEEE80211_F_NOBRIDGE },\t\\\n\t{ \"stayauth\", IEEE80211_F_STAYAUTH },    \\\n    { \"nomimo\", IEEE80211_F_NOMIMO },    \\\n    { \"novht\", IEEE80211_F_NOVHT },        \\\n    { \"noht40\", IEEE80211_F_NOHT40 },     \\\n}\n\n#define SIOCG80211FLAGS\t\t_IOWR('i', 216, struct ifreq)\n#define SIOCS80211FLAGS\t\t _IOW('i', 217, struct ifreq)\n\nint\nieee80211_ioctl_setnwkeys(struct ieee80211com *ic,\n                          const struct ieee80211_nwkey *nwkey);\n\nint\nieee80211_ioctl_setwpaparms(struct ieee80211com *ic,\n                            const struct ieee80211_wpaparams *wpa);\n\nint\nieee80211_ioctl_getwpaparms(struct ieee80211com *ic,\n                            struct ieee80211_wpaparams *wpa);\n\nvoid\nieee80211_ess_getwpaparms(struct ieee80211_ess *ess,\n                          struct ieee80211_wpaparams *wpa);\n\n#endif /* _NET80211_IEEE80211_IOCTL_H_ */\n"
  },
  {
    "path": "itl80211/openbsd/net80211/ieee80211_mira.c",
    "content": "/*\n * Copyright (C) 2020  钟先耀\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n */\n/*    $OpenBSD: ieee80211_mira.c,v 1.30 2020/05/01 14:04:17 stsp Exp $    */\n\n/*\n * Copyright (c) 2016 Stefan Sperling <stsp@openbsd.org>\n * Copyright (c) 2016 Theo Buehler <tb@openbsd.org>\n * Copyright (c) 2006 Damien Bergamini <damien.bergamini@free.fr>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n#include <sys/param.h>\n#include <sys/systm.h>\n#include <sys/socket.h>\n\n#include <net/if.h>\n#include <net/if_media.h>\n\n#include <netinet/in.h>\n#include <netinet/if_ether.h>\n#include <sys/_arc4random.h>\n\n#include <net80211/ieee80211_var.h>\n#include <net80211/ieee80211_mira.h>\n\n/* Allow for aggressive down probing when channel quality changes. */\n#define MIRA_AGGRESSIVE_DOWNWARDS_PROBING\n\nconst struct ieee80211_ht_rateset *\tieee80211_mira_get_rateset(int, int, bool);\nvoid\tieee80211_mira_probe_timeout_up(void *);\nvoid\tieee80211_mira_probe_timeout_down(void *);\nuint64_t ieee80211_mira_get_txrate(int, int, bool is_40mhz);\nuint16_t ieee80211_mira_legacy_txtime(uint32_t, int, struct ieee80211com *);\nuint32_t ieee80211_mira_ht_txtime(uint32_t, int, int, int, bool is_40mhz);\nint\tieee80211_mira_best_basic_rate(struct ieee80211_node *);\nint\tieee80211_mira_ack_rate(struct ieee80211_node *);\nuint64_t ieee80211_mira_toverhead(struct ieee80211_mira_node *,\n                                  struct ieee80211com *, struct ieee80211_node *);\nvoid\tieee80211_mira_update_stats(struct ieee80211_mira_node *,\n                                    struct ieee80211com *, struct ieee80211_node *);\nvoid\tieee80211_mira_reset_goodput_stats(struct ieee80211_mira_node *);\nvoid\tieee80211_mira_reset_driver_stats(struct ieee80211_mira_node *);\nint\tieee80211_mira_next_lower_intra_rate(struct ieee80211_mira_node *,\n                                         struct ieee80211_node *);\nint\tieee80211_mira_next_intra_rate(struct ieee80211_mira_node *,\n                                   struct ieee80211_node *);\nconst struct ieee80211_ht_rateset * ieee80211_mira_next_rateset(\n                                                                struct ieee80211_mira_node *, struct ieee80211_node *);\nint\tieee80211_mira_best_mcs_in_rateset(struct ieee80211_mira_node *,\n                                       const struct ieee80211_ht_rateset *);\nvoid\tieee80211_mira_probe_next_rateset(struct ieee80211_mira_node *,\n                                          struct ieee80211_node *, const struct ieee80211_ht_rateset *);\nint\tieee80211_mira_next_mcs(struct ieee80211_mira_node *,\n                            struct ieee80211_node *);\nint\tieee80211_mira_prev_mcs(struct ieee80211_mira_node *,\n                            struct ieee80211_node *);\nint\tieee80211_mira_probe_valid(struct ieee80211_mira_node *,\n                               struct ieee80211_node *);\nvoid\tieee80211_mira_probe_done(struct ieee80211_mira_node *);\nint\tieee80211_mira_intra_mode_ra_finished(\n                                          struct ieee80211_mira_node *, struct ieee80211_node *);\nvoid\tieee80211_mira_trigger_next_rateset(struct ieee80211_mira_node *mn,\n                                            struct ieee80211_node *);\nint\tieee80211_mira_inter_mode_ra_finished(\n                                          struct ieee80211_mira_node *, struct ieee80211_node *);\nint\tieee80211_mira_best_rate(struct ieee80211_mira_node *,\n                             struct ieee80211_node *);\nvoid\tieee80211_mira_update_probe_interval(\n                                             struct ieee80211_mira_goodput_stats *);\nvoid\tieee80211_mira_schedule_probe_timers(struct ieee80211_mira_node *,\n                                             struct ieee80211_node *);\nint\tieee80211_mira_check_probe_timers(struct ieee80211_mira_node *,\n                                      struct ieee80211_node *);\nvoid\tieee80211_mira_probe_next_rate(struct ieee80211_mira_node *,\n                                       struct ieee80211_node *);\nint\tieee80211_mira_valid_tx_mcs(struct ieee80211com *, int);\nuint32_t ieee80211_mira_valid_rates(struct ieee80211com *,\n                                    struct ieee80211_node *);\nuint32_t ieee80211_mira_mcs_below(struct ieee80211_mira_node *, int, int, bool);\nvoid\tieee80211_mira_set_rts_threshold(struct ieee80211_mira_node *,\n                                         struct ieee80211com *, struct ieee80211_node *);\nvoid\tieee80211_mira_reset_collision_stats(struct ieee80211_mira_node *);\n\n/* We use fixed point arithmetic with 64 bit integers. */\n#define MIRA_FP_SHIFT    21\n#define MIRA_FP_INT(x)    (x ## ULL << MIRA_FP_SHIFT) /* the integer x */\n#define MIRA_FP_1    MIRA_FP_INT(1)\n\n/* Multiply two fixed point numbers. */\n#define MIRA_FP_MUL(a, b) \\\n(((a) * (b)) >> MIRA_FP_SHIFT)\n\n/* Divide two fixed point numbers. */\n#define MIRA_FP_DIV(a, b) \\\n(b == 0 ? (uint64_t)-1 : (((a) << MIRA_FP_SHIFT) / (b)))\n\n#ifdef MIRA_DEBUG\n#define DPRINTF(x)    do { if (mira_debug > 0) printf x; } while (0)\n#define DPRINTFN(n, x)    do { if (mira_debug >= (n)) printf x; } while (0)\nint mira_debug = 1;\n#else\n#define DPRINTF(x)    do { ; } while (0)\n#define DPRINTFN(n, x)    do { ; } while (0)\n#endif\n\n#ifdef MIRA_DEBUG\nvoid\nmira_fixedp_split(uint32_t *i, uint32_t *f, uint64_t fp)\n{\n    uint64_t tmp;\n    \n    /* integer part */\n    *i = (fp >> MIRA_FP_SHIFT);\n    \n    /* fractional part */\n    tmp = (fp & ((uint64_t)-1 >> (64 - MIRA_FP_SHIFT)));\n    tmp *= 100;\n    *f = (uint32_t)(tmp >> MIRA_FP_SHIFT);\n}\n\nchar *\nmira_fp_sprintf(uint64_t fp)\n{\n    uint32_t i, f;\n    static char buf[64];\n    int ret;\n    \n    mira_fixedp_split(&i, &f, fp);\n    ret = snprintf(buf, sizeof(buf), \"%u.%02u\", i, f);\n    if (ret == -1 || ret >= sizeof(buf))\n        return \"ERR\";\n    \n    return buf;\n}\n\nvoid\nmira_print_driver_stats(struct ieee80211_mira_node *mn,\n                        struct ieee80211_node *ni) {\n    DPRINTF((\"%s driver stats:\\n\", ether_sprintf(ni->ni_macaddr)));\n    DPRINTF((\"mn->frames = %u\\n\", mn->frames));\n    DPRINTF((\"mn->retries = %u\\n\", mn->retries));\n    DPRINTF((\"mn->txfail = %u\\n\", mn->txfail));\n    DPRINTF((\"mn->ampdu_size = %u\\n\", mn->ampdu_size));\n    DPRINTF((\"mn->agglen = %u\\n\", mn->agglen));\n}\n#endif /* MIRA_DEBUG */\n\nconst struct ieee80211_ht_rateset *\nieee80211_mira_get_rateset(int mcs, int sgi, bool is_40mhz)\n{\n    const struct ieee80211_ht_rateset *rs;\n    int i;\n    int first = 0;\n    int last = IEEE80211_HT_RATESET_MIMO4_SGI;\n    \n    if (is_40mhz) {\n        first = IEEE80211_HT_RATESET_CBW40_SISO;\n        last = IEEE80211_HT_RATESET_CBW40_MIMO4_SGI;\n    }\n    \n    for (i = first; i <= last; i++) {\n        rs = &ieee80211_std_ratesets_11n[i];\n        if (sgi != rs->sgi)\n            continue;\n        if (mcs >= rs->min_mcs && mcs <= rs->max_mcs)\n            return rs;\n    }\n    \n    panic(\"MCS %d is not part of any rateset\", mcs);\n    return NULL;\n}\n\n/*\n * Probe timers.\n */\n\n/* Constants related to timeouts for time-driven rate probing. */\n#define IEEE80211_MIRA_PROBE_TIMEOUT_MIN    2        /* in msec */\n#define IEEE80211_MIRA_PROBE_INTVAL_MAX        (1 << 10)    /* 2^10 */\n\nvoid\nieee80211_mira_probe_timeout_up(void *arg)\n{\n    struct ieee80211_mira_node *mn = (struct ieee80211_mira_node *)arg;\n    int s;\n    \n    s = splnet();\n    mn->probe_timer_expired[IEEE80211_MIRA_PROBE_TO_UP] = 1;\n    DPRINTFN(3, (\"probe up timeout fired\\n\"));\n    splx(s);\n}\n\nvoid\nieee80211_mira_probe_timeout_down(void *arg)\n{\n    struct ieee80211_mira_node *mn = (struct ieee80211_mira_node *)arg;\n    int s;\n    \n    s = splnet();\n    mn->probe_timer_expired[IEEE80211_MIRA_PROBE_TO_DOWN] = 1;\n    DPRINTFN(3, (\"probe down timeout fired\\n\"));\n    splx(s);\n}\n\n/*\n * Update goodput statistics.\n */\n\nuint64_t\nieee80211_mira_get_txrate(int mcs, int sgi, bool is_40mhz)\n{\n    const struct ieee80211_ht_rateset *rs;\n    uint64_t txrate;\n    \n    rs = ieee80211_mira_get_rateset(mcs, sgi, is_40mhz);\n    txrate = rs->rates[mcs - rs->min_mcs];\n    txrate <<= MIRA_FP_SHIFT; /* convert to fixed-point */\n    txrate *= 500; /* convert to kbit/s */\n    txrate /= 1000; /* convert to mbit/s */\n    \n    return txrate;\n}\n\n/* Based on rt2661_txtime in the ral(4) driver. */\nuint16_t\nieee80211_mira_legacy_txtime(uint32_t len, int rate, struct ieee80211com *ic)\n{\n#define MIRA_RATE_IS_OFDM(rate) ((rate) >= 12 && (rate) != 22)\n    uint16_t txtime;\n    \n    if (MIRA_RATE_IS_OFDM(rate)) {\n        /* IEEE Std 802.11g-2003, pp. 44 */\n        txtime = (8 + 4 * len + 3 + rate - 1) / rate;\n        txtime = 16 + 4 + 4 * txtime + 6;\n    } else {\n        /* IEEE Std 802.11b-1999, pp. 28 */\n        txtime = (16 * len + rate - 1) / rate;\n        if (rate != 2 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE))\n            txtime +=  72 + 24;\n        else\n            txtime += 144 + 48;\n    }\n    return txtime;\n}\n\nuint32_t\nieee80211_mira_ht_txtime(uint32_t len, int mcs, int is2ghz, int sgi, bool is_40mhz)\n{\n    const struct ieee80211_ht_rateset *rs;\n    /* XXX These constants should be macros in ieee80211.h instead. */\n    const uint32_t t_lstf = 8; /* usec legacy short training field */\n    const uint32_t t_lltf = 8; /* usec legacy long training field */\n    const uint32_t t_lsig = 4; /* usec legacy signal field */\n    const uint32_t t_htstf = 4; /* usec HT short training field */\n    const uint32_t t_ltstf = 4; /* usec HT long training field */\n    const uint32_t t_htsig = 8; /* usec HT signal field */\n    const uint32_t t_sym = 4; /* usec symbol interval */\n    const uint32_t t_syms_n = 36; /* usec symbol interval for sgi numerator */\n    const uint32_t t_syms_d = 10; /* usec symbol interval for sgi denominator */\n    uint32_t n_sym, n_dbps;\n    uint32_t t_plcp;\n    uint32_t t_data;\n    uint32_t txtime;\n    \n    /*\n     * Calculate approximate frame Tx time in usec.\n     * See 802.11-2012, 20.4.3 \"TXTIME calculation\" and\n     * 20.3.11.1 \"Equation (20-32)\".\n     * XXX Assumes a 20MHz channel, HT-mixed frame format, no STBC.\n     */\n    t_plcp = t_lstf + t_lltf + t_lsig + t_htstf + 4 * t_ltstf + t_htsig;\n    rs = ieee80211_mira_get_rateset(mcs, sgi, is_40mhz);\n    n_dbps = rs->rates[mcs - rs->min_mcs] * 2;\n    n_sym = ((8 * len + 16 + 6) / n_dbps); /* \"Equation (20-32)\" */\n    if (sgi)\n        t_data = (t_syms_n * n_sym) / t_syms_d;\n    else\n        t_data = t_sym * n_sym;\n    \n    txtime = t_plcp + t_data;\n    if (is2ghz)\n        txtime += 6; /* aSignalExtension */\n    \n    return txtime;\n}\n\nint\nieee80211_mira_best_basic_rate(struct ieee80211_node *ni)\n{\n    struct ieee80211_rateset *rs = &ni->ni_rates;\n    int i, best, rval;\n    \n    /* Default to 1 Mbit/s on 2GHz and 6 Mbit/s on 5GHz. */\n    best = IEEE80211_IS_CHAN_2GHZ(ni->ni_chan) ? 2 : 12;\n    \n    for (i = 0; i < rs->rs_nrates; i++) {\n        if ((rs->rs_rates[i] & IEEE80211_RATE_BASIC) == 0)\n            continue;\n        rval = (rs->rs_rates[i] & IEEE80211_RATE_VAL);\n        if (rval > best)\n            best = rval;\n    }\n    \n    return best;\n}\n\n/*\n * See 802.11-2012, 9.7.6.5 \"Rate selection for control response frames\".\n */\nint\nieee80211_mira_ack_rate(struct ieee80211_node *ni)\n{\n    /*\n     * Assume the ACK was sent at a mandatory ERP OFDM rate.\n     * In the worst case, the driver has retried at non-HT rates,\n     * so for MCS 0 assume we didn't actually send an OFDM frame\n     * and ACKs arrived at a basic rate.\n     */\n    if (ni->ni_txmcs == 0)\n        return ieee80211_mira_best_basic_rate(ni);\n    else if (ni->ni_txmcs == 1)\n        return 12;    /* 6 Mbit/s */\n    else if (ni->ni_txmcs >= 2)\n        return 24;    /* 12 Mbit/s */\n    else\n        return 48;    /* 24 Mbit/s */\n}\n\nuint64_t\nieee80211_mira_toverhead(struct ieee80211_mira_node *mn,\n                         struct ieee80211com *ic, struct ieee80211_node *ni)\n{\n    /* XXX These should be macros in ieee80211.h. */\n#define MIRA_RTSLEN IEEE80211_MIN_LEN\n#define MIRA_CTSLEN (sizeof(struct ieee80211_frame_cts) + IEEE80211_CRC_LEN)\n    uint32_t overhead;\n    uint64_t toverhead;\n    int rate, rts;\n    enum ieee80211_htprot htprot;\n    int sgi = (ni->ni_flags & (IEEE80211_NODE_HT_SGI20 | IEEE80211_NODE_HT_SGI40)) ? 1 : 0;\n    \n    overhead = ieee80211_mira_ht_txtime(0, ni->ni_txmcs,\n                                        IEEE80211_IS_CHAN_2GHZ(ni->ni_chan), sgi, ni->ni_chw == IEEE80211_CHAN_WIDTH_40);\n    \n    htprot = (enum ieee80211_htprot)(ic->ic_bss->ni_htop1 & IEEE80211_HTOP1_PROT_MASK);\n    if (htprot == IEEE80211_HTPROT_NONMEMBER ||\n        htprot == IEEE80211_HTPROT_NONHT_MIXED)\n        rts = 1;\n    else if (htprot == IEEE80211_HTPROT_20MHZ &&\n             (ic->ic_htcaps & IEEE80211_HTCAP_CBW20_40))\n        rts = 1;\n    else\n        rts = (mn->ampdu_size > ieee80211_mira_get_rts_threshold(mn,\n                                                                 ic, ni, mn->ampdu_size));\n    \n    if (rts) {\n        /* Assume RTS/CTS were sent at a basic rate. */\n        rate = ieee80211_min_basic_rate(ic);\n        overhead += ieee80211_mira_legacy_txtime(MIRA_RTSLEN, rate, ic);\n        overhead += ieee80211_mira_legacy_txtime(MIRA_CTSLEN, rate, ic);\n    }\n    \n    if (mn->agglen == 1) {\n        /* Single-frame transmissions must wait for an ACK frame. */\n        rate = ieee80211_mira_ack_rate(ni);\n        overhead += ieee80211_mira_legacy_txtime(IEEE80211_ACK_LEN,\n                                                 rate, ic);\n    }\n    \n    toverhead = overhead;\n    toverhead <<= MIRA_FP_SHIFT; /* convert to fixed-point */\n    toverhead /= 1000; /* convert to msec */\n    toverhead /= 1000; /* convert to sec */\n    \n#ifdef MIRA_DEBUG\n    if (mira_debug > 3) {\n        uint32_t txtime;\n        txtime = ieee80211_mira_ht_txtime(mn->ampdu_size, ni->ni_txmcs,\n                                          IEEE80211_IS_CHAN_2GHZ(ni->ni_chan), sgi, ni->ni_chw == 40);\n        txtime += overhead - ieee80211_mira_ht_txtime(0, ni->ni_txmcs,\n                                                      IEEE80211_IS_CHAN_2GHZ(ni->ni_chan), sgi, ni->ni_chw == IEEE80211_CHAN_WIDTH_40);\n        DPRINTFN(4, (\"txtime: %u usec\\n\", txtime));\n        DPRINTFN(4, (\"overhead: %u usec\\n\", overhead));\n        DPRINTFN(4, (\"toverhead: %s\\n\", mira_fp_sprintf(toverhead)));\n    }\n#endif\n    return toverhead;\n}\n\nvoid\nieee80211_mira_update_stats(struct ieee80211_mira_node *mn,\n                            struct ieee80211com *ic, struct ieee80211_node *ni)\n{\n    /* Magic numbers from MiRA paper. */\n    static const uint64_t alpha = MIRA_FP_1 / 8; /* 1/8 = 0.125 */\n    static const uint64_t beta =  MIRA_FP_1 / 4; /* 1/4 = 0.25 */\n    uint64_t sfer, delta, toverhead;\n    uint64_t agglen = mn->agglen;\n    uint64_t ampdu_size = mn->ampdu_size * 8; /* convert to bits */\n    int sgi = (ni->ni_flags & (IEEE80211_NODE_HT_SGI20 | IEEE80211_NODE_HT_SGI40)) ? 1 : 0;\n    uint64_t rate = ieee80211_mira_get_txrate(ni->ni_txmcs, sgi, ni->ni_chw == IEEE80211_CHAN_WIDTH_40);\n    struct ieee80211_mira_goodput_stats *g = &mn->g[ni->ni_txmcs];\n    \n    if (mn->frames == 0)\n        return; /* avoid divide-by-zero in sfer calculation below */\n    \n    g->nprobes += mn->agglen;\n    g->nprobe_bytes += mn->ampdu_size;\n    \n    ampdu_size <<= MIRA_FP_SHIFT; /* convert to fixed-point */\n    agglen <<= MIRA_FP_SHIFT;\n    /* XXX range checks? */\n    \n    ampdu_size = ampdu_size / 1000; /* kbit */\n    ampdu_size = ampdu_size / 1000; /* mbit */\n    \n    /* Compute Sub-Frame Error Rate (see section 2.2 in MiRA paper). */\n    sfer = mn->frames * mn->txfail + mn->retries;\n    if ((sfer >> MIRA_FP_SHIFT) != 0) { /* bug in wifi driver */\n        if (ic->ic_if.if_flags & IFF_DEBUG) {\n#ifdef DIAGNOSTIC\n            printf(\"%s: mira sfer overflow\\n\",\n                   ether_sprintf(ni->ni_macaddr));\n#endif\n#ifdef MIRA_DEBUG\n            mira_print_driver_stats(mn, ni);\n#endif\n        }\n        ieee80211_mira_probe_done(mn);\n        return;\n    }\n    sfer <<= MIRA_FP_SHIFT; /* convert to fixed-point */\n    sfer /= (mn->txfail + 1) * mn->frames;\n    if (sfer > MIRA_FP_1) { /* bug in wifi driver */\n        if (ic->ic_if.if_flags & IFF_DEBUG) {\n#ifdef DIAGNOSTIC\n            printf(\"%s: mira sfer > 1\\n\",\n                   ether_sprintf(ni->ni_macaddr));\n#endif\n#ifdef MIRA_DEBUG\n            mira_print_driver_stats(mn, ni);\n#endif\n        }\n        sfer = MIRA_FP_1; /* round down */\n    }\n    \n    /* Store current loss percentage SFER. */\n    g->loss = sfer * 100;\n#ifdef MIRA_DEBUG\n    if (g->loss && ieee80211_mira_probe_valid(mn, ni))\n        DPRINTFN(2, (\"frame error rate at MCS %d: %s%%\\n\",\n                     ni->ni_txmcs, mira_fp_sprintf(g->loss)));\n#endif\n    \n    /*\n     * Update goodput statistics (see section 5.1.2 in MiRA paper).\n     * We use a slightly modified but equivalent calculation which\n     * is tuned towards our fixed-point number format.\n     */\n    \n    g->average_agg = MIRA_FP_MUL(MIRA_FP_1 - alpha, g->average_agg);\n    g->average_agg += MIRA_FP_MUL(alpha, agglen);\n    \n    toverhead = ieee80211_mira_toverhead(mn, ic, ni);\n    toverhead = MIRA_FP_MUL(toverhead, rate);\n    g->measured = MIRA_FP_DIV(MIRA_FP_1 - sfer, MIRA_FP_1 +\n                              MIRA_FP_DIV(toverhead, MIRA_FP_MUL(ampdu_size, g->average_agg)));\n    g->measured = MIRA_FP_MUL(g->measured, rate);\n    \n    g->average = MIRA_FP_MUL(MIRA_FP_1 - alpha, g->average);\n    g->average += MIRA_FP_MUL(alpha, g->measured);\n    \n    g->stddeviation = MIRA_FP_MUL(MIRA_FP_1 - beta, g->stddeviation);\n    if (g->average > g->measured)\n        delta = g->average - g->measured;\n    else\n        delta = g->measured - g->average;\n    g->stddeviation += MIRA_FP_MUL(beta, delta);\n}\n\nvoid\nieee80211_mira_reset_goodput_stats(struct ieee80211_mira_node *mn)\n{\n    int i;\n    \n    for (i = 0; i < nitems(mn->g); i++) {\n        struct ieee80211_mira_goodput_stats *g = &mn->g[i];\n        memset(g, 0, sizeof(*g));\n        g->average_agg = 1;\n        g->probe_interval = IEEE80211_MIRA_PROBE_TIMEOUT_MIN;\n    }\n}\n\nvoid\nieee80211_mira_reset_driver_stats(struct ieee80211_mira_node *mn)\n{\n    mn->frames = 0;\n    mn->retries = 0;\n    mn->txfail = 0;\n    mn->ampdu_size = 0;\n    mn->agglen = 1;\n}\n\n/*\n * Rate selection.\n */\n\n/* A rate's goodput has to be at least this much larger to be \"better\". */\n#define IEEE80211_MIRA_RATE_THRESHOLD    (MIRA_FP_1 / 64) /* ~ 0.015 */\n\n#define IEEE80211_MIRA_LOSS_THRESHOLD    10    /* in percent */\n\n/* Number of (sub-)frames which render a probe valid. */\n#define IEEE80211_MIRA_MIN_PROBE_FRAMES    4\n\n/* Number of bytes which, alternatively, render a probe valid. */\n#define IEEE80211_MIRA_MIN_PROBE_BYTES (2 * IEEE80211_MAX_LEN)\n\n/* Number of Tx failures which, alternatively, render a probe valid. */\n#define IEEE80211_MIRA_MAX_PROBE_TXFAIL 1\n\n/* Number of Tx retries which, alternatively, render a probe valid. */\n#define IEEE80211_MIRA_MAX_PROBE_RETRIES 4\n\nint\nieee80211_mira_next_lower_intra_rate(struct ieee80211_mira_node *mn,\n                                     struct ieee80211_node *ni)\n{\n    const struct ieee80211_ht_rateset *rs;\n    int i, next;\n    int sgi = (ni->ni_flags & (IEEE80211_NODE_HT_SGI20 | IEEE80211_NODE_HT_SGI40)) ? 1 : 0;\n    \n    rs = ieee80211_mira_get_rateset(ni->ni_txmcs, sgi, ni->ni_chw == IEEE80211_CHAN_WIDTH_40);\n    if (ni->ni_txmcs == rs->min_mcs)\n        return rs->min_mcs;\n    \n    next = ni->ni_txmcs;\n    for (i = rs->nrates - 1; i >= 0; i--) {\n        if ((mn->valid_rates & (1 << (i + rs->min_mcs))) == 0)\n            continue;\n        if (i + rs->min_mcs < ni->ni_txmcs) {\n            next = i + rs->min_mcs;\n            break;\n        }\n    }\n    \n    return next;\n}\n\nint\nieee80211_mira_next_intra_rate(struct ieee80211_mira_node *mn,\n                               struct ieee80211_node *ni)\n{\n    const struct ieee80211_ht_rateset *rs;\n    int i, next;\n    int sgi = (ni->ni_flags & (IEEE80211_NODE_HT_SGI20 | IEEE80211_NODE_HT_SGI40)) ? 1 : 0;\n    \n    rs = ieee80211_mira_get_rateset(ni->ni_txmcs, sgi, ni->ni_chw == IEEE80211_CHAN_WIDTH_40);\n    if (ni->ni_txmcs == rs->max_mcs)\n        return rs->max_mcs;\n    \n    next = ni->ni_txmcs;\n    for (i = 0; i < rs->nrates; i++) {\n        if ((mn->valid_rates & (1 << (i + rs->min_mcs))) == 0)\n            continue;\n        if (i + rs->min_mcs > ni->ni_txmcs) {\n            next = i + rs->min_mcs;\n            break;\n        }\n    }\n    \n    return next;\n}\n\nconst struct ieee80211_ht_rateset *\nieee80211_mira_next_rateset(struct ieee80211_mira_node *mn,\n                            struct ieee80211_node *ni)\n{\n    const struct ieee80211_ht_rateset *rs, *rsnext;\n    int next;\n    int mcs = ni->ni_txmcs;\n    int sgi = (ni->ni_flags & (IEEE80211_NODE_HT_SGI20 | IEEE80211_NODE_HT_SGI40)) ? 1 : 0;\n    \n    rs = ieee80211_mira_get_rateset(mcs, sgi, ni->ni_chw == IEEE80211_CHAN_WIDTH_40);\n    if (mn->probing & IEEE80211_MIRA_PROBING_UP) {\n        if (rs->max_mcs == 7)    /* MCS 0-7 */\n            next = sgi ? IEEE80211_HT_RATESET_MIMO2_SGI :\n            IEEE80211_HT_RATESET_MIMO2;\n        else if (rs->max_mcs == 15)    /* MCS 8-15 */\n            next = sgi ? IEEE80211_HT_RATESET_MIMO3_SGI :\n            IEEE80211_HT_RATESET_MIMO3;\n        else if (rs->max_mcs == 23)    /* MCS 16-23 */\n            next = sgi ? IEEE80211_HT_RATESET_MIMO4_SGI :\n            IEEE80211_HT_RATESET_MIMO4;\n        else                /* MCS 24-31 */\n            return NULL;\n    } else if (mn->probing & IEEE80211_MIRA_PROBING_DOWN) {\n        if (rs->min_mcs == 24)    /* MCS 24-31 */\n            next = sgi ? IEEE80211_HT_RATESET_MIMO3_SGI :\n            IEEE80211_HT_RATESET_MIMO3;\n        else if (rs->min_mcs == 16)    /* MCS 16-23 */\n            next = sgi ? IEEE80211_HT_RATESET_MIMO2_SGI :\n            IEEE80211_HT_RATESET_MIMO2;\n        else if (rs->min_mcs == 8)    /* MCS 8-15 */\n            next = sgi ? IEEE80211_HT_RATESET_SISO_SGI :\n            IEEE80211_HT_RATESET_SISO;\n        else                /* MCS 0-7 */\n            return NULL;\n    } else\n        panic(\"%s: invalid probing mode %d\", __func__, mn->probing);\n    \n    rsnext = &ieee80211_std_ratesets_11n[next];\n    if ((rsnext->mcs_mask & mn->valid_rates) == 0)\n        return NULL;\n    \n    return rsnext;\n}\n\nint\nieee80211_mira_best_mcs_in_rateset(struct ieee80211_mira_node *mn,\n                                   const struct ieee80211_ht_rateset *rs)\n{\n    uint64_t gmax = 0;\n    int i, best_mcs = rs->min_mcs;\n    \n    for (i = 0; i < rs->nrates; i++) {\n        int mcs = rs->min_mcs + i;\n        struct ieee80211_mira_goodput_stats *g = &mn->g[mcs];\n        if (((1 << mcs) & mn->valid_rates) == 0)\n            continue;\n        if (g->measured > gmax + IEEE80211_MIRA_RATE_THRESHOLD) {\n            gmax = g->measured;\n            best_mcs = mcs;\n        }\n    }\n    \n    return best_mcs;\n}\n\nvoid\nieee80211_mira_probe_next_rateset(struct ieee80211_mira_node *mn,\n                                  struct ieee80211_node *ni, const struct ieee80211_ht_rateset *rsnext)\n{\n    const struct ieee80211_ht_rateset *rs;\n    struct ieee80211_mira_goodput_stats *g;\n    int best_mcs, i;\n    int sgi = (ni->ni_flags & (IEEE80211_NODE_HT_SGI20 | IEEE80211_NODE_HT_SGI40)) ? 1 : 0;\n    \n    /* Find most recently measured best MCS from the current rateset. */\n    rs = ieee80211_mira_get_rateset(ni->ni_txmcs, sgi, ni->ni_chw == IEEE80211_CHAN_WIDTH_40);\n    best_mcs = ieee80211_mira_best_mcs_in_rateset(mn, rs);\n    \n    /* Switch to the next rateset. */\n    ni->ni_txmcs = rsnext->min_mcs;\n    if ((mn->valid_rates & (1 << rsnext->min_mcs)) == 0)\n        ni->ni_txmcs = ieee80211_mira_next_intra_rate(mn, ni);\n    \n    /* Select the lowest rate from the next rateset with loss-free\n     * goodput close to the current best measurement. */\n    g = &mn->g[best_mcs];\n    for (i = 0; i < rsnext->nrates; i++) {\n        int mcs = rsnext->min_mcs + i;\n        uint64_t txrate = rsnext->rates[i];\n        \n        if ((mn->valid_rates & (1 << mcs)) == 0)\n            continue;\n        \n        txrate = txrate * 500; /* convert to kbit/s */\n        txrate <<= MIRA_FP_SHIFT; /* convert to fixed-point */\n        txrate /= 1000; /* convert to mbit/s */\n        \n        if (txrate > g->measured + IEEE80211_MIRA_RATE_THRESHOLD) {\n            ni->ni_txmcs = mcs;\n            break;\n        }\n    }\n    /* If all rates are lower the maximum rate is the closest match. */\n    if (i == rsnext->nrates)\n        ni->ni_txmcs = rsnext->max_mcs;\n    \n    /* Add rates from the next rateset as candidates. */\n    mn->candidate_rates |= (1 << ni->ni_txmcs);\n    if (mn->probing & IEEE80211_MIRA_PROBING_UP) {\n        mn->candidate_rates |=\n        (1 << ieee80211_mira_next_intra_rate(mn, ni));\n    } else if (mn->probing & IEEE80211_MIRA_PROBING_DOWN) {\n#ifdef MIRA_AGGRESSIVE_DOWNWARDS_PROBING\n        mn->candidate_rates |= ieee80211_mira_mcs_below(mn,\n                                                        ni->ni_txmcs, sgi, ni->ni_chw == IEEE80211_CHAN_WIDTH_40);\n#else\n        mn->candidate_rates |=\n        (1 << ieee80211_mira_next_lower_intra_rate(mn, ni));\n#endif\n    } else\n        panic(\"%s: invalid probing mode %d\", __func__, mn->probing);\n}\n\nint\nieee80211_mira_next_mcs(struct ieee80211_mira_node *mn,\n                        struct ieee80211_node *ni)\n{\n    int next;\n    \n    if (mn->probing & IEEE80211_MIRA_PROBING_DOWN)\n        next = ieee80211_mira_next_lower_intra_rate(mn, ni);\n    else if (mn->probing & IEEE80211_MIRA_PROBING_UP)\n        next = ieee80211_mira_next_intra_rate(mn, ni);\n    else\n        panic(\"%s: invalid probing mode %d\", __func__, mn->probing);\n    \n    return next;\n}\n\nint\nieee80211_mira_prev_mcs(struct ieee80211_mira_node *mn,\n                        struct ieee80211_node *ni)\n{\n    int next;\n    \n    if (mn->probing & IEEE80211_MIRA_PROBING_DOWN)\n        next = ieee80211_mira_next_intra_rate(mn, ni);\n    else if (mn->probing & IEEE80211_MIRA_PROBING_UP)\n        next = ieee80211_mira_next_lower_intra_rate(mn, ni);\n    else\n        panic(\"%s: invalid probing mode %d\", __func__, mn->probing);\n    \n    return next;\n}\n\nint\nieee80211_mira_probe_valid(struct ieee80211_mira_node *mn,\n                           struct ieee80211_node *ni)\n{\n    struct ieee80211_mira_goodput_stats *g = &mn->g[ni->ni_txmcs];\n    \n    return (g->nprobes >= IEEE80211_MIRA_MIN_PROBE_FRAMES ||\n            g->nprobe_bytes >= IEEE80211_MIRA_MIN_PROBE_BYTES ||\n            mn->txfail >= IEEE80211_MIRA_MAX_PROBE_TXFAIL ||\n            mn->retries >= IEEE80211_MIRA_MAX_PROBE_RETRIES);\n}\n\nvoid\nieee80211_mira_probe_done(struct ieee80211_mira_node *mn)\n{\n    int mcs;\n    \n    /* Reset probe interval of the best rate. */\n    mn->g[mn->best_mcs].probe_interval = IEEE80211_MIRA_PROBE_TIMEOUT_MIN;\n    mn->g[mn->best_mcs].nprobes = 0;\n    mn->g[mn->best_mcs].nprobe_bytes = 0;\n    \n    /* Update probing interval of other probed rates. */\n    for (mcs = 0; mcs < IEEE80211_HT_RATESET_NUM_MCS; mcs++) {\n        if (mcs != mn->best_mcs && (mn->probed_rates & (1 << mcs)))\n            ieee80211_mira_update_probe_interval(&mn->g[mcs]);\n    }\n    \n    ieee80211_mira_cancel_timeouts(mn);\n    ieee80211_mira_reset_driver_stats(mn);\n    ieee80211_mira_reset_collision_stats(mn);\n    mn->probing = IEEE80211_MIRA_NOT_PROBING;\n    mn->probed_rates = 0;\n    mn->candidate_rates = 0;\n}\n\nint\nieee80211_mira_intra_mode_ra_finished(struct ieee80211_mira_node *mn,\n                                      struct ieee80211_node *ni)\n{\n    const struct ieee80211_ht_rateset *rs;\n    struct ieee80211_mira_goodput_stats *g = &mn->g[ni->ni_txmcs];\n    int next_mcs, best_mcs, probed_rates;\n    uint64_t next_rate;\n    int sgi = (ni->ni_flags & (IEEE80211_NODE_HT_SGI20 | IEEE80211_NODE_HT_SGI40)) ? 1 : 0;\n    bool is_40mhz = (ni->ni_chw == IEEE80211_CHAN_WIDTH_40);\n    \n    if (!ieee80211_mira_probe_valid(mn, ni))\n        return 0;\n    \n    probed_rates = (mn->probed_rates | (1 << ni->ni_txmcs));\n    \n    /* Check if the min/max MCS in this rateset has been probed. */\n    rs = ieee80211_mira_get_rateset(ni->ni_txmcs, sgi, is_40mhz);\n    if (mn->probing & IEEE80211_MIRA_PROBING_DOWN) {\n        if (ni->ni_txmcs == rs->min_mcs ||\n            probed_rates & (1 << rs->min_mcs)) {\n            ieee80211_mira_trigger_next_rateset(mn, ni);\n            return 1;\n        }\n    } else if (mn->probing & IEEE80211_MIRA_PROBING_UP) {\n        if (ni->ni_txmcs == rs->max_mcs ||\n            probed_rates & (1 << rs->max_mcs)) {\n            ieee80211_mira_trigger_next_rateset(mn, ni);\n            return 1;\n        }\n    }\n    \n    /*\n     * Check if the measured goodput is loss-free and better than the\n     * loss-free goodput of the candidate rate.\n     */\n    next_mcs = ieee80211_mira_next_mcs(mn, ni);\n    if (next_mcs == ni->ni_txmcs) {\n        ieee80211_mira_trigger_next_rateset(mn, ni);\n        return 1;\n    }\n    next_rate = ieee80211_mira_get_txrate(next_mcs, sgi, is_40mhz);\n    if (g->loss == 0 &&\n        g->measured >= next_rate + IEEE80211_MIRA_RATE_THRESHOLD) {\n        ieee80211_mira_trigger_next_rateset(mn, ni);\n        return 1;\n    }\n    \n    /* Check if we had a better measurement at a previously probed MCS. */\n    best_mcs = ieee80211_mira_best_mcs_in_rateset(mn, rs);\n    if (best_mcs != ni->ni_txmcs && (probed_rates & (1 << best_mcs))) {\n        if ((mn->probing & IEEE80211_MIRA_PROBING_UP) &&\n            best_mcs < ni->ni_txmcs) {\n            ieee80211_mira_trigger_next_rateset(mn, ni);\n            return 1;\n        }\n        if ((mn->probing & IEEE80211_MIRA_PROBING_DOWN) &&\n            best_mcs > ni->ni_txmcs) {\n            ieee80211_mira_trigger_next_rateset(mn, ni);\n            return 1;\n        }\n    }\n    \n    /* Check if all rates in the set of candidate rates have been probed. */\n    if ((mn->candidate_rates & probed_rates) == mn->candidate_rates) {\n        /* Remain in the current rateset until above checks trigger. */\n        return 1;\n    }\n    \n    return 0;\n}\n\nvoid\nieee80211_mira_trigger_next_rateset(struct ieee80211_mira_node *mn,\n                                    struct ieee80211_node *ni)\n{\n    const struct ieee80211_ht_rateset *rsnext;\n    \n    rsnext = ieee80211_mira_next_rateset(mn, ni);\n    if (rsnext) {\n        ieee80211_mira_probe_next_rateset(mn, ni, rsnext);\n        mn->probing |= IEEE80211_MIRA_PROBING_INTER;\n    } else\n        mn->probing &= ~IEEE80211_MIRA_PROBING_INTER;\n}\n\nint\nieee80211_mira_inter_mode_ra_finished(struct ieee80211_mira_node *mn,\n                                      struct ieee80211_node *ni)\n{\n    return ((mn->probing & IEEE80211_MIRA_PROBING_INTER) == 0);\n}\n\nint\nieee80211_mira_best_rate(struct ieee80211_mira_node *mn,\n                         struct ieee80211_node *ni)\n{\n    int i, best = 0;\n    uint64_t gmax = 0;\n    \n    for (i = 0; i < nitems(mn->g); i++) {\n        struct ieee80211_mira_goodput_stats *g = &mn->g[i];\n        if (((1 << i) & mn->valid_rates) == 0)\n            continue;\n        if (g->measured > gmax + IEEE80211_MIRA_RATE_THRESHOLD) {\n            gmax = g->measured;\n            best = i;\n        }\n    }\n    \n#ifdef MIRA_DEBUG\n    if (mn->best_mcs != best) {\n        DPRINTF((\"MCS %d is best; MCS{Mbps|probe interval}:\", best));\n        for (i = 0; i < IEEE80211_HT_RATESET_NUM_MCS; i++) {\n            struct ieee80211_mira_goodput_stats *g = &mn->g[i];\n            if ((mn->valid_rates & (1 << i)) == 0)\n                continue;\n            DPRINTF((\" %d{%s|%dms}\", i,\n                     mira_fp_sprintf(g->measured),\n                     g->probe_interval));\n        }\n        DPRINTF((\"\\n\"));\n    }\n#endif\n    return best;\n}\n\n/* See section 5.1.1 (at \"Adaptive probing interval\") in MiRA paper. */\nvoid\nieee80211_mira_update_probe_interval(struct ieee80211_mira_goodput_stats *g)\n{\n    uint64_t lt;\n    int intval;\n    \n    lt = g->loss / IEEE80211_MIRA_LOSS_THRESHOLD;\n    if (lt < MIRA_FP_1)\n        lt = MIRA_FP_1;\n    lt >>= MIRA_FP_SHIFT; /* round to integer */\n    \n    intval = (1 << g->nprobes); /* 2^nprobes */\n    if (intval > IEEE80211_MIRA_PROBE_INTVAL_MAX)\n        intval = IEEE80211_MIRA_PROBE_INTVAL_MAX;\n    \n    g->probe_interval = IEEE80211_MIRA_PROBE_TIMEOUT_MIN * intval * lt;\n}\n\nvoid\nieee80211_mira_schedule_probe_timers(struct ieee80211_mira_node *mn,\n                                     struct ieee80211_node *ni)\n{\n    struct ieee80211_mira_goodput_stats *g;\n    CTimeout **to;\n    int mcs;\n    \n    mcs = ieee80211_mira_next_intra_rate(mn, ni);\n    to = &mn->probe_to[IEEE80211_MIRA_PROBE_TO_UP];\n    g = &mn->g[mcs];\n    if (mcs != ni->ni_txmcs && !timeout_pending(to) &&\n        !mn->probe_timer_expired[IEEE80211_MIRA_PROBE_TO_UP]) {\n        timeout_add_msec(to, g->probe_interval);\n        DPRINTFN(3, (\"start probing up for node %s at MCS %d in at \"\n                     \"least %d msec\\n\",\n                     ether_sprintf(ni->ni_macaddr), mcs, g->probe_interval));\n    }\n    \n    mcs = ieee80211_mira_next_lower_intra_rate(mn, ni);\n    to = &mn->probe_to[IEEE80211_MIRA_PROBE_TO_DOWN];\n    g = &mn->g[mcs];\n    if (mcs != ni->ni_txmcs && !timeout_pending(to) &&\n        !mn->probe_timer_expired[IEEE80211_MIRA_PROBE_TO_DOWN]) {\n        timeout_add_msec(to, g->probe_interval);\n        DPRINTFN(3, (\"start probing down for node %s at MCS %d in at \"\n                     \"least %d msec\\n\",\n                     ether_sprintf(ni->ni_macaddr), mcs, g->probe_interval));\n    }\n}\n\nint\nieee80211_mira_check_probe_timers(struct ieee80211_mira_node *mn,\n                                  struct ieee80211_node *ni)\n{\n    int ret = 0, expired_timer = IEEE80211_MIRA_PROBE_TO_INVALID;\n    int mcs;\n    \n    if (mn->probe_timer_expired[IEEE80211_MIRA_PROBE_TO_UP] &&\n        mn->probe_timer_expired[IEEE80211_MIRA_PROBE_TO_DOWN]) {\n        if (arc4random_uniform(2))\n            expired_timer = IEEE80211_MIRA_PROBE_TO_UP;\n        else\n            expired_timer = IEEE80211_MIRA_PROBE_TO_DOWN;\n    } else if (mn->probe_timer_expired[IEEE80211_MIRA_PROBE_TO_DOWN])\n        expired_timer = IEEE80211_MIRA_PROBE_TO_DOWN;\n    else if (mn->probe_timer_expired[IEEE80211_MIRA_PROBE_TO_UP])\n        expired_timer = IEEE80211_MIRA_PROBE_TO_UP;\n    \n    if (expired_timer != IEEE80211_MIRA_PROBE_TO_INVALID)\n        mn->probe_timer_expired[expired_timer] = 0;\n    \n    switch (expired_timer) {\n        case IEEE80211_MIRA_PROBE_TO_UP:\n            /* Do time-based upwards probing on next frame. */\n            DPRINTFN(2, (\"probe timer expired: probe upwards\\n\"));\n            mn->probing = IEEE80211_MIRA_PROBING_UP;\n            mcs = ieee80211_mira_next_intra_rate(mn, ni);\n            mn->candidate_rates = (1 << mcs);\n            ret = 1;\n            break;\n        case IEEE80211_MIRA_PROBE_TO_DOWN:\n            /* Do time-based downwards probing on next frame. */\n            DPRINTFN(2, (\"probe timer expired: probe downwards\\n\"));\n            mn->probing = IEEE80211_MIRA_PROBING_DOWN;\n            mcs = ieee80211_mira_next_lower_intra_rate(mn, ni);\n            mn->candidate_rates = (1 << mcs);\n            ret = 1;\n            break;\n        case IEEE80211_MIRA_PROBE_TO_INVALID:\n        default:\n            ret = 0;\n            break;\n    }\n    \n    return ret;\n}\n\nvoid\nieee80211_mira_probe_next_rate(struct ieee80211_mira_node *mn,\n                               struct ieee80211_node *ni)\n{\n    /* Select the next rate to probe. */\n    mn->probed_rates |= (1 << ni->ni_txmcs);\n    ni->ni_txmcs = ieee80211_mira_next_mcs(mn, ni);\n}\n\nint\nieee80211_mira_valid_tx_mcs(struct ieee80211com *ic, int mcs)\n{\n    uint32_t ntxstreams = 1;\n    static const int max_mcs[] = { 7, 15, 23, 31 };\n    \n    if ((ic->ic_tx_mcs_set & IEEE80211_TX_RX_MCS_NOT_EQUAL) == 0)\n        return isset(ic->ic_sup_mcs, mcs);\n    \n    ntxstreams += ((ic->ic_tx_mcs_set & IEEE80211_TX_SPATIAL_STREAMS) >> 2);\n    if (ntxstreams < 1 || ntxstreams > 4)\n        panic(\"invalid number of Tx streams: %u\", ntxstreams);\n    return (mcs <= max_mcs[ntxstreams - 1] && isset(ic->ic_sup_mcs, mcs));\n}\n\nuint32_t\nieee80211_mira_valid_rates(struct ieee80211com *ic, struct ieee80211_node *ni)\n{\n    uint32_t valid_mcs = 0;\n    int i;\n    \n    for (i = 0; i < IEEE80211_HT_RATESET_NUM_MCS; i++) {\n        if (!isset(ni->ni_rxmcs, i))\n            continue;\n        if (!ieee80211_mira_valid_tx_mcs(ic, i))\n            continue;\n        valid_mcs |= (1 << i);\n    }\n    \n    return valid_mcs;\n}\n\nuint32_t\nieee80211_mira_mcs_below(struct ieee80211_mira_node *mn, int mcs, int sgi, bool is_40mhz)\n{\n    const struct ieee80211_ht_rateset *rs;\n    uint32_t mcs_mask;\n    int i;\n    \n    rs = ieee80211_mira_get_rateset(mcs, sgi, is_40mhz);\n    mcs_mask = (1 << rs->min_mcs);\n    for (i = rs->min_mcs + 1; i < mcs; i++) {\n        if ((mn->valid_rates & (1 << i)) == 0)\n            continue;\n        mcs_mask |= (1 << i);\n    }\n    \n    return mcs_mask;\n}\n\n/*\n * Constants involved in detecting suspected frame collisions.\n * See section 5.2 of MiRA paper\n */\n#define MIRA_COLLISION_LOSS_PERCENTAGE    10    /* from MiRA paper */\n#define MIRA_COLLISION_DETECTED        3    /* from MiRA paper */\n\n/*\n * XXX The paper's algorithm assumes aggregated frames. This is particularly\n * important for the detection of consecutive frame collisions which indicate\n * high competition for air time. Because we do not yet support Tx aggregation,\n * we run the algorithm over the result of several frames instead.\n * We also aggregate retries across all frames and act upon a percentage of\n * retried frames, rather than acting on retries seen for one aggregated frame.\n *\n * The collision window size (number of frames sent) needs to be short to\n * ensure our detection of consecutive collisions remains somewhat accurate.\n * We really have no idea how much time passes between frames in the window!\n * The good news is that users will only care about collision detection during\n * a transmit burst anyway, and we have this case more or less covered.\n */\n#define MIRA_COLLISION_MIN_FRAMES    6    /* XXX magic number */\n#define MIRA_COLLISION_RETRY_PERCENTAGE    60    /* XXX magic number */\n\n/* Set RTS threshold based on suspected collision from other STAs. */\nvoid\nieee80211_mira_set_rts_threshold(struct ieee80211_mira_node *mn,\n                                 struct ieee80211com *ic, struct ieee80211_node *ni)\n{\n    uint16_t rtsthreshold = mn->rts_threshold;\n    uint32_t loss, retry;\n    \n    /* Update collision window stats. */\n    mn->ifwnd_frames += mn->frames;\n    mn->ifwnd_retries += mn->retries;\n    mn->ifwnd_txfail += mn->txfail;\n    if (mn->ifwnd_frames < MIRA_COLLISION_MIN_FRAMES)\n        return; /* not enough frames yet */\n    \n    /* Check whether the loss pattern indicates frame collisions. */\n    loss = (mn->ifwnd_txfail * 100) / mn->ifwnd_frames;\n    retry = (mn->ifwnd_retries * 100) / mn->ifwnd_frames;\n    if (retry > MIRA_COLLISION_RETRY_PERCENTAGE &&\n        loss < MIRA_COLLISION_LOSS_PERCENTAGE) {\n        if (mn->ifwnd == 0) {\n            /* First frame collision confirmed. */\n            mn->ifwnd = MIRA_COLLISION_DETECTED;\n        } else if (mn->ifwnd == MIRA_COLLISION_DETECTED) {\n            /* Successive frame collision confirmed. Use RTS. */\n            rtsthreshold = IEEE80211_RTS_DEFAULT;\n        }\n    } else {\n        if (mn->ifwnd > 0)\n            mn->ifwnd--;\n        if (mn->ifwnd == 0)\n            rtsthreshold = IEEE80211_RTS_MAX;\n    }\n    \n    mn->rts_threshold = rtsthreshold;\n    ieee80211_mira_reset_collision_stats(mn);\n}\n\nint\nieee80211_mira_get_rts_threshold(struct ieee80211_mira_node *mn,\n                                 struct ieee80211com *ic, struct ieee80211_node *ni, size_t framelen)\n{\n    int rtsrate = ieee80211_min_basic_rate(ic);\n    uint64_t txtime, rtsoverhead;\n    /* Magic number from MiRA paper (\"cost/benefit ratio\"). */\n    static const uint64_t k = MIRA_FP_1 + (MIRA_FP_1 / 2); /* 1.5 */\n    \n    if (mn->probing || mn->rts_threshold >= IEEE80211_RTS_MAX)\n        return IEEE80211_RTS_MAX;\n    \n    /* Use RTS only if potential gains outweigh overhead. */\n    txtime = ieee80211_mira_ht_txtime(framelen, ni->ni_txmcs,\n                                      IEEE80211_IS_CHAN_2GHZ(ni->ni_chan),\n                                      (ni->ni_flags & (IEEE80211_NODE_HT_SGI20 | IEEE80211_NODE_HT_SGI40)) ? 1 : 0, \n                                      ni->ni_chw == IEEE80211_CHAN_WIDTH_40);\n    rtsoverhead = ieee80211_mira_legacy_txtime(MIRA_RTSLEN, rtsrate, ic);\n    rtsoverhead += ieee80211_mira_legacy_txtime(MIRA_CTSLEN, rtsrate, ic);\n    /* convert to fixed-point */\n    txtime <<= MIRA_FP_SHIFT;\n    rtsoverhead <<= MIRA_FP_SHIFT;\n    if (txtime >= MIRA_FP_MUL(k, rtsoverhead))\n        return mn->rts_threshold;\n    \n    return IEEE80211_RTS_MAX;\n}\n\nvoid\nieee80211_mira_reset_collision_stats(struct ieee80211_mira_node *mn)\n{\n    mn->ifwnd_frames = 0;\n    mn->ifwnd_retries = 0;\n    mn->ifwnd_txfail = 0;\n}\n\nvoid\nieee80211_mira_choose(struct ieee80211_mira_node *mn, struct ieee80211com *ic,\n                      struct ieee80211_node *ni)\n{\n    struct ieee80211_mira_goodput_stats *g = &mn->g[ni->ni_txmcs];\n    int s;\n    int sgi = (ni->ni_flags & (IEEE80211_NODE_HT_SGI20 | IEEE80211_NODE_HT_SGI40)) ? 1 : 0;\n    const struct ieee80211_ht_rateset *rs;\n    \n    s = splnet();\n    \n    if (mn->valid_rates == 0)\n        mn->valid_rates = ieee80211_mira_valid_rates(ic, ni);\n    \n#ifdef MIRA_DEBUG\n    if (mira_debug >= 5)\n        mira_print_driver_stats(mn, ni);\n#endif\n    ieee80211_mira_update_stats(mn, ic, ni);\n    \n    if (mn->probing) {\n        /* Probe another rate or settle at the best rate. */\n        if (!ieee80211_mira_intra_mode_ra_finished(mn, ni)) {\n            if (ieee80211_mira_probe_valid(mn, ni)) {\n                ieee80211_mira_probe_next_rate(mn, ni);\n                ieee80211_mira_reset_driver_stats(mn);\n            }\n            DPRINTFN(4, (\"probing MCS %d\\n\", ni->ni_txmcs));\n        } else if (ieee80211_mira_inter_mode_ra_finished(mn, ni)) {\n            mn->best_mcs = ieee80211_mira_best_rate(mn, ni);\n            ni->ni_txmcs = mn->best_mcs;\n            ieee80211_mira_probe_done(mn);\n        }\n        \n        splx(s);\n        return;\n    } else {\n        ieee80211_mira_set_rts_threshold(mn, ic, ni);\n        ieee80211_mira_reset_driver_stats(mn);\n        ieee80211_mira_schedule_probe_timers(mn, ni);\n    }\n    \n    if (ieee80211_mira_check_probe_timers(mn, ni)) {\n        /* Time-based probing has triggered. */\n        splx(s);\n        return;\n    }\n    \n    /* Check if event-based probing should be triggered. */\n    rs = ieee80211_mira_get_rateset(ni->ni_txmcs, sgi, ni->ni_chw == IEEE80211_CHAN_WIDTH_40);\n    if (g->measured < g->average - 2 * g->stddeviation &&\n        ni->ni_txmcs != rs->min_mcs) {\n        /* Channel becomes bad. Probe downwards. */\n        DPRINTFN(2, (\"channel becomes bad; probe downwards\\n\"));\n        DPRINTFN(3, (\"measured: %s Mbit/s\\n\",\n                     mira_fp_sprintf(g->measured)));\n        DPRINTFN(3, (\"average: %s Mbit/s\\n\",\n                     mira_fp_sprintf(g->average)));\n        DPRINTFN(3, (\"stddeviation: %s\\n\",\n                     mira_fp_sprintf(g->stddeviation)));\n        mn->probing = IEEE80211_MIRA_PROBING_DOWN;\n        mn->probed_rates = 0;\n#ifdef MIRA_AGGRESSIVE_DOWNWARDS_PROBING\n        /* Allow for probing all the way down within this rateset. */\n        mn->candidate_rates = ieee80211_mira_mcs_below(mn,\n                                                       ni->ni_txmcs, sgi, ni->ni_chw == IEEE80211_CHAN_WIDTH_40);\n#else\n        /* Probe the lower candidate rate to see if it's any better. */\n        mn->candidate_rates =\n        (1 << ieee80211_mira_next_lower_intra_rate(mn, ni));\n#endif\n        ieee80211_mira_cancel_timeouts(mn);\n    } else if (g->measured > g->average + 2 * g->stddeviation &&\n               ni->ni_txmcs != rs->max_mcs) {\n        /* Channel becomes good. */\n        DPRINTFN(2, (\"channel becomes good; probe upwards\\n\"));\n        DPRINTFN(3, (\"measured: %s Mbit/s\\n\",\n                     mira_fp_sprintf(g->measured)));\n        DPRINTFN(3, (\"average: %s Mbit/s\\n\",\n                     mira_fp_sprintf(g->average)));\n        DPRINTFN(3, (\"stddeviation: %s\\n\",\n                     mira_fp_sprintf(g->stddeviation)));\n        mn->probing = IEEE80211_MIRA_PROBING_UP;\n        mn->probed_rates = 0;\n        /* Probe the upper candidate rate to see if it's any better. */\n        mn->candidate_rates =\n        (1 << ieee80211_mira_next_intra_rate(mn, ni));\n        ieee80211_mira_cancel_timeouts(mn);\n    } else {\n        /* Remain at current rate. */\n        mn->probing = IEEE80211_MIRA_NOT_PROBING;\n        mn->probed_rates = 0;\n        mn->candidate_rates = 0;\n    }\n    \n    splx(s);\n}\n\nvoid\nieee80211_mira_node_init(struct ieee80211_mira_node *mn)\n{\n    memset(mn, 0, sizeof(*mn));\n    mn->agglen = 1;\n    mn->rts_threshold = IEEE80211_RTS_MAX;\n    ieee80211_mira_reset_goodput_stats(mn);\n    ieee80211_mira_reset_collision_stats(mn);\n    \n    memset(mn->probe_to, 0, sizeof(mn->probe_to) * nitems(mn->probe_to));\n    timeout_set(&mn->probe_to[IEEE80211_MIRA_PROBE_TO_UP],\n                ieee80211_mira_probe_timeout_up, mn);\n    timeout_set(&mn->probe_to[IEEE80211_MIRA_PROBE_TO_DOWN],\n                ieee80211_mira_probe_timeout_down, mn);\n}\n\nvoid\nieee80211_mira_cancel_timeouts(struct ieee80211_mira_node *mn)\n{\n    int t;\n    \n    for (t = 0; t < nitems(mn->probe_to); t++)\n        timeout_del(&mn->probe_to[t]);\n}\n\nvoid\nieee80211_mira_node_free(struct ieee80211_mira_node *mn)\n{\n    int t;\n    \n    for (t = 0; t < nitems(mn->probe_to); t++) {\n        timeout_del(&mn->probe_to[t]);\n        timeout_free(&mn->probe_to[t]);\n    }\n}\n\nint\nieee80211_mira_is_probing(struct ieee80211_mira_node *mn)\n{\n    return mn->probing != IEEE80211_MIRA_NOT_PROBING;\n}\n\nint\nieee80211_mira_get_best_mcs(struct ieee80211_mira_node *mn)\n{\n    return mn->best_mcs;\n}\n"
  },
  {
    "path": "itl80211/openbsd/net80211/ieee80211_mira.h",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n/*\t$OpenBSD: ieee80211_mira.h,v 1.5 2019/02/27 04:10:40 stsp Exp $\t*/\n\n/*\n * Copyright (c) 2016 Stefan Sperling <stsp@openbsd.org>\n * Copyright (c) 2016 Theo Buehler <tb@openbsd.org>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n#ifndef _NET80211_IEEE80211_MIRA_H_\n#define _NET80211_IEEE80211_MIRA_H_\n\n/* \n * MiRA - \"MIMO Rate Adaptation in 802.11n Wireless Networks\"\n * Ioannis Pefkianakis, Yun Hu, Starsky H.Y. Wong, Hao Yang, Songwu Lu\n * http://www.cs.ucla.edu/wing/publication/papers/Pefkianakis.MOBICOM10.pdf\n */\n\n/* \n * Goodput statistics struct. Measures the effective data rate of an MCS\n * index and contains data related to time-based probing to a new rate.\n * All uint64_t numbers in this struct use fixed-point arithmetic.\n */\nstruct ieee80211_mira_goodput_stats {\n\tuint64_t measured;\t/* Most recently measured goodput. */\n\tuint64_t average;\t/* Average measured goodput. */\n\tuint64_t average_agg;\t/* Average number of subframes per frame. */\n\tuint64_t stddeviation;\t/* Goodput standard deviation. */\n\n\t/* These fields are used while calculating probe intervals: */\n\tuint64_t loss;\t\t/* This rate's loss percentage SFER. */\n\tuint32_t nprobes;\t/* Number of probe attempts. */\n\tuint32_t nprobe_bytes;\t/* Number of bytes sent while probing. */\n\tint probe_interval;\t/* Probe interval for this rate. */\n\tint probe_timeout_triggered; /* It is time to probe this rate. */\n};\n\n/*\n * Rate control state.\n */\nstruct ieee80211_mira_node {\n\t/*\n\t * Fields set by drivers before calling ieee80211_mira_choose().\n\t */\n\tuint32_t frames;\t/* Increment per (sub-)frame transmitted. */\n\tuint32_t retries;\t/* Increment per Tx retry (frame not ACKed). */\n\tuint32_t txfail;\t/* Increment per Tx failure (also not ACKed). */\n\tuint32_t ampdu_size;\t/* Length of last (aggregated) frame sent. */\n\tuint32_t agglen;\t/* Number of subframes in last frame (1-64). */\n\n\t/* \n\t * Private fields for use by the rate control algorithm.\n\t */\n\n\t/* Bitmaps MCS 0-31. */\n\tuint32_t valid_rates;\n\tuint32_t candidate_rates;\n\tuint32_t probed_rates;\n\n\t/* Timeouts which trigger time-driven probing. */\n\tCTimeout* probe_to[2];\n#define IEEE80211_MIRA_PROBE_TO_INVALID\t-1\n#define IEEE80211_MIRA_PROBE_TO_UP\t0\n#define IEEE80211_MIRA_PROBE_TO_DOWN\t1\n\tint probe_timer_expired[2];\n\n\t/* Probing state. */\n\tint probing;\n#define IEEE80211_MIRA_NOT_PROBING\t0x0\n#define IEEE80211_MIRA_PROBING_DOWN\t0x1\n#define IEEE80211_MIRA_PROBING_UP\t0x2\n#define IEEE80211_MIRA_PROBING_INTER\t0x4 /* combined with UP or DOWN */\n\n\t/* The current best MCS found by probing. */\n\tint best_mcs;\n\n\t/* Goodput statistics for each MCS. */\n\tstruct ieee80211_mira_goodput_stats g[IEEE80211_HT_RATESET_NUM_MCS];\n\n\t/* Interference observation window (see MiRA paper section 5.2). */\n\tint ifwnd;\n\tuint32_t ifwnd_frames;\n\tuint32_t ifwnd_retries;\n\tuint32_t ifwnd_txfail;\n\n\t/* Current RTS threshold for this node. */\n\tint rts_threshold;\n};\n\n/* Initialize rate control state. */\nvoid\tieee80211_mira_node_init(struct ieee80211_mira_node *);\n\n/* Called by drivers from the Tx completion interrupt handler. */\nvoid\tieee80211_mira_choose(struct ieee80211_mira_node *,\n\t    struct ieee80211com *, struct ieee80211_node *);\n\n/* Cancel timeouts scheduled by ieee80211_mira_choose(). */\nvoid\tieee80211_mira_cancel_timeouts(struct ieee80211_mira_node *);\n\n/* Release rate control state. */\nvoid    ieee80211_mira_node_free(struct ieee80211_mira_node *);\n\n/* Returns RTS threshold to be used for a frame about to be transmitted. */\nint\tieee80211_mira_get_rts_threshold(struct ieee80211_mira_node *,\n    struct ieee80211com *, struct ieee80211_node *, size_t);\nint ieee80211_mira_is_probing(struct ieee80211_mira_node *);\nint ieee80211_mira_get_best_mcs(struct ieee80211_mira_node *mn);\n#endif /* _NET80211_IEEE80211_MIRA_H_ */\n"
  },
  {
    "path": "itl80211/openbsd/net80211/ieee80211_node.c",
    "content": "/*\n * Copyright (C) 2020  钟先耀\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n */\n/*\t$OpenBSD: ieee80211_node.c,v 1.173 2019/09/02 12:54:21 stsp Exp $\t*/\n/*\t$NetBSD: ieee80211_node.c,v 1.14 2004/05/09 09:18:47 dyoung Exp $\t*/\n\n/*-\n * Copyright (c) 2001 Atsushi Onoe\n * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting\n * Copyright (c) 2008 Damien Bergamini\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. The name of the author may not be used to endorse or promote products\n *    derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <sys/param.h>\n#include <sys/systm.h>\n#include <sys/mbuf.h>\n#include <sys/malloc.h>\n#include <sys/kernel.h>\n#include <sys/socket.h>\n#include <sys/sockio.h>\n#include <sys/endian.h>\n#include <sys/errno.h>\n#include <sys/sysctl.h>\n#include <sys/tree.h>\n\n#include <net/if.h>\n#include <net/if_dl.h>\n#include <net/if_media.h>\n\n#include <netinet/in.h>\n#include <netinet/if_ether.h>\n\n#if NBRIDGE > 0\n#include <net/if_bridge.h>\n#endif\n\n#include <net80211/ieee80211_var.h>\n#include <net80211/ieee80211_priv.h>\n\nstruct ieee80211_node *ieee80211_node_alloc(struct ieee80211com *);\nvoid ieee80211_node_free(struct ieee80211com *, struct ieee80211_node *);\nvoid ieee80211_node_copy(struct ieee80211com *, struct ieee80211_node *,\n                         const struct ieee80211_node *);\nvoid ieee80211_choose_rsnparams(struct ieee80211com *);\nu_int8_t ieee80211_node_getrssi(struct ieee80211com *,\n                                const struct ieee80211_node *);\nint ieee80211_node_checkrssi(struct ieee80211com *,\n                             const struct ieee80211_node *);\nint ieee80211_ess_is_better(struct ieee80211com *ic, struct ieee80211_node *,\n                            struct ieee80211_node *);\nvoid ieee80211_node_set_timeouts(struct ieee80211_node *);\nvoid ieee80211_setup_node(struct ieee80211com *, struct ieee80211_node *,\n                          const u_int8_t *);\nstruct ieee80211_node *ieee80211_alloc_node_helper(struct ieee80211com *);\nvoid ieee80211_node_switch_bss(struct ieee80211com *, struct ieee80211_node *);\nvoid ieee80211_node_addba_request(struct ieee80211_node *, int);\nvoid ieee80211_node_addba_request_ac_be_to(void *);\nvoid ieee80211_node_addba_request_ac_bk_to(void *);\nvoid ieee80211_node_addba_request_ac_vi_to(void *);\nvoid ieee80211_node_addba_request_ac_vo_to(void *);\nvoid ieee80211_needs_auth(struct ieee80211com *, struct ieee80211_node *);\n#ifndef IEEE80211_STA_ONLY\nvoid ieee80211_node_join_ht(struct ieee80211com *, struct ieee80211_node *);\nvoid ieee80211_node_join_rsn(struct ieee80211com *, struct ieee80211_node *);\nvoid ieee80211_node_join_11g(struct ieee80211com *, struct ieee80211_node *);\nvoid ieee80211_node_leave_ht(struct ieee80211com *, struct ieee80211_node *);\nvoid ieee80211_node_leave_vht(struct ieee80211com *, struct ieee80211_node *);\nvoid ieee80211_node_leave_rsn(struct ieee80211com *, struct ieee80211_node *);\nvoid ieee80211_node_leave_11g(struct ieee80211com *, struct ieee80211_node *);\nvoid ieee80211_inact_timeout(void *);\nvoid ieee80211_node_cache_timeout(void *);\n#endif\nvoid ieee80211_clean_inactive_nodes(struct ieee80211com *, int);\n\n#ifndef IEEE80211_STA_ONLY\nvoid\nieee80211_inact_timeout(void *arg)\n{\n    struct ieee80211com *ic = (struct ieee80211com *)arg;\n    struct ieee80211_node *ni, *next_ni;\n    int s;\n    \n    s = splnet();\n    for (ni = RB_MIN(ieee80211_tree, &ic->ic_tree);\n         ni != NULL; ni = next_ni) {\n        next_ni = RB_NEXT(ieee80211_tree, &ic->ic_tree, ni);\n        if (ni->ni_refcnt > 0)\n            continue;\n        if (ni->ni_inact < IEEE80211_INACT_MAX)\n            ni->ni_inact++;\n    }\n    splx(s);\n    \n    timeout_add_sec(&ic->ic_inact_timeout, IEEE80211_INACT_WAIT);\n}\n\nvoid\nieee80211_node_cache_timeout(void *arg)\n{\n    struct ieee80211com *ic = (struct ieee80211com *)arg;\n    \n    ieee80211_clean_nodes(ic, 1);\n    timeout_add_sec(&ic->ic_node_cache_timeout, IEEE80211_CACHE_WAIT);\n}\n#endif\n\n/*\n * For debug purposes\n */\nvoid\nieee80211_print_ess(struct ieee80211_ess *ess)\n{\n    ieee80211_print_essid(ess->essid, ess->esslen);\n    if (ess->flags & IEEE80211_F_RSNON) {\n        XYLog(\" wpa\");\n        if (ess->rsnprotos & IEEE80211_PROTO_RSN)\n            XYLog(\",wpa2\");\n        if (ess->rsnprotos & IEEE80211_PROTO_WPA)\n            XYLog(\",wpa1\");\n        \n        if (ess->rsnakms & IEEE80211_AKM_8021X ||\n            ess->rsnakms & IEEE80211_AKM_SHA256_8021X)\n            XYLog(\",802.1x\");\n        XYLog(\" \");\n        \n        if (ess->rsnciphers & IEEE80211_CIPHER_USEGROUP)\n            XYLog(\" usegroup\");\n        if (ess->rsnciphers & IEEE80211_CIPHER_WEP40)\n            XYLog(\" wep40\");\n        if (ess->rsnciphers & IEEE80211_CIPHER_WEP104)\n            XYLog(\" wep104\");\n        if (ess->rsnciphers & IEEE80211_CIPHER_TKIP)\n            XYLog(\" tkip\");\n        if (ess->rsnciphers & IEEE80211_CIPHER_CCMP)\n            XYLog(\" ccmp\");\n    }\n    if (ess->flags & IEEE80211_F_WEPON) {\n        int i = ess->def_txkey;\n        \n        XYLog(\" wep,\");\n        if (ess->nw_keys[i].k_cipher & IEEE80211_CIPHER_WEP40)\n            XYLog(\"wep40\");\n        if (ess->nw_keys[i].k_cipher & IEEE80211_CIPHER_WEP104)\n            XYLog(\"wep104\");\n    }\n    if (ess->flags == 0)\n        XYLog(\" clear\");\n    XYLog(\"\\n\");\n}\n\nvoid\nieee80211_print_ess_list(struct ieee80211com *ic)\n{\n    struct _ifnet\t\t*ifp = &ic->ic_if;\n    struct ieee80211_ess\t*ess;\n    \n    XYLog(\"%s: known networks\\n\", ifp->if_xname);\n    TAILQ_FOREACH(ess, &ic->ic_ess, ess_next) {\n        ieee80211_print_ess(ess);\n    }\n}\n\nstruct ieee80211_ess *\nieee80211_get_ess(struct ieee80211com *ic, const char *nwid, int len)\n{\n    struct ieee80211_ess\t*ess;\n    \n    TAILQ_FOREACH(ess, &ic->ic_ess, ess_next) {\n        if (len == ess->esslen &&\n            memcmp(ess->essid, nwid, ess->esslen) == 0)\n            return ess;\n    }\n    \n    return NULL;\n}\n\nvoid\nieee80211_del_ess(struct ieee80211com *ic, char *nwid, int len, int all)\n{\n    struct ieee80211_ess *ess, *next;\n    \n    TAILQ_FOREACH_SAFE(ess, &ic->ic_ess, ess_next, next) {\n        if (ess == NULL) {\n            XYLog(\"%s: ess == NULL!!!\\n\", __FUNCTION__);\n            continue;\n        }\n        if (all == 1 || (ess->esslen == len &&\n                         memcmp(ess->essid, nwid, len) == 0)) {\n            TAILQ_REMOVE(&ic->ic_ess, ess, ess_next);\n            explicit_bzero(ess, sizeof(*ess));\n            free(ess);\n            if (TAILQ_EMPTY(&ic->ic_ess))\n                ic->ic_flags &= ~IEEE80211_F_AUTO_JOIN;\n            if (all != 1)\n                return;\n        }\n    }\n}\n\n/* Keep in sync with ieee80211_ioctl.c:ieee80211_ioctl_setnwkeys() */\nstatic int\nieee80211_ess_setnwkeys(struct ieee80211_ess *ess,\n                        const struct ieee80211_nwkey *nwkey)\n{\n    struct ieee80211_key *k;\n    int error, i;\n    \n    if (nwkey->i_wepon == IEEE80211_NWKEY_OPEN) {\n        if (!(ess->flags & IEEE80211_F_WEPON))\n            return 0;\n        ess->flags &= ~IEEE80211_F_WEPON;\n        return ENETRESET;\n    }\n    if (nwkey->i_defkid < 1 || nwkey->i_defkid > IEEE80211_WEP_NKID)\n        return EINVAL;\n    \n    for (i = 0; i < IEEE80211_WEP_NKID; i++) {\n        if (nwkey->i_key[i].i_keylen == 0 ||\n            nwkey->i_key[i].i_keydat == NULL)\n            continue;\t/* entry not set */\n        if (nwkey->i_key[i].i_keylen > IEEE80211_KEYBUF_SIZE)\n            return EINVAL;\n        \n        /* map wep key to ieee80211_key */\n        k = &ess->nw_keys[i];\n        memset(k, 0, sizeof(*k));\n        if (nwkey->i_key[i].i_keylen <= 5)\n            k->k_cipher = IEEE80211_CIPHER_WEP40;\n        else\n            k->k_cipher = IEEE80211_CIPHER_WEP104;\n        k->k_len = ieee80211_cipher_keylen(k->k_cipher);\n        k->k_flags = IEEE80211_KEY_GROUP | IEEE80211_KEY_TX;\n        error = copyin((const user_addr_t)nwkey->i_key[i].i_keydat, k->k_key, k->k_len);\n        if (error != 0)\n            return error;\n    }\n    ess->def_txkey = nwkey->i_defkid - 1;\n    ess->flags |= IEEE80211_F_WEPON;\n    \n    return ENETRESET;\n}\n\n\n/* Keep in sync with ieee80211_ioctl.c:ieee80211_ioctl_setwpaparms() */\nstatic int\nieee80211_ess_setwpaparms(struct ieee80211_ess *ess,\n                          const struct ieee80211_wpaparams *wpa)\n{\n    if (!wpa->i_enabled) {\n        if (!(ess->flags & IEEE80211_F_RSNON))\n            return 0;\n        ess->flags &= ~IEEE80211_F_RSNON;\n        ess->rsnprotos = 0;\n        ess->rsnakms = 0;\n        ess->rsngroupcipher = (enum ieee80211_cipher)0;\n        ess->rsnciphers = 0;\n        return ENETRESET;\n    }\n    \n    ess->rsnprotos = 0;\n    if (wpa->i_protos & IEEE80211_WPA_PROTO_WPA1)\n        ess->rsnprotos |= IEEE80211_PROTO_WPA;\n    if (wpa->i_protos & IEEE80211_WPA_PROTO_WPA2)\n        ess->rsnprotos |= IEEE80211_PROTO_RSN;\n    if (ess->rsnprotos == 0)\t/* set to default (RSN) */\n        ess->rsnprotos = IEEE80211_PROTO_RSN;\n    \n    ess->rsnakms = 0;\n    if (wpa->i_akms & IEEE80211_WPA_AKM_PSK)\n        ess->rsnakms |= IEEE80211_AKM_PSK;\n    if (wpa->i_akms & IEEE80211_WPA_AKM_SHA256_PSK)\n        ess->rsnakms |= IEEE80211_AKM_SHA256_PSK;\n    if (wpa->i_akms & IEEE80211_WPA_AKM_8021X)\n        ess->rsnakms |= IEEE80211_AKM_8021X;\n    if (wpa->i_akms & IEEE80211_WPA_AKM_SHA256_8021X)\n        ess->rsnakms |= IEEE80211_AKM_SHA256_8021X;\n    if (ess->rsnakms == 0)\t/* set to default (PSK) */\n        ess->rsnakms = IEEE80211_AKM_PSK;\n    \n    if (wpa->i_groupcipher == IEEE80211_WPA_CIPHER_WEP40)\n        ess->rsngroupcipher = IEEE80211_CIPHER_WEP40;\n    else if (wpa->i_groupcipher == IEEE80211_WPA_CIPHER_TKIP)\n        ess->rsngroupcipher = IEEE80211_CIPHER_TKIP;\n    else if (wpa->i_groupcipher == IEEE80211_WPA_CIPHER_CCMP)\n        ess->rsngroupcipher = IEEE80211_CIPHER_CCMP;\n    else if (wpa->i_groupcipher == IEEE80211_WPA_CIPHER_WEP104)\n        ess->rsngroupcipher = IEEE80211_CIPHER_WEP104;\n    else  {\t/* set to default */\n        if (ess->rsnprotos & IEEE80211_PROTO_WPA)\n            ess->rsngroupcipher = IEEE80211_CIPHER_TKIP;\n        else\n            ess->rsngroupcipher = IEEE80211_CIPHER_CCMP;\n    }\n    \n    ess->rsnciphers = 0;\n    if (wpa->i_ciphers & IEEE80211_WPA_CIPHER_TKIP)\n        ess->rsnciphers |= IEEE80211_CIPHER_TKIP;\n    if (wpa->i_ciphers & IEEE80211_WPA_CIPHER_CCMP)\n        ess->rsnciphers |= IEEE80211_CIPHER_CCMP;\n    if (wpa->i_ciphers & IEEE80211_WPA_CIPHER_USEGROUP)\n        ess->rsnciphers = IEEE80211_CIPHER_USEGROUP;\n    if (ess->rsnciphers == 0) { /* set to default (CCMP, TKIP if WPA1) */\n        ess->rsnciphers = IEEE80211_CIPHER_CCMP;\n        if (ess->rsnprotos & IEEE80211_PROTO_WPA)\n            ess->rsnciphers |= IEEE80211_CIPHER_TKIP;\n    }\n    \n    ess->flags |= IEEE80211_F_RSNON;\n    \n    if (ess->rsnakms &\n        (IEEE80211_AKM_8021X|IEEE80211_AKM_SHA256_8021X))\n        ess->flags |= IEEE80211_JOIN_8021X;\n    \n    return ENETRESET;\n}\n\nstatic void\nieee80211_ess_clear_wep(struct ieee80211_ess *ess)\n{\n    int i;\n    \n    /* Disable WEP */\n    for (i = 0; i < IEEE80211_WEP_NKID; i++) {\n        explicit_bzero(&ess->nw_keys[i], sizeof(ess->nw_keys[0]));\n    }\n    ess->def_txkey = 0;\n    ess->flags &= ~IEEE80211_F_WEPON;\n}\n\nstatic void\nieee80211_ess_clear_wpa(struct ieee80211_ess *ess)\n{\n    /* Disable WPA */\n    ess->rsnprotos = ess->rsnakms =\n    ess->rsnciphers = 0;\n    ess->rsngroupcipher = (enum ieee80211_cipher)0;\n    explicit_bzero(ess->psk, sizeof(ess->psk));\n    ess->flags &= ~(IEEE80211_F_PSK | IEEE80211_F_RSNON);\n}\n\nint\nieee80211_add_ess(struct ieee80211com *ic, struct ieee80211_join *join)\n{\n    struct ieee80211_ess *ess;\n    int new_value = 0, ness = 0;\n    \n    /* only valid for station (aka, client) mode */\n    if (ic->ic_opmode != IEEE80211_M_STA)\n        return (0);\n    \n    TAILQ_FOREACH(ess, &ic->ic_ess, ess_next) {\n        if (ess->esslen == join->i_len &&\n            memcmp(ess->essid, join->i_nwid, ess->esslen) == 0)\n            break;\n        ness++;\n    }\n    \n    if (ess == NULL) {\n        /* if not found, and wpa/wep are set, then return */\n        if ((join->i_flags & IEEE80211_JOIN_WPA) &&\n            (join->i_flags & IEEE80211_JOIN_NWKEY)) {\n            return (EINVAL);\n        }\n        if (ness > IEEE80211_CACHE_SIZE)\n            return (ERANGE);\n        new_value = 1;\n        ess = (struct ieee80211_ess *)malloc(sizeof(*ess), 0, 0);\n        if (ess == NULL)\n            return (ENOMEM);\n        memcpy(ess->essid, join->i_nwid, join->i_len);\n        ess->esslen = join->i_len;\n    }\n    \n    if (join->i_flags & IEEE80211_JOIN_WPA) {\n        if (join->i_wpaparams.i_enabled) {\n            if (!(ic->ic_caps & IEEE80211_C_RSN)) {\n                free(ess);\n                return ENODEV;\n            }\n            ieee80211_ess_setwpaparms(ess,\n                                      &join->i_wpaparams);\n            if (join->i_flags & IEEE80211_JOIN_WPAPSK) {\n                ess->flags |= IEEE80211_F_PSK;\n                explicit_bzero(ess->psk, sizeof(ess->psk));\n                memcpy(ess->psk, &join->i_wpapsk.i_psk,\n                       sizeof(ess->psk));\n            }\n            ieee80211_ess_clear_wep(ess);\n        } else {\n            ieee80211_ess_clear_wpa(ess);\n        }\n    } else if (join->i_flags & IEEE80211_JOIN_NWKEY) {\n        if (join->i_nwkey.i_wepon) {\n            if (!(ic->ic_caps & IEEE80211_C_WEP)) {\n                free(ess);\n                return ENODEV;\n            }\n            ieee80211_ess_setnwkeys(ess, &join->i_nwkey);\n            ieee80211_ess_clear_wpa(ess);\n        } else {\n            ieee80211_ess_clear_wep(ess);\n        }\n    }\n    \n    if (new_value)\n        TAILQ_INSERT_TAIL(&ic->ic_ess, ess, ess_next);\n    \n    return (0);\n}\n\nuint8_t\nieee80211_ess_adjust_rssi(struct ieee80211com *ic, struct ieee80211_node *ni)\n{\n    uint8_t rssi = ni->ni_rssi;\n    \n    /*\n     * Slightly punish 2 GHz RSSI values since they are usually\n     * stronger than 5 GHz RSSI values.\n     */\n    if (IEEE80211_IS_CHAN_2GHZ(ni->ni_chan)) {\n        if (ic->ic_max_rssi) {\n            uint8_t p = (5 * ic->ic_max_rssi) / 100;\n            if (rssi >= p)\n                rssi -= p; /* punish by 5% */\n        } else  {\n            if (rssi >= 8)\n                rssi -= 8; /* punish by 8 dBm */\n        }\n    }\n    \n    return rssi;\n}\n\nint\nieee80211_ess_calculate_score(struct ieee80211com *ic,\n                              struct ieee80211_node *ni)\n{\n    int score = 0;\n    uint8_t\tmin_5ghz_rssi;\n    \n    if (ic->ic_max_rssi)\n        min_5ghz_rssi = IEEE80211_RSSI_THRES_RATIO_5GHZ;\n    else\n        min_5ghz_rssi = (uint8_t)IEEE80211_RSSI_THRES_5GHZ;\n    \n    /* not using join any */\n    if (ieee80211_get_ess(ic, (const char*)ni->ni_essid, ni->ni_esslen))\n        score += 32;\n    \n    /* Calculate the crypto score */\n    if (ni->ni_rsnprotos & IEEE80211_PROTO_RSN)\n        score += 16;\n    if (ni->ni_rsnprotos & IEEE80211_PROTO_WPA)\n        score += 8;\n    if (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY)\n        score += 4;\n    \n    /* 5GHz with a good signal */\n    if (IEEE80211_IS_CHAN_5GHZ(ni->ni_chan) &&\n        ni->ni_rssi > min_5ghz_rssi)\n        score += 2;\n    \n    /* HT/VHT available */\n    if (ieee80211_node_supports_ht(ni))\n        score++;\n    if (ieee80211_node_supports_vht(ni))\n        score++;\n    \n    /* Boost this AP if it had no auth/assoc failures in the past. */\n    if (ni->ni_fails == 0)\n        score += 21;\n    \n    return score;\n}\n\n/*\n * Given two APs, determine the \"better\" one of the two.\n * We compute a score based on the following attributes:\n *\n *  crypto: wpa2 > wpa1 > wep > open\n *  band: 5 GHz > 2 GHz provided 5 GHz rssi is above threshold\n *  supported standard revisions: 11ac > 11n > 11a/b/g\n *  rssi: rssi1 > rssi2 as a numeric comparison with a slight\n *         disadvantage for 2 GHz APs\n *\n * Crypto carries most weight, followed by band, followed by rssi.\n */\nint\nieee80211_ess_is_better(struct ieee80211com *ic,\n                        struct ieee80211_node *nicur, struct ieee80211_node *nican)\n{\n    struct _ifnet\t\t*ifp = &ic->ic_if;\n    int\t\t\t score_cur = 0, score_can = 0;\n    int\t\t\t cur_rssi, can_rssi;\n    \n    score_cur = ieee80211_ess_calculate_score(ic, nicur);\n    score_can = ieee80211_ess_calculate_score(ic, nican);\n    \n    cur_rssi = ieee80211_ess_adjust_rssi(ic, nicur);\n    can_rssi = ieee80211_ess_adjust_rssi(ic, nican);\n    \n    if (can_rssi > cur_rssi)\n        score_can++;\n    \n    if ((ifp->if_flags & IFF_DEBUG) && (score_can <= score_cur)) {\n        XYLog(\"%s: AP %s \", ifp->if_xname,\n              ether_sprintf(nican->ni_bssid));\n        ieee80211_print_essid(nican->ni_essid, nican->ni_esslen);\n        XYLog(\" score %d\\n\", score_can);\n    }\n    \n    return score_can > score_cur;\n}\n\n/* Determine whether a candidate AP belongs to a given ESS. */\nint\nieee80211_match_ess(struct ieee80211_ess *ess, struct ieee80211_node *ni)\n{\n    if (ess->esslen != 0 &&\n        (ess->esslen != ni->ni_esslen ||\n         memcmp(ess->essid, ni->ni_essid, ess->esslen) != 0)) {\n        ni->ni_assoc_fail |= IEEE80211_NODE_ASSOCFAIL_ESSID;\n        return 0;\n    }\n    \n    if (ess->flags & (IEEE80211_F_PSK | IEEE80211_F_RSNON)) {\n        /* Ensure same WPA version. */\n        if ((ni->ni_rsnprotos & IEEE80211_PROTO_RSN) &&\n            (ess->rsnprotos & IEEE80211_PROTO_RSN) == 0) {\n            ni->ni_assoc_fail |= IEEE80211_NODE_ASSOCFAIL_WPA_PROTO;\n            return 0;\n        }\n        if ((ni->ni_rsnprotos & IEEE80211_PROTO_WPA) &&\n            (ess->rsnprotos & IEEE80211_PROTO_WPA) == 0) {\n            ni->ni_assoc_fail |= IEEE80211_NODE_ASSOCFAIL_WPA_PROTO;\n            return 0;\n        }\n    } else if (ess->flags & IEEE80211_F_WEPON) {\n        if ((ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) == 0) {\n            ni->ni_assoc_fail |= IEEE80211_NODE_ASSOCFAIL_PRIVACY;\n            return 0;\n        }\n    } else {\n        if ((ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) != 0) {\n            ni->ni_assoc_fail |= IEEE80211_NODE_ASSOCFAIL_PRIVACY;\n            return 0;\n        }\n    }\n    \n    if (ess->esslen == 0 &&\n        (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) != 0) {\n        ni->ni_assoc_fail |= IEEE80211_NODE_ASSOCFAIL_PRIVACY;\n        return 0;\n    }\n    \n    return 1;\n}\n\nvoid\nieee80211_switch_ess(struct ieee80211com *ic)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct _ifnet\t\t*ifp = &ic->ic_if;\n    struct ieee80211_ess\t*ess, *seless = NULL;\n    struct ieee80211_node\t*ni, *selni = NULL;\n    \n    if (!ISSET(ifp->if_flags, IFF_RUNNING))\n        return;\n    \n    /* Find the best AP matching an entry on our ESS join list. */\n    RB_FOREACH(ni, ieee80211_tree, &ic->ic_tree) {\n        if ((ic->ic_flags & IEEE80211_F_DESBSSID) &&\n            !IEEE80211_ADDR_EQ(ic->ic_des_bssid, ni->ni_bssid))\n            continue;\n        \n        TAILQ_FOREACH(ess, &ic->ic_ess, ess_next) {\n            if (ieee80211_match_ess(ess, ni))\n                break;\n        }\n        if (ess == NULL)\n            continue;\n        \n        /*\n         * Operate only on ic_des_essid if auto-join is disabled.\n         * We might have a password stored for this network.\n         */\n        if (!ISSET(ic->ic_flags, IEEE80211_F_AUTO_JOIN)) {\n            if (ic->ic_des_esslen == ni->ni_esslen &&\n                memcmp(ic->ic_des_essid, ni->ni_essid,\n                       ni->ni_esslen) == 0 &&\n                ni->ni_esslen > 0) {\n                ieee80211_set_ess(ic, ess, ni);\n                return;\n            }\n            continue;\n        }\n        \n        if (selni == NULL) {\n            seless = ess;\n            selni = ni;\n            continue;\n        }\n        \n        if (ieee80211_ess_is_better(ic, selni, ni)) {\n            seless = ess;\n            selni = ni;\n        }\n    }\n    \n    if (selni && seless && !(selni->ni_esslen == ic->ic_des_esslen &&\n                             (memcmp(ic->ic_des_essid, selni->ni_essid,\n                                     IEEE80211_NWID_LEN) == 0))) {\n        if (ifp->if_flags & IFF_DEBUG) {\n            XYLog(\"%s: best AP %s \", ifp->if_xname,\n                  ether_sprintf(selni->ni_bssid));\n            ieee80211_print_essid(selni->ni_essid,\n                                  selni->ni_esslen);\n            XYLog(\" score %d\\n\",\n                  ieee80211_ess_calculate_score(ic, selni));\n            XYLog(\"%s: switching to network \", ifp->if_xname);\n            ieee80211_print_essid(selni->ni_essid,\n                                  selni->ni_esslen);\n            if (seless->esslen == 0)\n                XYLog(\" via join any\");\n            XYLog(\"\\n\");\n            \n        }\n        ieee80211_set_ess(ic, seless, selni);\n    }\n}\n\nvoid\nieee80211_set_ess(struct ieee80211com *ic, struct ieee80211_ess *ess, \n                  struct ieee80211_node *ni)\n{\n    memset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN);\n    ic->ic_des_esslen = ni->ni_esslen;\n    memcpy(ic->ic_des_essid, ni->ni_essid, ic->ic_des_esslen);\n    \n    ieee80211_disable_wep(ic);\n    ieee80211_disable_rsn(ic);\n    \n    if (ess->flags & IEEE80211_F_RSNON) {\n        explicit_bzero(ic->ic_psk, sizeof(ic->ic_psk));\n        memcpy(ic->ic_psk, ess->psk, sizeof(ic->ic_psk));\n        \n        ic->ic_rsnprotos = ess->rsnprotos;\n        ic->ic_rsnakms = ess->rsnakms;\n        ic->ic_rsngroupcipher = ess->rsngroupcipher;\n        ic->ic_rsnciphers = ess->rsnciphers;\n        ic->ic_flags |= IEEE80211_F_RSNON;\n        if (ess->flags & IEEE80211_F_PSK)\n            ic->ic_flags |= IEEE80211_F_PSK;\n    } else if (ess->flags & IEEE80211_F_WEPON) {\n        struct ieee80211_key\t*k;\n        int\t\t\t i;\n        \n        for (i = 0; i < IEEE80211_WEP_NKID; i++) {\n            k = &ic->ic_nw_keys[i];\n            if (k->k_cipher != IEEE80211_CIPHER_NONE)\n                (*ic->ic_delete_key)(ic, NULL, k);\n            memcpy(&ic->ic_nw_keys[i], &ess->nw_keys[i],\n                   sizeof(struct ieee80211_key));\n            (*ic->ic_set_key)(ic, NULL, k);\n        }\n        ic->ic_def_txkey = ess->def_txkey;\n        ic->ic_flags |= IEEE80211_F_WEPON;\n    }\n}\n\nvoid\nieee80211_deselect_ess(struct ieee80211com *ic)\n{\n    memset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN);\n    ic->ic_des_esslen = 0;\n    ieee80211_disable_wep(ic);\n    ieee80211_disable_rsn(ic);\n}\n\nvoid\nieee80211_node_attach(struct _ifnet *ifp)\n{\n    struct ieee80211com *ic = (struct ieee80211com *)ifp;\n#ifndef IEEE80211_STA_ONLY\n    int size;\n#endif\n    \n    RB_INIT(&ic->ic_tree);\n    ic->ic_node_alloc = ieee80211_node_alloc;\n    ic->ic_node_free = ieee80211_node_free;\n    ic->ic_node_copy = ieee80211_node_copy;\n    ic->ic_node_getrssi = ieee80211_node_getrssi;\n    ic->ic_node_checkrssi = ieee80211_node_checkrssi;\n    ic->ic_scangen = 1;\n    ic->ic_max_nnodes = ieee80211_cache_size;\n    \n    if (ic->ic_max_aid == 0)\n        ic->ic_max_aid = IEEE80211_AID_DEF;\n    else if (ic->ic_max_aid > IEEE80211_AID_MAX)\n        ic->ic_max_aid = IEEE80211_AID_MAX;\n#ifndef IEEE80211_STA_ONLY\n    size = howmany(ic->ic_max_aid, 32) * sizeof(u_int32_t);\n    ic->ic_aid_bitmap = (u_int32_t *)malloc(size, 0, 0);\n    if (ic->ic_aid_bitmap == NULL) {\n        /* XXX no way to recover */\n        XYLog(\"%s: no memory for AID bitmap!\\n\", __FUNCTION__);\n        ic->ic_max_aid = 0;\n    }\n    if (ic->ic_caps & (IEEE80211_C_HOSTAP | IEEE80211_C_IBSS)) {\n        ic->ic_tim_len = howmany(ic->ic_max_aid, 8);\n        ic->ic_tim_bitmap = (u_int8_t*)malloc(ic->ic_tim_len, 0, 0);\n        if (ic->ic_tim_bitmap == NULL) {\n            XYLog(\"%s: no memory for TIM bitmap!\\n\", __FUNCTION__);\n            ic->ic_tim_len = 0;\n        } else\n            ic->ic_set_tim = ieee80211_set_tim;\n        timeout_set(&ic->ic_rsn_timeout,\n                    ieee80211_gtk_rekey_timeout, ic);\n        timeout_set(&ic->ic_inact_timeout,\n                    ieee80211_inact_timeout, ic);\n        timeout_set(&ic->ic_node_cache_timeout,\n                    ieee80211_node_cache_timeout, ic);\n    }\n#endif\n    TAILQ_INIT(&ic->ic_ess);\n}\n\nstruct ieee80211_node *\nieee80211_alloc_node_helper(struct ieee80211com *ic)\n{\n    struct ieee80211_node *ni;\n    if (ic->ic_nnodes >= ic->ic_max_nnodes)\n        ieee80211_clean_nodes(ic, 0);\n    if (ic->ic_nnodes >= ic->ic_max_nnodes)\n        return NULL;\n    ni = (*ic->ic_node_alloc)(ic);\n    return ni;\n}\n\nvoid\nieee80211_node_lateattach(struct _ifnet *ifp)\n{\n    struct ieee80211com *ic = (struct ieee80211com *)ifp;\n    struct ieee80211_node *ni;\n    \n    ni = ieee80211_alloc_node_helper(ic);\n    if (ni == NULL)\n        panic(\"unable to setup inital BSS node\");\n    ni->ni_chan = IEEE80211_CHAN_ANYC;\n    ic->ic_bss = ieee80211_ref_node(ni);\n    ic->ic_txpower = IEEE80211_TXPOWER_MAX;\n#ifndef IEEE80211_STA_ONLY\n    mq_init(&ni->ni_savedq, IEEE80211_PS_MAX_QUEUE, IPL_NET);\n#endif\n}\n\nvoid\nieee80211_node_detach(struct _ifnet *ifp)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct ieee80211com *ic = (struct ieee80211com *)ifp;\n    \n    if (ic->ic_bss != NULL) {\n        (*ic->ic_node_free)(ic, ic->ic_bss);\n        ic->ic_bss = NULL;\n    }\n    ieee80211_del_ess(ic, NULL, 0, 1);\n    ieee80211_free_allnodes(ic, 1);\n#ifndef IEEE80211_STA_ONLY\n    free(ic->ic_aid_bitmap);\n    free(ic->ic_tim_bitmap);\n    timeout_del(&ic->ic_inact_timeout);\n    timeout_free(&ic->ic_inact_timeout);\n    timeout_del(&ic->ic_node_cache_timeout);\n    timeout_free(&ic->ic_node_cache_timeout);\n    timeout_del(&ic->ic_tkip_micfail_timeout);\n    timeout_free(&ic->ic_tkip_micfail_timeout);\n#endif\n    timeout_del(&ic->ic_rsn_timeout);\n    timeout_free(&ic->ic_rsn_timeout);\n}\n\n/*\n * AP scanning support.\n */\n\n/*\n * Initialize the active channel set based on the set\n * of available channels and the current PHY mode.\n */\nvoid\nieee80211_reset_scan(struct _ifnet *ifp)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct ieee80211com *ic = (struct ieee80211com *)ifp;\n    \n    memcpy(ic->ic_chan_scan, ic->ic_chan_active,\n           sizeof(ic->ic_chan_active));\n    /* NB: hack, setup so next_scan starts with the first channel */\n    if (ic->ic_bss != NULL && ic->ic_bss->ni_chan == IEEE80211_CHAN_ANYC)\n        ic->ic_bss->ni_chan = &ic->ic_channels[IEEE80211_CHAN_MAX];\n}\n\n/*\n * Increase a node's inactivity counter.\n * This counter get reset to zero if a frame is received.\n * This function is intended for station mode only.\n * See ieee80211_node_cache_timeout() for hostap mode.\n */\nvoid\nieee80211_node_raise_inact(void *arg, struct ieee80211_node *ni)\n{\n    if (ni->ni_refcnt == 0 && ni->ni_inact < IEEE80211_INACT_SCAN)\n        ni->ni_inact++;\n}\n\n/*\n * Begin an active scan.\n */\nvoid\nieee80211_begin_scan(struct _ifnet *ifp)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct ieee80211com *ic = (struct ieee80211com *)ifp;\n    \n    /*\n     * In all but hostap mode scanning starts off in\n     * an active mode before switching to passive.\n     */\n#ifndef IEEE80211_STA_ONLY\n    if (ic->ic_opmode != IEEE80211_M_HOSTAP)\n#endif\n    {\n        ic->ic_flags |= IEEE80211_F_ASCAN;\n        ic->ic_stats.is_scan_active++;\n    }\n#ifndef IEEE80211_STA_ONLY\n    else\n        ic->ic_stats.is_scan_passive++;\n#endif\n    if (ifp->if_flags & IFF_DEBUG)\n        XYLog(\"%s: begin %s scan\\n\", ifp->if_xname,\n              (ic->ic_flags & IEEE80211_F_ASCAN) ?\n              \"active\" : \"passive\");\n    \n    \n    if (ic->ic_opmode == IEEE80211_M_STA) {\n        ieee80211_node_cleanup(ic, ic->ic_bss);\n        ieee80211_iterate_nodes(ic, ieee80211_node_raise_inact, NULL);\n    }\n    \n    /*\n     * Reset the current mode. Setting the current mode will also\n     * reset scan state.\n     */\n    if (IFM_MODE(ic->ic_media.ifm_cur->ifm_media) == IFM_AUTO)\n        ic->ic_curmode = IEEE80211_MODE_AUTO;\n    ieee80211_setmode(ic, (enum ieee80211_phymode)ic->ic_curmode);\n    \n    ic->ic_scan_count = 0;\n    \n    /* Scan the next channel. */\n    ieee80211_next_scan(ifp);\n}\n\n/*\n * Switch to the next channel marked for scanning.\n */\nvoid\nieee80211_next_scan(struct _ifnet *ifp)\n{\n    struct ieee80211com *ic = (struct ieee80211com *)ifp;\n    struct ieee80211_channel *chan;\n    \n    chan = ic->ic_bss->ni_chan;\n    for (;;) {\n        if (++chan > &ic->ic_channels[IEEE80211_CHAN_MAX])\n            chan = &ic->ic_channels[0];\n        if (isset(ic->ic_chan_scan, ieee80211_chan2ieee(ic, chan))) {\n            /*\n             * Ignore channels marked passive-only\n             * during an active scan.\n             */\n            if ((ic->ic_flags & IEEE80211_F_ASCAN) == 0 ||\n                (chan->ic_flags & IEEE80211_CHAN_PASSIVE) == 0)\n                break;\n        }\n        if (chan == ic->ic_bss->ni_chan) {\n            ieee80211_end_scan(ifp);\n            return;\n        }\n    }\n    clrbit(ic->ic_chan_scan, ieee80211_chan2ieee(ic, chan));\n    DPRINTF((\"chan %d->%d\\n\",\n             ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan),\n             ieee80211_chan2ieee(ic, chan)));\n    ic->ic_bss->ni_chan = chan;\n    ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);\n}\n\n#ifndef IEEE80211_STA_ONLY\nvoid\nieee80211_create_ibss(struct ieee80211com* ic, struct ieee80211_channel *chan)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct ieee80211_node *ni;\n    struct _ifnet *ifp = &ic->ic_if;\n    \n    ni = ic->ic_bss;\n    if (ifp->if_flags & IFF_DEBUG)\n        XYLog(\"%s: creating ibss\\n\", ifp->if_xname);\n    ic->ic_flags |= IEEE80211_F_SIBSS;\n    ni->ni_chan = chan;\n    ni->ni_rates = ic->ic_sup_rates[ieee80211_chan2mode(ic, ni->ni_chan)];\n    ni->ni_txrate = 0;\n    IEEE80211_ADDR_COPY(ni->ni_macaddr, ic->ic_myaddr);\n    IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_myaddr);\n    if (ic->ic_opmode == IEEE80211_M_IBSS) {\n        if ((ic->ic_flags & IEEE80211_F_DESBSSID) != 0)\n            IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_des_bssid);\n        else\n            ni->ni_bssid[0] |= 0x02;\t/* local bit for IBSS */\n    }\n    ni->ni_esslen = ic->ic_des_esslen;\n    memcpy(ni->ni_essid, ic->ic_des_essid, ni->ni_esslen);\n    ni->ni_rssi = 0;\n    ni->ni_rstamp = 0;\n    memset(ni->ni_tstamp, 0, sizeof(ni->ni_tstamp));\n    ni->ni_intval = ic->ic_lintval;\n    ni->ni_capinfo = IEEE80211_CAPINFO_IBSS;\n    if (ic->ic_flags & IEEE80211_F_WEPON)\n        ni->ni_capinfo |= IEEE80211_CAPINFO_PRIVACY;\n    if (ic->ic_flags & IEEE80211_F_HTON) {\n        const struct ieee80211_edca_ac_params *ac_qap;\n        struct ieee80211_edca_ac_params *ac;\n        int aci;\n        \n        /*\n         * Configure HT protection. This will be updated later\n         * based on the number of non-HT nodes in the node cache.\n         */\n        ic->ic_protmode = IEEE80211_PROT_NONE;\n        ni->ni_htop1 = IEEE80211_HTPROT_NONE;\n        /* Disallow Greenfield mode. None of our drivers support it. */\n        ni->ni_htop1 |= IEEE80211_HTOP1_NONGF_STA;\n        if (ic->ic_updateprot)\n            ic->ic_updateprot(ic);\n        \n        /* Configure QoS EDCA parameters. */\n        for (aci = 0; aci < EDCA_NUM_AC; aci++) {\n            ac = &ic->ic_edca_ac[aci];\n            ac_qap = &ieee80211_qap_edca_table[ic->ic_curmode][aci];\n            ac->ac_acm       = ac_qap->ac_acm;\n            ac->ac_aifsn     = ac_qap->ac_aifsn;\n            ac->ac_ecwmin    = ac_qap->ac_ecwmin;\n            ac->ac_ecwmax    = ac_qap->ac_ecwmax;\n            ac->ac_txoplimit = ac_qap->ac_txoplimit;\n        }\n        if (ic->ic_updateedca)\n            (*ic->ic_updateedca)(ic);\n    }\n    if (ic->ic_flags & IEEE80211_F_RSNON) {\n        struct ieee80211_key *k;\n        \n        /* initialize 256-bit global key counter to a random value */\n        arc4random_buf(ic->ic_globalcnt, EAPOL_KEY_NONCE_LEN);\n        \n        ni->ni_rsnprotos = ic->ic_rsnprotos;\n        ni->ni_rsnakms = ic->ic_rsnakms;\n        ni->ni_rsnciphers = ic->ic_rsnciphers;\n        ni->ni_rsngroupcipher = ic->ic_rsngroupcipher;\n        ni->ni_rsngroupmgmtcipher = ic->ic_rsngroupmgmtcipher;\n        ni->ni_rsncaps = 0;\n        if (ic->ic_caps & IEEE80211_C_MFP) {\n            ni->ni_rsncaps |= IEEE80211_RSNCAP_MFPC;\n            if (ic->ic_flags & IEEE80211_F_MFPR)\n                ni->ni_rsncaps |= IEEE80211_RSNCAP_MFPR;\n        }\n        \n        ic->ic_def_txkey = 1;\n        ic->ic_flags &= ~IEEE80211_F_COUNTERM;\n        k = &ic->ic_nw_keys[ic->ic_def_txkey];\n        memset(k, 0, sizeof(*k));\n        k->k_id = ic->ic_def_txkey;\n        k->k_cipher = ni->ni_rsngroupcipher;\n        k->k_flags = IEEE80211_KEY_GROUP | IEEE80211_KEY_TX;\n        k->k_len = ieee80211_cipher_keylen(k->k_cipher);\n        arc4random_buf(k->k_key, k->k_len);\n        (*ic->ic_set_key)(ic, ni, k);\t/* XXX */\n        \n        if (ic->ic_caps & IEEE80211_C_MFP) {\n            ic->ic_igtk_kid = 4;\n            k = &ic->ic_nw_keys[ic->ic_igtk_kid];\n            memset(k, 0, sizeof(*k));\n            k->k_id = ic->ic_igtk_kid;\n            k->k_cipher = ni->ni_rsngroupmgmtcipher;\n            k->k_flags = IEEE80211_KEY_IGTK | IEEE80211_KEY_TX;\n            k->k_len = 16;\n            arc4random_buf(k->k_key, k->k_len);\n            (*ic->ic_set_key)(ic, ni, k);\t/* XXX */\n        }\n        /*\n         * In HostAP mode, multicast traffic is sent using ic_bss\n         * as the Tx node, so mark our node as valid so we can send\n         * multicast frames using the group key we've just configured.\n         */\n        ni->ni_port_valid = 1;\n        ni->ni_flags |= IEEE80211_NODE_TXPROT;\n        \n        /* schedule a GTK/IGTK rekeying after 3600s */\n        timeout_add_sec(&ic->ic_rsn_timeout, 3600);\n    }\n    timeout_add_sec(&ic->ic_inact_timeout, IEEE80211_INACT_WAIT);\n    timeout_add_sec(&ic->ic_node_cache_timeout, IEEE80211_CACHE_WAIT);\n    ieee80211_new_state(ic, IEEE80211_S_RUN, -1);\n}\n#endif\t/* IEEE80211_STA_ONLY */\n\nint\nieee80211_match_bss(struct ieee80211com *ic, struct ieee80211_node *ni,\n                    int bgscan)\n{\n    u_int8_t rate;\n    int fail;\n    \n    fail = 0;\n    if ((ic->ic_flags & IEEE80211_F_BGSCAN) == 0 &&\n        isclr(ic->ic_chan_active, ieee80211_chan2ieee(ic, ni->ni_chan)))\n        fail |= IEEE80211_NODE_ASSOCFAIL_CHAN;\n    if (ic->ic_des_chan != IEEE80211_CHAN_ANYC &&\n        ni->ni_chan != ic->ic_des_chan)\n        fail |= IEEE80211_NODE_ASSOCFAIL_CHAN;\n#ifndef IEEE80211_STA_ONLY\n    if (ic->ic_opmode == IEEE80211_M_IBSS) {\n        if ((ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) == 0)\n            fail |= IEEE80211_NODE_ASSOCFAIL_IBSS;\n    } else\n#endif\n    {\n        if ((ni->ni_capinfo & IEEE80211_CAPINFO_ESS) == 0)\n            fail |= IEEE80211_NODE_ASSOCFAIL_IBSS;\n    }\n    if (ic->ic_flags & (IEEE80211_F_WEPON | IEEE80211_F_RSNON)) {\n        if ((ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) == 0)\n            fail |= IEEE80211_NODE_ASSOCFAIL_PRIVACY;\n    } else {\n        if (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY)\n            fail |= IEEE80211_NODE_ASSOCFAIL_PRIVACY;\n    }\n    \n    rate = ieee80211_fix_rate(ic, ni, IEEE80211_F_DONEGO);\n    if (rate & IEEE80211_RATE_BASIC)\n        fail |= IEEE80211_NODE_ASSOCFAIL_BASIC_RATE;\n    if (ISSET(ic->ic_flags, IEEE80211_F_AUTO_JOIN) &&\n        ic->ic_des_esslen == 0)\n        fail |= IEEE80211_NODE_ASSOCFAIL_ESSID;\n    if (ic->ic_des_esslen != 0 &&\n        (ni->ni_esslen != ic->ic_des_esslen ||\n         memcmp(ni->ni_essid, ic->ic_des_essid, ic->ic_des_esslen) != 0))\n        fail |= IEEE80211_NODE_ASSOCFAIL_ESSID;\n    if ((ic->ic_flags & IEEE80211_F_DESBSSID) &&\n        !IEEE80211_ADDR_EQ(ic->ic_des_bssid, ni->ni_bssid))\n        fail |= IEEE80211_NODE_ASSOCFAIL_BSSID;\n    \n    if (ic->ic_flags & IEEE80211_F_RSNON) {\n        /*\n         * If at least one RSN IE field from the AP's RSN IE fails\n         * to overlap with any value the STA supports, the STA shall\n         * decline to associate with that AP.\n         */\n        if ((ni->ni_rsnprotos & ic->ic_rsnprotos) == 0)\n            fail |= IEEE80211_NODE_ASSOCFAIL_WPA_PROTO;\n        if ((ni->ni_rsnakms & ic->ic_rsnakms) == 0)\n            fail |= IEEE80211_NODE_ASSOCFAIL_WPA_PROTO;\n        if ((ni->ni_rsnakms & ic->ic_rsnakms &\n             ~(IEEE80211_AKM_PSK | IEEE80211_AKM_SHA256_PSK)) == 0) {\n            /* AP only supports PSK AKMPs */\n            if (!(ic->ic_flags & IEEE80211_F_PSK))\n                fail |= IEEE80211_NODE_ASSOCFAIL_WPA_PROTO;\n        }\n        if (ni->ni_rsngroupcipher != IEEE80211_CIPHER_WEP40 &&\n            ni->ni_rsngroupcipher != IEEE80211_CIPHER_TKIP &&\n            ni->ni_rsngroupcipher != IEEE80211_CIPHER_CCMP &&\n            ni->ni_rsngroupcipher != IEEE80211_CIPHER_WEP104)\n            fail |= IEEE80211_NODE_ASSOCFAIL_WPA_PROTO;\n        if ((ni->ni_rsnciphers & ic->ic_rsnciphers) == 0)\n            fail |= IEEE80211_NODE_ASSOCFAIL_WPA_PROTO;\n        \n        /* we only support BIP as the IGTK cipher */\n        if ((ni->ni_rsncaps & IEEE80211_RSNCAP_MFPC) &&\n            ni->ni_rsngroupmgmtcipher != IEEE80211_CIPHER_BIP)\n            fail |= IEEE80211_NODE_ASSOCFAIL_WPA_PROTO;\n        \n        /* we do not support MFP but AP requires it */\n        if (!(ic->ic_caps & IEEE80211_C_MFP) &&\n            (ni->ni_rsncaps & IEEE80211_RSNCAP_MFPR))\n            fail |= IEEE80211_NODE_ASSOCFAIL_WPA_PROTO;\n        \n        /* we require MFP but AP does not support it */\n        if ((ic->ic_caps & IEEE80211_C_MFP) &&\n            (ic->ic_flags & IEEE80211_F_MFPR) &&\n            !(ni->ni_rsncaps & IEEE80211_RSNCAP_MFPC))\n            fail |= IEEE80211_NODE_ASSOCFAIL_WPA_PROTO;\n    }\n    \n    if (ic->ic_if.if_flags & IFF_DEBUG && ieee80211_debug) {\n        XYLog(\"%s: %c %s%c %3d%c %+4d %2dM%c %4s%c %7s%c %3s%c %.*s %s\\n\",\n              ic->ic_if.if_xname,\n              fail ? '-' : '+',\n              ether_sprintf(ni->ni_bssid),\n              fail & IEEE80211_NODE_ASSOCFAIL_BSSID ? '!' : ' ',\n              \n              ieee80211_chan2ieee(ic, ni->ni_chan),\n              fail & IEEE80211_NODE_ASSOCFAIL_CHAN ? '!' : ' ',\n              \n              ni->ni_rssi,\n              \n              (rate & IEEE80211_RATE_VAL) / 2,\n              fail & IEEE80211_NODE_ASSOCFAIL_BASIC_RATE ? '!' : ' ',\n              \n              (ni->ni_capinfo & IEEE80211_CAPINFO_ESS) ? \"ess\" :\n              (ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) ? \"ibss\" :\n              \"????\",\n              fail & IEEE80211_NODE_ASSOCFAIL_IBSS ? '!' : ' ',\n              \n              (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) ?\n              \"privacy\" : \"no\",\n              fail & IEEE80211_NODE_ASSOCFAIL_PRIVACY ? '!' : ' ',\n              \n              (ic->ic_flags & IEEE80211_F_RSNON) ?\n              \"rsn\" : \"no\",\n              fail & IEEE80211_NODE_ASSOCFAIL_WPA_PROTO ? '!' : ' ',\n              \n              ni->ni_esslen + 1,\n              ni->ni_essid,\n              fail & IEEE80211_NODE_ASSOCFAIL_ESSID ? \"!\" : \"\");\n    }\n    \n    /* We don't care about unrelated networks during background scans. */\n    if (bgscan) {\n        if ((fail & IEEE80211_NODE_ASSOCFAIL_ESSID) == 0)\n            ni->ni_assoc_fail = fail;\n    } else\n        ni->ni_assoc_fail = fail;\n    if ((fail & IEEE80211_NODE_ASSOCFAIL_ESSID) == 0)\n        ic->ic_bss->ni_assoc_fail = ni->ni_assoc_fail;\n    \n    return fail;\n}\n\nstruct ieee80211_node_switch_bss_arg {\n    u_int8_t cur_macaddr[IEEE80211_ADDR_LEN];\n    u_int8_t sel_macaddr[IEEE80211_ADDR_LEN];\n};\n\n/* Implements ni->ni_unref_cb(). */\nvoid\nieee80211_node_switch_bss(struct ieee80211com *ic, struct ieee80211_node *ni)\n{\n    struct _ifnet *ifp = &ic->ic_if;\n    struct ieee80211_node_switch_bss_arg *sba = (struct ieee80211_node_switch_bss_arg *)ni->ni_unref_arg;\n    struct ieee80211_node *curbs, *selbs;\n    \n    splassert(IPL_NET);\n    \n    if ((ic->ic_flags & IEEE80211_F_BGSCAN) == 0) {\n        free(sba);\n        return;\n    }\n    \n    ic->ic_xflags &= ~IEEE80211_F_TX_MGMT_ONLY;\n    \n    selbs = ieee80211_find_node(ic, sba->sel_macaddr);\n    if (selbs == NULL) {\n        free(sba);\n        ic->ic_flags &= ~IEEE80211_F_BGSCAN;\n        ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);\n        return;\n    }\n    \n    curbs = ieee80211_find_node(ic, sba->cur_macaddr);\n    if (curbs == NULL) {\n        free(sba);\n        ic->ic_flags &= ~IEEE80211_F_BGSCAN;\n        ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);\n        return;\n    }\n    \n    if (ifp->if_flags & IFF_DEBUG) {\n        XYLog(\"%s: roaming from %s chan %d \",\n              ifp->if_xname, ether_sprintf(curbs->ni_macaddr),\n              ieee80211_chan2ieee(ic, curbs->ni_chan));\n        XYLog(\"to %s chan %d\\n\", ether_sprintf(selbs->ni_macaddr),\n              ieee80211_chan2ieee(ic, selbs->ni_chan));\n    }\n    ieee80211_node_newstate(curbs, IEEE80211_STA_CACHE);\n    ieee80211_node_join_bss(ic, selbs); /* frees arg and ic->ic_bss */\n}\n\nvoid\nieee80211_node_join_bss(struct ieee80211com *ic, struct ieee80211_node *selbs, int force_reauth)\n{\n    XYLog(\"%s selbs=%s mac=%s chan=%d rssi=%d protos=%d akms=%d ciphers=%d\\n\", __FUNCTION__, selbs->ni_essid, ether_sprintf(selbs->ni_bssid), ieee80211_chan2ieee(ic, selbs->ni_chan), selbs->ni_rssi, selbs->ni_rsnprotos, selbs->ni_rsnakms, selbs->ni_rsnciphers);\n    enum ieee80211_phymode mode;\n    struct ieee80211_node *ni;\n    uint32_t assoc_fail = 0;\n    \n    /* Reinitialize media mode and channels if needed. */\n    mode = ieee80211_chan2mode(ic, selbs->ni_chan);\n    if (mode != ic->ic_curmode)\n        ieee80211_setmode(ic, mode);\n    \n    /* Keep recorded association failures for this BSS/ESS intact. */\n    if (IEEE80211_ADDR_EQ(ic->ic_bss->ni_macaddr, selbs->ni_macaddr) ||\n        (ic->ic_des_esslen > 0 && ic->ic_des_esslen == selbs->ni_esslen &&\n         memcmp(ic->ic_des_essid, selbs->ni_essid, selbs->ni_esslen) == 0))\n        assoc_fail = ic->ic_bss->ni_assoc_fail;\n    \n    (*ic->ic_node_copy)(ic, ic->ic_bss, selbs);\n    ni = ic->ic_bss;\n    ni->ni_assoc_fail |= assoc_fail;\n    \n    ic->ic_curmode = ieee80211_chan2mode(ic, ni->ni_chan);\n    \n    /* Make sure we send valid rates in an association request. */\n    if (ic->ic_opmode == IEEE80211_M_STA)\n        ieee80211_fix_rate(ic, ni,\n                           IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE |\n                           IEEE80211_F_DONEGO | IEEE80211_F_DODEL);\n    \n    if (ic->ic_flags & IEEE80211_F_RSNON)\n        ieee80211_choose_rsnparams(ic);\n    else if (ic->ic_flags & IEEE80211_F_WEPON)\n        ni->ni_rsncipher = IEEE80211_CIPHER_USEGROUP;\n    \n    ieee80211_node_newstate(selbs, IEEE80211_STA_BSS);\n#ifndef IEEE80211_STA_ONLY\n    if (ic->ic_opmode == IEEE80211_M_IBSS) {\n        ieee80211_fix_rate(ic, ni, IEEE80211_F_DOFRATE |\n                           IEEE80211_F_DONEGO | IEEE80211_F_DODEL);\n        if (ni->ni_rates.rs_nrates == 0) {\n            ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);\n            return;\n        }\n        ieee80211_new_state(ic, IEEE80211_S_RUN, -1);\n    } else\n#endif\n    {\n        int bgscan = ((ic->ic_flags & IEEE80211_F_BGSCAN) &&\n                      ic->ic_opmode == IEEE80211_M_STA &&\n                      ic->ic_state == IEEE80211_S_RUN);\n        int roamscan = bgscan &&\n                    (ic->ic_flags & IEEE80211_F_DISABLE_BG_AUTO_CONNECT) == 0;\n        int auth_next = (ic->ic_opmode == IEEE80211_M_STA &&\n                         ic->ic_state == IEEE80211_S_AUTH);\n        int mgt = -1;\n        \n        XYLog(\"%s ic_state=%d\\n\", __FUNCTION__, ic->ic_state);\n        \n        timeout_del(&ic->ic_bgscan_timeout);\n        ic->ic_flags &= ~IEEE80211_F_BGSCAN;\n        \n        if (!force_reauth) {\n            /*\n             * After a background scan, we have now switched APs.\n             * Pretend we were just de-authed, which makes\n             * ieee80211_new_state() try to re-auth and thus send\n             * an AUTH frame to our newly selected AP.\n             */\n            if (roamscan)\n                mgt = IEEE80211_FC0_SUBTYPE_DEAUTH;\n            /*\n             * If we are trying another AP after the previous one\n             * failed (state transition AUTH->AUTH), ensure that\n             * ieee80211_new_state() tries to send another auth frame.\n             */\n            else if (auth_next)\n                mgt = IEEE80211_FC0_SUBTYPE_AUTH;\n        } else {\n            mgt = IEEE80211_FC0_SUBTYPE_DEAUTH;\n        }\n        \n        ieee80211_new_state(ic, IEEE80211_S_AUTH, mgt);\n    }\n}\n\nstruct ieee80211_node *\nieee80211_node_choose_bss(struct ieee80211com *ic, int bgscan,\n                          struct ieee80211_node **curbs)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct ieee80211_node *ni, *nextbs, *selbs = NULL,\n    *selbs2 = NULL, *selbs5 = NULL;\n    uint8_t min_5ghz_rssi;\n    \n    ni = RB_MIN(ieee80211_tree, &ic->ic_tree);\n    \n    for (; ni != NULL; ni = nextbs) {\n        nextbs = RB_NEXT(ieee80211_tree, &ic->ic_tree, ni);\n        if (ni->ni_fails) {\n            /*\n             * The configuration of the access points may change\n             * during my scan.  So delete the entry for the AP\n             * and retry to associate if there is another beacon.\n             */\n            if (ni->ni_fails++ > 2)\n                ieee80211_free_node(ic, ni);\n            DPRINTF((\"%s %s ni->ni_fails=%d\\n\", __FUNCTION__, ni->ni_essid, ni->ni_fails));\n            continue;\n        }\n        \n        if (curbs && ieee80211_node_cmp(ic->ic_bss, ni) == 0)\n            *curbs = ni;\n        \n        int fail = ieee80211_match_bss(ic, ni, bgscan);\n        if (fail != 0) {\n            DPRINTF((\"%s ieee80211_match_bss==FALSE, ssid=%s, bssid=%s, %d\\n\", __FUNCTION__, ni->ni_essid, ether_sprintf(ni->ni_bssid), fail));\n            continue;\n        }\n        \n        if (ic->ic_caps & IEEE80211_C_SCANALLBAND) {\n            if (IEEE80211_IS_CHAN_2GHZ(ni->ni_chan) &&\n                (selbs2 == NULL || ni->ni_rssi > selbs2->ni_rssi))\n                selbs2 = ni;\n            else if (IEEE80211_IS_CHAN_5GHZ(ni->ni_chan) &&\n                     (selbs5 == NULL || ni->ni_rssi > selbs5->ni_rssi))\n                selbs5 = ni;\n        } else if (selbs == NULL || ni->ni_rssi > selbs->ni_rssi)\n            selbs = ni;\n    }\n    \n    if (ic->ic_max_rssi)\n        min_5ghz_rssi = IEEE80211_RSSI_THRES_RATIO_5GHZ;\n    else\n        min_5ghz_rssi = (uint8_t)IEEE80211_RSSI_THRES_5GHZ;\n    \n    /*\n     * Prefer a 5Ghz AP even if its RSSI is weaker than the best 2Ghz AP\n     * (as long as it meets the minimum RSSI threshold) since the 5Ghz band\n     * is usually less saturated.\n     */\n    if (selbs5 != NULL) {\n        XYLog(\"%s 5ghz ssid=%s mac=%s rssi=%d\\n\", __FUNCTION__, selbs5->ni_essid, ether_sprintf(selbs5->ni_bssid), selbs5->ni_rssi);\n    }\n    if (selbs2 != NULL) {\n        XYLog(\"%s 2ghz ssid=%s mac=%s rssi=%d\\n\", __FUNCTION__, selbs2->ni_essid, ether_sprintf(selbs2->ni_bssid), selbs2->ni_rssi);\n    }\n    if (selbs5 && (*ic->ic_node_checkrssi)(ic, selbs5))\n        selbs = selbs5;\n    else if (selbs5 && selbs2)\n        selbs = (selbs5->ni_rssi >= selbs2->ni_rssi ? selbs5 : selbs2);\n    else if (selbs2)\n        selbs = selbs2;\n    else if (selbs5)\n        selbs = selbs5;\n    \n    return selbs;\n}\n\n/*\n * Complete a scan of potential channels.\n */\nvoid\nieee80211_end_scan(struct _ifnet *ifp)\n{\n    struct ieee80211com *ic = (struct ieee80211com *)ifp;\n    struct ieee80211_node *ni, *selbs = NULL, *curbs = NULL;\n    int bgscan = ((ic->ic_flags & IEEE80211_F_BGSCAN) &&\n                  ic->ic_opmode == IEEE80211_M_STA &&\n                  ic->ic_state == IEEE80211_S_RUN);\n    int roamscan = bgscan &&\n                (ic->ic_flags & IEEE80211_F_DISABLE_BG_AUTO_CONNECT) == 0;\n    \n    if (ic->ic_event_handler)\n        (*ic->ic_event_handler)(ic, IEEE80211_EVT_SCAN_DONE, NULL);\n    \n    if (ifp->if_flags & IFF_DEBUG)\n        XYLog(\"%s: end %s scan\\n\", ifp->if_xname,\n              bgscan ? (roamscan ? \"roam\" : \"background\") :\n              ((ic->ic_flags & IEEE80211_F_ASCAN) ?\n               \"active\" : \"passive\"));\n    \n    if (ic->ic_scan_count)\n        ic->ic_flags &= ~IEEE80211_F_ASCAN;\n    \n    if (ic->ic_opmode == IEEE80211_M_STA)\n        ieee80211_clean_inactive_nodes(ic, IEEE80211_INACT_SCAN);\n    \n    ni = RB_MIN(ieee80211_tree, &ic->ic_tree);\n    \n#ifndef IEEE80211_STA_ONLY\n    if (ic->ic_opmode == IEEE80211_M_HOSTAP) {\n        /* XXX off stack? */\n        u_char occupied[howmany(IEEE80211_CHAN_MAX, NBBY)];\n        int i, fail;\n        \n        /*\n         * The passive scan to look for existing AP's completed,\n         * select a channel to camp on.  Identify the channels\n         * that already have one or more AP's and try to locate\n         * an unoccupied one.  If that fails, pick a random\n         * channel from the active set.\n         */\n        memset(occupied, 0, sizeof(occupied));\n        RB_FOREACH(ni, ieee80211_tree, &ic->ic_tree)\n        setbit(occupied, ieee80211_chan2ieee(ic, ni->ni_chan));\n        for (i = 0; i < IEEE80211_CHAN_MAX; i++)\n            if (isset(ic->ic_chan_active, i) && isclr(occupied, i))\n                break;\n        if (i == IEEE80211_CHAN_MAX) {\n            fail = arc4random() & 3;\t/* random 0-3 */\n            for (i = 0; i < IEEE80211_CHAN_MAX; i++)\n                if (isset(ic->ic_chan_active, i) && fail-- == 0)\n                    break;\n        }\n        ieee80211_create_ibss(ic, &ic->ic_channels[i]);\n        return;\n    }\n#endif\n    if (ni == NULL) {\n        DPRINTF((\"no scan candidate\\n\"));\n    notfound:\n        \n#ifndef IEEE80211_STA_ONLY\n        if (ic->ic_opmode == IEEE80211_M_IBSS &&\n            (ic->ic_flags & IEEE80211_F_IBSSON) &&\n            ic->ic_des_esslen != 0) {\n            ieee80211_create_ibss(ic, ic->ic_ibss_chan);\n            return;\n        }\n#endif\n        if (ic->ic_state != IEEE80211_S_RUN) {\n            /*\n             * Reset the list of channels to scan and scan the next mode\n             * if nothing has been found.\n             * If the device scans all bands in one fell swoop, return\n             * current scan results to userspace regardless of mode.\n             * This will loop forever until an access point is found.\n             */\n            ieee80211_reset_scan(ifp);\n            if (ieee80211_next_mode(ifp) == IEEE80211_MODE_AUTO ||\n                (ic->ic_caps & IEEE80211_C_SCANALLBAND))\n                ic->ic_scan_count++;\n            \n            ieee80211_next_scan(ifp);\n        }\n        return;\n    }\n    \n    /* Possibly switch which ssid we are associated with */\n    if (!bgscan && ic->ic_opmode == IEEE80211_M_STA)\n        ieee80211_switch_ess(ic);\n    \n    selbs = ieee80211_node_choose_bss(ic, bgscan, &curbs);\n    if (bgscan) {\n        struct ieee80211_node_switch_bss_arg *arg;\n        \n        ic->ic_flags &= ~IEEE80211_F_DISABLE_BG_AUTO_CONNECT;\n        if (!roamscan) {\n            ic->ic_flags &= ~IEEE80211_F_BGSCAN;\n            return;\n        }\n        \n        /* AP disappeared? Should not happen. */\n        if (selbs == NULL || curbs == NULL) {\n            ic->ic_flags &= ~IEEE80211_F_BGSCAN;\n            XYLog(\"%s %d AP disappeared? Should not happen.\\n\", __FUNCTION__, __LINE__);\n            goto notfound;\n        }\n        \n        /*\n         * After a background scan we might end up choosing the\n         * same AP again. Do not change ic->ic_bss in this case,\n         * and make background scans less frequent.\n         */\n        if (selbs == curbs) {\n            if (ic->ic_bgscan_fail < IEEE80211_BGSCAN_FAIL_MAX)\n                ic->ic_bgscan_fail++;\n            ic->ic_flags &= ~IEEE80211_F_BGSCAN;\n            /*\n              * HT is negotiated during association so we must use\n              * ic_bss to check HT. The nodes tree was re-populated\n              * during background scan and therefore selbs and curbs\n              * may not carry HT information.\n              */\n             ni = ic->ic_bss;\n             if (ni->ni_flags & IEEE80211_NODE_HE)\n                 ieee80211_setmode(ic, IEEE80211_MODE_11AX);\n             else if (ni->ni_flags & IEEE80211_NODE_VHT)\n                ieee80211_setmode(ic, IEEE80211_MODE_11AC);\n             else if (ni->ni_flags & IEEE80211_NODE_HT)\n                 ieee80211_setmode(ic, IEEE80211_MODE_11N);\n             else\n                 ieee80211_setmode(ic,\n                     ieee80211_chan2mode(ic, ni->ni_chan));\n            return;\n        }\n        \n        arg = (struct ieee80211_node_switch_bss_arg *)malloc(sizeof(*arg), 0, 0);\n        if (arg == NULL) {\n            ic->ic_flags &= ~IEEE80211_F_BGSCAN;\n            return;\n        }\n        \n        ic->ic_bgscan_fail = 0;\n        \n        /*\n         * We are going to switch APs. Stop A-MPDU Tx and\n         * queue a de-auth frame addressed to our current AP.\n         */\n        ieee80211_stop_ampdu_tx(ic, ic->ic_bss,\n                                IEEE80211_FC0_SUBTYPE_DEAUTH);\n        if (IEEE80211_SEND_MGMT(ic, ic->ic_bss,\n                                IEEE80211_FC0_SUBTYPE_DEAUTH,\n                                IEEE80211_REASON_AUTH_LEAVE) != 0) {\n            ic->ic_flags &= ~IEEE80211_F_BGSCAN;\n            free(arg);\n            return;\n        }\n        \n        /* Prevent dispatch of additional data frames to hardware. */\n        ic->ic_xflags |= IEEE80211_F_TX_MGMT_ONLY;\n        \n        /*\n         * Install a callback which will switch us to the new AP once\n         * all dispatched frames have been processed by hardware.\n         */\n        IEEE80211_ADDR_COPY(arg->cur_macaddr, curbs->ni_macaddr);\n        IEEE80211_ADDR_COPY(arg->sel_macaddr, selbs->ni_macaddr);\n        ic->ic_bss->ni_unref_arg = arg;\n        ic->ic_bss->ni_unref_arg_size = sizeof(*arg);\n        ic->ic_bss->ni_unref_cb = ieee80211_node_switch_bss;\n        /* F_BGSCAN flag gets cleared in ieee80211_node_join_bss(). */\n        return;\n    } else if (selbs == NULL)\n        goto notfound;\n    \n    ieee80211_node_join_bss(ic, selbs);\n}\n\n/*\n * Autoselect the best RSN parameters (protocol, AKMP, pairwise cipher...)\n * that are supported by both peers (STA mode only).\n */\nvoid\nieee80211_choose_rsnparams(struct ieee80211com *ic)\n{\n    struct ieee80211_node *ni = ic->ic_bss;\n    struct ieee80211_pmk *pmk;\n    \n    /* filter out unsupported protocol versions */\n    ni->ni_rsnprotos &= ic->ic_rsnprotos;\n    /* prefer RSN (aka WPA2) over WPA */\n    if (ni->ni_rsnprotos & IEEE80211_PROTO_RSN)\n        ni->ni_rsnprotos = IEEE80211_PROTO_RSN;\n    else\n        ni->ni_rsnprotos = IEEE80211_PROTO_WPA;\n    \n    /* filter out unsupported AKMPs */\n    ni->ni_rsnakms &= ic->ic_rsnakms;\n    /* prefer SHA-256 based AKMPs */\n    if ((ic->ic_flags & IEEE80211_F_PSK) && (ni->ni_rsnakms &\n                                             (IEEE80211_AKM_PSK | IEEE80211_AKM_SHA256_PSK))) {\n        /* AP supports PSK AKMP and a PSK is configured */\n        if (ni->ni_rsnakms & IEEE80211_AKM_SHA256_PSK)\n            ni->ni_rsnakms = IEEE80211_AKM_SHA256_PSK;\n        else\n            ni->ni_rsnakms = IEEE80211_AKM_PSK;\n    } else {\n        if (ni->ni_rsnakms & IEEE80211_AKM_SHA256_8021X)\n            ni->ni_rsnakms = IEEE80211_AKM_SHA256_8021X;\n        else\n            ni->ni_rsnakms = IEEE80211_AKM_8021X;\n        /* check if we have a cached PMK for this AP */\n        if (ni->ni_rsnprotos == IEEE80211_PROTO_RSN &&\n            (pmk = ieee80211_pmksa_find(ic, ni, NULL)) != NULL) {\n            memcpy(ni->ni_pmkid, pmk->pmk_pmkid,\n                   IEEE80211_PMKID_LEN);\n            ni->ni_flags |= IEEE80211_NODE_PMKID;\n        }\n    }\n    \n    /* filter out unsupported pairwise ciphers */\n    ni->ni_rsnciphers &= ic->ic_rsnciphers;\n    /* prefer CCMP over TKIP */\n    if (ni->ni_rsnciphers & IEEE80211_CIPHER_CCMP)\n        ni->ni_rsnciphers = IEEE80211_CIPHER_CCMP;\n    else\n        ni->ni_rsnciphers = IEEE80211_CIPHER_TKIP;\n    ni->ni_rsncipher = (enum ieee80211_cipher)ni->ni_rsnciphers;\n    \n    /* use MFP if we both support it */\n    if ((ic->ic_caps & IEEE80211_C_MFP) &&\n        (ni->ni_rsncaps & IEEE80211_RSNCAP_MFPC))\n        ni->ni_flags |= IEEE80211_NODE_MFP;\n}\n\nint\nieee80211_get_rate(struct ieee80211com *ic)\n{\n    u_int8_t (*rates)[IEEE80211_RATE_MAXSIZE];\n    int rate;\n    \n    rates = &ic->ic_bss->ni_rates.rs_rates;\n    \n    if (ic->ic_fixed_rate != -1)\n        rate = (*rates)[ic->ic_fixed_rate];\n    else if (ic->ic_state == IEEE80211_S_RUN)\n        rate = (*rates)[ic->ic_bss->ni_txrate];\n    else\n        rate = 0;\n    \n    return rate & IEEE80211_RATE_VAL;\n}\n\nstruct ieee80211_node *\nieee80211_node_alloc(struct ieee80211com *ic)\n{\n    return (struct ieee80211_node *)malloc(sizeof(struct ieee80211_node), 0, 0);\n}\n\nvoid\nieee80211_node_cleanup(struct ieee80211com *ic, struct ieee80211_node *ni)\n{\n    if (ni == NULL) {\n        return;\n    }\n    if (ni->ni_rsnie != NULL) {\n        free(ni->ni_rsnie);\n        ni->ni_rsnie = NULL;\n    }\n    if (ni->ni_rsnie_tlv != NULL && ni->ni_rsnie_tlv_len > 0) {\n        free(ni->ni_rsnie_tlv);\n        ni->ni_rsnie_tlv = NULL;\n        ni->ni_rsnie_tlv_len = 0;\n    }\n    ieee80211_ba_del(ni);\n    ieee80211_ba_free(ni);\n    if (ni->ni_unref_arg != NULL) {\n        free(ni->ni_unref_arg);\n        ni->ni_unref_arg = NULL;\n        ni->ni_unref_arg_size = 0;\n    }\n    \n#ifndef IEEE80211_STA_ONLY\n    mq_purge(&ni->ni_savedq);\n#endif\n}\n\nvoid\nieee80211_node_free(struct ieee80211com *ic, struct ieee80211_node *ni)\n{\n    ieee80211_node_cleanup(ic, ni);\n    free(ni);\n}\n\nvoid\nieee80211_node_copy(struct ieee80211com *ic,\n                    struct ieee80211_node *dst, const struct ieee80211_node *src)\n{\n    ieee80211_node_cleanup(ic, dst);\n    *dst = *src;\n    dst->ni_rsnie = NULL;\n    if (src->ni_rsnie != NULL)\n        ieee80211_save_ie(src->ni_rsnie, &dst->ni_rsnie);\n    dst->ni_rsnie_tlv = NULL;\n    dst->ni_rsnie_tlv_len = 0;\n    if (src->ni_rsnie_tlv != NULL) {\n        ieee80211_save_ie_tlv(src->ni_rsnie_tlv, &dst->ni_rsnie_tlv, &dst->ni_rsnie_tlv_len, src->ni_rsnie_tlv_len);\n    }\n    ieee80211_node_set_timeouts(dst);\n#ifndef IEEE80211_STA_ONLY\n    mq_init(&dst->ni_savedq, IEEE80211_PS_MAX_QUEUE, IPL_NET);\n#endif\n}\n\nu_int8_t\nieee80211_node_getrssi(struct ieee80211com *ic,\n                       const struct ieee80211_node *ni)\n{\n    return ni->ni_rssi;\n}\n\nint\nieee80211_node_checkrssi(struct ieee80211com *ic,\n                         const struct ieee80211_node *ni)\n{\n    uint8_t thres;\n    \n    if (ni->ni_chan == IEEE80211_CHAN_ANYC)\n        return 0;\n    \n    if (ic->ic_max_rssi) {\n        thres = (IEEE80211_IS_CHAN_2GHZ(ni->ni_chan)) ?\n        IEEE80211_RSSI_THRES_RATIO_2GHZ :\n        IEEE80211_RSSI_THRES_RATIO_5GHZ;\n        return ((ni->ni_rssi * 100) / ic->ic_max_rssi >= thres);\n    }\n    \n    thres = (IEEE80211_IS_CHAN_2GHZ(ni->ni_chan)) ?\n    IEEE80211_RSSI_THRES_2GHZ :\n    IEEE80211_RSSI_THRES_5GHZ;\n    return (ni->ni_rssi >= (u_int8_t)thres);\n}\n\nvoid\nieee80211_node_set_timeouts(struct ieee80211_node *ni)\n{\n    int i;\n    \n    memset(ni->ni_addba_req_to, 0, sizeof(ni->ni_addba_req_to) * nitems(ni->ni_addba_req_to));\n#ifndef IEEE80211_STA_ONLY\n    timeout_set(&ni->ni_eapol_to, ieee80211_eapol_timeout, ni);\n    timeout_set(&ni->ni_sa_query_to, ieee80211_sa_query_timeout, ni);\n#endif\n    timeout_set(&ni->ni_addba_req_to[EDCA_AC_BE],\n                ieee80211_node_addba_request_ac_be_to, ni);\n    timeout_set(&ni->ni_addba_req_to[EDCA_AC_BK],\n                ieee80211_node_addba_request_ac_bk_to, ni);\n    timeout_set(&ni->ni_addba_req_to[EDCA_AC_VI],\n                ieee80211_node_addba_request_ac_vi_to, ni);\n    timeout_set(&ni->ni_addba_req_to[EDCA_AC_VO],\n                ieee80211_node_addba_request_ac_vo_to, ni);\n    for (i = 0; i < nitems(ni->ni_addba_req_intval); i++)\n        ni->ni_addba_req_intval[i] = 1;\n}\n\nvoid\nieee80211_setup_node(struct ieee80211com *ic,\n                     struct ieee80211_node *ni, const u_int8_t *macaddr)\n{\n    int i, s;\n    \n    DPRINTF((\"%s %s\\n\", __FUNCTION__, ether_sprintf((u_int8_t *)macaddr)));\n    IEEE80211_ADDR_COPY(ni->ni_macaddr, macaddr);\n    ieee80211_node_newstate(ni, IEEE80211_STA_CACHE);\n    \n    ni->ni_ic = ic;\t/* back-pointer */\n    /* Initialize cached last sequence numbers with invalid values. */\n    ni->ni_rxseq = 0xffffU;\n    for (i=0; i < IEEE80211_NUM_TID; ++i)\n        ni->ni_qos_rxseqs[i] = 0xffffU;\n#ifndef IEEE80211_STA_ONLY\n    mq_init(&ni->ni_savedq, IEEE80211_PS_MAX_QUEUE, IPL_NET);\n#endif\n    ieee80211_node_set_timeouts(ni);\n    \n    s = splnet();\n    RB_INSERT(ieee80211_tree, &ic->ic_tree, ni);\n    ic->ic_nnodes++;\n    splx(s);\n}\n\nstruct ieee80211_node *\nieee80211_alloc_node(struct ieee80211com *ic, const u_int8_t *macaddr)\n{\n    struct ieee80211_node *ni = ieee80211_alloc_node_helper(ic);\n    if (ni != NULL)\n        ieee80211_setup_node(ic, ni, macaddr);\n    else\n        ic->ic_stats.is_rx_nodealloc++;\n    return ni;\n}\n\nstruct ieee80211_node *\nieee80211_dup_bss(struct ieee80211com *ic, const u_int8_t *macaddr)\n{\n    XYLog(\"%s %d\\n\", __FUNCTION__, __LINE__);\n    struct ieee80211_node *ni = ieee80211_alloc_node_helper(ic);\n    if (ni != NULL) {\n        ieee80211_setup_node(ic, ni, macaddr);\n        /*\n         * Inherit from ic_bss.\n         */\n        IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_bss->ni_bssid);\n        ni->ni_chan = ic->ic_bss->ni_chan;\n    } else\n        ic->ic_stats.is_rx_nodealloc++;\n    return ni;\n}\n\nstruct ieee80211_node *\nieee80211_find_node(struct ieee80211com *ic, const u_int8_t *macaddr)\n{\n    struct ieee80211_node *ni;\n    int cmp;\n    \n    /* similar to RBT_FIND except we compare keys, not nodes */\n    ni = RB_ROOT(&ic->ic_tree);\n    while (ni != NULL) {\n        cmp = memcmp(macaddr, ni->ni_macaddr, IEEE80211_ADDR_LEN);\n        if (cmp < 0)\n            ni = RB_LEFT(ni, ni_node);\n        else if (cmp > 0)\n            ni = RB_RIGHT(ni, ni_node);\n        else\n            break;\n    }\n    return ni;\n}\n\n/*\n * Return a reference to the appropriate node for sending\n * a data frame.  This handles node discovery in adhoc networks.\n *\n * Drivers will call this, so increase the reference count before\n * returning the node.\n */\nstruct ieee80211_node *\nieee80211_find_txnode(struct ieee80211com *ic, const u_int8_t *macaddr)\n{\n#ifndef IEEE80211_STA_ONLY\n    struct ieee80211_node *ni;\n    int s;\n#endif\n    \n    /*\n     * The destination address should be in the node table\n     * unless we are operating in station mode or this is a\n     * multicast/broadcast frame.\n     */\n    if (ic->ic_opmode == IEEE80211_M_STA || IEEE80211_IS_MULTICAST(macaddr))\n        return ieee80211_ref_node(ic->ic_bss);\n    \n#ifndef IEEE80211_STA_ONLY\n    s = splnet();\n    ni = ieee80211_find_node(ic, macaddr);\n    splx(s);\n    if (ni == NULL) {\n        if (ic->ic_opmode != IEEE80211_M_IBSS &&\n            ic->ic_opmode != IEEE80211_M_AHDEMO)\n            return NULL;\n        \n        /*\n         * Fake up a node; this handles node discovery in\n         * adhoc mode.  Note that for the driver's benefit\n         * we we treat this like an association so the driver\n         * has an opportunity to setup its private state.\n         *\n         * XXX need better way to handle this; issue probe\n         *     request so we can deduce rate set, etc.\n         */\n        if ((ni = ieee80211_dup_bss(ic, macaddr)) == NULL)\n            return NULL;\n        /* XXX no rate negotiation; just dup */\n        ni->ni_rates = ic->ic_bss->ni_rates;\n        ni->ni_txrate = 0;\n        if (ic->ic_newassoc)\n            (*ic->ic_newassoc)(ic, ni, 1);\n    }\n    return ieee80211_ref_node(ni);\n#else\n    return NULL;\t/* can't get there */\n#endif\t/* IEEE80211_STA_ONLY */\n}\n\n/*\n * It is usually desirable to process a Rx packet using its sender's\n * node-record instead of the BSS record.\n *\n * - AP mode: keep a node-record for every authenticated/associated\n *   station *in the BSS*. For future use, we also track neighboring\n *   APs, since they might belong to the same ESS.  APs in the same\n *   ESS may bridge packets to each other, forming a Wireless\n *   Distribution System (WDS).\n *\n * - IBSS mode: keep a node-record for every station *in the BSS*.\n *   Also track neighboring stations by their beacons/probe responses.\n *\n * - monitor mode: keep a node-record for every sender, regardless\n *   of BSS.\n *\n * - STA mode: the only available node-record is the BSS record,\n *   ic->ic_bss.\n *\n * Of all the 802.11 Control packets, only the node-records for\n * RTS packets node-record can be looked up.\n *\n * Return non-zero if the packet's node-record is kept, zero\n * otherwise.\n */\nstatic __inline int\nieee80211_needs_rxnode(struct ieee80211com *ic,\n                       const struct ieee80211_frame *wh, const u_int8_t **bssid)\n{\n    int monitor, rc = 0;\n    \n    monitor = (ic->ic_opmode == IEEE80211_M_MONITOR);\n    \n    *bssid = NULL;\n    \n    switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {\n        case IEEE80211_FC0_TYPE_CTL:\n            if (!monitor)\n                break;\n            return (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==\n            IEEE80211_FC0_SUBTYPE_RTS;\n        case IEEE80211_FC0_TYPE_MGT:\n            *bssid = wh->i_addr3;\n            switch (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) {\n                case IEEE80211_FC0_SUBTYPE_BEACON:\n                case IEEE80211_FC0_SUBTYPE_PROBE_RESP:\n                    break;\n                default:\n#ifndef IEEE80211_STA_ONLY\n                    if (ic->ic_opmode == IEEE80211_M_STA)\n                        break;\n                    rc = IEEE80211_ADDR_EQ(*bssid, ic->ic_bss->ni_bssid) ||\n                    IEEE80211_ADDR_EQ(*bssid, etherbroadcastaddr);\n#endif\n                    break;\n            }\n            break;\n        case IEEE80211_FC0_TYPE_DATA:\n            switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) {\n                case IEEE80211_FC1_DIR_NODS:\n                    *bssid = wh->i_addr3;\n#ifndef IEEE80211_STA_ONLY\n                    if (ic->ic_opmode == IEEE80211_M_IBSS ||\n                        ic->ic_opmode == IEEE80211_M_AHDEMO)\n                        rc = IEEE80211_ADDR_EQ(*bssid,\n                                               ic->ic_bss->ni_bssid);\n#endif\n                    break;\n                case IEEE80211_FC1_DIR_TODS:\n                    *bssid = wh->i_addr1;\n#ifndef IEEE80211_STA_ONLY\n                    if (ic->ic_opmode == IEEE80211_M_HOSTAP)\n                        rc = IEEE80211_ADDR_EQ(*bssid,\n                                               ic->ic_bss->ni_bssid);\n#endif\n                    break;\n                case IEEE80211_FC1_DIR_FROMDS:\n                case IEEE80211_FC1_DIR_DSTODS:\n                    *bssid = wh->i_addr2;\n#ifndef IEEE80211_STA_ONLY\n                    rc = (ic->ic_opmode == IEEE80211_M_HOSTAP);\n#endif\n                    break;\n            }\n            break;\n    }\n    return monitor || rc;\n}\n\n/* \n * Drivers call this, so increase the reference count before returning\n * the node.\n */\nstruct ieee80211_node *\nieee80211_find_rxnode(struct ieee80211com *ic,\n                      const struct ieee80211_frame *wh)\n{\n    static const u_int8_t zero[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };\n    struct ieee80211_node *ni;\n    const u_int8_t *bssid;\n    int s;\n    \n    if (!ieee80211_needs_rxnode(ic, wh, &bssid))\n        return ieee80211_ref_node(ic->ic_bss);\n    \n    s = splnet();\n    ni = ieee80211_find_node(ic, wh->i_addr2);\n    splx(s);\n    \n    if (ni != NULL)\n        return ieee80211_ref_node(ni);\n#ifndef IEEE80211_STA_ONLY\n    if (ic->ic_opmode == IEEE80211_M_HOSTAP)\n        return ieee80211_ref_node(ic->ic_bss);\n#endif\n    /* XXX see remarks in ieee80211_find_txnode */\n    /* XXX no rate negotiation; just dup */\n    if ((ni = ieee80211_dup_bss(ic, wh->i_addr2)) == NULL)\n        return ieee80211_ref_node(ic->ic_bss);\n    \n    IEEE80211_ADDR_COPY(ni->ni_bssid, (bssid != NULL) ? bssid : zero);\n    \n    ni->ni_rates = ic->ic_bss->ni_rates;\n    ni->ni_txrate = 0;\n    if (ic->ic_newassoc)\n        (*ic->ic_newassoc)(ic, ni, 1);\n    \n    DPRINTF((\"faked-up node %p for %s\\n\", ni,\n             ether_sprintf((u_int8_t *)wh->i_addr2)));\n    \n    return ieee80211_ref_node(ni);\n}\n\nvoid\nieee80211_ba_del(struct ieee80211_node *ni)\n{\n    int tid;\n    \n    for (tid = 0; tid < nitems(ni->ni_rx_ba); tid++) {\n        struct ieee80211_rx_ba *ba = &ni->ni_rx_ba[tid];\n        if (ba->ba_state != IEEE80211_BA_INIT) {\n            if (timeout_pending(&ba->ba_to))\n                timeout_del(&ba->ba_to);\n            if (timeout_pending(&ba->ba_gap_to))\n                timeout_del(&ba->ba_gap_to);\n            ba->ba_state = IEEE80211_BA_INIT;\n        }\n    }\n    \n    for (tid = 0; tid < nitems(ni->ni_tx_ba); tid++) {\n        struct ieee80211_tx_ba *ba = &ni->ni_tx_ba[tid];\n        if (ba->ba_state != IEEE80211_BA_INIT) {\n            if (timeout_pending(&ba->ba_to))\n                timeout_del(&ba->ba_to);\n            ba->ba_state = IEEE80211_BA_INIT;\n        }\n    }\n    \n    timeout_del(&ni->ni_addba_req_to[EDCA_AC_BE]);\n    timeout_del(&ni->ni_addba_req_to[EDCA_AC_BK]);\n    timeout_del(&ni->ni_addba_req_to[EDCA_AC_VI]);\n    timeout_del(&ni->ni_addba_req_to[EDCA_AC_VO]);\n}\n\nvoid ieee80211_ba_free(struct ieee80211_node *ni)\n{\n    int tid;\n    \n    for (tid = 0; tid < nitems(ni->ni_rx_ba); tid++) {\n        struct ieee80211_rx_ba *ba = &ni->ni_rx_ba[tid];\n        timeout_free(&ba->ba_to);\n        timeout_free(&ba->ba_gap_to);\n    }\n    \n    for (tid = 0; tid < nitems(ni->ni_tx_ba); tid++) {\n        struct ieee80211_tx_ba *ba = &ni->ni_tx_ba[tid];\n        timeout_free(&ba->ba_to);\n    }\n    \n    timeout_free(&ni->ni_addba_req_to[EDCA_AC_BE]);\n    timeout_free(&ni->ni_addba_req_to[EDCA_AC_BK]);\n    timeout_free(&ni->ni_addba_req_to[EDCA_AC_VI]);\n    timeout_free(&ni->ni_addba_req_to[EDCA_AC_VO]);\n}\n\nvoid\nieee80211_free_node(struct ieee80211com *ic, struct ieee80211_node *ni)\n{\n    DPRINTF((\"%s %s %s\\n\", __FUNCTION__, ni->ni_essid, ether_sprintf(ni->ni_bssid)));\n    if (ni == ic->ic_bss)\n        panic(\"freeing bss node\");\n    \n    splassert(IPL_NET);\n    \n    DPRINTF((\"%s, %s\\n\", __FUNCTION__, ether_sprintf(ni->ni_macaddr)));\n#ifndef IEEE80211_STA_ONLY\n    timeout_del(&ni->ni_eapol_to);\n    timeout_free(&ni->ni_eapol_to);\n    timeout_del(&ni->ni_sa_query_to);\n    timeout_free(&ni->ni_sa_query_to);\n    IEEE80211_AID_CLR(ni->ni_associd, ic->ic_aid_bitmap);\n#endif\n    ieee80211_ba_del(ni);\n    ieee80211_ba_free(ni);\n    RB_REMOVE(ieee80211_tree, &ic->ic_tree, ni);\n    ic->ic_nnodes--;\n#ifndef IEEE80211_STA_ONLY\n    if (mq_purge(&ni->ni_savedq) > 0) {\n        if (ic->ic_set_tim != NULL)\n            (*ic->ic_set_tim)(ic, ni->ni_associd, 0);\n    }\n#endif\n    (*ic->ic_node_free)(ic, ni);\n    /* TBD indicate to drivers that a new node can be allocated */\n}\n\nvoid\nieee80211_release_node(struct ieee80211com *ic, struct ieee80211_node *ni)\n{\n    int s;\n    \n    DPRINTF((\"%s refcnt %u\\n\", ether_sprintf(ni->ni_macaddr),\n             ni->ni_refcnt));\n    s = splnet();\n    if (ieee80211_node_decref(ni) == 0) {\n        if (ni->ni_unref_cb) {\n            (*ni->ni_unref_cb)(ic, ni);\n            ni->ni_unref_cb = NULL;\n            /* Freed by callback if necessary: */\n            ni->ni_unref_arg = NULL;\n            ni->ni_unref_arg_size = 0;\n        }\n        if (ni->ni_state == IEEE80211_STA_COLLECT)\n            ieee80211_free_node(ic, ni);\n    }\n    splx(s);\n}\n\nvoid\nieee80211_free_allnodes(struct ieee80211com *ic, int clear_ic_bss)\n{\n    struct ieee80211_node *ni, *next_ni;\n    int s;\n    \n    DPRINTF((\"freeing all nodes\\n\"));\n    s = splnet();\n    for (ni = RB_MIN(ieee80211_tree, &ic->ic_tree);\n         ni != NULL; ni = next_ni) {\n        next_ni = RB_NEXT(ieee80211_tree, &ic->ic_tree, ni);\n        if (!clear_ic_bss && ic->ic_bss != NULL) {\n            if (memcmp(ic->ic_bss->ni_bssid, ni->ni_bssid, IEEE80211_ADDR_LEN) == 0\n                && strncmp((const char *)ic->ic_bss->ni_essid, (const char *)ni->ni_essid, IEEE80211_NWID_LEN) == 0) {\n                continue;\n            }\n        }\n        ieee80211_free_node(ic, ni);\n    }\n    splx(s);\n    \n    if (clear_ic_bss && ic->ic_bss != NULL)\n        ieee80211_node_cleanup(ic, ic->ic_bss);\n}\n\nvoid\nieee80211_clean_cached(struct ieee80211com *ic)\n{\n    struct ieee80211_node *ni, *next_ni;\n    int s;\n    \n    s = splnet();\n    for (ni = RB_MIN(ieee80211_tree, &ic->ic_tree);\n         ni != NULL; ni = next_ni) {\n        next_ni = RB_NEXT(ieee80211_tree, &ic->ic_tree, ni);\n        if (ni->ni_state == IEEE80211_STA_CACHE)\n            ieee80211_free_node(ic, ni);\n    }\n    splx(s);\n}\n\nvoid\nieee80211_clean_sta_bss_node(struct ieee80211com *ic)\n{\n    struct ieee80211_node *ni, *next_ni;\n    int s;\n    \n    s = splnet();\n    if (ic->ic_bss == NULL)\n        return;\n\n    for (ni = RB_MIN(ieee80211_tree, &ic->ic_tree);\n         ni != NULL; ni = next_ni) {\n        next_ni = RB_NEXT(ieee80211_tree, &ic->ic_tree, ni);\n        if (ni->ni_state == IEEE80211_STA_BSS) {\n            if (memcmp(ic->ic_bss->ni_bssid, ni->ni_bssid, IEEE80211_ADDR_LEN) != 0)\n                ieee80211_node_newstate(ni, IEEE80211_STA_CACHE);\n        }\n    }\n    splx(s);\n}\n/*\n * Timeout inactive nodes.\n *\n * If called because of a cache timeout, which happens only in hostap and ibss\n * modes, clean all inactive cached or authenticated nodes but don't de-auth\n * any associated nodes. Also update HT protection settings.\n *\n * Else, this function is called because a new node must be allocated but the\n * node cache is full. In this case, return as soon as a free slot was made\n * available. If acting as hostap, clean cached nodes regardless of their\n * recent activity and also allow de-authing of authenticated nodes older\n * than one cache wait interval, and de-authing of inactive associated nodes.\n */\nvoid\nieee80211_clean_nodes(struct ieee80211com *ic, int cache_timeout)\n{\n    struct ieee80211_node *ni, *next_ni;\n    u_int gen = ic->ic_scangen++;\t\t/* NB: ok 'cuz single-threaded*/\n    int s;\n#ifndef IEEE80211_STA_ONLY\n    int nnodes = 0, nonht = 0, nonhtassoc = 0;\n    struct _ifnet *ifp = &ic->ic_if;\n    enum ieee80211_htprot htprot = IEEE80211_HTPROT_NONE;\n    enum ieee80211_protmode protmode = IEEE80211_PROT_NONE;\n#endif\n    \n    s = splnet();\n    for (ni = RB_MIN(ieee80211_tree, &ic->ic_tree);\n         ni != NULL; ni = next_ni) {\n        next_ni = RB_NEXT(ieee80211_tree, &ic->ic_tree, ni);\n        if (!cache_timeout && ic->ic_nnodes < ic->ic_max_nnodes)\n            break;\n        if (ni->ni_scangen == gen)\t/* previously handled */\n            continue;\n#ifndef IEEE80211_STA_ONLY\n        nnodes++;\n        if ((ic->ic_flags & IEEE80211_F_HTON) && cache_timeout) {\n            /*\n             * Check if node supports 802.11n.\n             * Only require HT capabilities IE for this check.\n             * Nodes might never reveal their supported MCS to us\n             * unless they go through a full association sequence.\n             * ieee80211_node_supports_ht() could misclassify them.\n             */\n            if ((ni->ni_flags & IEEE80211_NODE_HTCAP) == 0) {\n                nonht++;\n                if (ni->ni_state == IEEE80211_STA_ASSOC)\n                    nonhtassoc++;\n            }\n        }\n#endif\n        ni->ni_scangen = gen;\n        if (ni->ni_refcnt > 0)\n            continue;\n#ifndef IEEE80211_STA_ONLY\n        if ((ic->ic_opmode == IEEE80211_M_HOSTAP ||\n             ic->ic_opmode == IEEE80211_M_IBSS) &&\n            ic->ic_state == IEEE80211_S_RUN) {\n            if (cache_timeout) {\n                if (ni->ni_state != IEEE80211_STA_COLLECT &&\n                    (ni->ni_state == IEEE80211_STA_ASSOC ||\n                     ni->ni_inact < IEEE80211_INACT_MAX))\n                    continue;\n            } else {\n                if (ic->ic_opmode == IEEE80211_M_HOSTAP &&\n                    ((ni->ni_state == IEEE80211_STA_ASSOC &&\n                      ni->ni_inact < IEEE80211_INACT_MAX) ||\n                     (ni->ni_state == IEEE80211_STA_AUTH &&\n                      ni->ni_inact == 0)))\n                    continue;\n                \n                if (ic->ic_opmode == IEEE80211_M_IBSS &&\n                    ni->ni_state != IEEE80211_STA_COLLECT &&\n                    ni->ni_state != IEEE80211_STA_CACHE &&\n                    ni->ni_inact < IEEE80211_INACT_MAX)\n                    continue;\n            }\n        }\n        if (ifp->if_flags & IFF_DEBUG)\n            XYLog(\"%s, %s: station %s purged from node cache\\n\", __FUNCTION__,\n                  ifp->if_xname, ether_sprintf(ni->ni_macaddr));\n#endif\n        /*\n         * If we're hostap and the node is authenticated, send\n         * a deauthentication frame. The node will be freed when\n         * the driver calls ieee80211_release_node().\n         */\n#ifndef IEEE80211_STA_ONLY\n        nnodes--;\n        if ((ic->ic_flags & IEEE80211_F_HTON) && cache_timeout) {\n            if ((ni->ni_flags & IEEE80211_NODE_HTCAP) == 0) {\n                nonht--;\n                if (ni->ni_state == IEEE80211_STA_ASSOC)\n                    nonhtassoc--;\n            }\n        }\n        if (ic->ic_opmode == IEEE80211_M_HOSTAP &&\n            ni->ni_state >= IEEE80211_STA_AUTH &&\n            ni->ni_state != IEEE80211_STA_COLLECT) {\n            IEEE80211_SEND_MGMT(ic, ni,\n                                IEEE80211_FC0_SUBTYPE_DEAUTH,\n                                IEEE80211_REASON_AUTH_EXPIRE);\n            ieee80211_node_leave(ic, ni);\n        } else\n#endif\n            ieee80211_free_node(ic, ni);\n        ic->ic_stats.is_node_timeout++;\n    }\n    \n#ifndef IEEE80211_STA_ONLY\n    if ((ic->ic_flags & IEEE80211_F_HTON) && cache_timeout) {\n        uint16_t htop1 = ic->ic_bss->ni_htop1;\n        \n        /* Update HT protection settings. */\n        if (nonht) {\n            protmode = IEEE80211_PROT_CTSONLY;\n            if (nonhtassoc)\n                htprot = IEEE80211_HTPROT_NONHT_MIXED;\n            else\n                htprot = IEEE80211_HTPROT_NONMEMBER;\n        }\n        if ((htop1 & IEEE80211_HTOP1_PROT_MASK) != htprot) {\n            htop1 &= ~IEEE80211_HTOP1_PROT_MASK;\n            htop1 |= htprot;\n            ic->ic_bss->ni_htop1 = htop1;\n            ic->ic_protmode = protmode;\n            if (ic->ic_updateprot)\n                ic->ic_updateprot(ic);\n        }\n    }\n    \n    /*\n     * During a cache timeout we iterate over all nodes.\n     * Check for node leaks by comparing the actual number of cached\n     * nodes with the ic_nnodes count, which is maintained while adding\n     * and removing nodes from the cache.\n     */\n    if ((ifp->if_flags & IFF_DEBUG) && cache_timeout &&\n        nnodes != ic->ic_nnodes)\n        XYLog(\"%s: number of cached nodes is %d, expected %d,\"\n              \"possible nodes leak\\n\", ifp->if_xname, nnodes,\n              ic->ic_nnodes);\n#endif\n    splx(s);\n}\n\nvoid\nieee80211_clean_inactive_nodes(struct ieee80211com *ic, int inact_max)\n{\n    DPRINTF((\"%s\\n\", __FUNCTION__));\n    struct ieee80211_node *ni, *next_ni;\n    u_int gen = ic->ic_scangen++;\t/* NB: ok 'cuz single-threaded*/\n    int s;\n    \n    s = splnet();\n    for (ni = RB_MIN(ieee80211_tree, &ic->ic_tree);\n         ni != NULL; ni = next_ni) {\n        next_ni = RB_NEXT(ieee80211_tree, &ic->ic_tree, ni);\n        if (ni->ni_scangen == gen)\t/* previously handled */\n            continue;\n        ni->ni_scangen = gen;\n        if (ni->ni_refcnt > 0 || ni->ni_inact < inact_max)\n            continue;\n        ieee80211_free_node(ic, ni);\n        ic->ic_stats.is_node_timeout++;\n    }\n    \n    splx(s);\n}\n\nvoid\nieee80211_iterate_nodes(struct ieee80211com *ic, ieee80211_iter_func *f,\n                        void *arg)\n{\n    struct ieee80211_node *ni;\n    int s;\n    \n    s = splnet();\n    RB_FOREACH(ni, ieee80211_tree, &ic->ic_tree)\n    (*f)(arg, ni);\n    splx(s);\n}\n\n\n/*\n * Install received HT caps information in the node's state block.\n */\nvoid\nieee80211_setup_htcaps(struct ieee80211_node *ni, const uint8_t *data,\n                       uint8_t len)\n{\n    uint16_t rxrate;\n    \n    if (len != 26)\n        return;\n    \n    ni->ni_htcaps = (data[0] | (data[1] << 8));\n    ni->ni_htcaps &= le16toh(ni->ni_ic->ic_htcaps |\n                             ~(IEEE80211_HTCAP_CBW20_40 |\n                               IEEE80211_HTCAP_SGI40 |\n                               IEEE80211_HTCAP_SGI20 |\n                               IEEE80211_HTCAP_GF |\n                               IEEE80211_HTCAP_LDPC |\n                               IEEE80211_HTCAP_DSSSCCK40));\n    if (!(ni->ni_ic->ic_htcaps & IEEE80211_HTCAP_TXSTBC))\n        ni->ni_htcaps &= ~IEEE80211_HTCAP_RXSTBC_MASK;\n    if (!(ni->ni_ic->ic_htcaps & IEEE80211_HTCAP_RXSTBC_MASK))\n        ni->ni_htcaps &= ~IEEE80211_HTCAP_TXSTBC;\n    \n    ni->ni_ampdu_param = data[2];\n    \n    memcpy(ni->ni_rxmcs, &data[3], sizeof(ni->ni_rxmcs));\n    /* clear reserved bits */\n    clrbit(ni->ni_rxmcs, 77);\n    clrbit(ni->ni_rxmcs, 78);\n    clrbit(ni->ni_rxmcs, 79);\n    \n    /* Max MCS Rx rate in 1Mb/s units (0 means \"not specified\"). */\n    rxrate = ((data[13] | (data[14]) << 8) & IEEE80211_MCS_RX_RATE_HIGH);\n    if (rxrate < 1024)\n        ni->ni_max_rxrate = rxrate;\n    \n    ni->ni_tx_mcs_set = data[15];\n    ni->ni_htxcaps = (data[19] | (data[20] << 8));\n    ni->ni_txbfcaps = (data[21] | (data[22] << 8) | (data[23] << 16) |\n                       (data[24] << 24));\n    ni->ni_aselcaps = data[25];\n    \n    ni->ni_flags |= IEEE80211_NODE_HTCAP;\n}\n\n#ifndef IEEE80211_STA_ONLY\n/* \n * Handle nodes switching from 11n into legacy modes.\n */\nvoid\nieee80211_clear_htcaps(struct ieee80211_node *ni)\n{\n    ni->ni_htcaps = 0;\n    ni->ni_ampdu_param = 0;\n    memset(ni->ni_rxmcs, 0, sizeof(ni->ni_rxmcs));\n    ni->ni_max_rxrate = 0;\n    ni->ni_tx_mcs_set = 0;\n    ni->ni_htxcaps = 0;\n    ni->ni_txbfcaps = 0;\n    ni->ni_aselcaps = 0;\n    \n    ni->ni_flags &= ~(IEEE80211_NODE_HT | IEEE80211_NODE_HT_SGI20 |\n                      IEEE80211_NODE_HT_SGI40 | IEEE80211_NODE_HTCAP);\n    \n}\n#endif\n\n/*\n * Install received HT op information in the node's state block.\n */\nint\nieee80211_setup_htop(struct ieee80211_node *ni, const uint8_t *data,\n                     uint8_t len, int isprobe)\n{\n    if (len != 22)\n        return 0;\n    \n    ni->ni_primary_chan = data[0]; /* XXX corresponds to ni_chan */\n    \n    ni->ni_htop0 = data[1];\n    ni->ni_htop1 = (data[2] | (data[3] << 8));\n    ni->ni_htop2 = (data[3] | (data[4] << 8));\n    \n    /*\n     * According to 802.11-2012 Table 8-130 the Basic MCS set is\n     * only \"present in Beacon, Probe Response, Mesh Peering Open\n     * and Mesh Peering Confirm frames. Otherwise reserved.\"\n     */\n    if (isprobe)\n        memcpy(ni->ni_basic_mcs, &data[6], sizeof(ni->ni_basic_mcs));\n    \n    return 1;\n}\n\n/*\n * Parse an 802.11ac VHT operation IE.\n */\nvoid\nieee80211_setup_vhtopmode(struct ieee80211_node *ni, const uint8_t *ie)\n{\n    /* vht operation */\n    struct ieee80211_ie_vht_operation *op = (struct ieee80211_ie_vht_operation *)ie;\n    ni->ni_vht_chanwidth = op->chan_width;\n    ni->ni_vht_chan1 = op->center_freq_seg1_idx;\n    ni->ni_vht_chan2 = op->center_freq_seg2_idx;\n    ni->ni_vht_basicmcs = op->basic_mcs_set;\n\n    DPRINTF((\"%s: chan1=%d, chan2=%d, chanwidth=%d, basicmcs=0x%04x\\n\",\n        __func__,\n        ni->ni_vht_chan1,\n        ni->ni_vht_chan2,\n        ni->ni_vht_chanwidth,\n        ni->ni_vht_basicmcs));\n}\n\n/*\n * Parse an 802.11ac VHT capability IE.\n */\nvoid\nieee80211_setup_vhtcaps(struct ieee80211com *ic, struct ieee80211_node *ni, const uint8_t *ie)\n{\n    uint32_t val, val1, val2;\n    int i;\n    uint16_t rx_mcs_map;\n    uint16_t rx_highest;\n    uint16_t tx_mcs_map;\n    uint16_t tx_highest;\n    \n    uint32_t own_vhtcap = ic->ic_vhtcaps;\n    uint32_t new_vhtcap = 0, peer_vhtcap;\n    /* vht capability */\n    peer_vhtcap = le32dec(ie + 2);\n    /* suppmcs */\n    rx_mcs_map = le16dec(ie + 6);\n    rx_highest = le16dec(ie + 8);\n    tx_mcs_map = le16dec(ie + 10);\n    tx_highest = le16dec(ie + 12);\n    \n#define    MS(_v, _f)    (((_v) & _f) >> _f##_S)\n#define    SM(_v, _f)    (((_v) << _f##_S) & _f)\n    \n    val1 = MS(own_vhtcap, IEEE80211_VHTCAP_MAX_MPDU_MASK);\n    val2 = MS(peer_vhtcap, IEEE80211_VHTCAP_MAX_MPDU_MASK);\n    val = MIN(val1, val2);\n    new_vhtcap |= SM(val, IEEE80211_VHTCAP_MAX_MPDU_MASK);\n    \n    /* Supported Channel Width */\n    val1 = MS(own_vhtcap,\n              IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_MASK);\n    val2 = MS(peer_vhtcap,\n              IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_MASK);\n    if ((val2 == 2) &&\n        ((own_vhtcap & IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_160_80P80MHZ) == 0))\n        val2 = 1;\n    if ((val2 == 1) &&\n        ((own_vhtcap & IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_160MHZ) == 0))\n        val2 = 0;\n    val = MIN(val1, val2);\n    new_vhtcap |= SM(val, IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_MASK);\n    \n    /* RX LDPC */\n    val1 = MS(own_vhtcap, IEEE80211_VHTCAP_RXLDPC);\n    val2 = MS(peer_vhtcap, IEEE80211_VHTCAP_RXLDPC);\n    val = MIN(val1, val2);\n    new_vhtcap |= SM(val, IEEE80211_VHTCAP_RXLDPC);\n    \n    /* Short-GI 80 */\n    val1 = MS(own_vhtcap, IEEE80211_VHTCAP_SHORT_GI_80);\n    val2 = MS(peer_vhtcap, IEEE80211_VHTCAP_SHORT_GI_80);\n    val = MIN(val1, val2);\n    new_vhtcap |= SM(val, IEEE80211_VHTCAP_SHORT_GI_80);\n    \n    /* Short-GI 160 */\n    val2 = val1 = MS(own_vhtcap, IEEE80211_VHTCAP_SHORT_GI_160);\n    val2 = MS(peer_vhtcap, IEEE80211_VHTCAP_SHORT_GI_160);\n    val = MIN(val1, val2);\n    new_vhtcap |= SM(val, IEEE80211_VHTCAP_SHORT_GI_160);\n    \n    /*\n     * STBC is slightly more complicated.\n     *\n     * In non-STA mode, we just announce our capabilities and that\n     * is that.\n     *\n     * In STA mode, we should calculate our capabilities based on\n     * local capabilities /and/ what the remote says. So:\n     *\n     * + Only TX STBC if we support it and the remote supports RX STBC;\n     * + Only announce RX STBC if we support it and the remote supports\n     *   TX STBC;\n     * + RX STBC should be the minimum of local and remote RX STBC;\n     */\n    \n    /* TX STBC */\n    val1 = MS(own_vhtcap, IEEE80211_VHTCAP_TXSTBC);\n    /* STA mode - enable it only if node RXSTBC is non-zero */\n    val2 = !! MS(peer_vhtcap, IEEE80211_VHTCAP_RXSTBC_MASK);\n    val = MIN(val1, val2);\n    /* XXX For now, use the 11n config flag */\n    if ((ic->ic_htcaps & IEEE80211_HTCAP_TXSTBC) == 0)\n        val = 0;\n    new_vhtcap |= SM(val, IEEE80211_VHTCAP_TXSTBC);\n    \n    /* RX STBC1..4 */\n    val1 = MS(own_vhtcap, IEEE80211_VHTCAP_RXSTBC_MASK);\n    /* STA mode - enable it only if node TXSTBC is non-zero */\n    val2 = MS(peer_vhtcap, IEEE80211_VHTCAP_TXSTBC);\n    val = MIN(val1, val2);\n    /* XXX For now, use the 11n config flag */\n    if ((ic->ic_htcaps & IEEE80211_HTCAP_RXSTBC_MASK) == 0)\n        val = 0;\n    new_vhtcap |= SM(val, IEEE80211_VHTCAP_RXSTBC_MASK);\n    \n    /*\n     * Finally - if RXSTBC is 0, then don't enable TXSTBC.\n     * Strictly speaking a device can TXSTBC and not RXSTBC, but\n     * it would be silly.\n     */\n    if (val == 0)\n        new_vhtcap &= ~IEEE80211_VHTCAP_TXSTBC;\n    \n    /*\n     * Some of these fields require other fields to exist.\n     * So before using it, the parent field needs to be checked\n     * otherwise the overridden value may be wrong.\n     *\n     * For example, if SU beamformee is set to 0, then BF STS\n     * needs to be 0.\n     */\n    \n    /* SU Beamformer capable */\n    val1 = MS(own_vhtcap,\n              IEEE80211_VHTCAP_SU_BEAMFORMER_CAPABLE);\n    val2 = MS(peer_vhtcap,\n              IEEE80211_VHTCAP_SU_BEAMFORMER_CAPABLE);\n    val = MIN(val1, val2);\n    new_vhtcap |= SM(val, IEEE80211_VHTCAP_SU_BEAMFORMER_CAPABLE);\n    \n    /* SU Beamformee capable */\n    val1 = MS(own_vhtcap,\n              IEEE80211_VHTCAP_SU_BEAMFORMEE_CAPABLE);\n    val2 = MS(peer_vhtcap,\n              IEEE80211_VHTCAP_SU_BEAMFORMEE_CAPABLE);\n    val = MIN(val1, val2);\n    new_vhtcap |= SM(val, IEEE80211_VHTCAP_SU_BEAMFORMEE_CAPABLE);\n    \n    /* Beamformee STS capability - only if SU beamformee capable */\n    val1 = MS(own_vhtcap, IEEE80211_VHTCAP_BEAMFORMEE_STS_MASK);\n    val2 = MS(peer_vhtcap, IEEE80211_VHTCAP_BEAMFORMEE_STS_MASK);\n    val = MIN(val1, val2);\n    if ((new_vhtcap & IEEE80211_VHTCAP_SU_BEAMFORMEE_CAPABLE) == 0)\n        val = 0;\n    new_vhtcap |= SM(val, IEEE80211_VHTCAP_BEAMFORMEE_STS_MASK);\n    \n    /* Sounding dimensions - only if SU beamformer capable */\n    val1 = MS(own_vhtcap,\n              IEEE80211_VHTCAP_SOUNDING_DIMENSIONS_MASK);\n    val2 = MS(peer_vhtcap,\n              IEEE80211_VHTCAP_SOUNDING_DIMENSIONS_MASK);\n    val = MIN(val1, val2);\n    if ((new_vhtcap & IEEE80211_VHTCAP_SU_BEAMFORMER_CAPABLE) == 0)\n        val = 0;\n    new_vhtcap |= SM(val, IEEE80211_VHTCAP_SOUNDING_DIMENSIONS_MASK);\n    \n    /*\n     * MU Beamformer capable - only if SU BFF capable, MU BFF capable\n     * and STA (not AP)\n     */\n    val1 = MS(own_vhtcap,\n              IEEE80211_VHTCAP_MU_BEAMFORMER_CAPABLE);\n    val2 = MS(peer_vhtcap,\n              IEEE80211_VHTCAP_MU_BEAMFORMER_CAPABLE);\n    val = MIN(val1, val2);\n    if ((new_vhtcap & IEEE80211_VHTCAP_SU_BEAMFORMER_CAPABLE) == 0)\n        val = 0;\n    /* Only enable for STA mode */\n    new_vhtcap |= SM(val, IEEE80211_VHTCAP_SU_BEAMFORMER_CAPABLE);\n    \n    /*\n     * MU Beamformee capable - only if SU BFE capable, MU BFE capable\n     * and AP (not STA)\n     */\n    /* Only enable for AP mode */\n    val = 0;\n    new_vhtcap |= SM(val, IEEE80211_VHTCAP_SU_BEAMFORMEE_CAPABLE);\n    \n    /* VHT TXOP PS */\n    val1 = MS(own_vhtcap, IEEE80211_VHTCAP_VHT_TXOP_PS);\n    val2 = MS(peer_vhtcap, IEEE80211_VHTCAP_VHT_TXOP_PS);\n    val = MIN(val1, val2);\n    new_vhtcap |= SM(val, IEEE80211_VHTCAP_VHT_TXOP_PS);\n    \n    /* HTC_VHT */\n    val1 = MS(own_vhtcap, IEEE80211_VHTCAP_HTC_VHT);\n    val2 = MS(peer_vhtcap, IEEE80211_VHTCAP_HTC_VHT);\n    val = MIN(val1, val2);\n    new_vhtcap |= SM(val, IEEE80211_VHTCAP_HTC_VHT);\n    \n    /* A-MPDU length max */\n    val1 = MS(own_vhtcap,\n              IEEE80211_VHTCAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK);\n    val2 = MS(peer_vhtcap,\n              IEEE80211_VHTCAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK);\n    val = MIN(val1, val2);\n    new_vhtcap |= SM(val, IEEE80211_VHTCAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK);\n    \n    /*\n     * Link adaptation is only valid if HTC-VHT capable is 1.\n     * Otherwise, always set it to 0.\n     */\n    val1 = MS(own_vhtcap,\n              IEEE80211_VHTCAP_VHT_LINK_ADAPTATION_VHT_MASK);\n    val2 = MS(peer_vhtcap,\n              IEEE80211_VHTCAP_VHT_LINK_ADAPTATION_VHT_MASK);\n    val = MIN(val1, val2);\n    if ((new_vhtcap & IEEE80211_VHTCAP_HTC_VHT) == 0)\n        val = 0;\n    new_vhtcap |= SM(val, IEEE80211_VHTCAP_VHT_LINK_ADAPTATION_VHT_MASK);\n    \n    /*\n     * The following two options are 0 if the pattern may change, 1 if it\n     * does not change.  So, downgrade to the higher value.\n     */\n    \n    /* RX antenna pattern */\n    val1 = MS(own_vhtcap, IEEE80211_VHTCAP_RX_ANTENNA_PATTERN);\n    val2 = MS(peer_vhtcap, IEEE80211_VHTCAP_RX_ANTENNA_PATTERN);\n    val = MAX(val1, val2);\n    new_vhtcap |= SM(val, IEEE80211_VHTCAP_RX_ANTENNA_PATTERN);\n    \n    /* TX antenna pattern */\n    val1 = MS(own_vhtcap, IEEE80211_VHTCAP_TX_ANTENNA_PATTERN);\n    val2 = MS(peer_vhtcap, IEEE80211_VHTCAP_TX_ANTENNA_PATTERN);\n    val = MAX(val1, val2);\n    new_vhtcap |= SM(val, IEEE80211_VHTCAP_TX_ANTENNA_PATTERN);\n    \n    /* copy EXT_NSS_BW Support value or remove the capability */\n    if (ic->ic_caps & IEEE80211_C_SUPPORTS_VHT_EXT_NSS_BW) {\n        new_vhtcap |= IEEE80211_VHTCAP_EXT_NSS_BW_MASK;\n    } else {\n        tx_highest &= ~htole16(IEEE80211_VHT_EXT_NSS_BW_CAPABLE);\n    }\n    \n#undef SM\n#undef MS\n    ni->ni_vhtcaps = new_vhtcap;\n    \n    /*\n     * MCS set - again, we announce what we want to use\n     * based on configuration, device capabilities and\n     * already-learnt vhtcap/vhtinfo IE information.\n     */\n\n    /* MCS set - start with whatever the device supports */\n    for (i = 0; i < 8; i++) {\n        uint16_t own_rx, own_tx, peer_rx, peer_tx;\n        \n        own_rx = le16toh(ic->ic_vht_rx_mcs_map);\n        own_rx = (own_rx >> i * 2) & IEEE80211_VHT_MCS_NOT_SUPPORTED;\n\n        own_tx = le16toh(ic->ic_vht_tx_mcs_map);\n        own_tx = (own_tx >> i * 2) & IEEE80211_VHT_MCS_NOT_SUPPORTED;\n\n        peer_rx = le16toh(rx_mcs_map);\n        peer_rx = (peer_rx >> i * 2) & IEEE80211_VHT_MCS_NOT_SUPPORTED;\n\n        peer_tx = le16toh(tx_mcs_map);\n        peer_tx = (peer_tx >> i * 2) & IEEE80211_VHT_MCS_NOT_SUPPORTED;\n\n        if (peer_tx != IEEE80211_VHT_MCS_NOT_SUPPORTED) {\n            if (own_rx == IEEE80211_VHT_MCS_NOT_SUPPORTED)\n                peer_tx = IEEE80211_VHT_MCS_NOT_SUPPORTED;\n            else if (own_rx < peer_tx)\n                peer_tx = own_rx;\n        }\n\n        if (peer_rx != IEEE80211_VHT_MCS_NOT_SUPPORTED) {\n            if (own_tx == IEEE80211_VHT_MCS_NOT_SUPPORTED)\n                peer_rx = IEEE80211_VHT_MCS_NOT_SUPPORTED;\n            else if (own_tx < peer_rx)\n                peer_rx = own_tx;\n        }\n\n        rx_mcs_map &=\n            ~cpu_to_le16(IEEE80211_VHT_MCS_NOT_SUPPORTED << i * 2);\n        rx_mcs_map |= cpu_to_le16(peer_rx << i * 2);\n\n        tx_mcs_map &=\n            ~cpu_to_le16(IEEE80211_VHT_MCS_NOT_SUPPORTED << i * 2);\n        tx_mcs_map |= cpu_to_le16(peer_tx << i * 2);\n    }\n    ni->ni_vht_mcsinfo.rx_mcs_map = rx_mcs_map;\n    ni->ni_vht_mcsinfo.tx_mcs_map = tx_mcs_map;\n    ni->ni_vht_mcsinfo.tx_highest = tx_highest;\n    ni->ni_vht_mcsinfo.rx_highest = rx_highest;\n    \n    ni->ni_flags |= IEEE80211_NODE_VHTCAP;\n}\n\n#ifndef IEEE80211_STA_ONLY\n/*\n * Handle nodes switching from 11ac into legacy modes.\n */\nvoid\nieee80211_clear_vhtcaps(struct ieee80211_node *ni)\n{\n    ni->ni_vhtcaps = 0;\n    memset(&ni->ni_vht_mcsinfo, 0, sizeof(ni->ni_vht_mcsinfo));\n    \n    ni->ni_flags &= ~(IEEE80211_NODE_VHT | IEEE80211_NODE_VHT_SGI80 |\n                      IEEE80211_NODE_VHT_SGI160 | IEEE80211_NODE_VHTCAP);\n    \n}\n#endif\n\nvoid\nieee80211_setup_hecaps(struct ieee80211_node *ni, const uint8_t *data,\n                       uint8_t len)\n{\n    struct ieee80211_he_cap_elem *he_cap_ie_elem = (struct ieee80211_he_cap_elem *)data;\n    uint8_t mcs_nss_size, he_ppe_size, he_total_size;\n    \n    mcs_nss_size = ieee80211_he_mcs_nss_size(he_cap_ie_elem);\n    he_ppe_size =\n        ieee80211_he_ppe_size(data[sizeof(ni->ni_he_cap_elem) +\n                        mcs_nss_size],\n                      he_cap_ie_elem->phy_cap_info);\n    he_total_size = sizeof(ni->ni_he_cap_elem) + mcs_nss_size +\n            he_ppe_size;\n    \n    if (len < he_total_size)\n        return;\n    \n    memcpy(&ni->ni_he_cap_elem, data, sizeof(ni->ni_he_cap_elem));\n    \n    /* HE Tx/Rx HE MCS NSS Support Field */\n    memcpy(&ni->ni_he_mcs_nss_supp,\n           &data[sizeof(ni->ni_he_cap_elem)], mcs_nss_size);\n    \n    /* Check if there are (optional) PPE Thresholds */\n    if (ni->ni_he_cap_elem.phy_cap_info[6] &\n        IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT)\n        memcpy(ni->ni_ppe_thres,\n               &data[sizeof(ni->ni_he_cap_elem) + mcs_nss_size],\n               he_ppe_size);\n}\n\nint\nieee80211_setup_heop(struct ieee80211_node *ni, const uint8_t *data,\n                     uint8_t len)\n{\n    struct ieee80211_he_operation *he_op_ie = (struct ieee80211_he_operation *)data;\n    \n    ni->ni_he_oper_params = le32toh(he_op_ie->he_oper_params);\n    ni->ni_he_oper_nss_set = le16toh(he_op_ie->he_mcs_nss_set);\n    bzero(&ni->ni_he_optional, sizeof(ni->ni_he_optional));\n    if (len > __offsetof(struct ieee80211_he_operation, optional)) {\n        memcpy(ni->ni_he_optional, he_op_ie->optional, min(sizeof(ni->ni_he_optional), len - __offsetof(struct ieee80211_he_operation, optional)));\n    }\n    return 1;\n}\n\n/*\n * Install received rate set information in the node's state block.\n */\nint\nieee80211_setup_rates(struct ieee80211com *ic, struct ieee80211_node *ni,\n                      const u_int8_t *rates, const u_int8_t *xrates, int flags)\n{\n    struct ieee80211_rateset *rs = &ni->ni_rates;\n    \n    memset(rs, 0, sizeof(*rs));\n    rs->rs_nrates = rates[1];\n    memcpy(rs->rs_rates, rates + 2, rs->rs_nrates);\n    if (xrates != NULL) {\n        u_int8_t nxrates;\n        /*\n         * Tack on 11g extended supported rate element.\n         */\n        nxrates = xrates[1];\n        if (rs->rs_nrates + nxrates > IEEE80211_RATE_MAXSIZE) {\n            nxrates = IEEE80211_RATE_MAXSIZE - rs->rs_nrates;\n            DPRINTF((\"extended rate set too large; \"\n                     \"only using %u of %u rates\\n\",\n                     nxrates, xrates[1]));\n            ic->ic_stats.is_rx_rstoobig++;\n        }\n        memcpy(rs->rs_rates + rs->rs_nrates, xrates+2, nxrates);\n        rs->rs_nrates += nxrates;\n    }\n    return ieee80211_fix_rate(ic, ni, flags);\n}\n\nvoid\nieee80211_node_trigger_addba_req(struct ieee80211_node *ni, int tid)\n{\n    if (ni->ni_tx_ba[tid].ba_state == IEEE80211_BA_INIT &&\n        !timeout_pending(&ni->ni_addba_req_to[tid])) {\n        timeout_add_sec(&ni->ni_addba_req_to[tid],\n                        ni->ni_addba_req_intval[tid]);\n    }\n}\n\nvoid\nieee80211_node_addba_request(struct ieee80211_node *ni, int tid)\n{\n    struct ieee80211com *ic = ni->ni_ic;\n    uint16_t ssn = ni->ni_qos_txseqs[tid];\n    \n    ieee80211_addba_request(ic, ni, ssn, tid);\n}\n\nvoid\nieee80211_node_addba_request_ac_be_to(void *arg)\n{\n    struct ieee80211_node *ni = (struct ieee80211_node *)arg;\n    ieee80211_node_addba_request(ni, EDCA_AC_BE);\n}\n\nvoid\nieee80211_node_addba_request_ac_bk_to(void *arg)\n{\n    struct ieee80211_node *ni = (struct ieee80211_node *)arg;\n    ieee80211_node_addba_request(ni, EDCA_AC_BK);\n}\n\nvoid\nieee80211_node_addba_request_ac_vi_to(void *arg)\n{\n    struct ieee80211_node *ni = (struct ieee80211_node *)arg;\n    ieee80211_node_addba_request(ni, EDCA_AC_VI);\n}\n\nvoid\nieee80211_node_addba_request_ac_vo_to(void *arg)\n{\n    struct ieee80211_node *ni = (struct ieee80211_node *)arg;\n    ieee80211_node_addba_request(ni, EDCA_AC_VO);\n}\n\n#ifndef IEEE80211_STA_ONLY\n/*\n * Check if the specified node supports ERP.\n */\nint\nieee80211_iserp_sta(const struct ieee80211_node *ni)\n{\n    static const u_int8_t rates[] = { 2, 4, 11, 22, 12, 24, 48 };\n    const struct ieee80211_rateset *rs = &ni->ni_rates;\n    int i, j;\n    \n    /*\n     * A STA supports ERP operation if it includes all the Clause 19\n     * mandatory rates in its supported rate set.\n     */\n    for (i = 0; i < nitems(rates); i++) {\n        for (j = 0; j < rs->rs_nrates; j++) {\n            if ((rs->rs_rates[j] & IEEE80211_RATE_VAL) == rates[i])\n                break;\n        }\n        if (j == rs->rs_nrates)\n            return 0;\n    }\n    return 1;\n}\n\n/*\n * This function is called to notify the 802.1X PACP machine that a new\n * 802.1X port is enabled and must be authenticated. For 802.11, a port\n * becomes enabled whenever a STA successfully completes Open System\n * authentication with an AP.\n */\nvoid\nieee80211_needs_auth(struct ieee80211com *ic, struct ieee80211_node *ni)\n{\n    /*\n     * XXX this could be done via the route socket of via a dedicated\n     * EAP socket or another kernel->userland notification mechanism.\n     * The notification should include the MAC address (ni_macaddr).\n     */\n}\n\n/*\n * Handle an HT STA joining an HT network.\n */\nvoid\nieee80211_node_join_ht(struct ieee80211com *ic, struct ieee80211_node *ni)\n{\n    /* Update HT protection setting. */\n    if ((ni->ni_flags & IEEE80211_NODE_HT) == 0) {\n        uint16_t htop1 = ic->ic_bss->ni_htop1;\n        htop1 &= ~IEEE80211_HTOP1_PROT_MASK;\n        htop1 |= IEEE80211_HTPROT_NONHT_MIXED;\n        ic->ic_bss->ni_htop1 = htop1;\n        if (ic->ic_updateprot)\n            ic->ic_updateprot(ic);\n    }\n}\n\n/*\n * Handle a station joining an RSN network.\n */\nvoid\nieee80211_node_join_rsn(struct ieee80211com *ic, struct ieee80211_node *ni)\n{\n    DPRINTF((\"station %s associated using proto %d akm 0x%x \"\n             \"cipher 0x%x groupcipher 0x%x\\n\", ether_sprintf(ni->ni_macaddr),\n             ni->ni_rsnprotos, ni->ni_rsnakms, ni->ni_rsnciphers,\n             ni->ni_rsngroupcipher));\n    \n    ni->ni_rsn_state = RSNA_AUTHENTICATION;\n    \n    ni->ni_key_count = 0;\n    ni->ni_port_valid = 0;\n    ni->ni_flags &= ~IEEE80211_NODE_TXRXPROT;\n    ni->ni_flags &= ~IEEE80211_NODE_RSN_NEW_PTK;\n    ni->ni_replaycnt = -1;\t/* XXX */\n    ni->ni_rsn_retries = 0;\n    ni->ni_rsncipher = (enum ieee80211_cipher)ni->ni_rsnciphers;\n    \n    ni->ni_rsn_state = RSNA_AUTHENTICATION_2;\n    \n    /* generate a new authenticator nonce (ANonce) */\n    arc4random_buf(ni->ni_nonce, EAPOL_KEY_NONCE_LEN);\n    \n    if (!ieee80211_is_8021x_akm((enum ieee80211_akm)ni->ni_rsnakms)) {\n        memcpy(ni->ni_pmk, ic->ic_psk, IEEE80211_PMK_LEN);\n        ni->ni_flags |= IEEE80211_NODE_PMK;\n        (void)ieee80211_send_4way_msg1(ic, ni);\n    } else if (ni->ni_flags & IEEE80211_NODE_PMK) {\n        /* skip 802.1X auth if a cached PMK was found */\n        (void)ieee80211_send_4way_msg1(ic, ni);\n    } else {\n        /* no cached PMK found, needs full 802.1X auth */\n        ieee80211_needs_auth(ic, ni);\n    }\n}\n\nvoid\nieee80211_count_longslotsta(void *arg, struct ieee80211_node *ni)\n{\n    int *longslotsta = (int *)arg;\n    \n    if (ni->ni_associd == 0 || ni->ni_state == IEEE80211_STA_COLLECT)\n        return;\n    \n    if (!(ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME))\n        (*longslotsta)++;\n}\n\nvoid\nieee80211_count_nonerpsta(void *arg, struct ieee80211_node *ni)\n{\n    int *nonerpsta = (int *)arg;\n    \n    if (ni->ni_associd == 0 || ni->ni_state == IEEE80211_STA_COLLECT)\n        return;\n    \n    if (!ieee80211_iserp_sta(ni))\n        (*nonerpsta)++;\n}\n\nvoid\nieee80211_count_pssta(void *arg, struct ieee80211_node *ni)\n{\n    int *pssta = (int *)arg;\n    \n    if (ni->ni_associd == 0 || ni->ni_state == IEEE80211_STA_COLLECT)\n        return;\n    \n    if (ni->ni_pwrsave == IEEE80211_PS_DOZE)\n        (*pssta)++;\n}\n\nvoid\nieee80211_count_rekeysta(void *arg, struct ieee80211_node *ni)\n{\n    int *rekeysta = (int *)arg;\n    \n    if (ni->ni_associd == 0 || ni->ni_state == IEEE80211_STA_COLLECT)\n        return;\n    \n    if (ni->ni_flags & IEEE80211_NODE_REKEY)\n        (*rekeysta)++;\n}\n\n/*\n * Handle a station joining an 11g network.\n */\nvoid\nieee80211_node_join_11g(struct ieee80211com *ic, struct ieee80211_node *ni)\n{\n    int longslotsta = 0, nonerpsta = 0;\n    \n    if (!(ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME)) {\n        /*\n         * Joining STA doesn't support short slot time.  We must\n         * disable the use of short slot time for all other associated\n         * STAs and give the driver a chance to reconfigure the\n         * hardware.\n         */\n        ieee80211_iterate_nodes(ic,\n                                ieee80211_count_longslotsta, &longslotsta);\n        if (longslotsta == 1) {\n            if (ic->ic_caps & IEEE80211_C_SHSLOT)\n                ieee80211_set_shortslottime(ic, 0);\n        }\n        DPRINTF((\"[%s] station needs long slot time, count %d\\n\",\n                 ether_sprintf(ni->ni_macaddr), longslotsta));\n    }\n    \n    if (!ieee80211_iserp_sta(ni)) {\n        /*\n         * Joining STA is non-ERP.\n         */\n        ieee80211_iterate_nodes(ic,\n                                ieee80211_count_nonerpsta, &nonerpsta);\n        DPRINTF((\"[%s] station is non-ERP, %d non-ERP \"\n                 \"stations associated\\n\", ether_sprintf(ni->ni_macaddr),\n                 nonerpsta));\n        /* must enable the use of protection */\n        if (ic->ic_protmode != IEEE80211_PROT_NONE) {\n            DPRINTF((\"enable use of protection\\n\"));\n            ic->ic_flags |= IEEE80211_F_USEPROT;\n        }\n        \n        if (!(ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE))\n            ic->ic_flags &= ~IEEE80211_F_SHPREAMBLE;\n    } else\n        ni->ni_flags |= IEEE80211_NODE_ERP;\n}\n\nvoid\nieee80211_node_join(struct ieee80211com *ic, struct ieee80211_node *ni,\n                    int resp)\n{\n    int newassoc = (ni->ni_state != IEEE80211_STA_ASSOC);\n    \n    if (ni->ni_associd == 0) {\n        u_int16_t aid;\n        \n        /*\n         * It would be clever to search the bitmap\n         * more efficiently, but this will do for now.\n         */\n        for (aid = 1; aid < ic->ic_max_aid; aid++) {\n            if (!IEEE80211_AID_ISSET(aid,\n                                     ic->ic_aid_bitmap))\n                break;\n        }\n        if (aid >= ic->ic_max_aid) {\n            IEEE80211_SEND_MGMT(ic, ni, resp,\n                                IEEE80211_REASON_ASSOC_TOOMANY);\n            ieee80211_node_leave(ic, ni);\n            return;\n        }\n        ni->ni_associd = aid | 0xc000;\n        IEEE80211_AID_SET(ni->ni_associd, ic->ic_aid_bitmap);\n        if (ic->ic_curmode == IEEE80211_MODE_11G ||\n            (ic->ic_curmode == IEEE80211_MODE_11N &&\n             IEEE80211_IS_CHAN_2GHZ(ic->ic_bss->ni_chan)))\n            ieee80211_node_join_11g(ic, ni);\n    }\n    \n    DPRINTF((\"station %s %s associated at aid %d\\n\",\n             ether_sprintf(ni->ni_macaddr), newassoc ? \"newly\" : \"already\",\n             ni->ni_associd & ~0xc000));\n    \n    ieee80211_ht_negotiate(ic, ni);\n    if (ic->ic_flags & IEEE80211_F_HTON)\n        ieee80211_node_join_ht(ic, ni);\n    \n    /* give driver a chance to setup state like ni_txrate */\n    if (ic->ic_newassoc)\n        (*ic->ic_newassoc)(ic, ni, newassoc);\n    IEEE80211_SEND_MGMT(ic, ni, resp, IEEE80211_STATUS_SUCCESS);\n    ieee80211_node_newstate(ni, IEEE80211_STA_ASSOC);\n    \n    if (!(ic->ic_flags & IEEE80211_F_RSNON)) {\n        ni->ni_port_valid = 1;\n        ni->ni_rsncipher = IEEE80211_CIPHER_USEGROUP;\n    } else\n        ieee80211_node_join_rsn(ic, ni);\n    \n#if NBRIDGE > 0\n    /*\n     * If the parent interface is a bridge port, learn\n     * the node's address dynamically on this interface.\n     */\n    if (ic->ic_if.if_bridgeidx != 0)\n        bridge_update(&ic->ic_if,\n                      (struct ether_addr *)ni->ni_macaddr, 0);\n#endif\n}\n\n/*\n * Handle a VHT STA leaving a VHT network.\n */\nvoid\nieee80211_node_leave_vht(struct ieee80211com *ic, struct ieee80211_node *ni)\n{\n    ieee80211_clear_vhtcaps(ni);\n}\n\n/*\n * Handle an HT STA leaving an HT network.\n */\nvoid\nieee80211_node_leave_ht(struct ieee80211com *ic, struct ieee80211_node *ni)\n{\n    struct ieee80211_rx_ba *ba;\n    u_int8_t tid;\n    int i;\n    \n    /* free all Block Ack records */\n    ieee80211_ba_del(ni);\n    ieee80211_ba_free(ni);\n    for (tid = 0; tid < IEEE80211_NUM_TID; tid++) {\n        ba = &ni->ni_rx_ba[tid];\n        if (ba->ba_buf != NULL) {\n            for (i = 0; i < IEEE80211_BA_MAX_WINSZ; i++)\n                mbuf_freem(ba->ba_buf[i].m);\n            free(ba->ba_buf);\n            ba->ba_buf = NULL;\n        }\n    }\n    \n    ieee80211_clear_htcaps(ni);\n}\n\n/*\n * Handle a station leaving an RSN network.\n */\nvoid\nieee80211_node_leave_rsn(struct ieee80211com *ic, struct ieee80211_node *ni)\n{\n    int rekeysta = 0;\n    \n    ni->ni_rsn_state = RSNA_DISCONNECTED;\n    \n    ni->ni_rsn_state = RSNA_INITIALIZE;\n    if (ni->ni_flags & IEEE80211_NODE_REKEY) {\n        ni->ni_flags &= ~IEEE80211_NODE_REKEY;\n        ieee80211_iterate_nodes(ic,\n                                ieee80211_count_rekeysta, &rekeysta);\n        if (rekeysta == 0)\n            ieee80211_setkeysdone(ic);\n    }\n    ni->ni_flags &= ~IEEE80211_NODE_PMK;\n    ni->ni_rsn_gstate = RSNA_IDLE;\n    \n    timeout_del(&ni->ni_eapol_to);\n    timeout_del(&ni->ni_sa_query_to);\n    \n    ni->ni_rsn_retries = 0;\n    ni->ni_flags &= ~IEEE80211_NODE_TXRXPROT;\n    ni->ni_port_valid = 0;\n    (*ic->ic_delete_key)(ic, ni, &ni->ni_pairwise_key);\n}\n\n/*\n * Handle a station leaving an 11g network.\n */\nvoid\nieee80211_node_leave_11g(struct ieee80211com *ic, struct ieee80211_node *ni)\n{\n    int longslotsta = 0, nonerpsta = 0;\n    \n    if (!(ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME)) {\n        /* leaving STA did not support short slot time */\n        ieee80211_iterate_nodes(ic,\n                                ieee80211_count_longslotsta, &longslotsta);\n        if (longslotsta == 1) {\n            /*\n             * All associated STAs now support short slot time, so\n             * enable this feature and give the driver a chance to\n             * reconfigure the hardware. Notice that IBSS always\n             * use a long slot time.\n             */\n            if ((ic->ic_caps & IEEE80211_C_SHSLOT) &&\n                ic->ic_opmode != IEEE80211_M_IBSS)\n                ieee80211_set_shortslottime(ic, 1);\n        }\n        DPRINTF((\"[%s] long slot time station leaves, count %d\\n\",\n                 ether_sprintf(ni->ni_macaddr), longslotsta));\n    }\n    \n    if (!(ni->ni_flags & IEEE80211_NODE_ERP)) {\n        /* leaving STA was non-ERP */\n        ieee80211_iterate_nodes(ic,\n                                ieee80211_count_nonerpsta, &nonerpsta);\n        if (nonerpsta == 1) {\n            /*\n             * All associated STAs are now ERP capable, disable use\n             * of protection and re-enable short preamble support.\n             */\n            ic->ic_flags &= ~IEEE80211_F_USEPROT;\n            if (ic->ic_caps & IEEE80211_C_SHPREAMBLE)\n                ic->ic_flags |= IEEE80211_F_SHPREAMBLE;\n        }\n        DPRINTF((\"[%s] non-ERP station leaves, count %d\\n\",\n                 ether_sprintf(ni->ni_macaddr), nonerpsta));\n    }\n}\n\n/*\n * Handle bookkeeping for station deauthentication/disassociation\n * when operating as an ap.\n */\nvoid\nieee80211_node_leave(struct ieee80211com *ic, struct ieee80211_node *ni)\n{\n    if (ic->ic_opmode != IEEE80211_M_HOSTAP)\n        panic(\"not in ap mode, mode %u\", ic->ic_opmode);\n    \n    if (ni->ni_state == IEEE80211_STA_COLLECT)\n        return;\n    /*\n     * If node wasn't previously associated all we need to do is\n     * reclaim the reference.\n     */\n    if (ni->ni_associd == 0) {\n        ieee80211_node_newstate(ni, IEEE80211_STA_COLLECT);\n        return;\n    }\n    \n    if (ni->ni_pwrsave == IEEE80211_PS_DOZE)\n        ni->ni_pwrsave = IEEE80211_PS_AWAKE;\n    \n    if (mq_purge(&ni->ni_savedq) > 0) {\n        if (ic->ic_set_tim != NULL)\n            (*ic->ic_set_tim)(ic, ni->ni_associd, 0);\n    }\n    \n    if (ic->ic_flags & IEEE80211_F_RSNON)\n        ieee80211_node_leave_rsn(ic, ni);\n    \n    if (ic->ic_curmode == IEEE80211_MODE_11G ||\n        (ic->ic_curmode == IEEE80211_MODE_11N &&\n         IEEE80211_IS_CHAN_2GHZ(ic->ic_bss->ni_chan)))\n        ieee80211_node_leave_11g(ic, ni);\n    \n    if (ni->ni_flags & IEEE80211_NODE_HT)\n        ieee80211_node_leave_ht(ic, ni);\n    \n    if (ni->ni_flags & IEEE80211_NODE_VHT)\n        ieee80211_node_leave_vht(ic, ni);\n\n    if (ic->ic_node_leave != NULL)\n        (*ic->ic_node_leave)(ic, ni);\n    \n    ieee80211_node_newstate(ni, IEEE80211_STA_COLLECT);\n    \n#if NBRIDGE > 0\n    /*\n     * If the parent interface is a bridge port, delete\n     * any dynamically learned address for this node.\n     */\n    if (ic->ic_if.if_bridgeidx != 0)\n        bridge_update(&ic->ic_if,\n                      (struct ether_addr *)ni->ni_macaddr, 1);\n#endif\n}\n\nstatic int\nieee80211_do_slow_print(struct ieee80211com *ic, int *did_print)\n{\n    static const struct timeval merge_print_intvl = {\n        .tv_sec = 1, .tv_usec = 0\n    };\n    if ((ic->ic_if.if_flags & IFF_LINK0) == 0)\n        return 0;\n    if (!*did_print && (ic->ic_if.if_flags & IFF_DEBUG) == 0 &&\n        !ratecheck(&ic->ic_last_merge_print, &merge_print_intvl))\n        return 0;\n    \n    *did_print = 1;\n    return 1;\n}\n\n/* ieee80211_ibss_merge helps merge 802.11 ad hoc networks.  The\n * convention, set by the Wireless Ethernet Compatibility Alliance\n * (WECA), is that an 802.11 station will change its BSSID to match\n * the \"oldest\" 802.11 ad hoc network, on the same channel, that\n * has the station's desired SSID.  The \"oldest\" 802.11 network\n * sends beacons with the greatest TSF timestamp.\n *\n * Return ENETRESET if the BSSID changed, 0 otherwise.\n *\n * XXX Perhaps we should compensate for the time that elapses\n * between the MAC receiving the beacon and the host processing it\n * in ieee80211_ibss_merge.\n */\nint\nieee80211_ibss_merge(struct ieee80211com *ic, struct ieee80211_node *ni,\n                     u_int64_t local_tsft)\n{\n    u_int64_t beacon_tsft;\n    int did_print = 0, sign;\n    union {\n        u_int64_t\tword;\n        u_int8_t\ttstamp[8];\n    } u;\n    \n    /* ensure alignment */\n    (void)memcpy(&u, &ni->ni_tstamp[0], sizeof(u));\n    beacon_tsft = letoh64(u.word);\n    \n    /* we are faster, let the other guy catch up */\n    if (beacon_tsft < local_tsft)\n        sign = -1;\n    else\n        sign = 1;\n    \n    if (IEEE80211_ADDR_EQ(ni->ni_bssid, ic->ic_bss->ni_bssid)) {\n        if (!ieee80211_do_slow_print(ic, &did_print))\n            return 0;\n        XYLog(\"%s: tsft offset %s%llu\\n\", ic->ic_if.if_xname,\n              (sign < 0) ? \"-\" : \"\",\n              (sign < 0)\n              ? (local_tsft - beacon_tsft)\n              : (beacon_tsft - local_tsft));\n        return 0;\n    }\n    \n    if (sign < 0)\n        return 0;\n    \n    if (ieee80211_match_bss(ic, ni, 0) != 0)\n        return 0;\n    \n    if (ieee80211_do_slow_print(ic, &did_print)) {\n        XYLog(\"%s: ieee80211_ibss_merge: bssid mismatch %s\\n\",\n              ic->ic_if.if_xname, ether_sprintf(ni->ni_bssid));\n        XYLog(\"%s: my tsft %llu beacon tsft %llu\\n\",\n              ic->ic_if.if_xname, local_tsft, beacon_tsft);\n        XYLog(\"%s: sync TSF with %s\\n\",\n              ic->ic_if.if_xname, ether_sprintf(ni->ni_macaddr));\n    }\n    \n    ic->ic_flags &= ~IEEE80211_F_SIBSS;\n    \n    /* negotiate rates with new IBSS */\n    ieee80211_fix_rate(ic, ni, IEEE80211_F_DOFRATE |\n                       IEEE80211_F_DONEGO | IEEE80211_F_DODEL);\n    if (ni->ni_rates.rs_nrates == 0) {\n        if (ieee80211_do_slow_print(ic, &did_print)) {\n            XYLog(\"%s: rates mismatch, BSSID %s\\n\",\n                  ic->ic_if.if_xname, ether_sprintf(ni->ni_bssid));\n        }\n        return 0;\n    }\n    \n    if (ieee80211_do_slow_print(ic, &did_print)) {\n        XYLog(\"%s: sync BSSID %s -> \",\n              ic->ic_if.if_xname, ether_sprintf(ic->ic_bss->ni_bssid));\n        XYLog(\"%s \", ether_sprintf(ni->ni_bssid));\n        XYLog(\"(from %s)\\n\", ether_sprintf(ni->ni_macaddr));\n    }\n    \n    ieee80211_node_newstate(ni, IEEE80211_STA_BSS);\n    (*ic->ic_node_copy)(ic, ic->ic_bss, ni);\n    \n    return ENETRESET;\n}\n\nvoid\nieee80211_set_tim(struct ieee80211com *ic, int aid, int set)\n{\n    if (set)\n        setbit(ic->ic_tim_bitmap, aid & ~0xc000);\n    else\n        clrbit(ic->ic_tim_bitmap, aid & ~0xc000);\n}\n\n/*\n * This function shall be called by drivers immediately after every DTIM.\n * Transmit all group addressed MSDUs buffered at the AP.\n */\nvoid\nieee80211_notify_dtim(struct ieee80211com *ic)\n{\n    /* NB: group addressed MSDUs are buffered in ic_bss */\n    struct ieee80211_node *ni = ic->ic_bss;\n    struct _ifnet *ifp = &ic->ic_if;\n    struct ieee80211_frame *wh;\n    mbuf_t m;\n    \n    _KASSERT(ic->ic_opmode == IEEE80211_M_HOSTAP);\n    \n    while ((m = mq_dequeue(&ni->ni_savedq)) != NULL) {\n        if (!mq_empty(&ni->ni_savedq)) {\n            /* more queued frames, set the more data bit */\n            wh = mtod(m, struct ieee80211_frame *);\n            wh->i_fc[1] |= IEEE80211_FC1_MORE_DATA;\n        }\n        mq_enqueue(&ic->ic_pwrsaveq, m);\n        (*ifp->if_start)(ifp);\n    }\n    /* XXX assumes everything has been sent */\n    ic->ic_tim_mcast_pending = 0;\n}\n#endif\t/* IEEE80211_STA_ONLY */\n\n/*\n * Compare nodes in the tree by lladdr\n */\nint\nieee80211_node_cmp(const struct ieee80211_node *b1,\n                   const struct ieee80211_node *b2)\n{\n    return (memcmp(b1->ni_macaddr, b2->ni_macaddr, IEEE80211_ADDR_LEN));\n}\n\n/*\n * Compare nodes in the tree by essid\n */\nint\nieee80211_ess_cmp(const struct ieee80211_ess_rbt *b1,\n                  const struct ieee80211_ess_rbt *b2)\n{\n    return (memcmp(b1->essid, b2->essid, IEEE80211_NWID_LEN));\n}\n\n/*\n * Generate red-black tree function logic\n */\nRB_GENERATE(ieee80211_tree, ieee80211_node, ni_node, ieee80211_node_cmp);\nRB_GENERATE(ieee80211_ess_tree, ieee80211_ess_rbt, ess_rbt, ieee80211_ess_cmp);\n"
  },
  {
    "path": "itl80211/openbsd/net80211/ieee80211_node.h",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n/*\t$OpenBSD: ieee80211_node.h,v 1.87 2020/07/21 08:38:59 stsp Exp $\t*/\n/*\t$NetBSD: ieee80211_node.h,v 1.9 2004/04/30 22:57:32 dyoung Exp $\t*/\n\n/*-\n * Copyright (c) 2001 Atsushi Onoe\n * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. The name of the author may not be used to endorse or promote products\n *    derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * $FreeBSD: src/sys/net80211/ieee80211_node.h,v 1.10 2004/04/05 22:10:26 sam Exp $\n */\n#ifndef _NET80211_IEEE80211_NODE_H_\n#define _NET80211_IEEE80211_NODE_H_\n\n#include <sys/tree.h>\n#include <sys/_mbuf.h>\n#include <libkern/OSAtomic.h>\n\n#define\tIEEE80211_PSCAN_WAIT\t5\t\t/* passive scan wait */\n#define\tIEEE80211_TRANS_WAIT\t5\t\t/* transition wait */\n#define\tIEEE80211_INACT_WAIT\t5\t\t/* inactivity timer interval */\n#define\tIEEE80211_INACT_MAX\t(300/IEEE80211_INACT_WAIT)\n#define\tIEEE80211_CACHE_SIZE\t200\n#define\tIEEE80211_CACHE_WAIT\t30\n#define\tIEEE80211_INACT_SCAN\t10\t\t/* for station mode */\n\nstruct ieee80211_rateset {\n\tu_int8_t\t\trs_nrates;\n\tu_int8_t\t\trs_rates[IEEE80211_RATE_MAXSIZE];\n};\n\nextern const struct ieee80211_rateset ieee80211_std_rateset_11a;\nextern const struct ieee80211_rateset ieee80211_std_rateset_11b;\nextern const struct ieee80211_rateset ieee80211_std_rateset_11g;\n\n/* Index into ieee80211_std_rateset_11n[] array. */\n#define IEEE80211_HT_RATESET_SISO\t0\n#define IEEE80211_HT_RATESET_SISO_SGI\t1\n#define IEEE80211_HT_RATESET_MIMO2\t2\n#define IEEE80211_HT_RATESET_MIMO2_SGI\t3\n#define IEEE80211_HT_RATESET_MIMO3\t4\n#define IEEE80211_HT_RATESET_MIMO3_SGI\t5\n#define IEEE80211_HT_RATESET_MIMO4\t6\n#define IEEE80211_HT_RATESET_MIMO4_SGI\t7\n#define IEEE80211_HT_RATESET_CBW40_SISO    8\n#define IEEE80211_HT_RATESET_CBW40_SISO_SGI    9\n#define IEEE80211_HT_RATESET_CBW40_MIMO2    10\n#define IEEE80211_HT_RATESET_CBW40_MIMO2_SGI    11\n#define IEEE80211_HT_RATESET_CBW40_MIMO3    12\n#define IEEE80211_HT_RATESET_CBW40_MIMO3_SGI    13\n#define IEEE80211_HT_RATESET_CBW40_MIMO4    14\n#define IEEE80211_HT_RATESET_CBW40_MIMO4_SGI    15\n#define IEEE80211_HT_NUM_RATESETS    16\n\n/* Maximum number of rates in a HT rateset. */\n#define IEEE80211_HT_RATESET_MAX_NRATES\t8\n\n/* Number of MCS indices represented by struct ieee80211_ht_rateset. */\n#define IEEE80211_HT_RATESET_NUM_MCS 32\n\nstruct ieee80211_ht_rateset {\n\tuint32_t nrates;\n\tuint32_t rates[IEEE80211_HT_RATESET_MAX_NRATES]; /* 500 kbit/s units */\n\n\t/*\n\t * This bitmask can only express MCS 0 - MCS 31.\n\t * IEEE 802.11 defined 77 HT MCS in total but common hardware\n\t * implementations tend to support MCS index 0 through 31 only.\n\t */\n\tuint32_t mcs_mask;\n\n\t/* Range of MCS indices represented in this rateset. */\n\tint min_mcs;\n\tint max_mcs;\n\n\tint sgi;\n};\n\nextern const struct ieee80211_ht_rateset ieee80211_std_ratesets_11n[];\n\n/* Index into ieee80211_std_rateset_11ac[] array. */\n#define IEEE80211_VHT_RATESET_SISO\t\t0\n#define IEEE80211_VHT_RATESET_SISO_SGI\t\t1\n#define IEEE80211_VHT_RATESET_MIMO2\t\t2\n#define IEEE80211_VHT_RATESET_MIMO2_SGI\t\t3\n#define IEEE80211_VHT_RATESET_SISO_40\t\t4\n#define IEEE80211_VHT_RATESET_SISO_40_SGI\t5\n#define IEEE80211_VHT_RATESET_MIMO2_40\t\t6\n#define IEEE80211_VHT_RATESET_MIMO2_40_SGI\t7\n#define IEEE80211_VHT_RATESET_SISO_80\t\t8\n#define IEEE80211_VHT_RATESET_SISO_80_SGI\t9\n#define IEEE80211_VHT_RATESET_MIMO2_80\t\t10\n#define IEEE80211_VHT_RATESET_MIMO2_80_SGI\t11\n#define IEEE80211_VHT_RATESET_SISO_160      12\n#define IEEE80211_VHT_RATESET_SISO_160_SGI  13\n#define IEEE80211_VHT_RATESET_MIMO2_160     14\n#define IEEE80211_VHT_RATESET_MIMO2_160_SGI 15\n#define IEEE80211_VHT_NUM_RATESETS\t\t16\n\n/* Maximum number of rates in a VHT rateset. */\n#define IEEE80211_VHT_RATESET_MAX_NRATES\t10\n\n/* Number of MCS indices represented by struct ieee80211_vht_rateset. */\n#define IEEE80211_VHT_RATESET_NUM_MCS   IEEE80211_VHT_RATESET_MAX_NRATES\n\nstruct ieee80211_vht_rateset {\n\tuint32_t nrates;\n\tuint32_t rates[IEEE80211_VHT_RATESET_MAX_NRATES]; /* 500 kbit/s units */\n\n\t/* Number of spatial streams used by rates in this rateset. */\n\tint num_ss;\n\n\tint sgi;\n};\n\nextern const struct ieee80211_vht_rateset ieee80211_std_ratesets_11ac[];\n\n#define IEEE80211_HE_RATESET_SISO        0\n#define IEEE80211_HE_RATESET_MIMO2        1\n#define IEEE80211_HE_RATESET_SISO_40        2\n#define IEEE80211_HE_RATESET_MIMO2_40        3\n#define IEEE80211_HE_RATESET_SISO_80        4\n#define IEEE80211_HE_RATESET_MIMO2_80        5\n#define IEEE80211_HE_RATESET_SISO_160      6\n#define IEEE80211_HE_RATESET_MIMO2_160     7\n#define IEEE80211_HE_NUM_RATESETS        8\n\n/* Maximum number of rates in a HT rateset. */\n#define IEEE80211_HE_RATESET_MAX_NRATES    12\n\n/* Number of MCS indices represented by struct ieee80211_he_rateset. */\n#define IEEE80211_HE_RATESET_NUM_MCS    IEEE80211_HE_RATESET_MAX_NRATES\n\nstruct ieee80211_he_rateset {\n    uint32_t nrates;\n    uint32_t rates[IEEE80211_HE_RATESET_MAX_NRATES]; /* 500 kbit/s units */\n\n    /* Number of spatial streams used by rates in this rateset. */\n    int num_ss;\n};\n\nextern const struct ieee80211_he_rateset ieee80211_std_ratesets_11ax[];\n\nenum ieee80211_node_state {\n\tIEEE80211_STA_CACHE,\t/* cached node */\n\tIEEE80211_STA_BSS,\t/* ic->ic_bss, the network we joined */\n\tIEEE80211_STA_AUTH,\t/* successfully authenticated */\n\tIEEE80211_STA_ASSOC,\t/* successfully associated */\n\tIEEE80211_STA_COLLECT\t/* This node remains in the cache while\n\t\t\t\t * the driver sends a de-auth message;\n\t\t\t\t * afterward it should be freed to make room\n\t\t\t\t * for a new node.\n\t\t\t\t */\n};\n\n#define\tieee80211_node_newstate(__ni, __state)\t\\\n\tdo {\t\t\t\t\t\\\n\t\t(__ni)->ni_state = (__state);\t\\\n\t} while (0)\n\nenum ieee80211_node_psstate {\n\tIEEE80211_PS_AWAKE,\n\tIEEE80211_PS_DOZE\n};\n\n#define\tIEEE80211_PS_MAX_QUEUE\t50\t/* maximum saved packets */\n\n/* Authenticator state machine: 4-Way Handshake (see 8.5.6.1.1) */\nenum {\n\tRSNA_INITIALIZE,\n\tRSNA_AUTHENTICATION,\n\tRSNA_AUTHENTICATION_2,\n\tRSNA_INITPMK,\n\tRSNA_INITPSK,\n\tRSNA_PTKSTART,\n\tRSNA_PTKCALCNEGOTIATING,\n\tRSNA_PTKCALCNEGOTIATING_2,\n\tRSNA_PTKINITNEGOTIATING,\n\tRSNA_PTKINITDONE,\n\tRSNA_DISCONNECT,\n\tRSNA_DISCONNECTED\n};\n\n/* Authenticator state machine: Group Key Handshake (see 8.5.6.1.2) */\nenum {\n\tRSNA_IDLE,\n\tRSNA_REKEYNEGOTIATING,\n\tRSNA_REKEYESTABLISHED,\n\tRSNA_KEYERROR\n};\n\n/* Supplicant state machine: 4-Way Handshake (not documented in standard) */\nenum {\n\tRSNA_SUPP_INITIALIZE,\t\t/* not expecting any messages */\n\tRSNA_SUPP_PTKSTART,\t\t/* awaiting handshake message 1 */\n\tRSNA_SUPP_PTKNEGOTIATING,\t/* got message 1 and derived PTK */\n\tRNSA_SUPP_PTKDONE\t\t/* got message 3 and authenticated AP */\n};\n\nstruct ieee80211_rxinfo {\n\tu_int32_t\t\trxi_flags;\n\tu_int32_t\t\trxi_tstamp;\n\tint             rxi_rssi;\n    uint8_t         rxi_chan;\n};\n#define IEEE80211_RXI_HWDEC\t\t0x00000001\n#define IEEE80211_RXI_AMPDU_DONE\t0x00000002\n#define IEEE80211_RXI_HWDEC_SAME_PN    0x00000004\n#define IEEE80211_RXI_SAME_SEQ         0x00000008\n\n/* Block Acknowledgement Record */\nstruct ieee80211_tx_ba {\n\tstruct ieee80211_node\t*ba_ni;\t/* backpointer for callbacks */\n\tCTimeout*\t\tba_to;\n\tint\t\t\tba_timeout_val;\n\tint\t\t\tba_state;\n#define IEEE80211_BA_INIT\t0\n#define IEEE80211_BA_REQUESTED\t1\n#define IEEE80211_BA_AGREED\t2\n\n\t/* ADDBA parameter set field for this BA agreement. */\n\tu_int16_t\t\tba_params;\n\n\t/* These values are IEEE802.11 frame sequence numbers (0x0-0xfff) */\n\tu_int16_t\t\tba_winstart;\n\tu_int16_t\t\tba_winend;\n\n\t/* Number of A-MPDU subframes in reorder buffer. */\n\tu_int16_t\t\tba_winsize;\n#define IEEE80211_BA_MAX_WINSZ\t64\t/* corresponds to maximum ADDBA BUFSZ */\n\n\tu_int8_t\t\tba_token;\n\n\t/* Bitmap for ACK'd frames in the current BA window. */\n\tuint64_t\t\tba_bitmap;\n};\n\nstruct ieee80211_ba_buf {\n    mbuf_t m;\n    struct ieee80211_rxinfo    rxi;\n};\n\nstruct ieee80211_rx_ba {\n\tstruct ieee80211_node\t*ba_ni;\t/* backpointer for callbacks */\n\tstruct ieee80211_ba_buf\t*ba_buf;\n\tCTimeout*\t\tba_to;\n\tint\t\t\tba_timeout_val;\n\tint\t\t\tba_state;\n\tu_int16_t\t\tba_params;\n\tu_int16_t\t\tba_winstart;\n\tu_int16_t\t\tba_winend;\n\tu_int16_t\t\tba_winsize;\n\tu_int16_t\t\tba_head;\n\tCTimeout*\t\tba_gap_to;\n#define IEEE80211_BA_GAP_TIMEOUT\t300 /* msec */\n\n\t/*\n\t * Counter for frames forced to wait in the reordering buffer\n\t * due to a leading gap caused by one or more missing frames.\n\t */\n\tint\t\t\tba_gapwait;\n\n\t/* Counter for consecutive frames which missed the BA window. */\n\tint\t\t\tba_winmiss;\n\t/* Sequence number of previous frame which missed the BA window. */\n\tuint16_t\t\tba_missedsn;\n\t/* Window moves forward after this many frames have missed it. */\n#define IEEE80211_BA_MAX_WINMISS\t8\n\n\tuint8_t\t\t\tba_token;\n};\n\n/*\n * Node specific information.  Note that drivers are expected\n * to derive from this structure to add device-specific per-node\n * state.  This is done by overriding the ic_node_* methods in\n * the ieee80211com structure.\n */\nstruct ieee80211_node {\n\tRB_ENTRY(ieee80211_node)\tni_node;\n\n\tstruct ieee80211com\t*ni_ic;\t\t/* back-pointer */\n\n\tu_int\t\t\tni_refcnt;\n\tu_int\t\t\tni_scangen;\t/* gen# for timeout scan */\n\n\t/* hardware */\n\tu_int32_t\t\tni_rstamp;\t/* recv timestamp */\n\tu_int8_t\t\tni_rssi;\t/* recv ssi */\n\n\t/* header */\n\tu_int8_t\t\tni_macaddr[IEEE80211_ADDR_LEN];\n\tu_int8_t\t\tni_bssid[IEEE80211_ADDR_LEN];\n\n\t/* beacon, probe response */\n\tu_int8_t\t\tni_tstamp[8];\t/* from last rcv'd beacon */\n\tu_int16_t\t\tni_intval;\t/* beacon interval */\n\tu_int16_t\t\tni_capinfo;\t/* capabilities */\n\tu_int8_t\t\tni_esslen;\n\tu_int8_t\t\tni_essid[IEEE80211_NWID_LEN];\n\tstruct ieee80211_rateset ni_rates;\t/* negotiated rate set */\n\tu_int8_t\t\t*ni_country;\t/* country information XXX */\n\tstruct ieee80211_channel *ni_chan;\n\tu_int8_t\t\tni_erp;\t\t/* 11g only */\n#ifdef AIRPORT\n    u_int64_t       ni_age_ts;\n#endif\n\n\t/* DTIM and contention free period (CFP) */\n\tu_int8_t\t\tni_dtimcount;\n\tu_int8_t\t\tni_dtimperiod;\n#ifdef notyet\n\tu_int8_t\t\tni_cfpperiod;\t/* # of DTIMs between CFPs */\n\tu_int16_t\t\tni_cfpduremain;\t/* remaining cfp duration */\n\tu_int16_t\t\tni_cfpmaxduration;/* max CFP duration in TU */\n\tu_int16_t\t\tni_nextdtim;\t/* time to next DTIM */\n\tu_int16_t\t\tni_timoffset;\n#endif\n\n\t/* power saving mode */\n\tu_int8_t\t\tni_pwrsave;\n\tstruct mbuf_queue\tni_savedq;\t/* packets queued for pspoll */\n\n\t/* RSN */\n\tCTimeout*\t\tni_eapol_to;\n\tu_int\t\t\tni_rsn_state;\n\tu_int\t\t\tni_rsn_supp_state;\n\tu_int\t\t\tni_rsn_gstate;\n\tu_int\t\t\tni_rsn_retries;\n\tu_int\t\t\tni_supported_rsnprotos;\n\tu_int\t\t\tni_rsnprotos;\n\tu_int\t\t\tni_supported_rsnakms;\n\tu_int\t\t\tni_rsnakms;\n\tu_int\t\t\tni_rsnciphers;\n\tenum ieee80211_cipher\tni_rsngroupcipher;\n\tenum ieee80211_cipher\tni_rsngroupmgmtcipher;\n\tu_int16_t\t\tni_rsncaps;\n\tenum ieee80211_cipher\tni_rsncipher;\n\tu_int8_t\t\tni_nonce[EAPOL_KEY_NONCE_LEN];\n\tu_int8_t\t\tni_pmk[IEEE80211_PMK_LEN];\n\tu_int8_t\t\tni_pmkid[IEEE80211_PMKID_LEN];\n\tu_int64_t\t\tni_replaycnt;\n\tu_int8_t\t\tni_replaycnt_ok;\n\tu_int64_t\t\tni_reqreplaycnt;\n\tu_int8_t\t\tni_reqreplaycnt_ok;\n\tu_int8_t\t\t*ni_rsnie;\n    u_int8_t        *ni_rsnie_tlv;\n    uint32_t        ni_rsnie_tlv_len;\n\tstruct ieee80211_key\tni_pairwise_key;\n\tstruct ieee80211_ptk\tni_ptk;\n\tu_int8_t\t\tni_key_count;\n\tint\t\t\tni_port_valid;\n\n\t/* SA Query */\n\tu_int16_t\t\tni_sa_query_trid;\n\tCTimeout*\t\tni_sa_query_to;\n\tint\t\t\tni_sa_query_count;\n\n\t/* HT capabilities */\n\tuint16_t\t\tni_htcaps;\n\tuint8_t\t\t\tni_ampdu_param;\n\tuint8_t\t\t\tni_rxmcs[howmany(80,NBBY)];\n\tuint16_t\t\tni_max_rxrate;\t/* in Mb/s, 0 <= rate <= 1023 */\n\tuint8_t\t\t\tni_tx_mcs_set;\n\tuint16_t\t\tni_htxcaps;// extended_ht_cap_info\n\tuint32_t\t\tni_txbfcaps;\n\tuint8_t\t\t\tni_aselcaps;// antenna_selection_info\n\n\t/* HT operation */\n\tuint8_t\t\t\tni_primary_chan; /* XXX corresponds to ni_chan */\n\tuint8_t\t\t\tni_htop0;// ht_param\n\tuint16_t\t\tni_htop1;// operation_mode\n\tuint16_t\t\tni_htop2;// stbc_param\n\tuint8_t\t\t\tni_basic_mcs[howmany(128,NBBY)];\n\n    uint8_t            ni_ht2ndchan;    /* HT 2nd channel */\n    uint8_t            ni_chw;        /* negotiated channel width */\n    \n    /* VHT state */\n    uint32_t        ni_vhtcaps;\n    uint16_t        ni_vht_basicmcs;\n    uint16_t        ni_vht_pad2;\n    struct ieee80211_vht_mcs_info    ni_vht_mcsinfo;\n    uint8_t            ni_vht_chan1;    /* 20/40/80/160 - VHT chan1 */\n    uint8_t            ni_vht_chan2;    /* 80+80 - VHT chan2 */\n    uint8_t            ni_vht_chanwidth;    /* IEEE80211_VHT_CHANWIDTH_ */\n    uint8_t            ni_vht_pad1;\n    uint32_t        ni_vht_spare[8];\n    \n    /* HE state */\n    struct ieee80211_he_cap_elem ni_he_cap_elem;   /* Fixed portion of the HE capabilities element. */\n    struct ieee80211_he_mcs_nss_supp ni_he_mcs_nss_supp;   /* The supported NSS/MCS combinations. */\n    uint8_t ni_ppe_thres[IEEE80211_HE_PPE_THRES_MAX_LEN]; /* Holds the PPE Thresholds data. */\n    uint32_t        ni_he_oper_params;\n    uint16_t        ni_he_oper_nss_set;\n    uint8_t         ni_he_optional[8];\n    \n\t/* Timeout handlers which trigger Tx Block Ack negotiation. */\n\tCTimeout*\t\tni_addba_req_to[IEEE80211_NUM_TID];\n\tint\t\t\tni_addba_req_intval[IEEE80211_NUM_TID];\n#define IEEE80211_ADDBA_REQ_INTVAL_MAX 30\t/* in seconds */\n\n\t/* Block Ack records */\n\tstruct ieee80211_tx_ba\tni_tx_ba[IEEE80211_NUM_TID];\n\tstruct ieee80211_rx_ba\tni_rx_ba[IEEE80211_NUM_TID];\n\n\tint\t\t\tni_txmcs;\t/* current MCS used for TX */\n\tint\t\t\tni_vht_ss;\t/* VHT # spatial streams */\n    \n    uint8_t     ni_rx_nss;\n\n\t/* others */\n\tu_int16_t\t\tni_associd;\t/* assoc response */\n\tu_int16_t\t\tni_txseq;\t/* seq to be transmitted */\n\tu_int16_t\t\tni_rxseq;\t/* seq previous received */\n\tu_int16_t\t\tni_qos_txseqs[IEEE80211_NUM_TID];\n\tu_int16_t\t\tni_qos_rxseqs[IEEE80211_NUM_TID];\n\tint\t\t\tni_fails;\t/* failure count to associate */\n\tuint32_t\t\tni_assoc_fail;\t/* assoc failure reasons */\n#define IEEE80211_NODE_ASSOCFAIL_CHAN\t\t0x01\n#define IEEE80211_NODE_ASSOCFAIL_IBSS\t\t0x02\n#define IEEE80211_NODE_ASSOCFAIL_PRIVACY\t0x04\n#define IEEE80211_NODE_ASSOCFAIL_BASIC_RATE\t0x08\n#define IEEE80211_NODE_ASSOCFAIL_ESSID\t\t0x10\n#define IEEE80211_NODE_ASSOCFAIL_BSSID\t\t0x20\n#define IEEE80211_NODE_ASSOCFAIL_WPA_PROTO\t0x40\n#define IEEE80211_NODE_ASSOCFAIL_WPA_KEY\t0x80\n\n\tint\t\t\tni_inact;\t/* inactivity mark count */\n\tint\t\t\tni_txrate;\t/* index to ni_rates[] */\n\tint\t\t\tni_state;\n\n\tu_int32_t\t\tni_flags;\t/* special-purpose state */\n#define IEEE80211_NODE_ERP\t\t0x0001\n#define IEEE80211_NODE_QOS\t\t0x0002\n#define IEEE80211_NODE_REKEY\t\t0x0004\t/* GTK rekeying in progress */\n#define IEEE80211_NODE_RXPROT\t\t0x0008\t/* RX protection ON */\n#define IEEE80211_NODE_TXPROT\t\t0x0010\t/* TX protection ON */\n#define IEEE80211_NODE_TXRXPROT\t\\\n\t(IEEE80211_NODE_TXPROT | IEEE80211_NODE_RXPROT)\n#define IEEE80211_NODE_RXMGMTPROT\t0x0020\t/* RX MMPDU protection ON */\n#define IEEE80211_NODE_TXMGMTPROT\t0x0040\t/* TX MMPDU protection ON */\n#define IEEE80211_NODE_MFP\t\t0x0080\t/* MFP negotiated */\n#define IEEE80211_NODE_PMK\t\t0x0100\t/* ni_pmk set */\n#define IEEE80211_NODE_PMKID\t\t0x0200\t/* ni_pmkid set */\n#define IEEE80211_NODE_HT\t\t0x0400\t/* HT negotiated */\n#define IEEE80211_NODE_SA_QUERY\t\t0x0800\t/* SA Query in progress */\n#define IEEE80211_NODE_SA_QUERY_FAILED\t0x1000\t/* last SA Query failed */\n#define IEEE80211_NODE_RSN_NEW_PTK\t0x2000\t/* expecting a new PTK */\n#define IEEE80211_NODE_HT_SGI20\t\t0x4000\t/* SGI on 20 MHz negotiated */ \n#define IEEE80211_NODE_HT_SGI40\t\t0x8000\t/* SGI on 40 MHz negotiated */ \n#define IEEE80211_NODE_VHT\t\t0x10000\t/* VHT negotiated */\n#define IEEE80211_NODE_HTCAP\t\t0x20000\t/* claims to support HT */\n#define IEEE80211_NODE_VHTCAP       0x40000 /* claims to support VHT */\n#define IEEE80211_NODE_VHT_SGI80    0x80000    /* SGI on 80 MHz negotiated */\n#define IEEE80211_NODE_VHT_SGI160   0x100000    /* SGI on 160 MHz negotiated */\n#define IEEE80211_NODE_HE       0x200000    /* HE negotiated */\n\n\t/* If not NULL, this function gets called when ni_refcnt hits zero. */\n\tvoid\t\t\t(*ni_unref_cb)(struct ieee80211com *,\n\t\t\t\t\tstruct ieee80211_node *);\n\tvoid *\t\t\tni_unref_arg;\n\tsize_t \t\t\tni_unref_arg_size;\n    \n#ifdef AIRPORT\n    uint8_t verb[0x1024];//冗余信息 zxy\n#endif\n};\n\nRB_HEAD(ieee80211_tree, ieee80211_node);\n\nstruct ieee80211_ess_rbt {\n\tRB_ENTRY(ieee80211_ess_rbt)\t ess_rbt;\n\tu_int8_t\t\t\t esslen;\n\tu_int8_t\t\t\t essid[IEEE80211_NWID_LEN];\n\tstruct ieee80211_node\t\t*ni2;\n\tstruct ieee80211_node\t\t*ni5;\n\tstruct ieee80211_node\t\t*ni;\n};\n\nRB_HEAD(ieee80211_ess_tree, ieee80211_ess_rbt);\n\nstatic inline void\nieee80211_node_incref(struct ieee80211_node *ni)\n{\n    int        s;\n\n    s = splnet();\n    ni->ni_refcnt++;\n    splx(s);\n}\n\nstatic inline u_int\nieee80211_node_decref(struct ieee80211_node *ni)\n{\n    u_int        refcnt;\n    int         s;\n\n    s = splnet();\n    refcnt = --ni->ni_refcnt;\n    splx(s);\n    return refcnt;\n}\n\nstatic inline struct ieee80211_node *\nieee80211_ref_node(struct ieee80211_node *ni)\n{\n\tieee80211_node_incref(ni);\n\treturn ni;\n}\n\nstatic inline void\nieee80211_unref_node(struct ieee80211_node **ni)\n{\n\tieee80211_node_decref(*ni);\n\t*ni = NULL;\t\t\t/* guard against use */\n}\n\n/* \n * Check if the peer supports HT.\n * Require a HT capabilities IE and at least one of the mandatory MCS.\n * MCS 0-7 are mandatory but some APs have particular MCS disabled.\n */\nstatic inline int\nieee80211_node_supports_ht(struct ieee80211_node *ni)\n{\n\treturn ((ni->ni_flags & IEEE80211_NODE_HTCAP) &&\n\t    ni->ni_rxmcs[0] & 0xff);\n}\n\nstatic inline int\nieee80211_node_supports_vht(struct ieee80211_node *ni)\n{\n    return ((ni->ni_flags & IEEE80211_NODE_VHTCAP));\n}\n\n/* Check if the peer supports HT short guard interval (SGI) on 20 MHz. */\nstatic inline int\nieee80211_node_supports_ht_sgi20(struct ieee80211_node *ni)\n{\n\treturn ieee80211_node_supports_ht(ni) &&\n\t    (ni->ni_htcaps & IEEE80211_HTCAP_SGI20);\n}\n\n/* Check if the peer supports HT short guard interval (SGI) on 40 MHz. */\nstatic inline int\nieee80211_node_supports_ht_sgi40(struct ieee80211_node *ni)\n{\n\treturn ieee80211_node_supports_ht(ni) &&\n\t    (ni->ni_htcaps & IEEE80211_HTCAP_SGI40);\n}\n\n/* Check if the peer can receive frames sent on a 40 MHz channel. */\nstatic inline int\nieee80211_node_supports_ht_chan40(struct ieee80211_node *ni)\n{\n    return (ieee80211_node_supports_ht(ni) &&\n        (ni->ni_htcaps & IEEE80211_HTCAP_CBW20_40) &&\n        (ni->ni_htop0 & IEEE80211_HTOP0_CHW));\n}\n\nstatic inline int\nieee80211_node_supports_vht_sgi80(struct ieee80211_node *ni)\n{\n    return ieee80211_node_supports_vht(ni) &&\n        (ni->ni_vhtcaps & IEEE80211_VHTCAP_SHORT_GI_80);\n}\n\nstatic inline int\nieee80211_node_supports_vht_sgi160(struct ieee80211_node *ni)\n{\n    return ieee80211_node_supports_vht(ni) &&\n        (ni->ni_vhtcaps & IEEE80211_VHTCAP_SHORT_GI_160);\n}\n\nstatic inline int\nieee80211_node_supports_sgi(struct ieee80211_node *ni)\n{\n    if (ni->ni_flags & IEEE80211_NODE_HE)\n        return 0;\n    if (ni->ni_flags & IEEE80211_NODE_VHT) {\n        switch (ni->ni_chw) {\n            case IEEE80211_CHAN_WIDTH_20:\n                return ieee80211_node_supports_ht_sgi20(ni);\n            case IEEE80211_CHAN_WIDTH_40:\n                return ieee80211_node_supports_ht_sgi40(ni);\n            case IEEE80211_CHAN_WIDTH_80:\n                return ieee80211_node_supports_vht_sgi80(ni);\n            case IEEE80211_CHAN_WIDTH_80P80:\n            case IEEE80211_CHAN_WIDTH_160:\n                return ieee80211_node_supports_vht_sgi160(ni);\n            default:\n                return false;\n        }\n    }\n    if (ni->ni_flags & IEEE80211_NODE_HT) {\n        switch (ni->ni_chw) {\n            case IEEE80211_CHAN_WIDTH_20:\n                return ieee80211_node_supports_ht_sgi20(ni);\n            case IEEE80211_CHAN_WIDTH_40:\n                return ieee80211_node_supports_ht_sgi40(ni);\n            default:\n                return false;\n        }\n    }\n    return 0;\n}\n\nstruct ieee80211com;\n\ntypedef void ieee80211_iter_func(void *, struct ieee80211_node *);\n\nvoid ieee80211_node_attach(struct _ifnet *);\nvoid ieee80211_node_lateattach(struct _ifnet *);\nvoid ieee80211_node_detach(struct _ifnet *);\n\nvoid ieee80211_begin_scan(struct _ifnet *);\nvoid ieee80211_next_scan(struct _ifnet *);\nvoid ieee80211_end_scan(struct _ifnet *);\nvoid ieee80211_reset_scan(struct _ifnet *);\nstruct ieee80211_node *ieee80211_alloc_node(struct ieee80211com *,\n\t\tconst u_int8_t *);\nstruct ieee80211_node *ieee80211_dup_bss(struct ieee80211com *,\n\t\tconst u_int8_t *);\nstruct ieee80211_node *ieee80211_find_node(struct ieee80211com *,\n\t\tconst u_int8_t *);\nvoid ieee80211_ba_del(struct ieee80211_node *);\nvoid ieee80211_ba_free(struct ieee80211_node *ni);\nstruct ieee80211_node *ieee80211_find_rxnode(struct ieee80211com *,\n\t\tconst struct ieee80211_frame *);\nstruct ieee80211_node *ieee80211_find_txnode(struct ieee80211com *,\n\t\tconst u_int8_t *);\nvoid ieee80211_release_node(struct ieee80211com *,\n\t\tstruct ieee80211_node *);\nvoid ieee80211_node_cleanup(struct ieee80211com *, struct ieee80211_node *);\nvoid ieee80211_free_allnodes(struct ieee80211com *, int);\nvoid ieee80211_iterate_nodes(struct ieee80211com *,\n\t\tieee80211_iter_func *, void *);\nvoid ieee80211_clean_cached(struct ieee80211com *);\nvoid ieee80211_clean_sta_bss_node(struct ieee80211com *);\nvoid ieee80211_clean_nodes(struct ieee80211com *, int);\nvoid ieee80211_setup_htcaps(struct ieee80211_node *, const uint8_t *,\n    uint8_t);\nvoid ieee80211_clear_htcaps(struct ieee80211_node *);\nint ieee80211_setup_htop(struct ieee80211_node *, const uint8_t *,\n    uint8_t, int);\nvoid ieee80211_setup_vhtcaps(struct ieee80211com *, struct ieee80211_node *, const uint8_t *);\nvoid ieee80211_setup_vhtopmode(struct ieee80211_node *, const uint8_t *);\nvoid ieee80211_clear_vhtcaps(struct ieee80211_node *);\nvoid ieee80211_setup_hecaps(struct ieee80211_node *, const uint8_t *,\n                           uint8_t);\nint ieee80211_setup_heop(struct ieee80211_node *, const uint8_t *,\n    uint8_t);\nint ieee80211_setup_rates(struct ieee80211com *,\n\t    struct ieee80211_node *, const u_int8_t *, const u_int8_t *, int);\nvoid ieee80211_node_trigger_addba_req(struct ieee80211_node *, int);\nint ieee80211_iserp_sta(const struct ieee80211_node *);\nvoid ieee80211_count_longslotsta(void *, struct ieee80211_node *);\nvoid ieee80211_count_nonerpsta(void *, struct ieee80211_node *);\nvoid ieee80211_count_pssta(void *, struct ieee80211_node *);\nvoid ieee80211_count_rekeysta(void *, struct ieee80211_node *);\nvoid ieee80211_node_join(struct ieee80211com *,\n\t\tstruct ieee80211_node *, int);\nvoid ieee80211_node_leave(struct ieee80211com *,\n\t\tstruct ieee80211_node *);\nint ieee80211_match_bss(struct ieee80211com *, struct ieee80211_node *, int);\nstruct ieee80211_node *ieee80211_node_choose_bss(struct ieee80211com *, int,\n\t\tstruct ieee80211_node **);\nvoid ieee80211_node_join_bss(struct ieee80211com *, struct ieee80211_node *, int force_reauth = 0);\nvoid ieee80211_create_ibss(struct ieee80211com* ,\n\t\tstruct ieee80211_channel *);\nvoid ieee80211_notify_dtim(struct ieee80211com *);\nvoid ieee80211_set_tim(struct ieee80211com *, int, int);\nvoid ieee80211_free_node(struct ieee80211com *, struct ieee80211_node *);\n\nint ieee80211_node_cmp(const struct ieee80211_node *,\n\t\tconst struct ieee80211_node *);\nint ieee80211_ess_cmp(const struct ieee80211_ess_rbt *,\n\t\tconst struct ieee80211_ess_rbt *);\nRB_PROTOTYPE(ieee80211_tree, ieee80211_node, ni_node, ieee80211_node_cmp);\nRB_PROTOTYPE(ieee80211_ess_tree, ieee80211_ess_rbt, ess_rbt, ieee80211_ess_cmp);\n\n#endif /* _NET80211_IEEE80211_NODE_H_ */\n"
  },
  {
    "path": "itl80211/openbsd/net80211/ieee80211_output.c",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n/*    $OpenBSD: ieee80211_output.c,v 1.132 2020/12/08 15:52:04 stsp Exp $    */\n/*    $NetBSD: ieee80211_output.c,v 1.13 2004/05/31 11:02:55 dyoung Exp $    */\n\n/*-\n * Copyright (c) 2001 Atsushi Onoe\n * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting\n * Copyright (c) 2007-2009 Damien Bergamini\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. The name of the author may not be used to endorse or promote products\n *    derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <sys/param.h>\n#include <sys/systm.h>\n#include <sys/mbuf.h>\n#include <sys/kernel.h>\n#include <sys/socket.h>\n#include <sys/sockio.h>\n#include <sys/endian.h>\n#include <sys/errno.h>\n#include <sys/sysctl.h>\n#include <sys/kpi_mbuf.h>\n\n#include <net/if.h>\n#include <net/if_dl.h>\n#include <net/if_media.h>\n#include <net/if_llc.h>\n#include <net/bpf.h>\n\n#include <netinet/in.h>\n#include <netinet/if_ether.h>\n#include <netinet/ip.h>\n#ifdef INET6\n#include <netinet/ip6.h>\n#endif\n\n#if NVLAN > 0\n#include <net/if_vlan_var.h>\n#endif\n\n#include <net80211/ieee80211_var.h>\n#include <net80211/ieee80211_priv.h>\n\nint\tieee80211_mgmt_output(struct _ifnet *, struct ieee80211_node *,\n\t    mbuf_t, int);\nint\tieee80211_can_use_ampdu(struct ieee80211com *,\n\t    struct ieee80211_node *);\nu_int8_t *ieee80211_add_rsn_body(u_int8_t *, struct ieee80211com *,\n\t    const struct ieee80211_node *, int);\nmbuf_t ieee80211_getmgmt(int, int, u_int);\nmbuf_t ieee80211_get_probe_req(struct ieee80211com *,\n\t    struct ieee80211_node *);\n#ifndef IEEE80211_STA_ONLY\nmbuf_t ieee80211_get_probe_resp(struct ieee80211com *,\n\t    struct ieee80211_node *);\n#endif\nmbuf_t ieee80211_get_auth(struct ieee80211com *,\n\t    struct ieee80211_node *, u_int16_t, u_int16_t);\nmbuf_t ieee80211_get_deauth(struct ieee80211com *,\n\t    struct ieee80211_node *, u_int16_t);\nmbuf_t ieee80211_get_assoc_req(struct ieee80211com *,\n\t    struct ieee80211_node *, int);\n#ifndef IEEE80211_STA_ONLY\nmbuf_t ieee80211_get_assoc_resp(struct ieee80211com *,\n\t    struct ieee80211_node *, u_int16_t);\n#endif\nmbuf_t ieee80211_get_disassoc(struct ieee80211com *,\n\t    struct ieee80211_node *, u_int16_t);\nmbuf_t ieee80211_get_addba_req(struct ieee80211com *,\n\t    struct ieee80211_node *, u_int8_t);\nmbuf_t ieee80211_get_addba_resp(struct ieee80211com *,\n\t    struct ieee80211_node *, u_int8_t, u_int8_t, u_int16_t);\nmbuf_t ieee80211_get_delba(struct ieee80211com *,\n\t    struct ieee80211_node *, u_int8_t, u_int8_t, u_int16_t);\nuint8_t *ieee80211_add_wme_info(uint8_t *, struct ieee80211com *);\n#ifndef IEEE80211_STA_ONLY\nuint8_t *ieee80211_add_wme_param(uint8_t *, struct ieee80211com *);\n#endif\nmbuf_t ieee80211_get_sa_query(struct ieee80211com *,\n\t    struct ieee80211_node *, u_int8_t);\nmbuf_t ieee80211_get_action(struct ieee80211com *,\n\t    struct ieee80211_node *, u_int8_t, u_int8_t, int);\n\n/*\n * IEEE 802.11 output routine. Normally this will directly call the\n * Ethernet output routine because 802.11 encapsulation is called\n * later by the driver. This function can be used to send raw frames\n * if the mbuf has been tagged with a 802.11 data link type.\n */\nint\nieee80211_output(struct _ifnet *ifp, mbuf_t m, struct sockaddr *dst,\n    struct rtentry *rt)\n{\n    XYLog(\"%s 啊啊啊啊\\n\", __FUNCTION__);\n\tstruct ieee80211_frame *wh;\n\tstruct m_tag *mtag;\n\tint error = 0;\n    \n    //TODO\n//\n//\t/* Interface has to be up and running */\n//\tif ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) !=\n//\t    (IFF_UP | IFF_RUNNING)) {\n//\t\terror = ENETDOWN;\n//\t\tgoto bad;\n//\t}\n//\n//\t/* Try to get the DLT from a mbuf tag */\n//\tif ((mtag = m_tag_find(m, PACKET_TAG_DLT, NULL)) != NULL) {\n//\t\tstruct ieee80211com *ic = (struct ieee80211com *)ifp;\n//\t\tu_int dlt = *(u_int *)(mtag + 1);\n//\n//\t\t/* Fallback to ethernet for non-802.11 linktypes */\n//\t\tif (!(dlt == DLT_IEEE802_11 || dlt == DLT_IEEE802_11_RADIO))\n//\t\t\tgoto fallback;\n//\n//\t\tif (mbuf_pkthdr_len(m) < sizeof(struct ieee80211_frame_min))\n//\t\t\treturn (EINVAL);\n//\t\twh = mtod(m, struct ieee80211_frame *);\n//\t\tif ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) !=\n//\t\t    IEEE80211_FC0_VERSION_0)\n//\t\t\treturn (EINVAL);\n//\t\tif (!(ic->ic_caps & IEEE80211_C_RAWCTL) &&\n//\t\t    (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==\n//\t\t    IEEE80211_FC0_TYPE_CTL)\n//\t\t\treturn (EINVAL);\n//\n//\t\treturn (if_enqueue(ifp, m));\n//\t}\n\n fallback:\n\treturn (if_enqueue(ifp, m));\n\n bad:\n\tmbuf_freem(m);\n\treturn (error);\n}\n\nconst char *\nieee80211_action_name(struct ieee80211_frame *wh)\n{\n    const u_int8_t *frm = (const uint8_t *)&wh[1];\n    const char *categ_ba_name[3] = { \"addba_req\", \"addba_resp\", \"delba\" };\n    \n    if (frm[0] == IEEE80211_CATEG_BA && frm[1] < nitems(categ_ba_name))\n        return categ_ba_name[frm[1]];\n    \n    return \"action\";\n}\n\n/*\n * Send a management frame to the specified node.  The node pointer\n * must have a reference as the pointer will be passed to the driver\n * and potentially held for a long time.  If the frame is successfully\n * dispatched to the driver, then it is responsible for freeing the\n * reference (and potentially free'ing up any associated storage).\n */\nint\nieee80211_mgmt_output(struct _ifnet *ifp, struct ieee80211_node *ni,\n    mbuf_t m, int type)\n{\n\tstruct ieee80211com *ic = (struct ieee80211com *)ifp;\n\tstruct ieee80211_frame *wh;\n\n\tif (ni == NULL)\n            panic(\"null node\");\n        ni->ni_inact = 0;\n\n        /*\n         * We want to pass the node down to the driver's start\n         * routine.  We could stick this in an m_tag and tack that\n         * on to the mbuf.  However that's rather expensive to do\n         * for every frame so instead we stuff it in a special pkthdr\n         * field.\n         */\n    mbuf_prepend(&m, sizeof(struct ieee80211_frame), MBUF_DONTWAIT);\n        if (m == NULL)\n            return ENOMEM;\n    mbuf_pkthdr_setrcvif(m, (ifnet_t)ni);\n\n        wh = mtod(m, struct ieee80211_frame *);\n        wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT | type;\n        wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;\n        *(u_int16_t *)&wh->i_dur[0] = 0;\n        *(u_int16_t *)&wh->i_seq[0] =\n            htole16(ni->ni_txseq << IEEE80211_SEQ_SEQ_SHIFT);\n        ni->ni_txseq = (ni->ni_txseq + 1) & 0xfff;\n        IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_macaddr);\n        IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_myaddr);\n        IEEE80211_ADDR_COPY(wh->i_addr3, ni->ni_bssid);\n\n        /* check if protection is required for this mgmt frame */\n        if ((ic->ic_caps & IEEE80211_C_MFP) &&\n            (type == IEEE80211_FC0_SUBTYPE_DISASSOC ||\n             type == IEEE80211_FC0_SUBTYPE_DEAUTH ||\n             type == IEEE80211_FC0_SUBTYPE_ACTION)) {\n            /*\n             * Hack: we should not set the Protected bit in outgoing\n             * group management frames, however it is used as an\n             * indication to the drivers that they must encrypt the\n             * frame.  Drivers should clear this bit from group\n             * management frames (software crypto code will do it).\n             * XXX could use an mbuf flag..\n             */\n            if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||\n                (ni->ni_flags & IEEE80211_NODE_TXMGMTPROT))\n                wh->i_fc[1] |= IEEE80211_FC1_PROTECTED;\n        }\n\n        if (ifp->if_flags & IFF_DEBUG) {\n            /* avoid to print too many frames */\n            if (\n    #ifndef IEEE80211_STA_ONLY\n                ic->ic_opmode == IEEE80211_M_IBSS ||\n    #endif\n    #ifdef IEEE80211_DEBUG\n                ieee80211_debug > 1 ||\n    #endif\n                (type & IEEE80211_FC0_SUBTYPE_MASK) !=\n                IEEE80211_FC0_SUBTYPE_PROBE_RESP) {\n                const char *subtype_name;\n                if ((type & IEEE80211_FC0_SUBTYPE_MASK) ==\n                    IEEE80211_FC0_SUBTYPE_ACTION)\n                    subtype_name = ieee80211_action_name(wh);\n                else\n                    subtype_name = ieee80211_mgt_subtype_name[\n                        (type & IEEE80211_FC0_SUBTYPE_MASK) >>\n                        IEEE80211_FC0_SUBTYPE_SHIFT];\n                XYLog(\"%s: sending %s to %s on channel %u mode %s\\n\",\n                    ifp->if_xname, subtype_name,\n                    ether_sprintf(ni->ni_macaddr),\n                    ieee80211_chan2ieee(ic, ni->ni_chan),\n                    ieee80211_phymode_name[ic->ic_curmode]);\n            }\n        }\n\n    #ifndef IEEE80211_STA_ONLY\n        if (ic->ic_opmode == IEEE80211_M_HOSTAP &&\n            ieee80211_pwrsave(ic, m, ni) != 0)\n            return 0;\n    #endif\n        mq_enqueue(&ic->ic_mgtq, m);\n        ifp->if_timer = 1;\n        ifp->if_start(ifp);\n        return 0;\n}\n\n/*-\n * EDCA tables are computed using the following formulas:\n *\n * 1) EDCATable (non-AP QSTA)\n *\n * AC     CWmin \t   CWmax\t   AIFSN  TXOP limit(ms)\n * -------------------------------------------------------------\n * AC_BK  aCWmin\t   aCWmax\t   7\t  0\n * AC_BE  aCWmin\t   aCWmax\t   3\t  0\n * AC_VI  (aCWmin+1)/2-1   aCWmin\t   2\t  agn=3.008 b=6.016 others=0\n * AC_VO  (aCWmin+1)/4-1   (aCWmin+1)/2-1  2\t  agn=1.504 b=3.264 others=0\n *\n * 2) QAPEDCATable (QAP)\n *\n * AC     CWmin \t   CWmax\t   AIFSN  TXOP limit(ms)\n * -------------------------------------------------------------\n * AC_BK  aCWmin\t   aCWmax\t   7\t  0\n * AC_BE  aCWmin\t   4*(aCWmin+1)-1  3\t  0\n * AC_VI  (aCWmin+1)/2-1   aCWmin\t   1\t  agn=3.008 b=6.016 others=0\n * AC_VO  (aCWmin+1)/4-1   (aCWmin+1)/2-1  1\t  agn=1.504 b=3.264 others=0\n *\n * and the following aCWmin/aCWmax values:\n *\n * PHY\t\taCWmin\taCWmax\n * ---------------------------\n * 11A\t\t15\t1023\n * 11B  \t31\t1023\n * 11G\t\t15*\t1023\t(*) aCWmin(1)\n * 11N\t\t15\t1023\n */\nconst struct ieee80211_edca_ac_params\n    ieee80211_edca_table[IEEE80211_MODE_MAX][EDCA_NUM_AC] = {\n\t[IEEE80211_MODE_11B] = {\n\t\t[EDCA_AC_BK] = { 5, 10, 7,   0 },\n\t\t[EDCA_AC_BE] = { 5, 10, 3,   0 },\n\t\t[EDCA_AC_VI] = { 4,  5, 2, 188 },\n\t\t[EDCA_AC_VO] = { 3,  4, 2, 102 }\n\t},\n\t[IEEE80211_MODE_11A] = {\n\t\t[EDCA_AC_BK] = { 4, 10, 7,   0 },\n\t\t[EDCA_AC_BE] = { 4, 10, 3,   0 },\n\t\t[EDCA_AC_VI] = { 3,  4, 2,  94 },\n\t\t[EDCA_AC_VO] = { 2,  3, 2,  47 }\n\t},\n\t[IEEE80211_MODE_11G] = {\n\t\t[EDCA_AC_BK] = { 4, 10, 7,   0 },\n\t\t[EDCA_AC_BE] = { 4, 10, 3,   0 },\n\t\t[EDCA_AC_VI] = { 3,  4, 2,  94 },\n\t\t[EDCA_AC_VO] = { 2,  3, 2,  47 }\n\t},\n\t[IEEE80211_MODE_11N] = {\n\t\t[EDCA_AC_BK] = { 4, 10, 7,   0 },\n\t\t[EDCA_AC_BE] = { 4, 10, 3,   0 },\n\t\t[EDCA_AC_VI] = { 3,  4, 2,  94 },\n\t\t[EDCA_AC_VO] = { 2,  3, 2,  47 }\n\t},\n    [IEEE80211_MODE_11AC] = {\n        [EDCA_AC_BK] = { 4, 10, 7,   0 },\n        [EDCA_AC_BE] = { 4, 10, 3,   0 },\n        [EDCA_AC_VI] = { 3,  4, 2,  94 },\n        [EDCA_AC_VO] = { 2,  3, 2,  47 }\n    },\n};\n\n#ifndef IEEE80211_STA_ONLY\nconst struct ieee80211_edca_ac_params\n    ieee80211_qap_edca_table[IEEE80211_MODE_MAX][EDCA_NUM_AC] = {\n\t[IEEE80211_MODE_11B] = {\n\t\t[EDCA_AC_BK] = { 5, 10, 7,   0 },\n\t\t[EDCA_AC_BE] = { 5,  7, 3,   0 },\n\t\t[EDCA_AC_VI] = { 4,  5, 1, 188 },\n\t\t[EDCA_AC_VO] = { 3,  4, 1, 102 }\n\t},\n\t[IEEE80211_MODE_11A] = {\n\t\t[EDCA_AC_BK] = { 4, 10, 7,   0 },\n\t\t[EDCA_AC_BE] = { 4,  6, 3,   0 },\n\t\t[EDCA_AC_VI] = { 3,  4, 1,  94 },\n\t\t[EDCA_AC_VO] = { 2,  3, 1,  47 }\n\t},\n\t[IEEE80211_MODE_11G] = {\n\t\t[EDCA_AC_BK] = { 4, 10, 7,   0 },\n\t\t[EDCA_AC_BE] = { 4,  6, 3,   0 },\n\t\t[EDCA_AC_VI] = { 3,  4, 1,  94 },\n\t\t[EDCA_AC_VO] = { 2,  3, 1,  47 }\n\t},\n\t[IEEE80211_MODE_11N] = {\n\t\t[EDCA_AC_BK] = { 4, 10, 7,   0 },\n\t\t[EDCA_AC_BE] = { 4,  6, 3,   0 },\n\t\t[EDCA_AC_VI] = { 3,  4, 1,  94 },\n\t\t[EDCA_AC_VO] = { 2,  3, 1,  47 }\n\t},\n    [IEEE80211_MODE_11AC] = {\n        [EDCA_AC_BK] = { 4, 10, 7,   0 },\n        [EDCA_AC_BE] = { 4,  6, 3,   0 },\n        [EDCA_AC_VI] = { 3,  4, 1,  94 },\n        [EDCA_AC_VO] = { 2,  3, 1,  47 }\n    },\n};\n#endif\t/* IEEE80211_STA_ONLY */\n\n/*\n * Return the EDCA Access Category to be used for transmitting a frame with\n * user-priority `up'.\n */\nenum ieee80211_edca_ac\nieee80211_up_to_ac(struct ieee80211com *ic, int up)\n{\n\t/* see Table 9-1 */\n\tstatic const enum ieee80211_edca_ac up_to_ac[] = {\n\t\tEDCA_AC_BE,\t/* BE */\n\t\tEDCA_AC_BK,\t/* BK */\n\t\tEDCA_AC_BK,\t/* -- */\n\t\tEDCA_AC_BE,\t/* EE */\n\t\tEDCA_AC_VI,\t/* CL */\n\t\tEDCA_AC_VI,\t/* VI */\n\t\tEDCA_AC_VO,\t/* VO */\n\t\tEDCA_AC_VO\t/* NC */\n\t};\n\tenum ieee80211_edca_ac ac;\n\n\tac = (up <= 7) ? up_to_ac[up] : EDCA_AC_BE;\n\n#ifndef IEEE80211_STA_ONLY\n\tif (ic->ic_opmode == IEEE80211_M_HOSTAP)\n\t\treturn ac;\n#endif\n\t/*\n\t * We do not support the admission control procedure defined in\n\t * IEEE Std 802.11-2012 section 9.19.4.2.3. The spec says that\n\t * non-AP QSTAs that don't support this procedure shall use EDCA\n\t * parameters of a lower priority AC that does not require\n\t * admission control.\n\t */\n\twhile (ac != EDCA_AC_BK && ic->ic_edca_ac[ac].ac_acm) {\n\t\tswitch (ac) {\n\t\tcase EDCA_AC_BK:\n\t\t\t/* can't get there */\n\t\t\tbreak;\n\t\tcase EDCA_AC_BE:\n\t\t\t/* BE shouldn't require admission control */\n\t\t\tac = EDCA_AC_BK;\n\t\t\tbreak;\n\t\tcase EDCA_AC_VI:\n\t\t\tac = EDCA_AC_BE;\n\t\t\tbreak;\n\t\tcase EDCA_AC_VO:\n\t\t\tac = EDCA_AC_VI;\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn ac;\n}\n\n/*\n * Get mbuf's user-priority: if mbuf is not VLAN tagged, select user-priority\n * based on the DSCP (Differentiated Services Codepoint) field.\n */\nint\nieee80211_classify(struct ieee80211com *ic, mbuf_t m)\n{\n\tstruct ether_header eh;\n\tu_int8_t ds_field;\n#if NVLAN > 0\n\tif (m->m_flags & M_VLANTAG)\t/* use VLAN 802.1D user-priority */\n\t\treturn EVL_PRIOFTAG(m->m_pkthdr.ether_vtag);\n#endif\n    mbuf_copydata(m, 0, sizeof(eh), (caddr_t)&eh);\n    if (eh.ether_type == htons(ETHERTYPE_IP)) {\n        struct ip ip;\n        mbuf_copydata(m, sizeof(eh), sizeof(ip), (caddr_t)&ip);\n        if (ip.ip_v != 4)\n            return 0;\n        ds_field = ip.ip_tos;\n    }\n#ifdef INET6\n    else if (eh.ether_type == htons(ETHERTYPE_IPV6)) {\n        struct ip6_hdr ip6;\n        u_int32_t flowlabel;\n        mbuf_copydata(m, sizeof(eh), sizeof(ip6), (caddr_t)&ip6);\n        flowlabel = ntohl(ip6.ip6_flow);\n        if ((flowlabel >> 28) != 6)\n            return 0;\n        ds_field = (flowlabel >> 20) & 0xff;\n    }\n#endif    /* INET6 */\n    else    /* neither IPv4 nor IPv6 */\n        return 0;\n\n    /*\n     * Map Differentiated Services Codepoint field (see RFC2474).\n     * Preserves backward compatibility with IP Precedence field.\n     */\n    switch (ds_field & 0xfc) {\n        case IPTOS_PREC_PRIORITY:\n            return EDCA_AC_VI;\n        case IPTOS_PREC_IMMEDIATE:\n            return EDCA_AC_BK;\n        case IPTOS_PREC_FLASH:\n        case IPTOS_PREC_FLASHOVERRIDE:\n        case IPTOS_PREC_CRITIC_ECP:\n        case IPTOS_PREC_INTERNETCONTROL:\n        case IPTOS_PREC_NETCONTROL:\n            return EDCA_AC_VO;\n        default:\n            return EDCA_AC_BE;\n    }\n}\n\nint\nieee80211_can_use_ampdu(struct ieee80211com *ic, struct ieee80211_node *ni)\n{\n\treturn (ni->ni_flags & IEEE80211_NODE_HT) &&\n    (ic->ic_caps & IEEE80211_C_TX_AMPDU) &&\n    !(ic->ic_opmode == IEEE80211_M_STA && ni != ic->ic_bss) &&\n    /*\n     * Don't use A-MPDU on non-encrypted networks. There are devices\n     * with buggy firmware which allow an attacker to inject 802.11\n     * frames into a wifi network by embedding rouge A-MPDU subframes\n     * in an arbitrary data payload (e.g. PNG images) which may end\n     * up appearing as actual frames after de-aggregation by a buggy\n     * device; see https://github.com/rpp0/aggr-inject for details.\n     * WPA2 prevents this injection attack since the attacker would\n     * need to inject frames which get decrypted correctly.\n     */\n    ((ic->ic_flags & IEEE80211_F_RSNON) &&\n      (ni->ni_rsnprotos & IEEE80211_PROTO_RSN));\n}\n\nvoid\nieee80211_tx_compressed_bar(struct ieee80211com *ic, struct ieee80211_node *ni,\n    int tid, uint16_t ssn)\n{\n\tstruct _ifnet *ifp = &ic->ic_if;\n\tmbuf_t m;\n\n\tm = ieee80211_get_compressed_bar(ic, ni, tid, ssn);\n    if (m == NULL)\n        return;\n\n    ieee80211_ref_node(ni);\n    if (mq_enqueue(&ic->ic_mgtq, m) == 0)\n        ifp->if_start(ifp);\n    else\n        ieee80211_release_node(ic, ni);\n}\n\n/*\n * Encapsulate an outbound data frame.  The mbuf chain is updated and\n * a reference to the destination node is returned.  If an error is\n * encountered NULL is returned and the node reference will also be NULL.\n *\n * NB: The caller is responsible for free'ing a returned node reference.\n *     The convention is ic_bss is not reference counted; the caller must\n *     maintain that.\n */\nmbuf_t\nieee80211_encap(struct _ifnet *ifp, mbuf_t m, struct ieee80211_node **pni)\n{\n\tstruct ieee80211com *ic = (struct ieee80211com *)ifp;\n\tstruct ether_header eh;\n\tstruct ieee80211_frame *wh;\n\tstruct ieee80211_node *ni = NULL;\n\tstruct llc *llc;\n\tmbuf_tag_id_t mtag;\n\tu_int8_t *addr;\n\tu_int dlt, hdrlen;\n\tint addqos, tid = 0;\n\n\t/* Handle raw frames if mbuf is tagged as 802.11 */\n    if (0) {\n//    if (mbuf_tag_find(m, mtag, (mbuf_tag_type_t)PACKET_TAG_DLT, &tag_len, (void**)&tag_data) == 0) {\n//\tif ((mtag = m_tag_find(m, PACKET_TAG_DLT, NULL)) != NULL) {\n\t\tdlt = *(u_int *)(mtag + 1);\n\n\t\tif (!(dlt == DLT_IEEE802_11 || dlt == DLT_IEEE802_11_RADIO))\n\t\t\tgoto fallback;\n\n\t\twh = mtod(m, struct ieee80211_frame *);\n\t\tswitch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) {\n\t\tcase IEEE80211_FC1_DIR_NODS:\n\t\tcase IEEE80211_FC1_DIR_FROMDS:\n\t\t\taddr = wh->i_addr1;\n\t\t\tbreak;\n\t\tcase IEEE80211_FC1_DIR_DSTODS:\n\t\tcase IEEE80211_FC1_DIR_TODS:\n\t\t\taddr = wh->i_addr3;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tgoto bad;\n\t\t}\n\n\t\tni = ieee80211_find_txnode(ic, addr);\n\t\tif (ni == NULL)\n\t\t\tni = ieee80211_ref_node(ic->ic_bss);\n\t\tif (ni == NULL) {\n\t\t\tXYLog(\"%s: no node for dst %s, \"\n\t\t\t    \"discard raw tx frame\\n\", ifp->if_xname,\n\t\t\t    ether_sprintf(addr));\n\t\t\tic->ic_stats.is_tx_nonode++;\n\t\t\tgoto bad;\n\t\t}\n\t\tni->ni_inact = 0;\n\n\t\t*pni = ni;\n\t\treturn (m);\n\t}\n\nfallback:\n    if (mbuf_len(m) < sizeof(struct ether_header)) {\n        mbuf_pullup(&m, sizeof(struct ether_header));\n        if (m == NULL) {\n            ic->ic_stats.is_tx_nombuf++;\n            goto bad;\n        }\n    }\n    memcpy(&eh, mtod(m, caddr_t), sizeof(struct ether_header));\n    \n    ni = ieee80211_find_txnode(ic, eh.ether_dhost);\n    if (ni == NULL) {\n        DPRINTF((\"no node for dst %s, discard frame\\n\",\n                 ether_sprintf(eh.ether_dhost)));\n        ic->ic_stats.is_tx_nonode++;\n        goto bad;\n    }\n    \n#ifndef IEEE80211_STA_ONLY\n    if (ic->ic_opmode == IEEE80211_M_HOSTAP && ni != ic->ic_bss &&\n        ni->ni_state != IEEE80211_STA_ASSOC) {\n        ic->ic_stats.is_tx_nonode++;\n        goto bad;\n    }\n#endif\n    \n    if ((ic->ic_flags & IEEE80211_F_RSNON) &&\n        !ni->ni_port_valid &&\n        eh.ether_type != htons(ETHERTYPE_PAE)) {\n        DPRINTF((\"port not valid: %s\\n\",\n                 ether_sprintf(eh.ether_dhost)));\n        ic->ic_stats.is_tx_noauth++;\n        goto bad;\n    }\n    \n    if ((ic->ic_flags & IEEE80211_F_COUNTERM) &&\n        ni->ni_rsncipher == IEEE80211_CIPHER_TKIP)\n    /* XXX TKIP countermeasures! */;\n    \n    ni->ni_inact = 0;\n    \n    if ((ic->ic_flags & IEEE80211_F_QOS) &&\n        (ni->ni_flags & IEEE80211_NODE_QOS) &&\n        /* do not QoS-encapsulate EAPOL frames */\n        eh.ether_type != htons(ETHERTYPE_PAE)) {\n        struct ieee80211_tx_ba *ba;\n        tid = ieee80211_classify(ic, m);\n        ba = &ni->ni_tx_ba[tid];\n        /* We use QoS data frames for aggregation only. */\n        if (ba->ba_state != IEEE80211_BA_AGREED) {\n            hdrlen = sizeof(struct ieee80211_frame);\n            addqos = 0;\n            if ((ic->ic_caps & IEEE80211_C_TX_AMPDU_SETUP_IN_RS) == 0 &&\n                ieee80211_can_use_ampdu(ic, ni))\n                ieee80211_node_trigger_addba_req(ni, tid);\n        } else {\n            hdrlen = sizeof(struct ieee80211_qosframe);\n            addqos = 1;\n        }\n    } else {\n        hdrlen = sizeof(struct ieee80211_frame);\n        addqos = 0;\n    }\n    mbuf_adj(m, sizeof(struct ether_header) - LLC_SNAPFRAMELEN);\n    llc = mtod(m, struct llc *);\n    llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;\n    llc->llc_control = LLC_UI;\n    llc->llc_snap.org_code[0] = 0;\n    llc->llc_snap.org_code[1] = 0;\n    llc->llc_snap.org_code[2] = 0;\n    llc->llc_snap.ether_type = eh.ether_type;\n    mbuf_prepend(&m, hdrlen, MBUF_DONTWAIT);\n    if (m == NULL) {\n        ic->ic_stats.is_tx_nombuf++;\n        goto bad;\n    }\n    wh = mtod(m, struct ieee80211_frame *);\n    wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_DATA;\n    *(u_int16_t *)&wh->i_dur[0] = 0;\n    if (addqos) {\n        struct ieee80211_qosframe *qwh =\n        (struct ieee80211_qosframe *)wh;\n        u_int16_t qos = tid;\n        \n        if (ic->ic_tid_noack & (1 << tid))\n            qos |= IEEE80211_QOS_ACK_POLICY_NOACK;\n        else {\n            /* Use HT immediate block-ack. */\n            qos |= IEEE80211_QOS_ACK_POLICY_NORMAL;\n        }\n        qwh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_QOS;\n        *(u_int16_t *)qwh->i_qos = htole16(qos);\n        *(u_int16_t *)qwh->i_seq =\n        htole16(ni->ni_qos_txseqs[tid] << IEEE80211_SEQ_SEQ_SHIFT);\n        ni->ni_qos_txseqs[tid] = (ni->ni_qos_txseqs[tid] + 1) & 0xfff;\n    } else {\n        *(u_int16_t *)&wh->i_seq[0] =\n        htole16(ni->ni_txseq << IEEE80211_SEQ_SEQ_SHIFT);\n        ni->ni_txseq = (ni->ni_txseq + 1) & 0xfff;\n    }\n    switch (ic->ic_opmode) {\n        case IEEE80211_M_STA:\n            wh->i_fc[1] = IEEE80211_FC1_DIR_TODS;\n            IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_bssid);\n            IEEE80211_ADDR_COPY(wh->i_addr2, eh.ether_shost);\n            IEEE80211_ADDR_COPY(wh->i_addr3, eh.ether_dhost);\n            break;\n#ifndef IEEE80211_STA_ONLY\n        case IEEE80211_M_IBSS:\n        case IEEE80211_M_AHDEMO:\n            wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;\n            IEEE80211_ADDR_COPY(wh->i_addr1, eh.ether_dhost);\n            IEEE80211_ADDR_COPY(wh->i_addr2, eh.ether_shost);\n            IEEE80211_ADDR_COPY(wh->i_addr3, ic->ic_bss->ni_bssid);\n            break;\n        case IEEE80211_M_HOSTAP:\n            wh->i_fc[1] = IEEE80211_FC1_DIR_FROMDS;\n            IEEE80211_ADDR_COPY(wh->i_addr1, eh.ether_dhost);\n            IEEE80211_ADDR_COPY(wh->i_addr2, ni->ni_bssid);\n            IEEE80211_ADDR_COPY(wh->i_addr3, eh.ether_shost);\n            break;\n#endif\n        default:\n            /* should not get there */\n            goto bad;\n    }\n    \n    if ((ic->ic_flags & IEEE80211_F_WEPON) ||\n        ((ic->ic_flags & IEEE80211_F_RSNON) &&\n         (ni->ni_flags & IEEE80211_NODE_TXPROT)))\n        wh->i_fc[1] |= IEEE80211_FC1_PROTECTED;\n    \n#ifndef IEEE80211_STA_ONLY\n    if (ic->ic_opmode == IEEE80211_M_HOSTAP &&\n        ieee80211_pwrsave(ic, m, ni) != 0) {\n        *pni = NULL;\n        return NULL;\n    }\n#endif\n    *pni = ni;\n    return m;\nbad:\n    mbuf_freem(m);\n    if (ni != NULL)\n        ieee80211_release_node(ic, ni);\n    *pni = NULL;\n    return NULL;\n}\n\n/*\n * Add a Capability Information field to a frame (see 7.3.1.4).\n */\nu_int8_t *\nieee80211_add_capinfo(u_int8_t *frm, struct ieee80211com *ic,\n    const struct ieee80211_node *ni)\n{\n\tu_int16_t capinfo;\n\n#ifndef IEEE80211_STA_ONLY\n    if (ic->ic_opmode == IEEE80211_M_IBSS)\n        capinfo = IEEE80211_CAPINFO_IBSS;\n    else if (ic->ic_opmode == IEEE80211_M_HOSTAP)\n        capinfo = IEEE80211_CAPINFO_ESS;\n    else\n#endif\n        capinfo = 0;\n#ifndef IEEE80211_STA_ONLY\n    if (ic->ic_opmode == IEEE80211_M_HOSTAP &&\n        (ic->ic_flags & (IEEE80211_F_WEPON | IEEE80211_F_RSNON)))\n        capinfo |= IEEE80211_CAPINFO_PRIVACY;\n#endif\n    /* NB: some 11a AP's reject the request when short preamble is set */\n    if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&\n        IEEE80211_IS_CHAN_2GHZ(ni->ni_chan))\n        capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE;\n    if (ic->ic_flags & IEEE80211_F_SHSLOT)\n        capinfo |= IEEE80211_CAPINFO_SHORT_SLOTTIME;\n    LE_WRITE_2(frm, capinfo);\n    return frm + 2;\n}\n\n/*\n * Add an SSID element to a frame (see 7.3.2.1).\n */\nu_int8_t *\nieee80211_add_ssid(u_int8_t *frm, const u_int8_t *ssid, u_int len)\n{\n\t*frm++ = IEEE80211_ELEMID_SSID;\n    *frm++ = len;\n    memcpy(frm, ssid, len);\n    return frm + len;\n}\n\n/*\n * Add a supported rates element to a frame (see 7.3.2.2).\n */\nu_int8_t *\nieee80211_add_rates(u_int8_t *frm, const struct ieee80211_rateset *rs)\n{\n\tint nrates;\n\n\t*frm++ = IEEE80211_ELEMID_RATES;\n    nrates = min(rs->rs_nrates, IEEE80211_RATE_SIZE);\n    *frm++ = nrates;\n    memcpy(frm, rs->rs_rates, nrates);\n    return frm + nrates;\n}\n\n#ifndef IEEE80211_STA_ONLY\n/*\n * Add a DS Parameter Set element to a frame (see 7.3.2.4).\n */\nu_int8_t *\nieee80211_add_ds_params(u_int8_t *frm, struct ieee80211com *ic,\n    const struct ieee80211_node *ni)\n{\n\t*frm++ = IEEE80211_ELEMID_DSPARMS;\n    *frm++ = 1;\n    *frm++ = ieee80211_chan2ieee(ic, ni->ni_chan);\n    return frm;\n}\n\n/*\n * Add a TIM element to a frame (see 7.3.2.6 and Annex L).\n */\nu_int8_t *\nieee80211_add_tim(u_int8_t *frm, struct ieee80211com *ic)\n{\n\tu_int i, offset = 0, len;\n\n\t/* find first non-zero octet in the virtual bit map */\n    for (i = 0; i < ic->ic_tim_len && ic->ic_tim_bitmap[i] == 0; i++);\n\n    /* clear the lsb as it is reserved for the broadcast indication bit */\n    if (i < ic->ic_tim_len)\n        offset = i & ~1;\n\n    /* find last non-zero octet in the virtual bit map */\n    for (i = ic->ic_tim_len - 1; i > 0 && ic->ic_tim_bitmap[i] == 0; i--);\n\n    len = i - offset + 1;\n\n    *frm++ = IEEE80211_ELEMID_TIM;\n    *frm++ = len + 3;        /* length */\n    *frm++ = ic->ic_dtim_count;    /* DTIM count */\n    *frm++ = ic->ic_dtim_period;    /* DTIM period */\n\n    /* Bitmap Control */\n    *frm = offset;\n    /* set broadcast/multicast indication bit if necessary */\n    if (ic->ic_dtim_count == 0 && ic->ic_tim_mcast_pending)\n        *frm |= 0x01;\n    frm++;\n\n    /* Partial Virtual Bitmap */\n    memcpy(frm, &ic->ic_tim_bitmap[offset], len);\n    return frm + len;\n}\n\n/*\n * Add an IBSS Parameter Set element to a frame (see 7.3.2.7).\n */\nu_int8_t *\nieee80211_add_ibss_params(u_int8_t *frm, const struct ieee80211_node *ni)\n{\n\t*frm++ = IEEE80211_ELEMID_IBSSPARMS;\n    *frm++ = 2;\n    LE_WRITE_2(frm, 0);    /* TODO: ATIM window */\n    return frm + 2;\n}\n\n/*\n * Add an EDCA Parameter Set element to a frame (see 7.3.2.29).\n */\nu_int8_t *\nieee80211_add_edca_params(u_int8_t *frm, struct ieee80211com *ic)\n{\n\tconst struct ieee80211_edca_ac_params *edca;\n\tint aci;\n\n\t*frm++ = IEEE80211_ELEMID_EDCAPARMS;\n    *frm++ = 18;    /* length */\n    *frm++ = 0;    /* QoS Info */\n    *frm++ = 0;    /* reserved */\n\n    /* setup AC Parameter Records */\n    edca = ieee80211_edca_table[ic->ic_curmode];\n    for (aci = 0; aci < EDCA_NUM_AC; aci++) {\n        const struct ieee80211_edca_ac_params *ac = &edca[aci];\n\n        *frm++ = (aci << 5) | ((ac->ac_acm & 0x1) << 4) |\n             (ac->ac_aifsn & 0xf);\n        *frm++ = (ac->ac_ecwmax << 4) |\n             (ac->ac_ecwmin & 0xf);\n        LE_WRITE_2(frm, ac->ac_txoplimit); frm += 2;\n    }\n    return frm;\n}\n\n/*\n * Add an ERP element to a frame (see 7.3.2.13).\n */\nu_int8_t *\nieee80211_add_erp(u_int8_t *frm, struct ieee80211com *ic)\n{\n\tu_int8_t erp;\n\tint nonerpsta = 0;\n\n\t*frm++ = IEEE80211_ELEMID_ERP;\n    *frm++ = 1;\n    erp = 0;\n    /*\n     * The NonERP_Present bit shall be set to 1 when a NonERP STA\n     * is associated with the BSS.\n     */\n    ieee80211_iterate_nodes(ic, ieee80211_count_nonerpsta, &nonerpsta);\n    if (nonerpsta != 0)\n        erp |= IEEE80211_ERP_NON_ERP_PRESENT;\n    /*\n     * If one or more NonERP STAs are associated in the BSS, the\n     * Use_Protection bit shall be set to 1 in transmitted ERP\n     * Information Elements.\n     */\n    if (ic->ic_flags & IEEE80211_F_USEPROT)\n        erp |= IEEE80211_ERP_USE_PROTECTION;\n    /*\n     * The Barker_Preamble_Mode bit shall be set to 1 by the ERP\n     * Information Element sender if one or more associated NonERP\n     * STAs are not short preamble capable.\n     */\n    if (!(ic->ic_flags & IEEE80211_F_SHPREAMBLE))\n        erp |= IEEE80211_ERP_BARKER_MODE;\n    *frm++ = erp;\n    return frm;\n}\n#endif\t/* IEEE80211_STA_ONLY */\n\n/*\n * Add a QoS Capability element to a frame (see 7.3.2.35).\n */\nu_int8_t *\nieee80211_add_qos_capability(u_int8_t *frm, struct ieee80211com *ic)\n{\n\t*frm++ = IEEE80211_ELEMID_QOS_CAP;\n    *frm++ = 1;\n    *frm++ = 0;    /* QoS Info */\n    return frm;\n}\n\n#define    WME_OUI_BYTES        0x00, 0x50, 0xf2\n\n/*\n * Add a Wifi-Alliance WME (aka WMM) info element to a frame.\n * WME is a requirement for Wifi-Alliance compliance and some\n * 11n APs will not negotiate HT if this element is missing.\n */\nuint8_t *\nieee80211_add_wme_info(uint8_t *frm, struct ieee80211com *ic)\n{\n\tstatic const struct ieee80211_wme_info info = {\n        .wme_id        = IEEE80211_ELEMID_VENDOR,\n        .wme_len    = sizeof(struct ieee80211_wme_info) - 2,\n        .wme_oui    = { WME_OUI_BYTES },\n        .wme_type    = WME_OUI_TYPE,\n        .wme_subtype    = WME_INFO_OUI_SUBTYPE,\n        .wme_version    = WME_VERSION,\n        .wme_info    = 0,\n    };\n    memcpy(frm, &info, sizeof(info));\n    return frm + sizeof(info);\n}\n\n#ifndef IEEE80211_STA_ONLY\n/*\n * Add a Wifi-Alliance WMM (aka WME) parameter element to a frame.\n */\nuint8_t *\nieee80211_add_wme_param(uint8_t *frm, struct ieee80211com *ic)\n{\n\tconst struct ieee80211_edca_ac_params *edca;\n\tint aci;\n\n\t*frm++ = IEEE80211_ELEMID_VENDOR;\n    *frm++ = 24;\n    memcpy(frm, MICROSOFT_OUI, 3); frm += 3;\n    *frm++ = 2; /* OUI type */\n    *frm++ = 1; /* OUI subtype */\n    *frm++ = 1; /* version */\n    *frm++ = 0; /* info */\n    *frm++ = 0; /* reserved */\n\n    /* setup AC Parameter Records */\n    edca = ieee80211_edca_table[ic->ic_curmode];\n    for (aci = 0; aci < EDCA_NUM_AC; aci++) {\n        const struct ieee80211_edca_ac_params *ac = &edca[aci];\n\n        *frm++ = (aci << 5) | ((ac->ac_acm & 0x1) << 4) |\n             (ac->ac_aifsn & 0xf);\n        *frm++ = (ac->ac_ecwmax << 4) |\n             (ac->ac_ecwmin & 0xf);\n        LE_WRITE_2(frm, ac->ac_txoplimit); frm += 2;\n    }\n\n    return frm;\n}\n#endif\n\n/*\n * Add an RSN element to a frame (see 802.11-2012 8.4.2.27)\n */\nu_int8_t *\nieee80211_add_rsn_body(u_int8_t *frm, struct ieee80211com *ic,\n    const struct ieee80211_node *ni, int wpa)\n{\n\tconst u_int8_t *oui = wpa ? MICROSOFT_OUI : IEEE80211_OUI;\n\tu_int8_t *pcount;\n    u_int16_t count, rsncaps;\n\n\t/* write Version field */\n    LE_WRITE_2(frm, 1); frm += 2;\n\n    /* write Group Data Cipher Suite field (see 802.11-2012 Table 8-99) */\n    memcpy(frm, oui, 3); frm += 3;\n    switch (ni->ni_rsngroupcipher) {\n    case IEEE80211_CIPHER_WEP40:\n        *frm++ = 1;\n        break;\n    case IEEE80211_CIPHER_TKIP:\n        *frm++ = 2;\n        break;\n    case IEEE80211_CIPHER_CCMP:\n        *frm++ = 4;\n        break;\n    case IEEE80211_CIPHER_WEP104:\n        *frm++ = 5;\n        break;\n    default:\n        /* can't get there */\n        panic(\"invalid group data cipher!\");\n    }\n\n    pcount = frm; frm += 2;\n    count = 0;\n    /* write Pairwise Cipher Suite List */\n    if (ni->ni_rsnciphers & IEEE80211_CIPHER_USEGROUP) {\n        memcpy(frm, oui, 3); frm += 3;\n        *frm++ = 0;\n        count++;\n    }\n    if (ni->ni_rsnciphers & IEEE80211_CIPHER_TKIP) {\n        memcpy(frm, oui, 3); frm += 3;\n        *frm++ = 2;\n        count++;\n    }\n    if (ni->ni_rsnciphers & IEEE80211_CIPHER_CCMP) {\n        memcpy(frm, oui, 3); frm += 3;\n        *frm++ = 4;\n        count++;\n    }\n    /* write Pairwise Cipher Suite Count field */\n    LE_WRITE_2(pcount, count);\n\n    pcount = frm; frm += 2;\n    count = 0;\n    /* write AKM Suite List (see Table 20dc) */\n    if (ni->ni_rsnakms & IEEE80211_AKM_8021X) {\n        memcpy(frm, oui, 3); frm += 3;\n        *frm++ = 1;\n        count++;\n    }\n    if (ni->ni_rsnakms & IEEE80211_AKM_PSK) {\n        memcpy(frm, oui, 3); frm += 3;\n        *frm++ = 2;\n        count++;\n    }\n    if (!wpa && (ni->ni_rsnakms & IEEE80211_AKM_SHA256_8021X)) {\n        memcpy(frm, oui, 3); frm += 3;\n        *frm++ = 5;\n        count++;\n    }\n    if (!wpa && (ni->ni_rsnakms & IEEE80211_AKM_SHA256_PSK)) {\n        memcpy(frm, oui, 3); frm += 3;\n        *frm++ = 6;\n        count++;\n    }\n    /* write AKM Suite List Count field */\n    LE_WRITE_2(pcount, count);\n\n    if (wpa)\n        return frm;\n\n    /* write RSN Capabilities field */\n    rsncaps = (ni->ni_rsncaps & (IEEE80211_RSNCAP_PTKSA_RCNT_MASK |\n        IEEE80211_RSNCAP_GTKSA_RCNT_MASK));\n    if (ic->ic_caps & IEEE80211_C_MFP) {\n        rsncaps |= IEEE80211_RSNCAP_MFPC;\n        if (ic->ic_flags & IEEE80211_F_MFPR)\n            rsncaps |= IEEE80211_RSNCAP_MFPR;\n    }\n    if (ic->ic_flags & IEEE80211_F_PBAR)\n        rsncaps |= IEEE80211_RSNCAP_PBAC;\n    LE_WRITE_2(frm, rsncaps); frm += 2;\n\n    if (ni->ni_flags & IEEE80211_NODE_PMKID) {\n        /* write PMKID Count field */\n        LE_WRITE_2(frm, 1); frm += 2;\n        /* write PMKID List (only 1) */\n        memcpy(frm, ni->ni_pmkid, IEEE80211_PMKID_LEN);\n        frm += IEEE80211_PMKID_LEN;\n    }\n\n    if (!(ic->ic_caps & IEEE80211_C_MFP))\n        return frm;\n\n    if ((ni->ni_flags & IEEE80211_NODE_PMKID) == 0) {\n        /* no PMKID (PMKID Count=0) */\n        LE_WRITE_2(frm, 0); frm += 2;\n    }\n\n    /* write Group Integrity Cipher Suite field */\n    memcpy(frm, oui, 3); frm += 3;\n    switch (ic->ic_rsngroupmgmtcipher) {\n    case IEEE80211_CIPHER_BIP:\n        *frm++ = 6;\n        break;\n    default:\n        /* can't get there */\n        panic(\"invalid integrity group cipher!\");\n    }\n    return frm;\n}\n\nu_int8_t *\nieee80211_add_rsn(u_int8_t *frm, struct ieee80211com *ic,\n    const struct ieee80211_node *ni)\n{\n\tu_int8_t *plen;\n\n\t*frm++ = IEEE80211_ELEMID_RSN;\n    plen = frm++;    /* length filled in later */\n    frm = ieee80211_add_rsn_body(frm, ic, ni, 0);\n\n    /* write length field */\n    *plen = frm - plen - 1;\n    return frm;\n}\n\n/*\n * Add a vendor-specific WPA element to a frame.\n * This is required for compatibility with Wi-Fi Alliance WPA.\n */\nu_int8_t *\nieee80211_add_wpa(u_int8_t *frm, struct ieee80211com *ic,\n    const struct ieee80211_node *ni)\n{\n\tu_int8_t *plen;\n\n\t*frm++ = IEEE80211_ELEMID_VENDOR;\n    plen = frm++;    /* length filled in later */\n    memcpy(frm, MICROSOFT_OUI, 3); frm += 3;\n    *frm++ = 1;    /* WPA */\n    frm = ieee80211_add_rsn_body(frm, ic, ni, 1);\n\n    /* write length field */\n    *plen = frm - plen - 1;\n    return frm;\n}\n\n/*\n * Add an extended supported rates element to a frame (see 7.3.2.14).\n */\nu_int8_t *\nieee80211_add_xrates(u_int8_t *frm, const struct ieee80211_rateset *rs)\n{\n\tint nrates;\n\n    _KASSERT(rs->rs_nrates > IEEE80211_RATE_SIZE);\n\n    *frm++ = IEEE80211_ELEMID_XRATES;\n    nrates = rs->rs_nrates - IEEE80211_RATE_SIZE;\n    *frm++ = nrates;\n    memcpy(frm, rs->rs_rates + IEEE80211_RATE_SIZE, nrates);\n    return frm + nrates;\n}\n\nuint8_t *\nieee80211_add_ht_ie(uint8_t *frm, struct ieee80211com *ic, struct ieee80211_node *ni)\n{\n    *frm++ = IEEE80211_ELEMID_HTCAPS;\n    *frm++ = 26;\n    uint16_t cap = ni->ni_htcaps;;\n    cap |= ic->ic_htcaps;\n    switch (ni->ni_htop0 & IEEE80211_HTOP0_SCO_MASK) {\n            XYLog(\"%s line=%d\\n\", __FUNCTION__, __LINE__);\n        case IEEE80211_HTOP0_SCO_SCA:\n            XYLog(\"%s line=%d\\n\", __FUNCTION__, __LINE__);\n            if (ni->ni_chan != NULL) {\n                XYLog(\"%s line=%d\\n\", __FUNCTION__, __LINE__);\n                if ((ni->ni_chan->ic_flags & IEEE80211_CHAN_HT40U) == 0) {\n                    XYLog(\"%s line=%d\\n\", __FUNCTION__, __LINE__);\n                    cap &= ~IEEE80211_HTCAP_CBW20_40;\n                    cap &= ~IEEE80211_HTCAP_SGI40;\n                }\n            }\n            break;\n        case IEEE80211_HTOP0_SCO_SCB:\n            XYLog(\"%s line=%d\\n\", __FUNCTION__, __LINE__);\n            if (ni->ni_chan != NULL) {\n                XYLog(\"%s line=%d\\n\", __FUNCTION__, __LINE__);\n                if ((ni->ni_chan->ic_flags & IEEE80211_CHAN_HT40D) == 0) {\n                    XYLog(\"%s line=%d\\n\", __FUNCTION__, __LINE__);\n                    cap &= ~IEEE80211_HTCAP_CBW20_40;\n                    cap &= ~IEEE80211_HTCAP_SGI40;\n                }\n            }\n            break;\n\n        default:\n            break;\n    }\n    LE_WRITE_2(frm, cap); frm += 2;\n    *frm++ = ic->ic_ampdu_params;\n    memcpy(frm, ic->ic_sup_mcs, 10); frm += 10;// rx_mask\n    LE_WRITE_2(frm, (ic->ic_max_rxrate & IEEE80211_MCS_RX_RATE_HIGH)); frm += 2;// rx_highest\n    *frm++ = ic->ic_tx_mcs_set;// tx_params\n    *frm++ = 0; /* reserved */\n    *frm++ = 0; /* reserved */\n    *frm++ = 0; /* reserved */\n    LE_WRITE_2(frm, ic->ic_htxcaps); frm += 2;\n    LE_WRITE_4(frm, ic->ic_txbfcaps); frm += 4;\n    *frm++ = ic->ic_aselcaps;\n    return frm;\n}\n\n/*\n * Add an HT Capabilities element to a frame (see 7.3.2.57).\n */\nuint8_t *\nieee80211_add_htcaps(uint8_t *frm, struct ieee80211com *ic)\n{\n\t*frm++ = IEEE80211_ELEMID_HTCAPS;\n    *frm++ = sizeof(struct ieee80211_ie_htcap) - 2;\n    LE_WRITE_2(frm, ic->ic_htcaps); frm += 2;\n    *frm++ = ic->ic_ampdu_params;\n    memcpy(frm, ic->ic_sup_mcs, 10); frm += 10;\n    LE_WRITE_2(frm, (ic->ic_max_rxrate & IEEE80211_MCS_RX_RATE_HIGH));\n    frm += 2;\n    *frm++ = ic->ic_tx_mcs_set;\n    *frm++ = 0; /* reserved */\n    *frm++ = 0; /* reserved */\n    *frm++ = 0; /* reserved */\n    LE_WRITE_2(frm, ic->ic_htxcaps); frm += 2;\n    LE_WRITE_4(frm, ic->ic_txbfcaps); frm += 4;\n    *frm++ = ic->ic_aselcaps;\n    return frm;\n}\n\nuint8_t *\nieee80211_add_vhtcaps(uint8_t *frm, struct ieee80211com *ic)\n{\n    *frm++ = IEEE80211_ELEMID_VHT_CAP;\n    *frm++ = sizeof(struct ieee80211_ie_vhtcap) - 2;\n    /* 32-bit VHT capability */\n    LE_WRITE_4(frm, ic->ic_vhtcaps); frm += 4;\n    /* suppmcs */\n    LE_WRITE_2(frm, ic->ic_vht_rx_mcs_map); frm += 2;\n    LE_WRITE_2(frm, ic->ic_vht_rx_highest); frm += 2;\n    LE_WRITE_2(frm, ic->ic_vht_tx_mcs_map); frm += 2;\n    LE_WRITE_2(frm, ic->ic_vht_tx_highest); frm += 2;\n    return frm;\n}\n\nuint8_t *\nieee80211_add_hecaps(uint8_t *frm, struct ieee80211com *ic)\n{\n    uint8_t nss_size, ie_len;\n    uint8_t *orig_pos = frm;\n    \n    nss_size = ieee80211_he_mcs_nss_size(&ic->ic_he_cap_elem);\n    ie_len = 2 + 1 +\n    sizeof(ic->ic_he_cap_elem) + nss_size +\n    ieee80211_he_ppe_size(ic->ic_ppe_thres[0],\n                  ic->ic_he_cap_elem.phy_cap_info);\n    \n    *frm++ = IEEE80211_ELEMID_EXTENSION;\n    frm++; /* We'll set the size later below */\n    *frm++ = IEEE80211_ELEMID_EXT_HE_CAPABILITY;\n    \n    /* Fixed data */\n    memcpy(frm, &ic->ic_he_cap_elem, sizeof(ic->ic_he_cap_elem));\n    frm += sizeof(ic->ic_he_cap_elem);\n    \n    memcpy(frm, &ic->ic_he_mcs_nss_supp, nss_size);\n    frm += nss_size;\n    \n    /* Check if PPE Threshold should be present */\n    if ((ic->ic_he_cap_elem.phy_cap_info[6] &\n         IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) == 0)\n        return frm;\n    \n    /*\n     * Calculate how many PPET16/PPET8 pairs are to come. Algorithm:\n     * (NSS_M1 + 1) x (num of 1 bits in RU_INDEX_BITMASK)\n     */\n    nss_size = hweight8(ic->ic_ppe_thres[0] &\n             IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK);\n    \n    nss_size *= (1 + ((ic->ic_ppe_thres[0] & IEEE80211_PPE_THRES_NSS_MASK) >>\n           IEEE80211_PPE_THRES_NSS_POS));\n    \n    /*\n     * Each pair is 6 bits, and we need to add the 7 \"header\" bits to the\n     * total size.\n     */\n    nss_size = (nss_size * IEEE80211_PPE_THRES_INFO_PPET_SIZE * 2) + 7;\n    nss_size = DIV_ROUND_UP(nss_size, 8);\n    \n    /* Copy PPE Thresholds */\n    memcpy(frm, &ic->ic_ppe_thres, nss_size);\n    frm += nss_size;\n    \n    orig_pos[1] = (frm - orig_pos) - 2;\n    return frm;\n}\n\n#ifndef IEEE80211_STA_ONLY\n/*\n * Add an HT Operation element to a frame (see 7.3.2.58).\n */\nu_int8_t *\nieee80211_add_htop(u_int8_t *frm, struct ieee80211com *ic)\n{\n\t*frm++ = IEEE80211_ELEMID_HTOP;\n    *frm++ = 22;\n    *frm++ = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan);\n    *frm++ = ic->ic_bss->ni_htop0;\n    LE_WRITE_2(frm, ic->ic_bss->ni_htop1); frm += 2;\n    LE_WRITE_2(frm, ic->ic_bss->ni_htop2); frm += 2;\n    memset(frm, 0, 16); frm += 16;\n    return frm;\n}\n#endif\t/* !IEEE80211_STA_ONLY */\n\n#ifndef IEEE80211_STA_ONLY\n/*\n * Add a Timeout Interval element to a frame (see 7.3.2.49).\n */\nu_int8_t *\nieee80211_add_tie(u_int8_t *frm, u_int8_t type, u_int32_t value)\n{\n\t*frm++ = IEEE80211_ELEMID_TIE;\n    *frm++ = 5;    /* length */\n    *frm++ = type;    /* Timeout Interval type */\n    LE_WRITE_4(frm, value);\n    return frm + 4;\n}\n#endif\n\nmbuf_t\nieee80211_getmgmt(int flags, int type, u_int pktlen)\n{\n\tmbuf_t m;\n\n\t/* reserve space for 802.11 header */\n\tpktlen += sizeof(struct ieee80211_frame);\n\n\tif (pktlen > MCLBYTES)\n\t\tpanic(\"management frame too large: %u\", pktlen);\n    mbuf_gethdr(flags, type, &m);\n\tif (m == NULL)\n\t\treturn NULL;\n\tif (pktlen > mbuf_get_mhlen()) {\n        mbuf_mclget(flags, type, &m);\n\t\tif (!(mbuf_flags(m) & MBUF_EXT))\n\t\t\treturn mbuf_free(m);\n\t}\n\tmbuf_setdata(m, (u_int8_t*) mbuf_data(m) + sizeof(struct ieee80211_frame), mbuf_len(m) - sizeof(struct ieee80211_frame));\n\treturn m;\n}\n\n/*-\n * Probe request frame format:\n * [tlv] SSID\n * [tlv] Supported rates\n * [tlv] Extended Supported Rates (802.11g)\n * [tlv] HT Capabilities (802.11n)\n */\nmbuf_t\nieee80211_get_probe_req(struct ieee80211com *ic, struct ieee80211_node *ni)\n{\n\tconst struct ieee80211_rateset *rs =\n\t    &ic->ic_sup_rates[ieee80211_chan2mode(ic, ni->ni_chan)];\n\tmbuf_t m;\n\tu_int8_t *frm;\n\n\tm = ieee80211_getmgmt(MBUF_DONTWAIT, MT_DATA,\n\t    2 + ic->ic_des_esslen +\n\t    2 + min(rs->rs_nrates, IEEE80211_RATE_SIZE) +\n\t    ((rs->rs_nrates > IEEE80211_RATE_SIZE) ?\n\t\t2 + rs->rs_nrates - IEEE80211_RATE_SIZE : 0) +\n\t    ((ic->ic_flags & IEEE80211_F_HTON) ? sizeof(struct ieee80211_ie_htcap) + sizeof(struct ieee80211_wme_info) : 0) +\n        ((ic->ic_flags & IEEE80211_F_VHTON) ? sizeof(struct ieee80211_ie_vhtcap) : 0));\n\tif (m == NULL)\n\t\treturn NULL;\n\n\tfrm = mtod(m, u_int8_t *);\n\tfrm = ieee80211_add_ssid(frm, ic->ic_des_essid, ic->ic_des_esslen);\n\tfrm = ieee80211_add_rates(frm, rs);\n\tif (rs->rs_nrates > IEEE80211_RATE_SIZE)\n\t\tfrm = ieee80211_add_xrates(frm, rs);\n\tif (ic->ic_flags & IEEE80211_F_HTON) {\n\t\tfrm = ieee80211_add_htcaps(frm, ic);\n\t\tfrm = ieee80211_add_wme_info(frm, ic);\n\t}\n    if (ic->ic_flags & IEEE80211_F_VHTON)\n        frm = ieee80211_add_vhtcaps(frm, ic);\n    size_t l = frm - mtod(m, u_int8_t *);\n    mbuf_pkthdr_setlen(m, l);\n    mbuf_setlen(m, l);\n\n\treturn m;\n}\n\n#ifndef IEEE80211_STA_ONLY\n/*-\n * Probe response frame format:\n * [8]   Timestamp\n * [2]   Beacon interval\n * [2]   Capability\n * [tlv] Service Set Identifier (SSID)\n * [tlv] Supported rates\n * [tlv] DS Parameter Set (802.11g)\n * [tlv] ERP Information (802.11g)\n * [tlv] Extended Supported Rates (802.11g)\n * [tlv] RSN (802.11i)\n * [tlv] EDCA Parameter Set (802.11e)\n * [tlv] HT Capabilities (802.11n)\n * [tlv] HT Operation (802.11n)\n */\nmbuf_t\nieee80211_get_probe_resp(struct ieee80211com *ic, struct ieee80211_node *ni)\n{\n\tconst struct ieee80211_rateset *rs = &ic->ic_bss->ni_rates;\n\tmbuf_t m;\n\tu_int8_t *frm;\n\n\tm = ieee80211_getmgmt(MBUF_DONTWAIT, MT_DATA,\n\t    8 + 2 + 2 +\n\t    2 + ni->ni_esslen +\n\t    2 + min(rs->rs_nrates, IEEE80211_RATE_SIZE) +\n\t    2 + 1 +\n\t    ((ic->ic_opmode == IEEE80211_M_IBSS) ? 2 + 2 : 0) +\n\t    ((ic->ic_curmode == IEEE80211_MODE_11G) ? 2 + 1 : 0) +\n\t    ((rs->rs_nrates > IEEE80211_RATE_SIZE) ?\n\t\t2 + rs->rs_nrates - IEEE80211_RATE_SIZE : 0) +\n\t    (((ic->ic_flags & IEEE80211_F_RSNON) &&\n\t      (ic->ic_bss->ni_rsnprotos & IEEE80211_PROTO_RSN)) ?\n\t\t2 + IEEE80211_RSNIE_MAXLEN : 0) +\n\t    ((ic->ic_flags & IEEE80211_F_QOS) ? 2 + 18 : 0) +\n\t    (((ic->ic_flags & IEEE80211_F_RSNON) &&\n\t      (ic->ic_bss->ni_rsnprotos & IEEE80211_PROTO_WPA)) ?\n\t\t2 + IEEE80211_WPAIE_MAXLEN : 0) +\n\t    ((ic->ic_flags & IEEE80211_F_HTON) ? 28 + 24 + 26 : 0));\n\tif (m == NULL)\n\t\treturn NULL;\n\n\tfrm = mtod(m, u_int8_t *);\n\tmemset(frm, 0, 8); frm += 8;\t/* timestamp is set by hardware */\n\tLE_WRITE_2(frm, ic->ic_bss->ni_intval); frm += 2;\n\tfrm = ieee80211_add_capinfo(frm, ic, ni);\n\tfrm = ieee80211_add_ssid(frm, ic->ic_bss->ni_essid,\n\t    ic->ic_bss->ni_esslen);\n\tfrm = ieee80211_add_rates(frm, rs);\n\tfrm = ieee80211_add_ds_params(frm, ic, ni);\n\tif (ic->ic_opmode == IEEE80211_M_IBSS)\n\t\tfrm = ieee80211_add_ibss_params(frm, ni);\n\tif (ic->ic_curmode == IEEE80211_MODE_11G)\n\t\tfrm = ieee80211_add_erp(frm, ic);\n\tif (rs->rs_nrates > IEEE80211_RATE_SIZE)\n\t\tfrm = ieee80211_add_xrates(frm, rs);\n\tif ((ic->ic_flags & IEEE80211_F_RSNON) &&\n\t    (ic->ic_bss->ni_rsnprotos & IEEE80211_PROTO_RSN))\n\t\tfrm = ieee80211_add_rsn(frm, ic, ic->ic_bss);\n\tif (ic->ic_flags & IEEE80211_F_QOS)\n\t\tfrm = ieee80211_add_edca_params(frm, ic);\n\tif ((ic->ic_flags & IEEE80211_F_RSNON) &&\n\t    (ic->ic_bss->ni_rsnprotos & IEEE80211_PROTO_WPA))\n\t\tfrm = ieee80211_add_wpa(frm, ic, ic->ic_bss);\n\tif (ic->ic_flags & IEEE80211_F_HTON) {\n\t\tfrm = ieee80211_add_htcaps(frm, ic);\n\t\tfrm = ieee80211_add_htop(frm, ic);\n\t\tfrm = ieee80211_add_wme_param(frm, ic);\n\t}\n\n    size_t l = frm - mtod(m, u_int8_t *);\n    mbuf_pkthdr_setlen(m, l);\n    mbuf_setlen(m, l);\n\n\treturn m;\n}\n#endif\t/* IEEE80211_STA_ONLY */\n\n/*-\n * Authentication frame format:\n * [2] Authentication algorithm number\n * [2] Authentication transaction sequence number\n * [2] Status code\n */\nmbuf_t\nieee80211_get_auth(struct ieee80211com *ic, struct ieee80211_node *ni,\n    u_int16_t status, u_int16_t seq)\n{\n\tmbuf_t m;\n    u_int8_t *frm;\n    \n    mbuf_gethdr(MBUF_DONTWAIT, MT_DATA, &m);\n    if (m == NULL)\n        return NULL;\n    mbuf_align_32(m, 2 * 3);\n    mbuf_pkthdr_setlen(m, 2 * 3);\n    mbuf_setlen(m, 2 * 3);\n    \n    frm = mtod(m, u_int8_t *);\n    LE_WRITE_2(frm, IEEE80211_AUTH_ALG_OPEN); frm += 2;\n    LE_WRITE_2(frm, seq); frm += 2;\n    LE_WRITE_2(frm, status);\n\n\treturn m;\n}\n\n/*-\n * Deauthentication frame format:\n * [2] Reason code\n */\nmbuf_t\nieee80211_get_deauth(struct ieee80211com *ic, struct ieee80211_node *ni,\n    u_int16_t reason)\n{\n\tmbuf_t m;\n    \n    mbuf_gethdr(MBUF_DONTWAIT, MT_DATA, &m);\n    if (m == NULL)\n        return NULL;\n    mbuf_align_32(m, 2);\n    \n    mbuf_pkthdr_setlen(m, 2);\n    mbuf_setlen(m, 2);\n    *mtod(m, u_int16_t *) = htole16(reason);\n\n\treturn m;\n}\n\n/*-\n * (Re)Association request frame format:\n * [2]   Capability information\n * [2]   Listen interval\n * [6*]  Current AP address (Reassociation only)\n * [tlv] SSID\n * [tlv] Supported rates\n * [tlv] Extended Supported Rates (802.11g)\n * [tlv] RSN (802.11i)\n * [tlv] QoS Capability (802.11e)\n * [tlv] HT Capabilities (802.11n)\n */\nmbuf_t\nieee80211_get_assoc_req(struct ieee80211com *ic, struct ieee80211_node *ni,\n    int type)\n{\n\tconst struct ieee80211_rateset *rs = &ni->ni_rates;\n\tmbuf_t m;\n\tu_int8_t *frm;\n\tu_int16_t capinfo;\n\n\tm = ieee80211_getmgmt(MBUF_DONTWAIT, MT_DATA,\n\t    2 + 2 +\n\t    ((type == IEEE80211_FC0_SUBTYPE_REASSOC_REQ) ?\n\t\tIEEE80211_ADDR_LEN : 0) +\n\t    2 + ni->ni_esslen +\n\t    2 + min(rs->rs_nrates, IEEE80211_RATE_SIZE) +\n\t    ((rs->rs_nrates > IEEE80211_RATE_SIZE) ?\n\t\t2 + rs->rs_nrates - IEEE80211_RATE_SIZE : 0) +\n\t    (((ic->ic_flags & IEEE80211_F_RSNON) &&\n\t      (ni->ni_rsnprotos & IEEE80211_PROTO_RSN)) ?\n\t\t2 + IEEE80211_RSNIE_MAXLEN : 0) +\n\t    ((ni->ni_flags & IEEE80211_NODE_QOS) ? 2 + 1 : 0) +\n\t    (((ic->ic_flags & IEEE80211_F_RSNON) &&\n\t      (ni->ni_rsnprotos & IEEE80211_PROTO_WPA)) ?\n\t\t2 + IEEE80211_WPAIE_MAXLEN : 0) +\n\t    ((ic->ic_flags & IEEE80211_F_HTON) ? sizeof(struct ieee80211_ie_htcap) + sizeof(struct ieee80211_wme_info) : 0) +\n        ((ic->ic_flags & IEEE80211_F_VHTON) ? sizeof(struct ieee80211_ie_vhtcap) + 2 : 0) +\n        ((ic->ic_flags & IEEE80211_F_HEON) ? (sizeof(struct ieee80211_he_cap_elem) + 2 + 1 + sizeof(struct ieee80211_he_mcs_nss_supp) + IEEE80211_HE_PPE_THRES_MAX_LEN) : 0));\n\tif (m == NULL)\n\t\treturn NULL;\n\n\tfrm = mtod(m, u_int8_t *);\n\tcapinfo = IEEE80211_CAPINFO_ESS;\n\tif (ic->ic_flags & IEEE80211_F_WEPON)\n\t\tcapinfo |= IEEE80211_CAPINFO_PRIVACY;\n\tif ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&\n\t    IEEE80211_IS_CHAN_2GHZ(ni->ni_chan))\n\t\tcapinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE;\n\tif (ic->ic_caps & IEEE80211_C_SHSLOT)\n\t\tcapinfo |= IEEE80211_CAPINFO_SHORT_SLOTTIME;\n\tLE_WRITE_2(frm, capinfo); frm += 2;\n\tLE_WRITE_2(frm, ic->ic_lintval); frm += 2;\n\tif (type == IEEE80211_FC0_SUBTYPE_REASSOC_REQ) {\n\t\tIEEE80211_ADDR_COPY(frm, ic->ic_bss->ni_bssid);\n\t\tfrm += IEEE80211_ADDR_LEN;\n\t}\n\tfrm = ieee80211_add_ssid(frm, ni->ni_essid, ni->ni_esslen);\n\tfrm = ieee80211_add_rates(frm, rs);\n\tif (rs->rs_nrates > IEEE80211_RATE_SIZE)\n\t\tfrm = ieee80211_add_xrates(frm, rs);\n\tif ((ic->ic_flags & IEEE80211_F_RSNON) &&\n\t\t(ni->ni_rsnprotos & IEEE80211_PROTO_RSN)) {\n#ifdef USE_APPLE_SUPPLICANT\n\t\tif (ic->ic_rsn_ie_override[1] > 0) {\n\t\t\tmemcpy(frm, ic->ic_rsn_ie_override, 2 + ic->ic_rsn_ie_override[1]);\n\t\t\tfrm += 2 + ic->ic_rsn_ie_override[1];\n\t\t}\n\t\telse\n#endif\n\t\tfrm = ieee80211_add_rsn(frm, ic, ni);\n\t}\n\tif (ni->ni_flags & IEEE80211_NODE_QOS)\n\t\tfrm = ieee80211_add_qos_capability(frm, ic);\n\tif ((ic->ic_flags & IEEE80211_F_RSNON) &&\n\t\t(ni->ni_rsnprotos & IEEE80211_PROTO_WPA)) {\n#ifdef USE_APPLE_SUPPLICANT\n\t\tif (ic->ic_rsn_ie_override[1] > 0) {\n\t\t\tmemcpy(frm, ic->ic_rsn_ie_override, 2 + ic->ic_rsn_ie_override[1]);\n\t\t\tfrm += 2 + ic->ic_rsn_ie_override[1];\n\t\t}\n\t\telse\n#endif\n\t\tfrm = ieee80211_add_wpa(frm, ic, ni);\n\t}\n\tif (ic->ic_flags & IEEE80211_F_HTON) {\n\t\tfrm = ieee80211_add_htcaps(frm, ic);\n\t\tfrm = ieee80211_add_wme_info(frm, ic);\n\t}\n    \n    if (ic->ic_flags & IEEE80211_F_VHTON)\n        frm = ieee80211_add_vhtcaps(frm, ic);\n    \n    if (ic->ic_flags & IEEE80211_F_HEON)\n        frm = ieee80211_add_hecaps(frm, ic);\n\n    size_t l = frm - mtod(m, u_int8_t *);\n    mbuf_pkthdr_setlen(m, l);\n    mbuf_setlen(m, l);\n\n\treturn m;\n}\n\n#ifndef IEEE80211_STA_ONLY\n/*-\n * (Re)Association response frame format:\n * [2]   Capability information\n * [2]   Status code\n * [2]   Association ID (AID)\n * [tlv] Supported rates\n * [tlv] Extended Supported Rates (802.11g)\n * [tlv] EDCA Parameter Set (802.11e)\n * [tlv] Timeout Interval (802.11w)\n * [tlv] HT Capabilities (802.11n)\n * [tlv] HT Operation (802.11n)\n */\nmbuf_t\nieee80211_get_assoc_resp(struct ieee80211com *ic, struct ieee80211_node *ni,\n    u_int16_t status)\n{\n\tconst struct ieee80211_rateset *rs = &ni->ni_rates;\n\tmbuf_t m;\n\tu_int8_t *frm;\n\n\tm = ieee80211_getmgmt(MBUF_DONTWAIT, MT_DATA,\n\t    2 + 2 + 2 +\n\t    2 + min(rs->rs_nrates, IEEE80211_RATE_SIZE) +\n\t    ((rs->rs_nrates > IEEE80211_RATE_SIZE) ?\n\t\t2 + rs->rs_nrates - IEEE80211_RATE_SIZE : 0) +\n\t    ((ni->ni_flags & IEEE80211_NODE_QOS) ? 2 + 18 : 0) +\n\t    ((status == IEEE80211_STATUS_TRY_AGAIN_LATER) ? 2 + 7 : 0) +\n\t    ((ic->ic_flags & IEEE80211_F_HTON) ? 28 + 24 + 26 : 0));\n\tif (m == NULL)\n\t\treturn NULL;\n\n\tfrm = mtod(m, u_int8_t *);\n\tfrm = ieee80211_add_capinfo(frm, ic, ni);\n\tLE_WRITE_2(frm, status); frm += 2;\n\tif (status == IEEE80211_STATUS_SUCCESS)\n\t\tLE_WRITE_2(frm, ni->ni_associd);\n\telse\n\t\tLE_WRITE_2(frm, 0);\n\tfrm += 2;\n\tfrm = ieee80211_add_rates(frm, rs);\n\tif (rs->rs_nrates > IEEE80211_RATE_SIZE)\n\t\tfrm = ieee80211_add_xrates(frm, rs);\n\tif (ni->ni_flags & IEEE80211_NODE_QOS)\n\t\tfrm = ieee80211_add_edca_params(frm, ic);\n\tif ((ni->ni_flags & IEEE80211_NODE_MFP) &&\n\t    status == IEEE80211_STATUS_TRY_AGAIN_LATER) {\n\t\t/* Association Comeback Time */\n\t\tfrm = ieee80211_add_tie(frm, 3, 1000 /* XXX */);\n\t}\n\tif (ic->ic_flags & IEEE80211_F_HTON) {\n\t\tfrm = ieee80211_add_htcaps(frm, ic);\n\t\tfrm = ieee80211_add_htop(frm, ic);\n\t\tfrm = ieee80211_add_wme_param(frm, ic);\n\t}\n\n    size_t l = frm - mtod(m, u_int8_t *);\n    mbuf_pkthdr_setlen(m, l);\n    mbuf_setlen(m, l);\n\n\treturn m;\n}\n#endif\t/* IEEE80211_STA_ONLY */\n\n/*-\n * Disassociation frame format:\n * [2] Reason code\n */\nmbuf_t\nieee80211_get_disassoc(struct ieee80211com *ic, struct ieee80211_node *ni,\n    u_int16_t reason)\n{\n\tmbuf_t m;\n\n\tmbuf_gethdr(MBUF_DONTWAIT, MT_DATA, &m);\n\tif (m == NULL)\n\t\treturn NULL;\n\tmbuf_align_32(m, 2);\n    mbuf_pkthdr_setlen(m, 2);\n    mbuf_setlen(m, 2);\n\n\t*mtod(m, u_int16_t *) = htole16(reason);\n\n\treturn m;\n}\n\n/*-\n * ADDBA Request frame format:\n * [1] Category\n * [1] Action\n * [1] Dialog Token\n * [2] Block Ack Parameter Set\n * [2] Block Ack Timeout Value\n * [2] Block Ack Starting Sequence Control\n */\nmbuf_t\nieee80211_get_addba_req(struct ieee80211com *ic, struct ieee80211_node *ni,\n    u_int8_t tid)\n{\n\tstruct ieee80211_tx_ba *ba = &ni->ni_tx_ba[tid];\n\tmbuf_t m;\n\tu_int8_t *frm;\n\n\tm = ieee80211_getmgmt(MBUF_DONTWAIT, MT_DATA, 9);\n\tif (m == NULL)\n\t\treturn m;\n\n\tfrm = mtod(m, u_int8_t *);\n\t*frm++ = IEEE80211_CATEG_BA;\n\t*frm++ = IEEE80211_ACTION_ADDBA_REQ;\n\t*frm++ = ba->ba_token;\n\tLE_WRITE_2(frm, ba->ba_params); frm += 2;\n\tLE_WRITE_2(frm, ba->ba_timeout_val / IEEE80211_DUR_TU); frm += 2;\n\tLE_WRITE_2(frm, ba->ba_winstart << IEEE80211_SEQ_SEQ_SHIFT); frm += 2;\n\n    size_t l = frm - mtod(m, u_int8_t *);\n    mbuf_pkthdr_setlen(m, l);\n    mbuf_setlen(m, l);\n\n\treturn m;\n}\n\n/* Move Tx BA window forward to the specified SSN. */\nvoid\nieee80211_output_ba_move_window(struct ieee80211com *ic,\n    struct ieee80211_node *ni, uint8_t tid, uint16_t ssn)\n{\n\tstruct ieee80211_tx_ba *ba = &ni->ni_tx_ba[tid];\n\tuint16_t s = ba->ba_winstart;\n\n\twhile (SEQ_LT(s, ssn) && ba->ba_bitmap) {\n\t\ts = (s + 1) % 0xfff;\n\t\tba->ba_bitmap >>= 1;\n\t}\n\n\tba->ba_winstart = (ssn & 0xfff);\n\tba->ba_winend = (ba->ba_winstart + ba->ba_winsize - 1) & 0xfff;\n}\n\n/*\n * Move Tx BA window forward up to the first hole in the bitmap\n * or up to the specified SSN, whichever comes first.\n * After calling this function, frames before the start of the\n * potentially changed BA window should be discarded.\n */\nvoid\nieee80211_output_ba_move_window_to_first_unacked(struct ieee80211com *ic,\n    struct ieee80211_node *ni, uint8_t tid, uint16_t ssn)\n{\n\tstruct ieee80211_tx_ba *ba = &ni->ni_tx_ba[tid];\n\tuint16_t s = ba->ba_winstart;\n\tuint64_t bitmap = ba->ba_bitmap;\n\tint can_move_window = 0;\n\n\twhile (bitmap && SEQ_LT(s, ssn)) {\n\t\tif ((bitmap & 1) == 0)\n\t\t\tbreak;\n\t\ts = (s + 1) % 0xfff;\n\t\tbitmap >>= 1;\n\t\tcan_move_window = 1;\n\t}\n\n\tif (can_move_window)\n\t\tieee80211_output_ba_move_window(ic, ni, tid, s);\n}\n\n/* Record an ACK for a frame with a given SSN within the Tx BA window. */\nvoid\nieee80211_output_ba_record_ack(struct ieee80211com *ic,\n    struct ieee80211_node *ni, uint8_t tid, uint16_t ssn)\n{\n\tstruct ieee80211_tx_ba *ba = &ni->ni_tx_ba[tid];\n\tint i = 0;\n\tuint16_t s = ba->ba_winstart;\n\n\t_KASSERT(!SEQ_LT(ssn, ba->ba_winstart));\n\t_KASSERT(!SEQ_LT(ba->ba_winend, ssn));\n\n\twhile (SEQ_LT(s, ssn)) {\n\t\ts = (s + 1) % 0xfff;\n\t\ti++;\n\t}\n\tif (i < ba->ba_winsize)\n\t\tba->ba_bitmap |= (1 << i);\n}\n\n/*-\n * ADDBA Response frame format:\n * [1] Category\n * [1] Action\n * [1] Dialog Token\n * [2] Status Code\n * [2] Block Ack Parameter Set\n * [2] Block Ack Timeout Value\n */\nmbuf_t\nieee80211_get_addba_resp(struct ieee80211com *ic, struct ieee80211_node *ni,\n    u_int8_t tid, u_int8_t token, u_int16_t status)\n{\n\tstruct ieee80211_rx_ba *ba = &ni->ni_rx_ba[tid];\n\tmbuf_t m;\n\tu_int8_t *frm;\n\tu_int16_t params;\n\n\tm = ieee80211_getmgmt(MBUF_DONTWAIT, MT_DATA, 9);\n\tif (m == NULL)\n\t\treturn m;\n\n\tfrm = mtod(m, u_int8_t *);\n\t*frm++ = IEEE80211_CATEG_BA;\n\t*frm++ = IEEE80211_ACTION_ADDBA_RESP;\n\t*frm++ = token;\n\tLE_WRITE_2(frm, status); frm += 2;\n\tif (status == 0)\n\t\tparams = ba->ba_params;\n\telse\n\t\tparams = tid << IEEE80211_ADDBA_TID_SHIFT;\n\tLE_WRITE_2(frm, params); frm += 2;\n\tif (status == 0)\n\t\tLE_WRITE_2(frm, ba->ba_timeout_val / IEEE80211_DUR_TU);\n\telse\n\t\tLE_WRITE_2(frm, 0);\n\tfrm += 2;\n\n    size_t l = frm - mtod(m, u_int8_t *);\n    mbuf_pkthdr_setlen(m, l);\n    mbuf_setlen(m, l);\n\n\treturn m;\n}\n\n/*-\n * DELBA frame format:\n * [1] Category\n * [1] Action\n * [2] DELBA Parameter Set\n * [2] Reason Code\n */\nmbuf_t\nieee80211_get_delba(struct ieee80211com *ic, struct ieee80211_node *ni,\n    u_int8_t tid, u_int8_t dir, u_int16_t reason)\n{\n\tmbuf_t m;\n\tu_int8_t *frm;\n\tu_int16_t params;\n\n\tm = ieee80211_getmgmt(MBUF_DONTWAIT, MT_DATA, 6);\n\tif (m == NULL)\n\t\treturn m;\n\n\tfrm = mtod(m, u_int8_t *);\n\t*frm++ = IEEE80211_CATEG_BA;\n\t*frm++ = IEEE80211_ACTION_DELBA;\n\tparams = tid << 12;\n\tif (dir)\n\t\tparams |= IEEE80211_DELBA_INITIATOR;\n\tLE_WRITE_2(frm, params); frm += 2;\n\tLE_WRITE_2(frm, reason); frm += 2;\n\n    size_t l = frm - mtod(m, u_int8_t *);\n    mbuf_pkthdr_setlen(m, l);\n    mbuf_setlen(m, l);\n\n\treturn m;\n}\n\n/*-\n * SA Query Request/Reponse frame format:\n * [1]  Category\n * [1]  Action\n * [16] Transaction Identifier\n */\nmbuf_t\nieee80211_get_sa_query(struct ieee80211com *ic, struct ieee80211_node *ni,\n    u_int8_t action)\n{\n\tmbuf_t m;\n\tu_int8_t *frm;\n\n\tm = ieee80211_getmgmt(MBUF_DONTWAIT, MT_DATA, 4);\n\tif (m == NULL)\n\t\treturn NULL;\n\n\tfrm = mtod(m, u_int8_t *);\n\t*frm++ = IEEE80211_CATEG_SA_QUERY;\n\t*frm++ = action;\t/* ACTION_SA_QUERY_REQ/RESP */\n\tLE_WRITE_2(frm, ni->ni_sa_query_trid); frm += 2;\n\n    size_t l = frm - mtod(m, u_int8_t *);\n    mbuf_pkthdr_setlen(m, l);\n    mbuf_setlen(m, l);\n\n\treturn m;\n}\n\nmbuf_t\nieee80211_get_action(struct ieee80211com *ic, struct ieee80211_node *ni,\n    u_int8_t categ, u_int8_t action, int arg)\n{\n\tmbuf_t m = NULL;\n\n\tswitch (categ) {\n\tcase IEEE80211_CATEG_BA:\n\t\tswitch (action) {\n\t\tcase IEEE80211_ACTION_ADDBA_REQ:\n\t\t\tm = ieee80211_get_addba_req(ic, ni, arg & 0xffff);\n\t\t\tbreak;\n\t\tcase IEEE80211_ACTION_ADDBA_RESP:\n\t\t\tm = ieee80211_get_addba_resp(ic, ni, arg & 0xff,\n\t\t\t    arg >> 8, arg >> 16);\n\t\t\tbreak;\n\t\tcase IEEE80211_ACTION_DELBA:\n\t\t\tm = ieee80211_get_delba(ic, ni, arg & 0xff, arg >> 8,\n\t\t\t    arg >> 16);\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\tcase IEEE80211_CATEG_SA_QUERY:\n\t\tswitch (action) {\n#ifndef IEEE80211_STA_ONLY\n\t\tcase IEEE80211_ACTION_SA_QUERY_REQ:\n#endif\n\t\tcase IEEE80211_ACTION_SA_QUERY_RESP:\n\t\t\tm = ieee80211_get_sa_query(ic, ni, action);\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\t}\n\treturn m;\n}\n\n/*\n * Send a management frame.  The node is for the destination (or ic_bss\n * when in station mode).  Nodes other than ic_bss have their reference\n * count bumped to reflect our use for an indeterminant time.\n */\nint\nieee80211_send_mgmt(struct ieee80211com *ic, struct ieee80211_node *ni,\n    int type, int arg1, int arg2)\n{\n#define\tsenderr(_x, _v)\tdo { ic->ic_stats._v++; ret = _x; goto bad; } while (0)\n\tstruct _ifnet *ifp = &ic->ic_if;\n\tmbuf_t m;\n\tint ret, timer;\n\n\tif (ni == NULL)\n\t\tpanic(\"null node\");\n\n\t/*\n\t * Hold a reference on the node so it doesn't go away until after\n\t * the xmit is complete all the way in the driver.  On error we\n\t * will remove our reference.\n\t */\n\tieee80211_ref_node(ni);\n\ttimer = 0;\n\tswitch (type) {\n\tcase IEEE80211_FC0_SUBTYPE_PROBE_REQ:\n\t\tif ((m = ieee80211_get_probe_req(ic, ni)) == NULL)\n\t\t\tsenderr(ENOMEM, is_tx_nombuf);\n\n\t\ttimer = IEEE80211_TRANS_WAIT;\n\t\tbreak;\n#ifndef IEEE80211_STA_ONLY\n\tcase IEEE80211_FC0_SUBTYPE_PROBE_RESP:\n\t\tif ((m = ieee80211_get_probe_resp(ic, ni)) == NULL)\n\t\t\tsenderr(ENOMEM, is_tx_nombuf);\n\t\tbreak;\n#endif\n\tcase IEEE80211_FC0_SUBTYPE_AUTH:\n\t\tm = ieee80211_get_auth(ic, ni, arg1 >> 16, arg1 & 0xffff);\n\t\tif (m == NULL)\n\t\t\tsenderr(ENOMEM, is_tx_nombuf);\n\n\t\tif (ic->ic_opmode == IEEE80211_M_STA)\n\t\t\ttimer = IEEE80211_TRANS_WAIT;\n\t\tbreak;\n\n\tcase IEEE80211_FC0_SUBTYPE_DEAUTH:\n\t\tif ((m = ieee80211_get_deauth(ic, ni, arg1)) == NULL)\n\t\t\tsenderr(ENOMEM, is_tx_nombuf);\n#ifndef IEEE80211_STA_ONLY\n\t\tif ((ifp->if_flags & IFF_DEBUG) &&\n\t\t    (ic->ic_opmode == IEEE80211_M_HOSTAP ||\n\t\t    ic->ic_opmode == IEEE80211_M_IBSS))\n\t\t\tXYLog(\"%s: station %s deauthenticate (reason %d)\\n\",\n\t\t\t    ifp->if_xname, ether_sprintf(ni->ni_macaddr),\n\t\t\t    arg1);\n#endif\n\t\tbreak;\n\n\tcase IEEE80211_FC0_SUBTYPE_ASSOC_REQ:\n\tcase IEEE80211_FC0_SUBTYPE_REASSOC_REQ:\n\t\tif ((m = ieee80211_get_assoc_req(ic, ni, type)) == NULL)\n\t\t\tsenderr(ENOMEM, is_tx_nombuf);\n\n\t\ttimer = IEEE80211_TRANS_WAIT;\n\t\tbreak;\n#ifndef IEEE80211_STA_ONLY\n\tcase IEEE80211_FC0_SUBTYPE_ASSOC_RESP:\n\tcase IEEE80211_FC0_SUBTYPE_REASSOC_RESP:\n\t\tif ((m = ieee80211_get_assoc_resp(ic, ni, arg1)) == NULL)\n\t\t\tsenderr(ENOMEM, is_tx_nombuf);\n\t\tbreak;\n#endif\n\tcase IEEE80211_FC0_SUBTYPE_DISASSOC:\n\t\tif ((m = ieee80211_get_disassoc(ic, ni, arg1)) == NULL)\n\t\t\tsenderr(ENOMEM, is_tx_nombuf);\n#ifndef IEEE80211_STA_ONLY\n\t\tif ((ifp->if_flags & IFF_DEBUG) &&\n\t\t    (ic->ic_opmode == IEEE80211_M_HOSTAP ||\n\t\t    ic->ic_opmode == IEEE80211_M_IBSS))\n\t\t\tXYLog(\"%s: station %s disassociate (reason %d)\\n\",\n\t\t\t    ifp->if_xname, ether_sprintf(ni->ni_macaddr),\n\t\t\t    arg1);\n#endif\n\t\tbreak;\n\n\tcase IEEE80211_FC0_SUBTYPE_ACTION:\n\t\tm = ieee80211_get_action(ic, ni, arg1 >> 16, arg1 & 0xffff,\n\t\t    arg2);\n\t\tif (m == NULL)\n\t\t\tsenderr(ENOMEM, is_tx_nombuf);\n\t\tbreak;\n\n\tdefault:\n\t\tDPRINTF((\"invalid mgmt frame type %u\\n\", type));\n\t\tsenderr(EINVAL, is_tx_unknownmgt);\n\t\t/* NOTREACHED */\n\t}\n\n\tret = ieee80211_mgmt_output(ifp, ni, m, type);\n\tif (ret == 0) {\n\t\tif (timer)\n\t\t\tic->ic_mgt_timer = timer;\n\t} else {\nbad:\n\t\tieee80211_release_node(ic, ni);\n\t}\n\treturn ret;\n#undef senderr\n}\n\n/*\n * Build a RTS (Request To Send) control frame (see 7.2.1.1).\n */\nmbuf_t\nieee80211_get_rts(struct ieee80211com *ic, const struct ieee80211_frame *wh,\n    u_int16_t dur)\n{\n\tstruct ieee80211_frame_rts *rts;\n\tmbuf_t m;\n\n\tmbuf_gethdr(MBUF_DONTWAIT, MT_DATA, &m);\n\tif (m == NULL)\n\t\treturn NULL;\n\n    size_t l = sizeof(struct ieee80211_frame_rts);\n    mbuf_pkthdr_setlen(m, l);\n    mbuf_setlen(m, l);\n\n\trts = mtod(m, struct ieee80211_frame_rts *);\n\trts->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_CTL |\n\t    IEEE80211_FC0_SUBTYPE_RTS;\n\trts->i_fc[1] = IEEE80211_FC1_DIR_NODS;\n\t*(u_int16_t *)rts->i_dur = htole16(dur);\n\tIEEE80211_ADDR_COPY(rts->i_ra, wh->i_addr1);\n\tIEEE80211_ADDR_COPY(rts->i_ta, wh->i_addr2);\n\n\treturn m;\n}\n\n/*\n * Build a CTS-to-self (Clear To Send) control frame (see 7.2.1.2).\n */\nmbuf_t\nieee80211_get_cts_to_self(struct ieee80211com *ic, u_int16_t dur)\n{\n\tstruct ieee80211_frame_cts *cts;\n\tmbuf_t m;\n\n    mbuf_gethdr(MBUF_DONTWAIT, MT_DATA, &m);\n\tif (m == NULL)\n\t\treturn NULL;\n\n    size_t l = sizeof(struct ieee80211_frame_cts);\n    mbuf_pkthdr_setlen(m, l);\n    mbuf_setlen(m, l);\n\n\tcts = mtod(m, struct ieee80211_frame_cts *);\n\tcts->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_CTL |\n\t    IEEE80211_FC0_SUBTYPE_CTS;\n\tcts->i_fc[1] = IEEE80211_FC1_DIR_NODS;\n\t*(u_int16_t *)cts->i_dur = htole16(dur);\n\tIEEE80211_ADDR_COPY(cts->i_ra, ic->ic_myaddr);\n\n\treturn m;\n}\n\n/*\n * Build a compressed Block Ack Request control frame.\n */\nmbuf_t\nieee80211_get_compressed_bar(struct ieee80211com *ic,\n    struct ieee80211_node *ni, int tid, uint16_t ssn)\n{\n\tstruct ieee80211_frame_min *wh;\n\tuint8_t *frm;\n\tuint16_t ctl;\n\tmbuf_t m;\n\n    mbuf_gethdr(MBUF_DONTWAIT, MT_DATA, &m);\n\tif (m == NULL)\n\t\treturn NULL;\n\n    size_t l = sizeof(struct ieee80211_frame_min) +\n    sizeof(ctl) + sizeof(ssn);\n    mbuf_pkthdr_setlen(m, l);\n    mbuf_setlen(m, l);\n\n\twh = mtod(m, struct ieee80211_frame_min *);\n\twh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_CTL |\n\t    IEEE80211_FC0_SUBTYPE_BAR;\n\twh->i_fc[1] = IEEE80211_FC1_DIR_NODS;\n\t*(u_int16_t *)wh->i_dur = 0;\n\tIEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_macaddr);\n\tIEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_myaddr);\n\tfrm = (uint8_t *)&wh[1];\n\n\tctl = IEEE80211_BA_COMPRESSED | (tid << IEEE80211_BA_TID_INFO_SHIFT);\n\tLE_WRITE_2(frm, ctl);\n\tfrm += 2;\n\n\tLE_WRITE_2(frm, ssn << IEEE80211_SEQ_SEQ_SHIFT);\n\tfrm += 2;\n\n    l = frm - mtod(m, u_int8_t *);\n    mbuf_pkthdr_setlen(m, l);\n    mbuf_setlen(m, l);\n    \n    mbuf_pkthdr_setrcvif(m, (ifnet_t)ni);\n//\tm->m_pkthdr.ph_cookie = ni;\n\n\treturn m;\n}\n\n#ifndef IEEE80211_STA_ONLY\n/*-\n * Beacon frame format:\n * [8]   Timestamp\n * [2]   Beacon interval\n * [2]   Capability\n * [tlv] Service Set Identifier (SSID)\n * [tlv] Supported rates\n * [tlv] DS Parameter Set (802.11g)\n * [tlv] IBSS Parameter Set\n * [tlv] Traffic Indication Map (TIM)\n * [tlv] ERP Information (802.11g)\n * [tlv] Extended Supported Rates (802.11g)\n * [tlv] RSN (802.11i)\n * [tlv] EDCA Parameter Set (802.11e)\n * [tlv] HT Capabilities (802.11n)\n * [tlv] HT Operation (802.11n)\n */\nmbuf_t\nieee80211_beacon_alloc(struct ieee80211com *ic, struct ieee80211_node *ni)\n{\n\tconst struct ieee80211_rateset *rs = &ni->ni_rates;\n\tstruct ieee80211_frame *wh;\n\tmbuf_t m;\n\tu_int8_t *frm;\n\n\tm = ieee80211_getmgmt(MBUF_DONTWAIT, MT_DATA,\n\t    8 + 2 + 2 +\n\t    2 + ((ic->ic_userflags & IEEE80211_F_HIDENWID) ?\n\t    0 : ni->ni_esslen) +\n\t    2 + min(rs->rs_nrates, IEEE80211_RATE_SIZE) +\n\t    2 + 1 +\n\t    2 + ((ic->ic_opmode == IEEE80211_M_IBSS) ? 2 : 254) +\n\t    ((ic->ic_curmode == IEEE80211_MODE_11G) ? 2 + 1 : 0) +\n\t    ((rs->rs_nrates > IEEE80211_RATE_SIZE) ?\n\t\t2 + rs->rs_nrates - IEEE80211_RATE_SIZE : 0) +\n\t    (((ic->ic_flags & IEEE80211_F_RSNON) &&\n\t      (ni->ni_rsnprotos & IEEE80211_PROTO_RSN)) ?\n\t\t2 + IEEE80211_RSNIE_MAXLEN : 0) +\n\t    ((ic->ic_flags & IEEE80211_F_QOS) ? 2 + 18 : 0) +\n\t    (((ic->ic_flags & IEEE80211_F_RSNON) &&\n\t      (ni->ni_rsnprotos & IEEE80211_PROTO_WPA)) ?\n\t\t2 + IEEE80211_WPAIE_MAXLEN : 0) +\n\t    ((ic->ic_flags & IEEE80211_F_HTON) ? 28 + 24 + 26 : 0));\n\tif (m == NULL)\n\t\treturn NULL;\n\n    mbuf_prepend(&m, sizeof(struct ieee80211_frame), MBUF_DONTWAIT);\n\tif (m == NULL)\n\t\treturn NULL;\n\twh = mtod(m, struct ieee80211_frame *);\n\twh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT |\n\t    IEEE80211_FC0_SUBTYPE_BEACON;\n\twh->i_fc[1] = IEEE80211_FC1_DIR_NODS;\n\t*(u_int16_t *)wh->i_dur = 0;\n\tIEEE80211_ADDR_COPY(wh->i_addr1, etherbroadcastaddr);\n\tIEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_myaddr);\n\tIEEE80211_ADDR_COPY(wh->i_addr3, ni->ni_bssid);\n\t*(u_int16_t *)wh->i_seq = 0;\n\n\tfrm = (u_int8_t *)&wh[1];\n\tmemset(frm, 0, 8); frm += 8;\t/* timestamp is set by hardware */\n\tLE_WRITE_2(frm, ni->ni_intval); frm += 2;\n\tfrm = ieee80211_add_capinfo(frm, ic, ni);\n\tif (ic->ic_userflags & IEEE80211_F_HIDENWID)\n\t\tfrm = ieee80211_add_ssid(frm, NULL, 0);\n\telse\n\t\tfrm = ieee80211_add_ssid(frm, ni->ni_essid, ni->ni_esslen);\n\tfrm = ieee80211_add_rates(frm, rs);\n\tfrm = ieee80211_add_ds_params(frm, ic, ni);\n\tif (ic->ic_opmode == IEEE80211_M_IBSS)\n\t\tfrm = ieee80211_add_ibss_params(frm, ni);\n\telse\n\t\tfrm = ieee80211_add_tim(frm, ic);\n\tif (ic->ic_curmode == IEEE80211_MODE_11G)\n\t\tfrm = ieee80211_add_erp(frm, ic);\n\tif (rs->rs_nrates > IEEE80211_RATE_SIZE)\n\t\tfrm = ieee80211_add_xrates(frm, rs);\n\tif ((ic->ic_flags & IEEE80211_F_RSNON) &&\n\t    (ni->ni_rsnprotos & IEEE80211_PROTO_RSN))\n\t\tfrm = ieee80211_add_rsn(frm, ic, ni);\n\tif (ic->ic_flags & IEEE80211_F_QOS)\n\t\tfrm = ieee80211_add_edca_params(frm, ic);\n\tif ((ic->ic_flags & IEEE80211_F_RSNON) &&\n\t    (ni->ni_rsnprotos & IEEE80211_PROTO_WPA))\n\t\tfrm = ieee80211_add_wpa(frm, ic, ni);\n\tif (ic->ic_flags & IEEE80211_F_HTON) {\n\t\tfrm = ieee80211_add_htcaps(frm, ic);\n\t\tfrm = ieee80211_add_htop(frm, ic);\n\t\tfrm = ieee80211_add_wme_param(frm, ic);\n\t}\n\n    size_t l = frm - mtod(m, u_int8_t *);\n    mbuf_pkthdr_setlen(m, l);\n    mbuf_setlen(m, l);\n    mbuf_pkthdr_setrcvif(m, (ifnet_t)ni);\n//\tm->m_pkthdr.ph_cookie = ni;\n\n\treturn m;\n}\n\n/*\n * Check if an outgoing MSDU or management frame should be buffered into\n * the AP for power management.  Return 1 if the frame was buffered into\n * the AP, or 0 if the frame shall be transmitted immediately.\n */\nint\nieee80211_pwrsave(struct ieee80211com *ic, mbuf_t m,\n    struct ieee80211_node *ni)\n{\n\tconst struct ieee80211_frame *wh;\n\tint pssta = 0;\n\n\t_KASSERT(ic->ic_opmode == IEEE80211_M_HOSTAP);\n\tif (!(ic->ic_caps & IEEE80211_C_APPMGT))\n\t\treturn 0;\n\n\twh = mtod(m, struct ieee80211_frame *);\n\tif (IEEE80211_IS_MULTICAST(wh->i_addr1)) {\n\t\t/*\n\t\t * Buffer group addressed MSDUs with the Order bit clear\n\t\t * if any associated STAs are in PS mode.\n\t\t */\n\t\tieee80211_iterate_nodes(ic, ieee80211_count_pssta, &pssta);\n\t\tif ((wh->i_fc[1] & IEEE80211_FC1_ORDER) || pssta == 0)\n\t\t\treturn 0;\n\t\tic->ic_tim_mcast_pending = 1;\n\t} else {\n\t\t/*\n\t\t * Buffer MSDUs, A-MSDUs or management frames destined for\n\t\t * PS STAs.\n\t\t */\n\t\tif (ni->ni_pwrsave == IEEE80211_PS_AWAKE ||\n\t\t    (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==\n\t\t    IEEE80211_FC0_TYPE_CTL)\n\t\t\treturn 0;\n\t\tif (mq_empty(&ni->ni_savedq))\n\t\t\t(*ic->ic_set_tim)(ic, ni->ni_associd, 1);\n\t}\n\t/* NB: ni == ic->ic_bss for broadcast/multicast */\n\t/*\n\t * Similar to ieee80211_mgmt_output, store the node in a\n\t * special pkthdr field.\n\t */\n    mbuf_pkthdr_setrcvif(m, (ifnet_t)ni);\n//\tm->m_pkthdr.ph_cookie = ni;\n\tmq_enqueue(&ni->ni_savedq, m);\n\treturn 1;\n}\n#endif\t/* IEEE80211_STA_ONLY */\n"
  },
  {
    "path": "itl80211/openbsd/net80211/ieee80211_pae_input.c",
    "content": "/*\n * Copyright (C) 2020  钟先耀\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n */\n/*\t$OpenBSD: ieee80211_pae_input.c,v 1.33 2019/09/02 12:54:21 stsp Exp $\t*/\n\n/*-\n * Copyright (c) 2007,2008 Damien Bergamini <damien.bergamini@free.fr>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n/*\n * This code implements the 4-Way Handshake and Group Key Handshake protocols\n * (both Supplicant and Authenticator Key Receive state machines) defined in\n * IEEE Std 802.11-2007 section 8.5.\n */\n\n#include <sys/param.h>\n#include <sys/systm.h>\n#include <sys/mbuf.h>\n#include <sys/kernel.h>\n#include <sys/socket.h>\n#include <sys/sockio.h>\n#include <sys/errno.h>\n\n#include <net/if.h>\n#include <net/if_dl.h>\n#include <net/if_media.h>\n\n#include <netinet/in.h>\n#include <netinet/if_ether.h>\n#include <sys/_arc4random.h>\n\n#include <net80211/ieee80211_var.h>\n#include <net80211/ieee80211_priv.h>\n\nvoid\tieee80211_recv_4way_msg1(struct ieee80211com *,\n                                 struct ieee80211_eapol_key *, struct ieee80211_node *);\n#ifndef IEEE80211_STA_ONLY\nvoid\tieee80211_recv_4way_msg2(struct ieee80211com *,\n                                 struct ieee80211_eapol_key *, struct ieee80211_node *,\n                                 const u_int8_t *);\n#endif\nint\tieee80211_must_update_group_key(struct ieee80211_key *, const uint8_t *,\n                                    int);\nvoid\tieee80211_recv_4way_msg3(struct ieee80211com *,\n                                 struct ieee80211_eapol_key *, struct ieee80211_node *);\n#ifndef IEEE80211_STA_ONLY\nvoid\tieee80211_recv_4way_msg4(struct ieee80211com *,\n                                 struct ieee80211_eapol_key *, struct ieee80211_node *);\nvoid\tieee80211_recv_4way_msg2or4(struct ieee80211com *,\n                                    struct ieee80211_eapol_key *, struct ieee80211_node *);\n#endif\nvoid\tieee80211_recv_rsn_group_msg1(struct ieee80211com *,\n                                      struct ieee80211_eapol_key *, struct ieee80211_node *);\nvoid\tieee80211_recv_wpa_group_msg1(struct ieee80211com *,\n                                      struct ieee80211_eapol_key *, struct ieee80211_node *);\n#ifndef IEEE80211_STA_ONLY\nvoid\tieee80211_recv_group_msg2(struct ieee80211com *,\n                                  struct ieee80211_eapol_key *, struct ieee80211_node *);\nvoid\tieee80211_recv_eapol_key_req(struct ieee80211com *,\n                                     struct ieee80211_eapol_key *, struct ieee80211_node *);\n#endif\n\n/*\n * Process an incoming EAPOL frame.  Notice that we are only interested in\n * EAPOL-Key frames with an IEEE 802.11 or WPA descriptor type.\n */\nvoid\nieee80211_eapol_key_input(struct ieee80211com *ic, mbuf_t m,\n                          struct ieee80211_node *ni)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct _ifnet *ifp = &ic->ic_if;\n    struct ether_header *eh;\n    struct ieee80211_eapol_key *key;\n    u_int16_t info, desc;\n    int totlen, bodylen, paylen;\n    \n    ifp->if_ibytes += mbuf_pkthdr_len(m);\n    \n    eh = mtod(m, struct ether_header *);\n    if (IEEE80211_IS_MULTICAST(eh->ether_dhost)) {\n        ifp->if_imcasts++;\n        goto done;\n    }\n    mbuf_adj(m, sizeof(*eh));\n    \n    if (mbuf_pkthdr_len(m) < sizeof(*key))\n        goto done;\n    if (mbuf_len(m) < sizeof(*key) &&\n        (mbuf_pullup(&m, sizeof(*key)))) {\n        ic->ic_stats.is_rx_nombuf++;\n        goto done;\n    }\n    key = mtod(m, struct ieee80211_eapol_key *);\n    \n    if (key->type != EAPOL_KEY)\n        goto done;\n    ic->ic_stats.is_rx_eapol_key++;\n    \n    if ((ni->ni_rsnprotos == IEEE80211_PROTO_RSN &&\n         key->desc != EAPOL_KEY_DESC_IEEE80211) ||\n        (ni->ni_rsnprotos == IEEE80211_PROTO_WPA &&\n         key->desc != EAPOL_KEY_DESC_WPA))\n        goto done;\n    \n    /* check packet body length */\n    bodylen = BE_READ_2(key->len);\n    totlen = 4 + bodylen;\n    if (mbuf_pkthdr_len(m) < totlen || totlen > MCLBYTES)\n        goto done;\n    \n    /* check key data length */\n    paylen = BE_READ_2(key->paylen);\n    if (paylen > totlen - sizeof(*key))\n        goto done;\n    \n    info = BE_READ_2(key->info);\n    \n    /* discard EAPOL-Key frames with an unknown descriptor version */\n    desc = info & EAPOL_KEY_VERSION_MASK;\n    if (desc < EAPOL_KEY_DESC_V1 || desc > EAPOL_KEY_DESC_V3)\n        goto done;\n    \n    if (ieee80211_is_sha256_akm((enum ieee80211_akm)ni->ni_rsnakms)) {\n        if (desc != EAPOL_KEY_DESC_V3)\n            goto done;\n    } else if (ni->ni_rsncipher == IEEE80211_CIPHER_CCMP ||\n               ni->ni_rsngroupcipher == IEEE80211_CIPHER_CCMP) {\n        if (desc != EAPOL_KEY_DESC_V2)\n            goto done;\n    }\n    \n    /* make sure the key data field is contiguous */\n    if (mbuf_len(m) < totlen && mbuf_pullup(&m, totlen)) {\n        ic->ic_stats.is_rx_nombuf++;\n        goto done;\n    }\n    key = mtod(m, struct ieee80211_eapol_key *);\n    \n    /* determine message type (see 8.5.3.7) */\n    if (info & EAPOL_KEY_REQUEST) {\n#ifndef IEEE80211_STA_ONLY\n        /* EAPOL-Key Request frame */\n        ieee80211_recv_eapol_key_req(ic, key, ni);\n#endif\n    } else if (info & EAPOL_KEY_PAIRWISE) {\n        /* 4-Way Handshake */\n        if (info & EAPOL_KEY_KEYMIC) {\n            if (info & EAPOL_KEY_KEYACK)\n                ieee80211_recv_4way_msg3(ic, key, ni);\n#ifndef IEEE80211_STA_ONLY\n            else\n                ieee80211_recv_4way_msg2or4(ic, key, ni);\n#endif\n        } else if (info & EAPOL_KEY_KEYACK)\n            ieee80211_recv_4way_msg1(ic, key, ni);\n    } else {\n        /* Group Key Handshake */\n        if (!(info & EAPOL_KEY_KEYMIC))\n            goto done;\n        if (info & EAPOL_KEY_KEYACK) {\n            if (key->desc == EAPOL_KEY_DESC_WPA)\n                ieee80211_recv_wpa_group_msg1(ic, key, ni);\n            else\n                ieee80211_recv_rsn_group_msg1(ic, key, ni);\n        }\n#ifndef IEEE80211_STA_ONLY\n        else\n            ieee80211_recv_group_msg2(ic, key, ni);\n#endif\n    }\ndone:\n    mbuf_freem(m);\n}\n\n/*\n * Process Message 1 of the 4-Way Handshake (sent by Authenticator).\n */\nvoid\nieee80211_recv_4way_msg1(struct ieee80211com *ic,\n                         struct ieee80211_eapol_key *key, struct ieee80211_node *ni)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct ieee80211_ptk tptk;\n    struct ieee80211_pmk *pmk;\n    const u_int8_t *frm, *efrm;\n    const u_int8_t *pmkid;\n    \n#ifndef IEEE80211_STA_ONLY\n    if (ic->ic_opmode != IEEE80211_M_STA &&\n        ic->ic_opmode != IEEE80211_M_IBSS)\n        return;\n#endif\n    /*\n     * Message 1 is always expected while RSN is active since some\n     * APs will rekey the PTK by sending Msg1/4 after some time.\n     */\n    if (ni->ni_rsn_supp_state == RSNA_SUPP_INITIALIZE) {\n        DPRINTF((\"unexpected in state: %d\\n\", ni->ni_rsn_supp_state));\n        return;\n    }\n    /* enforce monotonicity of key request replay counter */\n    if (ni->ni_replaycnt_ok &&\n        BE_READ_8(key->replaycnt) <= ni->ni_replaycnt) {\n        ic->ic_stats.is_rx_eapol_replay++;\n        return;\n    }\n    \n    /* parse key data field (may contain an encapsulated PMKID) */\n    frm = (const u_int8_t *)&key[1];\n    efrm = frm + BE_READ_2(key->paylen);\n    \n    pmkid = NULL;\n    while (frm + 2 <= efrm) {\n        if (frm + 2 + frm[1] > efrm)\n            break;\n        switch (frm[0]) {\n            case IEEE80211_ELEMID_VENDOR:\n                if (frm[1] < 4)\n                    break;\n                if (memcmp(&frm[2], IEEE80211_OUI, 3) == 0) {\n                    switch (frm[5]) {\n                        case IEEE80211_KDE_PMKID:\n                            pmkid = frm;\n                            break;\n                    }\n                }\n                break;\n        }\n        frm += 2 + frm[1];\n    }\n    /* check that the PMKID KDE is valid (if present) */\n    if (pmkid != NULL && pmkid[1] != 4 + 16)\n        return;\n    \n    if (ieee80211_is_8021x_akm((enum ieee80211_akm)ni->ni_rsnakms)) {\n        /* retrieve the PMK for this (AP,PMKID) */\n        pmk = ieee80211_pmksa_find(ic, ni,\n                                   (pmkid != NULL) ? &pmkid[6] : NULL);\n        if (pmk == NULL) {\n            DPRINTF((\"no PMK available for %s\\n\",\n                     ether_sprintf(ni->ni_macaddr)));\n            return;\n        }\n        memcpy(ni->ni_pmk, pmk->pmk_key, IEEE80211_PMK_LEN);\n    } else    /* use pre-shared key */\n        memcpy(ni->ni_pmk, ic->ic_psk, IEEE80211_PMK_LEN);\n    ni->ni_flags |= IEEE80211_NODE_PMK;\n    \n    /* save authenticator's nonce (ANonce) */\n    memcpy(ni->ni_nonce, key->nonce, EAPOL_KEY_NONCE_LEN);\n    \n    /* generate supplicant's nonce (SNonce) */\n    arc4random_buf(ic->ic_nonce, EAPOL_KEY_NONCE_LEN);\n    \n    /* TPTK = CalcPTK(PMK, ANonce, SNonce) */\n    ieee80211_derive_ptk((enum ieee80211_akm)ni->ni_rsnakms, ni->ni_pmk, ni->ni_macaddr,\n                         ic->ic_myaddr, ni->ni_nonce, ic->ic_nonce, &tptk);\n    \n    /* We are now expecting a new pairwise key. */\n    ni->ni_flags |= IEEE80211_NODE_RSN_NEW_PTK;\n    \n    if (ic->ic_if.if_flags & IFF_DEBUG)\n        XYLog(\"%s: received msg %d/%d of the %s handshake from %s\\n\",\n              ic->ic_if.if_xname, 1, 4, \"4-way\",\n              ether_sprintf(ni->ni_macaddr));\n    \n    /* send message 2 to authenticator using TPTK */\n    (void)ieee80211_send_4way_msg2(ic, ni, key->replaycnt, &tptk);\n}\n\n#ifndef IEEE80211_STA_ONLY\n/*\n * Process Message 2 of the 4-Way Handshake (sent by Supplicant).\n */\nvoid\nieee80211_recv_4way_msg2(struct ieee80211com *ic,\n                         struct ieee80211_eapol_key *key, struct ieee80211_node *ni,\n                         const u_int8_t *rsnie)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct ieee80211_ptk tptk;\n    \n    if (ic->ic_opmode != IEEE80211_M_HOSTAP &&\n        ic->ic_opmode != IEEE80211_M_IBSS)\n        return;\n    \n    /* discard if we're not expecting this message */\n    if (ni->ni_rsn_state != RSNA_PTKSTART &&\n        ni->ni_rsn_state != RSNA_PTKCALCNEGOTIATING) {\n        DPRINTF((\"unexpected in state: %d\\n\", ni->ni_rsn_state));\n        return;\n    }\n    ni->ni_rsn_state = RSNA_PTKCALCNEGOTIATING;\n    \n    /* NB: replay counter has already been verified by caller */\n    \n    /* PTK = CalcPTK(ANonce, SNonce) */\n    ieee80211_derive_ptk((enum ieee80211_akm)ni->ni_rsnakms, ni->ni_pmk, ic->ic_myaddr,\n                         ni->ni_macaddr, ni->ni_nonce, key->nonce, &tptk);\n    \n    /* check Key MIC field using KCK */\n    if (ieee80211_eapol_key_check_mic(key, tptk.kck) != 0) {\n        DPRINTF((\"key MIC failed\\n\"));\n        ic->ic_stats.is_rx_eapol_badmic++;\n        return;    /* will timeout.. */\n    }\n    \n    timeout_del(&ni->ni_eapol_to);\n    ni->ni_rsn_state = RSNA_PTKCALCNEGOTIATING_2;\n    ni->ni_rsn_retries = 0;\n    \n    /* install TPTK as PTK now that MIC is verified */\n    memcpy(&ni->ni_ptk, &tptk, sizeof(tptk));\n    \n    /*\n     * The RSN IE must match bit-wise with what the STA included in its\n     * (Re)Association Request.\n     */\n    if (ni->ni_rsnie == NULL || rsnie[1] != ni->ni_rsnie[1] ||\n        memcmp(rsnie, ni->ni_rsnie, 2 + rsnie[1]) != 0) {\n        IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DEAUTH,\n                            IEEE80211_REASON_RSN_DIFFERENT_IE);\n        ieee80211_node_leave(ic, ni);\n        return;\n    }\n    \n    if (ic->ic_if.if_flags & IFF_DEBUG)\n        XYLog(\"%s: received msg %d/%d of the %s handshake from %s\\n\",\n              ic->ic_if.if_xname, 2, 4, \"4-way\",\n              ether_sprintf(ni->ni_macaddr));\n    \n    /* send message 3 to supplicant */\n    (void)ieee80211_send_4way_msg3(ic, ni);\n}\n#endif\t/* IEEE80211_STA_ONLY */\n\n/* \n * Check if a group key must be updated with a new GTK from an EAPOL frame.\n * Manipulated group key handshake messages could trick clients into\n * reinstalling an already used group key and hence lower or reset the\n * associated replay counter. This check prevents such attacks.\n */\nint\nieee80211_must_update_group_key(struct ieee80211_key *k, const uint8_t *gtk,\n                                int len)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    return (k->k_cipher == IEEE80211_CIPHER_NONE || k->k_len != len ||\n            memcmp(k->k_key, gtk, len) != 0);\n}\n\n/*\n * Process Message 3 of the 4-Way Handshake (sent by Authenticator).\n */\nvoid\nieee80211_recv_4way_msg3(struct ieee80211com *ic,\n                         struct ieee80211_eapol_key *key, struct ieee80211_node *ni)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct ieee80211_ptk tptk;\n    struct ieee80211_key *k;\n    const u_int8_t *frm, *efrm;\n    const u_int8_t *rsnie1, *rsnie2, *gtk, *igtk;\n    u_int16_t info, reason = 0;\n    int keylen, deferlink = 0;\n    \n#ifndef IEEE80211_STA_ONLY\n    if (ic->ic_opmode != IEEE80211_M_STA &&\n        ic->ic_opmode != IEEE80211_M_IBSS)\n        return;\n#endif\n    /* discard if we're not expecting this message */\n    if (ni->ni_rsn_supp_state != RSNA_SUPP_PTKNEGOTIATING &&\n        ni->ni_rsn_supp_state != RNSA_SUPP_PTKDONE) {\n        DPRINTF((\"unexpected in state: %d\\n\", ni->ni_rsn_supp_state));\n        return;\n    }\n    /* enforce monotonicity of key request replay counter */\n    if (ni->ni_replaycnt_ok &&\n        BE_READ_8(key->replaycnt) <= ni->ni_replaycnt) {\n        ic->ic_stats.is_rx_eapol_replay++;\n        return;\n    }\n    /* make sure that a PMK has been selected */\n    if (!(ni->ni_flags & IEEE80211_NODE_PMK)) {\n        DPRINTF((\"no PMK found for %s\\n\",\n                 ether_sprintf(ni->ni_macaddr)));\n        return;\n    }\n    /* check that ANonce matches that of Message 1 */\n    if (memcmp(key->nonce, ni->ni_nonce, EAPOL_KEY_NONCE_LEN) != 0) {\n        DPRINTF((\"ANonce does not match msg 1/4\\n\"));\n        return;\n    }\n    /* TPTK = CalcPTK(PMK, ANonce, SNonce) */\n    ieee80211_derive_ptk((enum ieee80211_akm)ni->ni_rsnakms, ni->ni_pmk, ni->ni_macaddr,\n                         ic->ic_myaddr, key->nonce, ic->ic_nonce, &tptk);\n    \n    info = BE_READ_2(key->info);\n    \n    /* check Key MIC field using KCK */\n    if (ieee80211_eapol_key_check_mic(key, tptk.kck) != 0) {\n        DPRINTF((\"key MIC failed\\n\"));\n        ic->ic_stats.is_rx_eapol_badmic++;\n        return;\n    }\n    /* install TPTK as PTK now that MIC is verified */\n    memcpy(&ni->ni_ptk, &tptk, sizeof(tptk));\n    \n    /* if encrypted, decrypt Key Data field using KEK */\n    if ((info & EAPOL_KEY_ENCRYPTED) &&\n        ieee80211_eapol_key_decrypt(key, ni->ni_ptk.kek) != 0) {\n        DPRINTF((\"decryption failed\\n\"));\n        return;\n    }\n    \n    /* parse key data field */\n    frm = (const u_int8_t *)&key[1];\n    efrm = frm + BE_READ_2(key->paylen);\n    \n    /*\n     * Some WPA1+WPA2 APs (like hostapd) appear to include both WPA and\n     * RSN IEs in message 3/4.  We only take into account the IE of the\n     * version of the protocol we negotiated at association time.\n     */\n    rsnie1 = rsnie2 = gtk = igtk = NULL;\n    while (frm + 2 <= efrm) {\n        if (frm + 2 + frm[1] > efrm)\n            break;\n        switch (frm[0]) {\n            case IEEE80211_ELEMID_RSN:\n                if (ni->ni_rsnprotos != IEEE80211_PROTO_RSN)\n                    break;\n                if (rsnie1 == NULL)\n                    rsnie1 = frm;\n                else if (rsnie2 == NULL)\n                    rsnie2 = frm;\n                /* ignore others if more than two RSN IEs */\n                break;\n            case IEEE80211_ELEMID_VENDOR:\n                if (frm[1] < 4)\n                    break;\n                if (memcmp(&frm[2], IEEE80211_OUI, 3) == 0) {\n                    switch (frm[5]) {\n                        case IEEE80211_KDE_GTK:\n                            gtk = frm;\n                            break;\n                        case IEEE80211_KDE_IGTK:\n                            if (ni->ni_flags & IEEE80211_NODE_MFP)\n                                igtk = frm;\n                            break;\n                    }\n                } else if (memcmp(&frm[2], MICROSOFT_OUI, 3) == 0) {\n                    switch (frm[5]) {\n                        case 1:    /* WPA */\n                            if (ni->ni_rsnprotos !=\n                                IEEE80211_PROTO_WPA)\n                                break;\n                            rsnie1 = frm;\n                            break;\n                    }\n                }\n                break;\n        }\n        frm += 2 + frm[1];\n    }\n    /* first WPA/RSN IE is mandatory */\n    if (rsnie1 == NULL) {\n        DPRINTF((\"missing RSN IE\\n\"));\n        return;\n    }\n    /* key data must be encrypted if GTK is included */\n    if (gtk != NULL && !(info & EAPOL_KEY_ENCRYPTED)) {\n        DPRINTF((\"GTK not encrypted\\n\"));\n        return;\n    }\n    /* GTK KDE must be included if IGTK KDE is present */\n    if (igtk != NULL && gtk == NULL) {\n        DPRINTF((\"IGTK KDE found but GTK KDE missing\\n\"));\n        return;\n    }\n    /* check that the Install bit is set if using pairwise keys */\n    if (ni->ni_rsncipher != IEEE80211_CIPHER_USEGROUP &&\n        !(info & EAPOL_KEY_INSTALL)) {\n        DPRINTF((\"pairwise cipher but !Install\\n\"));\n        return;\n    }\n    \n    /*\n     * Check that first WPA/RSN IE is identical to the one received in\n     * the beacon or probe response frame.\n     */\n    if (ni->ni_rsnie == NULL || rsnie1[1] != ni->ni_rsnie[1] ||\n        memcmp(rsnie1, ni->ni_rsnie, 2 + rsnie1[1]) != 0) {\n        reason = IEEE80211_REASON_RSN_DIFFERENT_IE;\n        goto deauth;\n    }\n    \n    /*\n     * If a second RSN information element is present, use its pairwise\n     * cipher suite or deauthenticate.\n     */\n    if (rsnie2 != NULL) {\n        struct ieee80211_rsnparams rsn;\n        \n        if (ieee80211_parse_rsn(ic, rsnie2, &rsn) == 0) {\n            if (rsn.rsn_akms != ni->ni_rsnakms ||\n                rsn.rsn_groupcipher != ni->ni_rsngroupcipher ||\n                rsn.rsn_nciphers != 1 ||\n                !(rsn.rsn_ciphers & ic->ic_rsnciphers)) {\n                reason = IEEE80211_REASON_BAD_PAIRWISE_CIPHER;\n                goto deauth;\n            }\n            /* use pairwise cipher suite of second RSN IE */\n            ni->ni_rsnciphers = rsn.rsn_ciphers;\n            ni->ni_rsncipher = (enum ieee80211_cipher)ni->ni_rsnciphers;\n        }\n    }\n    \n    /* update the last seen value of the key replay counter field */\n    ni->ni_replaycnt = BE_READ_8(key->replaycnt);\n    ni->ni_replaycnt_ok = 1;\n    \n    if (ic->ic_if.if_flags & IFF_DEBUG)\n        XYLog(\"%s: received msg %d/%d of the %s handshake from %s\\n\",\n              ic->ic_if.if_xname, 3, 4, \"4-way\",\n              ether_sprintf(ni->ni_macaddr));\n    \n    /* send message 4 to authenticator */\n    if (ieee80211_send_4way_msg4(ic, ni) != 0)\n        return;    /* ..authenticator will retry */\n    \n    /*\n     * Only install a new pairwise key if we are still expecting a new key,\n     * as indicated by the NODE_RSN_NEW_PTK flag. An adversary could be\n     * sending manipulated retransmissions of message 3 of the 4-way\n     * handshake in an attempt to trick us into reinstalling an already\n     * used pairwise key. If this attack succeeded, the incremental nonce\n     * and replay counter associated with the key would be reset.\n     * Against CCMP, the adversary could abuse this to replay and decrypt\n     * packets. Against TKIP, it would become possible to replay, decrypt,\n     * and forge packets.\n     */\n    if (ni->ni_rsncipher != IEEE80211_CIPHER_USEGROUP &&\n        (ni->ni_flags & IEEE80211_NODE_RSN_NEW_PTK)) {\n        u_int64_t prsc;\n        \n        /* check that key length matches that of pairwise cipher */\n        keylen = ieee80211_cipher_keylen(ni->ni_rsncipher);\n        if (BE_READ_2(key->keylen) != keylen) {\n            reason = IEEE80211_REASON_AUTH_LEAVE;\n            goto deauth;\n        }\n        prsc = (gtk == NULL) ? LE_READ_6(key->rsc) : 0;\n        \n        /* map PTK to 802.11 key */\n        k = &ni->ni_pairwise_key;\n        memset(k, 0, sizeof(*k));\n        k->k_cipher = ni->ni_rsncipher;\n        k->k_rsc[0] = prsc;\n        k->k_len = keylen;\n        memcpy(k->k_key, ni->ni_ptk.tk, k->k_len);\n        /* install the PTK */\n        switch ((*ic->ic_set_key)(ic, ni, k)) {\n            case 0:\n                break;\n            case EBUSY:\n                deferlink = 1;\n                break;\n            default:\n                reason = IEEE80211_REASON_AUTH_LEAVE;\n                goto deauth;\n        }\n        ni->ni_flags &= ~IEEE80211_NODE_RSN_NEW_PTK;\n        ni->ni_flags &= ~IEEE80211_NODE_TXRXPROT;\n        ni->ni_flags |= IEEE80211_NODE_RXPROT;\n    } else if (ni->ni_rsncipher != IEEE80211_CIPHER_USEGROUP)\n        XYLog(\"%s: unexpected pairwise key update received from %s\\n\",\n              ic->ic_if.if_xname, ether_sprintf(ni->ni_macaddr));\n    \n    if (gtk != NULL) {\n        u_int8_t kid;\n        \n        /* check that key length matches that of group cipher */\n        keylen = ieee80211_cipher_keylen(ni->ni_rsngroupcipher);\n        if (gtk[1] != 6 + keylen) {\n            reason = IEEE80211_REASON_AUTH_LEAVE;\n            goto deauth;\n        }\n        /* map GTK to 802.11 key */\n        kid = gtk[6] & 3;\n        k = &ic->ic_nw_keys[kid];\n        if (ieee80211_must_update_group_key(k, &gtk[8], keylen)) {\n            memset(k, 0, sizeof(*k));\n            k->k_id = kid;    /* 0-3 */\n            k->k_cipher = ni->ni_rsngroupcipher;\n            k->k_flags = IEEE80211_KEY_GROUP;\n            if (gtk[6] & (1 << 2))\n                k->k_flags |= IEEE80211_KEY_TX;\n            XYLog(\"%s k_len=%d rsc=%02X %02X %02X %02X %02X %02X\\n\", __FUNCTION__, keylen\n                  , key->rsc[0], key->rsc[1], key->rsc[2], key->rsc[3], key->rsc[4], key->rsc[5]);\n            k->k_rsc[0] = LE_READ_6(key->rsc);\n            k->k_len = keylen;\n            memcpy(k->k_key, &gtk[8], k->k_len);\n            /* install the GTK */\n            switch ((*ic->ic_set_key)(ic, ni, k)) {\n                case 0:\n                    break;\n                case EBUSY:\n                    deferlink = 1;\n                    break;\n                default:\n                reason = IEEE80211_REASON_AUTH_LEAVE;\n                goto deauth;\n            }\n        }\n    }\n    if (igtk != NULL) {    /* implies MFP && gtk != NULL */\n        u_int16_t kid;\n        \n        /* check that the IGTK KDE is valid */\n        if (igtk[1] != 4 + 24) {\n            reason = IEEE80211_REASON_AUTH_LEAVE;\n            goto deauth;\n        }\n        kid = LE_READ_2(&igtk[6]);\n        if (kid != 4 && kid != 5) {\n            DPRINTF((\"unsupported IGTK id %u\\n\", kid));\n            reason = IEEE80211_REASON_AUTH_LEAVE;\n            goto deauth;\n        }\n        /* map IGTK to 802.11 key */\n        k = &ic->ic_nw_keys[kid];\n        if (ieee80211_must_update_group_key(k, &igtk[14], 16)) {\n            memset(k, 0, sizeof(*k));\n            k->k_id = kid;    /* either 4 or 5 */\n            k->k_cipher = ni->ni_rsngroupmgmtcipher;\n            k->k_flags = IEEE80211_KEY_IGTK;\n            k->k_mgmt_rsc = LE_READ_6(&igtk[8]);    /* IPN */\n            k->k_len = 16;\n            memcpy(k->k_key, &igtk[14], k->k_len);\n            /* install the IGTK */\n            switch ((*ic->ic_set_key)(ic, ni, k)) {\n                case 0:\n                    break;\n                case EBUSY:\n                    deferlink = 1;\n                    break;\n                default:\n                    reason = IEEE80211_REASON_AUTH_LEAVE;\n                    goto deauth;\n            }\n        }\n    }\n    if (info & EAPOL_KEY_INSTALL)\n        ni->ni_flags |= IEEE80211_NODE_TXRXPROT;\n    \n    if (info & EAPOL_KEY_SECURE) {\n        ni->ni_flags |= IEEE80211_NODE_TXRXPROT;\n#ifndef IEEE80211_STA_ONLY\n        if (ic->ic_opmode != IEEE80211_M_IBSS ||\n            ++ni->ni_key_count == 2)\n#endif\n        {\n            if (deferlink == 0) {\n                DPRINTF((\"marking port %s valid\\n\",\n                         ether_sprintf(ni->ni_macaddr)));\n                ni->ni_port_valid = 1;\n                ieee80211_set_link_state(ic, LINK_STATE_UP);\n            }\n            ni->ni_assoc_fail = 0;\n            if (ic->ic_opmode == IEEE80211_M_STA)\n                ic->ic_rsngroupcipher = ni->ni_rsngroupcipher;\n        }\n    }\ndeauth:\n    if (reason != 0) {\n        IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DEAUTH,\n                            reason);\n        ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);\n    }\n}\n\n#ifndef IEEE80211_STA_ONLY\n/*\n * Process Message 4 of the 4-Way Handshake (sent by Supplicant).\n */\nvoid\nieee80211_recv_4way_msg4(struct ieee80211com *ic,\n                         struct ieee80211_eapol_key *key, struct ieee80211_node *ni)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    if (ic->ic_opmode != IEEE80211_M_HOSTAP &&\n        ic->ic_opmode != IEEE80211_M_IBSS)\n        return;\n    \n    /* discard if we're not expecting this message */\n    if (ni->ni_rsn_state != RSNA_PTKINITNEGOTIATING) {\n        DPRINTF((\"unexpected in state: %d\\n\", ni->ni_rsn_state));\n        return;\n    }\n    \n    /* NB: replay counter has already been verified by caller */\n    \n    /* check Key MIC field using KCK */\n    if (ieee80211_eapol_key_check_mic(key, ni->ni_ptk.kck) != 0) {\n        DPRINTF((\"key MIC failed\\n\"));\n        ic->ic_stats.is_rx_eapol_badmic++;\n        return;    /* will timeout.. */\n    }\n    \n    timeout_del(&ni->ni_eapol_to);\n    ni->ni_rsn_state = RSNA_PTKINITDONE;\n    ni->ni_rsn_retries = 0;\n    \n    if (ni->ni_rsncipher != IEEE80211_CIPHER_USEGROUP) {\n        struct ieee80211_key *k;\n        \n        /* map PTK to 802.11 key */\n        k = &ni->ni_pairwise_key;\n        memset(k, 0, sizeof(*k));\n        k->k_cipher = ni->ni_rsncipher;\n        k->k_len = ieee80211_cipher_keylen(k->k_cipher);\n        memcpy(k->k_key, ni->ni_ptk.tk, k->k_len);\n        /* install the PTK */\n        switch ((*ic->ic_set_key)(ic, ni, k)) {\n            case 0:\n            case EBUSY:\n                break;\n            default:\n                IEEE80211_SEND_MGMT(ic, ni,\n                                    IEEE80211_FC0_SUBTYPE_DEAUTH,\n                                    IEEE80211_REASON_ASSOC_TOOMANY);\n                ieee80211_node_leave(ic, ni);\n                return;\n        }\n        ni->ni_flags |= IEEE80211_NODE_TXRXPROT;\n    }\n    if (ic->ic_opmode != IEEE80211_M_IBSS || ++ni->ni_key_count == 2) {\n        DPRINTF((\"marking port %s valid\\n\",\n                 ether_sprintf(ni->ni_macaddr)));\n        ni->ni_port_valid = 1;\n    }\n    \n    if (ic->ic_if.if_flags & IFF_DEBUG)\n        XYLog(\"%s: received msg %d/%d of the %s handshake from %s\\n\",\n              ic->ic_if.if_xname, 4, 4, \"4-way\",\n              ether_sprintf(ni->ni_macaddr));\n    \n    /* initiate a group key handshake for WPA */\n    if (ni->ni_rsnprotos == IEEE80211_PROTO_WPA)\n        (void)ieee80211_send_group_msg1(ic, ni);\n    else\n        ni->ni_rsn_gstate = RSNA_IDLE;\n}\n\n/*\n * Differentiate Message 2 from Message 4 of the 4-Way Handshake based on\n * the presence of an RSN or WPA Information Element.\n */\nvoid\nieee80211_recv_4way_msg2or4(struct ieee80211com *ic,\n                            struct ieee80211_eapol_key *key, struct ieee80211_node *ni)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    const u_int8_t *frm, *efrm;\n    const u_int8_t *rsnie;\n    \n    if (BE_READ_8(key->replaycnt) != ni->ni_replaycnt) {\n        ic->ic_stats.is_rx_eapol_replay++;\n        return;\n    }\n    \n    /* parse key data field (check if an RSN IE is present) */\n    frm = (const u_int8_t *)&key[1];\n    efrm = frm + BE_READ_2(key->paylen);\n    \n    rsnie = NULL;\n    while (frm + 2 <= efrm) {\n        if (frm + 2 + frm[1] > efrm)\n            break;\n        switch (frm[0]) {\n            case IEEE80211_ELEMID_RSN:\n                rsnie = frm;\n                break;\n            case IEEE80211_ELEMID_VENDOR:\n                if (frm[1] < 4)\n                    break;\n                if (memcmp(&frm[2], MICROSOFT_OUI, 3) == 0) {\n                    switch (frm[5]) {\n                        case 1:    /* WPA */\n                            rsnie = frm;\n                            break;\n                    }\n                }\n        }\n        frm += 2 + frm[1];\n    }\n    if (rsnie != NULL)\n        ieee80211_recv_4way_msg2(ic, key, ni, rsnie);\n    else\n        ieee80211_recv_4way_msg4(ic, key, ni);\n}\n#endif\t/* IEEE80211_STA_ONLY */\n\n/*\n * Process Message 1 of the RSN Group Key Handshake (sent by Authenticator).\n */\nvoid\nieee80211_recv_rsn_group_msg1(struct ieee80211com *ic,\n                              struct ieee80211_eapol_key *key, struct ieee80211_node *ni)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct ieee80211_key *k;\n    const u_int8_t *frm, *efrm;\n    const u_int8_t *gtk, *igtk;\n    u_int16_t info, kid, reason = 0;\n    int keylen;\n    \n#ifndef IEEE80211_STA_ONLY\n    if (ic->ic_opmode != IEEE80211_M_STA &&\n        ic->ic_opmode != IEEE80211_M_IBSS)\n        return;\n#endif\n    /* discard if we're not expecting this message */\n    if (ni->ni_rsn_supp_state != RNSA_SUPP_PTKDONE) {\n        DPRINTF((\"unexpected in state: %d\\n\", ni->ni_rsn_supp_state));\n        return;\n    }\n    /* enforce monotonicity of key request replay counter */\n    if (BE_READ_8(key->replaycnt) <= ni->ni_replaycnt) {\n        ic->ic_stats.is_rx_eapol_replay++;\n        return;\n    }\n    /* check Key MIC field using KCK */\n    if (ieee80211_eapol_key_check_mic(key, ni->ni_ptk.kck) != 0) {\n        DPRINTF((\"key MIC failed\\n\"));\n        ic->ic_stats.is_rx_eapol_badmic++;\n        return;\n    }\n    info = BE_READ_2(key->info);\n    \n    /* check that encrypted and decrypt Key Data field using KEK */\n    if (!(info & EAPOL_KEY_ENCRYPTED) ||\n        ieee80211_eapol_key_decrypt(key, ni->ni_ptk.kek) != 0) {\n        DPRINTF((\"decryption failed\\n\"));\n        return;\n    }\n    \n    /* parse key data field (shall contain a GTK KDE) */\n    frm = (const u_int8_t *)&key[1];\n    efrm = frm + BE_READ_2(key->paylen);\n    \n    gtk = igtk = NULL;\n    while (frm + 2 <= efrm) {\n        if (frm + 2 + frm[1] > efrm)\n            break;\n        switch (frm[0]) {\n            case IEEE80211_ELEMID_VENDOR:\n                if (frm[1] < 4)\n                    break;\n                if (memcmp(&frm[2], IEEE80211_OUI, 3) == 0) {\n                    switch (frm[5]) {\n                        case IEEE80211_KDE_GTK:\n                            gtk = frm;\n                            break;\n                        case IEEE80211_KDE_IGTK:\n                            if (ni->ni_flags & IEEE80211_NODE_MFP)\n                                igtk = frm;\n                            break;\n                    }\n                }\n                break;\n        }\n        frm += 2 + frm[1];\n    }\n    /* check that the GTK KDE is present */\n    if (gtk == NULL) {\n        DPRINTF((\"GTK KDE missing\\n\"));\n        return;\n    }\n    \n    /* check that key length matches that of group cipher */\n    keylen = ieee80211_cipher_keylen(ni->ni_rsngroupcipher);\n    if (gtk[1] != 6 + keylen)\n        return;\n    \n    /* map GTK to 802.11 key */\n    kid = gtk[6] & 3;\n    k = &ic->ic_nw_keys[kid];\n    if (ieee80211_must_update_group_key(k, &gtk[8], keylen)) {\n        memset(k, 0, sizeof(*k));\n        k->k_id = kid;    /* 0-3 */\n        k->k_cipher = ni->ni_rsngroupcipher;\n        k->k_flags = IEEE80211_KEY_GROUP;\n        if (gtk[6] & (1 << 2))\n            k->k_flags |= IEEE80211_KEY_TX;\n        k->k_rsc[0] = LE_READ_6(key->rsc);\n        k->k_len = keylen;\n        memcpy(k->k_key, &gtk[8], k->k_len);\n        /* install the GTK */\n        switch ((*ic->ic_set_key)(ic, ni, k)) {\n            case 0:\n            case EBUSY:\n                break;\n            default:\n                reason = IEEE80211_REASON_AUTH_LEAVE;\n                goto deauth;\n        }\n    }\n    if (igtk != NULL) {    /* implies MFP */\n        /* check that the IGTK KDE is valid */\n        if (igtk[1] != 4 + 24) {\n            reason = IEEE80211_REASON_AUTH_LEAVE;\n            goto deauth;\n        }\n        kid = LE_READ_2(&igtk[6]);\n        if (kid != 4 && kid != 5) {\n            DPRINTF((\"unsupported IGTK id %u\\n\", kid));\n            reason = IEEE80211_REASON_AUTH_LEAVE;\n            goto deauth;\n        }\n        /* map IGTK to 802.11 key */\n        k = &ic->ic_nw_keys[kid];\n        if (ieee80211_must_update_group_key(k, &igtk[14], 16)) {\n            memset(k, 0, sizeof(*k));\n            k->k_id = kid;    /* either 4 or 5 */\n            k->k_cipher = ni->ni_rsngroupmgmtcipher;\n            k->k_flags = IEEE80211_KEY_IGTK;\n            k->k_mgmt_rsc = LE_READ_6(&igtk[8]);    /* IPN */\n            k->k_len = 16;\n            memcpy(k->k_key, &igtk[14], k->k_len);\n            /* install the IGTK */\n            switch ((*ic->ic_set_key)(ic, ni, k)) {\n                case 0:\n                case EBUSY:\n                    break;\n                default:\n                    reason = IEEE80211_REASON_AUTH_LEAVE;\n                    goto deauth;\n            }\n        }\n    }\n    if (info & EAPOL_KEY_SECURE) {\n#ifndef IEEE80211_STA_ONLY\n        if (ic->ic_opmode != IEEE80211_M_IBSS ||\n            ++ni->ni_key_count == 2)\n#endif\n        {\n            DPRINTF((\"marking port %s valid\\n\",\n                     ether_sprintf(ni->ni_macaddr)));\n            ni->ni_port_valid = 1;\n            ieee80211_set_link_state(ic, LINK_STATE_UP);\n            ni->ni_assoc_fail = 0;\n        }\n    }\n    /* update the last seen value of the key replay counter field */\n    ni->ni_replaycnt = BE_READ_8(key->replaycnt);\n    \n    if (ic->ic_if.if_flags & IFF_DEBUG)\n        XYLog(\"%s: received msg %d/%d of the %s handshake from %s\\n\",\n              ic->ic_if.if_xname, 1, 2, \"group key\",\n              ether_sprintf(ni->ni_macaddr));\n    \n    /* send message 2 to authenticator */\n    (void)ieee80211_send_group_msg2(ic, ni, NULL);\n    return;\ndeauth:\n    IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DEAUTH, reason);\n    ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);\n}\n\n/*\n * Process Message 1 of the WPA Group Key Handshake (sent by Authenticator).\n */\nvoid\nieee80211_recv_wpa_group_msg1(struct ieee80211com *ic,\n                              struct ieee80211_eapol_key *key, struct ieee80211_node *ni)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct ieee80211_key *k;\n    u_int16_t info;\n    u_int8_t kid;\n    int keylen;\n    const uint8_t *gtk;\n    \n#ifndef IEEE80211_STA_ONLY\n    if (ic->ic_opmode != IEEE80211_M_STA &&\n        ic->ic_opmode != IEEE80211_M_IBSS)\n        return;\n#endif\n    /* discard if we're not expecting this message */\n    if (ni->ni_rsn_supp_state != RNSA_SUPP_PTKDONE) {\n        DPRINTF((\"unexpected in state: %d\\n\", ni->ni_rsn_supp_state));\n        return;\n    }\n    /* enforce monotonicity of key request replay counter */\n    if (BE_READ_8(key->replaycnt) <= ni->ni_replaycnt) {\n        ic->ic_stats.is_rx_eapol_replay++;\n        return;\n    }\n    /* check Key MIC field using KCK */\n    if (ieee80211_eapol_key_check_mic(key, ni->ni_ptk.kck) != 0) {\n        DPRINTF((\"key MIC failed\\n\"));\n        ic->ic_stats.is_rx_eapol_badmic++;\n        return;\n    }\n    /*\n     * EAPOL-Key data field is encrypted even though WPA doesn't set\n     * the ENCRYPTED bit in the info field.\n     */\n    if (ieee80211_eapol_key_decrypt(key, ni->ni_ptk.kek) != 0) {\n        DPRINTF((\"decryption failed\\n\"));\n        return;\n    }\n    \n    /* check that key length matches that of group cipher */\n    keylen = ieee80211_cipher_keylen(ni->ni_rsngroupcipher);\n    if (BE_READ_2(key->keylen) != keylen)\n        return;\n    \n    /* check that the data length is large enough to hold the key */\n    if (BE_READ_2(key->paylen) < keylen)\n        return;\n    \n    info = BE_READ_2(key->info);\n    \n    /* map GTK to 802.11 key */\n    kid = (info >> EAPOL_KEY_WPA_KID_SHIFT) & 3;\n    k = &ic->ic_nw_keys[kid];\n    gtk = (const uint8_t *)&key[1]; /* key data field contains the GTK */\n    if (ieee80211_must_update_group_key(k, gtk, keylen)) {\n        memset(k, 0, sizeof(*k));\n        k->k_id = kid;    /* 0-3 */\n        k->k_cipher = ni->ni_rsngroupcipher;\n        k->k_flags = IEEE80211_KEY_GROUP;\n        if (info & EAPOL_KEY_WPA_TX)\n            k->k_flags |= IEEE80211_KEY_TX;\n        k->k_rsc[0] = LE_READ_6(key->rsc);\n        k->k_len = keylen;\n        memcpy(k->k_key, gtk, k->k_len);\n        /* install the GTK */\n        switch ((*ic->ic_set_key)(ic, ni, k)) {\n            case 0:\n            case EBUSY:\n                break;\n            default:\n                IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DEAUTH,\n                                    IEEE80211_REASON_AUTH_LEAVE);\n                ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);\n                return;\n        }\n    }\n    if (info & EAPOL_KEY_SECURE) {\n#ifndef IEEE80211_STA_ONLY\n        if (ic->ic_opmode != IEEE80211_M_IBSS ||\n            ++ni->ni_key_count == 2)\n#endif\n        {\n            DPRINTF((\"marking port %s valid\\n\",\n                     ether_sprintf(ni->ni_macaddr)));\n            ni->ni_port_valid = 1;\n            ieee80211_set_link_state(ic, LINK_STATE_UP);\n            ni->ni_assoc_fail = 0;\n        }\n    }\n    /* update the last seen value of the key replay counter field */\n    ni->ni_replaycnt = BE_READ_8(key->replaycnt);\n    \n    if (ic->ic_if.if_flags & IFF_DEBUG)\n        XYLog(\"%s: received msg %d/%d of the %s handshake from %s\\n\",\n              ic->ic_if.if_xname, 1, 2, \"group key\",\n              ether_sprintf(ni->ni_macaddr));\n    \n    /* send message 2 to authenticator */\n    (void)ieee80211_send_group_msg2(ic, ni, k);\n}\n\n#ifndef IEEE80211_STA_ONLY\n/*\n * Process Message 2 of the Group Key Handshake (sent by Supplicant).\n */\nvoid\nieee80211_recv_group_msg2(struct ieee80211com *ic,\n                          struct ieee80211_eapol_key *key, struct ieee80211_node *ni)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    if (ic->ic_opmode != IEEE80211_M_HOSTAP &&\n        ic->ic_opmode != IEEE80211_M_IBSS)\n        return;\n    \n    /* discard if we're not expecting this message */\n    if (ni->ni_rsn_gstate != RSNA_REKEYNEGOTIATING) {\n        DPRINTF((\"%s: unexpected in state: %d\\n\", ic->ic_if.if_xname,\n                 ni->ni_rsn_gstate));\n        return;\n    }\n    /* enforce monotonicity of key request replay counter */\n    if (BE_READ_8(key->replaycnt) != ni->ni_replaycnt) {\n        ic->ic_stats.is_rx_eapol_replay++;\n        return;\n    }\n    /* check Key MIC field using KCK */\n    if (ieee80211_eapol_key_check_mic(key, ni->ni_ptk.kck) != 0) {\n        DPRINTF((\"key MIC failed\\n\"));\n        ic->ic_stats.is_rx_eapol_badmic++;\n        return;\n    }\n    \n    timeout_del(&ni->ni_eapol_to);\n    ni->ni_rsn_gstate = RSNA_REKEYESTABLISHED;\n    \n    if (ni->ni_flags & IEEE80211_NODE_REKEY) {\n        int rekeysta = 0;\n        ni->ni_flags &= ~IEEE80211_NODE_REKEY;\n        ieee80211_iterate_nodes(ic,\n                                ieee80211_count_rekeysta, &rekeysta);\n        if (rekeysta == 0)\n            ieee80211_setkeysdone(ic);\n    }\n    ni->ni_flags |= IEEE80211_NODE_TXRXPROT;\n    \n    ni->ni_rsn_gstate = RSNA_IDLE;\n    ni->ni_rsn_retries = 0;\n    \n    if (ic->ic_if.if_flags & IFF_DEBUG)\n        XYLog(\"%s: received msg %d/%d of the %s handshake from %s\\n\",\n              ic->ic_if.if_xname, 2, 2, \"group key\",\n              ether_sprintf(ni->ni_macaddr));\n}\n\n/*\n * EAPOL-Key Request frames are sent by the supplicant to request that the\n * authenticator initiates either a 4-Way Handshake or Group Key Handshake,\n * or to report a MIC failure in a TKIP MSDU.\n */\nvoid\nieee80211_recv_eapol_key_req(struct ieee80211com *ic,\n                             struct ieee80211_eapol_key *key, struct ieee80211_node *ni)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    u_int16_t info;\n    \n    if (ic->ic_opmode != IEEE80211_M_HOSTAP &&\n        ic->ic_opmode != IEEE80211_M_IBSS)\n        return;\n    \n    /* discard if we're not expecting this message */\n    if (ni->ni_rsn_state != RSNA_PTKINITDONE) {\n        DPRINTF((\"unexpected in state: %d\\n\", ni->ni_rsn_state));\n        return;\n    }\n    /* enforce monotonicity of key request replay counter */\n    if (ni->ni_reqreplaycnt_ok &&\n        BE_READ_8(key->replaycnt) <= ni->ni_reqreplaycnt) {\n        ic->ic_stats.is_rx_eapol_replay++;\n        return;\n    }\n    info = BE_READ_2(key->info);\n    \n    if (!(info & EAPOL_KEY_KEYMIC) ||\n        ieee80211_eapol_key_check_mic(key, ni->ni_ptk.kck) != 0) {\n        DPRINTF((\"key request MIC failed\\n\"));\n        ic->ic_stats.is_rx_eapol_badmic++;\n        return;\n    }\n    /* update key request replay counter now that MIC is verified */\n    ni->ni_reqreplaycnt = BE_READ_8(key->replaycnt);\n    ni->ni_reqreplaycnt_ok = 1;\n    \n    if (info & EAPOL_KEY_ERROR) {    /* TKIP MIC failure */\n        /* ignore reports from STAs not using TKIP */\n        if (ic->ic_bss->ni_rsngroupcipher != IEEE80211_CIPHER_TKIP &&\n            ni->ni_rsncipher != IEEE80211_CIPHER_TKIP) {\n            DPRINTF((\"MIC failure report from !TKIP STA: %s\\n\",\n                     ether_sprintf(ni->ni_macaddr)));\n            return;\n        }\n        ic->ic_stats.is_rx_remmicfail++;\n        ieee80211_michael_mic_failure(ic, LE_READ_6(key->rsc));\n        \n    } else if (info & EAPOL_KEY_PAIRWISE) {\n        /* initiate a 4-Way Handshake */\n        \n    } else {\n        /*\n         * Should change the GTK, initiate the 4-Way Handshake and\n         * then execute a Group Key Handshake with all supplicants.\n         */\n    }\n}\n#endif\t/* IEEE80211_STA_ONLY */\n"
  },
  {
    "path": "itl80211/openbsd/net80211/ieee80211_pae_output.c",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n/*\t$OpenBSD: ieee80211_pae_output.c,v 1.30 2017/12/21 12:09:38 mpi Exp $\t*/\n\n/*-\n * Copyright (c) 2007,2008 Damien Bergamini <damien.bergamini@free.fr>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n/*\n * This code implements the 4-Way Handshake and Group Key Handshake protocols\n * (both Supplicant and Authenticator Key Transmit state machines) defined in\n * IEEE Std 802.11-2007 section 8.5.\n */\n\n#include <sys/param.h>\n#include <sys/systm.h>\n#include <sys/mbuf.h>\n#include <sys/kernel.h>\n#include <sys/socket.h>\n#include <sys/sockio.h>\n#include <sys/endian.h>\n#include <sys/errno.h>\n\n#include <net/if.h>\n#include <net/if_dl.h>\n#include <net/if_media.h>\n#include <net/if_llc.h>\n\n#include <netinet/in.h>\n#include <netinet/if_ether.h>\n#include <netinet/ip.h>\n\n#include <net80211/ieee80211_var.h>\n#include <net80211/ieee80211_priv.h>\n\nint\t\tieee80211_send_eapol_key(struct ieee80211com *ic, mbuf_t m,\n                                 struct ieee80211_node *ni, const struct ieee80211_ptk *ptk);\n#ifndef IEEE80211_STA_ONLY\nu_int8_t\t*ieee80211_add_gtk_kde(u_int8_t *, struct ieee80211_node *,\n                                   const struct ieee80211_key *);\nu_int8_t\t*ieee80211_add_pmkid_kde(u_int8_t *, const u_int8_t *);\nu_int8_t\t*ieee80211_add_igtk_kde(u_int8_t *,\n                                    const struct ieee80211_key *);\n#endif\nmbuf_t \tieee80211_get_eapol_key(int, int, u_int);\n\n/*\n * Send an EAPOL-Key frame to node `ni'.  If MIC or encryption is required,\n * the PTK must be passed (otherwise it can be set to NULL.)\n */\nint\nieee80211_send_eapol_key(struct ieee80211com *ic, mbuf_t m,\n                         struct ieee80211_node *ni, const struct ieee80211_ptk *ptk)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct _ifnet *ifp = &ic->ic_if;\n    struct ether_header *eh;\n    struct ieee80211_eapol_key *key;\n    u_int16_t info;\n    int len, error = 0;\n    \n    mbuf_prepend(&m, sizeof(struct ether_header), MBUF_DONTWAIT);\n    if (m == NULL)\n        return ENOMEM;\n    /* no need to m_pullup here (ok by construction) */\n    eh = mtod(m, struct ether_header *);\n    eh->ether_type = htons(ETHERTYPE_PAE);\n    IEEE80211_ADDR_COPY(eh->ether_shost, ic->ic_myaddr);\n    IEEE80211_ADDR_COPY(eh->ether_dhost, ni->ni_macaddr);\n    \n    key = (struct ieee80211_eapol_key *)&eh[1];\n    key->version = EAPOL_VERSION;\n    key->type = EAPOL_KEY;\n    key->desc = (ni->ni_rsnprotos == IEEE80211_PROTO_RSN) ?\n    EAPOL_KEY_DESC_IEEE80211 : EAPOL_KEY_DESC_WPA;\n    \n    info = BE_READ_2(key->info);\n    /* use V3 descriptor if KDF is SHA256-based */\n    if (ieee80211_is_sha256_akm((enum ieee80211_akm)ni->ni_rsnakms))\n        info |= EAPOL_KEY_DESC_V3;\n    /* use V2 descriptor if pairwise or group cipher is CCMP */\n    else if (ni->ni_rsncipher == IEEE80211_CIPHER_CCMP ||\n             ni->ni_rsngroupcipher == IEEE80211_CIPHER_CCMP)\n        info |= EAPOL_KEY_DESC_V2;\n    else\n        info |= EAPOL_KEY_DESC_V1;\n    BE_WRITE_2(key->info, info);\n    \n    len = mbuf_len(m) - sizeof(struct ether_header);\n    BE_WRITE_2(key->paylen, len - sizeof(*key));\n    BE_WRITE_2(key->len, len - 4);\n    \n#ifndef IEEE80211_STA_ONLY\n    if (info & EAPOL_KEY_ENCRYPTED) {\n        if (ni->ni_rsnprotos == IEEE80211_PROTO_WPA) {\n            /* clear \"Encrypted\" bit for WPA */\n            info &= ~EAPOL_KEY_ENCRYPTED;\n            BE_WRITE_2(key->info, info);\n        }\n        ieee80211_eapol_key_encrypt(ic, key, ptk->kek);\n        \n        if ((info & EAPOL_KEY_VERSION_MASK) != EAPOL_KEY_DESC_V1) {\n            /* AES Key Wrap adds 8 bytes + padding */\n            size_t l = sizeof(*eh) + 4 + BE_READ_2(key->len);\n            mbuf_pkthdr_setlen(m, l);\n            mbuf_setlen(m, l);\n        }\n    }\n#endif\n    if (info & EAPOL_KEY_KEYMIC)\n        ieee80211_eapol_key_mic(key, ptk->kck);\n    \n#ifndef IEEE80211_STA_ONLY\n    /* start a 100ms timeout if an answer is expected from supplicant */\n    if (info & EAPOL_KEY_KEYACK)\n        timeout_add_msec(&ni->ni_eapol_to, 100);\n#endif\n    \n    error = ifq_enqueue(&ifp->if_snd, m);\n    if (error) {\n        XYLog(\"%s enqueue fail!!\\n\", __FUNCTION__);\n        return (error);\n    }\n    (*ifp->if_start)(ifp);\n    return 0;\n}\n\n#ifndef IEEE80211_STA_ONLY\n/*\n * Handle EAPOL-Key timeouts (no answer from supplicant).\n */\nvoid\nieee80211_eapol_timeout(void *arg)\n{\n    struct ieee80211_node *ni = (struct ieee80211_node *)arg;\n    struct ieee80211com *ic = ni->ni_ic;\n    int s;\n    \n    DPRINTF((\"no answer from station %s in state %d\\n\",\n        ether_sprintf(ni->ni_macaddr), ni->ni_rsn_state));\n\n    s = splnet();\n\n    switch (ni->ni_rsn_state) {\n    case RSNA_PTKSTART:\n    case RSNA_PTKCALCNEGOTIATING:\n        (void)ieee80211_send_4way_msg1(ic, ni);\n        break;\n    case RSNA_PTKINITNEGOTIATING:\n        (void)ieee80211_send_4way_msg3(ic, ni);\n        break;\n    }\n\n    switch (ni->ni_rsn_gstate) {\n    case RSNA_REKEYNEGOTIATING:\n        (void)ieee80211_send_group_msg1(ic, ni);\n        break;\n    }\n\n    splx(s);\n}\n\n/*\n * Add a GTK KDE to an EAPOL-Key frame (see Figure 144).\n */\nu_int8_t *\nieee80211_add_gtk_kde(u_int8_t *frm, struct ieee80211_node *ni,\n                      const struct ieee80211_key *k)\n{\n    _KASSERT(k->k_flags & IEEE80211_KEY_GROUP);\n    \n    *frm++ = IEEE80211_ELEMID_VENDOR;\n    *frm++ = 6 + k->k_len;\n    memcpy(frm, IEEE80211_OUI, 3); frm += 3;\n    *frm++ = IEEE80211_KDE_GTK;\n    *frm = k->k_id & 3;\n    /*\n     * The TxRx flag for sending a GTK is always the opposite of whether\n     * the pairwise key is used for data encryption/integrity or not.\n     */\n    if (ni->ni_rsncipher == IEEE80211_CIPHER_USEGROUP)\n        *frm |= 1 << 2;    /* set the Tx bit */\n    frm++;\n    *frm++ = 0;    /* reserved */\n    memcpy(frm, k->k_key, k->k_len);\n    return frm + k->k_len;\n}\n\n/*\n * Add a PMKID KDE to an EAPOL-Key frame (see Figure 146).\n */\nu_int8_t *\nieee80211_add_pmkid_kde(u_int8_t *frm, const u_int8_t *pmkid)\n{\n    *frm++ = IEEE80211_ELEMID_VENDOR;\n    *frm++ = 20;\n    memcpy(frm, IEEE80211_OUI, 3); frm += 3;\n    *frm++ = IEEE80211_KDE_PMKID;\n    memcpy(frm, pmkid, IEEE80211_PMKID_LEN);\n    return frm + IEEE80211_PMKID_LEN;\n}\n\n/*\n * Add an IGTK KDE to an EAPOL-Key frame (see Figure 8-32a).\n */\nu_int8_t *\nieee80211_add_igtk_kde(u_int8_t *frm, const struct ieee80211_key *k)\n{\n    _KASSERT(k->k_flags & IEEE80211_KEY_IGTK);\n    \n    *frm++ = IEEE80211_ELEMID_VENDOR;\n    *frm++ = 4 + 24;\n    memcpy(frm, IEEE80211_OUI, 3); frm += 3;\n    *frm++ = IEEE80211_KDE_IGTK;\n    LE_WRITE_2(frm, k->k_id); frm += 2;\n    LE_WRITE_6(frm, k->k_tsc); frm += 6;    /* IPN */\n    memcpy(frm, k->k_key, 16);\n    return frm + 16;\n}\n#endif\t/* IEEE80211_STA_ONLY */\n\nmbuf_t\nieee80211_get_eapol_key(int flags, int type, u_int pktlen)\n{\n    mbuf_t m;\n    \n    /* reserve space for 802.11 encapsulation and EAPOL-Key header */\n    pktlen += sizeof(struct ieee80211_frame) + LLC_SNAPFRAMELEN +\n    sizeof(struct ieee80211_eapol_key);\n    \n    if (pktlen > MCLBYTES)\n        panic(\"EAPOL-Key frame too large: %u\", pktlen);\n    mbuf_gethdr(flags, type, &m);\n    if (m == NULL)\n        return NULL;\n    if (pktlen > mbuf_get_mhlen()) {\n        mbuf_mclget(flags, type, &m);\n        if (!(mbuf_flags(m) & MBUF_EXT))\n            return mbuf_free(m);\n    }\n    mbuf_setdata(m, (char*)mbuf_data(m) +\n                 sizeof(struct ieee80211_frame) +\n                 LLC_SNAPFRAMELEN, mbuf_len(m)\n                 - sizeof(struct ieee80211_frame) - LLC_SNAPFRAMELEN);\n    return m;\n}\n\n#ifndef IEEE80211_STA_ONLY\n/*\n * Send 4-Way Handshake Message 1 to the supplicant.\n */\nint\nieee80211_send_4way_msg1(struct ieee80211com *ic, struct ieee80211_node *ni)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct ieee80211_eapol_key *key;\n    mbuf_t m;\n    u_int16_t info, keylen;\n    u_int8_t *frm;\n    \n    ni->ni_rsn_state = RSNA_PTKSTART;\n    if (++ni->ni_rsn_retries > 3) {\n        IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DEAUTH,\n                            IEEE80211_REASON_4WAY_TIMEOUT);\n        ieee80211_node_leave(ic, ni);\n        return 0;\n    }\n    m = ieee80211_get_eapol_key(MBUF_DONTWAIT, MT_DATA,\n                                (ni->ni_rsnprotos == IEEE80211_PROTO_RSN) ? 2 + 20 : 0);\n    if (m == NULL) {\n        XYLog(\"%s\\n ieee80211_get_eapol_key==NULL\", __FUNCTION__);\n        return ENOMEM;\n    }\n    key = mtod(m, struct ieee80211_eapol_key *);\n    memset(key, 0, sizeof(*key));\n    \n    info = EAPOL_KEY_PAIRWISE | EAPOL_KEY_KEYACK;\n    BE_WRITE_2(key->info, info);\n    \n    /* copy the authenticator's nonce (ANonce) */\n    memcpy(key->nonce, ni->ni_nonce, EAPOL_KEY_NONCE_LEN);\n    \n    keylen = ieee80211_cipher_keylen(ni->ni_rsncipher);\n    BE_WRITE_2(key->keylen, keylen);\n    \n    frm = (u_int8_t *)&key[1];\n    /* NB: WPA does not have PMKID KDE */\n    if (ni->ni_rsnprotos == IEEE80211_PROTO_RSN &&\n        ieee80211_is_8021x_akm((enum ieee80211_akm)ni->ni_rsnakms))\n        frm = ieee80211_add_pmkid_kde(frm, ni->ni_pmkid);\n    \n    size_t l = frm - (u_int8_t *)key;\n    mbuf_pkthdr_setlen(m, l);\n    mbuf_setlen(m, l);\n    \n    if (ic->ic_if.if_flags & IFF_DEBUG)\n        XYLog(\"%s: sending msg %d/%d of the %s handshake to %s\\n\",\n               ic->ic_if.if_xname, 1, 4, \"4-way\",\n               ether_sprintf(ni->ni_macaddr));\n    \n    ni->ni_replaycnt++;\n    BE_WRITE_8(key->replaycnt, ni->ni_replaycnt);\n    \n    return ieee80211_send_eapol_key(ic, m, ni, NULL);\n}\n#endif\t/* IEEE80211_STA_ONLY */\n\n/*\n * Send 4-Way Handshake Message 2 to the authenticator.\n */\nint\nieee80211_send_4way_msg2(struct ieee80211com *ic, struct ieee80211_node *ni,\n                         const u_int8_t *replaycnt, const struct ieee80211_ptk *tptk)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct ieee80211_eapol_key *key;\n    mbuf_t m;\n    u_int16_t info;\n    u_int8_t *frm;\n    \n    ni->ni_rsn_supp_state = RSNA_SUPP_PTKNEGOTIATING;\n    m = ieee80211_get_eapol_key(MBUF_DONTWAIT, MT_DATA,\n                                (ni->ni_rsnprotos == IEEE80211_PROTO_WPA) ?\n                                2 + IEEE80211_WPAIE_MAXLEN :\n                                2 + IEEE80211_RSNIE_MAXLEN);\n    if (m == NULL)\n        return ENOMEM;\n    key = mtod(m, struct ieee80211_eapol_key *);\n    memset(key, 0, sizeof(*key));\n    \n    info = EAPOL_KEY_PAIRWISE | EAPOL_KEY_KEYMIC;\n    BE_WRITE_2(key->info, info);\n    \n    /* copy key replay counter from Message 1/4 */\n    memcpy(key->replaycnt, replaycnt, 8);\n    \n    /* copy the supplicant's nonce (SNonce) */\n    memcpy(key->nonce, ic->ic_nonce, EAPOL_KEY_NONCE_LEN);\n    \n    frm = (u_int8_t *)&key[1];\n    /* add the WPA/RSN IE used in the (Re)Association Request */\n    if (ni->ni_rsnprotos == IEEE80211_PROTO_WPA) {\n        int keylen;\n        frm = ieee80211_add_wpa(frm, ic, ni);\n        /* WPA sets the key length field here */\n        keylen = ieee80211_cipher_keylen(ni->ni_rsncipher);\n        BE_WRITE_2(key->keylen, keylen);\n    } else\t/* RSN */\n        frm = ieee80211_add_rsn(frm, ic, ni);\n    size_t l = frm - (u_int8_t *)key;\n    mbuf_pkthdr_setlen(m, l);\n    mbuf_setlen(m, l);\n    \n    if (ic->ic_if.if_flags & IFF_DEBUG)\n        XYLog(\"%s: sending msg %d/%d of the %s handshake to %s, type=%s\\n\",\n               ic->ic_if.if_xname, 2, 4, \"4-way\",\n              ether_sprintf(ni->ni_macaddr), ni->ni_rsnprotos == IEEE80211_PROTO_WPA ? \"WPA\" : \"RSN\");\n    \n    return ieee80211_send_eapol_key(ic, m, ni, tptk);\n}\n\n#ifndef IEEE80211_STA_ONLY\n/*\n * Send 4-Way Handshake Message 3 to the supplicant.\n */\nint\nieee80211_send_4way_msg3(struct ieee80211com *ic, struct ieee80211_node *ni)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct ieee80211_eapol_key *key;\n    struct ieee80211_key *k = NULL;\n    mbuf_t m;\n    u_int16_t info, keylen;\n    u_int8_t *frm;\n    \n    ni->ni_rsn_state = RSNA_PTKINITNEGOTIATING;\n    if (++ni->ni_rsn_retries > 3) {\n        IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DEAUTH,\n                            IEEE80211_REASON_4WAY_TIMEOUT);\n        ieee80211_node_leave(ic, ni);\n        return 0;\n    }\n    if (ni->ni_rsnprotos == IEEE80211_PROTO_RSN) {\n        k = &ic->ic_nw_keys[ic->ic_def_txkey];\n        m = ieee80211_get_eapol_key(MBUF_DONTWAIT, MT_DATA,\n                                    2 + IEEE80211_RSNIE_MAXLEN + 2 + 6 + k->k_len + 15 +\n                                    ((ni->ni_flags & IEEE80211_NODE_MFP) ? 2 + 28 : 0));\n    } else { /* WPA */\n        m = ieee80211_get_eapol_key(MBUF_DONTWAIT, MT_DATA,\n                                    2 + IEEE80211_WPAIE_MAXLEN +\n                                    ((ni->ni_flags & IEEE80211_NODE_MFP) ? 2 + 28 : 0));\n    }\n    if (m == NULL)\n        return ENOMEM;\n    key = mtod(m, struct ieee80211_eapol_key *);\n    memset(key, 0, sizeof(*key));\n    \n    info = EAPOL_KEY_PAIRWISE | EAPOL_KEY_KEYACK | EAPOL_KEY_KEYMIC;\n    if (ni->ni_rsncipher != IEEE80211_CIPHER_USEGROUP)\n        info |= EAPOL_KEY_INSTALL;\n    \n    /* use same nonce as in Message 1 */\n    memcpy(key->nonce, ni->ni_nonce, EAPOL_KEY_NONCE_LEN);\n    \n    ni->ni_replaycnt++;\n    BE_WRITE_8(key->replaycnt, ni->ni_replaycnt);\n    \n    keylen = ieee80211_cipher_keylen(ni->ni_rsncipher);\n    BE_WRITE_2(key->keylen, keylen);\n    \n    frm = (u_int8_t *)&key[1];\n    /* add the WPA/RSN IE included in Beacon/Probe Response */\n    if (ni->ni_rsnprotos == IEEE80211_PROTO_RSN) {\n        frm = ieee80211_add_rsn(frm, ic, ic->ic_bss);\n        /* encapsulate the GTK */\n        frm = ieee80211_add_gtk_kde(frm, ni, k);\n        LE_WRITE_6(key->rsc, k->k_tsc);\n        /* encapsulate the IGTK if MFP was negotiated */\n        if (ni->ni_flags & IEEE80211_NODE_MFP) {\n            frm = ieee80211_add_igtk_kde(frm,\n                                         &ic->ic_nw_keys[ic->ic_igtk_kid]);\n        }\n        /* ask that the EAPOL-Key frame be encrypted */\n        info |= EAPOL_KEY_ENCRYPTED | EAPOL_KEY_SECURE;\n    } else\t/* WPA */\n        frm = ieee80211_add_wpa(frm, ic, ic->ic_bss);\n    \n    /* write the key info field */\n    BE_WRITE_2(key->info, info);\n    \n    size_t l = frm - (u_int8_t *)key;\n    mbuf_pkthdr_setlen(m, l);\n    mbuf_setlen(m, l);\n    \n    if (ic->ic_if.if_flags & IFF_DEBUG)\n        XYLog(\"%s: sending msg %d/%d of the %s handshake to %s\\n\",\n               ic->ic_if.if_xname, 3, 4, \"4-way\",\n               ether_sprintf(ni->ni_macaddr));\n    \n    return ieee80211_send_eapol_key(ic, m, ni, &ni->ni_ptk);\n}\n#endif\t/* IEEE80211_STA_ONLY */\n\n/*\n * Send 4-Way Handshake Message 4 to the authenticator.\n */\nint\nieee80211_send_4way_msg4(struct ieee80211com *ic, struct ieee80211_node *ni)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct ieee80211_eapol_key *key;\n    mbuf_t m;\n    u_int16_t info;\n    \n    ni->ni_rsn_supp_state = RNSA_SUPP_PTKDONE;\n    m = ieee80211_get_eapol_key(MBUF_DONTWAIT, MT_DATA, 0);\n    if (m == NULL)\n        return ENOMEM;\n    key = mtod(m, struct ieee80211_eapol_key *);\n    memset(key, 0, sizeof(*key));\n    \n    info = EAPOL_KEY_PAIRWISE | EAPOL_KEY_KEYMIC;\n    \n    /* copy key replay counter from authenticator */\n    BE_WRITE_8(key->replaycnt, ni->ni_replaycnt);\n    \n    if (ni->ni_rsnprotos == IEEE80211_PROTO_WPA) {\n        int keylen;\n        /* WPA sets the key length field here */\n        keylen = ieee80211_cipher_keylen(ni->ni_rsncipher);\n        BE_WRITE_2(key->keylen, keylen);\n    } else\n        info |= EAPOL_KEY_SECURE;\n    \n    /* write the key info field */\n    BE_WRITE_2(key->info, info);\n    \n    /* empty key data field */\n    mbuf_pkthdr_setlen(m, sizeof(*key));\n    mbuf_setlen(m, sizeof(*key));\n    \n    if (ic->ic_if.if_flags & IFF_DEBUG)\n        XYLog(\"%s: sending msg %d/%d of the %s handshake to %s\\n\",\n               ic->ic_if.if_xname, 4, 4, \"4-way\",\n               ether_sprintf(ni->ni_macaddr));\n    \n    return ieee80211_send_eapol_key(ic, m, ni, &ni->ni_ptk);\n}\n\n#ifndef IEEE80211_STA_ONLY\n/*\n * Send Group Key Handshake Message 1 to the supplicant.\n */\nint\nieee80211_send_group_msg1(struct ieee80211com *ic, struct ieee80211_node *ni)\n{\n    XYLog(\"%s Send Group Key Handshake Message 1 to the supplicant.\\n\", __FUNCTION__);\n    struct ieee80211_eapol_key *key;\n    const struct ieee80211_key *k;\n    mbuf_t m;\n    u_int16_t info;\n    u_int8_t *frm;\n    u_int8_t kid;\n    \n    ni->ni_rsn_gstate = RSNA_REKEYNEGOTIATING;\n    if (++ni->ni_rsn_retries > 3) {\n        IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DEAUTH,\n                            IEEE80211_REASON_GROUP_TIMEOUT);\n        ieee80211_node_leave(ic, ni);\n        return 0;\n    }\n    if (ni->ni_flags & IEEE80211_NODE_REKEY)\n        kid = (ic->ic_def_txkey == 1) ? 2 : 1;\n    else\n        kid = ic->ic_def_txkey;\n    k = &ic->ic_nw_keys[kid];\n    \n    m = ieee80211_get_eapol_key(MBUF_DONTWAIT, MT_DATA,\n                                ((ni->ni_rsnprotos == IEEE80211_PROTO_WPA) ?\n                                 k->k_len : 2 + 6 + k->k_len) +\n                                ((ni->ni_flags & IEEE80211_NODE_MFP) ? 2 + 28 : 0) +\n                                15);\n    if (m == NULL)\n        return ENOMEM;\n    key = mtod(m, struct ieee80211_eapol_key *);\n    memset(key, 0, sizeof(*key));\n    \n    info = EAPOL_KEY_KEYACK | EAPOL_KEY_KEYMIC | EAPOL_KEY_SECURE |\n    EAPOL_KEY_ENCRYPTED;\n    \n    ni->ni_replaycnt++;\n    BE_WRITE_8(key->replaycnt, ni->ni_replaycnt);\n    \n    frm = (u_int8_t *)&key[1];\n    if (ni->ni_rsnprotos == IEEE80211_PROTO_WPA) {\n        /* WPA does not have GTK KDE */\n        BE_WRITE_2(key->keylen, k->k_len);\n        memcpy(frm, k->k_key, k->k_len);\n        frm += k->k_len;\n        info |= (k->k_id & 0x3) << EAPOL_KEY_WPA_KID_SHIFT;\n        if (ni->ni_rsncipher == IEEE80211_CIPHER_USEGROUP)\n            info |= EAPOL_KEY_WPA_TX;\n    } else {\t/* RSN */\n        frm = ieee80211_add_gtk_kde(frm, ni, k);\n        if (ni->ni_flags & IEEE80211_NODE_MFP) {\n            if (ni->ni_flags & IEEE80211_NODE_REKEY)\n                kid = (ic->ic_igtk_kid == 4) ? 5 : 4;\n            else\n                kid = ic->ic_igtk_kid;\n            frm = ieee80211_add_igtk_kde(frm,\n                                         &ic->ic_nw_keys[kid]);\n        }\n    }\n    /* RSC = last transmit sequence number for the GTK */\n    LE_WRITE_6(key->rsc, k->k_tsc);\n    \n    /* write the key info field */\n    BE_WRITE_2(key->info, info);\n    \n    size_t l = frm - (u_int8_t *)key;\n    mbuf_pkthdr_setlen(m, l);\n    mbuf_setlen(m, l);\n    \n    if (ic->ic_if.if_flags & IFF_DEBUG)\n        XYLog(\"%s: sending msg %d/%d of the %s handshake to %s\\n\",\n               ic->ic_if.if_xname, 1, 2, \"group key\",\n               ether_sprintf(ni->ni_macaddr));\n    \n    return ieee80211_send_eapol_key(ic, m, ni, &ni->ni_ptk);\n}\n#endif\t/* IEEE80211_STA_ONLY */\n\n/*\n * Send Group Key Handshake Message 2 to the authenticator.\n */\nint\nieee80211_send_group_msg2(struct ieee80211com *ic, struct ieee80211_node *ni,\n                          const struct ieee80211_key *k)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct ieee80211_eapol_key *key;\n    u_int16_t info;\n    mbuf_t m;\n    \n    m = ieee80211_get_eapol_key(MBUF_DONTWAIT, MT_DATA, 0);\n    if (m == NULL)\n        return ENOMEM;\n    key = mtod(m, struct ieee80211_eapol_key *);\n    memset(key, 0, sizeof(*key));\n    \n    info = EAPOL_KEY_KEYMIC | EAPOL_KEY_SECURE;\n    \n    /* copy key replay counter from authenticator */\n    BE_WRITE_8(key->replaycnt, ni->ni_replaycnt);\n    \n    if (ni->ni_rsnprotos == IEEE80211_PROTO_WPA) {\n        /* WPA sets the key length and key id fields here */\n        BE_WRITE_2(key->keylen, k->k_len);\n        info |= (k->k_id & 3) << EAPOL_KEY_WPA_KID_SHIFT;\n    }\n    \n    /* write the key info field */\n    BE_WRITE_2(key->info, info);\n    \n    /* empty key data field */\n    mbuf_pkthdr_setlen(m, sizeof(*key));\n    mbuf_setlen(m, sizeof(*key));\n    \n    if (ic->ic_if.if_flags & IFF_DEBUG)\n        XYLog(\"%s: sending msg %d/%d of the %s handshake to %s\\n\",\n               ic->ic_if.if_xname, 2, 2, \"group key\",\n               ether_sprintf(ni->ni_macaddr));\n    \n    return ieee80211_send_eapol_key(ic, m, ni, &ni->ni_ptk);\n}\n\n/*\n * EAPOL-Key Request frames are sent by the supplicant to request that the\n * authenticator initiates either a 4-Way Handshake or Group Key Handshake,\n * or to report a MIC failure in a TKIP MSDU.\n */\nint\nieee80211_send_eapol_key_req(struct ieee80211com *ic,\n                             struct ieee80211_node *ni, u_int16_t info, u_int64_t tsc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct ieee80211_eapol_key *key;\n    mbuf_t m;\n    \n    m = ieee80211_get_eapol_key(MBUF_DONTWAIT, MT_DATA, 0);\n    if (m == NULL)\n        return ENOMEM;\n    key = mtod(m, struct ieee80211_eapol_key *);\n    memset(key, 0, sizeof(*key));\n    \n    info |= EAPOL_KEY_REQUEST;\n    BE_WRITE_2(key->info, info);\n    \n    /* in case of TKIP MIC failure, fill the RSC field */\n    if (info & EAPOL_KEY_ERROR)\n        LE_WRITE_6(key->rsc, tsc);\n    \n    /* use our separate key replay counter for key requests */\n    BE_WRITE_8(key->replaycnt, ni->ni_reqreplaycnt);\n    ni->ni_reqreplaycnt++;\n    \n    /* empty key data field */\n    mbuf_pkthdr_setlen(m, sizeof(*key));\n    mbuf_setlen(m, sizeof(*key));\n    \n    if (ic->ic_if.if_flags & IFF_DEBUG)\n        XYLog(\"%s: sending EAPOL-Key request to %s\\n\",\n               ic->ic_if.if_xname, ether_sprintf(ni->ni_macaddr));\n    \n    return ieee80211_send_eapol_key(ic, m, ni, &ni->ni_ptk);\n}\n"
  },
  {
    "path": "itl80211/openbsd/net80211/ieee80211_priv.h",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n/*\t$OpenBSD: ieee80211_priv.h,v 1.5 2009/01/26 19:09:41 damien Exp $\t*/\n\n/*-\n * Copyright (c) 2008 Damien Bergamini <damien.bergamini@free.fr>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n#ifndef _NET80211_IEEE80211_PRIV_H_\n#define _NET80211_IEEE80211_PRIV_H_\n\n#ifdef IEEE80211_DEBUG\nextern int ieee80211_debug;\n#define DPRINTF(X) do {\t\t\t\t\\\n\tif (ieee80211_debug) {\t\t\t\\\n\t\tXYLog(\"%s ieee80211: \", __FUNCTION__);\t\\\n\t\tXYLog X;\t\t\t\\\n\t}\t\t\t\t\t\\\n} while(0)\n#else\n#define DPRINTF(X)\n#endif\n\n#define SEQ_LT(a,b)\t\\\n\t((((u_int16_t)(a) - (u_int16_t)(b)) & 0xfff) > 2048)\n\n#define IEEE80211_AID_SET(b, w) \\\n\t((w)[IEEE80211_AID(b) / 32] |= (1 << (IEEE80211_AID(b) % 32)))\n#define IEEE80211_AID_CLR(b, w) \\\n\t((w)[IEEE80211_AID(b) / 32] &= ~(1 << (IEEE80211_AID(b) % 32)))\n#define IEEE80211_AID_ISSET(b, w) \\\n\t((w)[IEEE80211_AID(b) / 32] & (1 << (IEEE80211_AID(b) % 32)))\n\n#define IEEE80211_RSNIE_MAXLEN\t\t\t\t\t\t\\\n\t(2 +\t\t/* Version */\t\t\t\t\t\\\n\t 4 +\t\t/* Group Data Cipher Suite */\t\t\t\\\n\t 2 +\t\t/* Pairwise Cipher Suite Count */\t\t\\\n\t 4 * 2 +\t/* Pairwise Cipher Suite List (max 2) */\t\\\n\t 2 +\t\t/* AKM Suite List Count */\t\t\t\\\n\t 4 * 4 +\t/* AKM Suite List (max 4) */\t\t\t\\\n\t 2 +\t\t/* RSN Capabilities */\t\t\t\t\\\n\t 2 +\t\t/* PMKID Count */\t\t\t\t\\\n\t 16 * 1 +\t/* PMKID List (max 1) */\t\t\t\\\n\t 4)\t\t/* 11w: Group Integrity Cipher Suite */\n\n#define IEEE80211_WPAIE_MAXLEN\t\t\t\t\t\t\\\n\t(4 +\t\t/* MICROSOFT_OUI */\t\t\t\t\\\n\t 2 +\t\t/* Version */\t\t\t\t\t\\\n\t 4 +\t\t/* Group Cipher Suite */\t\t\t\\\n\t 2 +\t\t/* Pairwise Cipher Suite Count */\t\t\\\n\t 4 * 2 +\t/* Pairwise Cipher Suite List (max 2) */\t\\\n\t 2 +\t\t/* AKM Suite List Count */\t\t\t\\\n\t 4 * 2)\t\t/* AKM Suite List (max 2) */\n\nstruct ieee80211_rsnparams {\n\tu_int16_t\t\trsn_nakms;\n\tu_int32_t\t\trsn_akms;\n\tu_int16_t\t\trsn_nciphers;\n\tu_int32_t\t\trsn_ciphers;\n\tenum ieee80211_cipher\trsn_groupcipher;\n\tenum ieee80211_cipher\trsn_groupmgmtcipher;\n\tu_int16_t\t\trsn_caps;\n\tu_int8_t\t\trsn_npmkids;\n\tconst u_int8_t\t\t*rsn_pmkids;\n};\n\n/* unaligned big endian access */\n#define BE_READ_2(p)\t\t\t\t\\\n\t((u_int16_t)\t\t\t\t\\\n         ((((const u_int8_t *)(p))[0] << 8) |\t\\\n          (((const u_int8_t *)(p))[1])))\n\n#define BE_READ_8(p)\t\t\t\t\t\t\\\n\t((u_int64_t)(p)[0] << 56 | (u_int64_t)(p)[1] << 48 |\t\\\n\t (u_int64_t)(p)[2] << 40 | (u_int64_t)(p)[3] << 32 |\t\\\n\t (u_int64_t)(p)[4] << 24 | (u_int64_t)(p)[5] << 16 |\t\\\n\t (u_int64_t)(p)[6] <<  8 | (u_int64_t)(p)[7])\n\n#define BE_WRITE_2(p, v) do {\t\t\t\\\n\t((u_int8_t *)(p))[0] = (v) >> 8;\t\\\n\t((u_int8_t *)(p))[1] = (v) & 0xff;\t\\\n} while (0)\n\n#define BE_WRITE_8(p, v) do {\t\t\t\\\n\t(p)[0] = (v) >> 56; (p)[1] = (v) >> 48;\t\\\n\t(p)[2] = (v) >> 40; (p)[3] = (v) >> 32;\t\\\n\t(p)[4] = (v) >> 24; (p)[5] = (v) >> 16;\t\\\n\t(p)[6] = (v) >>  8; (p)[7] = (v);\t\\\n} while (0)\n\n/* unaligned little endian access */\n#define LE_READ_2(p)\t\t\t\t\t\\\n\t((u_int16_t)\t\t\t\t\t\\\n\t ((((const u_int8_t *)(p))[0]) |\t\t\\\n\t  (((const u_int8_t *)(p))[1] <<  8)))\n\n#define LE_READ_4(p)\t\t\t\t\t\\\n\t((u_int32_t)\t\t\t\t\t\\\n\t ((((const u_int8_t *)(p))[0])       |\t\t\\\n\t  (((const u_int8_t *)(p))[1] <<  8) |\t\t\\\n\t  (((const u_int8_t *)(p))[2] << 16) |\t\t\\\n\t  (((const u_int8_t *)(p))[3] << 24)))\n\n#define LE_READ_6(p)\t\t\t\t\t\t\\\n\t((u_int64_t)(p)[5] << 40 | (u_int64_t)(p)[4] << 32 |\t\\\n\t (u_int64_t)(p)[3] << 24 | (u_int64_t)(p)[2] << 16 |\t\\\n\t (u_int64_t)(p)[1] <<  8 | (u_int64_t)(p)[0])\n\n#define LE_WRITE_2(p, v) do {\t\t\t\\\n\t((u_int8_t *)(p))[0] = (v) & 0xff;\t\\\n\t((u_int8_t *)(p))[1] = (v) >> 8;\t\\\n} while (0)\n\n#define LE_WRITE_4(p, v) do {\t\t\t\\\n\t(p)[3] = (v) >> 24; (p)[2] = (v) >> 16;\t\\\n\t(p)[1] = (v) >>  8; (p)[0] = (v);\t\\\n} while (0)\n\n#define LE_WRITE_6(p, v) do {\t\t\t\\\n\t(p)[5] = (v) >> 40; (p)[4] = (v) >> 32;\t\\\n\t(p)[3] = (v) >> 24; (p)[2] = (v) >> 16;\t\\\n\t(p)[1] = (v) >>  8; (p)[0] = (v);\t\\\n} while (0)\n\n#endif /* _NET80211_IEEE80211_PRIV_H_ */\n"
  },
  {
    "path": "itl80211/openbsd/net80211/ieee80211_proto.c",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n/*\t$OpenBSD: ieee80211_proto.c,v 1.95 2019/09/02 12:54:21 stsp Exp $\t*/\n/*\t$NetBSD: ieee80211_proto.c,v 1.8 2004/04/30 23:58:20 dyoung Exp $\t*/\n\n/*-\n * Copyright (c) 2001 Atsushi Onoe\n * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting\n * Copyright (c) 2008, 2009 Damien Bergamini\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. The name of the author may not be used to endorse or promote products\n *    derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*\n * IEEE 802.11 protocol support.\n */\n\n#include <sys/param.h>\n#include <sys/systm.h>\n#include <sys/mbuf.h>\n#include <sys/kernel.h>\n#include <sys/socket.h>\n#include <sys/sockio.h>\n#include <sys/endian.h>\n#include <sys/errno.h>\n#include <sys/sysctl.h>\n\n#include <net/if.h>\n#include <net/if_dl.h>\n#include <net/if_media.h>\n#include <net/if_llc.h>\n#include <net/route.h>\n\n#include <netinet/in.h>\n#include <netinet/if_ether.h>\n\n#include <net80211/ieee80211_var.h>\n#include <net80211/ieee80211_priv.h>\n\nconst char * const ieee80211_mgt_subtype_name[] = {\n\t\"assoc_req\",\t\"assoc_resp\",\t\"reassoc_req\",\t\"reassoc_resp\",\n\t\"probe_req\",\t\"probe_resp\",\t\"reserved#6\",\t\"reserved#7\",\n\t\"beacon\",\t\"atim\",\t\t\"disassoc\",\t\"auth\",\n\t\"deauth\",\t\"action\",\t\"action_noack\",\t\"reserved#15\"\n};\nconst char * const ieee80211_state_name[IEEE80211_S_MAX] = {\n\t\"INIT\",\t\t/* IEEE80211_S_INIT */\n\t\"SCAN\",\t\t/* IEEE80211_S_SCAN */\n\t\"AUTH\",\t\t/* IEEE80211_S_AUTH */\n\t\"ASSOC\",\t/* IEEE80211_S_ASSOC */\n\t\"RUN\"\t\t/* IEEE80211_S_RUN */\n};\nconst char * const ieee80211_phymode_name[] = {\n\t\"auto\",\t\t/* IEEE80211_MODE_AUTO */\n\t\"11a\",\t\t/* IEEE80211_MODE_11A */\n\t\"11b\",\t\t/* IEEE80211_MODE_11B */\n\t\"11g\",\t\t/* IEEE80211_MODE_11G */\n\t\"11n\",\t\t/* IEEE80211_MODE_11N */\n    \"11ac\",     /* IEEE80211_MODE_11AC */\n    \"11ax\",     /* IEEE80211_MODE_11AX */\n};\n\nvoid ieee80211_set_beacon_miss_threshold(struct ieee80211com *);\nint ieee80211_newstate(struct ieee80211com *, enum ieee80211_state, int);\n\nvoid\nieee80211_proto_attach(struct _ifnet *ifp)\n{\n\tstruct ieee80211com *ic = (struct ieee80211com *)ifp;\n\n\tmq_init(&ic->ic_mgtq, IFQ_MAXLEN, IPL_NET);\n\tmq_init(&ic->ic_pwrsaveq, IFQ_MAXLEN, IPL_NET);\n\n\tifp->if_hdrlen = sizeof(struct ieee80211_frame);\n\n\tic->ic_rtsthreshold = IEEE80211_RTS_MAX;\n\tic->ic_fragthreshold = 2346;\t\t/* XXX not used yet */\n\tic->ic_fixed_rate = -1;\t\t\t/* no fixed rate */\n\tic->ic_fixed_mcs = -1;\t\t\t/* no fixed mcs */\n\tic->ic_protmode = IEEE80211_PROT_CTSONLY;\n\n\t/* protocol state change handler */\n\tic->ic_newstate = ieee80211_newstate;\n\n\t/* initialize management frame handlers */\n\tic->ic_recv_mgmt = ieee80211_recv_mgmt;\n\tic->ic_send_mgmt = ieee80211_send_mgmt;\n}\n\nvoid\nieee80211_proto_detach(struct _ifnet *ifp)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n\tstruct ieee80211com *ic = (struct ieee80211com *)ifp;\n\n\tmq_purge(&ic->ic_mgtq);\n\tmq_purge(&ic->ic_pwrsaveq);\n}\n\nvoid\nieee80211_print_essid(const u_int8_t *essid, int len)\n{\n\tint i;\n\tconst u_int8_t *p;\n\n    XYLog(\"%s\\n\", essid);\n//\tif (len > IEEE80211_NWID_LEN)\n//\t\tlen = IEEE80211_NWID_LEN;\n//\t/* determine printable or not */\n//\tfor (i = 0, p = essid; i < len; i++, p++) {\n//\t\tif (*p < ' ' || *p > 0x7e)\n//\t\t\tbreak;\n//\t}\n//\tif (i == len) {\n//\t\tXYLog(\"\\\"\");\n//\t\tfor (i = 0, p = essid; i < len; i++, p++)\n//\t\t\tXYLog(\"%c\", *p);\n//\t\tXYLog(\"\\\"\");\n//\t} else {\n//\t\tXYLog(\"0x\");\n//\t\tfor (i = 0, p = essid; i < len; i++, p++)\n//\t\t\tXYLog(\"%02x\", *p);\n//\t}\n}\n\n#ifdef IEEE80211_DEBUG\nvoid\nieee80211_dump_pkt(const u_int8_t *buf, int len, int rate, int rssi)\n{\n\tstruct ieee80211_frame *wh;\n\tint i;\n\n\twh = (struct ieee80211_frame *)buf;\n\tswitch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) {\n\tcase IEEE80211_FC1_DIR_NODS:\n\t\tXYLog(\"NODS %s\", ether_sprintf(wh->i_addr2));\n\t\tXYLog(\"->%s\", ether_sprintf(wh->i_addr1));\n\t\tXYLog(\"(%s)\", ether_sprintf(wh->i_addr3));\n\t\tbreak;\n\tcase IEEE80211_FC1_DIR_TODS:\n\t\tXYLog(\"TODS %s\", ether_sprintf(wh->i_addr2));\n\t\tXYLog(\"->%s\", ether_sprintf(wh->i_addr3));\n\t\tXYLog(\"(%s)\", ether_sprintf(wh->i_addr1));\n\t\tbreak;\n\tcase IEEE80211_FC1_DIR_FROMDS:\n\t\tXYLog(\"FRDS %s\", ether_sprintf(wh->i_addr3));\n\t\tXYLog(\"->%s\", ether_sprintf(wh->i_addr1));\n\t\tXYLog(\"(%s)\", ether_sprintf(wh->i_addr2));\n\t\tbreak;\n\tcase IEEE80211_FC1_DIR_DSTODS:\n\t\tXYLog(\"DSDS %s\", ether_sprintf((u_int8_t *)&wh[1]));\n\t\tXYLog(\"->%s\", ether_sprintf(wh->i_addr3));\n\t\tXYLog(\"(%s\", ether_sprintf(wh->i_addr2));\n\t\tXYLog(\"->%s)\", ether_sprintf(wh->i_addr1));\n\t\tbreak;\n\t}\n\tswitch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {\n\tcase IEEE80211_FC0_TYPE_DATA:\n\t\tXYLog(\" data\");\n\t\tbreak;\n\tcase IEEE80211_FC0_TYPE_MGT:\n\t\tXYLog(\" %s\", ieee80211_mgt_subtype_name[\n\t\t    (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK)\n\t\t    >> IEEE80211_FC0_SUBTYPE_SHIFT]);\n\t\tbreak;\n\tdefault:\n\t\tXYLog(\" type#%d\", wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK);\n\t\tbreak;\n\t}\n\tif (wh->i_fc[1] & IEEE80211_FC1_WEP)\n\t\tXYLog(\" WEP\");\n\tif (rate >= 0)\n\t\tXYLog(\" %d%sM\", rate / 2, (rate & 1) ? \".5\" : \"\");\n\tif (rssi >= 0)\n\t\tXYLog(\" +%d\", rssi);\n\tXYLog(\"\\n\");\n\tif (len > 0) {\n\t\tfor (i = 0; i < len; i++) {\n\t\t\tif ((i & 1) == 0)\n\t\t\t\tXYLog(\" \");\n\t\t\tXYLog(\"%02x\", buf[i]);\n\t\t}\n\t\tXYLog(\"\\n\");\n\t}\n}\n#endif\n\nint\nieee80211_fix_rate(struct ieee80211com *ic, struct ieee80211_node *ni,\n    int flags)\n{\n#define\tRV(v)\t((v) & IEEE80211_RATE_VAL)\n\tint i, j, ignore, error;\n\tint okrate, badrate, fixedrate;\n\tconst struct ieee80211_rateset *srs;\n\tstruct ieee80211_rateset *nrs;\n\tu_int8_t r;\n\n\t/*\n\t * If the fixed rate check was requested but no fixed rate has been\n\t * defined then just remove the check.\n\t */\n\tif ((flags & IEEE80211_F_DOFRATE) && ic->ic_fixed_rate == -1)\n\t\tflags &= ~IEEE80211_F_DOFRATE;\n\n\terror = 0;\n\tokrate = badrate = fixedrate = 0;\n\tsrs = &ic->ic_sup_rates[ieee80211_chan2mode(ic, ni->ni_chan)];\n\tnrs = &ni->ni_rates;\n\tfor (i = 0; i < nrs->rs_nrates; ) {\n\t\tignore = 0;\n\t\tif (flags & IEEE80211_F_DOSORT) {\n\t\t\t/*\n\t\t\t * Sort rates.\n\t\t\t */\n\t\t\tfor (j = i + 1; j < nrs->rs_nrates; j++) {\n\t\t\t\tif (RV(nrs->rs_rates[i]) >\n\t\t\t\t    RV(nrs->rs_rates[j])) {\n\t\t\t\t\tr = nrs->rs_rates[i];\n\t\t\t\t\tnrs->rs_rates[i] = nrs->rs_rates[j];\n\t\t\t\t\tnrs->rs_rates[j] = r;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tr = nrs->rs_rates[i] & IEEE80211_RATE_VAL;\n\t\tbadrate = r;\n\t\tif (flags & IEEE80211_F_DOFRATE) {\n\t\t\t/*\n\t\t\t * Check fixed rate is included.\n\t\t\t */\n\t\t\tif (r == RV(srs->rs_rates[ic->ic_fixed_rate]))\n\t\t\t\tfixedrate = r;\n\t\t}\n\t\tif (flags & IEEE80211_F_DONEGO) {\n\t\t\t/*\n\t\t\t * Check against supported rates.\n\t\t\t */\n\t\t\tfor (j = 0; j < srs->rs_nrates; j++) {\n\t\t\t\tif (r == RV(srs->rs_rates[j])) {\n\t\t\t\t\t/*\n\t\t\t\t\t * Overwrite with the supported rate\n\t\t\t\t\t * value so any basic rate bit is set.\n\t\t\t\t\t * This insures that response we send\n\t\t\t\t\t * to stations have the necessary basic\n\t\t\t\t\t * rate bit set.\n\t\t\t\t\t */\n\t\t\t\t\tnrs->rs_rates[i] = srs->rs_rates[j];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (j == srs->rs_nrates) {\n\t\t\t\t/*\n\t\t\t\t * A rate in the node's rate set is not\n\t\t\t\t * supported.  If this is a basic rate and we\n\t\t\t\t * are operating as an AP then this is an error.\n\t\t\t\t * Otherwise we just discard/ignore the rate.\n\t\t\t\t * Note that this is important for 11b stations\n\t\t\t\t * when they want to associate with an 11g AP.\n\t\t\t\t */\n#ifndef IEEE80211_STA_ONLY\n\t\t\t\tif (ic->ic_opmode == IEEE80211_M_HOSTAP &&\n\t\t\t\t    (nrs->rs_rates[i] & IEEE80211_RATE_BASIC))\n\t\t\t\t\terror++;\n#endif\n\t\t\t\tignore++;\n\t\t\t}\n\t\t}\n\t\tif (flags & IEEE80211_F_DODEL) {\n\t\t\t/*\n\t\t\t * Delete unacceptable rates.\n\t\t\t */\n\t\t\tif (ignore) {\n\t\t\t\tnrs->rs_nrates--;\n\t\t\t\tfor (j = i; j < nrs->rs_nrates; j++)\n\t\t\t\t\tnrs->rs_rates[j] = nrs->rs_rates[j + 1];\n\t\t\t\tnrs->rs_rates[j] = 0;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\tif (!ignore)\n\t\t\tokrate = nrs->rs_rates[i];\n\t\ti++;\n\t}\n\tif (okrate == 0 || error != 0 ||\n\t    ((flags & IEEE80211_F_DOFRATE) && fixedrate == 0))\n\t\treturn badrate | IEEE80211_RATE_BASIC;\n\telse\n\t\treturn RV(okrate);\n#undef RV\n}\n\n/*\n * Reset 11g-related state.\n */\nvoid\nieee80211_reset_erp(struct ieee80211com *ic)\n{\n\tic->ic_flags &= ~IEEE80211_F_USEPROT;\n\n\tieee80211_set_shortslottime(ic,\n\t    ic->ic_curmode == IEEE80211_MODE_11A ||\n\t    (ic->ic_curmode == IEEE80211_MODE_11N &&\n\t    IEEE80211_IS_CHAN_5GHZ(ic->ic_ibss_chan))\n#ifndef IEEE80211_STA_ONLY\n\t    ||\n\t    ((ic->ic_curmode == IEEE80211_MODE_11G ||\n\t    (ic->ic_curmode == IEEE80211_MODE_11N &&\n\t    IEEE80211_IS_CHAN_2GHZ(ic->ic_ibss_chan))) &&\n\t     ic->ic_opmode == IEEE80211_M_HOSTAP &&\n\t     (ic->ic_caps & IEEE80211_C_SHSLOT))\n#endif\n\t);\n\n\tif (ic->ic_curmode == IEEE80211_MODE_11A ||\n\t    (ic->ic_curmode == IEEE80211_MODE_11N &&\n\t    IEEE80211_IS_CHAN_5GHZ(ic->ic_ibss_chan)) ||\n\t    (ic->ic_caps & IEEE80211_C_SHPREAMBLE))\n\t\tic->ic_flags |= IEEE80211_F_SHPREAMBLE;\n\telse\n\t\tic->ic_flags &= ~IEEE80211_F_SHPREAMBLE;\n}\n\n/*\n * Set the short slot time state and notify the driver.\n */\nvoid\nieee80211_set_shortslottime(struct ieee80211com *ic, int on)\n{\n\tif (on)\n\t\tic->ic_flags |= IEEE80211_F_SHSLOT;\n\telse\n\t\tic->ic_flags &= ~IEEE80211_F_SHSLOT;\n\n\t/* notify the driver */\n\tif (ic->ic_updateslot != NULL)\n\t\tic->ic_updateslot(ic);\n}\n\n/*\n * This function is called by the 802.1X PACP machine (via an ioctl) when\n * the transmit key machine (4-Way Handshake for 802.11) should run.\n */\nint\nieee80211_keyrun(struct ieee80211com *ic, u_int8_t *macaddr)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n\tstruct ieee80211_node *ni = ic->ic_bss;\n#ifndef IEEE80211_STA_ONLY\n\tstruct ieee80211_pmk *pmk;\n#endif\n\n\t/* STA must be associated or AP must be ready */\n\tif (ic->ic_state != IEEE80211_S_RUN ||\n\t    !(ic->ic_flags & IEEE80211_F_RSNON))\n\t\treturn ENETDOWN;\n\n\tni->ni_rsn_supp_state = RSNA_SUPP_PTKSTART;\n#ifndef IEEE80211_STA_ONLY\n\tif (ic->ic_opmode == IEEE80211_M_STA)\n#endif\n\t\treturn 0;\t/* supplicant only, do nothing */\n\n#ifndef IEEE80211_STA_ONLY\n\t/* find the STA with which we must start the key exchange */\n\tif ((ni = ieee80211_find_node(ic, macaddr)) == NULL) {\n\t\tDPRINTF((\"no node found for %s\\n\", ether_sprintf(macaddr)));\n\t\treturn EINVAL;\n\t}\n\t/* check that the STA is in the correct state */\n\tif (ni->ni_state != IEEE80211_STA_ASSOC ||\n\t    ni->ni_rsn_state != RSNA_AUTHENTICATION_2) {\n\t\tDPRINTF((\"unexpected in state %d\\n\", ni->ni_rsn_state));\n\t\treturn EINVAL;\n\t}\n\tni->ni_rsn_state = RSNA_INITPMK;\n\n\t/* make sure a PMK is available for this STA, otherwise deauth it */\n\tif ((pmk = ieee80211_pmksa_find(ic, ni, NULL)) == NULL) {\n\t\tDPRINTF((\"no PMK available for %s\\n\", ether_sprintf(macaddr)));\n\t\tIEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DEAUTH,\n\t\t    IEEE80211_REASON_AUTH_LEAVE);\n\t\tieee80211_node_leave(ic, ni);\n\t\treturn EINVAL;\n\t}\n\tmemcpy(ni->ni_pmk, pmk->pmk_key, IEEE80211_PMK_LEN);\n\tmemcpy(ni->ni_pmkid, pmk->pmk_pmkid, IEEE80211_PMKID_LEN);\n\tni->ni_flags |= IEEE80211_NODE_PMK;\n\n\t/* initiate key exchange (4-Way Handshake) with STA */\n\treturn ieee80211_send_4way_msg1(ic, ni);\n#endif\t/* IEEE80211_STA_ONLY */\n}\n\n#ifndef IEEE80211_STA_ONLY\n/*\n * Initiate a group key handshake with a node.\n */\nstatic void\nieee80211_node_gtk_rekey(void *arg, struct ieee80211_node *ni)\n{\n\tstruct ieee80211com *ic = (struct ieee80211com *)arg;\n\n\tif (ni->ni_state != IEEE80211_STA_ASSOC ||\n\t    ni->ni_rsn_gstate != RSNA_IDLE)\n\t\treturn;\n\n\t/* initiate a group key handshake with STA */\n\tni->ni_flags |= IEEE80211_NODE_REKEY;\n\tif (ieee80211_send_group_msg1(ic, ni) != 0)\n\t\tni->ni_flags &= ~IEEE80211_NODE_REKEY;\n}\n\n/*\n * This function is called in HostAP mode when the group key needs to be\n * changed.\n */\nvoid\nieee80211_setkeys(struct ieee80211com *ic)\n{\n\tstruct ieee80211_key *k;\n\tu_int8_t kid;\n    int rekeysta = 0;\n\n\t/* Swap(GM, GN) */\n\tkid = (ic->ic_def_txkey == 1) ? 2 : 1;\n\tk = &ic->ic_nw_keys[kid];\n\tmemset(k, 0, sizeof(*k));\n\tk->k_id = kid;\n\tk->k_cipher = ic->ic_bss->ni_rsngroupcipher;\n\tk->k_flags = IEEE80211_KEY_GROUP | IEEE80211_KEY_TX;\n\tk->k_len = ieee80211_cipher_keylen(k->k_cipher);\n\tarc4random_buf(k->k_key, k->k_len);\n\n\tif (ic->ic_caps & IEEE80211_C_MFP) {\n\t\t/* Swap(GM_igtk, GN_igtk) */\n\t\tkid = (ic->ic_igtk_kid == 4) ? 5 : 4;\n\t\tk = &ic->ic_nw_keys[kid];\n\t\tmemset(k, 0, sizeof(*k));\n\t\tk->k_id = kid;\n\t\tk->k_cipher = ic->ic_bss->ni_rsngroupmgmtcipher;\n\t\tk->k_flags = IEEE80211_KEY_IGTK | IEEE80211_KEY_TX;\n\t\tk->k_len = 16;\n\t\tarc4random_buf(k->k_key, k->k_len);\n\t}\n\n\tieee80211_iterate_nodes(ic, ieee80211_node_gtk_rekey, ic);\n    ieee80211_iterate_nodes(ic, ieee80211_count_rekeysta, &rekeysta);\n    if (rekeysta == 0)\n        ieee80211_setkeysdone(ic);\n}\n\n/*\n * The group key handshake has been completed with all associated stations.\n */\nvoid\nieee80211_setkeysdone(struct ieee80211com *ic)\n{\n\tu_int8_t kid;\n\n\t/* install GTK */\n\tkid = (ic->ic_def_txkey == 1) ? 2 : 1;\n    switch ((*ic->ic_set_key)(ic, ic->ic_bss, &ic->ic_nw_keys[kid])) {\n        case 0:\n        case EBUSY:\n            ic->ic_def_txkey = kid;\n            break;\n        default:\n            break;\n    }\n\n\tif (ic->ic_caps & IEEE80211_C_MFP) {\n\t\t/* install IGTK */\n\t\tkid = (ic->ic_igtk_kid == 4) ? 5 : 4;\n        switch ((*ic->ic_set_key)(ic, ic->ic_bss, &ic->ic_nw_keys[kid])) {\n            case 0:\n            case EBUSY:\n                ic->ic_igtk_kid = kid;\n                break;\n            default:\n                break;\n        }\n\t}\n}\n\n/*\n * Group key lifetime has expired, update it.\n */\nvoid\nieee80211_gtk_rekey_timeout(void *arg)\n{\n\tstruct ieee80211com *ic = (struct ieee80211com *)arg;\n\tint s;\n\n\ts = splnet();\n\tieee80211_setkeys(ic);\n\tsplx(s);\n\n\t/* re-schedule a GTK rekeying after 3600s */\n\ttimeout_add_sec(&ic->ic_rsn_timeout, 3600);\n}\n\nvoid\nieee80211_sa_query_timeout(void *arg)\n{\n\tstruct ieee80211_node *ni = (struct ieee80211_node *)arg;\n\tstruct ieee80211com *ic = ni->ni_ic;\n\tint s;\n\n\ts = splnet();\n\tif (++ni->ni_sa_query_count >= 3) {\n\t\tni->ni_flags &= ~IEEE80211_NODE_SA_QUERY;\n\t\tni->ni_flags |= IEEE80211_NODE_SA_QUERY_FAILED;\n\t} else\t/* retry SA Query Request */\n\t\tieee80211_sa_query_request(ic, ni);\n\tsplx(s);\n}\n\n/*\n * Request that a SA Query Request frame be sent to a specified peer STA\n * to which the STA is associated.\n */\nvoid\nieee80211_sa_query_request(struct ieee80211com *ic, struct ieee80211_node *ni)\n{\n\t/* MLME-SAQuery.request */\n\n\tif (!(ni->ni_flags & IEEE80211_NODE_SA_QUERY)) {\n\t\tni->ni_flags |= IEEE80211_NODE_SA_QUERY;\n\t\tni->ni_flags &= ~IEEE80211_NODE_SA_QUERY_FAILED;\n\t\tni->ni_sa_query_count = 0;\n\t}\n\t/* generate new Transaction Identifier */\n\tni->ni_sa_query_trid++;\n\n\t/* send SA Query Request */\n\tIEEE80211_SEND_ACTION(ic, ni, IEEE80211_CATEG_SA_QUERY,\n\t    IEEE80211_ACTION_SA_QUERY_REQ, 0);\n\ttimeout_add_msec(&ni->ni_sa_query_to, 10);\n}\n#endif\t/* IEEE80211_STA_ONLY */\n\nvoid\nieee80211_ht_negotiate_chw(struct ieee80211com *ic, struct ieee80211_node *ni)\n{\n    int ht_param;\n\n    if (!ni || !ni->ni_chan)\n        return;\n    \n    ni->ni_chw = IEEE80211_CHAN_WIDTH_20;\n    ni->ni_chan->ic_center_freq1 = ni->ni_chan->ic_freq;\n\n    if (((ic->ic_htcaps & IEEE80211_HTCAP_40INTOLERANT) || (ni->ni_htcaps & IEEE80211_HTCAP_40INTOLERANT) || (ic->ic_userflags & IEEE80211_F_NOHT40))\n        && IEEE80211_IS_CHAN_2GHZ(ni->ni_chan)) {\n        ni->ni_chw = IEEE80211_CHAN_WIDTH_20;\n    } else if ((ni->ni_htcaps & IEEE80211_HTCAP_CBW20_40) && IEEE80211_IS_CHAN_HT40(ni->ni_chan) && (ic->ic_htcaps & IEEE80211_HTCAP_CBW20_40)) {\n        ht_param = ni->ni_htop0 & IEEE80211_HTOP0_SCO_MASK;\n        if ((ht_param == IEEE80211_HTOP0_SCO_SCA) ||\n            (ht_param == IEEE80211_HTOP0_SCO_SCB))\n            ni->ni_chw = IEEE80211_CHAN_WIDTH_40;\n    }\n    \n    if (ni->ni_chw == IEEE80211_CHAN_WIDTH_40) {\n        if ((ni->ni_htop0 & IEEE80211_HTOP0_SCO_MASK) == IEEE80211_HTOP0_SCO_SCA)\n            ni->ni_chan->ic_center_freq1 = ni->ni_chan->ic_freq + 10;\n        else\n            ni->ni_chan->ic_center_freq1 = ni->ni_chan->ic_freq - 10;\n    }\n}\n\nvoid\nieee80211_ht_negotiate(struct ieee80211com *ic, struct ieee80211_node *ni)\n{\n\tint i;\n\n\tni->ni_flags &= ~(IEEE80211_NODE_HT | IEEE80211_NODE_HT_SGI20 |\n\t    IEEE80211_NODE_HT_SGI40);\n    ni->ni_chw = IEEE80211_CHAN_WIDTH_20;\n    ni->ni_chan->ic_center_freq1 = ni->ni_chan->ic_freq;\n\n\t/* Check if we support HT. */\n\tif ((ic->ic_modecaps & (1 << IEEE80211_MODE_11N)) == 0)\n\t\treturn;\n\n\t/* Check if HT support has been explicitly disabled. */\n\tif ((ic->ic_flags & IEEE80211_F_HTON) == 0)\n\t\treturn;\n\n\t/*\n\t * Check if the peer supports HT.\n\t * Require at least one of the mandatory MCS.\n\t * MCS 0-7 are mandatory but some APs have particular MCS disabled.\n\t */\n\tif (!ieee80211_node_supports_ht(ni)) {\n\t\tic->ic_stats.is_ht_nego_no_mandatory_mcs++;\n\t\treturn;\n\t}\n\n\tif (ic->ic_opmode == IEEE80211_M_STA) {\n\t\t/* We must support the AP's basic MCS set. */\n\t\tfor (i = 0; i < IEEE80211_HT_NUM_MCS; i++) {\n\t\t\tif (isset(ni->ni_basic_mcs, i) &&\n\t\t\t    !isset(ic->ic_sup_mcs, i)) {\n\t\t\t\tic->ic_stats.is_ht_nego_no_basic_mcs++;\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t * Don't allow group cipher (includes WEP) or TKIP\n\t * for pairwise encryption (see 802.11-2012 11.1.6).\n\t */\n\tif (ic->ic_flags & IEEE80211_F_WEPON) {\n\t\tic->ic_stats.is_ht_nego_bad_crypto++;\n\t\treturn;\n\t}\n\tif ((ic->ic_flags & IEEE80211_F_RSNON) &&\n\t    (ni->ni_rsnciphers & IEEE80211_CIPHER_USEGROUP ||\n\t    ni->ni_rsnciphers & IEEE80211_CIPHER_TKIP)) {\n\t\tic->ic_stats.is_ht_nego_bad_crypto++;\n\t\treturn;\n\t}\n\n\tni->ni_flags |= IEEE80211_NODE_HT;\n    \n    if (ieee80211_node_supports_ht_sgi20(ni))\n        ni->ni_flags |= IEEE80211_NODE_HT_SGI20;\n    \n    ieee80211_ht_negotiate_chw(ic, ni);\n    \n    if (ni->ni_chw == IEEE80211_CHAN_WIDTH_40 && ieee80211_node_supports_ht_sgi40(ni))\n        ni->ni_flags |= IEEE80211_NODE_HT_SGI40;\n    \n    XYLog(\"%s chan_width=%s\\n\", __FUNCTION__, ieee80211_chan_width_name[ni->ni_chw]);\n}\n\nvoid\nieee80211_vht_negotiate(struct ieee80211com *ic, struct ieee80211_node *ni)\n{\n    uint8_t ext_nss_bw_supp, supp_chwidth;\n    uint16_t cf0, cf1;\n    int ccfs0, ccfs1, ccfs2;\n    int ccf0, ccf1;\n    bool support_80_80 = false;\n    bool support_160 = false;\n    \n    ni->ni_flags &= ~(IEEE80211_NODE_VHT | IEEE80211_NODE_VHT_SGI80 |\n                      IEEE80211_NODE_VHT_SGI160);\n    /* Check if we support VHT. */\n    if ((ic->ic_modecaps & (1 << IEEE80211_MODE_11AC)) == 0)\n        return;\n\n    if (ic->ic_userflags & IEEE80211_F_NOVHT)\n        return;\n\n    /* Check if VHT support has been explicitly disabled. */\n    if ((ic->ic_flags & IEEE80211_F_VHTON) == 0)\n        return;\n    \n    if (!IEEE80211_IS_CHAN_5GHZ(ni->ni_chan))\n        return;\n    \n    if (!ieee80211_node_supports_vht(ni)) {\n        ic->ic_stats.is_vht_nego_no_mandatory_mcs++;\n        return;\n    }\n    \n    /*\n     * Don't allow group cipher (includes WEP) or TKIP\n     * for pairwise encryption (see 802.11-2012 11.1.6).\n     */\n    if (ic->ic_flags & IEEE80211_F_WEPON) {\n        ic->ic_stats.is_vht_nego_bad_crypto++;\n        return;\n    }\n    if ((ic->ic_flags & IEEE80211_F_RSNON) &&\n        (ni->ni_rsnciphers & IEEE80211_CIPHER_USEGROUP ||\n        ni->ni_rsnciphers & IEEE80211_CIPHER_TKIP)) {\n        ic->ic_stats.is_vht_nego_bad_crypto++;\n        return;\n    }\n    \n    support_160 = (ni->ni_vhtcaps & (IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_MASK |\n                  IEEE80211_VHTCAP_EXT_NSS_BW_MASK));\n    support_80_80 = ((ni->ni_vhtcaps &\n             IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_160_80P80MHZ) ||\n            (ni->ni_vhtcaps & IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_160MHZ &&\n             ni->ni_vhtcaps & IEEE80211_VHTCAP_EXT_NSS_BW_MASK) ||\n            ((ni->ni_vhtcaps & IEEE80211_VHTCAP_EXT_NSS_BW_MASK) >>\n                    IEEE80211_VHTCAP_EXT_NSS_BW_SHIFT > 1));\n    \n    ext_nss_bw_supp = u32_get_bits(ni->ni_vhtcaps,\n                      IEEE80211_VHTCAP_EXT_NSS_BW_MASK);\n    supp_chwidth = u32_get_bits(ni->ni_vhtcaps,\n                       IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_MASK);\n    \n    ccfs0 = ni->ni_vht_chan1;\n    ccfs1 = ni->ni_vht_chan2;\n    ccfs2 = (le16toh(ni->ni_htop1) &\n                IEEE80211_HT_OP_MODE_CCFS2_MASK)\n            >> IEEE80211_HT_OP_MODE_CCFS2_SHIFT;\n    \n    ccf0 = ccfs0;\n    \n    if ((ic->ic_caps & IEEE80211_C_SUPPORTS_VHT_EXT_NSS_BW) == 0)\n        ext_nss_bw_supp = 0;\n    \n    /*\n     * Cf. IEEE 802.11 Table 9-250\n     *\n     * We really just consider that because it's inefficient to connect\n     * at a higher bandwidth than we'll actually be able to use.\n     */\n    switch ((supp_chwidth << 4) | ext_nss_bw_supp) {\n    default:\n    case 0x00:\n        ccf1 = 0;\n        support_160 = false;\n        support_80_80 = false;\n        break;\n    case 0x01:\n        support_80_80 = false;\n    case 0x02:\n    case 0x03:\n        ccf1 = ccfs2;\n        break;\n    case 0x10:\n        ccf1 = ccfs1;\n        break;\n    case 0x11:\n    case 0x12:\n        if (!ccfs1)\n            ccf1 = ccfs2;\n        else\n            ccf1 = ccfs1;\n        break;\n    case 0x13:\n    case 0x20:\n    case 0x23:\n        ccf1 = ccfs1;\n        break;\n    }\n    \n    cf0 = ieee80211_ieee2mhz(ccf0, ni->ni_chan->ic_flags);\n    cf1 = ieee80211_ieee2mhz(ccf1, ni->ni_chan->ic_flags);\n    \n    switch (ni->ni_vht_chanwidth) {\n        case IEEE80211_VHT_CHANWIDTH_80P80MHZ:\n            ni->ni_chw = IEEE80211_CHAN_WIDTH_80P80;\n            ni->ni_chan->ic_center_freq1 = cf0;\n            ni->ni_chan->ic_center_freq2 = cf1;\n            break;\n        case IEEE80211_VHT_CHANWIDTH_160MHZ:\n            ni->ni_chw = IEEE80211_CHAN_WIDTH_160;\n            ni->ni_chan->ic_center_freq1 = cf0;\n            break;\n        case IEEE80211_VHT_CHANWIDTH_80MHZ:\n            ni->ni_chw = IEEE80211_CHAN_WIDTH_80;\n            ni->ni_chan->ic_center_freq1 = cf0;\n            /* If needed, adjust based on the newer interop workaround. */\n            if (ccf1) {\n                unsigned int diff = abs(ccf1 - ccf0);\n                if ((diff == 8) && support_160) {\n                    ni->ni_chw = IEEE80211_CHAN_WIDTH_160;\n                    ni->ni_chan->ic_center_freq1 = cf1;\n                } else if ((diff > 8) && support_80_80) {\n                    ni->ni_chw = IEEE80211_CHAN_WIDTH_80P80;\n                    ni->ni_chan->ic_center_freq2 = cf1;\n                }\n            }\n            break;\n        case IEEE80211_VHT_CHANWIDTH_USE_HT:\n            /* Use HT negotiate information */\n            break;\n            \n        default:\n            return;\n    }\n    \n    ni->ni_flags |= IEEE80211_NODE_VHT;\n    \n    if (ieee80211_node_supports_vht_sgi80(ni))\n        ni->ni_flags |= IEEE80211_NODE_VHT_SGI80;\n    if (ieee80211_node_supports_vht_sgi160(ni))\n        ni->ni_flags |= IEEE80211_NODE_VHT_SGI160;\n    \n    XYLog(\"%s chan_width=%s support_160=%d support_80_80=%d\\n\", __FUNCTION__, ieee80211_chan_width_name[ni->ni_chw], support_160, support_80_80);\n}\n\nvoid\nieee80211_he_negotiate(struct ieee80211com *ic, struct ieee80211_node *ni)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    uint8_t ext_nss_bw_supp, supp_chwidth;\n    uint16_t cf0, cf1;\n    int ccfs0, ccfs1, ccfs2;\n    int ccf0, ccf1;\n    bool support_80_80 = false;\n    bool support_160 = false;\n    struct ieee80211_vht_operation *he_oper_vht = (struct ieee80211_vht_operation *)ni->ni_he_optional;\n    \n    ni->ni_flags &= ~IEEE80211_NODE_HE;\n    \n    /* Check if we support HE. */\n    if ((ic->ic_modecaps & (1 << IEEE80211_MODE_11AX)) == 0)\n        return;\n\n    /* Check if HE support has been explicitly disabled. */\n    if ((ic->ic_flags & IEEE80211_F_HEON) == 0)\n        return;\n    \n    ni->ni_flags |= IEEE80211_NODE_HE;\n    \n    if (!(htole32(ni->ni_he_oper_params) & IEEE80211_HE_OPERATION_VHT_OPER_INFO))\n        return;\n    \n    support_160 = (ni->ni_vhtcaps & (IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_MASK |\n                  IEEE80211_VHTCAP_EXT_NSS_BW_MASK));\n    support_80_80 = ((ni->ni_vhtcaps &\n             IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_160_80P80MHZ) ||\n            (ni->ni_vhtcaps & IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_160MHZ &&\n             ni->ni_vhtcaps & IEEE80211_VHTCAP_EXT_NSS_BW_MASK) ||\n            ((ni->ni_vhtcaps & IEEE80211_VHTCAP_EXT_NSS_BW_MASK) >>\n                    IEEE80211_VHTCAP_EXT_NSS_BW_SHIFT > 1));\n    \n    ext_nss_bw_supp = u32_get_bits(ni->ni_vhtcaps,\n                      IEEE80211_VHTCAP_EXT_NSS_BW_MASK);\n    supp_chwidth = u32_get_bits(ni->ni_vhtcaps,\n                       IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_MASK);\n    \n    ccfs0 = he_oper_vht->center_freq_seg0_idx;\n    ccfs1 = he_oper_vht->center_freq_seg1_idx;\n    ccfs2 = (le16toh(ni->ni_htop1) &\n                IEEE80211_HT_OP_MODE_CCFS2_MASK)\n            >> IEEE80211_HT_OP_MODE_CCFS2_SHIFT;\n    \n    ccf0 = ccfs0;\n    \n    if ((ic->ic_caps & IEEE80211_C_SUPPORTS_VHT_EXT_NSS_BW) == 0)\n        ext_nss_bw_supp = 0;\n    \n    /*\n     * Cf. IEEE 802.11 Table 9-250\n     *\n     * We really just consider that because it's inefficient to connect\n     * at a higher bandwidth than we'll actually be able to use.\n     */\n    switch ((supp_chwidth << 4) | ext_nss_bw_supp) {\n    default:\n    case 0x00:\n        ccf1 = 0;\n        support_160 = false;\n        support_80_80 = false;\n        break;\n    case 0x01:\n        support_80_80 = false;\n    case 0x02:\n    case 0x03:\n        ccf1 = ccfs2;\n        break;\n    case 0x10:\n        ccf1 = ccfs1;\n        break;\n    case 0x11:\n    case 0x12:\n        if (!ccfs1)\n            ccf1 = ccfs2;\n        else\n            ccf1 = ccfs1;\n        break;\n    case 0x13:\n    case 0x20:\n    case 0x23:\n        ccf1 = ccfs1;\n        break;\n    }\n    \n    cf0 = ieee80211_ieee2mhz(ccf0, ni->ni_chan->ic_flags);\n    cf1 = ieee80211_ieee2mhz(ccf1, ni->ni_chan->ic_flags);\n    \n    switch (he_oper_vht->chan_width) {\n        case IEEE80211_VHT_CHANWIDTH_80P80MHZ:\n            ni->ni_chw = IEEE80211_CHAN_WIDTH_80P80;\n            ni->ni_chan->ic_center_freq1 = cf0;\n            ni->ni_chan->ic_center_freq2 = cf1;\n            break;\n        case IEEE80211_VHT_CHANWIDTH_160MHZ:\n            ni->ni_chw = IEEE80211_CHAN_WIDTH_160;\n            ni->ni_chan->ic_center_freq1 = cf0;\n            break;\n        case IEEE80211_VHT_CHANWIDTH_80MHZ:\n            ni->ni_chw = IEEE80211_CHAN_WIDTH_80;\n            ni->ni_chan->ic_center_freq1 = cf0;\n            /* If needed, adjust based on the newer interop workaround. */\n            if (ccf1) {\n                unsigned int diff = abs(ccf1 - ccf0);\n                if ((diff == 8) && support_160) {\n                    ni->ni_chw = IEEE80211_CHAN_WIDTH_160;\n                    ni->ni_chan->ic_center_freq1 = cf1;\n                } else if ((diff > 8) && support_80_80) {\n                    ni->ni_chw = IEEE80211_CHAN_WIDTH_80P80;\n                    ni->ni_chan->ic_center_freq2 = cf1;\n                }\n            }\n            break;\n        case IEEE80211_VHT_CHANWIDTH_USE_HT:\n            /* Use HT negotiate information */\n            break;\n            \n        default:\n            return;\n    }\n    \n    XYLog(\"%s chan_width=%s\\n\", __FUNCTION__, ieee80211_chan_width_name[ni->ni_chw]);\n}\n\nvoid\nieee80211_sta_set_rx_nss(struct ieee80211com *ic, struct ieee80211_node *ni)\n{\n    uint8_t ht_rx_nss = 0, vht_rx_nss = 0, he_rx_nss = 0, rx_nss;\n    bool support_160;\n\n    if (ni->ni_flags & IEEE80211_NODE_HE) {\n        int i;\n        uint8_t rx_mcs_80 = 0, rx_mcs_160 = 0;\n        uint16_t mcs_160_map =\n            le16toh(ni->ni_he_mcs_nss_supp.rx_mcs_160);\n        uint16_t mcs_80_map = le16toh(ni->ni_he_mcs_nss_supp.rx_mcs_80);\n\n        for (i = 7; i >= 0; i--) {\n            uint8_t mcs_160 = (mcs_160_map >> (2 * i)) & 3;\n\n            if (mcs_160 != IEEE80211_VHT_MCS_NOT_SUPPORTED) {\n                rx_mcs_160 = i + 1;\n                break;\n            }\n        }\n        for (i = 7; i >= 0; i--) {\n            uint8_t mcs_80 = (mcs_80_map >> (2 * i)) & 3;\n\n            if (mcs_80 != IEEE80211_VHT_MCS_NOT_SUPPORTED) {\n                rx_mcs_80 = i + 1;\n                break;\n            }\n        }\n\n        support_160 = ni->ni_he_cap_elem.phy_cap_info[0] &\n                  IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G;\n\n        if (support_160)\n            he_rx_nss = min(rx_mcs_80, rx_mcs_160);\n        else\n            he_rx_nss = rx_mcs_80;\n    }\n\n    if (ni->ni_flags & IEEE80211_NODE_HT) {\n        if (ni->ni_rxmcs[0])\n            ht_rx_nss++;\n        if (ni->ni_rxmcs[1])\n            ht_rx_nss++;\n        if (ni->ni_rxmcs[2])\n            ht_rx_nss++;\n        if (ni->ni_rxmcs[3])\n            ht_rx_nss++;\n        /* FIXME: consider rx_highest? */\n    }\n\n    if (ni->ni_flags & IEEE80211_NODE_VHT) {\n        int i;\n        uint16_t rx_mcs_map;\n\n        rx_mcs_map = le16toh(ni->ni_vht_mcsinfo.rx_mcs_map);\n\n        for (i = 7; i >= 0; i--) {\n            uint8_t mcs = (rx_mcs_map >> (2 * i)) & 3;\n\n            if (mcs != IEEE80211_VHT_MCS_NOT_SUPPORTED) {\n                vht_rx_nss = i + 1;\n                break;\n            }\n        }\n        /* FIXME: consider rx_highest? */\n    }\n\n    rx_nss = max(vht_rx_nss, ht_rx_nss);\n    rx_nss = max(he_rx_nss, rx_nss);\n    ni->ni_rx_nss = max_t(u8, 1, rx_nss);\n    XYLog(\"%s ni_rx_nss: %d\\n\", __FUNCTION__, ni->ni_rx_nss);\n}\n\nvoid\nieee80211_tx_ba_timeout(void *arg)\n{\n\tstruct ieee80211_tx_ba *ba = (struct ieee80211_tx_ba *)arg;\n\tstruct ieee80211_node *ni = ba->ba_ni;\n\tstruct ieee80211com *ic = ni->ni_ic;\n\tu_int8_t tid;\n\tint s;\n\n\ts = splnet();\n\ttid = ((caddr_t)ba - (caddr_t)ni->ni_tx_ba) / sizeof(*ba);\n\tif (ba->ba_state == IEEE80211_BA_REQUESTED) {\n\t\t/* MLME-ADDBA.confirm(TIMEOUT) */\n\t\tba->ba_state = IEEE80211_BA_INIT;\n\t\tif (ni->ni_addba_req_intval[tid] <\n\t\t    IEEE80211_ADDBA_REQ_INTVAL_MAX)\n\t\t\tni->ni_addba_req_intval[tid]++;\n\t\t/*\n\t\t * In case the peer believes there is an existing\n\t\t * block ack agreement with us, try to delete it.\n\t\t */\n\t\tIEEE80211_SEND_ACTION(ic, ni, IEEE80211_CATEG_BA,\n\t\t    IEEE80211_ACTION_DELBA,\n\t\t    IEEE80211_REASON_SETUP_REQUIRED << 16 | 1 << 8 | tid);\n\t} else if (ba->ba_state == IEEE80211_BA_AGREED) {\n\t\t/* Block Ack inactivity timeout */\n\t\tic->ic_stats.is_ht_tx_ba_timeout++;\n\t\tieee80211_delba_request(ic, ni, IEEE80211_REASON_TIMEOUT,\n\t\t    1, tid);\n\t}\n\tsplx(s);\n}\n\nvoid\nieee80211_rx_ba_timeout(void *arg)\n{\n\tstruct ieee80211_rx_ba *ba = (struct ieee80211_rx_ba *)arg;\n\tstruct ieee80211_node *ni = ba->ba_ni;\n\tstruct ieee80211com *ic = ni->ni_ic;\n\tu_int8_t tid;\n\tint s;\n\n\tic->ic_stats.is_ht_rx_ba_timeout++;\n\n\ts = splnet();\n\n\t/* Block Ack inactivity timeout */\n\ttid = ((caddr_t)ba - (caddr_t)ni->ni_rx_ba) / sizeof(*ba);\n\tieee80211_delba_request(ic, ni, IEEE80211_REASON_TIMEOUT, 0, tid);\n\n\tsplx(s);\n}\n\n/*\n * Request initiation of Block Ack with the specified peer.\n */\nint\nieee80211_addba_request(struct ieee80211com *ic, struct ieee80211_node *ni,\n    u_int16_t ssn, u_int8_t tid)\n{\n\tstruct ieee80211_tx_ba *ba = &ni->ni_tx_ba[tid];\n\n\tif (ba->ba_state != IEEE80211_BA_INIT)\n\t\treturn EBUSY;\n\n\t/* MLME-ADDBA.request */\n\n\t/* setup Block Ack */\n\tba->ba_ni = ni;\n\tba->ba_state = IEEE80211_BA_REQUESTED;\n\tba->ba_token = ic->ic_dialog_token++;\n\tba->ba_timeout_val = 0;\n\ttimeout_set(&ba->ba_to, ieee80211_tx_ba_timeout, ba);\n\tba->ba_winsize = IEEE80211_BA_MAX_WINSZ;\n\tba->ba_winstart = ssn;\n\tba->ba_winend = (ba->ba_winstart + ba->ba_winsize - 1) & 0xfff;\n\tba->ba_params =\n\t    (ba->ba_winsize << IEEE80211_ADDBA_BUFSZ_SHIFT) |\n\t    (tid << IEEE80211_ADDBA_TID_SHIFT);\n    if (ic->ic_caps & IEEE80211_C_AMSDU_IN_AMPDU) {\n        ba->ba_params |= IEEE80211_ADDBA_AMSDU;\n    }\n\tif ((ic->ic_htcaps & IEEE80211_HTCAP_DELAYEDBA) == 0)\n\t\t/* immediate BA */\n\t\tba->ba_params |= IEEE80211_ADDBA_BA_POLICY;\n    \n    if ((ic->ic_caps & IEEE80211_C_TX_AMPDU_SETUP_IN_HW) &&\n        ic->ic_ampdu_tx_start != NULL) {\n        int err = ic->ic_ampdu_tx_start(ic, ni, tid);\n        if (err && err != EBUSY) {\n            /* driver failed to setup, rollback */\n            ieee80211_addba_resp_refuse(ic, ni, tid,\n                                        IEEE80211_STATUS_UNSPECIFIED);\n        } else if (err == 0)\n            ieee80211_addba_resp_accept(ic, ni, tid);\n        return err; /* The device will send an ADDBA frame. */\n    }\n\n    timeout_add_sec(&ba->ba_to, 1);    /* dot11ADDBAResponseTimeout */\n    IEEE80211_SEND_ACTION(ic, ni, IEEE80211_CATEG_BA,\n                          IEEE80211_ACTION_ADDBA_REQ, tid);\n\treturn 0;\n}\n\n/*\n * Request the deletion of Block Ack with a peer and notify driver.\n */\nvoid\nieee80211_delba_request(struct ieee80211com *ic, struct ieee80211_node *ni,\n    u_int16_t reason, u_int8_t dir, u_int8_t tid)\n{\n\t/* MLME-DELBA.request */\n\n\tif (reason) {\n\t\t/* transmit a DELBA frame */\n\t\tIEEE80211_SEND_ACTION(ic, ni, IEEE80211_CATEG_BA,\n\t\t    IEEE80211_ACTION_DELBA, reason << 16 | dir << 8 | tid);\n\t}\n\tif (dir) {\n\t\t/* MLME-DELBA.confirm(Originator) */\n\t\tstruct ieee80211_tx_ba *ba = &ni->ni_tx_ba[tid];\n\n\t\tif (ic->ic_ampdu_tx_stop != NULL)\n\t\t\tic->ic_ampdu_tx_stop(ic, ni, tid);\n\n\t\tba->ba_state = IEEE80211_BA_INIT;\n\t\t/* stop Block Ack inactivity timer */\n\t\ttimeout_del(&ba->ba_to);\n\t} else {\n\t\t/* MLME-DELBA.confirm(Recipient) */\n\t\tstruct ieee80211_rx_ba *ba = &ni->ni_rx_ba[tid];\n\t\tint i;\n\n\t\tif (ic->ic_ampdu_rx_stop != NULL)\n\t\t\tic->ic_ampdu_rx_stop(ic, ni, tid);\n\n\t\tba->ba_state = IEEE80211_BA_INIT;\n\t\t/* stop Block Ack inactivity timer */\n\t\ttimeout_del(&ba->ba_to);\n\t\ttimeout_del(&ba->ba_gap_to);\n\n\t\tif (ba->ba_buf != NULL) {\n\t\t\t/* free all MSDUs stored in reordering buffer */\n\t\t\tfor (i = 0; i < IEEE80211_BA_MAX_WINSZ; i++)\n\t\t\t\tmbuf_freem(ba->ba_buf[i].m);\n\t\t\t/* free reordering buffer */\n\t\t\tfree(ba->ba_buf);\n\t\t\tba->ba_buf = NULL;\n\t\t}\n\t}\n}\n\n#ifndef IEEE80211_STA_ONLY\nvoid\nieee80211_auth_open_confirm(struct ieee80211com *ic,\n    struct ieee80211_node *ni, uint16_t seq)\n{\n\tstruct _ifnet *ifp = &ic->ic_if;\n\n\tIEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_AUTH, seq + 1);\n\tif (ifp->if_flags & IFF_DEBUG)\n\t\tXYLog(\"%s: station %s %s authenticated (open)\\n\",\n\t\t    ifp->if_xname,\n\t\t    ether_sprintf((u_int8_t *)ni->ni_macaddr),\n\t\t    ni->ni_state != IEEE80211_STA_CACHE ?\n\t\t    \"newly\" : \"already\");\n\tieee80211_node_newstate(ni, IEEE80211_STA_AUTH);\n}\n#endif\n\nvoid\nieee80211_try_another_bss(struct ieee80211com *ic)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n\tstruct ieee80211_node *curbs, *selbs;\n\tstruct _ifnet *ifp = &ic->ic_if;\n\n\t/* Don't select our current AP again. */\n\tcurbs = ieee80211_find_node(ic, ic->ic_bss->ni_macaddr);\n\tif (curbs) {\n\t\tcurbs->ni_fails++;\n\t\tieee80211_node_newstate(curbs, IEEE80211_STA_CACHE);\n\t}\n\n\t/* Try a different AP from the same ESS if available. */\n\tif (ic->ic_caps & IEEE80211_C_SCANALLBAND) {\n\t\t/*\n\t\t * Make sure we will consider APs on all bands during\n\t\t * access point selection in ieee80211_node_choose_bss().\n\t\t * During multi-band scans, our previous AP may be trying\n\t\t * to steer us onto another band by denying authentication.\n\t\t */\n\t\tieee80211_setmode(ic, IEEE80211_MODE_AUTO);\n\t}\n\tselbs = ieee80211_node_choose_bss(ic, 0, NULL);\n\tif (selbs == NULL)\n\t\treturn;\n\n\t/* Should not happen but seriously, don't try the same AP again. */\n\tif (memcmp(selbs->ni_macaddr, ic->ic_bss->ni_macaddr,\n\t    IEEE80211_NWID_LEN) == 0)\n\t\treturn;\n\n\tif (ifp->if_flags & IFF_DEBUG)\n\t\tXYLog(\"%s: trying AP %s on channel %d instead\\n\",\n\t\t    ifp->if_xname, ether_sprintf(selbs->ni_macaddr),\n\t\t    ieee80211_chan2ieee(ic, selbs->ni_chan));\n\n\t/* Triggers an AUTH->AUTH transition, avoiding another SCAN. */\n\tieee80211_node_join_bss(ic, selbs);\n}\n\nvoid\nieee80211_auth_open(struct ieee80211com *ic, const struct ieee80211_frame *wh,\n    struct ieee80211_node *ni, struct ieee80211_rxinfo *rxi, u_int16_t seq,\n    u_int16_t status)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n\tstruct _ifnet *ifp = &ic->ic_if;\n\tswitch (ic->ic_opmode) {\n#ifndef IEEE80211_STA_ONLY\n\tcase IEEE80211_M_IBSS:\n\t\tif (ic->ic_state != IEEE80211_S_RUN ||\n\t\t    seq != IEEE80211_AUTH_OPEN_REQUEST) {\n\t\t\tDPRINTF((\"discard auth from %s; state %u, seq %u\\n\",\n\t\t\t    ether_sprintf((u_int8_t *)wh->i_addr2),\n\t\t\t    ic->ic_state, seq));\n\t\t\tic->ic_stats.is_rx_bad_auth++;\n\t\t\treturn;\n\t\t}\n\t\tieee80211_new_state(ic, IEEE80211_S_AUTH,\n\t\t    wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);\n\n\t\t/* In IBSS mode no (re)association frames are sent. */\n\t\tif (ic->ic_flags & IEEE80211_F_RSNON)\n\t\t\tni->ni_rsn_supp_state = RSNA_SUPP_PTKSTART;\n\t\tbreak;\n\n\tcase IEEE80211_M_AHDEMO:\n\t\t/* should not come here */\n\t\tbreak;\n\n\tcase IEEE80211_M_HOSTAP:\n\t\tif (ic->ic_state != IEEE80211_S_RUN ||\n\t\t    seq != IEEE80211_AUTH_OPEN_REQUEST) {\n\t\t\tDPRINTF((\"discard auth from %s; state %u, seq %u\\n\",\n\t\t\t    ether_sprintf((u_int8_t *)wh->i_addr2),\n\t\t\t    ic->ic_state, seq));\n\t\t\tic->ic_stats.is_rx_bad_auth++;\n\t\t\treturn;\n\t\t}\n\t\tif (ni == ic->ic_bss) {\n\t\t\tni = ieee80211_find_node(ic, wh->i_addr2);\n\t\t\tif (ni == NULL)\n\t\t\t\tni = ieee80211_alloc_node(ic, wh->i_addr2);\n\t\t\tif (ni == NULL) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tIEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_bss->ni_bssid);\n\t\t\tni->ni_rssi = rxi->rxi_rssi;\n\t\t\tni->ni_rstamp = rxi->rxi_tstamp;\n\t\t\tni->ni_chan = ic->ic_bss->ni_chan;\n\t\t}\n\n\t\t/*\n\t\t * Drivers may want to set up state before confirming.\n\t\t * In which case this returns EBUSY and the driver will\n\t\t * later call ieee80211_auth_open_confirm() by itself.\n\t\t */\n\t\tif (ic->ic_newauth && ic->ic_newauth(ic, ni,\n\t\t    ni->ni_state != IEEE80211_STA_CACHE, seq) != 0)\n\t\t\tbreak;\n\t\tieee80211_auth_open_confirm(ic, ni, seq);\n\t\tbreak;\n#endif\t/* IEEE80211_STA_ONLY */\n\n\tcase IEEE80211_M_STA:\n\t\tif (ic->ic_state != IEEE80211_S_AUTH ||\n\t\t    seq != IEEE80211_AUTH_OPEN_RESPONSE) {\n\t\t\tic->ic_stats.is_rx_bad_auth++;\n\t\t\tDPRINTF((\"discard auth from %s; state %u, seq %u\\n\",\n\t\t\t    ether_sprintf((u_int8_t *)wh->i_addr2),\n\t\t\t    ic->ic_state, seq));\n\t\t\treturn;\n\t\t}\n\t\tif (ic->ic_flags & IEEE80211_F_RSNON) {\n\t\t\t/* XXX not here! */\n\t\t\tic->ic_bss->ni_flags &= ~IEEE80211_NODE_TXRXPROT;\n\t\t\tic->ic_bss->ni_port_valid = 0;\n\t\t\tic->ic_bss->ni_replaycnt_ok = 0;\n\t\t\t(*ic->ic_delete_key)(ic, ic->ic_bss,\n\t\t\t    &ic->ic_bss->ni_pairwise_key);\n\t\t}\n\t\tif (status != 0) {\n\t\t\tif (ifp->if_flags & IFF_DEBUG)\n\t\t\t\tXYLog(\"%s: open authentication failed \"\n\t\t\t\t    \"(status %d) for %s\\n\", ifp->if_xname,\n\t\t\t\t    status,\n\t\t\t\t    ether_sprintf((u_int8_t *)wh->i_addr3));\n\t\t\tif (ni != ic->ic_bss)\n\t\t\t\tni->ni_fails++;\n\t\t\telse\n\t\t\t\tieee80211_try_another_bss(ic);\n\t\t\tic->ic_stats.is_rx_auth_fail++;\n\t\t\treturn;\n\t\t}\n\t\tieee80211_new_state(ic, IEEE80211_S_ASSOC,\n\t\t    wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n}\n\nvoid\nieee80211_set_beacon_miss_threshold(struct ieee80211com *ic)\n{\n\tstruct _ifnet *ifp = &ic->ic_if;\n\n\t/*\n\t * Scale the missed beacon counter threshold to the AP's actual\n     * beacon interval.\n\t */\n\tint btimeout = MIN(IEEE80211_BEACON_MISS_THRES * ic->ic_bss->ni_intval,\n         IEEE80211_BEACON_MISS_THRES * (IEEE80211_DUR_TU / 10));\n    /* Ensure that at least one beacon may be missed. */\n\tbtimeout = MAX(btimeout, 2 * ic->ic_bss->ni_intval);\n\tif (ic->ic_bss->ni_intval > 0) /* don't crash if interval is bogus */\n\t\tic->ic_bmissthres = btimeout / ic->ic_bss->ni_intval;\n\n\tif (ifp->if_flags & IFF_DEBUG)\n\t\tXYLog(\"%s: missed beacon threshold set to %d beacons, \"\n\t\t    \"beacon interval is %u TU\\n\", ifp->if_xname,\n\t\t    ic->ic_bmissthres, ic->ic_bss->ni_intval);\n}\n\n/* Tell our peer, and the driver, to stop A-MPDU Tx for all TIDs. */\nvoid\nieee80211_stop_ampdu_tx(struct ieee80211com *ic, struct ieee80211_node *ni,\n    int mgt)\n{\n\tint tid;\n\n\tfor (tid = 0; tid < nitems(ni->ni_tx_ba); tid++) {\n\t\tstruct ieee80211_tx_ba *ba = &ni->ni_tx_ba[tid];\n\t\tif (ba->ba_state != IEEE80211_BA_AGREED)\n\t\t\tcontinue;\n        ieee80211_delba_request(ic, ni,\n                                ((ic->ic_caps & IEEE80211_C_TX_AMPDU_SETUP_IN_HW) || mgt == -1) ? 0 : IEEE80211_REASON_AUTH_LEAVE, 1, tid);\n\t}\n}\n\nvoid\nieee80211_check_wpa_supplicant_failure(struct ieee80211com *ic,\n    struct ieee80211_node *ni)\n{\n\tstruct ieee80211_node *ni2;\n\n\tif (ic->ic_opmode != IEEE80211_M_STA\n#ifndef IEEE80211_STA_ONLY\n\t    && ic->ic_opmode != IEEE80211_M_IBSS\n#endif\n\t    )\n\t\treturn;\n\n\tif (ni->ni_rsn_supp_state != RSNA_SUPP_PTKNEGOTIATING)\n\t\treturn;\n\n\tni->ni_assoc_fail |= IEEE80211_NODE_ASSOCFAIL_WPA_KEY;\n\n\tif (ni != ic->ic_bss)\n\t\treturn;\n\n\t/* Also update the copy of our AP's node in the node cache. */\n\tni2 = ieee80211_find_node(ic, ic->ic_bss->ni_macaddr);\n\tif (ni2)\n\t\tni2->ni_assoc_fail |= ic->ic_bss->ni_assoc_fail;\n}\n\nint\nieee80211_newstate(struct ieee80211com *ic, enum ieee80211_state nstate,\n    int mgt)\n{\n\tstruct _ifnet *ifp = &ic->ic_if;\n\tstruct ieee80211_node *ni;\n\tenum ieee80211_state ostate;\n\tu_int rate;\n#ifndef IEEE80211_STA_ONLY\n\tint s;\n#endif\n\n\tostate = ic->ic_state;\n\tif (ifp->if_flags & IFF_DEBUG)\n\t\tXYLog(\"%s: %s -> %s\\n\", ifp->if_xname,\n\t\t    ieee80211_state_name[ostate], ieee80211_state_name[nstate]);\n\tic->ic_state = nstate;\t\t\t/* state transition */\n\tni = ic->ic_bss;\t\t\t/* NB: no reference held */\n\tieee80211_set_link_state(ic, LINK_STATE_DOWN);\n\tic->ic_xflags &= ~IEEE80211_F_TX_MGMT_ONLY;\n\tswitch (nstate) {\n\tcase IEEE80211_S_INIT:\n\t\t/*\n\t\t * If mgt = -1, driver is already partway down, so do\n\t\t * not send management frames.\n\t\t */\n\t\tswitch (ostate) {\n\t\tcase IEEE80211_S_INIT:\n\t\t\tbreak;\n\t\tcase IEEE80211_S_RUN:\n\t\t\tif (mgt == -1)\n\t\t\t\tgoto justcleanup;\n\t\t\tieee80211_stop_ampdu_tx(ic, ni, mgt);\n\t\t\tieee80211_ba_del(ni);\n\t\t\tswitch (ic->ic_opmode) {\n\t\t\tcase IEEE80211_M_STA:\n\t\t\t\tIEEE80211_SEND_MGMT(ic, ni,\n\t\t\t\t    IEEE80211_FC0_SUBTYPE_DISASSOC,\n\t\t\t\t    IEEE80211_REASON_ASSOC_LEAVE);\n\t\t\t\tbreak;\n#ifndef IEEE80211_STA_ONLY\n\t\t\tcase IEEE80211_M_HOSTAP:\n\t\t\t\ts = splnet();\n\t\t\t\tRB_FOREACH(ni, ieee80211_tree, &ic->ic_tree) {\n\t\t\t\t\tif (ni->ni_state != IEEE80211_STA_ASSOC)\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\tIEEE80211_SEND_MGMT(ic, ni,\n\t\t\t\t\t    IEEE80211_FC0_SUBTYPE_DISASSOC,\n\t\t\t\t\t    IEEE80211_REASON_ASSOC_LEAVE);\n\t\t\t\t}\n\t\t\t\tsplx(s);\n\t\t\t\tbreak;\n#endif\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t/* FALLTHROUGH */\n\t\tcase IEEE80211_S_ASSOC:\n\t\t\tif (mgt == -1)\n\t\t\t\tgoto justcleanup;\n\t\t\tswitch (ic->ic_opmode) {\n\t\t\tcase IEEE80211_M_STA:\n\t\t\t\tIEEE80211_SEND_MGMT(ic, ni,\n\t\t\t\t    IEEE80211_FC0_SUBTYPE_DEAUTH,\n\t\t\t\t    IEEE80211_REASON_AUTH_LEAVE);\n\t\t\t\tbreak;\n#ifndef IEEE80211_STA_ONLY\n\t\t\tcase IEEE80211_M_HOSTAP:\n\t\t\t\ts = splnet();\n\t\t\t\tRB_FOREACH(ni, ieee80211_tree, &ic->ic_tree) {\n\t\t\t\t\tIEEE80211_SEND_MGMT(ic, ni,\n\t\t\t\t\t    IEEE80211_FC0_SUBTYPE_DEAUTH,\n\t\t\t\t\t    IEEE80211_REASON_AUTH_LEAVE);\n\t\t\t\t}\n\t\t\t\tsplx(s);\n\t\t\t\tbreak;\n#endif\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t/* FALLTHROUGH */\n\t\tcase IEEE80211_S_AUTH:\n\t\tcase IEEE80211_S_SCAN:\njustcleanup:\n#ifndef IEEE80211_STA_ONLY\n\t\t\tif (ic->ic_opmode == IEEE80211_M_HOSTAP)\n\t\t\t\ttimeout_del(&ic->ic_rsn_timeout);\n#endif\n\t\t\tieee80211_ba_del(ni);\n\t\t\ttimeout_del(&ic->ic_bgscan_timeout);\n\t\t\tic->ic_bgscan_fail = 0;\n\t\t\tic->ic_mgt_timer = 0;\n\t\t\tmq_purge(&ic->ic_mgtq);\n\t\t\tmq_purge(&ic->ic_pwrsaveq);\n\t\t\tieee80211_free_allnodes(ic, 1);\n\t\t\tbreak;\n\t\t}\n\t\tni->ni_rsn_supp_state = RSNA_SUPP_INITIALIZE;\n\t\tni->ni_assoc_fail = 0;\n\t\tif (ic->ic_flags & IEEE80211_F_RSNON)\n\t\t\tieee80211_crypto_clear_groupkeys(ic);\n\t\tbreak;\n\tcase IEEE80211_S_SCAN:\n\t\tic->ic_flags &= ~IEEE80211_F_SIBSS;\n\t\t/* initialize bss for probe request */\n\t\tIEEE80211_ADDR_COPY(ni->ni_macaddr, etherbroadcastaddr);\n\t\tIEEE80211_ADDR_COPY(ni->ni_bssid, etherbroadcastaddr);\n\t\tni->ni_rates = ic->ic_sup_rates[\n\t\t\tieee80211_chan2mode(ic, ni->ni_chan)];\n\t\tni->ni_associd = 0;\n\t\tni->ni_rstamp = 0;\n\t\tni->ni_rsn_supp_state = RSNA_SUPP_INITIALIZE;\n\t\tif (ic->ic_flags & IEEE80211_F_RSNON)\n\t\t\tieee80211_crypto_clear_groupkeys(ic);\n\t\tswitch (ostate) {\n\t\tcase IEEE80211_S_INIT:\n#ifndef IEEE80211_STA_ONLY\n\t\t\tif (ic->ic_opmode == IEEE80211_M_HOSTAP &&\n\t\t\t    ic->ic_des_chan != IEEE80211_CHAN_ANYC) {\n\t\t\t\t/*\n\t\t\t\t * AP operation and we already have a channel;\n\t\t\t\t * bypass the scan and startup immediately.\n\t\t\t\t */\n\t\t\t\tieee80211_create_ibss(ic, ic->ic_des_chan);\n\t\t\t} else\n#endif\n\t\t\t\tieee80211_begin_scan(ifp);\n\t\t\tbreak;\n\t\tcase IEEE80211_S_SCAN:\n\t\t\t/* scan next */\n\t\t\tif (ic->ic_flags & IEEE80211_F_ASCAN) {\n\t\t\t\tIEEE80211_SEND_MGMT(ic, ni,\n\t\t\t\t    IEEE80211_FC0_SUBTYPE_PROBE_REQ, 0);\n\t\t\t}\n\t\t\tbreak;\n\t\tcase IEEE80211_S_RUN:\n\t\t\t/* beacon miss */\n\t\t\tif (ifp->if_flags & IFF_DEBUG) {\n\t\t\t\t/* XXX bssid clobbered above */\n\t\t\t\tXYLog(\"%s: no recent beacons from %s;\"\n\t\t\t\t    \" rescanning\\n\", ifp->if_xname,\n\t\t\t\t    ether_sprintf(ic->ic_bss->ni_bssid));\n\t\t\t}\n\t\t\ttimeout_del(&ic->ic_bgscan_timeout);\n\t\t\tic->ic_bgscan_fail = 0;\n\t\t\tieee80211_stop_ampdu_tx(ic, ni, mgt);\n\t\t\tieee80211_free_allnodes(ic, 1);\n\t\t\t/* FALLTHROUGH */\n\t\tcase IEEE80211_S_AUTH:\n\t\tcase IEEE80211_S_ASSOC:\n\t\t\t/* timeout restart scan */\n\t\t\tni = ieee80211_find_node(ic, ic->ic_bss->ni_macaddr);\n\t\t\tif (ni != NULL)\n\t\t\t\tni->ni_fails++;\n\t\t\tieee80211_begin_scan(ifp);\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\tcase IEEE80211_S_AUTH:\n        ieee80211_clean_sta_bss_node(ic);\n\t\tif (ostate == IEEE80211_S_RUN)\n\t\t\tieee80211_check_wpa_supplicant_failure(ic, ni);\n\t\tni->ni_rsn_supp_state = RSNA_SUPP_INITIALIZE;\n\t\tif (ic->ic_flags & IEEE80211_F_RSNON)\n\t\t\tieee80211_crypto_clear_groupkeys(ic);\n\t\tswitch (ostate) {\n\t\tcase IEEE80211_S_INIT:\n\t\t\tif (ifp->if_flags & IFF_DEBUG)\n\t\t\t\tXYLog(\"%s: invalid transition %s -> %s\\n\",\n\t\t\t\t    ifp->if_xname, ieee80211_state_name[ostate],\n\t\t\t\t    ieee80211_state_name[nstate]);\n\t\t\tbreak;\n\t\tcase IEEE80211_S_SCAN:\n\t\t\tIEEE80211_SEND_MGMT(ic, ni,\n\t\t\t    IEEE80211_FC0_SUBTYPE_AUTH, 1);\n\t\t\tbreak;\n\t\tcase IEEE80211_S_AUTH:\n\t\tcase IEEE80211_S_ASSOC:\n\t\t\tswitch (mgt) {\n\t\t\tcase IEEE80211_FC0_SUBTYPE_AUTH:\n\t\t\t\tif (ic->ic_opmode == IEEE80211_M_STA) {\n\t\t\t\t\tIEEE80211_SEND_MGMT(ic, ni,\n\t\t\t\t\t    IEEE80211_FC0_SUBTYPE_AUTH,\n\t\t\t\t\t    IEEE80211_AUTH_OPEN_REQUEST);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase IEEE80211_FC0_SUBTYPE_DEAUTH:\n\t\t\t\t/* ignore and retry scan on timeout */\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase IEEE80211_S_RUN:\n\t\t\ttimeout_del(&ic->ic_bgscan_timeout);\n\t\t\tic->ic_bgscan_fail = 0;\n\t\t\tieee80211_stop_ampdu_tx(ic, ni, mgt);\n\t\t\tieee80211_ba_del(ni);\n\t\t\tswitch (mgt) {\n\t\t\tcase IEEE80211_FC0_SUBTYPE_AUTH:\n\t\t\t\tIEEE80211_SEND_MGMT(ic, ni,\n\t\t\t\t    IEEE80211_FC0_SUBTYPE_AUTH, 2);\n\t\t\t\tic->ic_state = ostate;\t/* stay RUN */\n\t\t\t\tbreak;\n\t\t\tcase IEEE80211_FC0_SUBTYPE_DEAUTH:\n\t\t\t\t/* try to reauth */\n\t\t\t\tIEEE80211_SEND_MGMT(ic, ni,\n\t\t\t\t    IEEE80211_FC0_SUBTYPE_AUTH, 1);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\tcase IEEE80211_S_ASSOC:\n\t\tswitch (ostate) {\n\t\tcase IEEE80211_S_INIT:\n\t\tcase IEEE80211_S_SCAN:\n\t\tcase IEEE80211_S_ASSOC:\n\t\t\tif (ifp->if_flags & IFF_DEBUG)\n\t\t\t\tXYLog(\"%s: invalid transition %s -> %s\\n\",\n\t\t\t\t    ifp->if_xname, ieee80211_state_name[ostate],\n\t\t\t\t    ieee80211_state_name[nstate]);\n\t\t\tbreak;\n\t\tcase IEEE80211_S_AUTH:\n\t\t\tIEEE80211_SEND_MGMT(ic, ni,\n\t\t\t    IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 0);\n\t\t\tbreak;\n\t\tcase IEEE80211_S_RUN:\n\t\t\tieee80211_stop_ampdu_tx(ic, ni, mgt);\n\t\t\tieee80211_ba_del(ni);\n\t\t\tIEEE80211_SEND_MGMT(ic, ni,\n\t\t\t    IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 1);\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\tcase IEEE80211_S_RUN:\n\t\tswitch (ostate) {\n\t\tcase IEEE80211_S_INIT:\n\t\t\tif (ic->ic_opmode == IEEE80211_M_MONITOR)\n\t\t\t\tbreak;\n\t\tcase IEEE80211_S_AUTH:\n\t\tcase IEEE80211_S_RUN:\n\t\t\tif (ifp->if_flags & IFF_DEBUG)\n\t\t\t\tXYLog(\"%s: invalid transition %s -> %s\\n\",\n\t\t\t\t    ifp->if_xname, ieee80211_state_name[ostate],\n\t\t\t\t    ieee80211_state_name[nstate]);\n\t\t\tbreak;\n\t\tcase IEEE80211_S_SCAN:\t\t/* adhoc/hostap mode */\n\t\tcase IEEE80211_S_ASSOC:\t\t/* infra mode */\n\t\t\tif (ni->ni_txrate >= ni->ni_rates.rs_nrates)\n\t\t\t\tpanic(\"%s: bogus xmit rate %u setup\",\n\t\t\t\t    __FUNCTION__, ni->ni_txrate);\n\t\t\tif (ifp->if_flags & IFF_DEBUG) {\n\t\t\t\tXYLog(\"%s: %s with %s ssid \",\n\t\t\t\t    ifp->if_xname,\n\t\t\t\t    ic->ic_opmode == IEEE80211_M_STA ?\n\t\t\t\t    \"associated\" : \"synchronized\",\n\t\t\t\t    ether_sprintf(ni->ni_bssid));\n\t\t\t\tieee80211_print_essid(ic->ic_bss->ni_essid,\n\t\t\t\t    ni->ni_esslen);\n\t\t\t\trate = ni->ni_rates.rs_rates[ni->ni_txrate] &\n\t\t\t\t    IEEE80211_RATE_VAL;\n\t\t\t\tXYLog(\" channel %d\",\n\t\t\t\t    ieee80211_chan2ieee(ic, ni->ni_chan));\n\t\t\t\tif (ni->ni_flags & IEEE80211_NODE_HT)\n\t\t\t\t\tXYLog(\" start MCS %u\", ni->ni_txmcs);\n\t\t\t\telse\n\t\t\t\t\tXYLog(\" start %u%sMb\",\n\t\t\t\t\t    rate / 2, (rate & 1) ? \".5\" : \"\");\n\t\t\t\tXYLog(\" %s preamble %s slot time%s%s%s%s\\n\",\n\t\t\t\t    (ic->ic_flags & IEEE80211_F_SHPREAMBLE) ?\n\t\t\t\t\t\"short\" : \"long\",\n\t\t\t\t    (ic->ic_flags & IEEE80211_F_SHSLOT) ?\n\t\t\t\t\t\"short\" : \"long\",\n\t\t\t\t    (ic->ic_flags & IEEE80211_F_USEPROT) ?\n\t\t\t\t\t\" protection enabled\" : \"\",\n\t\t\t\t    (ni->ni_flags & IEEE80211_NODE_HT) ?\n\t\t\t\t\t\" HT enabled\" : \"\",\n                    (ni->ni_flags & IEEE80211_NODE_VHT) ?\n                    \" VHT enabled\" : \"\",\n                    (ni->ni_flags & IEEE80211_NODE_HE) ?\n                    \" HE enabled\" : \"\");\n\t\t\t}\n#ifdef USE_APPLE_SUPPLICANT\n            {\n#elif (defined IO80211FAMILY_V2)\n            if (ieee80211_is_8021x_akm((enum ieee80211_akm)ni->ni_rsnakms) ||\n                !(ic->ic_flags & IEEE80211_F_RSNON)) {\n#else\n\t\t\tif (!(ic->ic_flags & IEEE80211_F_RSNON)) {\n#endif\n\t\t\t\t/*\n\t\t\t\t * NB: When RSN is enabled, we defer setting\n\t\t\t\t * the link up until the port is valid.\n\t\t\t\t */\n\t\t\t\tieee80211_set_link_state(ic, LINK_STATE_UP);\n\t\t\t\tni->ni_assoc_fail = 0;\n\t\t\t}\n            ni->ni_fails = 0;\n            ni = ieee80211_find_node(ic, ni->ni_macaddr);\n            if (ni)\n                ni->ni_fails = 0;\n\t\t\tic->ic_mgt_timer = 0;\n\t\t\tieee80211_set_beacon_miss_threshold(ic);\n\t\t\t(*ifp->if_start)(ifp);\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\t}\n\treturn 0;\n}\n\nvoid\nieee80211_set_link_state(struct ieee80211com *ic, int nstate)\n{\n\tstruct _ifnet *ifp = &ic->ic_if;\n    int link_state;\n    \n\tswitch (ic->ic_opmode) {\n#ifndef IEEE80211_STA_ONLY\n\tcase IEEE80211_M_IBSS:\n\tcase IEEE80211_M_HOSTAP:\n\t\tnstate = LINK_STATE_UNKNOWN;\n\t\tbreak;\n#endif\n\tcase IEEE80211_M_MONITOR:\n\t\tnstate = LINK_STATE_DOWN;\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n    link_state = nstate;\n    if (link_state != ifp->if_link_state) {\n        ifp->if_link_state = link_state;\n        if (link_state == LINK_STATE_UP) {\n            XYLog(\"%s LINK_STATE_IS_UP\\n\", __FUNCTION__);\n            ifp->controller->setLinkStatus(kIONetworkLinkValid | kIONetworkLinkActive, ifp->controller->getCurrentMedium());\n        } else {\n            XYLog(\"%s LINK_STATE_IS_DOWN\\n\", __FUNCTION__);\n            ifp->controller->setLinkStatus(kIONetworkLinkValid);\n        }\n    }\n//\tif (nstate != ifp->if_link_state) {\n//\t\tifp->if_link_state = nstate;\n//\t\tif (LINK_STATE_IS_UP(nstate)) {\n//\t\t\tstruct if_ieee80211_data ifie;\n//\t\t\tmemset(&ifie, 0, sizeof(ifie));\n//\t\t\tifie.ifie_nwid_len = ic->ic_bss->ni_esslen;\n//\t\t\tmemcpy(ifie.ifie_nwid, ic->ic_bss->ni_essid,\n//\t\t\t    sizeof(ifie.ifie_nwid));\n//\t\t\tmemcpy(ifie.ifie_addr, ic->ic_bss->ni_bssid,\n//\t\t\t    sizeof(ifie.ifie_addr));\n//\t\t\tifie.ifie_channel = ieee80211_chan2ieee(ic,\n//\t\t\t    ic->ic_bss->ni_chan);\n//\t\t\tifie.ifie_flags = ic->ic_flags;\n//\t\t\tifie.ifie_xflags = ic->ic_xflags;\n//\t\t\trtm_80211info(&ic->ic_if, &ifie);\n//\t\t}\n//\t\tif_link_state_change(ifp);\n//\t}\n}\n"
  },
  {
    "path": "itl80211/openbsd/net80211/ieee80211_proto.h",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n/*\t$OpenBSD: ieee80211_proto.h,v 1.46 2019/09/12 12:55:07 stsp Exp $\t*/\n/*\t$NetBSD: ieee80211_proto.h,v 1.3 2003/10/13 04:23:56 dyoung Exp $\t*/\n\n/*-\n * Copyright (c) 2001 Atsushi Onoe\n * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. The name of the author may not be used to endorse or promote products\n *    derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * $FreeBSD: src/sys/net80211/ieee80211_proto.h,v 1.4 2003/08/19 22:17:03 sam Exp $\n */\n#ifndef _NET80211_IEEE80211_PROTO_H_\n#define _NET80211_IEEE80211_PROTO_H_\n\n/*\n * 802.11 protocol implementation definitions.\n */\n\nenum ieee80211_state {\n\tIEEE80211_S_INIT\t= 0,\t/* default state */\n\tIEEE80211_S_SCAN\t= 1,\t/* scanning */\n\tIEEE80211_S_AUTH\t= 2,\t/* try to authenticate */\n\tIEEE80211_S_ASSOC\t= 3,\t/* try to assoc */\n\tIEEE80211_S_RUN\t\t= 4\t/* associated */\n};\n#define\tIEEE80211_S_MAX\t\t(IEEE80211_S_RUN+1)\n\n#define\tIEEE80211_SEND_MGMT(_ic,_ni,_type,_arg) \\\n\t((*(_ic)->ic_send_mgmt)(_ic, _ni, _type, _arg, 0))\n/* shortcut */\n#define IEEE80211_SEND_ACTION(_ic,_ni,_categ,_action,_arg) \\\n\t((*(_ic)->ic_send_mgmt)(_ic, _ni, IEEE80211_FC0_SUBTYPE_ACTION, \\\n\t    (_categ) << 16 | (_action), _arg))\n\nextern\tconst char * const ieee80211_mgt_subtype_name[];\nextern\tconst char * const ieee80211_state_name[IEEE80211_S_MAX];\nextern\tconst char * const ieee80211_phymode_name[];\n\nextern\tvoid ieee80211_proto_attach(struct _ifnet *);\nextern\tvoid ieee80211_proto_detach(struct _ifnet *);\n\nstruct ieee80211_node;\nstruct ieee80211_rxinfo;\nstruct ieee80211_rsnparams;\nextern\tvoid ieee80211_set_link_state(struct ieee80211com *, int);\nextern\tu_int ieee80211_get_hdrlen(const struct ieee80211_frame *);\nextern\tint ieee80211_classify(struct ieee80211com *, mbuf_t);\nextern\tvoid ieee80211_inputm(struct _ifnet *, mbuf_t,\n\t\tstruct ieee80211_node *, struct ieee80211_rxinfo *,\n\t\tstruct mbuf_list *);\nextern\tvoid ieee80211_input(struct _ifnet *, mbuf_t,\n\t\tstruct ieee80211_node *, struct ieee80211_rxinfo *);\nextern\tint ieee80211_output(struct _ifnet *, mbuf_t, struct sockaddr *,\n\t\tstruct rtentry *);\nextern\tvoid ieee80211_recv_mgmt(struct ieee80211com *, mbuf_t,\n\t\tstruct ieee80211_node *, struct ieee80211_rxinfo *, int);\nextern\tint ieee80211_send_mgmt(struct ieee80211com *, struct ieee80211_node *,\n\t\tint, int, int);\nextern\tvoid ieee80211_eapol_key_input(struct ieee80211com *, mbuf_t,\n\t\tstruct ieee80211_node *);\nextern\tvoid ieee80211_tx_compressed_bar(struct ieee80211com *,\n\t\tstruct ieee80211_node *, int, uint16_t);\nextern\tmbuf_t ieee80211_encap(struct _ifnet *, mbuf_t,\n\t\tstruct ieee80211_node **);\nextern\tmbuf_t ieee80211_get_rts(struct ieee80211com *,\n\t\tconst struct ieee80211_frame *, u_int16_t);\nextern\tmbuf_t ieee80211_get_cts_to_self(struct ieee80211com *,\n\t\tu_int16_t);\nextern\tmbuf_t ieee80211_get_compressed_bar(struct ieee80211com *,\n\t\tstruct ieee80211_node *, int, uint16_t);\nextern\tmbuf_t ieee80211_beacon_alloc(struct ieee80211com *,\n\t\tstruct ieee80211_node *);\nextern int ieee80211_save_ie(const u_int8_t *, u_int8_t **);\nextern int ieee80211_save_ie_tlv(const u_int8_t *, u_int8_t **, uint32_t *, uint32_t save_len);\nextern\tvoid ieee80211_eapol_timeout(void *);\nextern\tint ieee80211_send_4way_msg1(struct ieee80211com *,\n\t\tstruct ieee80211_node *);\nextern\tint ieee80211_send_4way_msg2(struct ieee80211com *,\n\t\tstruct ieee80211_node *, const u_int8_t *,\n\t\tconst struct ieee80211_ptk *);\nextern\tint ieee80211_send_4way_msg3(struct ieee80211com *,\n\t\tstruct ieee80211_node *);\nextern\tint ieee80211_send_4way_msg4(struct ieee80211com *,\n\t\tstruct ieee80211_node *);\nextern\tint ieee80211_send_group_msg1(struct ieee80211com *,\n\t\tstruct ieee80211_node *);\nextern\tint ieee80211_send_group_msg2(struct ieee80211com *,\n\t\tstruct ieee80211_node *, const struct ieee80211_key *);\nextern\tint ieee80211_send_eapol_key_req(struct ieee80211com *,\n\t\tstruct ieee80211_node *, u_int16_t, u_int64_t);\nextern\tint ieee80211_pwrsave(struct ieee80211com *, mbuf_t,\n\t\tstruct ieee80211_node *);\n#define    ieee80211_new_state(_ic, _nstate, _arg) \\\ndo {    \\\nXYLog(\"%s %d nstate=%d\\n\", __FUNCTION__, __LINE__, (_nstate));  \\\n(((_ic)->ic_newstate)((_ic), (_nstate), (_arg)));   \\\n} while (0)\nextern\tenum ieee80211_edca_ac ieee80211_up_to_ac(struct ieee80211com *, int);\nextern\tu_int8_t *ieee80211_add_capinfo(u_int8_t *, struct ieee80211com *,\n\t\tconst struct ieee80211_node *);\nextern\tu_int8_t *ieee80211_add_ssid(u_int8_t *, const u_int8_t *, u_int);\nextern\tu_int8_t *ieee80211_add_rates(u_int8_t *,\n\t\tconst struct ieee80211_rateset *);\nextern\tu_int8_t *ieee80211_add_fh_params(u_int8_t *, struct ieee80211com *,\n\t\tconst struct ieee80211_node *);\nextern\tu_int8_t *ieee80211_add_ds_params(u_int8_t *, struct ieee80211com *,\n\t\tconst struct ieee80211_node *);\nextern\tu_int8_t *ieee80211_add_tim(u_int8_t *, struct ieee80211com *);\nextern\tu_int8_t *ieee80211_add_ibss_params(u_int8_t *,\n\t\tconst struct ieee80211_node *);\nextern\tu_int8_t *ieee80211_add_edca_params(u_int8_t *, struct ieee80211com *);\nextern\tu_int8_t *ieee80211_add_erp(u_int8_t *, struct ieee80211com *);\nextern\tu_int8_t *ieee80211_add_qos_capability(u_int8_t *,\n\t\tstruct ieee80211com *);\nextern\tu_int8_t *ieee80211_add_rsn(u_int8_t *, struct ieee80211com *,\n\t\tconst struct ieee80211_node *);\nextern\tu_int8_t *ieee80211_add_wpa(u_int8_t *, struct ieee80211com *,\n\t\tconst struct ieee80211_node *);\nextern\tu_int8_t *ieee80211_add_xrates(u_int8_t *,\n\t\tconst struct ieee80211_rateset *);\nextern\tu_int8_t *ieee80211_add_htcaps(u_int8_t *, struct ieee80211com *);\nextern\tu_int8_t *ieee80211_add_htop(u_int8_t *, struct ieee80211com *);\nextern\tu_int8_t *ieee80211_add_tie(u_int8_t *, u_int8_t, u_int32_t);\nextern  u_int8_t *ieee80211_add_vhtcaps(u_int8_t *, struct ieee80211com *);\nextern  u_int8_t *ieee80211_add_hecaps(u_int8_t *, struct ieee80211com *);\nextern\tint ieee80211_parse_rsn(struct ieee80211com *, const u_int8_t *,\n\t\tstruct ieee80211_rsnparams *);\nextern\tint ieee80211_parse_wpa(struct ieee80211com *, const u_int8_t *,\n\t\tstruct ieee80211_rsnparams *);\nextern\tvoid ieee80211_print_essid(const u_int8_t *, int);\n#ifdef IEEE80211_DEBUG\nextern\tvoid ieee80211_dump_pkt(const u_int8_t *, int, int, int);\n#endif\nextern\tint ieee80211_ibss_merge(struct ieee80211com *,\n\t\tstruct ieee80211_node *, u_int64_t);\nextern\tvoid ieee80211_reset_erp(struct ieee80211com *);\nextern\tvoid ieee80211_set_shortslottime(struct ieee80211com *, int);\nextern\tvoid ieee80211_auth_open_confirm(struct ieee80211com *,\n\t    struct ieee80211_node *, uint16_t);\nextern\tvoid ieee80211_auth_open(struct ieee80211com *,\n\t    const struct ieee80211_frame *, struct ieee80211_node *,\n\t    struct ieee80211_rxinfo *rs, u_int16_t, u_int16_t);\nextern\tvoid ieee80211_stop_ampdu_tx(struct ieee80211com *,\n\t    struct ieee80211_node *, int);\nextern\tvoid ieee80211_gtk_rekey_timeout(void *);\nextern\tint ieee80211_keyrun(struct ieee80211com *, u_int8_t *);\nextern\tvoid ieee80211_setkeys(struct ieee80211com *);\nextern\tvoid ieee80211_setkeysdone(struct ieee80211com *);\nextern\tvoid ieee80211_sa_query_timeout(void *);\nextern\tvoid ieee80211_sa_query_request(struct ieee80211com *,\n\t    struct ieee80211_node *);\nextern  void ieee80211_ht_negotiate_chw(struct ieee80211com *,\n    struct ieee80211_node *);\nextern\tvoid ieee80211_ht_negotiate(struct ieee80211com *,\n    struct ieee80211_node *);\nextern  void ieee80211_vht_negotiate(struct ieee80211com *,\n    struct ieee80211_node *);\nextern  void ieee80211_he_negotiate(struct ieee80211com *,\n    struct ieee80211_node *);\nextern  void ieee80211_sta_set_rx_nss(struct ieee80211com *, struct ieee80211_node *);\nextern\tvoid ieee80211_tx_ba_timeout(void *);\nextern\tvoid ieee80211_rx_ba_timeout(void *);\nextern\tint ieee80211_addba_request(struct ieee80211com *,\n\t    struct ieee80211_node *,  u_int16_t, u_int8_t);\nextern\tvoid ieee80211_delba_request(struct ieee80211com *,\n\t    struct ieee80211_node *, u_int16_t, u_int8_t, u_int8_t);\nextern\tvoid ieee80211_addba_req_accept(struct ieee80211com *,\n\t    struct ieee80211_node *, uint8_t);\nextern\tvoid ieee80211_addba_req_refuse(struct ieee80211com *,\n\t    struct ieee80211_node *, uint8_t);\nextern\tvoid ieee80211_addba_resp_accept(struct ieee80211com *,\n\t    struct ieee80211_node *, uint8_t);\nextern\tvoid ieee80211_addba_resp_refuse(struct ieee80211com *,\n\t    struct ieee80211_node *, uint8_t, uint16_t);\nextern\tvoid ieee80211_output_ba_move_window(struct ieee80211com *,\n\t    struct ieee80211_node *, uint8_t, uint16_t);\nextern\tvoid ieee80211_output_ba_move_window_to_first_unacked(\n\t    struct ieee80211com *, struct ieee80211_node *, uint8_t, uint16_t);\nextern\tvoid ieee80211_output_ba_record_ack(struct ieee80211com *,\n\t    struct ieee80211_node *, uint8_t, uint16_t);\n\n#endif /* _NET80211_IEEE80211_PROTO_H_ */\n"
  },
  {
    "path": "itl80211/openbsd/net80211/ieee80211_ra.c",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n/*\n * Copyright (c) 2021 Christian Ehrhardt <ehrhardt@genua.de>\n * Copyright (c) 2016, 2021 Stefan Sperling <stsp@openbsd.org>\n * Copyright (c) 2016 Theo Buehler <tb@openbsd.org>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n#include <sys/param.h>\n#include <sys/systm.h>\n#include <sys/socket.h>\n\n#include <net/if.h>\n#include <net/if_media.h>\n\n#include <netinet/in.h>\n#include <netinet/if_ether.h>\n\n#include <net80211/ieee80211_var.h>\n#include <net80211/ieee80211_ra.h>\n\nint    ieee80211_ra_next_intra_rate(struct ieee80211_ra_node *, struct ieee80211com *,\n        struct ieee80211_node *);\nconst struct ieee80211_ra_rate * ieee80211_ra_next_rateset(\n            struct ieee80211_ra_node *, struct ieee80211com *, struct ieee80211_node *);\nint    ieee80211_ra_best_mcs_in_rateset(struct ieee80211_ra_node *,\n        const struct ieee80211_ra_rate *);\nvoid    ieee80211_ra_probe_next_rateset(struct ieee80211_ra_node *, struct ieee80211com *,\n        struct ieee80211_node *, const struct ieee80211_ra_rate *);\nint    ieee80211_ra_next_mcs(struct ieee80211_ra_node *, struct ieee80211com *,\n        struct ieee80211_node *);\nvoid    ieee80211_ra_probe_done(struct ieee80211_ra_node *);\nint    ieee80211_ra_intra_mode_ra_finished(\n        struct ieee80211_ra_node *, struct ieee80211com *, struct ieee80211_node *);\nvoid    ieee80211_ra_trigger_next_rateset(struct ieee80211_ra_node *, struct ieee80211com *,\n        struct ieee80211_node *);\nint    ieee80211_ra_inter_mode_ra_finished(\n        struct ieee80211_ra_node *, struct ieee80211_node *);\nint    ieee80211_ra_best_rate(struct ieee80211_ra_node *,\n        struct ieee80211_node *);\nvoid    ieee80211_ra_probe_next_rate(struct ieee80211_ra_node *, struct ieee80211com *,\n        struct ieee80211_node *);\nint    ieee80211_ra_valid_tx_mcs(struct ieee80211_node *, int);\nuint32_t ieee80211_ra_valid_rates(struct ieee80211com *,\n        struct ieee80211_node *);\nint    ieee80211_ra_probe_valid(struct ieee80211_ra_goodput_stats *);\n\n/* We use fixed point arithmetic with 64 bit integers. */\n#define RA_FP_SHIFT    21\n#define RA_FP_INT(x)    (x ## ULL << RA_FP_SHIFT) /* the integer x */\n#define RA_FP_1    RA_FP_INT(1)\n\n/* Multiply two fixed point numbers. */\n#define RA_FP_MUL(a, b) \\\n    (((a) * (b)) >> RA_FP_SHIFT)\n\n/* Divide two fixed point numbers. */\n#define RA_FP_DIV(a, b) \\\n    (b == 0 ? (uint64_t)-1 : (((a) << RA_FP_SHIFT) / (b)))\n\n#ifdef RA_DEBUG\n#define DPRINTF(x)    do { if (ra_debug > 0) printf x; } while (0)\n#define DPRINTFN(n, x)    do { if (ra_debug >= (n)) printf x; } while (0)\nint ra_debug = 0;\n#else\n#define DPRINTF(x)    do { ; } while (0)\n#define DPRINTFN(n, x)    do { ; } while (0)\n#endif\n\n#ifdef RA_DEBUG\nvoid\nra_fixedp_split(uint32_t *i, uint32_t *f, uint64_t fp)\n{\n    uint64_t tmp;\n\n    /* integer part */\n    *i = (fp >> RA_FP_SHIFT);\n\n     /* fractional part */\n    tmp = (fp & ((uint64_t)-1 >> (64 - RA_FP_SHIFT)));\n    tmp *= 100;\n    *f = (uint32_t)(tmp >> RA_FP_SHIFT);\n}\n\nchar *\nra_fp_sprintf(uint64_t fp)\n{\n    uint32_t i, f;\n    static char buf[64];\n    int ret;\n\n    ra_fixedp_split(&i, &f, fp);\n    ret = snprintf(buf, sizeof(buf), \"%u.%02u\", i, f);\n    if (ret == -1 || ret >= sizeof(buf))\n        return \"ERR\";\n\n    return buf;\n}\n#endif /* RA_DEBUG */\n\nstatic int is_ht(struct ieee80211_node *ni)\n{\n    return (ni->ni_flags & IEEE80211_NODE_HT);\n}\n\nstatic int is_vht(struct ieee80211_node *ni)\n{\n    return (ni->ni_flags & IEEE80211_NODE_VHT);\n}\n\nstatic int is_he(struct ieee80211_node *ni)\n{\n    return (ni->ni_flags & IEEE80211_NODE_HE);\n}\n\nstatic int support_nss(struct ieee80211_node *ni)\n{\n    uint32_t ntxstreams = 0;\n    struct ieee80211com *ic = ni->ni_ic;\n    int i;\n    if ((ic->ic_tx_mcs_set & IEEE80211_TX_RX_MCS_NOT_EQUAL) == 0) {\n        for (i = 0; i < 4; i++) {\n            if ((is_vht(ni) || is_he(ni)) &&\n                ic->ic_vht_sup_mcs[i] == 0) {\n                break;\n            } else if (ic->ic_sup_mcs[i] == 0) {\n                break;\n            }\n            ntxstreams++;\n            if (ntxstreams >= ni->ni_rx_nss)\n                break;\n        }\n        return ntxstreams;\n    }\n    return MIN(1 + ((ic->ic_tx_mcs_set & IEEE80211_TX_SPATIAL_STREAMS) >> 2), ni->ni_rx_nss);\n}\n\nstatic void build_rateset(struct ieee80211_ra_node *rn, enum ieee80211_phymode mode)\n{\n    int i;\n    struct ieee80211_ra_rate *ra_rate;\n    const struct ieee80211_ht_rateset *ht_rate;\n    const struct ieee80211_vht_rateset *vht_rate;\n    const struct ieee80211_he_rateset *he_rate;\n    rn->rs_phymode = mode;\n    switch (rn->rs_phymode) {\n        case IEEE80211_MODE_11N:\n            rn->active_rs_count = IEEE80211_HT_NUM_RATESETS;\n            for (i = 0; i < IEEE80211_HT_NUM_RATESETS; i++) {\n                ra_rate = &rn->active_rs[i];\n                ht_rate = &ieee80211_std_ratesets_11n[i];\n                ra_rate->band_width = (i >= IEEE80211_HT_RATESET_CBW40_SISO ? IEEE80211_CHAN_WIDTH_40 : IEEE80211_CHAN_WIDTH_20);\n                ra_rate->max_mcs = ht_rate->max_mcs;\n                ra_rate->min_mcs = ht_rate->min_mcs;\n                ra_rate->nrates = ht_rate->nrates;\n                ra_rate->sgi = ht_rate->sgi;\n                ra_rate->nss = (ht_rate->max_mcs + 1) / 8;\n                ra_rate->rs_index = i;\n                memcpy(ra_rate->rates, ht_rate->rates, sizeof(ht_rate->rates));\n            }\n            break;\n            \n        case IEEE80211_MODE_11AC:\n            rn->active_rs_count = IEEE80211_VHT_NUM_RATESETS;\n            for (i = 0; i < IEEE80211_HT_NUM_RATESETS; i++) {\n                ra_rate = &rn->active_rs[i];\n                vht_rate = &ieee80211_std_ratesets_11ac[i];\n                int bw = IEEE80211_CHAN_WIDTH_20;\n                switch (i / 4) {\n                    case 0:\n                        bw = IEEE80211_CHAN_WIDTH_20;\n                        break;\n                    case 1:\n                        bw = IEEE80211_CHAN_WIDTH_40;\n                        break;\n                    case 2:\n                        bw = IEEE80211_CHAN_WIDTH_80;\n                        break;\n                    case 3:\n                        bw = IEEE80211_CHAN_WIDTH_160;\n                        break;\n                    default:\n                        break;\n                }\n                ra_rate->band_width = bw;\n                ra_rate->max_mcs = vht_rate->nrates - 1;\n                ra_rate->min_mcs = 0;\n                ra_rate->nrates = vht_rate->nrates;\n                ra_rate->sgi = vht_rate->sgi;\n                ra_rate->nss = vht_rate->num_ss;\n                ra_rate->rs_index = i;\n                memcpy(ra_rate->rates, vht_rate->rates, sizeof(vht_rate->rates));\n            }\n            break;\n        \n        case IEEE80211_MODE_11AX:\n            rn->active_rs_count = IEEE80211_HT_NUM_RATESETS;\n            for (i = 0; i < IEEE80211_HT_NUM_RATESETS; i++) {\n                ra_rate = &rn->active_rs[i];\n                he_rate = &ieee80211_std_ratesets_11ax[i];\n                int bw = IEEE80211_CHAN_WIDTH_20;\n                switch (i / 2) {\n                    case 0:\n                        bw = IEEE80211_CHAN_WIDTH_20;\n                        break;\n                    case 1:\n                        bw = IEEE80211_CHAN_WIDTH_40;\n                        break;\n                    case 2:\n                        bw = IEEE80211_CHAN_WIDTH_80;\n                        break;\n                    case 3:\n                        bw = IEEE80211_CHAN_WIDTH_160;\n                        break;\n                    default:\n                        break;\n                }\n                ra_rate->band_width = bw;\n                ra_rate->max_mcs = he_rate->nrates - 1;\n                ra_rate->min_mcs = 0;\n                ra_rate->sgi = 0;\n                ra_rate->nss = ((i + 1) % 2) + 1;\n                ra_rate->nrates = he_rate->nrates;\n                ra_rate->rs_index = i;\n                memcpy(ra_rate->rates, he_rate->rates, sizeof(he_rate->rates));\n            }\n            break;\n        default:\n            XYLog(\"%s invalid mode=%d\\n\", __FUNCTION__, mode);\n            break;\n    }\n}\n\nconst struct ieee80211_ra_rate *\nieee80211_ra_get_rateset(struct ieee80211_ra_node *ra, struct ieee80211com *ic, struct ieee80211_node *ni, int mcs)\n{\n    int i;\n    int sup_nss = support_nss(ni);\n    struct ieee80211_ra_rate *last_ra_rate = &ra->active_rs[ra->rs_index];\n    if (last_ra_rate->min_mcs <= mcs && mcs <= last_ra_rate->max_mcs) {\n        return last_ra_rate;\n    }\n    int search_direction = mcs - last_ra_rate->max_mcs;\n    for (i = ra->rs_index; (search_direction > 0 ? (i <= ra->active_rs_count - 1) : (i >= 0)); search_direction > 0 ? i++ : i--) {\n        const struct ieee80211_ra_rate *ra_rate = &ra->active_rs[i];\n        if (ra_rate->sgi && !ieee80211_node_supports_sgi(ni))\n            continue;\n        if (ra_rate->nss > sup_nss)\n            continue;\n        if (ra_rate->band_width > ni->ni_chw)\n            continue;\n        if (mcs >= ra_rate->min_mcs && mcs <= ra_rate->max_mcs)\n            return ra_rate;\n    }\n    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);\n}\n\nint\nieee80211_ra_use_ht_sgi(struct ieee80211_node *ni)\n{\n    if ((ni->ni_chw == IEEE80211_CHAN_WIDTH_40) &&\n        ieee80211_node_supports_ht_chan40(ni)) {\n        if (ni->ni_flags & IEEE80211_NODE_HT_SGI40)\n            return 1;\n    } else if (ni->ni_flags & IEEE80211_NODE_HT_SGI20)\n        return 1;\n    \n    return 0;\n}\n\n/*\n * Update goodput statistics.\n */\n\nuint64_t\nieee80211_ra_get_txrate(struct ieee80211_ra_node *ra, struct ieee80211com *ic, struct ieee80211_node *ni, int mcs)\n{\n    const struct ieee80211_ra_rate *rs;\n    uint64_t txrate;\n\n    rs = ieee80211_ra_get_rateset(ra, ic, ni, mcs);\n    txrate = rs->rates[mcs - rs->min_mcs];\n    txrate <<= RA_FP_SHIFT; /* convert to fixed-point */\n    txrate *= 500; /* convert to kbit/s */\n    txrate /= 1000; /* convert to mbit/s */\n\n    return txrate;\n}\n\n/*\n * Rate selection.\n */\n\n/* A rate's goodput has to be at least this much larger to be \"better\". */\n#define IEEE80211_RA_RATE_THRESHOLD    (RA_FP_1 / 64) /* ~ 0.015 */\n\nint\nieee80211_ra_next_lower_intra_rate(struct ieee80211_ra_node *rn, struct ieee80211com *ic,\n    struct ieee80211_node *ni)\n{\n    const struct ieee80211_ra_rate *rs;\n    int i, next;\n\n    rs = ieee80211_ra_get_rateset(rn, ic, ni, ni->ni_txmcs);\n    if (ni->ni_txmcs == rs->min_mcs)\n        return rs->min_mcs;\n\n    next = ni->ni_txmcs;\n    for (i = rs->nrates - 1; i >= 0; i--) {\n        if ((rn->valid_rates & (1 << (i + rs->min_mcs))) == 0)\n            continue;\n        if (i + rs->min_mcs < ni->ni_txmcs) {\n            next = i + rs->min_mcs;\n            break;\n        }\n    }\n\n    return next;\n}\n\nint\nieee80211_ra_next_intra_rate(struct ieee80211_ra_node *rn, struct ieee80211com *ic,\n    struct ieee80211_node *ni)\n{\n    const struct ieee80211_ra_rate *rs;\n    int i, next;\n\n    rs = ieee80211_ra_get_rateset(rn, ic, ni, ni->ni_txmcs);\n    if (ni->ni_txmcs == rs->max_mcs)\n        return rs->max_mcs;\n\n    next = ni->ni_txmcs;\n    for (i = 0; i < rs->nrates; i++) {\n        if ((rn->valid_rates & (1 << (i + rs->min_mcs))) == 0)\n            continue;\n        if (i + rs->min_mcs > ni->ni_txmcs) {\n            next = i + rs->min_mcs;\n            break;\n        }\n    }\n\n    return next;\n}\n\nconst struct ieee80211_ra_rate *\nieee80211_ra_next_rateset(struct ieee80211_ra_node *rn, struct ieee80211com *ic,\n    struct ieee80211_node *ni)\n{\n    const struct ieee80211_ra_rate *rs, *rsnext = NULL;\n    int next = 0;\n    bool found = false;\n\n    rs = ieee80211_ra_get_rateset(rn, ic, ni, ni->ni_txmcs);\n    if (rn->probing & IEEE80211_RA_PROBING_UP) {\n        next = rs->rs_index;\n        while (next < rn->active_rs_count - 1) {\n            next++;\n            rsnext = &rn->active_rs[next];\n            if (rsnext->band_width > ni->ni_chw)\n                continue;\n            if (rsnext->nss > support_nss(ni))\n                continue;\n            found = true;\n            break;\n        }\n        \n    } else if (rn->probing & IEEE80211_RA_PROBING_DOWN) {\n        next = rs->rs_index;\n        while (next > 0) {\n            next--;\n            rsnext = &rn->active_rs[next];\n            if (rsnext->band_width > ni->ni_chw)\n                continue;\n            if (rsnext->nss > support_nss(ni))\n                continue;\n            found = true;\n            break;\n        }\n    } else\n        panic(\"%s: invalid probing mode %d\", __func__, rn->probing);\n    \n    if (found) {\n#ifdef RA_DEBUG\n        DPRINTF((\"%s rs befor_idx=%d after_idx=%d sgi=%d nss=%d sup_nss=%d bw=%d probing=%d\\n\", __FUNCTION__, rs->rs_index, rsnext->rs_index, rsnext->sgi, rsnext->nss, support_nss(ni), rsnext->band_width, rn->probing));\n#endif\n        return rsnext;\n    }\n    return NULL;\n\n//    if ((rsnext->mcs_mask & rn->valid_rates) == 0)\n//        return NULL;\n}\n\nint\nieee80211_ra_best_mcs_in_rateset(struct ieee80211_ra_node *rn,\n    const struct ieee80211_ra_rate *rs)\n{\n    uint64_t gmax = 0;\n    int i, best_mcs = rs->min_mcs;\n\n    for (i = 0; i < rs->nrates; i++) {\n        int mcs = rs->min_mcs + i;\n        struct ieee80211_ra_goodput_stats *g = &rn->g[mcs];\n        if (((1 << mcs) & rn->valid_rates) == 0)\n            continue;\n        if (g->measured > gmax + IEEE80211_RA_RATE_THRESHOLD) {\n            gmax = g->measured;\n            best_mcs = mcs;\n        }\n    }\n\n    return best_mcs;\n}\n\nvoid\nieee80211_ra_probe_next_rateset(struct ieee80211_ra_node *rn, struct ieee80211com *ic,\n    struct ieee80211_node *ni, const struct ieee80211_ra_rate *rsnext)\n{\n    const struct ieee80211_ra_rate *rs;\n    struct ieee80211_ra_goodput_stats *g;\n    int best_mcs, i;\n\n    /* Find most recently measured best MCS from the current rateset. */\n    rs = ieee80211_ra_get_rateset(rn, ic, ni, ni->ni_txmcs);\n    best_mcs = ieee80211_ra_best_mcs_in_rateset(rn, rs);\n\n    /* Switch to the next rateset. */\n    ni->ni_txmcs = rsnext->min_mcs;\n    rn->bw = rsnext->band_width;\n    rn->nss = rsnext->nss;\n    rn->sgi = rsnext->sgi;\n    rn->rs_index = rsnext->rs_index;\n    if ((rn->valid_rates & (1 << rsnext->min_mcs)) == 0)\n        ni->ni_txmcs = ieee80211_ra_next_intra_rate(rn, ic, ni);\n\n    /* Select the lowest rate from the next rateset with loss-free\n     * goodput close to the current best measurement. */\n    g = &rn->g[best_mcs];\n    for (i = 0; i < rsnext->nrates; i++) {\n        int mcs = rsnext->min_mcs + i;\n        uint64_t txrate = rsnext->rates[i];\n\n        if ((rn->valid_rates & (1 << mcs)) == 0)\n            continue;\n\n        txrate = txrate * 500; /* convert to kbit/s */\n        txrate <<= RA_FP_SHIFT; /* convert to fixed-point */\n        txrate /= 1000; /* convert to mbit/s */\n\n        if (txrate > g->measured + IEEE80211_RA_RATE_THRESHOLD) {\n            ni->ni_txmcs = mcs;\n            break;\n        }\n    }\n    /* If all rates are lower the maximum rate is the closest match. */\n    if (i == rsnext->nrates)\n        ni->ni_txmcs = rsnext->max_mcs;\n\n    /* Add rates from the next rateset as candidates. */\n    rn->candidate_rates |= (1 << ni->ni_txmcs);\n    if (rn->probing & IEEE80211_RA_PROBING_UP) {\n        rn->candidate_rates |=\n          (1 << ieee80211_ra_next_intra_rate(rn, ic, ni));\n    } else if (rn->probing & IEEE80211_RA_PROBING_DOWN) {\n        rn->candidate_rates |=\n            (1 << ieee80211_ra_next_lower_intra_rate(rn, ic, ni));\n    } else\n        panic(\"%s: invalid probing mode %d\", __func__, rn->probing);\n}\n\nint\nieee80211_ra_next_mcs(struct ieee80211_ra_node *rn, struct ieee80211com *ic,\n    struct ieee80211_node *ni)\n{\n    int next;\n\n    if (rn->probing & IEEE80211_RA_PROBING_DOWN)\n        next = ieee80211_ra_next_lower_intra_rate(rn, ic, ni);\n    else if (rn->probing & IEEE80211_RA_PROBING_UP)\n        next = ieee80211_ra_next_intra_rate(rn, ic, ni);\n    else\n        panic(\"%s: invalid probing mode %d\", __func__, rn->probing);\n\n    return next;\n}\n\nvoid\nieee80211_ra_probe_clear(struct ieee80211_ra_node *rn,\n    struct ieee80211_node *ni)\n{\n    struct ieee80211_ra_goodput_stats *g = &rn->g[ni->ni_txmcs];\n\n    g->nprobe_pkts = 0;\n    g->nprobe_fail = 0;\n}\n\nint\nieee80211_ra_probe_valid(struct ieee80211_ra_goodput_stats *g)\n{\n    /* 128 packets make up a valid probe in any case. */\n    if (g->nprobe_pkts >= 128)\n        return 1;\n    \n    /* 8 packets with > 75% loss make a valid probe, too. */\n    if (g->nprobe_pkts >= 8 &&\n        g->nprobe_pkts - g->nprobe_fail < g->nprobe_pkts / 4)\n        return 1;\n    \n    return 0;\n}\n\nvoid\nieee80211_ra_probe_done(struct ieee80211_ra_node *rn)\n{\n    rn->probing = IEEE80211_RA_NOT_PROBING;\n    rn->probed_rates = 0;\n    rn->valid_probes = 0;\n    rn->candidate_rates = 0;\n}\n\nint\nieee80211_ra_intra_mode_ra_finished(struct ieee80211_ra_node *rn, struct ieee80211com *ic,\n    struct ieee80211_node *ni)\n{\n    const struct ieee80211_ra_rate *rs;\n    struct ieee80211_ra_goodput_stats *g = &rn->g[ni->ni_txmcs];\n    int next_mcs, best_mcs;\n    uint64_t next_rate;\n\n    rn->probed_rates = (rn->probed_rates | (1 << ni->ni_txmcs));\n\n    /* Check if the min/max MCS in this rateset has been probed. */\n    rs = ieee80211_ra_get_rateset(rn, ic, ni, ni->ni_txmcs);\n    if (rn->probing & IEEE80211_RA_PROBING_DOWN) {\n        if (ni->ni_txmcs == rs->min_mcs ||\n            rn->probed_rates & (1 << rs->min_mcs)) {\n            ieee80211_ra_trigger_next_rateset(rn, ic, ni);\n            return 1;\n        }\n    } else if (rn->probing & IEEE80211_RA_PROBING_UP) {\n        if (ni->ni_txmcs == rs->max_mcs ||\n            rn->probed_rates & (1 << rs->max_mcs)) {\n            ieee80211_ra_trigger_next_rateset(rn, ic, ni);\n            return 1;\n        }\n    }\n\n    /*\n     * Check if the measured goodput is loss-free and better than the\n     * loss-free goodput of the candidate rate.\n     */\n    next_mcs = ieee80211_ra_next_mcs(rn, ic, ni);\n    if (next_mcs == ni->ni_txmcs) {\n        ieee80211_ra_trigger_next_rateset(rn, ic, ni);\n        return 1;\n    }\n    next_rate = ieee80211_ra_get_txrate(rn, ic, ni, next_mcs);\n    if (g->loss == 0 &&\n        g->measured >= next_rate + IEEE80211_RA_RATE_THRESHOLD) {\n        ieee80211_ra_trigger_next_rateset(rn, ic, ni);\n        return 1;\n    }\n\n    /* Check if we had a better measurement at a previously probed MCS. */\n    best_mcs = ieee80211_ra_best_mcs_in_rateset(rn, rs);\n    if (best_mcs != ni->ni_txmcs && (rn->probed_rates & (1 << best_mcs))) {\n        if ((rn->probing & IEEE80211_RA_PROBING_UP) &&\n            best_mcs < ni->ni_txmcs) {\n            ieee80211_ra_trigger_next_rateset(rn, ic, ni);\n            return 1;\n        }\n        if ((rn->probing & IEEE80211_RA_PROBING_DOWN) &&\n            best_mcs > ni->ni_txmcs) {\n            ieee80211_ra_trigger_next_rateset(rn, ic, ni);\n            return 1;\n        }\n    }\n\n    /* Check if all rates in the set of candidate rates have been probed. */\n    if ((rn->candidate_rates & rn->probed_rates) == rn->candidate_rates) {\n        /* Remain in the current rateset until above checks trigger. */\n        rn->probing &= ~IEEE80211_RA_PROBING_INTER;\n        return 1;\n    }\n\n    return 0;\n}\n\nvoid\nieee80211_ra_trigger_next_rateset(struct ieee80211_ra_node *rn, struct ieee80211com *ic,\n    struct ieee80211_node *ni)\n{\n    const struct ieee80211_ra_rate *rsnext;\n\n    rsnext = ieee80211_ra_next_rateset(rn, ic, ni);\n    if (rsnext) {\n        ieee80211_ra_probe_next_rateset(rn, ic, ni, rsnext);\n        rn->probing |= IEEE80211_RA_PROBING_INTER;\n    } else\n        rn->probing &= ~IEEE80211_RA_PROBING_INTER;\n}\n\nint\nieee80211_ra_inter_mode_ra_finished(struct ieee80211_ra_node *rn,\n    struct ieee80211_node *ni)\n{\n    return ((rn->probing & IEEE80211_RA_PROBING_INTER) == 0);\n}\n\nint\nieee80211_ra_best_rate(struct ieee80211_ra_node *rn,\n    struct ieee80211_node *ni)\n{\n    int i, best = rn->best_mcs;\n    uint64_t gmax = rn->g[rn->best_mcs].measured;\n\n    for (i = 0; i < nitems(rn->g); i++) {\n        struct ieee80211_ra_goodput_stats *g = &rn->g[i];\n        if (((1 << i) & rn->valid_rates) == 0)\n            continue;\n        if (g->measured > gmax + IEEE80211_RA_RATE_THRESHOLD) {\n            gmax = g->measured;\n            best = i;\n        }\n    }\n\n#ifdef RA_DEBUG\n    if (rn->best_mcs != best) {\n        DPRINTF((\"MCS %d is best; MCS{cur|avg|loss}:\", best));\n        for (i = 0; i < IEEE80211_HT_RATESET_NUM_MCS; i++) {\n            struct ieee80211_ra_goodput_stats *g = &rn->g[i];\n            if ((rn->valid_rates & (1 << i)) == 0)\n                continue;\n            DPRINTF((\" %d{%s|\", i, ra_fp_sprintf(g->measured)));\n            DPRINTF((\"%s|\", ra_fp_sprintf(g->average)));\n            DPRINTF((\"%s%%}\", ra_fp_sprintf(g->loss)));\n        }\n        DPRINTF((\"\\n\"));\n    }\n#endif\n    return best;\n}\n\nvoid\nieee80211_ra_probe_next_rate(struct ieee80211_ra_node *rn, struct ieee80211com *ic,\n    struct ieee80211_node *ni)\n{\n    /* Select the next rate to probe. */\n    rn->probed_rates |= (1 << ni->ni_txmcs);\n    ni->ni_txmcs = ieee80211_ra_next_mcs(rn, ic, ni);\n}\n\nint\nieee80211_ra_valid_tx_mcs(struct ieee80211_node *ni, int mcs)\n{\n    struct ieee80211com *ic = ni->ni_ic;\n    uint32_t ntxstreams = support_nss(ni);\n    static const int max_ht_mcs[] = { 7, 15, 23, 31 };\n    static const int max_vht_mcs = 9;\n\n    if ((ic->ic_tx_mcs_set & IEEE80211_TX_RX_MCS_NOT_EQUAL) == 0) {\n        if (is_he(ni) || is_vht(ni))\n            return isset(ic->ic_vht_sup_mcs, mcs);\n        return isset(ic->ic_sup_mcs, mcs);\n    }\n\n    if (is_he(ni) || is_vht(ni))\n        return mcs < max_vht_mcs && isset(ic->ic_vht_sup_mcs, mcs);\n\n    if (ntxstreams < 1 || ntxstreams > 4)\n        panic(\"invalid number of Tx streams: %u\", ntxstreams);\n    return (mcs <= max_ht_mcs[ntxstreams - 1] && isset(ic->ic_sup_mcs, mcs));\n}\n\nint\nieee80211_ra_vht_highest_rx_mcs(struct ieee80211_node *ni, int nss)\n{\n    uint16_t rx_mcs;\n\n    rx_mcs = le16toh(ni->ni_vht_mcsinfo.rx_mcs_map) &\n        (IEEE80211_VHT_MCS_NOT_SUPPORTED << (2 * (nss - 1)));\n    rx_mcs >>= (2 * (nss - 1));\n\n    return rx_mcs;\n}\n\nint\nieee80211_ra_valid_rx_mcs(struct ieee80211_node *ni, int mcs)\n{\n    uint16_t rx_mcs;\n\n    if (is_he(ni) || is_vht(ni)) {\n        rx_mcs = ieee80211_ra_vht_highest_rx_mcs(ni, ni->ni_rx_nss > 1 ? 2 : 1);\n        if (rx_mcs == 0 && mcs == 8)\n            return 0;\n        else if (rx_mcs == 1 && mcs == 9)\n            return 0;\n\n        if (mcs == 9 && ni->ni_chw == IEEE80211_CHAN_WIDTH_20)\n            return 0;\n    } else if (!isset(ni->ni_rxmcs, mcs))\n        return 0;\n    return 1;\n}\n\nuint32_t\nieee80211_ra_valid_rates(struct ieee80211com *ic, struct ieee80211_node *ni)\n{\n    uint32_t valid_mcs = 0;\n    uint32_t max_mcs = (is_he(ni) || is_vht(ni)) ? IEEE80211_VHT_RATESET_NUM_MCS : IEEE80211_HT_RATESET_NUM_MCS;\n    int i;\n\n    for (i = 0; i < max_mcs; i++) {\n        if (!ieee80211_ra_valid_rx_mcs(ni, i))\n            continue;\n\n        if (!ieee80211_ra_valid_tx_mcs(ni, i))\n            continue;\n        valid_mcs |= (1 << i);\n    }\n\n    return valid_mcs;\n}\n\nvoid\nieee80211_ra_add_stats_ht(struct ieee80211_ra_node *rn,\n    struct ieee80211com *ic, struct ieee80211_node *ni,\n    int mcs, uint32_t total, uint32_t fail)\n{\n    static const uint64_t alpha = RA_FP_1 / 8; /* 1/8 = 0.125 */\n    static const uint64_t beta =  RA_FP_1 / 4; /* 1/4 = 0.25 */\n    int s;\n    struct ieee80211_ra_goodput_stats *g;\n    uint64_t sfer, rate, delta;\n\n    /*\n     * Ignore invalid values. These values may come from hardware\n     * so asserting valid values via panic is not appropriate.\n     */\n    if (mcs < 0 || mcs >= IEEE80211_HT_RATESET_NUM_MCS)\n        return;\n    if (total == 0)\n        return;\n\n    s = splnet();\n\n    g = &rn->g[mcs];\n    g->nprobe_pkts += total;\n    g->nprobe_fail += fail;\n\n    if (!ieee80211_ra_probe_valid(g)) {\n        splx(s);\n        return;\n    }\n    rn->valid_probes |= 1U << mcs;\n\n    if (g->nprobe_fail > g->nprobe_pkts) {\n        DPRINTF((\"%s fail %u > pkts %u\\n\",\n            ether_sprintf(ni->ni_macaddr),\n            g->nprobe_fail, g->nprobe_pkts));\n        g->nprobe_fail = g->nprobe_pkts;\n    }\n\n    sfer = g->nprobe_fail << RA_FP_SHIFT;\n    sfer /= g->nprobe_pkts;\n    g->nprobe_fail = 0;\n    g->nprobe_pkts = 0;\n\n    rate = ieee80211_ra_get_txrate(rn, ic, ni, mcs);\n\n    g->loss = sfer * 100;\n    g->measured = RA_FP_MUL(RA_FP_1 - sfer, rate);\n    g->average = RA_FP_MUL(RA_FP_1 - alpha, g->average);\n    g->average += RA_FP_MUL(alpha, g->measured);\n\n    g->stddeviation = RA_FP_MUL(RA_FP_1 - beta, g->stddeviation);\n    if (g->average > g->measured)\n        delta = g->average - g->measured;\n    else\n        delta = g->measured - g->average;\n    g->stddeviation += RA_FP_MUL(beta, delta);\n\n    splx(s);\n}\n\nvoid\nieee80211_ra_choose(struct ieee80211_ra_node *rn, struct ieee80211com *ic,\n    struct ieee80211_node *ni)\n{\n    struct ieee80211_ra_goodput_stats *g = &rn->g[ni->ni_txmcs];\n    int s;\n    const struct ieee80211_ra_rate *rs, *rsnext;\n\n    s = splnet();\n\n    if (rn->valid_rates == 0)\n        rn->valid_rates = ieee80211_ra_valid_rates(ic, ni);\n\n    if (rn->probing) {\n        /* Probe another rate or settle at the best rate. */\n        if (!(rn->valid_probes & (1UL << ni->ni_txmcs))) {\n            splx(s);\n            return;\n        }\n        ieee80211_ra_probe_clear(rn, ni);\n        if (!ieee80211_ra_intra_mode_ra_finished(rn, ic, ni)) {\n            ieee80211_ra_probe_next_rate(rn, ic, ni);\n            DPRINTFN(3, (\"probing MCS %d\\n\", ni->ni_txmcs));\n        } else if (ieee80211_ra_inter_mode_ra_finished(rn, ni)) {\n            rn->best_mcs = ieee80211_ra_best_rate(rn, ni);\n            ni->ni_txmcs = rn->best_mcs;\n            ieee80211_ra_probe_done(rn);\n        }\n\n        splx(s);\n        return;\n    } else {\n        rn->valid_probes = 0;\n    }\n\n    rs = ieee80211_ra_get_rateset(rn, ic, ni, ni->ni_txmcs);\n    if ((g->measured >> RA_FP_SHIFT) == 0LL ||\n        (g->average >= 3 * g->stddeviation &&\n        g->measured < g->average - 3 * g->stddeviation)) {\n        /* Channel becomes bad. Probe downwards. */\n        rn->probing = IEEE80211_RA_PROBING_DOWN;\n        rn->probed_rates = 0;\n        if (ni->ni_txmcs == rs->min_mcs) {\n            rsnext = ieee80211_ra_next_rateset(rn, ic, ni);\n            if (rsnext) {\n                ieee80211_ra_probe_next_rateset(rn, ic, ni,\n                    rsnext);\n            } else {\n                /* Cannot probe further down. */\n                rn->probing = IEEE80211_RA_NOT_PROBING;\n            }\n        } else {\n            ni->ni_txmcs = ieee80211_ra_next_mcs(rn, ic, ni);\n            rn->candidate_rates = (1 << ni->ni_txmcs);\n        }\n    } else if (g->loss < 2 * RA_FP_1 ||\n        g->measured > g->average + 3 * g->stddeviation) {\n        /* Channel becomes good. */\n        rn->probing = IEEE80211_RA_PROBING_UP;\n        rn->probed_rates = 0;\n        if (ni->ni_txmcs == rs->max_mcs) {\n            rsnext = ieee80211_ra_next_rateset(rn, ic, ni);\n            if (rsnext) {\n                ieee80211_ra_probe_next_rateset(rn, ic, ni,\n                    rsnext);\n            } else {\n                /* Cannot probe further up. */\n                rn->probing = IEEE80211_RA_NOT_PROBING;\n            }\n        } else {\n            ni->ni_txmcs = ieee80211_ra_next_mcs(rn, ic, ni);\n            rn->candidate_rates = (1 << ni->ni_txmcs);\n        }\n    } else {\n        /* Remain at current rate. */\n        rn->probing = IEEE80211_RA_NOT_PROBING;\n        rn->probed_rates = 0;\n        rn->candidate_rates = 0;\n    }\n\n    splx(s);\n\n    if (rn->probing) {\n        if (rn->probing & IEEE80211_RA_PROBING_UP)\n            DPRINTFN(2, (\"channel becomes good; probe up\\n\"));\n        else\n            DPRINTFN(2, (\"channel becomes bad; probe down\\n\"));\n\n        DPRINTFN(3, (\"measured: %s Mbit/s\\n\",\n            ra_fp_sprintf(g->measured)));\n        DPRINTFN(3, (\"average: %s Mbit/s\\n\",\n            ra_fp_sprintf(g->average)));\n        DPRINTFN(3, (\"stddeviation: %s\\n\",\n            ra_fp_sprintf(g->stddeviation)));\n        DPRINTFN(3, (\"loss: %s%%\\n\", ra_fp_sprintf(g->loss)));\n    }\n}\n\nvoid\nieee80211_ra_node_init(struct ieee80211com *ic, struct ieee80211_ra_node *rn, struct ieee80211_node *ni)\n{\n    memset(rn, 0, sizeof(*rn));\n    build_rateset(rn, (enum ieee80211_phymode)ic->ic_curmode);\n    rn->bw = ni->ni_chw;\n    rn->sgi = ieee80211_node_supports_sgi(ni);\n    rn->nss = support_nss(ni);\n    switch (ni->ni_chw) {\n        case IEEE80211_CHAN_WIDTH_20:\n            if (is_he(ni)) {\n                rn->rs_index = IEEE80211_HE_RATESET_SISO;\n            } else if (is_vht(ni)) {\n                rn->rs_index = IEEE80211_VHT_RATESET_SISO;\n            } else if (is_ht(ni)) {\n                rn->rs_index = IEEE80211_HT_RATESET_SISO;\n            }\n            break;\n        case IEEE80211_CHAN_WIDTH_40:\n            if (is_he(ni)) {\n                rn->rs_index = IEEE80211_HE_RATESET_SISO_40;\n            } else if (is_vht(ni)) {\n                rn->rs_index = IEEE80211_VHT_RATESET_SISO_40;\n            } else if (is_ht(ni)) {\n                rn->rs_index = IEEE80211_HT_RATESET_CBW40_SISO;\n            }\n            break;\n        case IEEE80211_CHAN_WIDTH_80:\n            if (is_he(ni)) {\n                rn->rs_index = IEEE80211_HE_RATESET_SISO_80;\n            } else if (is_vht(ni)) {\n                rn->rs_index = IEEE80211_VHT_RATESET_SISO_80;\n            }\n            break;\n        case IEEE80211_CHAN_WIDTH_80P80:\n        case IEEE80211_CHAN_WIDTH_160:\n            if (is_he(ni)) {\n                rn->rs_index = IEEE80211_HE_RATESET_SISO_160;\n            } else if (is_vht(ni)) {\n                rn->rs_index = IEEE80211_VHT_RATESET_SISO_160;\n            }\n            break;\n            \n        default:\n            rn->rs_index = 0;\n            break;\n    }\n}\n"
  },
  {
    "path": "itl80211/openbsd/net80211/ieee80211_ra.h",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n/*    $OpenBSD: ieee80211_ra.h,v 1.1 2021/03/12 16:26:27 stsp Exp $    */\n\n/*\n * Copyright (c) 2021 Christian Ehrhardt <ehrhardt@genua.de>\n * Copyright (c) 2021 Stefan Sperling <stsp@openbsd.org>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n#ifndef _NET80211_IEEE80211_RA_H_\n#define _NET80211_IEEE80211_RA_H_\n\n/*\n * Goodput statistics struct. Measures the effective data rate of an MCS.\n * All uint64_t numbers in this struct use fixed-point arithmetic.\n */\nstruct ieee80211_ra_goodput_stats {\n    uint64_t measured;    /* Most recently measured goodput. */\n    uint64_t average;    /* Average measured goodput. */\n    uint64_t stddeviation;    /* Goodput standard deviation. */\n     uint64_t loss;        /* This rate's loss percentage SFER. */\n    uint32_t nprobe_pkts;    /* Number of packets in current probe. */\n    uint32_t nprobe_fail;    /* Number of failed packets. */\n};\n\n#define IEEE80211_RATESET_MAX_NRATES    11\n#define IEEE80211_RATESET_MAX_RATE_SET    max(IEEE80211_HT_NUM_RATESETS, IEEE80211_VHT_NUM_RATESETS)\n\nstruct ieee80211_ra_rate {\n    int min_mcs;\n    int max_mcs;\n    int band_width;\n    int sgi;\n    int nss;\n    int rs_index;\n    uint32_t nrates;\n    uint32_t rates[IEEE80211_RATESET_MAX_NRATES]; /* 500 kbit/s units */\n};\n\n/*\n * Rate adaptation state.\n *\n * Drivers should not modify any fields of this structure directly.\n * Use ieee80211_ra_init() and ieee80211_ra_add_stats() only.\n */\nstruct ieee80211_ra_node {\n    /* Bitmaps MCS 0-31. */\n    uint32_t valid_probes;\n    uint32_t valid_rates;\n    uint32_t candidate_rates;\n    uint32_t probed_rates;\n\n    /* Probing state. */\n    int probing;\n#define IEEE80211_RA_NOT_PROBING    0x0\n#define IEEE80211_RA_PROBING_DOWN    0x1\n#define IEEE80211_RA_PROBING_UP        0x2\n#define IEEE80211_RA_PROBING_INTER    0x4 /* combined with UP or DOWN */\n\n    /* The current best MCS found by probing. */\n    int best_mcs;\n\n    /* Goodput statistics for each MCS. */\n    struct ieee80211_ra_goodput_stats g[IEEE80211_HT_RATESET_NUM_MCS];\n    \n    int bw;\n    int sgi;\n    int nss;\n    \n    int rs_index;\n    \n    uint32_t    active_rs_count;\n    enum ieee80211_phymode  rs_phymode;\n    struct ieee80211_ra_rate active_rs[IEEE80211_RATESET_MAX_RATE_SET];\n};\n\n/* Initialize rate adaptation state. */\nvoid    ieee80211_ra_node_init(struct ieee80211com *, struct ieee80211_ra_node *, struct ieee80211_node *);\n\n/*\n * Drivers report information about 802.11n/HT Tx attempts here.\n * mcs: The HT MCS used during this Tx attempt.\n * total: How many Tx attempts (initial attempt + any retries) were made?\n * fail: How many of these Tx attempts failed?\n */\nvoid    ieee80211_ra_add_stats_ht(struct ieee80211_ra_node *,\n        struct ieee80211com *, struct ieee80211_node *,\n        int mcs, unsigned int total, unsigned int fail);\n\n/* Drivers call this function to update ni->ni_txmcs. */\nvoid    ieee80211_ra_choose(struct ieee80211_ra_node *,\n        struct ieee80211com *, struct ieee80211_node *);\n\n/* Get the HT rateset for a particular HT MCS with SGI on/off. */\nconst struct ieee80211_ra_rate *ieee80211_ra_get_rateset(struct ieee80211_ra_node *, struct ieee80211com *,\n                                                         struct ieee80211_node *, int);\n/* Check whether SGI should be used. */\nint     ieee80211_ra_use_ht_sgi(struct ieee80211_node *);\n#endif /* _NET80211_IEEE80211_RA_H_ */\n"
  },
  {
    "path": "itl80211/openbsd/net80211/ieee80211_radiotap.h",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n/* $OpenBSD: ieee80211_radiotap.h,v 1.16 2020/10/09 08:53:16 mpi Exp $ */\n/* $FreeBSD: src/sys/net80211/ieee80211_radiotap.h,v 1.3 2004/04/05 22:13:21 sam Exp $ */\n/* $NetBSD: ieee80211_radiotap.h,v 1.9 2004/06/06 04:13:28 dyoung Exp $ */\n\n/*-\n * Copyright (c) 2003, 2004 David Young.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,\n * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A\n * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL DAVID\n * YOUNG BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED\n * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY\n * OF SUCH DAMAGE.\n */\n#ifndef _NET_IF_IEEE80211RADIOTAP_H_\n#define _NET_IF_IEEE80211RADIOTAP_H_\n\n/* A generic radio capture format is desirable. There is one for\n * Linux, but it is neither rigidly defined (there were not even\n * units given for some fields) nor easily extensible.\n *\n * I suggest the following extensible radio capture format. It is\n * based on a bitmap indicating which fields are present.\n *\n * I am trying to describe precisely what the application programmer\n * should expect in the following, and for that reason I tell the\n * units and origin of each measurement (where it applies), or else I\n * use sufficiently weaselly language (\"is a monotonically nondecreasing\n * function of...\") that I cannot set false expectations for lawyerly\n * readers.\n */\n\n/* XXX tcpdump/libpcap do not tolerate variable-length headers,\n * yet, so we pad every radiotap header to 64 bytes. Ugh.\n */\n#define IEEE80211_RADIOTAP_HDRLEN\t64\n\n/* The radio capture header precedes the 802.11 header. */\nstruct ieee80211_radiotap_header {\n\tu_int8_t\tit_version;\t/* Version 0. Only increases\n\t\t\t\t\t * for drastic changes,\n\t\t\t\t\t * introduction of compatible\n\t\t\t\t\t * new fields does not count.\n\t\t\t\t\t */\n\tu_int8_t\tit_pad;\n\tu_int16_t       it_len;         /* length of the whole\n\t\t\t\t\t * header in bytes, including\n\t\t\t\t\t * it_version, it_pad,\n\t\t\t\t\t * it_len, and data fields.\n\t\t\t\t\t */\n\tu_int32_t       it_present;     /* A bitmap telling which\n\t\t\t\t\t * fields are present. Set bit 31\n\t\t\t\t\t * (0x80000000) to extend the\n\t\t\t\t\t * bitmap by another 32 bits.\n\t\t\t\t\t * Additional extensions are made\n\t\t\t\t\t * by setting bit 31.\n\t\t\t\t\t */\n} __packed;\n\n/* Name                                 Data type       Units\n * ----                                 ---------       -----\n *\n * IEEE80211_RADIOTAP_TSFT              u_int64_t       microseconds\n *\n *      Value in microseconds of the MAC's 64-bit 802.11 Time\n *      Synchronization Function timer when the first bit of the\n *      MPDU arrived at the MAC. For received frames, only.\n *\n * IEEE80211_RADIOTAP_CHANNEL           2 x u_int16_t   MHz, bitmap\n *\n *      Tx/Rx frequency in MHz, followed by flags (see below).\n *\n * IEEE80211_RADIOTAP_FHSS              u_int16_t       see below\n *\n *      For frequency-hopping radios, the hop set (first byte)\n *      and pattern (second byte).\n *\n * IEEE80211_RADIOTAP_RATE              u_int8_t        500kb/s or MCS index\n *\n *      Tx/Rx data rate in units of 500kb/s. If the high bit (0x80) is set\n *      the remaining bits contain an MCS index instead of a date rate.\n *\n * IEEE80211_RADIOTAP_DBM_ANTSIGNAL     int8_t          decibels from\n *                                                      one milliwatt (dBm)\n *\n *      RF signal power at the antenna, decibel difference from\n *      one milliwatt.\n *\n * IEEE80211_RADIOTAP_DBM_ANTNOISE      int8_t          decibels from\n *                                                      one milliwatt (dBm)\n *\n *      RF noise power at the antenna, decibel difference from one\n *      milliwatt.\n *\n * IEEE80211_RADIOTAP_DB_ANTSIGNAL      u_int8_t        decibel (dB)\n *\n *      RF signal power at the antenna, decibel difference from an\n *      arbitrary, fixed reference.\n *\n * IEEE80211_RADIOTAP_DB_ANTNOISE       u_int8_t        decibel (dB)\n *\n *      RF noise power at the antenna, decibel difference from an\n *      arbitrary, fixed reference point.\n *\n * IEEE80211_RADIOTAP_BARKER_CODE_LOCK  u_int16_t       unitless\n *\n *      Quality of Barker code lock. Unitless. Monotonically\n *      nondecreasing with \"better\" lock strength. Called \"Signal\n *      Quality\" in datasheets.  (Is there a standard way to measure\n *      this?)\n *\n * IEEE80211_RADIOTAP_TX_ATTENUATION    u_int16_t       unitless\n *\n *      Transmit power expressed as unitless distance from max\n *      power set at factory calibration.  0 is max power.\n *      Monotonically nondecreasing with lower power levels.\n *\n * IEEE80211_RADIOTAP_DB_TX_ATTENUATION u_int16_t       decibels (dB)\n *\n *      Transmit power expressed as decibel distance from max power\n *      set at factory calibration.  0 is max power.  Monotonically\n *      nondecreasing with lower power levels.\n *\n * IEEE80211_RADIOTAP_DBM_TX_POWER      int8_t          decibels from\n *                                                      one milliwatt (dBm)\n *\n *      Transmit power expressed as dBm (decibels from a 1 milliwatt\n *      reference). This is the absolute power level measured at\n *      the antenna port.\n *\n * IEEE80211_RADIOTAP_FLAGS             u_int8_t        bitmap\n *\n *      Properties of transmitted and received frames. See flags\n *      defined below.\n *\n * IEEE80211_RADIOTAP_ANTENNA           u_int8_t        antenna index\n *\n *      Unitless indication of the Rx/Tx antenna for this packet.\n *      The first antenna is antenna 0.\n *\n * IEEE80211_RADIOTAP_FCS           \tu_int32_t       data\n *\n *\tFCS from frame in network byte order.\n *\n * IEEE80211_RADIOTAP_RSSI              2x u_int8_t    RSSI, max RSSI\n *\n *\tA relative Received Signal Strength Index\n */\nenum ieee80211_radiotap_type {\n\tIEEE80211_RADIOTAP_TSFT = 0,\n\tIEEE80211_RADIOTAP_FLAGS = 1,\n\tIEEE80211_RADIOTAP_RATE = 2,\n\tIEEE80211_RADIOTAP_CHANNEL = 3,\n\tIEEE80211_RADIOTAP_FHSS = 4,\n\tIEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5,\n\tIEEE80211_RADIOTAP_DBM_ANTNOISE = 6,\n\tIEEE80211_RADIOTAP_LOCK_QUALITY = 7,\n\tIEEE80211_RADIOTAP_TX_ATTENUATION = 8,\n\tIEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9,\n\tIEEE80211_RADIOTAP_DBM_TX_POWER = 10,\n\tIEEE80211_RADIOTAP_ANTENNA = 11,\n\tIEEE80211_RADIOTAP_DB_ANTSIGNAL = 12,\n\tIEEE80211_RADIOTAP_DB_ANTNOISE = 13,\n\tIEEE80211_RADIOTAP_FCS = 14,\n\tIEEE80211_RADIOTAP_RSSI = 16,\n\tIEEE80211_RADIOTAP_EXT = 31\n};\n\n#ifndef _KERNEL\n/* For IEEE80211_RADIOTAP_CHANNEL */\n#define IEEE80211_CHAN_CCK\t0x0020\t/* CCK channel */\n#define IEEE80211_CHAN_OFDM\t0x0040\t/* OFDM channel */\n#define IEEE80211_CHAN_2GHZ\t0x0080\t/* 2 GHz spectrum channel */\n#define IEEE80211_CHAN_5GHZ\t0x0100\t/* 5 GHz spectrum channel */\n#define IEEE80211_CHAN_PASSIVE\t0x0200\t/* Only passive scan allowed */\n#define IEEE80211_CHAN_DYN\t0x0400\t/* Dynamic CCK-OFDM channel */\n#define IEEE80211_CHAN_GFSK\t0x0800\t/* GFSK channel (FHSS PHY) */\n#define IEEE80211_CHAN_XR\t0x1000\t/* Extended range OFDM channel */\n#define IEEE80211_CHAN_HT\t0x2000\t/* 11n/HT channel */\n#define IEEE80211_CHAN_VHT\t0x4000\t/* 11ac/VHT channel */\n#endif\t/* !_KERNEL */\n\n/* For IEEE80211_RADIOTAP_FLAGS */\n#define\tIEEE80211_RADIOTAP_F_CFP\t0x01\t/* sent/received\n\t\t\t\t\t\t * during CFP\n\t\t\t\t\t\t */\n#define\tIEEE80211_RADIOTAP_F_SHORTPRE\t0x02\t/* sent/received\n\t\t\t\t\t\t * with short\n\t\t\t\t\t\t * preamble\n\t\t\t\t\t\t */\n#define\tIEEE80211_RADIOTAP_F_WEP\t0x04\t/* sent/received\n\t\t\t\t\t\t * with WEP encryption\n\t\t\t\t\t\t */\n#define\tIEEE80211_RADIOTAP_F_FRAG\t0x08\t/* sent/received\n\t\t\t\t\t\t * with fragmentation\n\t\t\t\t\t\t */\n#define\tIEEE80211_RADIOTAP_F_FCS\t0x10\t/* frame includes FCS */\n\n#endif /* _NET_IF_IEEE80211RADIOTAP_H_ */\n"
  },
  {
    "path": "itl80211/openbsd/net80211/ieee80211_regdomain.c",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n/*\t$OpenBSD: ieee80211_regdomain.c,v 1.10 2015/11/24 13:45:06 mpi Exp $\t*/\n\n/*\n * Copyright (c) 2004, 2005 Reyk Floeter <reyk@openbsd.org>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n/*\n * Basic regulation domain extensions for the IEEE 802.11 stack\n */\n\n#include <sys/param.h>\n#include <sys/systm.h>\n#include <sys/mbuf.h>\n#include <sys/kernel.h>\n#include <sys/socket.h>\n#include <sys/sockio.h>\n#include <sys/endian.h>\n#include <sys/errno.h>\n\n#include <net/if.h>\n#include <net/if_dl.h>\n#include <sys/_if_media.h>\n#include <net/if_llc.h>\n\n#include <netinet/in.h>\n#include <netinet/if_ether.h>\n\n#include <net80211/ieee80211_var.h>\n#include <net80211/ieee80211_regdomain.h>\n\nint\t ieee80211_regdomain_compare_cn(const void *, const void *);\nint\t ieee80211_regdomain_compare_rn(const void *, const void *);\n\nstatic const struct ieee80211_regdomainname\nieee80211_r_names[] = IEEE80211_REGDOMAIN_NAMES;\n\nstatic const struct ieee80211_regdomainmap\nieee80211_r_map[] = IEEE80211_REGDOMAIN_MAP;\n\nstatic const struct ieee80211_countryname\nieee80211_r_ctry[] = IEEE80211_REGDOMAIN_COUNTRY_NAMES;\n\n#ifndef bsearch\nconst void *bsearch(const void *, const void *, size_t, size_t,\n    int (*)(const void *, const void *));\n\nconst void *\nbsearch(const void *key, const void *base0, size_t nmemb, size_t size,\n    int (*compar)(const void *, const void *))\n{\n\tconst char *base = (const char *)base0;\n\tint lim, cmp;\n\tconst void *p;\n\n\tfor (lim = nmemb; lim != 0; lim >>= 1) {\n\t\tp = base + (lim >> 1) * size;\n\t\tcmp = (*compar)(key, p);\n\t\tif (cmp == 0)\n\t\t\treturn ((const void *)p);\n\t\tif (cmp > 0) {  /* key > p: move right */\n\t\t\tbase = (const char *)p + size;\n\t\t\tlim--;\n\t\t} /* else move left */\n\t}\n\treturn (NULL);\n}\n#endif\n\nint\nieee80211_regdomain_compare_cn(const void *a, const void *b)\n{\n\treturn (strcmp(((const struct ieee80211_countryname*)a)->cn_name,\n\t    ((const struct ieee80211_countryname*)b)->cn_name));\n}\n\nint\nieee80211_regdomain_compare_rn(const void *a, const void *b)\n{\n\treturn (strcmp(((const struct ieee80211_regdomainname*)a)->rn_name,\n\t    ((const struct ieee80211_regdomainname*)b)->rn_name));\n}\n\nu_int16_t\nieee80211_name2countrycode(const char *name)\n{\n\tconst struct ieee80211_countryname key = { CTRY_DEFAULT, name }, *value;\n\n\tif ((value = (const struct ieee80211_countryname*)bsearch((const void *)&key, (const void *)&ieee80211_r_ctry,\n\t    nitems(ieee80211_r_ctry), sizeof(struct ieee80211_countryname),\n\t    ieee80211_regdomain_compare_cn)) != NULL)\n\t\treturn (value->cn_code);\n\n\treturn (CTRY_DEFAULT);\n}\n\nu_int32_t\nieee80211_name2regdomain(const char *name)\n{\n\tconst struct ieee80211_regdomainname *value;\n\tstruct ieee80211_regdomainname key;\n\n\tkey.rn_domain = DMN_DEFAULT;\n\tkey.rn_name = name;\n\n\tif ((value = (const struct ieee80211_regdomainname *)bsearch((const void *)&key, (const void *)&ieee80211_r_names,\n\t    nitems(ieee80211_r_names), sizeof(struct ieee80211_regdomainname),\n\t    ieee80211_regdomain_compare_rn)) != NULL)\n\t\treturn ((u_int32_t)value->rn_domain);\n\n\treturn ((u_int32_t)DMN_DEFAULT);\n}\n\nconst char *\nieee80211_countrycode2name(u_int16_t code)\n{\n\tint i;\n\n\t/* Linear search over the table */\n\tfor (i = 0; i < (sizeof(ieee80211_r_ctry) /\n\t    sizeof(ieee80211_r_ctry[0])); i++)\n\t\tif (ieee80211_r_ctry[i].cn_code == code)\n\t\t\treturn (ieee80211_r_ctry[i].cn_name);\n\n\treturn (NULL);\n}\n\nconst char *\nieee80211_regdomain2name(u_int32_t regdomain)\n{\n\tint i;\n\n\t/* Linear search over the table */\n\tfor (i = 0; i < (sizeof(ieee80211_r_names) /\n\t\tsizeof(ieee80211_r_names[0])); i++)\n\t\tif (ieee80211_r_names[i].rn_domain == regdomain)\n\t\t\treturn (ieee80211_r_names[i].rn_name);\n\n\treturn (ieee80211_r_names[0].rn_name);\n}\n\nu_int32_t\nieee80211_regdomain2flag(u_int16_t regdomain, u_int16_t mhz)\n{\n\tint i;\n\n\tfor (i = 0; i < (sizeof(ieee80211_r_map) /\n\t\tsizeof(ieee80211_r_map[0])); i++) {\n\t\tif (ieee80211_r_map[i].rm_domain == regdomain) {\n\t\t\tif (mhz >= 2000 && mhz <= 3000)\n\t\t\t\treturn ((u_int32_t)\n\t\t\t\t    ieee80211_r_map[i].rm_domain_2ghz);\n\t\t\tif (mhz >= IEEE80211_CHANNELS_5GHZ_MIN &&\n\t\t\t    mhz <= IEEE80211_CHANNELS_5GHZ_MAX)\n\t\t\t\treturn ((u_int32_t)\n\t\t\t\t    ieee80211_r_map[i].rm_domain_5ghz);\n\t\t}\n\t}\n\n\treturn ((u_int32_t)DMN_DEBUG);\n}\n\nu_int32_t\nieee80211_countrycode2regdomain(u_int16_t code)\n{\n\tint i;\n\n\tfor (i = 0; i < nitems(ieee80211_r_ctry); i++)\n\t\tif (ieee80211_r_ctry[i].cn_code == code)\n\t\t\treturn (ieee80211_r_ctry[i].cn_domain);\n\n\treturn ((u_int32_t)DMN_DEFAULT);\n}\n"
  },
  {
    "path": "itl80211/openbsd/net80211/ieee80211_regdomain.h",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n/*     $OpenBSD: ieee80211_regdomain.h,v 1.9 2016/01/12 09:28:09 stsp Exp $ */\n\n/*\n * Copyright (c) 2004, 2005 Reyk Floeter <reyk@openbsd.org>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n#ifndef _NET80211_IEEE80211_REGDOMAIN_H_\n#define _NET80211_IEEE80211_REGDOMAIN_H_\n\ntypedef u_int32_t ieee80211_regdomain_t;\n\nenum ieee80211_regdomain {\n\tDMN_DEFAULT\t\t= 0x00,\n\tDMN_NULL_WORLD\t\t= 0x03,\n\tDMN_NULL_ETSIB\t\t= 0x07,\n\tDMN_NULL_ETSIC\t\t= 0x08,\n\tDMN_FCC1_FCCA\t\t= 0x10,\n\tDMN_FCC1_WORLD\t\t= 0x11,\n\tDMN_FCC2_FCCA\t\t= 0x20,\n\tDMN_FCC2_WORLD\t\t= 0x21,\n\tDMN_FCC2_ETSIC\t\t= 0x22,\n\tDMN_FRANCE_NULL\t\t= 0x31,\n\tDMN_FCC3_FCCA\t\t= 0x3A,\n\tDMN_ETSI1_WORLD\t\t= 0x37,\n\tDMN_ETSI3_ETSIA\t\t= 0x32,\n\tDMN_ETSI2_WORLD\t\t= 0x35,\n\tDMN_ETSI3_WORLD\t\t= 0x36,\n\tDMN_ETSI4_WORLD\t\t= 0x30,\n\tDMN_ETSI4_ETSIC\t\t= 0x38,\n\tDMN_ETSI5_WORLD\t\t= 0x39,\n\tDMN_ETSI6_WORLD\t\t= 0x34,\n\tDMN_ETSI_NULL\t\t= 0x33,\n\tDMN_MKK1_MKKA\t\t= 0x40,\n\tDMN_MKK1_MKKB\t\t= 0x41,\n\tDMN_APL4_WORLD\t\t= 0x42,\n\tDMN_MKK2_MKKA\t\t= 0x43,\n\tDMN_APL_NULL\t\t= 0x44,\n\tDMN_APL2_WORLD\t\t= 0x45,\n\tDMN_APL2_APLC\t\t= 0x46,\n\tDMN_APL3_WORLD\t\t= 0x47,\n\tDMN_MKK1_FCCA\t\t= 0x48,\n\tDMN_APL2_APLD\t\t= 0x49,\n\tDMN_MKK1_MKKA1\t\t= 0x4A,\n\tDMN_MKK1_MKKA2\t\t= 0x4B,\n\tDMN_APL1_WORLD\t\t= 0x52,\n\tDMN_APL1_FCCA\t\t= 0x53,\n\tDMN_APL1_APLA\t\t= 0x54,\n\tDMN_APL1_ETSIC\t\t= 0x55,\n\tDMN_APL2_ETSIC\t\t= 0x56,\n\tDMN_APL5_WORLD\t\t= 0x58,\n\tDMN_WOR0_WORLD\t\t= 0x60,\n\tDMN_WOR1_WORLD\t\t= 0x61,\n\tDMN_WOR2_WORLD\t\t= 0x62,\n\tDMN_WOR3_WORLD\t\t= 0x63,\n\tDMN_WOR4_WORLD\t\t= 0x64,\n\tDMN_WOR5_ETSIC\t\t= 0x65,\n\tDMN_WOR01_WORLD\t\t= 0x66,\n\tDMN_WOR02_WORLD\t\t= 0x67,\n\tDMN_EU1_WORLD\t\t= 0x68,\n\tDMN_WOR9_WORLD\t\t= 0x69,\n\tDMN_WORA_WORLD\t\t= 0x6A,\n\n\tDMN_APL1\t\t= 0xf0000001,\n\tDMN_APL2\t\t= 0xf0000002,\n\tDMN_APL3\t\t= 0xf0000004,\n\tDMN_APL4\t\t= 0xf0000008,\n\tDMN_APL5\t\t= 0xf0000010,\n\tDMN_ETSI1\t\t= 0xf0000020,\n\tDMN_ETSI2\t\t= 0xf0000040,\n\tDMN_ETSI3\t\t= 0xf0000080,\n\tDMN_ETSI4\t\t= 0xf0000100,\n\tDMN_ETSI5\t\t= 0xf0000200,\n\tDMN_ETSI6\t\t= 0xf0000400,\n\tDMN_ETSIA\t\t= 0xf0000800,\n\tDMN_ETSIB\t\t= 0xf0001000,\n\tDMN_ETSIC\t\t= 0xf0002000,\n\tDMN_FCC1\t\t= 0xf0004000,\n\tDMN_FCC2\t\t= 0xf0008000,\n\tDMN_FCC3\t\t= 0xf0010000,\n\tDMN_FCCA\t\t= 0xf0020000,\n\tDMN_APLD\t\t= 0xf0040000,\n\tDMN_MKK1\t\t= 0xf0080000,\n\tDMN_MKK2\t\t= 0xf0100000,\n\tDMN_MKKA\t\t= 0xf0200000,\n\tDMN_NULL\t\t= 0xf0400000,\n\tDMN_WORLD\t\t= 0xf0800000,\n\tDMN_DEBUG               = 0xf1000000\t/* used for debugging */\n};\n\n#define IEEE80211_DMN(_d)\t((_d) & ~0xf0000000)\n\nstruct ieee80211_regdomainname {\n\tu_int32_t\trn_domain;\n\tconst char\t*rn_name;\n};\n\n#define IEEE80211_REGDOMAIN_NAMES {\t\t\t\t\t\\\n\t{ DMN_APL1,\t\t    \"APL1\" },\t\t\t\t\\\n\t{ DMN_APL1_APLA,\t    \"APL1A\" },\t\t\t\t\\\n\t{ DMN_APL1_ETSIC,\t    \"APL1_ETSIC\" },\t\t\t\\\n\t{ DMN_APL1_FCCA,\t    \"APL1_FCCA\" },\t\t\t\\\n\t{ DMN_APL1_WORLD,\t    \"APL1W\" },\t\t\t\t\\\n\t{ DMN_APL2,\t\t    \"APL2\" },\t\t\t\t\\\n\t{ DMN_APL2_APLC,\t    \"APL2C\" },\t\t\t\t\\\n\t{ DMN_APL2_APLD,\t    \"APL2D\" },\t\t\t\t\\\n\t{ DMN_APL2_ETSIC,\t    \"APL2_ETSIC\" },\t\t\t\\\n\t{ DMN_APL2_WORLD,\t    \"APL2W\" },\t\t\t\t\\\n\t{ DMN_APL3,\t\t    \"APL3\" },\t\t\t\t\\\n\t{ DMN_APL3_WORLD,\t    \"APL3W\" },\t\t\t\t\\\n\t{ DMN_APL4,\t\t    \"APL4\" },\t\t\t\t\\\n\t{ DMN_APL4_WORLD,\t    \"APL4W\" },\t\t\t\t\\\n\t{ DMN_APL5,\t\t    \"APL5\" },\t\t\t\t\\\n\t{ DMN_APL5_WORLD,\t    \"APL5W\" },\t\t\t\t\\\n\t{ DMN_APLD,\t\t    \"APLD\" },\t\t\t\t\\\n\t{ DMN_APL_NULL,\t\t    \"APL\" },\t\t\t\t\\\n\t{ DMN_DEBUG,\t\t    \"DEBUG\" },\t\t\t\t\\\n\t{ DMN_ETSI1,\t\t    \"ETSI1\" },\t\t\t\t\\\n\t{ DMN_ETSI1_WORLD,\t    \"ETSI1W\" },\t\t\t\t\\\n\t{ DMN_ETSI2,\t\t    \"ETSI2\" },\t\t\t\t\\\n\t{ DMN_ETSI2_WORLD,\t    \"ETSI2W\" },\t\t\t\t\\\n\t{ DMN_ETSI3,\t\t    \"ETSI3\" },\t\t\t\t\\\n\t{ DMN_ETSI3_ETSIA,\t    \"ETSI3A\" },\t\t\t\t\\\n\t{ DMN_ETSI3_WORLD,\t    \"ETSI3W,\" },\t\t\t\\\n\t{ DMN_ETSI4,\t\t    \"ETSI4\" },\t\t\t\t\\\n\t{ DMN_ETSI4_ETSIC,\t    \"ETSI4C\" },\t\t\t\t\\\n\t{ DMN_ETSI4_WORLD,\t    \"ETSI4W\" },\t\t\t\t\\\n\t{ DMN_ETSI5,\t\t    \"ETSI5\" },\t\t\t\t\\\n\t{ DMN_ETSI5_WORLD,\t    \"ETSI5W\" },\t\t\t\t\\\n\t{ DMN_ETSI6,\t\t    \"ETSI6\" },\t\t\t\t\\\n\t{ DMN_ETSI6_WORLD,\t    \"ETSI6W\" },\t\t\t\t\\\n\t{ DMN_ETSIA,\t\t    \"ETSIA\" },\t\t\t\t\\\n\t{ DMN_ETSIB,\t\t    \"ETSIB\" },\t\t\t\t\\\n\t{ DMN_ETSIC,\t\t    \"ETSIC\" },\t\t\t\t\\\n\t{ DMN_ETSI_NULL,\t    \"ETSI\" },\t\t\t\t\\\n\t{ DMN_EU1_WORLD,\t    \"EU1W\" },\t\t\t\t\\\n\t{ DMN_FCC1,\t\t    \"FCC1\" },\t\t\t\t\\\n\t{ DMN_FCC1_FCCA,\t    \"FCC1A\" },\t\t\t\t\\\n\t{ DMN_FCC1_WORLD,\t    \"FCC1W\" },\t\t\t\t\\\n\t{ DMN_FCC2,\t\t    \"FCC2\" },\t\t\t\t\\\n\t{ DMN_FCC2_ETSIC,\t    \"FCC2C\" },\t\t\t\t\\\n\t{ DMN_FCC2_FCCA,\t    \"FCC2A\" },\t\t\t\t\\\n\t{ DMN_FCC2_WORLD,\t    \"FCC2W\" },\t\t\t\t\\\n\t{ DMN_FCC3,\t\t    \"FCC3\" },\t\t\t\t\\\n\t{ DMN_FCC3_FCCA,\t    \"FCC3A\" },\t\t\t\t\\\n\t{ DMN_FCCA,\t\t    \"FCCA\" },\t\t\t\t\\\n\t{ DMN_FRANCE_NULL,\t    \"FRANCE\" },\t\t\t\t\\\n\t{ DMN_MKK1,\t\t    \"MKK1\" },\t\t\t\t\\\n\t{ DMN_MKK1_FCCA,\t    \"MKK1_FCCA\" },\t\t\t\\\n\t{ DMN_MKK1_MKKA,\t    \"MKK1A\" },\t\t\t\t\\\n\t{ DMN_MKK1_MKKA1,\t    \"MKK1A1\" },\t\t\t\t\\\n\t{ DMN_MKK1_MKKA2,\t    \"MKK1A2\" },\t\t\t\t\\\n\t{ DMN_MKK1_MKKB,\t    \"MKK1B\" },\t\t\t\t\\\n\t{ DMN_MKK2,\t\t    \"MKK2\" },\t\t\t\t\\\n\t{ DMN_MKK2_MKKA,\t    \"MKK2A\" },\t\t\t\t\\\n\t{ DMN_MKKA,\t\t    \"MKKA\" },\t\t\t\t\\\n\t{ DMN_DEFAULT,\t\t    \"NONE\" },\t\t\t\t\\\n\t{ DMN_NULL,\t\t    \"NONE\" },\t\t\t\t\\\n\t{ DMN_NULL_ETSIB,\t    \"ETSIB\" },\t\t\t\t\\\n\t{ DMN_NULL_ETSIC,\t    \"ETSIC\" },\t\t\t\t\\\n\t{ DMN_WOR01_WORLD,\t    \"WOR01W\" },\t\t\t\t\\\n\t{ DMN_WOR02_WORLD,\t    \"WOR02W\" },\t\t\t\t\\\n\t{ DMN_WOR0_WORLD,\t    \"WOR0W\" },\t\t\t\t\\\n\t{ DMN_WOR1_WORLD,\t    \"WOR1W\" },\t\t\t\t\\\n\t{ DMN_WOR2_WORLD,\t    \"WOR2W\" },\t\t\t\t\\\n\t{ DMN_WOR3_WORLD,\t    \"WOR3W\" },\t\t\t\t\\\n\t{ DMN_WOR4_WORLD,\t    \"WOR4W\" },\t\t\t\t\\\n\t{ DMN_WOR5_ETSIC,\t    \"WOR5_ETSIC\" },\t\t\t\\\n\t{ DMN_WOR9_WORLD,\t    \"WOR9W\" },\t\t\t\t\\\n\t{ DMN_WORA_WORLD,\t    \"WORAW\" },\t\t\t\t\\\n\t{ DMN_NULL_WORLD,\t    \"WORLD\" },\t\t\t\t\\\n\t{ DMN_WORLD,\t\t    \"WORLD\" }\t\t\t\t\\\n}\n\nstruct ieee80211_regdomainmap {\n\tu_int16_t\trm_domain;\n\tu_int32_t\trm_domain_5ghz;\n\tu_int32_t\trm_domain_2ghz;\n};\n\n#define IEEE80211_REGDOMAIN_MAP {\t\t\t\t\t\\\n\t{ DMN_DEFAULT,\t\tDMN_DEBUG,\tDMN_DEBUG },\t\t\\\n\t{ DMN_NULL_WORLD,\tDMN_NULL,\tDMN_WORLD },\t\t\\\n\t{ DMN_NULL_ETSIB,\tDMN_NULL,\tDMN_ETSIB },\t\t\\\n\t{ DMN_NULL_ETSIC,\tDMN_NULL,\tDMN_ETSIC },\t\t\\\n\t{ DMN_FCC1_FCCA,\tDMN_FCC1,\tDMN_FCCA },\t\t\\\n\t{ DMN_FCC1_WORLD,\tDMN_FCC1,\tDMN_WORLD },\t\t\\\n\t{ DMN_FCC2_FCCA,\tDMN_FCC2,\tDMN_FCCA },\t\t\\\n\t{ DMN_FCC2_WORLD,\tDMN_FCC2,\tDMN_WORLD },\t\t\\\n\t{ DMN_FCC2_ETSIC,\tDMN_FCC2,\tDMN_ETSIC },\t\t\\\n\t{ DMN_FRANCE_NULL,\tDMN_ETSI3,\tDMN_ETSI3 },\t\t\\\n\t{ DMN_FCC3_FCCA,\tDMN_FCC3,\tDMN_WORLD },\t\t\\\n\t{ DMN_ETSI1_WORLD,\tDMN_ETSI1,\tDMN_WORLD },\t\t\\\n\t{ DMN_ETSI3_ETSIA,\tDMN_ETSI3,\tDMN_WORLD },\t\t\\\n\t{ DMN_ETSI2_WORLD,\tDMN_ETSI2,\tDMN_WORLD },\t\t\\\n\t{ DMN_ETSI3_WORLD,\tDMN_ETSI3,\tDMN_WORLD },\t\t\\\n\t{ DMN_ETSI4_WORLD,\tDMN_ETSI4,\tDMN_WORLD },\t\t\\\n\t{ DMN_ETSI4_ETSIC,\tDMN_ETSI4,\tDMN_ETSIC },\t\t\\\n\t{ DMN_ETSI5_WORLD,\tDMN_ETSI5,\tDMN_WORLD },\t\t\\\n\t{ DMN_ETSI6_WORLD,\tDMN_ETSI6,\tDMN_WORLD },\t\t\\\n\t{ DMN_ETSI_NULL,\tDMN_ETSI1,\tDMN_ETSI1 },\t\t\\\n\t{ DMN_MKK1_MKKA,\tDMN_MKK1,\tDMN_MKKA },\t\t\\\n\t{ DMN_MKK1_MKKB,\tDMN_MKK1,\tDMN_MKKA },\t\t\\\n\t{ DMN_APL4_WORLD,\tDMN_APL4,\tDMN_WORLD },\t\t\\\n\t{ DMN_MKK2_MKKA,\tDMN_MKK2,\tDMN_MKKA },\t\t\\\n\t{ DMN_APL_NULL,\t\tDMN_APL1,\tDMN_NULL },\t\t\\\n\t{ DMN_APL2_WORLD,\tDMN_APL2,\tDMN_WORLD },\t\t\\\n\t{ DMN_APL2_APLC,\tDMN_APL2,\tDMN_WORLD },\t\t\\\n\t{ DMN_APL3_WORLD,\tDMN_APL3,\tDMN_WORLD },\t\t\\\n\t{ DMN_MKK1_FCCA,\tDMN_MKK1,\tDMN_FCCA },\t\t\\\n\t{ DMN_APL2_APLD,\tDMN_APL2,\tDMN_APLD },\t\t\\\n\t{ DMN_MKK1_MKKA1,\tDMN_MKK1,\tDMN_MKKA },\t\t\\\n\t{ DMN_MKK1_MKKA2,\tDMN_MKK1,\tDMN_MKKA },\t\t\\\n\t{ DMN_APL1_WORLD,\tDMN_APL1,\tDMN_WORLD },\t\t\\\n\t{ DMN_APL1_FCCA,\tDMN_APL1,\tDMN_FCCA },\t\t\\\n\t{ DMN_APL1_APLA,\tDMN_APL1,\tDMN_WORLD },\t\t\\\n\t{ DMN_APL1_ETSIC,\tDMN_APL1,\tDMN_ETSIC },\t\t\\\n\t{ DMN_APL2_ETSIC,\tDMN_APL2,\tDMN_ETSIC },\t\t\\\n\t{ DMN_APL5_WORLD,\tDMN_APL5,\tDMN_WORLD },\t\t\\\n\t{ DMN_WOR0_WORLD,\tDMN_WORLD,\tDMN_WORLD },\t\t\\\n\t{ DMN_WOR1_WORLD,\tDMN_WORLD,\tDMN_WORLD },\t\t\\\n\t{ DMN_WOR2_WORLD,\tDMN_WORLD,\tDMN_WORLD },\t\t\\\n\t{ DMN_WOR3_WORLD,\tDMN_WORLD,\tDMN_WORLD },\t\t\\\n\t{ DMN_WOR4_WORLD,\tDMN_WORLD,\tDMN_WORLD },\t\t\\\n\t{ DMN_WOR5_ETSIC,\tDMN_WORLD,\tDMN_WORLD },\t\t\\\n\t{ DMN_WOR01_WORLD,\tDMN_WORLD,\tDMN_WORLD },\t\t\\\n\t{ DMN_WOR02_WORLD,\tDMN_WORLD,\tDMN_WORLD },\t\t\\\n\t{ DMN_EU1_WORLD,\tDMN_ETSI1,\tDMN_WORLD },\t\t\\\n\t{ DMN_WOR9_WORLD,\tDMN_WORLD,\tDMN_WORLD },\t\t\\\n\t{ DMN_WORA_WORLD,\tDMN_WORLD,\tDMN_WORLD },\t\t\\\n}\n\nenum ieee80211_countrycode {\n\tCTRY_DEFAULT            = 0,   /* Default domain (NA) */\n\tCTRY_ALBANIA            = 8,   /* Albania */\n\tCTRY_ALGERIA            = 12,  /* Algeria */\n\tCTRY_ARGENTINA          = 32,  /* Argentina */\n\tCTRY_ARMENIA            = 51,  /* Armenia */\n\tCTRY_AUSTRALIA          = 36,  /* Australia */\n\tCTRY_AUSTRIA            = 40,  /* Austria */\n\tCTRY_AZERBAIJAN         = 31,  /* Azerbaijan */\n\tCTRY_BAHRAIN            = 48,  /* Bahrain */\n\tCTRY_BELARUS            = 112, /* Belarus */\n\tCTRY_BELGIUM            = 56,  /* Belgium */\n\tCTRY_BELIZE             = 84,  /* Belize */\n\tCTRY_BOLIVIA            = 68,  /* Bolivia */\n\tCTRY_BRAZIL             = 76,  /* Brazil */\n\tCTRY_BRUNEI_DARUSSALAM  = 96,  /* Brunei Darussalam */\n\tCTRY_BULGARIA           = 100, /* Bulgaria */\n\tCTRY_CANADA             = 124, /* Canada */\n\tCTRY_CHILE              = 152, /* Chile */\n\tCTRY_CHINA              = 156, /* People's Republic of China */\n\tCTRY_COLOMBIA           = 170, /* Colombia */\n\tCTRY_COSTA_RICA         = 188, /* Costa Rica */\n\tCTRY_CROATIA            = 191, /* Croatia */\n\tCTRY_CYPRUS             = 196, /* Cyprus */\n\tCTRY_CZECH              = 203, /* Czech Republic */\n\tCTRY_DENMARK            = 208, /* Denmark */\n\tCTRY_DOMINICAN_REPUBLIC = 214, /* Dominican Republic */\n\tCTRY_ECUADOR            = 218, /* Ecuador */\n\tCTRY_EGYPT              = 818, /* Egypt */\n\tCTRY_EL_SALVADOR        = 222, /* El Salvador */\n\tCTRY_ESTONIA            = 233, /* Estonia */\n\tCTRY_FAEROE_ISLANDS     = 234, /* Faeroe Islands */\n\tCTRY_FINLAND            = 246, /* Finland */\n\tCTRY_FRANCE             = 250, /* France */\n\tCTRY_FRANCE2            = 255, /* France2 */\n\tCTRY_GEORGIA            = 268, /* Georgia */\n\tCTRY_GERMANY            = 276, /* Germany */\n\tCTRY_GREECE             = 300, /* Greece */\n\tCTRY_GUATEMALA          = 320, /* Guatemala */\n\tCTRY_HONDURAS           = 340, /* Honduras */\n\tCTRY_HONG_KONG          = 344, /* Hong Kong S.A.R., P.R.C. */\n\tCTRY_HUNGARY            = 348, /* Hungary */\n\tCTRY_ICELAND            = 352, /* Iceland */\n\tCTRY_INDIA              = 356, /* India */\n\tCTRY_INDONESIA          = 360, /* Indonesia */\n\tCTRY_IRAN               = 364, /* Iran */\n\tCTRY_IRAQ               = 368, /* Iraq */\n\tCTRY_IRELAND            = 372, /* Ireland */\n\tCTRY_ISRAEL             = 376, /* Israel */\n\tCTRY_ITALY              = 380, /* Italy */\n\tCTRY_JAMAICA            = 388, /* Jamaica */\n\tCTRY_JAPAN              = 392, /* Japan */\n\tCTRY_JAPAN1             = 393, /* Japan (JP1) */\n\tCTRY_JAPAN2             = 394, /* Japan (JP0) */\n\tCTRY_JAPAN3             = 395, /* Japan (JP1-1) */\n\tCTRY_JAPAN4             = 396, /* Japan (JE1) */\n\tCTRY_JAPAN5             = 397, /* Japan (JE2) */\n\tCTRY_JORDAN             = 400, /* Jordan */\n\tCTRY_KAZAKHSTAN         = 398, /* Kazakhstan */\n\tCTRY_KENYA              = 404, /* Kenya */\n\tCTRY_KOREA_NORTH        = 408, /* North Korea */\n\tCTRY_KOREA_ROC          = 410, /* South Korea */\n\tCTRY_KOREA_ROC2         = 411, /* South Korea */\n\tCTRY_KUWAIT             = 414, /* Kuwait */\n\tCTRY_LATVIA             = 428, /* Latvia */\n\tCTRY_LEBANON            = 422, /* Lebanon */\n\tCTRY_LIBYA              = 434, /* Libya */\n\tCTRY_LIECHTENSTEIN      = 438, /* Liechtenstein */\n\tCTRY_LITHUANIA          = 440, /* Lithuania */\n\tCTRY_LUXEMBOURG         = 442, /* Luxembourg */\n\tCTRY_MACAU              = 446, /* Macau */\n\tCTRY_MACEDONIA          = 807, /* Republic of Macedonia */\n\tCTRY_MALAYSIA           = 458, /* Malaysia */\n\tCTRY_MEXICO             = 484, /* Mexico */\n\tCTRY_MONACO             = 492, /* Principality of Monaco */\n\tCTRY_MOROCCO            = 504, /* Morocco */\n\tCTRY_NETHERLANDS        = 528, /* Netherlands */\n\tCTRY_NEW_ZEALAND        = 554, /* New Zealand */\n\tCTRY_NICARAGUA          = 558, /* Nicaragua */\n\tCTRY_NORWAY             = 578, /* Norway */\n\tCTRY_OMAN               = 512, /* Oman */\n\tCTRY_PAKISTAN           = 586, /* Islamic Republic of Pakistan */\n\tCTRY_PANAMA             = 591, /* Panama */\n\tCTRY_PARAGUAY           = 600, /* Paraguay */\n\tCTRY_PERU               = 604, /* Peru */\n\tCTRY_PHILIPPINES        = 608, /* Republic of the Philippines */\n\tCTRY_POLAND             = 616, /* Poland */\n\tCTRY_PORTUGAL           = 620, /* Portugal */\n\tCTRY_PUERTO_RICO        = 630, /* Puerto Rico */\n\tCTRY_QATAR              = 634, /* Qatar */\n\tCTRY_ROMANIA            = 642, /* Romania */\n\tCTRY_RUSSIA             = 643, /* Russia */\n\tCTRY_SAUDI_ARABIA       = 682, /* Saudi Arabia */\n\tCTRY_SINGAPORE          = 702, /* Singapore */\n\tCTRY_SLOVAKIA           = 703, /* Slovak Republic */\n\tCTRY_SLOVENIA           = 705, /* Slovenia */\n\tCTRY_SOUTH_AFRICA       = 710, /* South Africa */\n\tCTRY_SPAIN              = 724, /* Spain */\n\tCTRY_SRI_LANKA          = 728, /* Sri Lanka */\n\tCTRY_SWEDEN             = 752, /* Sweden */\n\tCTRY_SWITZERLAND        = 756, /* Switzerland */\n\tCTRY_SYRIA              = 760, /* Syria */\n\tCTRY_TAIWAN             = 158, /* Taiwan */\n\tCTRY_THAILAND           = 764, /* Thailand */\n\tCTRY_TRINIDAD_Y_TOBAGO  = 780, /* Trinidad y Tobago */\n\tCTRY_TUNISIA            = 788, /* Tunisia */\n\tCTRY_TURKEY             = 792, /* Turkey */\n\tCTRY_UAE                = 784, /* U.A.E. */\n\tCTRY_UKRAINE            = 804, /* Ukraine */\n\tCTRY_UNITED_KINGDOM     = 826, /* United Kingdom */\n\tCTRY_UNITED_STATES      = 840, /* United States */\n\tCTRY_URUGUAY            = 858, /* Uruguay */\n\tCTRY_UZBEKISTAN         = 860, /* Uzbekistan */\n\tCTRY_VENEZUELA          = 862, /* Venezuela */\n\tCTRY_VIET_NAM           = 704, /* Viet Nam */\n\tCTRY_YEMEN              = 887, /* Yemen */\n\tCTRY_ZIMBABWE           = 716, /* Zimbabwe */\n};\n\nstruct ieee80211_countryname {\n\tu_int16_t\tcn_code;\n\tconst char\t*cn_name;\n\tu_int32_t\tcn_domain;\n};\n\n#define IEEE80211_REGDOMAIN_COUNTRY_NAMES {\t\t\t\t\\\n\t{ CTRY_DEFAULT,            \"00\", DMN_DEFAULT },\t\t\t\\\n\t{ CTRY_UAE,                \"ae\", DMN_NULL_WORLD },\t\t\\\n\t{ CTRY_ALBANIA,            \"al\", DMN_NULL_WORLD },\t\t\\\n\t{ CTRY_ARMENIA,            \"am\", DMN_ETSI4_WORLD },\t\t\\\n\t{ CTRY_ARGENTINA,          \"ar\", DMN_APL3_WORLD },\t\t\\\n\t{ CTRY_AUSTRIA,            \"at\", DMN_ETSI5_WORLD },\t\t\\\n\t{ CTRY_AUSTRALIA,          \"au\", DMN_FCC2_WORLD },\t\t\\\n\t{ CTRY_AZERBAIJAN,         \"az\", DMN_ETSI4_WORLD },\t\t\\\n\t{ CTRY_BELGIUM,            \"be\", DMN_ETSI4_WORLD },\t\t\\\n\t{ CTRY_BULGARIA,           \"bg\", DMN_ETSI6_WORLD },\t\t\\\n\t{ CTRY_BAHRAIN,            \"bh\", DMN_NULL_WORLD },\t\t\\\n\t{ CTRY_BRUNEI_DARUSSALAM,  \"bn\", DMN_APL1_WORLD },\t\t\\\n\t{ CTRY_BOLIVIA,            \"bo\", DMN_APL1_ETSIC },\t\t\\\n\t{ CTRY_BRAZIL,             \"br\", DMN_NULL_ETSIC },\t\t\\\n\t{ CTRY_BELARUS,            \"by\", DMN_NULL_WORLD },\t\t\\\n\t{ CTRY_BELIZE,             \"bz\", DMN_NULL_ETSIC },\t\t\\\n\t{ CTRY_CANADA,             \"ca\", DMN_FCC2_FCCA },\t\t\\\n\t{ CTRY_SWITZERLAND,        \"ch\", DMN_ETSI2_WORLD },\t\t\\\n\t{ CTRY_CHILE,              \"cl\", DMN_APL5_WORLD },\t\t\\\n\t{ CTRY_CHINA,              \"cn\", DMN_APL1_WORLD },\t\t\\\n\t{ CTRY_COLOMBIA,           \"co\", DMN_FCC1_FCCA },\t\t\\\n\t{ CTRY_COSTA_RICA,         \"cr\", DMN_NULL_WORLD },\t\t\\\n\t{ CTRY_CYPRUS,             \"cy\", DMN_ETSI1_WORLD },\t\t\\\n\t{ CTRY_CZECH,              \"cz\", DMN_ETSI3_WORLD },\t\t\\\n\t{ CTRY_GERMANY,            \"de\", DMN_ETSI1_WORLD },\t\t\\\n\t{ CTRY_DENMARK,            \"dk\", DMN_ETSI1_WORLD },\t\t\\\n\t{ CTRY_DOMINICAN_REPUBLIC, \"do\", DMN_FCC1_FCCA },\t\t\\\n\t{ CTRY_ALGERIA,            \"dz\", DMN_NULL_WORLD },\t\t\\\n\t{ CTRY_ECUADOR,            \"ec\", DMN_NULL_WORLD },\t\t\\\n\t{ CTRY_ESTONIA,            \"ee\", DMN_ETSI1_WORLD },\t\t\\\n\t{ CTRY_EGYPT,              \"eg\", DMN_NULL_WORLD },\t\t\\\n\t{ CTRY_SPAIN,              \"es\", DMN_ETSI1_WORLD },\t\t\\\n\t{ CTRY_FRANCE2,            \"f2\", DMN_ETSI3_WORLD },\t\t\\\n\t{ CTRY_FINLAND,            \"fi\", DMN_ETSI1_WORLD },\t\t\\\n\t{ CTRY_FAEROE_ISLANDS,     \"fo\", DMN_NULL_WORLD },\t\t\\\n\t{ CTRY_FRANCE,             \"fr\", DMN_ETSI3_WORLD },\t\t\\\n\t{ CTRY_GEORGIA,            \"ge\", DMN_ETSI4_WORLD },\t\t\\\n\t{ CTRY_GREECE,             \"gr\", DMN_NULL_WORLD },\t\t\\\n\t{ CTRY_GUATEMALA,          \"gt\", DMN_FCC1_FCCA },\t\t\\\n\t{ CTRY_HONG_KONG,          \"hk\", DMN_FCC2_WORLD },\t\t\\\n\t{ CTRY_HONDURAS,           \"hn\", DMN_NULL_WORLD },\t\t\\\n\t{ CTRY_CROATIA,            \"hr\", DMN_ETSI3_WORLD },\t\t\\\n\t{ CTRY_HUNGARY,            \"hu\", DMN_ETSI2_WORLD },\t\t\\\n\t{ CTRY_INDONESIA,          \"id\", DMN_NULL_WORLD },\t\t\\\n\t{ CTRY_IRELAND,            \"ie\", DMN_ETSI1_WORLD },\t\t\\\n\t{ CTRY_ISRAEL,             \"il\", DMN_NULL_WORLD },\t\t\\\n\t{ CTRY_INDIA,              \"in\", DMN_NULL_WORLD },\t\t\\\n\t{ CTRY_IRAQ,               \"iq\", DMN_NULL_WORLD },\t\t\\\n\t{ CTRY_IRAN,               \"ir\", DMN_APL1_WORLD },\t\t\\\n\t{ CTRY_ICELAND,            \"is\", DMN_ETSI1_WORLD },\t\t\\\n\t{ CTRY_ITALY,              \"it\", DMN_ETSI1_WORLD },\t\t\\\n\t{ CTRY_JAPAN1,             \"j1\", DMN_MKK1_MKKB },\t\t\\\n\t{ CTRY_JAPAN2,             \"j2\", DMN_MKK1_FCCA },\t\t\\\n\t{ CTRY_JAPAN3,             \"j3\", DMN_MKK2_MKKA },\t\t\\\n\t{ CTRY_JAPAN4,             \"j4\", DMN_MKK1_MKKA1 },\t\t\\\n\t{ CTRY_JAPAN5,             \"j5\", DMN_MKK1_MKKA2 },\t\t\\\n\t{ CTRY_JAMAICA,            \"jm\", DMN_NULL_WORLD },\t\t\\\n\t{ CTRY_JORDAN,             \"jo\", DMN_NULL_WORLD },\t\t\\\n\t{ CTRY_JAPAN,              \"jp\", DMN_MKK1_MKKA },\t\t\\\n\t{ CTRY_KOREA_ROC2,         \"k2\", DMN_APL2_APLD },\t\t\\\n\t{ CTRY_KENYA,              \"ke\", DMN_NULL_WORLD },\t\t\\\n\t{ CTRY_KOREA_NORTH,        \"kp\", DMN_APL2_WORLD },\t\t\\\n\t{ CTRY_KOREA_ROC,          \"kr\", DMN_APL2_WORLD },\t\t\\\n\t{ CTRY_KUWAIT,             \"kw\", DMN_NULL_WORLD },\t\t\\\n\t{ CTRY_KAZAKHSTAN,         \"kz\", DMN_NULL_WORLD },\t\t\\\n\t{ CTRY_LEBANON,            \"lb\", DMN_NULL_WORLD },\t\t\\\n\t{ CTRY_LIECHTENSTEIN,      \"li\", DMN_ETSI2_WORLD },\t\t\\\n\t{ CTRY_SRI_LANKA,          \"lk\", DMN_NULL_WORLD },\t\t\\\n\t{ CTRY_LITHUANIA,          \"lt\", DMN_ETSI1_WORLD },\t\t\\\n\t{ CTRY_LUXEMBOURG,         \"lu\", DMN_ETSI1_WORLD },\t\t\\\n\t{ CTRY_LATVIA,             \"lv\", DMN_NULL_WORLD },\t\t\\\n\t{ CTRY_LIBYA,              \"ly\", DMN_NULL_WORLD },\t\t\\\n\t{ CTRY_MOROCCO,            \"ma\", DMN_NULL_WORLD },\t\t\\\n\t{ CTRY_MONACO,             \"mc\", DMN_ETSI4_WORLD },\t\t\\\n\t{ CTRY_MACEDONIA,          \"mk\", DMN_NULL_WORLD },\t\t\\\n\t{ CTRY_MACAU,              \"mo\", DMN_FCC2_WORLD },\t\t\\\n\t{ CTRY_MEXICO,             \"mx\", DMN_FCC1_FCCA },\t\t\\\n\t{ CTRY_MALAYSIA,           \"my\", DMN_NULL_WORLD },\t\t\\\n\t{ CTRY_NICARAGUA,          \"ni\", DMN_NULL_WORLD },\t\t\\\n\t{ CTRY_NETHERLANDS,        \"nl\", DMN_ETSI1_WORLD },\t\t\\\n\t{ CTRY_NORWAY,             \"no\", DMN_ETSI1_WORLD },\t\t\\\n\t{ CTRY_NEW_ZEALAND,        \"nz\", DMN_FCC2_ETSIC },\t\t\\\n\t{ CTRY_OMAN,               \"om\", DMN_NULL_WORLD },\t\t\\\n\t{ CTRY_PANAMA,             \"pa\", DMN_FCC1_FCCA },\t\t\\\n\t{ CTRY_PERU,               \"pe\", DMN_NULL_WORLD },\t\t\\\n\t{ CTRY_PHILIPPINES,        \"ph\", DMN_FCC1_WORLD },\t\t\\\n\t{ CTRY_PAKISTAN,           \"pk\", DMN_NULL_WORLD },\t\t\\\n\t{ CTRY_POLAND,             \"pl\", DMN_ETSI1_WORLD },\t\t\\\n\t{ CTRY_PUERTO_RICO,        \"pr\", DMN_FCC1_FCCA },\t\t\\\n\t{ CTRY_PORTUGAL,           \"pt\", DMN_ETSI1_WORLD },\t\t\\\n\t{ CTRY_PARAGUAY,           \"py\", DMN_NULL_WORLD },\t\t\\\n\t{ CTRY_QATAR,              \"qa\", DMN_NULL_WORLD },\t\t\\\n\t{ CTRY_ROMANIA,            \"ro\", DMN_NULL_WORLD },\t\t\\\n\t{ CTRY_RUSSIA,             \"ru\", DMN_NULL_WORLD },\t\t\\\n\t{ CTRY_SAUDI_ARABIA,       \"sa\", DMN_NULL_WORLD },\t\t\\\n\t{ CTRY_SWEDEN,             \"se\", DMN_ETSI1_WORLD },\t\t\\\n\t{ CTRY_SINGAPORE,          \"sg\", DMN_APL4_WORLD },\t\t\\\n\t{ CTRY_SLOVENIA,           \"si\", DMN_ETSI1_WORLD },\t\t\\\n\t{ CTRY_SLOVAKIA,           \"sk\", DMN_ETSI3_WORLD },\t\t\\\n\t{ CTRY_EL_SALVADOR,        \"sv\", DMN_NULL_WORLD },\t\t\\\n\t{ CTRY_SYRIA,              \"sy\", DMN_NULL_WORLD },\t\t\\\n\t{ CTRY_THAILAND,           \"th\", DMN_APL2_WORLD },\t\t\\\n\t{ CTRY_TUNISIA,            \"tn\", DMN_ETSI3_WORLD },\t\t\\\n\t{ CTRY_TURKEY,             \"tr\", DMN_ETSI3_WORLD },\t\t\\\n\t{ CTRY_TRINIDAD_Y_TOBAGO,  \"tt\", DMN_ETSI4_WORLD },\t\t\\\n\t{ CTRY_TAIWAN,             \"tw\", DMN_APL3_WORLD },\t\t\\\n\t{ CTRY_UKRAINE,            \"ua\", DMN_NULL_WORLD },\t\t\\\n\t{ CTRY_UNITED_KINGDOM,     \"uk\", DMN_ETSI1_WORLD },\t\t\\\n\t{ CTRY_UNITED_STATES,      \"us\", DMN_FCC1_FCCA },\t\t\\\n\t{ CTRY_URUGUAY,            \"uy\", DMN_APL2_WORLD },\t\t\\\n\t{ CTRY_UZBEKISTAN,         \"uz\", DMN_FCC3_FCCA },\t\t\\\n\t{ CTRY_VENEZUELA,          \"ve\", DMN_APL2_ETSIC },\t\t\\\n\t{ CTRY_VIET_NAM,           \"vn\", DMN_NULL_WORLD },\t\t\\\n\t{ CTRY_YEMEN,              \"ye\", DMN_NULL_WORLD },\t\t\\\n\t{ CTRY_SOUTH_AFRICA,       \"za\", DMN_ETSI1_WORLD },\t\t\\\n\t{ CTRY_ZIMBABWE,           \"zw\", DMN_NULL_WORLD },\t\t\\\n}\n\nenum ieee80211_ctl {\n\tCTL_11A\t\t= 0x00,\n\tCTL_11B\t\t= 0x01,\n\tCTL_11G\t\t= 0x02,\n\tCTL_TURBO\t= 0x03,\n\tCTL_TURBO_G\t= 0x04,\n\tCTL_FCC\t\t= 0x10,\n\tCTL_ETSI\t= 0x30,\n\tCTL_MKK\t\t= 0x40,\n\tCTL_NONE\t= 0xff\n};\n\n#define IEEE80211_CHANNELS_2GHZ_MIN\t2412\t/* 2GHz channel 1 */\n#define IEEE80211_CHANNELS_2GHZ_MAX\t2732\t/* 2GHz channel 26 */\n\nstruct ieee80211_regchannel {\n\tu_int16_t\trc_channel;\n\tu_int32_t\trc_domain;\n\tu_int32_t\trc_mode;\n};\n\n#define IEEE80211_CHANNELS_2GHZ {\t\t\t\t\t\\\n\t{ 2412, DMN_APLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2417, DMN_APLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2422, DMN_APLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2427, DMN_APLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2432, DMN_APLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2437, DMN_APLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2442, DMN_APLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2447, DMN_APLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2452, DMN_APLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2457, DMN_APLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2462, DMN_APLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2467, DMN_APLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2472, DMN_APLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t{ 2432, DMN_ETSIB, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2442, DMN_ETSIB, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t{ 2412, DMN_ETSIC, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2417, DMN_ETSIC, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2422, DMN_ETSIC, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2427, DMN_ETSIC, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2432, DMN_ETSIC, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2442, DMN_ETSIC, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2447, DMN_ETSIC, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2452, DMN_ETSIC, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2457, DMN_ETSIC, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2462, DMN_ETSIC, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2467, DMN_ETSIC, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2472, DMN_ETSIC, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t{ 2412, DMN_FCCA, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2417, DMN_FCCA, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2422, DMN_FCCA, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2427, DMN_FCCA, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2432, DMN_FCCA, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2442, DMN_FCCA, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2447, DMN_FCCA, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2452, DMN_FCCA, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2457, DMN_FCCA, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2462, DMN_FCCA, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t{ 2412, DMN_MKKA, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2417, DMN_MKKA, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2422, DMN_MKKA, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2427, DMN_MKKA, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2432, DMN_MKKA, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2437, DMN_MKKA, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2442, DMN_MKKA, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2447, DMN_MKKA, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2452, DMN_MKKA, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2457, DMN_MKKA, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2462, DMN_MKKA, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2467, DMN_MKKA, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2472, DMN_MKKA, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2484, DMN_MKKA, IEEE80211_CHAN_CCK },\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t{ 2412, DMN_WORLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2417, DMN_WORLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2422, DMN_WORLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2427, DMN_WORLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2432, DMN_WORLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2442, DMN_WORLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2447, DMN_WORLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2452, DMN_WORLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2457, DMN_WORLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2462, DMN_WORLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2467, DMN_WORLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n\t{ 2472, DMN_WORLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM },\t\\\n}\n\n#define IEEE80211_CHANNELS_5GHZ_MIN\t5005\t/* 5GHz channel 1 */\n#define IEEE80211_CHANNELS_5GHZ_MAX\t6100\t/* 5GHz channel 220 */\n\n#define IEEE80211_CHANNELS_5GHZ {\t\t\t\t\t\\\n\t{ 5745, DMN_APL1, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5765, DMN_APL1, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5785, DMN_APL1, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5805, DMN_APL1, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5825, DMN_APL1, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t{ 5745, DMN_APL2, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5765, DMN_APL2, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5785, DMN_APL2, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5805, DMN_APL2, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t{ 5280, DMN_APL3, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5300, DMN_APL3, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5320, DMN_APL3, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5745, DMN_APL3, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5765, DMN_APL3, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5785, DMN_APL3, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5805, DMN_APL3, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t{ 5180, DMN_APL4, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5200, DMN_APL4, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5220, DMN_APL4, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5240, DMN_APL4, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5745, DMN_APL4, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5765, DMN_APL4, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5785, DMN_APL4, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5805, DMN_APL4, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5825, DMN_APL4, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t{ 5745, DMN_APL5, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5765, DMN_APL5, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5785, DMN_APL5, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5805, DMN_APL5, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5825, DMN_APL5, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t{ 5180, DMN_ETSI1, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5200, DMN_ETSI1, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5220, DMN_ETSI1, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5240, DMN_ETSI1, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5260, DMN_ETSI1, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5280, DMN_ETSI1, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5300, DMN_ETSI1, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5320, DMN_ETSI1, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5500, DMN_ETSI1, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5520, DMN_ETSI1, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5540, DMN_ETSI1, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5560, DMN_ETSI1, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5580, DMN_ETSI1, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5600, DMN_ETSI1, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5620, DMN_ETSI1, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5640, DMN_ETSI1, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5660, DMN_ETSI1, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5680, DMN_ETSI1, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5700, DMN_ETSI1, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t{ 5180, DMN_ETSI2, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5200, DMN_ETSI2, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5220, DMN_ETSI2, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5240, DMN_ETSI2, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t{ 5180, DMN_ETSI3, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5200, DMN_ETSI3, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5220, DMN_ETSI3, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5240, DMN_ETSI3, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5260, DMN_ETSI3, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5280, DMN_ETSI3, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5300, DMN_ETSI3, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5320, DMN_ETSI3, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t{ 5180, DMN_ETSI4, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5200, DMN_ETSI4, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5220, DMN_ETSI4, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5240, DMN_ETSI4, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5260, DMN_ETSI4, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5280, DMN_ETSI4, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5300, DMN_ETSI4, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5320, DMN_ETSI4, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t{ 5180, DMN_ETSI5, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5200, DMN_ETSI5, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5220, DMN_ETSI5, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5240, DMN_ETSI5, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t{ 5180, DMN_ETSI6, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5200, DMN_ETSI6, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5220, DMN_ETSI6, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5240, DMN_ETSI6, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5260, DMN_ETSI6, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5280, DMN_ETSI6, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5500, DMN_ETSI6, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5520, DMN_ETSI6, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5540, DMN_ETSI6, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5560, DMN_ETSI6, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5580, DMN_ETSI6, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5600, DMN_ETSI6, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5620, DMN_ETSI6, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5640, DMN_ETSI6, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5660, DMN_ETSI6, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5680, DMN_ETSI6, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5700, DMN_ETSI6, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t{ 5180, DMN_FCC1, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5200, DMN_FCC1, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5220, DMN_FCC1, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5240, DMN_FCC1, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5260, DMN_FCC1, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5280, DMN_FCC1, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5300, DMN_FCC1, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5320, DMN_FCC1, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5745, DMN_FCC1, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5765, DMN_FCC1, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5785, DMN_FCC1, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5805, DMN_FCC1, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5825, DMN_FCC1, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t{ 5180, DMN_FCC2, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5200, DMN_FCC2, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5220, DMN_FCC2, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5240, DMN_FCC2, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5260, DMN_FCC2, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5280, DMN_FCC2, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5300, DMN_FCC2, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5320, DMN_FCC2, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5745, DMN_FCC2, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5765, DMN_FCC2, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5785, DMN_FCC2, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5805, DMN_FCC2, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5825, DMN_FCC2, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t{ 5180, DMN_FCC3, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5200, DMN_FCC3, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5220, DMN_FCC3, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5240, DMN_FCC3, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5260, DMN_FCC3, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5280, DMN_FCC3, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5300, DMN_FCC3, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5320, DMN_FCC3, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5500, DMN_FCC3, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5520, DMN_FCC3, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5540, DMN_FCC3, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5560, DMN_FCC3, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5580, DMN_FCC3, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5600, DMN_FCC3, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5620, DMN_FCC3, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5640, DMN_FCC3, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5660, DMN_FCC3, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5680, DMN_FCC3, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5700, DMN_FCC3, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5745, DMN_FCC3, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5765, DMN_FCC3, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5785, DMN_FCC3, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5805, DMN_FCC3, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5825, DMN_FCC3, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t{ 5170, DMN_MKK1, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5190, DMN_MKK1, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5210, DMN_MKK1, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5230, DMN_MKK1, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t{ 5040, DMN_MKK2, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5060, DMN_MKK2, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5080, DMN_MKK2, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5170, DMN_MKK2, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5190, DMN_MKK2, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5210, DMN_MKK2, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5230, DMN_MKK2, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t{ 5180, DMN_WORLD, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5200, DMN_WORLD, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5220, DMN_WORLD, IEEE80211_CHAN_OFDM },\t\t\t\\\n\t{ 5240, DMN_WORLD, IEEE80211_CHAN_OFDM },\t\t\t\\\n}\n\n//__BEGIN_DECLS\n\nextern u_int16_t\t ieee80211_name2countrycode(const char *);\nextern u_int32_t\t ieee80211_name2regdomain(const char *);\nextern const char\t*ieee80211_countrycode2name(u_int16_t);\nextern const char\t*ieee80211_regdomain2name(u_int32_t);\nextern u_int32_t\t ieee80211_regdomain2flag(u_int16_t, u_int16_t);\nextern u_int32_t\t ieee80211_countrycode2regdomain(u_int16_t);\n\n//__END_DECLS\n\n#endif /* _NET80211_IEEE80211_REGDOMAIN_H_ */\n"
  },
  {
    "path": "itl80211/openbsd/net80211/ieee80211_rssadapt.c",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n/*\t$OpenBSD: ieee80211_rssadapt.c,v 1.11 2014/12/23 03:24:08 tedu Exp $\t*/\n/*\t$NetBSD: ieee80211_rssadapt.c,v 1.7 2004/05/25 04:33:59 dyoung Exp $\t*/\n\n/*-\n * Copyright (c) 2003, 2004 David Young.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or\n * without modification, are permitted provided that the following\n * conditions are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above\n *    copyright notice, this list of conditions and the following\n *    disclaimer in the documentation and/or other materials provided\n *    with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY David Young ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,\n * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A\n * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL David\n * Young BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED\n * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY\n * OF SUCH DAMAGE.\n */\n\n#include <sys/param.h>\n#include <sys/systm.h>\n#include <sys/kernel.h>\n#include <sys/socket.h>\n#include <sys/time.h>\n\n#include <net/if.h>\n#include <net/if_media.h>\n\n#include <netinet/in.h>\n#include <netinet/if_ether.h>\n\n#include <net80211/ieee80211_var.h>\n#include <net80211/ieee80211_rssadapt.h>\n\n#ifdef interpolate\n#undef interpolate\n#endif\n#define interpolate(parm, old, new)\t\t\t\t\\\n\t((parm##_old * (old) +\t\t\t\t\t\\\n\t(parm##_denom - parm##_old) * (new)) / parm##_denom)\n\n#ifdef IEEE80211_DEBUG\nstatic\tstruct timeval lastrateadapt;\t/* time of last rate adaptation msg */\nstatic\tint currssadaptps = 0;\t\t/* rate-adaptation msgs this second */\nstatic\tint ieee80211_adaptrate = 4;\t/* rate-adaptation max msgs/sec */\n\n#define RSSADAPT_DO_PRINT() \\\n\t((ieee80211_rssadapt_debug > 0) && \\\n\t ppsratecheck(&lastrateadapt, &currssadaptps, ieee80211_adaptrate))\n#define\tRSSADAPT_PRINTF(X) \\\n\tif (RSSADAPT_DO_PRINT()) \\\n\t\tXYLog X\n\nint ieee80211_rssadapt_debug = 0;\n\n#else\n#define\tRSSADAPT_DO_PRINT() (0)\n#define\tRSSADAPT_PRINTF(X)\n#endif\n\nstatic const struct ieee80211_rssadapt_expavgctl master_expavgctl = {\n\t.rc_decay_denom\t\t= 16,\n\t.rc_decay_old\t\t= 15,\n\t.rc_thresh_denom\t= 8,\n\t.rc_thresh_old\t\t= 4,\n\t.rc_avgrssi_denom\t= 8,\n\t.rc_avgrssi_old\t\t= 4\n};\n\nint\nieee80211_rssadapt_choose(struct ieee80211_rssadapt *ra,\n    const struct ieee80211_rateset *rs, const struct ieee80211_frame *wh,\n    u_int len, int fixed_rate, const char *dvname, int do_not_adapt)\n{\n\tu_int16_t (*thrs)[IEEE80211_RATE_SIZE];\n\tint flags = 0, i, rateidx = 0, thridx, top;\n\n\tif ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL)\n\t\tflags |= IEEE80211_RATE_BASIC;\n\n\tfor (i = 0, top = IEEE80211_RSSADAPT_BKT0;\n\t     i < IEEE80211_RSSADAPT_BKTS;\n\t     i++, top <<= IEEE80211_RSSADAPT_BKTPOWER) {\n\t\tthridx = i;\n\t\tif (len <= top)\n\t\t\tbreak;\n\t}\n\n\tthrs = &ra->ra_rate_thresh[thridx];\n\n\tif (fixed_rate != -1) {\n\t\tif ((rs->rs_rates[fixed_rate] & flags) == flags) {\n\t\t\trateidx = fixed_rate;\n\t\t\tgoto out;\n\t\t}\n\t\tflags |= IEEE80211_RATE_BASIC;\n\t\ti = fixed_rate;\n\t} else\n\t\ti = rs->rs_nrates;\n\n\twhile (--i >= 0) {\n\t\trateidx = i;\n\t\tif ((rs->rs_rates[i] & flags) != flags)\n\t\t\tcontinue;\n\t\tif (do_not_adapt)\n\t\t\tbreak;\n\t\tif ((*thrs)[i] < ra->ra_avg_rssi)\n\t\t\tbreak;\n\t}\n\nout:\n#ifdef IEEE80211_DEBUG\n\tif (ieee80211_rssadapt_debug && dvname != NULL) {\n\t\tXYLog(\"%s: dst %s threshold[%d, %d.%d] %d < %d\\n\",\n\t\t    dvname, ether_sprintf((u_int8_t *)wh->i_addr1), len,\n\t\t    (rs->rs_rates[rateidx] & IEEE80211_RATE_VAL) / 2,\n\t\t    (rs->rs_rates[rateidx] & IEEE80211_RATE_VAL) * 5 % 10,\n\t\t    (*thrs)[rateidx], ra->ra_avg_rssi);\n\t}\n#endif /* IEEE80211_DEBUG */\n\treturn rateidx;\n}\n\nvoid\nieee80211_rssadapt_updatestats(struct ieee80211_rssadapt *ra)\n{\n\tlong interval;\n\n\tra->ra_pktrate =\n\t    (ra->ra_pktrate + 10 * (ra->ra_nfail + ra->ra_nok)) / 2;\n\tra->ra_nfail = ra->ra_nok = 0;\n\n\t/* a node is eligible for its rate to be raised every 1/10 to 10\n\t * seconds, more eligible in proportion to recent packet rates.\n\t */\n\tinterval = MAX(100000, 10000000 / MAX(1, 10 * ra->ra_pktrate));\n\tra->ra_raise_interval.tv_sec = interval / (1000 * 1000);\n\tra->ra_raise_interval.tv_usec = interval % (1000 * 1000);\n}\n\nvoid\nieee80211_rssadapt_input(struct ieee80211com *ic,\n    const struct ieee80211_node *ni, struct ieee80211_rssadapt *ra, int rssi)\n{\n#ifdef IEEE80211_DEBUG\n\tint last_avg_rssi = ra->ra_avg_rssi;\n#endif\n\n\tra->ra_avg_rssi = interpolate(master_expavgctl.rc_avgrssi,\n\t    ra->ra_avg_rssi, (rssi << 8));\n\n\tRSSADAPT_PRINTF((\"%s: src %s rssi %d avg %d -> %d\\n\",\n\t    ic->ic_if.if_xname, ether_sprintf((u_int8_t *)ni->ni_macaddr),\n\t    rssi, last_avg_rssi, ra->ra_avg_rssi));\n}\n\n/*\n * Adapt the data rate to suit the conditions.  When a transmitted\n * packet is dropped after IEEE80211_RSSADAPT_RETRY_LIMIT retransmissions,\n * raise the RSS threshold for transmitting packets of similar length at\n * the same data rate.\n */\nvoid\nieee80211_rssadapt_lower_rate(struct ieee80211com *ic,\n    const struct ieee80211_node *ni, struct ieee80211_rssadapt *ra,\n    const struct ieee80211_rssdesc *id)\n{\n\tconst struct ieee80211_rateset *rs = &ni->ni_rates;\n\tu_int16_t last_thr;\n\tu_int i, thridx, top;\n\n\tra->ra_nfail++;\n\n\tif (id->id_rateidx >= rs->rs_nrates) {\n\t\tRSSADAPT_PRINTF((\"ieee80211_rssadapt_lower_rate: \"\n\t\t    \"%s rate #%d > #%d out of bounds\\n\",\n\t\t    ether_sprintf((u_int8_t *)ni->ni_macaddr), id->id_rateidx,\n\t\t    rs->rs_nrates - 1));\n\t\treturn;\n\t}\n\n\tfor (i = 0, top = IEEE80211_RSSADAPT_BKT0;\n\t     i < IEEE80211_RSSADAPT_BKTS;\n\t     i++, top <<= IEEE80211_RSSADAPT_BKTPOWER) {\n\t\tthridx = i;\n\t\tif (id->id_len <= top)\n\t\t\tbreak;\n\t}\n\n\tlast_thr = ra->ra_rate_thresh[thridx][id->id_rateidx];\n\tra->ra_rate_thresh[thridx][id->id_rateidx] =\n\t    interpolate(master_expavgctl.rc_thresh, last_thr,\n\t    (id->id_rssi << 8));\n\n\tRSSADAPT_PRINTF((\"%s: dst %s rssi %d threshold[%d, %d.%d] %d -> %d\\n\",\n\t    ic->ic_if.if_xname, ether_sprintf((u_int8_t *)ni->ni_macaddr),\n\t    id->id_rssi, id->id_len,\n\t    (rs->rs_rates[id->id_rateidx] & IEEE80211_RATE_VAL) / 2,\n\t    (rs->rs_rates[id->id_rateidx] & IEEE80211_RATE_VAL) * 5 % 10,\n\t    last_thr, ra->ra_rate_thresh[thridx][id->id_rateidx]));\n}\n\nvoid\nieee80211_rssadapt_raise_rate(struct ieee80211com *ic,\n    struct ieee80211_rssadapt *ra, const struct ieee80211_rssdesc *id)\n{\n\tu_int16_t (*thrs)[IEEE80211_RATE_SIZE], newthr, oldthr;\n\tconst struct ieee80211_node *ni = id->id_node;\n\tconst struct ieee80211_rateset *rs = &ni->ni_rates;\n\tint i, rate, top;\n#ifdef IEEE80211_DEBUG\n\tint j;\n#endif\n\n\tra->ra_nok++;\n\n\tif (!ratecheck(&ra->ra_last_raise, &ra->ra_raise_interval))\n\t\treturn;\n\n\tfor (i = 0, top = IEEE80211_RSSADAPT_BKT0;\n\t     i < IEEE80211_RSSADAPT_BKTS;\n\t     i++, top <<= IEEE80211_RSSADAPT_BKTPOWER) {\n\t\tthrs = &ra->ra_rate_thresh[i];\n\t\tif (id->id_len <= top)\n\t\t\tbreak;\n\t}\n\n\tif (id->id_rateidx + 1 < rs->rs_nrates &&\n\t    (*thrs)[id->id_rateidx + 1] > (*thrs)[id->id_rateidx]) {\n\t\trate = (rs->rs_rates[id->id_rateidx + 1] & IEEE80211_RATE_VAL);\n\n\t\tRSSADAPT_PRINTF((\"%s: threshold[%d, %d.%d] decay %d \",\n\t\t    ic->ic_if.if_xname, IEEE80211_RSSADAPT_BKT0 <<\n\t\t\t(IEEE80211_RSSADAPT_BKTPOWER * i),\n\t\t    rate / 2, rate * 5 % 10, (*thrs)[id->id_rateidx + 1]));\n\t\toldthr = (*thrs)[id->id_rateidx + 1];\n\t\tif ((*thrs)[id->id_rateidx] == 0)\n\t\t\tnewthr = ra->ra_avg_rssi;\n\t\telse\n\t\t\tnewthr = (*thrs)[id->id_rateidx];\n\t\t(*thrs)[id->id_rateidx + 1] =\n\t\t    interpolate(master_expavgctl.rc_decay, oldthr, newthr);\n\n\t\tRSSADAPT_PRINTF((\"-> %d\\n\", (*thrs)[id->id_rateidx + 1]));\n\t}\n\n#ifdef IEEE80211_DEBUG\n\tif (RSSADAPT_DO_PRINT()) {\n\t\tXYLog(\"%s: dst %s thresholds\\n\", ic->ic_if.if_xname,\n\t\t    ether_sprintf((u_int8_t *)ni->ni_macaddr));\n\t\tfor (i = 0; i < IEEE80211_RSSADAPT_BKTS; i++) {\n\t\t\tXYLog(\"%d-byte\", IEEE80211_RSSADAPT_BKT0 <<\n\t\t\t    (IEEE80211_RSSADAPT_BKTPOWER * i));\n\t\t\tfor (j = 0; j < rs->rs_nrates; j++) {\n\t\t\t\trate = (rs->rs_rates[j] & IEEE80211_RATE_VAL);\n\t\t\t\tXYLog(\", T[%d.%d] = %d\", rate / 2,\n\t\t\t\t    rate * 5 % 10, ra->ra_rate_thresh[i][j]);\n\t\t\t}\n\t\t\tXYLog(\"\\n\");\n\t\t}\n\t}\n#endif /* IEEE80211_DEBUG */\n}\n"
  },
  {
    "path": "itl80211/openbsd/net80211/ieee80211_rssadapt.h",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n/* $OpenBSD: ieee80211_rssadapt.h,v 1.5 2010/07/17 16:25:09 damien Exp $ */\n/* $NetBSD: ieee80211_rssadapt.h,v 1.3 2004/05/06 03:03:20 dyoung Exp $ */\n\n/*-\n * Copyright (c) 2003, 2004 David Young.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or\n * without modification, are permitted provided that the following\n * conditions are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above\n *    copyright notice, this list of conditions and the following\n *    disclaimer in the documentation and/or other materials provided\n *    with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY David Young ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,\n * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A\n * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL David\n * Young BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED\n * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY\n * OF SUCH DAMAGE.\n */\n#ifndef _NET80211_IEEE80211_RSSADAPT_H_\n#define _NET80211_IEEE80211_RSSADAPT_H_\n\n/* Data-rate adaptation loosely based on \"Link Adaptation Strategy\n * for IEEE 802.11 WLAN via Received Signal Strength Measurement\"\n * by Javier del Prado Pavon and Sunghyun Choi.\n */\n\n/* Buckets for frames 0-128 bytes long, 129-1024, 1025-maximum. */\n#define\tIEEE80211_RSSADAPT_BKTS\t\t3\n#define IEEE80211_RSSADAPT_BKT0\t\t128\n#define\tIEEE80211_RSSADAPT_BKTPOWER\t3\t/* 2**_BKTPOWER */\n\n#define\tieee80211_rssadapt_thresh_new \\\n    (ieee80211_rssadapt_thresh_denom - ieee80211_rssadapt_thresh_old)\n#define\tieee80211_rssadapt_decay_new \\\n    (ieee80211_rssadapt_decay_denom - ieee80211_rssadapt_decay_old)\n#define\tieee80211_rssadapt_avgrssi_new \\\n    (ieee80211_rssadapt_avgrssi_denom - ieee80211_rssadapt_avgrssi_old)\n\nstruct ieee80211_rssadapt_expavgctl {\n\t/* RSS threshold decay. */\n\tu_int rc_decay_denom;\n\tu_int rc_decay_old;\n\t/* RSS threshold update. */\n\tu_int rc_thresh_denom;\n\tu_int rc_thresh_old;\n\t/* RSS average update. */\n\tu_int rc_avgrssi_denom;\n\tu_int rc_avgrssi_old;\n};\n\nstruct ieee80211_rssadapt {\n\t/* exponential average RSSI << 8 */\n\tu_int16_t\t\tra_avg_rssi;\n\t/* Tx failures in this update interval */\n\tu_int32_t\t\tra_nfail;\n\t/* Tx successes in this update interval */\n\tu_int32_t\t\tra_nok;\n\t/* exponential average packets/second */\n\tu_int32_t\t\tra_pktrate;\n\t/* RSSI threshold for each Tx rate */\n\tu_int16_t\t\tra_rate_thresh[IEEE80211_RSSADAPT_BKTS]\n\t\t\t\t    [IEEE80211_RATE_SIZE];\n\tstruct timeval\t\tra_last_raise;\n\tstruct timeval\t\tra_raise_interval;\n};\n\n/* Properties of a Tx packet, for link adaptation. */\nstruct ieee80211_rssdesc {\n\tu_int\t\t\t id_len;\t/* Tx packet length */\n\tu_int\t\t\t id_rateidx;\t/* index into ni->ni_rates */\n\tstruct ieee80211_node\t*id_node;\t/* destination STA MAC */\n\tu_int8_t\t\t id_rssi;\t/* destination STA avg RSS @\n\t\t\t\t\t\t * Tx time\n\t\t\t\t\t\t */\n};\n\nvoid\tieee80211_rssadapt_updatestats(struct ieee80211_rssadapt *);\nvoid\tieee80211_rssadapt_input(struct ieee80211com *,\n\t    const struct ieee80211_node *, struct ieee80211_rssadapt *, int);\nvoid\tieee80211_rssadapt_lower_rate(struct ieee80211com *,\n\t    const struct ieee80211_node *, struct ieee80211_rssadapt *,\n\t    const struct ieee80211_rssdesc *);\nvoid\tieee80211_rssadapt_raise_rate(struct ieee80211com *,\n\t    struct ieee80211_rssadapt *, const struct ieee80211_rssdesc *);\nint\tieee80211_rssadapt_choose(struct ieee80211_rssadapt *,\n\t    const struct ieee80211_rateset *, const struct ieee80211_frame *,\n\t    u_int, int, const char *, int);\n#ifdef IEEE80211_DEBUG\nextern int ieee80211_rssadapt_debug;\n#endif /* IEEE80211_DEBUG */\n\n#endif /* _NET80211_IEEE80211_RSSADAPT_H_ */\n"
  },
  {
    "path": "itl80211/openbsd/net80211/ieee80211_var.h",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n/*\t$OpenBSD: ieee80211_var.h,v 1.97 2019/07/29 10:50:09 stsp Exp $\t*/\n/*\t$NetBSD: ieee80211_var.h,v 1.7 2004/05/06 03:07:10 dyoung Exp $\t*/\n\n/*-\n * Copyright (c) 2001 Atsushi Onoe\n * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. The name of the author may not be used to endorse or promote products\n *    derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * $FreeBSD: src/sys/net80211/ieee80211_var.h,v 1.15 2004/04/05 22:10:26 sam Exp $\n */\n#ifndef _NET80211_IEEE80211_VAR_H_\n#define _NET80211_IEEE80211_VAR_H_\n\n/*\n * Definitions for IEEE 802.11 drivers.\n */\n\n#define explicit_bzero bzero\n#define nitems(arr) (sizeof(arr) / sizeof((arr)[0]))\n\n\n\n#ifdef\tSMALL_KERNEL\n#define IEEE80211_STA_ONLY\t1\n#endif\n\n#include <sys/param.h>\n#include <sys/timeout.h>\n#include <sys/_if_ether.h>\n#include <sys/_if_media.h>\n#include <sys/_arc4random.h>\n#include <sys/_task.h>\n#include <sys/_ifq.h>\n#include <sys/_malloc.h>\n\n#include <sys/kpi_mbuf.h>\n#include <net80211/ieee80211.h>\n#include <net80211/ieee80211_crypto.h>\n#include <net80211/ieee80211_ioctl.h>\t\t/* for ieee80211_stats */\n#include <net80211/ieee80211_node.h>\n#include <net80211/ieee80211_proto.h>\n\n#include <IOKit/IOLib.h>\n\n#define IEEE80211_DEBUG\n\n#define _KASSERT(exp) KASSERT(exp, \"\")\n\n#define CLUSTER_SIZE 4096\n\n#define    ALIGNED_POINTER(p,t)    1\n\nextern int TX_TYPE_MGMT;\n\nextern int TX_TYPE_FRAME;\n\nextern int _stop(struct kmod_info*, void*);\n\nextern int _start(struct kmod_info*, void*);\n\nextern int timingsafe_bcmp(const void *b1, const void *b2, size_t n);\n\n/*\n * ppsratecheck(): packets (or events) per second limitation.\n */\nstatic int\nppsratecheck(struct timeval *lasttime, int *curpps, int maxpps)\n{\n    struct timeval tv, delta;\n    int rv;\n\n    microuptime(&tv);\n\n    timersub(&tv, lasttime, &delta);\n\n    /*\n     * check for 0,0 is so that the message will be seen at least once.\n     * if more than one second have passed since the last update of\n     * lasttime, reset the counter.\n     *\n     * we do increment *curpps even in *curpps < maxpps case, as some may\n     * try to use *curpps for stat purposes as well.\n     */\n    if (maxpps == 0)\n        rv = 0;\n    else if ((lasttime->tv_sec == 0 && lasttime->tv_usec == 0) ||\n        delta.tv_sec >= 1) {\n        *lasttime = tv;\n        *curpps = 0;\n        rv = 1;\n    } else if (maxpps < 0)\n        rv = 1;\n    else if (*curpps < maxpps)\n        rv = 1;\n    else\n        rv = 0;\n\n#if 1 /*DIAGNOSTIC?*/\n    /* be careful about wrap-around */\n    if (*curpps + 1 > *curpps)\n        *curpps = *curpps + 1;\n#else\n    /*\n     * assume that there's not too many calls to this function.\n     * not sure if the assumption holds, as it depends on *caller's*\n     * behavior, not the behavior of this function.\n     * IMHO it is wrong to make assumption on the caller's behavior,\n     * so the above #if is #if 1, not #ifdef DIAGNOSTIC.\n     */\n    *curpps = *curpps + 1;\n#endif\n    \n    return (rv);\n}\n\n/*\n * ratecheck(): simple time-based rate-limit checking.  see ratecheck(9)\n * for usage and rationale.\n */\nstatic int\nratecheck(struct timeval *lasttime, const struct timeval *mininterval)\n{\n    struct timeval tv, delta;\n    int rv = 0;\n\n    getmicrouptime(&tv);\n\n    timersub(&tv, lasttime, &delta);\n\n    /*\n     * check for 0,0 is so that the message will be seen at least once,\n     * even if interval is huge.\n     */\n    if (timercmp(&delta, mininterval, >=) ||\n        (lasttime->tv_sec == 0 && lasttime->tv_usec == 0)) {\n        *lasttime = tv;\n        rv = 1;\n    }\n\n    return (rv);\n}\n\nstatic u_int32_t ether_crc32_le_update(u_int32_t crc, const u_int8_t *buf, size_t len)\n{\n    static const u_int32_t crctab[] = {\n        0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,\n        0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,\n        0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,\n        0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c\n    };\n    size_t i;\n\n    for (i = 0; i < len; i++) {\n        crc ^= buf[i];\n        crc = (crc >> 4) ^ crctab[crc & 0xf];\n        crc = (crc >> 4) ^ crctab[crc & 0xf];\n    }\n\n    return (crc);\n}\n\nstatic char* ether_sprintf(const uint8_t *ap)\n{\n         static char etherbuf[18];\n         snprintf(etherbuf, sizeof (etherbuf), \"%6D\", ap, \":\");\n         return (etherbuf);\n}\n\nstatic void array_sprintf(char *output, uint8_t output_size, const uint8_t *array, const uint8_t len)\n{\n    uint8_t index = 0;\n    for (index = 0; index < len; index++) {\n        snprintf(output, output_size, \"0x%02x \", array++);\n    }\n}\n\n#define\tIEEE80211_CHAN_MAX\t255\n#define\tIEEE80211_CHAN_ANY\t0xffff\t\t/* token for ``any channel'' */\n#define\tIEEE80211_CHAN_ANYC \\\n\t((struct ieee80211_channel *) NULL)\n\n#define\tIEEE80211_TXPOWER_MAX\t100\t/* max power */\n#define\tIEEE80211_TXPOWER_MIN\t-50\t/* kill radio (if possible) */\n\n#define IEEE80211_RSSI_THRES_2GHZ\t\t(-60)\t/* in dBm */\n#define IEEE80211_RSSI_THRES_5GHZ\t\t(-70)\t/* in dBm */\n#define IEEE80211_RSSI_THRES_RATIO_2GHZ\t\t50\t/* in percent */\n#define IEEE80211_RSSI_THRES_RATIO_5GHZ\t\t40\t/* in percent */\n\n#define IEEE80211_BGSCAN_FAIL_MAX\t\t360\t/* units of 500 msec */\n\n/*\n * Missed beacon threshold: An access point has disappeared if this amount\n * of consecutive beacons have been missed.\n * This value needs to be high enough to avoid frequent re-connects to APs\n * which suffer from occasional packet loss, and low enough to avoid a long\n * delay before we start scanning when an AP has actually disappeared.\n *\n * The beacon interval is variable, but generally in the order of 100ms.\n * So 30 beacons implies a grace period of about 3 seconds before we start\n * searching for a new AP.\n */\n#define IEEE80211_BEACON_MISS_THRES        30    /* units of beacons */\n\nenum ieee80211_phytype {\n\tIEEE80211_T_DS,\t\t\t/* direct sequence spread spectrum */\n\tIEEE80211_T_OFDM,\t\t/* frequency division multiplexing */\n\tIEEE80211_T_XR\t\t        /* extended range mode */\n};\n#define\tIEEE80211_T_CCK\tIEEE80211_T_DS\t/* more common nomenclature */\n\n/* XXX not really a mode; there are really multiple PHY's */\nenum ieee80211_phymode {\n\tIEEE80211_MODE_AUTO\t= 0,\t/* autoselect */\n\tIEEE80211_MODE_11A\t= 1,\t/* 5GHz, OFDM */\n\tIEEE80211_MODE_11B\t= 2,\t/* 2GHz, CCK */\n\tIEEE80211_MODE_11G\t= 3,\t/* 2GHz, OFDM */\n\tIEEE80211_MODE_11N\t= 4,\t/* 2GHz/5GHz, OFDM/HT */\n\tIEEE80211_MODE_11AC\t= 5,\t/* 5GHz, OFDM/VHT */\n    IEEE80211_MODE_11AX = 6,    /* 5GHz, 6GHz, HE */\n};\n#define\tIEEE80211_MODE_MAX\t(IEEE80211_MODE_11AX+1)\n\nenum ieee80211_opmode {\n\tIEEE80211_M_STA\t\t= 1,\t/* infrastructure station */\n#ifndef IEEE80211_STA_ONLY\n\tIEEE80211_M_IBSS\t= 0,\t/* IBSS (adhoc) station */\n\tIEEE80211_M_AHDEMO\t= 3,\t/* Old lucent compatible adhoc demo */\n\tIEEE80211_M_HOSTAP\t= 6,\t/* Software Access Point */\n#endif\n\tIEEE80211_M_MONITOR\t= 8\t/* Monitor mode */\n};\n\n/*\n * 802.11g protection mode.\n */\nenum ieee80211_protmode {\n\tIEEE80211_PROT_NONE\t= 0,\t/* no protection */\n\tIEEE80211_PROT_CTSONLY\t= 1,\t/* CTS to self */\n\tIEEE80211_PROT_RTSCTS\t= 2\t/* RTS-CTS */\n};\n\n/*\n * Channels are specified by frequency and attributes.\n */\nstruct ieee80211_channel {\n\tu_int16_t\tic_freq;\t/* setting in MHz */\n\tu_int32_t\tic_flags;\t/* see below */\n    u_int16_t   ic_center_freq1;\n    u_int16_t   ic_center_freq2;\n};\n\n/*\n * Channel attributes (XXX must keep in sync with radiotap flags).\n */\n#define IEEE80211_CHAN_CCK\t0x0020\t/* CCK channel */\n#define IEEE80211_CHAN_OFDM\t0x0040\t/* OFDM channel */\n#define IEEE80211_CHAN_2GHZ\t0x0080\t/* 2 GHz spectrum channel */\n#define IEEE80211_CHAN_5GHZ\t0x0100\t/* 5 GHz spectrum channel */\n#define IEEE80211_CHAN_PASSIVE\t0x0200\t/* Only passive scan allowed */\n#define IEEE80211_CHAN_DYN\t0x0400\t/* Dynamic CCK-OFDM channel */\n#define IEEE80211_CHAN_XR\t0x1000\t/* Extended range OFDM channel */\n\n#define IEEE80211_CHAN_HT20    0x00010000 /* HT 20 channel */\n#define IEEE80211_CHAN_HT40U    0x00020000 /* HT 40 channel w/ ext above */\n#define IEEE80211_CHAN_HT40D    0x00040000 /* HT 40 channel w/ ext below */\n#define IEEE80211_CHAN_DFS    0x00080000 /* DFS required */\n#define IEEE80211_CHAN_4MSXMIT    0x00100000 /* 4ms limit on frame length */\n#define IEEE80211_CHAN_NOADHOC    0x00200000 /* adhoc mode not allowed */\n#define IEEE80211_CHAN_NOHOSTAP    0x00400000 /* hostap mode not allowed */\n#define IEEE80211_CHAN_11D    0x00800000 /* 802.11d required */\n#define IEEE80211_CHAN_VHT20    0x01000000 /* VHT20 channel */\n#define IEEE80211_CHAN_VHT40U    0x02000000 /* VHT40 channel, ext above */\n#define IEEE80211_CHAN_VHT40D    0x04000000 /* VHT40 channel, ext below */\n#define IEEE80211_CHAN_VHT80    0x08000000 /* VHT80 channel */\n#define IEEE80211_CHAN_VHT160    0x10000000 /* VHT160 channel */\n#define IEEE80211_CHAN_VHT80_80    0x20000000 /* VHT80+80 channel */\n\n#define IEEE80211_CHAN_HT40    (IEEE80211_CHAN_HT40U | IEEE80211_CHAN_HT40D)\n#define IEEE80211_CHAN_HT    (IEEE80211_CHAN_HT20 | IEEE80211_CHAN_HT40)\n\n#define IEEE80211_CHAN_VHT40    (IEEE80211_CHAN_VHT40U | IEEE80211_CHAN_VHT40D)\n#define IEEE80211_CHAN_VHT    (IEEE80211_CHAN_VHT20 | IEEE80211_CHAN_VHT40 \\\n                | IEEE80211_CHAN_VHT80 | IEEE80211_CHAN_VHT80_80 \\\n                | IEEE80211_CHAN_VHT160)\n\n#define IEEE80211_CHAN_ALL  \\\n    (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_5GHZ | \\\n    IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM | IEEE80211_CHAN_PASSIVE | IEEE80211_CHAN_DYN | IEEE80211_CHAN_XR | \\\n    IEEE80211_CHAN_HT | IEEE80211_CHAN_VHT)\n\n/*\n * Useful combinations of channel characteristics.\n */\n#define IEEE80211_CHAN_A \\\n\t(IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM)\n#define IEEE80211_CHAN_B \\\n\t(IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_CCK)\n#define IEEE80211_CHAN_PUREG \\\n\t(IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_OFDM)\n#define IEEE80211_CHAN_G \\\n\t(IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN)\n\n#define\tIEEE80211_IS_CHAN_A(_c) \\\n\t(((_c)->ic_flags & IEEE80211_CHAN_A) == IEEE80211_CHAN_A)\n#define\tIEEE80211_IS_CHAN_B(_c) \\\n\t(((_c)->ic_flags & IEEE80211_CHAN_B) == IEEE80211_CHAN_B)\n#define\tIEEE80211_IS_CHAN_PUREG(_c) \\\n\t(((_c)->ic_flags & IEEE80211_CHAN_PUREG) == IEEE80211_CHAN_PUREG)\n#define\tIEEE80211_IS_CHAN_G(_c) \\\n\t(((_c)->ic_flags & IEEE80211_CHAN_G) == IEEE80211_CHAN_G)\n#define\tIEEE80211_IS_CHAN_N(_c) \\\n\t(((_c)->ic_flags & IEEE80211_CHAN_HT) != 0)\n#define\tIEEE80211_IS_CHAN_AC(_c) \\\n\t(((_c)->ic_flags & IEEE80211_CHAN_VHT) != 0)\n\n#define\tIEEE80211_IS_CHAN_2GHZ(_c) \\\n\t(((_c)->ic_flags & IEEE80211_CHAN_2GHZ) != 0)\n#define\tIEEE80211_IS_CHAN_5GHZ(_c) \\\n\t(((_c)->ic_flags & IEEE80211_CHAN_5GHZ) != 0)\n#define\tIEEE80211_IS_CHAN_OFDM(_c) \\\n\t(((_c)->ic_flags & IEEE80211_CHAN_OFDM) != 0)\n#define\tIEEE80211_IS_CHAN_CCK(_c) \\\n\t(((_c)->ic_flags & IEEE80211_CHAN_CCK) != 0)\n#define\tIEEE80211_IS_CHAN_XR(_c) \\\n\t(((_c)->ic_flags & IEEE80211_CHAN_XR) != 0)\n\n/*\n * EDCA AC parameters.\n */\nstruct ieee80211_edca_ac_params {\n\tu_int8_t\tac_ecwmin;\t/* CWmin = 2^ECWmin - 1 */\n\tu_int8_t\tac_ecwmax;\t/* CWmax = 2^ECWmax - 1 */\n\tu_int8_t\tac_aifsn;\n\tu_int16_t\tac_txoplimit;\t/* 32TU */\n#define IEEE80211_TXOP_TO_US(txop)\t((txop) * 32)\n\n\tu_int8_t\tac_acm;\n};\n\nextern const struct ieee80211_edca_ac_params\n\t    ieee80211_edca_table[IEEE80211_MODE_MAX][EDCA_NUM_AC];\nextern const struct ieee80211_edca_ac_params\n\t    ieee80211_qap_edca_table[IEEE80211_MODE_MAX][EDCA_NUM_AC];\n\n#define IEEE80211_DEFRAG_SIZE\t3\t/* must be >= 3 according to spec */\n/*\n * Entry in the fragment cache.\n */\nstruct ieee80211_defrag {\n\tCTimeout*\tdf_to;\n\tmbuf_t df_m;\n\tu_int16_t\tdf_seq;\n\tu_int8_t\tdf_frag;\n};\n\n#define IEEE80211_PROTO_NONE\t0\n#define IEEE80211_PROTO_RSN\t(1 << 0)\n#define IEEE80211_PROTO_WPA\t(1 << 1)\n\n#define\tIEEE80211_SCAN_UNLOCKED\t0x0\n#define\tIEEE80211_SCAN_LOCKED\t0x1\n#define\tIEEE80211_SCAN_REQUEST\t0x2\n#define\tIEEE80211_SCAN_RESUME\t0x4\n\n#define IEEE80211_GROUP_NKID\t6\n\nstruct ieee80211com {\n\tstruct arpcom\t\tic_ac;\n\tLIST_ENTRY(ieee80211com) ic_list;\t/* chain of all ieee80211com */\n\tvoid\t\t\t(*ic_recv_mgmt)(struct ieee80211com *,\n\t\t\t\t    mbuf_t, struct ieee80211_node *,\n\t\t\t\t    struct ieee80211_rxinfo *, int);\n\tint\t\t\t(*ic_send_mgmt)(struct ieee80211com *,\n\t\t\t\t    struct ieee80211_node *, int, int, int);\n\tint\t\t\t(*ic_newstate)(struct ieee80211com *,\n\t\t\t\t    enum ieee80211_state, int);\n\tint\t\t\t(*ic_newauth)(struct ieee80211com *,\n\t\t\t\t    struct ieee80211_node *, int, uint16_t);\n\tvoid\t\t\t(*ic_newassoc)(struct ieee80211com *,\n\t\t\t\t    struct ieee80211_node *, int);\n\tvoid\t\t\t(*ic_node_leave)(struct ieee80211com *,\n\t\t\t\t    struct ieee80211_node *);\n\tvoid\t\t\t(*ic_updateslot)(struct ieee80211com *);\n\tvoid\t\t\t(*ic_updateedca)(struct ieee80211com *);\n    void            (*ic_updatedtim)(struct ieee80211com *);\n\tvoid\t\t\t(*ic_set_tim)(struct ieee80211com *, int, int);\n\tint\t\t\t(*ic_set_key)(struct ieee80211com *,\n\t\t\t\t    struct ieee80211_node *,\n\t\t\t\t    struct ieee80211_key *);\n\tvoid\t\t\t(*ic_delete_key)(struct ieee80211com *,\n\t\t\t\t    struct ieee80211_node *,\n\t\t\t\t    struct ieee80211_key *);\n\tint\t\t\t(*ic_ampdu_tx_start)(struct ieee80211com *,\n\t\t\t\t    struct ieee80211_node *, u_int8_t);\n\tvoid\t\t\t(*ic_ampdu_tx_stop)(struct ieee80211com *,\n\t\t\t\t    struct ieee80211_node *, u_int8_t);\n\tint\t\t\t(*ic_ampdu_rx_start)(struct ieee80211com *,\n\t\t\t\t    struct ieee80211_node *, u_int8_t);\n\tvoid\t\t\t(*ic_ampdu_rx_stop)(struct ieee80211com *,\n\t\t\t\t    struct ieee80211_node *, u_int8_t);\n\tvoid\t\t\t(*ic_updateprot)(struct ieee80211com *);\n\tint\t\t\t(*ic_bgscan_start)(struct ieee80211com *);\n    /* The channel width has changed (20<->2040) */\n    void            (*ic_update_chw)(struct ieee80211com *);\n    void            (*ic_event_handler)(struct ieee80211com *, int, void *);\n\tCTimeout*\t\tic_bgscan_timeout;\n\tuint32_t\t\tic_bgscan_fail;\n\tu_int8_t\t\tic_myaddr[IEEE80211_ADDR_LEN];\n\tstruct ieee80211_rateset ic_sup_rates[IEEE80211_MODE_MAX];\n\tstruct ieee80211_channel ic_channels[IEEE80211_CHAN_MAX+1];\n\tu_char\t\t\tic_chan_avail[howmany(IEEE80211_CHAN_MAX,NBBY)];\n\tu_char\t\t\tic_chan_active[howmany(IEEE80211_CHAN_MAX, NBBY)];\n\tu_char\t\t\tic_chan_scan[howmany(IEEE80211_CHAN_MAX,NBBY)];\n\tstruct mbuf_queue\tic_mgtq;\n\tstruct mbuf_queue\tic_pwrsaveq;\n\tu_int8_t\t\tic_scan_count;\t/* count scans */\n\tu_int32_t\t\tic_flags;\t/* state flags */\n\tu_int32_t\t\tic_xflags;\t/* more flags */\n    \n\tu_int32_t\t\tic_userflags;\t/* yet more flags */\n\tu_int32_t\t\tic_caps;\t/* capabilities */\n\tu_int16_t\t\tic_modecaps;\t/* set of mode capabilities */\n\tu_int16_t\t\tic_curmode;\t/* current mode */\n\tenum ieee80211_phytype\tic_phytype;\t/* XXX wrong for multi-mode */\n\tenum ieee80211_opmode\tic_opmode;\t/* operation mode */\n\tenum ieee80211_state\tic_state;\t/* 802.11 state */\n\tu_int32_t\t\t*ic_aid_bitmap;\n\tu_int16_t\t\tic_max_aid;\n\tenum ieee80211_protmode\tic_protmode;\t/* 802.11g/n protection mode */\n\tstruct ifmedia\t\tic_media;\t/* interface media config */\n\tcaddr_t\t\t\tic_rawbpf;\t/* packet filter structure */\n\tstruct ieee80211_node\t*ic_bss;\t/* information for this node */\n\tstruct ieee80211_channel *ic_ibss_chan;\n\tint\t\t\tic_fixed_rate;\t/* index to ic_sup_rates[] */\n\tu_int16_t\t\tic_rtsthreshold;\n\tu_int16_t\t\tic_fragthreshold;\n\tu_int\t\t\tic_scangen;\t/* gen# for timeout scan */\n\tstruct ieee80211_node\t*(*ic_node_alloc)(struct ieee80211com *);\n\tvoid\t\t\t(*ic_node_free)(struct ieee80211com *,\n\t\t\t\t\tstruct ieee80211_node *);\n\tvoid\t\t\t(*ic_node_copy)(struct ieee80211com *,\n\t\t\t\t\tstruct ieee80211_node *,\n\t\t\t\t\tconst struct ieee80211_node *);\n\tu_int8_t\t\t(*ic_node_getrssi)(struct ieee80211com *,\n\t\t\t\t\tconst struct ieee80211_node *);\n\tint\t\t\t(*ic_node_checkrssi)(struct ieee80211com *,\n\t\t\t\t\tconst struct ieee80211_node *);\n\tu_int8_t\t\tic_max_rssi;\n\tstruct ieee80211_tree\tic_tree;\n\tint\t\t\tic_nnodes;\t/* length of ic_nnodes */\n\tint\t\t\tic_max_nnodes;\t/* max length of ic_nnodes */\n\tu_int16_t\t\tic_lintval;\t/* listen interval */\n\tint16_t\t\t\tic_txpower;\t/* tx power setting (dBm) */\n\tint\t\t\tic_bmissthres;\t/* beacon miss threshold */\n\tint\t\t\tic_mgt_timer;\t/* mgmt timeout */\n#ifndef IEEE80211_STA_ONLY\n\tCTimeout*\t\tic_inact_timeout; /* node inactivity timeout */\n\tCTimeout*\t\tic_node_cache_timeout;\n#endif\n\tint\t\t\tic_des_esslen;\n\tu_int8_t\t\tic_des_essid[IEEE80211_NWID_LEN];\n\tstruct ieee80211_channel *ic_des_chan;\t/* desired channel */\n\tu_int8_t\t\tic_des_bssid[IEEE80211_ADDR_LEN];\n#ifdef USE_APPLE_SUPPLICANT\n\tu_int8_t\t\tic_rsn_ie_override[257];\n#endif\n    u_int16_t       ic_deauth_reason;\n    u_int16_t       ic_assoc_status;\n\tstruct ieee80211_key\tic_nw_keys[IEEE80211_GROUP_NKID];\n\tint\t\t\tic_def_txkey;\t/* group data key index */\n#define ic_wep_txkey\tic_def_txkey\n\tint\t\t\tic_igtk_kid;\t/* IGTK key index */\n\tu_int32_t\t\tic_iv;\t\t/* initial vector for wep */\n\tstruct ieee80211_stats\tic_stats;\t/* statistics */\n\tstruct timeval\t\tic_last_merge_print;\t/* for rate-limiting\n\t\t\t\t\t\t\t * IBSS merge print-outs\n\t\t\t\t\t\t\t */\n\tstruct ieee80211_edca_ac_params ic_edca_ac[EDCA_NUM_AC];\n\tu_int\t\t\tic_edca_updtcount;\n\tu_int16_t\t\tic_tid_noack;\n\tu_int8_t\t\tic_globalcnt[EAPOL_KEY_NONCE_LEN];\n\tu_int8_t\t\tic_nonce[EAPOL_KEY_NONCE_LEN];\n\tu_int8_t\t\tic_psk[IEEE80211_PMK_LEN];\n\tCTimeout*\t\tic_rsn_timeout;\n\tint\t\t\tic_tkip_micfail;\n\tu_int64_t\t\tic_tkip_micfail_last_tsc;\n#ifndef IEEE80211_STA_ONLY\n\tCTimeout*\t\tic_tkip_micfail_timeout;\n#endif\n\n\tTAILQ_HEAD(, ieee80211_pmk) ic_pmksa;\t/* PMKSA cache */\n\tu_int\t\t\tic_rsnprotos;\n\tu_int\t\t\tic_rsnakms;\n\tu_int\t\t\tic_rsnciphers;\n\tenum ieee80211_cipher\tic_rsngroupcipher;\n\tenum ieee80211_cipher\tic_rsngroupmgmtcipher;\n\n#ifdef notyet\n\tstruct ieee80211_defrag\tic_defrag[IEEE80211_DEFRAG_SIZE];\n\tint\t\t\tic_defrag_cur;\n#endif\n\n\tu_int8_t\t\t*ic_tim_bitmap;\n\tu_int\t\t\tic_tim_len;\n\tu_int\t\t\tic_tim_mcast_pending;\n\tu_int\t\t\tic_dtim_period;\n\tu_int\t\t\tic_dtim_count;\n\n\tu_int32_t\t\tic_txbfcaps;\n\tu_int16_t\t\tic_htcaps;\n    uint32_t        ic_vhtcaps;\n    uint32_t        ic_hecaps;\n\tu_int8_t\t\tic_ampdu_params;\n\tu_int8_t\t\tic_sup_mcs[howmany(80, NBBY)];\n\tu_int16_t\t\tic_max_rxrate;\t/* in Mb/s, 0 <= rate <= 1023 */\n\tu_int8_t\t\tic_tx_mcs_set;\n\tu_int16_t\t\tic_htxcaps;\n\tu_int8_t\t\tic_aselcaps;\n\tu_int8_t\t\tic_dialog_token;\n\tint\t\t\tic_fixed_mcs;\n    uint64_t        ic_last_cache_scan_ts;\n    uint16_t        ic_vht_tx_mcs_map;\n    uint16_t        ic_vht_rx_mcs_map;\n    uint16_t        ic_vht_tx_highest;\n    uint16_t        ic_vht_rx_highest;\n    uint16_t        ic_vht_sup_mcs[howmany(80, NBBY)];\n    \n    /* HE state */\n    struct ieee80211_he_cap_elem ic_he_cap_elem;   /* Fixed portion of the HE capabilities element. */\n    struct ieee80211_he_mcs_nss_supp ic_he_mcs_nss_supp;   /* The supported NSS/MCS combinations. */\n    uint8_t ic_ppe_thres[IEEE80211_HE_PPE_THRES_MAX_LEN]; /* Holds the PPE Thresholds data. */\n    \n\tTAILQ_HEAD(, ieee80211_ess)\t ic_ess;\n};\n#define\tic_if\t\tic_ac.ac_if\n#define\tic_softc\tic_if.if_softc\n\n/* list of APs we want to automatically use */\n/* all data is copied from struct ieee80211com */\nstruct ieee80211_ess {\n\t/* nwid */\n\tint\t\t\tesslen;\n\tu_int8_t\t\tessid[IEEE80211_NWID_LEN];\n\n\t/* clear/wep/wpa */\n\tu_int32_t\t\tflags;\n\n\t/* nwkey */\n\tstruct ieee80211_key    nw_keys[IEEE80211_GROUP_NKID];\n\tint\t\t\tdef_txkey;\n\n\t/* wpakey */\n\tu_int8_t\t\tpsk[IEEE80211_PMK_LEN];\n\tu_int\t\t\trsnprotos;\n\tu_int\t\t\trsnakms;\n\tu_int\t\t\trsnciphers;\n\tenum ieee80211_cipher\trsngroupcipher;\n\n\tTAILQ_ENTRY(ieee80211_ess) ess_next;\n};\n\n#define\tIEEE80211_ADDR_EQ(a1,a2)\t(memcmp(a1,a2,IEEE80211_ADDR_LEN) == 0)\n#define\tIEEE80211_ADDR_COPY(dst,src)\tmemcpy(dst,src,IEEE80211_ADDR_LEN)\n\n/* ic_flags */\n#define\tIEEE80211_F_ASCAN\t0x00000001\t/* STATUS: active scan */\n#define\tIEEE80211_F_SIBSS\t0x00000002\t/* STATUS: start IBSS */\n#define\tIEEE80211_F_WEPON\t0x00000100\t/* CONF: WEP enabled */\n#define\tIEEE80211_F_IBSSON\t0x00000200\t/* CONF: IBSS creation enable */\n#define\tIEEE80211_F_PMGTON\t0x00000400\t/* CONF: Power mgmt enable */\n#define\tIEEE80211_F_DESBSSID\t0x00000800\t/* CONF: des_bssid is set */\n#define\tIEEE80211_F_ROAMING\t0x00002000\t/* CONF: roaming enabled */\n#define\tIEEE80211_F_TXPMGT\t0x00018000\t/* STATUS: tx power */\n#define IEEE80211_F_TXPOW_OFF\t0x00000000\t/* TX Power: radio disabled */\n#define IEEE80211_F_TXPOW_FIXED\t0x00008000\t/* TX Power: fixed rate */\n#define IEEE80211_F_TXPOW_AUTO\t0x00010000\t/* TX Power: undefined */\n#define\tIEEE80211_F_SHSLOT\t0x00020000\t/* STATUS: short slot time */\n#define\tIEEE80211_F_SHPREAMBLE\t0x00040000\t/* STATUS: short preamble */\n#define IEEE80211_F_QOS\t\t0x00080000\t/* CONF: QoS enabled */\n#define\tIEEE80211_F_USEPROT\t0x00100000\t/* STATUS: protection enabled */\n#define\tIEEE80211_F_RSNON\t0x00200000\t/* CONF: RSN enabled */\n#define\tIEEE80211_F_PSK\t\t0x00400000\t/* CONF: pre-shared key set */\n#define IEEE80211_F_COUNTERM\t0x00800000\t/* STATUS: countermeasures */\n#define IEEE80211_F_MFPR\t0x01000000\t/* CONF: MFP required */\n#define\tIEEE80211_F_HTON\t0x02000000\t/* CONF: HT enabled */\n#define\tIEEE80211_F_PBAR\t0x04000000\t/* CONF: PBAC required */\n#define\tIEEE80211_F_BGSCAN\t0x08000000\t/* STATUS: background scan */\n#define IEEE80211_F_AUTO_JOIN\t0x10000000\t/* CONF: auto-join active */\n#define\tIEEE80211_F_VHTON\t0x20000000\t/* CONF: VHT enabled */\n#define IEEE80211_F_DISABLE_BG_AUTO_CONNECT 0x40000000  /* CONF: disable auto connect to wifi when doing backgound scan */\n#define IEEE80211_F_HEON    0x80000000  /* CONF: HE enabled */\n\n/* ic_xflags */\n#define\tIEEE80211_F_TX_MGMT_ONLY 0x00000001\t/* leave data frames on ifq */\n\n/* ic_caps */\n#define\tIEEE80211_C_WEP\t\t0x00000001\t/* CAPABILITY: WEP available */\n#define\tIEEE80211_C_IBSS\t0x00000002\t/* CAPABILITY: IBSS available */\n#define\tIEEE80211_C_PMGT\t0x00000004\t/* CAPABILITY: Power mgmt */\n#define\tIEEE80211_C_HOSTAP\t0x00000008\t/* CAPABILITY: HOSTAP avail */\n#define\tIEEE80211_C_AHDEMO\t0x00000010\t/* CAPABILITY: Old Adhoc Demo */\n#define\tIEEE80211_C_APPMGT\t0x00000020\t/* CAPABILITY: AP power mgmt */\n#define\tIEEE80211_C_TXPMGT\t0x00000040\t/* CAPABILITY: tx power mgmt */\n#define\tIEEE80211_C_SHSLOT\t0x00000080\t/* CAPABILITY: short slottime */\n#define\tIEEE80211_C_SHPREAMBLE\t0x00000100\t/* CAPABILITY: short preamble */\n#define\tIEEE80211_C_MONITOR\t0x00000200\t/* CAPABILITY: monitor mode */\n#define IEEE80211_C_SCANALL\t0x00000400\t/* CAPABILITY: scan all chan */\n#define IEEE80211_C_QOS\t\t0x00000800\t/* CAPABILITY: QoS avail */\n#define IEEE80211_C_RSN\t\t0x00001000\t/* CAPABILITY: RSN avail */\n#define IEEE80211_C_MFP\t\t0x00002000\t/* CAPABILITY: MFP avail */\n#define IEEE80211_C_RAWCTL\t0x00004000\t/* CAPABILITY: raw ctl */\n#define IEEE80211_C_SCANALLBAND\t0x00008000\t/* CAPABILITY: scan all bands */\n#define IEEE80211_C_TX_AMPDU\t0x00010000\t/* CAPABILITY: send A-MPDU */\n#define IEEE80211_C_AMSDU_IN_AMPDU 0x00020000 /* CAPABILITY: Rx AMSDU inside AMPDU */\n#define IEEE80211_C_TX_AMPDU_SETUP_IN_HW 0x00040000 /* CAPABILITY: BA negotiation in HW */\n#define IEEE80211_C_SUPPORTS_VHT_EXT_NSS_BW 0x00080000  /* CAPABILITY: for 160mhz */\n#define IEEE80211_C_TX_AMPDU_SETUP_IN_RS 0x00100000\n\n/* flags for ieee80211_fix_rate() */\n#define\tIEEE80211_F_DOSORT\t0x00000001\t/* sort rate list */\n#define\tIEEE80211_F_DOFRATE\t0x00000002\t/* use fixed rate */\n#define\tIEEE80211_F_DONEGO\t0x00000004\t/* calc negotiated rate */\n#define\tIEEE80211_F_DODEL\t0x00000008\t/* delete ignore rate */\n\n#define IEEE80211_EVT_STA_ASSOC_DONE            1\n#define IEEE80211_EVT_STA_DEAUTH                2\n#define IEEE80211_EVT_COUNTRY_CODE_UPDATE       3\n#define IEEE80211_EVT_SCAN_DONE                 4\n\nvoid\tieee80211_ifattach(struct _ifnet *, IOEthernetController *controller);\nvoid\tieee80211_ifdetach(struct _ifnet *);\nvoid\tieee80211_channel_init(struct _ifnet *);\nvoid\tieee80211_media_init(struct _ifnet *);\nint\tieee80211_media_change(struct _ifnet *);\nvoid\tieee80211_media_status(struct _ifnet *, struct ifmediareq *);\nint\tieee80211_ioctl(struct _ifnet *, u_long, caddr_t);\nint\tieee80211_get_rate(struct ieee80211com *);\nvoid\tieee80211_watchdog(struct _ifnet *);\nint\tieee80211_fix_rate(struct ieee80211com *, struct ieee80211_node *, int);\nuint64_t\tieee80211_rate2media(struct ieee80211com *, int,\n\t\t    enum ieee80211_phymode);\nint\tieee80211_media2rate(uint64_t);\nuint64_t\tieee80211_mcs2media(struct ieee80211com *, int,\n\t\t    enum ieee80211_phymode);\nint\tieee80211_media2mcs(uint64_t);\nu_int8_t ieee80211_rate2plcp(u_int8_t, enum ieee80211_phymode);\nu_int8_t ieee80211_plcp2rate(u_int8_t, enum ieee80211_phymode);\nu_int\tieee80211_mhz2ieee(u_int, u_int);\nu_int\tieee80211_chan2ieee(struct ieee80211com *,\n\t\tconst struct ieee80211_channel *);\nu_int\tieee80211_ieee2mhz(u_int, u_int);\nint\tieee80211_min_basic_rate(struct ieee80211com *);\nint\tieee80211_max_basic_rate(struct ieee80211com *);\nint\tieee80211_setmode(struct ieee80211com *, enum ieee80211_phymode);\nenum ieee80211_phymode ieee80211_next_mode(struct _ifnet *);\nenum ieee80211_phymode ieee80211_chan2mode(struct ieee80211com *,\n\t\tconst struct ieee80211_channel *);\nvoid\tieee80211_disable_wep(struct ieee80211com *); \nvoid\tieee80211_disable_rsn(struct ieee80211com *); \nint\tieee80211_add_ess(struct ieee80211com *, struct ieee80211_join *);\nvoid\tieee80211_del_ess(struct ieee80211com *, char *, int, int);\nvoid\tieee80211_set_ess(struct ieee80211com *, struct ieee80211_ess *,\n\t    struct ieee80211_node *);\nvoid    ieee80211_deselect_ess(struct ieee80211com *);\nstruct ieee80211_ess *ieee80211_get_ess(struct ieee80211com *, const char *, int);\nvoid ieee80211_begin_cache_bgscan(struct _ifnet *);\n\nextern\tint ieee80211_cache_size;\n\n#endif /* _NET80211_IEEE80211_VAR_H_ */\n"
  },
  {
    "path": "itl80211/openbsd/net80211/timeout.c",
    "content": "//\n//  timeout.cpp\n//  AppleIntelWifiAdapter\n//\n//  Created by 钟先耀 on 2020/1/30.\n//  Copyright © 2020 钟先耀. All rights reserved.\n//\n\n/*\n * Copyright (C) 2020  钟先耀\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n */\n\n#ifndef timeout_cpp\n#define timeout_cpp\n\n#include <sys/timeout.h>\n#include <IOKit/IOCommandGate.h>\n\nextern IOWorkLoop *_fWorkloop;\nextern IOCommandGate *_fCommandGate;\n\nint splnet()\n{\n    return 1;\n}\n\nvoid splx(int s)\n{\n}\n\nvoid timeout_set(CTimeout **t, void (*fn)(void *), void *arg)\n{\n    _fCommandGate->runAction(&CTimeout::timeout_set, t, (void*)fn, arg);\n}\n\nint timeout_add_msec(CTimeout **to, int msecs)\n{\n    return _fCommandGate->runAction(&CTimeout::timeout_add_msec, to, _fWorkloop, &msecs) == kIOReturnSuccess ? 1 : 0;\n}\n\nint timeout_add_sec(CTimeout **to, int secs)\n{\n    return timeout_add_msec(to, secs * 1000);\n}\n\nint timeout_add_usec(CTimeout **to, int usecs)\n{\n    return timeout_add_msec(to, (int) usecs / 1000);\n}\n\nint timeout_del(CTimeout **to)\n{\n    //    IOLog(\"timeout_del\\n\");\n    return _fCommandGate->runAction(&CTimeout::timeout_del, to, _fWorkloop) == kIOReturnSuccess ? 1 : 0;\n}\n\nint timeout_free(CTimeout **to)\n{\n    return _fCommandGate->runAction(&CTimeout::timeout_free, to, _fWorkloop) == kIOReturnSuccess ? 1 : 0;\n}\n\nint timeout_pending(CTimeout **to)\n{\n    return _fCommandGate->runAction(&CTimeout::timeout_pending, to) == kIOReturnSuccess ? 1 : 0;\n}\n\nint timeout_initialized(CTimeout **to)\n{\n    return (*to) != NULL;\n}\n\n#endif /* timeout_cpp */\n"
  },
  {
    "path": "itl80211/openbsd/sys/CTimeout.hpp",
    "content": "//\n//  CTimeout.h\n//  AppleIntelWifiAdapter\n//\n//  Created by 钟先耀 on 2020/1/30.\n//  Copyright © 2020 钟先耀. All rights reserved.\n//\n\n/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n\n#ifndef CTimeout_h\n#define CTimeout_h\n\n#include <IOKit/IOTimerEventSource.h>\n#include <libkern/c++/OSObject.h>\n\nclass CTimeout : public OSObject {\n    OSDeclareDefaultStructors(CTimeout)\n    \npublic:\n    static void timeoutOccurred(OSObject* owner, IOTimerEventSource* timer);\n    \n    static IOReturn timeout_add_msec(OSObject *target, void *arg0, void *arg1, void *arg2, void *arg3);\n    \n    static IOReturn timeout_del(OSObject *target, void *arg0, void *arg1, void *arg2, void *arg3);\n    \n    static IOReturn timeout_free(OSObject *target, void *arg0, void *arg1, void *arg2, void *arg3);\n    \n    static IOReturn timeout_set(OSObject *target, void *arg0, void *arg1, void *arg2, void *arg3);\n    \n    static IOReturn timeout_pending(OSObject *target, void *arg0, void *arg1, void *arg2, void *arg3);\n    \npublic:\n    IOTimerEventSource* tm;\n    void (*to_func)(void *);        /* function to call */\n    void *to_arg;                /* function argument */\n    bool isPending;\n};\n\n#endif /* CTimeout_h */\n"
  },
  {
    "path": "itl80211/openbsd/sys/_arc4random.h",
    "content": "//\n//  _arc4random.h\n//  AppleIntelWifiAdapter\n//\n//  Created by 钟先耀 on 2020/1/22.\n//  Copyright © 2020 钟先耀. All rights reserved.\n//\n/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n\n#ifndef _arc4random_h\n#define _arc4random_h\n\n#include <sys/sysctl.h>\n#include <sys/param.h>\n#include <sys/time.h>\n#include <sys/random.h>\n\n#include <IOKit/IOLib.h>\n\n/* Add platform entropy 32 bytes (256 bits) at a time. */\n#define ADD_ENTROPY 32\n\n/* Re-seed from the platform RNG after generating this many bytes. */\n#define BYTES_BEFORE_RESEED 1600000\n\nstatic inline u_int32_t arc4random()\n{\n    u_int32_t r;\n    read_random(&r, sizeof(r));\n    return r;\n}\n\nstatic inline void arc4random_buf(void *buf, size_t n)\n{\n    read_random(buf, (u_int)n);\n}\n\nstatic inline u_int32_t arc4random_uniform(u_int32_t upper_bound)\n{\n    u_int32_t r, min;\n\n    if (upper_bound < 2)\n        return 0;\n\n    /* 2**32 % x == (2**32 - x) % x */\n    min = -upper_bound % upper_bound;\n\n    /*\n     * This could theoretically loop forever but each retry has\n     * p > 0.5 (worst case, usually far better) of selecting a\n     * number inside the range we need, so it should rarely need\n     * to re-roll.\n     */\n    for (;;) {\n        r = arc4random();\n        if (r >= min)\n            break;\n    }\n\n    return r % upper_bound;\n}\n\n#endif\n"
  },
  {
    "path": "itl80211/openbsd/sys/_buf.h",
    "content": "//\n//  _buf.h\n//  AppleIntelWifiAdapter\n//\n//  Created by 钟先耀 on 2020/1/25.\n//  Copyright © 2020 钟先耀. All rights reserved.\n//\n\n/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n\n#ifndef _buf_h\n#define _buf_h\n\n/* Macros to clear/set/test flags. */\n#define SET(t, f)       (t) |= (f)\n#define CLR(t, f)       (t) &= ~(f)\n#define ISSET(t, f)     ((t) & (f))\n\n#endif /* _buf_h */\n"
  },
  {
    "path": "itl80211/openbsd/sys/_clock.h",
    "content": "/*\n* Copyright (C) 2021  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n\n#ifndef _clock_h\n#define _clock_h\n\n#include <sys/time.h>\n\n#define hz  100\n#define ticks   \\\n({  \\\nuint64_t t; \\\nuint64_t k;  \\\nclock_get_uptime(&t);   \\\nabsolutetime_to_nanoseconds(t, &k);  \\\n(int)((k * hz) / 1000000000);  \\\n})\n\n#endif /* _clock_h */\n"
  },
  {
    "path": "itl80211/openbsd/sys/_if_ether.h",
    "content": "//\n//  _if_ether.h\n//  AppleIntelWifiAdapter\n//\n//  Created by 钟先耀 on 2020/1/22.\n//  Copyright © 2020 钟先耀. All rights reserved.\n//\n/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n/*    $OpenBSD: if_ether.h,v 1.76 2019/07/17 16:46:18 mpi Exp $    */\n/*    $NetBSD: if_ether.h,v 1.22 1996/05/11 13:00:00 mycroft Exp $    */\n\n/*\n * Copyright (c) 1982, 1986, 1993\n *    The Regents of the University of California.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the University nor the names of its contributors\n *    may be used to endorse or promote products derived from this software\n *    without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n *    @(#)if_ether.h    8.1 (Berkeley) 6/10/93\n */\n\n#ifndef _if_ether_h\n#define _if_ether_h\n\n#include <net/if.h>\n#include <net/if_var.h>\n#include <sys/queue.h>\n#include <sys/CTimeout.hpp>\n#include <sys/_if_media.h>\n#include <sys/_ifq.h>\n#include <net/if_dl.h>\n\n#include <IOKit/network/IOPacketQueue.h>\n#include <IOKit/network/IOEthernetInterface.h>\n\n#define    ETHER_IS_MULTICAST(addr) (*(addr) & 0x01) /* is address mcast/bcast? */\n#define    ETHER_IS_BROADCAST(addr) \\\n    (((addr)[0] & (addr)[1] & (addr)[2] & \\\n      (addr)[3] & (addr)[4] & (addr)[5]) == 0xff)\n#define    ETHER_IS_ANYADDR(addr)        \\\n    (((addr)[0] | (addr)[1] | (addr)[2] | \\\n      (addr)[3] | (addr)[4] | (addr)[5]) == 0x00)\n#define    ETHER_IS_EQ(a1, a2)    (memcmp((a1), (a2), ETHER_ADDR_LEN) == 0)\n\n#define ETHER_ADDR_LEN 6\n\n/*\n * Ethernet CRC32 polynomials (big- and little-endian verions).\n */\n#define    ETHER_CRC_POLY_LE    0xedb88320\n#define    ETHER_CRC_POLY_BE    0x04c11db6\n\n/*\n * Values for if_link_state.\n */\n#define LINK_STATE_UNKNOWN    0    /* link unknown */\n#define LINK_STATE_INVALID    1    /* link invalid */\n#define LINK_STATE_DOWN        2    /* link is down */\n#define LINK_STATE_KALIVE_DOWN    3    /* keepalive reports down */\n#define LINK_STATE_UP        4    /* link is up */\n#define LINK_STATE_HALF_DUPLEX    5    /* link is up and half duplex */\n#define LINK_STATE_FULL_DUPLEX    6    /* link is up and full duplex */\n\n#define LINK_STATE_IS_UP(_s)    \\\n        ((_s) >= LINK_STATE_UP || (_s) == LINK_STATE_UNKNOWN)\n\n#define splassert(x) (x)\n\n\n/*\n * Status bit descriptions for the various interface types.\n */\nstruct if_status_description {\n    u_char    ifs_type;\n    u_char    ifs_state;\n    const char *ifs_string;\n};\n\n#define LINK_STATE_DESC_MATCH(_ifs, _t, _s)                \\\n    (((_ifs)->ifs_type == (_t) || (_ifs)->ifs_type == 0) &&        \\\n        (_ifs)->ifs_state == (_s))\n\n\n#define LINK_STATE_DESCRIPTIONS {                    \\\n    { IFT_ETHER, LINK_STATE_DOWN, \"no carrier\" },            \\\n                                    \\\n    { IFT_IEEE80211, LINK_STATE_DOWN, \"no network\" },        \\\n                                    \\\n    { IFT_PPP, LINK_STATE_DOWN, \"no carrier\" },            \\\n                                    \\\n    { IFT_CARP, LINK_STATE_DOWN, \"backup\" },            \\\n    { IFT_CARP, LINK_STATE_UP, \"master\" },                \\\n    { IFT_CARP, LINK_STATE_HALF_DUPLEX, \"master\" },            \\\n    { IFT_CARP, LINK_STATE_FULL_DUPLEX, \"master\" },            \\\n                                    \\\n    { 0, LINK_STATE_UP, \"active\" },                    \\\n    { 0, LINK_STATE_HALF_DUPLEX, \"active\" },            \\\n    { 0, LINK_STATE_FULL_DUPLEX, \"active\" },            \\\n                                    \\\n    { 0, LINK_STATE_UNKNOWN, \"unknown\" },                \\\n    { 0, LINK_STATE_INVALID, \"invalid\" },                \\\n    { 0, LINK_STATE_DOWN, \"down\" },                    \\\n    { 0, LINK_STATE_KALIVE_DOWN, \"keepalive down\" },        \\\n    { 0, 0, NULL }                            \\\n}\n\n/*\n * Length of interface description, including terminating '\\0'.\n */\n#define    IFDESCRSIZE    64\n\n/*\n * Ethernet multicast address structure.  There is one of these for each\n * multicast address or range of multicast addresses that we are supposed\n * to listen to on a particular interface.  They are kept in a linked list,\n * rooted in the interface's arpcom structure.  (This really has nothing to\n * do with ARP, or with the Internet address family, but this appears to be\n * the minimally-disrupting place to put it.)\n */\nstruct ether_multi {\n    u_int8_t enm_addrlo[ETHER_ADDR_LEN]; /* low  or only address of range */\n    u_int8_t enm_addrhi[ETHER_ADDR_LEN]; /* high or only address of range */\n    u_int     enm_refcount;        /* no. claims to this addr/range */\n    LIST_ENTRY(ether_multi) enm_list;\n};\n\nstruct _ifnet {                /* and the entries */\n    IOEthernetInterface *iface;\n    IOEthernetController* controller;\n    int if_link_state;\n    void *if_softc;\n//    struct    refcnt if_refcnt;\n    int if_hdrlen;\n    TAILQ_ENTRY(_ifnet) if_list;    /* [k] all struct ifnets are chained */\n    TAILQ_HEAD(, ifaddr) if_addrlist; /* [N] list of addresses per if */\n    TAILQ_HEAD(, ifmaddr) if_maddrlist; /* [N] list of multicast records */\n    TAILQ_HEAD(, ifg_list) if_groups; /* [N] list of groups per if */\n//    struct hook_desc_head *if_addrhooks; /* [I] address change callbacks */\n//    struct hook_desc_head *if_linkstatehooks; /* [I] link change callbacks*/\n//    struct hook_desc_head *if_detachhooks; /* [I] detach callbacks */\n                /* [I] check or clean routes (+ or -)'d */\n    void    (*if_rtrequest)(struct _ifnet *, int, struct rtentry *);\n    char    if_xname[IFNAMSIZ];    /* [I] external name (name + unit) */\n    int    if_pcount;        /* [k] # of promiscuous listeners */\n    unsigned int if_bridgeidx;    /* [k] used by bridge ports */\n    caddr_t    if_bpf;            /* packet filter structure */\n    caddr_t if_switchport;        /* used by switch ports */\n    caddr_t if_mcast;        /* used by multicast code */\n    caddr_t if_mcast6;        /* used by IPv6 multicast code */\n    caddr_t    if_pf_kif;        /* pf interface abstraction */\n    \n    IONetworkStats *netStat;\n    ///extra\n    uint32_t if_ierrors;\n    uint32_t if_oerrors;\n    uint32_t if_ipackets;\n    uint32_t if_imcasts;\n    int if_ibytes;\n    \n    \n//    union {\n//        struct srpl carp_s;    /* carp if list (used by !carp ifs) */\n//        struct _ifnet *carp_d;    /* ptr to carpdev (used by carp ifs) */\n//    } if_carp_ptr;\n#define if_carp        if_carp_ptr.carp_s\n#define if_carpdev    if_carp_ptr.carp_d\n    unsigned int if_index;        /* [I] unique index for this if */\n    short    if_timer;        /* time 'til if_watchdog called */\n    unsigned short if_flags;    /* [N] up/down, broadcast, etc. */\n    int    if_xflags;        /* [N] extra softnet flags */\n    struct    if_data if_data;    /* stats and other data about if */\n    struct    cpumem *if_counters;    /* per cpu stats */\n    uint32_t if_hardmtu;        /* [d] maximum MTU device supports */\n    char    if_description[IFDESCRSIZE]; /* [c] interface description */\n    u_short    if_rtlabelid;        /* [c] next route label */\n    uint8_t if_priority;        /* [c] route priority offset */\n    uint8_t if_llprio;        /* [N] link layer priority */\n    CTimeout* if_slowtimo;    /* [I] watchdog timeout */\n//    struct    task if_watchdogtask;    /* [I] watchdog task */\n//    struct    task if_linkstatetask;    /* [I] task to do route updates */\n//\n//    /* procedure handles */\n//    SRPL_HEAD(, ifih) if_inputs;    /* [k] input routines (dequeue) */\n    int    (*if_output)(struct _ifnet *, mbuf_t, struct sockaddr *,\n             struct rtentry *);    /* output routine (enqueue) */\n                    /* link level output function */\n    int    (*if_ll_output)(struct _ifnet *, mbuf_t,\n            struct sockaddr *, struct rtentry *);\n    int    (*if_enqueue)(struct _ifnet *, mbuf_t);\n    void    (*if_start)(struct _ifnet *);    /* initiate output */\n    int    (*if_ioctl)(struct _ifnet *, u_long, caddr_t); /* ioctl hook */\n    void    (*if_watchdog)(struct _ifnet *);    /* timer routine */\n    int    (*if_wol)(struct _ifnet *, int);    /* WoL routine **/\n\n    /* queues */\n    struct    _ifqueue if_snd;        /* transmit queue */\n    struct    _ifqueue **if_ifqs;    /* [I] pointer to an array of sndqs */\n    void    (*if_qstart)(struct _ifqueue *);\n    unsigned int if_nifqs;        /* [I] number of output queues */\n    unsigned int if_txmit;        /* [c] txmitigation amount */\n\n//    struct    ifiqueue if_rcv;    /* rx/input queue */\n//    struct    ifiqueue **if_iqs;    /* [I] pointer to the array of iqs */\n    unsigned int if_niqs;        /* [I] number of input queues */\n\n    struct sockaddr_dl *if_sadl;    /* [N] pointer to our sockaddr_dl */\n\n    void    *if_afdata[AF_MAX];\n};\n\n/*\n * Structure shared between the ethernet driver modules and\n * the address resolution code.  For example, each ec_softc or il_softc\n * begins with this structure.\n */\nstruct  arpcom {\n    struct     _ifnet ac_if;            /* network-visible interface */\n    u_int8_t ac_enaddr[ETHER_ADDR_LEN];    /* ethernet hardware address */\n    char     ac__pad[2];            /* pad for some machines */\n    LIST_HEAD(, ether_multi) ac_multiaddrs;    /* list of multicast addrs */\n    int     ac_multicnt;            /* length of ac_multiaddrs */\n    int     ac_multirangecnt;        /* number of mcast ranges */\n\n    void    *ac_trunkport;\n};\n\nstatic inline u_int8_t etherbroadcastaddr[ETHER_ADDR_LEN] =\n    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };\nstatic inline u_int8_t etheranyaddr[ETHER_ADDR_LEN] =\n    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };\n#define senderr(e) { error = (e); goto bad;}\n\nstatic inline int\nif_setlladdr(struct _ifnet *ifp, const uint8_t *lladdr)\n{\n    memcpy(((struct arpcom *)ifp)->ac_enaddr, lladdr, ETHER_ADDR_LEN);\n    return (0);\n}\n\nstatic inline int\nif_attach(struct _ifnet *ifp)\n{\n    ifp->if_link_state = -1;\n    return 0;\n}\n\nstatic inline int\nif_detach(struct _ifnet *ifp)\n{\n    ifp->if_link_state = -1;\n    return 0;\n}\n\nstatic inline int\nether_ifattach(struct _ifnet *ifp, IOEthernetInterface *iface)\n{\n    ifp->iface = iface;\n}\n\nstatic inline void\nether_ifdetach(struct _ifnet *ifp)\n{\n    ifp->iface = NULL;\n}\n\n#endif /* _if_ether_h */\n"
  },
  {
    "path": "itl80211/openbsd/sys/_if_media.h",
    "content": "/*    $OpenBSD: if_media.h,v 1.41 2018/02/04 10:06:51 stsp Exp $    */\n/*    $NetBSD: if_media.h,v 1.22 2000/02/17 21:53:16 sommerfeld Exp $    */\n\n/*-\n * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.\n * All rights reserved.\n *\n * This code is derived from software contributed to The NetBSD Foundation\n * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,\n * NASA Ames Research Center.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS\n * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED\n * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS\n * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*\n * Copyright (c) 1997\n *    Jonathan Stone and Jason R. Thorpe.  All rights reserved.\n *\n * This software is derived from information provided by Matt Thomas.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    This product includes software developed by Jonathan Stone\n *    and Jason R. Thorpe for the NetBSD Project.\n * 4. The names of the authors may not be used to endorse or promote products\n *    derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,\n * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED\n * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n */\n\n#ifndef _NET2_IF_MEDIA_H_\n#define _NET2_IF_MEDIA_H_\n\n#include <sys/queue.h>\n\n#include <IOKit/IOLib.h>\n#include <linux/types.h>\n\n#define _KERNEL\n\n#ifdef _KERNEL\n\nstruct ifmediareq {\n    char        ifm_name[IFNAMSIZ];    /* if name, e.g. \"en0\" */\n    uint64_t    ifm_current;        /* get/set current media options */\n    uint64_t    ifm_mask;        /* don't care mask */\n    uint64_t    ifm_status;        /* media status */\n    uint64_t    ifm_active;        /* active options */\n    int        ifm_count;        /* # entries in ifm_ulist array */\n    uint64_t    *ifm_ulist;        /* media words */\n};\n\n/*\n * Driver callbacks for media status and change requests.\n */\ntypedef    int (*ifm_change_cb_t)(struct _ifnet *);\ntypedef    void (*ifm_stat_cb_t)(struct _ifnet *, struct ifmediareq *);\n\n/*\n * In-kernel representation of a single supported media type.\n */\nstruct ifmedia_entry {\n    TAILQ_ENTRY(ifmedia_entry) ifm_list;\n    uint64_t    ifm_media;    /* description of this media attachment */\n    u_int    ifm_data;    /* for driver-specific use */\n    void    *ifm_aux;    /* for driver-specific use */\n};\n\n/*\n * One of these goes into a network interface's softc structure.\n * It is used to keep general media state.\n */\nstruct ifmedia {\n    uint64_t    ifm_mask;    /* mask of changes we don't care about */\n    uint64_t    ifm_media;    /* current user-set media word */\n    struct ifmedia_entry *ifm_cur;    /* currently selected media */\n    TAILQ_HEAD(, ifmedia_entry) ifm_list; /* list of all supported media */\n    ifm_change_cb_t    ifm_change;    /* media change driver callback */\n    ifm_stat_cb_t    ifm_status;    /* media status driver callback */\n};\n\n//\n/* Initialize an interface's struct if_media field. */\nstatic inline void ifmedia_init(struct ifmedia *ifm, uint64_t dontcare_mask)\n{\n    TAILQ_INIT(&ifm->ifm_list);\n    ifm->ifm_cur = NULL;\n    ifm->ifm_media = 0;\n    ifm->ifm_mask = dontcare_mask;        /* IF don't-care bits */\n}\n\n//\n///* Add one supported medium to a struct ifmedia. */\n//void    ifmedia_add(struct ifmedia *, uint64_t, int, void *);\n//\n///* Add an array (of ifmedia_entry) media to a struct ifmedia. */\n//void    ifmedia_list_add(struct ifmedia *, struct ifmedia_entry *,\n//        int);\n//\n\n///* Common ioctl function for getting/setting media, called by driver. */\n//int    ifmedia_ioctl(struct _ifnet *, struct ifreq *, struct ifmedia *,\n//        u_long);\n//\n///* Locate a media entry */\n//struct    ifmedia_entry *ifmedia_match(struct ifmedia *, uint64_t, uint64_t);\n//\n\n///* Compute baudrate for a given media. */\n//uint64_t    ifmedia_baudrate(uint64_t);\n#endif /*_KERNEL */\n\n/*\n * if_media Options word:\n *    Bits    Use\n *    ----    -------\n *    0-7    Media subtype        MAX SUBTYPE == 255!\n *    8-15    Media type\n *    16-31    Type specific options\n *    32-39    Mode (for multi-mode devices)\n *    40-55    Shared (global) options\n *    56-63    Instance\n */\n\n/*\n * Ethernet\n */\n#define IFM_ETHER    0x0000000000000100ULL\n#define    IFM_10_T    3        /* 10BaseT - RJ45 */\n#define    IFM_10_2    4        /* 10Base2 - Thinnet */\n#define    IFM_10_5    5        /* 10Base5 - AUI */\n#define    IFM_100_TX    6        /* 100BaseTX - RJ45 */\n#define    IFM_100_FX    7        /* 100BaseFX - Fiber */\n#define    IFM_100_T4    8        /* 100BaseT4 - 4 pair cat 3 */\n#define    IFM_100_VG    9        /* 100VG-AnyLAN */\n#define    IFM_100_T2    10        /* 100BaseT2 */\n#define    IFM_1000_SX    11        /* 1000BaseSX - multi-mode fiber */\n#define    IFM_10_STP    12        /* 10BaseT over shielded TP */\n#define    IFM_10_FL    13        /* 10BaseFL - Fiber */\n#define    IFM_1000_LX    14        /* 1000baseLX - single-mode fiber */\n#define    IFM_1000_CX    15        /* 1000baseCX - 150ohm STP */\n#define    IFM_1000_T    16        /* 1000baseT - 4 pair cat 5 */\n#define    IFM_1000_TX    IFM_1000_T    /* for backwards compatibility */\n#define    IFM_HPNA_1    17        /* HomePNA 1.0 (1Mb/s) */\n#define    IFM_10G_LR    18        /* 10GBase-LR - single-mode fiber */\n#define    IFM_10G_SR    19        /* 10GBase-SR - multi-mode fiber */\n#define    IFM_10G_CX4    20        /* 10GBase-CX4 - copper */\n#define    IFM_2500_SX    21        /* 2500baseSX - multi-mode fiber */\n#define    IFM_10G_T    22        /* 10GbaseT cat 6 */\n#define    IFM_10G_SFP_CU    23        /* 10G SFP+ direct attached cable */\n#define    IFM_10G_LRM    24        /* 10GBase-LRM 850nm Multi-mode */\n#define    IFM_40G_CR4    25        /* 40GBase-CR4 */\n#define    IFM_40G_SR4    26        /* 40GBase-SR4 */\n#define    IFM_40G_LR4    27        /* 40GBase-LR4 */\n#define    IFM_1000_KX    28        /* 1000Base-KX backplane */\n#define    IFM_10G_KX4    29        /* 10GBase-KX4 backplane */\n#define    IFM_10G_KR    30        /* 10GBase-KR backplane */\n#define    IFM_10G_CR1    31        /* 10GBase-CR1 Twinax splitter */\n#define    IFM_20G_KR2    32        /* 20GBase-KR2 backplane */\n#define    IFM_2500_KX    33        /* 2500Base-KX backplane */\n#define    IFM_2500_T    34        /* 2500Base-T - RJ45 (NBaseT) */\n#define    IFM_5000_T    35        /* 5000Base-T - RJ45 (NBaseT) */\n#define    IFM_1000_SGMII    36        /* 1G media interface */\n#define    IFM_10G_SFI    37        /* 10G media interface */\n#define    IFM_40G_XLPPI    38        /* 40G media interface */\n#define    IFM_1000_CX_SGMII 39        /* 1000Base-CX-SGMII */\n#define    IFM_40G_KR4    40        /* 40GBase-KR4 */\n#define    IFM_10G_ER    41        /* 10GBase-ER */\n#define    IFM_100G_CR4    42        /* 100GBase-CR4 */\n#define    IFM_100G_SR4    43        /* 100GBase-SR4 */\n#define    IFM_100G_KR4    44        /* 100GBase-KR4 */\n#define    IFM_100G_LR4    45        /* 100GBase-LR4 */\n#define    IFM_56G_R4    46        /* 56GBase-R4 */\n#define    IFM_25G_CR    47        /* 25GBase-CR */\n#define    IFM_25G_KR    48        /* 25GBase-KR */\n#define    IFM_25G_SR    49        /* 25GBase-SR */\n#define    IFM_50G_CR2    50        /* 50GBase-CR2 */\n#define    IFM_50G_KR2    51        /* 50GBase-KR2 */\n#define    IFM_25G_LR    52        /* 25GBase-LR */\n#define    IFM_25G_ER    53        /* 25GBase-ER */\n#define    IFM_10G_AOC    54        /* 10G Active Optical Cable */\n#define    IFM_25G_AOC    55        /* 25G Active Optical Cable */\n#define    IFM_40G_AOC    56        /* 40G Active Optical Cable */\n#define    IFM_100G_AOC    57        /* 100G Active Optical Cable */\n\n#define    IFM_ETH_MASTER    0x0000000000010000ULL    /* master mode (1000baseT) */\n#define    IFM_ETH_RXPAUSE    0x0000000000020000ULL    /* receive PAUSE frames */\n#define    IFM_ETH_TXPAUSE    0x0000000000040000ULL    /* transmit PAUSE frames */\n\n/*\n * FDDI\n */\n#define    IFM_FDDI    0x0000000000000300ULL\n#define    IFM_FDDI_SMF    3        /* Single-mode fiber */\n#define    IFM_FDDI_MMF    4        /* Multi-mode fiber */\n#define IFM_FDDI_UTP    5        /* CDDI / UTP */\n#define IFM_FDDI_DA    0x00000100    /* Dual attach / single attach */\n\n/*\n * IEEE 802.11 Wireless\n */\n#define    IFM_IEEE80211    0x0000000000000400ULL\n#define    IFM_IEEE80211_FH1    3    /* Frequency Hopping 1Mbps */\n#define    IFM_IEEE80211_FH2    4    /* Frequency Hopping 2Mbps */\n#define    IFM_IEEE80211_DS2    5    /* Direct Sequence 2Mbps */\n#define    IFM_IEEE80211_DS5    6    /* Direct Sequence 5Mbps*/\n#define    IFM_IEEE80211_DS11    7    /* Direct Sequence 11Mbps*/\n#define    IFM_IEEE80211_DS1    8    /* Direct Sequence  1Mbps*/\n#define IFM_IEEE80211_DS22    9    /* Direct Sequence 22Mbps */\n#define IFM_IEEE80211_OFDM6    10    /* OFDM 6Mbps */\n#define IFM_IEEE80211_OFDM9    11    /* OFDM 9Mbps */\n#define IFM_IEEE80211_OFDM12    12    /* OFDM 12Mbps */\n#define IFM_IEEE80211_OFDM18    13    /* OFDM 18Mbps */\n#define IFM_IEEE80211_OFDM24    14    /* OFDM 24Mbps */\n#define IFM_IEEE80211_OFDM36    15    /* OFDM 36Mbps */\n#define IFM_IEEE80211_OFDM48    16    /* OFDM 48Mbps */\n#define IFM_IEEE80211_OFDM54    17    /* OFDM 54Mbps */\n#define IFM_IEEE80211_OFDM72    18    /* OFDM 72Mbps */\n#define IFM_IEEE80211_HT_MCS0    19    /* 11n MCS 0 */\n#define IFM_IEEE80211_HT_MCS1    20    /* 11n MCS 1 */\n#define IFM_IEEE80211_HT_MCS2    21    /* 11n MCS 2 */\n#define IFM_IEEE80211_HT_MCS3    22    /* 11n MCS 3 */\n#define IFM_IEEE80211_HT_MCS4    23    /* 11n MCS 4 */\n#define IFM_IEEE80211_HT_MCS5    24    /* 11n MCS 5 */\n#define IFM_IEEE80211_HT_MCS6    25    /* 11n MCS 6 */\n#define IFM_IEEE80211_HT_MCS7    26    /* 11n MCS 7 */\n#define IFM_IEEE80211_HT_MCS8    27    /* 11n MCS 8 */\n#define IFM_IEEE80211_HT_MCS9    28    /* 11n MCS 9 */\n#define IFM_IEEE80211_HT_MCS10    29    /* 11n MCS 10 */\n#define IFM_IEEE80211_HT_MCS11    30    /* 11n MCS 11 */\n#define IFM_IEEE80211_HT_MCS12    31    /* 11n MCS 12 */\n#define IFM_IEEE80211_HT_MCS13    32    /* 11n MCS 13 */\n#define IFM_IEEE80211_HT_MCS14    33    /* 11n MCS 14 */\n#define IFM_IEEE80211_HT_MCS15    34    /* 11n MCS 15 */\n#define IFM_IEEE80211_HT_MCS16    35    /* 11n MCS 16 */\n#define IFM_IEEE80211_HT_MCS17    36    /* 11n MCS 17 */\n#define IFM_IEEE80211_HT_MCS18    37    /* 11n MCS 18 */\n#define IFM_IEEE80211_HT_MCS19    38    /* 11n MCS 19 */\n#define IFM_IEEE80211_HT_MCS20    39    /* 11n MCS 20 */\n#define IFM_IEEE80211_HT_MCS21    40    /* 11n MCS 21 */\n#define IFM_IEEE80211_HT_MCS22    41    /* 11n MCS 22 */\n#define IFM_IEEE80211_HT_MCS23    42    /* 11n MCS 23 */\n#define IFM_IEEE80211_HT_MCS24    43    /* 11n MCS 24 */\n#define IFM_IEEE80211_HT_MCS25    44    /* 11n MCS 25 */\n#define IFM_IEEE80211_HT_MCS26    45    /* 11n MCS 26 */\n#define IFM_IEEE80211_HT_MCS27    46    /* 11n MCS 27 */\n#define IFM_IEEE80211_HT_MCS28    47    /* 11n MCS 28 */\n#define IFM_IEEE80211_HT_MCS29    48    /* 11n MCS 29 */\n#define IFM_IEEE80211_HT_MCS30    49    /* 11n MCS 30 */\n#define IFM_IEEE80211_HT_MCS31    50    /* 11n MCS 31 */\n#define IFM_IEEE80211_HT_MCS32    51    /* 11n MCS 32 */\n#define IFM_IEEE80211_HT_MCS33    52    /* 11n MCS 33 */\n#define IFM_IEEE80211_HT_MCS34    53    /* 11n MCS 34 */\n#define IFM_IEEE80211_HT_MCS35    54    /* 11n MCS 35 */\n#define IFM_IEEE80211_HT_MCS36    55    /* 11n MCS 36 */\n#define IFM_IEEE80211_HT_MCS37    56    /* 11n MCS 37 */\n#define IFM_IEEE80211_HT_MCS38    57    /* 11n MCS 38 */\n#define IFM_IEEE80211_HT_MCS39    58    /* 11n MCS 39 */\n#define IFM_IEEE80211_HT_MCS40    59    /* 11n MCS 40 */\n#define IFM_IEEE80211_HT_MCS41    60    /* 11n MCS 41 */\n#define IFM_IEEE80211_HT_MCS42    61    /* 11n MCS 42 */\n#define IFM_IEEE80211_HT_MCS43    62    /* 11n MCS 43 */\n#define IFM_IEEE80211_HT_MCS44    63    /* 11n MCS 44 */\n#define IFM_IEEE80211_HT_MCS45    64    /* 11n MCS 45 */\n#define IFM_IEEE80211_HT_MCS46    65    /* 11n MCS 46 */\n#define IFM_IEEE80211_HT_MCS47    66    /* 11n MCS 47 */\n#define IFM_IEEE80211_HT_MCS48    67    /* 11n MCS 48 */\n#define IFM_IEEE80211_HT_MCS49    68    /* 11n MCS 49 */\n#define IFM_IEEE80211_HT_MCS50    69    /* 11n MCS 50 */\n#define IFM_IEEE80211_HT_MCS51    70    /* 11n MCS 51 */\n#define IFM_IEEE80211_HT_MCS52    71    /* 11n MCS 52 */\n#define IFM_IEEE80211_HT_MCS53    72    /* 11n MCS 53 */\n#define IFM_IEEE80211_HT_MCS54    73    /* 11n MCS 54 */\n#define IFM_IEEE80211_HT_MCS55    74    /* 11n MCS 55 */\n#define IFM_IEEE80211_HT_MCS56    75    /* 11n MCS 56 */\n#define IFM_IEEE80211_HT_MCS57    76    /* 11n MCS 57 */\n#define IFM_IEEE80211_HT_MCS58    77    /* 11n MCS 58 */\n#define IFM_IEEE80211_HT_MCS59    78    /* 11n MCS 59 */\n#define IFM_IEEE80211_HT_MCS60    79    /* 11n MCS 60 */\n#define IFM_IEEE80211_HT_MCS61    80    /* 11n MCS 61 */\n#define IFM_IEEE80211_HT_MCS62    81    /* 11n MCS 62 */\n#define IFM_IEEE80211_HT_MCS63    82    /* 11n MCS 63 */\n#define IFM_IEEE80211_HT_MCS64    83    /* 11n MCS 64 */\n#define IFM_IEEE80211_HT_MCS65    84    /* 11n MCS 65 */\n#define IFM_IEEE80211_HT_MCS66    85    /* 11n MCS 66 */\n#define IFM_IEEE80211_HT_MCS67    86    /* 11n MCS 67 */\n#define IFM_IEEE80211_HT_MCS68    87    /* 11n MCS 68 */\n#define IFM_IEEE80211_HT_MCS69    88    /* 11n MCS 69 */\n#define IFM_IEEE80211_HT_MCS70    89    /* 11n MCS 70 */\n#define IFM_IEEE80211_HT_MCS71    90    /* 11n MCS 71 */\n#define IFM_IEEE80211_HT_MCS72    91    /* 11n MCS 72 */\n#define IFM_IEEE80211_HT_MCS73    92    /* 11n MCS 73 */\n#define IFM_IEEE80211_HT_MCS74    93    /* 11n MCS 74 */\n#define IFM_IEEE80211_HT_MCS75    94    /* 11n MCS 75 */\n#define IFM_IEEE80211_HT_MCS76    95    /* 11n MCS 76 */\n#define IFM_IEEE80211_VHT_MCS0    96    /* 11ac MCS 0 */\n#define IFM_IEEE80211_VHT_MCS1    97    /* 11ac MCS 1 */\n#define IFM_IEEE80211_VHT_MCS2    98    /* 11ac MCS 2 */\n#define IFM_IEEE80211_VHT_MCS3    99    /* 11ac MCS 3 */\n#define IFM_IEEE80211_VHT_MCS4    100    /* 11ac MCS 4 */\n#define IFM_IEEE80211_VHT_MCS5    101    /* 11ac MCS 5 */\n#define IFM_IEEE80211_VHT_MCS6    102    /* 11ac MCS 6 */\n#define IFM_IEEE80211_VHT_MCS7    103    /* 11ac MCS 7 */\n#define IFM_IEEE80211_VHT_MCS8    104    /* 11ac MCS 8 */\n#define IFM_IEEE80211_VHT_MCS9    105    /* 11ac MCS 9 */\n\n#define    IFM_IEEE80211_ADHOC    0x0000000000010000ULL    /* Operate in Adhoc mode */\n#define    IFM_IEEE80211_HOSTAP    0x0000000000020000ULL    /* Operate in Host AP mode */\n#define    IFM_IEEE80211_IBSS    0x0000000000040000ULL    /* Operate in IBSS mode */\n#define    IFM_IEEE80211_IBSSMASTER 0x0000000000080000ULL    /* Operate as an IBSS master */\n#define    IFM_IEEE80211_MONITOR    0x0000000000100000ULL    /* Operate in Monitor mode */\n\n/* operating mode for multi-mode devices */\n#define IFM_IEEE80211_11A    0x0000000100000000ULL    /* 5GHz, OFDM mode */\n#define IFM_IEEE80211_11B    0x0000000200000000ULL    /* Direct Sequence mode */\n#define IFM_IEEE80211_11G    0x0000000300000000ULL    /* 2GHz, CCK mode */\n#define IFM_IEEE80211_FH    0x0000000400000000ULL    /* 2GHz, GFSK mode */\n#define IFM_IEEE80211_11N    0x0000000800000000ULL    /* 11n/HT 2GHz/5GHz */\n#define IFM_IEEE80211_11AC    0x0000001000000000ULL    /* 11ac/VHT 5GHz */\n#define IFM_IEEE80211_11AX    0x0000002000000000ULL    /* 11ax/HE 5GHz/6GHz */\n\n/*\n * Digitally multiplexed \"Carrier\" Serial Interfaces\n */\n#define    IFM_TDM        0x0000000000000500ULL\n#define IFM_TDM_T1        3    /* T1 B8ZS+ESF 24 ts */\n#define IFM_TDM_T1_AMI        4    /* T1 AMI+SF 24 ts */\n#define IFM_TDM_E1        5    /* E1 HDB3+G.703 clearchannel 32 ts */\n#define IFM_TDM_E1_G704        6    /* E1 HDB3+G.703+G.704 channelized 31 ts */\n#define IFM_TDM_E1_AMI        7    /* E1 AMI+G.703 32 ts */\n#define IFM_TDM_E1_AMI_G704    8    /* E1 AMI+G.703+G.704 31 ts */\n#define IFM_TDM_T3        9    /* T3 B3ZS+C-bit 672 ts */\n#define IFM_TDM_T3_M13        10    /* T3 B3ZS+M13 672 ts */\n#define IFM_TDM_E3        11    /* E3 HDB3+G.751 512? ts */\n#define IFM_TDM_E3_G751        12    /* E3 G.751 512 ts */\n#define IFM_TDM_E3_G832        13    /* E3 G.832 512 ts */\n#define IFM_TDM_E1_G704_CRC4    14    /* E1 HDB3+G.703+G.704 31 ts + CRC4 */\n/*\n * 6 major ways that networks talk: Drivers enforce independent selection,\n * meaning, a driver will ensure that only one of these is set at a time.\n * Default is cisco hdlc mode with 32 bit CRC.\n */\n#define IFM_TDM_HDLC_CRC16    0x0100    /* Use 16-bit CRC for HDLC instead */\n#define IFM_TDM_PPP        0x0200    /* SPPP (dumb) */\n#define IFM_TDM_FR_ANSI        0x0400    /* Frame Relay + LMI ANSI \"Annex D\" */\n#define IFM_TDM_FR_CISCO    0x0800    /* Frame Relay + LMI Cisco */\n#define IFM_TDM_FR_ITU        0x1000    /* Frame Relay + LMI ITU \"Q933A\" */\n\n/* operating mode */\n#define IFM_TDM_MASTER        0x0000000100000000ULL    /* aka clock source internal */\n\n/*\n * Common Access Redundancy Protocol\n */\n#define    IFM_CARP        0x0000000000000600ULL\n\n/*\n * Shared media sub-types\n */\n#define    IFM_AUTO    0ULL        /* Autoselect best media */\n#define    IFM_MANUAL    1ULL        /* Jumper/dipswitch selects media */\n#define    IFM_NONE    2ULL        /* Deselect all media */\n\n/*\n * Shared options\n */\n#define IFM_FDX        0x0000010000000000ULL    /* Force full duplex */\n#define    IFM_HDX        0x0000020000000000ULL    /* Force half duplex */\n#define    IFM_FLOW    0x0000040000000000ULL    /* enable hardware flow control */\n#define IFM_FLAG0    0x0000100000000000ULL    /* Driver defined flag */\n#define IFM_FLAG1    0x0000200000000000ULL    /* Driver defined flag */\n#define IFM_FLAG2    0x0000400000000000ULL    /* Driver defined flag */\n#define    IFM_LOOP    0x0000800000000000ULL    /* Put hardware in loopback */\n\n/*\n * Masks\n */\n#define    IFM_NMASK    0x000000000000ff00ULL    /* Network type */\n#define    IFM_NSHIFT    8            /* Network type shift */\n#define    IFM_TMASK    0x00000000000000ffULL    /* Media sub-type */\n#define    IFM_TSHIFT    0            /* Sub-type shift */\n#define    IFM_IMASK    0xff00000000000000ULL    /* Instance */\n#define    IFM_ISHIFT    56            /* Instance shift */\n#define    IFM_OMASK    0x00000000ffff0000ULL    /* Type specific options */\n#define    IFM_OSHIFT    16            /* Specific options shift */\n#define    IFM_MMASK    0x000000ff00000000ULL    /* Mode */\n#define    IFM_MSHIFT    32            /* Mode shift */\n#define    IFM_GMASK    0x00ffff0000000000ULL    /* Global options */\n#define    IFM_GSHIFT    40            /* Global options shift */\n\n/* Ethernet flow control mask */\n#define    IFM_ETH_FMASK    (IFM_FLOW|IFM_ETH_RXPAUSE|IFM_ETH_TXPAUSE)\n\n#define    IFM_NMIN    IFM_ETHER    /* lowest Network type */\n#define    IFM_NMAX    IFM_NMASK    /* highest Network type */\n\n/*\n * Status bits\n */\n#define    IFM_AVALID    0x0000000000000001ULL    /* Active bit valid */\n#define    IFM_ACTIVE    0x0000000000000002ULL    /* Interface attached to working net */\n\n/* Mask of \"status valid\" bits, for ifconfig(8). */\n#define    IFM_STATUS_VALID    IFM_AVALID\n\n/* List of \"status valid\" bits, for ifconfig(8). */\n#define    IFM_STATUS_VALID_LIST {                        \\\nIFM_AVALID,                            \\\n0                                \\\n}\n\n/*\n * Macros to extract various bits of information from the media word.\n */\n#define    IFM_TYPE(x)    ((x) & IFM_NMASK)\n#define    IFM_SUBTYPE(x)    ((x) & IFM_TMASK)\n#define    IFM_INST(x)    (((x) & IFM_IMASK) >> IFM_ISHIFT)\n#define    IFM_OPTIONS(x)    ((x) & (IFM_OMASK|IFM_GMASK))\n#define    IFM_MODE(x)    ((x) & IFM_MMASK)\n\n#define    IFM_INST_MAX    IFM_INST(IFM_IMASK)\n#define    IFM_INST_ANY    ((uint64_t) -1)\n\n/*\n * Macro to create a media word.\n * All arguments are IFM_* macros, except 'instance' which is a 64-bit integer.\n * XXX 'operating mode' is not included here?!?\n */\n#define    IFM_MAKEWORD(type, subtype, options, instance)            \\\n((type) | (subtype) | (options) | \\\n((uint64_t)(instance) << IFM_ISHIFT))\n\n/*\n * Add a media configuration to the list of supported media\n * for a specific interface instance.\n */\nstatic inline void\nifmedia_add(struct ifmedia *ifm, uint64_t mword, int data, void *aux)\n{\n    struct ifmedia_entry *entry;\n    \n    entry = (struct ifmedia_entry *)IOMalloc(sizeof(*entry));\n    if (entry == NULL)\n        panic(\"ifmedia_add: can't malloc entry\");\n    \n    entry->ifm_media = mword;\n    entry->ifm_data = data;\n    entry->ifm_aux = aux;\n    \n    TAILQ_INSERT_TAIL(&ifm->ifm_list, entry, ifm_list);\n}\n\n///*\n// * NetBSD extension not defined in the BSDI API.  This is used in various\n// * places to get the canonical description for a given type/subtype.\n// *\n// * In the subtype and mediaopt descriptions, the valid TYPE bits are OR'd\n// * in to indicate which TYPE the subtype/option corresponds to.  If no\n// * TYPE is present, it is a shared media/mediaopt.\n// *\n// * Note that these are parsed case-insensitive.\n// *\n// * Order is important.  The first matching entry is the canonical name\n// * for a media type; subsequent matches are aliases.\n// */\n//struct ifmedia_description {\n//    uint64_t    ifmt_word;    /* word value; may be masked */\n//    const char    *ifmt_string;    /* description */\n//};\n\n#define    IFM_TYPE_DESCRIPTIONS {                        \\\n{ IFM_ETHER,            \"Ethernet\" },            \\\n{ IFM_ETHER,            \"ether\" },            \\\n{ IFM_FDDI,            \"FDDI\" },            \\\n{ IFM_IEEE80211,        \"IEEE802.11\" },            \\\n{ IFM_TDM,            \"TDM\" },            \\\n{ IFM_CARP,            \"CARP\" },            \\\n{ 0, NULL },                            \\\n}\n\n#define    IFM_TYPE_MATCH(dt, t)                        \\\n(IFM_TYPE((dt)) == 0 || IFM_TYPE((dt)) == IFM_TYPE((t)))\n\n#define    IFM_SUBTYPE_DESCRIPTIONS {                    \\\n{ IFM_AUTO,            \"autoselect\" },            \\\n{ IFM_AUTO,            \"auto\" },            \\\n{ IFM_MANUAL,            \"manual\" },            \\\n{ IFM_NONE,            \"none\" },            \\\n\\\n{ IFM_ETHER|IFM_10_T,        \"10baseT\" },            \\\n{ IFM_ETHER|IFM_10_T,        \"10baseT/UTP\" },        \\\n{ IFM_ETHER|IFM_10_T,        \"UTP\" },            \\\n{ IFM_ETHER|IFM_10_T,        \"10UTP\" },            \\\n{ IFM_ETHER|IFM_10_2,        \"10base2\" },            \\\n{ IFM_ETHER|IFM_10_2,        \"10base2/BNC\" },        \\\n{ IFM_ETHER|IFM_10_2,        \"BNC\" },            \\\n{ IFM_ETHER|IFM_10_2,        \"10BNC\" },            \\\n{ IFM_ETHER|IFM_10_5,        \"10base5\" },            \\\n{ IFM_ETHER|IFM_10_5,        \"10base5/AUI\" },        \\\n{ IFM_ETHER|IFM_10_5,        \"AUI\" },            \\\n{ IFM_ETHER|IFM_10_5,        \"10AUI\" },            \\\n{ IFM_ETHER|IFM_100_TX,        \"100baseTX\" },            \\\n{ IFM_ETHER|IFM_100_TX,        \"100TX\" },            \\\n{ IFM_ETHER|IFM_100_FX,        \"100baseFX\" },            \\\n{ IFM_ETHER|IFM_100_FX,        \"100FX\" },            \\\n{ IFM_ETHER|IFM_100_T4,        \"100baseT4\" },            \\\n{ IFM_ETHER|IFM_100_T4,        \"100T4\" },            \\\n{ IFM_ETHER|IFM_100_VG,        \"100baseVG\" },            \\\n{ IFM_ETHER|IFM_100_VG,        \"100VG\" },            \\\n{ IFM_ETHER|IFM_100_T2,        \"100baseT2\" },            \\\n{ IFM_ETHER|IFM_100_T2,        \"100T2\" },            \\\n{ IFM_ETHER|IFM_1000_SX,    \"1000baseSX\" },            \\\n{ IFM_ETHER|IFM_1000_SX,    \"1000SX\" },            \\\n{ IFM_ETHER|IFM_10_STP,        \"10baseSTP\" },            \\\n{ IFM_ETHER|IFM_10_STP,        \"STP\" },            \\\n{ IFM_ETHER|IFM_10_STP,        \"10STP\" },            \\\n{ IFM_ETHER|IFM_10_FL,        \"10baseFL\" },            \\\n{ IFM_ETHER|IFM_10_FL,        \"FL\" },                \\\n{ IFM_ETHER|IFM_10_FL,        \"10FL\" },            \\\n{ IFM_ETHER|IFM_1000_LX,    \"1000baseLX\" },            \\\n{ IFM_ETHER|IFM_1000_LX,    \"1000LX\" },            \\\n{ IFM_ETHER|IFM_1000_CX,    \"1000baseCX\" },            \\\n{ IFM_ETHER|IFM_1000_CX,    \"1000CX\" },            \\\n{ IFM_ETHER|IFM_1000_T,        \"1000baseT\" },            \\\n{ IFM_ETHER|IFM_1000_T,        \"1000T\" },            \\\n{ IFM_ETHER|IFM_1000_T,        \"1000baseTX\" },            \\\n{ IFM_ETHER|IFM_1000_T,        \"1000TX\" },            \\\n{ IFM_ETHER|IFM_HPNA_1,        \"HomePNA1\" },            \\\n{ IFM_ETHER|IFM_HPNA_1,        \"HPNA1\" },            \\\n{ IFM_ETHER|IFM_10G_LR,        \"10GbaseLR\" },            \\\n{ IFM_ETHER|IFM_10G_LR,        \"10GLR\" },            \\\n{ IFM_ETHER|IFM_10G_LR,        \"10GBASE-LR\" },            \\\n{ IFM_ETHER|IFM_10G_SR,        \"10GbaseSR\" },            \\\n{ IFM_ETHER|IFM_10G_SR,        \"10GSR\" },            \\\n{ IFM_ETHER|IFM_10G_SR,        \"10GBASE-SR\" },            \\\n{ IFM_ETHER|IFM_10G_CX4,    \"10GbaseCX4\" },            \\\n{ IFM_ETHER|IFM_10G_CX4,    \"10GCX4\" },            \\\n{ IFM_ETHER|IFM_10G_CX4,    \"10GBASE-CX4\" },        \\\n{ IFM_ETHER|IFM_2500_SX,    \"2500baseSX\" },            \\\n{ IFM_ETHER|IFM_2500_SX,    \"2500SX\" },            \\\n{ IFM_ETHER|IFM_10G_T,        \"10GbaseT\" },            \\\n{ IFM_ETHER|IFM_10G_T,        \"10GT\" },            \\\n{ IFM_ETHER|IFM_10G_T,        \"10GBASE-T\" },            \\\n{ IFM_ETHER|IFM_10G_SFP_CU,    \"10GSFP+Cu\" },            \\\n{ IFM_ETHER|IFM_10G_SFP_CU,    \"10GCu\" },            \\\n{ IFM_ETHER|IFM_10G_LRM,    \"10GbaseLRM\" },            \\\n{ IFM_ETHER|IFM_10G_LRM,    \"10GBASE-LRM\" },        \\\n{ IFM_ETHER|IFM_40G_CR4,    \"40GbaseCR4\" },            \\\n{ IFM_ETHER|IFM_40G_CR4,    \"40GBASE-CR4\" },        \\\n{ IFM_ETHER|IFM_40G_SR4,    \"40GbaseSR4\" },            \\\n{ IFM_ETHER|IFM_40G_SR4,    \"40GBASE-SR4\" },        \\\n{ IFM_ETHER|IFM_40G_LR4,    \"40GbaseLR4\" },            \\\n{ IFM_ETHER|IFM_40G_LR4,    \"40GBASE-LR4\" },        \\\n{ IFM_ETHER|IFM_1000_KX,    \"1000base-KX\" },        \\\n{ IFM_ETHER|IFM_1000_KX,    \"1000BASE-KX\" },        \\\n{ IFM_ETHER|IFM_10G_KX4,    \"10GbaseKX4\" },            \\\n{ IFM_ETHER|IFM_10G_KX4,    \"10GBASE-KX4\" },        \\\n{ IFM_ETHER|IFM_10G_KR,        \"10GbaseKR\" },            \\\n{ IFM_ETHER|IFM_10G_KR,        \"10GBASE-KR\" },            \\\n{ IFM_ETHER|IFM_10G_CR1,    \"10GbaseCR1\" },            \\\n{ IFM_ETHER|IFM_10G_CR1,    \"10GBASE-CR1\" },        \\\n{ IFM_ETHER|IFM_10G_AOC,    \"10G-AOC\" },            \\\n{ IFM_ETHER|IFM_20G_KR2,    \"20GbaseKR2\" },            \\\n{ IFM_ETHER|IFM_20G_KR2,    \"20GBASE-KR2\" },        \\\n{ IFM_ETHER|IFM_2500_KX,    \"2500baseKX\" },            \\\n{ IFM_ETHER|IFM_2500_KX,    \"2500BASE-KX\" },        \\\n{ IFM_ETHER|IFM_2500_T,        \"2500baseT\" },            \\\n{ IFM_ETHER|IFM_2500_T,        \"2500BASE-T\" },            \\\n{ IFM_ETHER|IFM_5000_T,        \"5000baseT\" },            \\\n{ IFM_ETHER|IFM_5000_T,        \"5000BASE-T\" },            \\\n{ IFM_ETHER|IFM_1000_SGMII,    \"1000base-SGMII\" },        \\\n{ IFM_ETHER|IFM_1000_SGMII,    \"1000BASE-SGMII\" },        \\\n{ IFM_ETHER|IFM_10G_SFI,    \"10GbaseSFI\" },            \\\n{ IFM_ETHER|IFM_10G_SFI,    \"10GBASE-SFI\" },        \\\n{ IFM_ETHER|IFM_40G_XLPPI,    \"40GbaseXLPPI\" },        \\\n{ IFM_ETHER|IFM_40G_XLPPI,    \"40GBASE-XLPPI\" },        \\\n{ IFM_ETHER|IFM_1000_CX_SGMII,    \"1000baseCX-SGMII\" },        \\\n{ IFM_ETHER|IFM_1000_CX_SGMII,    \"1000BASE-CX-SGMII\" },        \\\n{ IFM_ETHER|IFM_40G_KR4,    \"40GbaseKR4\" },            \\\n{ IFM_ETHER|IFM_40G_KR4,    \"40GBASE-KR4\" },        \\\n{ IFM_ETHER|IFM_40G_AOC,    \"40G-AOC\" },            \\\n{ IFM_ETHER|IFM_10G_ER,        \"10GbaseER\" },            \\\n{ IFM_ETHER|IFM_10G_ER,        \"10GBASE-ER\" },            \\\n{ IFM_ETHER|IFM_100G_CR4,    \"100GbaseCR4\" },        \\\n{ IFM_ETHER|IFM_100G_CR4,    \"100GBASE-CR4\" },        \\\n{ IFM_ETHER|IFM_100G_SR4,    \"100GbaseSR4\" },        \\\n{ IFM_ETHER|IFM_100G_SR4,    \"100GBASE-SR4\" },        \\\n{ IFM_ETHER|IFM_100G_KR4,    \"100GbaseKR4\" },        \\\n{ IFM_ETHER|IFM_100G_KR4,    \"100GBASE-KR4\" },        \\\n{ IFM_ETHER|IFM_100G_LR4,    \"100GbaseLR4\" },        \\\n{ IFM_ETHER|IFM_100G_LR4,    \"100GBASE-LR4\" },        \\\n{ IFM_ETHER|IFM_100G_AOC,    \"100G-AOC\" },            \\\n{ IFM_ETHER|IFM_56G_R4,        \"56GbaseR4\" },            \\\n{ IFM_ETHER|IFM_56G_R4,        \"56GBASE-R4\" },            \\\n{ IFM_ETHER|IFM_25G_CR,        \"25GbaseCR\" },            \\\n{ IFM_ETHER|IFM_25G_CR,        \"25GBASE-CR\" },            \\\n{ IFM_ETHER|IFM_25G_KR,        \"25GbaseKR\" },            \\\n{ IFM_ETHER|IFM_25G_KR,        \"25GBASE-KR\" },            \\\n{ IFM_ETHER|IFM_25G_SR,        \"25GbaseSR\" },            \\\n{ IFM_ETHER|IFM_25G_SR,        \"25GBASE-SR\" },            \\\n{ IFM_ETHER|IFM_25G_LR,        \"25GbaseLR\" },            \\\n{ IFM_ETHER|IFM_25G_LR,        \"25GBASE-LR\" },            \\\n{ IFM_ETHER|IFM_25G_ER,        \"25GbaseER\" },            \\\n{ IFM_ETHER|IFM_25G_ER,        \"25GBASE-ER\" },            \\\n{ IFM_ETHER|IFM_25G_AOC,    \"25G-AOC\" },            \\\n{ IFM_ETHER|IFM_50G_CR2,    \"50GbaseCR2\" },            \\\n{ IFM_ETHER|IFM_50G_CR2,    \"50GBASE-CR2\" },        \\\n{ IFM_ETHER|IFM_50G_KR2,    \"50GbaseKR2\" },            \\\n{ IFM_ETHER|IFM_50G_KR2,    \"50GBASE-KR2\" },        \\\n\\\n{ IFM_FDDI|IFM_FDDI_SMF,    \"Single-mode\" },        \\\n{ IFM_FDDI|IFM_FDDI_SMF,    \"SMF\" },            \\\n{ IFM_FDDI|IFM_FDDI_MMF,    \"Multi-mode\" },            \\\n{ IFM_FDDI|IFM_FDDI_MMF,    \"MMF\" },            \\\n{ IFM_FDDI|IFM_FDDI_UTP,    \"UTP\" },            \\\n{ IFM_FDDI|IFM_FDDI_UTP,    \"CDDI\" },            \\\n\\\n{ IFM_IEEE80211|IFM_IEEE80211_FH1,    \"FH1\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_FH2,    \"FH2\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_DS2,    \"DS2\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_DS5,    \"DS5\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_DS11,    \"DS11\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_DS1,    \"DS1\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_DS22,    \"DS22\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_OFDM6,    \"OFDM6\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_OFDM9,    \"OFDM9\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_OFDM12,    \"OFDM12\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_OFDM18,    \"OFDM18\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_OFDM24,    \"OFDM24\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_OFDM36,    \"OFDM36\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_OFDM48,    \"OFDM48\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_OFDM54,    \"OFDM54\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_OFDM72,    \"OFDM72\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS0,    \"HT-MCS0\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS1,    \"HT-MCS1\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS2,    \"HT-MCS2\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS3,    \"HT-MCS3\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS4,    \"HT-MCS4\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS5,    \"HT-MCS5\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS6,    \"HT-MCS6\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS7,    \"HT-MCS7\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS8,    \"HT-MCS8\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS9,    \"HT-MCS9\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS10,    \"HT-MCS10\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS11,    \"HT-MCS11\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS12,    \"HT-MCS12\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS13,    \"HT-MCS13\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS14,    \"HT-MCS14\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS15,    \"HT-MCS15\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS16,    \"HT-MCS16\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS17,    \"HT-MCS17\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS18,    \"HT-MCS18\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS19,    \"HT-MCS19\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS20,    \"HT-MCS20\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS21,    \"HT-MCS21\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS22,    \"HT-MCS22\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS23,    \"HT-MCS23\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS24,    \"HT-MCS24\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS25,    \"HT-MCS25\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS26,    \"HT-MCS26\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS27,    \"HT-MCS27\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS28,    \"HT-MCS28\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS29,    \"HT-MCS29\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS30,    \"HT-MCS30\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS31,    \"HT-MCS31\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS32,    \"HT-MCS32\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS33,    \"HT-MCS33\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS34,    \"HT-MCS34\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS35,    \"HT-MCS35\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS36,    \"HT-MCS36\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS37,    \"HT-MCS37\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS38,    \"HT-MCS38\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS39,    \"HT-MCS39\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS40,    \"HT-MCS40\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS41,    \"HT-MCS41\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS42,    \"HT-MCS42\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS43,    \"HT-MCS43\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS44,    \"HT-MCS44\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS45,    \"HT-MCS45\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS46,    \"HT-MCS46\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS47,    \"HT-MCS47\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS48,    \"HT-MCS48\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS49,    \"HT-MCS49\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS50,    \"HT-MCS50\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS51,    \"HT-MCS51\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS52,    \"HT-MCS52\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS53,    \"HT-MCS53\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS54,    \"HT-MCS54\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS55,    \"HT-MCS55\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS56,    \"HT-MCS56\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS57,    \"HT-MCS57\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS58,    \"HT-MCS58\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS59,    \"HT-MCS59\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS60,    \"HT-MCS60\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS61,    \"HT-MCS61\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS62,    \"HT-MCS62\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS63,    \"HT-MCS63\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS64,    \"HT-MCS64\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS65,    \"HT-MCS65\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS66,    \"HT-MCS66\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS67,    \"HT-MCS67\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS68,    \"HT-MCS68\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS69,    \"HT-MCS69\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS70,    \"HT-MCS70\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS71,    \"HT-MCS71\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS72,    \"HT-MCS72\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS73,    \"HT-MCS73\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS74,    \"HT-MCS74\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS75,    \"HT-MCS75\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS76,    \"HT-MCS76\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_VHT_MCS0,    \"VHT-MCS0\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_VHT_MCS1,    \"VHT-MCS1\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_VHT_MCS2,    \"VHT-MCS2\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_VHT_MCS3,    \"VHT-MCS3\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_VHT_MCS4,    \"VHT-MCS4\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_VHT_MCS5,    \"VHT-MCS5\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_VHT_MCS6,    \"VHT-MCS6\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_VHT_MCS7,    \"VHT-MCS7\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_VHT_MCS8,    \"VHT-MCS8\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_VHT_MCS9,    \"VHT-MCS9\" },        \\\n\\\n{ IFM_TDM|IFM_TDM_T1,        \"t1\" },                \\\n{ IFM_TDM|IFM_TDM_T1_AMI,    \"t1-ami\" },            \\\n{ IFM_TDM|IFM_TDM_E1,        \"e1\" },                \\\n{ IFM_TDM|IFM_TDM_E1_G704,    \"e1-g.704\" },            \\\n{ IFM_TDM|IFM_TDM_E1_AMI,    \"e1-ami\" },            \\\n{ IFM_TDM|IFM_TDM_E1_AMI_G704,    \"e1-ami-g.704\" },        \\\n{ IFM_TDM|IFM_TDM_T3,        \"t3\" },                \\\n{ IFM_TDM|IFM_TDM_T3_M13,    \"t3-m13\" },            \\\n{ IFM_TDM|IFM_TDM_E3,        \"e3\" },                \\\n{ IFM_TDM|IFM_TDM_E3_G751,    \"e3-g.751\" },            \\\n{ IFM_TDM|IFM_TDM_E3_G832,    \"e3-g.832\" },            \\\n{ IFM_TDM|IFM_TDM_E1_G704_CRC4,    \"e1-g.704-crc4\" },        \\\n\\\n{ 0, NULL },                            \\\n}\n\n#define IFM_MODE_DESCRIPTIONS {                        \\\n{ IFM_AUTO,                \"autoselect\" },        \\\n{ IFM_AUTO,                \"auto\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_11A,    \"11a\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_11B,    \"11b\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_11G,    \"11g\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_FH,    \"fh\" },            \\\n{ IFM_IEEE80211|IFM_IEEE80211_11N,    \"11n\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_11AC,    \"11ac\" },        \\\n{ IFM_TDM|IFM_TDM_MASTER,        \"master\" },        \\\n{ 0, NULL },                            \\\n}\n\n#define    IFM_OPTION_DESCRIPTIONS {                    \\\n{ IFM_FDX,            \"full-duplex\" },        \\\n{ IFM_FDX,            \"fdx\" },            \\\n{ IFM_HDX,            \"half-duplex\" },        \\\n{ IFM_HDX,            \"hdx\" },            \\\n{ IFM_FLAG0,            \"flag0\" },            \\\n{ IFM_FLAG1,            \"flag1\" },            \\\n{ IFM_FLAG2,            \"flag2\" },            \\\n{ IFM_LOOP,            \"loopback\" },            \\\n{ IFM_LOOP,            \"hw-loopback\"},            \\\n{ IFM_LOOP,            \"loop\" },            \\\n\\\n{ IFM_ETHER|IFM_ETH_MASTER,    \"master\" },            \\\n{ IFM_ETHER|IFM_ETH_RXPAUSE,    \"rxpause\" },            \\\n{ IFM_ETHER|IFM_ETH_TXPAUSE,    \"txpause\" },            \\\n\\\n{ IFM_FDDI|IFM_FDDI_DA,        \"dual-attach\" },        \\\n{ IFM_FDDI|IFM_FDDI_DA,        \"das\" },            \\\n\\\n{ IFM_IEEE80211|IFM_IEEE80211_ADHOC,    \"adhoc\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HOSTAP,    \"hostap\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_IBSS,    \"ibss\" },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_IBSSMASTER, \"ibss-master\" },    \\\n{ IFM_IEEE80211|IFM_IEEE80211_MONITOR,    \"monitor\" },        \\\n\\\n{ IFM_TDM|IFM_TDM_HDLC_CRC16,    \"hdlc-crc16\" },            \\\n{ IFM_TDM|IFM_TDM_PPP,        \"ppp\" },            \\\n{ IFM_TDM|IFM_TDM_FR_ANSI,    \"framerelay-ansi\" },        \\\n{ IFM_TDM|IFM_TDM_FR_CISCO,    \"framerelay-cisco\" },        \\\n{ IFM_TDM|IFM_TDM_FR_ANSI,    \"framerelay-itu\" },        \\\n\\\n{ 0, NULL },                            \\\n}\n\n/*\n * Baudrate descriptions for the various media types.\n */\nstruct ifmedia_baudrate {\n    uint64_t    ifmb_word;        /* media word */\n    uint64_t    ifmb_baudrate;        /* corresponding baudrate */\n};\n\n#define    IFM_BAUDRATE_DESCRIPTIONS {                    \\\n{ IFM_ETHER|IFM_10_T,        IF_Mbps(10) },            \\\n{ IFM_ETHER|IFM_10_2,        IF_Mbps(10) },            \\\n{ IFM_ETHER|IFM_10_5,        IF_Mbps(10) },            \\\n{ IFM_ETHER|IFM_100_TX,        IF_Mbps(100) },            \\\n{ IFM_ETHER|IFM_100_FX,        IF_Mbps(100) },            \\\n{ IFM_ETHER|IFM_100_T4,        IF_Mbps(100) },            \\\n{ IFM_ETHER|IFM_100_VG,        IF_Mbps(100) },            \\\n{ IFM_ETHER|IFM_100_T2,        IF_Mbps(100) },            \\\n{ IFM_ETHER|IFM_1000_SX,    IF_Mbps(1000) },        \\\n{ IFM_ETHER|IFM_10_STP,        IF_Mbps(10) },            \\\n{ IFM_ETHER|IFM_10_FL,        IF_Mbps(10) },            \\\n{ IFM_ETHER|IFM_1000_LX,    IF_Mbps(1000) },        \\\n{ IFM_ETHER|IFM_1000_CX,    IF_Mbps(1000) },        \\\n{ IFM_ETHER|IFM_1000_T,        IF_Mbps(1000) },        \\\n{ IFM_ETHER|IFM_HPNA_1,        IF_Mbps(1) },            \\\n{ IFM_ETHER|IFM_10G_LR,        IF_Gbps(10) },            \\\n{ IFM_ETHER|IFM_10G_SR,        IF_Gbps(10) },            \\\n{ IFM_ETHER|IFM_10G_CX4,    IF_Gbps(10) },            \\\n{ IFM_ETHER|IFM_2500_SX,    IF_Mbps(2500) },        \\\n{ IFM_ETHER|IFM_10G_T,        IF_Gbps(10) },            \\\n{ IFM_ETHER|IFM_10G_SFP_CU,    IF_Gbps(10) },            \\\n\\\n{ IFM_FDDI|IFM_FDDI_SMF,    IF_Mbps(100) },            \\\n{ IFM_FDDI|IFM_FDDI_MMF,    IF_Mbps(100) },            \\\n{ IFM_FDDI|IFM_FDDI_UTP,    IF_Mbps(100) },            \\\n\\\n{ IFM_IEEE80211|IFM_IEEE80211_FH1, IF_Mbps(1) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_FH2, IF_Mbps(2) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_DS1, IF_Mbps(1) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_DS2, IF_Mbps(2) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_DS5, IF_Mbps(5) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_DS11, IF_Mbps(11) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_DS22, IF_Mbps(22) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_OFDM6, IF_Mbps(6) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_OFDM9, IF_Mbps(9) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_OFDM12, IF_Mbps(12) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_OFDM18, IF_Mbps(18) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_OFDM24, IF_Mbps(24) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_OFDM36, IF_Mbps(36) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_OFDM48, IF_Mbps(48) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_OFDM54, IF_Mbps(54) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_OFDM72, IF_Mbps(72) },        \\\n/* These HT rates correspond to 20 MHz channel with no SGI. */    \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS0, IF_Kbps(6500) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS1, IF_Mbps(13) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS2, IF_Kbps(19500) },    \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS3, IF_Mbps(26) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS4, IF_Mbps(39) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS5, IF_Mbps(52) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS6, IF_Kbps(58500) },    \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS7, IF_Mbps(65) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS8, IF_Mbps(13) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS9, IF_Mbps(26) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS10, IF_Mbps(39) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS11, IF_Mbps(52) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS12, IF_Mbps(78) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS13, IF_Mbps(104) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS14, IF_Mbps(117) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS15, IF_Mbps(130) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS16, IF_Kbps(19500) },    \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS17, IF_Mbps(39) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS18, IF_Kbps(58500) },    \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS19, IF_Mbps(78) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS20, IF_Mbps(117) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS21, IF_Mbps(156) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS22, IF_Kbps(175500) },    \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS23, IF_Mbps(195) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS24, IF_Mbps(26) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS25, IF_Mbps(52) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS26, IF_Mbps(78) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS27, IF_Mbps(104) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS28, IF_Mbps(156) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS29, IF_Mbps(208) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS30, IF_Mbps(234) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS31, IF_Mbps(260) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS32, IF_Mbps(0) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS33, IF_Mbps(39) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS34, IF_Mbps(52) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS35, IF_Mbps(65) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS36, IF_Kbps(58500) },    \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS37, IF_Mbps(78) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS38, IF_Kbps(97500) },    \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS39, IF_Mbps(52) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS40, IF_Mbps(65) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS41, IF_Mbps(65) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS42, IF_Mbps(78) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS43, IF_Mbps(91) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS44, IF_Mbps(91) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS45, IF_Mbps(104) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS46, IF_Mbps(78) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS47, IF_Kbps(97500) },    \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS48, IF_Kbps(97500) },    \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS49, IF_Mbps(117) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS50, IF_Kbps(136500) },    \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS51, IF_Kbps(136500) },    \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS52, IF_Mbps(156) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS53, IF_Mbps(65) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS54, IF_Mbps(78) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS55, IF_Mbps(91) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS56, IF_Mbps(78) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS57, IF_Mbps(91) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS58, IF_Mbps(104) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS59, IF_Mbps(117) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS60, IF_Mbps(104) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS61, IF_Mbps(117) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS62, IF_Mbps(130) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS63, IF_Mbps(130) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS64, IF_Mbps(143) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS65, IF_Kbps(97500) },    \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS66, IF_Mbps(117) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS67, IF_Kbps(136500) },    \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS68, IF_Mbps(117) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS69, IF_Kbps(136500) },    \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS70, IF_Mbps(156) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS71, IF_Kbps(175500) },    \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS72, IF_Mbps(156) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS73, IF_Kbps(175500) },    \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS74, IF_Mbps(195) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS75, IF_Mbps(195) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_HT_MCS76, IF_Kbps(214500) },    \\\n/* These VHT rates correspond to 1 SS, no SGI, 40 MHz channel.*/\\\n{ IFM_IEEE80211|IFM_IEEE80211_VHT_MCS0, IF_Kbps(13500) },    \\\n{ IFM_IEEE80211|IFM_IEEE80211_VHT_MCS1, IF_Mbps(27) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_VHT_MCS2, IF_Kbps(40500) },    \\\n{ IFM_IEEE80211|IFM_IEEE80211_VHT_MCS3, IF_Mbps(54) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_VHT_MCS4, IF_Mbps(81) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_VHT_MCS5, IF_Mbps(108) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_VHT_MCS6, IF_Kbps(121500) },    \\\n{ IFM_IEEE80211|IFM_IEEE80211_VHT_MCS7, IF_Mbps(135) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_VHT_MCS8, IF_Mbps(162) },        \\\n{ IFM_IEEE80211|IFM_IEEE80211_VHT_MCS9, IF_Mbps(180) },        \\\n\\\n{ IFM_TDM|IFM_TDM_T1,        IF_Kbps(1536) },        \\\n{ IFM_TDM|IFM_TDM_T1_AMI,    IF_Kbps(1536) },        \\\n{ IFM_TDM|IFM_TDM_E1,        IF_Kbps(2048) },        \\\n{ IFM_TDM|IFM_TDM_E1_G704,    IF_Kbps(2048) },        \\\n{ IFM_TDM|IFM_TDM_E1_AMI,    IF_Kbps(2048) },        \\\n{ IFM_TDM|IFM_TDM_E1_AMI_G704,    IF_Kbps(2048) },        \\\n{ IFM_TDM|IFM_TDM_T3,        IF_Kbps(44736) },        \\\n{ IFM_TDM|IFM_TDM_T3_M13,    IF_Kbps(44736) },        \\\n{ IFM_TDM|IFM_TDM_E3,        IF_Kbps(34368) },        \\\n{ IFM_TDM|IFM_TDM_E3_G751,    IF_Kbps(34368) },        \\\n{ IFM_TDM|IFM_TDM_E3_G832,    IF_Kbps(34368) },        \\\n{ IFM_TDM|IFM_TDM_E1_G704_CRC4,    IF_Kbps(2048) },        \\\n\\\n{ 0, 0 },                            \\\n}\n\n/*\n * Status bit descriptions for the various media types.\n */\nstruct ifmedia_status_description {\n    uint64_t    ifms_type;\n    uint64_t    ifms_valid;\n    uint64_t    ifms_bit;\n    const char *ifms_string[2];\n};\n\n#define    IFM_STATUS_DESC(ifms, bit)                    \\\n(ifms)->ifms_string[((ifms)->ifms_bit & (bit)) ? 1 : 0]\n\n#define    IFM_STATUS_DESCRIPTIONS {                    \\\n{ IFM_ETHER,        IFM_AVALID,    IFM_ACTIVE,        \\\n{ \"no carrier\", \"active\" } },                \\\n{ IFM_FDDI,        IFM_AVALID,    IFM_ACTIVE,        \\\n{ \"no ring\", \"inserted\" } },                \\\n{ IFM_IEEE80211,    IFM_AVALID,    IFM_ACTIVE,        \\\n{ \"no network\", \"active\" } },                \\\n{ IFM_TDM,        IFM_AVALID,    IFM_ACTIVE,        \\\n{ \"no carrier\", \"active\" } },                \\\n{ IFM_CARP,        IFM_AVALID,    IFM_ACTIVE,        \\\n{ \"backup\", \"master\" } },                    \\\n{ 0,            0,        0,            \\\n{ NULL, NULL } }                        \\\n}\n\n/* Delete all media for a given media instance */\nstatic inline void ifmedia_delete_instance(struct ifmedia *ifm, uint64_t inst)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct ifmedia_entry *ife, *nife;\n    \n    TAILQ_FOREACH_SAFE(ife, &ifm->ifm_list, ifm_list, nife) {\n        if (inst == IFM_INST_ANY ||\n            inst == IFM_INST(ife->ifm_media)) {\n            TAILQ_REMOVE(&ifm->ifm_list, ife, ifm_list);\n            IOFree(ife, sizeof *ife);\n        }\n    }\n}\n\n/*\n * Find media entry matching a given ifm word.\n */\nstatic inline struct ifmedia_entry *\nifmedia_match(struct ifmedia *ifm, uint64_t target, uint64_t mask)\n{\n    struct ifmedia_entry *match, *next;\n    \n    match = NULL;\n    mask = ~mask;\n    \n    TAILQ_FOREACH(next, &ifm->ifm_list, ifm_list) {\n        if ((next->ifm_media & mask) == (target & mask)) {\n            if (match) {\n#if defined(IFMEDIA_DEBUG) || defined(DIAGNOSTIC)\n                XYLog(\"ifmedia_match: multiple match for \"\n                       \"0x%llx/0x%llx, selected instance %lld\\n\",\n                       target, mask, IFM_INST(match->ifm_media));\n#endif\n                break;\n            }\n            match = next;\n        }\n    }\n    \n    return (match);\n}\n\n/* Set default media type on initialization. */\nstatic inline void ifmedia_set(struct ifmedia *ifm, uint64_t target)\n{\n    struct ifmedia_entry *match;\n    \n    match = ifmedia_match(ifm, target, ifm->ifm_mask);\n    \n    /*\n     * If we didn't find the requested media, then we try to fall\n     * back to target-type (IFM_ETHER, e.g.) | IFM_NONE.  If that's\n     * not on the list, then we add it and set the media to it.\n     *\n     * Since ifmedia_set is almost always called with IFM_AUTO or\n     * with a known-good media, this really should only occur if we:\n     *\n     * a) didn't find any PHYs, or\n     * b) didn't find an autoselect option on the PHY when the\n     *    parent ethernet driver expected to.\n     *\n     * In either case, it makes sense to select no media.\n     */\n    if (match == NULL) {\n        XYLog(\"ifmedia_set: no match for 0x%llx/0x%llx\\n\",\n               target, ~ifm->ifm_mask);\n        target = (target & IFM_NMASK) | IFM_NONE;\n        match = ifmedia_match(ifm, target, ifm->ifm_mask);\n        if (match == NULL) {\n            ifmedia_add(ifm, target, 0, NULL);\n            match = ifmedia_match(ifm, target, ifm->ifm_mask);\n            if (match == NULL)\n                panic(\"ifmedia_set failed\");\n        }\n    }\n    ifm->ifm_cur = match;\n}\n\n#endif    /* _NET_IF_MEDIA_H_ */\n"
  },
  {
    "path": "itl80211/openbsd/sys/_ifq.cpp",
    "content": "//\n//  _ifq.cpp\n//  itlwm\n//\n//  Created by zxystd on 2022/8/13.\n//  Copyright © 2022 钟先耀. All rights reserved.\n//\n\n#include <sys/_ifq.h>\n\nvoid ifq_init(struct _ifqueue *ifq, struct _ifnet *ifp, unsigned int maxLen)\n{\n    if (!ifq->queue)\n        ifq->queue = IOPacketQueue::withCapacity(maxLen);\n    else\n        ifq->queue->setCapacity(maxLen);\n    ifq->ifq_oactive = 0;\n}\n\nvoid ifq_destroy(struct _ifqueue *ifq)\n{\n    if (ifq->queue) {\n        ifq->queue->release();\n        ifq->queue = nullptr;\n    }\n}\n\nvoid ifq_flush(struct _ifqueue *ifq)\n{\n    if (ifq->queue)\n        ifq->queue->lockFlush();\n}\n\nbool ifq_empty(struct _ifqueue *ifq)\n{\n    return ifq->queue->getSize() == 0;\n}\n\nuint32_t ifq_len(struct _ifqueue *ifq)\n{\n    return ifq->queue->getSize();\n}\n\nvoid ifq_set_maxlen(struct _ifqueue *ifq, uint32_t maxLen)\n{\n    ifq->queue->setCapacity(maxLen);\n}\n\nvoid ifq_set_oactive(struct _ifqueue *ifq)\n{\n    ifq->ifq_oactive = 1;\n}\n\nunsigned int ifq_is_oactive(struct _ifqueue *ifq)\n{\n    return ifq->ifq_oactive;\n}\n\nvoid ifq_clr_oactive(struct _ifqueue *ifq)\n{\n    ifq->ifq_oactive = 0;\n}\n\nmbuf_t ifq_dequeue(struct _ifqueue *ifq)\n{\n    return ifq->queue->lockDequeue();\n}\n\nint ifq_enqueue(struct _ifqueue *ifq, mbuf_t m)\n{\n    ifq->queue->lockEnqueueWithDrop(m);\n    return 0;\n}\n"
  },
  {
    "path": "itl80211/openbsd/sys/_ifq.h",
    "content": "//\n//  _ifq.h\n//  itlwm\n//\n//  Created by qcwap on 2020/3/1.\n//  Copyright © 2020 钟先耀. All rights reserved.\n//\n/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n\n#ifndef _ifq_h\n#define _ifq_h\n#include <net/if_var.h>\n#include <IOKit/network/IOPacketQueue.h>\n\nstruct _ifqueue {\n    unsigned int ifq_oactive;\n    IOPacketQueue *queue;\n};\n\nvoid ifq_init(struct _ifqueue *ifq, struct _ifnet *ifp, unsigned int maxLen);\n\nvoid ifq_destroy(struct _ifqueue *ifq);\n\nvoid ifq_flush(struct _ifqueue *ifq);\n\nbool ifq_empty(struct _ifqueue *ifq);\n\nuint32_t ifq_len(struct _ifqueue *ifq);\n\nvoid ifq_set_maxlen(struct _ifqueue *ifq, uint32_t maxLen);\n\nvoid ifq_set_oactive(struct _ifqueue *ifq);\n\nunsigned int ifq_is_oactive(struct _ifqueue *ifq);\n\nvoid ifq_clr_oactive(struct _ifqueue *ifq);\n\nmbuf_t ifq_dequeue(struct _ifqueue *ifq);\n\nint ifq_enqueue(struct _ifqueue *ifq, mbuf_t m);\n\n#endif /* _ifq_h */\n"
  },
  {
    "path": "itl80211/openbsd/sys/_malloc.h",
    "content": "//\n//  _malloc.h\n//  itlwm\n//\n//  Created by qcwap on 2020/7/24.\n//  Copyright © 2020 钟先耀. All rights reserved.\n//\n/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n\n#ifndef _malloc_h\n#define _malloc_h\n\n#include <IOKit/IOLib.h>\n\nstatic inline void*\nmalloc(vm_size_t len, int type, int how)\n{\n    void* addr = IOMalloc(len + sizeof(vm_size_t));\n    if (addr == NULL) {\n        return NULL;\n    }\n    *((vm_size_t*) addr) = len;\n    void *buf = (void*)((uint8_t*)addr + sizeof(vm_size_t));\n    bzero(buf, len);\n    return buf;\n}\n\nstatic inline void\nfree(void* addr)\n{\n    if (addr == NULL) {\n        return;\n    }\n    void* actual_addr = (void*)((uint8_t*)addr - sizeof(vm_size_t));\n    vm_size_t len = *((vm_size_t*) actual_addr);\n    IOFree(actual_addr, len + sizeof(vm_size_t));\n}\n\n#endif /* _malloc_h */\n"
  },
  {
    "path": "itl80211/openbsd/sys/_mbuf.cpp",
    "content": "//\n//  _mbuf.cpp\n//  itlwm\n//\n//  Created by qcwap on 2020/6/14.\n//  Copyright © 2020 钟先耀. All rights reserved.\n//\n/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n\n#include <sys/_mbuf.h>\nextern \"C\" {\n#include <net/bpf.h>\n}\n#include <IOKit/IOCommandGate.h>\n\nextern IOCommandGate *_fCommandGate;\n\nstruct network_header {\n    char pad[0x48];\n};\n\nstatic IOReturn _if_input(OSObject *target, void *arg0, void *arg1, void *arg2, void *arg3)\n{\n    mbuf_t m;\n    bool isEmpty = true;\n    struct _ifnet *ifq = (struct _ifnet *)arg0;\n    struct mbuf_list *ml = (struct mbuf_list *)arg1;\n    \n    MBUF_LIST_FOREACH(ml, m) {\n        if (ifq->iface == NULL) {\n            panic(\"%s ifq->iface == NULL!!!\\n\", __FUNCTION__);\n            break;\n        }\n        if (m == NULL) {\n            XYLog(\"%s m == NULL!!!\\n\", __FUNCTION__);\n            continue;\n        }\n        //        XYLog(\"%s %d 啊啊啊啊 ifq->iface->inputPacket(m) hdr_len=%d len=%d\\n\", __FUNCTION__, __LINE__, mbuf_pkthdr_len(m), mbuf_len(m));\n        isEmpty = false;\n        ifq->iface->inputPacket(m, 0, IONetworkInterface::kInputOptionQueuePacket);\n        if (ifq->netStat != NULL) {\n            ifq->netStat->inputPackets++;\n        }\n    }\n    if (!isEmpty) {\n        ifq->iface->flushInputQueue();\n    }\n    return kIOReturnSuccess;\n}\n\nint if_input(struct _ifnet *ifq, struct mbuf_list *ml)\n{\n    return _fCommandGate->runAction((IOCommandGate::Action)_if_input, ifq, ml);\n}\n\n"
  },
  {
    "path": "itl80211/openbsd/sys/_mbuf.h",
    "content": "//\n//  mbuf.h\n//  AppleIntelWifiAdapter\n//\n//  Created by 钟先耀 on 2020/1/22.\n//  Copyright © 2020 钟先耀. All rights reserved.\n//\n\n/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n/*    $OpenBSD: mbuf.h,v 1.245 2019/07/16 17:39:02 bluhm Exp $    */\n/*    $NetBSD: mbuf.h,v 1.19 1996/02/09 18:25:14 christos Exp $    */\n\n/*\n * Copyright (c) 1982, 1986, 1988, 1993\n *    The Regents of the University of California.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the University nor the names of its contributors\n *    may be used to endorse or promote products derived from this software\n *    without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n *    @(#)mbuf.h    8.5 (Berkeley) 2/19/95\n */\n\n#ifndef _mbuf_h\n#define _mbuf_h\n\n#include <linux/types.h>\n#include <sys/_if_ether.h>\n#include <sys/_ifq.h>\n#include <sys/mbuf.h>\n#include <sys/kpi_mbuf.h>\n#include <sys/errno.h>\n#include <IOKit/network/IOPacketQueue.h>\n#include <IOKit/IOLib.h>\n#include <IOKit/IOLocks.h>\n\n#define PACKET_TAG_DLT            0x0100 /* data link layer type */\n#define IPL_NET        6\n\n#define    mtod(x,t)    ((t) mbuf_data(x))\n#define    ml_len(_ml)        ((_ml)->ml_len)\n#define    ml_empty(_ml)        ((_ml)->ml_len == 0)\n\n#define MBUF_LIST_FIRST(_ml)    ((_ml)->ml_head)\n#define MBUF_LIST_NEXT(_m)    (mbuf_nextpkt((_m)))\n\n#define MBUF_LIST_FOREACH(_ml, _m)                    \\\n    for ((_m) = MBUF_LIST_FIRST(_ml);                \\\n        (_m) != NULL;                        \\\n        (_m) = MBUF_LIST_NEXT(_m))\n\n#define    mq_len(_mq)        ml_len(&(_mq)->mq_list)\n#define    mq_empty(_mq)        ml_empty(&(_mq)->mq_list)\n#define    mq_full(_mq)        (mq_len((_mq)) >= (_mq)->mq_maxlen)\n#define    mq_drops(_mq)        ((_mq)->mq_drops)\n#define    mq_set_maxlen(_mq, _l)    ((_mq)->mq_maxlen = (_l))\n\n//uipc_mbuf.c\n\nstruct mbuf_list {\n    mbuf_t ml_head;\n    mbuf_t ml_tail;\n    u_int  ml_len;\n};\n\nstruct mbuf_queue {\n    IORecursiveLock*        mq_mtx;\n    struct mbuf_list    mq_list;\n    u_int            mq_maxlen;\n    u_int            mq_drops;\n};\n\n/*\n * mbuf lists\n */\n\n#define MBUF_LIST_INITIALIZER() { NULL, NULL, 0 }\n\n#define MBUF_QUEUE_INITIALIZER(_maxlen, _ipl) \\\n{ MUTEX_INITIALIZER(_ipl), MBUF_LIST_INITIALIZER(), (_maxlen), 0 }\n\nstatic inline void\nml_init(struct mbuf_list *ml)\n{\n    ml->ml_head = ml->ml_tail = NULL;\n    ml->ml_len = 0;\n}\n\nstatic inline void\nml_enqueue(struct mbuf_list *ml, mbuf_t m)\n{\n    if (ml->ml_tail == NULL)\n        ml->ml_head = ml->ml_tail = m;\n    else {\n        mbuf_setnextpkt(ml->ml_tail, m);\n        ml->ml_tail = m;\n    }\n\n    mbuf_setnextpkt(m, NULL);\n    ml->ml_len++;\n}\n\nstatic inline void\nml_enlist(struct mbuf_list *mla, struct mbuf_list *mlb)\n{\n    if (!ml_empty(mlb)) {\n        if (ml_empty(mla))\n            mla->ml_head = mlb->ml_head;\n        else\n            mbuf_setnextpkt(mla->ml_tail, mlb->ml_head);\n        mla->ml_tail = mlb->ml_tail;\n        mla->ml_len += mlb->ml_len;\n\n        ml_init(mlb);\n    }\n}\n\nstatic inline mbuf_t\nml_dequeue(struct mbuf_list *ml)\n{\n    mbuf_t m;\n\n    m = ml->ml_head;\n    if (m != NULL) {\n        ml->ml_head = mbuf_nextpkt(m);\n        if (ml->ml_head == NULL)\n            ml->ml_tail = NULL;\n\n        mbuf_setnextpkt(m, NULL);\n        ml->ml_len--;\n    }\n\n    return (m);\n}\n\nstatic inline mbuf_t\nml_dechain(struct mbuf_list *ml)\n{\n    mbuf_t m0;\n\n    m0 = ml->ml_head;\n\n    ml_init(ml);\n\n    return (m0);\n}\n\nstatic inline unsigned int\nml_purge(struct mbuf_list *ml)\n{\n    mbuf_t m, n;\n    unsigned int len;\n\n    for (m = ml->ml_head; m != NULL; m = n) {\n        n = mbuf_nextpkt(m);\n        mbuf_freem(m);\n    }\n\n    len = ml->ml_len;\n    ml_init(ml);\n\n    return (len);\n}\n\n/*\n * mbuf queues\n */\n\nstatic inline void\nmq_init(struct mbuf_queue *mq, u_int maxlen, int ipl)\n{\n    mq->mq_mtx = IORecursiveLockAlloc();\n    ml_init(&mq->mq_list);\n    mq->mq_maxlen = maxlen;\n}\n\nstatic inline int\nmq_enqueue(struct mbuf_queue *mq, mbuf_t m)\n{\n    int dropped = 0;\n\n    IORecursiveLockLock(mq->mq_mtx);\n    \n    if (mq_len(mq) < mq->mq_maxlen)\n        ml_enqueue(&mq->mq_list, m);\n    else {\n        mq->mq_drops++;\n        dropped = 1;\n    }\n\n    if (dropped) {\n        mbuf_freem(m);\n    }\n    \n    IORecursiveLockUnlock(mq->mq_mtx);\n\n    return (dropped);\n}\n\nstatic inline mbuf_t\nmq_dequeue(struct mbuf_queue *mq)\n{\n    mbuf_t m;\n\n    IORecursiveLockLock(mq->mq_mtx);\n    m = ml_dequeue(&mq->mq_list);\n    IORecursiveLockUnlock(mq->mq_mtx);\n\n    return (m);\n}\n\nstatic inline int\nmq_enlist(struct mbuf_queue *mq, struct mbuf_list *ml)\n{\n    mbuf_t m;\n    int dropped = 0;\n\n    IORecursiveLockLock(mq->mq_mtx);\n    if (mq_len(mq) < mq->mq_maxlen)\n        ml_enlist(&mq->mq_list, ml);\n    else {\n        dropped = ml_len(ml);\n        mq->mq_drops += dropped;\n    }\n    IORecursiveLockUnlock(mq->mq_mtx);\n\n    if (dropped) {\n        while ((m = ml_dequeue(ml)) != NULL) {\n            mbuf_freem(m);\n        }\n    }\n\n    return (dropped);\n}\n\nstatic inline void\nmq_delist(struct mbuf_queue *mq, struct mbuf_list *ml)\n{\n    IORecursiveLockLock(mq->mq_mtx);\n    *ml = mq->mq_list;\n    ml_init(&mq->mq_list);\n    IORecursiveLockUnlock(mq->mq_mtx);\n}\n\nstatic inline mbuf_t\nmq_dechain(struct mbuf_queue *mq)\n{\n    mbuf_t m0;\n\n    IORecursiveLockLock(mq->mq_mtx);\n    m0 = ml_dechain(&mq->mq_list);\n    IORecursiveLockUnlock(mq->mq_mtx);\n\n    return (m0);\n}\n\nstatic inline unsigned int\nmq_purge(struct mbuf_queue *mq)\n{\n    struct mbuf_list ml;\n    \n    if (!mq->mq_mtx) {\n        return 0;\n    }\n    mq_delist(mq, &ml);\n\n    return (ml_purge(&ml));\n}\n\n/*\n * Concatenate mbuf chain n to m.\n * n might be copied into m (when n->m_len is small), therefore data portion of\n * n could be copied into an mbuf of different mbuf type.\n * Therefore both chains should be of the same type (e.g. MT_DATA).\n * Any m_pkthdr is not updated.\n */\nstatic inline void\nm_cat(mbuf_t m, mbuf_t n)\n{\n    while (mbuf_next(m))\n        m = mbuf_next(m);\n    while (n) {\n        if (mbuf_len(n) > mbuf_trailingspace(m)) {\n            /* just join the two chains */\n            mbuf_setnext(m, n);\n            return;\n        }\n        /* splat the data from one into the other */\n        memcpy(mtod(m, caddr_t) + mbuf_len(m), mtod(n, caddr_t),\n            mbuf_len(n));\n        mbuf_setlen(m, mbuf_len(m) + mbuf_len(n));\n        n = mbuf_free(n);\n    }\n}\n\n#define M_EXTWR        0x0008    /* external storage is writable */\n#define    MAXMCLBYTES    (64 * 1024)        /* largest cluster from the stack */\n\n/*\n * mbuf chain defragmenter. This function uses some evil tricks to defragment\n * an mbuf chain into a single buffer without changing the mbuf pointer.\n * This needs to know a lot of the mbuf internals to make this work.\n */\nstatic inline int\nm_defrag(mbuf_t m, int how)\n{\n    mbuf_t m0;\n\n    if (mbuf_next(m) == NULL)\n        return (0);\n\n//    KASSERT(m->m_flags & M_PKTHDR);\n    mbuf_gethdr(how, mbuf_type(m), &m0);\n    if (m0 == NULL)\n        return (ENOBUFS);\n    if (mbuf_pkthdr_len(m) > mbuf_get_mhlen()) {\n        mbuf_getcluster(how, mbuf_type(m), mbuf_pkthdr_len(m), &m0);\n//        if (!(m0->m_flags & M_EXT)) {\n//            m_free(m0);\n//            return (ENOBUFS);\n//        }\n    }\n    mbuf_copydata(m, 0, mbuf_pkthdr_len(m), mtod(m0, void*));\n    mbuf_pkthdr_setlen(m0, mbuf_pkthdr_len(m));\n    mbuf_setlen(m0, mbuf_pkthdr_len(m));\n\n    /* free chain behind and possible ext buf on the first mbuf */\n    mbuf_freem(mbuf_next(m));\n    mbuf_setnext(m, NULL);\n//    if (m->m_flags & M_EXT)\n//        m_extfree(m);\n\n    /*\n     * Bounce copy mbuf over to the original mbuf and set everything up.\n     * This needs to reset or clear all pointers that may go into the\n     * original mbuf chain.\n     */\n    if (mbuf_flags(m0) & MBUF_EXT) {\n//        memcpy(&m->m_ext, &m0->m_ext, sizeof(struct mbuf_ext));\n//        MCLINITREFERENCE(m);\n//        m->m_flags |= m0->m_flags & (M_EXT|M_EXTWR);\n//        m->m_data = m->m_ext.ext_buf;\n    } else {\n        mbuf_setdata(m, mbuf_pkthdr_header(m), mbuf_pkthdr_len(m));\n        memcpy(mbuf_data(m), mbuf_data(m0), mbuf_len(m0));\n    }\n    mbuf_pkthdr_setlen(m, mbuf_len(m0));\n    mbuf_setlen(m, mbuf_len(m0));\n\n    mbuf_setflags(m0, mbuf_flags(m0) & ~(MBUF_EXT | M_EXTWR));    /* cluster is gone */\n    mbuf_free(m0);\n\n    return (0);\n}\n\n/*\n * Duplicate mbuf pkthdr from from to to.\n * from must have M_PKTHDR set, and to must be empty.\n */\nstatic inline int\nm_dup_pkthdr(mbuf_t to, mbuf_t from, int wait)\n{\n    return mbuf_copy_pkthdr(to, from);\n}\n\nstatic inline mbuf_t\nm_dup_pkt(mbuf_t m0, unsigned int adj, int wait)\n{\n    mbuf_t m;\n    mbuf_dup(m0, wait, &m);\n    return m;\n//    mbuf_t m;\n//    int len;\n//\n//    len = mbuf_pkthdr_len(m0) + adj;\n//\n//    IOLog(\"itlwm: m_dup_pkt start, len=%lu\\n\", len);\n//\n//    if (len > MAXMCLBYTES) /* XXX */\n//        return (NULL);\n//\n//    mbuf_get((mbuf_how_t)wait, mbuf_type(m0), &m);\n//    if (m == NULL)\n//        return (NULL);\n//\n//    if (m_dup_pkthdr(m, m0, wait) != 0)\n//        goto fail;\n//\n//    if (len > mbuf_get_mhlen()) {\n////        MCLGETI(m, wait, NULL, len);\n//        mbuf_mclget(wait, MBUF_TYPE_DATA, &m);\n//        if (!ISSET(mbuf_flags(m), MBUF_EXT))\n//            goto fail;\n//    }\n//\n//    mbuf_setlen(m, len);\n//    mbuf_pkthdr_setlen(m, len);\n////    m->m_len = m->m_pkthdr.len = len;\n//    mbuf_adj(m, adj);\n//    mbuf_copydata(m0, 0, mbuf_pkthdr_len(m0), mtod(m, caddr_t));\n\n    return (m);\n\nfail:\n    IOLog(\"itlwm: m_dup_pkt fail!!!!\\n\");\n    mbuf_freem(m);\n    return (NULL);\n}\n\nint if_input(struct _ifnet *ifq, struct mbuf_list *ml);\n\nstatic inline int if_enqueue(struct _ifnet *ifq, mbuf_t m)\n{\n    if (ifq_enqueue(&ifq->if_snd, m)) {\n        XYLog(\"%s if_enqueue fail!!\\n\", __FUNCTION__);\n        return -ENOSPC;\n    }\n    return 0;\n}\n\n#endif /* _mbuf_h */\n"
  },
  {
    "path": "itl80211/openbsd/sys/_netstat.h",
    "content": "//\n//  _netstat.h\n//  itlwm\n//\n//  Created by qcwap on 2021/4/22.\n//  Copyright © 2021 钟先耀. All rights reserved.\n//\n\n#ifndef _netstat_h\n#define _netstat_h\n\n#include <linux/types.h>\n\nstatic inline const char *\nopenbsd_plural(u_int64_t n)\n{\n    return (n != 1 ? \"s\" : \"\");\n}\n\n/*\n * Dump IEEE802.11 per-interface statistics\n */\nstatic inline void\nnet80211_ifstats(struct ieee80211com *ic)\n{\n    struct ieee80211_stats *stats = &ic->ic_stats;\n\n#define    p(f, m)    XYLog(m, (unsigned long)stats->f, openbsd_plural(stats->f))\n    p(is_rx_badversion, \"\\t%lu input packet%s with bad version\\n\");\n    p(is_rx_tooshort, \"\\t%lu input packet%s too short\\n\");\n    p(is_rx_wrongbss, \"\\t%lu input packet%s from wrong bssid\\n\");\n    p(is_rx_dup, \"\\t%lu input packet duplicate%s discarded\\n\");\n    p(is_rx_wrongdir, \"\\t%lu input packet%s with wrong direction\\n\");\n    p(is_rx_mcastecho, \"\\t%lu input multicast echo packet%s discarded\\n\");\n    p(is_rx_notassoc, \"\\t%lu input packet%s from unassociated station discarded\\n\");\n    p(is_rx_nowep, \"\\t%lu input encrypted packet%s without wep/wpa config discarded\\n\");\n    p(is_rx_unencrypted, \"\\t%lu input unencrypted packet%s with wep/wpa config discarded\\n\");\n    p(is_rx_wepfail, \"\\t%lu input wep/wpa packet%s processing failed\\n\");\n    p(is_rx_decap, \"\\t%lu input packet decapsulation%s failed\\n\");\n    p(is_rx_mgtdiscard, \"\\t%lu input management packet%s discarded\\n\");\n    p(is_rx_ctl, \"\\t%lu input control packet%s discarded\\n\");\n    p(is_rx_rstoobig, \"\\t%lu input packet%s with truncated rate set\\n\");\n    p(is_rx_elem_missing, \"\\t%lu input packet%s with missing elements\\n\");\n    p(is_rx_elem_toobig, \"\\t%lu input packet%s with elements too big\\n\");\n    p(is_rx_elem_toosmall, \"\\t%lu input packet%s with elements too small\\n\");\n    p(is_rx_badchan, \"\\t%lu input packet%s with invalid channel\\n\");\n    p(is_rx_chanmismatch, \"\\t%lu input packet%s with mismatched channel\\n\");\n    p(is_rx_nodealloc, \"\\t%lu node allocation%s failed\\n\");\n    p(is_rx_ssidmismatch, \"\\t%lu input packet%s with mismatched ssid\\n\");\n    p(is_rx_auth_unsupported, \"\\t%lu input packet%s with unsupported auth algorithm\\n\");\n    p(is_rx_auth_fail, \"\\t%lu input authentication%s failed\\n\");\n    p(is_rx_assoc_bss, \"\\t%lu input association%s from wrong bssid\\n\");\n    p(is_rx_assoc_notauth, \"\\t%lu input association%s without authentication\\n\");\n    p(is_rx_assoc_capmismatch, \"\\t%lu input association%s with mismatched capabilities\\n\");\n    p(is_rx_assoc_norate, \"\\t%lu input association%s without matching rates\\n\");\n    p(is_rx_assoc_badrsnie, \"\\t%lu input association%s with bad rsn ie\\n\");\n    p(is_rx_deauth, \"\\t%lu input deauthentication packet%s\\n\");\n    p(is_rx_disassoc, \"\\t%lu input disassociation packet%s\\n\");\n    p(is_rx_badsubtype, \"\\t%lu input packet%s with unknown subtype\\n\");\n    p(is_rx_nombuf, \"\\t%lu input packet%s failed for lack of mbufs\\n\");\n    p(is_rx_decryptcrc, \"\\t%lu input decryption%s failed on crc\\n\");\n    p(is_rx_ahdemo_mgt, \"\\t%lu input ahdemo management packet%s discarded\\n\");\n    p(is_rx_bad_auth, \"\\t%lu input packet%s with bad auth request\\n\");\n    p(is_rx_eapol_key, \"\\t%lu input eapol-key packet%s\\n\");\n    p(is_rx_eapol_badmic, \"\\t%lu input eapol-key packet%s with bad mic\\n\");\n    p(is_rx_eapol_replay, \"\\t%lu input eapol-key packet%s replayed\\n\");\n    p(is_rx_locmicfail, \"\\t%lu input packet%s with bad tkip mic\\n\");\n    p(is_rx_remmicfail, \"\\t%lu input tkip mic failure notification%s\\n\");\n    p(is_rx_unauth, \"\\t%lu input packet%s on unauthenticated port\\n\");\n    p(is_tx_nombuf, \"\\t%lu output packet%s failed for lack of mbufs\\n\");\n    p(is_tx_nonode, \"\\t%lu output packet%s failed for no nodes\\n\");\n    p(is_tx_unknownmgt, \"\\t%lu output packet%s of unknown management type\\n\");\n    p(is_tx_noauth, \"\\t%lu output packet%s on unauthenticated port\\n\");\n    p(is_scan_active, \"\\t%lu active scan%s started\\n\");\n    p(is_scan_passive, \"\\t%lu passive scan%s started\\n\");\n    p(is_node_timeout, \"\\t%lu node%s timed out\\n\");\n    p(is_crypto_nomem, \"\\t%lu failure%s with no memory for crypto ctx\\n\");\n    p(is_ccmp_dec_errs, \"\\t%lu ccmp decryption error%s\\n\");\n    p(is_ccmp_replays, \"\\t%lu ccmp replayed frame%s \\n\");\n    p(is_cmac_icv_errs, \"\\t%lu cmac icv error%s\\n\");\n    p(is_cmac_replays, \"\\t%lu cmac replayed frame%s\\n\");\n    p(is_tkip_icv_errs, \"\\t%lu tkip icv error%s\\n\");\n    p(is_tkip_replays, \"\\t%lu tkip replay%s\\n\");\n    p(is_pbac_errs, \"\\t%lu pbac error%s\\n\");\n    p(is_ht_nego_no_mandatory_mcs, \"\\t%lu HT negotiation failure%s because \"\n        \"peer does not support MCS 0-7\\n\");\n    p(is_ht_nego_no_basic_mcs, \"\\t%lu HT negotiation failure%s because \"\n        \"we do not support basic MCS set\\n\");\n    p(is_ht_nego_bad_crypto,\n        \"\\t%lu HT negotiation failure%s because peer uses bad crypto\\n\");\n    p(is_ht_prot_change, \"\\t%lu HT protection change%s\\n\");\n    p(is_ht_rx_ba_agreements, \"\\t%lu new input block ack agreement%s\\n\");\n    p(is_ht_tx_ba_agreements, \"\\t%lu new output block ack agreement%s\\n\");\n    p(is_ht_rx_frame_below_ba_winstart,\n        \"\\t%lu input frame%s below block ack window start\\n\");\n    p(is_ht_rx_frame_above_ba_winend,\n        \"\\t%lu input frame%s above block ack window end\\n\");\n    p(is_ht_rx_ba_window_slide, \"\\t%lu input block ack window slide%s\\n\");\n    p(is_ht_rx_ba_window_jump, \"\\t%lu input block ack window jump%s\\n\");\n    p(is_ht_rx_ba_no_buf, \"\\t%lu duplicate input block ack frame%s\\n\");\n    p(is_ht_rx_ba_frame_lost,\n        \"\\t%lu expected input block ack frame%s never arrived\\n\");\n    p(is_ht_rx_ba_window_gap_timeout,\n        \"\\t%lu input block ack window gap%s timed out\\n\");\n    p(is_ht_rx_ba_timeout,\n        \"\\t%lu input block ack agreement%s timed out\\n\");\n    p(is_ht_tx_ba_timeout,\n        \"\\t%lu output block ack agreement%s timed out\\n\");\n    p(is_vht_nego_no_mandatory_mcs, \"\\t%lu VHT negotiation failure%s because \"\n        \"peer does not support MCS 0-9\\n\");\n    p(is_vht_nego_bad_crypto,\n        \"\\t%lu VHT negotiation failure%s because peer uses bad crypto\\n\");\n\n#undef p\n}\n\n#endif /* _netstat_h */\n"
  },
  {
    "path": "itl80211/openbsd/sys/_null.h",
    "content": "/*\t$OpenBSD: _null.h,v 1.2 2016/09/09 22:07:58 millert Exp $\t*/\n\n/*\n * Written by Todd C. Miller, September 9, 2016\n * Public domain.\n */\n\n#ifndef NULL\n#if !defined(__cplusplus)\n#define\tNULL\t((void *)0)\n#elif __cplusplus >= 201103L\n#define\tNULL\tnullptr\n#elif defined(__GNUG__)\n#define\tNULL\t__null\n#else\n#define\tNULL\t0L\n#endif\n#endif\n"
  },
  {
    "path": "itl80211/openbsd/sys/_task.cpp",
    "content": "//\n//  _task.cpp\n//  itlwm\n//\n//  Created by qcwap on 2020/3/1.\n//  Copyright © 2020 钟先耀. All rights reserved.\n//\n\n/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n\n#include <sys/_task.h>\n#include <sys/proc.h>\n\n#include <IOKit/IOLib.h>\n#include <IOKit/IOCommandGate.h>\n\nenum ETQ_STATE {\n    TQ_S_CREATED,\n    TQ_S_RUNNING,\n    TQ_S_DESTROYED\n};\n\nstruct taskq {\n    enum ETQ_STATE       tq_state;\n    unsigned int         tq_running;\n    unsigned int         tq_waiting;\n    unsigned int         tq_nthreads;\n    unsigned int         tq_flags;\n    const char        *tq_name;\n\n    IORecursiveLock *tq_mtx;\n    struct task_list     tq_worklist;\n};\n\nstatic const char taskq_sys_name[] = \"systq\";\n\nstruct taskq taskq_sys = {\n    TQ_S_CREATED,\n    0,\n    0,\n    1,\n    0,\n    taskq_sys_name,\n};\n\nstruct taskq *const systq = &taskq_sys;\n\nint\ntaskq_next_work(struct taskq *tq, struct task *work)\n{\n    struct task *next;\n    \n    //    IOLog(\"itlwm: taskq %s lock\\n\", __FUNCTION__);\n    IORecursiveLockLock(tq->tq_mtx);\n    \n    while ((next = TAILQ_FIRST(&tq->tq_worklist)) == NULL) {\n        if (tq->tq_state != TQ_S_RUNNING) {\n            IORecursiveLockUnlock(tq->tq_mtx);\n            return (0);\n        }\n        IORecursiveLockSleep(tq->tq_mtx, tq, THREAD_INTERRUPTIBLE);\n    }\n\n    TAILQ_REMOVE(&tq->tq_worklist, next, t_entry);\n    CLR(next->t_flags, TASK_ONQUEUE);\n\n    *work = *next; /* copy to caller to avoid races */\n\n    next = TAILQ_FIRST(&tq->tq_worklist);\n    IORecursiveLockUnlock(tq->tq_mtx);\n//    IOLog(\"itlwm: taskq %s unlock\\n\", __FUNCTION__);\n\n    if (next != NULL && tq->tq_nthreads > 1)\n        IORecursiveLockWakeup(tq->tq_mtx, tq, true);\n\n    return (1);\n}\n\nvoid\ntaskq_thread(void *xtq)\n{\n    struct taskq *tq = (struct taskq *)xtq;\n    struct task work;\n    int last;\n\n//    if (ISSET(tq->tq_flags, TASKQ_MPSAFE))\n//        KERNEL_UNLOCK();\n\n//    WITNESS_CHECKORDER(&tq->tq_lock_object, LOP_NEWORDER, NULL);\n    \n    IOLog(\"itlwm: taskq %s schedule task\\n\", __FUNCTION__);\n\n    while (taskq_next_work(tq, &work)) {\n//        WITNESS_LOCK(&tq->tq_lock_object, 0);\n//        IOLog(\"itlwm: taskq worker thread=%lld work=%s\\n\", thread_tid(current_thread()), work.name);\n        (*work.t_func)(work.t_arg);\n//        IOLog(\"itlwm: taskq worker thread=%lld work=%s done\", thread_tid(current_thread()), work.name);\n//        WITNESS_UNLOCK(&tq->tq_lock_object, 0);\n//        sched_pause(yield);\n        IOSleep(1);\n    }\n    \n    IOLog(\"itlwm: taskq %s schedule task done\\n\", __FUNCTION__);\n\n    IORecursiveLockLock(tq->tq_mtx);\n    last = (--tq->tq_running == 0);\n    IORecursiveLockUnlock(tq->tq_mtx);\n\n//    if (ISSET(tq->tq_flags, TASKQ_MPSAFE))\n//        KERNEL_LOCK();\n\n    if (last) {\n        IOLog(\"itlwm: taskq %s schedule task wakeup\\n\", __FUNCTION__);\n        IORecursiveLockWakeup(tq->tq_mtx, tq, false);\n    }\n\n//    kthread_exit(0);\n    thread_terminate(current_thread());\n}\n\nvoid taskq_create_thread(void *arg)\n{\n    struct taskq *tq = (struct taskq *)arg;\n    int rv;\n    IOLog(\"itlwm: taskq %s lock\\n\", __FUNCTION__);\n    IORecursiveLockLock(tq->tq_mtx);\n    switch (tq->tq_state) {\n        case TQ_S_DESTROYED:\n            IOLog(\"itlwm: taskq %s unlock\\n\", __FUNCTION__);\n            IORecursiveLockUnlock(tq->tq_mtx);\n            if (tq != systq) {\n                IORecursiveLockFree(tq->tq_mtx);\n                IOFree(tq, sizeof(*tq));\n            }\n            return;\n\n        case TQ_S_CREATED:\n            tq->tq_state = TQ_S_RUNNING;\n            break;\n\n        default:\n            IOLog(\"itlwm: unexpected %s tq state %u\", tq->tq_name, tq->tq_state);\n            IORecursiveLockUnlock(tq->tq_mtx);\n            if (tq != systq) {\n                IORecursiveLockFree(tq->tq_mtx);\n                IOFree(tq, sizeof(*tq));\n            }\n            return;\n    }\n\n    do {\n        tq->tq_running++;\n        IOLog(\"itlwm: taskq %s unlock\\n\", __FUNCTION__);\n        IORecursiveLockUnlock(tq->tq_mtx);\n\n        thread_t new_thread;\n        rv = kernel_thread_start((thread_continue_t)taskq_thread, tq, &new_thread);\n        thread_deallocate(new_thread);\n\n        IOLog(\"itlwm: taskq %s lock\\n\", __FUNCTION__);\n        IORecursiveLockLock(tq->tq_mtx);\n        if (rv != KERN_SUCCESS) {\n            IOLog(\"itlwm: tasq unable to create thread for \\\"%s\\\" taskq\\n\",\n                   tq->tq_name);\n\n            tq->tq_running--;\n            /* could have been destroyed during kthread_create */\n            if (tq->tq_state == TQ_S_DESTROYED &&\n                tq->tq_running == 0)\n                IORecursiveLockWakeup(tq->tq_mtx, tq, false);\n            break;\n        }\n    } while (tq->tq_running < tq->tq_nthreads);\n    \n    IOLog(\"itlwm: taskq %s unlock\\n\", __FUNCTION__);\n    IORecursiveLockUnlock(tq->tq_mtx);\n}\n\nvoid\ntaskq_init(void)\n{\n    systq->tq_mtx = IORecursiveLockAlloc();\n    TAILQ_INIT(&systq->tq_worklist);\n    thread_t new_thread;\n    kernel_thread_start((thread_continue_t)taskq_create_thread, systq, &new_thread);\n    thread_deallocate(new_thread);\n}\n\nstruct taskq *\ntaskq_create(const char *name, unsigned int nthreads, int ipl,\n             unsigned int flags)\n{\n    struct taskq *tq;\n\n    tq = (struct taskq *)IOMalloc(sizeof(*tq));\n    if (tq == NULL)\n        return (NULL);\n\n    tq->tq_state = TQ_S_CREATED;\n    tq->tq_running = 0;\n    tq->tq_waiting = 0;\n    tq->tq_nthreads = nthreads;\n    tq->tq_name = name;\n    tq->tq_flags = flags;\n    tq->tq_mtx = IORecursiveLockAlloc();\n\n    //    mtx_init_flags(&tq->tq_mtx, ipl, name, 0);\n    TAILQ_INIT(&tq->tq_worklist);\n    thread_t new_thread;\n    /* try to create a thread to guarantee that tasks will be serviced */\n    kernel_thread_start((thread_continue_t)taskq_create_thread, tq, &new_thread);\n    thread_deallocate(new_thread);\n    return (tq);\n}\n\nvoid\ntaskq_destroy(struct taskq *tq)\n{\n    if (!tq || !tq->tq_mtx) {\n        return;\n    }\n    IORecursiveLockLock(tq->tq_mtx);\n    switch (tq->tq_state) {\n        case TQ_S_CREATED:\n            /* tq is still referenced by taskq_create_thread */\n            tq->tq_state = TQ_S_DESTROYED;\n            IORecursiveLockUnlock(tq->tq_mtx);\n            return;\n\n        case TQ_S_RUNNING:\n            tq->tq_state = TQ_S_DESTROYED;\n            break;\n\n        default:\n            IOLog(\"itlwm: unexpected %s tq state %u\", tq->tq_name, tq->tq_state);\n            tq->tq_state = TQ_S_DESTROYED;\n            IORecursiveLockUnlock(tq->tq_mtx);\n            return;\n    }\n\n    while (tq->tq_running > 0) {\n        IORecursiveLockWakeup(tq->tq_mtx, tq, false);\n        IORecursiveLockSleep(tq->tq_mtx, tq, THREAD_INTERRUPTIBLE);\n    }\n\n    IORecursiveLockUnlock(tq->tq_mtx);\n    IORecursiveLockFree(tq->tq_mtx);\n    if (tq != systq) {\n        IOFree(tq, sizeof(*tq));\n    }\n    \n}\n\nvoid\ntask_set(struct task *t, void (*fn)(void *), void *arg, const char *name)\n{\n    t->t_func = fn;\n    t->t_arg = arg;\n    t->t_flags = 0;\n    memcpy(t->name, name, sizeof(t->name));\n}\n\nint\ntask_add(struct taskq *tq, struct task *w)\n{\n    int rv = 0;\n//    IOLog(\"itlwm: taskq task_add %s thread: %lld\\n\", w->name, thread_tid(current_thread()));\n    \n    if (ISSET(w->t_flags, TASK_ONQUEUE))\n        return (0);\n\n    IORecursiveLockLock(tq->tq_mtx);\n    if (ISSET(w->t_flags, TASK_ONQUEUE)) {\n//        IOLog(\"itlwm: taskq task_add %s is already on queue thread: %lld\\n\", w->name, thread_tid(current_thread()));\n        IORecursiveLockUnlock(tq->tq_mtx);\n        return (0);\n    }\n    if (!ISSET(w->t_flags, TASK_ONQUEUE)) {\n//        IOLog(\"itlwm: taskq task_add %s add to queue thread: %lld\\n\", w->name, thread_tid(current_thread()));\n        rv = 1;\n        SET(w->t_flags, TASK_ONQUEUE);\n        TAILQ_INSERT_TAIL(&tq->tq_worklist, w, t_entry);\n    }\n    IORecursiveLockUnlock(tq->tq_mtx);\n\n    if (rv)\n        IORecursiveLockWakeup(tq->tq_mtx, tq, true);\n\n    return (rv);\n}\n\nint\ntask_del(struct taskq *tq, struct task *w)\n{\n    int rv = 0;\n//    IOLog(\"itlwm: taskq task_del %s thread: %lld\\n\", w->name, thread_tid(current_thread()));\n    \n    if (!ISSET(w->t_flags, TASK_ONQUEUE))\n        return (0);\n\n    IORecursiveLockLock(tq->tq_mtx);\n    if (ISSET(w->t_flags, TASK_ONQUEUE)) {\n        rv = 1;\n        CLR(w->t_flags, TASK_ONQUEUE);\n        TAILQ_REMOVE(&tq->tq_worklist, w, t_entry);\n    }\n    IORecursiveLockUnlock(tq->tq_mtx);\n\n    return (rv);\n}\n"
  },
  {
    "path": "itl80211/openbsd/sys/_task.h",
    "content": "//\n//  _task.h\n//  itlwm\n//\n//  Created by qcwap on 2020/3/1.\n//  Copyright © 2020 钟先耀. All rights reserved.\n//\n/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n\n#ifndef _task_h\n#define _task_h\n\n#include <sys/queue.h>\n#include <sys/_buf.h>\n\n#include <IOKit/IOLocks.h>\n\nstruct task {\n    TAILQ_ENTRY(task) t_entry;\n    void        (*t_func)(void *);\n    void        *t_arg;\n    unsigned int    t_flags;\n    char name[256];\n};\n\n#define TASK_ONQUEUE        1\n#define TASK_BARRIER        2\n\nTAILQ_HEAD(task_list, task);\n\n#define TASKQ_MPSAFE        (1 << 0)\n\n#define TASK_INITIALIZER(_f, _a)  {{ NULL, NULL }, (_f), (_a), 0 }\n\n#define task_pending(_t)    ((_t)->t_flags & TASK_ONQUEUE)\n\nextern struct taskq *const systq;\n\nvoid taskq_init();\nstruct taskq    *taskq_create(const char *, unsigned int, int, unsigned int);\nvoid         taskq_destroy(struct taskq *);\nvoid         taskq_barrier(struct taskq *);\n\nvoid         taskq_del_barrier(struct taskq *, struct task *);\n\nvoid         task_set(struct task *, void (*)(void *), void *, const char *);\nint         task_add(struct taskq *, struct task *);\nint         task_del(struct taskq *, struct task *);\n\n#endif /* _task_h */\n"
  },
  {
    "path": "itl80211/openbsd/sys/arp.c",
    "content": "//\n//  arp.c\n//  itlwm\n//\n//  Created by zxystd on 2023/7/1.\n//  Copyright © 2023 钟先耀. All rights reserved.\n//\n\n#include \"arp.h\"\n\n#include <netinet/if_ether.h>\n#include <linux/types.h>\n#include <sys/_malloc.h>\n\n#define EXTRACT_16BITS(p) \\\n((u_int16_t)*((const u_int8_t *)(p) + 0) << 8 | \\\n(u_int16_t)*((const u_int8_t *)(p) + 1))\n#define EXTRACT_32BITS(p) \\\n((u_int32_t)*((const u_int8_t *)(p) + 0) << 24 | \\\n(u_int32_t)*((const u_int8_t *)(p) + 1) << 16 | \\\n(u_int32_t)*((const u_int8_t *)(p) + 2) << 8 | \\\n(u_int32_t)*((const u_int8_t *)(p) + 3))\n#define EXTRACT_24BITS(p) \\\n((u_int32_t)*((const u_int8_t *)(p) + 0) << 16 | \\\n(u_int32_t)*((const u_int8_t *)(p) + 1) << 8 | \\\n(u_int32_t)*((const u_int8_t *)(p) + 2))\n#define EXTRACT_LE_8BITS(p) (*(p))\n#define EXTRACT_LE_16BITS(p) \\\n    ((u_int16_t)*((const u_int8_t *)(p) + 1) << 8 | \\\n    (u_int16_t)*((const u_int8_t *)(p) + 0))\n#define EXTRACT_LE_32BITS(p) \\\n    ((u_int32_t)*((const u_int8_t *)(p) + 3) << 24 | \\\n    (u_int32_t)*((const u_int8_t *)(p) + 2) << 16 | \\\n    (u_int32_t)*((const u_int8_t *)(p) + 1) << 8 | \\\n    (u_int32_t)*((const u_int8_t *)(p) + 0))\n#define EXTRACT_LE_64BITS(p) \\\n    ((u_int64_t)*((const u_int8_t *)(p) + 7) << 56 | \\\n    (u_int64_t)*((const u_int8_t *)(p) + 6) << 48 | \\\n    (u_int64_t)*((const u_int8_t *)(p) + 5) << 40 | \\\n    (u_int64_t)*((const u_int8_t *)(p) + 4) << 32 | \\\n    (u_int64_t)*((const u_int8_t *)(p) + 3) << 24 | \\\n    (u_int64_t)*((const u_int8_t *)(p) + 2) << 16 | \\\n    (u_int64_t)*((const u_int8_t *)(p) + 1) << 8 | \\\n    (u_int64_t)*((const u_int8_t *)(p) + 0))\n\n#define ESRC(ep) ((ep)->ether_shost)\n#define EDST(ep) ((ep)->ether_dhost)\n#define SHA(ap) ((ap)->arp_sha)\n#define THA(ap) ((ap)->arp_tha)\n#define SPA(ap) ((ap)->arp_spa)\n#define TPA(ap) ((ap)->arp_tpa)\n\n#define HASHNAMESIZE 4096\n\nstruct hnamemem {\n    u_int32_t addr;\n    char *name;\n    struct hnamemem *nxt;\n};\n\nstruct enamemem {\n    u_short e_addr0;\n    u_short e_addr1;\n    u_short e_addr2;\n    char *e_name;\n    u_char *e_nsap;            /* used only for nsaptable[] */\n#define e_bs e_nsap            /* for bytestringtable */\n    struct enamemem *e_nxt;\n};\n\nstruct hnamemem hnametable[HASHNAMESIZE];\nstruct enamemem enametable[HASHNAMESIZE];\n\nstruct hnamemem *\nnewhnamemem(void)\n{\n    struct hnamemem *p;\n    static struct hnamemem *ptr = NULL;\n    static u_int num = 0;\n\n    if (num  <= 0) {\n        num = 64;\n        ptr = (struct hnamemem *)malloc(num * sizeof (*ptr), 0, 0);\n    }\n    --num;\n    p = ptr++;\n    return (p);\n}\n\nchar *\nintoa(u_int32_t addr)\n{\n    char *cp;\n    u_int byte;\n    int n;\n    static char buf[sizeof(\".xxx.xxx.xxx.xxx\")];\n\n    NTOHL(addr);\n    cp = &buf[sizeof buf];\n    *--cp = '\\0';\n\n    n = 4;\n    do {\n        byte = addr & 0xff;\n        *--cp = byte % 10 + '0';\n        byte /= 10;\n        if (byte > 0) {\n            *--cp = byte % 10 + '0';\n            byte /= 10;\n            if (byte > 0)\n                *--cp = byte + '0';\n        }\n        *--cp = '.';\n        addr >>= 8;\n    } while (--n > 0);\n\n    return cp + 1;\n}\n\nchar *\nsavestr(const char *str)\n{\n    size_t size;\n    char *p;\n    static char *strptr = NULL;\n    static size_t strsize = 0;\n\n    size = strlen(str) + 1;\n    if (size > strsize) {\n        strsize = 1024;\n        if (strsize < size)\n            strsize = size;\n        strptr = (char *)malloc(strsize, 0, 0);\n    }\n    (void)strlcpy(strptr, str, size);\n    p = strptr;\n    strptr += size;\n    strsize -= size;\n    return (p);\n}\n\n#define HOST_NAME_MAX        255\n\nchar *\ngetname(const u_char *ap)\n{\n    char host[HOST_NAME_MAX+1];\n    u_int32_t addr;\n    struct hnamemem *p;\n\n    /*\n     * Extract 32 bits in network order, dealing with alignment.\n     */\n    switch ((intptr_t)ap & (sizeof(u_int32_t)-1)) {\n\n    case 0:\n        addr = *(u_int32_t *)ap;\n        break;\n\n    case 2:\n#if BYTE_ORDER == BIG_ENDIAN\n        addr = ((u_int32_t)*(u_short *)ap << 16) |\n            (u_int32_t)*(u_short *)(ap + 2);\n#else\n        addr = ((u_int32_t)*(u_short *)(ap + 2) << 16) |\n            (u_int32_t)*(u_short *)ap;\n#endif\n        break;\n\n    default:\n#if BYTE_ORDER == BIG_ENDIAN\n        addr = ((u_int32_t)ap[0] << 24) |\n            ((u_int32_t)ap[1] << 16) |\n            ((u_int32_t)ap[2] << 8) |\n            (u_int32_t)ap[3];\n#else\n        addr = ((u_int32_t)ap[3] << 24) |\n            ((u_int32_t)ap[2] << 16) |\n            ((u_int32_t)ap[1] << 8) |\n            (u_int32_t)ap[0];\n#endif\n        break;\n    }\n\n    p = &hnametable[addr & (HASHNAMESIZE-1)];\n    for (; p->nxt; p = p->nxt) {\n        if (p->addr == addr)\n            return (p->name);\n    }\n    p->addr = addr;\n    p->nxt = newhnamemem();\n\n    p->name = savestr(intoa(addr));\n    return (p->name);\n}\n\nchar *\nether_ntoa(struct ether_addr *e)\n{\n    static char a[] = \"xx:xx:xx:xx:xx:xx\";\n\n    (void)snprintf(a, sizeof a, \"%02x:%02x:%02x:%02x:%02x:%02x\",\n        e->ether_addr_octet[0], e->ether_addr_octet[1],\n        e->ether_addr_octet[2], e->ether_addr_octet[3],\n        e->ether_addr_octet[4], e->ether_addr_octet[5]);\n\n    return (a);\n}\n\nstatic inline struct enamemem *\nlookup_emem(const u_char *ep)\n{\n    u_int i, j, k;\n    struct enamemem *tp;\n\n    k = (ep[0] << 8) | ep[1];\n    j = (ep[2] << 8) | ep[3];\n    i = (ep[4] << 8) | ep[5];\n\n    tp = &enametable[(i ^ j) & (HASHNAMESIZE-1)];\n    while (tp->e_nxt)\n        if (tp->e_addr0 == i &&\n            tp->e_addr1 == j &&\n            tp->e_addr2 == k)\n            return tp;\n        else\n            tp = tp->e_nxt;\n    tp->e_addr0 = i;\n    tp->e_addr1 = j;\n    tp->e_addr2 = k;\n    tp->e_nxt = (struct enamemem *)malloc(1 * sizeof(*tp), 0, 0);\n\n    return tp;\n}\n\nchar *\netheraddr_string(const u_char *ep)\n{\n    struct enamemem *tp;\n    struct ether_addr e;\n\n    tp = lookup_emem(ep);\n    if (tp->e_name)\n        return (tp->e_name);\n    memcpy(e.ether_addr_octet, ep, sizeof(e.ether_addr_octet));\n    tp->e_name = savestr(ether_ntoa(&e));\n    return (tp->e_name);\n}\n\n#define ipaddr_string(p) getname((const u_char *)(p))\n\nvoid\ndebug_print_arp(const char *tag, mbuf_t m)\n{\n    size_t len = mbuf_len(m);\n    ether_header_t *eh = (ether_header_t *)mbuf_data(m);\n    if (len >= sizeof(ether_header_t) &&\n        (eh->ether_type == htons(ETHERTYPE_ARP) || eh->ether_type == htons(ETHERTYPE_REVARP))) {\n        u_char *p = (u_char *)eh + sizeof(ether_header);\n        len -= sizeof(ether_header);\n        const struct ether_arp *ap = (const struct ether_arp *)p;\n        u_short pro, hrd, op;\n        pro = EXTRACT_16BITS(&ap->arp_pro);\n        hrd = EXTRACT_16BITS(&ap->arp_hrd);\n        op = EXTRACT_16BITS(&ap->arp_op);\n        if ((pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL)\n            || ap->arp_hln != sizeof(SHA(ap))\n            || ap->arp_pln != sizeof(SPA(ap))) {\n            XYLog(\"%s arp-#%d for proto #%d (%d) hardware #%d (%d)\\n\",\n                tag, op, pro, ap->arp_pln, hrd, ap->arp_hln);\n        }\n        if (pro == ETHERTYPE_TRAIL)\n            XYLog(\"%s trailer-\\n\", tag);\n        switch (op) {\n\n        case ARPOP_REQUEST:\n            XYLog(\"%s arp who-has %s tell %s\\n\", tag, ipaddr_string(TPA(ap)), ipaddr_string(SPA(ap)));\n            break;\n\n        case ARPOP_REPLY:\n            XYLog(\"%s arp reply %s is-at %s\\n\", tag, ipaddr_string(SPA(ap)), etheraddr_string(SHA(ap)));\n            break;\n\n        case ARPOP_REVREQUEST:\n            XYLog(\"%s rarp who-is %s tell %s\\n\", tag, etheraddr_string(THA(ap)),\n            etheraddr_string(SHA(ap)));\n            break;\n\n        case ARPOP_REVREPLY:\n            XYLog(\"%s rarp reply %s at %s\\n\", tag, etheraddr_string(THA(ap)),\n            ipaddr_string(TPA(ap)));\n            break;\n\n        default:\n            XYLog(\"%s arp-#%d\\n\", tag, op);\n            break;\n        }\n        if (hrd != ARPHRD_ETHER)\n            XYLog(\"%s  hardware #%d\\n\", tag, hrd);\n    }\n}\n"
  },
  {
    "path": "itl80211/openbsd/sys/arp.h",
    "content": "//\n//  arp.h\n//  itlwm\n//\n//  Created by zxystd on 2023/7/1.\n//  Copyright © 2023 钟先耀. All rights reserved.\n//\n\n#ifndef arp_h\n#define arp_h\n\n#include <sys/kpi_mbuf.h>\n\nvoid debug_print_arp(const char *tag, mbuf_t m);\n\n#endif /* arp_h */\n"
  },
  {
    "path": "itl80211/openbsd/sys/endian.h",
    "content": "//\n//  endian.h\n//  AppleIntelWifiAdapter\n//\n//  Created by 钟先耀 on 2020/1/22.\n//  Copyright © 2020 钟先耀. All rights reserved.\n//\n\n/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n\n#ifndef _SYS_ENDIAN_H_\n#define _SYS_ENDIAN_H_\n\n#include <sys/cdefs.h>\n#include <sys/_endian.h>\n#include <sys/_types.h>\n\n#define __FROM_SYS__ENDIAN\n#include <machine/endian.h>\n#undef __FROM_SYS__ENDIAN\n\n#define _KERNEL\n#define _LITTLE_ENDIAN    1234\n#define _BIG_ENDIAN    4321\n#define _PDP_ENDIAN    3412\n#define INET6\n\n//ZXY DEFINE\n#define _BYTE_ORDER _LITTLE_ENDIAN\n\n/* Note that these macros evaluate their arguments several times.  */\n\n#define __swap16gen(x)                            \\\n    (__uint16_t)(((__uint16_t)(x) & 0xffU) << 8 | ((__uint16_t)(x) & 0xff00U) >> 8)\n\n#define __swap32gen(x)                            \\\n    (__uint32_t)(((__uint32_t)(x) & 0xff) << 24 |            \\\n    ((__uint32_t)(x) & 0xff00) << 8 | ((__uint32_t)(x) & 0xff0000) >> 8 |\\\n    ((__uint32_t)(x) & 0xff000000) >> 24)\n\n#define __swap64gen(x)                            \\\n    (__uint64_t)((((__uint64_t)(x) & 0xff) << 56) |            \\\n        ((__uint64_t)(x) & 0xff00ULL) << 40 |            \\\n        ((__uint64_t)(x) & 0xff0000ULL) << 24 |            \\\n        ((__uint64_t)(x) & 0xff000000ULL) << 8 |            \\\n        ((__uint64_t)(x) & 0xff00000000ULL) >> 8 |            \\\n        ((__uint64_t)(x) & 0xff0000000000ULL) >> 24 |        \\\n        ((__uint64_t)(x) & 0xff000000000000ULL) >> 40 |        \\\n        ((__uint64_t)(x) & 0xff00000000000000ULL) >> 56)\n\nstatic __inline __uint16_t\n__swap16md(__uint16_t x)\n{\n    return (__swap16gen(x));\n}\n\nstatic __inline __uint32_t\n__swap32md(__uint32_t x)\n{\n    return (__swap32gen(x));\n}\n\nstatic __inline __uint64_t\n__swap64md(__uint64_t x)\n{\n    return (__swap64gen(x));\n}\n\n#define __swap16(x)                            \\\n    (__uint16_t)(__builtin_constant_p(x) ? __swap16gen(x) : __swap16md(x))\n#define __swap32(x)                            \\\n    (__uint32_t)(__builtin_constant_p(x) ? __swap32gen(x) : __swap32md(x))\n#define __swap64(x)                            \\\n    (__uint64_t)(__builtin_constant_p(x) ? __swap64gen(x) : __swap64md(x))\n\n#if _BYTE_ORDER == _LITTLE_ENDIAN\n\n#define _QUAD_HIGHWORD 1\n#define _QUAD_LOWWORD 0\n\n#define __htobe16    __swap16\n#define __htobe32    __swap32\n#define __htobe64    __swap64\n#define __htole16(x)    ((__uint16_t)(x))\n#define __htole32(x)    ((__uint32_t)(x))\n#define __htole64(x)    ((__uint64_t)(x))\n\n#define __bemtoh16(_x) __mswap16(_x)\n#define __bemtoh32(_x) __mswap32(_x)\n#define __bemtoh64(_x) __mswap64(_x)\n\n#define __htobem16(_x, _v) __swapm16((_x), (_v))\n#define __htobem32(_x, _v) __swapm32((_x), (_v))\n#define __htobem64(_x, _v) __swapm64((_x), (_v))\n\n#endif /* _BYTE_ORDER == _LITTLE_ENDIAN */\n\n#if _BYTE_ORDER == _BIG_ENDIAN\n\n#define _QUAD_HIGHWORD 0\n#define _QUAD_LOWWORD 1\n\n#define __htobe16(x)    ((__uint16_t)(x))\n#define __htobe32(x)    ((__uint32_t)(x))\n#define __htobe64(x)    ((__uint64_t)(x))\n#define __htole16    __swap16\n#define __htole32    __swap32\n#define __htole64    __swap64\n\n#define __lemtoh16(_x) __mswap16(_x)\n#define __lemtoh32(_x) __mswap32(_x)\n#define __lemtoh64(_x) __mswap64(_x)\n\n#define __htolem16(_x, _v) __swapm16((_x), (_v))\n#define __htolem32(_x, _v) __swapm32((_x), (_v))\n#define __htolem64(_x, _v) __swapm64((_x), (_v))\n\n#endif /* _BYTE_ORDER == _BIG_ENDIAN */\n\n\n#ifdef _KERNEL\n/*\n * Fill in the __hto[bl]em{16,32,64} and __[bl]emtoh{16,32,64} macros\n * that haven't been defined yet\n */\n\n#ifndef __bemtoh16\n#define __bemtoh16(_x)        __htobe16(*(__uint16_t *)(_x))\n#define __bemtoh32(_x)        __htobe32(*(__uint32_t *)(_x))\n#define __bemtoh64(_x)        __htobe64(*(__uint64_t *)(_x))\n#endif\n\n#ifndef __htobem16\n#define __htobem16(_x, _v)    (*(__uint16_t *)(_x) = __htobe16(_v))\n#define __htobem32(_x, _v)    (*(__uint32_t *)(_x) = __htobe32(_v))\n#define __htobem64(_x, _v)    (*(__uint64_t *)(_x) = __htobe64(_v))\n#endif\n\n#ifndef __lemtoh16\n#define __lemtoh16(_x)        __htole16(*(__uint16_t *)(_x))\n#define __lemtoh32(_x)        __htole32(*(__uint32_t *)(_x))\n#define __lemtoh64(_x)        __htole64(*(__uint64_t *)(_x))\n#endif\n\n#ifndef __htolem16\n#define __htolem16(_x, _v)    (*(__uint16_t *)(_x) = __htole16(_v))\n#define __htolem32(_x, _v)    (*(__uint32_t *)(_x) = __htole32(_v))\n#define __htolem64(_x, _v)    (*(__uint64_t *)(_x) = __htole64(_v))\n#endif\n#endif /* _KERNEL */\n\n/* Public names */\n#define LITTLE_ENDIAN    _LITTLE_ENDIAN\n#define BIG_ENDIAN    _BIG_ENDIAN\n#define PDP_ENDIAN    _PDP_ENDIAN\n#define BYTE_ORDER    _BYTE_ORDER\n\n\n/*\n * These are specified to be function-like macros to match the spec\n */\n#define htobe16(x)    __htobe16(x)\n#define htobe32(x)    __htobe32(x)\n#define htobe64(x)    __htobe64(x)\n#define htole16(x)    __htole16(x)\n#define htole32(x)    __htole32(x)\n#define htole64(x)    __htole64(x)\n\n/* POSIX names */\n#define be16toh(x)    __htobe16(x)\n#define be32toh(x)    __htobe32(x)\n#define be64toh(x)    __htobe64(x)\n#define le16toh(x)    __htole16(x)\n#define le32toh(x)    __htole32(x)\n#define le64toh(x)    __htole64(x)\n\n#define swap16(x) __swap16(x)\n#define swap32(x) __swap32(x)\n#define swap64(x) __swap64(x)\n\n#define swap16_multi(v, n) do {                        \\\n    __size_t __swap16_multi_n = (n);                \\\n    __uint16_t *__swap16_multi_v = (v);                \\\n                                    \\\n    while (__swap16_multi_n) {                    \\\n        *__swap16_multi_v = swap16(*__swap16_multi_v);        \\\n        __swap16_multi_v++;                    \\\n        __swap16_multi_n--;                    \\\n    }                                \\\n} while (0)\n\n/* original BSD names */\n#define betoh16(x)    __htobe16(x)\n#define betoh32(x)    __htobe32(x)\n#define betoh64(x)    __htobe64(x)\n#define letoh16(x)    __htole16(x)\n#define letoh32(x)    __htole32(x)\n#define letoh64(x)    __htole64(x)\n\n#ifndef htons\n/* these were exposed here before */\n#define htons(x)    __htobe16(x)\n#define htonl(x)    __htobe32(x)\n#define ntohs(x)    __htobe16(x)\n#define ntohl(x)    __htobe32(x)\n#endif\n\n/* ancient stuff */\n#define    NTOHL(x) (x) = ntohl((u_int32_t)(x))\n#define    NTOHS(x) (x) = ntohs((u_int16_t)(x))\n#define    HTONL(x) (x) = htonl((u_int32_t)(x))\n#define    HTONS(x) (x) = htons((u_int16_t)(x))\n\n#ifdef _KERNEL\n/* to/from memory conversions */\n#define bemtoh16    __bemtoh16\n#define bemtoh32    __bemtoh32\n#define bemtoh64    __bemtoh64\n#define htobem16    __htobem16\n#define htobem32    __htobem32\n#define htobem64    __htobem64\n#define lemtoh16    __lemtoh16\n#define lemtoh32    __lemtoh32\n#define lemtoh64    __lemtoh64\n#define htolem16    __htolem16\n#define htolem32    __htolem32\n#define htolem64    __htolem64\n#endif /* _KERNEL */\n\n#include <libkern/OSByteOrder.h>\n\n#define htobe16 OSSwapHostToBigInt16\n#define htobe32 OSSwapHostToBigInt32\n#define htobe64 OSSwapHostToBigInt64\n#define betoh16 OSSwapBigToHostInt16\n#define betoh32 OSSwapBigToHostInt32\n#define betoh64 OSSwapBigToHostInt64\n#define be32toh(x) OSSwapBigToHostInt32(x)\n#define le32toh(x) OSSwapLittleToHostInt32(x)\n#define htole16 OSSwapHostToLittleInt16\n#define htole32 OSSwapHostToLittleInt32\n#define htole64 OSSwapHostToLittleInt64\n#define letoh16 OSSwapLittleToHostInt16\n#define letoh32 OSSwapLittleToHostInt32\n#define letoh64 OSSwapLittleToHostInt64\n\nstatic __inline uint16_t\nbe16dec(const void *pp)\n{\n    uint8_t const *p = (uint8_t const *)pp;\n\n    return ((p[0] << 8) | p[1]);\n}\n\nstatic __inline uint32_t\nbe32dec(const void *pp)\n{\n    uint8_t const *p = (uint8_t const *)pp;\n\n    return (((unsigned)p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);\n}\n\nstatic __inline uint64_t\nbe64dec(const void *pp)\n{\n    uint8_t const *p = (uint8_t const *)pp;\n\n    return (((uint64_t)be32dec(p) << 32) | be32dec(p + 4));\n}\n\nstatic __inline uint16_t\nle16dec(const void *pp)\n{\n    uint8_t const *p = (uint8_t const *)pp;\n\n    return ((p[1] << 8) | p[0]);\n}\n\nstatic __inline uint32_t\nle32dec(const void *pp)\n{\n    uint8_t const *p = (uint8_t const *)pp;\n\n    return (((unsigned)p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]);\n}\n\nstatic __inline uint64_t\nle64dec(const void *pp)\n{\n    uint8_t const *p = (uint8_t const *)pp;\n\n    return (((uint64_t)le32dec(p + 4) << 32) | le32dec(p));\n}\n\nstatic __inline void\nbe16enc(void *pp, uint16_t u)\n{\n    uint8_t *p = (uint8_t *)pp;\n\n    p[0] = (u >> 8) & 0xff;\n    p[1] = u & 0xff;\n}\n\nstatic __inline void\nbe32enc(void *pp, uint32_t u)\n{\n    uint8_t *p = (uint8_t *)pp;\n\n    p[0] = (u >> 24) & 0xff;\n    p[1] = (u >> 16) & 0xff;\n    p[2] = (u >> 8) & 0xff;\n    p[3] = u & 0xff;\n}\n\nstatic __inline void\nbe64enc(void *pp, uint64_t u)\n{\n    uint8_t *p = (uint8_t *)pp;\n\n    be32enc(p, (uint32_t)(u >> 32));\n    be32enc(p + 4, (uint32_t)(u & 0xffffffffU));\n}\n\nstatic __inline void\nle16enc(void *pp, uint16_t u)\n{\n    uint8_t *p = (uint8_t *)pp;\n\n    p[0] = u & 0xff;\n    p[1] = (u >> 8) & 0xff;\n}\n\nstatic __inline void\nle32enc(void *pp, uint32_t u)\n{\n    uint8_t *p = (uint8_t *)pp;\n\n    p[0] = u & 0xff;\n    p[1] = (u >> 8) & 0xff;\n    p[2] = (u >> 16) & 0xff;\n    p[3] = (u >> 24) & 0xff;\n}\n\nstatic __inline void\nle64enc(void *pp, uint64_t u)\n{\n    uint8_t *p = (uint8_t *)pp;\n\n    le32enc(p, (uint32_t)(u & 0xffffffffU));\n    le32enc(p + 4, (uint32_t)(u >> 32));\n}\n\n#endif /* _SYS_ENDIAN_H_ */\n"
  },
  {
    "path": "itl80211/openbsd/sys/pcireg.h",
    "content": "/*\t$OpenBSD: pcireg.h,v 1.57 2019/05/30 21:44:21 kettenis Exp $\t*/\n/*\t$NetBSD: pcireg.h,v 1.26 2000/05/10 16:58:42 thorpej Exp $\t*/\n\n/*\n * Copyright (c) 1995, 1996 Christopher G. Demetriou.  All rights reserved.\n * Copyright (c) 1994, 1996 Charles Hannum.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *\tThis product includes software developed by Charles Hannum.\n * 4. The name of the author may not be used to endorse or promote products\n *    derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef _DEV_PCI_PCIREG_H_\n#define\t_DEV_PCI_PCIREG_H_\n\n#include <linux/types.h>\n\n/*\n * Standardized PCI configuration information\n *\n * XXX This is not complete.\n */\n\n#define\tPCI_CONFIG_SPACE_SIZE\t\t0x100\n#define\tPCIE_CONFIG_SPACE_SIZE\t\t0x1000\n\n/*\n * Device identification register; contains a vendor ID and a device ID.\n */\n#define\tPCI_ID_REG\t\t\t0x00\n\ntypedef u_int16_t pci_vendor_id_t;\ntypedef u_int16_t pci_product_id_t;\n\n#define\tPCI_VENDOR_SHIFT\t\t\t0\n#define\tPCI_VENDOR_MASK\t\t\t\t0xffff\n#define\tPCI_VENDOR(id) \\\n\t    (((id) >> PCI_VENDOR_SHIFT) & PCI_VENDOR_MASK)\n\n#define\tPCI_PRODUCT_SHIFT\t\t\t16\n#define\tPCI_PRODUCT_MASK\t\t\t0xffff\n#define\tPCI_PRODUCT(id) \\\n\t    (((id) >> PCI_PRODUCT_SHIFT) & PCI_PRODUCT_MASK)\n\n#define PCI_ID_CODE(vid,pid) \\\n\t((((vid) & PCI_VENDOR_MASK) << PCI_VENDOR_SHIFT) | \\\n\t (((pid) & PCI_PRODUCT_MASK) << PCI_PRODUCT_SHIFT))\n\n/*\n * Command and status register.\n */\n#define\tPCI_COMMAND_STATUS_REG\t\t\t0x04\n\n#define\tPCI_COMMAND_IO_ENABLE\t\t\t0x00000001\n#define\tPCI_COMMAND_MEM_ENABLE\t\t\t0x00000002\n#define\tPCI_COMMAND_MASTER_ENABLE\t\t0x00000004\n#define\tPCI_COMMAND_SPECIAL_ENABLE\t\t0x00000008\n#define\tPCI_COMMAND_INVALIDATE_ENABLE\t\t0x00000010\n#define\tPCI_COMMAND_PALETTE_ENABLE\t\t0x00000020\n#define\tPCI_COMMAND_PARITY_ENABLE\t\t0x00000040\n#define\tPCI_COMMAND_STEPPING_ENABLE\t\t0x00000080\n#define\tPCI_COMMAND_SERR_ENABLE\t\t\t0x00000100\n#define\tPCI_COMMAND_BACKTOBACK_ENABLE\t\t0x00000200\n#define PCI_COMMAND_INTERRUPT_DISABLE\t\t0x00000400\n\n#define\tPCI_STATUS_CAPLIST_SUPPORT\t\t0x00100000\n#define\tPCI_STATUS_66MHZ_SUPPORT\t\t0x00200000\n#define\tPCI_STATUS_UDF_SUPPORT\t\t\t0x00400000\n#define\tPCI_STATUS_BACKTOBACK_SUPPORT\t\t0x00800000\n#define\tPCI_STATUS_PARITY_ERROR\t\t\t0x01000000\n#define\tPCI_STATUS_DEVSEL_FAST\t\t\t0x00000000\n#define\tPCI_STATUS_DEVSEL_MEDIUM\t\t0x02000000\n#define\tPCI_STATUS_DEVSEL_SLOW\t\t\t0x04000000\n#define\tPCI_STATUS_DEVSEL_MASK\t\t\t0x06000000\n#define\tPCI_STATUS_TARGET_TARGET_ABORT\t\t0x08000000\n#define\tPCI_STATUS_MASTER_TARGET_ABORT\t\t0x10000000\n#define\tPCI_STATUS_MASTER_ABORT\t\t\t0x20000000\n#define\tPCI_STATUS_SPECIAL_ERROR\t\t0x40000000\n#define\tPCI_STATUS_PARITY_DETECT\t\t0x80000000\n\n#define\tPCI_COMMAND_STATUS_BITS \\\n    (\"\\020\\01IO\\02MEM\\03MASTER\\04SPECIAL\\05INVALIDATE\\06PALETTE\\07PARITY\"\\\n     \"\\010STEPPING\\011SERR\\012BACKTOBACK\\025CAPLIST\\026CLK66\\027UDF\"\\\n     \"\\030BACK2BACK_STAT\\031PARITY_STAT\\032DEVSEL_MEDIUM\\033DEVSEL_SLOW\"\\\n     \"\\034TARGET_TARGET_ABORT\\035MASTER_TARGET_ABORT\\036MASTER_ABORT\"\\\n     \"\\037SPECIAL_ERROR\\040PARITY_DETECT\")\n/*\n * PCI Class and Revision Register; defines type and revision of device.\n */\n#define\tPCI_CLASS_REG\t\t\t0x08\n\ntypedef u_int8_t pci_class_t;\ntypedef u_int8_t pci_subclass_t;\ntypedef u_int8_t pci_interface_t;\ntypedef u_int8_t pci_revision_t;\n\n#define\tPCI_CLASS_SHIFT\t\t\t\t24\n#define\tPCI_CLASS_MASK\t\t\t\t0xff\n#define\tPCI_CLASS(cr) \\\n\t    (((cr) >> PCI_CLASS_SHIFT) & PCI_CLASS_MASK)\n\n#define\tPCI_SUBCLASS_SHIFT\t\t\t16\n#define\tPCI_SUBCLASS_MASK\t\t\t0xff\n#define\tPCI_SUBCLASS(cr) \\\n\t    (((cr) >> PCI_SUBCLASS_SHIFT) & PCI_SUBCLASS_MASK)\n\n#define\tPCI_INTERFACE_SHIFT\t\t\t8\n#define\tPCI_INTERFACE_MASK\t\t\t0xff\n#define\tPCI_INTERFACE(cr) \\\n\t    (((cr) >> PCI_INTERFACE_SHIFT) & PCI_INTERFACE_MASK)\n\n#define\tPCI_REVISION_SHIFT\t\t\t0\n#define\tPCI_REVISION_MASK\t\t\t0xff\n#define\tPCI_REVISION(cr) \\\n\t    (((cr) >> PCI_REVISION_SHIFT) & PCI_REVISION_MASK)\n\n/* base classes */\n#define\tPCI_CLASS_PREHISTORIC\t\t\t0x00\n#define\tPCI_CLASS_MASS_STORAGE\t\t\t0x01\n#define\tPCI_CLASS_NETWORK\t\t\t0x02\n#define\tPCI_CLASS_DISPLAY\t\t\t0x03\n#define\tPCI_CLASS_MULTIMEDIA\t\t\t0x04\n#define\tPCI_CLASS_MEMORY\t\t\t0x05\n#define\tPCI_CLASS_BRIDGE\t\t\t0x06\n#define\tPCI_CLASS_COMMUNICATIONS\t\t0x07\n#define\tPCI_CLASS_SYSTEM\t\t\t0x08\n#define\tPCI_CLASS_INPUT\t\t\t\t0x09\n#define\tPCI_CLASS_DOCK\t\t\t\t0x0a\n#define\tPCI_CLASS_PROCESSOR\t\t\t0x0b\n#define\tPCI_CLASS_SERIALBUS\t\t\t0x0c\n#define\tPCI_CLASS_WIRELESS\t\t\t0x0d\n#define\tPCI_CLASS_I2O\t\t\t\t0x0e\n#define\tPCI_CLASS_SATCOM\t\t\t0x0f\n#define\tPCI_CLASS_CRYPTO\t\t\t0x10\n#define\tPCI_CLASS_DASP\t\t\t\t0x11\n#define\tPCI_CLASS_ACCELERATOR\t\t\t0x12\n#define\tPCI_CLASS_INSTRUMENTATION\t\t0x13\n#define\tPCI_CLASS_UNDEFINED\t\t\t0xff\n\n/* 0x00 prehistoric subclasses */\n#define\tPCI_SUBCLASS_PREHISTORIC_MISC\t\t0x00\n#define\tPCI_SUBCLASS_PREHISTORIC_VGA\t\t0x01\n\n/* 0x01 mass storage subclasses */\n#define\tPCI_SUBCLASS_MASS_STORAGE_SCSI\t\t0x00\n#define\tPCI_SUBCLASS_MASS_STORAGE_IDE\t\t0x01\n#define\tPCI_SUBCLASS_MASS_STORAGE_FLOPPY\t0x02\n#define\tPCI_SUBCLASS_MASS_STORAGE_IPI\t\t0x03\n#define\tPCI_SUBCLASS_MASS_STORAGE_RAID\t\t0x04\n#define\tPCI_SUBCLASS_MASS_STORAGE_ATA\t\t0x05\n#define\tPCI_SUBCLASS_MASS_STORAGE_SATA\t\t0x06\n#define\t PCI_INTERFACE_SATA_AHCI10\t\t0x01\n#define\tPCI_SUBCLASS_MASS_STORAGE_SAS\t\t0x07\n#define\tPCI_SUBCLASS_MASS_STORAGE_NVM\t\t0x08\n#define\tPCI_SUBCLASS_MASS_STORAGE_UFS\t\t0x09\n#define\tPCI_SUBCLASS_MASS_STORAGE_MISC\t\t0x80\n\n/* 0x02 network subclasses */\n#define\tPCI_SUBCLASS_NETWORK_ETHERNET\t\t0x00\n#define\tPCI_SUBCLASS_NETWORK_TOKENRING\t\t0x01\n#define\tPCI_SUBCLASS_NETWORK_FDDI\t\t0x02\n#define\tPCI_SUBCLASS_NETWORK_ATM\t\t0x03\n#define\tPCI_SUBCLASS_NETWORK_ISDN\t\t0x04\n#define\tPCI_SUBCLASS_NETWORK_WORLDFIP\t\t0x05\n#define\tPCI_SUBCLASS_NETWORK_PCIMGMULTICOMP\t0x06\n#define\tPCI_SUBCLASS_NETWORK_INFINIBAND\t\t0x07\n#define\tPCI_SUBCLASS_NETWORK_MISC\t\t0x80\n\n/* 0x03 display subclasses */\n#define\tPCI_SUBCLASS_DISPLAY_VGA\t\t0x00\n#define\tPCI_SUBCLASS_DISPLAY_XGA\t\t0x01\n#define\tPCI_SUBCLASS_DISPLAY_3D\t\t\t0x02\n#define\tPCI_SUBCLASS_DISPLAY_MISC\t\t0x80\n\n/* 0x04 multimedia subclasses */\n#define\tPCI_SUBCLASS_MULTIMEDIA_VIDEO\t\t0x00\n#define\tPCI_SUBCLASS_MULTIMEDIA_AUDIO\t\t0x01\n#define\tPCI_SUBCLASS_MULTIMEDIA_TELEPHONY\t0x02\n#define\tPCI_SUBCLASS_MULTIMEDIA_HDAUDIO\t\t0x03\n#define\tPCI_SUBCLASS_MULTIMEDIA_MISC\t\t0x80\n\n/* 0x05 memory subclasses */\n#define\tPCI_SUBCLASS_MEMORY_RAM\t\t\t0x00\n#define\tPCI_SUBCLASS_MEMORY_FLASH\t\t0x01\n#define\tPCI_SUBCLASS_MEMORY_MISC\t\t0x80\n\n/* 0x06 bridge subclasses */\n#define\tPCI_SUBCLASS_BRIDGE_HOST\t\t0x00\n#define\tPCI_SUBCLASS_BRIDGE_ISA\t\t\t0x01\n#define\tPCI_SUBCLASS_BRIDGE_EISA\t\t0x02\n#define\tPCI_SUBCLASS_BRIDGE_MC\t\t\t0x03\n#define\tPCI_SUBCLASS_BRIDGE_PCI\t\t\t0x04\n#define\tPCI_SUBCLASS_BRIDGE_PCMCIA\t\t0x05\n#define\tPCI_SUBCLASS_BRIDGE_NUBUS\t\t0x06\n#define\tPCI_SUBCLASS_BRIDGE_CARDBUS\t\t0x07\n#define\tPCI_SUBCLASS_BRIDGE_RACEWAY\t\t0x08\n#define\tPCI_SUBCLASS_BRIDGE_STPCI\t\t0x09\n#define\tPCI_SUBCLASS_BRIDGE_INFINIBAND\t\t0x0a\n#define\tPCI_SUBCLASS_BRIDGE_AS\t\t\t0x0b\n#define\tPCI_SUBCLASS_BRIDGE_MISC\t\t0x80\n\n/* 0x07 communications subclasses */\n#define\tPCI_SUBCLASS_COMMUNICATIONS_SERIAL\t0x00\n#define\tPCI_SUBCLASS_COMMUNICATIONS_PARALLEL\t0x01\n#define\tPCI_SUBCLASS_COMMUNICATIONS_MPSERIAL\t0x02\n#define\tPCI_SUBCLASS_COMMUNICATIONS_MODEM\t0x03\n#define\tPCI_SUBCLASS_COMMUNICATIONS_GPIB\t0x04\n#define\tPCI_SUBCLASS_COMMUNICATIONS_SMARTCARD\t0x05\n#define\tPCI_SUBCLASS_COMMUNICATIONS_MISC\t0x80\n\n/* 0x08 system subclasses */\n#define\tPCI_SUBCLASS_SYSTEM_PIC\t\t\t0x00\n#define\tPCI_SUBCLASS_SYSTEM_DMA\t\t\t0x01\n#define\tPCI_SUBCLASS_SYSTEM_TIMER\t\t0x02\n#define\tPCI_SUBCLASS_SYSTEM_RTC\t\t\t0x03\n#define\tPCI_SUBCLASS_SYSTEM_PCIHOTPLUG\t\t0x04\n#define\tPCI_SUBCLASS_SYSTEM_SDHC\t\t0x05\n#define\tPCI_SUBCLASS_SYSTEM_IOMMU\t\t0x06\n#define\tPCI_SUBCLASS_SYSTEM_ROOTCOMPEVENT\t0x07\n#define\tPCI_SUBCLASS_SYSTEM_MISC\t\t0x80\n\n/* 0x09 input subclasses */\n#define\tPCI_SUBCLASS_INPUT_KEYBOARD\t\t0x00\n#define\tPCI_SUBCLASS_INPUT_DIGITIZER\t\t0x01\n#define\tPCI_SUBCLASS_INPUT_MOUSE\t\t0x02\n#define\tPCI_SUBCLASS_INPUT_SCANNER\t\t0x03\n#define\tPCI_SUBCLASS_INPUT_GAMEPORT\t\t0x04\n#define\tPCI_SUBCLASS_INPUT_MISC\t\t\t0x80\n\n/* 0x0a dock subclasses */\n#define\tPCI_SUBCLASS_DOCK_GENERIC\t\t0x00\n#define\tPCI_SUBCLASS_DOCK_MISC\t\t\t0x80\n\n/* 0x0b processor subclasses */\n#define\tPCI_SUBCLASS_PROCESSOR_386\t\t0x00\n#define\tPCI_SUBCLASS_PROCESSOR_486\t\t0x01\n#define\tPCI_SUBCLASS_PROCESSOR_PENTIUM\t\t0x02\n#define\tPCI_SUBCLASS_PROCESSOR_ALPHA\t\t0x10\n#define\tPCI_SUBCLASS_PROCESSOR_POWERPC\t\t0x20\n#define\tPCI_SUBCLASS_PROCESSOR_MIPS\t\t0x30\n#define\tPCI_SUBCLASS_PROCESSOR_COPROC\t\t0x40\n\n/* 0x0c serial bus subclasses */\n#define\tPCI_SUBCLASS_SERIALBUS_FIREWIRE\t\t0x00\n#define\tPCI_SUBCLASS_SERIALBUS_ACCESS\t\t0x01\n#define\tPCI_SUBCLASS_SERIALBUS_SSA\t\t0x02\n#define\tPCI_SUBCLASS_SERIALBUS_USB\t\t0x03\n#define\tPCI_SUBCLASS_SERIALBUS_FIBER\t\t0x04\n#define\tPCI_SUBCLASS_SERIALBUS_SMBUS\t\t0x05\n#define\tPCI_SUBCLASS_SERIALBUS_INFINIBAND\t0x06\n#define\tPCI_SUBCLASS_SERIALBUS_IPMI\t\t0x07\n#define\tPCI_SUBCLASS_SERIALBUS_SERCOS\t\t0x08\n#define\tPCI_SUBCLASS_SERIALBUS_CANBUS\t\t0x09\n\n/* 0x0d wireless subclasses */\n#define\tPCI_SUBCLASS_WIRELESS_IRDA\t\t0x00\n#define\tPCI_SUBCLASS_WIRELESS_CONSUMERIR\t0x01\n#define\tPCI_SUBCLASS_WIRELESS_RF\t\t0x10\n#define\tPCI_SUBCLASS_WIRELESS_BLUETOOTH\t\t0x11\n#define\tPCI_SUBCLASS_WIRELESS_BROADBAND\t\t0x12\n#define\tPCI_SUBCLASS_WIRELESS_802_11A\t\t0x20\n#define\tPCI_SUBCLASS_WIRELESS_802_11B\t\t0x21\n#define\tPCI_SUBCLASS_WIRELESS_MISC\t\t0x80\n\n/* 0x0e I2O (Intelligent I/O) subclasses */\n#define\tPCI_SUBCLASS_I2O_STANDARD\t\t0x00\n\n/* 0x0f satellite communication subclasses */\n/*\tPCI_SUBCLASS_SATCOM_???\t\t\t0x00    / * XXX ??? */\n#define\tPCI_SUBCLASS_SATCOM_TV\t\t\t0x01\n#define\tPCI_SUBCLASS_SATCOM_AUDIO\t\t0x02\n#define\tPCI_SUBCLASS_SATCOM_VOICE\t\t0x03\n#define\tPCI_SUBCLASS_SATCOM_DATA\t\t0x04\n\n/* 0x10 encryption/decryption subclasses */\n#define\tPCI_SUBCLASS_CRYPTO_NETCOMP\t\t0x00\n#define\tPCI_SUBCLASS_CRYPTO_ENTERTAINMENT\t0x10\n#define\tPCI_SUBCLASS_CRYPTO_MISC\t\t0x80\n\n/* 0x11 data acquisition and signal processing subclasses */\n#define\tPCI_SUBCLASS_DASP_DPIO\t\t\t0x00\n#define\tPCI_SUBCLASS_DASP_TIMEFREQ\t\t0x01\n#define\tPCI_SUBCLASS_DASP_SYNC\t\t\t0x10\n#define\tPCI_SUBCLASS_DASP_MGMT\t\t\t0x20\n#define\tPCI_SUBCLASS_DASP_MISC\t\t\t0x80\n\n/*\n * PCI BIST/Header Type/Latency Timer/Cache Line Size Register.\n */\n#define\tPCI_BHLC_REG\t\t\t0x0c\n\n#define\tPCI_BIST_SHIFT\t\t\t\t24\n#define\tPCI_BIST_MASK\t\t\t\t0xff\n#define\tPCI_BIST(bhlcr) \\\n\t    (((bhlcr) >> PCI_BIST_SHIFT) & PCI_BIST_MASK)\n\n#define\tPCI_HDRTYPE_SHIFT\t\t\t16\n#define\tPCI_HDRTYPE_MASK\t\t\t0xff\n#define\tPCI_HDRTYPE(bhlcr) \\\n\t    (((bhlcr) >> PCI_HDRTYPE_SHIFT) & PCI_HDRTYPE_MASK)\n\n#define PCI_HDRTYPE_TYPE(bhlcr) \\\n\t    (PCI_HDRTYPE(bhlcr) & 0x7f)\n#define\tPCI_HDRTYPE_MULTIFN(bhlcr) \\\n\t    ((PCI_HDRTYPE(bhlcr) & 0x80) != 0)\n\n#define\tPCI_LATTIMER_SHIFT\t\t\t8\n#define\tPCI_LATTIMER_MASK\t\t\t0xff\n#define\tPCI_LATTIMER(bhlcr) \\\n\t    (((bhlcr) >> PCI_LATTIMER_SHIFT) & PCI_LATTIMER_MASK)\n\n#define\tPCI_CACHELINE_SHIFT\t\t\t0\n#define\tPCI_CACHELINE_MASK\t\t\t0xff\n#define\tPCI_CACHELINE(bhlcr) \\\n\t    (((bhlcr) >> PCI_CACHELINE_SHIFT) & PCI_CACHELINE_MASK)\n\n/* config registers for header type 0 devices */\n\n#define PCI_MAPS\t0x10\n#define PCI_CARDBUSCIS\t0x28\n#define PCI_SUBVEND_0\t0x2c\n#define PCI_SUBDEV_0\t0x2e\n#define PCI_EXROMADDR_0\t0x30\n#define PCI_INTLINE\t0x3c\n#define PCI_INTPIN\t0x3d\n#define PCI_MINGNT\t0x3e\n#define PCI_MAXLAT\t0x3f\n\n/* config registers for header type 1 devices */\n\n#define PCI_SECSTAT_1\t0 /**/\n\n#define PCI_PRIBUS_1\t0x18\n#define PCI_SECBUS_1\t0x19\n#define PCI_SUBBUS_1\t0x1a\n#define PCI_SECLAT_1\t0x1b\n\n#define PCI_IOBASEL_1\t0x1c\n#define PCI_IOLIMITL_1\t0x1d\n#define PCI_IOBASEH_1\t0 /**/\n#define PCI_IOLIMITH_1\t0 /**/\n\n#define PCI_MEMBASE_1\t0x20\n#define PCI_MEMLIMIT_1\t0x22\n\n#define PCI_PMBASEL_1\t0x24\n#define PCI_PMLIMITL_1\t0x26\n#define PCI_PMBASEH_1\t0 /**/\n#define PCI_PMLIMITH_1\t0 /**/\n\n#define PCI_BRIDGECTL_1 0 /**/\n\n#define PCI_SUBVEND_1\t0x34\n#define PCI_SUBDEV_1\t0x36\n#define PCI_EXROMADDR_1\t0x38\n\n/* config registers for header type 2 devices */\n\n#define PCI_SECSTAT_2\t0x16\n\n#define PCI_PRIBUS_2\t0x18\n#define PCI_SECBUS_2\t0x19\n#define PCI_SUBBUS_2\t0x1a\n#define PCI_SECLAT_2\t0x1b\n\n#define PCI_MEMBASE0_2\t0x1c\n#define PCI_MEMLIMIT0_2 0x20\n#define PCI_MEMBASE1_2\t0x24\n#define PCI_MEMLIMIT1_2 0x28\n#define PCI_IOBASE0_2\t0x2c\n#define PCI_IOLIMIT0_2\t0x30\n#define PCI_IOBASE1_2\t0x34\n#define PCI_IOLIMIT1_2\t0x38\n\n#define PCI_BRIDGECTL_2 0x3e\n\n#define PCI_SUBVEND_2\t0x40\n#define PCI_SUBDEV_2\t0x42\n\n#define PCI_PCCARDIF_2\t0x44\n\n/*\n * Mapping registers\n */\n#define\tPCI_MAPREG_START\t\t0x10\n#define\tPCI_MAPREG_END\t\t\t0x28\n#define\tPCI_MAPREG_PPB_END\t\t0x18\n#define\tPCI_MAPREG_PCB_END\t\t0x14\n\n#define\tPCI_MAPREG_TYPE(mr)\t\t\t\t\t\t\\\n\t    ((mr) & PCI_MAPREG_TYPE_MASK)\n#define\tPCI_MAPREG_TYPE_MASK\t\t\t0x00000001\n\n#define\tPCI_MAPREG_TYPE_MEM\t\t\t0x00000000\n#define\tPCI_MAPREG_TYPE_IO\t\t\t0x00000001\n\n#define\tPCI_MAPREG_MEM_TYPE(mr)\t\t\t\t\t\t\\\n\t    ((mr) & PCI_MAPREG_MEM_TYPE_MASK)\n#define\tPCI_MAPREG_MEM_TYPE_MASK\t\t0x00000006\n\n#define\tPCI_MAPREG_MEM_TYPE_32BIT\t\t0x00000000\n#define\tPCI_MAPREG_MEM_TYPE_32BIT_1M\t\t0x00000002\n#define\tPCI_MAPREG_MEM_TYPE_64BIT\t\t0x00000004\n\n#define _PCI_MAPREG_TYPEBITS(reg) \\\n\t(PCI_MAPREG_TYPE(reg) == PCI_MAPREG_TYPE_IO ? \\\n\treg & PCI_MAPREG_TYPE_MASK : \\\n\treg & (PCI_MAPREG_TYPE_MASK|PCI_MAPREG_MEM_TYPE_MASK))\n\n#define\tPCI_MAPREG_MEM_PREFETCHABLE(mr)\t\t\t\t\t\\\n\t    (((mr) & PCI_MAPREG_MEM_PREFETCHABLE_MASK) != 0)\n#define\tPCI_MAPREG_MEM_PREFETCHABLE_MASK\t0x00000008\n\n#define\tPCI_MAPREG_MEM_ADDR(mr)\t\t\t\t\t\t\\\n\t    ((mr) & PCI_MAPREG_MEM_ADDR_MASK)\n#define\tPCI_MAPREG_MEM_SIZE(mr)\t\t\t\t\t\t\\\n\t    (PCI_MAPREG_MEM_ADDR(mr) & -PCI_MAPREG_MEM_ADDR(mr))\n#define\tPCI_MAPREG_MEM_ADDR_MASK\t\t0xfffffff0\n\n#define\tPCI_MAPREG_MEM64_ADDR(mr)\t\t\t\t\t\\\n\t    ((mr) & PCI_MAPREG_MEM64_ADDR_MASK)\n#define\tPCI_MAPREG_MEM64_SIZE(mr)\t\t\t\t\t\\\n\t    (PCI_MAPREG_MEM64_ADDR(mr) & -PCI_MAPREG_MEM64_ADDR(mr))\n#define\tPCI_MAPREG_MEM64_ADDR_MASK\t\t0xfffffffffffffff0ULL\n\n#define\tPCI_MAPREG_IO_ADDR(mr)\t\t\t\t\t\t\\\n\t    ((mr) & PCI_MAPREG_IO_ADDR_MASK)\n#define\tPCI_MAPREG_IO_SIZE(mr)\t\t\t\t\t\t\\\n\t    (PCI_MAPREG_IO_ADDR(mr) & -PCI_MAPREG_IO_ADDR(mr))\n#define\tPCI_MAPREG_IO_ADDR_MASK\t\t\t0xfffffffe\n\n/*\n * Cardbus CIS pointer (PCI rev. 2.1)\n */\n#define PCI_CARDBUS_CIS_REG 0x28\n\n/*\n * Subsystem identification register; contains a vendor ID and a device ID.\n * Types/macros for PCI_ID_REG apply.\n * (PCI rev. 2.1)\n */\n#define PCI_SUBSYS_ID_REG 0x2c\n\n/*\n * Expansion ROM Base Address register\n * (PCI rev. 2.0)\n */\n#define PCI_ROM_REG 0x30\n\n#define PCI_ROM_ENABLE\t\t\t0x00000001\n#define PCI_ROM_ADDR_MASK\t\t0xfffff800\n#define PCI_ROM_ADDR(mr)\t\t\t\t\t\t\\\n\t    ((mr) & PCI_ROM_ADDR_MASK)\n#define PCI_ROM_SIZE(mr)\t\t\t\t\t\t\\\n\t    (PCI_ROM_ADDR(mr) & -PCI_ROM_ADDR(mr))\n\n/*\n * capabilities link list (PCI rev. 2.2)\n */\n#define PCI_CAPLISTPTR_REG\t\t0x34\t/* header type 0 */\n#define PCI_CARDBUS_CAPLISTPTR_REG\t0x14\t/* header type 2 */\n#define PCI_CAPLIST_PTR(cpr) ((cpr) & 0xff)\n#define PCI_CAPLIST_NEXT(cr) (((cr) >> 8) & 0xff)\n#define PCI_CAPLIST_CAP(cr) ((cr) & 0xff)\n\n#define PCI_CAP_RESERVED\t0x00\n#define PCI_CAP_PWRMGMT\t\t0x01\n#define PCI_CAP_AGP\t\t0x02\n#define PCI_CAP_VPD\t\t0x03\n#define PCI_CAP_SLOTID\t\t0x04\n#define PCI_CAP_MSI\t\t0x05\n#define PCI_CAP_CPCI_HOTSWAP\t0x06\n#define PCI_CAP_PCIX\t\t0x07\n#define PCI_CAP_HT\t\t0x08\n#define PCI_CAP_VENDSPEC\t0x09\n#define PCI_CAP_DEBUGPORT\t0x0a\n#define PCI_CAP_CPCI_RSRCCTL\t0x0b\n#define PCI_CAP_HOTPLUG\t\t0x0c\n#define PCI_CAP_AGP8\t\t0x0e\n#define PCI_CAP_SECURE\t\t0x0f\n#define PCI_CAP_PCIEXPRESS     \t0x10\n#define PCI_CAP_MSIX\t\t0x11\n#define PCI_CAP_SATA\t\t0x12\n\n/*\n * Vital Product Data; access via capability pointer (PCI rev 2.2).\n */\n#define\tPCI_VPD_ADDRESS_MASK\t0x7fff\n#define\tPCI_VPD_ADDRESS_SHIFT\t16\n#define\tPCI_VPD_ADDRESS(ofs)\t\\\n\t(((ofs) & PCI_VPD_ADDRESS_MASK) << PCI_VPD_ADDRESS_SHIFT)\n#define\tPCI_VPD_DATAREG(ofs)\t((ofs) + 4)\n#define\tPCI_VPD_OPFLAG\t\t0x80000000\n\n/*\n * Message Signaled Interrups; access via capability pointer.\n */\n#define PCI_MSI_MC\t\t0x00\n#define PCI_MSI_MC_C64\t\t0x00800000\n#define PCI_MSI_MC_MME\t\t0x00700000\n#define PCI_MSI_MC_MMC\t\t0x000e0000\n#define PCI_MSI_MC_MSIE\t\t0x00010000\n#define PCI_MSI_MA\t\t0x04\n#define PCI_MSI_MAU32\t\t0x08\n#define PCI_MSI_MD32\t\t0x08\n#define PCI_MSI_MD64\t\t0x0c\n\n/*\n * Power Management Control Status Register; access via capability pointer.\n */\n#define PCI_PMCSR\t\t0x04\n#define PCI_PMCSR_STATE_MASK\t0x0003\n#define PCI_PMCSR_STATE_D0\t0x0000\n#define PCI_PMCSR_STATE_D1\t0x0001\n#define PCI_PMCSR_STATE_D2\t0x0002\n#define PCI_PMCSR_STATE_D3\t0x0003\n#define PCI_PMCSR_PME_STATUS\t0x8000\n#define PCI_PMCSR_PME_EN\t0x0100\n\n/*\n * HyperTransport; access via capability pointer.\n */\n#define PCI_HT_CAP(cr) ((((cr) >> 27) < 0x08) ? \\\n    (((cr) >> 27) & 0x1c) : (((cr) >> 27) & 0x1f))\n\n#define PCI_HT_CAP_SLAVE\t0x00\n#define PCI_HT_CAP_HOST\t\t0x04\n#define PCI_HT_CAP_INTR\t\t0x10\n#define PCI_HT_CAP_MSI\t\t0x15\n\n#define PCI_HT_MSI_ENABLED\t0x00010000\n#define PCI_HT_MSI_FIXED\t0x00020000\n\n#define PCI_HT_MSI_FIXED_ADDR\t0xfee00000UL\n\n#define PCI_HT_MSI_ADDR\t\t0x04\n#define PCI_HT_MSI_ADDR_HI32\t0x08\n\n#define PCI_HT_INTR_DATA\t0x04\n\n/*\n * PCI Express; access via capability pointer.\n */\n#define PCI_PCIE_XCAP\t\t0x00\n#define PCI_PCIE_XCAP_SI\t0x01000000\n#define PCI_PCIE_XCAP_VER(x)\t(((x) >> 16) & 0x0f)\n#define PCI_PCIE_DCAP\t\t0x04\n#define PCI_PCIE_DCSR\t\t0x08\n#define PCI_PCIE_DCSR_ERO\t0x00000010\n#define PCI_PCIE_DCSR_ENS\t0x00000800\n#define PCI_PCIE_DCSR_MPS\t0x00007000\n#define PCI_PCIE_DCSR_CEE\t0x00010000\n#define PCI_PCIE_DCSR_NFE\t0x00020000\n#define PCI_PCIE_DCSR_FEE\t0x00040000\n#define PCI_PCIE_DCSR_URE\t0x00080000\n#define PCI_PCIE_LCAP\t\t0x0c\n#define PCI_PCIE_LCSR\t\t0x10\n#define PCI_PCIE_LCSR_ASPM_L0S\t0x00000001\n#define PCI_PCIE_LCSR_ASPM_L1\t0x00000002\n#define PCI_PCIE_LCSR_ES\t0x00000080\n#define PCI_PCIE_LCSR_ECPM\t0x00000100\n#define PCI_PCIE_SLCAP\t\t0x14\n#define PCI_PCIE_SLCAP_ABP\t0x00000001\n#define PCI_PCIE_SLCAP_PCP\t0x00000002\n#define PCI_PCIE_SLCAP_MSP\t0x00000004\n#define PCI_PCIE_SLCAP_AIP\t0x00000008\n#define PCI_PCIE_SLCAP_PIP\t0x00000010\n#define PCI_PCIE_SLCAP_HPS\t0x00000020\n#define PCI_PCIE_SLCAP_HPC\t0x00000040\n#define PCI_PCIE_SLCSR\t\t0x18\n#define PCI_PCIE_SLCSR_ABE\t0x00000001\n#define PCI_PCIE_SLCSR_PFE\t0x00000002\n#define PCI_PCIE_SLCSR_MSE\t0x00000004\n#define PCI_PCIE_SLCSR_PDE\t0x00000008\n#define PCI_PCIE_SLCSR_CCE\t0x00000010\n#define PCI_PCIE_SLCSR_HPE\t0x00000020\n#define PCI_PCIE_SLCSR_ABP\t0x00010000\n#define PCI_PCIE_SLCSR_PFD\t0x00020000\n#define PCI_PCIE_SLCSR_MSC\t0x00040000\n#define PCI_PCIE_SLCSR_PDC\t0x00080000\n#define PCI_PCIE_SLCSR_CC\t0x00100000\n#define PCI_PCIE_SLCSR_MS\t0x00200000\n#define PCI_PCIE_SLCSR_PDS\t0x00400000\n#define PCI_PCIE_SLCSR_LACS\t0x01000000\n#define PCI_PCIE_RCSR\t\t0x1c\n#define PCI_PCIE_DCSR2        0x28\n#define PCI_PCIE_DCSR2_LTREN    0x00000400\n#define PCI_PCIE_LCAP2        0x2c\n#define PCI_PCIE_LCSR2        0x30\n#define PCI_PCIE_LCSR2_TLS    0x0000000f\n#define PCI_PCIE_LCSR2_TLS_2_5    0x00000001\n#define PCI_PCIE_LCSR2_TLS_5    0x00000002\n#define PCI_PCIE_LCSR2_TLS_8    0x00000003\n#define PCI_PCIE_LCSR2_TLS_16    0x00000004\n#define PCI_PCIE_LCSR2_TLS_32    0x00000005\n\n/*\n * PCI Express; enhanced capabilities\n */\n#define PCI_PCIE_ECAP\t\t0x100\n#define\tPCI_PCIE_ECAP_ID(x)\t(((x) & 0x0000ffff))\n#define PCI_PCIE_ECAP_VER(x)\t(((x) >> 16) & 0x0f)\n#define\tPCI_PCIE_ECAP_NEXT(x)\t(((x) >> 20) & 0xffc)\n#define PCI_PCIE_ECAP_LAST\t0x0\n\n/*\n * Extended Message Signaled Interrups; access via capability pointer.\n */\n#define PCI_MSIX_MC_MSIXE\t0x80000000\n#define PCI_MSIX_MC_FM\t\t0x40000000\n#define PCI_MSIX_MC_TBLSZ_MASK\t0x07ff0000\n#define PCI_MSIX_MC_TBLSZ_SHIFT\t16\n#define PCI_MSIX_MC_TBLSZ(reg)\t\\\n\t(((reg) & PCI_MSIX_MC_TBLSZ_MASK) >> PCI_MSIX_MC_TBLSZ_SHIFT)\n#define PCI_MSIX_TABLE\t\t0x04\n#define  PCI_MSIX_TABLE_BIR\t0x00000007\n#define  PCI_MSIX_TABLE_OFF\t~(PCI_MSIX_TABLE_BIR)\n\n#define PCI_MSIX_MA(i)\t\t((i) * 16 + 0)\n#define PCI_MSIX_MAU32(i)\t((i) * 16 + 4)\n#define PCI_MSIX_MD(i)\t\t((i) * 16 + 8)\n#define PCI_MSIX_VC(i)\t\t((i) * 16 + 12)\n#define  PCI_MSIX_VC_MASK\t0x00000001\n\n/*\n * Interrupt Configuration Register; contains interrupt pin and line.\n */\n#define\tPCI_INTERRUPT_REG\t\t0x3c\n\ntypedef u_int8_t pci_intr_pin_t;\ntypedef u_int8_t pci_intr_line_t;\n\n#define\tPCI_INTERRUPT_PIN_SHIFT\t\t\t8\n#define\tPCI_INTERRUPT_PIN_MASK\t\t\t0xff\n#define\tPCI_INTERRUPT_PIN(icr) \\\n\t    (((icr) >> PCI_INTERRUPT_PIN_SHIFT) & PCI_INTERRUPT_PIN_MASK)\n\n#define\tPCI_INTERRUPT_LINE_SHIFT\t\t0\n#define\tPCI_INTERRUPT_LINE_MASK\t\t\t0xff\n#define\tPCI_INTERRUPT_LINE(icr) \\\n\t    (((icr) >> PCI_INTERRUPT_LINE_SHIFT) & PCI_INTERRUPT_LINE_MASK)\n\n#define\tPCI_MIN_GNT_SHIFT\t\t\t16\n#define\tPCI_MIN_GNT_MASK\t\t\t0xff\n#define\tPCI_MIN_GNT(icr) \\\n\t    (((icr) >> PCI_MIN_GNT_SHIFT) & PCI_MIN_GNT_MASK)\n\n#define\tPCI_MAX_LAT_SHIFT\t\t\t24\n#define\tPCI_MAX_LAT_MASK\t\t\t0xff\n#define\tPCI_MAX_LAT(icr) \\\n\t    (((icr) >> PCI_MAX_LAT_SHIFT) & PCI_MAX_LAT_MASK)\n\n#define\tPCI_INTERRUPT_PIN_NONE\t\t\t0x00\n#define\tPCI_INTERRUPT_PIN_A\t\t\t0x01\n#define\tPCI_INTERRUPT_PIN_B\t\t\t0x02\n#define\tPCI_INTERRUPT_PIN_C\t\t\t0x03\n#define\tPCI_INTERRUPT_PIN_D\t\t\t0x04\n#define\tPCI_INTERRUPT_PIN_MAX\t\t\t0x04\n\n/*\n * Vital Product Data resource tags.\n */\nstruct pci_vpd_smallres {\n\tuint8_t\t\tvpdres_byte0;\t\t/* length of data + tag */\n\t/* Actual data. */\n} __packed;\n\nstruct pci_vpd_largeres {\n\tuint8_t\t\tvpdres_byte0;\n\tuint8_t\t\tvpdres_len_lsb;\t\t/* length of data only */\n\tuint8_t\t\tvpdres_len_msb;\n\t/* Actual data. */\n} __packed;\n\n#define\tPCI_VPDRES_ISLARGE(x)\t\t\t((x) & 0x80)\n\n#define\tPCI_VPDRES_SMALL_LENGTH(x)\t\t((x) & 0x7)\n#define\tPCI_VPDRES_SMALL_NAME(x)\t\t(((x) >> 3) & 0xf)\n\n#define\tPCI_VPDRES_LARGE_NAME(x)\t\t((x) & 0x7f)\n\n#define\tPCI_VPDRES_TYPE_COMPATIBLE_DEVICE_ID\t0x3\t/* small */\n#define\tPCI_VPDRES_TYPE_VENDOR_DEFINED\t\t0xe\t/* small */\n#define\tPCI_VPDRES_TYPE_END_TAG\t\t\t0xf\t/* small */\n\n#define\tPCI_VPDRES_TYPE_IDENTIFIER_STRING\t0x02\t/* large */\n#define\tPCI_VPDRES_TYPE_VPD\t\t\t0x10\t/* large */\n\nstruct pci_vpd {\n\tuint8_t\t\tvpd_key0;\n\tuint8_t\t\tvpd_key1;\n\tuint8_t\t\tvpd_len;\t\t/* length of data only */\n\t/* Actual data. */\n} __packed;\n\n/*\n * Recommended VPD fields:\n *\n *\tPN\t\tPart number of assembly\n *\tFN\t\tFRU part number\n *\tEC\t\tEC level of assembly\n *\tMN\t\tManufacture ID\n *\tSN\t\tSerial Number\n *\n * Conditionally recommended VPD fields:\n *\n *\tLI\t\tLoad ID\n *\tRL\t\tROM Level\n *\tRM\t\tAlterable ROM Level\n *\tNA\t\tNetwork Address\n *\tDD\t\tDevice Driver Level\n *\tDG\t\tDiagnostic Level\n *\tLL\t\tLoadable Microcode Level\n *\tVI\t\tVendor ID/Device ID\n *\tFU\t\tFunction Number\n *\tSI\t\tSubsystem Vendor ID/Subsystem ID\n *\n * Additional VPD fields:\n *\n *\tZ0-ZZ\t\tUser/Product Specific\n */\n\n#endif /* _DEV_PCI_PCIREG_H_ */\n"
  },
  {
    "path": "itl80211/openbsd/sys/timeout.h",
    "content": "\n/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n/*\t$OpenBSD: timeout.h,v 1.29 2019/07/12 00:04:59 cheloha Exp $\t*/\n/*\n * Copyright (c) 2000-2001 Artur Grabowski <art@openbsd.org>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. The name of the author may not be used to endorse or promote products\n *    derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,\n * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\n * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL\n * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\n * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef _SYS_TIMEOUT_H_\n#define _SYS_TIMEOUT_H_\n\n\n#include <sys/param.h>\n#include <sys/systm.h>\n#include <sys/queue.h>            /* _Q_INVALIDATE */\n#include <sys/sysctl.h>\n#include <sys/_buf.h>\n#include <sys/kernel.h>\n\n#define _KERNEL\n#include <sys/CTimeout.hpp>\n#include <IOKit/IOTimerEventSource.h>\n#include <IOKit/IOWorkLoop.h>\n#include <IOKit/IOLocks.h>\n#include <libkern/c++/OSObject.h>\n\nvoid initTimeout(IOWorkLoop *workloop);\nvoid releaseTimeout();\nint splnet();\nvoid splx(int s);\nvoid timeout_set(CTimeout **t, void (*fn)(void *), void *arg);\nint timeout_add_msec(CTimeout **to, int msecs);\nint timeout_add_sec(CTimeout **to, int secs);\nint timeout_add_usec(CTimeout **to, int usecs);\nint timeout_del(CTimeout **to);\nint timeout_pending(CTimeout **to);\nint timeout_free(CTimeout **to);\n\nint timeout_initialized(CTimeout **to);\n\n#endif\t/* _SYS_TIMEOUT_H_ */\n"
  },
  {
    "path": "itl80211/openbsd/sys/tree.h",
    "content": "/*\t$OpenBSD: tree.h,v 1.29 2017/07/30 19:27:20 deraadt Exp $\t*/\n/*\n * Copyright 2002 Niels Provos <provos@citi.umich.edu>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef\t_SYS_TREE_H_\n#define\t_SYS_TREE_H_\n\n#include <sys/_null.h>\n\n/*\n * This file defines data structures for different types of trees:\n * splay trees and red-black trees.\n *\n * A splay tree is a self-organizing data structure.  Every operation\n * on the tree causes a splay to happen.  The splay moves the requested\n * node to the root of the tree and partly rebalances it.\n *\n * This has the benefit that request locality causes faster lookups as\n * the requested nodes move to the top of the tree.  On the other hand,\n * every lookup causes memory writes.\n *\n * The Balance Theorem bounds the total access time for m operations\n * and n inserts on an initially empty tree as O((m + n)lg n).  The\n * amortized cost for a sequence of m accesses to a splay tree is O(lg n);\n *\n * A red-black tree is a binary search tree with the node color as an\n * extra attribute.  It fulfills a set of conditions:\n *\t- every search path from the root to a leaf consists of the\n *\t  same number of black nodes,\n *\t- each red node (except for the root) has a black parent,\n *\t- each leaf node is black.\n *\n * Every operation on a red-black tree is bounded as O(lg n).\n * The maximum height of a red-black tree is 2lg (n+1).\n */\n\n#define SPLAY_HEAD(name, type)\t\t\t\t\t\t\\\nstruct name {\t\t\t\t\t\t\t\t\\\n\tstruct type *sph_root; /* root of the tree */\t\t\t\\\n}\n\n#define SPLAY_INITIALIZER(root)\t\t\t\t\t\t\\\n\t{ NULL }\n\n#define SPLAY_INIT(root) do {\t\t\t\t\t\t\\\n\t(root)->sph_root = NULL;\t\t\t\t\t\\\n} while (0)\n\n#define SPLAY_ENTRY(type)\t\t\t\t\t\t\\\nstruct {\t\t\t\t\t\t\t\t\\\n\tstruct type *spe_left; /* left element */\t\t\t\\\n\tstruct type *spe_right; /* right element */\t\t\t\\\n}\n\n#define SPLAY_LEFT(elm, field)\t\t(elm)->field.spe_left\n#define SPLAY_RIGHT(elm, field)\t\t(elm)->field.spe_right\n#define SPLAY_ROOT(head)\t\t(head)->sph_root\n#define SPLAY_EMPTY(head)\t\t(SPLAY_ROOT(head) == NULL)\n\n/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */\n#define SPLAY_ROTATE_RIGHT(head, tmp, field) do {\t\t\t\\\n\tSPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field);\t\\\n\tSPLAY_RIGHT(tmp, field) = (head)->sph_root;\t\t\t\\\n\t(head)->sph_root = tmp;\t\t\t\t\t\t\\\n} while (0)\n\n#define SPLAY_ROTATE_LEFT(head, tmp, field) do {\t\t\t\\\n\tSPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field);\t\\\n\tSPLAY_LEFT(tmp, field) = (head)->sph_root;\t\t\t\\\n\t(head)->sph_root = tmp;\t\t\t\t\t\t\\\n} while (0)\n\n#define SPLAY_LINKLEFT(head, tmp, field) do {\t\t\t\t\\\n\tSPLAY_LEFT(tmp, field) = (head)->sph_root;\t\t\t\\\n\ttmp = (head)->sph_root;\t\t\t\t\t\t\\\n\t(head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\t\t\\\n} while (0)\n\n#define SPLAY_LINKRIGHT(head, tmp, field) do {\t\t\t\t\\\n\tSPLAY_RIGHT(tmp, field) = (head)->sph_root;\t\t\t\\\n\ttmp = (head)->sph_root;\t\t\t\t\t\t\\\n\t(head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\t\\\n} while (0)\n\n#define SPLAY_ASSEMBLE(head, node, left, right, field) do {\t\t\\\n\tSPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field);\t\\\n\tSPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\\\n\tSPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field);\t\\\n\tSPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field);\t\\\n} while (0)\n\n/* Generates prototypes and inline functions */\n\n#define SPLAY_PROTOTYPE(name, type, field, cmp)\t\t\t\t\\\nvoid name##_SPLAY(struct name *, struct type *);\t\t\t\\\nvoid name##_SPLAY_MINMAX(struct name *, int);\t\t\t\t\\\nstruct type *name##_SPLAY_INSERT(struct name *, struct type *);\t\t\\\nstruct type *name##_SPLAY_REMOVE(struct name *, struct type *);\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n/* Finds the node with the same key as elm */\t\t\t\t\\\nstatic __unused __inline struct type *\t\t\t\t\t\\\nname##_SPLAY_FIND(struct name *head, struct type *elm)\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tif (SPLAY_EMPTY(head))\t\t\t\t\t\t\\\n\t\treturn(NULL);\t\t\t\t\t\t\\\n\tname##_SPLAY(head, elm);\t\t\t\t\t\\\n\tif ((cmp)(elm, (head)->sph_root) == 0)\t\t\t\t\\\n\t\treturn (head->sph_root);\t\t\t\t\\\n\treturn (NULL);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\nstatic __unused __inline struct type *\t\t\t\t\t\\\nname##_SPLAY_NEXT(struct name *head, struct type *elm)\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tname##_SPLAY(head, elm);\t\t\t\t\t\\\n\tif (SPLAY_RIGHT(elm, field) != NULL) {\t\t\t\t\\\n\t\telm = SPLAY_RIGHT(elm, field);\t\t\t\t\\\n\t\twhile (SPLAY_LEFT(elm, field) != NULL) {\t\t\\\n\t\t\telm = SPLAY_LEFT(elm, field);\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t} else\t\t\t\t\t\t\t\t\\\n\t\telm = NULL;\t\t\t\t\t\t\\\n\treturn (elm);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\nstatic __unused __inline struct type *\t\t\t\t\t\\\nname##_SPLAY_MIN_MAX(struct name *head, int val)\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tname##_SPLAY_MINMAX(head, val);\t\t\t\t\t\\\n        return (SPLAY_ROOT(head));\t\t\t\t\t\\\n}\n\n/* Main splay operation.\n * Moves node close to the key of elm to top\n */\n#define SPLAY_GENERATE(name, type, field, cmp)\t\t\t\t\\\nstruct type *\t\t\t\t\t\t\t\t\\\nname##_SPLAY_INSERT(struct name *head, struct type *elm)\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n    if (SPLAY_EMPTY(head)) {\t\t\t\t\t\t\\\n\t    SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL;\t\\\n    } else {\t\t\t\t\t\t\t\t\\\n\t    int __comp;\t\t\t\t\t\t\t\\\n\t    name##_SPLAY(head, elm);\t\t\t\t\t\\\n\t    __comp = (cmp)(elm, (head)->sph_root);\t\t\t\\\n\t    if(__comp < 0) {\t\t\t\t\t\t\\\n\t\t    SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\\\n\t\t    SPLAY_RIGHT(elm, field) = (head)->sph_root;\t\t\\\n\t\t    SPLAY_LEFT((head)->sph_root, field) = NULL;\t\t\\\n\t    } else if (__comp > 0) {\t\t\t\t\t\\\n\t\t    SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\\\n\t\t    SPLAY_LEFT(elm, field) = (head)->sph_root;\t\t\\\n\t\t    SPLAY_RIGHT((head)->sph_root, field) = NULL;\t\\\n\t    } else\t\t\t\t\t\t\t\\\n\t\t    return ((head)->sph_root);\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    (head)->sph_root = (elm);\t\t\t\t\t\t\\\n    return (NULL);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\nstruct type *\t\t\t\t\t\t\t\t\\\nname##_SPLAY_REMOVE(struct name *head, struct type *elm)\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tstruct type *__tmp;\t\t\t\t\t\t\\\n\tif (SPLAY_EMPTY(head))\t\t\t\t\t\t\\\n\t\treturn (NULL);\t\t\t\t\t\t\\\n\tname##_SPLAY(head, elm);\t\t\t\t\t\\\n\tif ((cmp)(elm, (head)->sph_root) == 0) {\t\t\t\\\n\t\tif (SPLAY_LEFT((head)->sph_root, field) == NULL) {\t\\\n\t\t\t(head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\\\n\t\t} else {\t\t\t\t\t\t\\\n\t\t\t__tmp = SPLAY_RIGHT((head)->sph_root, field);\t\\\n\t\t\t(head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\\\n\t\t\tname##_SPLAY(head, elm);\t\t\t\\\n\t\t\tSPLAY_RIGHT((head)->sph_root, field) = __tmp;\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t\treturn (elm);\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\treturn (NULL);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\nvoid\t\t\t\t\t\t\t\t\t\\\nname##_SPLAY(struct name *head, struct type *elm)\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tstruct type __node, *__left, *__right, *__tmp;\t\t\t\\\n\tint __comp;\t\t\t\t\t\t\t\\\n\\\n\tSPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\\\n\t__left = __right = &__node;\t\t\t\t\t\\\n\\\n\twhile ((__comp = (cmp)(elm, (head)->sph_root))) {\t\t\\\n\t\tif (__comp < 0) {\t\t\t\t\t\\\n\t\t\t__tmp = SPLAY_LEFT((head)->sph_root, field);\t\\\n\t\t\tif (__tmp == NULL)\t\t\t\t\\\n\t\t\t\tbreak;\t\t\t\t\t\\\n\t\t\tif ((cmp)(elm, __tmp) < 0){\t\t\t\\\n\t\t\t\tSPLAY_ROTATE_RIGHT(head, __tmp, field);\t\\\n\t\t\t\tif (SPLAY_LEFT((head)->sph_root, field) == NULL)\\\n\t\t\t\t\tbreak;\t\t\t\t\\\n\t\t\t}\t\t\t\t\t\t\\\n\t\t\tSPLAY_LINKLEFT(head, __right, field);\t\t\\\n\t\t} else if (__comp > 0) {\t\t\t\t\\\n\t\t\t__tmp = SPLAY_RIGHT((head)->sph_root, field);\t\\\n\t\t\tif (__tmp == NULL)\t\t\t\t\\\n\t\t\t\tbreak;\t\t\t\t\t\\\n\t\t\tif ((cmp)(elm, __tmp) > 0){\t\t\t\\\n\t\t\t\tSPLAY_ROTATE_LEFT(head, __tmp, field);\t\\\n\t\t\t\tif (SPLAY_RIGHT((head)->sph_root, field) == NULL)\\\n\t\t\t\t\tbreak;\t\t\t\t\\\n\t\t\t}\t\t\t\t\t\t\\\n\t\t\tSPLAY_LINKRIGHT(head, __left, field);\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\tSPLAY_ASSEMBLE(head, &__node, __left, __right, field);\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n/* Splay with either the minimum or the maximum element\t\t\t\\\n * Used to find minimum or maximum element in tree.\t\t\t\\\n */\t\t\t\t\t\t\t\t\t\\\nvoid name##_SPLAY_MINMAX(struct name *head, int __comp) \\\n{\t\t\t\t\t\t\t\t\t\\\n\tstruct type __node, *__left, *__right, *__tmp;\t\t\t\\\n\\\n\tSPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\\\n\t__left = __right = &__node;\t\t\t\t\t\\\n\\\n\twhile (1) {\t\t\t\t\t\t\t\\\n\t\tif (__comp < 0) {\t\t\t\t\t\\\n\t\t\t__tmp = SPLAY_LEFT((head)->sph_root, field);\t\\\n\t\t\tif (__tmp == NULL)\t\t\t\t\\\n\t\t\t\tbreak;\t\t\t\t\t\\\n\t\t\tif (__comp < 0){\t\t\t\t\\\n\t\t\t\tSPLAY_ROTATE_RIGHT(head, __tmp, field);\t\\\n\t\t\t\tif (SPLAY_LEFT((head)->sph_root, field) == NULL)\\\n\t\t\t\t\tbreak;\t\t\t\t\\\n\t\t\t}\t\t\t\t\t\t\\\n\t\t\tSPLAY_LINKLEFT(head, __right, field);\t\t\\\n\t\t} else if (__comp > 0) {\t\t\t\t\\\n\t\t\t__tmp = SPLAY_RIGHT((head)->sph_root, field);\t\\\n\t\t\tif (__tmp == NULL)\t\t\t\t\\\n\t\t\t\tbreak;\t\t\t\t\t\\\n\t\t\tif (__comp > 0) {\t\t\t\t\\\n\t\t\t\tSPLAY_ROTATE_LEFT(head, __tmp, field);\t\\\n\t\t\t\tif (SPLAY_RIGHT((head)->sph_root, field) == NULL)\\\n\t\t\t\t\tbreak;\t\t\t\t\\\n\t\t\t}\t\t\t\t\t\t\\\n\t\t\tSPLAY_LINKRIGHT(head, __left, field);\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\tSPLAY_ASSEMBLE(head, &__node, __left, __right, field);\t\t\\\n}\n\n#define SPLAY_NEGINF\t-1\n#define SPLAY_INF\t1\n\n#define SPLAY_INSERT(name, x, y)\tname##_SPLAY_INSERT(x, y)\n#define SPLAY_REMOVE(name, x, y)\tname##_SPLAY_REMOVE(x, y)\n#define SPLAY_FIND(name, x, y)\t\tname##_SPLAY_FIND(x, y)\n#define SPLAY_NEXT(name, x, y)\t\tname##_SPLAY_NEXT(x, y)\n#define SPLAY_MIN(name, x)\t\t(SPLAY_EMPTY(x) ? NULL\t\\\n\t\t\t\t\t: name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF))\n#define SPLAY_MAX(name, x)\t\t(SPLAY_EMPTY(x) ? NULL\t\\\n\t\t\t\t\t: name##_SPLAY_MIN_MAX(x, SPLAY_INF))\n\n#define SPLAY_FOREACH(x, name, head)\t\t\t\t\t\\\n\tfor ((x) = SPLAY_MIN(name, head);\t\t\t\t\\\n\t     (x) != NULL;\t\t\t\t\t\t\\\n\t     (x) = SPLAY_NEXT(name, head, x))\n\n/* Macros that define a red-black tree */\n#define RB_HEAD(name, type)\t\t\t\t\t\t\\\nstruct name {\t\t\t\t\t\t\t\t\\\n\tstruct type *rbh_root; /* root of the tree */\t\t\t\\\n}\n\n#define RB_INITIALIZER(root)\t\t\t\t\t\t\\\n\t{ NULL }\n\n#define RB_INIT(root) do {\t\t\t\t\t\t\\\n\t(root)->rbh_root = NULL;\t\t\t\t\t\\\n} while (0)\n\n#define RB_BLACK\t0\n#define RB_RED\t\t1\n#define RB_ENTRY(type)\t\t\t\t\t\t\t\\\nstruct {\t\t\t\t\t\t\t\t\\\n\tstruct type *rbe_left;\t\t/* left element */\t\t\\\n\tstruct type *rbe_right;\t\t/* right element */\t\t\\\n\tstruct type *rbe_parent;\t/* parent element */\t\t\\\n\tint rbe_color;\t\t\t/* node color */\t\t\\\n}\n\n#define RB_LEFT(elm, field)\t\t(elm)->field.rbe_left\n#define RB_RIGHT(elm, field)\t\t(elm)->field.rbe_right\n#define RB_PARENT(elm, field)\t\t(elm)->field.rbe_parent\n#define RB_COLOR(elm, field)\t\t(elm)->field.rbe_color\n#define RB_ROOT(head)\t\t\t(head)->rbh_root\n#define RB_EMPTY(head)\t\t\t(RB_ROOT(head) == NULL)\n\n#define RB_SET(elm, parent, field) do {\t\t\t\t\t\\\n\tRB_PARENT(elm, field) = parent;\t\t\t\t\t\\\n\tRB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL;\t\t\\\n\tRB_COLOR(elm, field) = RB_RED;\t\t\t\t\t\\\n} while (0)\n\n#define RB_SET_BLACKRED(black, red, field) do {\t\t\t\t\\\n\tRB_COLOR(black, field) = RB_BLACK;\t\t\t\t\\\n\tRB_COLOR(red, field) = RB_RED;\t\t\t\t\t\\\n} while (0)\n\n#ifndef RB_AUGMENT\n#define RB_AUGMENT(x)\tdo {} while (0)\n#endif\n\n#define RB_ROTATE_LEFT(head, elm, tmp, field) do {\t\t\t\\\n\t(tmp) = RB_RIGHT(elm, field);\t\t\t\t\t\\\n\tif ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field))) {\t\t\\\n\t\tRB_PARENT(RB_LEFT(tmp, field), field) = (elm);\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\tRB_AUGMENT(elm);\t\t\t\t\t\t\\\n\tif ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) {\t\t\\\n\t\tif ((elm) == RB_LEFT(RB_PARENT(elm, field), field))\t\\\n\t\t\tRB_LEFT(RB_PARENT(elm, field), field) = (tmp);\t\\\n\t\telse\t\t\t\t\t\t\t\\\n\t\t\tRB_RIGHT(RB_PARENT(elm, field), field) = (tmp);\t\\\n\t} else\t\t\t\t\t\t\t\t\\\n\t\t(head)->rbh_root = (tmp);\t\t\t\t\\\n\tRB_LEFT(tmp, field) = (elm);\t\t\t\t\t\\\n\tRB_PARENT(elm, field) = (tmp);\t\t\t\t\t\\\n\tRB_AUGMENT(tmp);\t\t\t\t\t\t\\\n\tif ((RB_PARENT(tmp, field)))\t\t\t\t\t\\\n\t\tRB_AUGMENT(RB_PARENT(tmp, field));\t\t\t\\\n} while (0)\n\n#define RB_ROTATE_RIGHT(head, elm, tmp, field) do {\t\t\t\\\n\t(tmp) = RB_LEFT(elm, field);\t\t\t\t\t\\\n\tif ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field))) {\t\t\\\n\t\tRB_PARENT(RB_RIGHT(tmp, field), field) = (elm);\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\tRB_AUGMENT(elm);\t\t\t\t\t\t\\\n\tif ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) {\t\t\\\n\t\tif ((elm) == RB_LEFT(RB_PARENT(elm, field), field))\t\\\n\t\t\tRB_LEFT(RB_PARENT(elm, field), field) = (tmp);\t\\\n\t\telse\t\t\t\t\t\t\t\\\n\t\t\tRB_RIGHT(RB_PARENT(elm, field), field) = (tmp);\t\\\n\t} else\t\t\t\t\t\t\t\t\\\n\t\t(head)->rbh_root = (tmp);\t\t\t\t\\\n\tRB_RIGHT(tmp, field) = (elm);\t\t\t\t\t\\\n\tRB_PARENT(elm, field) = (tmp);\t\t\t\t\t\\\n\tRB_AUGMENT(tmp);\t\t\t\t\t\t\\\n\tif ((RB_PARENT(tmp, field)))\t\t\t\t\t\\\n\t\tRB_AUGMENT(RB_PARENT(tmp, field));\t\t\t\\\n} while (0)\n\n/* Generates prototypes and inline functions */\n#define\tRB_PROTOTYPE(name, type, field, cmp)\t\t\t\t\\\n\tRB_PROTOTYPE_INTERNAL(name, type, field, cmp,)\n#define\tRB_PROTOTYPE_STATIC(name, type, field, cmp)\t\t\t\\\n\tRB_PROTOTYPE_INTERNAL(name, type, field, cmp, __attribute__((__unused__)) static)\n#define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr)\t\t\\\nattr void name##_RB_INSERT_COLOR(struct name *, struct type *);\t\t\\\nattr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\\\nattr struct type *name##_RB_REMOVE(struct name *, struct type *);\t\\\nattr struct type *name##_RB_INSERT(struct name *, struct type *);\t\\\nattr struct type *name##_RB_FIND(struct name *, struct type *);\t\t\\\nattr struct type *name##_RB_NFIND(struct name *, struct type *);\t\\\nattr struct type *name##_RB_NEXT(struct type *);\t\t\t\\\nattr struct type *name##_RB_PREV(struct type *);\t\t\t\\\nattr struct type *name##_RB_MINMAX(struct name *, int);\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\n/* Main rb operation.\n * Moves node close to the key of elm to top\n */\n#define\tRB_GENERATE(name, type, field, cmp)\t\t\t\t\\\n\tRB_GENERATE_INTERNAL(name, type, field, cmp,)\n#define\tRB_GENERATE_STATIC(name, type, field, cmp)\t\t\t\\\n\tRB_GENERATE_INTERNAL(name, type, field, cmp, __attribute__((__unused__)) static)\n#define RB_GENERATE_INTERNAL(name, type, field, cmp, attr)\t\t\\\nattr void\t\t\t\t\t\t\t\t\\\nname##_RB_INSERT_COLOR(struct name *head, struct type *elm)\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tstruct type *parent, *gparent, *tmp;\t\t\t\t\\\n\twhile ((parent = RB_PARENT(elm, field)) &&\t\t\t\\\n\t    RB_COLOR(parent, field) == RB_RED) {\t\t\t\\\n\t\tgparent = RB_PARENT(parent, field);\t\t\t\\\n\t\tif (parent == RB_LEFT(gparent, field)) {\t\t\\\n\t\t\ttmp = RB_RIGHT(gparent, field);\t\t\t\\\n\t\t\tif (tmp && RB_COLOR(tmp, field) == RB_RED) {\t\\\n\t\t\t\tRB_COLOR(tmp, field) = RB_BLACK;\t\\\n\t\t\t\tRB_SET_BLACKRED(parent, gparent, field);\\\n\t\t\t\telm = gparent;\t\t\t\t\\\n\t\t\t\tcontinue;\t\t\t\t\\\n\t\t\t}\t\t\t\t\t\t\\\n\t\t\tif (RB_RIGHT(parent, field) == elm) {\t\t\\\n\t\t\t\tRB_ROTATE_LEFT(head, parent, tmp, field);\\\n\t\t\t\ttmp = parent;\t\t\t\t\\\n\t\t\t\tparent = elm;\t\t\t\t\\\n\t\t\t\telm = tmp;\t\t\t\t\\\n\t\t\t}\t\t\t\t\t\t\\\n\t\t\tRB_SET_BLACKRED(parent, gparent, field);\t\\\n\t\t\tRB_ROTATE_RIGHT(head, gparent, tmp, field);\t\\\n\t\t} else {\t\t\t\t\t\t\\\n\t\t\ttmp = RB_LEFT(gparent, field);\t\t\t\\\n\t\t\tif (tmp && RB_COLOR(tmp, field) == RB_RED) {\t\\\n\t\t\t\tRB_COLOR(tmp, field) = RB_BLACK;\t\\\n\t\t\t\tRB_SET_BLACKRED(parent, gparent, field);\\\n\t\t\t\telm = gparent;\t\t\t\t\\\n\t\t\t\tcontinue;\t\t\t\t\\\n\t\t\t}\t\t\t\t\t\t\\\n\t\t\tif (RB_LEFT(parent, field) == elm) {\t\t\\\n\t\t\t\tRB_ROTATE_RIGHT(head, parent, tmp, field);\\\n\t\t\t\ttmp = parent;\t\t\t\t\\\n\t\t\t\tparent = elm;\t\t\t\t\\\n\t\t\t\telm = tmp;\t\t\t\t\\\n\t\t\t}\t\t\t\t\t\t\\\n\t\t\tRB_SET_BLACKRED(parent, gparent, field);\t\\\n\t\t\tRB_ROTATE_LEFT(head, gparent, tmp, field);\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\tRB_COLOR(head->rbh_root, field) = RB_BLACK;\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\nattr void\t\t\t\t\t\t\t\t\\\nname##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \\\n{\t\t\t\t\t\t\t\t\t\\\n\tstruct type *tmp;\t\t\t\t\t\t\\\n\twhile ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) &&\t\\\n\t    elm != RB_ROOT(head)) {\t\t\t\t\t\\\n\t\tif (RB_LEFT(parent, field) == elm) {\t\t\t\\\n\t\t\ttmp = RB_RIGHT(parent, field);\t\t\t\\\n\t\t\tif (RB_COLOR(tmp, field) == RB_RED) {\t\t\\\n\t\t\t\tRB_SET_BLACKRED(tmp, parent, field);\t\\\n\t\t\t\tRB_ROTATE_LEFT(head, parent, tmp, field);\\\n\t\t\t\ttmp = RB_RIGHT(parent, field);\t\t\\\n\t\t\t}\t\t\t\t\t\t\\\n\t\t\tif ((RB_LEFT(tmp, field) == NULL ||\t\t\\\n\t\t\t    RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\\\n\t\t\t    (RB_RIGHT(tmp, field) == NULL ||\t\t\\\n\t\t\t    RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\\\n\t\t\t\tRB_COLOR(tmp, field) = RB_RED;\t\t\\\n\t\t\t\telm = parent;\t\t\t\t\\\n\t\t\t\tparent = RB_PARENT(elm, field);\t\t\\\n\t\t\t} else {\t\t\t\t\t\\\n\t\t\t\tif (RB_RIGHT(tmp, field) == NULL ||\t\\\n\t\t\t\t    RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\\\n\t\t\t\t\tstruct type *oleft;\t\t\\\n\t\t\t\t\tif ((oleft = RB_LEFT(tmp, field)))\\\n\t\t\t\t\t\tRB_COLOR(oleft, field) = RB_BLACK;\\\n\t\t\t\t\tRB_COLOR(tmp, field) = RB_RED;\t\\\n\t\t\t\t\tRB_ROTATE_RIGHT(head, tmp, oleft, field);\\\n\t\t\t\t\ttmp = RB_RIGHT(parent, field);\t\\\n\t\t\t\t}\t\t\t\t\t\\\n\t\t\t\tRB_COLOR(tmp, field) = RB_COLOR(parent, field);\\\n\t\t\t\tRB_COLOR(parent, field) = RB_BLACK;\t\\\n\t\t\t\tif (RB_RIGHT(tmp, field))\t\t\\\n\t\t\t\t\tRB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\\\n\t\t\t\tRB_ROTATE_LEFT(head, parent, tmp, field);\\\n\t\t\t\telm = RB_ROOT(head);\t\t\t\\\n\t\t\t\tbreak;\t\t\t\t\t\\\n\t\t\t}\t\t\t\t\t\t\\\n\t\t} else {\t\t\t\t\t\t\\\n\t\t\ttmp = RB_LEFT(parent, field);\t\t\t\\\n\t\t\tif (RB_COLOR(tmp, field) == RB_RED) {\t\t\\\n\t\t\t\tRB_SET_BLACKRED(tmp, parent, field);\t\\\n\t\t\t\tRB_ROTATE_RIGHT(head, parent, tmp, field);\\\n\t\t\t\ttmp = RB_LEFT(parent, field);\t\t\\\n\t\t\t}\t\t\t\t\t\t\\\n\t\t\tif ((RB_LEFT(tmp, field) == NULL ||\t\t\\\n\t\t\t    RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\\\n\t\t\t    (RB_RIGHT(tmp, field) == NULL ||\t\t\\\n\t\t\t    RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\\\n\t\t\t\tRB_COLOR(tmp, field) = RB_RED;\t\t\\\n\t\t\t\telm = parent;\t\t\t\t\\\n\t\t\t\tparent = RB_PARENT(elm, field);\t\t\\\n\t\t\t} else {\t\t\t\t\t\\\n\t\t\t\tif (RB_LEFT(tmp, field) == NULL ||\t\\\n\t\t\t\t    RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\\\n\t\t\t\t\tstruct type *oright;\t\t\\\n\t\t\t\t\tif ((oright = RB_RIGHT(tmp, field)))\\\n\t\t\t\t\t\tRB_COLOR(oright, field) = RB_BLACK;\\\n\t\t\t\t\tRB_COLOR(tmp, field) = RB_RED;\t\\\n\t\t\t\t\tRB_ROTATE_LEFT(head, tmp, oright, field);\\\n\t\t\t\t\ttmp = RB_LEFT(parent, field);\t\\\n\t\t\t\t}\t\t\t\t\t\\\n\t\t\t\tRB_COLOR(tmp, field) = RB_COLOR(parent, field);\\\n\t\t\t\tRB_COLOR(parent, field) = RB_BLACK;\t\\\n\t\t\t\tif (RB_LEFT(tmp, field))\t\t\\\n\t\t\t\t\tRB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\\\n\t\t\t\tRB_ROTATE_RIGHT(head, parent, tmp, field);\\\n\t\t\t\telm = RB_ROOT(head);\t\t\t\\\n\t\t\t\tbreak;\t\t\t\t\t\\\n\t\t\t}\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\tif (elm)\t\t\t\t\t\t\t\\\n\t\tRB_COLOR(elm, field) = RB_BLACK;\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\nattr struct type *\t\t\t\t\t\t\t\\\nname##_RB_REMOVE(struct name *head, struct type *elm)\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tstruct type *child, *parent, *old = elm;\t\t\t\\\n\tint color;\t\t\t\t\t\t\t\\\n\tif (RB_LEFT(elm, field) == NULL)\t\t\t\t\\\n\t\tchild = RB_RIGHT(elm, field);\t\t\t\t\\\n\telse if (RB_RIGHT(elm, field) == NULL)\t\t\t\t\\\n\t\tchild = RB_LEFT(elm, field);\t\t\t\t\\\n\telse {\t\t\t\t\t\t\t\t\\\n\t\tstruct type *left;\t\t\t\t\t\\\n\t\telm = RB_RIGHT(elm, field);\t\t\t\t\\\n\t\twhile ((left = RB_LEFT(elm, field)))\t\t\t\\\n\t\t\telm = left;\t\t\t\t\t\\\n\t\tchild = RB_RIGHT(elm, field);\t\t\t\t\\\n\t\tparent = RB_PARENT(elm, field);\t\t\t\t\\\n\t\tcolor = RB_COLOR(elm, field);\t\t\t\t\\\n\t\tif (child)\t\t\t\t\t\t\\\n\t\t\tRB_PARENT(child, field) = parent;\t\t\\\n\t\tif (parent) {\t\t\t\t\t\t\\\n\t\t\tif (RB_LEFT(parent, field) == elm)\t\t\\\n\t\t\t\tRB_LEFT(parent, field) = child;\t\t\\\n\t\t\telse\t\t\t\t\t\t\\\n\t\t\t\tRB_RIGHT(parent, field) = child;\t\\\n\t\t\tRB_AUGMENT(parent);\t\t\t\t\\\n\t\t} else\t\t\t\t\t\t\t\\\n\t\t\tRB_ROOT(head) = child;\t\t\t\t\\\n\t\tif (RB_PARENT(elm, field) == old)\t\t\t\\\n\t\t\tparent = elm;\t\t\t\t\t\\\n\t\t(elm)->field = (old)->field;\t\t\t\t\\\n\t\tif (RB_PARENT(old, field)) {\t\t\t\t\\\n\t\t\tif (RB_LEFT(RB_PARENT(old, field), field) == old)\\\n\t\t\t\tRB_LEFT(RB_PARENT(old, field), field) = elm;\\\n\t\t\telse\t\t\t\t\t\t\\\n\t\t\t\tRB_RIGHT(RB_PARENT(old, field), field) = elm;\\\n\t\t\tRB_AUGMENT(RB_PARENT(old, field));\t\t\\\n\t\t} else\t\t\t\t\t\t\t\\\n\t\t\tRB_ROOT(head) = elm;\t\t\t\t\\\n\t\tRB_PARENT(RB_LEFT(old, field), field) = elm;\t\t\\\n\t\tif (RB_RIGHT(old, field))\t\t\t\t\\\n\t\t\tRB_PARENT(RB_RIGHT(old, field), field) = elm;\t\\\n\t\tif (parent) {\t\t\t\t\t\t\\\n\t\t\tleft = parent;\t\t\t\t\t\\\n\t\t\tdo {\t\t\t\t\t\t\\\n\t\t\t\tRB_AUGMENT(left);\t\t\t\\\n\t\t\t} while ((left = RB_PARENT(left, field)));\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t\tgoto color;\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\tparent = RB_PARENT(elm, field);\t\t\t\t\t\\\n\tcolor = RB_COLOR(elm, field);\t\t\t\t\t\\\n\tif (child)\t\t\t\t\t\t\t\\\n\t\tRB_PARENT(child, field) = parent;\t\t\t\\\n\tif (parent) {\t\t\t\t\t\t\t\\\n\t\tif (RB_LEFT(parent, field) == elm)\t\t\t\\\n\t\t\tRB_LEFT(parent, field) = child;\t\t\t\\\n\t\telse\t\t\t\t\t\t\t\\\n\t\t\tRB_RIGHT(parent, field) = child;\t\t\\\n\t\tRB_AUGMENT(parent);\t\t\t\t\t\\\n\t} else\t\t\t\t\t\t\t\t\\\n\t\tRB_ROOT(head) = child;\t\t\t\t\t\\\ncolor:\t\t\t\t\t\t\t\t\t\\\n\tif (color == RB_BLACK)\t\t\t\t\t\t\\\n\t\tname##_RB_REMOVE_COLOR(head, parent, child);\t\t\\\n\treturn (old);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n/* Inserts a node into the RB tree */\t\t\t\t\t\\\nattr struct type *\t\t\t\t\t\t\t\\\nname##_RB_INSERT(struct name *head, struct type *elm)\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tstruct type *tmp;\t\t\t\t\t\t\\\n\tstruct type *parent = NULL;\t\t\t\t\t\\\n\tint comp = 0;\t\t\t\t\t\t\t\\\n\ttmp = RB_ROOT(head);\t\t\t\t\t\t\\\n\twhile (tmp) {\t\t\t\t\t\t\t\\\n\t\tparent = tmp;\t\t\t\t\t\t\\\n\t\tcomp = (cmp)(elm, parent);\t\t\t\t\\\n\t\tif (comp < 0)\t\t\t\t\t\t\\\n\t\t\ttmp = RB_LEFT(tmp, field);\t\t\t\\\n\t\telse if (comp > 0)\t\t\t\t\t\\\n\t\t\ttmp = RB_RIGHT(tmp, field);\t\t\t\\\n\t\telse\t\t\t\t\t\t\t\\\n\t\t\treturn (tmp);\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\tRB_SET(elm, parent, field);\t\t\t\t\t\\\n\tif (parent != NULL) {\t\t\t\t\t\t\\\n\t\tif (comp < 0)\t\t\t\t\t\t\\\n\t\t\tRB_LEFT(parent, field) = elm;\t\t\t\\\n\t\telse\t\t\t\t\t\t\t\\\n\t\t\tRB_RIGHT(parent, field) = elm;\t\t\t\\\n\t\tRB_AUGMENT(parent);\t\t\t\t\t\\\n\t} else\t\t\t\t\t\t\t\t\\\n\t\tRB_ROOT(head) = elm;\t\t\t\t\t\\\n\tname##_RB_INSERT_COLOR(head, elm);\t\t\t\t\\\n\treturn (NULL);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n/* Finds the node with the same key as elm */\t\t\t\t\\\nattr struct type *\t\t\t\t\t\t\t\\\nname##_RB_FIND(struct name *head, struct type *elm)\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tstruct type *tmp = RB_ROOT(head);\t\t\t\t\\\n\tint comp;\t\t\t\t\t\t\t\\\n\twhile (tmp) {\t\t\t\t\t\t\t\\\n\t\tcomp = cmp(elm, tmp);\t\t\t\t\t\\\n\t\tif (comp < 0)\t\t\t\t\t\t\\\n\t\t\ttmp = RB_LEFT(tmp, field);\t\t\t\\\n\t\telse if (comp > 0)\t\t\t\t\t\\\n\t\t\ttmp = RB_RIGHT(tmp, field);\t\t\t\\\n\t\telse\t\t\t\t\t\t\t\\\n\t\t\treturn (tmp);\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\treturn (NULL);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n/* Finds the first node greater than or equal to the search key */\t\\\nattr struct type *\t\t\t\t\t\t\t\\\nname##_RB_NFIND(struct name *head, struct type *elm)\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tstruct type *tmp = RB_ROOT(head);\t\t\t\t\\\n\tstruct type *res = NULL;\t\t\t\t\t\\\n\tint comp;\t\t\t\t\t\t\t\\\n\twhile (tmp) {\t\t\t\t\t\t\t\\\n\t\tcomp = cmp(elm, tmp);\t\t\t\t\t\\\n\t\tif (comp < 0) {\t\t\t\t\t\t\\\n\t\t\tres = tmp;\t\t\t\t\t\\\n\t\t\ttmp = RB_LEFT(tmp, field);\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t\telse if (comp > 0)\t\t\t\t\t\\\n\t\t\ttmp = RB_RIGHT(tmp, field);\t\t\t\\\n\t\telse\t\t\t\t\t\t\t\\\n\t\t\treturn (tmp);\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\treturn (res);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n/* ARGSUSED */\t\t\t\t\t\t\t\t\\\nattr struct type *\t\t\t\t\t\t\t\\\nname##_RB_NEXT(struct type *elm)\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tif (RB_RIGHT(elm, field)) {\t\t\t\t\t\\\n\t\telm = RB_RIGHT(elm, field);\t\t\t\t\\\n\t\twhile (RB_LEFT(elm, field))\t\t\t\t\\\n\t\t\telm = RB_LEFT(elm, field);\t\t\t\\\n\t} else {\t\t\t\t\t\t\t\\\n\t\tif (RB_PARENT(elm, field) &&\t\t\t\t\\\n\t\t    (elm == RB_LEFT(RB_PARENT(elm, field), field)))\t\\\n\t\t\telm = RB_PARENT(elm, field);\t\t\t\\\n\t\telse {\t\t\t\t\t\t\t\\\n\t\t\twhile (RB_PARENT(elm, field) &&\t\t\t\\\n\t\t\t    (elm == RB_RIGHT(RB_PARENT(elm, field), field)))\\\n\t\t\t\telm = RB_PARENT(elm, field);\t\t\\\n\t\t\telm = RB_PARENT(elm, field);\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\treturn (elm);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n/* ARGSUSED */\t\t\t\t\t\t\t\t\\\nattr struct type *\t\t\t\t\t\t\t\\\nname##_RB_PREV(struct type *elm)\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tif (RB_LEFT(elm, field)) {\t\t\t\t\t\\\n\t\telm = RB_LEFT(elm, field);\t\t\t\t\\\n\t\twhile (RB_RIGHT(elm, field))\t\t\t\t\\\n\t\t\telm = RB_RIGHT(elm, field);\t\t\t\\\n\t} else {\t\t\t\t\t\t\t\\\n\t\tif (RB_PARENT(elm, field) &&\t\t\t\t\\\n\t\t    (elm == RB_RIGHT(RB_PARENT(elm, field), field)))\t\\\n\t\t\telm = RB_PARENT(elm, field);\t\t\t\\\n\t\telse {\t\t\t\t\t\t\t\\\n\t\t\twhile (RB_PARENT(elm, field) &&\t\t\t\\\n\t\t\t    (elm == RB_LEFT(RB_PARENT(elm, field), field)))\\\n\t\t\t\telm = RB_PARENT(elm, field);\t\t\\\n\t\t\telm = RB_PARENT(elm, field);\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\treturn (elm);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\nattr struct type *\t\t\t\t\t\t\t\\\nname##_RB_MINMAX(struct name *head, int val)\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tstruct type *tmp = RB_ROOT(head);\t\t\t\t\\\n\tstruct type *parent = NULL;\t\t\t\t\t\\\n\twhile (tmp) {\t\t\t\t\t\t\t\\\n\t\tparent = tmp;\t\t\t\t\t\t\\\n\t\tif (val < 0)\t\t\t\t\t\t\\\n\t\t\ttmp = RB_LEFT(tmp, field);\t\t\t\\\n\t\telse\t\t\t\t\t\t\t\\\n\t\t\ttmp = RB_RIGHT(tmp, field);\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\treturn (parent);\t\t\t\t\t\t\\\n}\n\n#define RB_NEGINF\t-1\n#define RB_INF\t1\n\n#define RB_INSERT(name, x, y)\tname##_RB_INSERT(x, y)\n#define RB_REMOVE(name, x, y)\tname##_RB_REMOVE(x, y)\n#define RB_FIND(name, x, y)\tname##_RB_FIND(x, y)\n#define RB_NFIND(name, x, y)\tname##_RB_NFIND(x, y)\n#define RB_NEXT(name, x, y)\tname##_RB_NEXT(y)\n#define RB_PREV(name, x, y)\tname##_RB_PREV(y)\n#define RB_MIN(name, x)\t\tname##_RB_MINMAX(x, RB_NEGINF)\n#define RB_MAX(name, x)\t\tname##_RB_MINMAX(x, RB_INF)\n\n#define RB_FOREACH(x, name, head)\t\t\t\t\t\\\n\tfor ((x) = RB_MIN(name, head);\t\t\t\t\t\\\n\t     (x) != NULL;\t\t\t\t\t\t\\\n\t     (x) = name##_RB_NEXT(x))\n\n#define RB_FOREACH_SAFE(x, name, head, y)\t\t\t\t\\\n\tfor ((x) = RB_MIN(name, head);\t\t\t\t\t\\\n\t    ((x) != NULL) && ((y) = name##_RB_NEXT(x), 1);\t\t\\\n\t     (x) = (y))\n\n#define RB_FOREACH_REVERSE(x, name, head)\t\t\t\t\\\n\tfor ((x) = RB_MAX(name, head);\t\t\t\t\t\\\n\t     (x) != NULL;\t\t\t\t\t\t\\\n\t     (x) = name##_RB_PREV(x))\n\n#define RB_FOREACH_REVERSE_SAFE(x, name, head, y)\t\t\t\\\n\tfor ((x) = RB_MAX(name, head);\t\t\t\t\t\\\n\t    ((x) != NULL) && ((y) = name##_RB_PREV(x), 1);\t\t\\\n\t     (x) = (y))\n\n\n/*\n * Copyright (c) 2016 David Gwynne <dlg@openbsd.org>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\nstruct rb_type {\n\tint\t\t(*t_compare)(const void *, const void *);\n\tvoid\t\t(*t_augment)(void *);\n\tunsigned int\t  t_offset;\t/* offset of rb_entry in type */\n};\n\nstruct rb_tree {\n\tstruct rb_entry\t*rbt_root;\n};\n\nstruct rb_entry {\n\tstruct rb_entry\t *rbt_parent;\n\tstruct rb_entry\t *rbt_left;\n\tstruct rb_entry\t *rbt_right;\n\tunsigned int\t  rbt_color;\n};\n\n#define RBT_HEAD(_name, _type)\t\t\t\t\t\t\\\nstruct _name {\t\t\t\t\t\t\t\t\\\n\tstruct rb_tree rbh_root;\t\t\t\t\t\\\n}\n\n#define RBT_ENTRY(_type)\tstruct rb_entry\n\nstatic inline void\n_rb_init(struct rb_tree *rbt)\n{\n\trbt->rbt_root = NULL;\n}\n\nstatic inline int\n_rb_empty(struct rb_tree *rbt)\n{\n\treturn (rbt->rbt_root == NULL);\n}\n\nvoid\t*_rb_insert(const struct rb_type *, struct rb_tree *, void *);\nvoid\t*_rb_remove(const struct rb_type *, struct rb_tree *, void *);\nvoid\t*_rb_find(const struct rb_type *, struct rb_tree *, const void *);\nvoid\t*_rb_nfind(const struct rb_type *, struct rb_tree *, const void *);\nvoid\t*_rb_root(const struct rb_type *, struct rb_tree *);\nvoid\t*_rb_min(const struct rb_type *, struct rb_tree *);\nvoid\t*_rb_max(const struct rb_type *, struct rb_tree *);\nvoid\t*_rb_next(const struct rb_type *, void *);\nvoid\t*_rb_prev(const struct rb_type *, void *);\nvoid\t*_rb_left(const struct rb_type *, void *);\nvoid\t*_rb_right(const struct rb_type *, void *);\nvoid\t*_rb_parent(const struct rb_type *, void *);\nvoid\t _rb_set_left(const struct rb_type *, void *, void *);\nvoid\t _rb_set_right(const struct rb_type *, void *, void *);\nvoid\t _rb_set_parent(const struct rb_type *, void *, void *);\nvoid\t _rb_poison(const struct rb_type *, void *, unsigned long);\nint\t _rb_check(const struct rb_type *, void *, unsigned long);\n\n#define RBT_INITIALIZER(_head)\t{ { NULL } }\n\n#define RBT_PROTOTYPE(_name, _type, _field, _cmp)\t\t\t\\\nextern const struct rb_type *const _name##_RBT_TYPE;\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n__unused static inline void\t\t\t\t\t\t\\\n_name##_RBT_INIT(struct _name *head)\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t_rb_init(&head->rbh_root);\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n__unused static inline struct _type *\t\t\t\t\t\\\n_name##_RBT_INSERT(struct _name *head, struct _type *elm)\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\treturn _rb_insert(_name##_RBT_TYPE, &head->rbh_root, elm);\t\\\n}\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n__unused static inline struct _type *\t\t\t\t\t\\\n_name##_RBT_REMOVE(struct _name *head, struct _type *elm)\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\treturn _rb_remove(_name##_RBT_TYPE, &head->rbh_root, elm);\t\\\n}\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n__unused static inline struct _type *\t\t\t\t\t\\\n_name##_RBT_FIND(struct _name *head, const struct _type *key)\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\treturn _rb_find(_name##_RBT_TYPE, &head->rbh_root, key);\t\\\n}\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n__unused static inline struct _type *\t\t\t\t\t\\\n_name##_RBT_NFIND(struct _name *head, const struct _type *key)\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\treturn _rb_nfind(_name##_RBT_TYPE, &head->rbh_root, key);\t\\\n}\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n__unused static inline struct _type *\t\t\t\t\t\\\n_name##_RBT_ROOT(struct _name *head)\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\treturn _rb_root(_name##_RBT_TYPE, &head->rbh_root);\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n__unused static inline int\t\t\t\t\t\t\\\n_name##_RBT_EMPTY(struct _name *head)\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\treturn _rb_empty(&head->rbh_root);\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n__unused static inline struct _type *\t\t\t\t\t\\\n_name##_RBT_MIN(struct _name *head)\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\treturn _rb_min(_name##_RBT_TYPE, &head->rbh_root);\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n__unused static inline struct _type *\t\t\t\t\t\\\n_name##_RBT_MAX(struct _name *head)\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\treturn _rb_max(_name##_RBT_TYPE, &head->rbh_root);\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n__unused static inline struct _type *\t\t\t\t\t\\\n_name##_RBT_NEXT(struct _type *elm)\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\treturn _rb_next(_name##_RBT_TYPE, elm);\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n__unused static inline struct _type *\t\t\t\t\t\\\n_name##_RBT_PREV(struct _type *elm)\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\treturn _rb_prev(_name##_RBT_TYPE, elm);\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n__unused static inline struct _type *\t\t\t\t\t\\\n_name##_RBT_LEFT(struct _type *elm)\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\treturn _rb_left(_name##_RBT_TYPE, elm);\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n__unused static inline struct _type *\t\t\t\t\t\\\n_name##_RBT_RIGHT(struct _type *elm)\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\treturn _rb_right(_name##_RBT_TYPE, elm);\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n__unused static inline struct _type *\t\t\t\t\t\\\n_name##_RBT_PARENT(struct _type *elm)\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\treturn _rb_parent(_name##_RBT_TYPE, elm);\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n__unused static inline void\t\t\t\t\t\t\\\n_name##_RBT_SET_LEFT(struct _type *elm, struct _type *left)\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\treturn _rb_set_left(_name##_RBT_TYPE, elm, left);\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n__unused static inline void\t\t\t\t\t\t\\\n_name##_RBT_SET_RIGHT(struct _type *elm, struct _type *right)\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\treturn _rb_set_right(_name##_RBT_TYPE, elm, right);\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n__unused static inline void\t\t\t\t\t\t\\\n_name##_RBT_SET_PARENT(struct _type *elm, struct _type *parent)\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\treturn _rb_set_parent(_name##_RBT_TYPE, elm, parent);\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n__unused static inline void\t\t\t\t\t\t\\\n_name##_RBT_POISON(struct _type *elm, unsigned long poison)\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\treturn _rb_poison(_name##_RBT_TYPE, elm, poison);\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n__unused static inline int\t\t\t\t\t\t\\\n_name##_RBT_CHECK(struct _type *elm, unsigned long poison)\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\treturn _rb_check(_name##_RBT_TYPE, elm, poison);\t\t\\\n}\n\n#define RBT_GENERATE_INTERNAL(_name, _type, _field, _cmp, _aug)\t\t\\\nstatic int\t\t\t\t\t\t\t\t\\\n_name##_RBT_COMPARE(const void *lptr, const void *rptr)\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tconst struct _type *l = lptr, *r = rptr;\t\t\t\\\n\treturn _cmp(l, r);\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\nstatic const struct rb_type _name##_RBT_INFO = {\t\t\t\\\n\t_name##_RBT_COMPARE,\t\t\t\t\t\t\\\n\t_aug,\t\t\t\t\t\t\t\t\\\n\toffsetof(struct _type, _field),\t\t\t\t\t\\\n};\t\t\t\t\t\t\t\t\t\\\nconst struct rb_type *const _name##_RBT_TYPE = &_name##_RBT_INFO\n\n#define RBT_GENERATE_AUGMENT(_name, _type, _field, _cmp, _aug)\t\t\\\nstatic void\t\t\t\t\t\t\t\t\\\n_name##_RBT_AUGMENT(void *ptr)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tstruct _type *p = ptr;\t\t\t\t\t\t\\\n\treturn _aug(p);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\nRBT_GENERATE_INTERNAL(_name, _type, _field, _cmp, _name##_RBT_AUGMENT)\n\n#define RBT_GENERATE(_name, _type, _field, _cmp)\t\t\t\\\n    RBT_GENERATE_INTERNAL(_name, _type, _field, _cmp, NULL)\n\n#define RBT_INIT(_name, _head)\t\t_name##_RBT_INIT(_head)\n#define RBT_INSERT(_name, _head, _elm)\t_name##_RBT_INSERT(_head, _elm)\n#define RBT_REMOVE(_name, _head, _elm)\t_name##_RBT_REMOVE(_head, _elm)\n#define RBT_FIND(_name, _head, _key)\t_name##_RBT_FIND(_head, _key)\n#define RBT_NFIND(_name, _head, _key)\t_name##_RBT_NFIND(_head, _key)\n#define RBT_ROOT(_name, _head)\t\t_name##_RBT_ROOT(_head)\n#define RBT_EMPTY(_name, _head)\t\t_name##_RBT_EMPTY(_head)\n#define RBT_MIN(_name, _head)\t\t_name##_RBT_MIN(_head)\n#define RBT_MAX(_name, _head)\t\t_name##_RBT_MAX(_head)\n#define RBT_NEXT(_name, _elm)\t\t_name##_RBT_NEXT(_elm)\n#define RBT_PREV(_name, _elm)\t\t_name##_RBT_PREV(_elm)\n#define RBT_LEFT(_name, _elm)\t\t_name##_RBT_LEFT(_elm)\n#define RBT_RIGHT(_name, _elm)\t\t_name##_RBT_RIGHT(_elm)\n#define RBT_PARENT(_name, _elm)\t\t_name##_RBT_PARENT(_elm)\n#define RBT_SET_LEFT(_name, _elm, _l)\t_name##_RBT_SET_LEFT(_elm, _l)\n#define RBT_SET_RIGHT(_name, _elm, _r)\t_name##_RBT_SET_RIGHT(_elm, _r)\n#define RBT_SET_PARENT(_name, _elm, _p)\t_name##_RBT_SET_PARENT(_elm, _p)\n#define RBT_POISON(_name, _elm, _p)\t_name##_RBT_POISON(_elm, _p)\n#define RBT_CHECK(_name, _elm, _p)\t_name##_RBT_CHECK(_elm, _p)\n\n#define RBT_FOREACH(_e, _name, _head)\t\t\t\t\t\\\n\tfor ((_e) = RBT_MIN(_name, (_head));\t\t\t\t\\\n\t     (_e) != NULL;\t\t\t\t\t\t\\\n\t     (_e) = RBT_NEXT(_name, (_e)))\n\n#define RBT_FOREACH_SAFE(_e, _name, _head, _n)\t\t\t\t\\\n\tfor ((_e) = RBT_MIN(_name, (_head));\t\t\t\t\\\n\t     (_e) != NULL && ((_n) = RBT_NEXT(_name, (_e)), 1);\t\\\n\t     (_e) = (_n))\n\n#define RBT_FOREACH_REVERSE(_e, _name, _head)\t\t\t\t\\\n\tfor ((_e) = RBT_MAX(_name, (_head));\t\t\t\t\\\n\t     (_e) != NULL;\t\t\t\t\t\t\\\n\t     (_e) = RBT_PREV(_name, (_e)))\n\n#define RBT_FOREACH_REVERSE_SAFE(_e, _name, _head, _n)\t\t\t\\\n\tfor ((_e) = RBT_MAX(_name, (_head));\t\t\t\t\\\n\t     (_e) != NULL && ((_n) = RBT_PREV(_name, (_e)), 1);\t\\\n\t     (_e) = (_n))\n\n#endif\t/* _SYS_TREE_H_ */\n"
  },
  {
    "path": "itl80211/zutil.c",
    "content": "//\n//  zutil.c\n//  itlwm\n//\n//  Created by qcwap on 2020/9/4.\n//  Copyright © 2020 钟先耀. All rights reserved.\n//\n\n#include <zutil.h>\nextern \"C\" {\ntypedef struct z_mem\n{\n    UInt32 alloc_size;\n    UInt8 data[0];\n} z_mem;\n\nvoid *zcalloc(void *opaque, uint items, uint size)\n{\n    void* result = NULL;\n    z_mem* zmem = NULL;\n    UInt32 allocSize =  items * size + sizeof(zmem);\n    \n    zmem = (z_mem*)IOMalloc(allocSize);\n    \n    if (zmem)\n    {\n        zmem->alloc_size = allocSize;\n        result = (void*)&(zmem->data);\n    }\n    \n    return result;\n}\n\nvoid zcfree(void *opaque, void *ptr)\n{\n    UInt32* skipper = (UInt32 *)ptr - 1;\n    z_mem* zmem = (z_mem*)skipper;\n    IOFree((void*)zmem, zmem->alloc_size);\n}\n}\n"
  },
  {
    "path": "itl80211/zutil.h",
    "content": "//\n//  zutil.h\n//  itlwm\n//\n//  Created by qcwap on 2020/9/4.\n//  Copyright © 2020 钟先耀. All rights reserved.\n//\n\n#ifndef zutil_h\n#define zutil_h\n\n#include <IOKit/IOLib.h>\n#include <IOKit/IOTypes.h>\n\nextern \"C\" {\nvoid *zcalloc(void *opaque, uint items, uint size);\n\nvoid zcfree(void *opaque, void *ptr);\n}\n\n#endif /* zutil_h */\n"
  },
  {
    "path": "itlwm/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>$(DEVELOPMENT_LANGUAGE)</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>$(MODULE_VERSION)</string>\n\t<key>CFBundleVersion</key>\n\t<string>$(MODULE_VERSION)</string>\n\t<key>IOKitPersonalities</key>\n\t<dict>\n\t\t<key>itlwm</key>\n\t\t<dict>\n\t\t\t<key>CFBundleIdentifier</key>\n\t\t\t<string>com.zxystd.itlwm</string>\n\t\t\t<key>IOClass</key>\n\t\t\t<string>itlwm</string>\n\t\t\t<key>IOMatchCategory</key>\n\t\t\t<string>IODefaultMatchCategory</string>\n\t\t\t<key>IOPCIPrimaryMatch</key>\n\t\t\t<string>0x00008086&amp;0x0000ffff</string>\n\t\t\t<key>IOProbeScore</key>\n\t\t\t<integer>2000</integer>\n\t\t\t<key>IOProviderClass</key>\n\t\t\t<string>IOPCIDevice</string>\n\t\t\t<key>IOUserClientClass</key>\n\t\t\t<string>ItlNetworkUserClient</string>\n\t\t\t<key>WiFiConfig</key>\n\t\t\t<dict>\n\t\t\t\t<key>WiFi_1</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>password</key>\n\t\t\t\t\t<string>zxyssdt112233</string>\n\t\t\t\t\t<key>ssid</key>\n\t\t\t\t\t<string>ssdt</string>\n\t\t\t\t</dict>\n\t\t\t\t<key>WiFi_2</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>password</key>\n\t\t\t\t\t<string>zxyssdt112233</string>\n\t\t\t\t\t<key>ssid</key>\n\t\t\t\t\t<string>ssdt_5G</string>\n\t\t\t\t</dict>\n\t\t\t\t<key>WiFi_3</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>password</key>\n\t\t\t\t\t<string></string>\n\t\t\t\t\t<key>ssid</key>\n\t\t\t\t\t<string>Redmi</string>\n\t\t\t\t</dict>\n\t\t\t\t<key>WiFi_4</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>password</key>\n\t\t\t\t\t<string>9utc5c5f</string>\n\t\t\t\t\t<key>ssid</key>\n\t\t\t\t\t<string>CMCC-KtG6</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t</dict>\n\t</dict>\n\t<key>NSHumanReadableCopyright</key>\n\t<string>Copyright © 2020 钟先耀. All rights reserved.</string>\n\t<key>OSBundleLibraries</key>\n\t<dict>\n\t\t<key>com.apple.iokit.IONetworkingFamily</key>\n\t\t<string>1.5.0</string>\n\t\t<key>com.apple.iokit.IOPCIFamily</key>\n\t\t<string>1.7</string>\n\t\t<key>com.apple.kpi.bsd</key>\n\t\t<string>8.10.0</string>\n\t\t<key>com.apple.kpi.iokit</key>\n\t\t<string>8.10.0</string>\n\t\t<key>com.apple.kpi.libkern</key>\n\t\t<string>8.10.0</string>\n\t\t<key>com.apple.kpi.mach</key>\n\t\t<string>8.10.0</string>\n\t</dict>\n\t<key>OSBundleRequired</key>\n\t<string>Network-Root</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "itlwm/ItlNetworkUserClient.cpp",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n\n#include \"ItlNetworkUserClient.hpp\"\n#include <sys/_netstat.h>\n\n#define super IOUserClient\nOSDefineMetaClassAndStructors( ItlNetworkUserClient, IOUserClient );\n\nconst IOControlMethodAction ItlNetworkUserClient::sMethods[IOCTL_ID_MAX] {\n    sDRIVER_INFO,\n    sSTA_INFO,\n    sPOWER,\n    sSTATE,\n    sNW_ID,\n    sWPA_KEY,\n    sASSOCIATE,\n    sDISASSOCIATE,\n    sJOIN,\n    sSCAN,\n    sSCAN_RESULT,\n    sTX_POWER_LEVEL,\n    sNW_BSSID,\n};\n\nbool ItlNetworkUserClient::initWithTask(task_t owningTask, void *securityID, UInt32 type, OSDictionary *properties)\n{\n    fTask = owningTask;\n    return super::initWithTask(owningTask, securityID, type, properties);\n}\n\nbool ItlNetworkUserClient::start(IOService *provider)\n{\n//    IOLog(\"start\\n\");\n    if( !super::start( provider ))\n        return false;\n    fDriver = OSDynamicCast(itlwm, provider);\n    fInf = fDriver->getNetworkInterface();\n    fIfp = fDriver->getIfp();\n    fDriverInfo = fDriver->fHalService->getDriverInfo();\n    fDriverController = fDriver->fHalService->getDriverController();\n    if (fDriver == NULL) {\n        return false;\n    }\n    return true;\n}\n\nIOReturn ItlNetworkUserClient::clientClose()\n{\n//    IOLog(\"clientClose\\n\");\n    if( !isInactive())\n        terminate();\n    return kIOReturnSuccess;\n}\n\nIOReturn ItlNetworkUserClient::clientDied()\n{\n//    IOLog(\"clientDied\\n\");\n    return super::clientDied();\n}\n\nvoid ItlNetworkUserClient::stop(IOService *provider)\n{\n//    IOLog(\"stop\\n\");\n    super::stop( provider );\n}\n\nIOReturn ItlNetworkUserClient::externalMethod(uint32_t selector, IOExternalMethodArguments * arguments, IOExternalMethodDispatch * dispatch, OSObject * target, void * reference)\n{\n    bool isSet = selector & IOCTL_MASK;\n    selector &= ~IOCTL_MASK;\n//    IOLog(\"externalMethod invoke. selector=0x%X isSet=%d\\n\", selector, isSet);\n    if (selector < 0 || selector > IOCTL_ID_MAX) {\n        return super::externalMethod(selector, arguments, NULL, this, NULL);\n    }\n    void *data = isSet ? (void *)arguments->structureInput : (void *)arguments->structureOutput;\n    if (!data) {\n        return kIOReturnError;\n    }\n    return sMethods[selector](this, data, isSet);\n}\n\nIOReturn ItlNetworkUserClient::\nsDRIVER_INFO(OSObject* target, void* data, bool isSet)\n{\n    ItlNetworkUserClient *that = OSDynamicCast(ItlNetworkUserClient, target);\n    ioctl_driver_info *drv_info = (ioctl_driver_info *)data;\n    memset(drv_info, 0, sizeof(*drv_info));\n    drv_info->version = IOCTL_VERSION;\n    snprintf(drv_info->bsd_name, sizeof(drv_info->bsd_name), \"%s%d\", ifnet_name(that->fInf->getIfnet()), ifnet_unit(that->fInf->getIfnet()));\n    strncpy(drv_info->fw_version, that->fDriverInfo->getFirmwareVersion(), sizeof(drv_info->fw_version));\n    snprintf(drv_info->driver_version, sizeof(drv_info->driver_version), \"%s%s\", ITLWM_VERSION, GIT_COMMIT);\n    return kIOReturnSuccess;\n}\n\nIOReturn ItlNetworkUserClient::\nsSTA_INFO(OSObject* target, void* data, bool isSet)\n{\n    ItlNetworkUserClient *that = OSDynamicCast(ItlNetworkUserClient, target);\n    struct ioctl_sta_info *st = (struct ioctl_sta_info *)data;\n    struct ieee80211com *ic = that->fDriver->fHalService->get80211Controller();\n    struct ieee80211_node *ic_bss = ic->ic_bss;\n    int nss;\n    int sgi;\n    int index = 0;\n    if (isSet) {\n        return kIOReturnError;\n    }\n    if (ic_bss == NULL) {\n        return kIOReturnError;\n    }\n    if (ic_bss->ni_chan == NULL) {\n        return kIOReturnError;\n    }\n    if (ic->ic_state != IEEE80211_S_RUN) {\n        return kIOReturnError;\n    }\n    st->version = IOCTL_VERSION;\n    st->op_mode = ic->ic_curmode > 0 ? (enum itl_phy_mode)(ic->ic_curmode - 1) : ITL80211_MODE_11A;\n    st->max_mcs = ic_bss->ni_txmcs;\n    st->cur_mcs = ic_bss->ni_txmcs;\n    st->channel = ieee80211_chan2ieee(ic, ic_bss->ni_chan);\n    switch (ic->ic_bss->ni_chw) {\n        case IEEE80211_CHAN_WIDTH_40:\n            st->band_width = 40;\n            break;\n        case IEEE80211_CHAN_WIDTH_80:\n            st->band_width = 80;\n            break;\n        case IEEE80211_CHAN_WIDTH_80P80:\n        case IEEE80211_CHAN_WIDTH_160:\n            st->band_width = 160;\n            break;\n            \n        default:\n            st->band_width = 20;\n            break;\n    }\n    st->rssi = -(0 - IWM_MIN_DBM - ic_bss->ni_rssi);\n    st->noise = that->fDriver->fHalService->getDriverInfo()->getBSSNoise();\n    sgi = ieee80211_node_supports_sgi(ic_bss);\n    if (ic->ic_curmode == IEEE80211_MODE_11AC) {\n        if (sgi) {\n            index += 1;\n        }\n        nss = that->fDriverInfo->getTxNSS();\n        switch (ic_bss->ni_chw) {\n            case IEEE80211_CHAN_WIDTH_40:\n                index += 4;\n                break;\n            case IEEE80211_CHAN_WIDTH_80:\n                index += 8;\n                break;\n            case IEEE80211_CHAN_WIDTH_80P80:\n            case IEEE80211_CHAN_WIDTH_160:\n                index += 12;\n                break;\n\n            default:\n                break;\n        }\n        index += 2 * (nss - 1);\n        const struct ieee80211_vht_rateset *rs = &ieee80211_std_ratesets_11ac[index];\n        st->rate = rs->rates[ic_bss->ni_txmcs % rs->nrates] / 2;\n    } else if (ic->ic_curmode == IEEE80211_MODE_11N) {\n        int is_40mhz = ic_bss->ni_chw == IEEE80211_CHAN_WIDTH_40;\n        if (sgi) {\n            index += 1;\n        }\n        if (is_40mhz) {\n            index += (IEEE80211_HT_RATESET_MIMO4_SGI + 1);\n        }\n        index += (ic_bss->ni_txmcs / 16);\n        nss = ic_bss->ni_txmcs / 8 + 1;\n        index += 2 * (nss - 1);\n        st->rate = ieee80211_std_ratesets_11n[index].rates[ic_bss->ni_txmcs % 8] / 2;\n    } else {\n        st->rate = ic_bss->ni_rates.rs_rates[ic_bss->ni_txrate];\n    }\n    memset(st->ssid, 0, sizeof(st->ssid));\n    bcopy(ic->ic_des_essid, st->ssid, ic->ic_des_esslen);\n    memset(st->bssid, 0, sizeof(st->bssid));\n    bcopy(ic->ic_bss->ni_bssid, st->bssid, ETHER_ADDR_LEN);\n    return kIOReturnSuccess;\n}\n\nIOReturn ItlNetworkUserClient::\nsPOWER(OSObject* target, void* data, bool isSet)\n{\n    ItlNetworkUserClient *that = OSDynamicCast(ItlNetworkUserClient, target);\n    struct ioctl_power *ip = (struct ioctl_power *)data;\n    if (isSet) {\n        if (ip->enabled) {\n            that->fDriver->enable(that->fInf);\n        } else {\n            net80211_ifstats(that->fDriver->fHalService->get80211Controller());\n            that->fDriver->disable(that->fInf);\n        }\n    } else {\n        memset(ip, 0, sizeof(*ip));\n        ip->version = IOCTL_VERSION;\n        ip->enabled = (that->fIfp->if_flags & (IFF_UP | IFF_RUNNING)) != 0;\n    }\n    return kIOReturnSuccess;\n}\n\nIOReturn ItlNetworkUserClient::\nsSTATE(OSObject* target, void* data, bool isSet)\n{\n    ItlNetworkUserClient *that = OSDynamicCast(ItlNetworkUserClient, target);\n    struct ioctl_state *st = (struct ioctl_state *)data;\n    if (isSet) {\n        return kIOReturnError;\n    }\n    memset(st, 0, sizeof(*st));\n    st->version = IOCTL_VERSION;\n    st->state = (itl_80211_state)that->fDriver->fHalService->get80211Controller()->ic_state;\n    return kIOReturnSuccess;\n}\n\nIOReturn ItlNetworkUserClient::\nsNW_BSSID(OSObject* target, void* data, bool isSet)\n{\n    ItlNetworkUserClient *that = OSDynamicCast(ItlNetworkUserClient, target);\n    struct ioctl_nw_bssid *nwid = (struct ioctl_nw_bssid *)data;\n    struct ieee80211com *ic = that->fDriver->fHalService->get80211Controller();\n    \n    if (isSet) {\n        if (IEEE80211_ADDR_EQ(nwid->bssid, etheranyaddr))\n            ic->ic_flags &= ~IEEE80211_F_DESBSSID;\n        else {\n            ic->ic_flags |= IEEE80211_F_DESBSSID;\n            IEEE80211_ADDR_COPY(ic->ic_des_bssid, nwid->bssid);\n        }\n        return kIOReturnSuccess;\n    }\n    memset(nwid, 0, sizeof(*nwid));\n    nwid->version = IOCTL_VERSION;\n    switch (ic->ic_state) {\n        case IEEE80211_S_INIT:\n        case IEEE80211_S_SCAN:\n#ifndef IEEE80211_STA_ONLY\n            if (ic->ic_opmode == IEEE80211_M_HOSTAP)\n                IEEE80211_ADDR_COPY(nwid->bssid,\n                                    ic->ic_myaddr);\n            else\n#endif\n                if (ic->ic_flags & IEEE80211_F_DESBSSID)\n                    IEEE80211_ADDR_COPY(nwid->bssid,\n                                        ic->ic_des_bssid);\n                else\n                    memset(nwid->bssid, 0, IEEE80211_ADDR_LEN);\n            break;\n        default:\n            IEEE80211_ADDR_COPY(nwid->bssid,\n                                ic->ic_bss->ni_bssid);\n            break;\n    }\n    return kIOReturnSuccess;\n}\n\nIOReturn ItlNetworkUserClient::\nsNW_ID(OSObject* target, void* data, bool isSet)\n{\n    ItlNetworkUserClient *that = OSDynamicCast(ItlNetworkUserClient, target);\n    struct ioctl_nw_id *nwid = (struct ioctl_nw_id *)data;\n    struct ieee80211com *ic = that->fDriver->fHalService->get80211Controller();\n    \n    if (isSet) {\n        if (nwid->len > IEEE80211_NWID_LEN) {\n            return kIOReturnError;\n        }\n        memset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN);\n        ic->ic_des_esslen = nwid->len;\n        memcpy(ic->ic_des_essid, nwid->nwid, nwid->len);\n        if (ic->ic_des_esslen > 0) {\n            /* 'nwid' disables auto-join magic */\n            ic->ic_flags &= ~IEEE80211_F_AUTO_JOIN;\n        } else if (!TAILQ_EMPTY(&ic->ic_ess)) {\n            /* '-nwid' re-enables auto-join */\n            ic->ic_flags |= IEEE80211_F_AUTO_JOIN;\n        }\n        /* disable WPA/WEP */\n        ieee80211_disable_rsn(ic);\n        ieee80211_disable_wep(ic);\n        return kIOReturnSuccess;\n    }\n    memset(nwid, 0, sizeof(*nwid));\n    nwid->version = IOCTL_VERSION;\n    switch (ic->ic_state) {\n    case IEEE80211_S_INIT:\n    case IEEE80211_S_SCAN:\n        nwid->len = ic->ic_des_esslen;\n        memcpy(nwid->nwid, ic->ic_des_essid, nwid->len);\n        break;\n    default:\n        nwid->len = ic->ic_bss->ni_esslen;\n        memcpy(nwid->nwid, ic->ic_bss->ni_essid, nwid->len);\n        break;\n    }\n    return kIOReturnSuccess;\n}\n\nIOReturn ItlNetworkUserClient::\nsWPA_KEY(OSObject* target, void* data, bool isSet)\n{\n    return kIOReturnSuccess;\n}\n\nIOReturn ItlNetworkUserClient::\nsASSOCIATE(OSObject* target, void* data, bool isSet)\n{\n    ItlNetworkUserClient *that = OSDynamicCast(ItlNetworkUserClient, target);\n    struct ioctl_associate *as = (struct ioctl_associate *)data;\n    that->fDriver->associateSSID(as->nwid.nwid, as->wpa_key.key);\n    return kIOReturnSuccess;\n}\n\nIOReturn ItlNetworkUserClient::\nsDISASSOCIATE(OSObject* target, void* data, bool isSet)\n{\n    ItlNetworkUserClient *that = OSDynamicCast(ItlNetworkUserClient, target);\n    struct ioctl_disassociate *dis = (struct ioctl_disassociate *)data;\n    struct ieee80211com *ic = that->fDriver->fHalService->get80211Controller();\n    if (ic->ic_state > IEEE80211_S_AUTH && ic->ic_bss != NULL)\n        IEEE80211_SEND_MGMT(ic, ic->ic_bss, IEEE80211_FC0_SUBTYPE_DEAUTH, IEEE80211_REASON_AUTH_LEAVE);\n    ieee80211_del_ess(ic, (char *)dis->ssid, strlen((char *)dis->ssid), 0);\n    ieee80211_deselect_ess(ic);\n    if (TAILQ_EMPTY(&ic->ic_ess)) {\n        ic->ic_flags |= IEEE80211_F_AUTO_JOIN;\n    }\n    ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);\n    return kIOReturnSuccess;\n}\n\nIOReturn ItlNetworkUserClient::\nsJOIN(OSObject* target, void* data, bool isSet)\n{\n    ItlNetworkUserClient *that = OSDynamicCast(ItlNetworkUserClient, target);\n    struct ioctl_join *join = (struct ioctl_join *)data;\n    that->fDriver->joinSSID(join->nwid.nwid, join->wpa_key.key);\n    return kIOReturnSuccess;\n}\n\nIOReturn ItlNetworkUserClient::\nsSCAN(OSObject* target, void* data, bool isSet)\n{\n    ItlNetworkUserClient *that = OSDynamicCast(ItlNetworkUserClient, target);\n    ieee80211_begin_cache_bgscan(that->fIfp);\n    return kIOReturnSuccess;\n}\n\nIOReturn ItlNetworkUserClient::\nsSCAN_RESULT(OSObject* target, void* data, bool isSet)\n{\n    ItlNetworkUserClient *that = OSDynamicCast(ItlNetworkUserClient, target);\n    struct ioctl_network_info *ni = (struct ioctl_network_info *)data;\n    ieee80211com *ic = that->fDriver->fHalService->get80211Controller();\n    if (that->fNextNodeToSend == NULL) {\n        if (that->fScanResultWrapping) {\n            that->fScanResultWrapping = false;\n            return kIONoScanResult;\n        } else {\n            that->fNextNodeToSend = RB_MIN(ieee80211_tree, &ic->ic_tree);\n            if (that->fNextNodeToSend == NULL) {\n                return kIONoScanResult;\n            }\n        }\n    }\n    bzero(ni, sizeof(*ni));\n    \n    ni->ni_rsncaps = that->fNextNodeToSend->ni_capinfo;;\n    ni->channel = ieee80211_chan2ieee(ic, that->fNextNodeToSend->ni_chan);\n    ni->ni_rsncipher = (enum itl80211_cipher)that->fNextNodeToSend->ni_rsncipher;\n    ni->rsn_akms = that->fNextNodeToSend->ni_rsnakms;\n    ni->rsn_ciphers = that->fNextNodeToSend->ni_rsnciphers;\n    ni->rsn_protos = that->fNextNodeToSend->ni_rsnprotos;\n    ni->rsn_groupcipher = (enum itl80211_cipher)that->fNextNodeToSend->ni_rsngroupcipher;\n    ni->rsn_groupmgmtcipher = (enum itl80211_cipher)that->fNextNodeToSend->ni_rsngroupmgmtcipher;\n    ni->supported_rsnakms = that->fNextNodeToSend->ni_supported_rsnakms;\n    ni->supported_rsnprotos = that->fNextNodeToSend->ni_supported_rsnprotos;\n    ni->noise = 0;\n    ni->rssi = -(0 - IWM_MIN_DBM - that->fNextNodeToSend->ni_rssi);\n    memcpy(ni->bssid, that->fNextNodeToSend->ni_bssid, 6);\n    memcpy(ni->ssid, that->fNextNodeToSend->ni_essid, 32);\n    that->fNextNodeToSend = RB_NEXT(ieee80211_tree, &ic->ic_tree, that->fNextNodeToSend);\n    if (that->fNextNodeToSend == NULL)\n        that->fScanResultWrapping = true;\n    return kIOReturnSuccess;\n}\n\nIOReturn ItlNetworkUserClient::\nsTX_POWER_LEVEL(OSObject* target, void* data, bool isSet)\n{\n    return kIOReturnSuccess;\n}\n"
  },
  {
    "path": "itlwm/ItlNetworkUserClient.hpp",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n\n#ifndef ItlNetworkUserClient_hpp\n#define ItlNetworkUserClient_hpp\n\n#include <IOKit/IOLib.h>\n#include <IOKit/IOUserClient.h>\n#include <IOKit/IOBufferMemoryDescriptor.h>\n#include <IOKit/network/IOEthernetInterface.h>\n#include \"itlwm.hpp\"\n#include <ClientKit/Common.h>\n\ntypedef IOReturn (*IOControlMethodAction)(OSObject * target, void *data, bool isSet);\n\nclass ItlNetworkUserClient : public IOUserClient {\n    \n    OSDeclareDefaultStructors( ItlNetworkUserClient );\n    \npublic:\n    \n    virtual bool start( IOService * provider ) override;\n    virtual void stop( IOService * provider ) override;\n    virtual bool initWithTask( task_t owningTask, void * securityID,\n    UInt32 type,  OSDictionary * properties ) override;\n    virtual IOReturn clientDied (void) override;\n    virtual IOReturn clientClose( void ) override;\n    virtual IOReturn externalMethod( uint32_t selector, IOExternalMethodArguments * arguments, IOExternalMethodDispatch * dispatch = 0, OSObject * target = 0, void * reference = 0 ) override;\n    \nprivate:\n    static IOReturn sDRIVER_INFO(OSObject* target, void* data, bool isSet);\n    static IOReturn sSTA_INFO(OSObject* target, void* data, bool isSet);\n    static IOReturn sPOWER(OSObject* target, void* data, bool isSet);\n    static IOReturn sSTATE(OSObject* target, void* data, bool isSet);\n    static IOReturn sNW_ID(OSObject* target, void* data, bool isSet);\n    static IOReturn sWPA_KEY(OSObject* target, void* data, bool isSet);\n    static IOReturn sASSOCIATE(OSObject* target, void* data, bool isSet);\n    static IOReturn sDISASSOCIATE(OSObject* target, void* data, bool isSet);\n    static IOReturn sJOIN(OSObject* target, void* data, bool isSet);\n    static IOReturn sSCAN(OSObject* target, void* data, bool isSet);\n    static IOReturn sSCAN_RESULT(OSObject* target, void* data, bool isSet);\n    static IOReturn sTX_POWER_LEVEL(OSObject* target, void* data, bool isSet);\n    static IOReturn sNW_BSSID(OSObject* target, void* data, bool isSet);\n    static const IOControlMethodAction sMethods[IOCTL_ID_MAX];\n    \nprivate:\n    task_t fTask;\n    itlwm *fDriver;\n    IOEthernetInterface *fInf;\n    struct _ifnet *fIfp;\n    ItlDriverController *fDriverController;\n    ItlDriverInfo *fDriverInfo;\n    \nprotected:\n    bool fScanResultWrapping;\n    ieee80211_node *fNextNodeToSend;\n};\n\n\n#endif /* ItlNetworkUserClient_hpp */\n"
  },
  {
    "path": "itlwm/PrivateSPI.pch",
    "content": "#include <libkern/libkern.h>\n#include <IOKit/IOTypes.h>\n#include <machine/types.h>\n#ifdef __PRIVATE_SPI__\ntypedef u_int32_t ifnet_ctl_cmd_t;\n#endif\n\n#ifndef __MAC_12_0\n#define __MAC_12_0  120000\n#endif\n\n#ifndef __MAC_13_0\n#define __MAC_13_0  130000\n#endif\n\n#ifndef __MAC_14_0\n#define __MAC_14_0  140000\n#endif\n\n#ifndef __MAC_14_4\n#define __MAC_14_4  140400\n#endif\n"
  },
  {
    "path": "itlwm/hal_iwm/ItlIwm.cpp",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n\n#include \"ItlIwm.hpp\"\n\n#define super ItlHalService\nOSDefineMetaClassAndStructors(ItlIwm, ItlHalService)\n\nvoid ItlIwm::\ndetach(IOPCIDevice *device)\n{\n    struct _ifnet *ifp = &com.sc_ic.ic_ac.ac_if;\n    struct iwm_softc *sc = &com;\n    \n    for (int txq_i = 0; txq_i < nitems(sc->txq); txq_i++)\n        iwm_free_tx_ring(sc, &sc->txq[txq_i]);\n    iwm_rs_free(sc);\n    iwm_free_rx_ring(sc, &sc->rxq);\n    iwm_dma_contig_free(&sc->ict_dma);\n    iwm_dma_contig_free(&sc->kw_dma);\n    iwm_dma_contig_free(&sc->sched_dma);\n    iwm_dma_contig_free(&sc->fw_dma);\n    ieee80211_ifdetach(ifp);\n    taskq_destroy(systq);\n    taskq_destroy(com.sc_nswq);\n    releaseAll();\n}\n\nbool ItlIwm::\nattach(IOPCIDevice *device)\n{\n    pci.pa_tag = device;\n    pci.workloop = getMainWorkLoop();\n    if (!iwm_attach(&com, &pci)) {\n        detach(device);\n        releaseAll();\n        return false;\n    }\n    return true;\n}\n\nvoid ItlIwm::\nfree()\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    super::free();\n}\n\nvoid ItlIwm::\nreleaseAll()\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    pci_intr_handle *intrHandler = com.ih;\n    if (com.sc_calib_to) {\n        timeout_del(&com.sc_calib_to);\n        timeout_free(&com.sc_calib_to);\n    }\n    if (com.sc_led_blink_to) {\n        timeout_del(&com.sc_led_blink_to);\n        timeout_free(&com.sc_led_blink_to);\n    }\n    if (intrHandler) {\n        if (intrHandler->intr && intrHandler->workloop) {\n//            intrHandler->intr->disable();\n            intrHandler->workloop->removeEventSource(intrHandler->intr);\n            intrHandler->intr->release();\n        }\n        intrHandler->intr = NULL;\n        intrHandler->workloop = NULL;\n        intrHandler->arg = NULL;\n        intrHandler->dev = NULL;\n        intrHandler->func = NULL;\n        intrHandler->release();\n        com.ih = NULL;\n    }\n    pci.pa_tag = NULL;\n    pci.workloop = NULL;\n}\n\nIOReturn ItlIwm::\nenable(IONetworkInterface *netif)\n{\n    XYLog(\"%s\\n\", __PRETTY_FUNCTION__);\n    struct _ifnet *ifp = &com.sc_ic.ic_ac.ac_if;\n    if (ifp->if_flags & IFF_UP) {\n        XYLog(\"%s already in activating state\\n\", __FUNCTION__);\n        return kIOReturnSuccess;\n    }\n    ifp->if_flags |= IFF_UP;\n    iwm_activate(&com, DVACT_RESUME);\n    iwm_activate(&com, DVACT_WAKEUP);\n    return kIOReturnSuccess;\n}\n\nIOReturn ItlIwm::\ndisable(IONetworkInterface *netif)\n{\n    struct _ifnet *ifp = &com.sc_ic.ic_ac.ac_if;\n    if (!(ifp->if_flags & IFF_UP)) {\n        XYLog(\"%s already in diactivating state\\n\", __FUNCTION__);\n        return kIOReturnSuccess;\n    }\n    ifp->if_flags &= ~IFF_UP;\n    iwm_activate(&com, DVACT_QUIESCE);\n    return kIOReturnSuccess;\n}\n\nstruct ieee80211com *ItlIwm::\nget80211Controller()\n{\n    return &com.sc_ic;\n}\n\nItlDriverInfo *ItlIwm::\ngetDriverInfo()\n{\n    return this;\n}\n\nItlDriverController *ItlIwm::\ngetDriverController()\n{\n    return this;\n}\n\nvoid ItlIwm::\nclearScanningFlags()\n{\n    com.sc_flags &= ~(IWM_FLAG_SCANNING | IWM_FLAG_BGSCAN);\n}\n\nIOReturn ItlIwm::\nsetMulticastList(IOEthernetAddress *addr, int count)\n{\n    struct ieee80211com *ic = &com.sc_ic;\n    struct iwm_mcast_filter_cmd *cmd;\n    int len;\n    uint8_t addr_count;\n    int err;\n    \n    if (ic->ic_state != IEEE80211_S_RUN || ic->ic_bss == NULL)\n        return kIOReturnError;\n    addr_count = count;\n    if (count > IWM_MAX_MCAST_FILTERING_ADDRESSES)\n        addr_count = 0;\n    if (addr == NULL)\n        addr_count = 0;\n    len = roundup(sizeof(struct iwm_mcast_filter_cmd) + addr_count * ETHER_ADDR_LEN, 4);\n    XYLog(\"%s multicast count=%d bssid=%s\\n\", __FUNCTION__, count, ether_sprintf(ic->ic_bss->ni_bssid));\n    cmd = (struct iwm_mcast_filter_cmd *)malloc(len, 0, 0);\n    if (!cmd)\n        return kIOReturnError;\n    cmd->pass_all = addr_count == 0;\n    cmd->count = addr_count;\n    cmd->port_id = 0;\n    IEEE80211_ADDR_COPY(cmd->bssid, ic->ic_bss->ni_bssid);\n    if (addr_count > 0)\n        memcpy(cmd->addr_list,\n               addr->bytes, ETHER_ADDR_LEN * cmd->count);\n    err = iwm_send_cmd_pdu(&com, IWM_MCAST_FILTER_CMD, IWM_CMD_ASYNC, len,\n                     cmd);\n    ::free(cmd);\n    return err ? kIOReturnError : kIOReturnSuccess;\n}\n\nconst char *ItlIwm::\ngetFirmwareVersion()\n{\n    return com.sc_fwver;\n}\n\nconst char *ItlIwm::\ngetFirmwareName()\n{\n    return com.sc_fwname;\n}\n\nUInt32 ItlIwm::\nsupportedFeatures()\n{\n    return kIONetworkFeatureMultiPages;\n}\n\nconst char *ItlIwm::\ngetFirmwareCountryCode()\n{\n    return com.sc_fw_mcc;\n}\n\nuint32_t ItlIwm::\ngetTxQueueSize()\n{\n    return IWM_TX_RING_COUNT;\n}\n\nint16_t ItlIwm::\ngetBSSNoise()\n{\n    return com.sc_noise;\n}\n\nbool ItlIwm::\nis5GBandSupport()\n{\n    return com.sc_nvm.sku_cap_band_52GHz_enable;\n}\n\nint ItlIwm::\ngetTxNSS()\n{\n    return iwm_mimo_enabled(&com) &&\n    (com.sc_ic.ic_bss != NULL && com.sc_ic.ic_bss->ni_rx_nss > 1) ?\n    2 : 1;\n}\n"
  },
  {
    "path": "itlwm/hal_iwm/ItlIwm.hpp",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n\n#ifndef ItlIwm_hpp\n#define ItlIwm_hpp\n\n#include <compat.h>\n#include \"itlhdr.h\"\n#include <linux/kernel.h>\n\n#include <IOKit/IOWorkLoop.h>\n#include <IOKit/network/IOGatedOutputQueue.h>\n#include <libkern/c++/OSString.h>\n#include <IOKit/IOService.h>\n#include <IOKit/pci/IOPCIDevice.h>\n#include <IOKit/IOLib.h>\n#include <libkern/OSKextLib.h>\n#include <libkern/c++/OSMetaClass.h>\n#include <IOKit/IOFilterInterruptEventSource.h>\n\n#include <HAL/ItlHalService.hpp>\n#include <HAL/ItlDriverInfo.hpp>\n#include <HAL/ItlDriverController.hpp>\n\nclass ItlIwm : public ItlHalService, ItlDriverInfo, ItlDriverController {\n    OSDeclareDefaultStructors(ItlIwm)\n    \npublic:\n    //kext\n    void free() override;\n    virtual bool attach(IOPCIDevice *device) override;\n    virtual void detach(IOPCIDevice *device) override;\n    IOReturn enable(IONetworkInterface *netif) override;\n    IOReturn disable(IONetworkInterface *netif) override;\n    virtual struct ieee80211com *get80211Controller() override;\n    \n    static bool intrFilter(OSObject *object, IOFilterInterruptEventSource *src);\n    static IOReturn _iwm_start_task(OSObject *target, void *arg0, void *arg1, void *arg2, void *arg3);\n    \n    void releaseAll();\n    \n    struct _ifnet *getIfp();\n    struct iwm_softc *getSoft();\n    IOEthernetInterface *getNetworkInterface();\n    \n    virtual ItlDriverInfo *getDriverInfo() override;\n    \n    virtual ItlDriverController *getDriverController() override;\n    \n    //driver info\n    virtual const char *getFirmwareVersion() override;\n    \n    virtual int16_t getBSSNoise() override;\n    \n    virtual bool is5GBandSupport() override;\n    \n    virtual int getTxNSS() override;\n    \n    virtual const char *getFirmwareName() override;\n    \n    virtual UInt32 supportedFeatures() override;\n\n    virtual const char *getFirmwareCountryCode() override;\n\n    virtual uint32_t getTxQueueSize() override;\n    \n    //driver controller\n    virtual void clearScanningFlags() override;\n    \n    virtual IOReturn setMulticastList(IOEthernetAddress *addr, int count) override;\n    \n    //utils\n    int    iwm_send_bt_init_conf(struct iwm_softc *);\n    \n    //fw\n    static uint8_t iwm_fw_valid_tx_ant(struct iwm_softc *sc);\n    static uint8_t iwm_fw_valid_rx_ant(struct iwm_softc *sc);\n    void    iwm_toggle_tx_ant(struct iwm_softc *sc, uint8_t *ant);\n    uint32_t iwm_get_tx_ant(struct iwm_softc *sc, struct ieee80211_node *ni,\n                            int type, struct ieee80211_frame *wh);\n    \n    //scan\n    uint8_t iwm_umac_scan_fill_channels(struct iwm_softc *sc,\n                                        struct iwm_scan_channel_cfg_umac *chan, int n_ssids, int bgscan);\n    \n    //coex\n    uint16_t iwm_coex_agg_time_limit(struct iwm_softc *, struct ieee80211_node *);\n    uint8_t iwm_coex_tx_prio(struct iwm_softc *, struct ieee80211_frame *, uint8_t);\n    static bool iwm_coex_is_ant_avail(struct iwm_softc *, u8);\n    static bool iwm_coex_is_mimo_allowed(struct iwm_softc *, struct ieee80211_node *);\n    static bool iwm_coex_is_tpc_allowed(struct iwm_softc *, bool);\n    static bool iwm_coex_is_shared_ant_avail(struct iwm_softc *);\n    \n    uint8_t iwm_lookup_cmd_ver(struct iwm_softc *, uint8_t, uint8_t);\n    int    iwm_store_cscheme(struct iwm_softc *, uint8_t *, size_t);\n    int    iwm_firmware_store_section(struct iwm_softc *, enum iwm_ucode_type,\n                                      uint8_t *, size_t);\n    int    iwm_set_default_calib(struct iwm_softc *, const void *);\n    void    iwm_fw_info_free(struct iwm_fw_info *);\n    int    iwm_read_firmware(struct iwm_softc *, enum iwm_ucode_type);\n    uint32_t iwm_read_prph_unlocked(struct iwm_softc *, uint32_t);\n    uint32_t iwm_read_prph(struct iwm_softc *, uint32_t);\n    void    iwm_write_prph_unlocked(struct iwm_softc *, uint32_t, uint32_t);\n    void    iwm_write_prph(struct iwm_softc *, uint32_t, uint32_t);\n    void    iwm_write_prph64(struct iwm_softc *, uint64_t, uint64_t);\n    int    iwm_read_mem(struct iwm_softc *, uint32_t, void *, int);\n    int    iwm_write_mem(struct iwm_softc *, uint32_t, const void *, int);\n    int    iwm_write_mem32(struct iwm_softc *, uint32_t, uint32_t);\n    int    iwm_poll_bit(struct iwm_softc *, int, uint32_t, uint32_t, int);\n    int    iwm_nic_lock(struct iwm_softc *);\n    void    iwm_nic_assert_locked(struct iwm_softc *);\n    void    iwm_nic_unlock(struct iwm_softc *);\n    void    iwm_set_bits_mask_prph(struct iwm_softc *, uint32_t, uint32_t,\n                                   uint32_t);\n    void    iwm_set_bits_prph(struct iwm_softc *, uint32_t, uint32_t);\n    void    iwm_clear_bits_prph(struct iwm_softc *, uint32_t, uint32_t);\n    int    iwm_dma_contig_alloc(bus_dma_tag_t, struct iwm_dma_info *, bus_size_t, bus_size_t);\n    void    iwm_dma_contig_free(struct iwm_dma_info *);\n    int    iwm_alloc_rx_ring(struct iwm_softc *, struct iwm_rx_ring *);\n    void    iwm_disable_rx_dma(struct iwm_softc *);\n    void    iwm_reset_rx_ring(struct iwm_softc *, struct iwm_rx_ring *);\n    void    iwm_free_rx_ring(struct iwm_softc *, struct iwm_rx_ring *);\n    int    iwm_alloc_tx_ring(struct iwm_softc *, struct iwm_tx_ring *, int);\n    void    iwm_reset_tx_ring(struct iwm_softc *, struct iwm_tx_ring *);\n    void    iwm_free_tx_ring(struct iwm_softc *, struct iwm_tx_ring *);\n    void    iwm_enable_rfkill_int(struct iwm_softc *);\n    int    iwm_check_rfkill(struct iwm_softc *);\n    void    iwm_enable_interrupts(struct iwm_softc *);\n    void    iwm_enable_fwload_interrupt(struct iwm_softc *);\n    void    iwm_restore_interrupts(struct iwm_softc *);\n    void    iwm_disable_interrupts(struct iwm_softc *);\n    void    iwm_ict_reset(struct iwm_softc *);\n    int    iwm_set_hw_ready(struct iwm_softc *);\n    int    iwm_prepare_card_hw(struct iwm_softc *);\n    void    iwm_apm_config(struct iwm_softc *);\n    int    iwm_apm_init(struct iwm_softc *);\n    void    iwm_apm_stop(struct iwm_softc *);\n    int    iwm_allow_mcast(struct iwm_softc *);\n    void    iwm_init_msix_hw(struct iwm_softc *);\n    void    iwm_conf_msix_hw(struct iwm_softc *, int);\n    int    iwm_clear_persistence_bit(struct iwm_softc *);\n    int    iwm_start_hw(struct iwm_softc *);\n    void    iwm_stop_device(struct iwm_softc *);\n    void    iwm_nic_config(struct iwm_softc *);\n    int    iwm_nic_rx_init(struct iwm_softc *);\n    int    iwm_nic_rx_legacy_init(struct iwm_softc *);\n    int    iwm_nic_rx_mq_init(struct iwm_softc *);\n    int    iwm_nic_tx_init(struct iwm_softc *);\n    int    iwm_nic_init(struct iwm_softc *);\n    int    iwm_enable_ac_txq(struct iwm_softc *, int, int);\n    int    iwm_enable_txq(struct iwm_softc *, int, int, int, int, int, int);\n    int    iwm_disable_txq(struct iwm_softc *, uint8_t, uint8_t, uint8_t);\n    int    iwm_enable_default_tx_queues(struct iwm_softc *);\n    int    iwm_disable_tx_queues(struct iwm_softc *);\n    int    iwm_post_alive(struct iwm_softc *);\n    struct iwm_phy_db_entry *iwm_phy_db_get_section(struct iwm_softc *, uint16_t,\n                                                    uint16_t);\n    int    iwm_phy_db_set_section(struct iwm_softc *,\n                                  struct iwm_calib_res_notif_phy_db *);\n    int    iwm_is_valid_channel(uint16_t);\n    uint8_t    iwm_ch_id_to_ch_index(uint16_t);\n    uint16_t iwm_channel_id_to_papd(uint16_t);\n    uint16_t iwm_channel_id_to_txp(struct iwm_softc *, uint16_t);\n    int    iwm_phy_db_get_section_data(struct iwm_softc *, uint32_t, uint8_t **,\n                                       uint16_t *, uint16_t);\n    int    iwm_send_phy_db_cmd(struct iwm_softc *, uint16_t, uint16_t, void *);\n    int    iwm_phy_db_send_all_channel_groups(struct iwm_softc *, uint16_t,\n                                              uint8_t);\n    int    iwm_send_phy_db_data(struct iwm_softc *);\n    void    iwm_te_v2_to_v1(const struct iwm_time_event_cmd_v2 *,\n                            struct iwm_time_event_cmd_v1 *);\n    int    iwm_send_time_event_cmd(struct iwm_softc *,\n                                   const struct iwm_time_event_cmd *);\n    void    iwm_protect_session(struct iwm_softc *, struct iwm_node *, uint32_t,\n                                uint32_t);\n    void    iwm_unprotect_session(struct iwm_softc *, struct iwm_node *);\n    int    iwm_nvm_read_chunk(struct iwm_softc *, uint16_t, uint16_t, uint16_t,\n                              uint8_t *, uint16_t *);\n    int    iwm_nvm_read_section(struct iwm_softc *, uint16_t, uint8_t *,\n                                uint16_t *, size_t);\n    void    iwm_init_channel_map(struct iwm_softc *, const uint16_t * const,\n                                 const uint8_t *nvm_channels, size_t nchan);\n    int    iwm_mimo_enabled(struct iwm_softc *);\n    void    iwm_setup_ht_rates(struct iwm_softc *);\n    void    iwm_setup_vht_rates(struct iwm_softc *);\n    static void    iwm_mac_ctxt_task(void *);\n    static void    iwm_chan_ctxt_task(void *);\n    static void    iwm_updateprot(struct ieee80211com *);\n    static void    iwm_updateslot(struct ieee80211com *);\n    static void    iwm_updateedca(struct ieee80211com *);\n    static void    iwm_updatedtim(struct ieee80211com *);\n    void   iwm_init_reorder_buffer(struct iwm_reorder_buffer *, uint16_t,\n                                   uint16_t);\n    void   iwm_clear_reorder_buffer(struct iwm_softc *, struct iwm_rxba_data *);\n    static int    iwm_ampdu_rx_start(struct ieee80211com *, struct ieee80211_node *,\n                                     uint8_t);\n    static void    iwm_ampdu_rx_stop(struct ieee80211com *, struct ieee80211_node *,\n                                     uint8_t);\n    static void   iwm_rx_ba_session_expired(void *);\n    static void   iwm_reorder_timer_expired(void *);\n    static uint8_t iwm_num_of_ant(uint8_t mask);\n    int    iwm_sta_rx_agg(struct iwm_softc *, struct ieee80211_node *, uint8_t,\n                           uint16_t, uint16_t, int, int);\n    static int    iwm_ampdu_tx_start(struct ieee80211com *, struct ieee80211_node *,\n                              uint8_t);\n    static void    iwm_ampdu_tx_stop(struct ieee80211com *, struct ieee80211_node *,\n                              uint8_t);\n    static void     iwm_update_chw(struct ieee80211com *);\n    int iwm_sta_tx_agg(struct iwm_softc *, struct ieee80211_node *,\n                        uint8_t, uint8_t, uint16_t, int);\n    static void    iwm_ba_task(void *);\n    \n    int    iwm_parse_nvm_data(struct iwm_softc *, const uint16_t *,\n                              const uint16_t *, const uint16_t *,\n                              const uint16_t *, const uint16_t *,\n                              const uint16_t *, int);\n    void    iwm_set_hw_address_8000(struct iwm_softc *, struct iwm_nvm_data *,\n                                    const uint16_t *, const uint16_t *);\n    int    iwm_parse_nvm_sections(struct iwm_softc *, struct iwm_nvm_section *);\n    int    iwm_nvm_init(struct iwm_softc *);\n    int    iwm_firmware_load_sect(struct iwm_softc *, uint32_t, const uint8_t *,\n                                  uint32_t);\n    int    iwm_firmware_load_chunk(struct iwm_softc *, uint32_t, const uint8_t *,\n                                   uint32_t);\n    int    iwm_load_firmware_7000(struct iwm_softc *, enum iwm_ucode_type);\n    int    iwm_load_cpu_sections_8000(struct iwm_softc *, struct iwm_fw_sects *,\n                                      int , int *);\n    int    iwm_load_firmware_8000(struct iwm_softc *, enum iwm_ucode_type);\n    int    iwm_load_firmware(struct iwm_softc *, enum iwm_ucode_type);\n    int    iwm_start_fw(struct iwm_softc *, enum iwm_ucode_type);\n    int    iwm_send_tx_ant_cfg(struct iwm_softc *, uint8_t);\n    int    iwm_send_phy_cfg_cmd(struct iwm_softc *);\n    int    iwm_load_ucode_wait_alive(struct iwm_softc *, enum iwm_ucode_type);\n    int    iwm_send_dqa_cmd(struct iwm_softc *);\n    int    iwm_run_init_mvm_ucode(struct iwm_softc *, int);\n    int    iwm_config_ltr(struct iwm_softc *);\n    int    iwm_rx_addbuf(struct iwm_softc *, int, int);\n    int    iwm_get_signal_strength(struct iwm_softc *, struct ieee80211_rx_status *, struct iwm_rx_phy_info *);\n    int    iwm_rxmq_get_signal_strength(struct iwm_softc *, struct ieee80211_rx_status *, uint32_t, struct iwm_rx_mpdu_desc *);\n    void    iwm_rx_rx_phy_cmd(struct iwm_softc *, struct iwm_rx_packet *,\n                              struct iwm_rx_data *);\n    int    iwm_get_noise(const struct iwm_statistics_rx_non_phy *);\n    int    iwm_rx_hwdecrypt(struct iwm_softc *, mbuf_t, uint32_t,\n               struct ieee80211_rxinfo *);\n    int    iwm_ccmp_decap(struct iwm_softc *, mbuf_t,\n                          struct ieee80211_node *, struct ieee80211_rxinfo *);\n    void    iwm_rx_frame(struct iwm_softc *, mbuf_t, int, uint32_t, int, int,\n                         uint32_t, struct ieee80211_rxinfo *, struct mbuf_list *);\n    void    iwm_rx_tx_cmd_single(struct iwm_softc *, struct iwm_tx_resp *,\n                                 int, int);\n    void    iwm_ampdu_tx_done(struct iwm_softc *, struct iwm_cmd_header *,\n                              struct iwm_node *, struct iwm_tx_ring *, uint32_t, uint8_t,\n                              uint8_t, uint16_t, int, struct iwm_agg_tx_status *);\n    void    iwm_rx_tx_ba_notif(struct iwm_softc *, struct iwm_rx_packet *, struct iwm_rx_data *);\n    void    iwm_rx_tx_cmd(struct iwm_softc *, struct iwm_rx_packet *,\n                          struct iwm_rx_data *);\n    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);\n    void iwm_rx_mpdu_mq(struct iwm_softc *sc, mbuf_t m, void *pktdata,\n                   size_t maxlen, struct mbuf_list *ml);\n    void    iwm_rx_bmiss(struct iwm_softc *, struct iwm_rx_packet *,\n                         struct iwm_rx_data *);\n    int    iwm_binding_cmd(struct iwm_softc *, struct iwm_node *, uint32_t);\n    int    iwm_phy_ctxt_cmd_uhb(struct iwm_softc *, struct iwm_phy_ctxt *, uint8_t,\n                                uint8_t, uint32_t, uint32_t);\n    void    iwm_phy_ctxt_cmd_hdr(struct iwm_softc *, struct iwm_phy_ctxt *,\n                                 struct iwm_phy_context_cmd *, uint32_t, uint32_t);\n    void    iwm_phy_ctxt_cmd_data(struct iwm_softc *, struct iwm_phy_context_cmd *,\n                                  struct ieee80211_channel *, uint8_t, uint8_t);\n    int    iwm_phy_ctxt_cmd(struct iwm_softc *, struct iwm_phy_ctxt *, uint8_t,\n                            uint8_t, uint32_t, uint32_t);\n    int    iwm_send_cmd(struct iwm_softc *, struct iwm_host_cmd *);\n    int    iwm_send_cmd_pdu(struct iwm_softc *, uint32_t, uint32_t, uint16_t,\n                            const void *);\n    int    iwm_send_cmd_status(struct iwm_softc *, struct iwm_host_cmd *,\n                               uint32_t *);\n    int    iwm_send_cmd_pdu_status(struct iwm_softc *, uint32_t, uint16_t,\n                                   const void *, uint32_t *);\n    void    iwm_free_resp(struct iwm_softc *, struct iwm_host_cmd *);\n    void    iwm_cmd_done(struct iwm_softc *, int, int, int);\n    void    iwm_update_sched(struct iwm_softc *, int, int, uint8_t, uint16_t);\n    void    iwm_reset_sched(struct iwm_softc *, int, int, uint8_t);\n    const struct iwl_rs_rate_info *iwm_tx_fill_cmd(struct iwm_softc *, struct iwm_node *,\n                                           struct ieee80211_frame *, struct iwm_tx_cmd *);\n    void iwm_txd_done(struct iwm_softc *, struct iwm_tx_data *);\n    void iwm_ampdu_txq_advance(struct iwm_softc *, struct iwm_tx_ring *, int);\n    void iwm_clear_oactive(struct iwm_softc *, struct iwm_tx_ring *);\n    int    iwm_tx(struct iwm_softc *, mbuf_t, struct ieee80211_node *, int);\n    int    iwm_flush_tx_path(struct iwm_softc *, int);\n    void    iwm_led_enable(struct iwm_softc *);\n    void    iwm_led_disable(struct iwm_softc *);\n    int    iwm_led_is_enabled(struct iwm_softc *);\n    static void    iwm_led_blink_timeout(void *);\n    void    iwm_led_blink_start(struct iwm_softc *);\n    void    iwm_led_blink_stop(struct iwm_softc *);\n    int    iwm_beacon_filter_send_cmd(struct iwm_softc *,\n                                      struct iwm_beacon_filter_cmd *);\n    void    iwm_beacon_filter_set_cqm_params(struct iwm_softc *, struct iwm_node *,\n                                             struct iwm_beacon_filter_cmd *);\n    int    iwm_update_beacon_abort(struct iwm_softc *, struct iwm_node *, int);\n    void    iwm_power_build_cmd(struct iwm_softc *, struct iwm_node *,\n                                struct iwm_mac_power_cmd *);\n    int    iwm_power_mac_update_mode(struct iwm_softc *, struct iwm_node *);\n    int    iwm_power_update_device(struct iwm_softc *);\n    int    iwm_enable_beacon_filter(struct iwm_softc *, struct iwm_node *);\n    int    iwm_disable_beacon_filter(struct iwm_softc *);\n    int    iwm_add_sta_cmd(struct iwm_softc *, struct iwm_node *, int, unsigned int);\n    int    iwm_add_aux_sta(struct iwm_softc *);\n    int    iwm_rm_sta_cmd(struct iwm_softc *, struct iwm_node *);\n    int    iwm_drain_sta(struct iwm_softc *, struct iwm_node *, bool);\n    uint16_t iwm_scan_rx_chain(struct iwm_softc *);\n    uint32_t iwm_scan_rate_n_flags(struct iwm_softc *, int, int);\n    uint8_t    iwm_lmac_scan_fill_channels(struct iwm_softc *,\n                                           struct iwm_scan_channel_cfg_lmac *, int, int);\n    int iwm_fill_probe_req_v1(struct iwm_softc *, struct iwm_scan_probe_req_v1 *);\n    int    iwm_fill_probe_req(struct iwm_softc *, struct iwm_scan_probe_req *);\n    int    iwm_lmac_scan(struct iwm_softc *, int);\n    int    iwm_config_umac_scan(struct iwm_softc *);\n    int    iwm_umac_scan_size(struct iwm_softc *sc);\n    struct iwm_scan_umac_chan_param *iwm_get_scan_req_umac_chan_param(struct iwm_softc *sc, struct iwm_scan_req_umac *req);\n    void *iwm_get_scan_req_umac_data(struct iwm_softc *sc, struct iwm_scan_req_umac *req);\n    int    iwm_umac_scan(struct iwm_softc *, int);\n    void    iwm_mcc_update(struct iwm_softc *, struct iwm_mcc_chub_notif *);\n    uint8_t    iwm_ridx2rate(struct ieee80211_rateset *, int);\n    void    iwm_ack_rates(struct iwm_softc *, struct iwm_node *, int *, int *);\n    void    iwm_mac_ctxt_cmd_common(struct iwm_softc *, struct iwm_node *,\n                                    struct iwm_mac_ctx_cmd *, uint32_t);\n    void    iwm_mac_ctxt_cmd_fill_sta(struct iwm_softc *, struct iwm_node *,\n                                      struct iwm_mac_data_sta *, int);\n    int    iwm_mac_ctxt_cmd(struct iwm_softc *, struct iwm_node *, uint32_t, int);\n    int    iwm_update_quotas(struct iwm_softc *, struct iwm_node *, int);\n    void    iwm_add_task(struct iwm_softc *, struct taskq *, struct task *);\n    void    iwm_del_task(struct iwm_softc *, struct taskq *, struct task *);\n    int    iwm_scan(struct iwm_softc *);\n    static int    iwm_bgscan(struct ieee80211com *);\n    int    iwm_umac_scan_abort(struct iwm_softc *);\n    int    iwm_lmac_scan_abort(struct iwm_softc *);\n    int    iwm_scan_abort(struct iwm_softc *);\n    int    iwm_phy_ctxt_update(struct iwm_softc *, struct iwm_phy_ctxt *,\n                               struct ieee80211_channel *, uint8_t, uint8_t, uint32_t);\n    int    iwm_auth(struct iwm_softc *);\n    int    iwm_deauth(struct iwm_softc *);\n    int    iwm_run(struct iwm_softc *);\n    int    iwm_run_stop(struct iwm_softc *);\n    static struct ieee80211_node *iwm_node_alloc(struct ieee80211com *);\n    int    iwm_set_key_v1(struct ieee80211com *, struct ieee80211_node *,\n                          struct ieee80211_key *);\n    static int    iwm_set_key(struct ieee80211com *, struct ieee80211_node *,\n                              struct ieee80211_key *);\n    void    iwm_delete_key_v1(struct ieee80211com *,\n                              struct ieee80211_node *, struct ieee80211_key *);\n    static void    iwm_delete_key(struct ieee80211com *,\n                                  struct ieee80211_node *, struct ieee80211_key *);\n    static void    iwm_calib_timeout(void *);\n    int    iwm_media_change(struct _ifnet *);\n    static void    iwm_newstate_task(void *);\n    static int    iwm_newstate(struct ieee80211com *, enum ieee80211_state, int);\n    void    iwm_endscan(struct iwm_softc *);\n    void    iwm_fill_sf_command(struct iwm_softc *, struct iwm_sf_cfg_cmd *,\n                                struct ieee80211_node *);\n    int    iwm_sf_config(struct iwm_softc *, int);\n    int    iwm_send_update_mcc_cmd(struct iwm_softc *, const char *);\n    int    iwm_send_soc_conf(struct iwm_softc *);\n    int    iwm_send_temp_report_ths_cmd(struct iwm_softc *);\n    void    iwm_tt_tx_backoff(struct iwm_softc *, uint32_t);\n    int iwm_fill_paging_mem(struct iwm_softc *, const struct iwm_fw_sects *);\n    int iwm_alloc_fw_paging_mem(struct iwm_softc *, const struct iwm_fw_sects *);\n    void    iwm_free_fw_paging(struct iwm_softc *);\n    int    iwm_save_fw_paging(struct iwm_softc *, const struct iwm_fw_sects *);\n    int    iwm_send_paging_cmd(struct iwm_softc *, const struct iwm_fw_sects *);\n    int    iwm_init_hw(struct iwm_softc *);\n    int    iwm_init(struct _ifnet *);\n    static void    iwm_start(struct _ifnet *);\n    void    iwm_stop(struct _ifnet *);\n    static void    iwm_watchdog(struct _ifnet *);\n    static int    iwm_ioctl(struct _ifnet *, u_long, caddr_t);\n#ifdef IWM_DEBUG\n    const char *iwm_desc_lookup(uint32_t);\n    void    iwm_nic_error(struct iwm_softc *);\n    void    iwm_nic_umac_error(struct iwm_softc *);\n#endif\n    void    iwm_rx_mpdu(struct iwm_softc *, mbuf_t, void *, size_t,\n                        struct mbuf_list *);\n    void   iwm_flip_address(uint8_t *);\n    int    iwm_detect_duplicate(struct iwm_softc *, mbuf_t,\n               struct iwm_rx_mpdu_desc *, struct ieee80211_rxinfo *);\n    int    iwm_is_sn_less(uint16_t, uint16_t, uint16_t);\n    void   iwm_release_frames(struct iwm_softc *, struct ieee80211_node *,\n               struct iwm_rxba_data *, struct iwm_reorder_buffer *, uint16_t,\n               struct mbuf_list *);\n    int    iwm_oldsn_workaround(struct iwm_softc *, struct ieee80211_node *,\n               int, struct iwm_reorder_buffer *, uint32_t, uint32_t);\n    int    iwm_rx_reorder(struct iwm_softc *, mbuf_t, int,\n               struct iwm_rx_mpdu_desc *, int, int, uint32_t,\n               struct ieee80211_rxinfo *, struct mbuf_list *);\n    int    iwm_rx_pkt_valid(struct iwm_rx_packet *);\n    void    iwm_rx_pkt(struct iwm_softc *, struct iwm_rx_data *,\n                       struct mbuf_list *);\n    void    iwm_notif_intr(struct iwm_softc *);\n    static int    iwm_intr(OSObject *object, IOInterruptEventSource* sender, int count);\n    static int    iwm_intr_msix(OSObject *object, IOInterruptEventSource* sender, int count);\n    static int    iwm_match(IOPCIDevice *);\n    int    iwm_preinit(struct iwm_softc *);\n    void    iwm_attach_hook(struct device *);\n    bool    iwm_attach(struct iwm_softc *, struct pci_attach_args *);\n    static void    iwm_init_task(void *);\n    int    iwm_activate(struct iwm_softc *, int);\n    int    iwm_resume(struct iwm_softc *);\n    \n    \n    \npublic:\n    IOInterruptEventSource* fInterrupt;\n    IOPCIDevice *pciNub;\n    struct pci_attach_args pci;\n    struct iwm_softc com;\n};\n\n#endif /* ItlIwm_hpp */\n"
  },
  {
    "path": "itlwm/hal_iwm/coex.cpp",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause\n/*\n * Copyright (C) 2013-2014, 2018-2020 Intel Corporation\n * Copyright (C) 2013-2015 Intel Mobile Communications GmbH\n */\n\n#include \"ItlIwm.hpp\"\n\n#define LINK_QUAL_AGG_TIME_LIMIT_DEF    (4000)\n#define LINK_QUAL_AGG_TIME_LIMIT_BT_ACT    (1200)\n\nuint16_t ItlIwm::\niwm_coex_agg_time_limit(struct iwm_softc *sc, struct ieee80211_node *ni)\n{\n    return LINK_QUAL_AGG_TIME_LIMIT_DEF;\n}\n\nuint8_t ItlIwm::\niwm_coex_tx_prio(struct iwm_softc *sc, struct ieee80211_frame *wh, uint8_t ac)\n{\n    uint8_t type, subtype;\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct ieee80211_node *ni = ic->ic_bss;\n    bool mplut_enabled = isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT);\n    \n    if (!ni || !ni->ni_chan)\n        return 0;\n    \n    if (!IEEE80211_IS_CHAN_2GHZ(ni->ni_chan))\n        return 0;\n\n    type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;\n    subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;\n    \n    if (type == IEEE80211_FC0_TYPE_DATA) {\n        if (ieee80211_has_qos(wh)) {\n            switch (ac) {\n                case EDCA_AC_BE:\n                    return mplut_enabled ? 1 : 0;\n                case EDCA_AC_VI:\n                    return mplut_enabled ? 2 : 3;\n                case EDCA_AC_VO:\n                    return 3;\n                default:\n                    return 0;\n            }\n        } else if (IEEE80211_IS_MULTICAST(wh->i_addr1))\n            return 3;\n        else\n            return 0;\n    } else if (type == IEEE80211_FC0_TYPE_MGT)\n        return subtype == IEEE80211_FC0_SUBTYPE_DISASSOC ? 0 : 3;\n    else if (type == IEEE80211_FC0_TYPE_CTL)\n        /* ignore cfend and cfendack frames as we never send those */\n        return 3;\n    \n    return 0;\n}\n\nbool ItlIwm::\niwm_coex_is_ant_avail(struct iwm_softc *sc, u8 ant)\n{\n#if 0\n    /* there is no other antenna, shared antenna is always available */\n    if (mvm->cfg->bt_shared_single_ant)\n        return true;\n#endif\n    \n    if (ant & sc->non_shared_ant)\n        return true;\n    \n#ifdef notyet_coex\n    return le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) <\n                BT_HIGH_TRAFFIC;\n#else\n    return true;\n#endif\n}\n\nbool ItlIwm::\niwm_coex_is_mimo_allowed(struct iwm_softc *sc, struct ieee80211_node *ni)\n{\n#ifdef notyet_coex\n    struct iwm_node *in = (struct iwm_node *)ni;\n    struct iwm_phy_ctxt *phy_ctxt = in->in_phyctxt;\n    enum iwl_bt_coex_lut_type lut_type;\n\n    if (sc->last_bt_notif.ttc_status & BIT(phy_ctxt->id))\n        return true;\n\n    if (le32_to_cpu(sc->last_bt_notif.bt_activity_grading) <\n        BT_HIGH_TRAFFIC)\n        return true;\n\n    /*\n     * In Tight / TxTxDis, BT can't Rx while we Tx, so use both antennas\n     * since BT is already killed.\n     * In Loose, BT can Rx while we Tx, so forbid MIMO to let BT Rx while\n     * we Tx.\n     * When we are in 5GHz, we'll get BT_COEX_INVALID_LUT allowing MIMO.\n     */\n    lut_type = iwl_get_coex_type(mvm, mvmsta->vif);\n    return lut_type != BT_COEX_LOOSE_LUT;\n#else\n    return true;\n#endif\n}\n\nbool ItlIwm::\niwm_coex_is_tpc_allowed(struct iwm_softc *mvm, bool is5G)\n{\n    if (is5G)\n        return false;\n    \n#ifdef notyet_coex\n    return le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) >= BT_LOW_TRAFFIC;\n#else\n    return false;\n#endif\n}\n\nbool ItlIwm::\niwm_coex_is_shared_ant_avail(struct iwm_softc *mvm)\n{\n#ifdef notyet_coex\n    return le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) < BT_HIGH_TRAFFIC;\n#else\n    return mvm->sc_device_family == IWM_DEVICE_FAMILY_9000 &&\n            (iwm_fw_valid_tx_ant(mvm) & IWM_ANT_B);\n#endif\n}\n"
  },
  {
    "path": "itlwm/hal_iwm/ctxt.cpp",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n/*    $OpenBSD: if_iwm.c,v 1.316 2020/12/07 20:09:24 tobhe Exp $    */\n\n/*\n * Copyright (c) 2014, 2016 genua gmbh <info@genua.de>\n *   Author: Stefan Sperling <stsp@openbsd.org>\n * Copyright (c) 2014 Fixup Software Ltd.\n * Copyright (c) 2017 Stefan Sperling <stsp@openbsd.org>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n/*-\n * Based on BSD-licensed source modules in the Linux iwlwifi driver,\n * which were used as the reference documentation for this implementation.\n *\n ***********************************************************************\n *\n * This file is provided under a dual BSD/GPLv2 license.  When using or\n * redistributing this file, you may do so under either license.\n *\n * GPL LICENSE SUMMARY\n *\n * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.\n * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH\n * Copyright(c) 2016 Intel Deutschland GmbH\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of version 2 of the GNU General Public License as\n * published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful, but\n * WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,\n * USA\n *\n * The full GNU General Public License is included in this distribution\n * in the file called COPYING.\n *\n * Contact Information:\n *  Intel Linux Wireless <ilw@linux.intel.com>\n * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497\n *\n *\n * BSD LICENSE\n *\n * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.\n * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH\n * Copyright(c) 2016 Intel Deutschland GmbH\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in\n *    the documentation and/or other materials provided with the\n *    distribution.\n *  * Neither the name Intel Corporation nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*-\n * Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n#include \"ItlIwm.hpp\"\n\nvoid ItlIwm::\niwm_phy_ctxt_cmd_hdr(struct iwm_softc *sc, struct iwm_phy_ctxt *ctxt,\n    struct iwm_phy_context_cmd *cmd, uint32_t action, uint32_t apply_time)\n{\n    memset(cmd, 0, sizeof(struct iwm_phy_context_cmd));\n\n    cmd->id_and_color = htole32(IWM_FW_CMD_ID_AND_COLOR(ctxt->id,\n        ctxt->color));\n    cmd->action = htole32(action);\n    cmd->apply_time = htole32(apply_time);\n}\n\nstatic uint8_t\niwm_get_channel_width(struct ieee80211com *ic, struct ieee80211_channel *c)\n{\n    uint8_t ret = IWM_PHY_VHT_CHANNEL_MODE20;\n    if (ic->ic_bss == NULL || ic->ic_state < IEEE80211_S_ASSOC) {\n        return ret;\n    }\n    switch (ic->ic_bss->ni_chw) {\n        case IEEE80211_CHAN_WIDTH_20_NOHT:\n        case IEEE80211_CHAN_WIDTH_20:\n            return IWM_PHY_VHT_CHANNEL_MODE20;\n        case IEEE80211_CHAN_WIDTH_40:\n            return IWM_PHY_VHT_CHANNEL_MODE40;\n        case IEEE80211_CHAN_WIDTH_80:\n            return IWM_PHY_VHT_CHANNEL_MODE80;\n        case IEEE80211_CHAN_WIDTH_160:\n            return IWM_PHY_VHT_CHANNEL_MODE160;\n        default:\n            XYLog(\"Invalid channel width=%u\\n\", ic->ic_bss->ni_chw);\n            return ret;\n    }\n}\n\nstatic uint8_t\niwm_get_ctrl_pos(struct ieee80211com *ic, struct ieee80211_channel *c)\n{\n    if (ic->ic_bss == NULL || ic->ic_state < IEEE80211_S_ASSOC || iwm_get_channel_width(ic, c) == IWM_PHY_VHT_CHANNEL_MODE20)\n        return IWM_PHY_VHT_CTRL_POS_1_BELOW;\n    \n    signed int offset = ic->ic_bss->ni_chan->ic_freq - ic->ic_bss->ni_chan->ic_center_freq1;\n    switch (offset) {\n        case -70:\n            return IWM_PHY_VHT_CTRL_POS_4_BELOW;\n        case -50:\n            return IWM_PHY_VHT_CTRL_POS_3_BELOW;\n        case -30:\n            return IWM_PHY_VHT_CTRL_POS_2_BELOW;\n        case -10:\n            return IWM_PHY_VHT_CTRL_POS_1_BELOW;\n        case  10:\n            return IWM_PHY_VHT_CTRL_POS_1_ABOVE;\n        case  30:\n            return IWM_PHY_VHT_CTRL_POS_2_ABOVE;\n        case  50:\n            return IWM_PHY_VHT_CTRL_POS_3_ABOVE;\n        case  70:\n            return IWM_PHY_VHT_CTRL_POS_4_ABOVE;\n        default:\n            XYLog(\"Invalid channel definition freq=%d %d\\n\", ic->ic_bss->ni_chan->ic_freq, offset);\n            /* fall through */\n        case 0:\n            /*\n             * The FW is expected to check the control channel position only\n             * when in HT/VHT and the channel width is not 20MHz. Return\n             * this value as the default one.\n             */\n            return IWM_PHY_VHT_CTRL_POS_1_BELOW;\n    }\n}\n\nvoid ItlIwm::\niwm_phy_ctxt_cmd_data(struct iwm_softc *sc, struct iwm_phy_context_cmd *cmd,\n    struct ieee80211_channel *chan, uint8_t chains_static,\n    uint8_t chains_dynamic)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    uint8_t active_cnt, idle_cnt;\n\n    cmd->ci.band = IEEE80211_IS_CHAN_2GHZ(chan) ?\n        IWM_PHY_BAND_24 : IWM_PHY_BAND_5;\n    cmd->ci.channel = ieee80211_chan2ieee(ic, chan);\n    cmd->ci.width = iwm_get_channel_width(ic, chan);\n    cmd->ci.ctrl_pos = iwm_get_ctrl_pos(ic, chan);\n\n    /* Set rx the chains */\n    idle_cnt = chains_static;\n    active_cnt = chains_dynamic;\n\n    cmd->rxchain_info = htole32(iwm_fw_valid_rx_ant(sc) <<\n                    IWM_PHY_RX_CHAIN_VALID_POS);\n    cmd->rxchain_info |= htole32(idle_cnt << IWM_PHY_RX_CHAIN_CNT_POS);\n    cmd->rxchain_info |= htole32(active_cnt <<\n        IWM_PHY_RX_CHAIN_MIMO_CNT_POS);\n\n    cmd->txchain_info = htole32(iwm_fw_valid_tx_ant(sc));\n}\n\nint ItlIwm::\niwm_phy_ctxt_cmd_uhb(struct iwm_softc *sc, struct iwm_phy_ctxt *ctxt,\n                     uint8_t chains_static, uint8_t chains_dynamic, uint32_t action,\n                     uint32_t apply_time)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct iwm_phy_context_cmd_uhb cmd;\n    uint8_t active_cnt, idle_cnt;\n    struct ieee80211_channel *chan = ctxt->channel;\n    \n    memset(&cmd, 0, sizeof(cmd));\n    cmd.id_and_color = htole32(IWM_FW_CMD_ID_AND_COLOR(ctxt->id,\n                                                       ctxt->color));\n    cmd.action = htole32(action);\n    cmd.apply_time = htole32(apply_time);\n    \n    cmd.ci.band = IEEE80211_IS_CHAN_2GHZ(chan) ?\n    IWM_PHY_BAND_24 : IWM_PHY_BAND_5;\n    cmd.ci.channel = htole32(ieee80211_chan2ieee(ic, chan));\n    cmd.ci.width = iwm_get_channel_width(ic, chan);\n    cmd.ci.ctrl_pos = iwm_get_ctrl_pos(ic, chan);\n    \n    idle_cnt = chains_static;\n    active_cnt = chains_dynamic;\n    cmd.rxchain_info = htole32(iwm_fw_valid_rx_ant(sc) <<\n                               IWM_PHY_RX_CHAIN_VALID_POS);\n    cmd.rxchain_info |= htole32(idle_cnt << IWM_PHY_RX_CHAIN_CNT_POS);\n    cmd.rxchain_info |= htole32(active_cnt <<\n                                IWM_PHY_RX_CHAIN_MIMO_CNT_POS);\n    cmd.txchain_info = htole32(iwm_fw_valid_tx_ant(sc));\n    \n    return iwm_send_cmd_pdu(sc, IWM_PHY_CONTEXT_CMD, 0, sizeof(cmd), &cmd);\n}\n\nint ItlIwm::\niwm_phy_ctxt_cmd(struct iwm_softc *sc, struct iwm_phy_ctxt *ctxt,\n    uint8_t chains_static, uint8_t chains_dynamic, uint32_t action,\n    uint32_t apply_time)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwm_phy_context_cmd cmd;\n    \n    /*\n     * Intel increased the size of the fw_channel_info struct and neglected\n     * to bump the phy_context_cmd struct, which contains an fw_channel_info\n     * member in the middle.\n     * To keep things simple we use a separate function to handle the larger\n     * variant of the phy context command.\n     */\n    if (isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS))\n        return iwm_phy_ctxt_cmd_uhb(sc, ctxt, chains_static,\n                                    chains_dynamic, action, apply_time);\n\n    iwm_phy_ctxt_cmd_hdr(sc, ctxt, &cmd, action, apply_time);\n\n    iwm_phy_ctxt_cmd_data(sc, &cmd, ctxt->channel,\n        chains_static, chains_dynamic);\n\n    return iwm_send_cmd_pdu(sc, IWM_PHY_CONTEXT_CMD, 0,\n        sizeof(struct iwm_phy_context_cmd), &cmd);\n}\n"
  },
  {
    "path": "itlwm/hal_iwm/fw.cpp",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n/*    $OpenBSD: if_iwm.c,v 1.316 2020/12/07 20:09:24 tobhe Exp $    */\n\n/*\n * Copyright (c) 2014, 2016 genua gmbh <info@genua.de>\n *   Author: Stefan Sperling <stsp@openbsd.org>\n * Copyright (c) 2014 Fixup Software Ltd.\n * Copyright (c) 2017 Stefan Sperling <stsp@openbsd.org>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n/*-\n * Based on BSD-licensed source modules in the Linux iwlwifi driver,\n * which were used as the reference documentation for this implementation.\n *\n ***********************************************************************\n *\n * This file is provided under a dual BSD/GPLv2 license.  When using or\n * redistributing this file, you may do so under either license.\n *\n * GPL LICENSE SUMMARY\n *\n * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.\n * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH\n * Copyright(c) 2016 Intel Deutschland GmbH\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of version 2 of the GNU General Public License as\n * published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful, but\n * WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,\n * USA\n *\n * The full GNU General Public License is included in this distribution\n * in the file called COPYING.\n *\n * Contact Information:\n *  Intel Linux Wireless <ilw@linux.intel.com>\n * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497\n *\n *\n * BSD LICENSE\n *\n * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.\n * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH\n * Copyright(c) 2016 Intel Deutschland GmbH\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in\n *    the documentation and/or other materials provided with the\n *    distribution.\n *  * Neither the name Intel Corporation nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*-\n * Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n#include \"ItlIwm.hpp\"\n#include \"rs.h\"\n#include <FwData.h>\n\nuint8_t ItlIwm::\niwm_lookup_cmd_ver(struct iwm_softc *sc, uint8_t grp, uint8_t cmd)\n{\n   const struct iwm_fw_cmd_version *entry;\n   int i;\n\n   for (i = 0; i < sc->n_cmd_versions; i++) {\n       entry = &sc->cmd_versions[i];\n       if (entry->group == grp && entry->cmd == cmd)\n           return entry->cmd_ver;\n   }\n\n   return IWM_FW_CMD_VER_UNKNOWN;\n}\n\nint ItlIwm::\niwm_store_cscheme(struct iwm_softc *sc, uint8_t *data, size_t dlen)\n{\n    struct iwm_fw_cscheme_list *l = (struct iwm_fw_cscheme_list *)data;\n    \n    if (dlen < sizeof(*l) ||\n        dlen < sizeof(l->size) + l->size * sizeof(*l->cs))\n        return EINVAL;\n    \n    /* we don't actually store anything for now, always use s/w crypto */\n    \n    return 0;\n}\n\nint ItlIwm::\niwm_firmware_store_section(struct iwm_softc *sc, enum iwm_ucode_type type,\n                           uint8_t *data, size_t dlen)\n{\n    struct iwm_fw_sects *fws;\n    struct iwm_fw_onesect *fwone;\n    \n    if (type >= IWM_UCODE_TYPE_MAX)\n        return EINVAL;\n    if (dlen < sizeof(uint32_t))\n        return EINVAL;\n    \n    fws = (struct iwm_fw_sects*)&sc->sc_fw.fw_sects[type];\n    if (fws->fw_count >= IWM_UCODE_SECT_MAX)\n        return EINVAL;\n    \n    fwone = (struct iwm_fw_onesect*)&fws->fw_sect[fws->fw_count];\n    \n    /* first 32bit are device load offset */\n    memcpy(&fwone->fws_devoff, data, sizeof(uint32_t));\n    \n    /* rest is data */\n    fwone->fws_data = data + sizeof(uint32_t);\n    fwone->fws_len = dlen - sizeof(uint32_t);\n    \n    fws->fw_count++;\n    fws->fw_totlen += fwone->fws_len;\n    \n    return 0;\n}\n\n#define IWM_DEFAULT_SCAN_CHANNELS 40\n/* Newer firmware might support more channels. Raise this value if needed. */\n#define IWM_MAX_SCAN_CHANNELS        52 /* as of 8265-34 firmware image */\n\nstruct iwm_tlv_calib_data {\n    uint32_t ucode_type;\n    struct iwm_tlv_calib_ctrl calib;\n} __packed;\n\nint ItlIwm::\niwm_set_default_calib(struct iwm_softc *sc, const void *data)\n{\n    const struct iwm_tlv_calib_data *def_calib = (const struct iwm_tlv_calib_data *)data;\n    uint32_t ucode_type = le32toh(def_calib->ucode_type);\n    \n    if (ucode_type >= IWM_UCODE_TYPE_MAX)\n        return EINVAL;\n    \n    sc->sc_default_calib[ucode_type].flow_trigger =\n    def_calib->calib.flow_trigger;\n    sc->sc_default_calib[ucode_type].event_trigger =\n    def_calib->calib.event_trigger;\n    \n    return 0;\n}\n\nvoid ItlIwm::\niwm_fw_info_free(struct iwm_fw_info *fw)\n{\n    ::free(fw->fw_rawdata);\n    fw->fw_rawdata = NULL;\n    fw->fw_rawsize = 0;\n    /* don't touch fw->fw_status */\n    memset(fw->fw_sects, 0, sizeof(fw->fw_sects));\n}\n\nvoid\niwm_fw_version_str(char *buf, size_t bufsize,\n    uint32_t major, uint32_t minor, uint32_t api)\n{\n    /*\n     * Starting with major version 35 the Linux driver prints the minor\n     * version in hexadecimal.\n     */\n    if (major >= 35)\n        snprintf(buf, bufsize, \"%u.%08x.%u\", major, minor, api);\n    else\n        snprintf(buf, bufsize, \"%u.%u.%u\", major, minor, api);\n}\n\nint ItlIwm::\niwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode_type ucode_type)\n{\n    struct iwm_fw_info *fw = &sc->sc_fw;\n    struct iwm_tlv_ucode_header *uhdr;\n    struct iwm_ucode_tlv tlv;\n    uint32_t usniffer_img;\n    uint32_t paging_mem_size;\n    uint32_t tlv_type;\n    uint8_t *data;\n    int err = 0;\n    size_t len;\n    OSData *fwData = NULL;\n    \n    if (fw->fw_status == IWM_FW_STATUS_DONE &&\n        ucode_type != IWM_UCODE_TYPE_INIT)\n        return 0;\n    \n    while (fw->fw_status == IWM_FW_STATUS_INPROGRESS)\n        tsleep_nsec(&sc->sc_fw, 0, \"iwmfwp\", INFSLP);\n    fw->fw_status = IWM_FW_STATUS_INPROGRESS;\n    \n    if (fw->fw_rawdata != NULL)\n        iwm_fw_info_free(fw);\n    \n    //TODO\n    //    err = loadfirmware(sc->sc_fwname,\n    //        (u_char **)&fw->fw_rawdata, &fw->fw_rawsize);\n//    IOLockLock(fwLoadLock);\n//    ResourceCallbackContext context =\n//    {\n//        .context = this,\n//        .resource = NULL\n//    };\n//\n//    //here leaks\n//    IOReturn ret = OSKextRequestResource(OSKextGetCurrentIdentifier(), sc->sc_fwname, onLoadFW, &context, NULL);\n//    IOLockSleep(fwLoadLock, this, 0);\n//    IOLockUnlock(fwLoadLock);\n//    if (context.resource == NULL) {\n//        XYLog(\"%s resource load fail.\\n\", sc->sc_fwname);\n//        goto out;\n//    }\n//    fw->fw_rawdata = malloc(context.resource->getLength(), 1, 1);\n//    memcpy(fw->fw_rawdata, context.resource->getBytesNoCopy(), context.resource->getLength());\n//    fw->fw_rawsize = context.resource->getLength();\n    fwData = getFWDescByName(sc->sc_fwname);\n    if (fwData == NULL) {\n        XYLog(\"%s resource load fail.\\n\", sc->sc_fwname);\n        err = EINVAL;\n        goto out;\n    }\n    fw->fw_rawsize = fwData->getLength() * 4;\n    fw->fw_rawdata = malloc(fw->fw_rawsize, 1, 1);\n    uncompressFirmware((u_char *)fw->fw_rawdata, (uint *)&fw->fw_rawsize, (u_char *)fwData->getBytesNoCopy(), fwData->getLength());\n    XYLog(\"load firmware %s done\\n\", sc->sc_fwname);\n    sc->sc_capaflags = 0;\n    sc->sc_capa_n_scan_channels = IWM_DEFAULT_SCAN_CHANNELS;\n    memset(sc->sc_enabled_capa, 0, sizeof(sc->sc_enabled_capa));\n    sc->n_cmd_versions = 0;\n    memset(sc->sc_ucode_api, 0, sizeof(sc->sc_ucode_api));\n    memcpy(sc->sc_fw_mcc, \"ZZ\", sizeof(sc->sc_fw_mcc));\n    sc->sc_fw_mcc_int = 0x3030;\n    \n    uhdr = (struct iwm_tlv_ucode_header *)fw->fw_rawdata;\n    if (*(uint32_t *)fw->fw_rawdata != 0\n        || le32toh(uhdr->magic) != IWM_TLV_UCODE_MAGIC) {\n        XYLog(\"%s: invalid firmware %s\\n\",\n              DEVNAME(sc), sc->sc_fwname);\n        err = EINVAL;\n        goto out;\n    }\n    \n    iwm_fw_version_str(sc->sc_fwver, sizeof(sc->sc_fwver),\n                       IWM_UCODE_MAJOR(le32toh(uhdr->ver)),\n                       IWM_UCODE_MINOR(le32toh(uhdr->ver)),\n                       IWM_UCODE_API(le32toh(uhdr->ver)));\n    \n    data = uhdr->data;\n    len = fw->fw_rawsize - sizeof(*uhdr);\n    \n    while (len >= sizeof(tlv)) {\n        size_t tlv_len;\n        void *tlv_data;\n        \n        memcpy(&tlv, data, sizeof(tlv));\n        tlv_len = le32toh(tlv.length);\n        tlv_type = le32toh(tlv.type);\n        \n        len -= sizeof(tlv);\n        data += sizeof(tlv);\n        tlv_data = data;\n        \n        if (len < tlv_len) {\n            XYLog(\"%s: firmware too short: %zu bytes\\n\",\n                  DEVNAME(sc), len);\n            err = EINVAL;\n            goto parse_out;\n        }\n        \n        switch (tlv_type) {\n            case IWM_UCODE_TLV_PROBE_MAX_LEN:\n                if (tlv_len < sizeof(uint32_t)) {\n                    err = EINVAL;\n                    goto parse_out;\n                }\n                sc->sc_capa_max_probe_len\n                = le32toh(*(uint32_t *)tlv_data);\n                if (sc->sc_capa_max_probe_len >\n                    IWM_SCAN_OFFLOAD_PROBE_REQ_SIZE) {\n                    err = EINVAL;\n                    goto parse_out;\n                }\n                break;\n            case IWM_UCODE_TLV_PAN:\n                if (tlv_len) {\n                    err = EINVAL;\n                    goto parse_out;\n                }\n                sc->sc_capaflags |= IWM_UCODE_TLV_FLAGS_PAN;\n                break;\n            case IWM_UCODE_TLV_FLAGS:\n                if (tlv_len < sizeof(uint32_t)) {\n                    err = EINVAL;\n                    goto parse_out;\n                }\n                /*\n                 * Apparently there can be many flags, but Linux driver\n                 * parses only the first one, and so do we.\n                 *\n                 * XXX: why does this override IWM_UCODE_TLV_PAN?\n                 * Intentional or a bug?  Observations from\n                 * current firmware file:\n                 *  1) TLV_PAN is parsed first\n                 *  2) TLV_FLAGS contains TLV_FLAGS_PAN\n                 * ==> this resets TLV_PAN to itself... hnnnk\n                 */\n                sc->sc_capaflags = le32toh(*(uint32_t *)tlv_data);\n                break;\n            case IWM_UCODE_TLV_CSCHEME:\n                err = iwm_store_cscheme(sc, (uint8_t*)tlv_data, tlv_len);\n                if (err)\n                    goto parse_out;\n                break;\n            case IWM_UCODE_TLV_NUM_OF_CPU: {\n                uint32_t num_cpu;\n                if (tlv_len != sizeof(uint32_t)) {\n                    err = EINVAL;\n                    goto parse_out;\n                }\n                num_cpu = le32toh(*(uint32_t *)tlv_data);\n                if (num_cpu < 1 || num_cpu > 2) {\n                    err = EINVAL;\n                    goto parse_out;\n                }\n                break;\n            }\n            case IWM_UCODE_TLV_SEC_RT:\n                err = iwm_firmware_store_section(sc,\n                                                 IWM_UCODE_TYPE_REGULAR, (uint8_t*)tlv_data, tlv_len);\n                if (err)\n                    goto parse_out;\n                break;\n            case IWM_UCODE_TLV_SEC_INIT:\n                err = iwm_firmware_store_section(sc,\n                                                 IWM_UCODE_TYPE_INIT, (uint8_t*)tlv_data, tlv_len);\n                if (err)\n                    goto parse_out;\n                break;\n            case IWM_UCODE_TLV_SEC_WOWLAN:\n                err = iwm_firmware_store_section(sc,\n                                                 IWM_UCODE_TYPE_WOW, (uint8_t*)tlv_data, tlv_len);\n                if (err)\n                    goto parse_out;\n                break;\n            case IWM_UCODE_TLV_DEF_CALIB:\n                if (tlv_len != sizeof(struct iwm_tlv_calib_data)) {\n                    err = EINVAL;\n                    goto parse_out;\n                }\n                err = iwm_set_default_calib(sc, tlv_data);\n                if (err)\n                    goto parse_out;\n                break;\n            case IWM_UCODE_TLV_PHY_SKU:\n                if (tlv_len != sizeof(uint32_t)) {\n                    err = EINVAL;\n                    goto parse_out;\n                }\n                sc->sc_fw_phy_config = le32toh(*(uint32_t *)tlv_data);\n                break;\n                \n            case IWM_UCODE_TLV_API_CHANGES_SET: {\n                struct iwm_ucode_api *api;\n                int idx, i;\n                if (tlv_len != sizeof(*api)) {\n                    err = EINVAL;\n                    goto parse_out;\n                }\n                api = (struct iwm_ucode_api *)tlv_data;\n                idx = le32toh(api->api_index);\n                if (idx >= howmany(IWM_NUM_UCODE_TLV_API, 32)) {\n                    err = EINVAL;\n                    goto parse_out;\n                }\n                for (i = 0; i < 32; i++) {\n                    if ((le32toh(api->api_flags) & (1 << i)) == 0)\n                        continue;\n                    setbit(sc->sc_ucode_api, i + (32 * idx));\n                }\n                break;\n            }\n                \n            case IWM_UCODE_TLV_ENABLED_CAPABILITIES: {\n                struct iwm_ucode_capa *capa;\n                int idx, i;\n                if (tlv_len != sizeof(*capa)) {\n                    err = EINVAL;\n                    goto parse_out;\n                }\n                capa = (struct iwm_ucode_capa *)tlv_data;\n                idx = le32toh(capa->api_index);\n                if (idx >= howmany(IWM_NUM_UCODE_TLV_CAPA, 32)) {\n                    goto parse_out;\n                }\n                for (i = 0; i < 32; i++) {\n                    if ((le32toh(capa->api_capa) & (1 << i)) == 0)\n                        continue;\n                    setbit(sc->sc_enabled_capa, i + (32 * idx));\n                }\n                break;\n            }\n                \n            case IWM_UCODE_TLV_CMD_VERSIONS:\n                if (tlv_len % sizeof(struct iwm_fw_cmd_version)) {\n                    tlv_len /= sizeof(struct iwm_fw_cmd_version);\n                    tlv_len *= sizeof(struct iwm_fw_cmd_version);\n                }\n                if (sc->n_cmd_versions != 0) {\n                    err = EINVAL;\n                    goto parse_out;\n                }\n                if (tlv_len > sizeof(sc->cmd_versions)) {\n                    err = EINVAL;\n                    goto parse_out;\n                }\n                memcpy(&sc->cmd_versions[0], tlv_data, tlv_len);\n                sc->n_cmd_versions = tlv_len / sizeof(struct iwm_fw_cmd_version);\n                break;\n            case IWM_UCODE_TLV_SDIO_ADMA_ADDR:\n            case IWM_UCODE_TLV_FW_GSCAN_CAPA:\n                /* ignore, not used by current driver */\n                break;\n                \n            case IWM_UCODE_TLV_SEC_RT_USNIFFER:\n                err = iwm_firmware_store_section(sc,\n                                                 IWM_UCODE_TYPE_REGULAR_USNIFFER, (uint8_t*)tlv_data,\n                                                 tlv_len);\n                if (err)\n                    goto parse_out;\n                break;\n                \n            case IWM_UCODE_TLV_PAGING:\n                if (tlv_len != sizeof(uint32_t)) {\n                    err = EINVAL;\n                    goto parse_out;\n                }\n                paging_mem_size = le32toh(*(const uint32_t *)tlv_data);\n                \n                DPRINTF((\"%s: Paging: paging enabled (size = %u bytes)\\n\",\n                      DEVNAME(sc), paging_mem_size));\n                if (paging_mem_size > IWM_MAX_PAGING_IMAGE_SIZE) {\n                    XYLog(\"%s: Driver only supports up to %u\"\n                          \" bytes for paging image (%u requested)\\n\",\n                          DEVNAME(sc), IWM_MAX_PAGING_IMAGE_SIZE,\n                          paging_mem_size);\n                    err = EINVAL;\n                    goto out;\n                }\n                if (paging_mem_size & (IWM_FW_PAGING_SIZE - 1)) {\n                    XYLog(\"%s: Paging: image isn't multiple of %u\\n\",\n                          DEVNAME(sc), IWM_FW_PAGING_SIZE);\n                    err = EINVAL;\n                    goto out;\n                }\n                \n                fw->fw_sects[IWM_UCODE_TYPE_REGULAR].paging_mem_size =\n                paging_mem_size;\n                usniffer_img = IWM_UCODE_TYPE_REGULAR_USNIFFER;\n                fw->fw_sects[usniffer_img].paging_mem_size =\n                paging_mem_size;\n                break;\n                \n            case IWM_UCODE_TLV_N_SCAN_CHANNELS:\n                if (tlv_len != sizeof(uint32_t)) {\n                    err = EINVAL;\n                    goto parse_out;\n                }\n                sc->sc_capa_n_scan_channels =\n                le32toh(*(uint32_t *)tlv_data);\n                if (sc->sc_capa_n_scan_channels > IWM_MAX_SCAN_CHANNELS) {\n                    err = ERANGE;\n                    goto parse_out;\n                }\n                break;\n                \n            case IWM_UCODE_TLV_FW_VERSION:\n                if (tlv_len != sizeof(uint32_t) * 3) {\n                    err = EINVAL;\n                    goto parse_out;\n                }\n                iwm_fw_version_str(sc->sc_fwver, sizeof(sc->sc_fwver),\n                                   le32toh(((uint32_t *)tlv_data)[0]),\n                                   le32toh(((uint32_t *)tlv_data)[1]),\n                                   le32toh(((uint32_t *)tlv_data)[2]));\n                break;\n                \n            case IWM_UCODE_TLV_FW_DBG_DEST:\n            case IWM_UCODE_TLV_FW_DBG_CONF:\n            case IWM_UCODE_TLV_UMAC_DEBUG_ADDRS:\n            case IWM_UCODE_TLV_LMAC_DEBUG_ADDRS:\n            case IWM_UCODE_TLV_TYPE_DEBUG_INFO:\n            case IWM_UCODE_TLV_TYPE_BUFFER_ALLOCATION:\n            case IWM_UCODE_TLV_TYPE_HCMD:\n            case IWM_UCODE_TLV_TYPE_REGIONS:\n            case IWM_UCODE_TLV_TYPE_TRIGGERS:\n                break;\n\n            case IWM_UCODE_TLV_HW_TYPE:\n                break;\n                \n            case IWM_UCODE_TLV_FW_MEM_SEG:\n                break;\n                /* undocumented TLVs found in iwm-9000-43 image */\n            case 0x1000003:\n            case 0x1000004:\n                break;\n            case 52://IWL_UCODE_TLV_IML\n            case 53://IWL_UCODE_TLV_FW_FMAC_API_VERSION\n            case 57://IWL_UCODE_TLV_FW_RECOVERY_INFO\n            case 59://IWL_UCODE_TLV_FW_FMAC_RECOVERY_INFO\n                break;\n            case 60: {//IWL_UCODE_TLV_FW_FSEQ_VERSION\n                typedef struct {\n                    u8 version[32];\n                    u8 sha1[20];\n                } SEQVER, *PSEQVER;\n                PSEQVER fseq_ver = (PSEQVER)tlv_data;\n                \n                if (tlv_len != sizeof(SEQVER)) {\n                    err = EINVAL;\n                    goto parse_out;\n                }\n                XYLog(\"TLV_FW_FSEQ_VERSION: %s\\n\",\n                         fseq_ver->version);\n            }\n                break;\n            /* TLVs 0x1000-0x2000 are for internal driver usage */\n            case 0x1000://IWL_UCODE_TLV_FW_DBG_DUMP_LST\n                \n                break;\n                \n            default:\n                err = EINVAL;\n                goto parse_out;\n        }\n        \n        /*\n         * Check for size_t overflow and ignore missing padding at\n         * end of firmware file.\n         */\n        if (roundup(tlv_len, 4) > len)\n            break;\n        \n        len -= roundup(tlv_len, 4);\n        data += roundup(tlv_len, 4);\n    }\n    \n    _KASSERT(err == 0);\n    \nparse_out:\n    if (err) {\n        XYLog(\"%s: firmware parse error %d, \"\n              \"section type %d\\n\", DEVNAME(sc), err, tlv_type);\n    }\n    \nout:\n    if (err) {\n        fw->fw_status = IWM_FW_STATUS_NONE;\n        if (fw->fw_rawdata != NULL)\n            iwm_fw_info_free(fw);\n    } else\n        fw->fw_status = IWM_FW_STATUS_DONE;\n    wakeupOn(&sc->sc_fw);\n    \n    OSSafeReleaseNULL(fwData);\n    return err;\n}\n\nint ItlIwm::\niwm_post_alive(struct iwm_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    int nwords;\n    int err, chnl;\n    uint32_t base;\n    \n    if (!iwm_nic_lock(sc))\n        return EBUSY;\n    \n    base = iwm_read_prph(sc, IWM_SCD_SRAM_BASE_ADDR);\n    \n    iwm_ict_reset(sc);\n    \n    iwm_nic_unlock(sc);\n    \n    /* Clear TX scheduler state in SRAM. */\n    nwords = (IWM_SCD_TRANS_TBL_MEM_UPPER_BOUND -\n              IWM_SCD_CONTEXT_MEM_LOWER_BOUND)\n    / sizeof(uint32_t);\n    err = iwm_write_mem(sc,\n                        sc->sched_base + IWM_SCD_CONTEXT_MEM_LOWER_BOUND,\n                        NULL, nwords);\n    if (err)\n        return err;\n    \n    if (!iwm_nic_lock(sc))\n        return EBUSY;\n    \n    /* Set physical address of TX scheduler rings (1KB aligned). */\n    iwm_write_prph(sc, IWM_SCD_DRAM_BASE_ADDR, sc->sched_dma.paddr >> 10);\n    \n    iwm_write_prph(sc, IWM_SCD_CHAINEXT_EN, 0);\n    \n    /* enable command channel */\n    err = iwm_enable_ac_txq(sc, sc->cmdqid, IWM_TX_FIFO_CMD);\n    if (err) {\n        iwm_nic_unlock(sc);\n        return err;\n    }\n    \n    /* Activate TX scheduler. */\n    iwm_write_prph(sc, IWM_SCD_TXFACT, 0xff);\n    \n    /* Enable DMA channels. */\n    for (chnl = 0; chnl < IWM_FH_TCSR_CHNL_NUM; chnl++) {\n        IWM_WRITE(sc, IWM_FH_TCSR_CHNL_TX_CONFIG_REG(chnl),\n                  IWM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |\n                  IWM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE);\n    }\n    \n    IWM_SETBITS(sc, IWM_FH_TX_CHICKEN_BITS_REG,\n                IWM_FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN);\n    \n    iwm_nic_unlock(sc);\n    \n    /* Enable L1-Active */\n    if (sc->sc_device_family < IWM_DEVICE_FAMILY_8000)\n        iwm_clear_bits_prph(sc, IWM_APMG_PCIDEV_STT_REG,\n                            IWM_APMG_PCIDEV_STT_VAL_L1_ACT_DIS);\n    \n    return err;\n}\n\nuint8_t ItlIwm::\niwm_fw_valid_tx_ant(struct iwm_softc *sc)\n{\n    uint8_t tx_ant;\n    \n    tx_ant = ((sc->sc_fw_phy_config & IWM_FW_PHY_CFG_TX_CHAIN)\n              >> IWM_FW_PHY_CFG_TX_CHAIN_POS);\n    \n    if (sc->sc_nvm.valid_tx_ant)\n        tx_ant &= sc->sc_nvm.valid_tx_ant;\n    \n    return tx_ant;\n}\n\nuint8_t ItlIwm::\niwm_fw_valid_rx_ant(struct iwm_softc *sc)\n{\n    uint8_t rx_ant;\n    \n    rx_ant = ((sc->sc_fw_phy_config & IWM_FW_PHY_CFG_RX_CHAIN)\n              >> IWM_FW_PHY_CFG_RX_CHAIN_POS);\n    \n    if (sc->sc_nvm.valid_rx_ant)\n        rx_ant &= sc->sc_nvm.valid_rx_ant;\n    \n    return rx_ant;\n}\n\nuint32_t ItlIwm::\niwm_get_tx_ant(struct iwm_softc *sc, struct ieee80211_node *ni,\n               int type, struct ieee80211_frame *wh)\n{\n    if (IEEE80211_IS_CHAN_2GHZ(ni->ni_chan) &&\n        !ItlIwm::iwm_coex_is_shared_ant_avail(sc))\n        return sc->non_shared_ant << RATE_MCS_ANT_POS;\n    \n    if (!IEEE80211_IS_MULTICAST(wh->i_addr1) && type == IEEE80211_FC0_TYPE_DATA)\n        return ((1 << sc->sc_tx_ant) << RATE_MCS_ANT_POS);\n    \n    return ((1 << sc->sc_mgmt_last_antenna_idx) << RATE_MCS_ANT_POS);\n}\n\nvoid ItlIwm::\niwm_toggle_tx_ant(struct iwm_softc *sc, uint8_t *ant)\n{\n    int i;\n    uint8_t ind = *ant;\n    uint8_t valid = iwm_fw_valid_tx_ant(sc);\n    for (i = 0; i < IWM_RATE_MCS_ANT_NUM; i++) {\n        ind = (ind + 1) % IWM_RATE_MCS_ANT_NUM;\n        if (valid & (1 << ind))\n            break;\n    }\n    \n    *ant = ind;\n}\n\nint ItlIwm::\niwm_firmware_load_sect(struct iwm_softc *sc, uint32_t dst_addr,\n                       const uint8_t *section, uint32_t byte_cnt)\n{\n    int err = EINVAL;\n    uint32_t chunk_sz, offset;\n    \n    chunk_sz = MIN(IWM_FH_MEM_TB_MAX_LENGTH, byte_cnt);\n    \n    for (offset = 0; offset < byte_cnt; offset += chunk_sz) {\n        uint32_t addr, len;\n        const uint8_t *data;\n        \n        addr = dst_addr + offset;\n        len = MIN(chunk_sz, byte_cnt - offset);\n        data = section + offset;\n        \n        err = iwm_firmware_load_chunk(sc, addr, data, len);\n        if (err)\n            break;\n    }\n    \n    return err;\n}\n\nint ItlIwm::\niwm_firmware_load_chunk(struct iwm_softc *sc, uint32_t dst_addr,\n                        const uint8_t *chunk, uint32_t byte_cnt)\n{\n    struct iwm_dma_info *dma = &sc->fw_dma;\n    int err;\n    \n    /* Copy firmware chunk into pre-allocated DMA-safe memory. */\n    memcpy(dma->vaddr, chunk, byte_cnt);\n    //        bus_dmamap_sync(sc->sc_dmat,\n    //            dma->map, 0, byte_cnt, BUS_DMASYNC_PREWRITE);\n    \n    if (dst_addr >= IWM_FW_MEM_EXTENDED_START &&\n        dst_addr <= IWM_FW_MEM_EXTENDED_END)\n        iwm_set_bits_prph(sc, IWM_LMPM_CHICK,\n                          IWM_LMPM_CHICK_EXTENDED_ADDR_SPACE);\n    \n    sc->sc_fw_chunk_done = 0;\n    \n    if (!iwm_nic_lock(sc))\n        return EBUSY;\n    \n    IWM_WRITE(sc, IWM_FH_TCSR_CHNL_TX_CONFIG_REG(IWM_FH_SRVC_CHNL),\n              IWM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE);\n    IWM_WRITE(sc, IWM_FH_SRVC_CHNL_SRAM_ADDR_REG(IWM_FH_SRVC_CHNL),\n              dst_addr);\n    IWM_WRITE(sc, IWM_FH_TFDIB_CTRL0_REG(IWM_FH_SRVC_CHNL),\n              dma->paddr & IWM_FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK);\n    IWM_WRITE(sc, IWM_FH_TFDIB_CTRL1_REG(IWM_FH_SRVC_CHNL),\n              (iwm_get_dma_hi_addr(dma->paddr)\n               << IWM_FH_MEM_TFDIB_REG1_ADDR_BITSHIFT) | byte_cnt);\n    IWM_WRITE(sc, IWM_FH_TCSR_CHNL_TX_BUF_STS_REG(IWM_FH_SRVC_CHNL),\n              1 << IWM_FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM |\n              1 << IWM_FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX |\n              IWM_FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID);\n    IWM_WRITE(sc, IWM_FH_TCSR_CHNL_TX_CONFIG_REG(IWM_FH_SRVC_CHNL),\n              IWM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE    |\n              IWM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE |\n              IWM_FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD);\n    \n    iwm_nic_unlock(sc);\n    \n    /* Wait for this segment to load. */\n    err = 0;\n    while (!sc->sc_fw_chunk_done) {\n        err = tsleep_nsec(&sc->sc_fw, 0, \"iwmfw\", SEC_TO_NSEC(1));\n        if (err)\n            break;\n    }\n    \n    if (!sc->sc_fw_chunk_done)\n        XYLog(\"%s: fw chunk addr 0x%x len %d failed to load\\n\",\n              DEVNAME(sc), dst_addr, byte_cnt);\n    \n    if (dst_addr >= IWM_FW_MEM_EXTENDED_START &&\n        dst_addr <= IWM_FW_MEM_EXTENDED_END) {\n        iwm_clear_bits_prph(sc, IWM_LMPM_CHICK,\n                            IWM_LMPM_CHICK_EXTENDED_ADDR_SPACE);\n    }\n    \n    return err;\n}\n\nint ItlIwm::\niwm_load_firmware_7000(struct iwm_softc *sc, enum iwm_ucode_type ucode_type)\n{\n    struct iwm_fw_sects *fws;\n    int err, i;\n    void *data;\n    uint32_t dlen;\n    uint32_t offset;\n    \n    fws = &sc->sc_fw.fw_sects[ucode_type];\n    for (i = 0; i < fws->fw_count; i++) {\n        data = fws->fw_sect[i].fws_data;\n        dlen = fws->fw_sect[i].fws_len;\n        offset = fws->fw_sect[i].fws_devoff;\n        if (dlen > sc->sc_fwdmasegsz) {\n            err = EFBIG;\n        } else\n            err = iwm_firmware_load_sect(sc, offset, (const uint8_t*)data, dlen);\n        if (err) {\n            XYLog(\"%s: could not load firmware chunk %u of %u\\n\",\n                  DEVNAME(sc), i, fws->fw_count);\n            return err;\n        }\n    }\n    \n    iwm_enable_interrupts(sc);\n    \n    IWM_WRITE(sc, IWM_CSR_RESET, 0);\n    \n    return 0;\n}\n\nint ItlIwm::\niwm_load_cpu_sections_8000(struct iwm_softc *sc, struct iwm_fw_sects *fws,\n                           int cpu, int *first_ucode_section)\n{\n    int shift_param;\n    int i, err = 0, sec_num = 0x1;\n    uint32_t val, last_read_idx = 0;\n    void *data;\n    uint32_t dlen;\n    uint32_t offset;\n    \n    if (cpu == 1) {\n        shift_param = 0;\n        *first_ucode_section = 0;\n    } else {\n        shift_param = 16;\n        (*first_ucode_section)++;\n    }\n    \n    for (i = *first_ucode_section; i < IWM_UCODE_SECT_MAX; i++) {\n        last_read_idx = i;\n        data = fws->fw_sect[i].fws_data;\n        dlen = fws->fw_sect[i].fws_len;\n        offset = fws->fw_sect[i].fws_devoff;\n        \n        /*\n         * CPU1_CPU2_SEPARATOR_SECTION delimiter - separate between\n         * CPU1 to CPU2.\n         * PAGING_SEPARATOR_SECTION delimiter - separate between\n         * CPU2 non paged to CPU2 paging sec.\n         */\n        if (!data || offset == IWM_CPU1_CPU2_SEPARATOR_SECTION ||\n            offset == IWM_PAGING_SEPARATOR_SECTION)\n            break;\n        \n        if (dlen > sc->sc_fwdmasegsz) {\n            err = EFBIG;\n        } else\n            err = iwm_firmware_load_sect(sc, offset, (const uint8_t*)data, dlen);\n        if (err) {\n            XYLog(\"%s: could not load firmware chunk %d \"\n                  \"(error %d)\\n\", DEVNAME(sc), i, err);\n            return err;\n        }\n        \n        /* Notify the ucode of the loaded section number and status */\n        if (iwm_nic_lock(sc)) {\n            val = IWM_READ(sc, IWM_FH_UCODE_LOAD_STATUS);\n            val = val | (sec_num << shift_param);\n            IWM_WRITE(sc, IWM_FH_UCODE_LOAD_STATUS, val);\n            sec_num = (sec_num << 1) | 0x1;\n            iwm_nic_unlock(sc);\n        } else {\n            err = EBUSY;\n            XYLog(\"%s: could not load firmware chunk %d \"\n                  \"(error %d)\\n\", DEVNAME(sc), i, err);\n            return err;\n        }\n    }\n    \n    *first_ucode_section = last_read_idx;\n    \n    if (iwm_nic_lock(sc)) {\n        if (cpu == 1)\n            IWM_WRITE(sc, IWM_FH_UCODE_LOAD_STATUS, 0xFFFF);\n        else\n            IWM_WRITE(sc, IWM_FH_UCODE_LOAD_STATUS, 0xFFFFFFFF);\n        iwm_nic_unlock(sc);\n    } else {\n        err = EBUSY;\n        XYLog(\"%s: could not finalize firmware loading (error %d)\\n\",\n              DEVNAME(sc), err);\n        return err;\n    }\n    \n    return 0;\n}\n\nint ItlIwm::\niwm_load_firmware_8000(struct iwm_softc *sc, enum iwm_ucode_type ucode_type)\n{\n    struct iwm_fw_sects *fws;\n    int err = 0;\n    int first_ucode_section;\n    \n    fws = &sc->sc_fw.fw_sects[ucode_type];\n    \n    /* configure the ucode to be ready to get the secured image */\n    /* release CPU reset */\n    if (iwm_nic_lock(sc)) {\n        iwm_write_prph(sc, IWM_RELEASE_CPU_RESET,\n                       IWM_RELEASE_CPU_RESET_BIT);\n        iwm_nic_unlock(sc);\n    }\n    \n    /* load to FW the binary Secured sections of CPU1 */\n    err = iwm_load_cpu_sections_8000(sc, fws, 1, &first_ucode_section);\n    if (err)\n        return err;\n    \n    /* load to FW the binary sections of CPU2 */\n    err = iwm_load_cpu_sections_8000(sc, fws, 2, &first_ucode_section);\n    if (err)\n        return err;\n    \n    iwm_enable_interrupts(sc);\n    return 0;\n}\n\nint ItlIwm::\niwm_load_firmware(struct iwm_softc *sc, enum iwm_ucode_type ucode_type)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    int err/*, w*/;\n    \n    sc->sc_uc.uc_intr = 0;\n    \n    if (sc->sc_device_family >= IWM_DEVICE_FAMILY_8000)\n        err = iwm_load_firmware_8000(sc, ucode_type);\n    else\n        err = iwm_load_firmware_7000(sc, ucode_type);\n    \n    if (err)\n        return err;\n    \n    /* wait for the firmware to load */\n//    for (w = 0; !sc->sc_uc.uc_intr && w < 10; w++) {\n//        err = tsleep_nsec(&sc->sc_uc, 0, \"iwmuc\", MSEC_TO_NSEC(100));\n//    }\n    err = tsleep_nsec(&sc->sc_uc, 0, \"iwmuc\", SEC_TO_NSEC(1));\n    if (err || !sc->sc_uc.uc_ok)\n        XYLog(\"%s: could not load firmware\\n\", DEVNAME(sc));\n    \n    return err;\n}\n\nint ItlIwm::\niwm_start_fw(struct iwm_softc *sc, enum iwm_ucode_type ucode_type)\n{\n    XYLog(\"%s ucode_type=%d\\n\", __FUNCTION__, ucode_type);\n    int err;\n    \n    IWM_WRITE(sc, IWM_CSR_INT, ~0);\n    \n    err = iwm_nic_init(sc);\n    if (err) {\n        XYLog(\"%s: unable to init nic\\n\", DEVNAME(sc));\n        return err;\n    }\n    \n    /* make sure rfkill handshake bits are cleared */\n    IWM_WRITE(sc, IWM_CSR_UCODE_DRV_GP1_CLR, IWM_CSR_UCODE_SW_BIT_RFKILL);\n    IWM_WRITE(sc, IWM_CSR_UCODE_DRV_GP1_CLR,\n              IWM_CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);\n    \n    /* clear (again), then enable firwmare load interrupt */\n    IWM_WRITE(sc, IWM_CSR_INT, ~0);\n    iwm_enable_fwload_interrupt(sc);\n    \n    /* really make sure rfkill handshake bits are cleared */\n    /* maybe we should write a few times more?  just to make sure */\n    IWM_WRITE(sc, IWM_CSR_UCODE_DRV_GP1_CLR, IWM_CSR_UCODE_SW_BIT_RFKILL);\n    IWM_WRITE(sc, IWM_CSR_UCODE_DRV_GP1_CLR, IWM_CSR_UCODE_SW_BIT_RFKILL);\n    \n    return iwm_load_firmware(sc, ucode_type);\n}\n\nint ItlIwm::\niwm_send_tx_ant_cfg(struct iwm_softc *sc, uint8_t valid_tx_ant)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwm_tx_ant_cfg_cmd tx_ant_cmd = {\n        .valid = htole32(valid_tx_ant),\n    };\n    \n    return iwm_send_cmd_pdu(sc, IWM_TX_ANT_CONFIGURATION_CMD,\n                            0, sizeof(tx_ant_cmd), &tx_ant_cmd);\n}\n\nint ItlIwm::\niwm_load_ucode_wait_alive(struct iwm_softc *sc,\n                          enum iwm_ucode_type ucode_type)\n{\n    XYLog(\"%s ucode_type=%d\\n\", __FUNCTION__, ucode_type);\n    enum iwm_ucode_type old_type = sc->sc_uc_current;\n    struct iwm_fw_sects *fw = &sc->sc_fw.fw_sects[ucode_type];\n    int err;\n    \n    err = iwm_read_firmware(sc, ucode_type);\n    if (err)\n        return err;\n    \n    if (isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_DQA_SUPPORT))\n        sc->cmdqid = IWM_DQA_CMD_QUEUE;\n    else\n        sc->cmdqid = IWM_CMD_QUEUE;\n    \n    sc->sc_uc_current = ucode_type;\n    err = iwm_start_fw(sc, ucode_type);\n    if (err) {\n        sc->sc_uc_current = old_type;\n        return err;\n    }\n    \n    err = iwm_post_alive(sc);\n    if (err)\n        return err;\n    \n    /*\n     * configure and operate fw paging mechanism.\n     * driver configures the paging flow only once, CPU2 paging image\n     * included in the IWM_UCODE_INIT image.\n     */\n    if (fw->paging_mem_size) {\n        err = iwm_save_fw_paging(sc, fw);\n        if (err) {\n            XYLog(\"%s: failed to save the FW paging image\\n\",\n                  DEVNAME(sc));\n            return err;\n        }\n        \n        err = iwm_send_paging_cmd(sc, fw);\n        if (err) {\n            XYLog(\"%s: failed to send the paging cmd\\n\",\n                  DEVNAME(sc));\n            iwm_free_fw_paging(sc);\n            return err;\n        }\n    }\n    \n    return 0;\n}\n\nint ItlIwm::\niwm_run_init_mvm_ucode(struct iwm_softc *sc, int justnvm)\n{\n    XYLog(\"%s justnvm=%d\\n\", __FUNCTION__, justnvm);\n    const int wait_flags = (IWM_INIT_COMPLETE | IWM_CALIB_COMPLETE);\n    int err;\n    \n    if ((sc->sc_flags & IWM_FLAG_RFKILL) && !justnvm) {\n        XYLog(\"%s: radio is disabled by hardware switch\\n\",\n              DEVNAME(sc));\n        return EPERM;\n    }\n    \n    sc->sc_init_complete = 0;\n    err = iwm_load_ucode_wait_alive(sc, IWM_UCODE_TYPE_INIT);\n    if (err) {\n        XYLog(\"%s: failed to load init firmware\\n\", DEVNAME(sc));\n        return err;\n    }\n    \n    if (sc->sc_device_family < IWM_DEVICE_FAMILY_8000) {\n        err = iwm_send_bt_init_conf(sc);\n        if (err) {\n            XYLog(\"%s: could not init bt coex (error %d)\\n\",\n                  DEVNAME(sc), err);\n            return err;\n        }\n    }\n    \n    if (justnvm) {\n        err = iwm_nvm_init(sc);\n        if (err) {\n            XYLog(\"%s: failed to read nvm\\n\", DEVNAME(sc));\n            return err;\n        }\n        \n        if (IEEE80211_ADDR_EQ(etheranyaddr, sc->sc_ic.ic_myaddr))\n            IEEE80211_ADDR_COPY(sc->sc_ic.ic_myaddr,\n                                sc->sc_nvm.hw_addr);\n        \n        return 0;\n    }\n    \n    err = iwm_sf_config(sc, IWM_SF_INIT_OFF);\n    if (err)\n        return err;\n    \n    /* Send TX valid antennas before triggering calibrations */\n    err = iwm_send_tx_ant_cfg(sc, iwm_fw_valid_tx_ant(sc));\n    if (err)\n        return err;\n    \n    /*\n     * Send phy configurations command to init uCode\n     * to start the 16.0 uCode init image internal calibrations.\n     */\n    err = iwm_send_phy_cfg_cmd(sc);\n    if (err)\n        return err;\n    \n    /*\n     * Nothing to do but wait for the init complete and phy DB\n     * notifications from the firmware.\n     */\n//    while ((sc->sc_init_complete & wait_flags) != wait_flags) {\n//        err = tsleep_nsec(&sc->sc_init_complete, 0, \"iwminit\",\n//                          SEC_TO_NSEC(2));\n//        if (err)\n//            break;\n//    }\n    err = tsleep_nsec(&sc->sc_init_complete, 0, \"iwminit\", SEC_TO_NSEC(2));\n    \n    return err;\n}\n\nint ItlIwm::\niwm_config_ltr(struct iwm_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwm_ltr_config_cmd cmd = {\n        .flags = htole32(IWM_LTR_CFG_FLAG_FEATURE_ENABLE),\n    };\n    \n    if (!sc->sc_ltr_enabled)\n        return 0;\n    \n    return iwm_send_cmd_pdu(sc, IWM_LTR_CONFIG, 0, sizeof(cmd), &cmd);\n}\n"
  },
  {
    "path": "itlwm/hal_iwm/hw.cpp",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n/*    $OpenBSD: if_iwm.c,v 1.316 2020/12/07 20:09:24 tobhe Exp $    */\n\n/*\n * Copyright (c) 2014, 2016 genua gmbh <info@genua.de>\n *   Author: Stefan Sperling <stsp@openbsd.org>\n * Copyright (c) 2014 Fixup Software Ltd.\n * Copyright (c) 2017 Stefan Sperling <stsp@openbsd.org>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n/*-\n * Based on BSD-licensed source modules in the Linux iwlwifi driver,\n * which were used as the reference documentation for this implementation.\n *\n ***********************************************************************\n *\n * This file is provided under a dual BSD/GPLv2 license.  When using or\n * redistributing this file, you may do so under either license.\n *\n * GPL LICENSE SUMMARY\n *\n * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.\n * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH\n * Copyright(c) 2016 Intel Deutschland GmbH\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of version 2 of the GNU General Public License as\n * published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful, but\n * WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,\n * USA\n *\n * The full GNU General Public License is included in this distribution\n * in the file called COPYING.\n *\n * Contact Information:\n *  Intel Linux Wireless <ilw@linux.intel.com>\n * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497\n *\n *\n * BSD LICENSE\n *\n * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.\n * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH\n * Copyright(c) 2016 Intel Deutschland GmbH\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in\n *    the documentation and/or other materials provided with the\n *    distribution.\n *  * Neither the name Intel Corporation nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*-\n * Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n#include \"ItlIwm.hpp\"\n\nvoid ItlIwm::\niwm_enable_rfkill_int(struct iwm_softc *sc)\n{\n    if (!sc->sc_msix) {\n        sc->sc_intmask = IWM_CSR_INT_BIT_RF_KILL;\n        IWM_WRITE(sc, IWM_CSR_INT_MASK, sc->sc_intmask);\n    } else {\n        IWM_WRITE(sc, IWM_CSR_MSIX_FH_INT_MASK_AD,\n                  sc->sc_fh_init_mask);\n        IWM_WRITE(sc, IWM_CSR_MSIX_HW_INT_MASK_AD,\n                  ~IWM_MSIX_HW_INT_CAUSES_REG_RF_KILL);\n        sc->sc_hw_mask = IWM_MSIX_HW_INT_CAUSES_REG_RF_KILL;\n    }\n    \n    if (sc->sc_device_family >= IWM_DEVICE_FAMILY_9000)\n        IWM_SETBITS(sc, IWM_CSR_GP_CNTRL,\n                    IWM_CSR_GP_CNTRL_REG_FLAG_RFKILL_WAKE_L1A_EN);\n}\n\nint ItlIwm::\niwm_check_rfkill(struct iwm_softc *sc)\n{\n    uint32_t v;\n    int s;\n    int rv;\n    \n    s = splnet();\n    \n    /*\n     * \"documentation\" is not really helpful here:\n     *  27:    HW_RF_KILL_SW\n     *    Indicates state of (platform's) hardware RF-Kill switch\n     *\n     * But apparently when it's off, it's on ...\n     */\n    v = IWM_READ(sc, IWM_CSR_GP_CNTRL);\n    rv = (v & IWM_CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) == 0;\n    if (rv) {\n        sc->sc_flags |= IWM_FLAG_RFKILL;\n    } else {\n        sc->sc_flags &= ~IWM_FLAG_RFKILL;\n    }\n    \n    XYLog(\"%s RF_KILL hw: %d\\n\", __FUNCTION__, rv);\n\n    splx(s);\n    return rv;\n}\n\nvoid ItlIwm::\niwm_enable_interrupts(struct iwm_softc *sc)\n{\n    if (!sc->sc_msix) {\n        sc->sc_intmask = IWM_CSR_INI_SET_MASK;\n        IWM_WRITE(sc, IWM_CSR_INT_MASK, sc->sc_intmask);\n    } else {\n        /*\n         * fh/hw_mask keeps all the unmasked causes.\n         * Unlike msi, in msix cause is enabled when it is unset.\n         */\n        sc->sc_hw_mask = sc->sc_hw_init_mask;\n        sc->sc_fh_mask = sc->sc_fh_init_mask;\n        IWM_WRITE(sc, IWM_CSR_MSIX_FH_INT_MASK_AD,\n                  ~sc->sc_fh_mask);\n        IWM_WRITE(sc, IWM_CSR_MSIX_HW_INT_MASK_AD,\n                  ~sc->sc_hw_mask);\n    }\n}\n\nvoid ItlIwm::\niwm_enable_fwload_interrupt(struct iwm_softc *sc)\n{\n    if (!sc->sc_msix) {\n        sc->sc_intmask = IWM_CSR_INT_BIT_FH_TX;\n        IWM_WRITE(sc, IWM_CSR_INT_MASK, sc->sc_intmask);\n    } else {\n        IWM_WRITE(sc, IWM_CSR_MSIX_HW_INT_MASK_AD,\n                  sc->sc_hw_init_mask);\n        IWM_WRITE(sc, IWM_CSR_MSIX_FH_INT_MASK_AD,\n                  ~IWM_MSIX_FH_INT_CAUSES_D2S_CH0_NUM);\n        sc->sc_fh_mask = IWM_MSIX_FH_INT_CAUSES_D2S_CH0_NUM;\n    }\n}\n\nvoid ItlIwm::\niwm_disable_interrupts(struct iwm_softc *sc)\n{\n    int s = splnet();\n    \n    if (!sc->sc_msix) {\n        IWM_WRITE(sc, IWM_CSR_INT_MASK, 0);\n        \n        /* acknowledge all interrupts */\n        IWM_WRITE(sc, IWM_CSR_INT, ~0);\n        IWM_WRITE(sc, IWM_CSR_FH_INT_STATUS, ~0);\n    } else {\n        IWM_WRITE(sc, IWM_CSR_MSIX_FH_INT_MASK_AD,\n                  sc->sc_fh_init_mask);\n        IWM_WRITE(sc, IWM_CSR_MSIX_HW_INT_MASK_AD,\n                  sc->sc_hw_init_mask);\n    }\n    \n    splx(s);\n}\n\nvoid ItlIwm::\niwm_ict_reset(struct iwm_softc *sc)\n{\n    iwm_disable_interrupts(sc);\n    \n    memset(sc->ict_dma.vaddr, 0, IWM_ICT_SIZE);\n    sc->ict_cur = 0;\n    \n    /* Set physical address of ICT (4KB aligned). */\n    IWM_WRITE(sc, IWM_CSR_DRAM_INT_TBL_REG,\n              IWM_CSR_DRAM_INT_TBL_ENABLE\n              | IWM_CSR_DRAM_INIT_TBL_WRAP_CHECK\n              | IWM_CSR_DRAM_INIT_TBL_WRITE_POINTER\n              | sc->ict_dma.paddr >> IWM_ICT_PADDR_SHIFT);\n    \n    /* Switch to ICT interrupt mode in driver. */\n    sc->sc_flags |= IWM_FLAG_USE_ICT;\n    \n    IWM_WRITE(sc, IWM_CSR_INT, ~0);\n    iwm_enable_interrupts(sc);\n}\n\n#define IWM_HW_READY_TIMEOUT 50\nint ItlIwm::\niwm_set_hw_ready(struct iwm_softc *sc)\n{\n    int ready;\n    \n    IWM_SETBITS(sc, IWM_CSR_HW_IF_CONFIG_REG,\n                IWM_CSR_HW_IF_CONFIG_REG_BIT_NIC_READY);\n    \n    ready = iwm_poll_bit(sc, IWM_CSR_HW_IF_CONFIG_REG,\n                         IWM_CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,\n                         IWM_CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,\n                         IWM_HW_READY_TIMEOUT);\n    if (ready)\n        IWM_SETBITS(sc, IWM_CSR_MBOX_SET_REG,\n                    IWM_CSR_MBOX_SET_REG_OS_ALIVE);\n    \n    return ready;\n}\n#undef IWM_HW_READY_TIMEOUT\n\nint ItlIwm::\niwm_prepare_card_hw(struct iwm_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    int t = 0;\n    int ntries;\n    \n    if (iwm_set_hw_ready(sc))\n        return 0;\n    \n    IWM_SETBITS(sc, IWM_CSR_DBG_LINK_PWR_MGMT_REG,\n                IWM_CSR_RESET_LINK_PWR_MGMT_DISABLED);\n    DELAY(1000);\n    \n    for (ntries = 0; ntries < 10; ntries++) {\n        /* If HW is not ready, prepare the conditions to check again */\n        IWM_SETBITS(sc, IWM_CSR_HW_IF_CONFIG_REG,\n                    IWM_CSR_HW_IF_CONFIG_REG_PREPARE);\n        do {\n            if (iwm_set_hw_ready(sc))\n                return 0;\n            DELAY(200);\n            t += 200;\n        } while (t < 150000);\n        DELAY(25000);\n    }\n    \n    return ETIMEDOUT;\n}\n\nvoid ItlIwm::\niwm_apm_config(struct iwm_softc *sc)\n{\n    pcireg_t lctl, cap;\n    \n    /*\n     * L0S states have been found to be unstable with our devices\n     * and in newer hardware they are not officially supported at\n     * all, so we must always set the L0S_DISABLED bit.\n     */\n    lctl = pci_conf_read(sc->sc_pct, sc->sc_pcitag,\n                         sc->sc_cap_off + PCI_PCIE_LCSR);\n    IWM_SETBITS(sc, IWM_CSR_GIO_REG, IWM_CSR_GIO_REG_VAL_L0S_DISABLED);\n    /*\n    * Disable L0s and L1s in PCIE register because we don't support ASPM now.\n    */\n    lctl &= ~(PCI_PCIE_LCSR_ASPM_L0S | PCI_PCIE_LCSR_ASPM_L1);\n    pci_conf_write(sc->sc_pct, sc->sc_pcitag, sc->sc_cap_off + PCI_PCIE_LCSR, lctl);\n    lctl = pci_conf_read(sc->sc_pct, sc->sc_pcitag, sc->sc_cap_off + PCI_PCIE_LCSR);\n    \n    cap = pci_conf_read(sc->sc_pct, sc->sc_pcitag,\n                        sc->sc_cap_off + PCI_PCIE_DCSR2);\n    sc->sc_ltr_enabled = (cap & PCI_PCIE_DCSR2_LTREN) ? 1 : 0;\n    XYLog(\"%s: L1 %sabled - LTR %sabled\\n\",\n          DEVNAME(sc),\n          (lctl & PCI_PCIE_LCSR_ASPM_L1) ? \"En\" : \"Dis\",\n          sc->sc_ltr_enabled ? \"En\" : \"Dis\");\n}\n\n/*\n * Start up NIC's basic functionality after it has been reset\n * e.g. after platform boot or shutdown.\n * NOTE:  This does not load uCode nor start the embedded processor\n */\nint ItlIwm::\niwm_apm_init(struct iwm_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    int err = 0;\n    \n    /* Disable L0S exit timer (platform NMI workaround) */\n    if (sc->sc_device_family < IWM_DEVICE_FAMILY_8000)\n        IWM_SETBITS(sc, IWM_CSR_GIO_CHICKEN_BITS,\n                    IWM_CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);\n    \n    /*\n     * Disable L0s without affecting L1;\n     *  don't wait for ICH L0s (ICH bug W/A)\n     */\n    IWM_SETBITS(sc, IWM_CSR_GIO_CHICKEN_BITS,\n                IWM_CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX);\n    \n    /* Set FH wait threshold to maximum (HW error during stress W/A) */\n    IWM_SETBITS(sc, IWM_CSR_DBG_HPET_MEM_REG, IWM_CSR_DBG_HPET_MEM_REG_VAL);\n    \n    /*\n     * Enable HAP INTA (interrupt from management bus) to\n     * wake device's PCI Express link L1a -> L0s\n     */\n    IWM_SETBITS(sc, IWM_CSR_HW_IF_CONFIG_REG,\n                IWM_CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A);\n    \n    iwm_apm_config(sc);\n    \n#if 0 /* not for 7k/8k */\n    /* Configure analog phase-lock-loop before activating to D0A */\n    if (trans->cfg->base_params->pll_cfg_val)\n        IWM_SETBITS(trans, IWM_CSR_ANA_PLL_CFG,\n                    trans->cfg->base_params->pll_cfg_val);\n#endif\n    \n    /*\n     * Set \"initialization complete\" bit to move adapter from\n     * D0U* --> D0A* (powered-up active) state.\n     */\n    IWM_SETBITS(sc, IWM_CSR_GP_CNTRL, IWM_CSR_GP_CNTRL_REG_FLAG_INIT_DONE);\n    \n    /*\n     * Wait for clock stabilization; once stabilized, access to\n     * device-internal resources is supported, e.g. iwm_write_prph()\n     * and accesses to uCode SRAM.\n     */\n    if (!iwm_poll_bit(sc, IWM_CSR_GP_CNTRL,\n                      IWM_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,\n                      IWM_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000)) {\n        XYLog(\"%s: timeout waiting for clock stabilization\\n\",\n              DEVNAME(sc));\n        err = ETIMEDOUT;\n        goto out;\n    }\n    \n    if (sc->host_interrupt_operation_mode) {\n        /*\n         * This is a bit of an abuse - This is needed for 7260 / 3160\n         * only check host_interrupt_operation_mode even if this is\n         * not related to host_interrupt_operation_mode.\n         *\n         * Enable the oscillator to count wake up time for L1 exit. This\n         * consumes slightly more power (100uA) - but allows to be sure\n         * that we wake up from L1 on time.\n         *\n         * This looks weird: read twice the same register, discard the\n         * value, set a bit, and yet again, read that same register\n         * just to discard the value. But that's the way the hardware\n         * seems to like it.\n         */\n        if (iwm_nic_lock(sc)) {\n            iwm_read_prph(sc, IWM_OSC_CLK);\n            iwm_read_prph(sc, IWM_OSC_CLK);\n            iwm_nic_unlock(sc);\n        }\n        iwm_set_bits_prph(sc, IWM_OSC_CLK, IWM_OSC_CLK_FORCE_CONTROL);\n        if (iwm_nic_lock(sc)) {\n            iwm_read_prph(sc, IWM_OSC_CLK);\n            iwm_read_prph(sc, IWM_OSC_CLK);\n            iwm_nic_unlock(sc);\n        }\n    }\n    \n    /*\n     * Enable DMA clock and wait for it to stabilize.\n     *\n     * Write to \"CLK_EN_REG\"; \"1\" bits enable clocks, while \"0\" bits\n     * do not disable clocks.  This preserves any hardware bits already\n     * set by default in \"CLK_CTRL_REG\" after reset.\n     */\n    if (sc->sc_device_family == IWM_DEVICE_FAMILY_7000) {\n        if (iwm_nic_lock(sc)) {\n            iwm_write_prph(sc, IWM_APMG_CLK_EN_REG,\n                           IWM_APMG_CLK_VAL_DMA_CLK_RQT);\n            iwm_nic_unlock(sc);\n        }\n        DELAY(20);\n        \n        /* Disable L1-Active */\n        iwm_set_bits_prph(sc, IWM_APMG_PCIDEV_STT_REG,\n                          IWM_APMG_PCIDEV_STT_VAL_L1_ACT_DIS);\n        \n        /* Clear the interrupt in APMG if the NIC is in RFKILL */\n        if (iwm_nic_lock(sc)) {\n            iwm_write_prph(sc, IWM_APMG_RTC_INT_STT_REG,\n                           IWM_APMG_RTC_INT_STT_RFKILL);\n            iwm_nic_unlock(sc);\n        }\n    }\nout:\n    if (err)\n        XYLog(\"%s: apm init error %d\\n\", DEVNAME(sc), err);\n    return err;\n}\n\nvoid ItlIwm::\niwm_apm_stop(struct iwm_softc *sc)\n{\n    IWM_SETBITS(sc, IWM_CSR_DBG_LINK_PWR_MGMT_REG,\n                IWM_CSR_RESET_LINK_PWR_MGMT_DISABLED);\n    IWM_SETBITS(sc, IWM_CSR_HW_IF_CONFIG_REG,\n                IWM_CSR_HW_IF_CONFIG_REG_PREPARE |\n                IWM_CSR_HW_IF_CONFIG_REG_ENABLE_PME);\n    DELAY(1000);\n    IWM_CLRBITS(sc, IWM_CSR_DBG_LINK_PWR_MGMT_REG,\n                IWM_CSR_RESET_LINK_PWR_MGMT_DISABLED);\n    DELAY(5000);\n    \n    /* stop device's busmaster DMA activity */\n    IWM_SETBITS(sc, IWM_CSR_RESET, IWM_CSR_RESET_REG_FLAG_STOP_MASTER);\n    \n    if (!iwm_poll_bit(sc, IWM_CSR_RESET,\n                      IWM_CSR_RESET_REG_FLAG_MASTER_DISABLED,\n                      IWM_CSR_RESET_REG_FLAG_MASTER_DISABLED, 100))\n        XYLog(\"%s: timeout waiting for master\\n\", DEVNAME(sc));\n    \n    /*\n     * Clear \"initialization complete\" bit to move adapter from\n     * D0A* (powered-up Active) --> D0U* (Uninitialized) state.\n     */\n    IWM_CLRBITS(sc, IWM_CSR_GP_CNTRL,\n                IWM_CSR_GP_CNTRL_REG_FLAG_INIT_DONE);\n}\n\nvoid ItlIwm::\niwm_init_msix_hw(struct iwm_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    iwm_conf_msix_hw(sc, 0);\n    \n    if (!sc->sc_msix)\n        return;\n    \n    sc->sc_fh_init_mask = ~IWM_READ(sc, IWM_CSR_MSIX_FH_INT_MASK_AD);\n    sc->sc_fh_mask = sc->sc_fh_init_mask;\n    sc->sc_hw_init_mask = ~IWM_READ(sc, IWM_CSR_MSIX_HW_INT_MASK_AD);\n    sc->sc_hw_mask = sc->sc_hw_init_mask;\n}\n\nvoid ItlIwm::\niwm_conf_msix_hw(struct iwm_softc *sc, int stopped)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    int vector = 0;\n    \n    if (!sc->sc_msix) {\n        /* Newer chips default to MSIX. */\n        if (sc->sc_mqrx_supported && !stopped && iwm_nic_lock(sc)) {\n            iwm_write_prph(sc, IWM_UREG_CHICK,\n                           IWM_UREG_CHICK_MSI_ENABLE);\n            iwm_nic_unlock(sc);\n        }\n        return;\n    }\n    \n    if (!stopped && iwm_nic_lock(sc)) {\n        iwm_write_prph(sc, IWM_UREG_CHICK, IWM_UREG_CHICK_MSIX_ENABLE);\n        iwm_nic_unlock(sc);\n    }\n    \n    /* Disable all interrupts */\n    IWM_WRITE(sc, IWM_CSR_MSIX_FH_INT_MASK_AD, ~0);\n    IWM_WRITE(sc, IWM_CSR_MSIX_HW_INT_MASK_AD, ~0);\n    \n    /* Map fallback-queue (command/mgmt) to a single vector */\n    IWM_WRITE_1(sc, IWM_CSR_MSIX_RX_IVAR(0),\n                vector | IWM_MSIX_NON_AUTO_CLEAR_CAUSE);\n    /* Map RSS queue (data) to the same vector */\n    IWM_WRITE_1(sc, IWM_CSR_MSIX_RX_IVAR(1),\n                vector | IWM_MSIX_NON_AUTO_CLEAR_CAUSE);\n    \n    /* Enable the RX queues cause interrupts */\n    IWM_CLRBITS(sc, IWM_CSR_MSIX_FH_INT_MASK_AD,\n                IWM_MSIX_FH_INT_CAUSES_Q0 | IWM_MSIX_FH_INT_CAUSES_Q1);\n    \n    /* Map non-RX causes to the same vector */\n    IWM_WRITE_1(sc, IWM_CSR_MSIX_IVAR(IWM_MSIX_IVAR_CAUSE_D2S_CH0_NUM),\n                vector | IWM_MSIX_NON_AUTO_CLEAR_CAUSE);\n    IWM_WRITE_1(sc, IWM_CSR_MSIX_IVAR(IWM_MSIX_IVAR_CAUSE_D2S_CH1_NUM),\n                vector | IWM_MSIX_NON_AUTO_CLEAR_CAUSE);\n    IWM_WRITE_1(sc, IWM_CSR_MSIX_IVAR(IWM_MSIX_IVAR_CAUSE_S2D),\n                vector | IWM_MSIX_NON_AUTO_CLEAR_CAUSE);\n    IWM_WRITE_1(sc, IWM_CSR_MSIX_IVAR(IWM_MSIX_IVAR_CAUSE_FH_ERR),\n                vector | IWM_MSIX_NON_AUTO_CLEAR_CAUSE);\n    IWM_WRITE_1(sc, IWM_CSR_MSIX_IVAR(IWM_MSIX_IVAR_CAUSE_REG_ALIVE),\n                vector | IWM_MSIX_NON_AUTO_CLEAR_CAUSE);\n    IWM_WRITE_1(sc, IWM_CSR_MSIX_IVAR(IWM_MSIX_IVAR_CAUSE_REG_WAKEUP),\n                vector | IWM_MSIX_NON_AUTO_CLEAR_CAUSE);\n    IWM_WRITE_1(sc, IWM_CSR_MSIX_IVAR(IWM_MSIX_IVAR_CAUSE_REG_IML),\n                vector | IWM_MSIX_NON_AUTO_CLEAR_CAUSE);\n    IWM_WRITE_1(sc, IWM_CSR_MSIX_IVAR(IWM_MSIX_IVAR_CAUSE_REG_CT_KILL),\n                vector | IWM_MSIX_NON_AUTO_CLEAR_CAUSE);\n    IWM_WRITE_1(sc, IWM_CSR_MSIX_IVAR(IWM_MSIX_IVAR_CAUSE_REG_RF_KILL),\n                vector | IWM_MSIX_NON_AUTO_CLEAR_CAUSE);\n    IWM_WRITE_1(sc, IWM_CSR_MSIX_IVAR(IWM_MSIX_IVAR_CAUSE_REG_PERIODIC),\n                vector | IWM_MSIX_NON_AUTO_CLEAR_CAUSE);\n    IWM_WRITE_1(sc, IWM_CSR_MSIX_IVAR(IWM_MSIX_IVAR_CAUSE_REG_SW_ERR),\n                vector | IWM_MSIX_NON_AUTO_CLEAR_CAUSE);\n    IWM_WRITE_1(sc, IWM_CSR_MSIX_IVAR(IWM_MSIX_IVAR_CAUSE_REG_SCD),\n                vector | IWM_MSIX_NON_AUTO_CLEAR_CAUSE);\n    IWM_WRITE_1(sc, IWM_CSR_MSIX_IVAR(IWM_MSIX_IVAR_CAUSE_REG_FH_TX),\n                vector | IWM_MSIX_NON_AUTO_CLEAR_CAUSE);\n    IWM_WRITE_1(sc, IWM_CSR_MSIX_IVAR(IWM_MSIX_IVAR_CAUSE_REG_HW_ERR),\n                vector | IWM_MSIX_NON_AUTO_CLEAR_CAUSE);\n    IWM_WRITE_1(sc, IWM_CSR_MSIX_IVAR(IWM_MSIX_IVAR_CAUSE_REG_HAP),\n                vector | IWM_MSIX_NON_AUTO_CLEAR_CAUSE);\n    \n    /* Enable non-RX causes interrupts */\n    IWM_CLRBITS(sc, IWM_CSR_MSIX_FH_INT_MASK_AD,\n                IWM_MSIX_FH_INT_CAUSES_D2S_CH0_NUM |\n                IWM_MSIX_FH_INT_CAUSES_D2S_CH1_NUM |\n                IWM_MSIX_FH_INT_CAUSES_S2D |\n                IWM_MSIX_FH_INT_CAUSES_FH_ERR);\n    IWM_CLRBITS(sc, IWM_CSR_MSIX_HW_INT_MASK_AD,\n                IWM_MSIX_HW_INT_CAUSES_REG_ALIVE |\n                IWM_MSIX_HW_INT_CAUSES_REG_WAKEUP |\n                IWM_MSIX_HW_INT_CAUSES_REG_IML |\n                IWM_MSIX_HW_INT_CAUSES_REG_CT_KILL |\n                IWM_MSIX_HW_INT_CAUSES_REG_RF_KILL |\n                IWM_MSIX_HW_INT_CAUSES_REG_PERIODIC |\n                IWM_MSIX_HW_INT_CAUSES_REG_SW_ERR |\n                IWM_MSIX_HW_INT_CAUSES_REG_SCD |\n                IWM_MSIX_HW_INT_CAUSES_REG_FH_TX |\n                IWM_MSIX_HW_INT_CAUSES_REG_HW_ERR |\n                IWM_MSIX_HW_INT_CAUSES_REG_HAP);\n}\n\nint ItlIwm::\niwm_clear_persistence_bit(struct iwm_softc *sc)\n{\n    uint32_t hpm, wprot;\n    \n    hpm = iwm_read_prph_unlocked(sc, IWM_HPM_DEBUG);\n    if (hpm != 0xa5a5a5a0 && (hpm & IWM_HPM_PERSISTENCE_BIT)) {\n        wprot = iwm_read_prph_unlocked(sc, IWM_PREG_PRPH_WPROT_9000);\n        if (wprot & IWM_PREG_WFPM_ACCESS) {\n            printf(\"%s: cannot clear persistence bit\\n\",\n                   DEVNAME(sc));\n            return EPERM;\n        }\n        iwm_write_prph_unlocked(sc, IWM_HPM_DEBUG,\n                                hpm & ~IWM_HPM_PERSISTENCE_BIT);\n    }\n    \n    return 0;\n}\n\nint ItlIwm::\niwm_start_hw(struct iwm_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    int err;\n    \n    err = iwm_prepare_card_hw(sc);\n    if (err)\n        return err;\n    \n    if (sc->sc_device_family == IWM_DEVICE_FAMILY_9000) {\n        err = iwm_clear_persistence_bit(sc);\n        if (err)\n            return err;\n    }\n    \n    /* Reset the entire device */\n    IWM_WRITE(sc, IWM_CSR_RESET, IWM_CSR_RESET_REG_FLAG_SW_RESET);\n    DELAY(5000);\n    \n    err = iwm_apm_init(sc);\n    if (err)\n        return err;\n    \n    iwm_init_msix_hw(sc);\n    \n    iwm_enable_rfkill_int(sc);\n    iwm_check_rfkill(sc);\n    \n    return 0;\n}\n\n\nvoid ItlIwm::\niwm_stop_device(struct iwm_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    int chnl, ntries;\n    int qid;\n    \n    iwm_disable_interrupts(sc);\n    sc->sc_flags &= ~IWM_FLAG_USE_ICT;\n    \n    /* Stop all DMA channels. */\n    if (iwm_nic_lock(sc)) {\n        /* Deactivate TX scheduler. */\n        iwm_write_prph(sc, IWM_SCD_TXFACT, 0);\n        \n        for (chnl = 0; chnl < IWM_FH_TCSR_CHNL_NUM; chnl++) {\n            IWM_WRITE(sc,\n                      IWM_FH_TCSR_CHNL_TX_CONFIG_REG(chnl), 0);\n            for (ntries = 0; ntries < 200; ntries++) {\n                uint32_t r;\n                \n                r = IWM_READ(sc, IWM_FH_TSSR_TX_STATUS_REG);\n                if (r & IWM_FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(\n                                                                chnl))\n                    break;\n                DELAY(20);\n            }\n        }\n        iwm_nic_unlock(sc);\n    }\n    iwm_disable_rx_dma(sc);\n    \n    iwm_reset_rx_ring(sc, &sc->rxq);\n    \n    for (qid = 0; qid < nitems(sc->txq); qid++)\n        iwm_reset_tx_ring(sc, &sc->txq[qid]);\n    \n    if (sc->sc_device_family == IWM_DEVICE_FAMILY_7000) {\n        if (iwm_nic_lock(sc)) {\n            /* Power-down device's busmaster DMA clocks */\n            iwm_write_prph(sc, IWM_APMG_CLK_DIS_REG,\n                           IWM_APMG_CLK_VAL_DMA_CLK_RQT);\n            iwm_nic_unlock(sc);\n        }\n        DELAY(5);\n    }\n    \n    /* Make sure (redundant) we've released our request to stay awake */\n    IWM_CLRBITS(sc, IWM_CSR_GP_CNTRL,\n                IWM_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);\n    if (sc->sc_nic_locks > 0)\n        XYLog(\"%s: %d active NIC locks forcefully cleared\\n\",\n              DEVNAME(sc), sc->sc_nic_locks);\n    sc->sc_nic_locks = 0;\n    \n    /* Stop the device, and put it in low power state */\n    iwm_apm_stop(sc);\n    \n    /* Reset the on-board processor. */\n    IWM_WRITE(sc, IWM_CSR_RESET, IWM_CSR_RESET_REG_FLAG_SW_RESET);\n    DELAY(5000);\n    \n    /*\n     * Upon stop, the IVAR table gets erased, so msi-x won't\n     * work. This causes a bug in RF-KILL flows, since the interrupt\n     * that enables radio won't fire on the correct irq, and the\n     * driver won't be able to handle the interrupt.\n     * Configure the IVAR table again after reset.\n     */\n    iwm_conf_msix_hw(sc, 1);\n    \n    /*\n     * Upon stop, the APM issues an interrupt if HW RF kill is set.\n     * Clear the interrupt again.\n     */\n    iwm_disable_interrupts(sc);\n    \n    /* Even though we stop the HW we still want the RF kill interrupt. */\n    iwm_enable_rfkill_int(sc);\n    iwm_check_rfkill(sc);\n    \n    iwm_prepare_card_hw(sc);\n}\n\nvoid ItlIwm::\niwm_nic_config(struct iwm_softc *sc)\n{\n    uint8_t radio_cfg_type, radio_cfg_step, radio_cfg_dash;\n    uint32_t mask, val, reg_val = 0;\n    \n    radio_cfg_type = (sc->sc_fw_phy_config & IWM_FW_PHY_CFG_RADIO_TYPE) >>\n    IWM_FW_PHY_CFG_RADIO_TYPE_POS;\n    radio_cfg_step = (sc->sc_fw_phy_config & IWM_FW_PHY_CFG_RADIO_STEP) >>\n    IWM_FW_PHY_CFG_RADIO_STEP_POS;\n    radio_cfg_dash = (sc->sc_fw_phy_config & IWM_FW_PHY_CFG_RADIO_DASH) >>\n    IWM_FW_PHY_CFG_RADIO_DASH_POS;\n    \n    reg_val |= IWM_CSR_HW_REV_STEP(sc->sc_hw_rev) <<\n    IWM_CSR_HW_IF_CONFIG_REG_POS_MAC_STEP;\n    reg_val |= IWM_CSR_HW_REV_DASH(sc->sc_hw_rev) <<\n    IWM_CSR_HW_IF_CONFIG_REG_POS_MAC_DASH;\n    \n    /* radio configuration */\n    reg_val |= radio_cfg_type << IWM_CSR_HW_IF_CONFIG_REG_POS_PHY_TYPE;\n    reg_val |= radio_cfg_step << IWM_CSR_HW_IF_CONFIG_REG_POS_PHY_STEP;\n    reg_val |= radio_cfg_dash << IWM_CSR_HW_IF_CONFIG_REG_POS_PHY_DASH;\n    \n    mask = IWM_CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH |\n    IWM_CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP |\n    IWM_CSR_HW_IF_CONFIG_REG_MSK_PHY_STEP |\n    IWM_CSR_HW_IF_CONFIG_REG_MSK_PHY_DASH |\n    IWM_CSR_HW_IF_CONFIG_REG_MSK_PHY_TYPE |\n    IWM_CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |\n    IWM_CSR_HW_IF_CONFIG_REG_BIT_MAC_SI;\n    \n    val = IWM_READ(sc, IWM_CSR_HW_IF_CONFIG_REG);\n    val &= ~mask;\n    val |= reg_val;\n    IWM_WRITE(sc, IWM_CSR_HW_IF_CONFIG_REG, val);\n    \n    /*\n     * W/A : NIC is stuck in a reset state after Early PCIe power off\n     * (PCIe power is lost before PERST# is asserted), causing ME FW\n     * to lose ownership and not being able to obtain it back.\n     */\n    if (sc->sc_device_family == IWM_DEVICE_FAMILY_7000)\n        iwm_set_bits_mask_prph(sc, IWM_APMG_PS_CTRL_REG,\n                               IWM_APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS,\n                               ~IWM_APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS);\n}\n\nint ItlIwm::\niwm_nic_rx_init(struct iwm_softc *sc)\n{\n    if (sc->sc_mqrx_supported)\n        return iwm_nic_rx_mq_init(sc);\n    else\n        return iwm_nic_rx_legacy_init(sc);\n}\n\nint ItlIwm::\niwm_nic_rx_mq_init(struct iwm_softc *sc)\n{\n    int enabled;\n    \n    if (!iwm_nic_lock(sc))\n        return EBUSY;\n    \n    /* Stop RX DMA. */\n    iwm_write_prph(sc, IWM_RFH_RXF_DMA_CFG, 0);\n    /* Disable RX used and free queue operation. */\n    iwm_write_prph(sc, IWM_RFH_RXF_RXQ_ACTIVE, 0);\n    \n    iwm_write_prph64(sc, IWM_RFH_Q0_FRBDCB_BA_LSB,\n                     sc->rxq.free_desc_dma.paddr);\n    iwm_write_prph64(sc, IWM_RFH_Q0_URBDCB_BA_LSB,\n                     sc->rxq.used_desc_dma.paddr);\n    iwm_write_prph64(sc, IWM_RFH_Q0_URBD_STTS_WPTR_LSB,\n                     sc->rxq.stat_dma.paddr);\n    iwm_write_prph(sc, IWM_RFH_Q0_FRBDCB_WIDX, 0);\n    iwm_write_prph(sc, IWM_RFH_Q0_FRBDCB_RIDX, 0);\n    iwm_write_prph(sc, IWM_RFH_Q0_URBDCB_WIDX, 0);\n    \n    /* We configure only queue 0 for now. */\n    enabled = ((1 << 0) << 16) | (1 << 0);\n    \n    /* Enable RX DMA, 4KB buffer size. */\n    iwm_write_prph(sc, IWM_RFH_RXF_DMA_CFG,\n                   IWM_RFH_DMA_EN_ENABLE_VAL |\n                   IWM_RFH_RXF_DMA_RB_SIZE_4K |\n                   IWM_RFH_RXF_DMA_MIN_RB_4_8 |\n                   IWM_RFH_RXF_DMA_DROP_TOO_LARGE_MASK |\n                   IWM_RFH_RXF_DMA_RBDCB_SIZE_512);\n    \n    /* Enable RX DMA snooping. */\n    iwm_write_prph(sc, IWM_RFH_GEN_CFG,\n                   IWM_RFH_GEN_CFG_RFH_DMA_SNOOP |\n                   IWM_RFH_GEN_CFG_SERVICE_DMA_SNOOP |\n                   (sc->sc_integrated ? IWM_RFH_GEN_CFG_RB_CHUNK_SIZE_64 :\n                    IWM_RFH_GEN_CFG_RB_CHUNK_SIZE_128));\n    \n    /* Enable the configured queue(s). */\n    iwm_write_prph(sc, IWM_RFH_RXF_RXQ_ACTIVE, enabled);\n    \n    iwm_nic_unlock(sc);\n    \n    IWM_WRITE_1(sc, IWM_CSR_INT_COALESCING, IWM_HOST_INT_TIMEOUT_DEF);\n    \n    IWM_WRITE(sc, IWM_RFH_Q0_FRBDCB_WIDX_TRG, 8);\n    \n    return 0;\n}\n\nint ItlIwm::\niwm_nic_rx_legacy_init(struct iwm_softc *sc)\n{\n    memset(sc->rxq.stat, 0, sizeof(*sc->rxq.stat));\n    \n    iwm_disable_rx_dma(sc);\n    \n    if (!iwm_nic_lock(sc))\n        return EBUSY;\n    \n    /* reset and flush pointers */\n    IWM_WRITE(sc, IWM_FH_MEM_RCSR_CHNL0_RBDCB_WPTR, 0);\n    IWM_WRITE(sc, IWM_FH_MEM_RCSR_CHNL0_FLUSH_RB_REQ, 0);\n    IWM_WRITE(sc, IWM_FH_RSCSR_CHNL0_RDPTR, 0);\n    IWM_WRITE(sc, IWM_FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0);\n    \n    /* Set physical address of RX ring (256-byte aligned). */\n    IWM_WRITE(sc,\n              IWM_FH_RSCSR_CHNL0_RBDCB_BASE_REG, sc->rxq.free_desc_dma.paddr >> 8);\n    \n    /* Set physical address of RX status (16-byte aligned). */\n    IWM_WRITE(sc,\n              IWM_FH_RSCSR_CHNL0_STTS_WPTR_REG, sc->rxq.stat_dma.paddr >> 4);\n    \n    /* Enable RX. */\n    IWM_WRITE(sc, IWM_FH_MEM_RCSR_CHNL0_CONFIG_REG,\n              IWM_FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL        |\n              IWM_FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY        |  /* HW bug */\n              IWM_FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL    |\n              (IWM_RX_RB_TIMEOUT << IWM_FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS) |\n              IWM_FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K        |\n              IWM_RX_QUEUE_SIZE_LOG << IWM_FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS);\n    \n    IWM_WRITE_1(sc, IWM_CSR_INT_COALESCING, IWM_HOST_INT_TIMEOUT_DEF);\n    \n    /* W/A for interrupt coalescing bug in 7260 and 3160 */\n    if (sc->host_interrupt_operation_mode)\n        IWM_SETBITS(sc, IWM_CSR_INT_COALESCING, IWM_HOST_INT_OPER_MODE);\n    \n    iwm_nic_unlock(sc);\n    \n    /*\n     * This value should initially be 0 (before preparing any RBs),\n     * and should be 8 after preparing the first 8 RBs (for example).\n     */\n    IWM_WRITE(sc, IWM_FH_RSCSR_CHNL0_WPTR, 8);\n    \n    return 0;\n}\n\nint ItlIwm::\niwm_nic_tx_init(struct iwm_softc *sc)\n{\n    int qid;\n    \n    if (!iwm_nic_lock(sc))\n        return EBUSY;\n    \n    /* Deactivate TX scheduler. */\n    iwm_write_prph(sc, IWM_SCD_TXFACT, 0);\n    \n    /* Set physical address of \"keep warm\" page (16-byte aligned). */\n    IWM_WRITE(sc, IWM_FH_KW_MEM_ADDR_REG, sc->kw_dma.paddr >> 4);\n    \n    for (qid = 0; qid < nitems(sc->txq); qid++) {\n        struct iwm_tx_ring *txq = &sc->txq[qid];\n        \n        /* Set physical address of TX ring (256-byte aligned). */\n        IWM_WRITE(sc, IWM_FH_MEM_CBBC_QUEUE(qid),\n                  txq->desc_dma.paddr >> 8);\n    }\n    \n    iwm_set_bits_prph(sc, IWM_SCD_GP_CTRL,\n                      IWM_SCD_GP_CTRL_AUTO_ACTIVE_MODE |\n                      IWM_SCD_GP_CTRL_ENABLE_31_QUEUES);\n    \n    iwm_nic_unlock(sc);\n    \n    return 0;\n}\n\nint ItlIwm::\niwm_nic_init(struct iwm_softc *sc)\n{\n    int err;\n    \n    iwm_apm_init(sc);\n    if (sc->sc_device_family == IWM_DEVICE_FAMILY_7000)\n        iwm_set_bits_mask_prph(sc, IWM_APMG_PS_CTRL_REG,\n                               IWM_APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,\n                               ~IWM_APMG_PS_CTRL_MSK_PWR_SRC);\n    \n    iwm_nic_config(sc);\n    \n    err = iwm_nic_rx_init(sc);\n    if (err)\n        return err;\n    \n    err = iwm_nic_tx_init(sc);\n    if (err)\n        return err;\n    \n    IWM_SETBITS(sc, IWM_CSR_MAC_SHADOW_REG_CTRL, 0x800fffff);\n    \n    return 0;\n}\n\nvoid ItlIwm::\niwm_restore_interrupts(struct iwm_softc *sc)\n{\n    IWM_WRITE(sc, IWM_CSR_INT_MASK, sc->sc_intmask);\n}\n"
  },
  {
    "path": "itlwm/hal_iwm/if_iwmreg.h",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n/*    $OpenBSD: if_iwmreg.h,v 1.48 2020/05/18 17:56:41 stsp Exp $    */\n\n/******************************************************************************\n *\n * This file is provided under a dual BSD/GPLv2 license.  When using or\n * redistributing this file, you may do so under either license.\n *\n * GPL LICENSE SUMMARY\n *\n * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of version 2 of the GNU General Public License as\n * published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful, but\n * WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,\n * USA\n *\n * The full GNU General Public License is included in this distribution\n * in the file called COPYING.\n *\n * Contact Information:\n *  Intel Linux Wireless <ilw@linux.intel.com>\n * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497\n *\n * BSD LICENSE\n *\n * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in\n *    the documentation and/or other materials provided with the\n *    distribution.\n *  * Neither the name Intel Corporation nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n *****************************************************************************/\n\n/*\n * CSR (control and status registers)\n *\n * CSR registers are mapped directly into PCI bus space, and are accessible\n * whenever platform supplies power to device, even when device is in\n * low power states due to driver-invoked device resets\n * (e.g. IWM_CSR_RESET_REG_FLAG_SW_RESET) or uCode-driven power-saving modes.\n *\n * Use iwl_write32() and iwl_read32() family to access these registers;\n * these provide simple PCI bus access, without waking up the MAC.\n * Do not use iwl_write_direct32() family for these registers;\n * no need to \"grab nic access\" via IWM_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ.\n * The MAC (uCode processor, etc.) does not need to be powered up for accessing\n * the CSR registers.\n *\n * NOTE:  Device does need to be awake in order to read this memory\n *        via IWM_CSR_EEPROM and IWM_CSR_OTP registers\n */\n#define IWM_CSR_HW_IF_CONFIG_REG    (0x000) /* hardware interface config */\n#define IWM_CSR_INT_COALESCING      (0x004) /* accum ints, 32-usec units */\n#define IWM_CSR_INT                 (0x008) /* host interrupt status/ack */\n#define IWM_CSR_INT_MASK            (0x00c) /* host interrupt enable */\n#define IWM_CSR_FH_INT_STATUS       (0x010) /* busmaster int status/ack*/\n#define IWM_CSR_GPIO_IN             (0x018) /* read external chip pins */\n#define IWM_CSR_RESET               (0x020) /* busmaster enable, NMI, etc*/\n#define IWM_CSR_GP_CNTRL            (0x024)\n\n/* 2nd byte of IWM_CSR_INT_COALESCING, not accessible via iwl_write32()! */\n#define IWM_CSR_INT_PERIODIC_REG    (0x005)\n\n/*\n * Hardware revision info\n * Bit fields:\n * 31-16:  Reserved\n *  15-4:  Type of device:  see IWM_CSR_HW_REV_TYPE_xxx definitions\n *  3-2:  Revision step:  0 = A, 1 = B, 2 = C, 3 = D\n *  1-0:  \"Dash\" (-) value, as in A-1, etc.\n */\n#define IWM_CSR_HW_REV              (0x028)\n\n/*\n * EEPROM and OTP (one-time-programmable) memory reads\n *\n * NOTE:  Device must be awake, initialized via apm_ops.init(),\n *        in order to read.\n */\n#define IWM_CSR_EEPROM_REG          (0x02c)\n#define IWM_CSR_EEPROM_GP           (0x030)\n#define IWM_CSR_OTP_GP_REG          (0x034)\n\n#define IWM_CSR_GIO_REG        (0x03C)\n#define IWM_CSR_GP_UCODE_REG    (0x048)\n#define IWM_CSR_GP_DRIVER_REG    (0x050)\n\n/*\n * UCODE-DRIVER GP (general purpose) mailbox registers.\n * SET/CLR registers set/clear bit(s) if \"1\" is written.\n */\n#define IWM_CSR_UCODE_DRV_GP1       (0x054)\n#define IWM_CSR_UCODE_DRV_GP1_SET   (0x058)\n#define IWM_CSR_UCODE_DRV_GP1_CLR   (0x05c)\n#define IWM_CSR_UCODE_DRV_GP2       (0x060)\n\n#define IWM_CSR_MBOX_SET_REG        (0x088)\n#define IWM_CSR_MBOX_SET_REG_OS_ALIVE    0x20\n\n#define IWM_CSR_LED_REG            (0x094)\n#define IWM_CSR_DRAM_INT_TBL_REG    (0x0A0)\n#define IWM_CSR_MAC_SHADOW_REG_CTRL    (0x0A8) /* 6000 and up */\n\n\n/* GIO Chicken Bits (PCI Express bus link power management) */\n#define IWM_CSR_GIO_CHICKEN_BITS    (0x100)\n\n/* Analog phase-lock-loop configuration  */\n#define IWM_CSR_ANA_PLL_CFG         (0x20c)\n\n/*\n * CSR Hardware Revision Workaround Register.  Indicates hardware rev;\n * \"step\" determines CCK backoff for txpower calculation.  Used for 4965 only.\n * See also IWM_CSR_HW_REV register.\n * Bit fields:\n *  3-2:  0 = A, 1 = B, 2 = C, 3 = D step\n *  1-0:  \"Dash\" (-) value, as in C-1, etc.\n */\n#define IWM_CSR_HW_REV_WA_REG        (0x22C)\n\n#define IWM_CSR_DBG_HPET_MEM_REG    (0x240)\n#define IWM_CSR_DBG_LINK_PWR_MGMT_REG    (0x250)\n\n/* Bits for IWM_CSR_HW_IF_CONFIG_REG */\n#define IWM_CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH    (0x00000003)\n#define IWM_CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP    (0x0000000C)\n#define IWM_CSR_HW_IF_CONFIG_REG_MSK_BOARD_VER    (0x000000C0)\n#define IWM_CSR_HW_IF_CONFIG_REG_BIT_MAC_SI    (0x00000100)\n#define IWM_CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI    (0x00000200)\n#define IWM_CSR_HW_IF_CONFIG_REG_MSK_PHY_TYPE    (0x00000C00)\n#define IWM_CSR_HW_IF_CONFIG_REG_MSK_PHY_DASH    (0x00003000)\n#define IWM_CSR_HW_IF_CONFIG_REG_MSK_PHY_STEP    (0x0000C000)\n\n#define IWM_CSR_HW_IF_CONFIG_REG_POS_MAC_DASH    (0)\n#define IWM_CSR_HW_IF_CONFIG_REG_POS_MAC_STEP    (2)\n#define IWM_CSR_HW_IF_CONFIG_REG_POS_BOARD_VER    (6)\n#define IWM_CSR_HW_IF_CONFIG_REG_POS_PHY_TYPE    (10)\n#define IWM_CSR_HW_IF_CONFIG_REG_POS_PHY_DASH    (12)\n#define IWM_CSR_HW_IF_CONFIG_REG_POS_PHY_STEP    (14)\n\n#define IWM_CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A    (0x00080000)\n#define IWM_CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM    (0x00200000)\n#define IWM_CSR_HW_IF_CONFIG_REG_BIT_NIC_READY    (0x00400000) /* PCI_OWN_SEM */\n#define IWM_CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE (0x02000000) /* ME_OWN */\n#define IWM_CSR_HW_IF_CONFIG_REG_PREPARE    (0x08000000) /* WAKE_ME */\n#define IWM_CSR_HW_IF_CONFIG_REG_ENABLE_PME    (0x10000000)\n#define IWM_CSR_HW_IF_CONFIG_REG_PERSIST_MODE    (0x40000000) /* PERSISTENCE */\n\n#define IWM_CSR_INT_PERIODIC_DIS        (0x00) /* disable periodic int*/\n#define IWM_CSR_INT_PERIODIC_ENA        (0xFF) /* 255*32 usec ~ 8 msec*/\n\n/* interrupt flags in INTA, set by uCode or hardware (e.g. dma),\n * acknowledged (reset) by host writing \"1\" to flagged bits. */\n#define IWM_CSR_INT_BIT_FH_RX    (1U << 31) /* Rx DMA, cmd responses, FH_INT[17:16] */\n#define IWM_CSR_INT_BIT_HW_ERR    (1 << 29) /* DMA hardware error FH_INT[31] */\n#define IWM_CSR_INT_BIT_RX_PERIODIC    (1 << 28) /* Rx periodic */\n#define IWM_CSR_INT_BIT_FH_TX    (1 << 27) /* Tx DMA FH_INT[1:0] */\n#define IWM_CSR_INT_BIT_SCD    (1 << 26) /* TXQ pointer advanced */\n#define IWM_CSR_INT_BIT_SW_ERR    (1 << 25) /* uCode error */\n#define IWM_CSR_INT_BIT_RF_KILL    (1 << 7)  /* HW RFKILL switch GP_CNTRL[27] toggled */\n#define IWM_CSR_INT_BIT_CT_KILL    (1 << 6)  /* Critical temp (chip too hot) rfkill */\n#define IWM_CSR_INT_BIT_SW_RX    (1 << 3)  /* Rx, command responses */\n#define IWM_CSR_INT_BIT_WAKEUP    (1 << 1)  /* NIC controller waking up (pwr mgmt) */\n#define IWM_CSR_INT_BIT_ALIVE    (1 << 0)  /* uCode interrupts once it initializes */\n\n#define IWM_CSR_INI_SET_MASK    (IWM_CSR_INT_BIT_FH_RX   | \\\n                 IWM_CSR_INT_BIT_HW_ERR  | \\\n                 IWM_CSR_INT_BIT_FH_TX   | \\\n                 IWM_CSR_INT_BIT_SW_ERR  | \\\n                 IWM_CSR_INT_BIT_RF_KILL | \\\n                 IWM_CSR_INT_BIT_SW_RX   | \\\n                 IWM_CSR_INT_BIT_WAKEUP  | \\\n                 IWM_CSR_INT_BIT_ALIVE   | \\\n                 IWM_CSR_INT_BIT_RX_PERIODIC)\n\n/* interrupt flags in FH (flow handler) (PCI busmaster DMA) */\n#define IWM_CSR_FH_INT_BIT_ERR       (1U << 31) /* Error */\n#define IWM_CSR_FH_INT_BIT_HI_PRIOR  (1 << 30) /* High priority Rx, bypass coalescing */\n#define IWM_CSR_FH_INT_BIT_RX_CHNL1  (1 << 17) /* Rx channel 1 */\n#define IWM_CSR_FH_INT_BIT_RX_CHNL0  (1 << 16) /* Rx channel 0 */\n#define IWM_CSR_FH_INT_BIT_TX_CHNL1  (1 << 1)  /* Tx channel 1 */\n#define IWM_CSR_FH_INT_BIT_TX_CHNL0  (1 << 0)  /* Tx channel 0 */\n\n#define IWM_CSR_FH_INT_RX_MASK    (IWM_CSR_FH_INT_BIT_HI_PRIOR | \\\n                IWM_CSR_FH_INT_BIT_RX_CHNL1 | \\\n                IWM_CSR_FH_INT_BIT_RX_CHNL0)\n\n#define IWM_CSR_FH_INT_TX_MASK    (IWM_CSR_FH_INT_BIT_TX_CHNL1 | \\\n                IWM_CSR_FH_INT_BIT_TX_CHNL0)\n\n/* GPIO */\n#define IWM_CSR_GPIO_IN_BIT_AUX_POWER                   (0x00000200)\n#define IWM_CSR_GPIO_IN_VAL_VAUX_PWR_SRC                (0x00000000)\n#define IWM_CSR_GPIO_IN_VAL_VMAIN_PWR_SRC               (0x00000200)\n\n/* RESET */\n#define IWM_CSR_RESET_REG_FLAG_NEVO_RESET                (0x00000001)\n#define IWM_CSR_RESET_REG_FLAG_FORCE_NMI                 (0x00000002)\n#define IWM_CSR_RESET_REG_FLAG_SW_RESET                  (0x00000080)\n#define IWM_CSR_RESET_REG_FLAG_MASTER_DISABLED           (0x00000100)\n#define IWM_CSR_RESET_REG_FLAG_STOP_MASTER               (0x00000200)\n#define IWM_CSR_RESET_LINK_PWR_MGMT_DISABLED             (0x80000000)\n\n/*\n * GP (general purpose) CONTROL REGISTER\n * Bit fields:\n *    27:  HW_RF_KILL_SW\n *         Indicates state of (platform's) hardware RF-Kill switch\n * 26-24:  POWER_SAVE_TYPE\n *         Indicates current power-saving mode:\n *         000 -- No power saving\n *         001 -- MAC power-down\n *         010 -- PHY (radio) power-down\n *         011 -- Error\n *   9-6:  SYS_CONFIG\n *         Indicates current system configuration, reflecting pins on chip\n *         as forced high/low by device circuit board.\n *     4:  GOING_TO_SLEEP\n *         Indicates MAC is entering a power-saving sleep power-down.\n *         Not a good time to access device-internal resources.\n *     3:  MAC_ACCESS_REQ\n *         Host sets this to request and maintain MAC wakeup, to allow host\n *         access to device-internal resources.  Host must wait for\n *         MAC_CLOCK_READY (and !GOING_TO_SLEEP) before accessing non-CSR\n *         device registers.\n *     2:  INIT_DONE\n *         Host sets this to put device into fully operational D0 power mode.\n *         Host resets this after SW_RESET to put device into low power mode.\n *     0:  MAC_CLOCK_READY\n *         Indicates MAC (ucode processor, etc.) is powered up and can run.\n *         Internal resources are accessible.\n *         NOTE:  This does not indicate that the processor is actually running.\n *         NOTE:  This does not indicate that device has completed\n *                init or post-power-down restore of internal SRAM memory.\n *                Use IWM_CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP as indication that\n *                SRAM is restored and uCode is in normal operation mode.\n *                Later devices (5xxx/6xxx/1xxx) use non-volatile SRAM, and\n *                do not need to save/restore it.\n *         NOTE:  After device reset, this bit remains \"0\" until host sets\n *                INIT_DONE\n */\n#define IWM_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY        (0x00000001)\n#define IWM_CSR_GP_CNTRL_REG_FLAG_INIT_DONE              (0x00000004)\n#define IWM_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ         (0x00000008)\n#define IWM_CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP         (0x00000010)\n\n#define IWM_CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN           (0x00000001)\n\n#define IWM_CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE         (0x07000000)\n#define IWM_CSR_GP_CNTRL_REG_FLAG_RFKILL_WAKE_L1A_EN     (0x04000000)\n#define IWM_CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW          (0x08000000)\n\n\n/* HW REV */\n#define IWM_CSR_HW_REV_DASH(_val)          (((_val) & 0x0000003) >> 0)\n#define IWM_CSR_HW_REV_STEP(_val)          (((_val) & 0x000000C) >> 2)\n\n#define IWM_CSR_HW_REV_TYPE_MSK        (0x000FFF0)\n#define IWM_CSR_HW_REV_TYPE_5300    (0x0000020)\n#define IWM_CSR_HW_REV_TYPE_5350    (0x0000030)\n#define IWM_CSR_HW_REV_TYPE_5100    (0x0000050)\n#define IWM_CSR_HW_REV_TYPE_5150    (0x0000040)\n#define IWM_CSR_HW_REV_TYPE_1000    (0x0000060)\n#define IWM_CSR_HW_REV_TYPE_6x00    (0x0000070)\n#define IWM_CSR_HW_REV_TYPE_6x50    (0x0000080)\n#define IWM_CSR_HW_REV_TYPE_6150    (0x0000084)\n#define IWM_CSR_HW_REV_TYPE_6x05    (0x00000B0)\n#define IWM_CSR_HW_REV_TYPE_6x30    IWM_CSR_HW_REV_TYPE_6x05\n#define IWM_CSR_HW_REV_TYPE_6x35    IWM_CSR_HW_REV_TYPE_6x05\n#define IWM_CSR_HW_REV_TYPE_2x30    (0x00000C0)\n#define IWM_CSR_HW_REV_TYPE_2x00    (0x0000100)\n#define IWM_CSR_HW_REV_TYPE_105        (0x0000110)\n#define IWM_CSR_HW_REV_TYPE_135        (0x0000120)\n#define IWM_CSR_HW_REV_TYPE_7265D    (0x0000210)\n#define IWM_CSR_HW_REV_TYPE_NONE    (0x00001F0)\n\n/* EEPROM REG */\n#define IWM_CSR_EEPROM_REG_READ_VALID_MSK    (0x00000001)\n#define IWM_CSR_EEPROM_REG_BIT_CMD        (0x00000002)\n#define IWM_CSR_EEPROM_REG_MSK_ADDR        (0x0000FFFC)\n#define IWM_CSR_EEPROM_REG_MSK_DATA        (0xFFFF0000)\n\n/* EEPROM GP */\n#define IWM_CSR_EEPROM_GP_VALID_MSK        (0x00000007) /* signature */\n#define IWM_CSR_EEPROM_GP_IF_OWNER_MSK    (0x00000180)\n#define IWM_CSR_EEPROM_GP_BAD_SIGNATURE_BOTH_EEP_AND_OTP    (0x00000000)\n#define IWM_CSR_EEPROM_GP_BAD_SIG_EEP_GOOD_SIG_OTP        (0x00000001)\n#define IWM_CSR_EEPROM_GP_GOOD_SIG_EEP_LESS_THAN_4K        (0x00000002)\n#define IWM_CSR_EEPROM_GP_GOOD_SIG_EEP_MORE_THAN_4K        (0x00000004)\n\n/* One-time-programmable memory general purpose reg */\n#define IWM_CSR_OTP_GP_REG_DEVICE_SELECT  (0x00010000) /* 0 - EEPROM, 1 - OTP */\n#define IWM_CSR_OTP_GP_REG_OTP_ACCESS_MODE  (0x00020000) /* 0 - absolute, 1 - relative */\n#define IWM_CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK    (0x00100000) /* bit 20 */\n#define IWM_CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK  (0x00200000) /* bit 21 */\n\n/* GP REG */\n#define IWM_CSR_GP_REG_POWER_SAVE_STATUS_MSK    (0x03000000) /* bit 24/25 */\n#define IWM_CSR_GP_REG_NO_POWER_SAVE            (0x00000000)\n#define IWM_CSR_GP_REG_MAC_POWER_SAVE           (0x01000000)\n#define IWM_CSR_GP_REG_PHY_POWER_SAVE           (0x02000000)\n#define IWM_CSR_GP_REG_POWER_SAVE_ERROR         (0x03000000)\n\n\n/* CSR GIO */\n#define IWM_CSR_GIO_REG_VAL_L0S_DISABLED    (0x00000002)\n\n/*\n * UCODE-DRIVER GP (general purpose) mailbox register 1\n * Host driver and uCode write and/or read this register to communicate with\n * each other.\n * Bit fields:\n *     4:  UCODE_DISABLE\n *         Host sets this to request permanent halt of uCode, same as\n *         sending CARD_STATE command with \"halt\" bit set.\n *     3:  CT_KILL_EXIT\n *         Host sets this to request exit from CT_KILL state, i.e. host thinks\n *         device temperature is low enough to continue normal operation.\n *     2:  CMD_BLOCKED\n *         Host sets this during RF KILL power-down sequence (HW, SW, CT KILL)\n *         to release uCode to clear all Tx and command queues, enter\n *         unassociated mode, and power down.\n *         NOTE:  Some devices also use HBUS_TARG_MBX_C register for this bit.\n *     1:  SW_BIT_RFKILL\n *         Host sets this when issuing CARD_STATE command to request\n *         device sleep.\n *     0:  MAC_SLEEP\n *         uCode sets this when preparing a power-saving power-down.\n *         uCode resets this when power-up is complete and SRAM is sane.\n *         NOTE:  device saves internal SRAM data to host when powering down,\n *                and must restore this data after powering back up.\n *                MAC_SLEEP is the best indication that restore is complete.\n *                Later devices (5xxx/6xxx/1xxx) use non-volatile SRAM, and\n *                do not need to save/restore it.\n */\n#define IWM_CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP             (0x00000001)\n#define IWM_CSR_UCODE_SW_BIT_RFKILL                     (0x00000002)\n#define IWM_CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED           (0x00000004)\n#define IWM_CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT      (0x00000008)\n#define IWM_CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE       (0x00000020)\n\n/* GP Driver */\n#define IWM_CSR_GP_DRIVER_REG_BIT_RADIO_SKU_MSK            (0x00000003)\n#define IWM_CSR_GP_DRIVER_REG_BIT_RADIO_SKU_3x3_HYB        (0x00000000)\n#define IWM_CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_HYB        (0x00000001)\n#define IWM_CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA        (0x00000002)\n#define IWM_CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6        (0x00000004)\n#define IWM_CSR_GP_DRIVER_REG_BIT_6050_1x2            (0x00000008)\n\n#define IWM_CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER        (0x00000080)\n\n/* GIO Chicken Bits (PCI Express bus link power management) */\n#define IWM_CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX  (0x00800000)\n#define IWM_CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER  (0x20000000)\n\n/* LED */\n#define IWM_CSR_LED_BSM_CTRL_MSK (0xFFFFFFDF)\n#define IWM_CSR_LED_REG_TURN_ON (0x60)\n#define IWM_CSR_LED_REG_TURN_OFF (0x20)\n\n/* ANA_PLL */\n#define IWM_CSR50_ANA_PLL_CFG_VAL        (0x00880300)\n\n/* HPET MEM debug */\n#define IWM_CSR_DBG_HPET_MEM_REG_VAL    (0xFFFF0000)\n\n/* DRAM INT TABLE */\n#define IWM_CSR_DRAM_INT_TBL_ENABLE        (1U << 31)\n#define IWM_CSR_DRAM_INIT_TBL_WRITE_POINTER    (1 << 28)\n#define IWM_CSR_DRAM_INIT_TBL_WRAP_CHECK    (1 << 27)\n\n/* SECURE boot registers */\n#define IWM_CSR_SECURE_BOOT_CONFIG_ADDR    (0x100)\n#define IWM_CSR_SECURE_BOOT_CONFIG_INSPECTOR_BURNED_IN_OTP    0x00000001\n#define IWM_CSR_SECURE_BOOT_CONFIG_INSPECTOR_NOT_REQ        0x00000002\n#define IWM_CSR_SECURE_BOOT_CPU1_STATUS_ADDR    (0x100)\n#define IWM_CSR_SECURE_BOOT_CPU2_STATUS_ADDR    (0x100)\n#define IWM_CSR_SECURE_BOOT_CPU_STATUS_VERF_STATUS    0x00000003\n#define IWM_CSR_SECURE_BOOT_CPU_STATUS_VERF_COMPLETED    0x00000002\n#define IWM_CSR_SECURE_BOOT_CPU_STATUS_VERF_SUCCESS    0x00000004\n#define IWM_CSR_SECURE_BOOT_CPU_STATUS_VERF_FAIL    0x00000008\n#define IWM_CSR_SECURE_BOOT_CPU_STATUS_SIGN_VERF_FAIL    0x00000010\n\n#define IWM_FH_UCODE_LOAD_STATUS    0x1af0\n\n#define IWM_FH_MEM_TB_MAX_LENGTH    0x20000\n\n/* 9000 rx series registers */\n\n#define IWM_RFH_Q0_FRBDCB_BA_LSB 0xA08000 /* 64 bit address */\n#define IWM_RFH_Q_FRBDCB_BA_LSB(q) (IWM_RFH_Q0_FRBDCB_BA_LSB + (q) * 8)\n/* Write index table */\n#define IWM_RFH_Q0_FRBDCB_WIDX 0xA08080\n#define IWM_RFH_Q_FRBDCB_WIDX(q) (IWM_RFH_Q0_FRBDCB_WIDX + (q) * 4)\n/* Write index table - shadow registers */\n#define IWM_RFH_Q0_FRBDCB_WIDX_TRG 0x1C80\n#define IWM_RFH_Q_FRBDCB_WIDX_TRG(q) (IWM_RFH_Q0_FRBDCB_WIDX_TRG + (q) * 4)\n/* Read index table */\n#define IWM_RFH_Q0_FRBDCB_RIDX 0xA080C0\n#define IWM_RFH_Q_FRBDCB_RIDX(q) (IWM_RFH_Q0_FRBDCB_RIDX + (q) * 4)\n/* Used list table */\n#define IWM_RFH_Q0_URBDCB_BA_LSB 0xA08100 /* 64 bit address */\n#define IWM_RFH_Q_URBDCB_BA_LSB(q) (IWM_RFH_Q0_URBDCB_BA_LSB + (q) * 8)\n/* Write index table */\n#define IWM_RFH_Q0_URBDCB_WIDX 0xA08180\n#define IWM_RFH_Q_URBDCB_WIDX(q) (IWM_RFH_Q0_URBDCB_WIDX + (q) * 4)\n#define IWM_RFH_Q0_URBDCB_VAID 0xA081C0\n#define IWM_RFH_Q_URBDCB_VAID(q) (IWM_RFH_Q0_URBDCB_VAID + (q) * 4)\n/* stts */\n#define IWM_RFH_Q0_URBD_STTS_WPTR_LSB 0xA08200 /*64 bits address */\n#define IWM_RFH_Q_URBD_STTS_WPTR_LSB(q) (IWM_RFH_Q0_URBD_STTS_WPTR_LSB + (q) * 8)\n\n#define IWM_RFH_Q0_ORB_WPTR_LSB 0xA08280\n#define IWM_RFH_Q_ORB_WPTR_LSB(q) (IWM_RFH_Q0_ORB_WPTR_LSB + (q) * 8)\n#define IWM_RFH_RBDBUF_RBD0_LSB 0xA08300\n#define IWM_RFH_RBDBUF_RBD_LSB(q) (IWM_RFH_RBDBUF_RBD0_LSB + (q) * 8)\n\n/**\n * RFH Status Register\n *\n * Bit fields:\n *\n * Bit 29: RBD_FETCH_IDLE\n * This status flag is set by the RFH when there is no active RBD fetch from\n * DRAM.\n * Once the RFH RBD controller starts fetching (or when there is a pending\n * RBD read response from DRAM), this flag is immediately turned off.\n *\n * Bit 30: SRAM_DMA_IDLE\n * This status flag is set by the RFH when there is no active transaction from\n * SRAM to DRAM.\n * Once the SRAM to DRAM DMA is active, this flag is immediately turned off.\n *\n * Bit 31: RXF_DMA_IDLE\n * This status flag is set by the RFH when there is no active transaction from\n * RXF to DRAM.\n * Once the RXF-to-DRAM DMA is active, this flag is immediately turned off.\n */\n#define IWM_RFH_GEN_STATUS          0xA09808\n#define IWM_RFH_GEN_STATUS_GEN3     0xA07824\n#define IWM_RBD_FETCH_IDLE  (1 << 29)\n#define IWM_SRAM_DMA_IDLE   (1 << 30)\n#define IWM_RXF_DMA_IDLE    (1U << 31)\n\n/* DMA configuration */\n#define IWM_RFH_RXF_DMA_CFG         0xA09820\n#define IWM_RFH_RXF_DMA_CFG_GEN3    0xA07880\n/* RB size */\n#define IWM_RFH_RXF_DMA_RB_SIZE_MASK (0x000F0000) /* bits 16-19 */\n#define IWM_RFH_RXF_DMA_RB_SIZE_POS 16\n#define IWM_RFH_RXF_DMA_RB_SIZE_1K  (0x1 << IWM_RFH_RXF_DMA_RB_SIZE_POS)\n#define IWM_RFH_RXF_DMA_RB_SIZE_2K  (0x2 << IWM_RFH_RXF_DMA_RB_SIZE_POS)\n#define IWM_RFH_RXF_DMA_RB_SIZE_4K  (0x4 << IWM_RFH_RXF_DMA_RB_SIZE_POS)\n#define IWM_RFH_RXF_DMA_RB_SIZE_8K  (0x8 << IWM_RFH_RXF_DMA_RB_SIZE_POS)\n#define IWM_RFH_RXF_DMA_RB_SIZE_12K (0x9 << IWM_RFH_RXF_DMA_RB_SIZE_POS)\n#define IWM_RFH_RXF_DMA_RB_SIZE_16K (0xA << IWM_RFH_RXF_DMA_RB_SIZE_POS)\n#define IWM_RFH_RXF_DMA_RB_SIZE_20K (0xB << IWM_RFH_RXF_DMA_RB_SIZE_POS)\n#define IWM_RFH_RXF_DMA_RB_SIZE_24K (0xC << IWM_RFH_RXF_DMA_RB_SIZE_POS)\n#define IWM_RFH_RXF_DMA_RB_SIZE_28K (0xD << IWM_RFH_RXF_DMA_RB_SIZE_POS)\n#define IWM_RFH_RXF_DMA_RB_SIZE_32K (0xE << IWM_RFH_RXF_DMA_RB_SIZE_POS)\n/* RB Circular Buffer size:defines the table sizes in RBD units */\n#define IWM_RFH_RXF_DMA_RBDCB_SIZE_MASK (0x00F00000) /* bits 20-23 */\n#define IWM_RFH_RXF_DMA_RBDCB_SIZE_POS 20\n#define IWM_RFH_RXF_DMA_RBDCB_SIZE_8        (0x3 << IWM_RFH_RXF_DMA_RBDCB_SIZE_POS)\n#define IWM_RFH_RXF_DMA_RBDCB_SIZE_16       (0x4 << IWM_RFH_RXF_DMA_RBDCB_SIZE_POS)\n#define IWM_RFH_RXF_DMA_RBDCB_SIZE_32       (0x5 << IWM_RFH_RXF_DMA_RBDCB_SIZE_POS)\n#define IWM_RFH_RXF_DMA_RBDCB_SIZE_64       (0x7 << IWM_RFH_RXF_DMA_RBDCB_SIZE_POS)\n#define IWM_RFH_RXF_DMA_RBDCB_SIZE_128      (0x7 << IWM_RFH_RXF_DMA_RBDCB_SIZE_POS)\n#define IWM_RFH_RXF_DMA_RBDCB_SIZE_256      (0x8 << IWM_RFH_RXF_DMA_RBDCB_SIZE_POS)\n#define IWM_RFH_RXF_DMA_RBDCB_SIZE_512      (0x9 << IWM_RFH_RXF_DMA_RBDCB_SIZE_POS)\n#define IWM_RFH_RXF_DMA_RBDCB_SIZE_1024     (0xA << IWM_RFH_RXF_DMA_RBDCB_SIZE_POS)\n#define IWM_RFH_RXF_DMA_RBDCB_SIZE_2048     (0xB << IWM_RFH_RXF_DMA_RBDCB_SIZE_POS)\n#define IWM_RFH_RXF_DMA_MIN_RB_SIZE_MASK    (0x03000000) /* bit 24-25 */\n#define IWM_RFH_RXF_DMA_MIN_RB_SIZE_POS     24\n#define IWM_RFH_RXF_DMA_MIN_RB_4_8          (3 << IWM_RFH_RXF_DMA_MIN_RB_SIZE_POS)\n#define IWM_RFH_RXF_DMA_DROP_TOO_LARGE_MASK (0x04000000) /* bit 26 */\n#define IWM_RFH_RXF_DMA_SINGLE_FRAME_MASK   (0x20000000) /* bit 29 */\n#define IWM_RFH_DMA_EN_MASK                 (0xC0000000) /* bits 30-31*/\n#define IWM_RFH_DMA_EN_ENABLE_VAL           (1U << 31)\n\n#define IWM_RFH_RXF_RXQ_ACTIVE 0xA0980C\n\n#define IWM_RFH_GEN_CFG     0xA09800\n#define IWM_RFH_GEN_CFG_SERVICE_DMA_SNOOP   (1 << 0)\n#define IWM_RFH_GEN_CFG_RFH_DMA_SNOOP       (1 << 1)\n#define IWM_RFH_GEN_CFG_RB_CHUNK_SIZE_128   0x00000010\n#define IWM_RFH_GEN_CFG_RB_CHUNK_SIZE_64    0x00000000\n/* the driver assumes everywhere that the default RXQ is 0 */\n#define IWM_RFH_GEN_CFG_DEFAULT_RXQ_NUM     0xF00\n\n/* end of 9000 rx series registers */\n\n#define IWM_LMPM_SECURE_UCODE_LOAD_CPU1_HDR_ADDR    0x1e78\n#define IWM_LMPM_SECURE_UCODE_LOAD_CPU2_HDR_ADDR    0x1e7c\n\n#define IWM_LMPM_SECURE_CPU1_HDR_MEM_SPACE        0x420000\n#define IWM_LMPM_SECURE_CPU2_HDR_MEM_SPACE        0x420400\n\n#define IWM_CSR_SECURE_TIME_OUT    (100)\n\n/* extended range in FW SRAM */\n#define IWM_FW_MEM_EXTENDED_START       0x40000\n#define IWM_FW_MEM_EXTENDED_END         0x57FFF\n\n/* FW chicken bits */\n#define IWM_LMPM_CHICK                0xa01ff8\n#define IWM_LMPM_CHICK_EXTENDED_ADDR_SPACE    0x01\n\n#define IWM_FH_TCSR_0_REG0 (0x1D00)\n\n/*\n * HBUS (Host-side Bus)\n *\n * HBUS registers are mapped directly into PCI bus space, but are used\n * to indirectly access device's internal memory or registers that\n * may be powered-down.\n *\n * Use iwl_write_direct32()/iwl_read_direct32() family for these registers;\n * host must \"grab nic access\" via CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ\n * to make sure the MAC (uCode processor, etc.) is powered up for accessing\n * internal resources.\n *\n * Do not use iwl_write32()/iwl_read32() family to access these registers;\n * these provide only simple PCI bus access, without waking up the MAC.\n */\n#define IWM_HBUS_BASE    (0x400)\n\n/*\n * Registers for accessing device's internal SRAM memory (e.g. SCD SRAM\n * structures, error log, event log, verifying uCode load).\n * First write to address register, then read from or write to data register\n * to complete the job.  Once the address register is set up, accesses to\n * data registers auto-increment the address by one dword.\n * Bit usage for address registers (read or write):\n *  0-31:  memory address within device\n */\n#define IWM_HBUS_TARG_MEM_RADDR     (IWM_HBUS_BASE+0x00c)\n#define IWM_HBUS_TARG_MEM_WADDR     (IWM_HBUS_BASE+0x010)\n#define IWM_HBUS_TARG_MEM_WDAT      (IWM_HBUS_BASE+0x018)\n#define IWM_HBUS_TARG_MEM_RDAT      (IWM_HBUS_BASE+0x01c)\n\n/* Mailbox C, used as workaround alternative to CSR_UCODE_DRV_GP1 mailbox */\n#define IWM_HBUS_TARG_MBX_C         (IWM_HBUS_BASE+0x030)\n#define IWM_HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED         (0x00000004)\n\n/*\n * Registers for accessing device's internal peripheral registers\n * (e.g. SCD, BSM, etc.).  First write to address register,\n * then read from or write to data register to complete the job.\n * Bit usage for address registers (read or write):\n *  0-15:  register address (offset) within device\n * 24-25:  (# bytes - 1) to read or write (e.g. 3 for dword)\n */\n#define IWM_HBUS_TARG_PRPH_WADDR    (IWM_HBUS_BASE+0x044)\n#define IWM_HBUS_TARG_PRPH_RADDR    (IWM_HBUS_BASE+0x048)\n#define IWM_HBUS_TARG_PRPH_WDAT     (IWM_HBUS_BASE+0x04c)\n#define IWM_HBUS_TARG_PRPH_RDAT     (IWM_HBUS_BASE+0x050)\n\n/* enable the ID buf for read */\n#define IWM_WFPM_PS_CTL_CLR            0xa0300c\n#define IWM_WFMP_MAC_ADDR_0            0xa03080\n#define IWM_WFMP_MAC_ADDR_1            0xa03084\n#define IWM_LMPM_PMG_EN                0xa01cec\n#define IWM_RADIO_REG_SYS_MANUAL_DFT_0        0xad4078\n#define IWM_RFIC_REG_RD                0xad0470\n#define IWM_WFPM_CTRL_REG            0xa03030\n#define IWM_WFPM_AUX_CTL_AUX_IF_MAC_OWNER_MSK    0x08000000\n#define IWM_ENABLE_WFPM                0x80000000\n\n#define IWM_AUX_MISC_REG            0xa200b0\n#define IWM_HW_STEP_LOCATION_BITS        24\n\n#define IWM_AUX_MISC_MASTER1_EN            0xa20818\n#define IWM_AUX_MISC_MASTER1_EN_SBE_MSK        0x1\n#define IWM_AUX_MISC_MASTER1_SMPHR_STATUS    0xa20800\n#define IWM_RSA_ENABLE                0xa24b08\n#define IWM_PREG_AUX_BUS_WPROT_0        0xa04cc0\n#define IWM_PREG_PRPH_WPROT_9000        0xa04ce0\n#define IWM_PREG_PRPH_WPROT_22000        0xa04d00\n#define IWM_SB_CFG_OVERRIDE_ADDR        0xa26c78\n#define IWM_SB_CFG_OVERRIDE_ENABLE        0x8000\n#define IWM_SB_CFG_BASE_OVERRIDE        0xa20000\n#define IWM_SB_MODIFY_CFG_FLAG            0xa03088\n#define IWM_SB_CPU_1_STATUS            0xa01e30\n#define IWM_SB_CPU_2_STATUS            0Xa01e34\n\n#define IWM_UREG_CHICK                0xa05c00\n#define IWM_UREG_CHICK_MSI_ENABLE        (1 << 24)\n#define IWM_UREG_CHICK_MSIX_ENABLE        (1 << 25)\n\n#define IWM_HPM_DEBUG                0xa03440\n#define IWM_HPM_PERSISTENCE_BIT            (1 << 12)\n#define IWM_PREG_WFPM_ACCESS            (1 << 12)\n\n/* Used to enable DBGM */\n#define IWM_HBUS_TARG_TEST_REG    (IWM_HBUS_BASE+0x05c)\n\n/*\n * Per-Tx-queue write pointer (index, really!)\n * Indicates index to next TFD that driver will fill (1 past latest filled).\n * Bit usage:\n *  0-7:  queue write index\n * 11-8:  queue selector\n */\n#define IWM_HBUS_TARG_WRPTR         (IWM_HBUS_BASE+0x060)\n\n/**********************************************************\n * CSR values\n **********************************************************/\n /*\n * host interrupt timeout value\n * used with setting interrupt coalescing timer\n * the CSR_INT_COALESCING is an 8 bit register in 32-usec unit\n *\n * default interrupt coalescing timer is 64 x 32 = 2048 usecs\n */\n#define IWM_HOST_INT_TIMEOUT_MAX    (0xFF)\n#define IWM_HOST_INT_TIMEOUT_DEF    (0x40)\n#define IWM_HOST_INT_TIMEOUT_MIN    (0x0)\n#define IWM_HOST_INT_OPER_MODE        (1U << 31)\n\n/*****************************************************************************\n *                        7000/3000 series SHR DTS addresses                 *\n *****************************************************************************/\n\n/* Diode Results Register Structure: */\n#define IWM_DTS_DIODE_REG_DIG_VAL        0x000000FF /* bits [7:0] */\n#define IWM_DTS_DIODE_REG_VREF_LOW        0x0000FF00 /* bits [15:8] */\n#define IWM_DTS_DIODE_REG_VREF_HIGH        0x00FF0000 /* bits [23:16] */\n#define IWM_DTS_DIODE_REG_VREF_ID        0x03000000 /* bits [25:24] */\n#define IWM_DTS_DIODE_REG_PASS_ONCE        0x80000000 /* bits [31:31] */\n#define IWM_DTS_DIODE_REG_FLAGS_MSK        0xFF000000 /* bits [31:24] */\n/* Those are the masks INSIDE the flags bit-field: */\n#define IWM_DTS_DIODE_REG_FLAGS_VREFS_ID_POS    0\n#define IWM_DTS_DIODE_REG_FLAGS_VREFS_ID    0x00000003 /* bits [1:0] */\n#define IWM_DTS_DIODE_REG_FLAGS_PASS_ONCE_POS    7\n#define IWM_DTS_DIODE_REG_FLAGS_PASS_ONCE    0x00000080 /* bits [7:7] */\n\n/*****************************************************************************\n *                        MSIX related registers                             *\n *****************************************************************************/\n\n#define IWM_CSR_MSIX_BASE            (0x2000)\n#define IWM_CSR_MSIX_FH_INT_CAUSES_AD        (IWM_CSR_MSIX_BASE + 0x800)\n#define IWM_CSR_MSIX_FH_INT_MASK_AD        (IWM_CSR_MSIX_BASE + 0x804)\n#define IWM_CSR_MSIX_HW_INT_CAUSES_AD        (IWM_CSR_MSIX_BASE + 0x808)\n#define IWM_CSR_MSIX_HW_INT_MASK_AD        (IWM_CSR_MSIX_BASE + 0x80C)\n#define IWM_CSR_MSIX_AUTOMASK_ST_AD        (IWM_CSR_MSIX_BASE + 0x810)\n#define IWM_CSR_MSIX_RX_IVAR_AD_REG        (IWM_CSR_MSIX_BASE + 0x880)\n#define IWM_CSR_MSIX_IVAR_AD_REG        (IWM_CSR_MSIX_BASE + 0x890)\n#define IWM_CSR_MSIX_PENDING_PBA_AD        (IWM_CSR_MSIX_BASE + 0x1000)\n#define IWM_CSR_MSIX_RX_IVAR(cause)        (IWM_CSR_MSIX_RX_IVAR_AD_REG + (cause))\n#define IWM_CSR_MSIX_IVAR(cause)        (IWM_CSR_MSIX_IVAR_AD_REG + (cause))\n\n/*\n * Causes for the FH register interrupts\n */\nenum iwm_msix_fh_int_causes {\n    IWM_MSIX_FH_INT_CAUSES_Q0        = (1 << 0),\n    IWM_MSIX_FH_INT_CAUSES_Q1        = (1 << 1),\n    IWM_MSIX_FH_INT_CAUSES_D2S_CH0_NUM    = (1 << 16),\n    IWM_MSIX_FH_INT_CAUSES_D2S_CH1_NUM    = (1 << 17),\n    IWM_MSIX_FH_INT_CAUSES_S2D        = (1 << 19),\n    IWM_MSIX_FH_INT_CAUSES_FH_ERR        = (1 << 21),\n};\n\n/*\n * Causes for the HW register interrupts\n */\nenum iwm_msix_hw_int_causes {\n    IWM_MSIX_HW_INT_CAUSES_REG_ALIVE    = (1 << 0),\n    IWM_MSIX_HW_INT_CAUSES_REG_WAKEUP    = (1 << 1),\n    IWM_MSIX_HW_INT_CAUSES_REG_IPC        = (1 << 1),\n    IWM_MSIX_HW_INT_CAUSES_REG_IML        = (1 << 2),\n    IWM_MSIX_HW_INT_CAUSES_REG_SW_ERR_V2    = (1 << 5),\n    IWM_MSIX_HW_INT_CAUSES_REG_CT_KILL    = (1 << 6),\n    IWM_MSIX_HW_INT_CAUSES_REG_RF_KILL    = (1 << 7),\n    IWM_MSIX_HW_INT_CAUSES_REG_PERIODIC    = (1 << 8),\n    IWM_MSIX_HW_INT_CAUSES_REG_SW_ERR    = (1 << 25),\n    IWM_MSIX_HW_INT_CAUSES_REG_SCD        = (1 << 26),\n    IWM_MSIX_HW_INT_CAUSES_REG_FH_TX    = (1 << 27),\n    IWM_MSIX_HW_INT_CAUSES_REG_HW_ERR    = (1 << 29),\n    IWM_MSIX_HW_INT_CAUSES_REG_HAP        = (1 << 30),\n};\n\n/*\n * Registers to map causes to vectors\n */\nenum iwm_msix_ivar_for_cause {\n    IWM_MSIX_IVAR_CAUSE_D2S_CH0_NUM        = 0x0,\n    IWM_MSIX_IVAR_CAUSE_D2S_CH1_NUM        = 0x1,\n    IWM_MSIX_IVAR_CAUSE_S2D            = 0x3,\n    IWM_MSIX_IVAR_CAUSE_FH_ERR        = 0x5,\n    IWM_MSIX_IVAR_CAUSE_REG_ALIVE        = 0x10,\n    IWM_MSIX_IVAR_CAUSE_REG_WAKEUP        = 0x11,\n    IWM_MSIX_IVAR_CAUSE_REG_IML        = 0x12,\n    IWM_MSIX_IVAR_CAUSE_REG_CT_KILL        = 0x16,\n    IWM_MSIX_IVAR_CAUSE_REG_RF_KILL        = 0x17,\n    IWM_MSIX_IVAR_CAUSE_REG_PERIODIC    = 0x18,\n    IWM_MSIX_IVAR_CAUSE_REG_SW_ERR        = 0x29,\n    IWM_MSIX_IVAR_CAUSE_REG_SCD        = 0x2a,\n    IWM_MSIX_IVAR_CAUSE_REG_FH_TX        = 0x2b,\n    IWM_MSIX_IVAR_CAUSE_REG_HW_ERR        = 0x2d,\n    IWM_MSIX_IVAR_CAUSE_REG_HAP        = 0x2e,\n};\n\n#define IWM_MSIX_AUTO_CLEAR_CAUSE        (0 << 7)\n#define IWM_MSIX_NON_AUTO_CLEAR_CAUSE        (1 << 7)\n\n/**\n * uCode API flags\n * @IWM_UCODE_TLV_FLAGS_PAN: This is PAN capable microcode; this previously\n *    was a separate TLV but moved here to save space.\n * @IWM_UCODE_TLV_FLAGS_NEWSCAN: new uCode scan behaviour on hidden SSID,\n *    treats good CRC threshold as a boolean\n * @IWM_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w).\n * @IWM_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P.\n * @IWM_UCODE_TLV_FLAGS_DW_BC_TABLE: The SCD byte count table is in DWORDS\n * @IWM_UCODE_TLV_FLAGS_UAPSD: This uCode image supports uAPSD\n * @IWM_UCODE_TLV_FLAGS_SHORT_BL: 16 entries of black list instead of 64 in scan\n *    offload profile config command.\n * @IWM_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS: D3 image supports up to six\n *    (rather than two) IPv6 addresses\n * @IWM_UCODE_TLV_FLAGS_NO_BASIC_SSID: not sending a probe with the SSID element\n *    from the probe request template.\n * @IWM_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL: new NS offload (small version)\n * @IWM_UCODE_TLV_FLAGS_NEW_NSOFFL_LARGE: new NS offload (large version)\n * @IWM_UCODE_TLV_FLAGS_P2P_PS: P2P client power save is supported (only on a\n *    single bound interface).\n * @IWM_UCODE_TLV_FLAGS_UAPSD_SUPPORT: General support for uAPSD\n * @IWM_UCODE_TLV_FLAGS_EBS_SUPPORT: this uCode image supports EBS.\n * @IWM_UCODE_TLV_FLAGS_P2P_PS_UAPSD: P2P client supports uAPSD power save\n * @IWM_UCODE_TLV_FLAGS_BCAST_FILTERING: uCode supports broadcast filtering.\n * @IWM_UCODE_TLV_FLAGS_GO_UAPSD: AP/GO interfaces support uAPSD clients\n *\n */\n#define IWM_UCODE_TLV_FLAGS_PAN            (1 << 0)\n#define IWM_UCODE_TLV_FLAGS_NEWSCAN        (1 << 1)\n#define IWM_UCODE_TLV_FLAGS_MFP            (1 << 2)\n#define IWM_UCODE_TLV_FLAGS_P2P            (1 << 3)\n#define IWM_UCODE_TLV_FLAGS_DW_BC_TABLE        (1 << 4)\n#define IWM_UCODE_TLV_FLAGS_SHORT_BL        (1 << 7)\n#define IWM_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS    (1 << 10)\n#define IWM_UCODE_TLV_FLAGS_NO_BASIC_SSID    (1 << 12)\n#define IWM_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL    (1 << 15)\n#define IWM_UCODE_TLV_FLAGS_NEW_NSOFFL_LARGE    (1 << 16)\n#define IWM_UCODE_TLV_FLAGS_P2P_PS        (1 << 21)\n#define IWM_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM    (1 << 22)\n#define IWM_UCODE_TLV_FLAGS_BSS_P2P_PS_SCM    (1 << 23)\n#define IWM_UCODE_TLV_FLAGS_UAPSD_SUPPORT    (1 << 24)\n#define IWM_UCODE_TLV_FLAGS_EBS_SUPPORT        (1 << 25)\n#define IWM_UCODE_TLV_FLAGS_P2P_PS_UAPSD    (1 << 26)\n#define IWM_UCODE_TLV_FLAGS_BCAST_FILTERING    (1 << 29)\n#define IWM_UCODE_TLV_FLAGS_GO_UAPSD        (1 << 30)\n#define IWM_UCODE_TLV_FLAGS_LTE_COEX        (1U << 31)\n\n#define IWM_UCODE_TLV_FLAG_BITS \\\n    \"\\020\\1PAN\\2NEWSCAN\\3MFP\\4P2P\\5DW_BC_TABLE\\6NEWBT_COEX\\7PM_CMD\\10SHORT_BL\\11RX_ENERGY\\12TIME_EVENT_V2\\13D3_6_IPV6\\14BF_UPDATED\\15NO_BASIC_SSID\\17D3_CONTINUITY\\20NEW_NSOFFL_S\\21NEW_NSOFFL_L\\22SCHED_SCAN\\24STA_KEY_CMD\\25DEVICE_PS_CMD\\26P2P_PS\\27P2P_PS_DCM\\30P2P_PS_SCM\\31UAPSD_SUPPORT\\32EBS\\33P2P_PS_UAPSD\\36BCAST_FILTERING\\37GO_UAPSD\\40LTE_COEX\"\n\n/**\n * uCode TLV api\n * @IWM_UCODE_TLV_API_FRAGMENTED_SCAN: This ucode supports active dwell time\n *    longer than the passive one, which is essential for fragmented scan.\n * @IWM_UCODE_TLV_API_WIFI_MCC_UPDATE: ucode supports MCC updates with source.\n * @IWM_UCODE_TLV_API_WIDE_CMD_HDR: ucode supports wide command header\n * @IWM_UCODE_TLV_API_LQ_SS_PARAMS: Configure STBC/BFER via LQ CMD ss_params\n * @IWM_UCODE_TLV_API_NEW_VERSION: new versioning format\n * @IWM_UCODE_TLV_API_TX_POWER_CHAIN: TX power API has larger command size\n *    (command version 3) that supports per-chain limits\n * @IWM_UCODE_TLV_API_SCAN_TSF_REPORT: Scan start time reported in scan\n *    iteration complete notification, and the timestamp reported for RX\n *    received during scan, are reported in TSF of the mac specified in the\n *    scan request.\n * @IWM_UCODE_TLV_API_TKIP_MIC_KEYS: This ucode supports version 2 of\n *    ADD_MODIFY_STA_KEY_API_S_VER_2.\n * @IWM_UCODE_TLV_API_STA_TYPE: This ucode supports station type assignement.\n * @IWM_UCODE_TLV_API_EXT_SCAN_PRIORITY: scan APIs use 8-level priority\n *    instead of 3.\n * @IWM_UCODE_TLV_API_NEW_RX_STATS: should new RX STATISTICS API be used\n *\n * @IWM_NUM_UCODE_TLV_API: number of bits used\n */\n#define IWM_UCODE_TLV_API_FRAGMENTED_SCAN    8\n#define IWM_UCODE_TLV_API_WIFI_MCC_UPDATE    9\n#define IWM_UCODE_TLV_API_WIDE_CMD_HDR        14\n#define IWM_UCODE_TLV_API_LQ_SS_PARAMS        18\n#define IWM_UCODE_TLV_API_NEW_VERSION        20\n#define IWM_UCODE_TLV_API_EXT_SCAN_PRIORITY    24\n#define IWM_UCODE_TLV_API_TX_POWER_CHAIN    27\n#define IWM_UCODE_TLV_API_SCAN_TSF_REPORT    28\n#define IWM_UCODE_TLV_API_TKIP_MIC_KEYS         29\n#define IWM_UCODE_TLV_API_STA_TYPE        30\n#define IWM_UCODE_TLV_API_NAN2_VER2        31\n#define IWM_UCODE_TLV_API_ADAPTIVE_DWELL    32\n#define IWM_UCODE_TLV_API_NEW_RX_STATS        35\n#define IWM_UCODE_TLV_API_QUOTA_LOW_LATENCY    38\n#define IWM_UCODE_TLV_API_ADAPTIVE_DWELL_V2    42\n#define IWM_UCODE_TLV_API_SCAN_EXT_CHAN_VER    58\n#define IWM_NUM_UCODE_TLV_API            128\n\n#define IWM_UCODE_TLV_API_BITS \\\n    \"\\020\\10FRAGMENTED_SCAN\\11WIFI_MCC_UPDATE\\16WIDE_CMD_HDR\\22LQ_SS_PARAMS\\30EXT_SCAN_PRIO\\33TX_POWER_CHAIN\\35TKIP_MIC_KEYS\"\n\n/**\n * uCode capabilities\n * @IWM_UCODE_TLV_CAPA_D0I3_SUPPORT: supports D0i3\n * @IWM_UCODE_TLV_CAPA_LAR_SUPPORT: supports Location Aware Regulatory\n * @IWM_UCODE_TLV_CAPA_UMAC_SCAN: supports UMAC scan.\n * @IWM_UCODE_TLV_CAPA_BEAMFORMER: supports Beamformer\n * @IWM_UCODE_TLV_CAPA_TOF_SUPPORT: supports Time of Flight (802.11mc FTM)\n * @IWM_UCODE_TLV_CAPA_TDLS_SUPPORT: support basic TDLS functionality\n * @IWM_UCODE_TLV_CAPA_TXPOWER_INSERTION_SUPPORT: supports insertion of current\n *    tx power value into TPC Report action frame and Link Measurement Report\n *    action frame\n * @IWM_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT: supports updating current\n *    channel in DS parameter set element in probe requests.\n * @IWM_UCODE_TLV_CAPA_WFA_TPC_REP_IE_SUPPORT: supports adding TPC Report IE in\n *    probe requests.\n * @IWM_UCODE_TLV_CAPA_QUIET_PERIOD_SUPPORT: supports Quiet Period requests\n * @IWM_UCODE_TLV_CAPA_DQA_SUPPORT: supports dynamic queue allocation (DQA),\n *    which also implies support for the scheduler configuration command\n * @IWM_UCODE_TLV_CAPA_TDLS_CHANNEL_SWITCH: supports TDLS channel switching\n * @IWM_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG: Consolidated D3-D0 image\n * @IWM_UCODE_TLV_CAPA_HOTSPOT_SUPPORT: supports Hot Spot Command\n * @IWM_UCODE_TLV_CAPA_DC2DC_SUPPORT: supports DC2DC Command\n * @IWM_UCODE_TLV_CAPA_2G_COEX_SUPPORT: supports 2G coex Command\n * @IWM_UCODE_TLV_CAPA_CSUM_SUPPORT: supports TCP Checksum Offload\n * @IWM_UCODE_TLV_CAPA_RADIO_BEACON_STATS: support radio and beacon statistics\n * @IWM_UCODE_TLV_CAPA_P2P_STANDALONE_UAPSD: support p2p standalone U-APSD\n * @IWM_UCODE_TLV_CAPA_BT_COEX_PLCR: enabled BT Coex packet level co-running\n * @IWM_UCODE_TLV_CAPA_LAR_MULTI_MCC: ucode supports LAR updates with different\n *    sources for the MCC. This TLV bit is a future replacement to\n *    IWM_UCODE_TLV_API_WIFI_MCC_UPDATE. When either is set, multi-source LAR\n *    is supported.\n * @IWM_UCODE_TLV_CAPA_BT_COEX_RRC: supports BT Coex RRC\n * @IWM_UCODE_TLV_CAPA_GSCAN_SUPPORT: supports gscan\n * @IWM_UCODE_TLV_CAPA_NAN_SUPPORT: supports NAN\n * @IWM_UCODE_TLV_CAPA_UMAC_UPLOAD: supports upload mode in umac (1=supported,\n *    0=no support)\n * @IWM_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE: extended DTS measurement\n * @IWM_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS: supports short PM timeouts\n * @IWM_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT: supports bt-coex Multi-priority LUT\n * @IWM_UCODE_TLV_CAPA_BEACON_ANT_SELECTION: firmware will decide on what\n *    antenna the beacon should be transmitted\n * @IWM_UCODE_TLV_CAPA_BEACON_STORING: firmware will store the latest beacon\n *    from AP and will send it upon d0i3 exit.\n * @IWM_UCODE_TLV_CAPA_LAR_SUPPORT_V2: support LAR API V2\n * @IWM_UCODE_TLV_CAPA_CT_KILL_BY_FW: firmware responsible for CT-kill\n * @IWM_UCODE_TLV_CAPA_TEMP_THS_REPORT_SUPPORT: supports temperature\n *    thresholds reporting\n * @IWM_UCODE_TLV_CAPA_CTDP_SUPPORT: supports cTDP command\n * @IWM_UCODE_TLV_CAPA_USNIFFER_UNIFIED: supports usniffer enabled in\n *    regular image.\n * @IWM_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG: support getting more shared\n *    memory addresses from the firmware.\n * @IWM_UCODE_TLV_CAPA_LQM_SUPPORT: supports Link Quality Measurement\n * @IWM_UCODE_TLV_CAPA_LMAC_UPLOAD: supports upload mode in lmac (1=supported,\n *    0=no support)\n *\n * @IWM_NUM_UCODE_TLV_CAPA: number of bits used\n */\n#define IWM_UCODE_TLV_CAPA_D0I3_SUPPORT            0\n#define IWM_UCODE_TLV_CAPA_LAR_SUPPORT            1\n#define IWM_UCODE_TLV_CAPA_UMAC_SCAN            2\n#define IWM_UCODE_TLV_CAPA_BEAMFORMER            3\n#define IWM_UCODE_TLV_CAPA_TOF_SUPPORT                  5\n#define IWM_UCODE_TLV_CAPA_TDLS_SUPPORT            6\n#define IWM_UCODE_TLV_CAPA_TXPOWER_INSERTION_SUPPORT    8\n#define IWM_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT    9\n#define IWM_UCODE_TLV_CAPA_WFA_TPC_REP_IE_SUPPORT    10\n#define IWM_UCODE_TLV_CAPA_QUIET_PERIOD_SUPPORT        11\n#define IWM_UCODE_TLV_CAPA_DQA_SUPPORT            12\n#define IWM_UCODE_TLV_CAPA_TDLS_CHANNEL_SWITCH        13\n#define IWM_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG        17\n#define IWM_UCODE_TLV_CAPA_HOTSPOT_SUPPORT        18\n#define IWM_UCODE_TLV_CAPA_DC2DC_CONFIG_SUPPORT        19\n#define IWM_UCODE_TLV_CAPA_2G_COEX_SUPPORT        20\n#define IWM_UCODE_TLV_CAPA_CSUM_SUPPORT            21\n#define IWM_UCODE_TLV_CAPA_RADIO_BEACON_STATS        22\n#define IWM_UCODE_TLV_CAPA_P2P_STANDALONE_UAPSD        26\n#define IWM_UCODE_TLV_CAPA_BT_COEX_PLCR            28\n#define IWM_UCODE_TLV_CAPA_LAR_MULTI_MCC        29\n#define IWM_UCODE_TLV_CAPA_BT_COEX_RRC            30\n#define IWM_UCODE_TLV_CAPA_GSCAN_SUPPORT        31\n#define IWM_UCODE_TLV_CAPA_NAN_SUPPORT            34\n#define IWM_UCODE_TLV_CAPA_UMAC_UPLOAD            35\n#define IWM_UCODE_TLV_CAPA_SOC_LATENCY_SUPPORT        37\n#define IWM_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT        39\n#define IWM_UCODE_TLV_CAPA_CDB_SUPPORT            40\n#define IWM_UCODE_TLV_CAPA_DYNAMIC_QUOTA                44\n#define IWM_UCODE_TLV_CAPA_COEX_SCHEMA_2            45\n#define IWM_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS        48\n#define IWM_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE        64\n#define IWM_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS        65\n#define IWM_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT        67\n#define IWM_UCODE_TLV_CAPA_MULTI_QUEUE_RX_SUPPORT    68\n#define IWM_UCODE_TLV_CAPA_BEACON_ANT_SELECTION        71\n#define IWM_UCODE_TLV_CAPA_BEACON_STORING        72\n#define IWM_UCODE_TLV_CAPA_LAR_SUPPORT_V3        73\n#define IWM_UCODE_TLV_CAPA_CT_KILL_BY_FW        74\n#define IWM_UCODE_TLV_CAPA_TEMP_THS_REPORT_SUPPORT    75\n#define IWM_UCODE_TLV_CAPA_CTDP_SUPPORT            76\n#define IWM_UCODE_TLV_CAPA_USNIFFER_UNIFIED        77\n#define IWM_UCODE_TLV_CAPA_LMAC_UPLOAD            79\n#define IWM_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG    80\n#define IWM_UCODE_TLV_CAPA_LQM_SUPPORT            81\n\n#define IWM_NUM_UCODE_TLV_CAPA 128\n\n/* The default calibrate table size if not specified by firmware file */\n#define IWM_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE    18\n#define IWM_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE        19\n#define IWM_MAX_PHY_CALIBRATE_TBL_SIZE            253\n\n/* The default max probe length if not specified by the firmware file */\n#define IWM_DEFAULT_MAX_PROBE_LENGTH    200\n\n/*\n * For 16.0 uCode and above, there is no differentiation between sections,\n * just an offset to the HW address.\n */\n#define IWM_CPU1_CPU2_SEPARATOR_SECTION        0xFFFFCCCC\n#define IWM_PAGING_SEPARATOR_SECTION        0xAAAABBBB\n\n/* uCode version contains 4 values: Major/Minor/API/Serial */\n#define IWM_UCODE_MAJOR(ver)    (((ver) & 0xFF000000) >> 24)\n#define IWM_UCODE_MINOR(ver)    (((ver) & 0x00FF0000) >> 16)\n#define IWM_UCODE_API(ver)    (((ver) & 0x0000FF00) >> 8)\n#define IWM_UCODE_SERIAL(ver)    ((ver) & 0x000000FF)\n\n/*\n * Calibration control struct.\n * Sent as part of the phy configuration command.\n * @flow_trigger: bitmap for which calibrations to perform according to\n *        flow triggers.\n * @event_trigger: bitmap for which calibrations to perform according to\n *        event triggers.\n */\nstruct iwm_tlv_calib_ctrl {\n    uint32_t flow_trigger;\n    uint32_t event_trigger;\n} __packed;\n\n#define IWM_FW_PHY_CFG_RADIO_TYPE_POS    0\n#define IWM_FW_PHY_CFG_RADIO_TYPE    (0x3 << IWM_FW_PHY_CFG_RADIO_TYPE_POS)\n#define IWM_FW_PHY_CFG_RADIO_STEP_POS    2\n#define IWM_FW_PHY_CFG_RADIO_STEP    (0x3 << IWM_FW_PHY_CFG_RADIO_STEP_POS)\n#define IWM_FW_PHY_CFG_RADIO_DASH_POS    4\n#define IWM_FW_PHY_CFG_RADIO_DASH    (0x3 << IWM_FW_PHY_CFG_RADIO_DASH_POS)\n#define IWM_FW_PHY_CFG_TX_CHAIN_POS    16\n#define IWM_FW_PHY_CFG_TX_CHAIN        (0xf << IWM_FW_PHY_CFG_TX_CHAIN_POS)\n#define IWM_FW_PHY_CFG_RX_CHAIN_POS    20\n#define IWM_FW_PHY_CFG_RX_CHAIN        (0xf << IWM_FW_PHY_CFG_RX_CHAIN_POS)\n\n#define IWM_UCODE_MAX_CS        1\n\n/**\n * struct iwm_fw_cipher_scheme - a cipher scheme supported by FW.\n * @cipher: a cipher suite selector\n * @flags: cipher scheme flags (currently reserved for a future use)\n * @hdr_len: a size of MPDU security header\n * @pn_len: a size of PN\n * @pn_off: an offset of pn from the beginning of the security header\n * @key_idx_off: an offset of key index byte in the security header\n * @key_idx_mask: a bit mask of key_idx bits\n * @key_idx_shift: bit shift needed to get key_idx\n * @mic_len: mic length in bytes\n * @hw_cipher: a HW cipher index used in host commands\n */\nstruct iwm_fw_cipher_scheme {\n    uint32_t cipher;\n    uint8_t flags;\n    uint8_t hdr_len;\n    uint8_t pn_len;\n    uint8_t pn_off;\n    uint8_t key_idx_off;\n    uint8_t key_idx_mask;\n    uint8_t key_idx_shift;\n    uint8_t mic_len;\n    uint8_t hw_cipher;\n} __packed;\n\n/**\n * struct iwm_fw_cscheme_list - a cipher scheme list\n * @size: a number of entries\n * @cs: cipher scheme entries\n */\nstruct iwm_fw_cscheme_list {\n    uint8_t size;\n    struct iwm_fw_cipher_scheme cs[];\n} __packed;\n\n/* v1/v2 uCode file layout */\nstruct iwm_ucode_header {\n    uint32_t ver;    /* major/minor/API/serial */\n    union {\n        struct {\n            uint32_t inst_size;    /* bytes of runtime code */\n            uint32_t data_size;    /* bytes of runtime data */\n            uint32_t init_size;    /* bytes of init code */\n            uint32_t init_data_size;    /* bytes of init data */\n            uint32_t boot_size;    /* bytes of bootstrap code */\n            uint8_t data[0];        /* in same order as sizes */\n        } v1;\n        struct {\n            uint32_t build;        /* build number */\n            uint32_t inst_size;    /* bytes of runtime code */\n            uint32_t data_size;    /* bytes of runtime data */\n            uint32_t init_size;    /* bytes of init code */\n            uint32_t init_data_size;    /* bytes of init data */\n            uint32_t boot_size;    /* bytes of bootstrap code */\n            uint8_t data[0];        /* in same order as sizes */\n        } v2;\n    } u;\n};\n\n/*\n * new TLV uCode file layout\n *\n * The new TLV file format contains TLVs, that each specify\n * some piece of data.\n */\n\n#define IWM_UCODE_TLV_INVALID        0 /* unused */\n#define IWM_UCODE_TLV_INST        1\n#define IWM_UCODE_TLV_DATA        2\n#define IWM_UCODE_TLV_INIT        3\n#define IWM_UCODE_TLV_INIT_DATA        4\n#define IWM_UCODE_TLV_BOOT        5\n#define IWM_UCODE_TLV_PROBE_MAX_LEN    6 /* a uint32_t value */\n#define IWM_UCODE_TLV_PAN        7\n#define IWM_UCODE_TLV_RUNT_EVTLOG_PTR    8\n#define IWM_UCODE_TLV_RUNT_EVTLOG_SIZE    9\n#define IWM_UCODE_TLV_RUNT_ERRLOG_PTR    10\n#define IWM_UCODE_TLV_INIT_EVTLOG_PTR    11\n#define IWM_UCODE_TLV_INIT_EVTLOG_SIZE    12\n#define IWM_UCODE_TLV_INIT_ERRLOG_PTR    13\n#define IWM_UCODE_TLV_ENHANCE_SENS_TBL    14\n#define IWM_UCODE_TLV_PHY_CALIBRATION_SIZE 15\n#define IWM_UCODE_TLV_WOWLAN_INST    16\n#define IWM_UCODE_TLV_WOWLAN_DATA    17\n#define IWM_UCODE_TLV_FLAGS        18\n#define IWM_UCODE_TLV_SEC_RT        19\n#define IWM_UCODE_TLV_SEC_INIT        20\n#define IWM_UCODE_TLV_SEC_WOWLAN    21\n#define IWM_UCODE_TLV_DEF_CALIB        22\n#define IWM_UCODE_TLV_PHY_SKU        23\n#define IWM_UCODE_TLV_SECURE_SEC_RT    24\n#define IWM_UCODE_TLV_SECURE_SEC_INIT    25\n#define IWM_UCODE_TLV_SECURE_SEC_WOWLAN    26\n#define IWM_UCODE_TLV_NUM_OF_CPU    27\n#define IWM_UCODE_TLV_CSCHEME        28\n\n    /*\n     * Following two are not in our base tag, but allow\n     * handling ucode version 9.\n     */\n#define IWM_UCODE_TLV_API_CHANGES_SET    29\n#define IWM_UCODE_TLV_ENABLED_CAPABILITIES 30\n#define IWM_UCODE_TLV_N_SCAN_CHANNELS    31\n#define IWM_UCODE_TLV_PAGING        32\n#define IWM_UCODE_TLV_SEC_RT_USNIFFER    34\n#define IWM_UCODE_TLV_SDIO_ADMA_ADDR    35\n#define IWM_UCODE_TLV_FW_VERSION    36\n#define IWM_UCODE_TLV_FW_DBG_DEST    38\n#define IWM_UCODE_TLV_FW_DBG_CONF    39\n#define IWM_UCODE_TLV_FW_DBG_TRIGGER    40\n#define IWM_UCODE_TLV_CMD_VERSIONS    48\n#define IWM_UCODE_TLV_FW_GSCAN_CAPA    50\n#define IWM_UCODE_TLV_FW_MEM_SEG    51\n\n#define IWM_UCODE_TLV_UMAC_DEBUG_ADDRS    54\n#define IWM_UCODE_TLV_LMAC_DEBUG_ADDRS    55\n#define IWM_UCODE_TLV_HW_TYPE        58\n\n#define IWM_UCODE_TLV_DEBUG_BASE        0x1000005\n#define IWM_UCODE_TLV_TYPE_DEBUG_INFO        (IWM_UCODE_TLV_DEBUG_BASE + 0)\n#define IWM_UCODE_TLV_TYPE_BUFFER_ALLOCATION    (IWM_UCODE_TLV_DEBUG_BASE + 1)\n#define IWM_UCODE_TLV_TYPE_HCMD            (IWM_UCODE_TLV_DEBUG_BASE + 2)\n#define IWM_UCODE_TLV_TYPE_REGIONS        (IWM_UCODE_TLV_DEBUG_BASE + 3)\n#define IWM_UCODE_TLV_TYPE_TRIGGERS        (IWM_UCODE_TLV_DEBUG_BASE + 4)\n#define IWM_UCODE_TLV_DEBUG_MAX            IWM_UCODE_TLV_TYPE_TRIGGERS\n\nstruct iwm_ucode_tlv {\n    uint32_t type;        /* see above */\n    uint32_t length;        /* not including type/length fields */\n    uint8_t data[0];\n};\n\nstruct iwm_ucode_api {\n    uint32_t api_index;\n    uint32_t api_flags;\n} __packed;\n\nstruct iwm_ucode_capa {\n    uint32_t api_index;\n    uint32_t api_capa;\n} __packed;\n\n#define IWM_TLV_UCODE_MAGIC    0x0a4c5749\n\nstruct iwm_tlv_ucode_header {\n    /*\n     * The TLV style ucode header is distinguished from\n     * the v1/v2 style header by first four bytes being\n     * zero, as such is an invalid combination of\n     * major/minor/API/serial versions.\n     */\n    uint32_t zero;\n    uint32_t magic;\n    uint8_t human_readable[64];\n    uint32_t ver;        /* major/minor/API/serial */\n    uint32_t build;\n    uint64_t ignore;\n    /*\n     * The data contained herein has a TLV layout,\n     * see above for the TLV header and types.\n     * Note that each TLV is padded to a length\n     * that is a multiple of 4 for alignment.\n     */\n    uint8_t data[0];\n};\n\n/*\n * Registers in this file are internal, not PCI bus memory mapped.\n * Driver accesses these via IWM_HBUS_TARG_PRPH_* registers.\n */\n#define IWM_PRPH_BASE    (0x00000)\n#define IWM_PRPH_END    (0xFFFFF)\n\n/* APMG (power management) constants */\n#define IWM_APMG_BASE            (IWM_PRPH_BASE + 0x3000)\n#define IWM_APMG_CLK_CTRL_REG        (IWM_APMG_BASE + 0x0000)\n#define IWM_APMG_CLK_EN_REG        (IWM_APMG_BASE + 0x0004)\n#define IWM_APMG_CLK_DIS_REG        (IWM_APMG_BASE + 0x0008)\n#define IWM_APMG_PS_CTRL_REG        (IWM_APMG_BASE + 0x000c)\n#define IWM_APMG_PCIDEV_STT_REG        (IWM_APMG_BASE + 0x0010)\n#define IWM_APMG_RFKILL_REG        (IWM_APMG_BASE + 0x0014)\n#define IWM_APMG_RTC_INT_STT_REG    (IWM_APMG_BASE + 0x001c)\n#define IWM_APMG_RTC_INT_MSK_REG    (IWM_APMG_BASE + 0x0020)\n#define IWM_APMG_DIGITAL_SVR_REG    (IWM_APMG_BASE + 0x0058)\n#define IWM_APMG_ANALOG_SVR_REG        (IWM_APMG_BASE + 0x006C)\n\n#define IWM_APMS_CLK_VAL_MRB_FUNC_MODE    (0x00000001)\n#define IWM_APMG_CLK_VAL_DMA_CLK_RQT    (0x00000200)\n#define IWM_APMG_CLK_VAL_BSM_CLK_RQT    (0x00000800)\n\n#define IWM_APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS    (0x00400000)\n#define IWM_APMG_PS_CTRL_VAL_RESET_REQ            (0x04000000)\n#define IWM_APMG_PS_CTRL_MSK_PWR_SRC            (0x03000000)\n#define IWM_APMG_PS_CTRL_VAL_PWR_SRC_VMAIN        (0x00000000)\n#define IWM_APMG_PS_CTRL_VAL_PWR_SRC_VAUX        (0x02000000)\n#define IWM_APMG_SVR_VOLTAGE_CONFIG_BIT_MSK        (0x000001E0) /* bit 8:5 */\n#define IWM_APMG_SVR_DIGITAL_VOLTAGE_1_32        (0x00000060)\n\n#define IWM_APMG_PCIDEV_STT_VAL_L1_ACT_DIS        (0x00000800)\n\n#define IWM_APMG_RTC_INT_STT_RFKILL            (0x10000000)\n\n/* Device system time */\n#define IWM_DEVICE_SYSTEM_TIME_REG 0xA0206C\n\n/* Device NMI register */\n#define IWM_DEVICE_SET_NMI_REG        0x00a01c30\n#define IWM_DEVICE_SET_NMI_VAL_HW    0x01\n#define IWM_DEVICE_SET_NMI_VAL_DRV    0x80\n#define IWM_DEVICE_SET_NMI_8000_REG    0x00a01c24\n#define IWM_DEVICE_SET_NMI_8000_VAL    0x1000000\n\n/*\n * Device reset for family 8000\n * write to bit 24 in order to reset the CPU\n*/\n#define IWM_RELEASE_CPU_RESET        0x300c\n#define IWM_RELEASE_CPU_RESET_BIT    0x1000000\n\n\n/*****************************************************************************\n *                        7000/3000 series SHR DTS addresses                 *\n *****************************************************************************/\n\n#define IWM_SHR_MISC_WFM_DTS_EN        (0x00a10024)\n#define IWM_DTSC_CFG_MODE        (0x00a10604)\n#define IWM_DTSC_VREF_AVG        (0x00a10648)\n#define IWM_DTSC_VREF5_AVG        (0x00a1064c)\n#define IWM_DTSC_CFG_MODE_PERIODIC    (0x2)\n#define IWM_DTSC_PTAT_AVG        (0x00a10650)\n\n\n/**\n * Tx Scheduler\n *\n * The Tx Scheduler selects the next frame to be transmitted, choosing TFDs\n * (Transmit Frame Descriptors) from up to 16 circular Tx queues resident in\n * host DRAM.  It steers each frame's Tx command (which contains the frame\n * data) into one of up to 7 prioritized Tx DMA FIFO channels within the\n * device.  A queue maps to only one (selectable by driver) Tx DMA channel,\n * but one DMA channel may take input from several queues.\n *\n * Tx DMA FIFOs have dedicated purposes.\n *\n * For 5000 series and up, they are used differently\n * (cf. iwl5000_default_queue_to_tx_fifo in iwl-5000.c):\n *\n * 0 -- EDCA BK (background) frames, lowest priority\n * 1 -- EDCA BE (best effort) frames, normal priority\n * 2 -- EDCA VI (video) frames, higher priority\n * 3 -- EDCA VO (voice) and management frames, highest priority\n * 4 -- unused\n * 5 -- unused\n * 6 -- unused\n * 7 -- Commands\n *\n * Driver should normally map queues 0-6 to Tx DMA/FIFO channels 0-6.\n * In addition, driver can map the remaining queues to Tx DMA/FIFO\n * channels 0-3 to support 11n aggregation via EDCA DMA channels.\n *\n * The driver sets up each queue to work in one of two modes:\n *\n * 1)  Scheduler-Ack, in which the scheduler automatically supports a\n *     block-ack (BA) window of up to 64 TFDs.  In this mode, each queue\n *     contains TFDs for a unique combination of Recipient Address (RA)\n *     and Traffic Identifier (TID), that is, traffic of a given\n *     Quality-Of-Service (QOS) priority, destined for a single station.\n *\n *     In scheduler-ack mode, the scheduler keeps track of the Tx status of\n *     each frame within the BA window, including whether it's been transmitted,\n *     and whether it's been acknowledged by the receiving station.  The device\n *     automatically processes block-acks received from the receiving STA,\n *     and reschedules un-acked frames to be retransmitted (successful\n *     Tx completion may end up being out-of-order).\n *\n *     The driver must maintain the queue's Byte Count table in host DRAM\n *     for this mode.\n *     This mode does not support fragmentation.\n *\n * 2)  FIFO (a.k.a. non-Scheduler-ACK), in which each TFD is processed in order.\n *     The device may automatically retry Tx, but will retry only one frame\n *     at a time, until receiving ACK from receiving station, or reaching\n *     retry limit and giving up.\n *\n *     The command queue (#4/#9) must use this mode!\n *     This mode does not require use of the Byte Count table in host DRAM.\n *\n * Driver controls scheduler operation via 3 means:\n * 1)  Scheduler registers\n * 2)  Shared scheduler data base in internal SRAM\n * 3)  Shared data in host DRAM\n *\n * Initialization:\n *\n * When loading, driver should allocate memory for:\n * 1)  16 TFD circular buffers, each with space for (typically) 256 TFDs.\n * 2)  16 Byte Count circular buffers in 16 KBytes contiguous memory\n *     (1024 bytes for each queue).\n *\n * After receiving \"Alive\" response from uCode, driver must initialize\n * the scheduler (especially for queue #4/#9, the command queue, otherwise\n * the driver can't issue commands!):\n */\n#define IWM_SCD_MEM_LOWER_BOUND        (0x0000)\n\n/**\n * Max Tx window size is the max number of contiguous TFDs that the scheduler\n * can keep track of at one time when creating block-ack chains of frames.\n * Note that \"64\" matches the number of ack bits in a block-ack packet.\n */\n#define IWM_SCD_WIN_SIZE                64\n#define IWM_SCD_FRAME_LIMIT                64\n\n#define IWM_SCD_TXFIFO_POS_TID            (0)\n#define IWM_SCD_TXFIFO_POS_RA            (4)\n#define IWM_SCD_QUEUE_RA_TID_MAP_RATID_MSK    (0x01FF)\n\n/* agn SCD */\n#define IWM_SCD_QUEUE_STTS_REG_POS_TXF        (0)\n#define IWM_SCD_QUEUE_STTS_REG_POS_ACTIVE    (3)\n#define IWM_SCD_QUEUE_STTS_REG_POS_WSL        (4)\n#define IWM_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN    (19)\n#define IWM_SCD_QUEUE_STTS_REG_MSK        (0x017F0000)\n\n#define IWM_SCD_QUEUE_CTX_REG1_CREDIT_POS    (8)\n#define IWM_SCD_QUEUE_CTX_REG1_CREDIT_MSK    (0x00FFFF00)\n#define IWM_SCD_QUEUE_CTX_REG1_SUPER_CREDIT_POS    (24)\n#define IWM_SCD_QUEUE_CTX_REG1_SUPER_CREDIT_MSK    (0xFF000000)\n#define IWM_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS    (0)\n#define IWM_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK    (0x0000007F)\n#define IWM_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS    (16)\n#define IWM_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK    (0x007F0000)\n#define IWM_SCD_GP_CTRL_ENABLE_31_QUEUES    (1 << 0)\n#define IWM_SCD_GP_CTRL_AUTO_ACTIVE_MODE    (1 << 18)\n\n/* Context Data */\n#define IWM_SCD_CONTEXT_MEM_LOWER_BOUND    (IWM_SCD_MEM_LOWER_BOUND + 0x600)\n#define IWM_SCD_CONTEXT_MEM_UPPER_BOUND    (IWM_SCD_MEM_LOWER_BOUND + 0x6A0)\n\n/* Tx status */\n#define IWM_SCD_TX_STTS_MEM_LOWER_BOUND    (IWM_SCD_MEM_LOWER_BOUND + 0x6A0)\n#define IWM_SCD_TX_STTS_MEM_UPPER_BOUND    (IWM_SCD_MEM_LOWER_BOUND + 0x7E0)\n\n/* Translation Data */\n#define IWM_SCD_TRANS_TBL_MEM_LOWER_BOUND (IWM_SCD_MEM_LOWER_BOUND + 0x7E0)\n#define IWM_SCD_TRANS_TBL_MEM_UPPER_BOUND (IWM_SCD_MEM_LOWER_BOUND + 0x808)\n\n#define IWM_SCD_CONTEXT_QUEUE_OFFSET(x)\\\n    (IWM_SCD_CONTEXT_MEM_LOWER_BOUND + ((x) * 8))\n\n#define IWM_SCD_TX_STTS_QUEUE_OFFSET(x)\\\n    (IWM_SCD_TX_STTS_MEM_LOWER_BOUND + ((x) * 16))\n\n#define IWM_SCD_TRANS_TBL_OFFSET_QUEUE(x) \\\n    ((IWM_SCD_TRANS_TBL_MEM_LOWER_BOUND + ((x) * 2)) & 0xfffc)\n\n#define IWM_SCD_BASE            (IWM_PRPH_BASE + 0xa02c00)\n\n#define IWM_SCD_SRAM_BASE_ADDR    (IWM_SCD_BASE + 0x0)\n#define IWM_SCD_DRAM_BASE_ADDR    (IWM_SCD_BASE + 0x8)\n#define IWM_SCD_AIT        (IWM_SCD_BASE + 0x0c)\n#define IWM_SCD_TXFACT        (IWM_SCD_BASE + 0x10)\n#define IWM_SCD_ACTIVE        (IWM_SCD_BASE + 0x14)\n#define IWM_SCD_QUEUECHAIN_SEL    (IWM_SCD_BASE + 0xe8)\n#define IWM_SCD_CHAINEXT_EN    (IWM_SCD_BASE + 0x244)\n#define IWM_SCD_AGGR_SEL    (IWM_SCD_BASE + 0x248)\n#define IWM_SCD_INTERRUPT_MASK    (IWM_SCD_BASE + 0x108)\n#define IWM_SCD_GP_CTRL        (IWM_SCD_BASE + 0x1a8)\n#define IWM_SCD_EN_CTRL        (IWM_SCD_BASE + 0x254)\n\nstatic inline unsigned int IWM_SCD_QUEUE_WRPTR(unsigned int chnl)\n{\n    if (chnl < 20)\n        return IWM_SCD_BASE + 0x18 + chnl * 4;\n    return IWM_SCD_BASE + 0x284 + (chnl - 20) * 4;\n}\n\nstatic inline unsigned int IWM_SCD_QUEUE_RDPTR(unsigned int chnl)\n{\n    if (chnl < 20)\n        return IWM_SCD_BASE + 0x68 + chnl * 4;\n    return IWM_SCD_BASE + 0x2B4 + chnl * 4;\n}\n\nstatic inline unsigned int IWM_SCD_QUEUE_STATUS_BITS(unsigned int chnl)\n{\n    if (chnl < 20)\n        return IWM_SCD_BASE + 0x10c + chnl * 4;\n    return IWM_SCD_BASE + 0x334 + chnl * 4;\n}\n\n/*********************** END TX SCHEDULER *************************************/\n\n/* Oscillator clock */\n#define IWM_OSC_CLK                (0xa04068)\n#define IWM_OSC_CLK_FORCE_CONTROL        (0x8)\n\n/****************************/\n/* Flow Handler Definitions */\n/****************************/\n\n/**\n * This I/O area is directly read/writable by driver (e.g. Linux uses writel())\n * Addresses are offsets from device's PCI hardware base address.\n */\n#define IWM_FH_MEM_LOWER_BOUND                   (0x1000)\n#define IWM_FH_MEM_UPPER_BOUND                   (0x2000)\n\n/**\n * Keep-Warm (KW) buffer base address.\n *\n * Driver must allocate a 4KByte buffer that is for keeping the\n * host DRAM powered on (via dummy accesses to DRAM) to maintain low-latency\n * DRAM access when doing Txing or Rxing.  The dummy accesses prevent host\n * from going into a power-savings mode that would cause higher DRAM latency,\n * and possible data over/under-runs, before all Tx/Rx is complete.\n *\n * Driver loads IWM_FH_KW_MEM_ADDR_REG with the physical address (bits 35:4)\n * of the buffer, which must be 4K aligned.  Once this is set up, the device\n * automatically invokes keep-warm accesses when normal accesses might not\n * be sufficient to maintain fast DRAM response.\n *\n * Bit fields:\n *  31-0:  Keep-warm buffer physical base address [35:4], must be 4K aligned\n */\n#define IWM_FH_KW_MEM_ADDR_REG             (IWM_FH_MEM_LOWER_BOUND + 0x97C)\n\n\n/**\n * TFD Circular Buffers Base (CBBC) addresses\n *\n * Device has 16 base pointer registers, one for each of 16 host-DRAM-resident\n * circular buffers (CBs/queues) containing Transmit Frame Descriptors (TFDs)\n * (see struct iwm_tfd_frame).  These 16 pointer registers are offset by 0x04\n * bytes from one another.  Each TFD circular buffer in DRAM must be 256-byte\n * aligned (address bits 0-7 must be 0).\n * Later devices have 20 (5000 series) or 30 (higher) queues, but the registers\n * for them are in different places.\n *\n * Bit fields in each pointer register:\n *  27-0: TFD CB physical base address [35:8], must be 256-byte aligned\n */\n#define IWM_FH_MEM_CBBC_0_15_LOWER_BOUND    (IWM_FH_MEM_LOWER_BOUND + 0x9D0)\n#define IWM_FH_MEM_CBBC_0_15_UPPER_BOUN        (IWM_FH_MEM_LOWER_BOUND + 0xA10)\n#define IWM_FH_MEM_CBBC_16_19_LOWER_BOUND    (IWM_FH_MEM_LOWER_BOUND + 0xBF0)\n#define IWM_FH_MEM_CBBC_16_19_UPPER_BOUND    (IWM_FH_MEM_LOWER_BOUND + 0xC00)\n#define IWM_FH_MEM_CBBC_20_31_LOWER_BOUND    (IWM_FH_MEM_LOWER_BOUND + 0xB20)\n#define IWM_FH_MEM_CBBC_20_31_UPPER_BOUND    (IWM_FH_MEM_LOWER_BOUND + 0xB80)\n\n/* Find TFD CB base pointer for given queue */\nstatic inline unsigned int IWM_FH_MEM_CBBC_QUEUE(unsigned int chnl)\n{\n    if (chnl < 16)\n        return IWM_FH_MEM_CBBC_0_15_LOWER_BOUND + 4 * chnl;\n    if (chnl < 20)\n        return IWM_FH_MEM_CBBC_16_19_LOWER_BOUND + 4 * (chnl - 16);\n    return IWM_FH_MEM_CBBC_20_31_LOWER_BOUND + 4 * (chnl - 20);\n}\n\n\n/**\n * Rx SRAM Control and Status Registers (RSCSR)\n *\n * These registers provide handshake between driver and device for the Rx queue\n * (this queue handles *all* command responses, notifications, Rx data, etc.\n * sent from uCode to host driver).  Unlike Tx, there is only one Rx\n * queue, and only one Rx DMA/FIFO channel.  Also unlike Tx, which can\n * concatenate up to 20 DRAM buffers to form a Tx frame, each Receive Buffer\n * Descriptor (RBD) points to only one Rx Buffer (RB); there is a 1:1\n * mapping between RBDs and RBs.\n *\n * Driver must allocate host DRAM memory for the following, and set the\n * physical address of each into device registers:\n *\n * 1)  Receive Buffer Descriptor (RBD) circular buffer (CB), typically with 256\n *     entries (although any power of 2, up to 4096, is selectable by driver).\n *     Each entry (1 dword) points to a receive buffer (RB) of consistent size\n *     (typically 4K, although 8K or 16K are also selectable by driver).\n *     Driver sets up RB size and number of RBDs in the CB via Rx config\n *     register IWM_FH_MEM_RCSR_CHNL0_CONFIG_REG.\n *\n *     Bit fields within one RBD:\n *     27-0:  Receive Buffer physical address bits [35:8], 256-byte aligned\n *\n *     Driver sets physical address [35:8] of base of RBD circular buffer\n *     into IWM_FH_RSCSR_CHNL0_RBDCB_BASE_REG [27:0].\n *\n * 2)  Rx status buffer, 8 bytes, in which uCode indicates which Rx Buffers\n *     (RBs) have been filled, via a \"write pointer\", actually the index of\n *     the RB's corresponding RBD within the circular buffer.  Driver sets\n *     physical address [35:4] into IWM_FH_RSCSR_CHNL0_STTS_WPTR_REG [31:0].\n *\n *     Bit fields in lower dword of Rx status buffer (upper dword not used\n *     by driver:\n *     31-12:  Not used by driver\n *     11- 0:  Index of last filled Rx buffer descriptor\n *             (device writes, driver reads this value)\n *\n * As the driver prepares Receive Buffers (RBs) for device to fill, driver must\n * enter pointers to these RBs into contiguous RBD circular buffer entries,\n * and update the device's \"write\" index register,\n * IWM_FH_RSCSR_CHNL0_RBDCB_WPTR_REG.\n *\n * This \"write\" index corresponds to the *next* RBD that the driver will make\n * available, i.e. one RBD past the tail of the ready-to-fill RBDs within\n * the circular buffer.  This value should initially be 0 (before preparing any\n * RBs), should be 8 after preparing the first 8 RBs (for example), and must\n * wrap back to 0 at the end of the circular buffer (but don't wrap before\n * \"read\" index has advanced past 1!  See below).\n * NOTE:  DEVICE EXPECTS THE WRITE INDEX TO BE INCREMENTED IN MULTIPLES OF 8.\n *\n * As the device fills RBs (referenced from contiguous RBDs within the circular\n * buffer), it updates the Rx status buffer in host DRAM, 2) described above,\n * to tell the driver the index of the latest filled RBD.  The driver must\n * read this \"read\" index from DRAM after receiving an Rx interrupt from device\n *\n * The driver must also internally keep track of a third index, which is the\n * next RBD to process.  When receiving an Rx interrupt, driver should process\n * all filled but unprocessed RBs up to, but not including, the RB\n * corresponding to the \"read\" index.  For example, if \"read\" index becomes \"1\",\n * driver may process the RB pointed to by RBD 0.  Depending on volume of\n * traffic, there may be many RBs to process.\n *\n * If read index == write index, device thinks there is no room to put new data.\n * Due to this, the maximum number of filled RBs is 255, instead of 256.  To\n * be safe, make sure that there is a gap of at least 2 RBDs between \"write\"\n * and \"read\" indexes; that is, make sure that there are no more than 254\n * buffers waiting to be filled.\n */\n#define IWM_FH_MEM_RSCSR_LOWER_BOUND    (IWM_FH_MEM_LOWER_BOUND + 0xBC0)\n#define IWM_FH_MEM_RSCSR_UPPER_BOUND    (IWM_FH_MEM_LOWER_BOUND + 0xC00)\n#define IWM_FH_MEM_RSCSR_CHNL0        (IWM_FH_MEM_RSCSR_LOWER_BOUND)\n\n/**\n * Physical base address of 8-byte Rx Status buffer.\n * Bit fields:\n *  31-0: Rx status buffer physical base address [35:4], must 16-byte aligned.\n */\n#define IWM_FH_RSCSR_CHNL0_STTS_WPTR_REG    (IWM_FH_MEM_RSCSR_CHNL0)\n\n/**\n * Physical base address of Rx Buffer Descriptor Circular Buffer.\n * Bit fields:\n *  27-0:  RBD CD physical base address [35:8], must be 256-byte aligned.\n */\n#define IWM_FH_RSCSR_CHNL0_RBDCB_BASE_REG    (IWM_FH_MEM_RSCSR_CHNL0 + 0x004)\n\n/**\n * Rx write pointer (index, really!).\n * Bit fields:\n *  11-0:  Index of driver's most recent prepared-to-be-filled RBD, + 1.\n *         NOTE:  For 256-entry circular buffer, use only bits [7:0].\n */\n#define IWM_FH_RSCSR_CHNL0_RBDCB_WPTR_REG    (IWM_FH_MEM_RSCSR_CHNL0 + 0x008)\n#define IWM_FH_RSCSR_CHNL0_WPTR        (IWM_FH_RSCSR_CHNL0_RBDCB_WPTR_REG)\n\n#define IWM_FW_RSCSR_CHNL0_RXDCB_RDPTR_REG    (IWM_FH_MEM_RSCSR_CHNL0 + 0x00c)\n#define IWM_FH_RSCSR_CHNL0_RDPTR        IWM_FW_RSCSR_CHNL0_RXDCB_RDPTR_REG\n\n/**\n * Rx Config/Status Registers (RCSR)\n * Rx Config Reg for channel 0 (only channel used)\n *\n * Driver must initialize IWM_FH_MEM_RCSR_CHNL0_CONFIG_REG as follows for\n * normal operation (see bit fields).\n *\n * Clearing IWM_FH_MEM_RCSR_CHNL0_CONFIG_REG to 0 turns off Rx DMA.\n * Driver should poll IWM_FH_MEM_RSSR_RX_STATUS_REG    for\n * IWM_FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE (bit 24) before continuing.\n *\n * Bit fields:\n * 31-30: Rx DMA channel enable: '00' off/pause, '01' pause at end of frame,\n *        '10' operate normally\n * 29-24: reserved\n * 23-20: # RBDs in circular buffer = 2^value; use \"8\" for 256 RBDs (normal),\n *        min \"5\" for 32 RBDs, max \"12\" for 4096 RBDs.\n * 19-18: reserved\n * 17-16: size of each receive buffer; '00' 4K (normal), '01' 8K,\n *        '10' 12K, '11' 16K.\n * 15-14: reserved\n * 13-12: IRQ destination; '00' none, '01' host driver (normal operation)\n * 11- 4: timeout for closing Rx buffer and interrupting host (units 32 usec)\n *        typical value 0x10 (about 1/2 msec)\n *  3- 0: reserved\n */\n#define IWM_FH_MEM_RCSR_LOWER_BOUND      (IWM_FH_MEM_LOWER_BOUND + 0xC00)\n#define IWM_FH_MEM_RCSR_UPPER_BOUND      (IWM_FH_MEM_LOWER_BOUND + 0xCC0)\n#define IWM_FH_MEM_RCSR_CHNL0            (IWM_FH_MEM_RCSR_LOWER_BOUND)\n\n#define IWM_FH_MEM_RCSR_CHNL0_CONFIG_REG    (IWM_FH_MEM_RCSR_CHNL0)\n#define IWM_FH_MEM_RCSR_CHNL0_RBDCB_WPTR    (IWM_FH_MEM_RCSR_CHNL0 + 0x8)\n#define IWM_FH_MEM_RCSR_CHNL0_FLUSH_RB_REQ    (IWM_FH_MEM_RCSR_CHNL0 + 0x10)\n\n#define IWM_FH_RCSR_CHNL0_RX_CONFIG_RB_TIMEOUT_MSK (0x00000FF0) /* bits 4-11 */\n#define IWM_FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_MSK   (0x00001000) /* bits 12 */\n#define IWM_FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME_MSK (0x00008000) /* bit 15 */\n#define IWM_FH_RCSR_CHNL0_RX_CONFIG_RB_SIZE_MSK   (0x00030000) /* bits 16-17 */\n#define IWM_FH_RCSR_CHNL0_RX_CONFIG_RBDBC_SIZE_MSK (0x00F00000) /* bits 20-23 */\n#define IWM_FH_RCSR_CHNL0_RX_CONFIG_DMA_CHNL_EN_MSK (0xC0000000) /* bits 30-31*/\n\n#define IWM_FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS    (20)\n#define IWM_FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS    (4)\n#define IWM_RX_RB_TIMEOUT    (0x11)\n\n#define IWM_FH_RCSR_RX_CONFIG_CHNL_EN_PAUSE_VAL         (0x00000000)\n#define IWM_FH_RCSR_RX_CONFIG_CHNL_EN_PAUSE_EOF_VAL     (0x40000000)\n#define IWM_FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL        (0x80000000)\n\n#define IWM_FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K    (0x00000000)\n#define IWM_FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K    (0x00010000)\n#define IWM_FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_12K   (0x00020000)\n#define IWM_FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_16K   (0x00030000)\n\n#define IWM_FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY              (0x00000004)\n#define IWM_FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_NO_INT_VAL    (0x00000000)\n#define IWM_FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL  (0x00001000)\n\n/**\n * Rx Shared Status Registers (RSSR)\n *\n * After stopping Rx DMA channel (writing 0 to\n * IWM_FH_MEM_RCSR_CHNL0_CONFIG_REG), driver must poll\n * IWM_FH_MEM_RSSR_RX_STATUS_REG until Rx channel is idle.\n *\n * Bit fields:\n *  24:  1 = Channel 0 is idle\n *\n * IWM_FH_MEM_RSSR_SHARED_CTRL_REG and IWM_FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV\n * contain default values that should not be altered by the driver.\n */\n#define IWM_FH_MEM_RSSR_LOWER_BOUND     (IWM_FH_MEM_LOWER_BOUND + 0xC40)\n#define IWM_FH_MEM_RSSR_UPPER_BOUND     (IWM_FH_MEM_LOWER_BOUND + 0xD00)\n\n#define IWM_FH_MEM_RSSR_SHARED_CTRL_REG (IWM_FH_MEM_RSSR_LOWER_BOUND)\n#define IWM_FH_MEM_RSSR_RX_STATUS_REG    (IWM_FH_MEM_RSSR_LOWER_BOUND + 0x004)\n#define IWM_FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV\\\n                    (IWM_FH_MEM_RSSR_LOWER_BOUND + 0x008)\n\n#define IWM_FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE    (0x01000000)\n\n#define IWM_FH_MEM_TFDIB_REG1_ADDR_BITSHIFT    28\n\n/* TFDB  Area - TFDs buffer table */\n#define IWM_FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK      (0xFFFFFFFF)\n#define IWM_FH_TFDIB_LOWER_BOUND       (IWM_FH_MEM_LOWER_BOUND + 0x900)\n#define IWM_FH_TFDIB_UPPER_BOUND       (IWM_FH_MEM_LOWER_BOUND + 0x958)\n#define IWM_FH_TFDIB_CTRL0_REG(_chnl)  (IWM_FH_TFDIB_LOWER_BOUND + 0x8 * (_chnl))\n#define IWM_FH_TFDIB_CTRL1_REG(_chnl)  (IWM_FH_TFDIB_LOWER_BOUND + 0x8 * (_chnl) + 0x4)\n\n/**\n * Transmit DMA Channel Control/Status Registers (TCSR)\n *\n * Device has one configuration register for each of 8 Tx DMA/FIFO channels\n * supported in hardware (don't confuse these with the 16 Tx queues in DRAM,\n * which feed the DMA/FIFO channels); config regs are separated by 0x20 bytes.\n *\n * To use a Tx DMA channel, driver must initialize its\n * IWM_FH_TCSR_CHNL_TX_CONFIG_REG(chnl) with:\n *\n * IWM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |\n * IWM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL\n *\n * All other bits should be 0.\n *\n * Bit fields:\n * 31-30: Tx DMA channel enable: '00' off/pause, '01' pause at end of frame,\n *        '10' operate normally\n * 29- 4: Reserved, set to \"0\"\n *     3: Enable internal DMA requests (1, normal operation), disable (0)\n *  2- 0: Reserved, set to \"0\"\n */\n#define IWM_FH_TCSR_LOWER_BOUND  (IWM_FH_MEM_LOWER_BOUND + 0xD00)\n#define IWM_FH_TCSR_UPPER_BOUND  (IWM_FH_MEM_LOWER_BOUND + 0xE60)\n\n/* Find Control/Status reg for given Tx DMA/FIFO channel */\n#define IWM_FH_TCSR_CHNL_NUM                            (8)\n\n/* TCSR: tx_config register values */\n#define IWM_FH_TCSR_CHNL_TX_CONFIG_REG(_chnl)    \\\n        (IWM_FH_TCSR_LOWER_BOUND + 0x20 * (_chnl))\n#define IWM_FH_TCSR_CHNL_TX_CREDIT_REG(_chnl)    \\\n        (IWM_FH_TCSR_LOWER_BOUND + 0x20 * (_chnl) + 0x4)\n#define IWM_FH_TCSR_CHNL_TX_BUF_STS_REG(_chnl)    \\\n        (IWM_FH_TCSR_LOWER_BOUND + 0x20 * (_chnl) + 0x8)\n\n#define IWM_FH_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_TXF    (0x00000000)\n#define IWM_FH_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_DRV    (0x00000001)\n\n#define IWM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE    (0x00000000)\n#define IWM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE        (0x00000008)\n\n#define IWM_FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_NOINT    (0x00000000)\n#define IWM_FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD    (0x00100000)\n#define IWM_FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD    (0x00200000)\n\n#define IWM_FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_NOINT    (0x00000000)\n#define IWM_FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_ENDTFD    (0x00400000)\n#define IWM_FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_IFTFD    (0x00800000)\n\n#define IWM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE        (0x00000000)\n#define IWM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE_EOF    (0x40000000)\n#define IWM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE        (0x80000000)\n\n#define IWM_FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_EMPTY    (0x00000000)\n#define IWM_FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_WAIT    (0x00002000)\n#define IWM_FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID    (0x00000003)\n\n#define IWM_FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM        (20)\n#define IWM_FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX        (12)\n\n/**\n * Tx Shared Status Registers (TSSR)\n *\n * After stopping Tx DMA channel (writing 0 to\n * IWM_FH_TCSR_CHNL_TX_CONFIG_REG(chnl)), driver must poll\n * IWM_FH_TSSR_TX_STATUS_REG until selected Tx channel is idle\n * (channel's buffers empty | no pending requests).\n *\n * Bit fields:\n * 31-24:  1 = Channel buffers empty (channel 7:0)\n * 23-16:  1 = No pending requests (channel 7:0)\n */\n#define IWM_FH_TSSR_LOWER_BOUND        (IWM_FH_MEM_LOWER_BOUND + 0xEA0)\n#define IWM_FH_TSSR_UPPER_BOUND        (IWM_FH_MEM_LOWER_BOUND + 0xEC0)\n\n#define IWM_FH_TSSR_TX_STATUS_REG    (IWM_FH_TSSR_LOWER_BOUND + 0x010)\n\n/**\n * Bit fields for TSSR(Tx Shared Status & Control) error status register:\n * 31:  Indicates an address error when accessed to internal memory\n *    uCode/driver must write \"1\" in order to clear this flag\n * 30:  Indicates that Host did not send the expected number of dwords to FH\n *    uCode/driver must write \"1\" in order to clear this flag\n * 16-9:Each status bit is for one channel. Indicates that an (Error) ActDMA\n *    command was received from the scheduler while the TRB was already full\n *    with previous command\n *    uCode/driver must write \"1\" in order to clear this flag\n * 7-0: Each status bit indicates a channel's TxCredit error. When an error\n *    bit is set, it indicates that the FH has received a full indication\n *    from the RTC TxFIFO and the current value of the TxCredit counter was\n *    not equal to zero. This mean that the credit mechanism was not\n *    synchronized to the TxFIFO status\n *    uCode/driver must write \"1\" in order to clear this flag\n */\n#define IWM_FH_TSSR_TX_ERROR_REG    (IWM_FH_TSSR_LOWER_BOUND + 0x018)\n#define IWM_FH_TSSR_TX_MSG_CONFIG_REG    (IWM_FH_TSSR_LOWER_BOUND + 0x008)\n\n#define IWM_FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(_chnl) ((1 << (_chnl)) << 16)\n\n/* Tx service channels */\n#define IWM_FH_SRVC_CHNL        (9)\n#define IWM_FH_SRVC_LOWER_BOUND    (IWM_FH_MEM_LOWER_BOUND + 0x9C8)\n#define IWM_FH_SRVC_UPPER_BOUND    (IWM_FH_MEM_LOWER_BOUND + 0x9D0)\n#define IWM_FH_SRVC_CHNL_SRAM_ADDR_REG(_chnl) \\\n        (IWM_FH_SRVC_LOWER_BOUND + ((_chnl) - 9) * 0x4)\n\n#define IWM_FH_TX_CHICKEN_BITS_REG    (IWM_FH_MEM_LOWER_BOUND + 0xE98)\n#define IWM_FH_TX_TRB_REG(_chan)    (IWM_FH_MEM_LOWER_BOUND + 0x958 + \\\n                    (_chan) * 4)\n\n/* Instruct FH to increment the retry count of a packet when\n * it is brought from the memory to TX-FIFO\n */\n#define IWM_FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN    (0x00000002)\n\n#define IWM_RX_QUEUE_SIZE                         256\n#define IWM_RX_QUEUE_MASK                         255\n#define IWM_RX_QUEUE_SIZE_LOG                     8\n\n/*\n * RX related structures and functions\n */\n#define IWM_RX_FREE_BUFFERS 64\n#define IWM_RX_LOW_WATERMARK 8\n\n/**\n * struct iwm_rb_status - reseve buffer status\n *     host memory mapped FH registers\n * @closed_rb_num [0:11] - Indicates the index of the RB which was closed\n * @closed_fr_num [0:11] - Indicates the index of the RX Frame which was closed\n * @finished_rb_num [0:11] - Indicates the index of the current RB\n *     in which the last frame was written to\n * @finished_fr_num [0:11] - Indicates the index of the RX Frame\n *     which was transferred\n */\nstruct iwm_rb_status {\n    uint16_t closed_rb_num;\n    uint16_t closed_fr_num;\n    uint16_t finished_rb_num;\n    uint16_t finished_fr_nam;\n    uint32_t unused;\n} __packed;\n\n\n#define IWM_TFD_QUEUE_SIZE_MAX        (256)\n#define IWM_TFD_QUEUE_SIZE_BC_DUP    (64)\n#define IWM_TFD_QUEUE_BC_SIZE        (IWM_TFD_QUEUE_SIZE_MAX + \\\n                    IWM_TFD_QUEUE_SIZE_BC_DUP)\n#define IWM_TX_DMA_MASK        DMA_BIT_MASK(36)\n#define IWM_NUM_OF_TBS        20\n\nstatic inline uint8_t iwm_get_dma_hi_addr(bus_addr_t addr)\n{\n    return (sizeof(addr) > sizeof(uint32_t) ? (addr >> 16) >> 16 : 0) & 0xF;\n}\n/**\n * struct iwm_tfd_tb transmit buffer descriptor within transmit frame descriptor\n *\n * This structure contains dma address and length of transmission address\n *\n * @lo: low [31:0] portion of the dma address of TX buffer\n *     every even is unaligned on 16 bit boundary\n * @hi_n_len 0-3 [35:32] portion of dma\n *         4-15 length of the tx buffer\n */\nstruct iwm_tfd_tb {\n    uint32_t lo;\n    uint16_t hi_n_len;\n} __packed;\n\n/**\n * struct iwm_tfd\n *\n * Transmit Frame Descriptor (TFD)\n *\n * @ __reserved1[3] reserved\n * @ num_tbs 0-4 number of active tbs\n *         5   reserved\n *          6-7 padding (not used)\n * @ tbs[20]    transmit frame buffer descriptors\n * @ __pad     padding\n *\n * Each Tx queue uses a circular buffer of 256 TFDs stored in host DRAM.\n * Both driver and device share these circular buffers, each of which must be\n * contiguous 256 TFDs x 128 bytes-per-TFD = 32 KBytes\n *\n * Driver must indicate the physical address of the base of each\n * circular buffer via the IWM_FH_MEM_CBBC_QUEUE registers.\n *\n * Each TFD contains pointer/size information for up to 20 data buffers\n * in host DRAM.  These buffers collectively contain the (one) frame described\n * by the TFD.  Each buffer must be a single contiguous block of memory within\n * itself, but buffers may be scattered in host DRAM.  Each buffer has max size\n * of (4K - 4).  The concatenates all of a TFD's buffers into a single\n * Tx frame, up to 8 KBytes in size.\n *\n * A maximum of 255 (not 256!) TFDs may be on a queue waiting for Tx.\n */\nstruct iwm_tfd {\n    uint8_t __reserved1[3];\n    uint8_t num_tbs;\n    struct iwm_tfd_tb tbs[IWM_NUM_OF_TBS];\n    uint32_t __pad;\n} __packed;\n\n/* Keep Warm Size */\n#define IWM_KW_SIZE 0x1000    /* 4k */\n\n/* Fixed (non-configurable) rx data from phy */\n\n/**\n * struct iwm_agn_schedq_bc_tbl scheduler byte count table\n *    base physical address provided by IWM_SCD_DRAM_BASE_ADDR\n * @tfd_offset  0-12 - tx command byte count\n *           12-16 - station index\n */\nstruct iwm_agn_scd_bc_tbl {\n    uint16_t tfd_offset[IWM_TFD_QUEUE_BC_SIZE];\n} __packed;\n\n/* Maximum number of Tx queues. */\n#define IWM_MAX_QUEUES    31\n\n/**\n * DQA - Dynamic Queue Allocation -introduction\n *\n * Dynamic Queue Allocation (AKA \"DQA\") is a feature implemented in iwlwifi\n * to allow dynamic allocation of queues on-demand, rather than allocate them\n * statically ahead of time. Ideally, we would like to allocate one queue\n * per RA/TID, thus allowing an AP - for example - to send BE traffic to STA2\n * even if it also needs to send traffic to a sleeping STA1, without being\n * blocked by the sleeping station.\n *\n * Although the queues in DQA mode are dynamically allocated, there are still\n * some queues that are statically allocated:\n *    TXQ #0 - command queue\n *    TXQ #1 - aux frames\n *    TXQ #2 - P2P device frames\n *    TXQ #3 - P2P GO/SoftAP GCAST/BCAST frames\n *    TXQ #4 - BSS DATA frames queue\n *    TXQ #5-8 - non-QoS data, QoS no-data, and MGMT frames queue pool\n *    TXQ #9 - P2P GO/SoftAP probe responses\n *    TXQ #10-31 - QoS DATA frames queue pool (for Tx aggregation)\n */\n\n/* static DQA Tx queue numbers */\n#define IWM_DQA_CMD_QUEUE        0\n#define IWM_DQA_AUX_QUEUE        1\n#define IWM_DQA_P2P_DEVICE_QUEUE    2\n#define IWM_DQA_INJECT_MONITOR_QUEUE    2\n#define IWM_DQA_GCAST_QUEUE        3\n#define IWM_DQA_BSS_CLIENT_QUEUE    4\n#define IWM_DQA_MIN_MGMT_QUEUE        5\n#define IWM_DQA_MAX_MGMT_QUEUE        8\n#define IWM_DQA_AP_PROBE_RESP_QUEUE    9\n#define IWM_DQA_MIN_DATA_QUEUE        10\n#define IWM_DQA_MAX_DATA_QUEUE        31\n\n/* Reserve 8 DQA Tx queues, from 10 up to 17, for A-MPDU aggregation. */\n#define IWM_MAX_TID_COUNT      8\n#define IWM_FIRST_AGG_TX_QUEUE IWM_DQA_MIN_DATA_QUEUE\n#define IWM_LAST_AGG_TX_QUEUE  (IWM_FIRST_AGG_TX_QUEUE + IWM_MAX_TID_COUNT - 1)\n\n/* legacy non-DQA queues; the legacy command queue uses a different number! */\n#define IWM_OFFCHANNEL_QUEUE    8\n#define IWM_CMD_QUEUE        9\n#define IWM_AUX_QUEUE        15\n\n#define IWM_TX_FIFO_BK    0\n#define IWM_TX_FIFO_BE    1\n#define IWM_TX_FIFO_VI    2\n#define IWM_TX_FIFO_VO    3\n#define IWM_TX_FIFO_MCAST    5\n#define IWM_TX_FIFO_CMD    7\n\n#define IWM_STATION_COUNT    16\n\n/*\n * Commands\n */\n#define IWM_ALIVE        0x1\n#define IWM_REPLY_ERROR        0x2\n#define IWM_INIT_COMPLETE_NOTIF    0x4\n\n/* PHY context commands */\n#define IWM_PHY_CONTEXT_CMD    0x8\n#define IWM_DBG_CFG        0x9\n\n/* UMAC scan commands */\n#define IWM_SCAN_ITERATION_COMPLETE_UMAC    0xb5\n#define IWM_SCAN_CFG_CMD            0xc\n#define IWM_SCAN_REQ_UMAC            0xd\n#define IWM_SCAN_ABORT_UMAC            0xe\n#define IWM_SCAN_COMPLETE_UMAC            0xf\n\n/* station table */\n#define IWM_ADD_STA_KEY    0x17\n#define IWM_ADD_STA    0x18\n#define IWM_REMOVE_STA    0x19\n\n/* TX */\n#define IWM_TX_CMD        0x1c\n#define IWM_TXPATH_FLUSH    0x1e\n#define IWM_MGMT_MCAST_KEY    0x1f\n\n/* scheduler config */\n#define IWM_SCD_QUEUE_CFG    0x1d\n\n/* Available options for the SCD_QUEUE_CFG HCMD */\n#define IWM_SCD_CFG_DISABLE_QUEUE   0\n#define IWM_SCD_CFG_ENABLE_QUEUE    1\n#define IWM_SCD_CFG_UPDATE_QUEUE_TID    2\n\n/* global key */\n#define IWM_WEP_KEY    0x20\n\n/* MAC and Binding commands */\n#define IWM_MAC_CONTEXT_CMD        0x28\n#define IWM_TIME_EVENT_CMD        0x29 /* both CMD and response */\n#define IWM_TIME_EVENT_NOTIFICATION    0x2a\n#define IWM_BINDING_CONTEXT_CMD        0x2b\n#define IWM_TIME_QUOTA_CMD        0x2c\n#define IWM_NON_QOS_TX_COUNTER_CMD    0x2d\n\n#define IWM_LQ_CMD    0x4e\n\n/* Calibration */\n#define IWM_TEMPERATURE_NOTIFICATION        0x62\n#define IWM_CALIBRATION_CFG_CMD            0x65\n#define IWM_CALIBRATION_RES_NOTIFICATION    0x66\n#define IWM_CALIBRATION_COMPLETE_NOTIFICATION    0x67\n#define IWM_RADIO_VERSION_NOTIFICATION        0x68\n\n/* paging block to FW cpu2 */\n#define IWM_FW_PAGING_BLOCK_CMD    0x4f\n\n/* Scan offload */\n#define IWM_SCAN_OFFLOAD_REQUEST_CMD        0x51\n#define IWM_SCAN_OFFLOAD_ABORT_CMD        0x52\n#define IWM_HOT_SPOT_CMD            0x53\n#define IWM_SCAN_OFFLOAD_COMPLETE        0x6d\n#define IWM_SCAN_OFFLOAD_UPDATE_PROFILES_CMD    0x6e\n#define IWM_SCAN_OFFLOAD_CONFIG_CMD        0x6f\n#define IWM_MATCH_FOUND_NOTIFICATION        0xd9\n#define IWM_SCAN_ITERATION_COMPLETE        0xe7\n\n/* Phy */\n#define IWM_PHY_CONFIGURATION_CMD        0x6a\n#define IWM_CALIB_RES_NOTIF_PHY_DB        0x6b\n#define IWM_PHY_DB_CMD                0x6c\n\n/* Power - legacy power table command */\n#define IWM_POWER_TABLE_CMD                0x77\n#define IWM_PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION    0x78\n#define IWM_LTR_CONFIG                    0xee\n\n/* Thermal Throttling*/\n#define IWM_REPLY_THERMAL_MNG_BACKOFF    0x7e\n\n/* NVM */\n#define IWM_NVM_ACCESS_CMD    0x88\n\n#define IWM_SET_CALIB_DEFAULT_CMD    0x8e\n\n#define IWM_BEACON_NOTIFICATION        0x90\n#define IWM_BEACON_TEMPLATE_CMD        0x91\n#define IWM_TX_ANT_CONFIGURATION_CMD    0x98\n#define IWM_BT_CONFIG            0x9b\n#define IWM_STATISTICS_NOTIFICATION    0x9d\n#define IWM_REDUCE_TX_POWER_CMD        0x9f\n\n/* RF-KILL commands and notifications */\n#define IWM_CARD_STATE_CMD        0xa0\n#define IWM_CARD_STATE_NOTIFICATION    0xa1\n\n#define IWM_MISSED_BEACONS_NOTIFICATION    0xa2\n\n#define IWM_MFUART_LOAD_NOTIFICATION    0xb1\n\n/* Power - new power table command */\n#define IWM_MAC_PM_POWER_TABLE    0xa9\n\n#define IWM_REPLY_RX_PHY_CMD    0xc0\n#define IWM_REPLY_RX_MPDU_CMD    0xc1\n#define IWM_BA_NOTIF        0xc5\n\n/* Location Aware Regulatory */\n#define IWM_MCC_UPDATE_CMD    0xc8\n#define IWM_MCC_CHUB_UPDATE_CMD    0xc9\n\n/* BT Coex */\n#define IWM_BT_COEX_PRIO_TABLE    0xcc\n#define IWM_BT_COEX_PROT_ENV    0xcd\n#define IWM_BT_PROFILE_NOTIFICATION    0xce\n#define IWM_BT_COEX_CI    0x5d\n\n#define IWM_REPLY_SF_CFG_CMD        0xd1\n#define IWM_REPLY_BEACON_FILTERING_CMD    0xd2\n\n/* DTS measurements */\n#define IWM_CMD_DTS_MEASUREMENT_TRIGGER        0xdc\n#define IWM_DTS_MEASUREMENT_NOTIFICATION    0xdd\n\n#define IWM_REPLY_DEBUG_CMD    0xf0\n#define IWM_DEBUG_LOG_MSG    0xf7\n\n#define IWM_MCAST_FILTER_CMD    0xd0\n\n/* D3 commands/notifications */\n#define IWM_D3_CONFIG_CMD        0xd3\n#define IWM_PROT_OFFLOAD_CONFIG_CMD    0xd4\n#define IWM_OFFLOADS_QUERY_CMD        0xd5\n#define IWM_REMOTE_WAKE_CONFIG_CMD    0xd6\n\n/* for WoWLAN in particular */\n#define IWM_WOWLAN_PATTERNS        0xe0\n#define IWM_WOWLAN_CONFIGURATION    0xe1\n#define IWM_WOWLAN_TSC_RSC_PARAM    0xe2\n#define IWM_WOWLAN_TKIP_PARAM        0xe3\n#define IWM_WOWLAN_KEK_KCK_MATERIAL    0xe4\n#define IWM_WOWLAN_GET_STATUSES        0xe5\n#define IWM_WOWLAN_TX_POWER_PER_DB    0xe6\n\n/* and for NetDetect */\n#define IWM_NET_DETECT_CONFIG_CMD        0x54\n#define IWM_NET_DETECT_PROFILES_QUERY_CMD    0x56\n#define IWM_NET_DETECT_PROFILES_CMD        0x57\n#define IWM_NET_DETECT_HOTSPOTS_CMD        0x58\n#define IWM_NET_DETECT_HOTSPOTS_QUERY_CMD    0x59\n\n/* system group command IDs */\n#define IWM_FSEQ_VER_MISMATCH_NOTIFICATION    0xff\n\n#define IWM_REPLY_MAX    0xff\n\n/* PHY_OPS subcommand IDs */\n#define IWM_CMD_DTS_MEASUREMENT_TRIGGER_WIDE    0x0\n#define IWM_CTDP_CONFIG_CMD            0x03\n#define IWM_TEMP_REPORTING_THRESHOLDS_CMD    0x04\n#define IWM_CT_KILL_NOTIFICATION        0xFE\n#define IWM_DTS_MEASUREMENT_NOTIF_WIDE        0xFF\n\n/* command groups */\n#define IWM_LEGACY_GROUP    0x0\n#define IWM_LONG_GROUP        0x1\n#define IWM_SYSTEM_GROUP    0x2\n#define IWM_MAC_CONF_GROUP    0x3\n#define IWM_PHY_OPS_GROUP    0x4\n#define IWM_DATA_PATH_GROUP    0x5\n#define IWM_PROT_OFFLOAD_GROUP    0xb\n\n/* SYSTEM_GROUP group subcommand IDs */\n\n#define IWM_SHARED_MEM_CFG_CMD        0x00\n#define IWM_SOC_CONFIGURATION_CMD    0x01\n#define IWM_INIT_EXTENDED_CFG_CMD    0x03\n#define IWM_FW_ERROR_RECOVERY_CMD    0x07\n\n/* DATA_PATH group subcommand IDs */\n#define IWM_DQA_ENABLE_CMD    0x00\n\n/*\n * struct iwm_dqa_enable_cmd\n * @cmd_queue: the TXQ number of the command queue\n */\nstruct iwm_dqa_enable_cmd {\n    uint32_t cmd_queue;\n} __packed; /* DQA_CONTROL_CMD_API_S_VER_1 */\n\n/**\n * struct iwm_cmd_response - generic response struct for most commands\n * @status: status of the command asked, changes for each one\n */\nstruct iwm_cmd_response {\n    uint32_t status;\n};\n\n/*\n * struct iwm_tx_ant_cfg_cmd\n * @valid: valid antenna configuration\n */\nstruct iwm_tx_ant_cfg_cmd {\n    uint32_t valid;\n} __packed;\n\n/**\n * struct iwm_reduce_tx_power_cmd - TX power reduction command\n * IWM_REDUCE_TX_POWER_CMD = 0x9f\n * @flags: (reserved for future implementation)\n * @mac_context_id: id of the mac ctx for which we are reducing TX power.\n * @pwr_restriction: TX power restriction in dBms.\n */\nstruct iwm_reduce_tx_power_cmd {\n    uint8_t flags;\n    uint8_t mac_context_id;\n    uint16_t pwr_restriction;\n} __packed; /* IWM_TX_REDUCED_POWER_API_S_VER_1 */\n\n/*\n * Calibration control struct.\n * Sent as part of the phy configuration command.\n * @flow_trigger: bitmap for which calibrations to perform according to\n *        flow triggers.\n * @event_trigger: bitmap for which calibrations to perform according to\n *        event triggers.\n */\nstruct iwm_calib_ctrl {\n    uint32_t flow_trigger;\n    uint32_t event_trigger;\n} __packed;\n\n/* This defines the bitmap of various calibrations to enable in both\n * init ucode and runtime ucode through IWM_CALIBRATION_CFG_CMD.\n */\n#define IWM_CALIB_CFG_XTAL_IDX            (1 << 0)\n#define IWM_CALIB_CFG_TEMPERATURE_IDX        (1 << 1)\n#define IWM_CALIB_CFG_VOLTAGE_READ_IDX        (1 << 2)\n#define IWM_CALIB_CFG_PAPD_IDX            (1 << 3)\n#define IWM_CALIB_CFG_TX_PWR_IDX        (1 << 4)\n#define IWM_CALIB_CFG_DC_IDX            (1 << 5)\n#define IWM_CALIB_CFG_BB_FILTER_IDX        (1 << 6)\n#define IWM_CALIB_CFG_LO_LEAKAGE_IDX        (1 << 7)\n#define IWM_CALIB_CFG_TX_IQ_IDX            (1 << 8)\n#define IWM_CALIB_CFG_TX_IQ_SKEW_IDX        (1 << 9)\n#define IWM_CALIB_CFG_RX_IQ_IDX            (1 << 10)\n#define IWM_CALIB_CFG_RX_IQ_SKEW_IDX        (1 << 11)\n#define IWM_CALIB_CFG_SENSITIVITY_IDX        (1 << 12)\n#define IWM_CALIB_CFG_CHAIN_NOISE_IDX        (1 << 13)\n#define IWM_CALIB_CFG_DISCONNECTED_ANT_IDX    (1 << 14)\n#define IWM_CALIB_CFG_ANT_COUPLING_IDX        (1 << 15)\n#define IWM_CALIB_CFG_DAC_IDX            (1 << 16)\n#define IWM_CALIB_CFG_ABS_IDX            (1 << 17)\n#define IWM_CALIB_CFG_AGC_IDX            (1 << 18)\n\n/*\n * Phy configuration command.\n */\nstruct iwm_phy_cfg_cmd {\n    uint32_t    phy_cfg;\n    struct iwm_calib_ctrl calib_control;\n} __packed;\n\n#define IWM_PHY_CFG_RADIO_TYPE    ((1 << 0) | (1 << 1))\n#define IWM_PHY_CFG_RADIO_STEP    ((1 << 2) | (1 << 3))\n#define IWM_PHY_CFG_RADIO_DASH    ((1 << 4) | (1 << 5))\n#define IWM_PHY_CFG_PRODUCT_NUMBER    ((1 << 6) | (1 << 7))\n#define IWM_PHY_CFG_TX_CHAIN_A    (1 << 8)\n#define IWM_PHY_CFG_TX_CHAIN_B    (1 << 9)\n#define IWM_PHY_CFG_TX_CHAIN_C    (1 << 10)\n#define IWM_PHY_CFG_RX_CHAIN_A    (1 << 12)\n#define IWM_PHY_CFG_RX_CHAIN_B    (1 << 13)\n#define IWM_PHY_CFG_RX_CHAIN_C    (1 << 14)\n\n#define IWM_MAX_DTS_TRIPS    8\n\n/**\n * struct iwm_ct_kill_notif - CT-kill entry notification\n *\n * @temperature: the current temperature in celsius\n * @reserved: reserved\n */\nstruct iwm_ct_kill_notif {\n    uint16_t temperature;\n    uint16_t reserved;\n} __packed; /* GRP_PHY_CT_KILL_NTF */\n\n/**\n * struct iwm_temp_report_ths_cmd - set temperature thresholds\n * (IWM_TEMP_REPORTING_THRESHOLDS_CMD)\n *\n * @num_temps: number of temperature thresholds passed\n * @thresholds: array with the thresholds to be configured\n */\nstruct iwm_temp_report_ths_cmd {\n    uint32_t num_temps;\n    uint16_t thresholds[IWM_MAX_DTS_TRIPS];\n} __packed; /* GRP_PHY_TEMP_REPORTING_THRESHOLDS_CMD */\n\n/*\n * PHY db\n */\n\n#define IWM_PHY_DB_CFG             1\n#define IWM_PHY_DB_CALIB_NCH        2\n#define IWM_PHY_DB_UNUSED        3\n#define IWM_PHY_DB_CALIB_CHG_PAPD    4\n#define IWM_PHY_DB_CALIB_CHG_TXP    5\n#define IWM_PHY_DB_MAX            6\n\n/*\n * phy db - configure operational ucode\n */\nstruct iwm_phy_db_cmd {\n    uint16_t type;\n    uint16_t length;\n    uint8_t data[];\n} __packed;\n\n/* for parsing of tx power channel group data that comes from the firmware*/\nstruct iwm_phy_db_chg_txp {\n    uint32_t space;\n    uint16_t max_channel_idx;\n} __packed;\n\n/*\n * phy db - Receive phy db chunk after calibrations\n */\nstruct iwm_calib_res_notif_phy_db {\n    uint16_t type;\n    uint16_t length;\n    uint8_t data[];\n} __packed;\n\n/* 7k family NVM HW-Section offset (in words) definitions */\n#define IWM_HW_ADDR    0x15\n/* 7k family NVM SW-Section offset (in words) definitions */\n#define IWM_NVM_SW_SECTION    0x1C0\n#define IWM_NVM_VERSION        0\n#define IWM_RADIO_CFG        1\n#define IWM_SKU            2\n#define IWM_N_HW_ADDRS        3\n#define IWM_NVM_CHANNELS    0x1E0 - IWM_NVM_SW_SECTION\n/* 7k family NVM calibration section offset (in words) definitions */\n#define IWM_NVM_CALIB_SECTION    0x2B8\n#define IWM_XTAL_CALIB        (0x316 - IWM_NVM_CALIB_SECTION)\n\n/* 8k family NVM HW-Section offset (in words) definitions */\n#define IWM_HW_ADDR0_WFPM_8000        0x12\n#define IWM_HW_ADDR1_WFPM_8000        0x16\n#define IWM_HW_ADDR0_PCIE_8000        0x8A\n#define IWM_HW_ADDR1_PCIE_8000        0x8E\n#define IWM_MAC_ADDRESS_OVERRIDE_8000    1\n\n/* 8k family NVM SW-Section offset (in words) definitions */\n#define IWM_NVM_SW_SECTION_8000    0x1C0\n#define IWM_NVM_VERSION_8000    0\n#define IWM_RADIO_CFG_8000    0\n#define IWM_SKU_8000        2\n#define IWM_N_HW_ADDRS_8000    3\n\n/* 8k family NVM REGULATORY -Section offset (in words) definitions */\n#define IWM_NVM_CHANNELS_8000        0\n#define IWM_NVM_LAR_OFFSET_8000_OLD    0x4C7\n#define IWM_NVM_LAR_OFFSET_8000        0x507\n#define IWM_NVM_LAR_ENABLED_8000    0x7\n\n/* 8k family NVM calibration section offset (in words) definitions */\n#define IWM_NVM_CALIB_SECTION_8000    0x2B8\n#define IWM_XTAL_CALIB_8000        (0x316 - IWM_NVM_CALIB_SECTION_8000)\n\n/* SKU Capabilities (actual values from NVM definition) */\n#define IWM_NVM_SKU_CAP_BAND_24GHZ    (1 << 0)\n#define IWM_NVM_SKU_CAP_BAND_52GHZ    (1 << 1)\n#define IWM_NVM_SKU_CAP_11N_ENABLE    (1 << 2)\n#define IWM_NVM_SKU_CAP_11AC_ENABLE    (1 << 3)\n#define IWM_NVM_SKU_CAP_MIMO_DISABLE    (1 << 5)\n\n/* radio config bits (actual values from NVM definition) */\n#define IWM_NVM_RF_CFG_DASH_MSK(x)   (x & 0x3)         /* bits 0-1   */\n#define IWM_NVM_RF_CFG_STEP_MSK(x)   ((x >> 2)  & 0x3) /* bits 2-3   */\n#define IWM_NVM_RF_CFG_TYPE_MSK(x)   ((x >> 4)  & 0x3) /* bits 4-5   */\n#define IWM_NVM_RF_CFG_PNUM_MSK(x)   ((x >> 6)  & 0x3) /* bits 6-7   */\n#define IWM_NVM_RF_CFG_TX_ANT_MSK(x) ((x >> 8)  & 0xF) /* bits 8-11  */\n#define IWM_NVM_RF_CFG_RX_ANT_MSK(x) ((x >> 12) & 0xF) /* bits 12-15 */\n\n#define IWM_NVM_RF_CFG_PNUM_MSK_8000(x)        (x & 0xF)\n#define IWM_NVM_RF_CFG_DASH_MSK_8000(x)        ((x >> 4) & 0xF)\n#define IWM_NVM_RF_CFG_STEP_MSK_8000(x)        ((x >> 8) & 0xF)\n#define IWM_NVM_RF_CFG_TYPE_MSK_8000(x)        ((x >> 12) & 0xFFF)\n#define IWM_NVM_RF_CFG_TX_ANT_MSK_8000(x)    ((x >> 24) & 0xF)\n#define IWM_NVM_RF_CFG_RX_ANT_MSK_8000(x)    ((x >> 28) & 0xF)\n\n/*\n * channel flags in NVM\n * @IWM_NVM_CHANNEL_VALID: channel is usable for this SKU/geo\n * @IWM_NVM_CHANNEL_IBSS: usable as an IBSS channel\n * @IWM_NVM_CHANNEL_ACTIVE: active scanning allowed\n * @IWM_NVM_CHANNEL_RADAR: radar detection required\n * @IWM_NVM_CHANNEL_DFS: dynamic freq selection candidate\n * @IWM_NVM_CHANNEL_WIDE: 20 MHz channel okay (?)\n * @IWM_NVM_CHANNEL_40MHZ: 40 MHz channel okay (?)\n * @IWM_NVM_CHANNEL_80MHZ: 80 MHz channel okay (?)\n * @IWM_NVM_CHANNEL_160MHZ: 160 MHz channel okay (?)\n */\n#define IWM_NVM_CHANNEL_VALID    (1 << 0)\n#define IWM_NVM_CHANNEL_IBSS    (1 << 1)\n#define IWM_NVM_CHANNEL_ACTIVE    (1 << 3)\n#define IWM_NVM_CHANNEL_RADAR    (1 << 4)\n#define IWM_NVM_CHANNEL_DFS    (1 << 7)\n#define IWM_NVM_CHANNEL_WIDE    (1 << 8)\n#define IWM_NVM_CHANNEL_40MHZ    (1 << 9)\n#define IWM_NVM_CHANNEL_80MHZ    (1 << 10)\n#define IWM_NVM_CHANNEL_160MHZ    (1 << 11)\n\n/* Target of the IWM_NVM_ACCESS_CMD */\n#define IWM_NVM_ACCESS_TARGET_CACHE    0\n#define IWM_NVM_ACCESS_TARGET_OTP    1\n#define IWM_NVM_ACCESS_TARGET_EEPROM    2\n\n/* Section types for IWM_NVM_ACCESS_CMD */\n#define IWM_NVM_SECTION_TYPE_HW            0\n#define IWM_NVM_SECTION_TYPE_SW            1\n#define IWM_NVM_SECTION_TYPE_PAPD        2\n#define IWM_NVM_SECTION_TYPE_REGULATORY        3\n#define IWM_NVM_SECTION_TYPE_CALIBRATION    4\n#define IWM_NVM_SECTION_TYPE_PRODUCTION        5\n#define IWM_NVM_SECTION_TYPE_POST_FCS_CALIB    6\n/* 7 unknown */\n#define IWM_NVM_SECTION_TYPE_REGULATORY_SDP    8\n/* 9 unknown */\n#define IWM_NVM_SECTION_TYPE_HW_8000        10\n#define IWM_NVM_SECTION_TYPE_MAC_OVERRIDE    11\n#define IWM_NVM_SECTION_TYPE_PHY_SKU        12\n#define IWM_NVM_NUM_OF_SECTIONS            13\n\n/**\n * enum iwm_nvm_type - nvm formats\n * @IWM_NVM: the regular format\n * @IWM_NVM_EXT: extended NVM format\n * @IWM_NVM_SDP: NVM format used by 3168 series\n */\nenum iwm_nvm_type {\n    IWM_NVM,\n    IWM_NVM_EXT,\n    IWM_NVM_SDP,\n};\n\n/**\n * struct iwm_nvm_access_cmd_ver2 - Request the device to send an NVM section\n * @op_code: 0 - read, 1 - write\n * @target: IWM_NVM_ACCESS_TARGET_*\n * @type: IWM_NVM_SECTION_TYPE_*\n * @offset: offset in bytes into the section\n * @length: in bytes, to read/write\n * @data: if write operation, the data to write. On read its empty\n */\nstruct iwm_nvm_access_cmd {\n    uint8_t op_code;\n    uint8_t target;\n    uint16_t type;\n    uint16_t offset;\n    uint16_t length;\n    uint8_t data[];\n} __packed; /* IWM_NVM_ACCESS_CMD_API_S_VER_2 */\n\n/*\n * Block paging calculations\n */\n#define IWM_PAGE_2_EXP_SIZE 12 /* 4K == 2^12 */\n#define IWM_FW_PAGING_SIZE (1 << IWM_PAGE_2_EXP_SIZE) /* page size is 4KB */\n#define IWM_PAGE_PER_GROUP_2_EXP_SIZE 3\n/* 8 pages per group */\n#define IWM_NUM_OF_PAGE_PER_GROUP (1 << IWM_PAGE_PER_GROUP_2_EXP_SIZE)\n/* don't change, support only 32KB size */\n#define IWM_PAGING_BLOCK_SIZE (IWM_NUM_OF_PAGE_PER_GROUP * IWM_FW_PAGING_SIZE)\n/* 32K == 2^15 */\n#define IWM_BLOCK_2_EXP_SIZE (IWM_PAGE_2_EXP_SIZE + IWM_PAGE_PER_GROUP_2_EXP_SIZE)\n\n/*\n * Image paging calculations\n */\n#define IWM_BLOCK_PER_IMAGE_2_EXP_SIZE 5\n/* 2^5 == 32 blocks per image */\n#define IWM_NUM_OF_BLOCK_PER_IMAGE (1 << IWM_BLOCK_PER_IMAGE_2_EXP_SIZE)\n/* maximum image size 1024KB */\n#define IWM_MAX_PAGING_IMAGE_SIZE (IWM_NUM_OF_BLOCK_PER_IMAGE * IWM_PAGING_BLOCK_SIZE)\n\n/* Virtual address signature */\n#define IWM_PAGING_ADDR_SIG 0xAA000000\n\n#define IWM_PAGING_CMD_IS_SECURED (1 << 9)\n#define IWM_PAGING_CMD_IS_ENABLED (1 << 8)\n#define IWM_PAGING_CMD_NUM_OF_PAGES_IN_LAST_GRP_POS 0\n#define IWM_PAGING_TLV_SECURE_MASK 1\n\n#define IWM_NUM_OF_FW_PAGING_BLOCKS    33 /* 32 for data and 1 block for CSS */\n\n/*\n * struct iwm_fw_paging_cmd - paging layout\n *\n * (IWM_FW_PAGING_BLOCK_CMD = 0x4f)\n *\n * Send to FW the paging layout in the driver.\n *\n * @flags: various flags for the command\n * @block_size: the block size in powers of 2\n * @block_num: number of blocks specified in the command.\n * @device_phy_addr: virtual addresses from device side\n*/\nstruct iwm_fw_paging_cmd {\n    uint32_t flags;\n    uint32_t block_size;\n    uint32_t block_num;\n    uint32_t device_phy_addr[IWM_NUM_OF_FW_PAGING_BLOCKS];\n} __packed; /* IWM_FW_PAGING_BLOCK_CMD_API_S_VER_1 */\n\n/**\n * struct iwm_nvm_access_resp_ver2 - response to IWM_NVM_ACCESS_CMD\n * @offset: offset in bytes into the section\n * @length: in bytes, either how much was written or read\n * @type: IWM_NVM_SECTION_TYPE_*\n * @status: 0 for success, fail otherwise\n * @data: if read operation, the data returned. Empty on write.\n */\nstruct iwm_nvm_access_resp {\n    uint16_t offset;\n    uint16_t length;\n    uint16_t type;\n    uint16_t status;\n    uint8_t data[];\n} __packed; /* IWM_NVM_ACCESS_CMD_RESP_API_S_VER_2 */\n\n/* IWM_ALIVE 0x1 */\n\n/* alive response is_valid values */\n#define IWM_ALIVE_RESP_UCODE_OK    (1 << 0)\n#define IWM_ALIVE_RESP_RFKILL    (1 << 1)\n\n/* alive response ver_type values */\n#define IWM_FW_TYPE_HW        0\n#define IWM_FW_TYPE_PROT    1\n#define IWM_FW_TYPE_AP        2\n#define IWM_FW_TYPE_WOWLAN    3\n#define IWM_FW_TYPE_TIMING    4\n#define IWM_FW_TYPE_WIPAN    5\n\n/* alive response ver_subtype values */\n#define IWM_FW_SUBTYPE_FULL_FEATURE    0\n#define IWM_FW_SUBTYPE_BOOTSRAP        1 /* Not valid */\n#define IWM_FW_SUBTYPE_REDUCED        2\n#define IWM_FW_SUBTYPE_ALIVE_ONLY    3\n#define IWM_FW_SUBTYPE_WOWLAN        4\n#define IWM_FW_SUBTYPE_AP_SUBTYPE    5\n#define IWM_FW_SUBTYPE_WIPAN        6\n#define IWM_FW_SUBTYPE_INITIALIZE    9\n\n#define IWM_ALIVE_STATUS_ERR 0xDEAD\n#define IWM_ALIVE_STATUS_OK 0xCAFE\n\n#define IWM_ALIVE_FLG_RFKILL    (1 << 0)\n\nstruct iwm_alive_resp_v1 {\n    uint16_t status;\n    uint16_t flags;\n    uint8_t ucode_minor;\n    uint8_t ucode_major;\n    uint16_t id;\n    uint8_t api_minor;\n    uint8_t api_major;\n    uint8_t ver_subtype;\n    uint8_t ver_type;\n    uint8_t mac;\n    uint8_t opt;\n    uint16_t reserved2;\n    uint32_t timestamp;\n    uint32_t error_event_table_ptr;    /* SRAM address for error log */\n    uint32_t log_event_table_ptr;    /* SRAM address for event log */\n    uint32_t cpu_register_ptr;\n    uint32_t dbgm_config_ptr;\n    uint32_t alive_counter_ptr;\n    uint32_t scd_base_ptr;        /* SRAM address for SCD */\n} __packed; /* IWM_ALIVE_RES_API_S_VER_1 */\n\nstruct iwm_alive_resp_v2 {\n    uint16_t status;\n    uint16_t flags;\n    uint8_t ucode_minor;\n    uint8_t ucode_major;\n    uint16_t id;\n    uint8_t api_minor;\n    uint8_t api_major;\n    uint8_t ver_subtype;\n    uint8_t ver_type;\n    uint8_t mac;\n    uint8_t opt;\n    uint16_t reserved2;\n    uint32_t timestamp;\n    uint32_t error_event_table_ptr;    /* SRAM address for error log */\n    uint32_t log_event_table_ptr;    /* SRAM address for LMAC event log */\n    uint32_t cpu_register_ptr;\n    uint32_t dbgm_config_ptr;\n    uint32_t alive_counter_ptr;\n    uint32_t scd_base_ptr;        /* SRAM address for SCD */\n    uint32_t st_fwrd_addr;        /* pointer to Store and forward */\n    uint32_t st_fwrd_size;\n    uint8_t umac_minor;            /* UMAC version: minor */\n    uint8_t umac_major;            /* UMAC version: major */\n    uint16_t umac_id;            /* UMAC version: id */\n    uint32_t error_info_addr;        /* SRAM address for UMAC error log */\n    uint32_t dbg_print_buff_addr;\n} __packed; /* ALIVE_RES_API_S_VER_2 */\n\nstruct iwm_alive_resp_v3 {\n    uint16_t status;\n    uint16_t flags;\n    uint32_t ucode_minor;\n    uint32_t ucode_major;\n    uint8_t ver_subtype;\n    uint8_t ver_type;\n    uint8_t mac;\n    uint8_t opt;\n    uint32_t timestamp;\n    uint32_t error_event_table_ptr;    /* SRAM address for error log */\n    uint32_t log_event_table_ptr;    /* SRAM address for LMAC event log */\n    uint32_t cpu_register_ptr;\n    uint32_t dbgm_config_ptr;\n    uint32_t alive_counter_ptr;\n    uint32_t scd_base_ptr;        /* SRAM address for SCD */\n    uint32_t st_fwrd_addr;        /* pointer to Store and forward */\n    uint32_t st_fwrd_size;\n    uint32_t umac_minor;        /* UMAC version: minor */\n    uint32_t umac_major;        /* UMAC version: major */\n    uint32_t error_info_addr;        /* SRAM address for UMAC error log */\n    uint32_t dbg_print_buff_addr;\n} __packed; /* ALIVE_RES_API_S_VER_3 */\n\n#define IWM_SOC_CONFIG_CMD_FLAGS_DISCRETE    (1 << 0)\n#define IWM_SOC_CONFIG_CMD_FLAGS_LOW_LATENCY    (1 << 1)\n\n#define IWM_SOC_FLAGS_LTR_APPLY_DELAY_MASK        0xc\n#define IWM_SOC_FLAGS_LTR_APPLY_DELAY_NONE        0\n#define IWM_SOC_FLAGS_LTR_APPLY_DELAY_200        1\n#define IWM_SOC_FLAGS_LTR_APPLY_DELAY_2500        2\n#define IWM_SOC_FLAGS_LTR_APPLY_DELAY_1820        3\n\n/**\n * struct iwm_soc_configuration_cmd - Set device stabilization latency\n *\n * @flags: soc settings flags.  In VER_1, we can only set the DISCRETE\n *    flag, because the FW treats the whole value as an integer. In\n *    VER_2, we can set the bits independently.\n * @latency: time for SOC to ensure stable power & XTAL\n */\nstruct iwm_soc_configuration_cmd {\n    uint32_t flags;\n    uint32_t latency;\n} __packed; /*\n             * SOC_CONFIGURATION_CMD_S_VER_1 (see description above)\n             * SOC_CONFIGURATION_CMD_S_VER_2\n             */\n\n/* Error response/notification */\n#define IWM_FW_ERR_UNKNOWN_CMD        0x0\n#define IWM_FW_ERR_INVALID_CMD_PARAM    0x1\n#define IWM_FW_ERR_SERVICE        0x2\n#define IWM_FW_ERR_ARC_MEMORY        0x3\n#define IWM_FW_ERR_ARC_CODE        0x4\n#define IWM_FW_ERR_WATCH_DOG        0x5\n#define IWM_FW_ERR_WEP_GRP_KEY_INDX    0x10\n#define IWM_FW_ERR_WEP_KEY_SIZE        0x11\n#define IWM_FW_ERR_OBSOLETE_FUNC    0x12\n#define IWM_FW_ERR_UNEXPECTED        0xFE\n#define IWM_FW_ERR_FATAL        0xFF\n\n/**\n * struct iwm_error_resp - FW error indication\n * ( IWM_REPLY_ERROR = 0x2 )\n * @error_type: one of IWM_FW_ERR_*\n * @cmd_id: the command ID for which the error occured\n * @bad_cmd_seq_num: sequence number of the erroneous command\n * @error_service: which service created the error, applicable only if\n *    error_type = 2, otherwise 0\n * @timestamp: TSF in usecs.\n */\nstruct iwm_error_resp {\n    uint32_t error_type;\n    uint8_t cmd_id;\n    uint8_t reserved1;\n    uint16_t bad_cmd_seq_num;\n    uint32_t error_service;\n    uint64_t timestamp;\n} __packed;\n\n#define IWM_FW_CMD_VER_UNKNOWN 99\n\n/**\n * struct iwm_fw_cmd_version - firmware command version entry\n * @cmd: command ID\n * @group: group ID\n * @cmd_ver: command version\n * @notif_ver: notification version\n */\nstruct iwm_fw_cmd_version {\n    uint8_t cmd;\n    uint8_t group;\n    uint8_t cmd_ver;\n    uint8_t notif_ver;\n} __packed;\n\n\n/* Common PHY, MAC and Bindings definitions */\n\n#define IWM_MAX_MACS_IN_BINDING    (3)\n#define IWM_MAX_BINDINGS    (4)\n#define IWM_AUX_BINDING_INDEX    (3)\n#define IWM_MAX_PHYS        (4)\n\n/* Used to extract ID and color from the context dword */\n#define IWM_FW_CTXT_ID_POS    (0)\n#define IWM_FW_CTXT_ID_MSK    (0xff << IWM_FW_CTXT_ID_POS)\n#define IWM_FW_CTXT_COLOR_POS    (8)\n#define IWM_FW_CTXT_COLOR_MSK    (0xff << IWM_FW_CTXT_COLOR_POS)\n#define IWM_FW_CTXT_INVALID    (0xffffffff)\n\n#define IWM_FW_CMD_ID_AND_COLOR(_id, _color) ((_id << IWM_FW_CTXT_ID_POS) |\\\n                      (_color << IWM_FW_CTXT_COLOR_POS))\n\n/* Possible actions on PHYs, MACs and Bindings */\n#define IWM_FW_CTXT_ACTION_STUB        0\n#define IWM_FW_CTXT_ACTION_ADD        1\n#define IWM_FW_CTXT_ACTION_MODIFY    2\n#define IWM_FW_CTXT_ACTION_REMOVE    3\n#define IWM_FW_CTXT_ACTION_NUM        4\n/* COMMON_CONTEXT_ACTION_API_E_VER_1 */\n\n/* Time Events */\n\n/* Time Event types, according to MAC type */\n\n/* BSS Station Events */\n#define IWM_TE_BSS_STA_AGGRESSIVE_ASSOC    0\n#define IWM_TE_BSS_STA_ASSOC        1\n#define IWM_TE_BSS_EAP_DHCP_PROT    2\n#define IWM_TE_BSS_QUIET_PERIOD        3\n\n/* P2P Device Events */\n#define IWM_TE_P2P_DEVICE_DISCOVERABLE    4\n#define IWM_TE_P2P_DEVICE_LISTEN    5\n#define IWM_TE_P2P_DEVICE_ACTION_SCAN    6\n#define IWM_TE_P2P_DEVICE_FULL_SCAN    7\n\n/* P2P Client Events */\n#define IWM_TE_P2P_CLIENT_AGGRESSIVE_ASSOC    8\n#define IWM_TE_P2P_CLIENT_ASSOC            9\n#define IWM_TE_P2P_CLIENT_QUIET_PERIOD        10\n\n/* P2P GO Events */\n#define IWM_TE_P2P_GO_ASSOC_PROT    11\n#define IWM_TE_P2P_GO_REPETITIVE_NOA    12\n#define IWM_TE_P2P_GO_CT_WINDOW        13\n\n/* WiDi Sync Events */\n#define IWM_TE_WIDI_TX_SYNC    14\n\n#define IWM_TE_MAX    15\n/* IWM_MAC_EVENT_TYPE_API_E_VER_1 */\n\n\n\n/* Time event - defines for command API v1 */\n\n/*\n * @IWM_TE_V1_FRAG_NONE: fragmentation of the time event is NOT allowed.\n * @IWM_TE_V1_FRAG_SINGLE: fragmentation of the time event is allowed, but only\n *    the first fragment is scheduled.\n * @IWM_TE_V1_FRAG_DUAL: fragmentation of the time event is allowed, but only\n *    the first 2 fragments are scheduled.\n * @IWM_TE_V1_FRAG_ENDLESS: fragmentation of the time event is allowed, and any\n *    number of fragments are valid.\n *\n * Other than the constant defined above, specifying a fragmentation value 'x'\n * means that the event can be fragmented but only the first 'x' will be\n * scheduled.\n */\n#define IWM_TE_V1_FRAG_NONE    0\n#define IWM_TE_V1_FRAG_SINGLE    1\n#define IWM_TE_V1_FRAG_DUAL    2\n#define IWM_TE_V1_FRAG_ENDLESS    0xffffffff\n\n/* If a Time Event can be fragmented, this is the max number of fragments */\n#define IWM_TE_V1_FRAG_MAX_MSK        0x0fffffff\n/* Repeat the time event endlessly (until removed) */\n#define IWM_TE_V1_REPEAT_ENDLESS    0xffffffff\n/* If a Time Event has bounded repetitions, this is the maximal value */\n#define IWM_TE_V1_REPEAT_MAX_MSK_V1    0x0fffffff\n\n/* Time Event dependencies: none, on another TE, or in a specific time */\n#define IWM_TE_V1_INDEPENDENT        0\n#define IWM_TE_V1_DEP_OTHER        (1 << 0)\n#define IWM_TE_V1_DEP_TSF        (1 << 1)\n#define IWM_TE_V1_EVENT_SOCIOPATHIC    (1 << 2)\n/* IWM_MAC_EVENT_DEPENDENCY_POLICY_API_E_VER_2 */\n\n/*\n * @IWM_TE_V1_NOTIF_NONE: no notifications\n * @IWM_TE_V1_NOTIF_HOST_EVENT_START: request/receive notification on event start\n * @IWM_TE_V1_NOTIF_HOST_EVENT_END:request/receive notification on event end\n * @IWM_TE_V1_NOTIF_INTERNAL_EVENT_START: internal FW use\n * @IWM_TE_V1_NOTIF_INTERNAL_EVENT_END: internal FW use.\n * @IWM_TE_V1_NOTIF_HOST_FRAG_START: request/receive notification on frag start\n * @IWM_TE_V1_NOTIF_HOST_FRAG_END:request/receive notification on frag end\n * @IWM_TE_V1_NOTIF_INTERNAL_FRAG_START: internal FW use.\n * @IWM_TE_V1_NOTIF_INTERNAL_FRAG_END: internal FW use.\n *\n * Supported Time event notifications configuration.\n * A notification (both event and fragment) includes a status indicating weather\n * the FW was able to schedule the event or not. For fragment start/end\n * notification the status is always success. There is no start/end fragment\n * notification for monolithic events.\n */\n#define IWM_TE_V1_NOTIF_NONE            0\n#define IWM_TE_V1_NOTIF_HOST_EVENT_START    (1 << 0)\n#define IWM_TE_V1_NOTIF_HOST_EVENT_END        (1 << 1)\n#define IWM_TE_V1_NOTIF_INTERNAL_EVENT_START    (1 << 2)\n#define IWM_TE_V1_NOTIF_INTERNAL_EVENT_END    (1 << 3)\n#define IWM_TE_V1_NOTIF_HOST_FRAG_START        (1 << 4)\n#define IWM_TE_V1_NOTIF_HOST_FRAG_END        (1 << 5)\n#define IWM_TE_V1_NOTIF_INTERNAL_FRAG_START    (1 << 6)\n#define IWM_TE_V1_NOTIF_INTERNAL_FRAG_END    (1 << 7)\n/* IWM_MAC_EVENT_ACTION_API_E_VER_2 */\n\n\n/* Time event - defines for command API */\n\n/**\n * DOC: Time Events - what is it?\n *\n * Time Events are a fw feature that allows the driver to control the presence\n * of the device on the channel. Since the fw supports multiple channels\n * concurrently, the fw may choose to jump to another channel at any time.\n * In order to make sure that the fw is on a specific channel at a certain time\n * and for a certain duration, the driver needs to issue a time event.\n *\n * The simplest example is for BSS association. The driver issues a time event,\n * waits for it to start, and only then tells mac80211 that we can start the\n * association. This way, we make sure that the association will be done\n * smoothly and won't be interrupted by channel switch decided within the fw.\n */\n\n /**\n * DOC: The flow against the fw\n *\n * When the driver needs to make sure we are in a certain channel, at a certain\n * time and for a certain duration, it sends a Time Event. The flow against the\n * fw goes like this:\n *    1) Driver sends a TIME_EVENT_CMD to the fw\n *    2) Driver gets the response for that command. This response contains the\n *       Unique ID (UID) of the event.\n *    3) The fw sends notification when the event starts.\n *\n * Of course the API provides various options that allow to cover parameters\n * of the flow.\n *    What is the duration of the event?\n *    What is the start time of the event?\n *    Is there an end-time for the event?\n *    How much can the event be delayed?\n *    Can the event be split?\n *    If yes what is the maximal number of chunks?\n *    etc...\n */\n\n/*\n * @IWM_TE_V2_FRAG_NONE: fragmentation of the time event is NOT allowed.\n * @IWM_TE_V2_FRAG_SINGLE: fragmentation of the time event is allowed, but only\n *  the first fragment is scheduled.\n * @IWM_TE_V2_FRAG_DUAL: fragmentation of the time event is allowed, but only\n *  the first 2 fragments are scheduled.\n * @IWM_TE_V2_FRAG_ENDLESS: fragmentation of the time event is allowed, and any\n *  number of fragments are valid.\n *\n * Other than the constant defined above, specifying a fragmentation value 'x'\n * means that the event can be fragmented but only the first 'x' will be\n * scheduled.\n */\n#define IWM_TE_V2_FRAG_NONE        0\n#define IWM_TE_V2_FRAG_SINGLE        1\n#define IWM_TE_V2_FRAG_DUAL        2\n#define IWM_TE_V2_FRAG_MAX        0xfe\n#define IWM_TE_V2_FRAG_ENDLESS        0xff\n\n/* Repeat the time event endlessly (until removed) */\n#define IWM_TE_V2_REPEAT_ENDLESS    0xff\n/* If a Time Event has bounded repetitions, this is the maximal value */\n#define IWM_TE_V2_REPEAT_MAX    0xfe\n\n#define IWM_TE_V2_PLACEMENT_POS    12\n#define IWM_TE_V2_ABSENCE_POS    15\n\n/* Time event policy values\n * A notification (both event and fragment) includes a status indicating weather\n * the FW was able to schedule the event or not. For fragment start/end\n * notification the status is always success. There is no start/end fragment\n * notification for monolithic events.\n *\n * @IWM_TE_V2_DEFAULT_POLICY: independent, social, present, unoticable\n * @IWM_TE_V2_NOTIF_HOST_EVENT_START: request/receive notification on event start\n * @IWM_TE_V2_NOTIF_HOST_EVENT_END:request/receive notification on event end\n * @IWM_TE_V2_NOTIF_INTERNAL_EVENT_START: internal FW use\n * @IWM_TE_V2_NOTIF_INTERNAL_EVENT_END: internal FW use.\n * @IWM_TE_V2_NOTIF_HOST_FRAG_START: request/receive notification on frag start\n * @IWM_TE_V2_NOTIF_HOST_FRAG_END:request/receive notification on frag end\n * @IWM_TE_V2_NOTIF_INTERNAL_FRAG_START: internal FW use.\n * @IWM_TE_V2_NOTIF_INTERNAL_FRAG_END: internal FW use.\n * @IWM_TE_V2_DEP_OTHER: depends on another time event\n * @IWM_TE_V2_DEP_TSF: depends on a specific time\n * @IWM_TE_V2_EVENT_SOCIOPATHIC: can't co-exist with other events of tha same MAC\n * @IWM_TE_V2_ABSENCE: are we present or absent during the Time Event.\n */\n#define IWM_TE_V2_DEFAULT_POLICY        0x0\n\n/* notifications (event start/stop, fragment start/stop) */\n#define IWM_TE_V2_NOTIF_HOST_EVENT_START    (1 << 0)\n#define IWM_TE_V2_NOTIF_HOST_EVENT_END        (1 << 1)\n#define IWM_TE_V2_NOTIF_INTERNAL_EVENT_START    (1 << 2)\n#define IWM_TE_V2_NOTIF_INTERNAL_EVENT_END    (1 << 3)\n\n#define IWM_TE_V2_NOTIF_HOST_FRAG_START        (1 << 4)\n#define IWM_TE_V2_NOTIF_HOST_FRAG_END        (1 << 5)\n#define IWM_TE_V2_NOTIF_INTERNAL_FRAG_START    (1 << 6)\n#define IWM_TE_V2_NOTIF_INTERNAL_FRAG_END    (1 << 7)\n#define IWM_T2_V2_START_IMMEDIATELY        (1 << 11)\n\n#define IWM_TE_V2_NOTIF_MSK    0xff\n\n/* placement characteristics */\n#define IWM_TE_V2_DEP_OTHER        (1 << IWM_TE_V2_PLACEMENT_POS)\n#define IWM_TE_V2_DEP_TSF        (1 << (IWM_TE_V2_PLACEMENT_POS + 1))\n#define IWM_TE_V2_EVENT_SOCIOPATHIC    (1 << (IWM_TE_V2_PLACEMENT_POS + 2))\n\n/* are we present or absent during the Time Event. */\n#define IWM_TE_V2_ABSENCE        (1 << IWM_TE_V2_ABSENCE_POS)\n\n/**\n * struct iwm_time_event_cmd_api - configuring Time Events\n * with struct IWM_MAC_TIME_EVENT_DATA_API_S_VER_2 (see also\n * with version 1. determined by IWM_UCODE_TLV_FLAGS)\n * ( IWM_TIME_EVENT_CMD = 0x29 )\n * @id_and_color: ID and color of the relevant MAC\n * @action: action to perform, one of IWM_FW_CTXT_ACTION_*\n * @id: this field has two meanings, depending on the action:\n *    If the action is ADD, then it means the type of event to add.\n *    For all other actions it is the unique event ID assigned when the\n *    event was added by the FW.\n * @apply_time: When to start the Time Event (in GP2)\n * @max_delay: maximum delay to event's start (apply time), in TU\n * @depends_on: the unique ID of the event we depend on (if any)\n * @interval: interval between repetitions, in TU\n * @duration: duration of event in TU\n * @repeat: how many repetitions to do, can be IWM_TE_REPEAT_ENDLESS\n * @max_frags: maximal number of fragments the Time Event can be divided to\n * @policy: defines whether uCode shall notify the host or other uCode modules\n *    on event and/or fragment start and/or end\n *    using one of IWM_TE_INDEPENDENT, IWM_TE_DEP_OTHER, IWM_TE_DEP_TSF\n *    IWM_TE_EVENT_SOCIOPATHIC\n *    using IWM_TE_ABSENCE and using IWM_TE_NOTIF_*\n */\nstruct iwm_time_event_cmd {\n    /* COMMON_INDEX_HDR_API_S_VER_1 */\n    uint32_t id_and_color;\n    uint32_t action;\n    uint32_t id;\n    /* IWM_MAC_TIME_EVENT_DATA_API_S_VER_2 */\n    uint32_t apply_time;\n    uint32_t max_delay;\n    uint32_t depends_on;\n    uint32_t interval;\n    uint32_t duration;\n    uint8_t repeat;\n    uint8_t max_frags;\n    uint16_t policy;\n} __packed; /* IWM_MAC_TIME_EVENT_CMD_API_S_VER_2 */\n\n/**\n * struct iwm_time_event_resp - response structure to iwm_time_event_cmd\n * @status: bit 0 indicates success, all others specify errors\n * @id: the Time Event type\n * @unique_id: the unique ID assigned (in ADD) or given (others) to the TE\n * @id_and_color: ID and color of the relevant MAC\n */\nstruct iwm_time_event_resp {\n    uint32_t status;\n    uint32_t id;\n    uint32_t unique_id;\n    uint32_t id_and_color;\n} __packed; /* IWM_MAC_TIME_EVENT_RSP_API_S_VER_1 */\n\n/**\n * struct iwm_time_event_notif - notifications of time event start/stop\n * ( IWM_TIME_EVENT_NOTIFICATION = 0x2a )\n * @timestamp: action timestamp in GP2\n * @session_id: session's unique id\n * @unique_id: unique id of the Time Event itself\n * @id_and_color: ID and color of the relevant MAC\n * @action: one of IWM_TE_NOTIF_START or IWM_TE_NOTIF_END\n * @status: true if scheduled, false otherwise (not executed)\n */\nstruct iwm_time_event_notif {\n    uint32_t timestamp;\n    uint32_t session_id;\n    uint32_t unique_id;\n    uint32_t id_and_color;\n    uint32_t action;\n    uint32_t status;\n} __packed; /* IWM_MAC_TIME_EVENT_NTFY_API_S_VER_1 */\n\n\n/* Bindings and Time Quota */\n\n/**\n * struct iwm_binding_cmd_v1 - configuring bindings\n * ( IWM_BINDING_CONTEXT_CMD = 0x2b )\n * @id_and_color: ID and color of the relevant Binding\n * @action: action to perform, one of IWM_FW_CTXT_ACTION_*\n * @macs: array of MAC id and colors which belong to the binding\n * @phy: PHY id and color which belongs to the binding\n * @lmac_id: the lmac id the binding belongs to\n */\nstruct iwm_binding_cmd_v1 {\n    /* COMMON_INDEX_HDR_API_S_VER_1 */\n    uint32_t id_and_color;\n    uint32_t action;\n    /* IWM_BINDING_DATA_API_S_VER_1 */\n    uint32_t macs[IWM_MAX_MACS_IN_BINDING];\n    uint32_t phy;\n} __packed; /* IWM_BINDING_CMD_API_S_VER_1 */\n\n/**\n * struct iwm_binding_cmd - configuring bindings\n * ( IWM_BINDING_CONTEXT_CMD = 0x2b )\n * @id_and_color: ID and color of the relevant Binding\n * @action: action to perform, one of IWM_FW_CTXT_ACTION_*\n * @macs: array of MAC id and colors which belong to the binding\n * @phy: PHY id and color which belongs to the binding\n * @lmac_id: the lmac id the binding belongs to\n */\nstruct iwm_binding_cmd {\n    /* COMMON_INDEX_HDR_API_S_VER_1 */\n    uint32_t id_and_color;\n    uint32_t action;\n    /* IWM_BINDING_DATA_API_S_VER_1 */\n    uint32_t macs[IWM_MAX_MACS_IN_BINDING];\n    uint32_t phy;\n    uint32_t lmac_id;\n} __packed; /* IWM_BINDING_CMD_API_S_VER_2 */\n\n#define IWM_LMAC_24G_INDEX        0\n#define IWM_LMAC_5G_INDEX        1\n\n/* The maximal number of fragments in the FW's schedule session */\n#define IWM_MAX_QUOTA 128\n\n/**\n * struct iwm_time_quota_data - configuration of time quota per binding\n * @id_and_color: ID and color of the relevant Binding\n * @quota: absolute time quota in TU. The scheduler will try to divide the\n *    remainig quota (after Time Events) according to this quota.\n * @max_duration: max uninterrupted context duration in TU\n */\nstruct iwm_time_quota_data_v1 {\n    uint32_t id_and_color;\n    uint32_t quota;\n    uint32_t max_duration;\n} __packed; /* IWM_TIME_QUOTA_DATA_API_S_VER_1 */\n\n/**\n * struct iwm_time_quota_cmd - configuration of time quota between bindings\n * ( IWM_TIME_QUOTA_CMD = 0x2c )\n * @quotas: allocations per binding\n */\nstruct iwm_time_quota_cmd_v1 {\n    struct iwm_time_quota_data_v1 quotas[IWM_MAX_BINDINGS];\n} __packed; /* IWM_TIME_QUOTA_ALLOCATION_CMD_API_S_VER_1 */\n\n#define IWM_QUOTA_LOW_LATENCY_NONE    0\n#define IWM_QUOTA_LOW_LATENCY_TX    (1 << 0)\n#define IWM_QUOTA_LOW_LATENCY_RX    (1 << 1)\n\n/**\n * struct iwm_time_quota_data - configuration of time quota per binding\n * @id_and_color: ID and color of the relevant Binding.\n * @quota: absolute time quota in TU. The scheduler will try to divide the\n *    remainig quota (after Time Events) according to this quota.\n * @max_duration: max uninterrupted context duration in TU\n * @low_latency: low latency status IWM_QUOTA_LOW_LATENCY_*\n */\nstruct iwm_time_quota_data {\n    uint32_t id_and_color;\n    uint32_t quota;\n    uint32_t max_duration;\n    uint32_t low_latency;\n}; /* TIME_QUOTA_DATA_API_S_VER_2 */\n\n/**\n * struct iwm_time_quota_cmd - configuration of time quota between bindings\n * ( TIME_QUOTA_CMD = 0x2c )\n * Note: on non-CDB the fourth one is the auxilary mac and is essentially zero.\n * On CDB the fourth one is a regular binding.\n *\n * @quotas: allocations per binding\n */\nstruct iwm_time_quota_cmd {\n    struct iwm_time_quota_data quotas[IWM_MAX_BINDINGS];\n} __packed; /* IWM_TIME_QUOTA_ALLOCATION_CMD_API_S_VER_2 */\n\n\n/* PHY context */\n\n/* Supported bands */\n#define IWM_PHY_BAND_5  (0)\n#define IWM_PHY_BAND_24 (1)\n\n/* Supported channel width, vary if there is VHT support */\n#define IWM_PHY_VHT_CHANNEL_MODE20    (0x0)\n#define IWM_PHY_VHT_CHANNEL_MODE40    (0x1)\n#define IWM_PHY_VHT_CHANNEL_MODE80    (0x2)\n#define IWM_PHY_VHT_CHANNEL_MODE160    (0x3)\n\n/*\n * Control channel position:\n * For legacy set bit means upper channel, otherwise lower.\n * For VHT - bit-2 marks if the control is lower/upper relative to center-freq\n *   bits-1:0 mark the distance from the center freq. for 20Mhz, offset is 0.\n *                                   center_freq\n *                                        |\n * 40Mhz                          |_______|_______|\n * 80Mhz                  |_______|_______|_______|_______|\n * 160Mhz |_______|_______|_______|_______|_______|_______|_______|_______|\n * code      011     010     001     000  |  100     101     110    111\n */\n#define IWM_PHY_VHT_CTRL_POS_1_BELOW  (0x0)\n#define IWM_PHY_VHT_CTRL_POS_2_BELOW  (0x1)\n#define IWM_PHY_VHT_CTRL_POS_3_BELOW  (0x2)\n#define IWM_PHY_VHT_CTRL_POS_4_BELOW  (0x3)\n#define IWM_PHY_VHT_CTRL_POS_1_ABOVE  (0x4)\n#define IWM_PHY_VHT_CTRL_POS_2_ABOVE  (0x5)\n#define IWM_PHY_VHT_CTRL_POS_3_ABOVE  (0x6)\n#define IWM_PHY_VHT_CTRL_POS_4_ABOVE  (0x7)\n\n/*\n * @band: IWM_PHY_BAND_*\n * @channel: channel number\n * @width: PHY_[VHT|LEGACY]_CHANNEL_*\n * @ctrl channel: PHY_[VHT|LEGACY]_CTRL_*\n */\nstruct iwm_fw_channel_info_v1 {\n    uint8_t band;\n    uint8_t channel;\n    uint8_t width;\n    uint8_t ctrl_pos;\n} __packed; /* CHANNEL_CONFIG_API_S_VER_1 */\n\n/*\n * struct iwm_fw_channel_info - channel information\n *\n * @channel: channel number\n * @band: PHY_BAND_*\n * @width: PHY_[VHT|LEGACY]_CHANNEL_*\n * @ctrl channel: PHY_[VHT|LEGACY]_CTRL_*\n * @reserved: for future use and alignment\n */\nstruct iwm_fw_channel_info {\n    uint32_t channel;\n    uint8_t band;\n    uint8_t width;\n    uint8_t ctrl_pos;\n    uint8_t reserved;\n} __packed; /* CHANNEL_CONFIG_API_S_VER_2 */\n\n#define IWM_PHY_RX_CHAIN_DRIVER_FORCE_POS    (0)\n#define IWM_PHY_RX_CHAIN_DRIVER_FORCE_MSK \\\n    (0x1 << IWM_PHY_RX_CHAIN_DRIVER_FORCE_POS)\n#define IWM_PHY_RX_CHAIN_VALID_POS        (1)\n#define IWM_PHY_RX_CHAIN_VALID_MSK \\\n    (0x7 << IWM_PHY_RX_CHAIN_VALID_POS)\n#define IWM_PHY_RX_CHAIN_FORCE_SEL_POS    (4)\n#define IWM_PHY_RX_CHAIN_FORCE_SEL_MSK \\\n    (0x7 << IWM_PHY_RX_CHAIN_FORCE_SEL_POS)\n#define IWM_PHY_RX_CHAIN_FORCE_MIMO_SEL_POS    (7)\n#define IWM_PHY_RX_CHAIN_FORCE_MIMO_SEL_MSK \\\n    (0x7 << IWM_PHY_RX_CHAIN_FORCE_MIMO_SEL_POS)\n#define IWM_PHY_RX_CHAIN_CNT_POS        (10)\n#define IWM_PHY_RX_CHAIN_CNT_MSK \\\n    (0x3 << IWM_PHY_RX_CHAIN_CNT_POS)\n#define IWM_PHY_RX_CHAIN_MIMO_CNT_POS    (12)\n#define IWM_PHY_RX_CHAIN_MIMO_CNT_MSK \\\n    (0x3 << IWM_PHY_RX_CHAIN_MIMO_CNT_POS)\n#define IWM_PHY_RX_CHAIN_MIMO_FORCE_POS    (14)\n#define IWM_PHY_RX_CHAIN_MIMO_FORCE_MSK \\\n    (0x1 << IWM_PHY_RX_CHAIN_MIMO_FORCE_POS)\n\n/* TODO: fix the value, make it depend on firmware at runtime? */\n#define IWM_NUM_PHY_CTX    3\n\n/* TODO: complete missing documentation */\n/**\n * struct iwm_phy_context_cmd - config of the PHY context\n * ( IWM_PHY_CONTEXT_CMD = 0x8 )\n * @id_and_color: ID and color of the relevant Binding\n * @action: action to perform, one of IWM_FW_CTXT_ACTION_*\n * @apply_time: 0 means immediate apply and context switch.\n *    other value means apply new params after X usecs\n * @tx_param_color: ???\n * @channel_info:\n * @txchain_info: ???\n * @rxchain_info: ???\n * @acquisition_data: ???\n * @dsp_cfg_flags: set to 0\n */\n/*\n * XXX Intel forgot to bump the PHY_CONTEXT command API when they increased\n * the size of fw_channel_info from v1 to v2.\n * To keep things simple we define two versions of this struct, and both\n * are labled as CMD_API_VER_1. (The Linux iwlwifi driver performs dark\n * magic with pointers to struct members instead.)\n */\n/* This version must be used if IWM_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS is set: */\nstruct iwm_phy_context_cmd_uhb {\n    /* COMMON_INDEX_HDR_API_S_VER_1 */\n    uint32_t id_and_color;\n    uint32_t action;\n    /* IWM_PHY_CONTEXT_DATA_API_S_VER_1 */\n    uint32_t apply_time;\n    uint32_t tx_param_color;\n    struct iwm_fw_channel_info ci;\n    uint32_t txchain_info;\n    uint32_t rxchain_info;\n    uint32_t acquisition_data;\n    uint32_t dsp_cfg_flags;\n} __packed; /* IWM_PHY_CONTEXT_CMD_API_VER_1 */\n/* This version must be used otherwise: */\nstruct iwm_phy_context_cmd {\n    /* COMMON_INDEX_HDR_API_S_VER_1 */\n    uint32_t id_and_color;\n    uint32_t action;\n    /* IWM_PHY_CONTEXT_DATA_API_S_VER_1 */\n    uint32_t apply_time;\n    uint32_t tx_param_color;\n    struct iwm_fw_channel_info_v1 ci;\n    uint32_t txchain_info;\n    uint32_t rxchain_info;\n    uint32_t acquisition_data;\n    uint32_t dsp_cfg_flags;\n} __packed; /* IWM_PHY_CONTEXT_CMD_API_VER_1 */\n\n#define IWM_RX_INFO_PHY_CNT 8\n#define IWM_RX_INFO_ENERGY_ANT_ABC_IDX 1\n#define IWM_RX_INFO_ENERGY_ANT_A_MSK 0x000000ff\n#define IWM_RX_INFO_ENERGY_ANT_B_MSK 0x0000ff00\n#define IWM_RX_INFO_ENERGY_ANT_C_MSK 0x00ff0000\n#define IWM_RX_INFO_ENERGY_ANT_A_POS 0\n#define IWM_RX_INFO_ENERGY_ANT_B_POS 8\n#define IWM_RX_INFO_ENERGY_ANT_C_POS 16\n\n#define IWM_RX_INFO_AGC_IDX 1\n#define IWM_RX_INFO_RSSI_AB_IDX 2\n#define IWM_OFDM_AGC_A_MSK 0x0000007f\n#define IWM_OFDM_AGC_A_POS 0\n#define IWM_OFDM_AGC_B_MSK 0x00003f80\n#define IWM_OFDM_AGC_B_POS 7\n#define IWM_OFDM_AGC_CODE_MSK 0x3fe00000\n#define IWM_OFDM_AGC_CODE_POS 20\n#define IWM_OFDM_RSSI_INBAND_A_MSK 0x00ff\n#define IWM_OFDM_RSSI_A_POS 0\n#define IWM_OFDM_RSSI_ALLBAND_A_MSK 0xff00\n#define IWM_OFDM_RSSI_ALLBAND_A_POS 8\n#define IWM_OFDM_RSSI_INBAND_B_MSK 0xff0000\n#define IWM_OFDM_RSSI_B_POS 16\n#define IWM_OFDM_RSSI_ALLBAND_B_MSK 0xff000000\n#define IWM_OFDM_RSSI_ALLBAND_B_POS 24\n\n/**\n * struct iwm_rx_phy_info - phy info\n * (IWM_REPLY_RX_PHY_CMD = 0xc0)\n * @non_cfg_phy_cnt: non configurable DSP phy data byte count\n * @cfg_phy_cnt: configurable DSP phy data byte count\n * @stat_id: configurable DSP phy data set ID\n * @reserved1:\n * @system_timestamp: GP2  at on air rise\n * @timestamp: TSF at on air rise\n * @beacon_time_stamp: beacon at on-air rise\n * @phy_flags: general phy flags: band, modulation, ...\n * @channel: channel number\n * @non_cfg_phy_buf: for various implementations of non_cfg_phy\n * @rate_n_flags: IWM_RATE_MCS_*\n * @byte_count: frame's byte-count\n * @frame_time: frame's time on the air, based on byte count and frame rate\n *    calculation\n * @mac_active_msk: what MACs were active when the frame was received\n *\n * Before each Rx, the device sends this data. It contains PHY information\n * about the reception of the packet.\n */\nstruct iwm_rx_phy_info {\n    uint8_t non_cfg_phy_cnt;\n    uint8_t cfg_phy_cnt;\n    uint8_t stat_id;\n    uint8_t reserved1;\n    uint32_t system_timestamp;\n    uint64_t timestamp;\n    uint32_t beacon_time_stamp;\n    uint16_t phy_flags;\n#define IWM_PHY_INFO_FLAG_SHPREAMBLE    (1 << 2)\n    uint16_t channel;\n    uint32_t non_cfg_phy[IWM_RX_INFO_PHY_CNT];\n    uint32_t rate_n_flags;\n    uint32_t byte_count;\n    uint16_t mac_active_msk;\n    uint16_t frame_time;\n} __packed;\n\nstruct iwm_rx_mpdu_res_start {\n    uint16_t byte_count;\n    uint16_t reserved;\n} __packed;\n\n/**\n * Values to parse %iwm_rx_phy_info phy_flags\n * @IWM_RX_RES_PHY_FLAGS_BAND_24: true if the packet was received on 2.4 band\n * @IWM_RX_RES_PHY_FLAGS_MOD_CCK:\n * @IWM_RX_RES_PHY_FLAGS_SHORT_PREAMBLE: true if packet's preamble was short\n * @IWM_RX_RES_PHY_FLAGS_NARROW_BAND:\n * @IWM_RX_RES_PHY_FLAGS_ANTENNA: antenna on which the packet was received\n * @IWM_RX_RES_PHY_FLAGS_AGG: set if the packet was part of an A-MPDU\n * @IWM_RX_RES_PHY_FLAGS_OFDM_HT: The frame was an HT frame\n * @IWM_RX_RES_PHY_FLAGS_OFDM_GF: The frame used GF preamble\n * @IWM_RX_RES_PHY_FLAGS_OFDM_VHT: The frame was a VHT frame\n */\n#define IWM_RX_RES_PHY_FLAGS_BAND_24        (1 << 0)\n#define IWM_RX_RES_PHY_FLAGS_MOD_CCK        (1 << 1)\n#define IWM_RX_RES_PHY_FLAGS_SHORT_PREAMBLE    (1 << 2)\n#define IWM_RX_RES_PHY_FLAGS_NARROW_BAND    (1 << 3)\n#define IWM_RX_RES_PHY_FLAGS_ANTENNA        (0x7 << 4)\n#define IWM_RX_RES_PHY_FLAGS_ANTENNA_POS    4\n#define IWM_RX_RES_PHY_FLAGS_AGG        (1 << 7)\n#define IWM_RX_RES_PHY_FLAGS_OFDM_HT        (1 << 8)\n#define IWM_RX_RES_PHY_FLAGS_OFDM_GF        (1 << 9)\n#define IWM_RX_RES_PHY_FLAGS_OFDM_VHT        (1 << 10)\n\n/**\n * Values written by fw for each Rx packet\n * @IWM_RX_MPDU_RES_STATUS_CRC_OK: CRC is fine\n * @IWM_RX_MPDU_RES_STATUS_OVERRUN_OK: there was no RXE overflow\n * @IWM_RX_MPDU_RES_STATUS_SRC_STA_FOUND:\n * @IWM_RX_MPDU_RES_STATUS_KEY_VALID:\n * @IWM_RX_MPDU_RES_STATUS_KEY_PARAM_OK:\n * @IWM_RX_MPDU_RES_STATUS_ICV_OK: ICV is fine, if not, the packet is destroyed\n * @IWM_RX_MPDU_RES_STATUS_MIC_OK: used for CCM alg only. TKIP MIC is checked\n *    in the driver.\n * @IWM_RX_MPDU_RES_STATUS_TTAK_OK: TTAK is fine\n * @IWM_RX_MPDU_RES_STATUS_MNG_FRAME_REPLAY_ERR:  valid for alg = CCM_CMAC or\n *    alg = CCM only. Checks replay attack for 11w frames. Relevant only if\n *    %IWM_RX_MPDU_RES_STATUS_ROBUST_MNG_FRAME is set.\n * @IWM_RX_MPDU_RES_STATUS_SEC_NO_ENC: this frame is not encrypted\n * @IWM_RX_MPDU_RES_STATUS_SEC_WEP_ENC: this frame is encrypted using WEP\n * @IWM_RX_MPDU_RES_STATUS_SEC_CCM_ENC: this frame is encrypted using CCM\n * @IWM_RX_MPDU_RES_STATUS_SEC_TKIP_ENC: this frame is encrypted using TKIP\n * @IWM_RX_MPDU_RES_STATUS_SEC_CCM_CMAC_ENC: this frame is encrypted using CCM_CMAC\n * @IWM_RX_MPDU_RES_STATUS_SEC_ENC_ERR: this frame couldn't be decrypted\n * @IWM_RX_MPDU_RES_STATUS_SEC_ENC_MSK: bitmask of the encryption algorithm\n * @IWM_RX_MPDU_RES_STATUS_DEC_DONE: this frame has been successfully decrypted\n * @IWM_RX_MPDU_RES_STATUS_PROTECT_FRAME_BIT_CMP:\n * @IWM_RX_MPDU_RES_STATUS_EXT_IV_BIT_CMP:\n * @IWM_RX_MPDU_RES_STATUS_KEY_ID_CMP_BIT:\n * @IWM_RX_MPDU_RES_STATUS_ROBUST_MNG_FRAME: this frame is an 11w management frame\n * @IWM_RX_MPDU_RES_STATUS_HASH_INDEX_MSK:\n * @IWM_RX_MPDU_RES_STATUS_STA_ID_MSK:\n * @IWM_RX_MPDU_RES_STATUS_RRF_KILL:\n * @IWM_RX_MPDU_RES_STATUS_FILTERING_MSK:\n * @IWM_RX_MPDU_RES_STATUS2_FILTERING_MSK:\n */\n#define IWM_RX_MPDU_RES_STATUS_CRC_OK            (1 << 0)\n#define IWM_RX_MPDU_RES_STATUS_OVERRUN_OK        (1 << 1)\n#define IWM_RX_MPDU_RES_STATUS_SRC_STA_FOUND        (1 << 2)\n#define IWM_RX_MPDU_RES_STATUS_KEY_VALID        (1 << 3)\n#define IWM_RX_MPDU_RES_STATUS_KEY_PARAM_OK        (1 << 4)\n#define IWM_RX_MPDU_RES_STATUS_ICV_OK            (1 << 5)\n#define IWM_RX_MPDU_RES_STATUS_MIC_OK            (1 << 6)\n#define IWM_RX_MPDU_RES_STATUS_TTAK_OK            (1 << 7)\n#define IWM_RX_MPDU_RES_STATUS_MNG_FRAME_REPLAY_ERR    (1 << 7)\n#define IWM_RX_MPDU_RES_STATUS_SEC_NO_ENC        (0 << 8)\n#define IWM_RX_MPDU_RES_STATUS_SEC_WEP_ENC        (1 << 8)\n#define IWM_RX_MPDU_RES_STATUS_SEC_CCM_ENC        (2 << 8)\n#define IWM_RX_MPDU_RES_STATUS_SEC_TKIP_ENC        (3 << 8)\n#define IWM_RX_MPDU_RES_STATUS_SEC_EXT_ENC        (4 << 8)\n#define IWM_RX_MPDU_RES_STATUS_SEC_CCM_CMAC_ENC        (6 << 8)\n#define IWM_RX_MPDU_RES_STATUS_SEC_ENC_ERR        (7 << 8)\n#define IWM_RX_MPDU_RES_STATUS_SEC_ENC_MSK        (7 << 8)\n#define IWM_RX_MPDU_RES_STATUS_DEC_DONE            (1 << 11)\n#define IWM_RX_MPDU_RES_STATUS_PROTECT_FRAME_BIT_CMP    (1 << 12)\n#define IWM_RX_MPDU_RES_STATUS_EXT_IV_BIT_CMP        (1 << 13)\n#define IWM_RX_MPDU_RES_STATUS_KEY_ID_CMP_BIT        (1 << 14)\n#define IWM_RX_MPDU_RES_STATUS_ROBUST_MNG_FRAME        (1 << 15)\n#define IWM_RX_MPDU_RES_STATUS_HASH_INDEX_MSK        (0x3F0000)\n#define IWM_RX_MPDU_RES_STATUS_STA_ID_MSK        (0x1f000000)\n#define IWM_RX_MPDU_RES_STATUS_RRF_KILL            (1 << 29)\n#define IWM_RX_MPDU_RES_STATUS_FILTERING_MSK        (0xc00000)\n#define IWM_RX_MPDU_RES_STATUS2_FILTERING_MSK        (0xc0000000)\n\n#define IWM_RX_MPDU_MFLG1_ADDRTYPE_MASK        0x03\n#define IWM_RX_MPDU_MFLG1_MIC_CRC_LEN_MASK    0xf0\n#define IWM_RX_MPDU_MFLG1_MIC_CRC_LEN_SHIFT    3\n\n#define IWM_RX_MPDU_MFLG2_HDR_LEN_MASK        0x1f\n#define    IWM_RX_MPDU_MFLG2_PAD            0x20\n#define IWM_RX_MPDU_MFLG2_AMSDU            0x40\n\n#define IWM_RX_MPDU_AMSDU_SUBFRAME_IDX_MASK    0x7f\n#define IWM_RX_MPDU_AMSDU_LAST_SUBFRAME                0x80\n\n#define IWM_RX_MPDU_PHY_AMPDU            (1 << 5)\n#define IWM_RX_MPDU_PHY_AMPDU_TOGGLE        (1 << 6)\n#define IWM_RX_MPDU_PHY_SHORT_PREAMBLE        (1 << 7)\n#define IWM_RX_MPDU_PHY_NCCK_ADDTL_NTFY        (1 << 7)\n#define IWM_RX_MPDU_PHY_TSF_OVERLOAD        (1 << 8)\n\nstruct iwm_rx_mpdu_desc_v1 {\n    union {\n        uint32_t rss_hash;\n        uint32_t phy_data2;\n    };\n    union {\n        uint32_t filter_match;\n        uint32_t phy_data3;\n    };\n    uint32_t rate_n_flags;\n    uint8_t energy_a;\n    uint8_t energy_b;\n    uint8_t channel;\n    uint8_t mac_context;\n    uint32_t gp2_on_air_rise;\n    union {\n        uint64_t tsf_on_air_rise;\n        struct {\n            uint32_t phy_data0;\n            uint32_t phy_data1;\n        };\n    };\n} __packed;\n\n#define IWM_RX_REORDER_DATA_INVALID_BAID       0x7f\n\n#define IWM_RX_MPDU_REORDER_NSSN_MASK          0x00000fff\n#define IWM_RX_MPDU_REORDER_SN_MASK            0x00fff000\n#define IWM_RX_MPDU_REORDER_SN_SHIFT           12\n#define IWM_RX_MPDU_REORDER_BAID_MASK          0x7f000000\n#define IWM_RX_MPDU_REORDER_BAID_SHIFT         24\n#define IWM_RX_MPDU_REORDER_BA_OLD_SN          0x80000000\n\nstruct iwm_rx_mpdu_desc {\n    uint16_t mpdu_len;\n    uint8_t mac_flags1;\n    uint8_t mac_flags2;\n    uint8_t amsdu_info;\n    uint16_t phy_info;\n    uint8_t mac_phy_idx;\n    uint16_t raw_csum;\n    union {\n        uint16_t l3l4_flags;\n        uint16_t phy_data4;\n    };\n    uint16_t status;\n    uint8_t hash_filter;\n    uint8_t sta_id_flags;\n    uint32_t reorder_data;\n    struct iwm_rx_mpdu_desc_v1 v1;\n} __packed;\n\n/**\n * struct iwm_radio_version_notif - information on the radio version\n * ( IWM_RADIO_VERSION_NOTIFICATION = 0x68 )\n * @radio_flavor:\n * @radio_step:\n * @radio_dash:\n */\nstruct iwm_radio_version_notif {\n    uint32_t radio_flavor;\n    uint32_t radio_step;\n    uint32_t radio_dash;\n} __packed; /* IWM_RADIO_VERSION_NOTOFICATION_S_VER_1 */\n\n#define IWM_CARD_ENABLED        0x00\n#define IWM_HW_CARD_DISABLED        0x01\n#define IWM_SW_CARD_DISABLED        0x02\n#define IWM_CT_KILL_CARD_DISABLED    0x04\n#define IWM_HALT_CARD_DISABLED        0x08\n#define IWM_CARD_DISABLED_MSK        0x0f\n#define IWM_CARD_IS_RX_ON        0x10\n\n/**\n * struct iwm_radio_version_notif - information on the radio version\n * (IWM_CARD_STATE_NOTIFICATION = 0xa1 )\n * @flags: %iwm_card_state_flags\n */\nstruct iwm_card_state_notif {\n    uint32_t flags;\n} __packed; /* CARD_STATE_NTFY_API_S_VER_1 */\n\n/**\n * struct iwm_missed_beacons_notif - information on missed beacons\n * ( IWM_MISSED_BEACONS_NOTIFICATION = 0xa2 )\n * @mac_id: interface ID\n * @consec_missed_beacons_since_last_rx: number of consecutive missed\n *    beacons since last RX.\n * @consec_missed_beacons: number of consecutive missed beacons\n * @num_expected_beacons:\n * @num_recvd_beacons:\n */\nstruct iwm_missed_beacons_notif {\n    uint32_t mac_id;\n    uint32_t consec_missed_beacons_since_last_rx;\n    uint32_t consec_missed_beacons;\n    uint32_t num_expected_beacons;\n    uint32_t num_recvd_beacons;\n} __packed; /* IWM_MISSED_BEACON_NTFY_API_S_VER_3 */\n\n/**\n * struct iwm_mfuart_load_notif - mfuart image version & status\n * ( IWM_MFUART_LOAD_NOTIFICATION = 0xb1 )\n * @installed_ver: installed image version\n * @external_ver: external image version\n * @status: MFUART loading status\n * @duration: MFUART loading time\n*/\nstruct iwm_mfuart_load_notif {\n    uint32_t installed_ver;\n    uint32_t external_ver;\n    uint32_t status;\n    uint32_t duration;\n} __packed; /*MFU_LOADER_NTFY_API_S_VER_1*/\n\n/**\n * struct iwm_set_calib_default_cmd - set default value for calibration.\n * ( IWM_SET_CALIB_DEFAULT_CMD = 0x8e )\n * @calib_index: the calibration to set value for\n * @length: of data\n * @data: the value to set for the calibration result\n */\nstruct iwm_set_calib_default_cmd {\n    uint16_t calib_index;\n    uint16_t length;\n    uint8_t data[0];\n} __packed; /* IWM_PHY_CALIB_OVERRIDE_VALUES_S */\n\n#define IWM_MAX_PORT_ID_NUM    2\n#define IWM_MAX_MCAST_FILTERING_ADDRESSES 256\n\n/**\n * struct iwm_mcast_filter_cmd - configure multicast filter.\n * @filter_own: Set 1 to filter out multicast packets sent by station itself\n * @port_id:    Multicast MAC addresses array specifier. This is a strange way\n *        to identify network interface adopted in host-device IF.\n *        It is used by FW as index in array of addresses. This array has\n *        IWM_MAX_PORT_ID_NUM members.\n * @count:    Number of MAC addresses in the array\n * @pass_all:    Set 1 to pass all multicast packets.\n * @bssid:    current association BSSID.\n * @addr_list:    Place holder for array of MAC addresses.\n *        IMPORTANT: add padding if necessary to ensure DWORD alignment.\n */\nstruct iwm_mcast_filter_cmd {\n    uint8_t filter_own;\n    uint8_t port_id;\n    uint8_t count;\n    uint8_t pass_all;\n    uint8_t bssid[6];\n    uint8_t reserved[2];\n    uint8_t addr_list[0];\n} __packed; /* IWM_MCAST_FILTERING_CMD_API_S_VER_1 */\n\nstruct iwm_statistics_dbg {\n    uint32_t burst_check;\n    uint32_t burst_count;\n    uint32_t wait_for_silence_timeout_cnt;\n    uint32_t reserved[3];\n} __packed; /* IWM_STATISTICS_DEBUG_API_S_VER_2 */\n\nstruct iwm_statistics_div {\n    uint32_t tx_on_a;\n    uint32_t tx_on_b;\n    uint32_t exec_time;\n    uint32_t probe_time;\n    uint32_t rssi_ant;\n    uint32_t reserved2;\n} __packed; /* IWM_STATISTICS_SLOW_DIV_API_S_VER_2 */\n\nstruct iwm_statistics_general_common {\n    uint32_t temperature;   /* radio temperature */\n    uint32_t temperature_m; /* radio voltage */\n    struct iwm_statistics_dbg dbg;\n    uint32_t sleep_time;\n    uint32_t slots_out;\n    uint32_t slots_idle;\n    uint32_t ttl_timestamp;\n    struct iwm_statistics_div div;\n    uint32_t rx_enable_counter;\n    /*\n     * num_of_sos_states:\n     *  count the number of times we have to re-tune\n     *  in order to get out of bad PHY status\n     */\n    uint32_t num_of_sos_states;\n} __packed; /* IWM_STATISTICS_GENERAL_API_S_VER_5 */\n\nstruct iwm_statistics_rx_non_phy {\n    uint32_t bogus_cts;    /* CTS received when not expecting CTS */\n    uint32_t bogus_ack;    /* ACK received when not expecting ACK */\n    uint32_t non_bssid_frames;    /* number of frames with BSSID that\n                     * doesn't belong to the STA BSSID */\n    uint32_t filtered_frames;    /* count frames that were dumped in the\n                 * filtering process */\n    uint32_t non_channel_beacons;    /* beacons with our bss id but not on\n                     * our serving channel */\n    uint32_t channel_beacons;    /* beacons with our bss id and in our\n                 * serving channel */\n    uint32_t num_missed_bcon;    /* number of missed beacons */\n    uint32_t adc_rx_saturation_time;    /* count in 0.8us units the time the\n                     * ADC was in saturation */\n    uint32_t ina_detection_search_time;/* total time (in 0.8us) searched\n                      * for INA */\n    uint32_t beacon_silence_rssi[3];/* RSSI silence after beacon frame */\n    uint32_t interference_data_flag;    /* flag for interference data\n                     * availability. 1 when data is\n                     * available. */\n    uint32_t channel_load;        /* counts RX Enable time in uSec */\n    uint32_t dsp_false_alarms;    /* DSP false alarm (both OFDM\n                     * and CCK) counter */\n    uint32_t beacon_rssi_a;\n    uint32_t beacon_rssi_b;\n    uint32_t beacon_rssi_c;\n    uint32_t beacon_energy_a;\n    uint32_t beacon_energy_b;\n    uint32_t beacon_energy_c;\n    uint32_t num_bt_kills;\n    uint32_t mac_id;\n    uint32_t directed_data_mpdu;\n} __packed; /* IWM_STATISTICS_RX_NON_PHY_API_S_VER_3 */\n\nstruct iwm_statistics_rx_phy {\n    uint32_t ina_cnt;\n    uint32_t fina_cnt;\n    uint32_t plcp_err;\n    uint32_t crc32_err;\n    uint32_t overrun_err;\n    uint32_t early_overrun_err;\n    uint32_t crc32_good;\n    uint32_t false_alarm_cnt;\n    uint32_t fina_sync_err_cnt;\n    uint32_t sfd_timeout;\n    uint32_t fina_timeout;\n    uint32_t unresponded_rts;\n    uint32_t rxe_frame_limit_overrun;\n    uint32_t sent_ack_cnt;\n    uint32_t sent_cts_cnt;\n    uint32_t sent_ba_rsp_cnt;\n    uint32_t dsp_self_kill;\n    uint32_t mh_format_err;\n    uint32_t re_acq_main_rssi_sum;\n    uint32_t reserved;\n} __packed; /* IWM_STATISTICS_RX_PHY_API_S_VER_2 */\n\nstruct iwm_statistics_rx_ht_phy {\n    uint32_t plcp_err;\n    uint32_t overrun_err;\n    uint32_t early_overrun_err;\n    uint32_t crc32_good;\n    uint32_t crc32_err;\n    uint32_t mh_format_err;\n    uint32_t agg_crc32_good;\n    uint32_t agg_mpdu_cnt;\n    uint32_t agg_cnt;\n    uint32_t unsupport_mcs;\n} __packed;  /* IWM_STATISTICS_HT_RX_PHY_API_S_VER_1 */\n\n#define IWM_MAX_CHAINS 3\n\nstruct iwm_statistics_tx_non_phy_agg {\n    uint32_t ba_timeout;\n    uint32_t ba_reschedule_frames;\n    uint32_t scd_query_agg_frame_cnt;\n    uint32_t scd_query_no_agg;\n    uint32_t scd_query_agg;\n    uint32_t scd_query_mismatch;\n    uint32_t frame_not_ready;\n    uint32_t underrun;\n    uint32_t bt_prio_kill;\n    uint32_t rx_ba_rsp_cnt;\n    int8_t txpower[IWM_MAX_CHAINS];\n    int8_t reserved;\n    uint32_t reserved2;\n} __packed; /* IWM_STATISTICS_TX_NON_PHY_AGG_API_S_VER_1 */\n\nstruct iwm_statistics_tx_channel_width {\n    uint32_t ext_cca_narrow_ch20[1];\n    uint32_t ext_cca_narrow_ch40[2];\n    uint32_t ext_cca_narrow_ch80[3];\n    uint32_t ext_cca_narrow_ch160[4];\n    uint32_t last_tx_ch_width_indx;\n    uint32_t rx_detected_per_ch_width[4];\n    uint32_t success_per_ch_width[4];\n    uint32_t fail_per_ch_width[4];\n}; /* IWM_STATISTICS_TX_CHANNEL_WIDTH_API_S_VER_1 */\n\nstruct iwm_statistics_tx {\n    uint32_t preamble_cnt;\n    uint32_t rx_detected_cnt;\n    uint32_t bt_prio_defer_cnt;\n    uint32_t bt_prio_kill_cnt;\n    uint32_t few_bytes_cnt;\n    uint32_t cts_timeout;\n    uint32_t ack_timeout;\n    uint32_t expected_ack_cnt;\n    uint32_t actual_ack_cnt;\n    uint32_t dump_msdu_cnt;\n    uint32_t burst_abort_next_frame_mismatch_cnt;\n    uint32_t burst_abort_missing_next_frame_cnt;\n    uint32_t cts_timeout_collision;\n    uint32_t ack_or_ba_timeout_collision;\n    struct iwm_statistics_tx_non_phy_agg agg;\n    struct iwm_statistics_tx_channel_width channel_width;\n} __packed; /* IWM_STATISTICS_TX_API_S_VER_4 */\n\n\nstruct iwm_statistics_bt_activity {\n    uint32_t hi_priority_tx_req_cnt;\n    uint32_t hi_priority_tx_denied_cnt;\n    uint32_t lo_priority_tx_req_cnt;\n    uint32_t lo_priority_tx_denied_cnt;\n    uint32_t hi_priority_rx_req_cnt;\n    uint32_t hi_priority_rx_denied_cnt;\n    uint32_t lo_priority_rx_req_cnt;\n    uint32_t lo_priority_rx_denied_cnt;\n} __packed;  /* IWM_STATISTICS_BT_ACTIVITY_API_S_VER_1 */\n\nstruct iwm_statistics_general {\n    struct iwm_statistics_general_common common;\n    uint32_t beacon_filtered;\n    uint32_t missed_beacons;\n    int8_t beacon_filter_average_energy;\n    int8_t beacon_filter_reason;\n    int8_t beacon_filter_current_energy;\n    int8_t beacon_filter_reserved;\n    uint32_t beacon_filter_delta_time;\n    struct iwm_statistics_bt_activity bt_activity;\n} __packed; /* IWM_STATISTICS_GENERAL_API_S_VER_5 */\n\nstruct iwm_statistics_rx {\n    struct iwm_statistics_rx_phy ofdm;\n    struct iwm_statistics_rx_phy cck;\n    struct iwm_statistics_rx_non_phy general;\n    struct iwm_statistics_rx_ht_phy ofdm_ht;\n} __packed; /* IWM_STATISTICS_RX_API_S_VER_3 */\n\n/*\n * IWM_STATISTICS_NOTIFICATION = 0x9d (notification only, not a command)\n *\n * By default, uCode issues this notification after receiving a beacon\n * while associated.  To disable this behavior, set DISABLE_NOTIF flag in the\n * IWM_REPLY_STATISTICS_CMD 0x9c, above.\n *\n * Statistics counters continue to increment beacon after beacon, but are\n * cleared when changing channels or when driver issues IWM_REPLY_STATISTICS_CMD\n * 0x9c with CLEAR_STATS bit set (see above).\n *\n * uCode also issues this notification during scans.  uCode clears statistics\n * appropriately so that each notification contains statistics for only the\n * one channel that has just been scanned.\n */\n\nstruct iwm_notif_statistics { /* IWM_STATISTICS_NTFY_API_S_VER_8 */\n    uint32_t flag;\n    struct iwm_statistics_rx rx;\n    struct iwm_statistics_tx tx;\n    struct iwm_statistics_general general;\n} __packed;\n\n/***********************************\n * Smart Fifo API\n ***********************************/\n/* Smart Fifo state */\n#define IWM_SF_LONG_DELAY_ON    0 /* should never be called by driver */\n#define IWM_SF_FULL_ON        1\n#define IWM_SF_UNINIT        2\n#define IWM_SF_INIT_OFF        3\n#define IWM_SF_HW_NUM_STATES    4\n\n/* Smart Fifo possible scenario */\n#define IWM_SF_SCENARIO_SINGLE_UNICAST    0\n#define IWM_SF_SCENARIO_AGG_UNICAST    1\n#define IWM_SF_SCENARIO_MULTICAST    2\n#define IWM_SF_SCENARIO_BA_RESP        3\n#define IWM_SF_SCENARIO_TX_RESP        4\n#define IWM_SF_NUM_SCENARIO        5\n\n#define IWM_SF_TRANSIENT_STATES_NUMBER 2 /* IWM_SF_LONG_DELAY_ON and IWM_SF_FULL_ON */\n#define IWM_SF_NUM_TIMEOUT_TYPES 2    /* Aging timer and Idle timer */\n\n/* smart FIFO default values */\n#define IWM_SF_W_MARK_SISO 4096\n#define IWM_SF_W_MARK_MIMO2 8192\n#define IWM_SF_W_MARK_MIMO3 6144\n#define IWM_SF_W_MARK_LEGACY 4096\n#define IWM_SF_W_MARK_SCAN 4096\n\n/* SF Scenarios timers for default configuration (aligned to 32 uSec) */\n#define IWM_SF_SINGLE_UNICAST_IDLE_TIMER_DEF 160    /* 150 uSec  */\n#define IWM_SF_SINGLE_UNICAST_AGING_TIMER_DEF 400    /* 0.4 mSec */\n#define IWM_SF_AGG_UNICAST_IDLE_TIMER_DEF 160        /* 150 uSec */\n#define IWM_SF_AGG_UNICAST_AGING_TIMER_DEF 400        /* 0.4 mSec */\n#define IWM_SF_MCAST_IDLE_TIMER_DEF 160            /* 150 mSec */\n#define IWM_SF_MCAST_AGING_TIMER_DEF 400        /* 0.4 mSec */\n#define IWM_SF_BA_IDLE_TIMER_DEF 160            /* 150 uSec */\n#define IWM_SF_BA_AGING_TIMER_DEF 400            /* 0.4 mSec */\n#define IWM_SF_TX_RE_IDLE_TIMER_DEF 160            /* 150 uSec */\n#define IWM_SF_TX_RE_AGING_TIMER_DEF 400        /* 0.4 mSec */\n\n/* SF Scenarios timers for FULL_ON state (aligned to 32 uSec) */\n#define IWM_SF_SINGLE_UNICAST_IDLE_TIMER 320    /* 300 uSec  */\n#define IWM_SF_SINGLE_UNICAST_AGING_TIMER 2016    /* 2 mSec */\n#define IWM_SF_AGG_UNICAST_IDLE_TIMER 320    /* 300 uSec */\n#define IWM_SF_AGG_UNICAST_AGING_TIMER 2016    /* 2 mSec */\n#define IWM_SF_MCAST_IDLE_TIMER 2016        /* 2 mSec */\n#define IWM_SF_MCAST_AGING_TIMER 10016        /* 10 mSec */\n#define IWM_SF_BA_IDLE_TIMER 320        /* 300 uSec */\n#define IWM_SF_BA_AGING_TIMER 2016        /* 2 mSec */\n#define IWM_SF_TX_RE_IDLE_TIMER 320        /* 300 uSec */\n#define IWM_SF_TX_RE_AGING_TIMER 2016        /* 2 mSec */\n\n#define IWM_SF_LONG_DELAY_AGING_TIMER 1000000    /* 1 Sec */\n\n#define IWM_SF_CFG_DUMMY_NOTIF_OFF    (1 << 16)\n\n/**\n * Smart Fifo configuration command.\n * @state: smart fifo state, types listed in enum %iwm_sf_state.\n * @watermark: Minimum allowed availabe free space in RXF for transient state.\n * @long_delay_timeouts: aging and idle timer values for each scenario\n * in long delay state.\n * @full_on_timeouts: timer values for each scenario in full on state.\n */\nstruct iwm_sf_cfg_cmd {\n    uint32_t state;\n    uint32_t watermark[IWM_SF_TRANSIENT_STATES_NUMBER];\n    uint32_t long_delay_timeouts[IWM_SF_NUM_SCENARIO][IWM_SF_NUM_TIMEOUT_TYPES];\n    uint32_t full_on_timeouts[IWM_SF_NUM_SCENARIO][IWM_SF_NUM_TIMEOUT_TYPES];\n} __packed; /* IWM_SF_CFG_API_S_VER_2 */\n\n/*\n * The first MAC indices (starting from 0)\n * are available to the driver, AUX follows\n */\n#define IWM_MAC_INDEX_AUX        4\n#define IWM_MAC_INDEX_MIN_DRIVER    0\n#define IWM_NUM_MAC_INDEX_DRIVER    IWM_MAC_INDEX_AUX\n\n#define IWM_AC_BK    0\n#define IWM_AC_BE    1\n#define IWM_AC_VI    2\n#define IWM_AC_VO    3\n#define IWM_AC_NUM    4\n\n/**\n * MAC context flags\n * @IWM_MAC_PROT_FLG_TGG_PROTECT: 11g protection when transmitting OFDM frames,\n *    this will require CCK RTS/CTS2self.\n *    RTS/CTS will protect full burst time.\n * @IWM_MAC_PROT_FLG_HT_PROT: enable HT protection\n * @IWM_MAC_PROT_FLG_FAT_PROT: protect 40 MHz transmissions\n * @IWM_MAC_PROT_FLG_SELF_CTS_EN: allow CTS2self\n */\n#define IWM_MAC_PROT_FLG_TGG_PROTECT    (1 << 3)\n#define IWM_MAC_PROT_FLG_HT_PROT    (1 << 23)\n#define IWM_MAC_PROT_FLG_FAT_PROT    (1 << 24)\n#define IWM_MAC_PROT_FLG_SELF_CTS_EN    (1 << 30)\n\n#define IWM_MAC_FLG_SHORT_SLOT        (1 << 4)\n#define IWM_MAC_FLG_SHORT_PREAMBLE    (1 << 5)\n\n/**\n * Supported MAC types\n * @IWM_FW_MAC_TYPE_FIRST: lowest supported MAC type\n * @IWM_FW_MAC_TYPE_AUX: Auxiliary MAC (internal)\n * @IWM_FW_MAC_TYPE_LISTENER: monitor MAC type (?)\n * @IWM_FW_MAC_TYPE_PIBSS: Pseudo-IBSS\n * @IWM_FW_MAC_TYPE_IBSS: IBSS\n * @IWM_FW_MAC_TYPE_BSS_STA: BSS (managed) station\n * @IWM_FW_MAC_TYPE_P2P_DEVICE: P2P Device\n * @IWM_FW_MAC_TYPE_P2P_STA: P2P client\n * @IWM_FW_MAC_TYPE_GO: P2P GO\n * @IWM_FW_MAC_TYPE_TEST: ?\n * @IWM_FW_MAC_TYPE_MAX: highest support MAC type\n */\n#define IWM_FW_MAC_TYPE_FIRST        1\n#define IWM_FW_MAC_TYPE_AUX        IWM_FW_MAC_TYPE_FIRST\n#define IWM_FW_MAC_TYPE_LISTENER    2\n#define IWM_FW_MAC_TYPE_PIBSS        3\n#define IWM_FW_MAC_TYPE_IBSS        4\n#define IWM_FW_MAC_TYPE_BSS_STA        5\n#define IWM_FW_MAC_TYPE_P2P_DEVICE    6\n#define IWM_FW_MAC_TYPE_P2P_STA        7\n#define IWM_FW_MAC_TYPE_GO        8\n#define IWM_FW_MAC_TYPE_TEST        9\n#define IWM_FW_MAC_TYPE_MAX        IWM_FW_MAC_TYPE_TEST\n/* IWM_MAC_CONTEXT_TYPE_API_E_VER_1 */\n\n/**\n * TSF hw timer ID\n * @IWM_TSF_ID_A: use TSF A\n * @IWM_TSF_ID_B: use TSF B\n * @IWM_TSF_ID_C: use TSF C\n * @IWM_TSF_ID_D: use TSF D\n * @IWM_NUM_TSF_IDS: number of TSF timers available\n */\n#define IWM_TSF_ID_A    0\n#define IWM_TSF_ID_B    1\n#define IWM_TSF_ID_C    2\n#define IWM_TSF_ID_D    3\n#define IWM_NUM_TSF_IDS    4\n/* IWM_TSF_ID_API_E_VER_1 */\n\n/**\n * struct iwm_mac_data_ap - configuration data for AP MAC context\n * @beacon_time: beacon transmit time in system time\n * @beacon_tsf: beacon transmit time in TSF\n * @bi: beacon interval in TU\n * @bi_reciprocal: 2^32 / bi\n * @dtim_interval: dtim transmit time in TU\n * @dtim_reciprocal: 2^32 / dtim_interval\n * @mcast_qid: queue ID for multicast traffic\n *    NOTE: obsolete from VER2 and on\n * @beacon_template: beacon template ID\n */\nstruct iwm_mac_data_ap {\n    uint32_t beacon_time;\n    uint64_t beacon_tsf;\n    uint32_t bi;\n    uint32_t bi_reciprocal;\n    uint32_t dtim_interval;\n    uint32_t dtim_reciprocal;\n    uint32_t mcast_qid;\n    uint32_t beacon_template;\n} __packed; /* AP_MAC_DATA_API_S_VER_2 */\n\n/**\n * struct iwm_mac_data_ibss - configuration data for IBSS MAC context\n * @beacon_time: beacon transmit time in system time\n * @beacon_tsf: beacon transmit time in TSF\n * @bi: beacon interval in TU\n * @bi_reciprocal: 2^32 / bi\n * @beacon_template: beacon template ID\n */\nstruct iwm_mac_data_ibss {\n    uint32_t beacon_time;\n    uint64_t beacon_tsf;\n    uint32_t bi;\n    uint32_t bi_reciprocal;\n    uint32_t beacon_template;\n} __packed; /* IBSS_MAC_DATA_API_S_VER_1 */\n\n/**\n * struct iwm_mac_data_sta - configuration data for station MAC context\n * @is_assoc: 1 for associated state, 0 otherwise\n * @dtim_time: DTIM arrival time in system time\n * @dtim_tsf: DTIM arrival time in TSF\n * @bi: beacon interval in TU, applicable only when associated\n * @bi_reciprocal: 2^32 / bi , applicable only when associated\n * @dtim_interval: DTIM interval in TU, applicable only when associated\n * @dtim_reciprocal: 2^32 / dtim_interval , applicable only when associated\n * @listen_interval: in beacon intervals, applicable only when associated\n * @assoc_id: unique ID assigned by the AP during association\n */\nstruct iwm_mac_data_sta {\n    uint32_t is_assoc;\n    uint32_t dtim_time;\n    uint64_t dtim_tsf;\n    uint32_t bi;\n    uint32_t bi_reciprocal;\n    uint32_t dtim_interval;\n    uint32_t dtim_reciprocal;\n    uint32_t listen_interval;\n    uint32_t assoc_id;\n    uint32_t assoc_beacon_arrive_time;\n} __packed; /* IWM_STA_MAC_DATA_API_S_VER_1 */\n\n/**\n * struct iwm_mac_data_go - configuration data for P2P GO MAC context\n * @ap: iwm_mac_data_ap struct with most config data\n * @ctwin: client traffic window in TU (period after TBTT when GO is present).\n *    0 indicates that there is no CT window.\n * @opp_ps_enabled: indicate that opportunistic PS allowed\n */\nstruct iwm_mac_data_go {\n    struct iwm_mac_data_ap ap;\n    uint32_t ctwin;\n    uint32_t opp_ps_enabled;\n} __packed; /* GO_MAC_DATA_API_S_VER_1 */\n\n/**\n * struct iwm_mac_data_p2p_sta - configuration data for P2P client MAC context\n * @sta: iwm_mac_data_sta struct with most config data\n * @ctwin: client traffic window in TU (period after TBTT when GO is present).\n *    0 indicates that there is no CT window.\n */\nstruct iwm_mac_data_p2p_sta {\n    struct iwm_mac_data_sta sta;\n    uint32_t ctwin;\n} __packed; /* P2P_STA_MAC_DATA_API_S_VER_1 */\n\n/**\n * struct iwm_mac_data_pibss - Pseudo IBSS config data\n * @stats_interval: interval in TU between statistics notifications to host.\n */\nstruct iwm_mac_data_pibss {\n    uint32_t stats_interval;\n} __packed; /* PIBSS_MAC_DATA_API_S_VER_1 */\n\n/*\n * struct iwm_mac_data_p2p_dev - configuration data for the P2P Device MAC\n * context.\n * @is_disc_extended: if set to true, P2P Device discoverability is enabled on\n *    other channels as well. This should be to true only in case that the\n *    device is discoverable and there is an active GO. Note that setting this\n *    field when not needed, will increase the number of interrupts and have\n *    effect on the platform power, as this setting opens the Rx filters on\n *    all macs.\n */\nstruct iwm_mac_data_p2p_dev {\n    uint32_t is_disc_extended;\n} __packed; /* _P2P_DEV_MAC_DATA_API_S_VER_1 */\n\n/**\n * MAC context filter flags\n * @IWM_MAC_FILTER_IN_PROMISC: accept all data frames\n * @IWM_MAC_FILTER_IN_CONTROL_AND_MGMT: pass all mangement and\n *    control frames to the host\n * @IWM_MAC_FILTER_ACCEPT_GRP: accept multicast frames\n * @IWM_MAC_FILTER_DIS_DECRYPT: don't decrypt unicast frames\n * @IWM_MAC_FILTER_DIS_GRP_DECRYPT: don't decrypt multicast frames\n * @IWM_MAC_FILTER_IN_BEACON: transfer foreign BSS's beacons to host\n *    (in station mode when associated)\n * @IWM_MAC_FILTER_OUT_BCAST: filter out all broadcast frames\n * @IWM_MAC_FILTER_IN_CRC32: extract FCS and append it to frames\n * @IWM_MAC_FILTER_IN_PROBE_REQUEST: pass probe requests to host\n */\n#define IWM_MAC_FILTER_IN_PROMISC        (1 << 0)\n#define IWM_MAC_FILTER_IN_CONTROL_AND_MGMT    (1 << 1)\n#define IWM_MAC_FILTER_ACCEPT_GRP        (1 << 2)\n#define IWM_MAC_FILTER_DIS_DECRYPT        (1 << 3)\n#define IWM_MAC_FILTER_DIS_GRP_DECRYPT        (1 << 4)\n#define IWM_MAC_FILTER_IN_BEACON        (1 << 6)\n#define IWM_MAC_FILTER_OUT_BCAST        (1 << 8)\n#define IWM_MAC_FILTER_IN_CRC32            (1 << 11)\n#define IWM_MAC_FILTER_IN_PROBE_REQUEST        (1 << 12)\n\n/**\n * QoS flags\n * @IWM_MAC_QOS_FLG_UPDATE_EDCA: ?\n * @IWM_MAC_QOS_FLG_TGN: HT is enabled\n * @IWM_MAC_QOS_FLG_TXOP_TYPE: ?\n *\n */\n#define IWM_MAC_QOS_FLG_UPDATE_EDCA    (1 << 0)\n#define IWM_MAC_QOS_FLG_TGN        (1 << 1)\n#define IWM_MAC_QOS_FLG_TXOP_TYPE    (1 << 4)\n\n/**\n * struct iwm_ac_qos - QOS timing params for IWM_MAC_CONTEXT_CMD\n * @cw_min: Contention window, start value in numbers of slots.\n *    Should be a power-of-2, minus 1.  Device's default is 0x0f.\n * @cw_max: Contention window, max value in numbers of slots.\n *    Should be a power-of-2, minus 1.  Device's default is 0x3f.\n * @aifsn:  Number of slots in Arbitration Interframe Space (before\n *    performing random backoff timing prior to Tx).  Device default 1.\n * @fifos_mask: FIFOs used by this MAC for this AC\n * @edca_txop:  Length of Tx opportunity, in uSecs.  Device default is 0.\n *\n * One instance of this config struct for each of 4 EDCA access categories\n * in struct iwm_qosparam_cmd.\n *\n * Device will automatically increase contention window by (2*CW) + 1 for each\n * transmission retry.  Device uses cw_max as a bit mask, ANDed with new CW\n * value, to cap the CW value.\n */\nstruct iwm_ac_qos {\n    uint16_t cw_min;\n    uint16_t cw_max;\n    uint8_t aifsn;\n    uint8_t fifos_mask;\n    uint16_t edca_txop;\n} __packed; /* IWM_AC_QOS_API_S_VER_2 */\n\n/**\n * struct iwm_mac_ctx_cmd - command structure to configure MAC contexts\n * ( IWM_MAC_CONTEXT_CMD = 0x28 )\n * @id_and_color: ID and color of the MAC\n * @action: action to perform, one of IWM_FW_CTXT_ACTION_*\n * @mac_type: one of IWM_FW_MAC_TYPE_*\n * @tsf_id: TSF HW timer, one of IWM_TSF_ID_*\n * @node_addr: MAC address\n * @bssid_addr: BSSID\n * @cck_rates: basic rates available for CCK\n * @ofdm_rates: basic rates available for OFDM\n * @protection_flags: combination of IWM_MAC_PROT_FLG_FLAG_*\n * @cck_short_preamble: 0x20 for enabling short preamble, 0 otherwise\n * @short_slot: 0x10 for enabling short slots, 0 otherwise\n * @filter_flags: combination of IWM_MAC_FILTER_*\n * @qos_flags: from IWM_MAC_QOS_FLG_*\n * @ac: one iwm_mac_qos configuration for each AC\n * @mac_specific: one of struct iwm_mac_data_*, according to mac_type\n */\nstruct iwm_mac_ctx_cmd {\n    /* COMMON_INDEX_HDR_API_S_VER_1 */\n    uint32_t id_and_color;\n    uint32_t action;\n    /* IWM_MAC_CONTEXT_COMMON_DATA_API_S_VER_1 */\n    uint32_t mac_type;\n    uint32_t tsf_id;\n    uint8_t node_addr[6];\n    uint16_t reserved_for_node_addr;\n    uint8_t bssid_addr[6];\n    uint16_t reserved_for_bssid_addr;\n    uint32_t cck_rates;\n    uint32_t ofdm_rates;\n    uint32_t protection_flags;\n    uint32_t cck_short_preamble;\n    uint32_t short_slot;\n    uint32_t filter_flags;\n    /* IWM_MAC_QOS_PARAM_API_S_VER_1 */\n    uint32_t qos_flags;\n    struct iwm_ac_qos ac[IWM_AC_NUM+1];\n    /* IWM_MAC_CONTEXT_COMMON_DATA_API_S */\n    union {\n        struct iwm_mac_data_ap ap;\n        struct iwm_mac_data_go go;\n        struct iwm_mac_data_sta sta;\n        struct iwm_mac_data_p2p_sta p2p_sta;\n        struct iwm_mac_data_p2p_dev p2p_dev;\n        struct iwm_mac_data_pibss pibss;\n        struct iwm_mac_data_ibss ibss;\n    };\n} __packed; /* IWM_MAC_CONTEXT_CMD_API_S_VER_1 */\n\nstatic inline uint32_t iwm_reciprocal(uint32_t v)\n{\n    if (!v)\n        return 0;\n    return 0xFFFFFFFF / v;\n}\n\n#define IWM_NONQOS_SEQ_GET    0x1\n#define IWM_NONQOS_SEQ_SET    0x2\nstruct iwm_nonqos_seq_query_cmd {\n    uint32_t get_set_flag;\n    uint32_t mac_id_n_color;\n    uint16_t value;\n    uint16_t reserved;\n} __packed; /* IWM_NON_QOS_TX_COUNTER_GET_SET_API_S_VER_1 */\n\n/* Power Management Commands, Responses, Notifications */\n\n/**\n * masks for LTR config command flags\n * @IWM_LTR_CFG_FLAG_FEATURE_ENABLE: Feature operational status\n * @IWM_LTR_CFG_FLAG_HW_DIS_ON_SHADOW_REG_ACCESS: allow LTR change on shadow\n *      memory access\n * @IWM_LTR_CFG_FLAG_HW_EN_SHRT_WR_THROUGH: allow LTR msg send on ANY LTR\n *      reg change\n * @IWM_LTR_CFG_FLAG_HW_DIS_ON_D0_2_D3: allow LTR msg send on transition from\n *      D0 to D3\n * @IWM_LTR_CFG_FLAG_SW_SET_SHORT: fixed static short LTR register\n * @IWM_LTR_CFG_FLAG_SW_SET_LONG: fixed static short LONG register\n * @IWM_LTR_CFG_FLAG_DENIE_C10_ON_PD: allow going into C10 on PD\n */\n#define IWM_LTR_CFG_FLAG_FEATURE_ENABLE            0x00000001\n#define IWM_LTR_CFG_FLAG_HW_DIS_ON_SHADOW_REG_ACCESS    0x00000002\n#define IWM_LTR_CFG_FLAG_HW_EN_SHRT_WR_THROUGH        0x00000004\n#define IWM_LTR_CFG_FLAG_HW_DIS_ON_D0_2_D3        0x00000008\n#define IWM_LTR_CFG_FLAG_SW_SET_SHORT            0x00000010\n#define IWM_LTR_CFG_FLAG_SW_SET_LONG            0x00000020\n#define IWM_LTR_CFG_FLAG_DENIE_C10_ON_PD        0x00000040\n\n/**\n * struct iwm_ltr_config_cmd_v1 - configures the LTR\n * @flags: See %enum iwm_ltr_config_flags\n */\nstruct iwm_ltr_config_cmd_v1 {\n    uint32_t flags;\n    uint32_t static_long;\n    uint32_t static_short;\n} __packed; /* LTR_CAPABLE_API_S_VER_1 */\n\n#define IWM_LTR_VALID_STATES_NUM 4\n\n/**\n * struct iwm_ltr_config_cmd - configures the LTR\n * @flags: See %enum iwm_ltr_config_flags\n * @static_long:\n * @static_short:\n * @ltr_cfg_values:\n * @ltr_short_idle_timeout:\n */\nstruct iwm_ltr_config_cmd {\n    uint32_t flags;\n    uint32_t static_long;\n    uint32_t static_short;\n    uint32_t ltr_cfg_values[IWM_LTR_VALID_STATES_NUM];\n    uint32_t ltr_short_idle_timeout;\n} __packed; /* LTR_CAPABLE_API_S_VER_2 */\n\n/* Radio LP RX Energy Threshold measured in dBm */\n#define IWM_POWER_LPRX_RSSI_THRESHOLD    75\n#define IWM_POWER_LPRX_RSSI_THRESHOLD_MAX    94\n#define IWM_POWER_LPRX_RSSI_THRESHOLD_MIN    30\n\n/**\n * Masks for iwm_mac_power_cmd command flags\n * @IWM_POWER_FLAGS_POWER_SAVE_ENA_MSK: '1' Allow to save power by turning off\n *        receiver and transmitter. '0' - does not allow.\n * @IWM_POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK: '0' Driver disables power management,\n *        '1' Driver enables PM (use rest of parameters)\n * @IWM_POWER_FLAGS_SKIP_OVER_DTIM_MSK: '0' PM have to walk up every DTIM,\n *        '1' PM could sleep over DTIM till listen Interval.\n * @IWM_POWER_FLAGS_SNOOZE_ENA_MSK: Enable snoozing only if uAPSD is enabled and all\n *        access categories are both delivery and trigger enabled.\n * @IWM_POWER_FLAGS_BT_SCO_ENA: Enable BT SCO coex only if uAPSD and\n *        PBW Snoozing enabled\n * @IWM_POWER_FLAGS_ADVANCE_PM_ENA_MSK: Advanced PM (uAPSD) enable mask\n * @IWM_POWER_FLAGS_LPRX_ENA_MSK: Low Power RX enable.\n * @IWM_POWER_FLAGS_AP_UAPSD_MISBEHAVING_ENA_MSK: AP/GO's uAPSD misbehaving\n *        detection enablement\n*/\n#define IWM_POWER_FLAGS_POWER_SAVE_ENA_MSK        (1 << 0)\n#define IWM_POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK    (1 << 1)\n#define IWM_POWER_FLAGS_SKIP_OVER_DTIM_MSK        (1 << 2)\n#define IWM_POWER_FLAGS_SNOOZE_ENA_MSK            (1 << 5)\n#define IWM_POWER_FLAGS_BT_SCO_ENA            (1 << 8)\n#define IWM_POWER_FLAGS_ADVANCE_PM_ENA_MSK        (1 << 9)\n#define IWM_POWER_FLAGS_LPRX_ENA_MSK            (1 << 11)\n#define IWM_POWER_FLAGS_UAPSD_MISBEHAVING_ENA_MSK    (1 << 12)\n\n#define IWM_POWER_VEC_SIZE 5\n\n/**\n * Masks for device power command flags\n * @IWM_DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK:\n *   '1' Allow to save power by turning off receiver and transmitter.\n *   '0' Do not allow. This flag should be always set to '1' unless\n *       one needs to disable actual power down for debug purposes.\n * @IWM_DEVICE_POWER_FLAGS_CAM_MSK:\n *   '1' CAM (Continuous Active Mode) is set, power management is disabled.\n *   '0' Power management is enabled, one of the power schemes is applied.\n */\n#define IWM_DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK    (1 << 0)\n#define IWM_DEVICE_POWER_FLAGS_CAM_MSK            (1 << 13)\n\n/**\n * struct iwm_device_power_cmd - device wide power command.\n * IWM_POWER_TABLE_CMD = 0x77 (command, has simple generic response)\n *\n * @flags:    Power table command flags from IWM_DEVICE_POWER_FLAGS_*\n */\nstruct iwm_device_power_cmd {\n    /* PM_POWER_TABLE_CMD_API_S_VER_6 */\n    uint16_t flags;\n    uint16_t reserved;\n} __packed;\n\n/**\n * struct iwm_mac_power_cmd - New power command containing uAPSD support\n * IWM_MAC_PM_POWER_TABLE = 0xA9 (command, has simple generic response)\n * @id_and_color:    MAC contex identifier\n * @flags:        Power table command flags from POWER_FLAGS_*\n * @keep_alive_seconds:    Keep alive period in seconds. Default - 25 sec.\n *            Minimum allowed:- 3 * DTIM. Keep alive period must be\n *            set regardless of power scheme or current power state.\n *            FW use this value also when PM is disabled.\n * @rx_data_timeout:    Minimum time (usec) from last Rx packet for AM to\n *            PSM transition - legacy PM\n * @tx_data_timeout:    Minimum time (usec) from last Tx packet for AM to\n *            PSM transition - legacy PM\n * @sleep_interval:    not in use\n * @skip_dtim_periods:    Number of DTIM periods to skip if Skip over DTIM flag\n *            is set. For example, if it is required to skip over\n *            one DTIM, this value need to be set to 2 (DTIM periods).\n * @rx_data_timeout_uapsd: Minimum time (usec) from last Rx packet for AM to\n *            PSM transition - uAPSD\n * @tx_data_timeout_uapsd: Minimum time (usec) from last Tx packet for AM to\n *            PSM transition - uAPSD\n * @lprx_rssi_threshold: Signal strength up to which LP RX can be enabled.\n *            Default: 80dbm\n * @num_skip_dtim:    Number of DTIMs to skip if Skip over DTIM flag is set\n * @snooze_interval:    Maximum time between attempts to retrieve buffered data\n *            from the AP [msec]\n * @snooze_window:    A window of time in which PBW snoozing insures that all\n *            packets received. It is also the minimum time from last\n *            received unicast RX packet, before client stops snoozing\n *            for data. [msec]\n * @snooze_step:    TBD\n * @qndp_tid:        TID client shall use for uAPSD QNDP triggers\n * @uapsd_ac_flags:    Set trigger-enabled and delivery-enabled indication for\n *            each corresponding AC.\n *            Use IEEE80211_WMM_IE_STA_QOSINFO_AC* for correct values.\n * @uapsd_max_sp:    Use IEEE80211_WMM_IE_STA_QOSINFO_SP_* for correct\n *            values.\n * @heavy_tx_thld_packets:    TX threshold measured in number of packets\n * @heavy_rx_thld_packets:    RX threshold measured in number of packets\n * @heavy_tx_thld_percentage:    TX threshold measured in load's percentage\n * @heavy_rx_thld_percentage:    RX threshold measured in load's percentage\n * @limited_ps_threshold:\n*/\nstruct iwm_mac_power_cmd {\n    /* CONTEXT_DESC_API_T_VER_1 */\n    uint32_t id_and_color;\n\n    /* CLIENT_PM_POWER_TABLE_S_VER_1 */\n    uint16_t flags;\n    uint16_t keep_alive_seconds;\n    uint32_t rx_data_timeout;\n    uint32_t tx_data_timeout;\n    uint32_t rx_data_timeout_uapsd;\n    uint32_t tx_data_timeout_uapsd;\n    uint8_t lprx_rssi_threshold;\n    uint8_t skip_dtim_periods;\n    uint16_t snooze_interval;\n    uint16_t snooze_window;\n    uint8_t snooze_step;\n    uint8_t qndp_tid;\n    uint8_t uapsd_ac_flags;\n    uint8_t uapsd_max_sp;\n    uint8_t heavy_tx_thld_packets;\n    uint8_t heavy_rx_thld_packets;\n    uint8_t heavy_tx_thld_percentage;\n    uint8_t heavy_rx_thld_percentage;\n    uint8_t limited_ps_threshold;\n    uint8_t reserved;\n} __packed;\n\n#define IWM_DEFAULT_PS_TX_DATA_TIMEOUT      (100 * 1000)\n#define IWM_DEFAULT_PS_RX_DATA_TIMEOUT      (100 * 1000)\n\n/*\n * struct iwm_uapsd_misbehaving_ap_notif - FW sends this notification when\n * associated AP is identified as improperly implementing uAPSD protocol.\n * IWM_PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION = 0x78\n * @sta_id: index of station in uCode's station table - associated AP ID in\n *        this context.\n */\nstruct iwm_uapsd_misbehaving_ap_notif {\n    uint32_t sta_id;\n    uint8_t mac_id;\n    uint8_t reserved[3];\n} __packed;\n\n/**\n * struct iwm_beacon_filter_cmd\n * IWM_REPLY_BEACON_FILTERING_CMD = 0xd2 (command)\n * @id_and_color: MAC contex identifier\n * @bf_energy_delta: Used for RSSI filtering, if in 'normal' state. Send beacon\n *      to driver if delta in Energy values calculated for this and last\n *      passed beacon is greater than this threshold. Zero value means that\n *      the Energy change is ignored for beacon filtering, and beacon will\n *      not be forced to be sent to driver regardless of this delta. Typical\n *      energy delta 5dB.\n * @bf_roaming_energy_delta: Used for RSSI filtering, if in 'roaming' state.\n *      Send beacon to driver if delta in Energy values calculated for this\n *      and last passed beacon is greater than this threshold. Zero value\n *      means that the Energy change is ignored for beacon filtering while in\n *      Roaming state, typical energy delta 1dB.\n * @bf_roaming_state: Used for RSSI filtering. If absolute Energy values\n *      calculated for current beacon is less than the threshold, use\n *      Roaming Energy Delta Threshold, otherwise use normal Energy Delta\n *      Threshold. Typical energy threshold is -72dBm.\n * @bf_temp_threshold: This threshold determines the type of temperature\n *    filtering (Slow or Fast) that is selected (Units are in Celsuis):\n *      If the current temperature is above this threshold - Fast filter\n *    will be used, If the current temperature is below this threshold -\n *    Slow filter will be used.\n * @bf_temp_fast_filter: Send Beacon to driver if delta in temperature values\n *      calculated for this and the last passed beacon is greater than this\n *      threshold. Zero value means that the temperature change is ignored for\n *      beacon filtering; beacons will not be  forced to be sent to driver\n *      regardless of whether its temerature has been changed.\n * @bf_temp_slow_filter: Send Beacon to driver if delta in temperature values\n *      calculated for this and the last passed beacon is greater than this\n *      threshold. Zero value means that the temperature change is ignored for\n *      beacon filtering; beacons will not be forced to be sent to driver\n *      regardless of whether its temerature has been changed.\n * @bf_enable_beacon_filter: 1, beacon filtering is enabled; 0, disabled.\n * @bf_escape_timer: Send beacons to driver if no beacons were passed\n *      for a specific period of time. Units: Beacons.\n * @ba_escape_timer: Fully receive and parse beacon if no beacons were passed\n *      for a longer period of time then this escape-timeout. Units: Beacons.\n * @ba_enable_beacon_abort: 1, beacon abort is enabled; 0, disabled.\n */\nstruct iwm_beacon_filter_cmd {\n    uint32_t bf_energy_delta;\n    uint32_t bf_roaming_energy_delta;\n    uint32_t bf_roaming_state;\n    uint32_t bf_temp_threshold;\n    uint32_t bf_temp_fast_filter;\n    uint32_t bf_temp_slow_filter;\n    uint32_t bf_enable_beacon_filter;\n    uint32_t bf_debug_flag;\n    uint32_t bf_escape_timer;\n    uint32_t ba_escape_timer;\n    uint32_t ba_enable_beacon_abort;\n} __packed;\n\n/* Beacon filtering and beacon abort */\n#define IWM_BF_ENERGY_DELTA_DEFAULT 5\n#define IWM_BF_ENERGY_DELTA_MAX 255\n#define IWM_BF_ENERGY_DELTA_MIN 0\n\n#define IWM_BF_ROAMING_ENERGY_DELTA_DEFAULT 1\n#define IWM_BF_ROAMING_ENERGY_DELTA_MAX 255\n#define IWM_BF_ROAMING_ENERGY_DELTA_MIN 0\n\n#define IWM_BF_ROAMING_STATE_DEFAULT 72\n#define IWM_BF_ROAMING_STATE_MAX 255\n#define IWM_BF_ROAMING_STATE_MIN 0\n\n#define IWM_BF_TEMP_THRESHOLD_DEFAULT 112\n#define IWM_BF_TEMP_THRESHOLD_MAX 255\n#define IWM_BF_TEMP_THRESHOLD_MIN 0\n\n#define IWM_BF_TEMP_FAST_FILTER_DEFAULT 1\n#define IWM_BF_TEMP_FAST_FILTER_MAX 255\n#define IWM_BF_TEMP_FAST_FILTER_MIN 0\n\n#define IWM_BF_TEMP_SLOW_FILTER_DEFAULT 5\n#define IWM_BF_TEMP_SLOW_FILTER_MAX 255\n#define IWM_BF_TEMP_SLOW_FILTER_MIN 0\n\n#define IWM_BF_ENABLE_BEACON_FILTER_DEFAULT 1\n\n#define IWM_BF_DEBUG_FLAG_DEFAULT 0\n\n#define IWM_BF_ESCAPE_TIMER_DEFAULT 50\n#define IWM_BF_ESCAPE_TIMER_MAX 1024\n#define IWM_BF_ESCAPE_TIMER_MIN 0\n\n#define IWM_BA_ESCAPE_TIMER_DEFAULT 6\n#define IWM_BA_ESCAPE_TIMER_D3 9\n#define IWM_BA_ESCAPE_TIMER_MAX 1024\n#define IWM_BA_ESCAPE_TIMER_MIN 0\n\n#define IWM_BA_ENABLE_BEACON_ABORT_DEFAULT 1\n\n#define IWM_BF_CMD_CONFIG_DEFAULTS                         \\\n    .bf_energy_delta = htole32(IWM_BF_ENERGY_DELTA_DEFAULT),         \\\n    .bf_roaming_energy_delta =                         \\\n        htole32(IWM_BF_ROAMING_ENERGY_DELTA_DEFAULT),         \\\n    .bf_roaming_state = htole32(IWM_BF_ROAMING_STATE_DEFAULT),         \\\n    .bf_temp_threshold = htole32(IWM_BF_TEMP_THRESHOLD_DEFAULT),     \\\n    .bf_temp_fast_filter = htole32(IWM_BF_TEMP_FAST_FILTER_DEFAULT), \\\n    .bf_temp_slow_filter = htole32(IWM_BF_TEMP_SLOW_FILTER_DEFAULT), \\\n    .bf_debug_flag = htole32(IWM_BF_DEBUG_FLAG_DEFAULT),         \\\n    .bf_escape_timer = htole32(IWM_BF_ESCAPE_TIMER_DEFAULT),         \\\n    .ba_escape_timer = htole32(IWM_BA_ESCAPE_TIMER_DEFAULT)\n\n/* Bit 14-16: Antenna selection (1) Ant A, (2) Ant B, (4) Ant C */\n#define IWM_RATE_MCS_ANT_POS        14\n#define IWM_RATE_MCS_ANT_A_MSK        (1 << IWM_RATE_MCS_ANT_POS)\n#define IWM_RATE_MCS_ANT_B_MSK        (2 << IWM_RATE_MCS_ANT_POS)\n#define IWM_RATE_MCS_ANT_C_MSK        (4 << IWM_RATE_MCS_ANT_POS)\n#define IWM_RATE_MCS_ANT_AB_MSK        (IWM_RATE_MCS_ANT_A_MSK | \\\n                     IWM_RATE_MCS_ANT_B_MSK)\n#define IWM_RATE_MCS_ANT_ABC_MSK        (IWM_RATE_MCS_ANT_AB_MSK | \\\n                     IWM_RATE_MCS_ANT_C_MSK)\n#define IWM_RATE_MCS_ANT_MSK        IWM_RATE_MCS_ANT_ABC_MSK\n#define IWM_RATE_MCS_ANT_NUM 3\n\n/* # entries in rate scale table to support Tx retries */\n#define  IWM_LQ_MAX_RETRY_NUM 16\n\n/* Antenna flags. */\n#define IWM_ANT_A    (1 << 0)\n#define IWM_ANT_B    (1 << 1)\n#define IWM_ANT_C    (1 << 2)\n/* Shortcuts. */\n#define IWM_ANT_AB    (IWM_ANT_A | IWM_ANT_B)\n#define IWM_ANT_BC    (IWM_ANT_B | IWM_ANT_C)\n#define IWM_ANT_ABC    (IWM_ANT_A | IWM_ANT_B | IWM_ANT_C)\n\n/**\n * struct iwm_lq_cmd - link quality command\n * @sta_id: station to update\n * @control: not used\n * @flags: combination of IWM_LQ_FLAG_*\n * @mimo_delim: the first SISO index in rs_table, which separates MIMO\n *    and SISO rates\n * @single_stream_ant_msk: best antenna for SISO (can be dual in CDD).\n *    Should be IWM_ANT_[ABC]\n * @dual_stream_ant_msk: best antennas for MIMO, combination of IWM_ANT_[ABC]\n * @initial_rate_index: first index from rs_table per AC category\n * @agg_time_limit: aggregation max time threshold in usec/100, meaning\n *    value of 100 is one usec. Range is 100 to 8000\n * @agg_disable_start_th: try-count threshold for starting aggregation.\n *    If a frame has higher try-count, it should not be selected for\n *    starting an aggregation sequence.\n * @agg_frame_cnt_limit: max frame count in an aggregation.\n *    0: no limit\n *    1: no aggregation (one frame per aggregation)\n *    2 - 0x3f: maximal number of frames (up to 3f == 63)\n * @rs_table: array of rates for each TX try, each is rate_n_flags,\n *    meaning it is a combination of IWM_RATE_MCS_* and IWM_RATE_*_PLCP\n * @ss_params: single stream features. declare whether STBC or BFER are allowed.\n */\nstruct iwm_lq_cmd {\n    uint8_t sta_id;\n    uint8_t reduced_tpc;\n    uint16_t control;\n    /* LINK_QUAL_GENERAL_PARAMS_API_S_VER_1 */\n    uint8_t flags;\n    uint8_t mimo_delim;\n    uint8_t single_stream_ant_msk;\n    uint8_t dual_stream_ant_msk;\n    uint8_t initial_rate_index[IWM_AC_NUM];\n    /* LINK_QUAL_AGG_PARAMS_API_S_VER_1 */\n    uint16_t agg_time_limit;\n    uint8_t agg_disable_start_th;\n    uint8_t agg_frame_cnt_limit;\n    uint32_t reserved2;\n    uint32_t rs_table[IWM_LQ_MAX_RETRY_NUM];\n    uint32_t ss_params;\n}; /* LINK_QUALITY_CMD_API_S_VER_1 */\n\n/**\n * bitmasks for tx_flags in TX command\n * @IWM_TX_CMD_FLG_PROT_REQUIRE: use RTS or CTS-to-self to protect the frame\n * @IWM_TX_CMD_FLG_ACK: expect ACK from receiving station\n * @IWM_TX_CMD_FLG_STA_RATE: use RS table with initial index from the TX command.\n *    Otherwise, use rate_n_flags from the TX command\n * @IWM_TX_CMD_FLG_BA: this frame is a block ack\n * @IWM_TX_CMD_FLG_BAR: this frame is a BA request, immediate BAR is expected\n *    Must set IWM_TX_CMD_FLG_ACK with this flag.\n * @IWM_TX_CMD_FLG_TXOP_PROT: protect frame with full TXOP protection\n * @IWM_TX_CMD_FLG_VHT_NDPA: mark frame is NDPA for VHT beamformer sequence\n * @IWM_TX_CMD_FLG_HT_NDPA: mark frame is NDPA for HT beamformer sequence\n * @IWM_TX_CMD_FLG_CSI_FDBK2HOST: mark to send feedback to host (only if good CRC)\n * @IWM_TX_CMD_FLG_BT_DIS: disable BT priority for this frame\n * @IWM_TX_CMD_FLG_SEQ_CTL: set if FW should override the sequence control.\n *    Should be set for mgmt, non-QOS data, mcast, bcast and in scan command\n * @IWM_TX_CMD_FLG_MORE_FRAG: this frame is non-last MPDU\n * @IWM_TX_CMD_FLG_NEXT_FRAME: this frame includes information of the next frame\n * @IWM_TX_CMD_FLG_TSF: FW should calculate and insert TSF in the frame\n *    Should be set for beacons and probe responses\n * @IWM_TX_CMD_FLG_CALIB: activate PA TX power calibrations\n * @IWM_TX_CMD_FLG_KEEP_SEQ_CTL: if seq_ctl is set, don't increase inner seq count\n * @IWM_TX_CMD_FLG_AGG_START: allow this frame to start aggregation\n * @IWM_TX_CMD_FLG_MH_PAD: driver inserted 2 byte padding after MAC header.\n *    Should be set for 26/30 length MAC headers\n * @IWM_TX_CMD_FLG_RESP_TO_DRV: zero this if the response should go only to FW\n * @IWM_TX_CMD_FLG_CCMP_AGG: this frame uses CCMP for aggregation acceleration\n * @IWM_TX_CMD_FLG_TKIP_MIC_DONE: FW already performed TKIP MIC calculation\n * @IWM_TX_CMD_FLG_DUR: disable duration overwriting used in PS-Poll Assoc-id\n * @IWM_TX_CMD_FLG_FW_DROP: FW should mark frame to be dropped\n * @IWM_TX_CMD_FLG_EXEC_PAPD: execute PAPD\n * @IWM_TX_CMD_FLG_PAPD_TYPE: 0 for reference power, 1 for nominal power\n * @IWM_TX_CMD_FLG_HCCA_CHUNK: mark start of TSPEC chunk\n */\n#define IWM_TX_CMD_FLG_PROT_REQUIRE    (1 << 0)\n#define IWM_TX_CMD_FLG_ACK        (1 << 3)\n#define IWM_TX_CMD_FLG_STA_RATE        (1 << 4)\n#define IWM_TX_CMD_FLG_BA        (1 << 5)\n#define IWM_TX_CMD_FLG_BAR        (1 << 6)\n#define IWM_TX_CMD_FLG_TXOP_PROT    (1 << 7)\n#define IWM_TX_CMD_FLG_VHT_NDPA        (1 << 8)\n#define IWM_TX_CMD_FLG_HT_NDPA        (1 << 9)\n#define IWM_TX_CMD_FLG_CSI_FDBK2HOST    (1 << 10)\n#define IWM_TX_CMD_FLG_BT_PRIO_POS      11\n#define IWM_TX_CMD_FLG_BT_DIS        (1 << 12)\n#define IWM_TX_CMD_FLG_SEQ_CTL        (1 << 13)\n#define IWM_TX_CMD_FLG_MORE_FRAG    (1 << 14)\n#define IWM_TX_CMD_FLG_NEXT_FRAME    (1 << 15)\n#define IWM_TX_CMD_FLG_TSF        (1 << 16)\n#define IWM_TX_CMD_FLG_CALIB        (1 << 17)\n#define IWM_TX_CMD_FLG_KEEP_SEQ_CTL    (1 << 18)\n#define IWM_TX_CMD_FLG_AGG_START    (1 << 19)\n#define IWM_TX_CMD_FLG_MH_PAD        (1 << 20)\n#define IWM_TX_CMD_FLG_RESP_TO_DRV    (1 << 21)\n#define IWM_TX_CMD_FLG_CCMP_AGG        (1 << 22)\n#define IWM_TX_CMD_FLG_TKIP_MIC_DONE    (1 << 23)\n#define IWM_TX_CMD_FLG_DUR        (1 << 25)\n#define IWM_TX_CMD_FLG_FW_DROP        (1 << 26)\n#define IWM_TX_CMD_FLG_EXEC_PAPD    (1 << 27)\n#define IWM_TX_CMD_FLG_PAPD_TYPE    (1 << 28)\n#define IWM_TX_CMD_FLG_HCCA_CHUNK    (1U << 31)\n/* IWM_TX_FLAGS_BITS_API_S_VER_1 */\n\n/*\n * TX command security control\n */\n#define IWM_TX_CMD_SEC_WEP        0x01\n#define IWM_TX_CMD_SEC_CCM        0x02\n#define IWM_TX_CMD_SEC_TKIP        0x03\n#define IWM_TX_CMD_SEC_EXT        0x04\n#define IWM_TX_CMD_SEC_MSK        0x07\n#define IWM_TX_CMD_SEC_WEP_KEY_IDX_POS    6\n#define IWM_TX_CMD_SEC_WEP_KEY_IDX_MSK    0xc0\n#define IWM_TX_CMD_SEC_KEY128        0x08\n\n/* TODO: how does these values are OK with only 16 bit variable??? */\n/*\n * TX command next frame info\n *\n * bits 0:2 - security control (IWM_TX_CMD_SEC_*)\n * bit 3 - immediate ACK required\n * bit 4 - rate is taken from STA table\n * bit 5 - frame belongs to BA stream\n * bit 6 - immediate BA response expected\n * bit 7 - unused\n * bits 8:15 - Station ID\n * bits 16:31 - rate\n */\n#define IWM_TX_CMD_NEXT_FRAME_ACK_MSK        (0x8)\n#define IWM_TX_CMD_NEXT_FRAME_STA_RATE_MSK    (0x10)\n#define IWM_TX_CMD_NEXT_FRAME_BA_MSK        (0x20)\n#define IWM_TX_CMD_NEXT_FRAME_IMM_BA_RSP_MSK    (0x40)\n#define IWM_TX_CMD_NEXT_FRAME_FLAGS_MSK        (0xf8)\n#define IWM_TX_CMD_NEXT_FRAME_STA_ID_MSK    (0xff00)\n#define IWM_TX_CMD_NEXT_FRAME_STA_ID_POS    (8)\n#define IWM_TX_CMD_NEXT_FRAME_RATE_MSK        (0xffff0000)\n#define IWM_TX_CMD_NEXT_FRAME_RATE_POS        (16)\n\n/*\n * TX command Frame life time in us - to be written in pm_frame_timeout\n */\n#define IWM_TX_CMD_LIFE_TIME_INFINITE    0xFFFFFFFF\n#define IWM_TX_CMD_LIFE_TIME_DEFAULT    2000000 /* 2000 ms*/\n#define IWM_TX_CMD_LIFE_TIME_PROBE_RESP    40000 /* 40 ms */\n#define IWM_TX_CMD_LIFE_TIME_EXPIRED_FRAME    0\n\n#define RX_REORDER_BUF_TIMEOUT_MQ_USEC (100000ULL)\n\n/*\n * TID for non QoS frames - to be written in tid_tspec\n */\n#define IWM_MAX_TID_COUNT      8\n#define IWM_TID_NON_QOS    0\n#define IWM_TID_MGMT   15\n\n/*\n * Limits on the retransmissions - to be written in {data,rts}_retry_limit\n */\n#define IWM_DEFAULT_TX_RETRY            15\n#define IWM_MGMT_DFAULT_RETRY_LIMIT        3\n#define IWM_RTS_DFAULT_RETRY_LIMIT        3\n#define IWM_BAR_DFAULT_RETRY_LIMIT        60\n#define IWM_LOW_RETRY_LIMIT            7\n\n/**\n * %iwl_tx_cmd offload_assist values\n * @TX_CMD_OFFLD_IP_HDR: offset to start of IP header (in words)\n *    from mac header end. For normal case it is 4 words for SNAP.\n *    note: tx_cmd, mac header and pad are not counted in the offset.\n *    This is used to help the offload in case there is tunneling such as\n *    IPv6 in IPv4, in such case the ip header offset should point to the\n *    inner ip header and IPv4 checksum of the external header should be\n *    calculated by driver.\n * @TX_CMD_OFFLD_L4_EN: enable TCP/UDP checksum\n * @TX_CMD_OFFLD_L3_EN: enable IP header checksum\n * @TX_CMD_OFFLD_MH_SIZE: size of the mac header in words. Includes the IV\n *    field. Doesn't include the pad.\n * @TX_CMD_OFFLD_PAD: mark 2-byte pad was inserted after the mac header for\n *    alignment\n * @TX_CMD_OFFLD_AMSDU: mark TX command is A-MSDU\n */\n#define IWM_TX_CMD_OFFLD_IP_HDR(x)    ((x) << 0)\n#define IWM_TX_CMD_OFFLD_L4_EN        (1 << 6)\n#define IWM_TX_CMD_OFFLD_L3_EN        (1 << 7)\n#define IWM_TX_CMD_OFFLD_MH_SIZE(x)    ((x) << 8)\n#define IWM_TX_CMD_OFFLD_PAD        (1 << 13)\n#define IWM_TX_CMD_OFFLD_AMSDU        (1 << 14)\n#define IWM_TX_CMD_OFFLD_MH_MASK    0x1f\n#define IWM_TX_CMD_OFFLD_IP_HDR_MASK    0x3f\n\n/* TODO: complete documentation for try_cnt and btkill_cnt */\n/**\n * struct iwm_tx_cmd - TX command struct to FW\n * ( IWM_TX_CMD = 0x1c )\n * @len: in bytes of the payload, see below for details\n * @offload_assist: TX offload configuration\n * @tx_flags: combination of IWM_TX_CMD_FLG_*\n * @rate_n_flags: rate for *all* Tx attempts, if IWM_TX_CMD_FLG_STA_RATE_MSK is\n *    cleared. Combination of IWM_RATE_MCS_*\n * @sta_id: index of destination station in FW station table\n * @sec_ctl: security control, IWM_TX_CMD_SEC_*\n * @initial_rate_index: index into the rate table for initial TX attempt.\n *    Applied if IWM_TX_CMD_FLG_STA_RATE_MSK is set, normally 0 for data frames.\n * @key: security key\n * @next_frame_flags: IWM_TX_CMD_SEC_* and IWM_TX_CMD_NEXT_FRAME_*\n * @life_time: frame life time (usecs??)\n * @dram_lsb_ptr: Physical address of scratch area in the command (try_cnt +\n *    btkill_cnd + reserved), first 32 bits. \"0\" disables usage.\n * @dram_msb_ptr: upper bits of the scratch physical address\n * @rts_retry_limit: max attempts for RTS\n * @data_retry_limit: max attempts to send the data packet\n * @tid_spec: TID/tspec\n * @pm_frame_timeout: PM TX frame timeout\n * @driver_txop: duration od EDCA TXOP, in 32-usec units. Set this if not\n *    specified by HCCA protocol\n *\n * The byte count (both len and next_frame_len) includes MAC header\n * (24/26/30/32 bytes)\n * + 2 bytes pad if 26/30 header size\n * + 8 byte IV for CCM or TKIP (not used for WEP)\n * + Data payload\n * + 8-byte MIC (not used for CCM/WEP)\n * It does not include post-MAC padding, i.e.,\n * MIC (CCM) 8 bytes, ICV (WEP/TKIP/CKIP) 4 bytes, CRC 4 bytes.\n * Range of len: 14-2342 bytes.\n *\n * After the struct fields the MAC header is placed, plus any padding,\n * and then the actial payload.\n */\nstruct iwm_tx_cmd {\n    uint16_t len;\n    uint16_t offload_assist;\n    uint32_t tx_flags;\n    struct {\n        uint8_t try_cnt;\n        uint8_t btkill_cnt;\n        uint16_t reserved;\n    } scratch; /* DRAM_SCRATCH_API_U_VER_1 */\n    uint32_t rate_n_flags;\n    uint8_t sta_id;\n    uint8_t sec_ctl;\n    uint8_t initial_rate_index;\n    uint8_t reserved2;\n    uint8_t key[16];\n    uint16_t next_frame_flags;\n    uint16_t reserved3;\n    uint32_t life_time;\n    uint32_t dram_lsb_ptr;\n    uint8_t dram_msb_ptr;\n    uint8_t rts_retry_limit;\n    uint8_t data_retry_limit;\n    uint8_t tid_tspec;\n    uint16_t pm_frame_timeout;\n    uint16_t driver_txop;\n    uint8_t payload[0];\n    struct ieee80211_frame hdr[0];\n} __packed; /* IWM_TX_CMD_API_S_VER_3 */\n\n/* For aggregation queues, index must be aligned to frame sequence number. */\n#define IWM_AGG_SSN_TO_TXQ_IDX(x)    ((x) & (IWM_TX_RING_COUNT - 1))\n\n/*\n * TX response related data\n */\n\n/*\n * status that is returned by the fw after attempts to Tx\n * @IWM_TX_STATUS_FAIL_STA_COLOR_MISMATCH: mismatch between color of Tx cmd and\n *    STA table\n * Valid only if frame_count =1\n */\n#define IWM_TX_STATUS_MSK        0x000000ff\n#define IWM_TX_STATUS_SUCCESS        0x01\n#define IWM_TX_STATUS_DIRECT_DONE    0x02\n/* postpone TX */\n#define IWM_TX_STATUS_POSTPONE_DELAY        0x40\n#define IWM_TX_STATUS_POSTPONE_FEW_BYTES    0x41\n#define IWM_TX_STATUS_POSTPONE_BT_PRIO        0x42\n#define IWM_TX_STATUS_POSTPONE_QUIET_PERIOD    0x43\n#define IWM_TX_STATUS_POSTPONE_CALC_TTAK    0x44\n/* abort TX */\n#define IWM_TX_STATUS_FAIL_INTERNAL_CROSSED_RETRY    0x81\n#define IWM_TX_STATUS_FAIL_SHORT_LIMIT            0x82\n#define IWM_TX_STATUS_FAIL_LONG_LIMIT            0x83\n#define IWM_TX_STATUS_FAIL_UNDERRUN            0x84\n#define IWM_TX_STATUS_FAIL_DRAIN_FLOW            0x85\n#define IWM_TX_STATUS_FAIL_RFKILL_FLUSH            0x86\n#define IWM_TX_STATUS_FAIL_LIFE_EXPIRE            0x87\n#define IWM_TX_STATUS_FAIL_DEST_PS            0x88\n#define IWM_TX_STATUS_FAIL_HOST_ABORTED            0x89\n#define IWM_TX_STATUS_FAIL_BT_RETRY            0x8a\n#define IWM_TX_STATUS_FAIL_STA_INVALID            0x8b\n#define IWM_TX_STATUS_FAIL_FRAG_DROPPED            0x8c\n#define IWM_TX_STATUS_FAIL_TID_DISABLE            0x8d\n#define IWM_TX_STATUS_FAIL_FIFO_FLUSHED            0x8e\n#define IWM_TX_STATUS_FAIL_SMALL_CF_POLL        0x8f\n#define IWM_TX_STATUS_FAIL_FW_DROP            0x90\n#define IWM_TX_STATUS_FAIL_STA_COLOR_MISMATCH        0x91\n#define IWM_TX_STATUS_INTERNAL_ABORT            0x92\n#define IWM_TX_MODE_MSK            0x00000f00\n#define IWM_TX_MODE_NO_BURST        0x00000000\n#define IWM_TX_MODE_IN_BURST_SEQ    0x00000100\n#define IWM_TX_MODE_FIRST_IN_BURST    0x00000200\n#define IWM_TX_QUEUE_NUM_MSK        0x0001f000\n#define IWM_TX_NARROW_BW_MSK        0x00060000\n#define IWM_TX_NARROW_BW_1DIV2        0x00020000\n#define IWM_TX_NARROW_BW_1DIV4        0x00040000\n#define IWM_TX_NARROW_BW_1DIV8        0x00060000\n\n/*\n * TX aggregation status\n * @IWM_AGG_TX_STATE_TRY_CNT_MSK: Retry count for 1st frame in aggregation (retries\n *    occur if tx failed for this frame when it was a member of a previous\n *    aggregation block). If rate scaling is used, retry count indicates the\n *    rate table entry used for all frames in the new agg.\n */\n#define IWM_AGG_TX_STATE_STATUS_MSK        0x0fff\n#define IWM_AGG_TX_STATE_TRANSMITTED        0x0000\n#define IWM_AGG_TX_STATE_UNDERRUN        0x0001\n#define IWM_AGG_TX_STATE_BT_PRIO        0x0002\n#define IWM_AGG_TX_STATE_FEW_BYTES        0x0004\n#define IWM_AGG_TX_STATE_ABORT            0x0008\n#define IWM_AGG_TX_STATE_TX_ON_AIR_DROP        0x0010\n#define IWM_AGG_TX_STATE_LAST_SENT_TRY_CNT    0x0020\n#define IWM_AGG_TX_STATE_LAST_SENT_BT_KILL    0x0040\n#define IWM_AGG_TX_STATE_SCD_QUERY        0x0080\n#define IWM_AGG_TX_STATE_TEST_BAD_CRC32        0x0100\n#define IWM_AGG_TX_STATE_RESPONSE        0x01ff\n#define IWM_AGG_TX_STATE_DUMP_TX        0x0200\n#define IWM_AGG_TX_STATE_DELAY_TX        0x0400\n#define IWM_AGG_TX_STATE_TRY_CNT_POS    12\n#define IWM_AGG_TX_STATE_TRY_CNT_MSK    (0xf << IWM_AGG_TX_STATE_TRY_CNT_POS)\n\n#define IWM_AGG_TX_STATE_LAST_SENT_MSK  (IWM_AGG_TX_STATE_LAST_SENT_TTL| \\\n                     IWM_AGG_TX_STATE_LAST_SENT_TRY_CNT| \\\n                     IWM_AGG_TX_STATE_LAST_SENT_BT_KILL)\n\n/*\n * The mask below describes a status where we are absolutely sure that the MPDU\n * wasn't sent. For BA/Underrun we cannot be that sure. All we know that we've\n * written the bytes to the TXE, but we know nothing about what the DSP did.\n */\n#define IWM_AGG_TX_STAT_FRAME_NOT_SENT (IWM_AGG_TX_STATE_FEW_BYTES | \\\n                    IWM_AGG_TX_STATE_ABORT | \\\n                    IWM_AGG_TX_STATE_SCD_QUERY)\n\n/*\n * IWM_REPLY_TX = 0x1c (response)\n *\n * This response may be in one of two slightly different formats, indicated\n * by the frame_count field:\n *\n * 1)    No aggregation (frame_count == 1).  This reports Tx results for a single\n *    frame. Multiple attempts, at various bit rates, may have been made for\n *    this frame.\n *\n * 2)    Aggregation (frame_count > 1).  This reports Tx results for two or more\n *    frames that used block-acknowledge.  All frames were transmitted at\n *    same rate. Rate scaling may have been used if first frame in this new\n *    agg block failed in previous agg block(s).\n *\n *    Note that, for aggregation, ACK (block-ack) status is not delivered\n *    here; block-ack has not been received by the time the device records\n *    this status.\n *    This status relates to reasons the tx might have been blocked or aborted\n *    within the device, rather than whether it was received successfully by\n *    the destination station.\n */\n\n/**\n * struct iwm_agg_tx_status - per packet TX aggregation status\n * @status: IWM_AGG_TX_STATE_*\n * @idx: Tx queue index of this frame\n * @qid: Tx queue ID of this frame\n */\nstruct iwm_agg_tx_status {\n    uint16_t status;\n    uint8_t idx;\n    uint8_t qid;\n} __packed;\n\n/*\n * definitions for initial rate index field\n * bits [3:0] initial rate index\n * bits [6:4] rate table color, used for the initial rate\n * bit-7 invalid rate indication\n */\n#define IWM_TX_RES_INIT_RATE_INDEX_MSK 0x0f\n#define IWM_TX_RES_RATE_TABLE_COLOR_MSK 0x70\n#define IWM_TX_RES_INV_RATE_INDEX_MSK 0x80\n\n#define IWM_TX_RES_GET_TID(_ra_tid) ((_ra_tid) & 0x0f)\n#define IWM_TX_RES_GET_RA(_ra_tid) ((_ra_tid) >> 4)\n\n/**\n * struct iwm_tx_resp - notifies that fw is TXing a packet\n * ( IWM_REPLY_TX = 0x1c )\n * @frame_count: 1 no aggregation, >1 aggregation\n * @bt_kill_count: num of times blocked by bluetooth (unused for agg)\n * @failure_rts: num of failures due to unsuccessful RTS\n * @failure_frame: num failures due to no ACK (unused for agg)\n * @initial_rate: for non-agg: rate of the successful Tx. For agg: rate of the\n *    Tx of all the batch. IWM_RATE_MCS_*\n * @wireless_media_time: for non-agg: RTS + CTS + frame tx attempts time + ACK.\n *    for agg: RTS + CTS + aggregation tx time + block-ack time.\n *    in usec.\n * @pa_status: tx power info\n * @pa_integ_res_a: tx power info\n * @pa_integ_res_b: tx power info\n * @pa_integ_res_c: tx power info\n * @measurement_req_id: tx power info\n * @tfd_info: TFD information set by the FH\n * @seq_ctl: sequence control field from IEEE80211 frame header\n * @byte_cnt: byte count from the Tx cmd\n * @tlc_info: TLC rate info\n * @ra_tid: bits [3:0] = ra, bits [7:4] = tid\n * @frame_ctrl: frame control\n * @status: for non-agg:  frame status IWM_TX_STATUS_*\n *    for agg: status of 1st frame, IWM_AGG_TX_STATE_*; other frame status fields\n *    follow this one, up to frame_count.\n *\n * After the array of statuses comes the SSN of the SCD. Look at\n * %iwm_get_scd_ssn for more details.\n */\nstruct iwm_tx_resp {\n    uint8_t frame_count;\n    uint8_t bt_kill_count;\n    uint8_t failure_rts;\n    uint8_t failure_frame;\n    uint32_t initial_rate;\n    uint16_t wireless_media_time;\n\n    uint8_t pa_status;\n    uint8_t pa_integ_res_a[3];\n    uint8_t pa_integ_res_b[3];\n    uint8_t pa_integ_res_c[3];\n    uint16_t measurement_req_id;\n    uint8_t reduced_tpc;\n    uint8_t reserved;\n\n    uint32_t tfd_info;\n    uint16_t seq_ctl;\n    uint16_t byte_cnt;\n    uint8_t tlc_info;\n    uint8_t ra_tid;\n    uint16_t frame_ctrl;\n    struct iwm_agg_tx_status status[];\n} __packed; /* IWM_TX_RSP_API_S_VER_3 */\n\n/**\n * struct iwm_ba_notif - notifies about reception of BA\n * ( IWM_BA_NOTIF = 0xc5 )\n * @sta_addr: MAC address\n * @sta_id: Index of recipient (BA-sending) station in fw's station table\n * @tid: tid of the session\n * @seq_ctl: sequence control field from IEEE80211 frame header (the first\n * bit in @bitmap corresponds to the sequence number stored here)\n * @bitmap: the bitmap of the BA notification as seen in the air\n * @scd_flow: the tx queue this BA relates to\n * @scd_ssn: the index of the last contiguously sent packet\n * @txed: number of Txed frames in this batch\n * @txed_2_done: number of Acked frames in this batch\n * @reduced_txp: power reduced according to TPC. This is the actual value and\n *     not a copy from the LQ command. Thus, if not the first rate was used\n *     for Tx-ing then this value will be set to 0 by FW.\n * @reserved1: reserved\n */\nstruct iwm_ba_notif {\n    uint8_t sta_addr[ETHER_ADDR_LEN];\n    uint16_t reserved;\n\n    uint8_t sta_id;\n    uint8_t tid;\n    uint16_t seq_ctl;\n    uint64_t bitmap;\n    uint16_t scd_flow;\n    uint16_t scd_ssn;\n    uint8_t txed;\n    uint8_t txed_2_done;\n    uint8_t reduced_txp;\n    uint8_t reserved1;\n} __packed;\n\n/*\n * struct iwm_mac_beacon_cmd - beacon template command\n * @tx: the tx commands associated with the beacon frame\n * @template_id: currently equal to the mac context id of the coresponding\n *  mac.\n * @tim_idx: the offset of the tim IE in the beacon\n * @tim_size: the length of the tim IE\n * @frame: the template of the beacon frame\n */\nstruct iwm_mac_beacon_cmd {\n    struct iwm_tx_cmd tx;\n    uint32_t template_id;\n    uint32_t tim_idx;\n    uint32_t tim_size;\n    struct ieee80211_frame frame[0];\n} __packed;\n\nstruct iwm_beacon_notif {\n    struct iwm_tx_resp beacon_notify_hdr;\n    uint64_t tsf;\n    uint32_t ibss_mgr_status;\n} __packed;\n\n/**\n * dump (flush) control flags\n * @IWM_DUMP_TX_FIFO_FLUSH: Dump MSDUs until the FIFO is empty\n *    and the TFD queues are empty.\n */\n#define IWM_DUMP_TX_FIFO_FLUSH    (1 << 1)\n\n/**\n * struct iwm_tx_path_flush_cmd -- queue/FIFO flush command\n * @queues_ctl: bitmap of queues to flush\n * @flush_ctl: control flags\n * @reserved: reserved\n */\nstruct iwm_tx_path_flush_cmd_v1 {\n    uint32_t queues_ctl;\n    uint16_t flush_ctl;\n    uint16_t reserved;\n} __packed; /* IWM_TX_PATH_FLUSH_CMD_API_S_VER_1 */\n\n/**\n * struct iwl_tx_path_flush_cmd -- queue/FIFO flush command\n * @sta_id: station ID to flush\n * @tid_mask: TID mask to flush\n * @reserved: reserved\n */\nstruct iwm_tx_path_flush_cmd {\n    uint32_t sta_id;\n    uint16_t tid_mask;\n    uint16_t reserved;\n} __packed; /* TX_PATH_FLUSH_CMD_API_S_VER_2 */\n\n/**\n * iwm_get_scd_ssn - returns the SSN of the SCD\n * @tx_resp: the Tx response from the fw (agg or non-agg)\n *\n * When the fw sends an AMPDU, it fetches the MPDUs one after the other. Since\n * it can't know that everything will go well until the end of the AMPDU, it\n * can't know in advance the number of MPDUs that will be sent in the current\n * batch. This is why it writes the agg Tx response while it fetches the MPDUs.\n * Hence, it can't know in advance what the SSN of the SCD will be at the end\n * of the batch. This is why the SSN of the SCD is written at the end of the\n * whole struct at a variable offset. This function knows how to cope with the\n * variable offset and returns the SSN of the SCD.\n */\nstatic inline uint32_t iwm_get_scd_ssn(struct iwm_tx_resp *tx_resp)\n{\n    return le32_to_cpup((uint32_t *)&tx_resp->status +\n                tx_resp->frame_count) & 0xfff;\n}\n\n/**\n * struct iwm_scd_txq_cfg_cmd - New txq hw scheduler config command\n * @token:\n * @sta_id: station id\n * @tid:\n * @scd_queue: scheduler queue to confiug\n * @enable: 1 queue enable, 0 queue disable\n * @aggregate: 1 aggregated queue, 0 otherwise\n * @tx_fifo: %enum iwm_tx_fifo\n * @window: BA window size\n * @ssn: SSN for the BA agreement\n */\nstruct iwm_scd_txq_cfg_cmd {\n    uint8_t token;\n    uint8_t sta_id;\n    uint8_t tid;\n    uint8_t scd_queue;\n    uint8_t enable;\n    uint8_t aggregate;\n    uint8_t tx_fifo;\n    uint8_t window;\n    uint16_t ssn;\n    uint16_t reserved;\n} __packed; /* SCD_QUEUE_CFG_CMD_API_S_VER_1 */\n\n/**\n * struct iwm_scd_txq_cfg_rsp\n * @token: taken from the command\n * @sta_id: station id from the command\n * @tid: tid from the command\n * @scd_queue: scd_queue from the command\n */\nstruct iwm_scd_txq_cfg_rsp {\n    uint8_t token;\n    uint8_t sta_id;\n    uint8_t tid;\n    uint8_t scd_queue;\n} __packed; /* SCD_QUEUE_CFG_RSP_API_S_VER_1 */\n\nstruct iwm_txq_scd_cfg {\n    uint8_t fifo;\n    uint8_t sta_id;\n    uint8_t tid;\n    bool aggregate;\n    int frame_limit;\n};\n\nconst uint8_t tid_to_mac80211_ac[] = {\n    EDCA_AC_BE,\n    EDCA_AC_BK,\n    EDCA_AC_BK,\n    EDCA_AC_BE,\n    EDCA_AC_VI,\n    EDCA_AC_VI,\n    EDCA_AC_VO,\n    EDCA_AC_VO,\n    EDCA_AC_VO, /* We treat MGMT as TID 8, which is set as AC_VO */\n};\n\n/* Scan Commands, Responses, Notifications */\n\n/* Max number of IEs for direct SSID scans in a command */\n#define IWM_PROBE_OPTION_MAX        20\n\n/**\n * struct iwm_ssid_ie - directed scan network information element\n *\n * Up to 20 of these may appear in IWM_REPLY_SCAN_CMD,\n * selected by \"type\" bit field in struct iwm_scan_channel;\n * each channel may select different ssids from among the 20 entries.\n * SSID IEs get transmitted in reverse order of entry.\n */\nstruct iwm_ssid_ie {\n    uint8_t id;\n    uint8_t len;\n    uint8_t ssid[IEEE80211_NWID_LEN];\n} __packed; /* IWM_SCAN_DIRECT_SSID_IE_API_S_VER_1 */\n\n/* scan offload */\n#define IWM_SCAN_MAX_BLACKLIST_LEN    64\n#define IWM_SCAN_SHORT_BLACKLIST_LEN    16\n#define IWM_SCAN_MAX_PROFILES        11\n#define IWM_SCAN_OFFLOAD_PROBE_REQ_SIZE    512\n\n/* Default watchdog (in MS) for scheduled scan iteration */\n#define IWM_SCHED_SCAN_WATCHDOG cpu_to_le16(15000)\n\n#define IWM_GOOD_CRC_TH_DEFAULT cpu_to_le16(1)\n#define IWM_CAN_ABORT_STATUS 1\n\n#define IWM_FULL_SCAN_MULTIPLIER 5\n#define IWM_FAST_SCHED_SCAN_ITERATIONS 3\n#define IWM_MAX_SCHED_SCAN_PLANS 2\n\n/**\n * iwm_scan_schedule_lmac - schedule of scan offload\n * @delay:        delay between iterations, in seconds.\n * @iterations:        num of scan iterations\n * @full_scan_mul:    number of partial scans before each full scan\n */\nstruct iwm_scan_schedule_lmac {\n    uint16_t delay;\n    uint8_t iterations;\n    uint8_t full_scan_mul;\n} __packed; /* SCAN_SCHEDULE_API_S */\n\n/**\n * iwm_scan_req_tx_cmd - SCAN_REQ_TX_CMD_API_S\n * @tx_flags: combination of TX_CMD_FLG_*\n * @rate_n_flags: rate for *all* Tx attempts, if TX_CMD_FLG_STA_RATE_MSK is\n *    cleared. Combination of RATE_MCS_*\n * @sta_id: index of destination station in FW station table\n * @reserved: for alignment and future use\n */\nstruct iwm_scan_req_tx_cmd {\n    uint32_t tx_flags;\n    uint32_t rate_n_flags;\n    uint8_t sta_id;\n    uint8_t reserved[3];\n} __packed;\n\n#define IWM_UNIFIED_SCAN_CHANNEL_FULL        (1 << 27)\n#define IWM_UNIFIED_SCAN_CHANNEL_PARTIAL    (1 << 28)\n\n/**\n * iwm_scan_channel_cfg_lmac - SCAN_CHANNEL_CFG_S_VER2\n * @flags:        bits 1-20: directed scan to i'th ssid\n *            other bits &enum iwm_scan_channel_flags_lmac\n * @channel_number:    channel number 1-13 etc\n * @iter_count:        scan iteration on this channel\n * @iter_interval:    interval in seconds between iterations on one channel\n */\nstruct iwm_scan_channel_cfg_lmac {\n    uint32_t flags;\n    uint16_t channel_num;\n    uint16_t iter_count;\n    uint32_t iter_interval;\n} __packed;\n\n/*\n * iwm_scan_probe_segment - PROBE_SEGMENT_API_S_VER_1\n * @offset: offset in the data block\n * @len: length of the segment\n */\nstruct iwm_scan_probe_segment {\n    uint16_t offset;\n    uint16_t len;\n} __packed;\n\n/* iwm_scan_probe_req - PROBE_REQUEST_FRAME_API_S_VER_2\n * @mac_header: first (and common) part of the probe\n * @band_data: band specific data\n * @common_data: last (and common) part of the probe\n * @buf: raw data block\n */\nstruct iwm_scan_probe_req_v1 {\n    struct iwm_scan_probe_segment mac_header;\n    struct iwm_scan_probe_segment band_data[2];\n    struct iwm_scan_probe_segment common_data;\n    uint8_t buf[IWM_SCAN_OFFLOAD_PROBE_REQ_SIZE];\n} __packed;\n\n/* iwl_scan_probe_req - PROBE_REQUEST_FRAME_API_S_VER_v2\n * @mac_header: first (and common) part of the probe\n * @band_data: band specific data\n * @common_data: last (and common) part of the probe\n * @buf: raw data block\n */\nstruct iwm_scan_probe_req {\n    struct iwm_scan_probe_segment mac_header;\n    struct iwm_scan_probe_segment band_data[3];\n    struct iwm_scan_probe_segment common_data;\n    uint8_t buf[IWM_SCAN_OFFLOAD_PROBE_REQ_SIZE];\n} __packed;\n\n\n#define IWM_SCAN_CHANNEL_FLAG_EBS        (1 << 0)\n#define IWM_SCAN_CHANNEL_FLAG_EBS_ACCURATE    (1 << 1)\n#define IWM_SCAN_CHANNEL_FLAG_CACHE_ADD        (1 << 2)\n\n/* iwm_scan_channel_opt - CHANNEL_OPTIMIZATION_API_S\n * @flags: enum iwm_scan_channel_flags\n * @non_ebs_ratio: defines the ratio of number of scan iterations where EBS is\n *    involved.\n *    1 - EBS is disabled.\n *    2 - every second scan will be full scan(and so on).\n */\nstruct iwm_scan_channel_opt {\n    uint16_t flags;\n    uint16_t non_ebs_ratio;\n} __packed;\n\n/**\n * LMAC scan flags\n * @IWM_LMAC_SCAN_FLAG_PASS_ALL: pass all beacons and probe responses\n *      without filtering.\n * @IWM_LMAC_SCAN_FLAG_PASSIVE: force passive scan on all channels\n * @IWM_LMAC_SCAN_FLAG_PRE_CONNECTION: single channel scan\n * @IWM_LMAC_SCAN_FLAG_ITER_COMPLETE: send iteration complete notification\n * @IWM_LMAC_SCAN_FLAG_MULTIPLE_SSIDS multiple SSID matching\n * @IWM_LMAC_SCAN_FLAG_FRAGMENTED: all passive scans will be fragmented\n * @IWM_LMAC_SCAN_FLAGS_RRM_ENABLED: insert WFA vendor-specific TPC report\n *      and DS parameter set IEs into probe requests.\n * @IWM_LMAC_SCAN_FLAG_EXTENDED_DWELL: use extended dwell time on channels\n *      1, 6 and 11.\n * @IWM_LMAC_SCAN_FLAG_MATCH: Send match found notification on matches\n */\n#define IWM_LMAC_SCAN_FLAG_PASS_ALL        (1 << 0)\n#define IWM_LMAC_SCAN_FLAG_PASSIVE        (1 << 1)\n#define IWM_LMAC_SCAN_FLAG_PRE_CONNECTION    (1 << 2)\n#define IWM_LMAC_SCAN_FLAG_ITER_COMPLETE    (1 << 3)\n#define IWM_LMAC_SCAN_FLAG_MULTIPLE_SSIDS    (1 << 4)\n#define IWM_LMAC_SCAN_FLAG_FRAGMENTED    (1 << 5)\n#define IWM_LMAC_SCAN_FLAGS_RRM_ENABLED    (1 << 6)\n#define IWM_LMAC_SCAN_FLAG_EXTENDED_DWELL    (1 << 7)\n#define IWM_LMAC_SCAN_FLAG_MATCH        (1 << 9)\n\n#define IWM_SCAN_PRIORITY_LOW        0\n#define IWM_SCAN_PRIORITY_MEDIUM    1\n#define IWM_SCAN_PRIORITY_HIGH        2\n\n/**\n * iwm_scan_req_lmac - SCAN_REQUEST_CMD_API_S_VER_1\n * @reserved1: for alignment and future use\n * @channel_num: num of channels to scan\n * @active-dwell: dwell time for active channels\n * @passive-dwell: dwell time for passive channels\n * @fragmented-dwell: dwell time for fragmented passive scan\n * @extended_dwell: dwell time for channels 1, 6 and 11 (in certain cases)\n * @reserved2: for alignment and future use\n * @rx_chain_selct: PHY_RX_CHAIN_* flags\n * @scan_flags: &enum iwm_lmac_scan_flags\n * @max_out_time: max time (in TU) to be out of associated channel\n * @suspend_time: pause scan this long (TUs) when returning to service channel\n * @flags: RXON flags\n * @filter_flags: RXON filter\n * @tx_cmd: tx command for active scan; for 2GHz and for 5GHz\n * @direct_scan: list of SSIDs for directed active scan\n * @scan_prio: enum iwm_scan_priority\n * @iter_num: number of scan iterations\n * @delay: delay in seconds before first iteration\n * @schedule: two scheduling plans. The first one is finite, the second one can\n *    be infinite.\n * @channel_opt: channel optimization options, for full and partial scan\n * @data: channel configuration and probe request packet.\n */\nstruct iwm_scan_req_lmac {\n    /* SCAN_REQUEST_FIXED_PART_API_S_VER_7 */\n    uint32_t reserved1;\n    uint8_t n_channels;\n    uint8_t active_dwell;\n    uint8_t passive_dwell;\n    uint8_t fragmented_dwell;\n    uint8_t extended_dwell;\n    uint8_t reserved2;\n    uint16_t rx_chain_select;\n    uint32_t scan_flags;\n    uint32_t max_out_time;\n    uint32_t suspend_time;\n    /* RX_ON_FLAGS_API_S_VER_1 */\n    uint32_t flags;\n    uint32_t filter_flags;\n    struct iwm_scan_req_tx_cmd tx_cmd[2];\n    struct iwm_ssid_ie direct_scan[IWM_PROBE_OPTION_MAX];\n    uint32_t scan_prio;\n    /* SCAN_REQ_PERIODIC_PARAMS_API_S */\n    uint32_t iter_num;\n    uint32_t delay;\n    struct iwm_scan_schedule_lmac schedule[IWM_MAX_SCHED_SCAN_PLANS];\n    struct iwm_scan_channel_opt channel_opt[2];\n    uint8_t data[];\n} __packed;\n\n/**\n * iwm_scan_offload_complete - PERIODIC_SCAN_COMPLETE_NTF_API_S_VER_2\n * @last_schedule_line: last schedule line executed (fast or regular)\n * @last_schedule_iteration: last scan iteration executed before scan abort\n * @status: enum iwm_scan_offload_complete_status\n * @ebs_status: EBS success status &enum iwm_scan_ebs_status\n * @time_after_last_iter; time in seconds elapsed after last iteration\n */\nstruct iwm_periodic_scan_complete {\n    uint8_t last_schedule_line;\n    uint8_t last_schedule_iteration;\n    uint8_t status;\n    uint8_t ebs_status;\n    uint32_t time_after_last_iter;\n    uint32_t reserved;\n} __packed;\n\n/**\n * struct iwm_scan_results_notif - scan results for one channel -\n *      SCAN_RESULT_NTF_API_S_VER_3\n * @channel: which channel the results are from\n * @band: 0 for 5.2 GHz, 1 for 2.4 GHz\n * @probe_status: IWM_SCAN_PROBE_STATUS_*, indicates success of probe request\n * @num_probe_not_sent: # of request that weren't sent due to not enough time\n * @duration: duration spent in channel, in usecs\n */\nstruct iwm_scan_results_notif {\n    uint8_t channel;\n    uint8_t band;\n    uint8_t probe_status;\n    uint8_t num_probe_not_sent;\n    uint32_t duration;\n} __packed;\n\n#define IWM_SCAN_CLIENT_SCHED_SCAN        (1 << 0)\n#define IWM_SCAN_CLIENT_NETDETECT        (1 << 1)\n#define IWM_SCAN_CLIENT_ASSET_TRACKING        (1 << 2)\n\n/**\n * iwm_scan_offload_blacklist - IWM_SCAN_OFFLOAD_BLACKLIST_S\n * @ssid:        MAC address to filter out\n * @reported_rssi:    AP rssi reported to the host\n * @client_bitmap: clients ignore this entry  - enum scan_framework_client\n */\nstruct iwm_scan_offload_blacklist {\n    uint8_t ssid[ETHER_ADDR_LEN];\n    uint8_t reported_rssi;\n    uint8_t client_bitmap;\n} __packed;\n\n#define IWM_NETWORK_TYPE_BSS    1\n#define IWM_NETWORK_TYPE_IBSS    2\n#define IWM_NETWORK_TYPE_ANY    3\n\n#define IWM_SCAN_OFFLOAD_SELECT_2_4    0x4\n#define IWM_SCAN_OFFLOAD_SELECT_5_2    0x8\n#define IWM_SCAN_OFFLOAD_SELECT_ANY    0xc\n\n/**\n * iwm_scan_offload_profile - IWM_SCAN_OFFLOAD_PROFILE_S\n * @ssid_index:        index to ssid list in fixed part\n * @unicast_cipher:    encryption olgorithm to match - bitmap\n * @aut_alg:        authentication olgorithm to match - bitmap\n * @network_type:    enum iwm_scan_offload_network_type\n * @band_selection:    enum iwm_scan_offload_band_selection\n * @client_bitmap:    clients waiting for match - enum scan_framework_client\n */\nstruct iwm_scan_offload_profile {\n    uint8_t ssid_index;\n    uint8_t unicast_cipher;\n    uint8_t auth_alg;\n    uint8_t network_type;\n    uint8_t band_selection;\n    uint8_t client_bitmap;\n    uint8_t reserved[2];\n} __packed;\n\n/**\n * iwm_scan_offload_profile_cfg - IWM_SCAN_OFFLOAD_PROFILES_CFG_API_S_VER_1\n * @blaclist:        AP list to filter off from scan results\n * @profiles:        profiles to search for match\n * @blacklist_len:    length of blacklist\n * @num_profiles:    num of profiles in the list\n * @match_notify:    clients waiting for match found notification\n * @pass_match:        clients waiting for the results\n * @active_clients:    active clients bitmap - enum scan_framework_client\n * @any_beacon_notify:    clients waiting for match notification without match\n */\nstruct iwm_scan_offload_profile_cfg {\n    struct iwm_scan_offload_profile profiles[IWM_SCAN_MAX_PROFILES];\n    uint8_t blacklist_len;\n    uint8_t num_profiles;\n    uint8_t match_notify;\n    uint8_t pass_match;\n    uint8_t active_clients;\n    uint8_t any_beacon_notify;\n    uint8_t reserved[2];\n} __packed;\n\n#define IWM_SCAN_OFFLOAD_COMPLETED    1\n#define IWM_SCAN_OFFLOAD_ABORTED    2\n\n/**\n * struct iwm_lmac_scan_complete_notif - notifies end of scanning (all channels)\n *    SCAN_COMPLETE_NTF_API_S_VER_3\n * @scanned_channels: number of channels scanned (and number of valid results)\n * @status: one of SCAN_COMP_STATUS_*\n * @bt_status: BT on/off status\n * @last_channel: last channel that was scanned\n * @tsf_low: TSF timer (lower half) in usecs\n * @tsf_high: TSF timer (higher half) in usecs\n * @results: an array of scan results, only \"scanned_channels\" of them are valid\n */\nstruct iwm_lmac_scan_complete_notif {\n    uint8_t scanned_channels;\n    uint8_t status;\n    uint8_t bt_status;\n    uint8_t last_channel;\n    uint32_t tsf_low;\n    uint32_t tsf_high;\n    struct iwm_scan_results_notif results[];\n} __packed;\n\n\n/* UMAC Scan API */\n\n/* The maximum of either of these cannot exceed 8, because we use an\n * 8-bit mask (see IWM_SCAN_MASK).\n */\n#define IWM_MAX_UMAC_SCANS 8\n#define IWM_MAX_LMAC_SCANS 1\n\n#define IWM_SCAN_CONFIG_FLAG_ACTIVATE            (1 << 0)\n#define IWM_SCAN_CONFIG_FLAG_DEACTIVATE            (1 << 1)\n#define IWM_SCAN_CONFIG_FLAG_FORBID_CHUB_REQS        (1 << 2)\n#define IWM_SCAN_CONFIG_FLAG_ALLOW_CHUB_REQS        (1 << 3)\n#define IWM_SCAN_CONFIG_FLAG_SET_TX_CHAINS        (1 << 8)\n#define IWM_SCAN_CONFIG_FLAG_SET_RX_CHAINS        (1 << 9)\n#define IWM_SCAN_CONFIG_FLAG_SET_AUX_STA_ID        (1 << 10)\n#define IWM_SCAN_CONFIG_FLAG_SET_ALL_TIMES        (1 << 11)\n#define IWM_SCAN_CONFIG_FLAG_SET_EFFECTIVE_TIMES    (1 << 12)\n#define IWM_SCAN_CONFIG_FLAG_SET_CHANNEL_FLAGS        (1 << 13)\n#define IWM_SCAN_CONFIG_FLAG_SET_LEGACY_RATES        (1 << 14)\n#define IWM_SCAN_CONFIG_FLAG_SET_MAC_ADDR        (1 << 15)\n#define IWM_SCAN_CONFIG_FLAG_SET_FRAGMENTED        (1 << 16)\n#define IWM_SCAN_CONFIG_FLAG_CLEAR_FRAGMENTED        (1 << 17)\n#define IWM_SCAN_CONFIG_FLAG_SET_CAM_MODE        (1 << 18)\n#define IWM_SCAN_CONFIG_FLAG_CLEAR_CAM_MODE        (1 << 19)\n#define IWM_SCAN_CONFIG_FLAG_SET_PROMISC_MODE        (1 << 20)\n#define IWM_SCAN_CONFIG_FLAG_CLEAR_PROMISC_MODE        (1 << 21)\n\n/* Bits 26-31 are for num of channels in channel_array */\n#define IWM_SCAN_CONFIG_N_CHANNELS(n) ((n) << 26)\n\n/* OFDM basic rates */\n#define IWM_SCAN_CONFIG_RATE_6M        (1 << 0)\n#define IWM_SCAN_CONFIG_RATE_9M        (1 << 1)\n#define IWM_SCAN_CONFIG_RATE_12M    (1 << 2)\n#define IWM_SCAN_CONFIG_RATE_18M    (1 << 3)\n#define IWM_SCAN_CONFIG_RATE_24M    (1 << 4)\n#define IWM_SCAN_CONFIG_RATE_36M    (1 << 5)\n#define IWM_SCAN_CONFIG_RATE_48M    (1 << 6)\n#define IWM_SCAN_CONFIG_RATE_54M    (1 << 7)\n/* CCK basic rates */\n#define IWM_SCAN_CONFIG_RATE_1M        (1 << 8)\n#define IWM_SCAN_CONFIG_RATE_2M        (1 << 9)\n#define IWM_SCAN_CONFIG_RATE_5M        (1 << 10)\n#define IWM_SCAN_CONFIG_RATE_11M    (1 << 11)\n\n/* Bits 16-27 are for supported rates */\n#define IWM_SCAN_CONFIG_SUPPORTED_RATE(rate)    ((rate) << 16)\n\n#define IWM_CHANNEL_FLAG_EBS                (1 << 0)\n#define IWM_CHANNEL_FLAG_ACCURATE_EBS            (1 << 1)\n#define IWM_CHANNEL_FLAG_EBS_ADD            (1 << 2)\n#define IWM_CHANNEL_FLAG_PRE_SCAN_PASSIVE2ACTIVE    (1 << 3)\n\n/**\n * struct iwm_scan_config\n * @flags:            enum scan_config_flags\n * @tx_chains:            valid_tx antenna - ANT_* definitions\n * @rx_chains:            valid_rx antenna - ANT_* definitions\n * @legacy_rates:        default legacy rates - enum scan_config_rates\n * @out_of_channel_time:    default max out of serving channel time\n * @suspend_time:        default max suspend time\n * @dwell_active:        default dwell time for active scan\n * @dwell_passive:        default dwell time for passive scan\n * @dwell_fragmented:        default dwell time for fragmented scan\n * @dwell_extended:        default dwell time for channels 1, 6 and 11\n * @mac_addr:            default mac address to be used in probes\n * @bcast_sta_id:        the index of the station in the fw\n * @channel_flags:        default channel flags - enum iwm_channel_flags\n *                scan_config_channel_flag\n * @channel_array:        default supported channels\n */\nstruct iwm_scan_config {\n    uint32_t flags;\n    uint32_t tx_chains;\n    uint32_t rx_chains;\n    uint32_t legacy_rates;\n    uint32_t out_of_channel_time;\n    uint32_t suspend_time;\n    uint8_t dwell_active;\n    uint8_t dwell_passive;\n    uint8_t dwell_fragmented;\n    uint8_t dwell_extended;\n    uint8_t mac_addr[ETHER_ADDR_LEN];\n    uint8_t bcast_sta_id;\n    uint8_t channel_flags;\n    uint8_t channel_array[];\n} __packed; /* SCAN_CONFIG_DB_CMD_API_S */\n\n/**\n * iwm_umac_scan_flags\n *@IWM_UMAC_SCAN_FLAG_PREEMPTIVE: scan process triggered by this scan request\n *    can be preempted by other scan requests with higher priority.\n *    The low priority scan will be resumed when the higher proirity scan is\n *    completed.\n *@IWM_UMAC_SCAN_FLAG_START_NOTIF: notification will be sent to the driver\n *    when scan starts.\n */\n#define IWM_UMAC_SCAN_FLAG_PREEMPTIVE        (1 << 0)\n#define IWM_UMAC_SCAN_FLAG_START_NOTIF        (1 << 1)\n\n#define IWM_UMAC_SCAN_UID_TYPE_OFFSET        0\n#define IWM_UMAC_SCAN_UID_SEQ_OFFSET        8\n\n#define IWM_UMAC_SCAN_GEN_FLAGS_PERIODIC    (1 << 0)\n#define IWM_UMAC_SCAN_GEN_FLAGS_OVER_BT        (1 << 1)\n#define IWM_UMAC_SCAN_GEN_FLAGS_PASS_ALL    (1 << 2)\n#define IWM_UMAC_SCAN_GEN_FLAGS_PASSIVE        (1 << 3)\n#define IWM_UMAC_SCAN_GEN_FLAGS_PRE_CONNECT    (1 << 4)\n#define IWM_UMAC_SCAN_GEN_FLAGS_ITER_COMPLETE    (1 << 5)\n#define IWM_UMAC_SCAN_GEN_FLAGS_MULTIPLE_SSID    (1 << 6)\n#define IWM_UMAC_SCAN_GEN_FLAGS_FRAGMENTED    (1 << 7)\n#define IWM_UMAC_SCAN_GEN_FLAGS_RRM_ENABLED    (1 << 8)\n#define IWM_UMAC_SCAN_GEN_FLAGS_MATCH        (1 << 9)\n#define IWM_UMAC_SCAN_GEN_FLAGS_EXTENDED_DWELL    (1 << 10)\n/* Extended dwell is obselete when adaptive dwell is used, making this\n * bit reusable. Hence, probe request defer is used only when adaptive\n * dwell is supported. */\n#define IWM_UMAC_SCAN_GEN_FLAGS_PROB_REQ_DEFER_SUPP    (1 << 10)\n#define IWM_UMAC_SCAN_GEN_FLAGS_LMAC2_FRAGMENTED    (1 << 11)\n#define IWM_UMAC_SCAN_GEN_FLAGS_ADAPTIVE_DWELL        (1 << 13)\n#define IWM_UMAC_SCAN_GEN_FLAGS_MAX_CHNL_TIME        (1 << 14)\n#define IWM_UMAC_SCAN_GEN_FLAGS_PROB_REQ_HIGH_TX_RATE    (1 << 15)\n\n/**\n * UMAC scan general flags #2\n * @IWM_UMAC_SCAN_GEN_FLAGS2_NOTIF_PER_CHNL: Whether to send a complete\n *    notification per channel or not.\n * @IWM_UMAC_SCAN_GEN_FLAGS2_ALLOW_CHNL_REORDER: Whether to allow channel\n *    reorder optimization or not.\n */\n#define IWM_UMAC_SCAN_GEN_FLAGS2_NOTIF_PER_CHNL        (1 << 0)\n#define IWM_UMAC_SCAN_GEN_FLAGS2_ALLOW_CHNL_REORDER    (1 << 1)\n\n/**\n * struct iwm_scan_channel_cfg_umac\n * @flags:        bitmap - 0-19:    directed scan to i'th ssid.\n * @channel_num:    channel number 1-13 etc.\n * @iter_count:        repetition count for the channel.\n * @iter_interval:    interval between two scan iterations on one channel.\n */\nstruct iwm_scan_channel_cfg_umac {\n    uint32_t flags;\n    uint8_t channel_num;\n    uint8_t iter_count;\n    uint16_t iter_interval;\n} __packed; /* SCAN_CHANNEL_CFG_S_VER1 */\n\n/**\n * struct iwm_scan_umac_schedule\n * @interval: interval in seconds between scan iterations\n * @iter_count: num of scan iterations for schedule plan, 0xff for infinite loop\n * @reserved: for alignment and future use\n */\nstruct iwm_scan_umac_schedule {\n    uint16_t interval;\n    uint8_t iter_count;\n    uint8_t reserved;\n} __packed; /* SCAN_SCHED_PARAM_API_S_VER_1 */\n\n/**\n * struct iwm_scan_req_umac_tail - the rest of the UMAC scan request command\n *      parameters following channels configuration array.\n * @schedule: two scheduling plans.\n * @delay: delay in TUs before starting the first scan iteration\n * @reserved: for future use and alignment\n * @preq: probe request with IEs blocks\n * @direct_scan: list of SSIDs for directed active scan\n */\nstruct iwm_scan_req_umac_tail_v1 {\n    /* SCAN_PERIODIC_PARAMS_API_S_VER_1 */\n    struct iwm_scan_umac_schedule schedule[IWM_MAX_SCHED_SCAN_PLANS];\n    uint16_t delay;\n    uint16_t reserved;\n    /* SCAN_PROBE_PARAMS_API_S_VER_1 */\n    struct iwm_scan_probe_req_v1 preq;\n    struct iwm_ssid_ie direct_scan[IWM_PROBE_OPTION_MAX];\n} __packed;\n\n/**\n * struct iwm_scan_req_umac_tail - the rest of the UMAC scan request command\n *      parameters following channels configuration array.\n * @schedule: two scheduling plans.\n * @delay: delay in TUs before starting the first scan iteration\n * @reserved: for future use and alignment\n * @preq: probe request with IEs blocks\n * @direct_scan: list of SSIDs for directed active scan\n */\nstruct iwm_scan_req_umac_tail_v2 {\n    /* SCAN_PERIODIC_PARAMS_API_S_VER_1 */\n    struct iwm_scan_umac_schedule schedule[IWM_MAX_SCHED_SCAN_PLANS];\n    uint16_t delay;\n    uint16_t reserved;\n    /* SCAN_PROBE_PARAMS_API_S_VER_2 */\n    struct iwm_scan_probe_req preq;\n    struct iwm_ssid_ie direct_scan[IWM_PROBE_OPTION_MAX];\n} __packed;\n\n/**\n * struct iwm_scan_umac_chan_param\n * @flags: channel flags &enum iwl_scan_channel_flags\n * @count: num of channels in scan request\n * @reserved: for future use and alignment\n */\nstruct iwm_scan_umac_chan_param {\n    uint8_t flags;\n    uint8_t count;\n    uint16_t reserved;\n} __packed; /* SCAN_CHANNEL_PARAMS_API_S_VER_1 */\n\n#define IWM_SCAN_LB_LMAC_IDX 0\n#define IWM_SCAN_HB_LMAC_IDX 1\n\n/**\n * struct iwm_scan_req_umac\n * @flags: &enum iwl_umac_scan_flags\n * @uid: scan id, &enum iwl_umac_scan_uid_offsets\n * @ooc_priority: out of channel priority - &enum iwl_scan_priority\n * @general_flags: &enum iwl_umac_scan_general_flags\n * @scan_start_mac_id: report the scan start TSF time according to this mac TSF\n * @extended_dwell: dwell time for channels 1, 6 and 11\n * @active_dwell: dwell time for active scan per LMAC\n * @passive_dwell: dwell time for passive scan per LMAC\n * @fragmented_dwell: dwell time for fragmented passive scan\n * @adwell_default_n_aps: for adaptive dwell the default number of APs\n *    per channel\n * @adwell_default_n_aps_social: for adaptive dwell the default\n *    number of APs per social (1,6,11) channel\n * @general_flags2: &enum iwl_umac_scan_general_flags2\n * @adwell_max_budget: for adaptive dwell the maximal budget of TU to be added\n *    to total scan time\n * @max_out_time: max out of serving channel time, per LMAC - for CDB there\n *    are 2 LMACs (high band and low band)\n * @suspend_time: max suspend time, per LMAC - for CDB there are 2 LMACs\n * @scan_priority: scan internal prioritization &enum iwl_scan_priority\n * @num_of_fragments: Number of fragments needed for full coverage per band.\n *    Relevant only for fragmented scan.\n * @channel: &struct iwm_scan_umac_chan_param\n * @reserved: for future use and alignment\n * @reserved3: for future use and alignment\n * @data: &struct iwm_scan_channel_cfg_umac and\n *    &struct iwm_scan_req_umac_tail\n */\nstruct iwm_scan_req_umac {\n    uint32_t flags;\n    uint32_t uid;\n    uint32_t ooc_priority;\n    /* SCAN_GENERAL_PARAMS_API_S_VER_1 */\n    uint16_t general_flags;\n    uint8_t reserved;\n    uint8_t scan_start_mac_id;\n    union {\n        struct {\n            uint8_t extended_dwell;\n            uint8_t active_dwell;\n            uint8_t passive_dwell;\n            uint8_t fragmented_dwell;\n            uint32_t max_out_time;\n            uint32_t suspend_time;\n            uint32_t scan_priority;\n            struct iwm_scan_umac_chan_param channel;\n            uint8_t data[];\n        } v1; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_1 */\n        struct {\n            uint8_t extended_dwell;\n            uint8_t active_dwell;\n            uint8_t passive_dwell;\n            uint8_t fragmented_dwell;\n            uint32_t max_out_time[2];\n            uint32_t suspend_time[2];\n            uint32_t scan_priority;\n            struct iwm_scan_umac_chan_param channel;\n            uint8_t data[];\n        } v6; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_6 */\n        struct {\n            uint8_t active_dwell;\n            uint8_t passive_dwell;\n            uint8_t fragmented_dwell;\n            uint8_t adwell_default_n_aps;\n            uint8_t adwell_default_n_aps_social;\n            uint8_t reserved3;\n            uint16_t adwell_max_budget;\n            uint32_t max_out_time[2];\n            uint32_t suspend_time[2];\n            uint32_t scan_priority;\n            struct iwm_scan_umac_chan_param channel;\n            uint8_t data[];\n        } v7; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_7 */\n        struct {\n            uint8_t active_dwell[2];\n            uint8_t reserved2;\n            uint8_t adwell_default_n_aps;\n            uint8_t adwell_default_n_aps_social;\n            uint8_t general_flags2;\n            uint16_t adwell_max_budget;\n            uint32_t max_out_time[2];\n            uint32_t suspend_time[2];\n            uint32_t scan_priority;\n            uint8_t passive_dwell[2];\n            uint8_t num_of_fragments[2];\n            struct iwm_scan_umac_chan_param channel;\n            uint8_t data[];\n        } v8; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_8 */\n        struct {\n            uint8_t active_dwell[2];\n            uint8_t adwell_default_hb_n_aps;\n            uint8_t adwell_default_lb_n_aps;\n            uint8_t adwell_default_n_aps_social;\n            uint8_t general_flags2;\n            uint16_t adwell_max_budget;\n            uint32_t max_out_time[2];\n            uint32_t suspend_time[2];\n            uint32_t scan_priority;\n            uint8_t passive_dwell[2];\n            uint8_t num_of_fragments[2];\n            struct iwm_scan_umac_chan_param channel;\n            uint8_t data[];\n        } v9; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_9 */\n    };\n} __packed;\n\n#define IWM_SCAN_REQ_UMAC_SIZE_V8 sizeof(struct iwm_scan_req_umac)\n#define IWM_SCAN_REQ_UMAC_SIZE_V7 48\n#define IWM_SCAN_REQ_UMAC_SIZE_V6 44\n#define IWM_SCAN_REQ_UMAC_SIZE_V1 36\n\n/**\n * struct iwm_umac_scan_abort\n * @uid: scan id, &enum iwm_umac_scan_uid_offsets\n * @flags: reserved\n */\nstruct iwm_umac_scan_abort {\n    uint32_t uid;\n    uint32_t flags;\n} __packed; /* SCAN_ABORT_CMD_UMAC_API_S_VER_1 */\n\n/**\n * struct iwm_umac_scan_complete\n * @uid: scan id, &enum iwm_umac_scan_uid_offsets\n * @last_schedule: last scheduling line\n * @last_iter:    last scan iteration number\n * @scan status: &enum iwm_scan_offload_complete_status\n * @ebs_status: &enum iwm_scan_ebs_status\n * @time_from_last_iter: time elapsed from last iteration\n * @reserved: for future use\n */\nstruct iwm_umac_scan_complete {\n    uint32_t uid;\n    uint8_t last_schedule;\n    uint8_t last_iter;\n    uint8_t status;\n    uint8_t ebs_status;\n    uint32_t time_from_last_iter;\n    uint32_t reserved;\n} __packed; /* SCAN_COMPLETE_NTF_UMAC_API_S_VER_1 */\n\n#define IWM_SCAN_OFFLOAD_MATCHING_CHANNELS_LEN 5\n/**\n * struct iwm_scan_offload_profile_match - match information\n * @bssid: matched bssid\n * @channel: channel where the match occurred\n * @energy:\n * @matching_feature:\n * @matching_channels: bitmap of channels that matched, referencing\n *    the channels passed in tue scan offload request\n */\nstruct iwm_scan_offload_profile_match {\n    uint8_t bssid[ETHER_ADDR_LEN];\n    uint16_t reserved;\n    uint8_t channel;\n    uint8_t energy;\n    uint8_t matching_feature;\n    uint8_t matching_channels[IWM_SCAN_OFFLOAD_MATCHING_CHANNELS_LEN];\n} __packed; /* SCAN_OFFLOAD_PROFILE_MATCH_RESULTS_S_VER_1 */\n\n/**\n * struct iwm_scan_offload_profiles_query - match results query response\n * @matched_profiles: bitmap of matched profiles, referencing the\n *    matches passed in the scan offload request\n * @last_scan_age: age of the last offloaded scan\n * @n_scans_done: number of offloaded scans done\n * @gp2_d0u: GP2 when D0U occurred\n * @gp2_invoked: GP2 when scan offload was invoked\n * @resume_while_scanning: not used\n * @self_recovery: obsolete\n * @reserved: reserved\n * @matches: array of match information, one for each match\n */\nstruct iwm_scan_offload_profiles_query {\n    uint32_t matched_profiles;\n    uint32_t last_scan_age;\n    uint32_t n_scans_done;\n    uint32_t gp2_d0u;\n    uint32_t gp2_invoked;\n    uint8_t resume_while_scanning;\n    uint8_t self_recovery;\n    uint16_t reserved;\n    struct iwm_scan_offload_profile_match matches[IWM_SCAN_MAX_PROFILES];\n} __packed; /* SCAN_OFFLOAD_PROFILES_QUERY_RSP_S_VER_2 */\n\n/**\n * struct iwm_umac_scan_iter_complete_notif - notifies end of scanning iteration\n * @uid: scan id, &enum iwm_umac_scan_uid_offsets\n * @scanned_channels: number of channels scanned and number of valid elements in\n *    results array\n * @status: one of SCAN_COMP_STATUS_*\n * @bt_status: BT on/off status\n * @last_channel: last channel that was scanned\n * @tsf_low: TSF timer (lower half) in usecs\n * @tsf_high: TSF timer (higher half) in usecs\n * @results: array of scan results, only \"scanned_channels\" of them are valid\n */\nstruct iwm_umac_scan_iter_complete_notif {\n    uint32_t uid;\n    uint8_t scanned_channels;\n    uint8_t status;\n    uint8_t bt_status;\n    uint8_t last_channel;\n    uint32_t tsf_low;\n    uint32_t tsf_high;\n    struct iwm_scan_results_notif results[];\n} __packed; /* SCAN_ITER_COMPLETE_NTF_UMAC_API_S_VER_1 */\n\n#define IWM_GSCAN_START_CMD            0x0\n#define IWM_GSCAN_STOP_CMD            0x1\n#define IWM_GSCAN_SET_HOTLIST_CMD        0x2\n#define IWM_GSCAN_RESET_HOTLIST_CMD        0x3\n#define IWM_GSCAN_SET_SIGNIFICANT_CHANGE_CMD    0x4\n#define IWM_GSCAN_RESET_SIGNIFICANT_CHANGE_CMD    0x5\n#define IWM_GSCAN_SIGNIFICANT_CHANGE_EVENT    0xFD\n#define IWM_GSCAN_HOTLIST_CHANGE_EVENT        0xFE\n#define IWM_GSCAN_RESULTS_AVAILABLE_EVENT    0xFF\n\n/* STA API */\n\n/**\n * flags for the ADD_STA host command\n * @IWM_STA_FLG_REDUCED_TX_PWR_CTRL:\n * @IWM_STA_FLG_REDUCED_TX_PWR_DATA:\n * @IWM_STA_FLG_DISABLE_TX: set if TX should be disabled\n * @IWM_STA_FLG_PS: set if STA is in Power Save\n * @IWM_STA_FLG_INVALID: set if STA is invalid\n * @IWM_STA_FLG_DLP_EN: Direct Link Protocol is enabled\n * @IWM_STA_FLG_SET_ALL_KEYS: the current key applies to all key IDs\n * @IWM_STA_FLG_DRAIN_FLOW: drain flow\n * @IWM_STA_FLG_PAN: STA is for PAN interface\n * @IWM_STA_FLG_CLASS_AUTH:\n * @IWM_STA_FLG_CLASS_ASSOC:\n * @IWM_STA_FLG_CLASS_MIMO_PROT:\n * @IWM_STA_FLG_MAX_AGG_SIZE_MSK: maximal size for A-MPDU\n * @IWM_STA_FLG_AGG_MPDU_DENS_MSK: maximal MPDU density for Tx aggregation\n * @IWM_STA_FLG_FAT_EN_MSK: support for channel width (for Tx). This flag is\n *    initialised by driver and can be updated by fw upon reception of\n *    action frames that can change the channel width. When cleared the fw\n *    will send all the frames in 20MHz even when FAT channel is requested.\n * @IWM_STA_FLG_MIMO_EN_MSK: support for MIMO. This flag is initialised by the\n *    driver and can be updated by fw upon reception of action frames.\n * @IWM_STA_FLG_MFP_EN: Management Frame Protection\n */\n#define IWM_STA_FLG_REDUCED_TX_PWR_CTRL    (1 << 3)\n#define IWM_STA_FLG_REDUCED_TX_PWR_DATA    (1 << 6)\n\n#define IWM_STA_FLG_DISABLE_TX        (1 << 4)\n\n#define IWM_STA_FLG_PS            (1 << 8)\n#define IWM_STA_FLG_DRAIN_FLOW        (1 << 12)\n#define IWM_STA_FLG_PAN            (1 << 13)\n#define IWM_STA_FLG_CLASS_AUTH        (1 << 14)\n#define IWM_STA_FLG_CLASS_ASSOC        (1 << 15)\n#define IWM_STA_FLG_RTS_MIMO_PROT    (1 << 17)\n\n#define IWM_STA_FLG_MAX_AGG_SIZE_SHIFT    19\n#define IWM_STA_FLG_MAX_AGG_SIZE_8K    (0 << IWM_STA_FLG_MAX_AGG_SIZE_SHIFT)\n#define IWM_STA_FLG_MAX_AGG_SIZE_16K    (1 << IWM_STA_FLG_MAX_AGG_SIZE_SHIFT)\n#define IWM_STA_FLG_MAX_AGG_SIZE_32K    (2 << IWM_STA_FLG_MAX_AGG_SIZE_SHIFT)\n#define IWM_STA_FLG_MAX_AGG_SIZE_64K    (3 << IWM_STA_FLG_MAX_AGG_SIZE_SHIFT)\n#define IWM_STA_FLG_MAX_AGG_SIZE_128K    (4 << IWM_STA_FLG_MAX_AGG_SIZE_SHIFT)\n#define IWM_STA_FLG_MAX_AGG_SIZE_256K    (5 << IWM_STA_FLG_MAX_AGG_SIZE_SHIFT)\n#define IWM_STA_FLG_MAX_AGG_SIZE_512K    (6 << IWM_STA_FLG_MAX_AGG_SIZE_SHIFT)\n#define IWM_STA_FLG_MAX_AGG_SIZE_1024K    (7 << IWM_STA_FLG_MAX_AGG_SIZE_SHIFT)\n#define IWM_STA_FLG_MAX_AGG_SIZE_2M    (8 << IWM_STA_FLG_MAX_AGG_SIZE_SHIFT)\n#define IWM_STA_FLG_MAX_AGG_SIZE_4M    (9 << IWM_STA_FLG_MAX_AGG_SIZE_SHIFT)\n#define IWM_STA_FLG_MAX_AGG_SIZE_MSK    (0xf << IWM_STA_FLG_MAX_AGG_SIZE_SHIFT)\n\n#define IWM_STA_FLG_AGG_MPDU_DENS_SHIFT    23\n#define IWM_STA_FLG_AGG_MPDU_DENS_2US    (4 << IWM_STA_FLG_AGG_MPDU_DENS_SHIFT)\n#define IWM_STA_FLG_AGG_MPDU_DENS_4US    (5 << IWM_STA_FLG_AGG_MPDU_DENS_SHIFT)\n#define IWM_STA_FLG_AGG_MPDU_DENS_8US    (6 << IWM_STA_FLG_AGG_MPDU_DENS_SHIFT)\n#define IWM_STA_FLG_AGG_MPDU_DENS_16US    (7 << IWM_STA_FLG_AGG_MPDU_DENS_SHIFT)\n#define IWM_STA_FLG_AGG_MPDU_DENS_MSK    (7 << IWM_STA_FLG_AGG_MPDU_DENS_SHIFT)\n\n#define IWM_STA_FLG_FAT_EN_20MHZ    (0 << 26)\n#define IWM_STA_FLG_FAT_EN_40MHZ    (1 << 26)\n#define IWM_STA_FLG_FAT_EN_80MHZ    (2 << 26)\n#define IWM_STA_FLG_FAT_EN_160MHZ    (3 << 26)\n#define IWM_STA_FLG_FAT_EN_MSK        (3 << 26)\n\n#define IWM_STA_FLG_MIMO_EN_SISO    (0 << 28)\n#define IWM_STA_FLG_MIMO_EN_MIMO2    (1 << 28)\n#define IWM_STA_FLG_MIMO_EN_MIMO3    (2 << 28)\n#define IWM_STA_FLG_MIMO_EN_MSK        (3 << 28)\n\n/**\n * key flags for the ADD_STA host command\n * @IWM_STA_KEY_FLG_NO_ENC: no encryption\n * @IWM_STA_KEY_FLG_WEP: WEP encryption algorithm\n * @IWM_STA_KEY_FLG_CCM: CCMP encryption algorithm\n * @IWM_STA_KEY_FLG_TKIP: TKIP encryption algorithm\n * @IWM_STA_KEY_FLG_EXT: extended cipher algorithm (depends on the FW support)\n * @IWM_STA_KEY_FLG_CMAC: CMAC encryption algorithm\n * @IWM_STA_KEY_FLG_ENC_UNKNOWN: unknown encryption algorithm\n * @IWM_STA_KEY_FLG_EN_MSK: mask for encryption algorithmi value\n * @IWM_STA_KEY_FLG_WEP_KEY_MAP: wep is either a group key (0 - legacy WEP) or from\n *    station info array (1 - n 1X mode)\n * @IWM_STA_KEY_FLG_KEYID_MSK: the index of the key\n * @IWM_STA_KEY_NOT_VALID: key is invalid\n * @IWM_STA_KEY_FLG_WEP_13BYTES: set for 13 bytes WEP key\n * @IWM_STA_KEY_MULTICAST: set for multicast key\n * @IWM_STA_KEY_MFP: key is used for Management Frame Protection\n */\n#define IWM_STA_KEY_FLG_NO_ENC        (0 << 0)\n#define IWM_STA_KEY_FLG_WEP        (1 << 0)\n#define IWM_STA_KEY_FLG_CCM        (2 << 0)\n#define IWM_STA_KEY_FLG_TKIP        (3 << 0)\n#define IWM_STA_KEY_FLG_EXT        (4 << 0)\n#define IWM_STA_KEY_FLG_CMAC        (6 << 0)\n#define IWM_STA_KEY_FLG_ENC_UNKNOWN    (7 << 0)\n#define IWM_STA_KEY_FLG_EN_MSK        (7 << 0)\n#define IWM_STA_KEY_FLG_WEP_KEY_MAP    (1 << 3)\n#define IWM_STA_KEY_FLG_KEYID_POS    8\n#define IWM_STA_KEY_FLG_KEYID_MSK    (3 << IWM_STA_KEY_FLG_KEYID_POS)\n#define IWM_STA_KEY_NOT_VALID        (1 << 11)\n#define IWM_STA_KEY_FLG_WEP_13BYTES    (1 << 12)\n#define IWM_STA_KEY_MULTICAST        (1 << 14)\n#define IWM_STA_KEY_MFP            (1 << 15)\n\n/**\n * indicate to the fw what flag are being changed\n * @IWM_STA_MODIFY_QUEUE_REMOVAL: this command removes a queue\n * @IWM_STA_MODIFY_TID_DISABLE_TX: this command modifies %tid_disable_tx\n * @IWM_STA_MODIFY_TX_RATE: unused\n * @IWM_STA_MODIFY_ADD_BA_TID: this command modifies %add_immediate_ba_tid\n * @IWM_STA_MODIFY_REMOVE_BA_TID: this command modifies %remove_immediate_ba_tid\n * @IWM_STA_MODIFY_SLEEPING_STA_TX_COUNT: this command modifies %sleep_tx_count\n * @IWM_STA_MODIFY_PROT_TH:\n * @IWM_STA_MODIFY_QUEUES: modify the queues used by this station\n */\n#define IWM_STA_MODIFY_QUEUE_REMOVAL        (1 << 0)\n#define IWM_STA_MODIFY_TID_DISABLE_TX        (1 << 1)\n#define IWM_STA_MODIFY_TX_RATE            (1 << 2)\n#define IWM_STA_MODIFY_ADD_BA_TID        (1 << 3)\n#define IWM_STA_MODIFY_REMOVE_BA_TID        (1 << 4)\n#define IWM_STA_MODIFY_SLEEPING_STA_TX_COUNT    (1 << 5)\n#define IWM_STA_MODIFY_PROT_TH            (1 << 6)\n#define IWM_STA_MODIFY_QUEUES            (1 << 7)\n\n#define IWM_STA_MODE_MODIFY    1\n\n/**\n * type of sleep of the station\n * @IWM_STA_SLEEP_STATE_AWAKE:\n * @IWM_STA_SLEEP_STATE_PS_POLL:\n * @IWM_STA_SLEEP_STATE_UAPSD:\n * @IWM_STA_SLEEP_STATE_MOREDATA: set more-data bit on\n *    (last) released frame\n */\n#define IWM_STA_SLEEP_STATE_AWAKE    0\n#define IWM_STA_SLEEP_STATE_PS_POLL    (1 << 0)\n#define IWM_STA_SLEEP_STATE_UAPSD    (1 << 1)\n#define IWM_STA_SLEEP_STATE_MOREDATA    (1 << 2)\n\n/* STA ID and color bits definitions */\n#define IWM_STA_ID_SEED        (0x0f)\n#define IWM_STA_ID_POS        (0)\n#define IWM_STA_ID_MSK        (IWM_STA_ID_SEED << IWM_STA_ID_POS)\n\n#define IWM_STA_COLOR_SEED    (0x7)\n#define IWM_STA_COLOR_POS    (4)\n#define IWM_STA_COLOR_MSK    (IWM_STA_COLOR_SEED << IWM_STA_COLOR_POS)\n\n#define IWM_STA_ID_N_COLOR_GET_COLOR(id_n_color) \\\n    (((id_n_color) & IWM_STA_COLOR_MSK) >> IWM_STA_COLOR_POS)\n#define IWM_STA_ID_N_COLOR_GET_ID(id_n_color)    \\\n    (((id_n_color) & IWM_STA_ID_MSK) >> IWM_STA_ID_POS)\n\n#define IWM_STA_KEY_MAX_NUM (16)\n#define IWM_STA_KEY_IDX_INVALID (0xff)\n#define IWM_STA_KEY_MAX_DATA_KEY_NUM (4)\n#define IWM_MAX_GLOBAL_KEYS (4)\n#define IWM_STA_KEY_LEN_WEP40 (5)\n#define IWM_STA_KEY_LEN_WEP104 (13)\n\n/**\n * struct iwm_keyinfo - key information\n * @key_flags: type %iwm_sta_key_flag\n * @tkip_rx_tsc_byte2: TSC[2] for key mix ph1 detection\n * @tkip_rx_ttak: 10-byte unicast TKIP TTAK for Rx\n * @key_offset: key offset in the fw's key table\n * @key: 16-byte unicast decryption key\n * @tx_secur_seq_cnt: initial RSC / PN needed for replay check\n * @hw_tkip_mic_rx_key: byte: MIC Rx Key - used for TKIP only\n * @hw_tkip_mic_tx_key: byte: MIC Tx Key - used for TKIP only\n */\nstruct iwm_keyinfo {\n    uint16_t key_flags;\n    uint8_t tkip_rx_tsc_byte2;\n    uint8_t reserved1;\n    uint16_t tkip_rx_ttak[5];\n    uint8_t key_offset;\n    uint8_t reserved2;\n    uint8_t key[16];\n    uint64_t tx_secur_seq_cnt;\n    uint64_t hw_tkip_mic_rx_key;\n    uint64_t hw_tkip_mic_tx_key;\n} __packed;\n\n#define IWM_ADD_STA_STATUS_MASK        0xFF\n#define IWM_ADD_STA_BAID_VALID_MASK    0x8000\n#define IWM_ADD_STA_BAID_MASK        0x7F00\n#define IWM_ADD_STA_BAID_SHIFT        8\n\n/**\n * struct iwm_add_sta_cmd_v7 - Add/modify a station in the fw's sta table.\n * ( REPLY_ADD_STA = 0x18 )\n * @add_modify: 1: modify existing, 0: add new station\n * @awake_acs:\n * @tid_disable_tx: is tid BIT(tid) enabled for Tx. Clear BIT(x) to enable\n *    AMPDU for tid x. Set %IWM_STA_MODIFY_TID_DISABLE_TX to change this field.\n * @mac_id_n_color: the Mac context this station belongs to\n * @addr[ETHER_ADDR_LEN]: station's MAC address\n * @sta_id: index of station in uCode's station table\n * @modify_mask: IWM_STA_MODIFY_*, selects which parameters to modify vs. leave\n *    alone. 1 - modify, 0 - don't change.\n * @station_flags: look at %iwm_sta_flags\n * @station_flags_msk: what of %station_flags have changed\n * @add_immediate_ba_tid: tid for which to add block-ack support (Rx)\n *    Set %IWM_STA_MODIFY_ADD_BA_TID to use this field, and also set\n *    add_immediate_ba_ssn.\n * @remove_immediate_ba_tid: tid for which to remove block-ack support (Rx)\n *    Set %IWM_STA_MODIFY_REMOVE_BA_TID to use this field\n * @add_immediate_ba_ssn: ssn for the Rx block-ack session. Used together with\n *    add_immediate_ba_tid.\n * @sleep_tx_count: number of packets to transmit to station even though it is\n *    asleep. Used to synchronise PS-poll and u-APSD responses while ucode\n *    keeps track of STA sleep state.\n * @sleep_state_flags: Look at %iwm_sta_sleep_flag.\n * @assoc_id: assoc_id to be sent in VHT PLCP (9-bit), for grp use 0, for AP\n *    mac-addr.\n * @beamform_flags: beam forming controls\n * @tfd_queue_msk: tfd queues used by this station\n *\n * The device contains an internal table of per-station information, with info\n * on security keys, aggregation parameters, and Tx rates for initial Tx\n * attempt and any retries (set by IWM_REPLY_TX_LINK_QUALITY_CMD).\n *\n * ADD_STA sets up the table entry for one station, either creating a new\n * entry, or modifying a pre-existing one.\n */\nstruct iwm_add_sta_cmd_v7 {\n    uint8_t add_modify;\n    uint8_t awake_acs;\n    uint16_t tid_disable_tx;\n    uint32_t mac_id_n_color;\n    uint8_t addr[ETHER_ADDR_LEN];    /* _STA_ID_MODIFY_INFO_API_S_VER_1 */\n    uint16_t reserved2;\n    uint8_t sta_id;\n    uint8_t modify_mask;\n    uint16_t reserved3;\n    uint32_t station_flags;\n    uint32_t station_flags_msk;\n    uint8_t add_immediate_ba_tid;\n    uint8_t remove_immediate_ba_tid;\n    uint16_t add_immediate_ba_ssn;\n    uint16_t sleep_tx_count;\n    uint16_t sleep_state_flags;\n    uint16_t assoc_id;\n    uint16_t beamform_flags;\n    uint32_t tfd_queue_msk;\n} __packed; /* ADD_STA_CMD_API_S_VER_7 */\n\n/**\n * struct iwm_add_sta_cmd - Add/modify a station in the fw's sta table.\n * ( REPLY_ADD_STA = 0x18 )\n * @add_modify: see &enum iwl_sta_mode\n * @awake_acs: ACs to transmit data on while station is sleeping (for U-APSD)\n * @tid_disable_tx: is tid BIT(tid) enabled for Tx. Clear BIT(x) to enable\n *    AMPDU for tid x. Set %STA_MODIFY_TID_DISABLE_TX to change this field.\n * @mac_id_n_color: the Mac context this station belongs to,\n *    see &enum iwl_ctxt_id_and_color\n * @addr: station's MAC address\n * @reserved2: reserved\n * @sta_id: index of station in uCode's station table\n * @modify_mask: STA_MODIFY_*, selects which parameters to modify vs. leave\n *    alone. 1 - modify, 0 - don't change.\n * @reserved3: reserved\n * @station_flags: look at &enum iwl_sta_flags\n * @station_flags_msk: what of %station_flags have changed,\n *    also &enum iwl_sta_flags\n * @add_immediate_ba_tid: tid for which to add block-ack support (Rx)\n *    Set %STA_MODIFY_ADD_BA_TID to use this field, and also set\n *    add_immediate_ba_ssn.\n * @remove_immediate_ba_tid: tid for which to remove block-ack support (Rx)\n *    Set %STA_MODIFY_REMOVE_BA_TID to use this field\n * @add_immediate_ba_ssn: ssn for the Rx block-ack session. Used together with\n *    add_immediate_ba_tid.\n * @sleep_tx_count: number of packets to transmit to station even though it is\n *    asleep. Used to synchronise PS-poll and u-APSD responses while ucode\n *    keeps track of STA sleep state.\n * @station_type: type of this station. See &enum iwl_sta_type.\n * @sleep_state_flags: Look at &enum iwl_sta_sleep_flag.\n * @assoc_id: assoc_id to be sent in VHT PLCP (9-bit), for grp use 0, for AP\n *    mac-addr.\n * @beamform_flags: beam forming controls\n * @tfd_queue_msk: tfd queues used by this station.\n *    Obselete for new TX API (9 and above).\n * @rx_ba_window: aggregation window size\n * @sp_length: the size of the SP in actual number of frames\n * @uapsd_acs:  4 LS bits are trigger enabled ACs, 4 MS bits are the deliver\n *    enabled ACs.\n *\n * The device contains an internal table of per-station information, with info\n * on security keys, aggregation parameters, and Tx rates for initial Tx\n * attempt and any retries (set by REPLY_TX_LINK_QUALITY_CMD).\n *\n * ADD_STA sets up the table entry for one station, either creating a new\n * entry, or modifying a pre-existing one.\n */\nstruct iwm_add_sta_cmd {\n    uint8_t add_modify;\n    uint8_t awake_acs;\n    uint16_t tid_disable_tx;\n    uint32_t mac_id_n_color;\n    uint8_t addr[ETHER_ADDR_LEN];    /* _STA_ID_MODIFY_INFO_API_S_VER_1 */\n    uint16_t reserved2;\n    uint8_t sta_id;\n    uint8_t modify_mask;\n    uint16_t reserved3;\n    uint32_t station_flags;\n    uint32_t station_flags_msk;\n    uint8_t add_immediate_ba_tid;\n    uint8_t remove_immediate_ba_tid;\n    uint16_t add_immediate_ba_ssn;\n    uint16_t sleep_tx_count;\n    uint8_t sleep_state_flags;\n    uint8_t station_type;\n    uint16_t assoc_id;\n    uint16_t beamform_flags;\n    uint32_t tfd_queue_msk;\n    uint16_t rx_ba_window;\n    uint8_t sp_length;\n    uint8_t uapsd_acs;\n} __packed; /* ADD_STA_CMD_API_S_VER_10 */\n\n/**\n * FW station types\n * ( REPLY_ADD_STA = 0x18 )\n * @IWM_STA_LINK: Link station - normal RX and TX traffic.\n * @IWM_STA_GENERAL_PURPOSE: General purpose. In AP mode used for beacons\n *    and probe responses.\n * @IWM_STA_MULTICAST: multicast traffic,\n * @IWM_STA_TDLS_LINK: TDLS link station\n * @IWM_STA_AUX_ACTIVITY: auxilary station (scan, ROC and so on).\n */\n#define IWM_STA_LINK        0\n#define IWM_STA_GENERAL_PURPOSE    1\n#define IWM_STA_MULTICAST    2\n#define IWM_STA_TDLS_LINK    3\n#define IWM_STA_AUX_ACTIVITY    4\n\n/**\n * struct iwm_add_sta_key_common - add/modify sta key common part\n * ( REPLY_ADD_STA_KEY = 0x17 )\n * @sta_id: index of station in uCode's station table\n * @key_offset: key offset in key storage\n * @key_flags: IWM_STA_KEY_FLG_*\n * @key: key material data\n * @rx_secur_seq_cnt: RX security sequence counter for the key\n */\nstruct iwm_add_sta_key_common {\n    uint8_t sta_id;\n    uint8_t key_offset;\n    uint16_t key_flags;\n    uint8_t key[32];\n    uint8_t rx_secur_seq_cnt[16];\n} __packed;\n\n/**\n * struct iwm_add_sta_key_cmd_v1 - add/modify sta key\n * @common: see &struct iwm_add_sta_key_common\n * @tkip_rx_tsc_byte2: TSC[2] for key mix ph1 detection\n * @reserved: reserved\n * @tkip_rx_ttak: 10-byte unicast TKIP TTAK for Rx\n */\nstruct iwm_add_sta_key_cmd_v1 {\n    struct iwm_add_sta_key_common common;\n    uint8_t tkip_rx_tsc_byte2;\n    uint8_t reserved;\n    uint16_t tkip_rx_ttak[5];\n} __packed; /* ADD_MODIFY_STA_KEY_API_S_VER_1 */\n\n/**\n * struct iwm_add_sta_key_cmd - add/modify sta key\n * @common: see &struct iwm_add_sta_key_common\n * @rx_mic_key: TKIP RX unicast or multicast key\n * @tx_mic_key: TKIP TX key\n * @transmit_seq_cnt: TSC, transmit packet number\n */\nstruct iwm_add_sta_key_cmd {\n    struct iwm_add_sta_key_common common;\n    uint64_t rx_mic_key;\n    uint64_t tx_mic_key;\n    uint64_t transmit_seq_cnt;\n} __packed; /* ADD_MODIFY_STA_KEY_API_S_VER_2 */\n\n/**\n * status in the response to ADD_STA command\n * @IWM_ADD_STA_SUCCESS: operation was executed successfully\n * @IWM_ADD_STA_STATIONS_OVERLOAD: no room left in the fw's station table\n * @IWM_ADD_STA_IMMEDIATE_BA_FAILURE: can't add Rx block ack session\n * @IWM_ADD_STA_MODIFY_NON_EXISTING_STA: driver requested to modify a station\n *    that doesn't exist.\n */\n#define IWM_ADD_STA_SUCCESS            0x1\n#define IWM_ADD_STA_STATIONS_OVERLOAD        0x2\n#define IWM_ADD_STA_IMMEDIATE_BA_FAILURE    0x4\n#define IWM_ADD_STA_MODIFY_NON_EXISTING_STA    0x8\n\n/**\n * struct iwm_rm_sta_cmd - Add / modify a station in the fw's station table\n * ( IWM_REMOVE_STA = 0x19 )\n * @sta_id: the station id of the station to be removed\n */\nstruct iwm_rm_sta_cmd {\n    uint8_t sta_id;\n    uint8_t reserved[3];\n} __packed; /* IWM_REMOVE_STA_CMD_API_S_VER_2 */\n\n/**\n * struct iwm_mgmt_mcast_key_cmd\n * ( IWM_MGMT_MCAST_KEY = 0x1f )\n * @ctrl_flags: %iwm_sta_key_flag\n * @IGTK:\n * @K1: IGTK master key\n * @K2: IGTK sub key\n * @sta_id: station ID that support IGTK\n * @key_id:\n * @receive_seq_cnt: initial RSC/PN needed for replay check\n */\nstruct iwm_mgmt_mcast_key_cmd {\n    uint32_t ctrl_flags;\n    uint8_t IGTK[16];\n    uint8_t K1[16];\n    uint8_t K2[16];\n    uint32_t key_id;\n    uint32_t sta_id;\n    uint64_t receive_seq_cnt;\n} __packed; /* SEC_MGMT_MULTICAST_KEY_CMD_API_S_VER_1 */\n\nstruct iwm_wep_key {\n    uint8_t key_index;\n    uint8_t key_offset;\n    uint16_t reserved1;\n    uint8_t key_size;\n    uint8_t reserved2[3];\n    uint8_t key[16];\n} __packed;\n\nstruct iwm_wep_key_cmd {\n    uint32_t mac_id_n_color;\n    uint8_t num_keys;\n    uint8_t decryption_type;\n    uint8_t flags;\n    uint8_t reserved;\n    struct iwm_wep_key wep_key[0];\n} __packed; /* SEC_CURR_WEP_KEY_CMD_API_S_VER_2 */\n\n/*\n * BT coex\n */\n\n#define IWM_BT_COEX_DISABLE        0x0\n#define IWM_BT_COEX_NW            0x1\n#define IWM_BT_COEX_BT            0x2\n#define IWM_BT_COEX_WIFI        0x3\n/* BT_COEX_MODES_E */\n\n#define IWM_BT_COEX_MPLUT_ENABLED    (1 << 0)\n#define IWM_BT_COEX_MPLUT_BOOST_ENABLED    (1 << 1)\n#define IWM_BT_COEX_SYNC2SCO_ENABLED    (1 << 2)\n#define IWM_BT_COEX_CORUN_ENABLED    (1 << 3)\n#define IWM_BT_COEX_HIGH_BAND_RET    (1 << 4)\n/* BT_COEX_MODULES_ENABLE_E_VER_1 */\n\n/**\n * struct iwm_bt_coex_cmd - bt coex configuration command\n * @mode: enum %iwm_bt_coex_mode\n * @enabled_modules: enum %iwm_bt_coex_enabled_modules\n *\n * The structure is used for the BT_COEX command.\n */\nstruct iwm_bt_coex_cmd {\n    uint32_t mode;\n    uint32_t enabled_modules;\n} __packed; /* BT_COEX_CMD_API_S_VER_6 */\n\n\n/*\n * Location Aware Regulatory (LAR) API - MCC updates\n */\n\n/**\n * struct iwm_mcc_update_cmd_v1 - Request the device to update geographic\n * regulatory profile according to the given MCC (Mobile Country Code).\n * The MCC is two letter-code, ascii upper case[A-Z] or '00' for world domain.\n * 'ZZ' MCC will be used to switch to NVM default profile; in this case, the\n * MCC in the cmd response will be the relevant MCC in the NVM.\n * @mcc: given mobile country code\n * @source_id: the source from where we got the MCC, see iwm_mcc_source\n * @reserved: reserved for alignment\n */\nstruct iwm_mcc_update_cmd_v1 {\n    uint16_t mcc;\n    uint8_t source_id;\n    uint8_t reserved;\n} __packed; /* LAR_UPDATE_MCC_CMD_API_S_VER_1 */\n\n/**\n * struct iwm_mcc_update_cmd - Request the device to update geographic\n * regulatory profile according to the given MCC (Mobile Country Code).\n * The MCC is two letter-code, ascii upper case[A-Z] or '00' for world domain.\n * 'ZZ' MCC will be used to switch to NVM default profile; in this case, the\n * MCC in the cmd response will be the relevant MCC in the NVM.\n * @mcc: given mobile country code\n * @source_id: the source from where we got the MCC, see iwm_mcc_source\n * @reserved: reserved for alignment\n * @key: integrity key for MCC API OEM testing\n * @reserved2: reserved\n */\nstruct iwm_mcc_update_cmd {\n    uint16_t mcc;\n    uint8_t source_id;\n    uint8_t reserved;\n    uint32_t key;\n    uint32_t reserved2[5];\n} __packed; /* LAR_UPDATE_MCC_CMD_API_S_VER_2 */\n\n/**\n * iwm_mcc_update_resp_v1  - response to MCC_UPDATE_CMD.\n * Contains the new channel control profile map, if changed, and the new MCC\n * (mobile country code).\n * The new MCC may be different than what was requested in MCC_UPDATE_CMD.\n * @status: see &enum iwm_mcc_update_status\n * @mcc: the new applied MCC\n * @cap: capabilities for all channels which matches the MCC\n * @source_id: the MCC source, see iwm_mcc_source\n * @n_channels: number of channels in @channels_data (may be 14, 39, 50 or 51\n *        channels, depending on platform)\n * @channels: channel control data map, DWORD for each channel. Only the first\n *    16bits are used.\n */\nstruct iwm_mcc_update_resp_v1  {\n    uint32_t status;\n    uint16_t mcc;\n    uint8_t cap;\n    uint8_t source_id;\n    uint32_t n_channels;\n    uint32_t channels[0];\n} __packed; /* LAR_UPDATE_MCC_CMD_RESP_S_VER_1 */\n\n/**\n * iwm_mcc_update_resp_v2 - response to MCC_UPDATE_CMD.\n * Contains the new channel control profile map, if changed, and the new MCC\n * (mobile country code).\n * The new MCC may be different than what was requested in MCC_UPDATE_CMD.\n * @status: see &enum iwm_mcc_update_status\n * @mcc: the new applied MCC\n * @cap: capabilities for all channels which matches the MCC\n * @source_id: the MCC source, see iwm_mcc_source\n * @time: time elapsed from the MCC test start (in 30 seconds TU)\n * @reserved: reserved.\n * @n_channels: number of channels in @channels_data (may be 14, 39, 50 or 51\n *        channels, depending on platform)\n * @channels: channel control data map, DWORD for each channel. Only the first\n *    16bits are used.\n */\nstruct iwm_mcc_update_resp_v2 {\n    uint32_t status;\n    uint16_t mcc;\n    uint8_t cap;\n    uint8_t source_id;\n    uint16_t time;\n    uint16_t reserved;\n    uint32_t n_channels;\n    uint32_t channels[0];\n} __packed; /* LAR_UPDATE_MCC_CMD_RESP_S_VER_2 */\n\n#define IWM_GEO_NO_INFO            0\n#define IWM_GEO_WMM_ETSI_5GHZ_INFO    (1 << 0)\n\n/**\n * iwm_mcc_update_resp_v3 - response to MCC_UPDATE_CMD.\n * Contains the new channel control profile map, if changed, and the new MCC\n * (mobile country code).\n * The new MCC may be different than what was requested in MCC_UPDATE_CMD.\n * @status: see &enum iwm_mcc_update_status\n * @mcc: the new applied MCC\n * @cap: capabilities for all channels which matches the MCC\n * @source_id: the MCC source, see IWM_MCC_SOURCE_*\n * @time: time elapsed from the MCC test start (in 30 seconds TU)\n * @geo_info: geographic specific profile information\n * @n_channels: number of channels in @channels_data (may be 14, 39, 50 or 51\n *        channels, depending on platform)\n * @channels: channel control data map, DWORD for each channel. Only the first\n *    16bits are used.\n */\nstruct iwm_mcc_update_resp_v3 {\n    uint32_t status;\n    uint16_t mcc;\n    uint8_t cap;\n    uint8_t source_id;\n    uint16_t time;\n    uint16_t geo_info;\n    uint32_t n_channels;\n    uint32_t channels[0];\n} __packed; /* LAR_UPDATE_MCC_CMD_RESP_S_VER_3 */\n\n/**\n * struct iwm_mcc_chub_notif - chub notifies of mcc change\n * (MCC_CHUB_UPDATE_CMD = 0xc9)\n * The Chub (Communication Hub, CommsHUB) is a HW component that connects to\n * the cellular and connectivity cores that gets updates of the mcc, and\n * notifies the ucode directly of any mcc change.\n * The ucode requests the driver to request the device to update geographic\n * regulatory  profile according to the given MCC (Mobile Country Code).\n * The MCC is two letter-code, ascii upper case[A-Z] or '00' for world domain.\n * 'ZZ' MCC will be used to switch to NVM default profile; in this case, the\n * MCC in the cmd response will be the relevant MCC in the NVM.\n * @mcc: given mobile country code\n * @source_id: identity of the change originator, see iwm_mcc_source\n * @reserved1: reserved for alignment\n */\nstruct iwm_mcc_chub_notif {\n    uint16_t mcc;\n    uint8_t source_id;\n    uint8_t reserved1;\n} __packed; /* LAR_MCC_NOTIFY_S */\n\n#define IWM_MCC_RESP_NEW_CHAN_PROFILE            0\n#define IWM_MCC_RESP_SAME_CHAN_PROFILE            1\n#define IWM_MCC_RESP_INVALID                2\n#define IWM_MCC_RESP_NVM_DISABLED            3\n#define IWM_MCC_RESP_ILLEGAL                4\n#define IWM_MCC_RESP_LOW_PRIORITY            5\n#define IWM_MCC_RESP_TEST_MODE_ACTIVE            6\n#define IWM_MCC_RESP_TEST_MODE_NOT_ACTIVE        7\n#define IWM_MCC_RESP_TEST_MODE_DENIAL_OF_SERVICE    8\n\n#define IWM_MCC_SOURCE_OLD_FW            0\n#define IWM_MCC_SOURCE_ME            1\n#define IWM_MCC_SOURCE_BIOS            2\n#define IWM_MCC_SOURCE_3G_LTE_HOST        3\n#define IWM_MCC_SOURCE_3G_LTE_DEVICE        4\n#define IWM_MCC_SOURCE_WIFI            5\n#define IWM_MCC_SOURCE_RESERVED            6\n#define IWM_MCC_SOURCE_DEFAULT            7\n#define IWM_MCC_SOURCE_UNINITIALIZED        8\n#define IWM_MCC_SOURCE_MCC_API            9\n#define IWM_MCC_SOURCE_GET_CURRENT        0x10\n#define IWM_MCC_SOURCE_GETTING_MCC_TEST_MODE    0x11\n\n/*\n * Some cherry-picked definitions\n */\n\n#define IWM_FRAME_LIMIT    64\n\n/*\n * From Linux commit ab02165ccec4c78162501acedeef1a768acdb811:\n *   As the firmware is slowly running out of command IDs and grouping of\n *   commands is desirable anyway, the firmware is extending the command\n *   header from 4 bytes to 8 bytes to introduce a group (in place of the\n *   former flags field, since that's always 0 on commands and thus can\n *   be easily used to distinguish between the two).\n *\n * These functions retrieve specific information from the id field in\n * the iwm_host_cmd struct which contains the command id, the group id,\n * and the version of the command.\n*/\nstatic inline uint8_t\niwm_cmd_opcode(uint32_t cmdid)\n{\n    return cmdid & 0xff;\n}\n\nstatic inline uint8_t\niwm_cmd_groupid(uint32_t cmdid)\n{\n    return ((cmdid & 0Xff00) >> 8);\n}\n\nstatic inline uint8_t\niwm_cmd_version(uint32_t cmdid)\n{\n    return ((cmdid & 0xff0000) >> 16);\n}\n\nstatic inline uint32_t\niwm_cmd_id(uint8_t opcode, uint8_t groupid, uint8_t version)\n{\n    return opcode + (groupid << 8) + (version << 16);\n}\n\n/* make uint16_t wide id out of uint8_t group and opcode */\n#define IWM_WIDE_ID(grp, opcode) ((grp << 8) | opcode)\n\nstruct iwm_cmd_header {\n    uint8_t code;\n    uint8_t flags;\n    uint8_t idx;\n    uint8_t qid;\n} __packed;\n\nstruct iwm_cmd_header_wide {\n    uint8_t opcode;\n    uint8_t group_id;\n    uint8_t idx;\n    uint8_t qid;\n    uint16_t length;\n    uint8_t reserved;\n    uint8_t version;\n} __packed;\n\n#define IWM_POWER_SCHEME_CAM    1\n#define IWM_POWER_SCHEME_BPS    2\n#define IWM_POWER_SCHEME_LP    3\n\n#define IWM_DEF_CMD_PAYLOAD_SIZE 320\n#define IWM_MAX_CMD_PAYLOAD_SIZE ((4096 - 4) - sizeof(struct iwm_cmd_header))\n#define IWM_CMD_FAILED_MSK 0x40\n\n/**\n * struct iwm_device_cmd\n *\n * For allocation of the command and tx queues, this establishes the overall\n * size of the largest command we send to uCode, except for commands that\n * aren't fully copied and use other TFD space.\n */\nstruct iwm_device_cmd {\n    union {\n        struct {\n            struct iwm_cmd_header hdr;\n            uint8_t data[IWM_DEF_CMD_PAYLOAD_SIZE];\n        };\n        struct {\n            struct iwm_cmd_header_wide hdr_wide;\n            uint8_t data_wide[IWM_DEF_CMD_PAYLOAD_SIZE -\n                    sizeof(struct iwm_cmd_header_wide) +\n                    sizeof(struct iwm_cmd_header)];\n        };\n    };\n} __packed;\n\nstruct iwm_rx_packet {\n    /*\n     * The first 4 bytes of the RX frame header contain both the RX frame\n     * size and some flags.\n     * Bit fields:\n     * 31:    flag flush RB request\n     * 30:    flag ignore TC (terminal counter) request\n     * 29:    flag fast IRQ request\n     * 28-26: Reserved\n     * 25:    Offload enabled\n     * 24:    RPF enabled\n     * 23:    RSS enabled\n     * 22:    Checksum enabled\n     * 21-16: RX queue\n     * 15-14: Reserved\n     * 13-00: RX frame size\n     */\n    uint32_t len_n_flags;\n    struct iwm_cmd_header hdr;\n    uint8_t data[];\n} __packed;\n\n#define    IWM_FH_RSCSR_FRAME_SIZE_MSK    0x00003fff\n#define    IWM_FH_RSCSR_FRAME_INVALID    0x55550000\n#define    IWM_FH_RSCSR_FRAME_ALIGN    0x40\n#define    IWM_FH_RSCSR_RPA_EN        (1 << 25)\n#define    IWM_FH_RSCSR_RADA_EN        (1 << 26)\n#define    IWM_FH_RSCSR_RXQ_POS        16\n#define    IWM_FH_RSCSR_RXQ_MASK        0x3F0000\n\nstatic uint32_t\niwm_rx_packet_len(const struct iwm_rx_packet *pkt)\n{\n\n    return le32toh(pkt->len_n_flags) & IWM_FH_RSCSR_FRAME_SIZE_MSK;\n}\n\nstatic uint32_t\niwm_rx_packet_payload_len(const struct iwm_rx_packet *pkt)\n{\n\n    return iwm_rx_packet_len(pkt) - sizeof(pkt->hdr);\n}\n\n\n#define IWM_MIN_DBM    -100\n#define IWM_MAX_DBM    -33    /* realistic guess */\n\n#define IWM_READ(sc, reg)                        \\\n    bus_space_read_4((sc)->sc_st, (sc)->sc_sh, (reg))\n\n#define IWM_WRITE(sc, reg, val)                        \\\n    bus_space_write_4((sc)->sc_st, (sc)->sc_sh, (reg), (val))\n\n#define IWM_WRITE_1(sc, reg, val)                    \\\n    bus_space_write_1((sc)->sc_st, (sc)->sc_sh, (reg), (val))\n\n#define IWM_SETBITS(sc, reg, mask)                    \\\n    IWM_WRITE(sc, reg, IWM_READ(sc, reg) | (mask))\n\n#define IWM_CLRBITS(sc, reg, mask)                    \\\n    IWM_WRITE(sc, reg, IWM_READ(sc, reg) & ~(mask))\n\n#define IWM_BARRIER_WRITE(sc)                        \\\n    bus_space_barrier((sc)->sc_st, (sc)->sc_sh, 0, (sc)->sc_sz,    \\\n        BUS_SPACE_BARRIER_WRITE)\n\n#define IWM_BARRIER_READ_WRITE(sc)                    \\\n    bus_space_barrier((sc)->sc_st, (sc)->sc_sh, 0, (sc)->sc_sz,    \\\n        BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE)\n"
  },
  {
    "path": "itlwm/hal_iwm/if_iwmvar.h",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n/*    $OpenBSD: if_iwmvar.h,v 1.57 2020/10/11 07:05:28 mpi Exp $    */\n\n/*\n * Copyright (c) 2014 genua mbh <info@genua.de>\n * Copyright (c) 2014 Fixup Software Ltd.\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n/*-\n * Based on BSD-licensed source modules in the Linux iwlwifi driver,\n * which were used as the reference documentation for this implementation.\n *\n * Driver version we are currently based off of is\n * Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd)\n *\n ***********************************************************************\n *\n * This file is provided under a dual BSD/GPLv2 license.  When using or\n * redistributing this file, you may do so under either license.\n *\n * GPL LICENSE SUMMARY\n *\n * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of version 2 of the GNU General Public License as\n * published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful, but\n * WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,\n * USA\n *\n * The full GNU General Public License is included in this distribution\n * in the file called COPYING.\n *\n * Contact Information:\n *  Intel Linux Wireless <ilw@linux.intel.com>\n * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497\n *\n *\n * BSD LICENSE\n *\n * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in\n *    the documentation and/or other materials provided with the\n *    distribution.\n *  * Neither the name Intel Corporation nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*-\n * Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n#include <net80211/ieee80211_var.h>\n#include <net80211/ieee80211_amrr.h>\n#include <net80211/ieee80211_ra.h>\n#include <net80211/ieee80211_radiotap.h>\n\n#include <IOKit/network/IOMbufMemoryCursor.h>\n#include <IOKit/IODMACommand.h>\n\n#include \"rs.h\"\n\nstruct iwm_rx_radiotap_header {\n    struct ieee80211_radiotap_header wr_ihdr;\n    uint64_t    wr_tsft;\n    uint8_t        wr_flags;\n    uint8_t        wr_rate;\n    uint16_t    wr_chan_freq;\n    uint16_t    wr_chan_flags;\n    int8_t        wr_dbm_antsignal;\n    int8_t        wr_dbm_antnoise;\n} __packed;\n\n#define IWM_RX_RADIOTAP_PRESENT                        \\\n    ((1 << IEEE80211_RADIOTAP_TSFT) |                \\\n     (1 << IEEE80211_RADIOTAP_FLAGS) |                \\\n     (1 << IEEE80211_RADIOTAP_RATE) |                \\\n     (1 << IEEE80211_RADIOTAP_CHANNEL) |                \\\n     (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) |            \\\n     (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE))\n\nstruct iwm_tx_radiotap_header {\n    struct ieee80211_radiotap_header wt_ihdr;\n    uint8_t        wt_flags;\n    uint8_t        wt_rate;\n    uint16_t    wt_chan_freq;\n    uint16_t    wt_chan_flags;\n} __packed;\n\n#define IWM_TX_RADIOTAP_PRESENT                        \\\n    ((1 << IEEE80211_RADIOTAP_FLAGS) |                \\\n     (1 << IEEE80211_RADIOTAP_RATE) |                \\\n     (1 << IEEE80211_RADIOTAP_CHANNEL))\n\n#define IWM_UCODE_SECT_MAX 16\n#define IWM_FWDMASEGSZ (192*1024)\n#define IWM_FWDMASEGSZ_8000 (320*1024)\n/* sanity check value */\n#define IWM_FWMAXSIZE (2*1024*1024)\n\n/*\n * fw_status is used to determine if we've already parsed the firmware file\n *\n * In addition to the following, status < 0 ==> -error\n */\n#define IWM_FW_STATUS_NONE        0\n#define IWM_FW_STATUS_INPROGRESS    1\n#define IWM_FW_STATUS_DONE        2\n\nenum iwm_ucode_type {\n    IWM_UCODE_TYPE_REGULAR,\n    IWM_UCODE_TYPE_INIT,\n    IWM_UCODE_TYPE_WOW,\n    IWM_UCODE_TYPE_REGULAR_USNIFFER,\n    IWM_UCODE_TYPE_MAX\n};\n\nstruct iwm_fw_onesect {\n    void *fws_data;\n    uint32_t fws_len;\n    uint32_t fws_devoff;\n};\n\nstruct iwm_fw_sects {\n    struct iwm_fw_onesect fw_sect[IWM_UCODE_SECT_MAX];\n    size_t fw_totlen;\n    int fw_count;\n    uint32_t paging_mem_size;\n};\n\nstruct iwm_fw_info {\n    void *fw_rawdata;\n    size_t fw_rawsize;\n    int fw_status;\n\n    struct iwm_fw_sects fw_sects[IWM_UCODE_TYPE_MAX];\n};\n\nstruct iwm_nvm_data {\n    int n_hw_addrs;\n    uint8_t hw_addr[ETHER_ADDR_LEN];\n\n    uint8_t calib_version;\n    uint16_t calib_voltage;\n\n    uint16_t raw_temperature;\n    uint16_t kelvin_temperature;\n    uint16_t kelvin_voltage;\n    uint16_t xtal_calib[2];\n\n    int sku_cap_band_24GHz_enable;\n    int sku_cap_band_52GHz_enable;\n    int sku_cap_11n_enable;\n    int sku_cap_11ac_enable;\n    int sku_cap_amt_enable;\n    int sku_cap_ipan_enable;\n    int sku_cap_mimo_disable;\n\n    uint8_t radio_cfg_type;\n    uint8_t radio_cfg_step;\n    uint8_t radio_cfg_dash;\n    uint8_t radio_cfg_pnum;\n    uint8_t valid_tx_ant, valid_rx_ant;\n    bool vht160_supported;\n\n    uint16_t nvm_version;\n    uint8_t max_tx_pwr_half_dbm;\n\n    int lar_enabled;\n};\n\n/* max bufs per tfd the driver will use */\n#define IWM_MAX_CMD_TBS_PER_TFD 2\n\nstruct iwm_host_cmd {\n    const void *data[IWM_MAX_CMD_TBS_PER_TFD];\n    struct iwm_rx_packet *resp_pkt;\n    size_t resp_pkt_len;\n    unsigned long _rx_page_addr;\n    uint32_t _rx_page_order;\n    int handler_status;\n\n    uint32_t flags;\n    uint16_t len[IWM_MAX_CMD_TBS_PER_TFD];\n    uint8_t dataflags[IWM_MAX_CMD_TBS_PER_TFD];\n    uint32_t id;\n};\n\n/*\n * DMA glue is from iwn\n */\n\nstruct iwm_dma_info {\n\tIOBufferMemoryDescriptor* buffer;\n    bus_addr_t        paddr;\n    void             *vaddr;\n    size_t        size;\n    IODMACommand *cmd;\n};\n\n/**\n * struct iwm_fw_paging\n * @fw_paging_block: dma memory info\n * @fw_paging_size: page size\n */\nstruct iwm_fw_paging {\n    struct iwm_dma_info fw_paging_block;\n    uint32_t fw_paging_size;\n};\n\n#define IWM_TX_RING_COUNT    256\n#define IWM_TX_RING_LOMARK    192\n#define IWM_TX_RING_HIMARK    224\n\nstruct iwm_tx_data {\n    bus_dmamap_t    map;\n    bus_addr_t    cmd_paddr;\n    bus_addr_t    scratch_paddr;\n    mbuf_t m;\n    struct iwm_node *in;\n    int txmcs;\n    int txrate;\n    int totlen;\n    uint16_t fc;\n    \n    struct ieee80211_tx_info info;\n};\n\nstruct iwm_tx_ring {\n    struct iwm_dma_info    desc_dma;\n    struct iwm_dma_info    cmd_dma;\n    struct iwm_tfd        *desc;\n    struct iwm_device_cmd    *cmd;\n    struct iwm_tx_data    data[IWM_TX_RING_COUNT];\n    int            qid;\n    int            queued;\n    int            cur;\n    int            read;\n    int            tail;\n};\n\n#define IWM_RX_MQ_RING_COUNT    512\n#define IWM_RX_RING_COUNT    256\n/* Linux driver optionally uses 8k buffer */\n#define IWM_RBUF_SIZE        4096\n\nstruct iwm_rx_data {\n    mbuf_t m;\n    bus_dmamap_t    map;\n};\n\nstruct iwm_rx_ring {\n    struct iwm_dma_info    free_desc_dma;\n    struct iwm_dma_info    stat_dma;\n    struct iwm_dma_info    used_desc_dma;\n    void            *desc;\n    struct iwm_rb_status    *stat;\n    struct iwm_rx_data    data[IWM_RX_MQ_RING_COUNT];\n    int            cur;\n};\n\n#define IWM_FLAG_USE_ICT    0x01    /* using Interrupt Cause Table */\n#define IWM_FLAG_RFKILL        0x02    /* radio kill switch is set */\n#define IWM_FLAG_SCANNING    0x04    /* scan in progress */\n#define IWM_FLAG_MAC_ACTIVE    0x08    /* MAC context added to firmware */\n#define IWM_FLAG_BINDING_ACTIVE    0x10    /* MAC->PHY binding added to firmware */\n#define IWM_FLAG_STA_ACTIVE    0x20    /* AP added to firmware station table */\n#define IWM_FLAG_TE_ACTIVE    0x40    /* time event is scheduled */\n#define IWM_FLAG_HW_ERR        0x80    /* hardware error occurred */\n#define IWM_FLAG_SHUTDOWN    0x100    /* shutting down; new tasks forbidden */\n#define IWM_FLAG_BGSCAN        0x200    /* background scan in progress */\n\nstruct iwm_ucode_status {\n    uint32_t uc_error_event_table;\n    uint32_t uc_umac_error_event_table;\n    uint32_t uc_log_event_table;\n\n    int uc_ok;\n    int uc_intr;\n};\n\n#define IWM_CMD_RESP_MAX PAGE_SIZE\n\n/* lower blocks contain EEPROM image and calibration data */\n#define IWM_OTP_LOW_IMAGE_SIZE_FAMILY_7000     16384\n#define IWM_OTP_LOW_IMAGE_SIZE_FAMILY_8000    32768\n\n#define IWM_TE_SESSION_PROTECTION_MAX_TIME_MS 1000\n#define IWM_TE_SESSION_PROTECTION_MIN_TIME_MS 400\n\nenum IWM_CMD_MODE {\n    IWM_CMD_ASYNC        = (1 << 0),\n    IWM_CMD_WANT_RESP    = (1 << 1),\n    IWM_CMD_SEND_IN_RFKILL    = (1 << 2),\n};\nenum iwm_hcmd_dataflag {\n    IWM_HCMD_DFL_NOCOPY     = (1 << 0),\n    IWM_HCMD_DFL_DUP        = (1 << 1),\n};\n\n#define IWM_NUM_PAPD_CH_GROUPS    9\n#define IWM_NUM_TXP_CH_GROUPS    9\n\nstruct iwm_phy_db_entry {\n    uint16_t size;\n    uint8_t *data;\n};\n\nstruct iwm_phy_db {\n    struct iwm_phy_db_entry    cfg;\n    struct iwm_phy_db_entry    calib_nch;\n    struct iwm_phy_db_entry    calib_ch_group_papd[IWM_NUM_PAPD_CH_GROUPS];\n    struct iwm_phy_db_entry    calib_ch_group_txp[IWM_NUM_TXP_CH_GROUPS];\n};\n\nstruct iwm_phy_ctxt {\n    uint16_t id;\n    uint16_t color;\n    uint32_t ref;\n    struct ieee80211_channel *channel;\n};\n\nstruct iwm_bf_data {\n    int bf_enabled;        /* filtering    */\n    int ba_enabled;        /* abort    */\n    int ave_beacon_signal;\n    int last_cqm_event;\n};\n\n/**\n * struct iwm_reorder_buffer - per ra/tid/queue reorder buffer\n * @head_sn: reorder window head sn\n * @num_stored: number of mpdus stored in the buffer\n * @buf_size: the reorder buffer size as set by the last addba request\n * @queue: queue of this reorder buffer\n * @last_amsdu: track last ASMDU SN for duplication detection\n * @last_sub_index: track ASMDU sub frame index for duplication detection\n * @reorder_timer: timer for frames are in the reorder buffer. For AMSDU\n *     it is the time of last received sub-frame\n * @removed: prevent timer re-arming\n * @valid: reordering is valid for this queue\n * @consec_oldsn_drops: consecutive drops due to old SN\n * @consec_oldsn_ampdu_gp2: A-MPDU GP2 timestamp to track\n *     when to apply old SN consecutive drop workaround\n * @consec_oldsn_prev_drop: track whether or not an MPDU\n *     that was single/part of the previous A-MPDU was\n *     dropped due to old SN\n */\nstruct iwm_reorder_buffer {\n    uint16_t head_sn;\n    uint16_t num_stored;\n    uint16_t buf_size;\n    uint16_t last_amsdu;\n    uint8_t last_sub_index;\n    CTimeout *reorder_timer;\n    int removed;\n    int valid;\n    unsigned int consec_oldsn_drops;\n    uint32_t consec_oldsn_ampdu_gp2;\n    unsigned int consec_oldsn_prev_drop;\n#define IWM_AMPDU_CONSEC_DROPS_DELBA   20\n};\n\n/**\n * struct iwm_reorder_buf_entry - reorder buffer entry per frame sequence\n number\n * @frames: list of mbufs stored (A-MSDU subframes share a sequence number)\n * @reorder_time: time the packet was stored in the reorder buffer\n */\nstruct iwm_reorder_buf_entry {\n    struct mbuf_list frames;\n    struct timeval reorder_time;\n    uint32_t rx_pkt_status;\n    int chanidx;\n    int is_shortpre;\n    uint32_t rate_n_flags;\n    uint32_t device_timestamp;\n    struct ieee80211_rxinfo rxi;\n};\n\n/**\n * struct iwm_rxba_data - BA session data\n * @sta_id: station id\n * @tid: tid of the session\n * @baid: baid of the session\n * @timeout: the timeout set in the addba request\n * @entries_per_queue: # of buffers per queue\n * @last_rx: last rx timestamp, updated only if timeout passed from last update\n * @session_timer: timer to check if BA session expired, runs at 2 * timeout\n * @sc: softc pointer, needed for timer context\n * @reorder_buf: reorder buffer\n * @reorder_buf_data: buffered frames, one entry per sequence number\n */\nstruct iwm_rxba_data {\n    uint8_t sta_id;\n    uint8_t tid;\n    uint8_t baid;\n    uint16_t timeout;\n    uint16_t entries_per_queue;\n    struct timeval last_rx;\n    CTimeout *session_timer;\n    struct iwm_softc *sc;\n    struct iwm_reorder_buffer reorder_buf;\n    struct iwm_reorder_buf_entry entries[IEEE80211_BA_MAX_WINSZ];\n};\n\nstatic inline struct iwm_rxba_data *\niwm_rxba_data_from_reorder_buf(struct iwm_reorder_buffer *buf)\n{\n    return (struct iwm_rxba_data *)((uint8_t *)buf -\n                    offsetof(struct iwm_rxba_data, reorder_buf));\n}\n\n/**\n * struct iwm_rxq_dup_data - per station per rx queue data\n * @last_seq: last sequence per tid for duplicate packet detection\n * @last_sub_frame: last subframe packet\n */\nstruct iwm_rxq_dup_data {\n    uint16_t last_seq[IWM_MAX_TID_COUNT + 1];\n    uint8_t last_sub_frame[IWM_MAX_TID_COUNT + 1];\n};\n\nstruct iwm_tx_ba {\n   struct iwm_node *    wn;\n    uint32_t rate_n_flags;\n    uint8_t lq_color;\n    uint16_t tx_time;\n    uint32_t tx_count_last;\n    uint32_t tx_count;\n    unsigned long tpt_meas_start;\n};\n\nstruct iwm_ba_task_data {\n    uint32_t        start_tidmask;\n    uint32_t        stop_tidmask;\n};\n\nstruct iwm_softc {\n\tstruct device sc_dev;\n\tstruct ieee80211com sc_ic;\n\tint (*sc_newstate)(struct ieee80211com *, enum ieee80211_state, int);\n\tint sc_newstate_pending;\n\n\tstruct ieee80211_amrr sc_amrr;\n\tCTimeout *sc_calib_to;\n\tCTimeout *sc_led_blink_to;\n    pci_intr_handle_t ih;\n\n\tstruct task\t\tinit_task; /* NB: not reference-counted */\n//\tstruct refcnt\t\ttask_refs;\n\tstruct task\t\tnewstate_task;\n\tenum ieee80211_state\tns_nstate;\n\tint\t\t\tns_arg;\n\n\t/* Task for firmware BlockAck setup/teardown and its arguments. */\n\tstruct task\t\tba_task;\n\tstruct iwm_ba_task_data    ba_rx;\n    struct iwm_ba_task_data    ba_tx;\n\n    /* Task for ERP/HT prot/slot-time/EDCA updates. */\n    struct task\t\tmac_ctxt_task;\n    struct task     chan_ctxt_task;\n\n\tbus_space_tag_t sc_st;\n\tbus_space_handle_t sc_sh;\n\tbus_size_t sc_sz;\n\tbus_dma_tag_t sc_dmat;\n\tpci_chipset_tag_t sc_pct;\n\tpcitag_t sc_pcitag;\n\tIOInterruptEventSource *sc_ih;\n    int sc_msix;\n\n\t/* TX scheduler rings. */\n\tstruct iwm_dma_info\t\tsched_dma;\n\tuint32_t\t\t\tsched_base;\n\n\t/* TX/RX rings. */\n\tstruct iwm_tx_ring txq[IWM_MAX_QUEUES];\n\tstruct iwm_rx_ring rxq;\n\tint qfullmsk;\n    int cmdqid;\n    \n    uint8_t sc_mgmt_last_antenna_idx;\n    uint8_t sc_tx_ant;\n\n\tint sc_sf_state;\n\n\t/* ICT table. */\n\tstruct iwm_dma_info\tict_dma;\n\tint\t\t\tict_cur;\n\n\tint sc_hw_rev;\n#define IWM_SILICON_A_STEP\t0\n#define IWM_SILICON_B_STEP\t1\n#define IWM_SILICON_C_STEP\t2\n#define IWM_SILICON_D_STEP\t3\n\tint sc_hw_id;\n\tint sc_device_family;\n#define IWM_DEVICE_FAMILY_7000\t1\n#define IWM_DEVICE_FAMILY_8000\t2\n#define IWM_DEVICE_FAMILY_9000  3\n\n\tstruct iwm_dma_info kw_dma;\n\tstruct iwm_dma_info fw_dma;\n\n\tint sc_fw_chunk_done;\n\tint sc_init_complete;\n#define IWM_INIT_COMPLETE\t0x01\n#define IWM_CALIB_COMPLETE\t0x02\n\n\tstruct iwm_ucode_status sc_uc;\n\tenum iwm_ucode_type sc_uc_current;\n\tchar sc_fwver[32];\n\n\tint sc_capaflags;\n\tint sc_capa_max_probe_len;\n\tint sc_capa_n_scan_channels;\n\tuint8_t sc_ucode_api[howmany(IWM_NUM_UCODE_TLV_API, NBBY)];\n    uint8_t sc_enabled_capa[howmany(IWM_NUM_UCODE_TLV_CAPA, NBBY)];\n#define IWM_MAX_FW_CMD_VERSIONS    64\n    struct iwm_fw_cmd_version cmd_versions[IWM_MAX_FW_CMD_VERSIONS];\n    int n_cmd_versions;\n\tchar sc_fw_mcc[3];\n    uint16_t sc_fw_mcc_int;\n\n\tint sc_intmask;\n\tint sc_flags;\n    \n    uint32_t sc_fh_init_mask;\n    uint32_t sc_hw_init_mask;\n    uint32_t sc_fh_mask;\n    uint32_t sc_hw_mask;\n\n\t/*\n\t * So why do we need a separate stopped flag and a generation?\n\t * the former protects the device from issueing commands when it's\n\t * stopped (duh).  The latter protects against race from a very\n\t * fast stop/unstop cycle where threads waiting for responses do\n\t * not have a chance to run in between.  Notably: we want to stop\n\t * the device from interrupt context when it craps out, so we\n\t * don't have the luxury of waiting for quiescense.\n\t */\n\tint sc_generation;\n\n//\tstruct rwlock ioctl_rwl;\n\n\tint sc_cap_off; /* PCIe caps */\n\n\tconst char *sc_fwname;\n    bus_size_t sc_fwdmasegsz;\n    size_t sc_nvm_max_section_size;\n    struct iwm_fw_info sc_fw;\n    int sc_fw_phy_config;\n    struct iwm_tlv_calib_ctrl sc_default_calib[IWM_UCODE_TYPE_MAX];\n\n\tstruct iwm_nvm_data sc_nvm;\n\tstruct iwm_phy_db sc_phy_db;\n\n\tstruct iwm_bf_data sc_bf;\n\n\tint sc_tx_timer[IWM_MAX_QUEUES];\n\tint sc_rx_ba_sessions;\n\n\tint sc_scan_last_antenna;\n\n\tint sc_fixed_ridx;\n\n\tint sc_staid;\n\tint sc_nodecolor;\n\n\tuint8_t *sc_cmd_resp_pkt[IWM_TX_RING_COUNT];\n\tsize_t sc_cmd_resp_len[IWM_TX_RING_COUNT];\n\tint sc_nic_locks;\n\n\tstruct taskq *sc_nswq;\n\n\tstruct iwm_rx_phy_info sc_last_phy_info;\n\tint sc_ampdu_ref;\n#define IWM_MAX_BAID   32\n    struct iwm_rxba_data sc_rxba_data[IWM_MAX_BAID];\n    \n    int agg_queue_mask;\n    int agg_tid_disable;\n    struct iwm_tx_ba sc_tx_ba[IEEE80211_NUM_TID];\n\n\tuint32_t sc_time_event_uid;\n\n\t/* phy contexts.  we only use the first one */\n\tstruct iwm_phy_ctxt sc_phyctxt[IWM_NUM_PHY_CTX];\n\n\tstruct iwm_notif_statistics sc_stats;\n\tint sc_noise;\n\n\tint host_interrupt_operation_mode;\n    int sc_ltr_enabled;\n    enum iwm_nvm_type nvm_type;\n    int support_ldpc;\n    uint8_t non_shared_ant;\n    \n    int sc_mqrx_supported;\n    int sc_integrated;\n    int sc_ltr_delay;\n    int sc_xtal_latency;\n    int sc_low_latency_xtal;\n    \n    /*\n     * Paging parameters - All of the parameters should be set by the\n     * opmode when paging is enabled\n     */\n    struct iwm_fw_paging fw_paging_db[IWM_NUM_OF_FW_PAGING_BLOCKS];\n    uint16_t num_of_paging_blk;\n    uint16_t num_of_pages_in_last_blk;\n\n#if NBPFILTER > 0\n\tcaddr_t\t\t\tsc_drvbpf;\n\n\tunion {\n\t\tstruct iwm_rx_radiotap_header th;\n\t\tuint8_t\tpad[IEEE80211_RADIOTAP_HDRLEN];\n\t} sc_rxtapu;\n#define sc_rxtap\tsc_rxtapu.th\n\tint\t\t\tsc_rxtap_len;\n\n\tunion {\n\t\tstruct iwm_tx_radiotap_header th;\n\t\tuint8_t\tpad[IEEE80211_RADIOTAP_HDRLEN];\n\t} sc_txtapu;\n#define sc_txtap\tsc_txtapu.th\n\tint\t\t\tsc_txtap_len;\n#endif\n    union {\n        struct iwl_lq_sta_rs_fw rs_fw;\n        struct iwl_lq_sta rs_drv;\n    } lq_sta;\n    int tx_protection;\n};\n\nstruct iwm_node {\n    struct ieee80211_node in_ni;\n    struct iwm_phy_ctxt *in_phyctxt;\n    uint8_t in_macaddr[ETHER_ADDR_LEN];\n\n    uint16_t in_id;\n    uint16_t in_color;\n\n    struct ieee80211_amrr_node in_amn;\n    int lq_rate_mismatch;\n    uint32_t next_ampdu_id;\n    \n    struct iwm_rxq_dup_data dup_data;\n};\n#define IWM_STATION_ID 0\n#define IWM_AUX_STA_ID 1\n#define IWM_MONITOR_STA_ID 2\n\n#define IWM_ICT_SIZE        4096\n#define IWM_ICT_COUNT        (IWM_ICT_SIZE / sizeof (uint32_t))\n#define IWM_ICT_PADDR_SHIFT    12\n"
  },
  {
    "path": "itlwm/hal_iwm/io.cpp",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n/*    $OpenBSD: if_iwm.c,v 1.316 2020/12/07 20:09:24 tobhe Exp $    */\n\n/*\n * Copyright (c) 2014, 2016 genua gmbh <info@genua.de>\n *   Author: Stefan Sperling <stsp@openbsd.org>\n * Copyright (c) 2014 Fixup Software Ltd.\n * Copyright (c) 2017 Stefan Sperling <stsp@openbsd.org>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n/*-\n * Based on BSD-licensed source modules in the Linux iwlwifi driver,\n * which were used as the reference documentation for this implementation.\n *\n ***********************************************************************\n *\n * This file is provided under a dual BSD/GPLv2 license.  When using or\n * redistributing this file, you may do so under either license.\n *\n * GPL LICENSE SUMMARY\n *\n * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.\n * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH\n * Copyright(c) 2016 Intel Deutschland GmbH\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of version 2 of the GNU General Public License as\n * published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful, but\n * WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,\n * USA\n *\n * The full GNU General Public License is included in this distribution\n * in the file called COPYING.\n *\n * Contact Information:\n *  Intel Linux Wireless <ilw@linux.intel.com>\n * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497\n *\n *\n * BSD LICENSE\n *\n * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.\n * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH\n * Copyright(c) 2016 Intel Deutschland GmbH\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in\n *    the documentation and/or other materials provided with the\n *    distribution.\n *  * Neither the name Intel Corporation nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*-\n * Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n#include \"ItlIwm.hpp\"\n#include <IOKit/IODMACommand.h>\n\nuint32_t ItlIwm::\niwm_read_prph_unlocked(struct iwm_softc *sc, uint32_t addr)\n{\n    IWM_WRITE(sc,\n        IWM_HBUS_TARG_PRPH_RADDR, ((addr & 0x000fffff) | (3 << 24)));\n    IWM_BARRIER_READ_WRITE(sc);\n    return IWM_READ(sc, IWM_HBUS_TARG_PRPH_RDAT);\n}\n\nuint32_t ItlIwm::\niwm_read_prph(struct iwm_softc *sc, uint32_t addr)\n{\n    iwm_nic_assert_locked(sc);\n    return iwm_read_prph_unlocked(sc, addr);\n}\n\nvoid ItlIwm::\niwm_write_prph_unlocked(struct iwm_softc *sc, uint32_t addr, uint32_t val)\n{\n    IWM_WRITE(sc,\n              IWM_HBUS_TARG_PRPH_WADDR, ((addr & 0x000fffff) | (3 << 24)));\n    IWM_BARRIER_WRITE(sc);\n    IWM_WRITE(sc, IWM_HBUS_TARG_PRPH_WDAT, val);\n}\n\nvoid ItlIwm::\niwm_write_prph(struct iwm_softc *sc, uint32_t addr, uint32_t val)\n{\n    iwm_nic_assert_locked(sc);\n    iwm_write_prph_unlocked(sc, addr, val);\n}\n\nvoid ItlIwm::\niwm_write_prph64(struct iwm_softc *sc, uint64_t addr, uint64_t val)\n{\n    iwm_write_prph(sc, (uint32_t)addr, val & 0xffffffff);\n    iwm_write_prph(sc, (uint32_t)addr + 4, val >> 32);\n}\n\nint ItlIwm::\niwm_read_mem(struct iwm_softc *sc, uint32_t addr, void *buf, int dwords)\n{\n    int offs, err = 0;\n    uint32_t *vals = (uint32_t*)buf;\n\n    if (iwm_nic_lock(sc)) {\n        IWM_WRITE(sc, IWM_HBUS_TARG_MEM_RADDR, addr);\n        for (offs = 0; offs < dwords; offs++)\n            vals[offs] = IWM_READ(sc, IWM_HBUS_TARG_MEM_RDAT);\n        iwm_nic_unlock(sc);\n    } else {\n        err = EBUSY;\n    }\n    return err;\n}\n\nint ItlIwm::\niwm_write_mem(struct iwm_softc *sc, uint32_t addr, const void *buf, int dwords)\n{\n    int offs;\n    const uint32_t *vals = (const uint32_t*)buf;\n\n    if (iwm_nic_lock(sc)) {\n        IWM_WRITE(sc, IWM_HBUS_TARG_MEM_WADDR, addr);\n        /* WADDR auto-increments */\n        for (offs = 0; offs < dwords; offs++) {\n            uint32_t val = vals ? vals[offs] : 0;\n            IWM_WRITE(sc, IWM_HBUS_TARG_MEM_WDAT, val);\n        }\n        iwm_nic_unlock(sc);\n    } else {\n        return EBUSY;\n    }\n    return 0;\n}\n\nint ItlIwm::\niwm_write_mem32(struct iwm_softc *sc, uint32_t addr, uint32_t val)\n{\n    return iwm_write_mem(sc, addr, &val, 1);\n}\n\nint ItlIwm::\niwm_poll_bit(struct iwm_softc *sc, int reg, uint32_t bits, uint32_t mask,\n    int timo)\n{\n    for (;;) {\n        if ((IWM_READ(sc, reg) & mask) == (bits & mask)) {\n            return 1;\n        }\n        if (timo < 10) {\n            return 0;\n        }\n        timo -= 10;\n        DELAY(10);\n    }\n}\n\nint ItlIwm::\niwm_nic_lock(struct iwm_softc *sc)\n{\n    if (sc->sc_nic_locks > 0) {\n        sc->sc_nic_locks++;\n        return 1; /* already locked */\n    }\n\n    IWM_SETBITS(sc, IWM_CSR_GP_CNTRL,\n        IWM_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);\n\n    if (sc->sc_device_family >= IWM_DEVICE_FAMILY_8000)\n        DELAY(2);\n\n    if (iwm_poll_bit(sc, IWM_CSR_GP_CNTRL,\n        IWM_CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,\n        IWM_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY\n         | IWM_CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP, 150000)) {\n        sc->sc_nic_locks++;\n        return 1;\n    }\n\n    XYLog(\"%s: acquiring device failed\\n\", DEVNAME(sc));\n    return 0;\n}\n\nvoid ItlIwm::\niwm_nic_assert_locked(struct iwm_softc *sc)\n{\n    if (sc->sc_nic_locks <= 0)\n        panic(\"%s: nic locks counter %d\", DEVNAME(sc), sc->sc_nic_locks);\n}\n\nvoid ItlIwm::\niwm_nic_unlock(struct iwm_softc *sc)\n{\n    if (sc->sc_nic_locks > 0) {\n        if (--sc->sc_nic_locks == 0)\n            IWM_CLRBITS(sc, IWM_CSR_GP_CNTRL,\n                IWM_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);\n    } else\n        XYLog(\"%s: NIC already unlocked\\n\", DEVNAME(sc));\n}\n\nvoid ItlIwm::\niwm_set_bits_mask_prph(struct iwm_softc *sc, uint32_t reg, uint32_t bits,\n    uint32_t mask)\n{\n    uint32_t val;\n\n    /* XXX: no error path? */\n    if (iwm_nic_lock(sc)) {\n        val = iwm_read_prph(sc, reg) & mask;\n        val |= bits;\n        iwm_write_prph(sc, reg, val);\n        iwm_nic_unlock(sc);\n    }\n}\n\nvoid ItlIwm::\niwm_set_bits_prph(struct iwm_softc *sc, uint32_t reg, uint32_t bits)\n{\n    iwm_set_bits_mask_prph(sc, reg, bits, ~0);\n}\n\nvoid ItlIwm::\niwm_clear_bits_prph(struct iwm_softc *sc, uint32_t reg, uint32_t bits)\n{\n    iwm_set_bits_mask_prph(sc, reg, 0, ~bits);\n}\n\nbool allocDmaMemory2(struct iwm_dma_info *dma, size_t size, int alignment)\n{\n    IOBufferMemoryDescriptor *bmd;\n    IODMACommand::Segment64 seg;\n    UInt64 ofs = 0;\n    UInt32 numSegs = 1;\n    \n    bmd = IOBufferMemoryDescriptor::inTaskWithPhysicalMask(kernel_task, kIODirectionInOut | kIOMemoryPhysicallyContiguous | kIOMapInhibitCache, size, DMA_BIT_MASK(36));\n    \n    if (bmd == NULL) {\n        XYLog(\"%s alloc DMA memory failed.\\n\", __FUNCTION__);\n        return false;\n    }\n    \n    bmd->prepare();\n    IODMACommand *cmd = IODMACommand::withSpecification(kIODMACommandOutputHost64, 64, 0, IODMACommand::kMapped, 0, alignment);\n    \n    if (cmd == NULL) {\n        XYLog(\"%s alloc IODMACommand memory failed.\\n\", __FUNCTION__);\n        bmd->complete();\n        bmd->release();\n        return false;\n    }\n    \n    cmd->setMemoryDescriptor(bmd);\n\n    if (cmd->gen64IOVMSegments(&ofs, &seg, &numSegs) != kIOReturnSuccess) {\n        cmd->release();\n        cmd = NULL;\n        bmd->complete();\n        bmd->release();\n        bmd = NULL;\n        return false;\n    }\n    dma->paddr = seg.fIOVMAddr;\n    dma->vaddr = bmd->getBytesNoCopy();\n    dma->size = size;\n    dma->buffer = bmd;\n    dma->cmd = cmd;\n    memset(dma->vaddr, 0, dma->size);\n    return true;\n}\n\nvoid ItlIwm::\niwm_dma_contig_free(struct iwm_dma_info *dma)\n{\n    if (dma == NULL || dma->cmd == NULL)\n        return;\n    if (dma->vaddr == NULL)\n        return;\n    dma->cmd->clearMemoryDescriptor();\n    dma->cmd->release();\n    dma->cmd = NULL;\n    dma->buffer->complete();\n    dma->buffer->release();\n    dma->buffer = NULL;\n    dma->vaddr = NULL;\n}\n\nint ItlIwm::\niwm_dma_contig_alloc(bus_dma_tag_t tag, struct iwm_dma_info *dma, bus_size_t size, bus_size_t alignment)\n{\n    if (!allocDmaMemory2(dma, size, alignment)) {\n        return 1;\n    }\n    \n    return 0;\n}\n"
  },
  {
    "path": "itlwm/hal_iwm/itlhdr.h",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n/*    $OpenBSD: if_iwm.c,v 1.316 2020/12/07 20:09:24 tobhe Exp $    */\n\n/*\n * Copyright (c) 2014, 2016 genua gmbh <info@genua.de>\n *   Author: Stefan Sperling <stsp@openbsd.org>\n * Copyright (c) 2014 Fixup Software Ltd.\n * Copyright (c) 2017 Stefan Sperling <stsp@openbsd.org>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n/*-\n * Based on BSD-licensed source modules in the Linux iwlwifi driver,\n * which were used as the reference documentation for this implementation.\n *\n ***********************************************************************\n *\n * This file is provided under a dual BSD/GPLv2 license.  When using or\n * redistributing this file, you may do so under either license.\n *\n * GPL LICENSE SUMMARY\n *\n * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.\n * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH\n * Copyright(c) 2016 Intel Deutschland GmbH\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of version 2 of the GNU General Public License as\n * published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful, but\n * WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,\n * USA\n *\n * The full GNU General Public License is included in this distribution\n * in the file called COPYING.\n *\n * Contact Information:\n *  Intel Linux Wireless <ilw@linux.intel.com>\n * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497\n *\n *\n * BSD LICENSE\n *\n * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.\n * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH\n * Copyright(c) 2016 Intel Deutschland GmbH\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in\n *    the documentation and/or other materials provided with the\n *    distribution.\n *  * Neither the name Intel Corporation nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*-\n * Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n#ifndef itlhdr_h\n#define itlhdr_h\n\n#include <sys/param.h>\n#include <sys/conf.h>\n#include <sys/kernel.h>\n#include <sys/malloc.h>\n#include <sys/mbuf.h>\n#include <sys/proc.h>\n#include <sys/socket.h>\n#include <sys/sockio.h>\n#include <sys/systm.h>\n#include <sys/endian.h>\n#include <sys/kpi_mbuf.h>\n\n#include \"if_iwmreg.h\"\n#include \"if_iwmvar.h\"\n#include <sys/pcireg.h>\n\n#define DEVNAME(_s)    (\"itlwm\")\n#define IWM_DEBUG\n\n#ifdef IWM_DEBUG\n#define DPRINTF(x)    do { if (iwm_debug > 0) XYLog x; } while (0)\n#define DPRINTFN(n, x)    do { if (iwm_debug >= (n)) XYLog x; } while (0)\nextern int iwm_debug;\n#else\n#define DPRINTF(x)    do { ; } while (0)\n#define DPRINTFN(n, x)    do { ; } while (0)\n#endif\n\n#define M_DEVBUF 2\n#define M_WAIT 3\n#define DELAY IODelay\n\n#define    INFSLP    UINT64_MAX\n\n#define IC2IFP(_ic_) (&(_ic_)->ic_if)\n#define LLADDR(s) ((caddr_t)((s)->sdl_data + (s)->sdl_nlen))\n\nconst uint8_t iwm_nvm_channels[] = {\n    /* 2.4 GHz */\n    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,\n    /* 5 GHz */\n    36, 40, 44 , 48, 52, 56, 60, 64,\n    100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144,\n    149, 153, 157, 161, 165\n};\n\nconst uint8_t iwm_nvm_channels_8000[] = {\n    /* 2.4 GHz */\n    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,\n    /* 5 GHz */\n    36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92,\n    96, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144,\n    149, 153, 157, 161, 165, 169, 173, 177, 181\n};\n\n#define IWM_NUM_2GHZ_CHANNELS    14\n#define IWM_FIRST_2GHZ_HT_MINUS        5\n#define IWM_LAST_2GHZ_HT_PLUS        9\n\nstruct iwm_nvm_section {\n    uint16_t length;\n    uint8_t *data;\n};\n\n/* Map ieee80211_edca_ac categories to firmware Tx FIFO. */\nconst uint8_t iwm_ac_to_tx_fifo[] = {\n    IWM_TX_FIFO_BE,\n    IWM_TX_FIFO_BK,\n    IWM_TX_FIFO_VI,\n    IWM_TX_FIFO_VO,\n};\n\n#endif /* itlhdr_h */\n"
  },
  {
    "path": "itlwm/hal_iwm/led.cpp",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n/*    $OpenBSD: if_iwm.c,v 1.316 2020/12/07 20:09:24 tobhe Exp $    */\n\n/*\n * Copyright (c) 2014, 2016 genua gmbh <info@genua.de>\n *   Author: Stefan Sperling <stsp@openbsd.org>\n * Copyright (c) 2014 Fixup Software Ltd.\n * Copyright (c) 2017 Stefan Sperling <stsp@openbsd.org>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n/*-\n * Based on BSD-licensed source modules in the Linux iwlwifi driver,\n * which were used as the reference documentation for this implementation.\n *\n ***********************************************************************\n *\n * This file is provided under a dual BSD/GPLv2 license.  When using or\n * redistributing this file, you may do so under either license.\n *\n * GPL LICENSE SUMMARY\n *\n * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.\n * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH\n * Copyright(c) 2016 Intel Deutschland GmbH\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of version 2 of the GNU General Public License as\n * published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful, but\n * WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,\n * USA\n *\n * The full GNU General Public License is included in this distribution\n * in the file called COPYING.\n *\n * Contact Information:\n *  Intel Linux Wireless <ilw@linux.intel.com>\n * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497\n *\n *\n * BSD LICENSE\n *\n * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.\n * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH\n * Copyright(c) 2016 Intel Deutschland GmbH\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in\n *    the documentation and/or other materials provided with the\n *    distribution.\n *  * Neither the name Intel Corporation nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*-\n * Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n#include \"ItlIwm.hpp\"\n\nvoid ItlIwm::\niwm_led_enable(struct iwm_softc *sc)\n{\n    IWM_WRITE(sc, IWM_CSR_LED_REG, IWM_CSR_LED_REG_TURN_ON);\n}\n\nvoid ItlIwm::\niwm_led_disable(struct iwm_softc *sc)\n{\n    IWM_WRITE(sc, IWM_CSR_LED_REG, IWM_CSR_LED_REG_TURN_OFF);\n}\n\nint ItlIwm::\niwm_led_is_enabled(struct iwm_softc *sc)\n{\n    return (IWM_READ(sc, IWM_CSR_LED_REG) == IWM_CSR_LED_REG_TURN_ON);\n}\n\n#define IWM_LED_BLINK_TIMEOUT_MSEC    200\n\nvoid ItlIwm::\niwm_led_blink_timeout(void *arg)\n{\n    struct iwm_softc *sc = (struct iwm_softc *)arg;\n    ItlIwm *that = container_of(sc, ItlIwm, com);\n\n    if (that->iwm_led_is_enabled(sc))\n        that->iwm_led_disable(sc);\n    else\n        that->iwm_led_enable(sc);\n\n    timeout_add_msec(&sc->sc_led_blink_to, IWM_LED_BLINK_TIMEOUT_MSEC);\n}\n\nvoid ItlIwm::\niwm_led_blink_start(struct iwm_softc *sc)\n{\n    timeout_add_msec(&sc->sc_led_blink_to, IWM_LED_BLINK_TIMEOUT_MSEC);\n    iwm_led_enable(sc);\n}\n\nvoid ItlIwm::\niwm_led_blink_stop(struct iwm_softc *sc)\n{\n    timeout_del(&sc->sc_led_blink_to);\n    iwm_led_disable(sc);\n}\n"
  },
  {
    "path": "itlwm/hal_iwm/mac80211.cpp",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n/*    $OpenBSD: if_iwm.c,v 1.316 2020/12/07 20:09:24 tobhe Exp $    */\n\n/*\n * Copyright (c) 2014, 2016 genua gmbh <info@genua.de>\n *   Author: Stefan Sperling <stsp@openbsd.org>\n * Copyright (c) 2014 Fixup Software Ltd.\n * Copyright (c) 2017 Stefan Sperling <stsp@openbsd.org>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n/*-\n * Based on BSD-licensed source modules in the Linux iwlwifi driver,\n * which were used as the reference documentation for this implementation.\n *\n ***********************************************************************\n *\n * This file is provided under a dual BSD/GPLv2 license.  When using or\n * redistributing this file, you may do so under either license.\n *\n * GPL LICENSE SUMMARY\n *\n * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.\n * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH\n * Copyright(c) 2016 Intel Deutschland GmbH\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of version 2 of the GNU General Public License as\n * published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful, but\n * WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,\n * USA\n *\n * The full GNU General Public License is included in this distribution\n * in the file called COPYING.\n *\n * Contact Information:\n *  Intel Linux Wireless <ilw@linux.intel.com>\n * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497\n *\n *\n * BSD LICENSE\n *\n * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.\n * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH\n * Copyright(c) 2016 Intel Deutschland GmbH\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in\n *    the documentation and/or other materials provided with the\n *    distribution.\n *  * Neither the name Intel Corporation nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*-\n * Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n#include \"ItlIwm.hpp\"\n#include <net/ethernet.h>\n#include <IOKit/IOCommandGate.h>\n#include <net80211/ieee80211_priv.h>\n#include \"rs.h\"\n\n#ifdef IWM_DEBUG\nint iwm_debug = 1;\n#endif\n\nint ItlIwm::\niwm_is_valid_channel(uint16_t ch_id)\n{\n    if (ch_id <= 14 ||\n        (36 <= ch_id && ch_id <= 64 && ch_id % 4 == 0) ||\n        (100 <= ch_id && ch_id <= 140 && ch_id % 4 == 0) ||\n        (145 <= ch_id && ch_id <= 165 && ch_id % 4 == 1))\n        return 1;\n    return 0;\n}\n\nuint8_t ItlIwm::\niwm_ch_id_to_ch_index(uint16_t ch_id)\n{\n    if (!iwm_is_valid_channel(ch_id))\n        return 0xff;\n    \n    if (ch_id <= 14)\n        return ch_id - 1;\n    if (ch_id <= 64)\n        return (ch_id + 20) / 4;\n    if (ch_id <= 140)\n        return (ch_id - 12) / 4;\n    return (ch_id - 13) / 4;\n}\n\n\nuint16_t ItlIwm::\niwm_channel_id_to_papd(uint16_t ch_id)\n{\n    if (!iwm_is_valid_channel(ch_id))\n        return 0xff;\n    \n    if (1 <= ch_id && ch_id <= 14)\n        return 0;\n    if (36 <= ch_id && ch_id <= 64)\n        return 1;\n    if (100 <= ch_id && ch_id <= 140)\n        return 2;\n    return 3;\n}\n\nuint16_t ItlIwm::\niwm_channel_id_to_txp(struct iwm_softc *sc, uint16_t ch_id)\n{\n    struct iwm_phy_db *phy_db = &sc->sc_phy_db;\n    struct iwm_phy_db_chg_txp *txp_chg;\n    int i;\n    uint8_t ch_index = iwm_ch_id_to_ch_index(ch_id);\n    \n    if (ch_index == 0xff)\n        return 0xff;\n    \n    for (i = 0; i < IWM_NUM_TXP_CH_GROUPS; i++) {\n        txp_chg = (struct iwm_phy_db_chg_txp *)phy_db->calib_ch_group_txp[i].data;\n        if (!txp_chg)\n            return 0xff;\n        /*\n         * Looking for the first channel group the max channel\n         * of which is higher than the requested channel.\n         */\n        if (le16toh(txp_chg->max_channel_idx) >= ch_index)\n            return i;\n    }\n    return 0xff;\n}\n\nint ItlIwm::\niwm_mimo_enabled(struct iwm_softc *sc)\n{\n   struct ieee80211com *ic = &sc->sc_ic;\n\n   return !sc->sc_nvm.sku_cap_mimo_disable &&\n       (ic->ic_userflags & IEEE80211_F_NOMIMO) == 0;\n}\n\nvoid ItlIwm::\niwm_init_channel_map(struct iwm_softc *sc, const uint16_t * const nvm_ch_flags,\n                     const uint8_t *nvm_channels, size_t nchan)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct iwm_nvm_data *data = &sc->sc_nvm;\n    int ch_idx;\n    struct ieee80211_channel *channel;\n    uint16_t ch_flags;\n    int is_5ghz;\n    int flags, hw_value;\n    \n    for (ch_idx = 0; ch_idx < nchan; ch_idx++) {\n        ch_flags = le16_to_cpup(nvm_ch_flags + ch_idx);\n        \n        if (ch_idx >= IWM_NUM_2GHZ_CHANNELS &&\n            !data->sku_cap_band_52GHz_enable)\n            ch_flags &= ~IWM_NVM_CHANNEL_VALID;\n        \n        if (!(ch_flags & IWM_NVM_CHANNEL_VALID))\n            continue;\n        \n        if (ch_flags & IWM_NVM_CHANNEL_160MHZ)\n            data->vht160_supported = true;\n        \n        hw_value = nvm_channels[ch_idx];\n        channel = &ic->ic_channels[hw_value];\n        \n        is_5ghz = ch_idx >= IWM_NUM_2GHZ_CHANNELS;\n        if (!is_5ghz) {\n            flags = IEEE80211_CHAN_2GHZ;\n            channel->ic_flags\n            = IEEE80211_CHAN_CCK\n            | IEEE80211_CHAN_OFDM\n            | IEEE80211_CHAN_DYN\n            | IEEE80211_CHAN_2GHZ;\n        } else {\n            flags = IEEE80211_CHAN_5GHZ;\n            channel->ic_flags =\n            IEEE80211_CHAN_A;\n        }\n        \n        if (!(ch_flags & IWM_NVM_CHANNEL_ACTIVE))\n            channel->ic_flags |= IEEE80211_CHAN_PASSIVE;\n        \n        if (data->sku_cap_11n_enable)\n            channel->ic_flags |= IEEE80211_CHAN_HT20;\n\n        if (!is_5ghz && (ch_flags & IWM_NVM_CHANNEL_40MHZ)) {\n            if (hw_value <= IWM_LAST_2GHZ_HT_PLUS) {\n                channel->ic_flags |= IEEE80211_CHAN_HT40U;\n            }\n            if (hw_value >= IWM_FIRST_2GHZ_HT_MINUS) {\n                channel->ic_flags |= IEEE80211_CHAN_HT40D;\n            }\n        } else if (ch_flags & IWM_NVM_CHANNEL_40MHZ) {\n            if ((ch_idx - IWM_NUM_2GHZ_CHANNELS) % 2 == 0) {\n                channel->ic_flags |= IEEE80211_CHAN_HT40U;\n            } else {\n                channel->ic_flags |= IEEE80211_CHAN_HT40D;\n            }\n        }\n\n        if (data->sku_cap_11ac_enable) {\n            if (ch_flags & IWM_NVM_CHANNEL_80MHZ) {\n                channel->ic_flags |= IEEE80211_CHAN_VHT80;\n            }\n            if (ch_flags & IWM_NVM_CHANNEL_160MHZ) {\n                channel->ic_flags |= IEEE80211_CHAN_VHT160;\n            }\n        }\n\n        if (ch_flags & IWM_NVM_CHANNEL_DFS) {\n            channel->ic_flags |= IEEE80211_CHAN_DFS;\n        }\n\n        channel->ic_freq = ieee80211_ieee2mhz(hw_value, flags);\n    }\n}\n\nvoid ItlIwm::\niwm_setup_ht_rates(struct iwm_softc *sc)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    uint8_t rx_ant;\n    \n    /* TX is supported with the same MCS as RX. */\n    ic->ic_tx_mcs_set = IEEE80211_TX_MCS_SET_DEFINED;\n    \n    memset(ic->ic_sup_mcs, 0, sizeof(ic->ic_sup_mcs));\n    ic->ic_sup_mcs[0] = 0xff;        /* MCS 0-7 */\n    \n    if (sc->support_ldpc)\n        ic->ic_htcaps |= IEEE80211_HTCAP_LDPC;\n    \n    if (!iwm_mimo_enabled(sc))\n        return;\n    \n    rx_ant = iwm_fw_valid_rx_ant(sc);\n    if ((rx_ant & IWM_ANT_AB) == IWM_ANT_AB ||\n        (rx_ant & IWM_ANT_BC) == IWM_ANT_BC)\n        ic->ic_sup_mcs[1] = 0xff;    /* MCS 8-15 */\n}\n\nvoid ItlIwm::\niwm_init_reorder_buffer(struct iwm_reorder_buffer *reorder_buf,\n                        uint16_t ssn, uint16_t buf_size)\n{\n    reorder_buf->head_sn = ssn;\n    reorder_buf->num_stored = 0;\n    reorder_buf->buf_size = buf_size;\n    reorder_buf->last_amsdu = 0;\n    reorder_buf->last_sub_index = 0;\n    reorder_buf->removed = 0;\n    reorder_buf->valid = 0;\n    reorder_buf->consec_oldsn_drops = 0;\n    reorder_buf->consec_oldsn_ampdu_gp2 = 0;\n    reorder_buf->consec_oldsn_prev_drop = 0;\n}\n\nvoid ItlIwm::\niwm_clear_reorder_buffer(struct iwm_softc *sc, struct iwm_rxba_data *rxba)\n{\n    int i;\n    struct iwm_reorder_buffer *reorder_buf = &rxba->reorder_buf;\n    struct iwm_reorder_buf_entry *entry;\n    \n    for (i = 0; i < reorder_buf->buf_size; i++) {\n        entry = &rxba->entries[i];\n        ml_purge(&entry->frames);\n        timerclear(&entry->reorder_time);\n    }\n    \n    reorder_buf->removed = 1;\n    timeout_del(&reorder_buf->reorder_timer);\n    timeout_free(&reorder_buf->reorder_timer);\n    timerclear(&rxba->last_rx);\n    timeout_del(&rxba->session_timer);\n    timeout_free(&rxba->session_timer);\n    rxba->baid = IWM_RX_REORDER_DATA_INVALID_BAID;\n}\n\nvoid ItlIwm::\niwm_rx_ba_session_expired(void *arg)\n{\n    struct iwm_rxba_data *rxba = (struct iwm_rxba_data *)arg;\n    struct iwm_softc *sc = rxba->sc;\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct ieee80211_node *ni = ic->ic_bss;\n    struct timeval now, timeout, expiry;\n    int s;\n    \n    s = splnet();\n    if ((sc->sc_flags & IWM_FLAG_SHUTDOWN) == 0 &&\n        ic->ic_state == IEEE80211_S_RUN &&\n        rxba->baid != IWM_RX_REORDER_DATA_INVALID_BAID) {\n        getmicrouptime(&now);\n        USEC_TO_TIMEVAL(RX_REORDER_BUF_TIMEOUT_MQ_USEC, &timeout);\n        timeradd(&rxba->last_rx, &timeout, &expiry);\n        if (timercmp(&now, &expiry, <)) {\n            timeout_add_usec(&rxba->session_timer, rxba->timeout);\n        } else {\n            ic->ic_stats.is_ht_rx_ba_timeout++;\n            ieee80211_delba_request(ic, ni,\n                                    IEEE80211_REASON_TIMEOUT, 0, rxba->tid);\n        }\n    }\n    splx(s);\n}\n\nvoid ItlIwm::\niwm_reorder_timer_expired(void *arg)\n{\n    struct mbuf_list ml = MBUF_LIST_INITIALIZER();\n    struct iwm_reorder_buffer *buf = (struct iwm_reorder_buffer *)arg;\n    struct iwm_rxba_data *rxba = iwm_rxba_data_from_reorder_buf(buf);\n    struct iwm_reorder_buf_entry *entries = &rxba->entries[0];\n    struct iwm_softc *sc = rxba->sc;\n    ItlIwm *that = container_of(sc, ItlIwm, com);\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct ieee80211_node *ni = ic->ic_bss;\n    int i, s;\n    uint16_t sn = 0, index = 0;\n    int expired = 0;\n    int cont = 0;\n    struct timeval now, timeout, expiry;\n    \n    if (!buf->num_stored || buf->removed)\n        return;\n    \n    s = splnet();\n    getmicrouptime(&now);\n    USEC_TO_TIMEVAL(RX_REORDER_BUF_TIMEOUT_MQ_USEC, &timeout);\n    \n    for (i = 0; i < buf->buf_size ; i++) {\n        index = (buf->head_sn + i) % buf->buf_size;\n        \n        if (ml_empty(&entries[index].frames)) {\n            /*\n             * If there is a hole and the next frame didn't expire\n             * we want to break and not advance SN.\n             */\n            cont = 0;\n            continue;\n        }\n        timeradd(&entries[index].reorder_time, &timeout, &expiry);\n        if (!cont && timercmp(&now, &expiry, <))\n            break;\n        \n        expired = 1;\n        /* continue until next hole after this expired frame */\n        cont = 1;\n        sn = (buf->head_sn + (i + 1)) & 0xfff;\n    }\n    \n    if (expired) {\n        /* SN is set to the last expired frame + 1 */\n        that->iwm_release_frames(sc, ni, rxba, buf, sn, &ml);\n        if_input(&sc->sc_ic.ic_if, &ml);\n        ic->ic_stats.is_ht_rx_ba_window_gap_timeout++;\n    } else {\n        /*\n         * If no frame expired and there are stored frames, index is now\n         * pointing to the first unexpired frame - modify reorder timeout\n         * accordingly.\n         */\n        timeout_add_usec(&buf->reorder_timer,\n                         RX_REORDER_BUF_TIMEOUT_MQ_USEC);\n    }\n    \n    splx(s);\n}\n\nuint8_t ItlIwm::\niwm_num_of_ant(uint8_t mask)\n{\n    return  !!((mask) & IWM_ANT_A) +\n        !!((mask) & IWM_ANT_B) +\n        !!((mask) & IWM_ANT_C);\n}\n\nvoid ItlIwm::\niwm_setup_vht_rates(struct iwm_softc *sc)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    uint8_t rx_ant, tx_ant;\n    unsigned int max_ampdu_exponent = IEEE80211_VHTCAP_MAX_AMPDU_1024K;\n    \n    if (ic->ic_userflags & IEEE80211_F_NOVHT)\n        return;\n    \n    /* enable 11ac support */\n    ic->ic_flags |= IEEE80211_F_VHTON;\n    \n    rx_ant = iwm_num_of_ant(iwm_fw_valid_rx_ant(sc));\n    tx_ant = iwm_num_of_ant(iwm_fw_valid_tx_ant(sc));\n    \n    ic->ic_vhtcaps = IEEE80211_VHTCAP_SHORT_GI_80 |\n    IEEE80211_VHTCAP_RXSTBC_1 |\n    IEEE80211_VHTCAP_SU_BEAMFORMEE_CAPABLE |\n    3 << IEEE80211_VHTCAP_BEAMFORMEE_STS_SHIFT |\n    max_ampdu_exponent <<\n    IEEE80211_VHTCAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT |\n    IEEE80211_VHTCAP_MU_BEAMFORMEE_CAPABLE;\n    \n    if (sc->sc_nvm.vht160_supported)\n    ic->ic_vhtcaps |= IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_160MHZ |\n            IEEE80211_VHTCAP_SHORT_GI_160;\n    \n    if (sc->support_ldpc)\n        ic->ic_vhtcaps |= IEEE80211_VHTCAP_RXLDPC;\n    if (!iwm_mimo_enabled(sc)) {\n        rx_ant = 1;\n        tx_ant = 1;\n    }\n    \n    if (tx_ant > 1)\n        ic->ic_vhtcaps |= IEEE80211_VHTCAP_TXSTBC;\n    else\n        ic->ic_vhtcaps |= IEEE80211_VHTCAP_TX_ANTENNA_PATTERN;\n    \n    ic->ic_vht_rx_mcs_map =\n    htole16(IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 |\n            IEEE80211_VHT_MCS_SUPPORT_0_9 << 2 |\n            IEEE80211_VHT_MCS_NOT_SUPPORTED << 4 |\n            IEEE80211_VHT_MCS_NOT_SUPPORTED << 6 |\n            IEEE80211_VHT_MCS_NOT_SUPPORTED << 8 |\n            IEEE80211_VHT_MCS_NOT_SUPPORTED << 10 |\n            IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 |\n            IEEE80211_VHT_MCS_NOT_SUPPORTED << 14);\n    if (rx_ant == 1) {\n        ic->ic_vhtcaps |= IEEE80211_VHTCAP_RX_ANTENNA_PATTERN;\n        /* this works because NOT_SUPPORTED == 3 */\n        ic->ic_vht_rx_mcs_map |=\n            htole16(IEEE80211_VHT_MCS_NOT_SUPPORTED << 2);\n    }\n    ic->ic_vht_tx_mcs_map = ic->ic_vht_rx_mcs_map;\n    ic->ic_vht_tx_highest = ic->ic_vht_rx_highest = 0;\n\n    memset(ic->ic_vht_sup_mcs, 0, sizeof(ic->ic_vht_sup_mcs));\n    ic->ic_vht_sup_mcs[0] = 0x03FF;        /* MCS 0-9 */\n    \n    if (!iwm_mimo_enabled(sc))\n        return;\n    \n    ic->ic_vht_sup_mcs[1] = 0x03FF;         /* MCS 0-9 */\n}\n\n#define IWM_MAX_RX_BA_SESSIONS 16\n\nint ItlIwm::\niwm_sta_rx_agg(struct iwm_softc *sc, struct ieee80211_node *ni, uint8_t tid,\n               uint16_t ssn, uint16_t winsize, int timeout_val, int start)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct iwm_add_sta_cmd cmd;\n    struct iwm_node *in = (struct iwm_node *)ni;\n    int err, s;\n    uint32_t status;\n    size_t cmdsize;\n    struct iwm_rxba_data *rxba = NULL;\n    uint8_t baid = 0;\n    \n    s = splnet();\n    \n    if (start && sc->sc_rx_ba_sessions >= IWM_MAX_RX_BA_SESSIONS) {\n        ieee80211_addba_req_refuse(ic, ni, tid);\n        splx(s);\n        return 0;\n    }\n    \n    memset(&cmd, 0, sizeof(cmd));\n    \n    cmd.sta_id = IWM_STATION_ID;\n    cmd.mac_id_n_color\n    = htole32(IWM_FW_CMD_ID_AND_COLOR(in->in_id, in->in_color));\n    cmd.add_modify = IWM_STA_MODE_MODIFY;\n    \n    if (start) {\n        cmd.add_immediate_ba_tid = (uint8_t)tid;\n        cmd.add_immediate_ba_ssn = ssn;\n        cmd.rx_ba_window = winsize;\n    } else {\n        cmd.remove_immediate_ba_tid = (uint8_t)tid;\n    }\n    cmd.modify_mask = start ? IWM_STA_MODIFY_ADD_BA_TID :\n    IWM_STA_MODIFY_REMOVE_BA_TID;\n    \n    status = IWM_ADD_STA_SUCCESS;\n    if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_STA_TYPE))\n        cmdsize = sizeof(cmd);\n    else\n        cmdsize = sizeof(struct iwm_add_sta_cmd_v7);\n    err = iwm_send_cmd_pdu_status(sc, IWM_ADD_STA, cmdsize, &cmd,\n                                  &status);\n    if (!err && (status & IWM_ADD_STA_STATUS_MASK) != IWM_ADD_STA_SUCCESS)\n        err = EIO;\n    if (err) {\n        if (start)\n            ieee80211_addba_req_refuse(ic, ni, tid);\n        splx(s);\n        return err;\n    }\n    \n    if (sc->sc_mqrx_supported) {\n        /* Deaggregation is done in hardware. */\n        if (start) {\n            if (!(status & IWM_ADD_STA_BAID_VALID_MASK)) {\n                ieee80211_addba_req_refuse(ic, ni, tid);\n                splx(s);\n                return EIO;\n            }\n            baid = (status & IWM_ADD_STA_BAID_MASK) >>\n            IWM_ADD_STA_BAID_SHIFT;\n            if (baid == IWM_RX_REORDER_DATA_INVALID_BAID ||\n                baid >= nitems(sc->sc_rxba_data)) {\n                ieee80211_addba_req_refuse(ic, ni, tid);\n                splx(s);\n                return EIO;\n            }\n            rxba = &sc->sc_rxba_data[baid];\n            if (rxba->baid != IWM_RX_REORDER_DATA_INVALID_BAID) {\n                ieee80211_addba_req_refuse(ic, ni, tid);\n                splx(s);\n                return 0;\n            }\n            rxba->sta_id = IWM_STATION_ID;\n            rxba->tid = tid;\n            rxba->baid = baid;\n            rxba->timeout = timeout_val;\n            getmicrouptime(&rxba->last_rx);\n            iwm_init_reorder_buffer(&rxba->reorder_buf, ssn,\n                                    winsize);\n            if (timeout_val != 0) {\n                struct ieee80211_rx_ba *ba;\n                timeout_add_usec(&rxba->session_timer,\n                                 timeout_val);\n                /* XXX disable net80211's BA timeout handler */\n                ba = &ni->ni_rx_ba[tid];\n                ba->ba_timeout_val = 0;\n            }\n        } else {\n            int i;\n            for (i = 0; i < nitems(sc->sc_rxba_data); i++) {\n                rxba = &sc->sc_rxba_data[i];\n                if (rxba->baid ==\n                    IWM_RX_REORDER_DATA_INVALID_BAID)\n                    continue;\n                if (rxba->tid != tid)\n                    continue;\n                iwm_clear_reorder_buffer(sc, rxba);\n                break;\n            }\n        }\n    }\n    \n    if (start) {\n        sc->sc_rx_ba_sessions++;\n        ieee80211_addba_req_accept(ic, ni, tid);\n    } else if (sc->sc_rx_ba_sessions > 0)\n        sc->sc_rx_ba_sessions--;\n    \n    splx(s);\n    return 0;\n}\n\nint ItlIwm::\niwm_sta_tx_agg(struct iwm_softc *sc, struct ieee80211_node *ni, uint8_t tid, uint8_t qid, uint16_t ssn, int start)\n{\n    struct iwm_add_sta_cmd cmd;\n    struct iwm_node *in = (struct iwm_node *)ni;\n    int err = 0;\n    uint32_t status;\n    size_t cmdsize;\n\n    memset(&cmd, 0, sizeof(cmd));\n\n    cmd.mac_id_n_color = htole32(IWM_FW_CMD_ID_AND_COLOR(in->in_id, in->in_color));\n    cmd.sta_id = IWM_STATION_ID;\n    cmd.add_modify = IWM_STA_MODE_MODIFY;\n    cmd.modify_mask = (IWM_STA_MODIFY_QUEUES | IWM_STA_MODIFY_TID_DISABLE_TX);\n    cmd.tfd_queue_msk = htole32(sc->agg_queue_mask);\n    cmd.tid_disable_tx = htole16(sc->agg_tid_disable);\n\n    if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_STA_TYPE))\n        cmdsize = sizeof(cmd);\n    else\n        cmdsize = sizeof(struct iwm_add_sta_cmd_v7);\n\n    status = IWM_ADD_STA_SUCCESS;\n    err = iwm_send_cmd_pdu_status(sc, IWM_ADD_STA, cmdsize, &cmd,\n                                  &status);\n\n    XYLog(\"%s tx agg %s. err=%d status=%d, mask_status=%d\\n\", __FUNCTION__, err ? \"failed\" : \"done\", err, status, (status & IWM_ADD_STA_STATUS_MASK));\n    \n    return err || ((status & IWM_ADD_STA_STATUS_MASK) != IWM_ADD_STA_SUCCESS);\n}\n\nvoid ItlIwm::\niwm_set_hw_address_8000(struct iwm_softc *sc, struct iwm_nvm_data *data,\n                        const uint16_t *mac_override, const uint16_t *nvm_hw)\n{\n    const uint8_t *hw_addr;\n    \n    if (mac_override) {\n        static const uint8_t reserved_mac[] = {\n            0x02, 0xcc, 0xaa, 0xff, 0xee, 0x00\n        };\n        \n        hw_addr = (const uint8_t *)(mac_override +\n                                    IWM_MAC_ADDRESS_OVERRIDE_8000);\n        \n        /*\n         * Store the MAC address from MAO section.\n         * No byte swapping is required in MAO section\n         */\n        memcpy(data->hw_addr, hw_addr, ETHER_ADDR_LEN);\n        \n        /*\n         * Force the use of the OTP MAC address in case of reserved MAC\n         * address in the NVM, or if address is given but invalid.\n         */\n        if (memcmp(reserved_mac, hw_addr, ETHER_ADDR_LEN) != 0 &&\n            (memcmp(etherbroadcastaddr, data->hw_addr,\n                    sizeof(etherbroadcastaddr)) != 0) &&\n            (memcmp(etheranyaddr, data->hw_addr,\n                    sizeof(etheranyaddr)) != 0) &&\n            !ETHER_IS_MULTICAST(data->hw_addr))\n            return;\n    }\n    \n    if (nvm_hw) {\n        /* Read the mac address from WFMP registers. */\n        uint32_t mac_addr0, mac_addr1;\n        \n        if (!iwm_nic_lock(sc))\n            goto out;\n        mac_addr0 = htole32(iwm_read_prph(sc, IWM_WFMP_MAC_ADDR_0));\n        mac_addr1 = htole32(iwm_read_prph(sc, IWM_WFMP_MAC_ADDR_1));\n        iwm_nic_unlock(sc);\n        \n        hw_addr = (const uint8_t *)&mac_addr0;\n        data->hw_addr[0] = hw_addr[3];\n        data->hw_addr[1] = hw_addr[2];\n        data->hw_addr[2] = hw_addr[1];\n        data->hw_addr[3] = hw_addr[0];\n        \n        hw_addr = (const uint8_t *)&mac_addr1;\n        data->hw_addr[4] = hw_addr[1];\n        data->hw_addr[5] = hw_addr[0];\n        \n        return;\n    }\nout:\n    XYLog(\"%s: mac address not found\\n\", DEVNAME(sc));\n    memset(data->hw_addr, 0, sizeof(data->hw_addr));\n}\n\n/*\n * RSSI values are reported by the FW as positive values - need to negate\n * to obtain their dBM.  Account for missing antennas by replacing 0\n * values by -256dBm: practically 0 power and a non-feasible 8 bit value.\n */\nint ItlIwm::\niwm_get_signal_strength(struct iwm_softc *sc, struct ieee80211_rx_status *rx_status, struct iwm_rx_phy_info *phy_info)\n{\n    int energy_a, energy_b, energy_c, max_energy;\n    uint32_t val;\n    \n    val = le32toh(phy_info->non_cfg_phy[IWM_RX_INFO_ENERGY_ANT_ABC_IDX]);\n    energy_a = (val & IWM_RX_INFO_ENERGY_ANT_A_MSK) >>\n    IWM_RX_INFO_ENERGY_ANT_A_POS;\n    energy_a = energy_a ? -energy_a : -256;\n    energy_b = (val & IWM_RX_INFO_ENERGY_ANT_B_MSK) >>\n    IWM_RX_INFO_ENERGY_ANT_B_POS;\n    energy_b = energy_b ? -energy_b : -256;\n    energy_c = (val & IWM_RX_INFO_ENERGY_ANT_C_MSK) >>\n    IWM_RX_INFO_ENERGY_ANT_C_POS;\n    energy_c = energy_c ? -energy_c : -256;\n    max_energy = MAX(energy_a, energy_b);\n    max_energy = MAX(max_energy, energy_c);\n    \n    rx_status->signal = max_energy;\n    rx_status->chains = (le16toh(phy_info->phy_flags) &\n                IWM_RX_RES_PHY_FLAGS_ANTENNA)\n                    >> IWM_RX_RES_PHY_FLAGS_ANTENNA_POS;\n    rx_status->chain_signal[0] = energy_a;\n    rx_status->chain_signal[1] = energy_b;\n    rx_status->chain_signal[2] = energy_c;\n    \n    return max_energy;\n}\n\nint ItlIwm::\niwm_rxmq_get_signal_strength(struct iwm_softc *sc, struct ieee80211_rx_status *rx_status, uint32_t rate_n_flags,\n                             struct iwm_rx_mpdu_desc *desc)\n{\n    int energy_a, energy_b;\n    \n    energy_a = desc->v1.energy_a;\n    energy_b = desc->v1.energy_b;\n    energy_a = energy_a ? -energy_a : -256;\n    energy_b = energy_b ? -energy_b : -256;\n    rx_status->signal = MAX(energy_a, energy_b);\n    rx_status->chains = (rate_n_flags & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_POS;\n    rx_status->chain_signal[0] = energy_a;\n    rx_status->chain_signal[1] = energy_b;\n    rx_status->chain_signal[2] = S8_MIN;\n    \n    return rx_status->signal;\n}\n\n/*\n * Retrieve the average noise (in dBm) among receivers.\n */\nint ItlIwm::\niwm_get_noise(const struct iwm_statistics_rx_non_phy *stats)\n{\n    int i, total, nbant, noise;\n    \n    total = nbant = noise = 0;\n    for (i = 0; i < 3; i++) {\n        noise = letoh32(stats->beacon_silence_rssi[i]) & 0xff;\n        if (noise) {\n            total += noise;\n            nbant++;\n        }\n    }\n    \n    /* There should be at least one antenna but check anyway. */\n    return (nbant == 0) ? -127 : (total / nbant) - 107;\n}\n\nint ItlIwm::\niwm_ccmp_decap(struct iwm_softc *sc, mbuf_t m, struct ieee80211_node *ni,\n               struct ieee80211_rxinfo *rxi)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct ieee80211_key *k = &ni->ni_pairwise_key;\n    struct ieee80211_frame *wh;\n    uint64_t pn, *prsc;\n    uint8_t *ivp;\n    uint8_t tid;\n    int hdrlen, hasqos;\n    \n    wh = mtod(m, struct ieee80211_frame *);\n    hdrlen = ieee80211_get_hdrlen(wh);\n    ivp = (uint8_t *)wh + hdrlen;\n    \n    /* Check that ExtIV bit is set. */\n    if (!(ivp[3] & IEEE80211_WEP_EXTIV))\n        return 1;\n    \n    hasqos = ieee80211_has_qos(wh);\n    tid = hasqos ? ieee80211_get_qos(wh) & IEEE80211_QOS_TID : 0;\n    prsc = &k->k_rsc[tid];\n    \n    /* Extract the 48-bit PN from the CCMP header. */\n    pn = (uint64_t)ivp[0]       |\n    (uint64_t)ivp[1] <<  8 |\n    (uint64_t)ivp[4] << 16 |\n    (uint64_t)ivp[5] << 24 |\n    (uint64_t)ivp[6] << 32 |\n    (uint64_t)ivp[7] << 40;\n    if (rxi->rxi_flags & IEEE80211_RXI_HWDEC_SAME_PN) {\n        if (pn < *prsc) {\n            ic->ic_stats.is_ccmp_replays++;\n            return 1;\n        }\n    } else if (pn <= *prsc) {\n        ic->ic_stats.is_ccmp_replays++;\n        return 1;\n    }\n    /* Last seen packet number is updated in ieee80211_inputm(). */\n    \n    /*\n     * Some firmware versions strip the MIC, and some don't. It is not\n     * clear which of the capability flags could tell us what to expect.\n     * For now, keep things simple and just leave the MIC in place if\n     * it is present.\n     *\n     * The IV will be stripped by ieee80211_inputm().\n     */\n    return 0;\n}\n\nint ItlIwm::\niwm_rx_hwdecrypt(struct iwm_softc *sc, mbuf_t m, uint32_t rx_pkt_status,\n                 struct ieee80211_rxinfo *rxi)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct _ifnet *ifp = IC2IFP(ic);\n    struct ieee80211_frame *wh;\n    struct ieee80211_node *ni;\n    int ret = 0;\n    uint8_t type, subtype;\n    \n    wh = mtod(m, struct ieee80211_frame *);\n    \n    type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;\n    if (type == IEEE80211_FC0_TYPE_CTL)\n        return 0;\n    \n    subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;\n    if (ieee80211_has_qos(wh) && (subtype & IEEE80211_FC0_SUBTYPE_NODATA))\n        return 0;\n    \n    if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||\n        !(wh->i_fc[1] & IEEE80211_FC1_PROTECTED))\n        return 0;\n    \n    ni = ieee80211_find_rxnode(ic, wh);\n    /* Handle hardware decryption. */\n    if ((ni->ni_flags & IEEE80211_NODE_RXPROT) &&\n        ni->ni_pairwise_key.k_cipher == IEEE80211_CIPHER_CCMP) {\n        if ((rx_pkt_status & IWM_RX_MPDU_RES_STATUS_SEC_ENC_MSK) !=\n            IWM_RX_MPDU_RES_STATUS_SEC_CCM_ENC) {\n            ic->ic_stats.is_ccmp_dec_errs++;\n            ret = 1;\n            goto out;\n        }\n        /* Check whether decryption was successful or not. */\n        if ((rx_pkt_status &\n             (IWM_RX_MPDU_RES_STATUS_DEC_DONE |\n              IWM_RX_MPDU_RES_STATUS_MIC_OK)) !=\n            (IWM_RX_MPDU_RES_STATUS_DEC_DONE |\n             IWM_RX_MPDU_RES_STATUS_MIC_OK)) {\n            ic->ic_stats.is_ccmp_dec_errs++;\n            ret = 1;\n            goto out;\n        }\n        rxi->rxi_flags |= IEEE80211_RXI_HWDEC;\n    }\nout:\n    if (ret)\n        ifp->netStat->inputErrors++;\n    ieee80211_release_node(ic, ni);\n    return ret;\n}\n\nvoid ItlIwm::\niwm_rx_frame(struct iwm_softc *sc, mbuf_t m, int chanidx,\n             uint32_t rx_pkt_status, int is_shortpre, int rate_n_flags,\n             uint32_t device_timestamp, struct ieee80211_rxinfo *rxi,\n             struct mbuf_list *ml)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct ieee80211_frame *wh;\n    struct ieee80211_node *ni;\n    struct _ifnet *ifp = IC2IFP(ic);\n    \n    if (chanidx < 0 || chanidx >= nitems(ic->ic_channels))\n        chanidx = ieee80211_chan2ieee(ic, ic->ic_ibss_chan);\n    \n    wh = mtod(m, struct ieee80211_frame *);\n    ni = ieee80211_find_rxnode(ic, wh);\n    if ((rxi->rxi_flags & IEEE80211_RXI_HWDEC) &&\n        iwm_ccmp_decap(sc, m, ni, rxi) != 0) {\n        if (ifp->netStat)\n            ifp->netStat->inputErrors++;\n        mbuf_freem(m);\n        ieee80211_release_node(ic, ni);\n        return;\n    }\n    \n#if NBPFILTER > 0\n    if (sc->sc_drvbpf != NULL) {\n        struct iwm_rx_radiotap_header *tap = &sc->sc_rxtap;\n        uint16_t chan_flags;\n        \n        tap->wr_flags = 0;\n        if (is_shortpre)\n            tap->wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;\n        tap->wr_chan_freq =\n        htole16(ic->ic_channels[chanidx].ic_freq);\n        chan_flags = ic->ic_channels[chanidx].ic_flags;\n        if (ic->ic_curmode != IEEE80211_MODE_11N)\n            chan_flags &= ~IEEE80211_CHAN_HT;\n        tap->wr_chan_flags = htole16(chan_flags);\n        tap->wr_dbm_antsignal = (int8_t)rxi->rxi_rssi;\n        tap->wr_dbm_antnoise = (int8_t)sc->sc_noise;\n        tap->wr_tsft = device_timestamp;\n        if (rate_n_flags & IWM_RATE_MCS_HT_MSK) {\n            uint8_t mcs = (rate_n_flags &\n                           (IWM_RATE_HT_MCS_RATE_CODE_MSK |\n                            IWM_RATE_HT_MCS_NSS_MSK));\n            tap->wr_rate = (0x80 | mcs);\n        } else {\n            uint8_t rate = (rate_n_flags &\n                            IWM_RATE_LEGACY_RATE_MSK);\n            switch (rate) {\n                    /* CCK rates. */\n                case  10: tap->wr_rate =   2; break;\n                case  20: tap->wr_rate =   4; break;\n                case  55: tap->wr_rate =  11; break;\n                case 110: tap->wr_rate =  22; break;\n                    /* OFDM rates. */\n                case 0xd: tap->wr_rate =  12; break;\n                case 0xf: tap->wr_rate =  18; break;\n                case 0x5: tap->wr_rate =  24; break;\n                case 0x7: tap->wr_rate =  36; break;\n                case 0x9: tap->wr_rate =  48; break;\n                case 0xb: tap->wr_rate =  72; break;\n                case 0x1: tap->wr_rate =  96; break;\n                case 0x3: tap->wr_rate = 108; break;\n                    /* Unknown rate: should not happen. */\n                default:  tap->wr_rate =   0;\n            }\n        }\n        \n        bpf_mtap_hdr(sc->sc_drvbpf, tap, sc->sc_rxtap_len,\n                     m, BPF_DIRECTION_IN);\n    }\n#endif\n    ieee80211_inputm(IC2IFP(ic), m, ni, rxi, ml);\n    ieee80211_release_node(ic, ni);\n}\n\n#define IWM_AGG_TX_STATE_(x) case IWM_AGG_TX_STATE_ ## x: return #x\nstatic const char *iwm_get_agg_tx_status(u16 status)\n{\n    switch (status & IWM_AGG_TX_STATE_STATUS_MSK) {\n    IWM_AGG_TX_STATE_(TRANSMITTED);\n    IWM_AGG_TX_STATE_(UNDERRUN);\n    IWM_AGG_TX_STATE_(BT_PRIO);\n    IWM_AGG_TX_STATE_(FEW_BYTES);\n    IWM_AGG_TX_STATE_(ABORT);\n    IWM_AGG_TX_STATE_(TX_ON_AIR_DROP);\n    IWM_AGG_TX_STATE_(LAST_SENT_TRY_CNT);\n    IWM_AGG_TX_STATE_(LAST_SENT_BT_KILL);\n    IWM_AGG_TX_STATE_(SCD_QUERY);\n    IWM_AGG_TX_STATE_(TEST_BAD_CRC32);\n    IWM_AGG_TX_STATE_(RESPONSE);\n    IWM_AGG_TX_STATE_(DUMP_TX);\n    IWM_AGG_TX_STATE_(DELAY_TX);\n    }\n\n    return \"UNKNOWN\";\n}\n\n#define IEEE80211_TX_MAX_RATES    4\n\nstatic int ieee80211_tx_get_rates(struct iwm_softc *sc,\n                  struct ieee80211_tx_info *info,\n                  int *retry_count)\n{\n    int count = -1;\n    int i;\n    int max_report_rates = 1;\n\n    for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {\n        if ((info->flags & IEEE80211_TX_CTL_AMPDU) &&\n            !(info->flags & IEEE80211_TX_STAT_AMPDU)) {\n            /* just the first aggr frame carry status info */\n            info->status.rates[i].idx = -1;\n            info->status.rates[i].count = 0;\n            break;\n        } else if (info->status.rates[i].idx < 0) {\n            break;\n        } else if (i >= max_report_rates) {\n            /* the HW cannot have attempted that rate */\n            info->status.rates[i].idx = -1;\n            info->status.rates[i].count = 0;\n            break;\n        }\n\n        count += info->status.rates[i].count;\n    }\n\n    if (count < 0)\n        count = 0;\n\n    *retry_count = count;\n    return i - 1;\n}\n\nvoid ieee80211_tx_status(struct iwm_softc *sc, struct ieee80211_tx_info *info, int tid, uint16_t fc, int ssn)\n{\n    struct _ifnet *ifp = &sc->sc_ic.ic_ac.ac_if;\n    int rates_idx, retry_count;\n    \n    if (!info)\n        return;\n    \n    rates_idx = ieee80211_tx_get_rates(sc, info, &retry_count);\n    \n    rs_drv_mac80211_tx_status(sc, sc->sc_ic.ic_bss, info, tid, fc, ssn);\n    if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) &&\n        (info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) &&\n        (ieee80211_is_data_qos(fc)))\n        ifp->netStat->outputErrors++;\n}\n\nvoid ItlIwm::\niwm_ampdu_txq_advance(struct iwm_softc *sc, struct iwm_tx_ring *ring, int idx)\n{\n    struct iwm_tx_data *txd;\n\n    while (ring->tail != idx) {\n        txd = &ring->data[ring->tail];\n        if (txd->m != NULL) {\n            if (ring->qid < IWM_FIRST_AGG_TX_QUEUE)\n                DPRINTF((\"%s: missed Tx completion: tail=%d \"\n                         \"idx=%d\\n\", __func__, ring->tail, idx));\n            iwm_reset_sched(sc, ring->qid, ring->tail, IWM_STATION_ID);\n            iwm_txd_done(sc, txd);\n            ring->queued--;\n        }\n        ring->tail = (ring->tail + 1) % IWM_TX_RING_COUNT;\n    }\n}\n\nvoid ItlIwm::\niwm_ampdu_rate_control(struct iwm_softc *sc, struct ieee80211_node *ni,\n    struct iwm_tx_ring *ring, uint16_t seq, uint16_t ssn, struct ieee80211_tx_info *tx_info, int tid, uint32_t rate_n_flags)\n{\n    int idx, end_idx;\n    struct iwm_tx_ba *tid_data = &sc->sc_tx_ba[tid];\n    int freed = 0;\n    bool rs_update = false;\n\n    /* pack lq color from tid_data along the reduced txp */\n    tx_info->status.status_driver_data[0] =\n        RS_DRV_DATA_PACK(tid_data->lq_color,\n                 tx_info->status.status_driver_data[0]);\n    tx_info->status.status_driver_data[1] = (void *)(uintptr_t)rate_n_flags;\n    /*\n    * Update Tx rate statistics for A-MPDUs before firmware's BA window.\n    */\n    idx = IWM_AGG_SSN_TO_TXQ_IDX(seq);\n    end_idx = IWM_AGG_SSN_TO_TXQ_IDX(ssn);\n    while (idx != end_idx) {\n        struct iwm_tx_data *txdata = &ring->data[idx];\n        struct ieee80211_tx_info *info = &txdata->info;\n\n        if (txdata->m != NULL) {\n            rs_update = true;\n            \n            memset(&info->status, 0, sizeof(info->status));\n            /* Packet was transmitted successfully, failures come as single\n             * frames because before failing a frame the firmware transmits\n             * it without aggregation at least once.\n             */\n            info->flags |= IEEE80211_TX_STAT_ACK;\n            \n            if (ieee80211_is_data_qos(txdata->fc))\n                freed++;\n            else\n                WARN_ON_ONCE(tid != IWL_MAX_TID_COUNT);\n            \n            /* this is the first skb we deliver in this batch */\n            /* put the rate scaling data there */\n            if (freed == 1) {\n                info->flags |= IEEE80211_TX_STAT_AMPDU;\n                memcpy(&info->status, &tx_info->status,\n                       sizeof(tx_info->status));\n                iwl_mvm_hwrate_to_tx_status(rate_n_flags, info);\n            }\n            \n            ieee80211_tx_status(sc, info, tid, txdata->fc, ssn);\n        }\n\n        idx = (idx + 1) % IWM_TX_RING_COUNT;\n    }\n    \n    /* We got a BA notif with 0 acked or scd_ssn didn't progress which is\n     * possible (i.e. first MPDU in the aggregation wasn't acked)\n     * Still it's important to update RS about sent vs. acked.\n     */\n    if (!rs_update) {\n        tx_info->band = IEEE80211_IS_CHAN_2GHZ(sc->sc_ic.ic_bss->ni_chan) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ;\n        iwl_mvm_hwrate_to_tx_status(rate_n_flags, tx_info);\n        DPRINTFN(3, (\"No reclaim. Update rs directly\\n\"));\n        iwl_mvm_rs_tx_status(sc, sc->sc_ic.ic_bss, tid, tx_info, false);\n    }\n}\n\nvoid ItlIwm::\niwm_rx_tx_ba_notif(struct iwm_softc *sc, struct iwm_rx_packet *pkt, struct iwm_rx_data *data)\n{\n    struct ieee80211_tx_ba *ba;\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct iwm_ba_notif *ba_notif = (struct iwm_ba_notif *)pkt->data;\n    struct iwm_tx_ring *ring;\n    uint16_t ssn;\n    int qid;\n    struct ieee80211_node *ni = ic->ic_bss;\n    struct iwm_node *in = (struct iwm_node *)ni;\n    struct iwm_tx_ba *tid_data;\n    struct ieee80211_tx_info ba_info = {};\n    \n    DPRINTFN(3, (\"TID = %d, SeqCtl = %d, bitmap = 0x%llx, scd_flow = %d, scd_ssn = %d sent:%d, acked:%d\\n\",\n                 ba_notif->tid, le16_to_cpu(ba_notif->seq_ctl),\n                 le64_to_cpu(ba_notif->bitmap), le16_to_cpu(ba_notif->scd_flow), le16_to_cpu(ba_notif->scd_ssn),\n                 ba_notif->txed, ba_notif->txed_2_done));\n    \n    if (ic->ic_state != IEEE80211_S_RUN)\n        return;\n    \n    if (iwm_rx_packet_payload_len(pkt) < sizeof(*ba_notif))\n        return;\n    \n    if (ba_notif->sta_id != IWM_STATION_ID ||\n        !IEEE80211_ADDR_EQ(in->in_macaddr, ba_notif->sta_addr))\n        return;\n    \n    qid = le16toh(ba_notif->scd_flow);\n    if (qid < IWM_FIRST_AGG_TX_QUEUE || qid > IWM_LAST_AGG_TX_QUEUE)\n        return;\n    \n    /* Protect against a firmware bug where the queue/TID are off. */\n    if (qid != IWM_FIRST_AGG_TX_QUEUE + ba_notif->tid)\n        return;\n    \n    sc->sc_tx_timer[qid] = 0;\n    \n    ba = &ni->ni_tx_ba[ba_notif->tid];\n    if (ba->ba_state != IEEE80211_BA_AGREED)\n        return;\n    \n    ring = &sc->txq[qid];\n    \n    /*\n     * The firmware's new BA window starting sequence number\n     * corresponds to the first hole in ban->scd_ssn, implying\n     * that all frames between 'seq' and 'ssn' (non-inclusive)\n     * have been acked.\n     */\n    ssn = le16toh(ba_notif->scd_ssn);\n    \n    /* pack lq color from tid_data along the reduced txp */\n    tid_data = &sc->sc_tx_ba[ba_notif->tid];\n    \n    ba_info.flags = IEEE80211_TX_STAT_AMPDU;\n    ba_info.status.ampdu_ack_len = ba_notif->txed_2_done;\n    ba_info.status.ampdu_len = ba_notif->txed;\n    ba_info.status.tx_time = tid_data->tx_time;\n    ba_info.status.status_driver_data[0] =\n        (void *)(uintptr_t)ba_notif->reduced_txp;\n    \n    if (SEQ_LT(ssn, ba->ba_winstart))\n        return;\n\n    /* Skip rate control if our Tx rate is fixed. */\n    if (ic->ic_fixed_mcs == -1)\n        iwm_ampdu_rate_control(sc, ni, ring,\n                               ba->ba_winstart, ssn, &ba_info, ba_notif->tid, tid_data->rate_n_flags);\n    \n    /*\n     * SSN corresponds to the first (perhaps not yet transmitted) frame\n     * in firmware's BA window. Firmware is not going to retransmit any\n     * frames before its BA window so mark them all as done.\n     */\n    ieee80211_output_ba_move_window(ic, ni, ba_notif->tid, ssn);\n    iwm_ampdu_txq_advance(sc, ring, IWM_AGG_SSN_TO_TXQ_IDX(ssn));\n    iwm_clear_oactive(sc, ring);\n}\n\nvoid ItlIwm::\niwm_ampdu_tx_done(struct iwm_softc *sc, struct iwm_cmd_header *cmd_hdr,\n    struct iwm_node *in, struct iwm_tx_ring *txq, uint32_t initial_rate,\n    uint8_t nframes, uint8_t failure_frame, uint16_t ssn, int status,\n    struct iwm_agg_tx_status *agg_status)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    int tid = cmd_hdr->qid - IWM_FIRST_AGG_TX_QUEUE;\n    struct iwm_tx_data *txdata = &txq->data[cmd_hdr->idx];\n    struct ieee80211_node *ni = &in->in_ni;\n    int txfail = (status != IWM_TX_STATUS_SUCCESS &&\n                  status != IWM_TX_STATUS_DIRECT_DONE);\n    struct ieee80211_tx_ba *ba;\n    \n    if (ic->ic_state != IEEE80211_S_RUN)\n        return;\n    \n    if (nframes > 1) {\n        return;\n    }\n    \n    if (ni == NULL)\n        return;\n    \n    ba = &ni->ni_tx_ba[tid];\n    if (ba->ba_state != IEEE80211_BA_AGREED)\n        return;\n    if (SEQ_LT(ssn, ba->ba_winstart))\n        return;\n    \n    /* This is a final single-frame Tx attempt. */\n    DPRINTFN(3, (\"%s: final tx status=0x%x qid=%d queued=%d idx=%d ssn=%u \"\n                 \"bitmap=0x%llx\\n\", __func__, status, cmd_hdr->qid, txq->queued,\n                 cmd_hdr->idx, ssn, ba->ba_bitmap));\n    \n    if (txfail) {\n        ieee80211_tx_compressed_bar(ic, ni, tid, ssn);\n        XYLog(\"%s sending bar ssn=%d tid=%d\\n\", __FUNCTION__, ssn, tid);\n    }\n    \n    /*\n     * SSN corresponds to the first (perhaps not yet transmitted) frame\n     * in firmware's BA window. Firmware is not going to retransmit any\n     * frames before its BA window so mark them all as done.\n     */\n    ieee80211_output_ba_move_window(ic, ni, tid, ssn);\n}\n\n#define IWL_MVM_TX_RES_GET_TID(_ra_tid) ((_ra_tid) & 0x0f)\n#define TX_RES_INIT_RATE_INDEX_MSK 0x0f\n#define TX_RES_RATE_TABLE_COLOR_POS 4\n#define TX_RES_RATE_TABLE_COLOR_MSK 0x70\n#define TX_RES_INV_RATE_INDEX_MSK 0x80\n#define TX_RES_RATE_TABLE_COL_GET(_f) (((_f) & TX_RES_RATE_TABLE_COLOR_MSK) >>\\\n                       TX_RES_RATE_TABLE_COLOR_POS)\n\nstatic inline struct iwm_agg_tx_status *\niwl_mvm_get_agg_status(struct iwm_softc *sc, void *tx_resp)\n{\n    return (struct iwm_agg_tx_status *)(((struct iwm_tx_resp *)tx_resp)->status);\n}\n\nstatic inline u32 iwl_mvm_get_scd_ssn(struct iwm_softc *sc,\n                      struct iwm_tx_resp *tx_resp)\n{\n    return le32_to_cpup((__le32 *)iwl_mvm_get_agg_status(sc, tx_resp) +\n                tx_resp->frame_count) & 0xfff;\n}\n\nvoid ItlIwm::\niwm_rx_tx_cmd_single(struct iwm_softc *sc, struct iwm_tx_resp *tx_resp,\n                     int qid, int idx)\n{\n    u32 status = le16toh(iwl_mvm_get_agg_status(sc, tx_resp)->status);\n    u16 ssn = iwl_mvm_get_scd_ssn(sc, tx_resp);\n    int tid = IWL_MVM_TX_RES_GET_TID(tx_resp->ra_tid);\n    struct iwm_tx_data *txd;\n    struct iwm_tx_ring *ring = &sc->txq[qid];\n    u8 skb_freed = 0;\n    u8 lq_color;\n    \n    while (ring->tail != idx) {\n        txd = &ring->data[ring->tail];\n        struct ieee80211_tx_info *info = &txd->info;\n        bool flushed = false;\n        if (txd->m != NULL) {\n            skb_freed++;\n\n            memset(&info->status, 0, sizeof(info->status));\n            info->flags &= ~(IEEE80211_TX_STAT_ACK | IEEE80211_TX_STAT_TX_FILTERED);\n\n            /* inform mac80211 about what happened with the frame */\n            switch (status & IWM_TX_STATUS_MSK) {\n            case IWM_TX_STATUS_SUCCESS:\n            case IWM_TX_STATUS_DIRECT_DONE:\n                info->flags |= IEEE80211_TX_STAT_ACK;\n                break;\n            case IWM_TX_STATUS_FAIL_FIFO_FLUSHED:\n            case IWM_TX_STATUS_FAIL_DRAIN_FLOW:\n                flushed = true;\n                break;\n            case IWM_TX_STATUS_FAIL_DEST_PS:\n                /* the FW should have stopped the queue and not\n                 * return this status\n                 */\n                WARN_ON(1);\n                info->flags |= IEEE80211_TX_STAT_TX_FILTERED;\n                break;\n            default:\n                break;\n            }\n\n            if ((status & IWM_TX_STATUS_MSK) != IWM_TX_STATUS_SUCCESS &&\n                ieee80211_is_mgmt(txd->fc))\n                iwm_toggle_tx_ant(sc, &sc->sc_mgmt_last_antenna_idx);\n            \n            if ((status & IWM_TX_STATUS_MSK) != IWM_TX_STATUS_SUCCESS &&\n                sc->sc_ic.ic_state <= IEEE80211_S_RUN)\n                iwm_toggle_tx_ant(sc, &sc->sc_tx_ant);\n                \n\n            /*\n             * If we are freeing multiple frames, mark all the frames\n             * but the first one as acked, since they were acknowledged\n             * before\n             * */\n            if (skb_freed > 1)\n                info->flags |= IEEE80211_TX_STAT_ACK;\n\n            info->status.rates[0].count = tx_resp->failure_frame + 1;\n            iwl_mvm_hwrate_to_tx_status(le32_to_cpu(tx_resp->initial_rate),\n                            info);\n            info->status.status_driver_data[1] =\n            (void *)(uintptr_t)le32_to_cpu(tx_resp->initial_rate);\n\n            /* Single frame failure in an AMPDU queue => send BAR */\n            if (info->flags & IEEE80211_TX_CTL_AMPDU &&\n                !(info->flags & IEEE80211_TX_STAT_ACK) &&\n                !(info->flags & IEEE80211_TX_STAT_TX_FILTERED) && !flushed)\n                info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;\n            info->flags &= ~IEEE80211_TX_CTL_AMPDU;\n\n            /*\n             * TODO: this is not accurate if we are freeing more than one\n             * packet.\n             */\n            info->status.tx_time =\n                le16_to_cpu(tx_resp->wireless_media_time);\n            BUILD_BUG_ON(ARRAY_SIZE(info->status.status_driver_data) < 1);\n            lq_color = TX_RES_RATE_TABLE_COL_GET(tx_resp->tlc_info);\n            info->status.status_driver_data[0] =\n                RS_DRV_DATA_PACK(lq_color, tx_resp->reduced_tpc);\n\n            ieee80211_tx_status(sc, info, tid, txd->fc, ssn);\n\n            iwm_reset_sched(sc, ring->qid, ring->tail, IWM_STATION_ID);\n            iwm_txd_done(sc, txd);\n            ring->queued--;\n        }\n        ring->tail = (ring->tail + 1) % IWM_TX_RING_COUNT;\n    }\n}\n\nvoid ItlIwm::\niwm_txd_done(struct iwm_softc *sc, struct iwm_tx_data *txd)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    \n    //    bus_dmamap_sync(sc->sc_dmat, txd->map, 0, txd->map->dm_mapsize,\n    //        BUS_DMASYNC_POSTWRITE);\n    //    bus_dmamap_unload(sc->sc_dmat, txd->map);\n    if (txd->m) {\n        mbuf_freem(txd->m);\n        txd->m = NULL;\n    }\n    \n    KASSERT(txd->in, \"txd->in\");\n    ieee80211_release_node(ic, &txd->in->in_ni);\n    txd->in = NULL;\n    txd->totlen = 0;\n    txd->txmcs = 0;\n    txd->txrate = 0;\n    txd->fc = 0;\n    memset(&txd->info, 0, sizeof(struct ieee80211_tx_info));\n}\n\nvoid ItlIwm::\niwm_clear_oactive(struct iwm_softc *sc, struct iwm_tx_ring *ring)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct _ifnet *ifp = &ic->ic_if;\n\n    if (ring->queued < IWM_TX_RING_LOMARK) {\n        sc->qfullmsk &= ~(1 << ring->qid);\n        if (sc->qfullmsk == 0 && ifq_is_oactive(&ifp->if_snd)) {\n            ifq_clr_oactive(&ifp->if_snd);\n            (*ifp->if_start)(ifp);\n        }\n#ifdef __PRIVATE_SPI__\n        ifp->iface->signalOutputThread();\n#endif\n    }\n}\n\n#define TX_RES_INIT_RATE_INDEX_MSK 0x0f\n#define TX_RES_RATE_TABLE_COLOR_POS 4\n#define TX_RES_RATE_TABLE_COLOR_MSK 0x70\n#define TX_RES_INV_RATE_INDEX_MSK 0x80\n#define TX_RES_RATE_TABLE_COL_GET(_f) (((_f) & TX_RES_RATE_TABLE_COLOR_MSK) >>\\\n                       TX_RES_RATE_TABLE_COLOR_POS)\n\nvoid ItlIwm::\niwm_rx_tx_cmd(struct iwm_softc *sc, struct iwm_rx_packet *pkt,\n              struct iwm_rx_data *data)\n{\n    struct iwm_cmd_header *cmd_hdr = &pkt->hdr;\n    int idx = cmd_hdr->idx;\n    int qid = cmd_hdr->qid;\n    struct iwm_tx_ring *ring;\n    struct iwm_tx_data *txd;\n    struct iwm_tx_resp *tx_resp = (struct iwm_tx_resp *)pkt->data;\n    uint32_t ssn;\n    uint32_t len = iwm_rx_packet_len(pkt);\n    struct iwm_tx_ba *tid_data;\n    \n    bus_dmamap_sync(sc->sc_dmat, data->map, 0, IWM_RBUF_SIZE,\n                    BUS_DMASYNC_POSTREAD);\n    \n    /* Sanity checks. */\n    if (sizeof(*tx_resp) > len)\n        return;\n    if (qid < IWM_FIRST_AGG_TX_QUEUE && tx_resp->frame_count > 1)\n        return;\n    if (qid > IWM_LAST_AGG_TX_QUEUE)\n        return;\n    if (sizeof(*tx_resp) + sizeof(ssn) +\n        tx_resp->frame_count * sizeof(struct iwm_agg_tx_status) > len)\n        return;\n    \n    sc->sc_tx_timer[qid] = 0;\n    \n    ring = &sc->txq[qid];\n    txd = &ring->data[idx];\n    \n    if (tx_resp->frame_count > 1) {\n        for (int i = 0; i < tx_resp->frame_count; i++) {\n            struct iwm_agg_tx_status *frame_status = iwl_mvm_get_agg_status(sc, tx_resp);\n            u16 fstatus = le16_to_cpu(frame_status[i].status);\n\n            DPRINTFN(3, (\"status %s (0x%04x), try-count (%d) qid (%d) seq (0x%x)\\n\",\n                         iwm_get_agg_tx_status(fstatus),\n                         fstatus & IWM_AGG_TX_STATE_STATUS_MSK,\n                         (fstatus & IWM_AGG_TX_STATE_TRY_CNT_MSK) >>\n                         IWM_AGG_TX_STATE_TRY_CNT_POS,\n                         qid,\n                         le16_to_cpu(frame_status[i].idx)));\n        }\n        int tid = cmd_hdr->qid - IWM_FIRST_AGG_TX_QUEUE;\n        if (tid < 0)\n            return;\n        tid_data = &sc->sc_tx_ba[tid];\n        tid_data->lq_color = TX_RES_RATE_TABLE_COL_GET(tx_resp->tlc_info);\n        tid_data->tx_time = le16toh(tx_resp->wireless_media_time);\n        tid_data->rate_n_flags = le32toh(tx_resp->initial_rate);\n        return;\n    }\n    \n    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));\n\n    ssn = iwm_get_scd_ssn(tx_resp);\n    iwm_rx_tx_cmd_single(sc, tx_resp, qid, IWM_AGG_SSN_TO_TXQ_IDX(ssn));\n    if (qid >= IWM_FIRST_AGG_TX_QUEUE) {\n        int status;\n        \n        status = le16toh(iwl_mvm_get_agg_status(sc, tx_resp)->status) & IWM_TX_STATUS_MSK;\n        iwm_ampdu_tx_done(sc, cmd_hdr, txd->in, ring,\n                          le32toh(tx_resp->initial_rate), tx_resp->frame_count,\n                          tx_resp->failure_frame, ssn, status, iwl_mvm_get_agg_status(sc, tx_resp));\n    }\n\n    iwm_clear_oactive(sc, ring);\n}\n\nvoid ItlIwm::\niwm_rx_bmiss(struct iwm_softc *sc, struct iwm_rx_packet *pkt,\n             struct iwm_rx_data *data)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct iwm_missed_beacons_notif *mbn = (struct iwm_missed_beacons_notif *)pkt->data;\n    uint32_t missed;\n    \n    if ((ic->ic_opmode != IEEE80211_M_STA) ||\n        (ic->ic_state != IEEE80211_S_RUN))\n        return;\n    \n    //        bus_dmamap_sync(sc->sc_dmat, data->map, sizeof(*pkt),\n    //            sizeof(*mbn), BUS_DMASYNC_POSTREAD);\n    \n    missed = le32toh(mbn->consec_missed_beacons_since_last_rx);\n    if (missed > ic->ic_bmissthres && ic->ic_mgt_timer == 0) {\n        if (ic->ic_if.if_flags & IFF_DEBUG)\n            XYLog(\"%s: receiving no beacons from %s; checking if \"\n                  \"this AP is still responding to probe requests\\n\",\n                  DEVNAME(sc), ether_sprintf(ic->ic_bss->ni_macaddr));\n        /*\n         * Rather than go directly to scan state, try to send a\n         * directed probe request first. If that fails then the\n         * state machine will drop us into scanning after timing\n         * out waiting for a probe response.\n         */\n        IEEE80211_SEND_MGMT(ic, ic->ic_bss,\n                            IEEE80211_FC0_SUBTYPE_PROBE_REQ, 0);\n    }\n    \n}\n\nstatic int\niwm_rate2ridx(struct iwm_softc *sc, int rate)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct ieee80211_node *ni = ic->ic_bss;\n    int ridx = -1, i;\n    \n    int min_ridx = (IEEE80211_IS_CHAN_5GHZ(ni->ni_chan)) ?\n        IWL_FIRST_OFDM_RATE : IWL_FIRST_CCK_RATE;\n    \n    for (i = 0; i < ieee80211_std_rateset_11g.rs_nrates; i++) {\n        if (ieee80211_std_rateset_11g.rs_rates[i] == rate) {\n            ridx = i;\n            break;\n        }\n    }\n    return ridx == -1 ? min_ridx : ridx;\n}\n\n/*\n * Fill in various bit for management frames, and leave them\n * unfilled for data frames (firmware takes care of that).\n * Return the selected TX rate.\n */\nconst struct iwl_rs_rate_info *ItlIwm::\niwm_tx_fill_cmd(struct iwm_softc *sc, struct iwm_node *in,\n                struct ieee80211_frame *wh, struct iwm_tx_cmd *tx)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct ieee80211_node *ni = &in->in_ni;\n    int type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;\n    int subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;\n    int ridx = -1, rate_flags;\n    int min_ridx = iwm_rate2ridx(sc, ieee80211_min_basic_rate(ic));\n    \n    tx->rts_retry_limit = IWM_RTS_DFAULT_RETRY_LIMIT;\n    \n    if (type == IEEE80211_FC0_TYPE_CTL &&\n        subtype == IEEE80211_FC0_SUBTYPE_BAR)\n        tx->data_retry_limit = IWM_BAR_DFAULT_RETRY_LIMIT;\n    else\n        tx->data_retry_limit = IWM_DEFAULT_TX_RETRY;\n    \n    if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||\n        type != IEEE80211_FC0_TYPE_DATA) {\n        /* for non-data, use the lowest supported rate */\n        ridx = min_ridx;\n        tx->data_retry_limit = IWM_MGMT_DFAULT_RETRY_LIMIT;\n    } else if (ic->ic_fixed_mcs != -1) {\n        if (ni->ni_flags & IEEE80211_NODE_VHT)\n            ridx = IWL_FIRST_OFDM_RATE;\n        else\n            ridx = sc->sc_fixed_ridx;\n    } else if (ic->ic_fixed_rate != -1) {\n        ridx = sc->sc_fixed_ridx;\n     } else {\n        /* Use firmware rateset retry table. */\n        tx->initial_rate_index = 0;\n        tx->tx_flags |= htole32(IWM_TX_CMD_FLG_STA_RATE);\n        if (ni->ni_flags & IEEE80211_NODE_HT) /* VHT implies HT */\n            return 0;\n        return &iwl_rates[iwm_rate2ridx(sc, ni->ni_txrate)];\n    }\n    \n    if (ridx == -1 || ridx >= IWL_RATE_COUNT_LEGACY)\n        ridx = min_ridx;\n    \n    rate_flags = iwm_get_tx_ant(sc, ni, type, wh);\n    XYLog(\"%s ridx=%d ant=%d\\n\", __FUNCTION__, ridx, (rate_flags >> RATE_MCS_ANT_POS));\n    /* Set CCK flag as needed */\n    if ((ridx >= IWL_FIRST_CCK_RATE) && (ridx <= IWL_LAST_CCK_RATE))\n        rate_flags |= RATE_MCS_CCK_MSK;\n    tx->rate_n_flags = htole32(rate_flags | iwl_mvm_mac80211_idx_to_hwrate(ridx));\n\n    return &iwl_rates[ridx];\n}\n\n#define TB0_SIZE 20\nint ItlIwm::\niwm_tx(struct iwm_softc *sc, mbuf_t m, struct ieee80211_node *ni, int ac)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct iwm_node *in = (struct iwm_node *)ni;\n    struct iwm_tx_ring *ring;\n    struct iwm_tx_data *data;\n    struct iwm_tfd *desc;\n    struct iwm_device_cmd *cmd;\n    struct iwm_tx_cmd *tx;\n    struct ieee80211_frame *wh;\n    struct ieee80211_key *k = NULL;\n    const struct iwl_rs_rate_info *rinfo;\n    uint8_t *ivp;\n    uint32_t flags;\n    u_int hdrlen;\n    IOPhysicalSegment *seg;\n    IOPhysicalSegment segs[IWM_NUM_OF_TBS - 2];\n    int nsegs = 0;\n    uint8_t tid, type, subtype;\n    int i, totlen, hasqos;\n    int rtsthres = ic->ic_rtsthreshold;\n    int qid;\n    uint16_t len, tb1_len;\n    \n    wh = mtod(m, struct ieee80211_frame *);\n    type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;\n    subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;\n    \n    if (type == IEEE80211_FC0_TYPE_CTL)\n        hdrlen = sizeof(struct ieee80211_frame_min);\n    else\n        hdrlen = ieee80211_get_hdrlen(wh);\n    \n    hasqos = ieee80211_has_qos(wh);\n    if (type == IEEE80211_FC0_TYPE_DATA)\n        tid = IWM_TID_NON_QOS;\n    else\n        tid = IWM_MAX_TID_COUNT;\n    \n    /*\n     * Map EDCA categories to Tx data queues.\n     *\n     * We use static data queue assignments even in DQA mode. We do not\n     * need to share Tx queues between stations because we only implement\n     * client mode; the firmware's station table contains only one entry\n     * which represents our access point.\n     */\n    if (isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_DQA_SUPPORT))\n        qid = IWM_DQA_MIN_MGMT_QUEUE + ac;\n    else\n        qid = ac;\n    \n    if (hasqos) {\n        struct ieee80211_tx_ba *ba;\n        uint16_t qos = ieee80211_get_qos(wh);\n        int qostid = qos & IEEE80211_QOS_TID;\n        int agg_qid = IWM_FIRST_AGG_TX_QUEUE + qostid;\n        \n        ba = &ni->ni_tx_ba[qostid];\n        if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&\n            type == IEEE80211_FC0_TYPE_DATA &&\n            subtype != IEEE80211_FC0_SUBTYPE_NODATA &&\n            sc->sc_tx_ba[tid].wn == in &&\n            ba->ba_state == IEEE80211_BA_AGREED) {\n            qid = agg_qid;\n            tid = qostid;\n            ac = ieee80211_up_to_ac(ic, qostid);\n        }\n    }\n    \n    ring = &sc->txq[qid];\n    desc = &ring->desc[ring->cur];\n    memset(desc, 0, sizeof(*desc));\n    data = &ring->data[ring->cur];\n    \n    cmd = &ring->cmd[ring->cur];\n    cmd->hdr.code = IWM_TX_CMD;\n    cmd->hdr.flags = 0;\n    cmd->hdr.qid = ring->qid;\n    cmd->hdr.idx = ring->cur;\n    \n    tx = (struct iwm_tx_cmd *)cmd->data;\n    memset(tx, 0, sizeof(*tx));\n    \n    rinfo = iwm_tx_fill_cmd(sc, in, wh, tx);\n    \n#if NBPFILTER > 0\n    if (sc->sc_drvbpf != NULL) {\n        struct iwm_tx_radiotap_header *tap = &sc->sc_txtap;\n        uint16_t chan_flags;\n        \n        tap->wt_flags = 0;\n        tap->wt_chan_freq = htole16(ni->ni_chan->ic_freq);\n        chan_flags = ni->ni_chan->ic_flags;\n        if (ic->ic_curmode != IEEE80211_MODE_11N)\n            chan_flags &= ~IEEE80211_CHAN_HT;\n        tap->wt_chan_flags = htole16(chan_flags);\n        if ((ni->ni_flags & IEEE80211_NODE_HT) &&\n            !IEEE80211_IS_MULTICAST(wh->i_addr1) &&\n            type == IEEE80211_FC0_TYPE_DATA &&\n            rinfo->ht_plcp != IWM_RATE_HT_SISO_MCS_INV_PLCP) {\n            tap->wt_rate = (0x80 | rinfo->ht_plcp);\n        } else\n            tap->wt_rate = rinfo->rate;\n        if ((ic->ic_flags & IEEE80211_F_WEPON) &&\n            (wh->i_fc[1] & IEEE80211_FC1_PROTECTED))\n            tap->wt_flags |= IEEE80211_RADIOTAP_F_WEP;\n        \n        bpf_mtap_hdr(sc->sc_drvbpf, tap, sc->sc_txtap_len,\n                     m, BPF_DIRECTION_OUT);\n    }\n#endif\n    totlen = mbuf_pkthdr_len(m);\n    \n    if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {\n        k = ieee80211_get_txkey(ic, wh, ni);\n        if ((k->k_flags & IEEE80211_KEY_GROUP) ||\n            (k->k_cipher != IEEE80211_CIPHER_CCMP)) {\n            if ((m = ieee80211_encrypt(ic, m, k)) == NULL)\n                return ENOBUFS;\n            /* 802.11 header may have moved. */\n            wh = mtod(m, struct ieee80211_frame *);\n            totlen = mbuf_pkthdr_len(m);\n            k = NULL; /* skip hardware crypto below */\n        } else {\n            /* HW appends CCMP MIC */\n            totlen += IEEE80211_CCMP_HDRLEN;\n        }\n    }\n    \n    flags = 0;\n    if (!IEEE80211_IS_MULTICAST(wh->i_addr1))\n        flags |= IWM_TX_CMD_FLG_ACK;\n    \n    if (type == IEEE80211_FC0_TYPE_DATA &&\n        !IEEE80211_IS_MULTICAST(wh->i_addr1) &&\n        (totlen + IEEE80211_CRC_LEN > rtsthres ||\n         (ic->ic_flags & IEEE80211_F_USEPROT)))\n        flags |= IWM_TX_CMD_FLG_PROT_REQUIRE;\n\n    if (type == IEEE80211_FC0_TYPE_CTL &&\n        subtype == IEEE80211_FC0_SUBTYPE_BAR) {\n        struct ieee80211_frame_min *mwh;\n        uint8_t *barfrm;\n        uint16_t ctl;\n        mwh = mtod(m, struct ieee80211_frame_min *);\n        barfrm = (uint8_t *)&mwh[1];\n        ctl = LE_READ_2(barfrm);\n        tid = (ctl & IEEE80211_BA_TID_INFO_MASK) >>\n            IEEE80211_BA_TID_INFO_SHIFT;\n        flags |= (IWM_TX_CMD_FLG_ACK | IWM_TX_CMD_FLG_BAR);\n    }\n    \n    tx->sta_id = IWM_STATION_ID;\n    \n    if (type == IEEE80211_FC0_TYPE_MGT) {\n        if (subtype == IEEE80211_FC0_SUBTYPE_ASSOC_REQ ||\n            subtype == IEEE80211_FC0_SUBTYPE_REASSOC_REQ)\n            tx->pm_frame_timeout = htole16(3);\n        else if (subtype == IEEE80211_FC0_SUBTYPE_ACTION)\n            tx->pm_frame_timeout = htole16(0);\n        else\n            tx->pm_frame_timeout = htole16(2);\n    } else {\n        tx->pm_frame_timeout = htole16(0);\n    }\n    \n    len = sizeof(struct iwm_tx_cmd) + sizeof(struct iwm_cmd_header) + hdrlen - TB0_SIZE;\n    \n    tb1_len = _ALIGN(len, 4);\n    /* Tell NIC about any 2-byte padding after MAC header */\n    if (tb1_len != len) {\n        flags |= IWM_TX_CMD_FLG_MH_PAD;\n        tx->offload_assist |= htole16(IWM_TX_CMD_OFFLD_PAD);\n    }\n    \n    tx->driver_txop = 0;\n    \n    tx->len = htole16(totlen);\n    tx->tid_tspec = tid;\n    tx->life_time = htole32(IWM_TX_CMD_LIFE_TIME_INFINITE);\n    \n    /* Set physical address of \"scratch area\". */\n    tx->dram_lsb_ptr = htole32(data->scratch_paddr);\n    tx->dram_msb_ptr = iwm_get_dma_hi_addr(data->scratch_paddr);\n    \n    /* Copy 802.11 header in TX command. */\n    memcpy(((uint8_t *)tx) + sizeof(*tx), wh, hdrlen);\n    \n    if  (k != NULL && k->k_cipher == IEEE80211_CIPHER_CCMP) {\n        /* Trim 802.11 header and prepend CCMP IV. */\n        mbuf_adj(m, hdrlen - IEEE80211_CCMP_HDRLEN);\n        ivp = mtod(m, u_int8_t *);\n        k->k_tsc++;    /* increment the 48-bit PN */\n        ivp[0] = k->k_tsc; /* PN0 */\n        ivp[1] = k->k_tsc >> 8; /* PN1 */\n        ivp[2] = 0;        /* Rsvd */\n        ivp[3] = k->k_id << 6 | IEEE80211_WEP_EXTIV;\n        ivp[4] = k->k_tsc >> 16; /* PN2 */\n        ivp[5] = k->k_tsc >> 24; /* PN3 */\n        ivp[6] = k->k_tsc >> 32; /* PN4 */\n        ivp[7] = k->k_tsc >> 40; /* PN5 */\n        \n        tx->sec_ctl = IWM_TX_CMD_SEC_CCM;\n        memcpy(tx->key, k->k_key, MIN(sizeof(tx->key), k->k_len));\n    } else {\n        /* Trim 802.11 header. */\n        mbuf_adj(m, hdrlen);\n        tx->sec_ctl = 0;\n    }\n    \n    flags |= (iwm_coex_tx_prio(sc, wh, ac) << IWM_TX_CMD_FLG_BT_PRIO_POS);\n    if (!hasqos)\n        flags |= IWM_TX_CMD_FLG_SEQ_CTL;\n    \n    tx->tx_flags |= htole32(flags);\n    \n    nsegs = data->map->cursor->getPhysicalSegmentsWithCoalesce(m, &segs[0], IWM_NUM_OF_TBS - 2);\n    //    XYLog(\"map frame dm_nsegs=%d\\n\", data->map->dm_nsegs);\n    if (nsegs == 0) {\n        XYLog(\"%s: can't map mbuf (error %d)\\n\", DEVNAME(sc), data->map->dm_nsegs);\n        mbuf_freem(m);\n        return ENOMEM;\n    }\n    data->m = m;\n    data->in = in;\n    data->txmcs = ni->ni_txmcs;\n    data->txrate = ni->ni_txrate;\n    data->totlen = totlen;\n    memcpy(&data->fc, &wh->i_fc[0], sizeof(uint16_t));\n    data->info.band = IEEE80211_IS_CHAN_2GHZ(ni->ni_chan) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ;\n    \n    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\",\n                 ring->qid, ring->cur, totlen, nsegs, le32toh(tx->tx_flags),\n                 le32toh(tx->rate_n_flags), tx->initial_rate_index,\n                 data->txmcs,\n                 data->txrate));\n    \n    /* Fill TX descriptor. */\n    desc->num_tbs = 2 + nsegs;\n    \n    desc->tbs[0].lo = htole32(data->cmd_paddr);\n    desc->tbs[0].hi_n_len = htole16(iwm_get_dma_hi_addr(data->cmd_paddr) |\n                                    (TB0_SIZE << 4));\n    desc->tbs[1].lo = htole32(data->cmd_paddr + TB0_SIZE);\n    desc->tbs[1].hi_n_len = htole16(iwm_get_dma_hi_addr(data->cmd_paddr) |\n                                    (tb1_len << 4));\n    \n    /* Other DMA segments are for data payload. */\n    for (i = 0; i < nsegs; i++) {\n        seg = &segs[i];\n        desc->tbs[i+2].lo = htole32(seg->location);\n        desc->tbs[i+2].hi_n_len =\n        htole16(iwm_get_dma_hi_addr(seg->location)\n                | ((seg->length) << 4));\n//        XYLog(\"DMA segments index=%d location=0x%llx length=%llu\", i, seg->location, seg->length);\n    }\n//    XYLog(\"----------end sending data------\\n\");\n    \n    //        bus_dmamap_sync(sc->sc_dmat, data->map, 0, data->map->dm_mapsize,\n    //            BUS_DMASYNC_PREWRITE);\n    //        bus_dmamap_sync(sc->sc_dmat, ring->cmd_dma.map,\n    //            (char *)(void *)cmd - (char *)(void *)ring->cmd_dma.vaddr,\n    //            sizeof (*cmd), BUS_DMASYNC_PREWRITE);\n    //        bus_dmamap_sync(sc->sc_dmat, ring->desc_dma.map,\n    //            (char *)(void *)desc - (char *)(void *)ring->desc_dma.vaddr,\n    //            sizeof (*desc), BUS_DMASYNC_PREWRITE);\n    \n    iwm_update_sched(sc, ring->qid, ring->cur, tx->sta_id, le16toh(tx->len));\n    \n    /* Kick TX ring. */\n    ring->cur = (ring->cur + 1) % IWM_TX_RING_COUNT;\n    IWM_WRITE(sc, IWM_HBUS_TARG_WRPTR, ring->qid << 8 | ring->cur);\n    \n    /* Mark TX ring as full if we reach a certain threshold. */\n    if (++ring->queued > IWM_TX_RING_HIMARK) {\n//        XYLog(\"%s qid=%d sc->qfullmsk is FULL ring->cur=%d ring->queued=%d\\n\", __FUNCTION__, ring->qid, ring->cur, ring->queued);\n        sc->qfullmsk |= 1 << ring->qid;\n    }\n    \n    if (ic->ic_if.if_flags & IFF_UP)\n        sc->sc_tx_timer[ring->qid] = 15;\n    \n    return 0;\n}\n\n#define IWM_TX_CRC_SIZE 4\n#define IWM_TX_DELIMITER_SIZE 4\n\nvoid ItlIwm::\niwm_update_sched(struct iwm_softc *sc, int qid, int cur, uint8_t sta_id, uint16_t len)\n{\n    DPRINTFN(3, (\"%s qid=%d cur=%d sta=%d len=%d\\n\", __FUNCTION__, qid, cur, sta_id, len));\n\n    struct iwm_agn_scd_bc_tbl *scd_bc_tbl;\n    uint8_t sec_ctl = 0;\n    uint16_t bc_ent;\n    struct iwm_tx_ring *txq = &sc->txq[qid];\n    iwm_tx_cmd *tx = (struct iwm_tx_cmd *)txq->cmd;\n    sec_ctl = tx->sec_ctl;\n\n    scd_bc_tbl = (struct iwm_agn_scd_bc_tbl *)sc->sched_dma.vaddr;\n    len += (IWM_TX_CRC_SIZE + IWM_TX_DELIMITER_SIZE);\n\n    switch (sec_ctl & IWM_TX_CMD_SEC_MSK) {\n    case IWM_TX_CMD_SEC_CCM:\n        len += IEEE80211_CCMP_MICLEN;\n        break;\n    case IWM_TX_CMD_SEC_TKIP:\n        len += IEEE80211_TKIP_ICVLEN;\n        break;\n    case IWM_TX_CMD_SEC_WEP:\n        len += IEEE80211_WEP_IVLEN + IEEE80211_WEP_ICVLEN;\n        break;\n    }\n\n    len = howmany(len, 4);\n    bc_ent = htole16(len | (IWM_STATION_ID << 12));\n    scd_bc_tbl[qid].tfd_offset[cur] = bc_ent;\n    if (cur < IWM_TFD_QUEUE_SIZE_BC_DUP) {\n        scd_bc_tbl[qid].tfd_offset[IWM_TFD_QUEUE_SIZE_MAX + cur] = bc_ent;\n    }\n}\n\nvoid ItlIwm::\niwm_reset_sched(struct iwm_softc *sc, int qid, int idx, uint8_t sta_id)\n{\n    DPRINTFN(3, (\"%s qid=%d idx=%d\\n\", __FUNCTION__, qid, idx));\n    \n    struct iwm_agn_scd_bc_tbl *scd_bc_tbl;\n    uint16_t val;\n    \n    scd_bc_tbl = (struct iwm_agn_scd_bc_tbl *)sc->sched_dma.vaddr;\n    \n    val = htole16(1 | (sta_id << 12));\n    \n    /* Update TX scheduler. */\n    scd_bc_tbl[qid].tfd_offset[idx] = val;\n    if (idx < IWM_TFD_QUEUE_SIZE_BC_DUP)\n        scd_bc_tbl[qid].tfd_offset[IWM_TFD_QUEUE_SIZE_MAX + idx] = val;\n}\n\nint ItlIwm::\niwm_flush_tx_path(struct iwm_softc *sc, int tfd_queue_msk)\n{\n    struct iwm_tx_path_flush_cmd_v1 flush_cmd = {\n        .queues_ctl = htole32(tfd_queue_msk),\n        .flush_ctl = htole16(IWM_DUMP_TX_FIFO_FLUSH),\n    };\n    int err;\n    \n    err = iwm_send_cmd_pdu(sc, IWM_TXPATH_FLUSH, 0,\n                           sizeof(flush_cmd), &flush_cmd);\n    if (err)\n        XYLog(\"%s: Flushing tx queue failed: %d\\n\", DEVNAME(sc), err);\n    return err;\n}\n\nstatic uint8_t iwm_mvm_mac80211_ac_to_ucode_ac(enum ieee80211_edca_ac ac)\n{\n   static const uint8_t mac80211_ac_to_ucode_ac[] = {\n       IWM_AC_BE,\n       IWM_AC_BK,\n       IWM_AC_VI,\n       IWM_AC_VO,\n   };\n\n   return mac80211_ac_to_ucode_ac[ac];\n}\n\nvoid ItlIwm::\niwm_mac_ctxt_cmd_common(struct iwm_softc *sc, struct iwm_node *in,\n                        struct iwm_mac_ctx_cmd *cmd, uint32_t action)\n{\n#define IWM_EXP2(x)    ((1 << (x)) - 1)    /* CWmin = 2^ECWmin - 1 */\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct ieee80211_node *ni = ic->ic_bss;\n    int cck_ack_rates, ofdm_ack_rates;\n    int i;\n    \n    cmd->id_and_color = htole32(IWM_FW_CMD_ID_AND_COLOR(in->in_id,\n                                                        in->in_color));\n    cmd->action = htole32(action);\n    \n    if (ic->ic_opmode == IEEE80211_M_MONITOR)\n        cmd->mac_type = htole32(IWM_FW_MAC_TYPE_LISTENER);\n    else if (ic->ic_opmode == IEEE80211_M_STA)\n        cmd->mac_type = htole32(IWM_FW_MAC_TYPE_BSS_STA);\n    else\n        panic(\"unsupported operating mode %d\\n\", ic->ic_opmode);\n    cmd->tsf_id = htole32(IWM_TSF_ID_A);\n    \n    IEEE80211_ADDR_COPY(cmd->node_addr, ic->ic_myaddr);\n    if (ic->ic_opmode == IEEE80211_M_MONITOR) {\n        IEEE80211_ADDR_COPY(cmd->bssid_addr, etherbroadcastaddr);\n        return;\n    }\n    \n    IEEE80211_ADDR_COPY(cmd->bssid_addr, in->in_macaddr);\n    iwm_ack_rates(sc, in, &cck_ack_rates, &ofdm_ack_rates);\n    cmd->cck_rates = htole32(cck_ack_rates);\n    cmd->ofdm_rates = htole32(ofdm_ack_rates);\n    \n    cmd->cck_short_preamble\n    = htole32((ic->ic_flags & IEEE80211_F_SHPREAMBLE)\n              ? IWM_MAC_FLG_SHORT_PREAMBLE : 0);\n    cmd->short_slot\n    = htole32((ic->ic_flags & IEEE80211_F_SHSLOT)\n              ? IWM_MAC_FLG_SHORT_SLOT : 0);\n    \n    for (i = 0; i < EDCA_NUM_AC; i++) {\n        struct ieee80211_edca_ac_params *ac = &ic->ic_edca_ac[i];\n        int txf = iwm_ac_to_tx_fifo[i];\n        uint8_t ucode_ac = iwm_mvm_mac80211_ac_to_ucode_ac((enum ieee80211_edca_ac)i);\n        \n        cmd->ac[ucode_ac].cw_min = htole16(IWM_EXP2(ac->ac_ecwmin));\n        cmd->ac[ucode_ac].cw_max = htole16(IWM_EXP2(ac->ac_ecwmax));\n        cmd->ac[ucode_ac].aifsn = ac->ac_aifsn;\n        cmd->ac[ucode_ac].fifos_mask = (1 << txf);\n        cmd->ac[ucode_ac].edca_txop = htole16(ac->ac_txoplimit * 32);\n    }\n    if (ni->ni_flags & IEEE80211_NODE_QOS)\n        cmd->qos_flags |= htole32(IWM_MAC_QOS_FLG_UPDATE_EDCA);\n    \n    if (ni->ni_flags & IEEE80211_NODE_HT) {\n        enum ieee80211_htprot htprot =\n        (enum ieee80211_htprot)(ni->ni_htop1 & IEEE80211_HTOP1_PROT_MASK);\n        \n        /* The fw does not distinguish between ht and fat */\n        uint32_t ht_flag = IWM_MAC_PROT_FLG_HT_PROT | IWM_MAC_PROT_FLG_FAT_PROT;\n        \n        /*\n         * See section 9.23.3.1 of IEEE 80211-2012.\n         * Nongreenfield HT STAs Present is not supported.\n         */\n        switch (htprot) {\n            case IEEE80211_HTPROT_NONE:\n                break;\n            case IEEE80211_HTPROT_NONMEMBER:\n            case IEEE80211_HTPROT_NONHT_MIXED:\n                cmd->protection_flags = htole32(ht_flag);\n                break;\n            case IEEE80211_HTPROT_20MHZ:\n                /* Protect when channel wider than 20MHz */\n                if (ni->ni_chw > IEEE80211_CHAN_WIDTH_20)\n                    cmd->protection_flags = htole32(ht_flag);\n                break;\n            default:\n                XYLog(\"Illegal protection mode %d\\n\", htprot);\n                break;\n        }\n        \n        cmd->qos_flags |= htole32(IWM_MAC_QOS_FLG_TGN);\n    }\n    if (ic->ic_flags & IEEE80211_F_USEPROT)\n        cmd->protection_flags |= htole32(IWM_MAC_PROT_FLG_TGG_PROTECT);\n    \n    cmd->filter_flags = htole32(IWM_MAC_FILTER_ACCEPT_GRP);\n#undef IWM_EXP2\n}\n\nvoid ItlIwm::\niwm_mac_ctxt_cmd_fill_sta(struct iwm_softc *sc, struct iwm_node *in,\n                          struct iwm_mac_data_sta *sta, int assoc)\n{\n    struct ieee80211_node *ni = &in->in_ni;\n    uint32_t dtim_off;\n    uint64_t tsf;\n    \n    dtim_off = ni->ni_dtimcount * ni->ni_intval * IEEE80211_DUR_TU;\n    memcpy(&tsf, ni->ni_tstamp, sizeof(tsf));\n    tsf = letoh64(tsf);\n    \n    sta->is_assoc = htole32(assoc);\n    sta->dtim_time = htole32(ni->ni_rstamp + dtim_off);\n    sta->dtim_tsf = htole64(tsf + dtim_off);\n    sta->bi = htole32(ni->ni_intval);\n    sta->bi_reciprocal = htole32(iwm_reciprocal(ni->ni_intval));\n    sta->dtim_interval = htole32(ni->ni_intval * ni->ni_dtimperiod);\n    sta->dtim_reciprocal = htole32(iwm_reciprocal(sta->dtim_interval));\n    sta->listen_interval = htole32(10);\n    sta->assoc_id = htole32(ni->ni_associd);\n    sta->assoc_beacon_arrive_time = htole32(ni->ni_rstamp);\n}\n\nint ItlIwm::\niwm_mac_ctxt_cmd(struct iwm_softc *sc, struct iwm_node *in, uint32_t action,\n                 int assoc)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct ieee80211_node *ni = &in->in_ni;\n    struct iwm_mac_ctx_cmd cmd;\n    int active = (sc->sc_flags & IWM_FLAG_MAC_ACTIVE);\n    \n    if (action == IWM_FW_CTXT_ACTION_ADD && active) {\n        XYLog(\"MAC already added\");\n        return 0;\n    }\n    if (action == IWM_FW_CTXT_ACTION_REMOVE && !active) {\n        XYLog(\"MAC already removed\");\n        return 0;\n    }\n    \n    memset(&cmd, 0, sizeof(cmd));\n    \n    iwm_mac_ctxt_cmd_common(sc, in, &cmd, action);\n    \n    if (ic->ic_opmode == IEEE80211_M_MONITOR) {\n        cmd.filter_flags |= htole32(IWM_MAC_FILTER_IN_PROMISC |\n                                    IWM_MAC_FILTER_IN_CONTROL_AND_MGMT |\n                                    IWM_MAC_FILTER_ACCEPT_GRP |\n                                    IWM_MAC_FILTER_IN_BEACON |\n                                    IWM_MAC_FILTER_IN_PROBE_REQUEST |\n                                    IWM_MAC_FILTER_IN_CRC32);\n    } else if (!assoc || !ni->ni_associd || !ni->ni_dtimperiod)\n    /*\n     * Allow beacons to pass through as long as we are not\n     * associated or we do not have dtim period information.\n     */\n        cmd.filter_flags |= htole32(IWM_MAC_FILTER_IN_BEACON);\n    else\n        iwm_mac_ctxt_cmd_fill_sta(sc, in, &cmd.sta, assoc);\n    \n    return iwm_send_cmd_pdu(sc, IWM_MAC_CONTEXT_CMD, 0, sizeof(cmd), &cmd);\n}\n\nint ItlIwm::\niwm_update_quotas(struct iwm_softc *sc, struct iwm_node *in, int running)\n{\n    struct iwm_time_quota_cmd_v1 cmd;\n    int i, idx, num_active_macs, quota, quota_rem;\n    int colors[IWM_MAX_BINDINGS] = { -1, -1, -1, -1, };\n    int n_ifs[IWM_MAX_BINDINGS] = {0, };\n    uint16_t id;\n    \n    memset(&cmd, 0, sizeof(cmd));\n    \n    /* currently, PHY ID == binding ID */\n    if (in && in->in_phyctxt) {\n        id = in->in_phyctxt->id;\n        KASSERT(id < IWM_MAX_BINDINGS, \"id < IWM_MAX_BINDINGS\");\n        colors[id] = in->in_phyctxt->color;\n        if (running)\n            n_ifs[id] = 1;\n    }\n    \n    /*\n     * The FW's scheduling session consists of\n     * IWM_MAX_QUOTA fragments. Divide these fragments\n     * equally between all the bindings that require quota\n     */\n    num_active_macs = 0;\n    for (i = 0; i < IWM_MAX_BINDINGS; i++) {\n        cmd.quotas[i].id_and_color = htole32(IWM_FW_CTXT_INVALID);\n        num_active_macs += n_ifs[i];\n    }\n    \n    quota = 0;\n    quota_rem = 0;\n    if (num_active_macs) {\n        quota = IWM_MAX_QUOTA / num_active_macs;\n        quota_rem = IWM_MAX_QUOTA % num_active_macs;\n    }\n    \n    for (idx = 0, i = 0; i < IWM_MAX_BINDINGS; i++) {\n        if (colors[i] < 0)\n            continue;\n        \n        cmd.quotas[idx].id_and_color =\n        htole32(IWM_FW_CMD_ID_AND_COLOR(i, colors[i]));\n        \n        if (n_ifs[i] <= 0) {\n            cmd.quotas[idx].quota = htole32(0);\n            cmd.quotas[idx].max_duration = htole32(0);\n        } else {\n            cmd.quotas[idx].quota = htole32(quota * n_ifs[i]);\n            cmd.quotas[idx].max_duration = htole32(0);\n        }\n        idx++;\n    }\n    \n    /* Give the remainder of the session to the first binding */\n    cmd.quotas[0].quota = htole32(le32toh(cmd.quotas[0].quota) + quota_rem);\n    \n    if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_QUOTA_LOW_LATENCY)) {\n        struct iwm_time_quota_cmd cmd_v2;\n        \n        memset(&cmd_v2, 0, sizeof(cmd_v2));\n        for (i = 0; i < IWM_MAX_BINDINGS; i++) {\n            cmd_v2.quotas[i].id_and_color =\n            cmd.quotas[i].id_and_color;\n            cmd_v2.quotas[i].quota = cmd.quotas[i].quota;\n            cmd_v2.quotas[i].max_duration =\n            cmd.quotas[i].max_duration;\n        }\n        return iwm_send_cmd_pdu(sc, IWM_TIME_QUOTA_CMD, 0,\n                                sizeof(cmd_v2), &cmd_v2);\n    }\n    \n    return iwm_send_cmd_pdu(sc, IWM_TIME_QUOTA_CMD, 0, sizeof(cmd), &cmd);\n}\n\nint ItlIwm::\niwm_auth(struct iwm_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct iwm_node *in = (struct iwm_node *)ic->ic_bss;\n    uint32_t duration;\n    int generation = sc->sc_generation, err;\n    \n    splassert(IPL_NET);\n    \n    in->in_ni.ni_chw = IEEE80211_CHAN_WIDTH_20_NOHT;\n    in->in_ni.ni_flags &= ~(IEEE80211_NODE_HT |\n                            IEEE80211_NODE_QOS |\n                            IEEE80211_NODE_HT_SGI20 |\n                            IEEE80211_NODE_HT_SGI40 |\n                            IEEE80211_NODE_VHT |\n                            IEEE80211_NODE_VHT_SGI80 |\n                            IEEE80211_NODE_VHT_SGI160);\n    if (ic->ic_opmode == IEEE80211_M_MONITOR) {\n        err = iwm_phy_ctxt_update(sc, &sc->sc_phyctxt[0],\n                                  ic->ic_ibss_chan, 1, 1, 0);\n        if (err)\n            return err;\n    } else {\n        err = iwm_phy_ctxt_update(sc, &sc->sc_phyctxt[0],\n                                  in->in_ni.ni_chan, 1, 1, 0);\n        if (err)\n            return err;\n    }\n    in->in_phyctxt = &sc->sc_phyctxt[0];\n    IEEE80211_ADDR_COPY(in->in_macaddr, in->in_ni.ni_macaddr);\n    \n    err = iwm_mac_ctxt_cmd(sc, in, IWM_FW_CTXT_ACTION_ADD, 0);\n    if (err) {\n        XYLog(\"%s: could not add MAC context (error %d)\\n\",\n              DEVNAME(sc), err);\n        return err;\n    }\n    sc->sc_flags |= IWM_FLAG_MAC_ACTIVE;\n    \n    err = iwm_binding_cmd(sc, in, IWM_FW_CTXT_ACTION_ADD);\n    if (err) {\n        XYLog(\"%s: could not add binding (error %d)\\n\",\n              DEVNAME(sc), err);\n        goto rm_mac_ctxt;\n    }\n    sc->sc_flags |= IWM_FLAG_BINDING_ACTIVE;\n    \n    err = iwm_add_sta_cmd(sc, in, 0, 0);\n    if (err) {\n        XYLog(\"%s: could not add sta (error %d)\\n\",\n              DEVNAME(sc), err);\n        goto rm_binding;\n    }\n    \n    iwm_toggle_tx_ant(sc, &sc->sc_tx_ant);\n    \n    if (ic->ic_opmode == IEEE80211_M_MONITOR)\n        return 0;\n    \n    /*\n     * Prevent the FW from wandering off channel during association\n     * by \"protecting\" the session with a time event.\n     */\n    if (in->in_ni.ni_intval)\n        duration = in->in_ni.ni_intval * 2;\n    else\n        duration = IEEE80211_DUR_TU;\n    iwm_protect_session(sc, in, duration, in->in_ni.ni_intval / 2);\n    \n    rs_drv_alloc_sta(sc, &in->in_ni);\n    \n    iwl_mvm_rs_rate_init(sc, ic->ic_bss,\n                         IEEE80211_IS_CHAN_2GHZ(ic->ic_bss->ni_chan) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ,\n                         false);\n    \n    return 0;\n    \nrm_binding:\n    if (generation == sc->sc_generation) {\n        iwm_binding_cmd(sc, in, IWM_FW_CTXT_ACTION_REMOVE);\n        sc->sc_flags &= ~IWM_FLAG_BINDING_ACTIVE;\n    }\nrm_mac_ctxt:\n    if (generation == sc->sc_generation) {\n        iwm_mac_ctxt_cmd(sc, in, IWM_FW_CTXT_ACTION_REMOVE, 0);\n        sc->sc_flags &= ~IWM_FLAG_MAC_ACTIVE;\n    }\n    return err;\n}\n\nint ItlIwm::\niwm_deauth(struct iwm_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct iwm_node *in = (struct iwm_node *)ic->ic_bss;\n    int ac, tfd_queue_msk, err, i;\n    \n    splassert(IPL_NET);\n    \n    iwm_unprotect_session(sc, in);\n    \n    if (sc->sc_flags & IWM_FLAG_STA_ACTIVE) {\n        err = iwm_rm_sta_cmd(sc, in);\n        if (err) {\n            XYLog(\"%s: could not remove STA (error %d)\\n\",\n                  DEVNAME(sc), err);\n            return err;\n        }\n        sc->sc_rx_ba_sessions = 0;\n        for (i = 0; i < nitems(sc->sc_tx_ba); i++)\n            sc->sc_tx_ba[i].wn = NULL;\n        sc->ba_rx.start_tidmask = 0;\n        sc->ba_rx.stop_tidmask = 0;\n        sc->ba_tx.start_tidmask = 0;\n        sc->ba_tx.stop_tidmask = 0;\n    }\n    \n    tfd_queue_msk = 0;\n    for (ac = 0; ac < EDCA_NUM_AC; ac++) {\n        int qid = ac;\n        if (isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_DQA_SUPPORT))\n            qid += IWM_DQA_MIN_MGMT_QUEUE;\n        tfd_queue_msk |= htole32(1 << qid);\n    }\n    \n    err = iwm_flush_tx_path(sc, tfd_queue_msk);\n    if (err) {\n        XYLog(\"%s: could not flush Tx path (error %d)\\n\",\n              DEVNAME(sc), err);\n        return err;\n    }\n    \n    if (sc->sc_flags & IWM_FLAG_BINDING_ACTIVE) {\n        err = iwm_binding_cmd(sc, in, IWM_FW_CTXT_ACTION_REMOVE);\n        if (err) {\n            XYLog(\"%s: could not remove binding (error %d)\\n\",\n                  DEVNAME(sc), err);\n            return err;\n        }\n        sc->sc_flags &= ~IWM_FLAG_BINDING_ACTIVE;\n    }\n    \n    if (sc->sc_flags & IWM_FLAG_MAC_ACTIVE) {\n        err = iwm_mac_ctxt_cmd(sc, in, IWM_FW_CTXT_ACTION_REMOVE, 0);\n        if (err) {\n            XYLog(\"%s: could not remove MAC context (error %d)\\n\",\n                  DEVNAME(sc), err);\n            return err;\n        }\n        sc->sc_flags &= ~IWM_FLAG_MAC_ACTIVE;\n    }\n    \n    in->in_ni.ni_chw = IEEE80211_CHAN_WIDTH_20_NOHT;\n    in->in_ni.ni_flags &= ~(IEEE80211_NODE_HT |\n                            IEEE80211_NODE_QOS |\n                            IEEE80211_NODE_HT_SGI20 |\n                            IEEE80211_NODE_HT_SGI40 |\n                            IEEE80211_NODE_VHT |\n                            IEEE80211_NODE_VHT_SGI80 |\n                            IEEE80211_NODE_VHT_SGI160);\n    /* Move unused PHY context to a default channel. */\n    err = iwm_phy_ctxt_update(sc, &sc->sc_phyctxt[0],\n                              &ic->ic_channels[1], 1, 1, 0);\n    if (err)\n        return err;\n    rs_drv_free_sta(sc, &in->in_ni);\n    \n    return 0;\n}\n\nint ItlIwm::\niwm_run(struct iwm_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct iwm_node *in = (struct iwm_node *)ic->ic_bss;\n    int err;\n    int chains = iwm_mimo_enabled(sc) ? 2 : 1;\n    \n    splassert(IPL_NET);\n    \n    if (ic->ic_opmode == IEEE80211_M_MONITOR) {\n        /* Add a MAC context and a sniffing STA. */\n        err = iwm_auth(sc);\n        if (err)\n            return err;\n    }\n    \n    if (in->in_ni.ni_chw == IEEE80211_CHAN_WIDTH_80P80) {\n        /* Fallback to 20mhz VHT */\n        in->in_ni.ni_chw = IEEE80211_CHAN_WIDTH_20;\n    }\n    \n    if (in->in_ni.ni_flags & IEEE80211_NODE_VHT) {\n        if (in->in_ni.ni_chw == IEEE80211_CHAN_WIDTH_20) {\n            ic->ic_vht_sup_mcs[0] = 0x01FF;        /* MCS 0-8 */\n            if (iwm_mimo_enabled(sc))\n                ic->ic_vht_sup_mcs[1] = 0x01FF;         /* MCS 0-8 */\n        } else {\n            ic->ic_vht_sup_mcs[0] = 0x03FF;        /* MCS 0-9 */\n            if (iwm_mimo_enabled(sc))\n                ic->ic_vht_sup_mcs[1] = 0x03FF;         /* MCS 0-9 */\n        }\n    }\n    \n    /* Configure Rx chains for MIMO. */\n    if ((ic->ic_opmode == IEEE80211_M_MONITOR ||\n         (in->in_ni.ni_flags & IEEE80211_NODE_HT) ||\n         (in->in_ni.ni_flags & IEEE80211_NODE_VHT))) {\n        err = iwm_phy_ctxt_update(sc, &sc->sc_phyctxt[0], in->in_ni.ni_chan,\n                               chains, chains, 0);\n        if (err) {\n            XYLog(\"%s: failed to update PHY\\n\",\n                  DEVNAME(sc));\n            return err;\n        }\n    }\n    \n    /* Update STA again, for HT-related settings such as MIMO. */\n     err = iwm_add_sta_cmd(sc, in, 1, 0);\n     if (err) {\n         XYLog(\"%s: could not update STA (error %d)\\n\",\n             DEVNAME(sc), err);\n         return err;\n     }\n    \n    /* We have now been assigned an associd by the AP. */\n    err = iwm_mac_ctxt_cmd(sc, in, IWM_FW_CTXT_ACTION_MODIFY, 1);\n    if (err) {\n        XYLog(\"%s: failed to update MAC\\n\", DEVNAME(sc));\n        return err;\n    }\n    \n    err = iwm_sf_config(sc, IWM_SF_FULL_ON);\n    if (err) {\n        XYLog(\"%s: could not set sf full on (error %d)\\n\",\n              DEVNAME(sc), err);\n        return err;\n    }\n    \n    err = iwm_allow_mcast(sc);\n    if (err) {\n        XYLog(\"%s: could not allow mcast (error %d)\\n\",\n              DEVNAME(sc), err);\n        return err;\n    }\n    \n    err = iwm_power_update_device(sc);\n    if (err) {\n        XYLog(\"%s: could not send power command (error %d)\\n\",\n              DEVNAME(sc), err);\n        return err;\n    }\n#ifdef notyet\n    /*\n     * Disabled for now. Default beacon filter settings\n     * prevent net80211 from getting ERP and HT protection\n     * updates from beacons.\n     */\n    err = iwm_enable_beacon_filter(sc, in);\n    if (err) {\n        XYLog(\"%s: could not enable beacon filter\\n\",\n              DEVNAME(sc));\n        return err;\n    }\n#endif\n    err = iwm_power_mac_update_mode(sc, in);\n    if (err) {\n        XYLog(\"%s: could not update MAC power (error %d)\\n\",\n              DEVNAME(sc), err);\n        return err;\n    }\n    \n    if (!isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_DYNAMIC_QUOTA)) {\n        err = iwm_update_quotas(sc, in, 1);\n        if (err) {\n            XYLog(\"%s: could not update quotas (error %d)\\n\",\n                  DEVNAME(sc), err);\n            return err;\n        }\n    }\n    \n    ieee80211_amrr_node_init(&sc->sc_amrr, &in->in_amn);\n    \n    if (ic->ic_opmode == IEEE80211_M_MONITOR) {\n        iwm_led_blink_start(sc);\n        return 0;\n    }\n    \n    /* Start at lowest available bit-rate, AMRR will raise. */\n    in->in_ni.ni_txrate = 0;\n    in->in_ni.ni_txmcs = 0;\n    \n    iwl_mvm_rs_rate_init(sc, ic->ic_bss,\n                         IEEE80211_IS_CHAN_2GHZ(ic->ic_bss->ni_chan) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ,\n                         true);\n    \n    timeout_add_msec(&sc->sc_calib_to, 500);\n    iwm_led_enable(sc);\n    \n    iwm_toggle_tx_ant(sc, &sc->sc_mgmt_last_antenna_idx);\n    \n    return 0;\n}\n\nint ItlIwm::\niwm_run_stop(struct iwm_softc *sc)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct iwm_node *in = (struct iwm_node *)ic->ic_bss;\n    int err, i, tid;\n    \n    splassert(IPL_NET);\n    \n    /*\n     * Stop Tx/Rx BA sessions now. We cannot rely on the BA task\n     * for this when moving out of RUN state since it runs in a\n     * separate thread.\n     * Note that in->in_ni (struct ieee80211_node) already represents\n     * our new access point in case we are roaming between APs.\n     * This means we cannot rely on struct ieee802111_node to tell\n     * us which BA sessions exist.\n     */\n    for (i = 0; i < nitems(sc->sc_rxba_data); i++) {\n        struct iwm_rxba_data *rxba = &sc->sc_rxba_data[i];\n        if (rxba->baid == IWM_RX_REORDER_DATA_INVALID_BAID)\n            continue;\n        iwm_sta_rx_agg(sc, &in->in_ni, rxba->tid, 0, 0, 0, 0);\n        iwm_clear_reorder_buffer(sc, rxba);\n        if (sc->sc_rx_ba_sessions > 0)\n            sc->sc_rx_ba_sessions--;\n    }\n    for (tid = 0; tid < IWM_MAX_TID_COUNT; tid++) {\n        int qid = IWM_FIRST_AGG_TX_QUEUE + tid;\n        struct iwm_tx_ring *ring = &sc->txq[qid];\n        if ((sc->agg_queue_mask & (1 << qid)) == 0)\n            continue;\n        err = iwm_sta_tx_agg(sc, &in->in_ni, tid, 0, 0, 0);\n        if (err)\n            return err;\n        iwm_ampdu_txq_advance(sc, ring, ring->cur);\n        iwm_clear_oactive(sc, ring);\n    }\n    ieee80211_ba_del(&in->in_ni);\n    sc->ba_tx.start_tidmask = 0;\n    sc->ba_tx.stop_tidmask = 0;\n    \n    if (ic->ic_opmode == IEEE80211_M_MONITOR)\n        iwm_led_blink_stop(sc);\n    \n    err = iwm_sf_config(sc, IWM_SF_INIT_OFF);\n    if (err)\n        return err;\n    \n    iwm_disable_beacon_filter(sc);\n    \n    if (!isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_DYNAMIC_QUOTA)) {\n        err = iwm_update_quotas(sc, in, 0);\n        if (err) {\n            XYLog(\"%s: could not update quotas (error %d)\\n\",\n                  DEVNAME(sc), err);\n            return err;\n        }\n    }\n    \n    /* Mark station as disassociated. */\n    err = iwm_mac_ctxt_cmd(sc, in, IWM_FW_CTXT_ACTION_MODIFY, 0);\n    if (err) {\n        XYLog(\"%s: failed to update MAC\\n\", DEVNAME(sc));\n        return err;\n    }\n    \n    /* Reset Tx chains in case MIMO was enabled. */\n    if ((in->in_ni.ni_flags & IEEE80211_NODE_HT) &&\n        iwm_mimo_enabled(sc)) {\n        err = iwm_phy_ctxt_update(sc, &sc->sc_phyctxt[0], in->in_ni.ni_chan, 1, 1, 0);\n        if (err) {\n            XYLog(\"%s: failed to update PHY\\n\", DEVNAME(sc));\n            return err;\n        }\n    }\n    \n    return 0;\n}\n\nstruct ieee80211_node *ItlIwm::\niwm_node_alloc(struct ieee80211com *ic)\n{\n    return (struct ieee80211_node *)malloc(sizeof (struct iwm_node), M_DEVBUF, M_NOWAIT | M_ZERO);\n}\n\nint ItlIwm::\niwm_set_key_v1(struct ieee80211com *ic, struct ieee80211_node *ni,\n    struct ieee80211_key *k)\n{\n   struct iwm_softc *sc = (struct iwm_softc *)ic->ic_softc;\n   struct iwm_add_sta_key_cmd_v1 cmd;\n\n   memset(&cmd, 0, sizeof(cmd));\n\n   cmd.common.key_flags = htole16(IWM_STA_KEY_FLG_CCM |\n       IWM_STA_KEY_FLG_WEP_KEY_MAP |\n       ((k->k_id << IWM_STA_KEY_FLG_KEYID_POS) &\n       IWM_STA_KEY_FLG_KEYID_MSK));\n   if (k->k_flags & IEEE80211_KEY_GROUP)\n       cmd.common.key_flags |= htole16(IWM_STA_KEY_MULTICAST);\n\n   memcpy(cmd.common.key, k->k_key, MIN(sizeof(cmd.common.key), k->k_len));\n   cmd.common.key_offset = 0;\n   cmd.common.sta_id = IWM_STATION_ID;\n\n   return iwm_send_cmd_pdu(sc, IWM_ADD_STA_KEY, IWM_CMD_ASYNC,\n       sizeof(cmd), &cmd);\n}\n\nint ItlIwm::\niwm_set_key(struct ieee80211com *ic, struct ieee80211_node *ni,\n    struct ieee80211_key *k)\n{\n    struct iwm_softc *sc = (struct iwm_softc *)ic->ic_softc;\n    struct iwm_add_sta_key_cmd cmd;\n    ItlIwm *that = container_of(sc, ItlIwm, com);\n    \n    if ((k->k_flags & IEEE80211_KEY_GROUP) ||\n        k->k_cipher != IEEE80211_CIPHER_CCMP)  {\n        /* Fallback to software crypto for other ciphers. */\n        return (ieee80211_set_key(ic, ni, k));\n    }\n    \n    if (!isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_TKIP_MIC_KEYS))\n        return that->iwm_set_key_v1(ic, ni, k);\n    \n    memset(&cmd, 0, sizeof(cmd));\n    \n    cmd.common.key_flags = htole16(IWM_STA_KEY_FLG_CCM |\n                                   IWM_STA_KEY_FLG_WEP_KEY_MAP |\n                                   ((k->k_id << IWM_STA_KEY_FLG_KEYID_POS) &\n                                    IWM_STA_KEY_FLG_KEYID_MSK));\n    if (k->k_flags & IEEE80211_KEY_GROUP)\n        cmd.common.key_flags |= htole16(IWM_STA_KEY_MULTICAST);\n    \n    memcpy(cmd.common.key, k->k_key, MIN(sizeof(cmd.common.key), k->k_len));\n    cmd.common.key_offset = 0;\n    cmd.common.sta_id = IWM_STATION_ID;\n    \n    cmd.transmit_seq_cnt = htole64(k->k_tsc);\n    \n    return that->iwm_send_cmd_pdu(sc, IWM_ADD_STA_KEY, IWM_CMD_ASYNC,\n                                  sizeof(cmd), &cmd);\n}\n\nvoid ItlIwm::\niwm_delete_key_v1(struct ieee80211com *ic, struct ieee80211_node *ni,\n    struct ieee80211_key *k)\n{\n   struct iwm_softc *sc = (struct iwm_softc *)ic->ic_softc;\n   struct iwm_add_sta_key_cmd_v1 cmd;\n\n   memset(&cmd, 0, sizeof(cmd));\n\n   cmd.common.key_flags = htole16(IWM_STA_KEY_NOT_VALID |\n       IWM_STA_KEY_FLG_NO_ENC | IWM_STA_KEY_FLG_WEP_KEY_MAP |\n       ((k->k_id << IWM_STA_KEY_FLG_KEYID_POS) &\n       IWM_STA_KEY_FLG_KEYID_MSK));\n   memcpy(cmd.common.key, k->k_key, MIN(sizeof(cmd.common.key), k->k_len));\n   cmd.common.key_offset = 0;\n   cmd.common.sta_id = IWM_STATION_ID;\n\n   iwm_send_cmd_pdu(sc, IWM_ADD_STA_KEY, IWM_CMD_ASYNC, sizeof(cmd), &cmd);\n}\n\nvoid ItlIwm::\niwm_delete_key(struct ieee80211com *ic, struct ieee80211_node *ni,\n    struct ieee80211_key *k)\n{\n    struct iwm_softc *sc = (struct iwm_softc *)ic->ic_softc;\n    struct iwm_add_sta_key_cmd cmd;\n    ItlIwm *that = container_of(sc, ItlIwm, com);\n    \n    if ((k->k_flags & IEEE80211_KEY_GROUP) ||\n        (k->k_cipher != IEEE80211_CIPHER_CCMP)) {\n        /* Fallback to software crypto for other ciphers. */\n        ieee80211_delete_key(ic, ni, k);\n        return;\n    }\n    \n    if ((sc->sc_flags & IWM_FLAG_STA_ACTIVE) == 0)\n        return;\n    \n    if (!isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_TKIP_MIC_KEYS))\n        return that->iwm_delete_key_v1(ic, ni, k);\n    \n    memset(&cmd, 0, sizeof(cmd));\n    \n    cmd.common.key_flags = htole16(IWM_STA_KEY_NOT_VALID |\n                                   IWM_STA_KEY_FLG_NO_ENC | IWM_STA_KEY_FLG_WEP_KEY_MAP |\n                                   ((k->k_id << IWM_STA_KEY_FLG_KEYID_POS) &\n                                    IWM_STA_KEY_FLG_KEYID_MSK));\n    memcpy(cmd.common.key, k->k_key, MIN(sizeof(cmd.common.key), k->k_len));\n    cmd.common.key_offset = 0;\n    cmd.common.sta_id = IWM_STATION_ID;\n    \n    that->iwm_send_cmd_pdu(sc, IWM_ADD_STA_KEY, IWM_CMD_ASYNC, sizeof(cmd), &cmd);\n}\n\nvoid ItlIwm::\niwm_calib_timeout(void *arg)\n{\n    struct iwm_softc *sc = (struct iwm_softc *)arg;\n    ItlIwm *that = container_of(sc, ItlIwm, com);\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct iwm_node *in = (struct iwm_node *)ic->ic_bss;\n    struct ieee80211_node *ni = &in->in_ni;\n    int s;\n    \n    s = splnet();\n    if ((ic->ic_fixed_rate == -1 || ic->ic_fixed_mcs == -1) &&\n        (ni->ni_flags & IEEE80211_NODE_HT) == 0 &&\n        ic->ic_opmode == IEEE80211_M_STA && ic->ic_bss) {\n        int old_txrate = ni->ni_txrate;\n        ieee80211_amrr_choose(&sc->sc_amrr, &in->in_ni, &in->in_amn);\n        /*\n         * If AMRR has chosen a new TX rate we must update\n         * the firwmare's LQ rate table.\n         * ni_txrate may change again before the task runs so\n         * cache the chosen rate in the iwm_node structure.\n         */\n        if (ni->ni_txrate != old_txrate) {\n            XYLog(\"iwm_calib_timeout in->ni_txrate=%d\\n\", in->in_ni.ni_txrate);\n            iwl_mvm_send_lq_cmd(sc, &sc->lq_sta.rs_drv.lq);\n        }\n    }\n    \n    splx(s);\n    \n    timeout_add_msec(&sc->sc_calib_to, 500);\n}\n\n/* Allow multicast from our BSSID. */\nint ItlIwm::\niwm_allow_mcast(struct iwm_softc *sc)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct iwm_node *in = (struct iwm_node *)ic->ic_bss;\n    struct iwm_mcast_filter_cmd *cmd;\n    size_t size;\n    int err;\n    \n    size = roundup(sizeof(*cmd), 4);\n    cmd = (struct iwm_mcast_filter_cmd*)malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO);\n    if (cmd == NULL)\n        return ENOMEM;\n    cmd->filter_own = 1;\n    cmd->port_id = 0;\n    cmd->count = 0;\n    cmd->pass_all = 1;\n    IEEE80211_ADDR_COPY(cmd->bssid, in->in_macaddr);\n    \n    err = iwm_send_cmd_pdu(sc, IWM_MCAST_FILTER_CMD,\n                           0, size, cmd);\n    ::free(cmd);\n    return err;\n}\n\n/*\n * This function is called by upper layer when an ADDBA request is received\n * from another STA and before the ADDBA response is sent.\n */\nint ItlIwm::\niwm_ampdu_rx_start(struct ieee80211com *ic, struct ieee80211_node *ni,\n                   uint8_t tid)\n{\n    struct iwm_softc *sc = (struct iwm_softc *)IC2IFP(ic)->if_softc;\n    ItlIwm *that = container_of(sc, ItlIwm, com);\n    \n    if (sc->sc_rx_ba_sessions >= IWM_MAX_RX_BA_SESSIONS ||\n        tid > IWM_MAX_TID_COUNT)\n        return ENOSPC;\n    \n    if (ic->ic_state != IEEE80211_S_RUN)\n        return ENOSPC;\n\n    if (sc->ba_rx.start_tidmask & (1 << tid))\n        return EBUSY;\n    \n    sc->ba_rx.start_tidmask |= (1 << tid);\n    that->iwm_add_task(sc, systq, &sc->ba_task);\n    \n    return EBUSY;\n}\n\n/*\n * This function is called by upper layer on teardown of an HT-immediate\n * Block Ack agreement (eg. upon receipt of a DELBA frame).\n */\nvoid ItlIwm::\niwm_ampdu_rx_stop(struct ieee80211com *ic, struct ieee80211_node *ni,\n                  uint8_t tid)\n{\n    struct iwm_softc *sc = (struct iwm_softc *)IC2IFP(ic)->if_softc;\n    ItlIwm *that = container_of(sc, ItlIwm, com);\n    \n    if (tid > IWM_MAX_TID_COUNT || sc->ba_rx.stop_tidmask & (1 << tid))\n        return;\n    \n    if (ic->ic_state != IEEE80211_S_RUN)\n        return;\n\n    sc->ba_rx.stop_tidmask |= (1 << tid);\n    that->iwm_add_task(sc, systq, &sc->ba_task);\n}\n\nint ItlIwm::\niwm_ampdu_tx_start(struct ieee80211com *ic, struct ieee80211_node *ni, uint8_t tid)\n{\n    struct ieee80211_tx_ba *ba = &ni->ni_tx_ba[tid];\n    struct iwm_softc *sc = (struct iwm_softc *)ic->ic_softc;\n    ItlIwm *that = container_of(sc, ItlIwm, com);\n    \n    /* We only implement Tx aggregation with DQA-capable firmware. */\n    if (!isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_DQA_SUPPORT))\n        return ENOTSUP;\n    \n    /* Ensure we can map this TID to an aggregation queue. */\n    if (tid >= IWM_MAX_TID_COUNT)\n        return EINVAL;\n    \n    /* We only support a fixed Tx aggregation window size, for now. */\n    if (ba->ba_winsize != IWM_FRAME_LIMIT)\n        return ENOTSUP;\n    \n    /* Is firmware already using Tx aggregation on this queue? */\n    if (sc->sc_tx_ba[tid].wn != NULL)\n        return ENOSPC;\n    \n    /* Are we already processing an ADDBA request? */\n    if (sc->ba_tx.start_tidmask & (1 << tid))\n        return EBUSY;\n    \n    sc->ba_tx.start_tidmask |= (1 << tid);\n    that->iwm_add_task(sc, systq, &sc->ba_task);\n    return EBUSY;\n}\n\nvoid ItlIwm::\niwm_ampdu_tx_stop(struct ieee80211com *ic, struct ieee80211_node *ni, uint8_t tid)\n{\n    struct iwm_softc *sc = (struct iwm_softc *)ic->ic_softc;\n    ItlIwm *that = container_of(sc, ItlIwm, com);\n\n    XYLog(\"%s\\n\", __FUNCTION__);\n\n    if (tid > IWM_MAX_TID_COUNT || sc->ba_tx.stop_tidmask & (1 << tid))\n        return;\n    \n    /* Is firmware currently using Tx aggregation on this queue? */\n    if (sc->sc_tx_ba[tid].wn == NULL)\n        return;\n    \n    sc->ba_tx.stop_tidmask |= (1 << tid);\n    that->iwm_add_task(sc, systq, &sc->ba_task);\n}\n\nvoid ItlIwm::\niwm_update_chw(struct ieee80211com *ic)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwm_softc *sc = (struct iwm_softc *)ic->ic_softc;\n    ItlIwm *that = container_of(sc, ItlIwm, com);\n    \n    if (ic->ic_state == IEEE80211_S_RUN && (sc->sc_flags & IWM_FLAG_STA_ACTIVE))\n        that->iwm_add_task(sc, systq, &sc->chan_ctxt_task);\n}\n\n/*\n * This function is called by upper layer when HT protection settings in\n * beacons have changed.\n */\nvoid ItlIwm::\niwm_updateprot(struct ieee80211com *ic)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwm_softc *sc = (struct iwm_softc *)ic->ic_softc;\n    ItlIwm *that = container_of(sc, ItlIwm, com);\n    \n    if (ic->ic_state == IEEE80211_S_RUN && (sc->sc_flags & IWM_FLAG_STA_ACTIVE))\n        that->iwm_add_task(sc, systq, &sc->mac_ctxt_task);\n}\n\nvoid ItlIwm::\niwm_updateslot(struct ieee80211com *ic)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwm_softc *sc = (struct iwm_softc *)ic->ic_softc;\n    ItlIwm *that = container_of(sc, ItlIwm, com);\n    \n    if (ic->ic_state == IEEE80211_S_RUN && (sc->sc_flags & IWM_FLAG_STA_ACTIVE))\n        that->iwm_add_task(sc, systq, &sc->mac_ctxt_task);\n}\n\nvoid ItlIwm::\niwm_updateedca(struct ieee80211com *ic)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwm_softc *sc = (struct iwm_softc *)ic->ic_softc;\n    ItlIwm *that = container_of(sc, ItlIwm, com);\n    \n    if (ic->ic_state == IEEE80211_S_RUN && (sc->sc_flags & IWM_FLAG_STA_ACTIVE))\n        that->iwm_add_task(sc, systq, &sc->mac_ctxt_task);\n}\n\nvoid ItlIwm::\niwm_updatedtim(struct ieee80211com *ic)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwm_softc *sc = (struct iwm_softc *)ic->ic_softc;\n    ItlIwm *that = container_of(sc, ItlIwm, com);\n    \n    if (ic->ic_state == IEEE80211_S_RUN && (sc->sc_flags & IWM_FLAG_STA_ACTIVE))\n        that->iwm_add_task(sc, systq, &sc->mac_ctxt_task);\n}\n\nint ItlIwm::iwm_media_change(struct _ifnet *ifp)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwm_softc *sc = (struct iwm_softc*)ifp->if_softc;\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct ieee80211_node *ni = ic->ic_bss;\n    uint8_t rate, ridx;\n    int err;\n    \n    err = ieee80211_media_change(ifp);\n    if (err != ENETRESET)\n        return err;\n    \n    if (ic->ic_fixed_mcs != -1) {\n        if (ni->ni_flags & IEEE80211_NODE_VHT)\n            sc->sc_fixed_ridx = iwm_mcs2ridx[ic->ic_fixed_mcs];\n        else if (ni->ni_flags & IEEE80211_NODE_HT)\n            sc->sc_fixed_ridx = iwm_mcs2ridx[ic->ic_fixed_mcs % 8];\n    } else if (ic->ic_fixed_rate != -1) {\n        rate = ic->ic_sup_rates[ic->ic_curmode].\n        rs_rates[ic->ic_fixed_rate] & IEEE80211_RATE_VAL;\n        /* Map 802.11 rate to HW rate index. */\n        for (ridx = 0; ridx <= ieee80211_std_rateset_11g.rs_nrates; ridx++)\n            if (ieee80211_std_rateset_11g.rs_rates[ridx] == rate)\n                break;\n        sc->sc_fixed_ridx = ridx;\n    }\n    \n    if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==\n        (IFF_UP | IFF_RUNNING)) {\n        iwm_stop(ifp);\n        err = iwm_init(ifp);\n    }\n    return err;\n}\n\nvoid ItlIwm::\niwm_newstate_task(void *psc)\n{\n    struct iwm_softc *sc = (struct iwm_softc *)psc;\n    ItlIwm *that = container_of(sc, ItlIwm, com);\n    struct ieee80211com *ic = &sc->sc_ic;\n    enum ieee80211_state nstate = sc->ns_nstate;\n    enum ieee80211_state ostate = ic->ic_state;\n    int arg = sc->ns_arg;\n    int err = 0, s = splnet();\n    \n    if (sc->sc_flags & IWM_FLAG_SHUTDOWN) {\n        /* iwm_stop() is waiting for us. */\n        //            refcnt_rele_wake(&sc->task_refs);\n        splx(s);\n        return;\n    }\n    \n    if (ostate == IEEE80211_S_SCAN) {\n        if (nstate == ostate) {\n            if (sc->sc_flags & IWM_FLAG_SCANNING) {\n                //                    refcnt_rele_wake(&sc->task_refs);\n                splx(s);\n                return;\n            }\n            /* Firmware is no longer scanning. Do another scan. */\n            goto next_scan;\n        } else\n            that->iwm_led_blink_stop(sc);\n    }\n    \n    if (nstate <= ostate) {\n        switch (ostate) {\n            case IEEE80211_S_RUN:\n                err = that->iwm_run_stop(sc);\n                if (err)\n                    goto out;\n                /* FALLTHROUGH */\n            case IEEE80211_S_ASSOC:\n            case IEEE80211_S_AUTH:\n                if (nstate <= IEEE80211_S_AUTH) {\n                    err = that->iwm_deauth(sc);\n                    if (err)\n                        goto out;\n                }\n                /* FALLTHROUGH */\n            case IEEE80211_S_SCAN:\n            case IEEE80211_S_INIT:\n                break;\n        }\n        \n        /* Die now if iwm_stop() was called while we were sleeping. */\n        if (sc->sc_flags & IWM_FLAG_SHUTDOWN) {\n            //                refcnt_rele_wake(&sc->task_refs);\n            splx(s);\n            return;\n        }\n    }\n    \n    switch (nstate) {\n        case IEEE80211_S_INIT:\n            break;\n            \n        case IEEE80211_S_SCAN:\n        next_scan:\n            err = that->iwm_scan(sc);\n            if (err)\n                break;\n            //            refcnt_rele_wake(&sc->task_refs);\n            splx(s);\n            return;\n            \n        case IEEE80211_S_AUTH:\n            err = that->iwm_auth(sc);\n            break;\n            \n        case IEEE80211_S_ASSOC:\n            break;\n            \n        case IEEE80211_S_RUN:\n            err = that->iwm_run(sc);\n            break;\n    }\n    \nout:\n    if ((sc->sc_flags & IWM_FLAG_SHUTDOWN) == 0) {\n        if (err)\n            task_add(systq, &sc->init_task);\n        else\n            sc->sc_newstate(ic, nstate, arg);\n    }\n    //        refcnt_rele_wake(&sc->task_refs);\n    splx(s);\n}\n\nint ItlIwm::\niwm_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct _ifnet *ifp = IC2IFP(ic);\n    struct iwm_softc *sc = (struct iwm_softc*)ifp->if_softc;\n    ItlIwm *that = container_of(sc, ItlIwm, com);\n    struct ieee80211_node *ni = ic->ic_bss;\n    \n    /*\n     * Prevent attemps to transition towards the same state, unless\n     * we are scanning in which case a SCAN -> SCAN transition\n     * triggers another scan iteration. And AUTH -> AUTH is needed\n     * to support band-steering.\n     */\n    if (sc->ns_nstate == nstate && nstate != IEEE80211_S_SCAN &&\n        nstate != IEEE80211_S_AUTH)\n    \n    if (ic->ic_state == IEEE80211_S_RUN) {\n        if (nstate == IEEE80211_S_SCAN) {\n             /*\n              * During RUN->SCAN we don't call sc_newstate() so\n              * we must stop A-MPDU Tx ourselves in this case.\n              */\n             ieee80211_stop_ampdu_tx(ic, ni, -1);\n             ieee80211_ba_del(ni);\n         }\n        timeout_del(&sc->sc_calib_to);\n        that->iwm_del_task(sc, systq, &sc->ba_task);\n        that->iwm_del_task(sc, systq, &sc->mac_ctxt_task);\n        that->iwm_del_task(sc, systq, &sc->chan_ctxt_task);\n    }\n    \n    sc->ns_nstate = nstate;\n    sc->ns_arg = arg;\n    \n    that->iwm_add_task(sc, sc->sc_nswq, &sc->newstate_task);\n    \n    return 0;\n}\n\nvoid ItlIwm::\niwm_endscan(struct iwm_softc *sc)\n{\n    struct ieee80211_node *ni, *nextbs;\n    struct ieee80211com *ic = &sc->sc_ic;\n    \n//    ni = RB_MIN(ieee80211_tree, &ic->ic_tree);\n//    for (; ni != NULL; ni = nextbs) {\n//        nextbs = RB_NEXT(ieee80211_tree, &ic->ic_tree, ni);\n//        XYLog(\"%s scan_result ssid=%s, bssid=%s, ni_rsnciphers=%d, ni_rsncipher=%d, ni_rsngroupmgmtcipher=%d, ni_rsngroupcipher=%d, ni_rssi=%d,  ni_capinfo=%d, ni_intval=%d, ni_rsnakms=%d, ni_supported_rsnakms=%d, ni_rsnprotos=%d, ni_supported_rsnprotos=%d, ni_rstamp=%d\\n\", __FUNCTION__, ni->ni_essid, ether_sprintf(ni->ni_bssid), ni->ni_rsnciphers, ni->ni_rsncipher, ni->ni_rsngroupmgmtcipher, ni->ni_rsngroupcipher, ni->ni_rssi, ni->ni_capinfo, ni->ni_intval, ni->ni_rsnakms, ni->ni_supported_rsnakms, ni->ni_rsnprotos, ni->ni_supported_rsnprotos, ni->ni_rstamp);\n//    }\n    \n    if ((sc->sc_flags & (IWM_FLAG_SCANNING | IWM_FLAG_BGSCAN)) == 0)\n        return;\n    \n    sc->sc_flags &= ~(IWM_FLAG_SCANNING | IWM_FLAG_BGSCAN);\n    ieee80211_end_scan(&ic->ic_if);\n}\n\n/*\n * Aging and idle timeouts for the different possible scenarios\n * in default configuration\n */\nstatic const uint32_t\niwm_sf_full_timeout_def[IWM_SF_NUM_SCENARIO][IWM_SF_NUM_TIMEOUT_TYPES] = {\n    {\n        htole32(IWM_SF_SINGLE_UNICAST_AGING_TIMER_DEF),\n        htole32(IWM_SF_SINGLE_UNICAST_IDLE_TIMER_DEF)\n    },\n    {\n        htole32(IWM_SF_AGG_UNICAST_AGING_TIMER_DEF),\n        htole32(IWM_SF_AGG_UNICAST_IDLE_TIMER_DEF)\n    },\n    {\n        htole32(IWM_SF_MCAST_AGING_TIMER_DEF),\n        htole32(IWM_SF_MCAST_IDLE_TIMER_DEF)\n    },\n    {\n        htole32(IWM_SF_BA_AGING_TIMER_DEF),\n        htole32(IWM_SF_BA_IDLE_TIMER_DEF)\n    },\n    {\n        htole32(IWM_SF_TX_RE_AGING_TIMER_DEF),\n        htole32(IWM_SF_TX_RE_IDLE_TIMER_DEF)\n    },\n};\n\n/*\n * Aging and idle timeouts for the different possible scenarios\n * in single BSS MAC configuration.\n */\nstatic const uint32_t\niwm_sf_full_timeout[IWM_SF_NUM_SCENARIO][IWM_SF_NUM_TIMEOUT_TYPES] = {\n    {\n        htole32(IWM_SF_SINGLE_UNICAST_AGING_TIMER),\n        htole32(IWM_SF_SINGLE_UNICAST_IDLE_TIMER)\n    },\n    {\n        htole32(IWM_SF_AGG_UNICAST_AGING_TIMER),\n        htole32(IWM_SF_AGG_UNICAST_IDLE_TIMER)\n    },\n    {\n        htole32(IWM_SF_MCAST_AGING_TIMER),\n        htole32(IWM_SF_MCAST_IDLE_TIMER)\n    },\n    {\n        htole32(IWM_SF_BA_AGING_TIMER),\n        htole32(IWM_SF_BA_IDLE_TIMER)\n    },\n    {\n        htole32(IWM_SF_TX_RE_AGING_TIMER),\n        htole32(IWM_SF_TX_RE_IDLE_TIMER)\n    },\n};\n\nvoid ItlIwm::\niwm_fill_sf_command(struct iwm_softc *sc, struct iwm_sf_cfg_cmd *sf_cmd,\n                    struct ieee80211_node *ni)\n{\n    int i, j, watermark;\n    \n    sf_cmd->watermark[IWM_SF_LONG_DELAY_ON] = htole32(IWM_SF_W_MARK_SCAN);\n    \n    /*\n     * If we are in association flow - check antenna configuration\n     * capabilities of the AP station, and choose the watermark accordingly.\n     */\n    if (ni) {\n        if (ni->ni_flags & IEEE80211_NODE_HT) {\n            if (ni->ni_rxmcs[1] != 0)\n                watermark = IWM_SF_W_MARK_MIMO2;\n            else\n                watermark = IWM_SF_W_MARK_SISO;\n        } else {\n            watermark = IWM_SF_W_MARK_LEGACY;\n        }\n        /* default watermark value for unassociated mode. */\n    } else {\n        watermark = IWM_SF_W_MARK_MIMO2;\n    }\n    sf_cmd->watermark[IWM_SF_FULL_ON] = htole32(watermark);\n    \n    for (i = 0; i < IWM_SF_NUM_SCENARIO; i++) {\n        for (j = 0; j < IWM_SF_NUM_TIMEOUT_TYPES; j++) {\n            sf_cmd->long_delay_timeouts[i][j] =\n            htole32(IWM_SF_LONG_DELAY_AGING_TIMER);\n        }\n    }\n    \n    if (ni) {\n        memcpy(sf_cmd->full_on_timeouts, iwm_sf_full_timeout,\n               sizeof(iwm_sf_full_timeout));\n    } else {\n        memcpy(sf_cmd->full_on_timeouts, iwm_sf_full_timeout_def,\n               sizeof(iwm_sf_full_timeout_def));\n    }\n    \n}\n\nint ItlIwm::\niwm_sf_config(struct iwm_softc *sc, int new_state)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct iwm_sf_cfg_cmd sf_cmd = {\n        .state = htole32(new_state),\n    };\n    int err = 0;\n    \n#if 0    /* only used for models with sdio interface, in iwlwifi */\n    if (sc->sc_device_family == IWM_DEVICE_FAMILY_8000)\n        sf_cmd.state |= htole32(IWM_SF_CFG_DUMMY_NOTIF_OFF);\n#endif\n    \n    switch (new_state) {\n        case IWM_SF_UNINIT:\n        case IWM_SF_INIT_OFF:\n            iwm_fill_sf_command(sc, &sf_cmd, NULL);\n            break;\n        case IWM_SF_FULL_ON:\n            iwm_fill_sf_command(sc, &sf_cmd, ic->ic_bss);\n            break;\n        default:\n            return EINVAL;\n    }\n    \n    err = iwm_send_cmd_pdu(sc, IWM_REPLY_SF_CFG_CMD, IWM_CMD_ASYNC,\n                           sizeof(sf_cmd), &sf_cmd);\n    return err;\n}\n\nint ItlIwm::\niwm_init_hw(struct iwm_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct ieee80211com *ic = &sc->sc_ic;\n    int err, i, ac, qid;\n    \n    err = iwm_preinit(sc);\n    if (err)\n        return err;\n    \n    err = iwm_start_hw(sc);\n    if (err) {\n        XYLog(\"%s: could not initialize hardware\\n\", DEVNAME(sc));\n        return err;\n    }\n    \n    err = iwm_run_init_mvm_ucode(sc, 0);\n    if (err)\n        return err;\n    \n    /* Should stop and start HW since INIT image just loaded. */\n    iwm_stop_device(sc);\n    err = iwm_start_hw(sc);\n    if (err) {\n        XYLog(\"%s: could not initialize hardware\\n\", DEVNAME(sc));\n        return err;\n    }\n    \n    /* Restart, this time with the regular firmware */\n    err = iwm_load_ucode_wait_alive(sc, IWM_UCODE_TYPE_REGULAR);\n    if (err) {\n        XYLog(\"%s: could not load firmware\\n\", DEVNAME(sc));\n        goto err;\n    }\n    \n    if (!iwm_nic_lock(sc))\n        return EBUSY;\n    \n    err = iwm_send_tx_ant_cfg(sc, iwm_fw_valid_tx_ant(sc));\n    if (err) {\n        XYLog(\"%s: could not init tx ant config (error %d)\\n\",\n              DEVNAME(sc), err);\n        goto err;\n    }\n    \n    err = iwm_send_phy_db_data(sc);\n    if (err) {\n        XYLog(\"%s: could not init phy db (error %d)\\n\",\n              DEVNAME(sc), err);\n        goto err;\n    }\n    \n    err = iwm_send_phy_cfg_cmd(sc);\n    if (err) {\n        XYLog(\"%s: could not send phy config (error %d)\\n\",\n              DEVNAME(sc), err);\n        goto err;\n    }\n    \n    err = iwm_send_bt_init_conf(sc);\n    if (err) {\n        XYLog(\"%s: could not init bt coex (error %d)\\n\",\n              DEVNAME(sc), err);\n        return err;\n    }\n    \n    if (isset(sc->sc_enabled_capa,\n              IWM_UCODE_TLV_CAPA_SOC_LATENCY_SUPPORT)) {\n        err = iwm_send_soc_conf(sc);\n        if (err)\n            return err;\n    }\n    \n    if (isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_DQA_SUPPORT)) {\n        err = iwm_send_dqa_cmd(sc);\n        if (err)\n            return err;\n    }\n    \n    /* Add auxiliary station for scanning */\n    err = iwm_add_aux_sta(sc);\n    if (err) {\n        XYLog(\"%s: could not add aux station (error %d)\\n\",\n              DEVNAME(sc), err);\n        goto err;\n    }\n    \n    for (i = 0; i < IWM_NUM_PHY_CTX; i++) {\n        /*\n         * The channel used here isn't relevant as it's\n         * going to be overwritten in the other flows.\n         * For now use the first channel we have.\n         */\n        sc->sc_phyctxt[i].id = i;\n        sc->sc_phyctxt[i].channel = &ic->ic_channels[1];\n        err = iwm_phy_ctxt_cmd(sc, &sc->sc_phyctxt[i], 1, 1,\n                               IWM_FW_CTXT_ACTION_ADD, 0);\n        if (err) {\n            XYLog(\"%s: could not add phy context %d (error %d)\\n\",\n                  DEVNAME(sc), i, err);\n            goto err;\n        }\n    }\n    \n    /* Initialize tx backoffs to the minimum. */\n    if (sc->sc_device_family == IWM_DEVICE_FAMILY_7000)\n        iwm_tt_tx_backoff(sc, 0);\n    \n    \n    err = iwm_config_ltr(sc);\n    if (err) {\n        XYLog(\"%s: PCIe LTR configuration failed (error %d)\\n\",\n              DEVNAME(sc), err);\n    }\n    \n    if (isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_CT_KILL_BY_FW)) {\n        err = iwm_send_temp_report_ths_cmd(sc);\n        if (err)\n            goto err;\n    }\n    \n    err = iwm_power_update_device(sc);\n    if (err) {\n        XYLog(\"%s: could not send power command (error %d)\\n\",\n              DEVNAME(sc), err);\n        goto err;\n    }\n    \n    if (isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_LAR_SUPPORT)) {\n        err = iwm_send_update_mcc_cmd(sc, \"ZZ\");\n        if (err) {\n            XYLog(\"%s: could not init LAR (error %d)\\n\",\n                  DEVNAME(sc), err);\n            goto err;\n        }\n    }\n    \n    if (isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_UMAC_SCAN)) {\n        err = iwm_config_umac_scan(sc);\n        if (err) {\n            XYLog(\"%s: could not configure scan (error %d)\\n\",\n                  DEVNAME(sc), err);\n            goto err;\n        }\n    }\n    \n    if (ic->ic_opmode == IEEE80211_M_MONITOR) {\n        if (isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_DQA_SUPPORT))\n            qid = IWM_DQA_INJECT_MONITOR_QUEUE;\n        else\n            qid = IWM_AUX_QUEUE;\n        err = iwm_enable_txq(sc, IWM_MONITOR_STA_ID, qid,\n                             iwm_ac_to_tx_fifo[EDCA_AC_BE], 0, IWM_MAX_TID_COUNT, 0);\n        if (err) {\n            XYLog(\"%s: could not enable monitor inject Tx queue \"\n                  \"(error %d)\\n\", DEVNAME(sc), err);\n            goto err;\n        }\n    } else {\n        for (ac = 0; ac < EDCA_NUM_AC; ac++) {\n            if (isset(sc->sc_enabled_capa,\n                      IWM_UCODE_TLV_CAPA_DQA_SUPPORT))\n                qid = ac + IWM_DQA_MIN_MGMT_QUEUE;\n            else\n                qid = ac;\n            err = iwm_enable_txq(sc, IWM_STATION_ID, qid,\n                                 iwm_ac_to_tx_fifo[ac], 0, IWM_TID_NON_QOS, 0);\n            if (err) {\n                XYLog(\"%s: could not enable Tx queue %d \"\n                      \"(error %d)\\n\", DEVNAME(sc), ac, err);\n                goto err;\n            }\n        }\n    }\n    \n    err = iwm_disable_beacon_filter(sc);\n    if (err) {\n        XYLog(\"%s: could not disable beacon filter (error %d)\\n\",\n              DEVNAME(sc), err);\n        goto err;\n    }\n    \nerr:\n    iwm_nic_unlock(sc);\n    return err;\n}\n\nint ItlIwm::\niwm_init(struct _ifnet *ifp)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwm_softc *sc = (struct iwm_softc*)ifp->if_softc;\n    struct ieee80211com *ic = &sc->sc_ic;\n    ItlIwm *that = container_of(sc, ItlIwm, com);\n    int err, generation;\n    \n    //    rw_assert_wrlock(&sc->ioctl_rwl);\n    sc->agg_tid_disable = 0xffff;\n    sc->agg_queue_mask = 0;\n    memset(sc->sc_tx_ba, 0, sizeof(sc->sc_tx_ba));\n    \n    generation = ++sc->sc_generation;\n    \n    KASSERT(sc->task_refs.refs == 0, \"sc->task_refs.refs == 0\");\n    //        refcnt_init(&sc->task_refs);\n    \n    err = iwm_init_hw(sc);\n    if (err) {\n        if (generation == sc->sc_generation)\n            iwm_stop_device(sc);\n        return err;\n    }\n    \n    if (sc->sc_nvm.sku_cap_11n_enable)\n        iwm_setup_ht_rates(sc);\n    \n    if (sc->sc_nvm.sku_cap_11ac_enable)\n        iwm_setup_vht_rates(sc);\n    \n    ifq_clr_oactive(&ifp->if_snd);\n    ifq_flush(&ifp->if_snd);\n    ifp->if_flags |= IFF_RUNNING;\n    \n    if (ic->ic_opmode == IEEE80211_M_MONITOR) {\n        ic->ic_bss->ni_chan = ic->ic_ibss_chan;\n        ieee80211_new_state(ic, IEEE80211_S_RUN, -1);\n        return 0;\n    }\n    \n    ieee80211_begin_scan(ifp);\n    \n    /*\n     * ieee80211_begin_scan() ends up scheduling iwm_newstate_task().\n     * Wait until the transition to SCAN state has completed.\n     */\n    do {\n        err = tsleep_nsec(&ic->ic_state, PCATCH, \"iwminit\",\n                          SEC_TO_NSEC(1));\n        if (generation != sc->sc_generation)\n            return ENXIO;\n        if (err) {\n            iwm_stop(ifp);\n            return err;\n        }\n    } while (ic->ic_state != IEEE80211_S_SCAN);\n    \n    return 0;\n}\n\nIOReturn ItlIwm::\n_iwm_start_task(OSObject *target, void *arg0, void *arg1, void *arg2, void *arg3)\n{\n    struct _ifnet *ifp = (struct _ifnet *)arg0;\n    struct iwm_softc *sc = (struct iwm_softc*)ifp->if_softc;\n    ItlIwm *that = container_of(sc, ItlIwm, com);\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct ieee80211_node *ni;\n    struct ether_header *eh;\n    mbuf_t m;\n    int ac = EDCA_AC_BE; /* XXX */\n    \n    if (!(ifp->if_flags & IFF_RUNNING) || ifq_is_oactive(&ifp->if_snd)) {\n        return kIOReturnOutputDropped;\n    }\n    \n    for (;;) {\n        /* why isn't this done per-queue? */\n        if (sc->qfullmsk != 0) {\n            ifq_set_oactive(&ifp->if_snd);\n            break;\n        }\n        \n        /* need to send management frames even if we're not RUNning */\n        m = mq_dequeue(&ic->ic_mgtq);\n        if (m) {\n            ni = (struct ieee80211_node *)mbuf_pkthdr_rcvif(m);\n            goto sendit;\n        }\n        \n        if (\n#ifndef AIRPORT\n            ic->ic_state != IEEE80211_S_RUN ||\n#endif\n            (ic->ic_xflags & IEEE80211_F_TX_MGMT_ONLY))\n            break;\n        \n        m = ifq_dequeue(&ifp->if_snd);\n        if (!m) {\n            break;\n        }\n        if (mbuf_len(m) < sizeof (*eh) &&\n            mbuf_pullup(&m, sizeof (*eh)) != 0) {\n            XYLog(\"%s %d OUTPUT_ERROR\\n\", __FUNCTION__, __LINE__);\n            ifp->netStat->outputErrors++;\n            continue;\n        }\n#if NBPFILTER > 0\n        if (ifp->if_bpf != NULL)\n            bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);\n#endif\n        if ((m = ieee80211_encap(ifp, m, &ni)) == NULL) {\n            XYLog(\"%s %d ieee80211_encap OUTPUT_ERROR\\n\", __FUNCTION__, __LINE__);\n            ifp->netStat->outputErrors++;\n            continue;\n        }\n//        XYLog(\"%s if_snd->send\\n\", __FUNCTION__);\n        \n    sendit:\n#if NBPFILTER > 0\n        if (ic->ic_rawbpf != NULL)\n            bpf_mtap(ic->ic_rawbpf, m, BPF_DIRECTION_OUT);\n#endif\n        if (that->iwm_tx(sc, m, ni, ac) != 0) {\n            XYLog(\"%s %d iwm_tx OUTPUT_ERROR\\n\", __FUNCTION__, __LINE__);\n            ieee80211_release_node(ic, ni);\n            ifp->netStat->outputErrors++;\n            continue;\n        }\n        ifp->netStat->outputPackets++;\n        \n        if (ifp->if_flags & IFF_UP)\n            ifp->if_timer = 1;\n    }\n    \n    return kIOReturnSuccess;\n}\n\nvoid ItlIwm::\niwm_start(struct _ifnet *ifp)\n{\n    struct iwm_softc *sc = (struct iwm_softc*)ifp->if_softc;\n    ItlIwm *that = container_of(sc, ItlIwm, com);\n//        if (that->outputThreadSignal) {\n//            semaphore_signal(that->outputThreadSignal);\n//        }\n    that->getMainCommandGate()->attemptAction(_iwm_start_task, &that->com.sc_ic.ic_ac.ac_if);\n//    _iwm_start_task(that, &that->com.sc_ic.ic_ac.ac_if, NULL, NULL, NULL);\n}\n\nvoid ItlIwm::\niwm_stop(struct _ifnet *ifp)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwm_softc *sc = (struct iwm_softc*)ifp->if_softc;\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct iwm_node *in = (struct iwm_node *)ic->ic_bss;\n    int i, s = splnet();\n    \n    //    rw_assert_wrlock(&sc->ioctl_rwl);\n    \n    sc->sc_flags |= IWM_FLAG_SHUTDOWN; /* Disallow new tasks. */\n    \n    /* Cancel scheduled tasks and let any stale tasks finish up. */\n    task_del(systq, &sc->init_task);\n    iwm_del_task(sc, sc->sc_nswq, &sc->newstate_task);\n    iwm_del_task(sc, systq, &sc->ba_task);\n    iwm_del_task(sc, systq, &sc->mac_ctxt_task);\n    iwm_del_task(sc, systq, &sc->chan_ctxt_task);\n    //    KASSERT(sc->task_refs.refs >= 1, \"sc->task_refs.refs >= 1\");\n    //    refcnt_finalize(&sc->task_refs, \"iwmstop\");\n    \n    iwm_stop_device(sc);\n    \n    /* Reset soft state. */\n    \n    sc->sc_generation++;\n    for (i = 0; i < nitems(sc->sc_cmd_resp_pkt); i++) {\n        ::free(sc->sc_cmd_resp_pkt[i]);\n        sc->sc_cmd_resp_pkt[i] = NULL;\n        sc->sc_cmd_resp_len[i] = 0;\n    }\n    ifp->if_flags &= ~IFF_RUNNING;\n    ifq_flush(&ifp->if_snd);\n    ifq_clr_oactive(&ifp->if_snd);\n    \n    in->in_phyctxt = NULL;\n    in->in_ni.ni_chw = IEEE80211_CHAN_WIDTH_20_NOHT;\n    IEEE80211_ADDR_COPY(in->in_macaddr, etheranyaddr);\n    \n    sc->sc_flags &= ~(IWM_FLAG_SCANNING | IWM_FLAG_BGSCAN);\n    sc->sc_flags &= ~IWM_FLAG_MAC_ACTIVE;\n    sc->sc_flags &= ~IWM_FLAG_BINDING_ACTIVE;\n    sc->sc_flags &= ~IWM_FLAG_STA_ACTIVE;\n    sc->sc_flags &= ~IWM_FLAG_TE_ACTIVE;\n    sc->sc_flags &= ~IWM_FLAG_HW_ERR;\n    sc->sc_flags &= ~IWM_FLAG_SHUTDOWN;\n\n    sc->sc_rx_ba_sessions = 0;\n    sc->ba_rx.start_tidmask = 0;\n    sc->ba_rx.stop_tidmask = 0;\n    for (i = 0; i < nitems(sc->sc_tx_ba); i++)\n        sc->sc_tx_ba[i].wn = NULL;\n    sc->ba_tx.start_tidmask = 0;\n    sc->ba_tx.stop_tidmask = 0;\n    \n    sc->sc_newstate(ic, IEEE80211_S_INIT, -1);\n    sc->ns_nstate = IEEE80211_S_INIT;\n    \n    timeout_del(&sc->sc_calib_to); /* XXX refcount? */\n    for (i = 0; i < nitems(sc->sc_rxba_data); i++) {\n        struct iwm_rxba_data *rxba = &sc->sc_rxba_data[i];\n        iwm_clear_reorder_buffer(sc, rxba);\n    }\n    iwm_led_blink_stop(sc);\n    memset(sc->sc_tx_timer, 0, sizeof(sc->sc_tx_timer));\n    ifp->if_timer = 0;\n    \n    splx(s);\n}\n\nvoid ItlIwm::\niwm_watchdog(struct _ifnet *ifp)\n{\n    struct iwm_softc *sc = (struct iwm_softc *)ifp->if_softc;\n    ItlIwm *that = container_of(sc, ItlIwm, com);\n    int i;\n    \n    ifp->if_timer = 0;\n\n    /*\n     * We maintain a separate timer for each Tx queue because\n     * Tx aggregation queues can get \"stuck\" while other queues\n     * keep working. The Linux driver uses a similar workaround.\n     */\n    for (i = 0; i < nitems(sc->sc_tx_timer); i++) {\n        if (sc->sc_tx_timer[i] > 0) {\n            if (--sc->sc_tx_timer[i] == 0) {\n                XYLog(\"%s: device timeout\\n\", DEVNAME(sc));\n#ifdef IWM_DEBUG\n                that->iwm_nic_error(sc);\n#endif\n                if ((sc->sc_flags & IWM_FLAG_SHUTDOWN) == 0) {\n                    task_add(systq, &sc->init_task);\n                }\n                XYLog(\"%s %d OUTPUT_ERROR\\n\", __FUNCTION__, __LINE__);\n                ifp->netStat->outputErrors++;\n                return;\n            }\n            ifp->if_timer = 1;\n        }\n    }\n    \n    ieee80211_watchdog(ifp);\n}\n\nint ItlIwm::\niwm_ioctl(struct _ifnet *ifp, u_long cmd, caddr_t data)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwm_softc *sc = (struct iwm_softc *)ifp->if_softc;\n    ItlIwm *that = container_of(sc, ItlIwm, com);\n    int s, err = 0, generation = sc->sc_generation;\n    \n    /*\n     * Prevent processes from entering this function while another\n     * process is tsleep'ing in it.\n     */\n    //    err = rw_enter(&sc->ioctl_rwl, RW_WRITE | RW_INTR);\n    if (err == 0 && generation != sc->sc_generation) {\n        //        rw_exit(&sc->ioctl_rwl);\n        return ENXIO;\n    }\n    if (err)\n        return err;\n    s = splnet();\n    \n    switch (cmd) {\n        case SIOCSIFADDR:\n            ifp->if_flags |= IFF_UP;\n            /* FALLTHROUGH */\n        case SIOCSIFFLAGS:\n            if (ifp->if_flags & IFF_UP) {\n                if (!(ifp->if_flags & IFF_RUNNING)) {\n                    err = that->iwm_init(ifp);\n                }\n            } else {\n                if (ifp->if_flags & IFF_RUNNING)\n                    that->iwm_stop(ifp);\n            }\n            break;\n            \n        default:\n            err = ieee80211_ioctl(ifp, cmd, data);\n    }\n    \n    if (err == ENETRESET) {\n        err = 0;\n        if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==\n            (IFF_UP | IFF_RUNNING)) {\n            that->iwm_stop(ifp);\n            err = that->iwm_init(ifp);\n        }\n    }\n    \n    splx(s);\n    //    rw_exit(&sc->ioctl_rwl);\n    \n    return err;\n}\n\n#ifdef IWM_DEBUG\n/*\n * Note: This structure is read from the device with IO accesses,\n * and the reading already does the endian conversion. As it is\n * read with uint32_t-sized accesses, any members with a different size\n * need to be ordered correctly though!\n */\nstruct iwm_error_event_table {\n    uint32_t valid;        /* (nonzero) valid, (0) log is empty */\n    uint32_t error_id;        /* type of error */\n    uint32_t trm_hw_status0;    /* TRM HW status */\n    uint32_t trm_hw_status1;    /* TRM HW status */\n    uint32_t blink2;        /* branch link */\n    uint32_t ilink1;        /* interrupt link */\n    uint32_t ilink2;        /* interrupt link */\n    uint32_t data1;        /* error-specific data */\n    uint32_t data2;        /* error-specific data */\n    uint32_t data3;        /* error-specific data */\n    uint32_t bcon_time;        /* beacon timer */\n    uint32_t tsf_low;        /* network timestamp function timer */\n    uint32_t tsf_hi;        /* network timestamp function timer */\n    uint32_t gp1;        /* GP1 timer register */\n    uint32_t gp2;        /* GP2 timer register */\n    uint32_t fw_rev_type;    /* firmware revision type */\n    uint32_t major;        /* uCode version major */\n    uint32_t minor;        /* uCode version minor */\n    uint32_t hw_ver;        /* HW Silicon version */\n    uint32_t brd_ver;        /* HW board version */\n    uint32_t log_pc;        /* log program counter */\n    uint32_t frame_ptr;        /* frame pointer */\n    uint32_t stack_ptr;        /* stack pointer */\n    uint32_t hcmd;        /* last host command header */\n    uint32_t isr0;        /* isr status register LMPM_NIC_ISR0:\n                           * rxtx_flag */\n    uint32_t isr1;        /* isr status register LMPM_NIC_ISR1:\n                           * host_flag */\n    uint32_t isr2;        /* isr status register LMPM_NIC_ISR2:\n                           * enc_flag */\n    uint32_t isr3;        /* isr status register LMPM_NIC_ISR3:\n                           * time_flag */\n    uint32_t isr4;        /* isr status register LMPM_NIC_ISR4:\n                           * wico interrupt */\n    uint32_t last_cmd_id;    /* last HCMD id handled by the firmware */\n    uint32_t wait_event;        /* wait event() caller address */\n    uint32_t l2p_control;    /* L2pControlField */\n    uint32_t l2p_duration;    /* L2pDurationField */\n    uint32_t l2p_mhvalid;    /* L2pMhValidBits */\n    uint32_t l2p_addr_match;    /* L2pAddrMatchStat */\n    uint32_t lmpm_pmg_sel;    /* indicate which clocks are turned on\n                               * (LMPM_PMG_SEL) */\n    uint32_t u_timestamp;    /* indicate when the date and time of the\n                              * compilation */\n    uint32_t flow_handler;    /* FH read/write pointers, RX credit */\n} __packed /* LOG_ERROR_TABLE_API_S_VER_3 */;\n\n/*\n * UMAC error struct - relevant starting from family 8000 chip.\n * Note: This structure is read from the device with IO accesses,\n * and the reading already does the endian conversion. As it is\n * read with u32-sized accesses, any members with a different size\n * need to be ordered correctly though!\n */\nstruct iwm_umac_error_event_table {\n    uint32_t valid;        /* (nonzero) valid, (0) log is empty */\n    uint32_t error_id;    /* type of error */\n    uint32_t blink1;    /* branch link */\n    uint32_t blink2;    /* branch link */\n    uint32_t ilink1;    /* interrupt link */\n    uint32_t ilink2;    /* interrupt link */\n    uint32_t data1;        /* error-specific data */\n    uint32_t data2;        /* error-specific data */\n    uint32_t data3;        /* error-specific data */\n    uint32_t umac_major;\n    uint32_t umac_minor;\n    uint32_t frame_pointer;    /* core register 27*/\n    uint32_t stack_pointer;    /* core register 28 */\n    uint32_t cmd_header;    /* latest host cmd sent to UMAC */\n    uint32_t nic_isr_pref;    /* ISR status register */\n} __packed;\n\n#define ERROR_START_OFFSET  (1 * sizeof(uint32_t))\n#define ERROR_ELEM_SIZE     (7 * sizeof(uint32_t))\n\nvoid ItlIwm::\niwm_nic_umac_error(struct iwm_softc *sc)\n{\n    struct iwm_umac_error_event_table table;\n    uint32_t base;\n    \n    base = sc->sc_uc.uc_umac_error_event_table;\n    \n    if (base < 0x800000) {\n        XYLog(\"%s: Invalid error log pointer 0x%08x\\n\",\n              DEVNAME(sc), base);\n        return;\n    }\n    \n    if (iwm_read_mem(sc, base, &table, sizeof(table)/sizeof(uint32_t))) {\n        XYLog(\"%s: reading errlog failed\\n\", DEVNAME(sc));\n        return;\n    }\n    \n    if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) {\n        XYLog(\"%s: Start UMAC Error Log Dump:\\n\", DEVNAME(sc));\n        XYLog(\"%s: Status: 0x%x, count: %d\\n\", DEVNAME(sc),\n              sc->sc_flags, table.valid);\n    }\n    \n    XYLog(\"%s: 0x%08X | %s\\n\", DEVNAME(sc), table.error_id,\n          iwm_desc_lookup(table.error_id));\n    XYLog(\"%s: 0x%08X | umac branchlink1\\n\", DEVNAME(sc), table.blink1);\n    XYLog(\"%s: 0x%08X | umac branchlink2\\n\", DEVNAME(sc), table.blink2);\n    XYLog(\"%s: 0x%08X | umac interruptlink1\\n\", DEVNAME(sc), table.ilink1);\n    XYLog(\"%s: 0x%08X | umac interruptlink2\\n\", DEVNAME(sc), table.ilink2);\n    XYLog(\"%s: 0x%08X | umac data1\\n\", DEVNAME(sc), table.data1);\n    XYLog(\"%s: 0x%08X | umac data2\\n\", DEVNAME(sc), table.data2);\n    XYLog(\"%s: 0x%08X | umac data3\\n\", DEVNAME(sc), table.data3);\n    XYLog(\"%s: 0x%08X | umac major\\n\", DEVNAME(sc), table.umac_major);\n    XYLog(\"%s: 0x%08X | umac minor\\n\", DEVNAME(sc), table.umac_minor);\n    XYLog(\"%s: 0x%08X | frame pointer\\n\", DEVNAME(sc),\n          table.frame_pointer);\n    XYLog(\"%s: 0x%08X | stack pointer\\n\", DEVNAME(sc),\n          table.stack_pointer);\n    XYLog(\"%s: 0x%08X | last host cmd\\n\", DEVNAME(sc), table.cmd_header);\n    XYLog(\"%s: 0x%08X | isr status reg\\n\", DEVNAME(sc),\n          table.nic_isr_pref);\n}\n\n#define IWM_FW_SYSASSERT_CPU_MASK 0xf0000000\nstatic struct {\n    const char *name;\n    uint8_t num;\n} advanced_lookup[] = {\n    { \"NMI_INTERRUPT_WDG\", 0x34 },\n    { \"SYSASSERT\", 0x35 },\n    { \"UCODE_VERSION_MISMATCH\", 0x37 },\n    { \"BAD_COMMAND\", 0x38 },\n    { \"BAD_COMMAND\", 0x39 },\n    { \"NMI_INTERRUPT_DATA_ACTION_PT\", 0x3C },\n    { \"FATAL_ERROR\", 0x3D },\n    { \"NMI_TRM_HW_ERR\", 0x46 },\n    { \"NMI_INTERRUPT_TRM\", 0x4C },\n    { \"NMI_INTERRUPT_BREAK_POINT\", 0x54 },\n    { \"NMI_INTERRUPT_WDG_RXF_FULL\", 0x5C },\n    { \"NMI_INTERRUPT_WDG_NO_RBD_RXF_FULL\", 0x64 },\n    { \"NMI_INTERRUPT_HOST\", 0x66 },\n    { \"NMI_INTERRUPT_LMAC_FATAL\", 0x70 },\n    { \"NMI_INTERRUPT_UMAC_FATAL\", 0x71 },\n    { \"NMI_INTERRUPT_OTHER_LMAC_FATAL\", 0x73 },\n    { \"NMI_INTERRUPT_ACTION_PT\", 0x7C },\n    { \"NMI_INTERRUPT_UNKNOWN\", 0x84 },\n    { \"NMI_INTERRUPT_INST_ACTION_PT\", 0x86 },\n    { \"ADVANCED_SYSASSERT\", 0 },\n};\n\nconst char *ItlIwm::\niwm_desc_lookup(uint32_t num)\n{\n    int i;\n    \n    for (i = 0; i < nitems(advanced_lookup) - 1; i++)\n        if (advanced_lookup[i].num ==\n            (num & ~IWM_FW_SYSASSERT_CPU_MASK))\n            return advanced_lookup[i].name;\n    \n    /* No entry matches 'num', so it is the last: ADVANCED_SYSASSERT */\n    return advanced_lookup[i].name;\n}\n\n/*\n * Support for dumping the error log seemed like a good idea ...\n * but it's mostly hex junk and the only sensible thing is the\n * hw/ucode revision (which we know anyway).  Since it's here,\n * I'll just leave it in, just in case e.g. the Intel guys want to\n * help us decipher some \"ADVANCED_SYSASSERT\" later.\n */\nvoid ItlIwm::\niwm_nic_error(struct iwm_softc *sc)\n{\n    struct iwm_error_event_table table;\n    uint32_t base;\n    \n    XYLog(\"%s: dumping device error log\\n\", DEVNAME(sc));\n    base = sc->sc_uc.uc_error_event_table;\n    if (base < 0x800000) {\n        XYLog(\"%s: Invalid error log pointer 0x%08x\\n\",\n              DEVNAME(sc), base);\n        return;\n    }\n    \n    if (iwm_read_mem(sc, base, &table, sizeof(table)/sizeof(uint32_t))) {\n        XYLog(\"%s: reading errlog failed\\n\", DEVNAME(sc));\n        return;\n    }\n    \n    if (!table.valid) {\n        XYLog(\"%s: errlog not found, skipping\\n\", DEVNAME(sc));\n        return;\n    }\n    \n    if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) {\n        XYLog(\"%s: Start Error Log Dump:\\n\", DEVNAME(sc));\n        XYLog(\"%s: Status: 0x%x, count: %d\\n\", DEVNAME(sc),\n              sc->sc_flags, table.valid);\n    }\n    \n    XYLog(\"%s: 0x%08X | %-28s\\n\", DEVNAME(sc), table.error_id,\n          iwm_desc_lookup(table.error_id));\n    XYLog(\"%s: %08X | trm_hw_status0\\n\", DEVNAME(sc),\n          table.trm_hw_status0);\n    XYLog(\"%s: %08X | trm_hw_status1\\n\", DEVNAME(sc),\n          table.trm_hw_status1);\n    XYLog(\"%s: %08X | branchlink2\\n\", DEVNAME(sc), table.blink2);\n    XYLog(\"%s: %08X | interruptlink1\\n\", DEVNAME(sc), table.ilink1);\n    XYLog(\"%s: %08X | interruptlink2\\n\", DEVNAME(sc), table.ilink2);\n    XYLog(\"%s: %08X | data1\\n\", DEVNAME(sc), table.data1);\n    XYLog(\"%s: %08X | data2\\n\", DEVNAME(sc), table.data2);\n    XYLog(\"%s: %08X | data3\\n\", DEVNAME(sc), table.data3);\n    XYLog(\"%s: %08X | beacon time\\n\", DEVNAME(sc), table.bcon_time);\n    XYLog(\"%s: %08X | tsf low\\n\", DEVNAME(sc), table.tsf_low);\n    XYLog(\"%s: %08X | tsf hi\\n\", DEVNAME(sc), table.tsf_hi);\n    XYLog(\"%s: %08X | time gp1\\n\", DEVNAME(sc), table.gp1);\n    XYLog(\"%s: %08X | time gp2\\n\", DEVNAME(sc), table.gp2);\n    XYLog(\"%s: %08X | uCode revision type\\n\", DEVNAME(sc),\n          table.fw_rev_type);\n    XYLog(\"%s: %08X | uCode version major\\n\", DEVNAME(sc),\n          table.major);\n    XYLog(\"%s: %08X | uCode version minor\\n\", DEVNAME(sc),\n          table.minor);\n    XYLog(\"%s: %08X | hw version\\n\", DEVNAME(sc), table.hw_ver);\n    XYLog(\"%s: %08X | board version\\n\", DEVNAME(sc), table.brd_ver);\n    XYLog(\"%s: %08X | hcmd\\n\", DEVNAME(sc), table.hcmd);\n    XYLog(\"%s: %08X | isr0\\n\", DEVNAME(sc), table.isr0);\n    XYLog(\"%s: %08X | isr1\\n\", DEVNAME(sc), table.isr1);\n    XYLog(\"%s: %08X | isr2\\n\", DEVNAME(sc), table.isr2);\n    XYLog(\"%s: %08X | isr3\\n\", DEVNAME(sc), table.isr3);\n    XYLog(\"%s: %08X | isr4\\n\", DEVNAME(sc), table.isr4);\n    XYLog(\"%s: %08X | last cmd Id\\n\", DEVNAME(sc), table.last_cmd_id);\n    XYLog(\"%s: %08X | wait_event\\n\", DEVNAME(sc), table.wait_event);\n    XYLog(\"%s: %08X | l2p_control\\n\", DEVNAME(sc), table.l2p_control);\n    XYLog(\"%s: %08X | l2p_duration\\n\", DEVNAME(sc), table.l2p_duration);\n    XYLog(\"%s: %08X | l2p_mhvalid\\n\", DEVNAME(sc), table.l2p_mhvalid);\n    XYLog(\"%s: %08X | l2p_addr_match\\n\", DEVNAME(sc), table.l2p_addr_match);\n    XYLog(\"%s: %08X | lmpm_pmg_sel\\n\", DEVNAME(sc), table.lmpm_pmg_sel);\n    XYLog(\"%s: %08X | timestamp\\n\", DEVNAME(sc), table.u_timestamp);\n    XYLog(\"%s: %08X | flow_handler\\n\", DEVNAME(sc), table.flow_handler);\n    \n    if (sc->sc_uc.uc_umac_error_event_table)\n        iwm_nic_umac_error(sc);\n}\n#endif\n\n#define ADVANCE_RXQ(sc) (sc->rxq.cur = (sc->rxq.cur + 1) % count);\n\nvoid ItlIwm::\niwm_notif_intr(struct iwm_softc *sc)\n{\n    struct mbuf_list ml = MBUF_LIST_INITIALIZER();\n    uint32_t wreg;\n    uint16_t hw;\n    int count;\n    \n    //        bus_dmamap_sync(sc->sc_dmat, sc->rxq.stat_dma.map,\n    //            0, sc->rxq.stat_dma.size, BUS_DMASYNC_POSTREAD);\n    \n    if (sc->sc_mqrx_supported) {\n        count = IWM_RX_MQ_RING_COUNT;\n        wreg = IWM_RFH_Q0_FRBDCB_WIDX_TRG;\n    } else {\n        count = IWM_RX_RING_COUNT;\n        wreg = IWM_FH_RSCSR_CHNL0_WPTR;\n    }\n    \n    hw = le16toh(sc->rxq.stat->closed_rb_num) & 0xfff;\n    hw &= (count - 1);\n    while (sc->rxq.cur != hw) {\n        struct iwm_rx_data *data = &sc->rxq.data[sc->rxq.cur];\n        iwm_rx_pkt(sc, data, &ml);\n        ADVANCE_RXQ(sc);\n    }\n    if_input(&sc->sc_ic.ic_if, &ml);\n    /*\n     * Tell the firmware what we have processed.\n     * Seems like the hardware gets upset unless we align the write by 8??\n     */\n    hw = (hw == 0) ? count - 1 : hw - 1;\n    IWM_WRITE(sc, wreg, hw & ~7);\n}\n\nint ItlIwm::\niwm_intr(OSObject *arg, IOInterruptEventSource* sender, int count)\n{\n    ItlIwm *that = (ItlIwm*)arg;\n    struct iwm_softc *sc = &that->com;\n    int handled = 0;\n    int rv = 0;\n    uint32_t r1, r2;\n    \n    if (sc->sc_flags & IWM_FLAG_USE_ICT) {\n        uint32_t *ict = (uint32_t *)sc->ict_dma.vaddr;\n        int tmp;\n        \n        tmp = htole32(ict[sc->ict_cur]);\n        if (!tmp)\n            goto out_ena;\n        \n        /*\n         * ok, there was something.  keep plowing until we have all.\n         */\n        r1 = r2 = 0;\n        while (tmp) {\n            r1 |= tmp;\n            ict[sc->ict_cur] = 0;\n            sc->ict_cur = (sc->ict_cur+1) % IWM_ICT_COUNT;\n            tmp = htole32(ict[sc->ict_cur]);\n        }\n        \n        /* this is where the fun begins.  don't ask */\n        if (r1 == 0xffffffff)\n            r1 = 0;\n        \n        /*\n         * Workaround for hardware bug where bits are falsely cleared\n         * when using interrupt coalescing.  Bit 15 should be set if\n         * bits 18 and 19 are set.\n         */\n        if (r1 & 0xc0000)\n            r1 |= 0x8000;\n        \n        r1 = (0xff & r1) | ((0xff00 & r1) << 16);\n    } else {\n        r1 = IWM_READ(sc, IWM_CSR_INT);\n        r2 = IWM_READ(sc, IWM_CSR_FH_INT_STATUS);\n    }\n    if (r1 == 0 && r2 == 0) {\n        goto out_ena;\n    }\n    if (r1 == 0xffffffff || (r1 & 0xfffffff0) == 0xa5a5a5a0)\n        goto out;\n    \n    IWM_WRITE(sc, IWM_CSR_INT, r1 | ~sc->sc_intmask);\n    \n    /* ignored */\n    handled |= (r1 & (IWM_CSR_INT_BIT_ALIVE /*| IWM_CSR_INT_BIT_SCD*/));\n    \n    if (r1 & IWM_CSR_INT_BIT_RF_KILL) {\n        handled |= IWM_CSR_INT_BIT_RF_KILL;\n        XYLog(\"%s RF_KILL has been toggled\\n\", __FUNCTION__);\n        that->iwm_check_rfkill(sc);\n        task_add(systq, &sc->init_task);\n        rv = 1;\n        goto out_ena;\n    }\n    \n    if (r1 & IWM_CSR_INT_BIT_SW_ERR) {\n#ifdef IWM_DEBUG\n        int i;\n        \n        that->iwm_nic_error(sc);\n        \n        /* Dump driver status (TX and RX rings) while we're here. */\n        XYLog(\"driver status:\\n\");\n        for (i = 0; i < IWM_MAX_QUEUES; i++) {\n            struct iwm_tx_ring *ring = &sc->txq[i];\n            XYLog(\"  tx ring %2d: qid=%-2d cur=%-3d \"\n                  \"queued=%-3d\\n\",\n                  i, ring->qid, ring->cur, ring->queued);\n        }\n        XYLog(\"  rx ring: cur=%d\\n\", sc->rxq.cur);\n        XYLog(\"  802.11 state %s\\n\",\n              ieee80211_state_name[sc->sc_ic.ic_state]);\n#endif\n        \n        XYLog(\"%s: fatal firmware error\\n\", DEVNAME(sc));\n        if ((sc->sc_flags & IWM_FLAG_SHUTDOWN) == 0)\n            task_add(systq, &sc->init_task);\n        rv = 1;\n        goto out;\n        \n    }\n    \n    if (r1 & IWM_CSR_INT_BIT_HW_ERR) {\n        handled |= IWM_CSR_INT_BIT_HW_ERR;\n        XYLog(\"%s: hardware error, stopping device \\n\", DEVNAME(sc));\n        if ((sc->sc_flags & IWM_FLAG_SHUTDOWN) == 0) {\n            sc->sc_flags |= IWM_FLAG_HW_ERR;\n            task_add(systq, &sc->init_task);\n        }\n        rv = 1;\n        goto out;\n    }\n    \n    /* firmware chunk loaded */\n    if (r1 & IWM_CSR_INT_BIT_FH_TX) {\n        IWM_WRITE(sc, IWM_CSR_FH_INT_STATUS, IWM_CSR_FH_INT_TX_MASK);\n        handled |= IWM_CSR_INT_BIT_FH_TX;\n        \n        sc->sc_fw_chunk_done = 1;\n        that->wakeupOn(&sc->sc_fw);\n    }\n    \n    if (r1 & (IWM_CSR_INT_BIT_FH_RX | IWM_CSR_INT_BIT_SW_RX |\n              IWM_CSR_INT_BIT_RX_PERIODIC)) {\n        if (r1 & (IWM_CSR_INT_BIT_FH_RX | IWM_CSR_INT_BIT_SW_RX)) {\n            handled |= (IWM_CSR_INT_BIT_FH_RX | IWM_CSR_INT_BIT_SW_RX);\n            IWM_WRITE(sc, IWM_CSR_FH_INT_STATUS, IWM_CSR_FH_INT_RX_MASK);\n        }\n        if (r1 & IWM_CSR_INT_BIT_RX_PERIODIC) {\n            handled |= IWM_CSR_INT_BIT_RX_PERIODIC;\n            IWM_WRITE(sc, IWM_CSR_INT, IWM_CSR_INT_BIT_RX_PERIODIC);\n        }\n        \n        /* Disable periodic interrupt; we use it as just a one-shot. */\n        IWM_WRITE_1(sc, IWM_CSR_INT_PERIODIC_REG, IWM_CSR_INT_PERIODIC_DIS);\n        \n        /*\n         * Enable periodic interrupt in 8 msec only if we received\n         * real RX interrupt (instead of just periodic int), to catch\n         * any dangling Rx interrupt.  If it was just the periodic\n         * interrupt, there was no dangling Rx activity, and no need\n         * to extend the periodic interrupt; one-shot is enough.\n         */\n        if (r1 & (IWM_CSR_INT_BIT_FH_RX | IWM_CSR_INT_BIT_SW_RX))\n            IWM_WRITE_1(sc, IWM_CSR_INT_PERIODIC_REG,\n                        IWM_CSR_INT_PERIODIC_ENA);\n        \n        that->iwm_notif_intr(sc);\n    }\n    \n    rv = 1;\n    \nout_ena:\n    that->iwm_restore_interrupts(sc);\nout:\n    return rv;\n}\n\nint ItlIwm::\niwm_intr_msix(OSObject *object, IOInterruptEventSource* sender, int count)\n{\n    ItlIwm *that = (ItlIwm*)object;\n    struct iwm_softc *sc = &that->com;\n    uint32_t inta_fh, inta_hw;\n    int vector = 0;\n    \n    inta_fh = IWM_READ(sc, IWM_CSR_MSIX_FH_INT_CAUSES_AD);\n    inta_hw = IWM_READ(sc, IWM_CSR_MSIX_HW_INT_CAUSES_AD);\n    IWM_WRITE(sc, IWM_CSR_MSIX_FH_INT_CAUSES_AD, inta_fh);\n    IWM_WRITE(sc, IWM_CSR_MSIX_HW_INT_CAUSES_AD, inta_hw);\n    inta_fh &= sc->sc_fh_mask;\n    inta_hw &= sc->sc_hw_mask;\n    \n    if (inta_fh & IWM_MSIX_FH_INT_CAUSES_Q0 ||\n        inta_fh & IWM_MSIX_FH_INT_CAUSES_Q1) {\n        that->iwm_notif_intr(sc);\n    }\n    \n    /* firmware chunk loaded */\n    if (inta_fh & IWM_MSIX_FH_INT_CAUSES_D2S_CH0_NUM) {\n        sc->sc_fw_chunk_done = 1;\n        that->wakeupOn(&sc->sc_fw);\n    }\n    \n    if ((inta_fh & IWM_MSIX_FH_INT_CAUSES_FH_ERR) ||\n        (inta_hw & IWM_MSIX_HW_INT_CAUSES_REG_SW_ERR) ||\n        (inta_hw & IWM_MSIX_HW_INT_CAUSES_REG_SW_ERR_V2)) {\n#ifdef IWM_DEBUG\n        int i;\n        \n        that->iwm_nic_error(sc);\n        \n        /* Dump driver status (TX and RX rings) while we're here. */\n        XYLog(\"driver status:\\n\");\n        for (i = 0; i < IWM_MAX_QUEUES; i++) {\n            struct iwm_tx_ring *ring = &sc->txq[i];\n            XYLog(\"  tx ring %2d: qid=%-2d cur=%-3d \"\n                  \"queued=%-3d\\n\",\n                  i, ring->qid, ring->cur, ring->queued);\n        }\n        XYLog(\"  rx ring: cur=%d\\n\", sc->rxq.cur);\n        XYLog(\"  802.11 state %s\\n\",\n              ieee80211_state_name[sc->sc_ic.ic_state]);\n#endif\n        \n        XYLog(\"%s: fatal firmware error\\n\", DEVNAME(sc));\n        if ((sc->sc_flags & IWM_FLAG_SHUTDOWN) == 0)\n            task_add(systq, &sc->init_task);\n        return 1;\n    }\n    \n    if (inta_hw & IWM_MSIX_HW_INT_CAUSES_REG_RF_KILL) {\n        that->iwm_check_rfkill(sc);\n        task_add(systq, &sc->init_task);\n    }\n    \n    if (inta_hw & IWM_MSIX_HW_INT_CAUSES_REG_HW_ERR) {\n        XYLog(\"%s: hardware error, stopping device \\n\", DEVNAME(sc));\n        if ((sc->sc_flags & IWM_FLAG_SHUTDOWN) == 0) {\n            sc->sc_flags |= IWM_FLAG_HW_ERR;\n            task_add(systq, &sc->init_task);\n        }\n        return 1;\n    }\n    \n    /*\n     * Before sending the interrupt the HW disables it to prevent\n     * a nested interrupt. This is done by writing 1 to the corresponding\n     * bit in the mask register. After handling the interrupt, it should be\n     * re-enabled by clearing this bit. This register is defined as\n     * write 1 clear (W1C) register, meaning that it's being clear\n     * by writing 1 to the bit.\n     */\n    IWM_WRITE(sc, IWM_CSR_MSIX_AUTOMASK_ST_AD, 1 << vector);\n    return 1;\n}\n\ntypedef void *iwm_match_t;\n\n#define PCI_VENDOR_INTEL 0x8086\n#define    PCI_PRODUCT_INTEL_WL_7260_1    0x08b1        /* Dual Band Wireless AC 7260 */\n#define    PCI_PRODUCT_INTEL_WL_7260_2    0x08b2        /* Dual Band Wireless AC 7260 */\n#define    PCI_PRODUCT_INTEL_WL_3160_1    0x08b3        /* Dual Band Wireless AC 3160 */\n#define    PCI_PRODUCT_INTEL_WL_3160_2    0x08b4        /* Dual Band Wireless AC 3160 */\n#define    PCI_PRODUCT_INTEL_WL_7265_1    0x095a        /* Dual Band Wireless AC 7265 */\n#define    PCI_PRODUCT_INTEL_WL_7265_2    0x095b        /* Dual Band Wireless AC 7265 */\n#define    PCI_PRODUCT_INTEL_WL_3165_1    0x3165        /* Dual Band Wireless AC 3165 */\n#define    PCI_PRODUCT_INTEL_WL_3165_2    0x3166        /* Dual Band Wireless AC 3165 */\n#define    PCI_PRODUCT_INTEL_WL_8260_1    0x24f3        /* Dual Band Wireless AC 8260 */\n#define    PCI_PRODUCT_INTEL_WL_8260_2    0x24f4        /* Dual Band Wireless AC 8260 */\n#define    PCI_PRODUCT_INTEL_WL_4165_1    0x24f5        /* Dual Band Wireless AC 4165 */\n#define    PCI_PRODUCT_INTEL_WL_4165_2    0x24f6        /* Dual Band Wireless AC 4165 */\n#define    PCI_PRODUCT_INTEL_WL_3168_1    0x24fb        /* Dual Band Wireless-AC 3168 */\n#define    PCI_PRODUCT_INTEL_WL_8265_1    0x24fd        /* Dual Band Wireless-AC 8265 */\n#define    PCI_PRODUCT_INTEL_WL_9260_1    0x2526\n#define    PCI_PRODUCT_INTEL_WL_9560_1    0x9df0        /* Dual Band Wireless AC 9560 */\n#define    PCI_PRODUCT_INTEL_WL_9560_2    0xa370        /* Dual Band Wireless AC 9560 */\n#define    PCI_PRODUCT_INTEL_WL_9560_3    0x31DC        /* Dual Band Wireless AC 9560 */\n#define    PCI_PRODUCT_INTEL_WL_9560_4    0x30DC        /* Dual Band Wireless AC 9560 */\n#define    PCI_PRODUCT_INTEL_WL_9560_5    0x271C        /* Dual Band Wireless AC 9560 */\n#define    PCI_PRODUCT_INTEL_WL_9560_6    0x271B        /* Dual Band Wireless AC 9560 */\n#define    PCI_PRODUCT_INTEL_WL_9462_1    0x42a4        /* Dual Band Wireless AC 9462 */\n#define    PCI_PRODUCT_INTEL_WL_9462_2    0x00a0        /* Dual Band Wireless AC 9462 */\n#define    PCI_PRODUCT_INTEL_WL_9462_3    0x00a4        /* Dual Band Wireless AC 9462 */\n#define    PCI_PRODUCT_INTEL_WL_9462_4    0x02a0        /* Dual Band Wireless AC 9462 */\n//#define    PCI_PRODUCT_INTEL_WL_9462_5    0x02a4        /* Dual Band Wireless AC 9462 */\n#define    PCI_PRODUCT_INTEL_WL_9462_6    0x40a4        /* Dual Band Wireless AC 9462 */\n#define    PCI_PRODUCT_INTEL_WL_9461_1    0x0060        /* Dual Band Wireless AC 9461 */\n#define    PCI_PRODUCT_INTEL_WL_9461_2    0x0064        /* Dual Band Wireless AC 9461 */\n#define    PCI_PRODUCT_INTEL_WL_9461_3    0x0260        /* Dual Band Wireless AC 9461 */\n#define    PCI_PRODUCT_INTEL_WL_9461_4    0x0264        /* Dual Band Wireless AC 9461 */\n\nstatic const struct pci_matchid iwm_devices[] = {\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_3160_1 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_3160_2 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_3165_1 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_3165_2 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_3168_1 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_7260_1 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_7260_2 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_7265_1 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_7265_2 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_8260_1 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_8260_2 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_8265_1 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_9260_1 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_9560_1 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_9560_2 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_9560_3 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_9560_4 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_9560_5 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_9560_6 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_9462_1 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_9462_2 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_9462_3 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_9462_4 },\n    //{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_9462_5 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_9462_6 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_9461_1 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_9461_2 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_9461_3 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_9461_4 }\n};\n\nint ItlIwm::\niwm_match(struct IOPCIDevice *device)\n{\n    int devId = device->configRead16(kIOPCIConfigDeviceID);\n    XYLog(\"%s devId=0x%04X\\n\", __FUNCTION__, devId);\n    return pci_matchbyid(PCI_VENDOR_INTEL, devId, iwm_devices,\n                         nitems(iwm_devices));\n}\n\nint ItlIwm::\niwm_preinit(struct iwm_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct _ifnet *ifp = IC2IFP(ic);\n    int err;\n    static int attached;\n    \n    err = iwm_prepare_card_hw(sc);\n    if (err) {\n        XYLog(\"%s: could not initialize hardware\\n\", DEVNAME(sc));\n        return err;\n    }\n    \n    if (attached) {\n        /* Update MAC in case the upper layers changed it. */\n        IEEE80211_ADDR_COPY(sc->sc_ic.ic_myaddr,\n                            ((struct arpcom *)ifp)->ac_enaddr);\n        return 0;\n    }\n    \n    err = iwm_start_hw(sc);\n    if (err) {\n        XYLog(\"%s: could not initialize hardware\\n\", DEVNAME(sc));\n        return err;\n    }\n    \n    err = iwm_run_init_mvm_ucode(sc, 1);\n    iwm_stop_device(sc);\n    if (err)\n        return err;\n    \n    /* Print version info and MAC address on first successful fw load. */\n    attached = 1;\n    XYLog(\"%s: hw rev 0x%x, fw ver %s, address %s\\n\",\n          DEVNAME(sc), sc->sc_hw_rev & IWM_CSR_HW_REV_TYPE_MSK,\n          sc->sc_fwver, ether_sprintf(sc->sc_nvm.hw_addr));\n    \n    if (sc->sc_nvm.sku_cap_11n_enable)\n        iwm_setup_ht_rates(sc);\n    \n    if (sc->sc_nvm.sku_cap_11ac_enable) {\n        iwm_setup_vht_rates(sc);\n    }\n    \n    /* not all hardware can do 5GHz band */\n    if (!sc->sc_nvm.sku_cap_band_52GHz_enable)\n        memset(&ic->ic_sup_rates[IEEE80211_MODE_11A], 0,\n               sizeof(ic->ic_sup_rates[IEEE80211_MODE_11A]));\n    \n    /* Configure channel information obtained from firmware. */\n    ieee80211_channel_init(ifp);\n    \n    /* Configure MAC address. */\n    err = if_setlladdr(ifp, ic->ic_myaddr);\n    if (err)\n        XYLog(\"%s: could not set MAC address (error %d)\\n\",\n              DEVNAME(sc), err);\n    \n    ieee80211_media_init(ifp);\n    \n    iwm_rs_free(sc);\n    iwm_rs_alloc(sc);\n    \n    return 0;\n}\n\nvoid ItlIwm::\niwm_attach_hook(struct device *self)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwm_softc *sc = (struct iwm_softc *)self;\n    \n    KASSERT(!cold, \"!cold\");\n    \n    iwm_preinit(sc);\n}\n\nbool ItlIwm::\nintrFilter(OSObject *object, IOFilterInterruptEventSource *src)\n{\n    ItlIwm *that = (ItlIwm*)object;\n    IWM_WRITE(&that->com, IWM_CSR_INT_MASK, 0);\n    return true;\n}\n\nbool ItlIwm::\niwm_attach(struct iwm_softc *sc, struct pci_attach_args *pa)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    pcireg_t reg, memtype;\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct _ifnet *ifp = &ic->ic_if;\n    int err;\n    int txq_i, i, j;\n    \n    sc->sc_pct = pa->pa_pc;\n    sc->sc_pcitag = pa->pa_tag;\n    sc->sc_dmat = pa->pa_dmat;\n    \n    //    rw_init(&sc->ioctl_rwl, \"iwmioctl\");\n    \n    err = pci_get_capability(sc->sc_pct, sc->sc_pcitag,\n                             PCI_CAP_PCIEXPRESS, &sc->sc_cap_off, NULL);\n    if (err == 0) {\n        XYLog(\"%s: PCIe capability structure not found!\\n\",\n              DEVNAME(sc));\n        return false;\n    }\n    \n    /* Clear device-specific \"PCI retry timeout\" register (41h). */\n    reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0x40);\n    pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, reg & ~0xff00);\n    \n    /* Enable bus-mastering and hardware bug workaround. */\n    reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, PCI_COMMAND_STATUS_REG);\n    reg |= PCI_COMMAND_MASTER_ENABLE;\n    /* if !MSI */\n    if (reg & PCI_COMMAND_INTERRUPT_DISABLE) {\n        reg &= ~PCI_COMMAND_INTERRUPT_DISABLE;\n    }\n    pci_conf_write(sc->sc_pct, sc->sc_pcitag, PCI_COMMAND_STATUS_REG, reg);\n    \n    memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, PCI_MAPREG_START);\n    err = pci_mapreg_map(pa, PCI_MAPREG_START, memtype, 0,\n                         &sc->sc_st, &sc->sc_sh, NULL, &sc->sc_sz, 0);\n    if (err) {\n        XYLog(\"%s: can't map mem space\\n\", DEVNAME(sc));\n        return false;\n    }\n    \n    if (0) {\n        //    if (pci_intr_map_msix(pa, 0, &sc->ih) == 0) {\n        sc->sc_msix = 1;\n    } else if (pci_intr_map_msi(pa, &sc->ih)) {\n        XYLog(\"%s: can't map interrupt\\n\", DEVNAME(sc));\n        return false;\n    }\n    \n    if (!sc->sc_msix) {\n        /* Hardware bug workaround. */\n        reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag,\n            PCI_COMMAND_STATUS_REG);\n        if (reg & PCI_COMMAND_INTERRUPT_DISABLE)\n            reg &= ~PCI_COMMAND_INTERRUPT_DISABLE;\n        pci_conf_write(sc->sc_pct, sc->sc_pcitag,\n            PCI_COMMAND_STATUS_REG, reg);\n    }\n    \n    int msiIntrIndex = -1;\n    for (int index = 0; ; index++)\n    {\n        int interruptType;\n        int ret = pa->pa_tag->getInterruptType(index, &interruptType);\n        if (ret != kIOReturnSuccess)\n            break;\n        if (interruptType & kIOInterruptTypePCIMessaged)\n        {\n            msiIntrIndex = index;\n            break;\n        }\n    }\n    if (msiIntrIndex == -1) {\n        XYLog(\"%s: can't find MSI interrupt controller\\n\", DEVNAME(sc));\n        return false;\n    }\n\n    if (sc->sc_msix)\n        sc->sc_ih =\n        IOFilterInterruptEventSource::filterInterruptEventSource(this,\n                                                                 (IOInterruptEventSource::Action)&ItlIwm::iwm_intr_msix,\n                                                                 &ItlIwm::intrFilter\n                                                                 ,pa->pa_tag, msiIntrIndex);\n    else\n        sc->sc_ih = IOFilterInterruptEventSource::filterInterruptEventSource(this,\n                                                                             (IOInterruptEventSource::Action)&ItlIwm::iwm_intr, &ItlIwm::intrFilter\n                                                                             , pa->pa_tag, msiIntrIndex);\n    if (sc->sc_ih == NULL || pa->workloop->addEventSource(sc->sc_ih) != kIOReturnSuccess) {\n        XYLog(\"%s: can't establish interrupt\\n\", DEVNAME(sc));\n        return false;\n    }\n    sc->sc_ih->enable();\n    \n    sc->sc_hw_rev = IWM_READ(sc, IWM_CSR_HW_REV);\n    int pa_id = pa->pa_tag->configRead16(kIOPCIConfigDeviceID);\n    switch (pa_id) {\n        case PCI_PRODUCT_INTEL_WL_3160_1:\n        case PCI_PRODUCT_INTEL_WL_3160_2:\n            sc->sc_fwname = \"iwm-3160-17\";\n            sc->host_interrupt_operation_mode = 1;\n            sc->sc_device_family = IWM_DEVICE_FAMILY_7000;\n            sc->sc_fwdmasegsz = IWM_FWDMASEGSZ;\n            sc->sc_nvm_max_section_size = 16384;\n            sc->nvm_type = IWM_NVM;\n            sc->support_ldpc = 0;\n            sc->non_shared_ant = IWM_ANT_A;\n            break;\n        case PCI_PRODUCT_INTEL_WL_3165_1:\n        case PCI_PRODUCT_INTEL_WL_3165_2:\n            sc->sc_fwname = \"iwm-7265-17\";\n            sc->host_interrupt_operation_mode = 0;\n            sc->sc_device_family = IWM_DEVICE_FAMILY_7000;\n            sc->sc_fwdmasegsz = IWM_FWDMASEGSZ;\n            sc->sc_nvm_max_section_size = 16384;\n            sc->nvm_type = IWM_NVM;\n            sc->support_ldpc = 0;\n            sc->non_shared_ant = IWM_ANT_A;\n            break;\n        case PCI_PRODUCT_INTEL_WL_3168_1:\n            sc->sc_fwname = \"iwm-3168-29\";\n            sc->host_interrupt_operation_mode = 0;\n            sc->sc_device_family = IWM_DEVICE_FAMILY_7000;\n            sc->sc_fwdmasegsz = IWM_FWDMASEGSZ;\n            sc->sc_nvm_max_section_size = 16384;\n            sc->nvm_type = IWM_NVM_SDP;\n            sc->support_ldpc = 0;\n            sc->non_shared_ant = IWM_ANT_A;\n            break;\n        case PCI_PRODUCT_INTEL_WL_7260_1:\n        case PCI_PRODUCT_INTEL_WL_7260_2:\n            sc->sc_fwname = \"iwm-7260-17\";\n            sc->host_interrupt_operation_mode = 1;\n            sc->sc_device_family = IWM_DEVICE_FAMILY_7000;\n            sc->sc_fwdmasegsz = IWM_FWDMASEGSZ;\n            sc->sc_nvm_max_section_size = 16384;\n            sc->nvm_type = IWM_NVM;\n            sc->support_ldpc = 0;\n            sc->non_shared_ant = IWM_ANT_A;\n            break;\n        case PCI_PRODUCT_INTEL_WL_7265_1:\n        case PCI_PRODUCT_INTEL_WL_7265_2:\n            sc->sc_fwname = \"iwm-7265-17\";\n            sc->host_interrupt_operation_mode = 0;\n            sc->sc_device_family = IWM_DEVICE_FAMILY_7000;\n            sc->sc_fwdmasegsz = IWM_FWDMASEGSZ;\n            sc->sc_nvm_max_section_size = 16384;\n            sc->nvm_type = IWM_NVM;\n            sc->support_ldpc = 1;\n            sc->non_shared_ant = IWM_ANT_A;\n            break;\n        case PCI_PRODUCT_INTEL_WL_8260_1:\n        case PCI_PRODUCT_INTEL_WL_8260_2:\n            sc->sc_fwname = \"iwm-8000C-36\";\n            sc->host_interrupt_operation_mode = 0;\n            sc->sc_device_family = IWM_DEVICE_FAMILY_8000;\n            sc->sc_fwdmasegsz = IWM_FWDMASEGSZ_8000;\n            sc->sc_nvm_max_section_size = 32768;\n            sc->nvm_type = IWM_NVM_EXT;\n            sc->support_ldpc = 1;\n            sc->non_shared_ant = IWM_ANT_A;\n            break;\n        case PCI_PRODUCT_INTEL_WL_8265_1:\n            sc->sc_fwname = \"iwm-8265-36\";\n            sc->host_interrupt_operation_mode = 0;\n            sc->sc_device_family = IWM_DEVICE_FAMILY_8000;\n            sc->sc_fwdmasegsz = IWM_FWDMASEGSZ_8000;\n            sc->sc_nvm_max_section_size = 32768;\n            sc->nvm_type = IWM_NVM_EXT;\n            sc->support_ldpc = 1;\n            sc->non_shared_ant = IWM_ANT_A;\n            break;\n        case PCI_PRODUCT_INTEL_WL_9260_1:\n            sc->sc_fwname = \"iwm-9260-46\";\n            sc->host_interrupt_operation_mode = 0;\n            sc->sc_device_family = IWM_DEVICE_FAMILY_9000;\n            sc->sc_fwdmasegsz = IWM_FWDMASEGSZ_8000;\n            sc->sc_nvm_max_section_size = 32768;\n            sc->sc_mqrx_supported = 1;\n            sc->support_ldpc = 1;\n            sc->non_shared_ant = IWM_ANT_B;\n            break;\n        case PCI_PRODUCT_INTEL_WL_9560_1:\n        case PCI_PRODUCT_INTEL_WL_9560_2:\n        case PCI_PRODUCT_INTEL_WL_9560_3:\n        case PCI_PRODUCT_INTEL_WL_9560_4:\n        case PCI_PRODUCT_INTEL_WL_9560_5:\n        case PCI_PRODUCT_INTEL_WL_9560_6:\n        case PCI_PRODUCT_INTEL_WL_9462_1:\n        case PCI_PRODUCT_INTEL_WL_9462_2:\n        case PCI_PRODUCT_INTEL_WL_9462_3:\n        case PCI_PRODUCT_INTEL_WL_9462_4:\n        //case PCI_PRODUCT_INTEL_WL_9462_5:\n        case PCI_PRODUCT_INTEL_WL_9462_6:\n        case PCI_PRODUCT_INTEL_WL_9461_1:\n        case PCI_PRODUCT_INTEL_WL_9461_2:\n        case PCI_PRODUCT_INTEL_WL_9461_3:\n        case PCI_PRODUCT_INTEL_WL_9461_4:\n            sc->sc_fwname = \"iwm-9000-46\";\n            sc->host_interrupt_operation_mode = 0;\n            sc->sc_device_family = IWM_DEVICE_FAMILY_9000;\n            sc->sc_fwdmasegsz = IWM_FWDMASEGSZ_8000;\n            sc->sc_nvm_max_section_size = 32768;\n            sc->sc_mqrx_supported = 1;\n            sc->sc_integrated = 1;\n            sc->support_ldpc = 1;\n            sc->sc_xtal_latency = 650;\n            sc->non_shared_ant = IWM_ANT_B;\n            break;\n        default:\n            XYLog(\"%s: unknown adapter type\\n\", DEVNAME(sc));\n            return false;\n    }\n    \n    /*\n     * In the 8000 HW family the format of the 4 bytes of CSR_HW_REV have\n     * changed, and now the revision step also includes bit 0-1 (no more\n     * \"dash\" value). To keep hw_rev backwards compatible - we'll store it\n     * in the old format.\n     */\n    if (sc->sc_device_family >= IWM_DEVICE_FAMILY_8000) {\n        uint32_t hw_step;\n        \n        sc->sc_hw_rev = (sc->sc_hw_rev & 0xfff0) |\n        (IWM_CSR_HW_REV_STEP(sc->sc_hw_rev << 2) << 2);\n        \n        if (iwm_prepare_card_hw(sc) != 0) {\n            XYLog(\"%s: could not initialize hardware\\n\",\n                  DEVNAME(sc));\n            return false;\n        }\n        \n        /*\n         * In order to recognize C step the driver should read the\n         * chip version id located at the AUX bus MISC address.\n         */\n        IWM_SETBITS(sc, IWM_CSR_GP_CNTRL,\n                    IWM_CSR_GP_CNTRL_REG_FLAG_INIT_DONE);\n        DELAY(2);\n        \n        err = iwm_poll_bit(sc, IWM_CSR_GP_CNTRL,\n                           IWM_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,\n                           IWM_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,\n                           25000);\n        if (!err) {\n            XYLog(\"%s: Failed to wake up the nic\\n\", DEVNAME(sc));\n            return false;\n        }\n        \n        if (iwm_nic_lock(sc)) {\n            hw_step = iwm_read_prph(sc, IWM_WFPM_CTRL_REG);\n            hw_step |= IWM_ENABLE_WFPM;\n            iwm_write_prph(sc, IWM_WFPM_CTRL_REG, hw_step);\n            hw_step = iwm_read_prph(sc, IWM_AUX_MISC_REG);\n            hw_step = (hw_step >> IWM_HW_STEP_LOCATION_BITS) & 0xF;\n            if (hw_step == 0x3)\n                sc->sc_hw_rev = (sc->sc_hw_rev & 0xFFFFFFF3) |\n                (IWM_SILICON_C_STEP << 2);\n            iwm_nic_unlock(sc);\n        } else {\n            XYLog(\"%s: Failed to lock the nic\\n\", DEVNAME(sc));\n            return false;\n        }\n    }\n    \n    XYLog(\"alloc contig\\n\");\n    \n    /*\n     * Allocate DMA memory for firmware transfers.\n     * Must be aligned on a 16-byte boundary.\n     */\n    err = iwm_dma_contig_alloc(sc->sc_dmat, &sc->fw_dma,\n        sc->sc_fwdmasegsz, 16);\n    if (err) {\n        XYLog(\"%s: could not allocate memory for firmware\\n\",\n            DEVNAME(sc));\n        return false;\n    }\n\n    /* Allocate \"Keep Warm\" page, used internally by the card. */\n    err = iwm_dma_contig_alloc(sc->sc_dmat, &sc->kw_dma, 4096, 4096);\n    if (err) {\n        XYLog(\"%s: could not allocate keep warm page\\n\", DEVNAME(sc));\n        goto fail1;\n    }\n\n    /* Allocate interrupt cause table (ICT).*/\n    err = iwm_dma_contig_alloc(sc->sc_dmat, &sc->ict_dma,\n        IWM_ICT_SIZE, 1<<IWM_ICT_PADDR_SHIFT);\n    if (err) {\n        XYLog(\"%s: could not allocate ICT table\\n\", DEVNAME(sc));\n        goto fail2;\n    }\n\n    /* TX scheduler rings must be aligned on a 1KB boundary. */\n    err = iwm_dma_contig_alloc(sc->sc_dmat, &sc->sched_dma,\n        nitems(sc->txq) * sizeof(struct iwm_agn_scd_bc_tbl), 1024);\n    if (err) {\n        XYLog(\"%s: could not allocate TX scheduler rings\\n\",\n            DEVNAME(sc));\n        goto fail3;\n    }\n\n    for (txq_i = 0; txq_i < nitems(sc->txq); txq_i++) {\n        err = iwm_alloc_tx_ring(sc, &sc->txq[txq_i], txq_i);\n        if (err) {\n            XYLog(\"%s: could not allocate TX ring %d\\n\",\n                DEVNAME(sc), txq_i);\n            goto fail4;\n        }\n    }\n\n    err = iwm_alloc_rx_ring(sc, &sc->rxq);\n    if (err) {\n        XYLog(\"%s: could not allocate RX ring\\n\", DEVNAME(sc));\n        goto fail4;\n    }\n    \n    taskq_init();\n    sc->sc_nswq = taskq_create(\"iwmns\", 1, IPL_NET, 0);\n    if (sc->sc_nswq == NULL)\n        goto fail4;\n    \n    XYLog(\"config ieee80211\\n\");\n    \n    /* Clear pending interrupts. */\n    IWM_WRITE(sc, IWM_CSR_INT, 0xffffffff);\n    \n    ic->ic_phytype = IEEE80211_T_OFDM;    /* not only, but not used */\n    ic->ic_opmode = IEEE80211_M_STA;    /* default to BSS mode */\n    ic->ic_state = IEEE80211_S_INIT;\n    \n    /* Set device capabilities. */\n    ic->ic_caps =\n    IEEE80211_C_WEP |        /* WEP */\n    IEEE80211_C_RSN |        /* WPA/RSN */\n    IEEE80211_C_SCANALL |    /* device scans all channels at once */\n    IEEE80211_C_SCANALLBAND |    /* device scans all bands at once */\n    IEEE80211_C_MONITOR |    /* monitor mode supported */\n    IEEE80211_C_SHSLOT |    /* short slot time supported */\n    IEEE80211_C_SHPREAMBLE;    /* short preamble supported */\n    \n    ic->ic_htcaps = IEEE80211_HTCAP_SGI20;\n    ic->ic_htcaps |=\n    (IEEE80211_HTCAP_SMPS_DIS << IEEE80211_HTCAP_SMPS_SHIFT);\n    ic->ic_htcaps |= (IEEE80211_HTCAP_CBW20_40 | IEEE80211_HTCAP_SGI40);\n    ic->ic_htxcaps = 0;\n    ic->ic_txbfcaps = 0;\n    ic->ic_aselcaps = 0;\n    ic->ic_ampdu_params = (IEEE80211_AMPDU_PARAM_SS_4 | 0x3 /* 64k */);\n    ic->ic_caps |= (IEEE80211_C_QOS | IEEE80211_C_TX_AMPDU | IEEE80211_C_AMSDU_IN_AMPDU);\n    ic->ic_caps |= IEEE80211_C_SUPPORTS_VHT_EXT_NSS_BW;\n#if 0\n    ic->ic_caps |= IEEE80211_C_TX_AMPDU_SETUP_IN_RS;\n#endif\n    \n    ic->ic_sup_rates[IEEE80211_MODE_11A] = ieee80211_std_rateset_11a;\n    ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b;\n    ic->ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_std_rateset_11g;\n    \n    for (i = 0; i < nitems(sc->sc_phyctxt); i++) {\n        sc->sc_phyctxt[i].id = i;\n    }\n    \n    sc->sc_amrr.amrr_min_success_threshold =  1;\n    sc->sc_amrr.amrr_max_success_threshold = 15;\n    \n    /* IBSS channel undefined for now. */\n    ic->ic_ibss_chan = &ic->ic_channels[1];\n    \n    ic->ic_max_rssi = IWM_MAX_DBM - IWM_MIN_DBM;\n    \n    ifp->if_softc = sc;\n    ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST | IFF_DEBUG;\n    ifp->if_ioctl = iwm_ioctl;\n    ifp->if_start = iwm_start;\n    ifp->if_watchdog = iwm_watchdog;\n    memcpy(ifp->if_xname, DEVNAME(sc), IFNAMSIZ);\n    \n    if_attach(ifp);\n    ieee80211_ifattach(ifp, getController());\n    ieee80211_media_init(ifp);\n    \n#if NBPFILTER > 0\n    iwm_radiotap_attach(sc);\n#endif\n    timeout_set(&sc->sc_calib_to, iwm_calib_timeout, sc);\n    timeout_set(&sc->sc_led_blink_to, iwm_led_blink_timeout, sc);\n    for (i = 0; i < nitems(sc->sc_rxba_data); i++) {\n        struct iwm_rxba_data *rxba = &sc->sc_rxba_data[i];\n        rxba->baid = IWM_RX_REORDER_DATA_INVALID_BAID;\n        rxba->sc = sc;\n        timeout_set(&rxba->session_timer, iwm_rx_ba_session_expired,\n                    rxba);\n        timeout_set(&rxba->reorder_buf.reorder_timer,\n                    iwm_reorder_timer_expired, &rxba->reorder_buf);\n        for (j = 0; j < nitems(rxba->entries); j++)\n            ml_init(&rxba->entries[j].frames);\n    }\n    task_set(&sc->init_task, iwm_init_task, sc, \"init_task\");\n    task_set(&sc->newstate_task, iwm_newstate_task, sc, \"newstate_task\");\n    task_set(&sc->ba_task, iwm_ba_task, sc, \"ba_task\");\n    task_set(&sc->mac_ctxt_task, iwm_mac_ctxt_task, sc, \"mac_ctxt_task\");\n    task_set(&sc->chan_ctxt_task, iwm_chan_ctxt_task, sc, \"chan_ctxt_task\");\n    \n    ic->ic_node_alloc = iwm_node_alloc;\n    ic->ic_bgscan_start = iwm_bgscan;\n    ic->ic_set_key = iwm_set_key;\n    ic->ic_delete_key = iwm_delete_key;\n    \n    /* Override 802.11 state transition machine. */\n    sc->sc_newstate = ic->ic_newstate;\n    ic->ic_newstate = iwm_newstate;\n    ic->ic_updateprot = iwm_updateprot;\n    ic->ic_updateslot = iwm_updateslot;\n    ic->ic_updateedca = iwm_updateedca;\n    ic->ic_updatedtim = iwm_updatedtim;\n    ic->ic_ampdu_rx_start = iwm_ampdu_rx_start;\n    ic->ic_ampdu_rx_stop = iwm_ampdu_rx_stop;\n    ic->ic_ampdu_tx_start = iwm_ampdu_tx_start;\n    ic->ic_ampdu_tx_stop = iwm_ampdu_tx_stop;\n    ic->ic_update_chw = iwm_update_chw;\n    /*\n     * We cannot read the MAC address without loading the\n     * firmware from disk. Postpone until mountroot is done.\n     */\n    //    config_mountroot(self, iwm_attach_hook);\n    if (iwm_preinit(sc)) {\n        goto fail5;\n    }\n    \n    XYLog(\"attach succeed.\\n\");\n    \n    return true;\n    \nfail5:\n    for (i = 0; i < nitems(sc->sc_rxba_data); i++) {\n        struct iwm_rxba_data *rxba = &sc->sc_rxba_data[i];\n        iwm_clear_reorder_buffer(sc, rxba);\n    }\nfail4:    while (--txq_i >= 0)\n    iwm_free_tx_ring(sc, &sc->txq[txq_i]);\n    iwm_free_rx_ring(sc, &sc->rxq);\n    iwm_dma_contig_free(&sc->sched_dma);\nfail3:    if (sc->ict_dma.vaddr != NULL)\n    iwm_dma_contig_free(&sc->ict_dma);\n    \nfail2:    iwm_dma_contig_free(&sc->kw_dma);\nfail1:    iwm_dma_contig_free(&sc->fw_dma);\n    XYLog(\"attach failed.\\n\");\n    return false;\n}\n\n#if NBPFILTER > 0\nvoid ItlIwm::\niwm_radiotap_attach(struct iwm_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    bpfattach(&sc->sc_drvbpf, &sc->sc_ic.ic_if, DLT_IEEE802_11_RADIO,\n              sizeof (struct ieee80211_frame) + IEEE80211_RADIOTAP_HDRLEN);\n    \n    sc->sc_rxtap_len = sizeof sc->sc_rxtapu;\n    sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);\n    sc->sc_rxtap.wr_ihdr.it_present = htole32(IWM_RX_RADIOTAP_PRESENT);\n    \n    sc->sc_txtap_len = sizeof sc->sc_txtapu;\n    sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);\n    sc->sc_txtap.wt_ihdr.it_present = htole32(IWM_TX_RADIOTAP_PRESENT);\n}\n#endif\n\nvoid ItlIwm::\niwm_init_task(void *arg1)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwm_softc *sc = (struct iwm_softc *)arg1;\n    ItlIwm *that = container_of(sc, ItlIwm, com);\n    struct _ifnet *ifp = &sc->sc_ic.ic_if;\n    int s = splnet();\n    int generation = sc->sc_generation;\n    int fatal = (sc->sc_flags & (IWM_FLAG_HW_ERR | IWM_FLAG_RFKILL));\n    \n    //    rw_enter_write(&sc->ioctl_rwl);\n    if (generation != sc->sc_generation) {\n        //        rw_exit(&sc->ioctl_rwl);\n        splx(s);\n        return;\n    }\n    \n    if (ifp->if_flags & IFF_RUNNING)\n        that->iwm_stop(ifp);\n    else\n        sc->sc_flags &= ~IWM_FLAG_HW_ERR;\n    \n    if (!fatal && (ifp->if_flags & (IFF_UP | IFF_RUNNING)) == IFF_UP)\n        that->iwm_init(ifp);\n    \n    //    rw_exit(&sc->ioctl_rwl);\n    splx(s);\n}\n\nvoid ItlIwm::\niwm_mac_ctxt_task(void *arg)\n{\n    struct iwm_softc *sc = (struct iwm_softc *)arg;\n    ItlIwm *that = container_of(sc, ItlIwm, com);\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct iwm_node *in = (struct iwm_node *)ic->ic_bss;\n    int err, s = splnet();\n    \n    if (sc->sc_flags & IWM_FLAG_SHUTDOWN ||\n        ic->ic_state != IEEE80211_S_RUN ||\n        in->in_phyctxt == NULL) {\n        //        refcnt_rele_wake(&sc->task_refs);\n        splx(s);\n        return;\n    }\n    \n    err = that->iwm_mac_ctxt_cmd(sc, in, IWM_FW_CTXT_ACTION_MODIFY, 1);\n    if (err)\n        printf(\"%s: failed to update MAC\\n\", DEVNAME(sc));\n    \n    that->iwm_unprotect_session(sc, in);\n    \n    //    refcnt_rele_wake(&sc->task_refs);\n    splx(s);\n}\n\nvoid ItlIwm::\niwm_chan_ctxt_task(void *arg)\n{\n    struct iwm_softc *sc = (struct iwm_softc *)arg;\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct iwm_node *in = (struct iwm_node *)ic->ic_bss;\n    ItlIwm *that = container_of(sc, ItlIwm, com);\n    int err, s = splnet();\n    \n    if (sc->sc_flags & IWM_FLAG_SHUTDOWN ||\n        ic->ic_state != IEEE80211_S_RUN ||\n        in->in_phyctxt == NULL) {\n        //        refcnt_rele_wake(&sc->task_refs);\n        splx(s);\n        return;\n    }\n    \n    int chains = that->iwm_mimo_enabled(sc) ? 2 : 1;\n    err = that->iwm_phy_ctxt_update(sc, in->in_phyctxt, in->in_ni.ni_chan,\n                                 chains, chains, 0);\n    if (err) {\n        XYLog(\"%s: failed to update PHY\\n\",\n              __FUNCTION__);\n        //        refcnt_rele_wake(&sc->task_refs);\n        splx(s);\n        return;\n    }\n\n    rs_drv_rate_update(sc, &in->in_ni, IEEE80211_IS_CHAN_2GHZ(in->in_ni.ni_chan) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ, true);\n    iwl_mvm_send_lq_cmd(sc, &sc->lq_sta.rs_drv.lq);\n    \n    //    refcnt_rele_wake(&sc->task_refs);\n    splx(s);\n}\n\nvoid ItlIwm::\niwm_ba_task(void *arg)\n{\n    struct iwm_softc *sc = (struct iwm_softc *)arg;\n    ItlIwm *that = container_of(sc, ItlIwm, com);\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct ieee80211_node *ni = ic->ic_bss;\n    int s = splnet();\n    int tid, err = 0;\n    \n    if ((sc->sc_flags & IWM_FLAG_SHUTDOWN) ||\n        ic->ic_state != IEEE80211_S_RUN) {\n//        refcnt_rele_wake(&sc->task_refs);\n        splx(s);\n        return;\n    }\n    \n    for (tid = 0; tid < IWM_MAX_TID_COUNT; tid++) {\n        if (sc->sc_flags & IWM_FLAG_SHUTDOWN)\n            break;\n        if (sc->ba_rx.start_tidmask & (1 << tid)) {\n            struct ieee80211_rx_ba *ba = &ni->ni_rx_ba[tid];\n            err = that->iwm_sta_rx_agg(sc, ni, tid,  ba->ba_winstart,\n                           ba->ba_winsize, ba->ba_timeout_val, 1);\n            sc->ba_rx.start_tidmask &= ~(1 << tid);\n        } else if (sc->ba_rx.stop_tidmask & (1 << tid)) {\n            err = that->iwm_sta_rx_agg(sc, ni, tid, 0, 0, 0, 0);\n            sc->ba_rx.stop_tidmask &= ~(1 << tid);\n        }\n    }\n    \n    for (tid = 0; tid < IWM_MAX_TID_COUNT && !err; tid++) {\n        if (sc->sc_flags & IWM_FLAG_SHUTDOWN)\n            break;\n        struct ieee80211_tx_ba *ba = &ni->ni_tx_ba[tid];\n        int qid = IWM_FIRST_AGG_TX_QUEUE + tid;\n        struct iwm_tx_ring *ring = &sc->txq[qid];\n        struct iwm_tx_ba *tx_ba;\n        uint16_t ssn = ba->ba_winstart;\n        if (sc->ba_tx.start_tidmask & (1 << tid)) {\n            uint8_t fifo = iwm_ac_to_tx_fifo[tid_to_mac80211_ac[tid]];\n\n            XYLog(\"%s tx_start ssn=%d, tid=%d scd_queue=%d\\n\", __FUNCTION__, ssn, tid, qid);\n\n            if (!that->iwm_nic_lock(sc))\n                goto out;\n            if (that->iwm_enable_txq(sc, IWM_STATION_ID, qid, fifo, ssn, tid, 1))\n                goto out;\n            /*\n             * If iwm_enable_txq() employed the SCD hardware bug\n             * workaround we must skip the frame with seqnum SSN.\n             */\n            if (IWM_AGG_SSN_TO_TXQ_IDX(ring->cur) !=\n                IWM_AGG_SSN_TO_TXQ_IDX(ssn)) {\n                ssn = (ssn + 1) & 0xfff;\n                ieee80211_output_ba_move_window(ic, ni, tid, ssn);\n                ni->ni_qos_txseqs[tid] = ssn;\n            }\n            if (that->iwm_add_sta_cmd(sc, (struct iwm_node *)ni, 1, IWM_STA_MODIFY_QUEUES))\n                goto out;\n\n            sc->agg_tid_disable &= ~(1 << tid);\n            sc->agg_queue_mask |= (1 << qid);\n            sc->sc_tx_ba[tid].wn = (iwm_node *)ni;\n            ba->ba_bitmap = 0;\n            if (!that->iwm_sta_tx_agg(sc, ni, tid, 0, ssn, 1)) {\n                ieee80211_addba_resp_accept(ic, ni, tid);\n                sc->lq_sta.rs_drv.lq.agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_DEF;\n\n                XYLog(\"Tx aggregation enabled on ra = %s tid = %d\\n\",\n                         ether_sprintf(ni->ni_macaddr), tid);\n\n                iwl_mvm_send_lq_cmd(sc, &sc->lq_sta.rs_drv.lq);\n            } else {\n            out:\n                ieee80211_addba_resp_refuse(ic, ni, tid,\n                                            IEEE80211_STATUS_UNSPECIFIED);\n            }\n            that->iwm_nic_unlock(sc);\n            sc->ba_tx.start_tidmask &= ~(1 << tid);\n        } else if (sc->ba_tx.stop_tidmask & (1 << tid)) {\n            sc->agg_tid_disable |= (1 << tid);\n            that->iwm_sta_tx_agg(sc, ni, tid, 0, 0, 0);\n            that->iwm_ampdu_txq_advance(sc, ring, ring->cur);\n            that->iwm_clear_oactive(sc, ring);\n            /* In DQA-mode the queue isn't removed on agg termination */\n            tx_ba = &sc->sc_tx_ba[tid];\n            tx_ba->wn = NULL;\n            tx_ba->lq_color = 0;\n            tx_ba->rate_n_flags = 0;\n            tx_ba->tpt_meas_start = 0;\n            tx_ba->tx_count = 0;\n            tx_ba->tx_count_last = 0;\n            tx_ba->tx_time = 0;\n            ba->ba_bitmap = 0;\n            sc->ba_tx.stop_tidmask &= ~(1 << tid);\n        }\n    }\n    \n    //    refcnt_rele_wake(&sc->task_refs);\n    splx(s);\n}\n\nint ItlIwm::\niwm_resume(struct iwm_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    pcireg_t reg;\n    \n    /* Clear device-specific \"PCI retry timeout\" register (41h). */\n    reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0x40);\n    pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, reg & ~0xff00);\n    \n    if (!sc->sc_msix) {\n        /* Hardware bug workaround. */\n        reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag,\n                            PCI_COMMAND_STATUS_REG);\n        if (reg & PCI_COMMAND_INTERRUPT_DISABLE)\n            reg &= ~PCI_COMMAND_INTERRUPT_DISABLE;\n        pci_conf_write(sc->sc_pct, sc->sc_pcitag,\n                       PCI_COMMAND_STATUS_REG, reg);\n    }\n\n    iwm_enable_rfkill_int(sc);\n    iwm_check_rfkill(sc);\n\n    return iwm_prepare_card_hw(sc);\n}\n\nvoid ItlIwm::\niwm_add_task(struct iwm_softc *sc, struct taskq *taskq, struct task *task)\n{\n    int s = splnet();\n    \n    if (sc->sc_flags & IWM_FLAG_SHUTDOWN) {\n        splx(s);\n        return;\n    }\n    \n    //    refcnt_take(&sc->task_refs);\n    if (!task_add(taskq, task)) {\n        //        refcnt_rele_wake(&sc->task_refs);\n    }\n    splx(s);\n}\n\nvoid ItlIwm::\niwm_del_task(struct iwm_softc *sc, struct taskq *taskq, struct task *task)\n{\n    if (task_del(taskq, task)) {\n        //        refcnt_rele(&sc->task_refs);\n    }\n}\n\nint ItlIwm::\niwm_activate(struct iwm_softc *sc, int act)\n{\n    struct _ifnet *ifp = &sc->sc_ic.ic_if;\n    int err = 0;\n    \n    switch (act) {\n        case DVACT_QUIESCE:\n            if (ifp->if_flags & IFF_RUNNING) {\n                //                rw_enter_write(&sc->ioctl_rwl);\n                iwm_stop(ifp);\n                //                rw_exit(&sc->ioctl_rwl);\n            }\n            break;\n        case DVACT_RESUME:\n            err = iwm_resume(sc);\n            if (err)\n                XYLog(\"%s: could not initialize hardware\\n\",\n                      DEVNAME(sc));\n            break;\n        case DVACT_WAKEUP:\n            /* Hardware should be up at this point. */\n            if (iwm_set_hw_ready(sc))\n                task_add(systq, &sc->init_task);\n            break;\n    }\n    \n    return 0;\n}\n"
  },
  {
    "path": "itlwm/hal_iwm/nvm.cpp",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n/*    $OpenBSD: if_iwm.c,v 1.316 2020/12/07 20:09:24 tobhe Exp $    */\n\n/*\n * Copyright (c) 2014, 2016 genua gmbh <info@genua.de>\n *   Author: Stefan Sperling <stsp@openbsd.org>\n * Copyright (c) 2014 Fixup Software Ltd.\n * Copyright (c) 2017 Stefan Sperling <stsp@openbsd.org>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n/*-\n * Based on BSD-licensed source modules in the Linux iwlwifi driver,\n * which were used as the reference documentation for this implementation.\n *\n ***********************************************************************\n *\n * This file is provided under a dual BSD/GPLv2 license.  When using or\n * redistributing this file, you may do so under either license.\n *\n * GPL LICENSE SUMMARY\n *\n * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.\n * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH\n * Copyright(c) 2016 Intel Deutschland GmbH\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of version 2 of the GNU General Public License as\n * published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful, but\n * WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,\n * USA\n *\n * The full GNU General Public License is included in this distribution\n * in the file called COPYING.\n *\n * Contact Information:\n *  Intel Linux Wireless <ilw@linux.intel.com>\n * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497\n *\n *\n * BSD LICENSE\n *\n * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.\n * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH\n * Copyright(c) 2016 Intel Deutschland GmbH\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in\n *    the documentation and/or other materials provided with the\n *    distribution.\n *  * Neither the name Intel Corporation nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*-\n * Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n#include \"ItlIwm.hpp\"\n\n/*\n * NVM read access and content parsing.  We do not support\n * external NVM or writing NVM.\n */\n\n/* list of NVM sections we are allowed/need to read */\nconst int iwm_nvm_to_read[] = {\n    IWM_NVM_SECTION_TYPE_HW,\n    IWM_NVM_SECTION_TYPE_SW,\n    IWM_NVM_SECTION_TYPE_REGULATORY,\n    IWM_NVM_SECTION_TYPE_CALIBRATION,\n    IWM_NVM_SECTION_TYPE_PRODUCTION,\n    IWM_NVM_SECTION_TYPE_REGULATORY_SDP,\n    IWM_NVM_SECTION_TYPE_HW_8000,\n    IWM_NVM_SECTION_TYPE_MAC_OVERRIDE,\n    IWM_NVM_SECTION_TYPE_PHY_SKU,\n};\n\n#define IWM_NVM_DEFAULT_CHUNK_SIZE    (2*1024)\n\n#define IWM_NVM_WRITE_OPCODE 1\n#define IWM_NVM_READ_OPCODE 0\n\nint ItlIwm::\niwm_nvm_read_chunk(struct iwm_softc *sc, uint16_t section, uint16_t offset,\n                   uint16_t length, uint8_t *data, uint16_t *len)\n{\n    offset = 0;\n    struct iwm_nvm_access_cmd nvm_access_cmd = {\n        .offset = htole16(offset),\n        .length = htole16(length),\n        .type = htole16(section),\n        .op_code = IWM_NVM_READ_OPCODE,\n    };\n    struct iwm_nvm_access_resp *nvm_resp;\n    struct iwm_rx_packet *pkt;\n    struct iwm_host_cmd cmd = {\n        .id = IWM_NVM_ACCESS_CMD,\n        .flags = (IWM_CMD_WANT_RESP | IWM_CMD_SEND_IN_RFKILL),\n        .resp_pkt_len = IWM_CMD_RESP_MAX,\n        .data = { &nvm_access_cmd, },\n    };\n    int err, offset_read;\n    size_t bytes_read;\n    uint8_t *resp_data;\n    \n    cmd.len[0] = sizeof(struct iwm_nvm_access_cmd);\n    \n    err = iwm_send_cmd(sc, &cmd);\n    if (err)\n        return err;\n    \n    pkt = cmd.resp_pkt;\n    if (pkt->hdr.flags & IWM_CMD_FAILED_MSK) {\n        err = EIO;\n        goto exit;\n    }\n    \n    /* Extract NVM response */\n    nvm_resp = (struct iwm_nvm_access_resp *)pkt->data;\n    if (nvm_resp == NULL)\n        return EIO;\n    \n    err = le16toh(nvm_resp->status);\n    bytes_read = le16toh(nvm_resp->length);\n    offset_read = le16toh(nvm_resp->offset);\n    resp_data = nvm_resp->data;\n    if (err) {\n        err = EINVAL;\n        goto exit;\n    }\n    \n    if (offset_read != offset) {\n        err = EINVAL;\n        goto exit;\n    }\n    \n    if (bytes_read > length) {\n        err = EINVAL;\n        goto exit;\n    }\n    \n    memcpy(data + offset, resp_data, bytes_read);\n    *len = bytes_read;\n    \nexit:\n    iwm_free_resp(sc, &cmd);\n    return err;\n}\n\n/*\n * Reads an NVM section completely.\n * NICs prior to 7000 family doesn't have a real NVM, but just read\n * section 0 which is the EEPROM. Because the EEPROM reading is unlimited\n * by uCode, we need to manually check in this case that we don't\n * overflow and try to read more than the EEPROM size.\n */\nint ItlIwm::\niwm_nvm_read_section(struct iwm_softc *sc, uint16_t section, uint8_t *data,\n                     uint16_t *len, size_t max_len)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    uint16_t chunklen, seglen;\n    int err = 0;\n    \n    chunklen = seglen = IWM_NVM_DEFAULT_CHUNK_SIZE;\n    *len = 0;\n    \n    /* Read NVM chunks until exhausted (reading less than requested) */\n    while (seglen == chunklen && *len < max_len) {\n        err = iwm_nvm_read_chunk(sc,\n                                 section, *len, chunklen, data, &seglen);\n        if (err)\n            return err;\n        \n        *len += seglen;\n    }\n    \n    return err;\n}\n\nint ItlIwm::\niwm_parse_nvm_data(struct iwm_softc *sc, const uint16_t *nvm_hw,\n                   const uint16_t *nvm_sw, const uint16_t *nvm_calib,\n                   const uint16_t *mac_override, const uint16_t *phy_sku,\n                   const uint16_t *regulatory, int n_regulatory)\n{\n    struct iwm_nvm_data *data = &sc->sc_nvm;\n    uint8_t hw_addr[ETHER_ADDR_LEN];\n    uint32_t sku;\n    uint16_t lar_config;\n    \n    data->nvm_version = le16_to_cpup(nvm_sw + IWM_NVM_VERSION);\n    \n    if (sc->sc_device_family == IWM_DEVICE_FAMILY_7000) {\n        uint16_t radio_cfg = le16_to_cpup(nvm_sw + IWM_RADIO_CFG);\n        data->radio_cfg_type = IWM_NVM_RF_CFG_TYPE_MSK(radio_cfg);\n        data->radio_cfg_step = IWM_NVM_RF_CFG_STEP_MSK(radio_cfg);\n        data->radio_cfg_dash = IWM_NVM_RF_CFG_DASH_MSK(radio_cfg);\n        data->radio_cfg_pnum = IWM_NVM_RF_CFG_PNUM_MSK(radio_cfg);\n        \n        sku = le16_to_cpup(nvm_sw + IWM_SKU);\n    } else {\n        uint32_t radio_cfg =\n        le32_to_cpup((uint32_t *)(phy_sku + IWM_RADIO_CFG_8000));\n        data->radio_cfg_type = IWM_NVM_RF_CFG_TYPE_MSK_8000(radio_cfg);\n        data->radio_cfg_step = IWM_NVM_RF_CFG_STEP_MSK_8000(radio_cfg);\n        data->radio_cfg_dash = IWM_NVM_RF_CFG_DASH_MSK_8000(radio_cfg);\n        data->radio_cfg_pnum = IWM_NVM_RF_CFG_PNUM_MSK_8000(radio_cfg);\n        data->valid_tx_ant = IWM_NVM_RF_CFG_TX_ANT_MSK_8000(radio_cfg);\n        data->valid_rx_ant = IWM_NVM_RF_CFG_RX_ANT_MSK_8000(radio_cfg);\n        \n        sku = le32_to_cpup((uint32_t *)(phy_sku + IWM_SKU_8000));\n    }\n    \n    data->sku_cap_band_24GHz_enable = sku & IWM_NVM_SKU_CAP_BAND_24GHZ;\n    data->sku_cap_band_52GHz_enable = sku & IWM_NVM_SKU_CAP_BAND_52GHZ;\n    data->sku_cap_11n_enable = sku & IWM_NVM_SKU_CAP_11N_ENABLE;\n    data->sku_cap_11ac_enable = sku & IWM_NVM_SKU_CAP_11AC_ENABLE;\n    data->sku_cap_mimo_disable = sku & IWM_NVM_SKU_CAP_MIMO_DISABLE;\n    \n    if (sc->sc_device_family >= IWM_DEVICE_FAMILY_8000) {\n        uint16_t lar_offset = data->nvm_version < 0xE39 ?\n        IWM_NVM_LAR_OFFSET_8000_OLD :\n        IWM_NVM_LAR_OFFSET_8000;\n        \n        lar_config = le16_to_cpup(regulatory + lar_offset);\n        data->lar_enabled = !!(lar_config &\n                               IWM_NVM_LAR_ENABLED_8000);\n        data->n_hw_addrs = le16_to_cpup(nvm_sw + IWM_N_HW_ADDRS_8000);\n    } else\n        data->n_hw_addrs = le16_to_cpup(nvm_sw + IWM_N_HW_ADDRS);\n    \n    \n    /* The byte order is little endian 16 bit, meaning 214365 */\n    if (sc->sc_device_family == IWM_DEVICE_FAMILY_7000) {\n        memcpy(hw_addr, nvm_hw + IWM_HW_ADDR, ETHER_ADDR_LEN);\n        data->hw_addr[0] = hw_addr[1];\n        data->hw_addr[1] = hw_addr[0];\n        data->hw_addr[2] = hw_addr[3];\n        data->hw_addr[3] = hw_addr[2];\n        data->hw_addr[4] = hw_addr[5];\n        data->hw_addr[5] = hw_addr[4];\n    } else\n        iwm_set_hw_address_8000(sc, data, mac_override, nvm_hw);\n    \n    if (sc->sc_device_family == IWM_DEVICE_FAMILY_7000) {\n        if (sc->nvm_type == IWM_NVM_SDP) {\n            iwm_init_channel_map(sc, regulatory, iwm_nvm_channels,\n                                 MIN(n_regulatory, nitems(iwm_nvm_channels)));\n        } else {\n            iwm_init_channel_map(sc, &nvm_sw[IWM_NVM_CHANNELS],\n                                 iwm_nvm_channels, nitems(iwm_nvm_channels));\n        }\n    } else\n        iwm_init_channel_map(sc, &regulatory[IWM_NVM_CHANNELS_8000],\n                             iwm_nvm_channels_8000,\n                             MIN(n_regulatory, nitems(iwm_nvm_channels_8000)));\n    \n    data->calib_version = 255;   /* TODO:\n                                  this value will prevent some checks from\n                                  failing, we need to check if this\n                                  field is still needed, and if it does,\n                                  where is it in the NVM */\n    \n    return 0;\n}\n\nint ItlIwm::\niwm_parse_nvm_sections(struct iwm_softc *sc, struct iwm_nvm_section *sections)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    const uint16_t *hw, *sw, *calib, *mac_override = NULL, *phy_sku = NULL;\n    const uint16_t *regulatory = NULL;\n    int n_regulatory = 0;\n    \n    /* Checking for required sections */\n    if (sc->sc_device_family == IWM_DEVICE_FAMILY_7000) {\n        if (!sections[IWM_NVM_SECTION_TYPE_SW].data ||\n            !sections[IWM_NVM_SECTION_TYPE_HW].data) {\n            return ENOENT;\n        }\n        \n        hw = (const uint16_t *) sections[IWM_NVM_SECTION_TYPE_HW].data;\n        \n        if (sc->nvm_type == IWM_NVM_SDP) {\n            if (!sections[IWM_NVM_SECTION_TYPE_REGULATORY_SDP].data)\n                return ENOENT;\n            regulatory = (const uint16_t *)\n            sections[IWM_NVM_SECTION_TYPE_REGULATORY_SDP].data;\n            n_regulatory =\n            sections[IWM_NVM_SECTION_TYPE_REGULATORY_SDP].length;\n        }\n    } else if (sc->sc_device_family >= IWM_DEVICE_FAMILY_8000) {\n        /* SW and REGULATORY sections are mandatory */\n        if (!sections[IWM_NVM_SECTION_TYPE_SW].data ||\n            !sections[IWM_NVM_SECTION_TYPE_REGULATORY].data) {\n            return ENOENT;\n        }\n        /* MAC_OVERRIDE or at least HW section must exist */\n        if (!sections[IWM_NVM_SECTION_TYPE_HW_8000].data &&\n            !sections[IWM_NVM_SECTION_TYPE_MAC_OVERRIDE].data) {\n            return ENOENT;\n        }\n        \n        /* PHY_SKU section is mandatory in B0 */\n        if (!sections[IWM_NVM_SECTION_TYPE_PHY_SKU].data) {\n            return ENOENT;\n        }\n        \n        regulatory = (const uint16_t *)\n        sections[IWM_NVM_SECTION_TYPE_REGULATORY].data;\n        n_regulatory = sections[IWM_NVM_SECTION_TYPE_REGULATORY].length;\n        hw = (const uint16_t *)\n        sections[IWM_NVM_SECTION_TYPE_HW_8000].data;\n        mac_override =\n        (const uint16_t *)\n        sections[IWM_NVM_SECTION_TYPE_MAC_OVERRIDE].data;\n        phy_sku = (const uint16_t *)\n        sections[IWM_NVM_SECTION_TYPE_PHY_SKU].data;\n    } else {\n        panic(\"unknown device family %d\\n\", sc->sc_device_family);\n    }\n    \n    sw = (const uint16_t *)sections[IWM_NVM_SECTION_TYPE_SW].data;\n    calib = (const uint16_t *)\n    sections[IWM_NVM_SECTION_TYPE_CALIBRATION].data;\n    \n    /* XXX should pass in the length of every section */\n    return iwm_parse_nvm_data(sc, hw, sw, calib, mac_override,\n                              phy_sku, regulatory, n_regulatory);\n}\n\nint ItlIwm::\niwm_nvm_init(struct iwm_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwm_nvm_section nvm_sections[IWM_NVM_NUM_OF_SECTIONS];\n    int i, section, err = 0;\n    uint16_t len;\n    uint8_t *buf;\n    const size_t bufsz = sc->sc_nvm_max_section_size;\n    \n    memset(nvm_sections, 0, sizeof(nvm_sections));\n    \n    buf = (uint8_t*)malloc(bufsz, M_DEVBUF, M_WAIT);\n    if (buf == NULL)\n        return ENOMEM;\n    \n    for (i = 0; i < nitems(iwm_nvm_to_read); i++) {\n        section = iwm_nvm_to_read[i];\n        _KASSERT(section <= nitems(nvm_sections));\n        \n        err = iwm_nvm_read_section(sc, section, buf, &len, bufsz);\n        if (err) {\n            err = 0;\n            continue;\n        }\n        nvm_sections[section].data = (uint8_t*)malloc(len, M_DEVBUF, M_WAIT);\n        if (nvm_sections[section].data == NULL) {\n            err = ENOMEM;\n            break;\n        }\n        memcpy(nvm_sections[section].data, buf, len);\n        nvm_sections[section].length = len;\n    }\n    ::free(buf);\n    if (err == 0)\n        err = iwm_parse_nvm_sections(sc, nvm_sections);\n    \n    for (i = 0; i < IWM_NVM_NUM_OF_SECTIONS; i++) {\n        if (nvm_sections[i].data != NULL)\n            ::free(nvm_sections[i].data);\n    }\n    \n    return err;\n}\n"
  },
  {
    "path": "itlwm/hal_iwm/phy.cpp",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n/*    $OpenBSD: if_iwm.c,v 1.316 2020/12/07 20:09:24 tobhe Exp $    */\n\n/*\n * Copyright (c) 2014, 2016 genua gmbh <info@genua.de>\n *   Author: Stefan Sperling <stsp@openbsd.org>\n * Copyright (c) 2014 Fixup Software Ltd.\n * Copyright (c) 2017 Stefan Sperling <stsp@openbsd.org>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n/*-\n * Based on BSD-licensed source modules in the Linux iwlwifi driver,\n * which were used as the reference documentation for this implementation.\n *\n ***********************************************************************\n *\n * This file is provided under a dual BSD/GPLv2 license.  When using or\n * redistributing this file, you may do so under either license.\n *\n * GPL LICENSE SUMMARY\n *\n * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.\n * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH\n * Copyright(c) 2016 Intel Deutschland GmbH\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of version 2 of the GNU General Public License as\n * published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful, but\n * WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,\n * USA\n *\n * The full GNU General Public License is included in this distribution\n * in the file called COPYING.\n *\n * Contact Information:\n *  Intel Linux Wireless <ilw@linux.intel.com>\n * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497\n *\n *\n * BSD LICENSE\n *\n * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.\n * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH\n * Copyright(c) 2016 Intel Deutschland GmbH\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in\n *    the documentation and/or other materials provided with the\n *    distribution.\n *  * Neither the name Intel Corporation nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*-\n * Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n#include \"ItlIwm.hpp\"\n\nstruct iwm_phy_db_entry * ItlIwm::\niwm_phy_db_get_section(struct iwm_softc *sc, uint16_t type, uint16_t chg_id)\n{\n    struct iwm_phy_db *phy_db = &sc->sc_phy_db;\n    \n    if (type >= IWM_PHY_DB_MAX)\n        return NULL;\n    \n    switch (type) {\n        case IWM_PHY_DB_CFG:\n            return &phy_db->cfg;\n        case IWM_PHY_DB_CALIB_NCH:\n            return &phy_db->calib_nch;\n        case IWM_PHY_DB_CALIB_CHG_PAPD:\n            if (chg_id >= IWM_NUM_PAPD_CH_GROUPS)\n                return NULL;\n            return &phy_db->calib_ch_group_papd[chg_id];\n        case IWM_PHY_DB_CALIB_CHG_TXP:\n            if (chg_id >= IWM_NUM_TXP_CH_GROUPS)\n                return NULL;\n            return &phy_db->calib_ch_group_txp[chg_id];\n        default:\n            return NULL;\n    }\n    return NULL;\n}\n\nint ItlIwm::\niwm_phy_db_set_section(struct iwm_softc *sc,\n                       struct iwm_calib_res_notif_phy_db *phy_db_notif)\n{\n    uint16_t type = le16toh(phy_db_notif->type);\n    uint16_t size  = le16toh(phy_db_notif->length);\n    struct iwm_phy_db_entry *entry;\n    uint16_t chg_id = 0;\n    \n    if (type == IWM_PHY_DB_CALIB_CHG_PAPD ||\n        type == IWM_PHY_DB_CALIB_CHG_TXP)\n        chg_id = le16toh(*(uint16_t *)phy_db_notif->data);\n    \n    entry = iwm_phy_db_get_section(sc, type, chg_id);\n    if (!entry)\n        return EINVAL;\n    \n    if (entry->data)\n        ::free(entry->data);\n    entry->data = (uint8_t*)malloc(size, M_DEVBUF, M_NOWAIT);\n    if (!entry->data) {\n        entry->size = 0;\n        return ENOMEM;\n    }\n    memcpy(entry->data, phy_db_notif->data, size);\n    entry->size = size;\n    \n    return 0;\n}\n\nint ItlIwm::\niwm_phy_db_get_section_data(struct iwm_softc *sc, uint32_t type, uint8_t **data,\n                            uint16_t *size, uint16_t ch_id)\n{\n    struct iwm_phy_db_entry *entry;\n    uint16_t ch_group_id = 0;\n    \n    if (type == IWM_PHY_DB_CALIB_CHG_PAPD)\n        ch_group_id = iwm_channel_id_to_papd(ch_id);\n    else if (type == IWM_PHY_DB_CALIB_CHG_TXP)\n        ch_group_id = iwm_channel_id_to_txp(sc, ch_id);\n    \n    entry = iwm_phy_db_get_section(sc, type, ch_group_id);\n    if (!entry)\n        return EINVAL;\n    \n    *data = entry->data;\n    *size = entry->size;\n    \n    return 0;\n}\n\nint ItlIwm::\niwm_send_phy_db_cmd(struct iwm_softc *sc, uint16_t type, uint16_t length,\n                    void *data)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwm_phy_db_cmd phy_db_cmd;\n    struct iwm_host_cmd cmd = {\n        .id = IWM_PHY_DB_CMD,\n        .flags = IWM_CMD_ASYNC,\n    };\n    \n    phy_db_cmd.type = le16toh(type);\n    phy_db_cmd.length = le16toh(length);\n    \n    cmd.data[0] = &phy_db_cmd;\n    cmd.len[0] = sizeof(struct iwm_phy_db_cmd);\n    cmd.data[1] = data;\n    cmd.len[1] = length;\n    \n    return iwm_send_cmd(sc, &cmd);\n}\n\nint ItlIwm::\niwm_phy_db_send_all_channel_groups(struct iwm_softc *sc, uint16_t type,\n                                   uint8_t max_ch_groups)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    uint16_t i;\n    int err;\n    struct iwm_phy_db_entry *entry;\n    \n    for (i = 0; i < max_ch_groups; i++) {\n        entry = iwm_phy_db_get_section(sc, type, i);\n        if (!entry)\n            return EINVAL;\n        \n        if (!entry->size)\n            continue;\n        \n        err = iwm_send_phy_db_cmd(sc, type, entry->size, entry->data);\n        if (err)\n            return err;\n        \n        DELAY(1000);\n    }\n    \n    return 0;\n}\n\nint ItlIwm::\niwm_send_phy_db_data(struct iwm_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    uint8_t *data = NULL;\n    uint16_t size = 0;\n    int err;\n    \n    err = iwm_phy_db_get_section_data(sc, IWM_PHY_DB_CFG, &data, &size, 0);\n    if (err)\n        return err;\n    \n    err = iwm_send_phy_db_cmd(sc, IWM_PHY_DB_CFG, size, data);\n    if (err)\n        return err;\n    \n    err = iwm_phy_db_get_section_data(sc, IWM_PHY_DB_CALIB_NCH,\n                                      &data, &size, 0);\n    if (err)\n        return err;\n    \n    err = iwm_send_phy_db_cmd(sc, IWM_PHY_DB_CALIB_NCH, size, data);\n    if (err)\n        return err;\n    \n    err = iwm_phy_db_send_all_channel_groups(sc,\n                                             IWM_PHY_DB_CALIB_CHG_PAPD, IWM_NUM_PAPD_CH_GROUPS);\n    if (err)\n        return err;\n    \n    err = iwm_phy_db_send_all_channel_groups(sc,\n                                             IWM_PHY_DB_CALIB_CHG_TXP, IWM_NUM_TXP_CH_GROUPS);\n    if (err)\n        return err;\n    \n    return 0;\n}\n\n/*\n * For the high priority TE use a time event type that has similar priority to\n * the FW's action scan priority.\n */\n#define IWM_ROC_TE_TYPE_NORMAL IWM_TE_P2P_DEVICE_DISCOVERABLE\n#define IWM_ROC_TE_TYPE_MGMT_TX IWM_TE_P2P_CLIENT_ASSOC\n\nint ItlIwm::\niwm_send_time_event_cmd(struct iwm_softc *sc,\n                        const struct iwm_time_event_cmd *cmd)\n{\n    struct iwm_rx_packet *pkt;\n    struct iwm_time_event_resp *resp;\n    struct iwm_host_cmd hcmd = {\n        .id = IWM_TIME_EVENT_CMD,\n        .flags = IWM_CMD_WANT_RESP,\n        .resp_pkt_len = sizeof(*pkt) + sizeof(*resp),\n    };\n    uint32_t resp_len;\n    int err;\n    \n    hcmd.data[0] = cmd;\n    hcmd.len[0] = sizeof(*cmd);\n    err = iwm_send_cmd(sc, &hcmd);\n    if (err)\n        return err;\n    \n    pkt = hcmd.resp_pkt;\n    if (!pkt || (pkt->hdr.flags & IWM_CMD_FAILED_MSK)) {\n        err = EIO;\n        goto out;\n    }\n    \n    resp_len = iwm_rx_packet_payload_len(pkt);\n    if (resp_len != sizeof(*resp)) {\n        err = EIO;\n        goto out;\n    }\n    \n    resp = (struct iwm_time_event_resp *)pkt->data;\n    if (le32toh(resp->status) == 0)\n        sc->sc_time_event_uid = le32toh(resp->unique_id);\n    else\n        err = EIO;\nout:\n    iwm_free_resp(sc, &hcmd);\n    return err;\n}\n\nvoid ItlIwm::\niwm_protect_session(struct iwm_softc *sc, struct iwm_node *in,\n                    uint32_t duration, uint32_t max_delay)\n{\n    struct iwm_time_event_cmd time_cmd;\n    \n    /* Do nothing if a time event is already scheduled. */\n    if (sc->sc_flags & IWM_FLAG_TE_ACTIVE)\n        return;\n    \n    memset(&time_cmd, 0, sizeof(time_cmd));\n    \n    time_cmd.action = htole32(IWM_FW_CTXT_ACTION_ADD);\n    time_cmd.id_and_color =\n    htole32(IWM_FW_CMD_ID_AND_COLOR(in->in_id, in->in_color));\n    time_cmd.id = htole32(IWM_TE_BSS_STA_AGGRESSIVE_ASSOC);\n    \n    time_cmd.apply_time = htole32(0);\n    \n    time_cmd.max_frags = IWM_TE_V2_FRAG_NONE;\n    time_cmd.max_delay = htole32(max_delay);\n    /* TODO: why do we need to interval = bi if it is not periodic? */\n    time_cmd.interval = htole32(1);\n    time_cmd.duration = htole32(duration);\n    time_cmd.repeat = 1;\n    time_cmd.policy\n    = htole16(IWM_TE_V2_NOTIF_HOST_EVENT_START |\n              IWM_TE_V2_NOTIF_HOST_EVENT_END |\n              IWM_T2_V2_START_IMMEDIATELY);\n    \n    if (iwm_send_time_event_cmd(sc, &time_cmd) == 0)\n        sc->sc_flags |= IWM_FLAG_TE_ACTIVE;\n    \n    DELAY(100);\n}\n\nvoid ItlIwm::\niwm_unprotect_session(struct iwm_softc *sc, struct iwm_node *in)\n{\n    struct iwm_time_event_cmd time_cmd;\n    \n    /* Do nothing if the time event has already ended. */\n    if ((sc->sc_flags & IWM_FLAG_TE_ACTIVE) == 0)\n        return;\n    \n    memset(&time_cmd, 0, sizeof(time_cmd));\n    \n    time_cmd.action = htole32(IWM_FW_CTXT_ACTION_REMOVE);\n    time_cmd.id_and_color =\n    htole32(IWM_FW_CMD_ID_AND_COLOR(in->in_id, in->in_color));\n    time_cmd.id = htole32(sc->sc_time_event_uid);\n    \n    if (iwm_send_time_event_cmd(sc, &time_cmd) == 0)\n        sc->sc_flags &= ~IWM_FLAG_TE_ACTIVE;\n    \n    DELAY(100);\n}\n\nint ItlIwm::\niwm_send_phy_cfg_cmd(struct iwm_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwm_phy_cfg_cmd phy_cfg_cmd;\n    enum iwm_ucode_type ucode_type = sc->sc_uc_current;\n    \n    phy_cfg_cmd.phy_cfg = htole32(sc->sc_fw_phy_config);\n    phy_cfg_cmd.calib_control.event_trigger =\n    sc->sc_default_calib[ucode_type].event_trigger;\n    phy_cfg_cmd.calib_control.flow_trigger =\n    sc->sc_default_calib[ucode_type].flow_trigger;\n    \n    return iwm_send_cmd_pdu(sc, IWM_PHY_CONFIGURATION_CMD, 0,\n                            sizeof(phy_cfg_cmd), &phy_cfg_cmd);\n}\n\nint ItlIwm::\niwm_send_dqa_cmd(struct iwm_softc *sc)\n{\n    struct iwm_dqa_enable_cmd dqa_cmd = {\n        .cmd_queue = htole32(IWM_DQA_CMD_QUEUE),\n    };\n    uint32_t cmd_id;\n    \n    cmd_id = iwm_cmd_id(IWM_DQA_ENABLE_CMD, IWM_DATA_PATH_GROUP, 0);\n    return iwm_send_cmd_pdu(sc, cmd_id, 0, sizeof(dqa_cmd), &dqa_cmd);\n}\n\nint ItlIwm::\niwm_binding_cmd(struct iwm_softc *sc, struct iwm_node *in, uint32_t action)\n{\n    struct iwm_binding_cmd cmd;\n    struct iwm_phy_ctxt *phyctxt = in->in_phyctxt;\n    uint32_t mac_id = IWM_FW_CMD_ID_AND_COLOR(in->in_id, in->in_color);\n    int i, err, active = (sc->sc_flags & IWM_FLAG_BINDING_ACTIVE);\n    uint32_t status;\n    size_t len;\n    \n    if (action == IWM_FW_CTXT_ACTION_ADD && active) {\n        XYLog(\"binding already added\\n\");\n        return 0;\n    }\n    if (action == IWM_FW_CTXT_ACTION_REMOVE && !active) {\n        XYLog(\"binding already removed\\n\");\n        return 0;\n    }\n    \n    if (phyctxt == NULL) /* XXX race with iwm_stop() */\n        return EINVAL;\n    \n    memset(&cmd, 0, sizeof(cmd));\n    \n    cmd.id_and_color\n    = htole32(IWM_FW_CMD_ID_AND_COLOR(phyctxt->id, phyctxt->color));\n    cmd.action = htole32(action);\n    cmd.phy = htole32(IWM_FW_CMD_ID_AND_COLOR(phyctxt->id, phyctxt->color));\n    \n    cmd.macs[0] = htole32(mac_id);\n    for (i = 1; i < IWM_MAX_MACS_IN_BINDING; i++)\n        cmd.macs[i] = htole32(IWM_FW_CTXT_INVALID);\n    \n    if (IEEE80211_IS_CHAN_2GHZ(phyctxt->channel) ||\n        !isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_CDB_SUPPORT))\n        cmd.lmac_id = htole32(IWM_LMAC_24G_INDEX);\n    else\n        cmd.lmac_id = htole32(IWM_LMAC_5G_INDEX);\n    \n    if (isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT))\n        len = sizeof(cmd);\n    else\n        len = sizeof(struct iwm_binding_cmd_v1);\n    \n    status = 0;\n    err = iwm_send_cmd_pdu_status(sc, IWM_BINDING_CONTEXT_CMD, len, &cmd,\n                                  &status);\n    if (err == 0 && status != 0)\n        err = EIO;\n    \n    return err;\n}\n\nint ItlIwm::\niwm_send_cmd(struct iwm_softc *sc, struct iwm_host_cmd *hcmd)\n{\n    struct iwm_tx_ring *ring = &sc->txq[sc->cmdqid];\n    struct iwm_tfd *desc;\n    struct iwm_tx_data *txdata;\n    struct iwm_device_cmd *cmd;\n    mbuf_t m;\n    bus_addr_t paddr;\n    uint32_t addr_lo;\n    int err = 0, i, paylen, off, s;\n    int idx, code, async, group_id;\n    size_t hdrlen, datasz;\n    uint8_t *data;\n    int generation = sc->sc_generation;\n    unsigned int max_chunks = 1;\n    IOPhysicalSegment seg;\n    \n    code = hcmd->id;\n    async = hcmd->flags & IWM_CMD_ASYNC;\n    idx = ring->cur;\n    \n    for (i = 0, paylen = 0; i < nitems(hcmd->len); i++) {\n        paylen += hcmd->len[i];\n    }\n    \n    /* If this command waits for a response, allocate response buffer. */\n    hcmd->resp_pkt = NULL;\n    if (hcmd->flags & IWM_CMD_WANT_RESP) {\n        uint8_t *resp_buf;\n        _KASSERT(!async);\n        _KASSERT(hcmd->resp_pkt_len >= sizeof(struct iwm_rx_packet));\n        _KASSERT(hcmd->resp_pkt_len <= IWM_CMD_RESP_MAX);\n        if (sc->sc_cmd_resp_pkt[idx] != NULL)\n            return ENOSPC;\n        resp_buf = (uint8_t *)malloc(hcmd->resp_pkt_len, M_DEVBUF,\n                                     M_NOWAIT | M_ZERO);\n        if (resp_buf == NULL)\n            return ENOMEM;\n        sc->sc_cmd_resp_pkt[idx] = resp_buf;\n        sc->sc_cmd_resp_len[idx] = hcmd->resp_pkt_len;\n    } else {\n        sc->sc_cmd_resp_pkt[idx] = NULL;\n    }\n    \n    s = splnet();\n    \n    desc = &ring->desc[idx];\n    txdata = &ring->data[idx];\n    \n    group_id = iwm_cmd_groupid(code);\n    if (group_id != 0) {\n        hdrlen = sizeof(cmd->hdr_wide);\n        datasz = sizeof(cmd->data_wide);\n    } else {\n        hdrlen = sizeof(cmd->hdr);\n        datasz = sizeof(cmd->data);\n    }\n    \n    if (paylen > datasz) {\n        /* Command is too large to fit in pre-allocated space. */\n        size_t totlen = hdrlen + paylen;\n        if (paylen > IWM_MAX_CMD_PAYLOAD_SIZE) {\n            XYLog(\"%s: firmware command too long (%zd bytes)\\n\",\n                  DEVNAME(sc), totlen);\n            err = EINVAL;\n            goto out;\n        }\n        mbuf_allocpacket(MBUF_WAITOK, totlen, &max_chunks, &m);\n        if (m == NULL) {\n            XYLog(\"%s: could not get fw cmd mbuf (%zd bytes)\\n\",\n                  DEVNAME(sc), totlen);\n            err = ENOMEM;\n            goto out;\n        }\n        mbuf_setlen(m, totlen);\n        mbuf_pkthdr_setlen(m, totlen);\n        cmd = mtod(m, struct iwm_device_cmd *);\n        txdata->map->dm_nsegs = txdata->map->cursor->getPhysicalSegmentsWithCoalesce(m, &seg, 1);\n        if (txdata->map->dm_nsegs == 0) {\n            XYLog(\"%s: could not load fw cmd mbuf (%zd bytes)\\n\",\n                  DEVNAME(sc), totlen);\n            mbuf_freem(m);\n            goto out;\n        }\n//        XYLog(\"map fw cmd dm_nsegs=%d\\n\", txdata->map->dm_nsegs);\n        txdata->m = m; /* mbuf will be freed in iwm_cmd_done() */\n        paddr = seg.location;\n    } else {\n        cmd = &ring->cmd[idx];\n        paddr = txdata->cmd_paddr;\n    }\n    \n    if (group_id != 0) {\n        cmd->hdr_wide.opcode = iwm_cmd_opcode(code);\n        cmd->hdr_wide.group_id = group_id;\n        cmd->hdr_wide.qid = ring->qid;\n        cmd->hdr_wide.idx = idx;\n        cmd->hdr_wide.length = htole16(paylen);\n        cmd->hdr_wide.version = iwm_cmd_version(code);\n        data = cmd->data_wide;\n    } else {\n        cmd->hdr.code = code;\n        cmd->hdr.flags = 0;\n        cmd->hdr.qid = ring->qid;\n        cmd->hdr.idx = idx;\n        data = cmd->data;\n    }\n    \n    for (i = 0, off = 0; i < nitems(hcmd->data); i++) {\n        if (hcmd->len[i] == 0)\n            continue;\n        memcpy(data + off, hcmd->data[i], hcmd->len[i]);\n        off += hcmd->len[i];\n    }\n    KASSERT(off == paylen, \"off == paylen\");\n    \n    /* lo field is not aligned */\n    addr_lo = htole32((uint32_t)paddr);\n    memcpy(&desc->tbs[0].lo, &addr_lo, sizeof(uint32_t));\n    desc->tbs[0].hi_n_len  = htole16(iwm_get_dma_hi_addr(paddr)\n                                     | ((hdrlen + paylen) << 4));\n    desc->num_tbs = 1;\n    \n    //    if (paylen > datasz) {\n    //        bus_dmamap_sync(sc->sc_dmat, txdata->map, 0,\n    //            hdrlen + paylen, BUS_DMASYNC_PREWRITE);\n    //    } else {\n    //        bus_dmamap_sync(sc->sc_dmat, ring->cmd_dma.map,\n    //            (char *)(void *)cmd - (char *)(void *)ring->cmd_dma.vaddr,\n    //            hdrlen + paylen, BUS_DMASYNC_PREWRITE);\n    //    }\n    //    bus_dmamap_sync(sc->sc_dmat, ring->desc_dma.map,\n    //        (char *)(void *)desc - (char *)(void *)ring->desc_dma.vaddr,\n    //        sizeof (*desc), BUS_DMASYNC_PREWRITE);\n    \n    /*\n     * Wake up the NIC to make sure that the firmware will see the host\n     * command - we will let the NIC sleep once all the host commands\n     * returned. This needs to be done only on 7000 family NICs.\n     */\n    if (sc->sc_device_family == IWM_DEVICE_FAMILY_7000) {\n        if (ring->queued == 0 && !iwm_nic_lock(sc)) {\n            err = EBUSY;\n            goto out;\n        }\n    }\n    \n    DPRINTFN(2, (\"%s: sending command 0x%x\\n\", __func__, code));\n\n    iwm_update_sched(sc, ring->qid, ring->cur, 0, 0);\n    /* Kick command ring. */\n    ring->queued++;\n    ring->cur = (ring->cur + 1) % IWM_TX_RING_COUNT;\n    IWM_WRITE(sc, IWM_HBUS_TARG_WRPTR, ring->qid << 8 | ring->cur);\n    \n    if (!async) {\n        err = tsleep_nsec(desc, PCATCH, \"iwmcmd\", SEC_TO_NSEC(2));\n        if (err == 0) {\n            /* if hardware is no longer up, return error */\n            if (generation != sc->sc_generation) {\n                err = ENXIO;\n                goto out;\n            }\n            \n            /* Response buffer will be freed in iwm_free_resp(). */\n            hcmd->resp_pkt = (struct iwm_rx_packet *)sc->sc_cmd_resp_pkt[idx];\n            sc->sc_cmd_resp_pkt[idx] = NULL;\n        } else if (generation == sc->sc_generation) {\n            ::free(sc->sc_cmd_resp_pkt[idx]);\n            sc->sc_cmd_resp_pkt[idx] = NULL;\n        }\n    }\nout:\n    splx(s);\n    \n    return err;\n}\n\nint ItlIwm::\niwm_send_cmd_pdu(struct iwm_softc *sc, uint32_t id, uint32_t flags,\n                 uint16_t len, const void *data)\n{\n    struct iwm_host_cmd cmd = {\n        .id = id,\n        .len = { len, },\n        .data = { data, },\n        .flags = flags,\n    };\n    \n    return iwm_send_cmd(sc, &cmd);\n}\n\nint ItlIwm::\niwm_send_cmd_status(struct iwm_softc *sc, struct iwm_host_cmd *cmd,\n                    uint32_t *status)\n{\n    struct iwm_rx_packet *pkt;\n    struct iwm_cmd_response *resp;\n    int err, resp_len;\n    \n    KASSERT((cmd->flags & IWM_CMD_WANT_RESP) == 0, \"(cmd->flags & IWM_CMD_WANT_RESP) == 0\");\n    cmd->flags |= IWM_CMD_WANT_RESP;\n    cmd->resp_pkt_len = sizeof(*pkt) + sizeof(*resp);\n    \n    err = iwm_send_cmd(sc, cmd);\n    if (err)\n        return err;\n    \n    pkt = cmd->resp_pkt;\n    if (pkt == NULL || (pkt->hdr.flags & IWM_CMD_FAILED_MSK))\n        return EIO;\n    \n    resp_len = iwm_rx_packet_payload_len(pkt);\n    if (resp_len != sizeof(*resp)) {\n        iwm_free_resp(sc, cmd);\n        return EIO;\n    }\n    \n    resp = (struct iwm_cmd_response *)pkt->data;\n    *status = le32toh(resp->status);\n    iwm_free_resp(sc, cmd);\n    return err;\n}\n\nint ItlIwm::\niwm_send_cmd_pdu_status(struct iwm_softc *sc, uint32_t id, uint16_t len,\n                        const void *data, uint32_t *status)\n{\n    struct iwm_host_cmd cmd = {\n        .id = id,\n        .len = { len, },\n        .data = { data, },\n    };\n    \n    return iwm_send_cmd_status(sc, &cmd, status);\n}\n\nvoid ItlIwm::\niwm_free_resp(struct iwm_softc *sc, struct iwm_host_cmd *hcmd)\n{\n    _KASSERT((hcmd->flags & (IWM_CMD_WANT_RESP)) == IWM_CMD_WANT_RESP);\n    ::free(hcmd->resp_pkt);\n    hcmd->resp_pkt = NULL;\n}\n\nvoid ItlIwm::\niwm_cmd_done(struct iwm_softc *sc, int qid, int idx, int code)\n{\n    struct iwm_tx_ring *ring = &sc->txq[sc->cmdqid];\n    struct iwm_tx_data *data;\n    \n    if (qid != sc->cmdqid) {\n        return;    /* Not a command ack. */\n    }\n    \n    data = &ring->data[idx];\n    \n    if (data->m != NULL) {\n        //        bus_dmamap_sync(sc->sc_dmat, data->map, 0,\n        //            data->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);\n        //        bus_dmamap_unload(sc->sc_dmat, data->map);\n        mbuf_freem(data->m);\n        data->m = NULL;\n    }\n    wakeupOn(&ring->desc[idx]);\n    \n    DPRINTFN(2, (\"%s: command 0x%x done\\n\", __func__, code));\n    \n    if (ring->queued == 0) {\n        XYLog(\"%s: unexpected firmware response to command 0x%x\\n\",\n              DEVNAME(sc), code);\n    } else if (--ring->queued == 0) {\n        /*\n         * 7000 family NICs are locked while commands are in progress.\n         * All commands are now done so we may unlock the NIC again.\n         */\n        if (sc->sc_device_family == IWM_DEVICE_FAMILY_7000)\n            iwm_nic_unlock(sc);\n    }\n}\n\nint ItlIwm::\niwm_phy_ctxt_update(struct iwm_softc *sc, struct iwm_phy_ctxt *phyctxt,\n                    struct ieee80211_channel *chan, uint8_t chains_static,\n                    uint8_t chains_dynamic, uint32_t apply_time)\n{\n    uint16_t band_flags = (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_5GHZ);\n    int err;\n    \n    if (isset(sc->sc_enabled_capa,\n              IWM_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT) &&\n        (phyctxt->channel->ic_flags & band_flags) !=\n        (chan->ic_flags & band_flags)) {\n        err = iwm_phy_ctxt_cmd(sc, phyctxt, chains_static,\n                               chains_dynamic, IWM_FW_CTXT_ACTION_REMOVE, apply_time);\n        if (err) {\n            printf(\"%s: could not remove PHY context \"\n                   \"(error %d)\\n\", DEVNAME(sc), err);\n            return err;\n        }\n        phyctxt->channel = chan;\n        err = iwm_phy_ctxt_cmd(sc, phyctxt, chains_static,\n                               chains_dynamic, IWM_FW_CTXT_ACTION_ADD, apply_time);\n        if (err) {\n            printf(\"%s: could not remove PHY context \"\n                   \"(error %d)\\n\", DEVNAME(sc), err);\n            return err;\n        }\n    } else {\n        phyctxt->channel = chan;\n        err = iwm_phy_ctxt_cmd(sc, phyctxt, chains_static,\n                               chains_dynamic, IWM_FW_CTXT_ACTION_MODIFY, apply_time);\n        if (err) {\n            printf(\"%s: could not update PHY context (error %d)\\n\",\n                   DEVNAME(sc), err);\n            return err;\n        }\n    }\n    \n    return 0;\n}\n"
  },
  {
    "path": "itlwm/hal_iwm/power.cpp",
    "content": "/*\n * Copyright (C) 2020  钟先耀\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n */\n/*    $OpenBSD: if_iwm.c,v 1.316 2020/12/07 20:09:24 tobhe Exp $    */\n\n/*\n * Copyright (c) 2014, 2016 genua gmbh <info@genua.de>\n *   Author: Stefan Sperling <stsp@openbsd.org>\n * Copyright (c) 2014 Fixup Software Ltd.\n * Copyright (c) 2017 Stefan Sperling <stsp@openbsd.org>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n/*-\n * Based on BSD-licensed source modules in the Linux iwlwifi driver,\n * which were used as the reference documentation for this implementation.\n *\n ***********************************************************************\n *\n * This file is provided under a dual BSD/GPLv2 license.  When using or\n * redistributing this file, you may do so under either license.\n *\n * GPL LICENSE SUMMARY\n *\n * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.\n * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH\n * Copyright(c) 2016 Intel Deutschland GmbH\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of version 2 of the GNU General Public License as\n * published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful, but\n * WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,\n * USA\n *\n * The full GNU General Public License is included in this distribution\n * in the file called COPYING.\n *\n * Contact Information:\n *  Intel Linux Wireless <ilw@linux.intel.com>\n * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497\n *\n *\n * BSD LICENSE\n *\n * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.\n * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH\n * Copyright(c) 2016 Intel Deutschland GmbH\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in\n *    the documentation and/or other materials provided with the\n *    distribution.\n *  * Neither the name Intel Corporation nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*-\n * Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n#include \"ItlIwm.hpp\"\n\n#define IWM_POWER_KEEP_ALIVE_PERIOD_SEC    25\n\nint ItlIwm::\niwm_beacon_filter_send_cmd(struct iwm_softc *sc,\n                           struct iwm_beacon_filter_cmd *cmd)\n{\n    return iwm_send_cmd_pdu(sc, IWM_REPLY_BEACON_FILTERING_CMD,\n                            0, sizeof(struct iwm_beacon_filter_cmd), cmd);\n}\n\nvoid ItlIwm::\niwm_beacon_filter_set_cqm_params(struct iwm_softc *sc, struct iwm_node *in,\n                                 struct iwm_beacon_filter_cmd *cmd)\n{\n    cmd->ba_enable_beacon_abort = htole32(sc->sc_bf.ba_enabled);\n}\n\nint ItlIwm::\niwm_update_beacon_abort(struct iwm_softc *sc, struct iwm_node *in, int enable)\n{\n    struct iwm_beacon_filter_cmd cmd = {\n        IWM_BF_CMD_CONFIG_DEFAULTS,\n        .bf_enable_beacon_filter = htole32(1),\n        .ba_enable_beacon_abort = htole32(enable),\n    };\n    \n    if (!sc->sc_bf.bf_enabled)\n        return 0;\n    \n    sc->sc_bf.ba_enabled = enable;\n    iwm_beacon_filter_set_cqm_params(sc, in, &cmd);\n    return iwm_beacon_filter_send_cmd(sc, &cmd);\n}\n\nvoid ItlIwm::\niwm_power_build_cmd(struct iwm_softc *sc, struct iwm_node *in,\n                    struct iwm_mac_power_cmd *cmd)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct ieee80211_node *ni = &in->in_ni;\n    int dtim_period, dtim_msec, keep_alive;\n    \n    cmd->id_and_color = htole32(IWM_FW_CMD_ID_AND_COLOR(in->in_id,\n                                                        in->in_color));\n    if (ni->ni_dtimperiod)\n        dtim_period = ni->ni_dtimperiod;\n    else\n        dtim_period = 1;\n    \n    /*\n     * Regardless of power management state the driver must set\n     * keep alive period. FW will use it for sending keep alive NDPs\n     * immediately after association. Check that keep alive period\n     * is at least 3 * DTIM.\n     */\n    dtim_msec = dtim_period * ni->ni_intval;\n    keep_alive = MAX(3 * dtim_msec, 1000 * IWM_POWER_KEEP_ALIVE_PERIOD_SEC);\n    keep_alive = roundup(keep_alive, 1000) / 1000;\n    cmd->keep_alive_seconds = htole16(keep_alive);\n    \n    if (ic->ic_opmode != IEEE80211_M_MONITOR)\n        cmd->flags = htole16(IWM_POWER_FLAGS_POWER_SAVE_ENA_MSK);\n}\n\nint ItlIwm::\niwm_power_mac_update_mode(struct iwm_softc *sc, struct iwm_node *in)\n{\n    int err;\n    int ba_enable;\n    struct iwm_mac_power_cmd cmd;\n    \n    memset(&cmd, 0, sizeof(cmd));\n    \n    iwm_power_build_cmd(sc, in, &cmd);\n    \n    err = iwm_send_cmd_pdu(sc, IWM_MAC_PM_POWER_TABLE, 0,\n                           sizeof(cmd), &cmd);\n    if (err != 0)\n        return err;\n    \n    ba_enable = !!(cmd.flags &\n                   htole16(IWM_POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK));\n    return iwm_update_beacon_abort(sc, in, ba_enable);\n}\n\nint ItlIwm::\niwm_power_update_device(struct iwm_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwm_device_power_cmd cmd = { };\n    struct ieee80211com *ic = &sc->sc_ic;\n    \n    if (ic->ic_opmode != IEEE80211_M_MONITOR)\n        cmd.flags = htole16(IWM_DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK);\n    \n    return iwm_send_cmd_pdu(sc,\n                            IWM_POWER_TABLE_CMD, 0, sizeof(cmd), &cmd);\n}\n\nint ItlIwm::\niwm_enable_beacon_filter(struct iwm_softc *sc, struct iwm_node *in)\n{\n    struct iwm_beacon_filter_cmd cmd = {\n        IWM_BF_CMD_CONFIG_DEFAULTS,\n        .bf_enable_beacon_filter = htole32(1),\n    };\n    int err;\n    \n    iwm_beacon_filter_set_cqm_params(sc, in, &cmd);\n    err = iwm_beacon_filter_send_cmd(sc, &cmd);\n    \n    if (err == 0)\n        sc->sc_bf.bf_enabled = 1;\n    \n    return err;\n}\n\nint ItlIwm::\niwm_disable_beacon_filter(struct iwm_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwm_beacon_filter_cmd cmd;\n    int err;\n    \n    memset(&cmd, 0, sizeof(cmd));\n    \n    err = iwm_beacon_filter_send_cmd(sc, &cmd);\n    if (err == 0)\n        sc->sc_bf.bf_enabled = 0;\n    \n    return err;\n}\n\nint ItlIwm::\niwm_add_sta_cmd(struct iwm_softc *sc, struct iwm_node *in, int update, unsigned int flags)\n{\n    struct iwm_add_sta_cmd add_sta_cmd;\n    int err;\n    uint32_t status;\n    size_t cmdsize;\n    uint32_t aggsize = 0;\n    uint32_t max_aggsize = (IWM_STA_FLG_MAX_AGG_SIZE_4M >> IWM_STA_FLG_MAX_AGG_SIZE_SHIFT);\n    struct ieee80211com *ic = &sc->sc_ic;\n    \n    if (!update && (sc->sc_flags & IWM_FLAG_STA_ACTIVE)) {\n        XYLog(\"STA already added\\n\");\n        return 0;\n    }\n    \n    memset(&add_sta_cmd, 0, sizeof(add_sta_cmd));\n    \n    if (ic->ic_opmode == IEEE80211_M_MONITOR)\n        add_sta_cmd.sta_id = IWM_MONITOR_STA_ID;\n    else\n        add_sta_cmd.sta_id = IWM_STATION_ID;\n    if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_STA_TYPE)) {\n        if (ic->ic_opmode == IEEE80211_M_MONITOR)\n            add_sta_cmd.station_type = IWM_STA_GENERAL_PURPOSE;\n        else\n            add_sta_cmd.station_type = IWM_STA_LINK;\n    }\n    add_sta_cmd.mac_id_n_color\n    = htole32(IWM_FW_CMD_ID_AND_COLOR(in->in_id, in->in_color));\n    if (ic->ic_opmode == IEEE80211_M_MONITOR) {\n        int qid;\n        IEEE80211_ADDR_COPY(&add_sta_cmd.addr, etheranyaddr);\n        if (isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_DQA_SUPPORT))\n            qid = IWM_DQA_INJECT_MONITOR_QUEUE;\n        else\n            qid = IWM_AUX_QUEUE;\n        add_sta_cmd.tfd_queue_msk |= htole32(1 << qid);\n    } else if (!update || (flags & IWM_STA_MODIFY_QUEUES)) {\n        if (!update) {\n            int ac;\n            sc->agg_queue_mask = 0;\n            sc->agg_tid_disable = 0xffff;\n            for (ac = 0; ac < EDCA_NUM_AC; ac++) {\n                int qid = ac;\n                if (isset(sc->sc_enabled_capa,\n                          IWM_UCODE_TLV_CAPA_DQA_SUPPORT))\n                    qid += IWM_DQA_MIN_MGMT_QUEUE;\n                sc->agg_queue_mask |= htole32(1 << qid);\n            }\n        }\n        add_sta_cmd.tfd_queue_msk = sc->agg_queue_mask;\n        IEEE80211_ADDR_COPY(&add_sta_cmd.addr, in->in_macaddr);\n    }\n    add_sta_cmd.add_modify = update ? 1 : 0;\n    add_sta_cmd.station_flags_msk\n    |= htole32(IWM_STA_FLG_FAT_EN_MSK | IWM_STA_FLG_MIMO_EN_MSK);\n    add_sta_cmd.tid_disable_tx = htole16(sc->agg_tid_disable);\n    if (update)\n        add_sta_cmd.modify_mask |= (IWM_STA_MODIFY_TID_DISABLE_TX);\n    \n    if ((in->in_ni.ni_flags & IEEE80211_NODE_HT) ||\n        (in->in_ni.ni_flags & IEEE80211_NODE_VHT)) {\n        add_sta_cmd.station_flags_msk\n        |= htole32(IWM_STA_FLG_MAX_AGG_SIZE_MSK |\n                   IWM_STA_FLG_AGG_MPDU_DENS_MSK);\n        \n        if (ic->ic_state >= IEEE80211_S_ASSOC) {\n            switch (in->in_ni.ni_chw) {\n                case IEEE80211_CHAN_WIDTH_80P80:\n                case IEEE80211_CHAN_WIDTH_160:\n                    add_sta_cmd.station_flags |= htole32(IWM_STA_FLG_FAT_EN_160MHZ);\n                case IEEE80211_CHAN_WIDTH_80:\n                    add_sta_cmd.station_flags |= htole32(IWM_STA_FLG_FAT_EN_80MHZ);\n                case IEEE80211_CHAN_WIDTH_40:\n                    add_sta_cmd.station_flags |= htole32(IWM_STA_FLG_FAT_EN_40MHZ);\n                case IEEE80211_CHAN_WIDTH_20:\n                default:\n                    add_sta_cmd.station_flags |= htole32(IWM_STA_FLG_FAT_EN_20MHZ);\n                    break;\n            }\n        }\n        \n        if (iwm_mimo_enabled(sc) && ic->ic_bss->ni_rx_nss > 1)\n            add_sta_cmd.station_flags |= htole32(IWM_STA_FLG_MIMO_EN_MIMO2);\n        else\n            add_sta_cmd.station_flags |= htole32(IWM_STA_FLG_MIMO_EN_SISO);\n        \n        if (in->in_ni.ni_flags & IEEE80211_NODE_VHT) {\n            aggsize = in->in_ni.ni_vhtcaps &\n            IEEE80211_VHTCAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;\n            aggsize >>=\n            IEEE80211_VHTCAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT;\n            add_sta_cmd.station_flags |=\n            htole32(min(max_aggsize, aggsize) << IWM_STA_FLG_MAX_AGG_SIZE_SHIFT);\n        }\n        else if (in->in_ni.ni_flags & IEEE80211_NODE_HT)\n            add_sta_cmd.station_flags |= htole32(IWM_STA_FLG_MAX_AGG_SIZE_64K);\n        \n        switch (ic->ic_ampdu_params & IEEE80211_AMPDU_PARAM_SS) {\n            case IEEE80211_AMPDU_PARAM_SS_2:\n                add_sta_cmd.station_flags\n                |= htole32(IWM_STA_FLG_AGG_MPDU_DENS_2US);\n                break;\n            case IEEE80211_AMPDU_PARAM_SS_4:\n                add_sta_cmd.station_flags\n                |= htole32(IWM_STA_FLG_AGG_MPDU_DENS_4US);\n                break;\n            case IEEE80211_AMPDU_PARAM_SS_8:\n                add_sta_cmd.station_flags\n                |= htole32(IWM_STA_FLG_AGG_MPDU_DENS_8US);\n                break;\n            case IEEE80211_AMPDU_PARAM_SS_16:\n                add_sta_cmd.station_flags\n                |= htole32(IWM_STA_FLG_AGG_MPDU_DENS_16US);\n                break;\n            default:\n                break;\n        }\n    }\n    \n    status = IWM_ADD_STA_SUCCESS;\n    if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_STA_TYPE))\n        cmdsize = sizeof(add_sta_cmd);\n    else\n        cmdsize = sizeof(struct iwm_add_sta_cmd_v7);\n    err = iwm_send_cmd_pdu_status(sc, IWM_ADD_STA, cmdsize,\n                                  &add_sta_cmd, &status);\n    if (!err && (status & IWM_ADD_STA_STATUS_MASK) != IWM_ADD_STA_SUCCESS) {\n        err = EIO;\n        XYLog(\"%s failed\\n\", __FUNCTION__);\n    } else\n        sc->sc_flags |= IWM_FLAG_STA_ACTIVE;\n\n    return err;\n}\n\nint ItlIwm::\niwm_add_aux_sta(struct iwm_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwm_add_sta_cmd cmd;\n    int err, qid;\n    uint32_t status;\n    size_t cmdsize;\n    \n    if (isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_DQA_SUPPORT)) {\n        qid = IWM_DQA_AUX_QUEUE;\n        err = iwm_enable_txq(sc, IWM_AUX_STA_ID, qid,\n                             IWM_TX_FIFO_MCAST, 0, IWM_MAX_TID_COUNT, 0);\n    } else {\n        qid = IWM_AUX_QUEUE;\n        err = iwm_enable_ac_txq(sc, qid, IWM_TX_FIFO_MCAST);\n    }\n    if (err)\n        return err;\n    \n    memset(&cmd, 0, sizeof(cmd));\n    cmd.sta_id = IWM_AUX_STA_ID;\n    if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_STA_TYPE))\n        cmd.station_type = IWM_STA_AUX_ACTIVITY;\n    cmd.mac_id_n_color =\n    htole32(IWM_FW_CMD_ID_AND_COLOR(IWM_MAC_INDEX_AUX, 0));\n    cmd.tfd_queue_msk = htole32(1 << qid);\n    cmd.tid_disable_tx = htole16(0xffff);\n    \n    status = IWM_ADD_STA_SUCCESS;\n    if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_STA_TYPE))\n        cmdsize = sizeof(cmd);\n    else\n        cmdsize = sizeof(struct iwm_add_sta_cmd_v7);\n    err = iwm_send_cmd_pdu_status(sc, IWM_ADD_STA, cmdsize, &cmd,\n                                  &status);\n    if (!err && (status & IWM_ADD_STA_STATUS_MASK) != IWM_ADD_STA_SUCCESS)\n        err = EIO;\n    \n    return err;\n}\n\nint ItlIwm::\niwm_drain_sta(struct iwm_softc *sc, struct iwm_node *in, bool drain)\n{\n    struct iwm_add_sta_cmd cmd = {};\n    int err;\n    uint32_t status;\n    size_t cmdsize;\n    \n    cmd.mac_id_n_color = cpu_to_le32(IWM_FW_CMD_ID_AND_COLOR(in->in_id, in->in_color));\n    cmd.sta_id = IWM_STATION_ID;\n    cmd.add_modify = IWM_STA_MODE_MODIFY;\n    cmd.station_flags = drain ? cpu_to_le32(IWM_STA_FLG_DRAIN_FLOW) : 0;\n    cmd.station_flags_msk = cpu_to_le32(IWM_STA_FLG_DRAIN_FLOW);\n    status = IWM_ADD_STA_SUCCESS;\n    if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_STA_TYPE))\n        cmdsize = sizeof(cmd);\n    else\n        cmdsize = sizeof(struct iwm_add_sta_cmd_v7);\n    err = iwm_send_cmd_pdu_status(sc, IWM_ADD_STA,\n                      cmdsize,\n                      &cmd, &status);\n    return err;\n}\n\nint ItlIwm::\niwm_rm_sta_cmd(struct iwm_softc *sc, struct iwm_node *in)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct iwm_rm_sta_cmd rm_sta_cmd;\n    int err;\n    uint8_t qid;\n    \n    if ((sc->sc_flags & IWM_FLAG_STA_ACTIVE) == 0) {\n        XYLog(\"sta already removed\\n\");\n        return 0;\n    }\n    \n    if (ic->ic_opmode == IEEE80211_M_STA) {\n        err = iwm_drain_sta(sc, in, true);\n        if (err) {\n            XYLog(\"%s can not drain sta(TRUE)\\n\", __FUNCTION__);\n            goto done;\n        }\n        err = iwm_flush_tx_path(sc, sc->agg_queue_mask);\n        if (err) {\n            XYLog(\"%s can not flush sta tx path\\n\", __FUNCTION__);\n            goto done;\n        }\n        err = iwm_drain_sta(sc, in, false);\n        if (err) {\n            XYLog(\"%s can not drain sta(FALSE)\\n\", __FUNCTION__);\n            goto done;\n        }\n        for (qid = IWM_FIRST_AGG_TX_QUEUE; qid <= IWM_LAST_AGG_TX_QUEUE; qid++) {\n            if (sc->agg_queue_mask & (1 << qid)) {\n                iwm_disable_txq(sc, qid, 0, 0);\n            }\n        }\n    }\n    memset(&rm_sta_cmd, 0, sizeof(rm_sta_cmd));\n    if (ic->ic_opmode == IEEE80211_M_MONITOR)\n        rm_sta_cmd.sta_id = IWM_MONITOR_STA_ID;\n    else\n        rm_sta_cmd.sta_id = IWM_STATION_ID;\n    \n    err = iwm_send_cmd_pdu(sc, IWM_REMOVE_STA, 0, sizeof(rm_sta_cmd),\n                           &rm_sta_cmd);\ndone:\n    sc->agg_queue_mask = 0;\n    sc->agg_tid_disable = 0xffff;\n    \n    sc->sc_flags &= ~IWM_FLAG_STA_ACTIVE;\n\n    return err;\n}\n"
  },
  {
    "path": "itlwm/hal_iwm/rs.cpp",
    "content": "//\n//  rs.cpp\n//  itlwm\n//\n//  Created by zxystd on 2021/8/27.\n//  Copyright © 2021 钟先耀. All rights reserved.\n//\n\n#include \"ItlIwm.hpp\"\n\n#define IWL_RATE_MAX_WINDOW        62    /* # tx in history window */\n\n/* Calculations of success ratio are done in fixed point where 12800 is 100%.\n * Use this macro when dealing with thresholds consts set as a percentage\n */\n#define RS_PERCENT(x) (128 * x)\n\nstatic u8 rs_ht_to_legacy[] = {\n    [IWL_RATE_MCS_0_INDEX] = IWL_RATE_6M_INDEX,\n    [IWL_RATE_MCS_1_INDEX] = IWL_RATE_9M_INDEX,\n    [IWL_RATE_MCS_2_INDEX] = IWL_RATE_12M_INDEX,\n    [IWL_RATE_MCS_3_INDEX] = IWL_RATE_18M_INDEX,\n    [IWL_RATE_MCS_4_INDEX] = IWL_RATE_24M_INDEX,\n    [IWL_RATE_MCS_5_INDEX] = IWL_RATE_36M_INDEX,\n    [IWL_RATE_MCS_6_INDEX] = IWL_RATE_48M_INDEX,\n    [IWL_RATE_MCS_7_INDEX] = IWL_RATE_54M_INDEX,\n    [IWL_RATE_MCS_8_INDEX] = IWL_RATE_54M_INDEX,\n    [IWL_RATE_MCS_9_INDEX] = IWL_RATE_54M_INDEX,\n};\n\nstatic const u8 ant_toggle_lookup[] = {\n    [ANT_NONE] = ANT_NONE,\n    [ANT_A] = ANT_B,\n    [ANT_B] = ANT_A,\n    [ANT_AB] = ANT_AB,\n};\n\n#define IWL_DECLARE_RATE_INFO(r, s, rp, rn)                  \\\n    [IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP,          \\\n                    IWL_RATE_HT_SISO_MCS_##s##_PLCP,  \\\n                    IWL_RATE_HT_MIMO2_MCS_##s##_PLCP, \\\n                    IWL_RATE_VHT_SISO_MCS_##s##_PLCP, \\\n                    IWL_RATE_VHT_MIMO2_MCS_##s##_PLCP,\\\n                    IWL_RATE_##rp##M_INDEX,          \\\n                    IWL_RATE_##rn##M_INDEX }\n\n#define IWL_DECLARE_MCS_RATE(s)                          \\\n    [IWL_RATE_MCS_##s##_INDEX] = { IWL_RATE_INVM_PLCP,          \\\n                       IWL_RATE_HT_SISO_MCS_##s##_PLCP,      \\\n                       IWL_RATE_HT_MIMO2_MCS_##s##_PLCP,  \\\n                       IWL_RATE_VHT_SISO_MCS_##s##_PLCP,  \\\n                       IWL_RATE_VHT_MIMO2_MCS_##s##_PLCP, \\\n                       IWL_RATE_INVM_INDEX,              \\\n                       IWL_RATE_INVM_INDEX }\n\n/*\n * Parameter order:\n *   rate, ht rate, prev rate, next rate\n *\n * If there isn't a valid next or previous rate then INV is used which\n * maps to IWL_RATE_INVALID\n *\n */\nstruct iwl_rs_rate_info iwl_rates[IWL_RATE_COUNT] = {\n    IWL_DECLARE_RATE_INFO(1, INV, INV, 2),   /*  1mbps */\n    IWL_DECLARE_RATE_INFO(2, INV, 1, 5),     /*  2mbps */\n    IWL_DECLARE_RATE_INFO(5, INV, 2, 11),    /*5.5mbps */\n    IWL_DECLARE_RATE_INFO(11, INV, 9, 12),   /* 11mbps */\n    IWL_DECLARE_RATE_INFO(6, 0, 5, 11),      /*  6mbps ; MCS 0 */\n    IWL_DECLARE_RATE_INFO(9, INV, 6, 11),    /*  9mbps */\n    IWL_DECLARE_RATE_INFO(12, 1, 11, 18),    /* 12mbps ; MCS 1 */\n    IWL_DECLARE_RATE_INFO(18, 2, 12, 24),    /* 18mbps ; MCS 2 */\n    IWL_DECLARE_RATE_INFO(24, 3, 18, 36),    /* 24mbps ; MCS 3 */\n    IWL_DECLARE_RATE_INFO(36, 4, 24, 48),    /* 36mbps ; MCS 4 */\n    IWL_DECLARE_RATE_INFO(48, 5, 36, 54),    /* 48mbps ; MCS 5 */\n    IWL_DECLARE_RATE_INFO(54, 6, 48, INV),   /* 54mbps ; MCS 6 */\n    IWL_DECLARE_MCS_RATE(7),                 /* MCS 7 */\n    IWL_DECLARE_MCS_RATE(8),                 /* MCS 8 */\n    IWL_DECLARE_MCS_RATE(9),                 /* MCS 9 */\n};\n\nenum rs_action {\n    RS_ACTION_STAY = 0,\n    RS_ACTION_DOWNSCALE = -1,\n    RS_ACTION_UPSCALE = 1,\n};\n\nenum rs_column_mode {\n    RS_INVALID = 0,\n    RS_LEGACY,\n    RS_SISO,\n    RS_MIMO2,\n};\n\n#define MAX_NEXT_COLUMNS 7\n#define MAX_COLUMN_CHECKS 3\n\nstruct rs_tx_column;\n\ntypedef bool (*allow_column_func_t) (struct iwm_softc *sc,\n                     struct ieee80211_node *ni,\n                     struct rs_rate *rate,\n                     const struct rs_tx_column *next_col);\n\nstruct rs_tx_column {\n    enum rs_column_mode mode;\n    u8 ant;\n    bool sgi;\n    enum rs_column next_columns[MAX_NEXT_COLUMNS];\n    allow_column_func_t checks[MAX_COLUMN_CHECKS];\n};\n\nstatic bool rs_ant_allow(struct iwm_softc *sc, struct ieee80211_node *ni,\n             struct rs_rate *rate,\n             const struct rs_tx_column *next_col)\n{\n    return ItlIwm::iwm_coex_is_ant_avail(sc, next_col->ant);\n}\n\nstatic bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwm_softc *sc, struct ieee80211_node *ni)\n{\n    return ItlIwm::iwm_coex_is_mimo_allowed(sc, ni);\n}\n\nstatic bool rs_mimo_allow(struct iwm_softc *sc, struct ieee80211_node *ni,\n              struct rs_rate *rate,\n              const struct rs_tx_column *next_col)\n{\n    ItlIwm *that = container_of(sc, ItlIwm, com);\n\n    if (!ieee80211_node_supports_ht(ni))\n        return false;\n\n//    if (sta->smps_mode == IEEE80211_SMPS_STATIC)\n//        return false;\n\n    if (that->iwm_num_of_ant(that->iwm_fw_valid_tx_ant(sc)) < 2)\n        return false;\n\n    if (!iwl_mvm_bt_coex_is_mimo_allowed(sc, ni))\n        return false;\n\n    if (sc->sc_nvm.sku_cap_mimo_disable)\n        return false;\n\n    return true;\n}\n\nstatic bool rs_siso_allow(struct iwm_softc *sc, struct ieee80211_node *ni,\n              struct rs_rate *rate,\n              const struct rs_tx_column *next_col)\n{\n    if (!ieee80211_node_supports_ht(ni))\n        return false;\n\n    return true;\n}\n\nstatic bool rs_sgi_allow(struct iwm_softc *sc, struct ieee80211_node *ni,\n             struct rs_rate *rate,\n             const struct rs_tx_column *next_col)\n{\n    if (is_ht20(rate) && (ieee80211_node_supports_ht_sgi20(ni)))\n        return true;\n    if (is_ht40(rate) && (ieee80211_node_supports_ht_sgi40(ni)))\n        return true;\n    if (is_ht80(rate) && (ieee80211_node_supports_vht_sgi80(ni)))\n        return true;\n    if (is_ht160(rate) && (ieee80211_node_supports_vht_sgi160(ni)))\n        return true;\n\n    return false;\n}\n\nstatic const struct rs_tx_column rs_tx_columns[] = {\n    [RS_COLUMN_LEGACY_ANT_A] = {\n        .mode = RS_LEGACY,\n        .ant = ANT_A,\n        .next_columns = {\n            RS_COLUMN_LEGACY_ANT_B,\n            RS_COLUMN_SISO_ANT_A,\n            RS_COLUMN_MIMO2,\n            RS_COLUMN_INVALID,\n            RS_COLUMN_INVALID,\n            RS_COLUMN_INVALID,\n            RS_COLUMN_INVALID,\n        },\n        .checks = {\n            rs_ant_allow,\n        },\n    },\n    [RS_COLUMN_LEGACY_ANT_B] = {\n        .mode = RS_LEGACY,\n        .ant = ANT_B,\n        .next_columns = {\n            RS_COLUMN_LEGACY_ANT_A,\n            RS_COLUMN_SISO_ANT_B,\n            RS_COLUMN_MIMO2,\n            RS_COLUMN_INVALID,\n            RS_COLUMN_INVALID,\n            RS_COLUMN_INVALID,\n            RS_COLUMN_INVALID,\n        },\n        .checks = {\n            rs_ant_allow,\n        },\n    },\n    [RS_COLUMN_SISO_ANT_A] = {\n        .mode = RS_SISO,\n        .ant = ANT_A,\n        .next_columns = {\n            RS_COLUMN_SISO_ANT_B,\n            RS_COLUMN_MIMO2,\n            RS_COLUMN_SISO_ANT_A_SGI,\n            RS_COLUMN_LEGACY_ANT_A,\n            RS_COLUMN_LEGACY_ANT_B,\n            RS_COLUMN_INVALID,\n            RS_COLUMN_INVALID,\n        },\n        .checks = {\n            rs_siso_allow,\n            rs_ant_allow,\n        },\n    },\n    [RS_COLUMN_SISO_ANT_B] = {\n        .mode = RS_SISO,\n        .ant = ANT_B,\n        .next_columns = {\n            RS_COLUMN_SISO_ANT_A,\n            RS_COLUMN_MIMO2,\n            RS_COLUMN_SISO_ANT_B_SGI,\n            RS_COLUMN_LEGACY_ANT_A,\n            RS_COLUMN_LEGACY_ANT_B,\n            RS_COLUMN_INVALID,\n            RS_COLUMN_INVALID,\n        },\n        .checks = {\n            rs_siso_allow,\n            rs_ant_allow,\n        },\n    },\n    [RS_COLUMN_SISO_ANT_A_SGI] = {\n        .mode = RS_SISO,\n        .ant = ANT_A,\n        .sgi = true,\n        .next_columns = {\n            RS_COLUMN_SISO_ANT_B_SGI,\n            RS_COLUMN_MIMO2_SGI,\n            RS_COLUMN_SISO_ANT_A,\n            RS_COLUMN_LEGACY_ANT_A,\n            RS_COLUMN_LEGACY_ANT_B,\n            RS_COLUMN_INVALID,\n            RS_COLUMN_INVALID,\n        },\n        .checks = {\n            rs_siso_allow,\n            rs_ant_allow,\n            rs_sgi_allow,\n        },\n    },\n    [RS_COLUMN_SISO_ANT_B_SGI] = {\n        .mode = RS_SISO,\n        .ant = ANT_B,\n        .sgi = true,\n        .next_columns = {\n            RS_COLUMN_SISO_ANT_A_SGI,\n            RS_COLUMN_MIMO2_SGI,\n            RS_COLUMN_SISO_ANT_B,\n            RS_COLUMN_LEGACY_ANT_A,\n            RS_COLUMN_LEGACY_ANT_B,\n            RS_COLUMN_INVALID,\n            RS_COLUMN_INVALID,\n        },\n        .checks = {\n            rs_siso_allow,\n            rs_ant_allow,\n            rs_sgi_allow,\n        },\n    },\n    [RS_COLUMN_MIMO2] = {\n        .mode = RS_MIMO2,\n        .ant = ANT_AB,\n        .next_columns = {\n            RS_COLUMN_SISO_ANT_A,\n            RS_COLUMN_MIMO2_SGI,\n            RS_COLUMN_LEGACY_ANT_A,\n            RS_COLUMN_LEGACY_ANT_B,\n            RS_COLUMN_INVALID,\n            RS_COLUMN_INVALID,\n            RS_COLUMN_INVALID,\n        },\n        .checks = {\n            rs_mimo_allow,\n        },\n    },\n    [RS_COLUMN_MIMO2_SGI] = {\n        .mode = RS_MIMO2,\n        .ant = ANT_AB,\n        .sgi = true,\n        .next_columns = {\n            RS_COLUMN_SISO_ANT_A_SGI,\n            RS_COLUMN_MIMO2,\n            RS_COLUMN_LEGACY_ANT_A,\n            RS_COLUMN_LEGACY_ANT_B,\n            RS_COLUMN_INVALID,\n            RS_COLUMN_INVALID,\n            RS_COLUMN_INVALID,\n        },\n        .checks = {\n            rs_mimo_allow,\n            rs_sgi_allow,\n        },\n    },\n};\n\nstatic inline u8 rs_extract_rate(u32 rate_n_flags)\n{\n    /* also works for HT because bits 7:6 are zero there */\n    return (u8)(rate_n_flags & RATE_LEGACY_RATE_MSK);\n}\n\nstatic int iwl_hwrate_to_plcp_idx(u32 rate_n_flags)\n{\n    int idx = 0;\n\n    if (rate_n_flags & RATE_MCS_HT_MSK) {\n        idx = rate_n_flags & RATE_HT_MCS_RATE_CODE_MSK;\n        idx += IWL_RATE_MCS_0_INDEX;\n\n        /* skip 9M not supported in HT*/\n        if (idx >= IWL_RATE_9M_INDEX)\n            idx += 1;\n        if ((idx >= IWL_FIRST_HT_RATE) && (idx <= IWL_LAST_HT_RATE))\n            return idx;\n    } else if (rate_n_flags & RATE_MCS_VHT_MSK ||\n           rate_n_flags & RATE_MCS_HE_MSK) {\n        idx = rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK;\n        idx += IWL_RATE_MCS_0_INDEX;\n\n        /* skip 9M not supported in VHT*/\n        if (idx >= IWL_RATE_9M_INDEX)\n            idx++;\n        if ((idx >= IWL_FIRST_VHT_RATE) && (idx <= IWL_LAST_VHT_RATE))\n            return idx;\n        if ((rate_n_flags & RATE_MCS_HE_MSK) &&\n            (idx <= IWL_LAST_HE_RATE))\n            return idx;\n    } else {\n        /* legacy rate format, search for match in table */\n\n        u8 legacy_rate = rs_extract_rate(rate_n_flags);\n        for (idx = 0; idx < ARRAY_SIZE(iwl_rates); idx++)\n            if (iwl_rates[idx].plcp == legacy_rate)\n                return idx;\n    }\n\n    return IWL_RATE_INVALID;\n}\n\nstatic void rs_rate_scale_perform(struct iwm_softc *sc,\n                  struct ieee80211_node *ni,\n                  struct iwl_lq_sta *lq_sta,\n                  int tid, bool ndp);\nstatic void rs_fill_lq_cmd(struct iwm_softc *sc,\n               struct ieee80211_node *ni,\n               struct iwl_lq_sta *lq_sta,\n               const struct rs_rate *initial_rate);\nstatic void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search);\n\n/*\n * The following tables contain the expected throughput metrics for all rates\n *\n *    1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 60 MBits\n *\n * where invalid entries are zeros.\n *\n * CCK rates are only valid in legacy table and will only be used in G\n * (2.4 GHz) band.\n */\nstatic const u16 expected_tpt_legacy[IWL_RATE_COUNT] = {\n    7, 13, 35, 58, 40, 57, 72, 98, 121, 154, 177, 186, 0, 0, 0\n};\n\n/* Expected TpT tables. 4 indexes:\n * 0 - NGI, 1 - SGI, 2 - AGG+NGI, 3 - AGG+SGI\n */\nstatic const u16 expected_tpt_siso_20MHz[4][IWL_RATE_COUNT] = {\n    {0, 0, 0, 0, 42, 0,  76, 102, 124, 159, 183, 193, 202, 216, 0},\n    {0, 0, 0, 0, 46, 0,  82, 110, 132, 168, 192, 202, 210, 225, 0},\n    {0, 0, 0, 0, 49, 0,  97, 145, 192, 285, 375, 420, 464, 551, 0},\n    {0, 0, 0, 0, 54, 0, 108, 160, 213, 315, 415, 465, 513, 608, 0},\n};\n\nstatic const u16 expected_tpt_siso_40MHz[4][IWL_RATE_COUNT] = {\n    {0, 0, 0, 0,  77, 0, 127, 160, 184, 220, 242, 250,  257,  269,  275},\n    {0, 0, 0, 0,  83, 0, 135, 169, 193, 229, 250, 257,  264,  275,  280},\n    {0, 0, 0, 0, 101, 0, 199, 295, 389, 570, 744, 828,  911, 1070, 1173},\n    {0, 0, 0, 0, 112, 0, 220, 326, 429, 629, 819, 912, 1000, 1173, 1284},\n};\n\nstatic const u16 expected_tpt_siso_80MHz[4][IWL_RATE_COUNT] = {\n    {0, 0, 0, 0, 130, 0, 191, 223, 244,  273,  288,  294,  298,  305,  308},\n    {0, 0, 0, 0, 138, 0, 200, 231, 251,  279,  293,  298,  302,  308,  312},\n    {0, 0, 0, 0, 217, 0, 429, 634, 834, 1220, 1585, 1760, 1931, 2258, 2466},\n    {0, 0, 0, 0, 241, 0, 475, 701, 921, 1343, 1741, 1931, 2117, 2468, 2691},\n};\n\nstatic const u16 expected_tpt_siso_160MHz[4][IWL_RATE_COUNT] = {\n    {0, 0, 0, 0, 191, 0, 244, 288,  298,  308,  313,  318,  323,  328,  330},\n    {0, 0, 0, 0, 200, 0, 251, 293,  302,  312,  317,  322,  327,  332,  334},\n    {0, 0, 0, 0, 439, 0, 875, 1307, 1736, 2584, 3419, 3831, 4240, 5049, 5581},\n    {0, 0, 0, 0, 488, 0, 972, 1451, 1925, 2864, 3785, 4240, 4691, 5581, 6165},\n};\n\nstatic const u16 expected_tpt_mimo2_20MHz[4][IWL_RATE_COUNT] = {\n    {0, 0, 0, 0,  74, 0, 123, 155, 179, 213, 235, 243, 250,  261, 0},\n    {0, 0, 0, 0,  81, 0, 131, 164, 187, 221, 242, 250, 256,  267, 0},\n    {0, 0, 0, 0,  98, 0, 193, 286, 375, 550, 718, 799, 878, 1032, 0},\n    {0, 0, 0, 0, 109, 0, 214, 316, 414, 607, 790, 879, 965, 1132, 0},\n};\n\nstatic const u16 expected_tpt_mimo2_40MHz[4][IWL_RATE_COUNT] = {\n    {0, 0, 0, 0, 123, 0, 182, 214, 235,  264,  279,  285,  289,  296,  300},\n    {0, 0, 0, 0, 131, 0, 191, 222, 242,  270,  284,  289,  293,  300,  303},\n    {0, 0, 0, 0, 200, 0, 390, 571, 741, 1067, 1365, 1505, 1640, 1894, 2053},\n    {0, 0, 0, 0, 221, 0, 430, 630, 816, 1169, 1490, 1641, 1784, 2053, 2221},\n};\n\nstatic const u16 expected_tpt_mimo2_80MHz[4][IWL_RATE_COUNT] = {\n    {0, 0, 0, 0, 182, 0, 240,  264,  278,  299,  308,  311,  313,  317,  319},\n    {0, 0, 0, 0, 190, 0, 247,  269,  282,  302,  310,  313,  315,  319,  320},\n    {0, 0, 0, 0, 428, 0, 833, 1215, 1577, 2254, 2863, 3147, 3418, 3913, 4219},\n    {0, 0, 0, 0, 474, 0, 920, 1338, 1732, 2464, 3116, 3418, 3705, 4225, 4545},\n};\n\nstatic const u16 expected_tpt_mimo2_160MHz[4][IWL_RATE_COUNT] = {\n    {0, 0, 0, 0, 240, 0, 278,  308,  313,  319,  322,  324,  328,  330,   334},\n    {0, 0, 0, 0, 247, 0, 282,  310,  315,  320,  323,  325,  329,  332,   338},\n    {0, 0, 0, 0, 875, 0, 1735, 2582, 3414, 5043, 6619, 7389, 8147, 9629,  10592},\n    {0, 0, 0, 0, 971, 0, 1925, 2861, 3779, 5574, 7304, 8147, 8976, 10592, 11640},\n};\n\n/* mbps, mcs */\nstatic const struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = {\n    {  \"1\", \"BPSK DSSS\"},\n    {  \"2\", \"QPSK DSSS\"},\n    {\"5.5\", \"BPSK CCK\"},\n    { \"11\", \"QPSK CCK\"},\n    {  \"6\", \"BPSK 1/2\"},\n    {  \"9\", \"BPSK 1/2\"},\n    { \"12\", \"QPSK 1/2\"},\n    { \"18\", \"QPSK 3/4\"},\n    { \"24\", \"16QAM 1/2\"},\n    { \"36\", \"16QAM 3/4\"},\n    { \"48\", \"64QAM 2/3\"},\n    { \"54\", \"64QAM 3/4\"},\n    { \"60\", \"64QAM 5/6\"},\n};\n\n#define MCS_INDEX_PER_STREAM    (8)\n\nstatic const char *rs_pretty_ant(u8 ant)\n{\n    static const char * const ant_name[] = {\n        [ANT_NONE] = \"None\",\n        [ANT_A]    = \"A\",\n        [ANT_B]    = \"B\",\n        [ANT_AB]   = \"AB\",\n        [ANT_C]    = \"C\",\n        [ANT_AC]   = \"AC\",\n        [ANT_BC]   = \"BC\",\n        [ANT_ABC]  = \"ABC\",\n    };\n\n    if (ant > ANT_ABC)\n        return \"UNKNOWN\";\n\n    return ant_name[ant];\n}\n\nstatic const char *rs_pretty_lq_type(enum iwl_table_type type)\n{\n    static const char * const lq_types[] = {\n        [LQ_NONE] = \"NONE\",\n        [LQ_LEGACY_A] = \"LEGACY_A\",\n        [LQ_LEGACY_G] = \"LEGACY_G\",\n        [LQ_HT_SISO] = \"HT SISO\",\n        [LQ_HT_MIMO2] = \"HT MIMO\",\n        [LQ_VHT_SISO] = \"VHT SISO\",\n        [LQ_VHT_MIMO2] = \"VHT MIMO\",\n        [LQ_HE_SISO] = \"HE SISO\",\n        [LQ_HE_MIMO2] = \"HE MIMO\",\n    };\n\n    if (type < LQ_NONE || type >= LQ_MAX)\n        return \"UNKNOWN\";\n\n    return lq_types[type];\n}\n\nstatic char *rs_pretty_rate(const struct rs_rate *rate)\n{\n    static char buf[40];\n    static const char * const legacy_rates[] = {\n        [IWL_RATE_1M_INDEX] = \"1M\",\n        [IWL_RATE_2M_INDEX] = \"2M\",\n        [IWL_RATE_5M_INDEX] = \"5.5M\",\n        [IWL_RATE_11M_INDEX] = \"11M\",\n        [IWL_RATE_6M_INDEX] = \"6M\",\n        [IWL_RATE_9M_INDEX] = \"9M\",\n        [IWL_RATE_12M_INDEX] = \"12M\",\n        [IWL_RATE_18M_INDEX] = \"18M\",\n        [IWL_RATE_24M_INDEX] = \"24M\",\n        [IWL_RATE_36M_INDEX] = \"36M\",\n        [IWL_RATE_48M_INDEX] = \"48M\",\n        [IWL_RATE_54M_INDEX] = \"54M\",\n    };\n    static const char *const ht_vht_rates[] = {\n        [IWL_RATE_MCS_0_INDEX] = \"MCS0\",\n        [IWL_RATE_MCS_1_INDEX] = \"MCS1\",\n        [IWL_RATE_MCS_2_INDEX] = \"MCS2\",\n        [IWL_RATE_MCS_3_INDEX] = \"MCS3\",\n        [IWL_RATE_MCS_4_INDEX] = \"MCS4\",\n        [IWL_RATE_MCS_5_INDEX] = \"MCS5\",\n        [IWL_RATE_MCS_6_INDEX] = \"MCS6\",\n        [IWL_RATE_MCS_7_INDEX] = \"MCS7\",\n        [IWL_RATE_MCS_8_INDEX] = \"MCS8\",\n        [IWL_RATE_MCS_9_INDEX] = \"MCS9\",\n    };\n    const char *rate_str;\n\n    if (is_type_legacy(rate->type) && (rate->index <= IWL_RATE_54M_INDEX))\n        rate_str = legacy_rates[rate->index];\n    else if ((is_type_ht(rate->type) || is_type_vht(rate->type)) &&\n         (rate->index >= IWL_RATE_MCS_0_INDEX) &&\n         (rate->index <= IWL_RATE_MCS_9_INDEX))\n        rate_str = ht_vht_rates[rate->index];\n    else\n        rate_str = NULL;\n\n    snprintf(buf, sizeof(buf), \"(%s|%s|%s)\", rs_pretty_lq_type(rate->type),\n        rs_pretty_ant(rate->ant), rate_str ?: \"BAD_RATE\");\n    return buf;\n}\n\nstatic inline void rs_dump_rate(struct iwm_softc *sc, const struct rs_rate *rate,\n                const char *prefix)\n{\n    IWL_DEBUG_RATE(sc,\n               \"%s: %s BW: %d SGI: %d LDPC: %d STBC: %d\\n\",\n               prefix, rs_pretty_rate(rate), rate->bw,\n               rate->sgi, rate->ldpc, rate->stbc);\n}\n\nstatic void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window)\n{\n    window->data = 0;\n    window->success_counter = 0;\n    window->success_ratio = IWL_INVALID_VALUE;\n    window->counter = 0;\n    window->average_tpt = IWL_INVALID_VALUE;\n}\n\nstatic void rs_rate_scale_clear_tbl_windows(struct iwm_softc *sc,\n                        struct iwl_scale_tbl_info *tbl)\n{\n    int i;\n\n    IWL_DEBUG_RATE(sc, \"Clearing up window stats\\n\");\n    for (i = 0; i < IWL_RATE_COUNT; i++)\n        rs_rate_scale_clear_window(&tbl->win[i]);\n\n    for (i = 0; i < ARRAY_SIZE(tbl->tpc_win); i++)\n        rs_rate_scale_clear_window(&tbl->tpc_win[i]);\n}\n\nstatic inline u8 rs_is_valid_ant(u8 valid_antenna, u8 ant_type)\n{\n    return (ant_type & valid_antenna) == ant_type;\n}\n\nextern int ieee80211_can_use_ampdu(struct ieee80211com *,\n                                      struct ieee80211_node *);\n\nstatic int rs_tl_turn_on_agg_for_tid(struct iwm_softc *sc,\n                     struct iwl_lq_sta *lq_data, u8 tid,\n                     struct ieee80211_node *ni)\n{\n    IWL_DEBUG_RATE(sc, \"Starting Tx agg: STA: %s tid: %d\\n\",\n             ether_sprintf(ni->ni_macaddr), tid);\n\n    /* start BA session until the peer sends del BA */\n    if (!ieee80211_can_use_ampdu(&sc->sc_ic, ni))\n        return -1;\n    ieee80211_node_trigger_addba_req(ni, tid);\n    return 0;\n}\n\nstatic void rs_tl_turn_on_agg(struct iwm_softc *sc,\n                  u8 tid, struct iwl_lq_sta *lq_sta,\n                  struct ieee80211_node *ni)\n{\n    struct iwm_tx_ba *tid_data;\n    struct ieee80211_tx_ba *tx_ba;\n    struct ieee80211com *ic = &sc->sc_ic;\n    \n    if ((ic->ic_caps & IEEE80211_C_TX_AMPDU_SETUP_IN_RS) == 0)\n        return;\n\n    /*\n     * In AP mode, tid can be equal to IWL_MAX_TID_COUNT\n     * when the frame is not QoS\n     */\n    if (WARN_ON_ONCE(tid > IWL_MAX_TID_COUNT)) {\n        IWL_ERR(mvm, \"tid exceeds max TID count: %d/%d\\n\",\n            tid, IWL_MAX_TID_COUNT);\n        return;\n    } else if (tid == IWL_MAX_TID_COUNT) {\n        return;\n    }\n\n    tx_ba = &ni->ni_tx_ba[tid];\n    tid_data = &sc->sc_tx_ba[tid];\n    if (sc->sc_ic.ic_state >= IEEE80211_S_RUN &&\n        tx_ba->ba_state == IEEE80211_BA_INIT &&\n        (lq_sta->tx_agg_tid_en & BIT(tid)) &&\n        tid_data->tx_count_last >= IWL_MVM_RS_AGG_START_THRESHOLD) {\n        IWL_DEBUG_RATE(\"RS: try to aggregate tid %d\\n\", tid);\n        rs_tl_turn_on_agg_for_tid(sc, lq_sta, tid, ni);\n    }\n}\n\nstatic inline int get_num_of_ant_from_rate(u32 rate_n_flags)\n{\n    return !!(rate_n_flags & RATE_MCS_ANT_A_MSK) +\n           !!(rate_n_flags & RATE_MCS_ANT_B_MSK) +\n           !!(rate_n_flags & RATE_MCS_ANT_C_MSK);\n}\n\n/*\n * Static function to get the expected throughput from an iwl_scale_tbl_info\n * that wraps a NULL pointer check\n */\nstatic s32 get_expected_tpt(struct iwl_scale_tbl_info *tbl, int rs_index)\n{\n    if (tbl->expected_tpt)\n        return tbl->expected_tpt[rs_index];\n    return 0;\n}\n\n/*\n * rs_collect_tx_data - Update the success/failure sliding window\n *\n * We keep a sliding window of the last 62 packets transmitted\n * at this rate.  window->data contains the bitmask of successful\n * packets.\n */\nstatic int _rs_collect_tx_data(struct iwm_softc *sc,\n                   struct iwl_scale_tbl_info *tbl,\n                   int scale_index, int attempts, int successes,\n                   struct iwl_rate_scale_data *window)\n{\n    static const u64 mask = (((u64)1) << (IWL_RATE_MAX_WINDOW - 1));\n    s32 fail_count, tpt;\n\n    /* Get expected throughput */\n    tpt = get_expected_tpt(tbl, scale_index);\n\n    /*\n     * Keep track of only the latest 62 tx frame attempts in this rate's\n     * history window; anything older isn't really relevant any more.\n     * If we have filled up the sliding window, drop the oldest attempt;\n     * if the oldest attempt (highest bit in bitmap) shows \"success\",\n     * subtract \"1\" from the success counter (this is the main reason\n     * we keep these bitmaps!).\n     */\n    while (attempts > 0) {\n        if (window->counter >= IWL_RATE_MAX_WINDOW) {\n            /* remove earliest */\n            window->counter = IWL_RATE_MAX_WINDOW - 1;\n\n            if (window->data & mask) {\n                window->data &= ~mask;\n                window->success_counter--;\n            }\n        }\n\n        /* Increment frames-attempted counter */\n        window->counter++;\n\n        /* Shift bitmap by one frame to throw away oldest history */\n        window->data <<= 1;\n\n        /* Mark the most recent #successes attempts as successful */\n        if (successes > 0) {\n            window->success_counter++;\n            window->data |= 0x1;\n            successes--;\n        }\n\n        attempts--;\n    }\n\n    /* Calculate current success ratio, avoid divide-by-0! */\n    if (window->counter > 0)\n        window->success_ratio = 128 * (100 * window->success_counter)\n                    / window->counter;\n    else\n        window->success_ratio = IWL_INVALID_VALUE;\n\n    fail_count = window->counter - window->success_counter;\n\n    /* Calculate average throughput, if we have enough history. */\n    if ((fail_count >= IWL_MVM_RS_RATE_MIN_FAILURE_TH) ||\n        (window->success_counter >= IWL_MVM_RS_RATE_MIN_SUCCESS_TH))\n        window->average_tpt = (window->success_ratio * tpt + 64) / 128;\n    else\n        window->average_tpt = IWL_INVALID_VALUE;\n\n    return 0;\n}\n\nstatic int rs_collect_tpc_data(struct iwm_softc *sc,\n                   struct iwl_lq_sta *lq_sta,\n                   struct iwl_scale_tbl_info *tbl,\n                   int scale_index, int attempts, int successes,\n                   u8 reduced_txp)\n{\n    struct iwl_rate_scale_data *window = NULL;\n\n    if (WARN_ON_ONCE(reduced_txp > TPC_MAX_REDUCTION))\n        return -EINVAL;\n\n    window = &tbl->tpc_win[reduced_txp];\n    return  _rs_collect_tx_data(sc, tbl, scale_index, attempts, successes,\n                    window);\n}\n\nstatic void rs_update_tid_tpt_stats(struct iwm_softc *sc,\n                    u8 tid, int successes)\n{\n    if (tid >= IWL_MAX_TID_COUNT)\n        return;\n\n    struct iwm_tx_ba *tid_data = &sc->sc_tx_ba[tid];\n\n    /*\n     * Measure if there're enough successful transmits per second.\n     * These statistics are used only to decide if we can start a\n     * BA session, so it should be updated only when A-MPDU is\n     * off.\n     */\n    if (tid_data->wn != NULL)\n        return;\n\n    if (time_is_before_jiffies(tid_data->tpt_meas_start + hz) ||\n        (tid_data->tx_count >= IWL_MVM_RS_AGG_START_THRESHOLD)) {\n        tid_data->tx_count_last = tid_data->tx_count;\n        tid_data->tx_count = 0;\n        tid_data->tpt_meas_start = ticks;\n    } else {\n        tid_data->tx_count += successes;\n    }\n}\n\nstatic int rs_collect_tlc_data(struct iwm_softc *sc,\n                   u8 tid,\n                   struct iwl_scale_tbl_info *tbl,\n                   int scale_index, int attempts, int successes)\n{\n    struct iwl_rate_scale_data *window = NULL;\n\n    if (scale_index < 0 || scale_index >= IWL_RATE_COUNT)\n        return -EINVAL;\n\n    if (tbl->column != RS_COLUMN_INVALID) {\n        struct lq_sta_pers *pers = &sc->lq_sta.rs_drv.pers;\n\n        pers->tx_stats[tbl->column][scale_index].total += attempts;\n        pers->tx_stats[tbl->column][scale_index].success += successes;\n    }\n\n    rs_update_tid_tpt_stats(sc, tid, successes);\n\n    /* Select window for current tx bit rate */\n    window = &(tbl->win[scale_index]);\n    return _rs_collect_tx_data(sc, tbl, scale_index, attempts, successes,\n                   window);\n}\n\n/* Convert rs_rate object into ucode rate bitmask */\nstatic u32 ucode_rate_from_rs_rate(struct iwm_softc *sc,\n                  struct rs_rate *rate)\n{\n    u32 ucode_rate = 0;\n    int index = rate->index;\n\n    ucode_rate |= ((rate->ant << RATE_MCS_ANT_POS) &\n             RATE_MCS_ANT_ABC_MSK);\n\n    if (is_legacy(rate)) {\n        ucode_rate |= iwl_rates[index].plcp;\n        if (index >= IWL_FIRST_CCK_RATE && index <= IWL_LAST_CCK_RATE)\n            ucode_rate |= RATE_MCS_CCK_MSK;\n        return ucode_rate;\n    }\n\n    /* set RTS protection for all non legacy rates\n     * This helps with congested environments reducing the conflict cost to\n     * RTS retries only, instead of the entire BA packet.\n     */\n    ucode_rate |= RATE_MCS_RTS_REQUIRED_MSK;\n\n    if (is_ht(rate)) {\n        if (index < IWL_FIRST_HT_RATE || index > IWL_LAST_HT_RATE) {\n            IWL_ERR(mvm, \"Invalid HT rate index %d\\n\", index);\n            index = IWL_LAST_HT_RATE;\n        }\n        ucode_rate |= RATE_MCS_HT_MSK;\n\n        if (is_ht_siso(rate))\n            ucode_rate |= iwl_rates[index].plcp_ht_siso;\n        else if (is_ht_mimo2(rate))\n            ucode_rate |= iwl_rates[index].plcp_ht_mimo2;\n        else\n            WARN_ON_ONCE(1);\n    } else if (is_vht(rate)) {\n        if (index < IWL_FIRST_VHT_RATE || index > IWL_LAST_VHT_RATE) {\n            IWL_ERR(mvm, \"Invalid VHT rate index %d\\n\", index);\n            index = IWL_LAST_VHT_RATE;\n        }\n        ucode_rate |= RATE_MCS_VHT_MSK;\n        if (is_vht_siso(rate))\n            ucode_rate |= iwl_rates[index].plcp_vht_siso;\n        else if (is_vht_mimo2(rate))\n            ucode_rate |= iwl_rates[index].plcp_vht_mimo2;\n        else\n            WARN_ON_ONCE(1);\n\n    } else {\n        IWL_ERR(mvm, \"Invalid rate->type %d\\n\", rate->type);\n    }\n\n    if (is_siso(rate) && rate->stbc) {\n        /* To enable STBC we need to set both a flag and ANT_AB */\n        ucode_rate |= RATE_MCS_ANT_AB_MSK;\n        ucode_rate |= RATE_MCS_STBC_MSK;\n    }\n\n    ucode_rate |= rate->bw;\n    if (rate->sgi)\n        ucode_rate |= RATE_MCS_SGI_MSK;\n    if (rate->ldpc)\n        ucode_rate |= RATE_MCS_LDPC_MSK;\n\n    return ucode_rate;\n}\n\n/* Convert a ucode rate into an rs_rate object */\nstatic int rs_rate_from_ucode_rate(const u32 ucode_rate,\n                   enum nl80211_band band,\n                   struct rs_rate *rate)\n{\n    u32 ant_msk = ucode_rate & RATE_MCS_ANT_ABC_MSK;\n    u8 num_of_ant = get_num_of_ant_from_rate(ucode_rate);\n    u8 nss;\n\n    memset(rate, 0, sizeof(*rate));\n    rate->index = iwl_hwrate_to_plcp_idx(ucode_rate);\n\n    if (rate->index == IWL_RATE_INVALID)\n        return -EINVAL;\n\n    rate->ant = (ant_msk >> RATE_MCS_ANT_POS);\n\n    /* Legacy */\n    if (!(ucode_rate & RATE_MCS_HT_MSK) &&\n        !(ucode_rate & RATE_MCS_VHT_MSK) &&\n        !(ucode_rate & RATE_MCS_HE_MSK)) {\n        if (num_of_ant == 1) {\n            if (band == NL80211_BAND_5GHZ)\n                rate->type = LQ_LEGACY_A;\n            else\n                rate->type = LQ_LEGACY_G;\n        }\n\n        return 0;\n    }\n\n    /* HT, VHT or HE */\n    if (ucode_rate & RATE_MCS_SGI_MSK)\n        rate->sgi = true;\n    if (ucode_rate & RATE_MCS_LDPC_MSK)\n        rate->ldpc = true;\n    if (ucode_rate & RATE_MCS_STBC_MSK)\n        rate->stbc = true;\n    if (ucode_rate & RATE_MCS_BF_MSK)\n        rate->bfer = true;\n\n    rate->bw = ucode_rate & RATE_MCS_CHAN_WIDTH_MSK;\n\n    if (ucode_rate & RATE_MCS_HT_MSK) {\n        nss = ((ucode_rate & RATE_HT_MCS_NSS_MSK) >>\n               RATE_HT_MCS_NSS_POS) + 1;\n\n        if (nss == 1) {\n            rate->type = LQ_HT_SISO;\n            WARN_ON(!rate->stbc && !rate->bfer && num_of_ant != 1,\n                  \"stbc %d bfer %d\",\n                  rate->stbc, rate->bfer);\n        } else if (nss == 2) {\n            rate->type = LQ_HT_MIMO2;\n            WARN_ON_ONCE(num_of_ant != 2);\n        } else {\n            WARN_ON_ONCE(1);\n        }\n    } else if (ucode_rate & RATE_MCS_VHT_MSK) {\n        nss = ((ucode_rate & RATE_VHT_MCS_NSS_MSK) >>\n               RATE_VHT_MCS_NSS_POS) + 1;\n\n        if (nss == 1) {\n            rate->type = LQ_VHT_SISO;\n            WARN_ON(!rate->stbc && !rate->bfer && num_of_ant != 1,\n                  \"stbc %d bfer %d\",\n                  rate->stbc, rate->bfer);\n        } else if (nss == 2) {\n            rate->type = LQ_VHT_MIMO2;\n            WARN_ON_ONCE(num_of_ant != 2);\n        } else {\n            WARN_ON_ONCE(1);\n        }\n    } else if (ucode_rate & RATE_MCS_HE_MSK) {\n        nss = ((ucode_rate & RATE_VHT_MCS_NSS_MSK) >>\n              RATE_VHT_MCS_NSS_POS) + 1;\n\n        if (nss == 1) {\n            rate->type = LQ_HE_SISO;\n            WARN_ON(!rate->stbc && !rate->bfer && num_of_ant != 1,\n                  \"stbc %d bfer %d\", rate->stbc, rate->bfer);\n        } else if (nss == 2) {\n            rate->type = LQ_HE_MIMO2;\n            WARN_ON_ONCE(num_of_ant != 2);\n        } else {\n            WARN_ON_ONCE(1);\n        }\n    }\n\n    WARN_ON_ONCE(rate->bw == RATE_MCS_CHAN_WIDTH_80 &&\n             !is_he(rate) && !is_vht(rate));\n\n    return 0;\n}\n\n/* switch to another antenna/antennas and return 1 */\n/* if no other valid antenna found, return 0 */\nstatic int rs_toggle_antenna(u32 valid_ant, struct rs_rate *rate)\n{\n    u8 new_ant_type;\n\n    if (!rate->ant || WARN_ON_ONCE(rate->ant & ANT_C))\n        return 0;\n\n    if (!rs_is_valid_ant(valid_ant, rate->ant))\n        return 0;\n\n    new_ant_type = ant_toggle_lookup[rate->ant];\n\n    while ((new_ant_type != rate->ant) &&\n           !rs_is_valid_ant(valid_ant, new_ant_type))\n        new_ant_type = ant_toggle_lookup[new_ant_type];\n\n    if (new_ant_type == rate->ant)\n        return 0;\n\n    rate->ant = new_ant_type;\n\n    return 1;\n}\n\nstatic u16 rs_get_supported_rates(struct iwl_lq_sta *lq_sta,\n                  struct rs_rate *rate)\n{\n    if (is_legacy(rate))\n        return lq_sta->active_legacy_rate;\n    else if (is_siso(rate))\n        return lq_sta->active_siso_rate;\n    else if (is_mimo2(rate))\n        return lq_sta->active_mimo2_rate;\n\n    WARN_ON_ONCE(1);\n    return 0;\n}\n\nstatic u16 rs_get_adjacent_rate(struct iwm_softc *sc, u8 index, u16 rate_mask,\n                int rate_type)\n{\n    u8 high = IWL_RATE_INVALID;\n    u8 low = IWL_RATE_INVALID;\n\n    /* 802.11A or ht walks to the next literal adjacent rate in\n     * the rate table */\n    if (is_type_a_band(rate_type) || !is_type_legacy(rate_type)) {\n        int i;\n        u32 mask;\n\n        /* Find the previous rate that is in the rate mask */\n        i = index - 1;\n        if (i >= 0)\n            mask = BIT(i);\n        for (; i >= 0; i--, mask >>= 1) {\n            if (rate_mask & mask) {\n                low = i;\n                break;\n            }\n        }\n\n        /* Find the next rate that is in the rate mask */\n        i = index + 1;\n        for (mask = (1 << i); i < IWL_RATE_COUNT; i++, mask <<= 1) {\n            if (rate_mask & mask) {\n                high = i;\n                break;\n            }\n        }\n\n        return (high << 8) | low;\n    }\n\n    low = index;\n    while (low != IWL_RATE_INVALID) {\n        low = iwl_rates[low].prev_rs;\n        if (low == IWL_RATE_INVALID)\n            break;\n        if (rate_mask & (1 << low))\n            break;\n    }\n\n    high = index;\n    while (high != IWL_RATE_INVALID) {\n        high = iwl_rates[high].next_rs;\n        if (high == IWL_RATE_INVALID)\n            break;\n        if (rate_mask & (1 << high))\n            break;\n    }\n\n    return (high << 8) | low;\n}\n\nstatic inline bool rs_rate_supported(struct iwl_lq_sta *lq_sta,\n                     struct rs_rate *rate)\n{\n    return BIT(rate->index) & rs_get_supported_rates(lq_sta, rate);\n}\n\n/* Get the next supported lower rate in the current column.\n * Return true if bottom rate in the current column was reached\n */\nstatic bool rs_get_lower_rate_in_column(struct iwl_lq_sta *lq_sta,\n                    struct rs_rate *rate)\n{\n    u8 low;\n    u16 high_low;\n    u16 rate_mask;\n    struct iwm_softc *sc = lq_sta->pers.drv;\n\n    rate_mask = rs_get_supported_rates(lq_sta, rate);\n    high_low = rs_get_adjacent_rate(sc, rate->index, rate_mask,\n                    rate->type);\n    low = high_low & 0xff;\n\n    /* Bottom rate of column reached */\n    if (low == IWL_RATE_INVALID)\n        return true;\n\n    rate->index = low;\n    return false;\n}\n\n/* Get the next rate to use following a column downgrade */\nstatic void rs_get_lower_rate_down_column(struct iwl_lq_sta *lq_sta,\n                      struct rs_rate *rate)\n{\n    struct iwm_softc *sc = lq_sta->pers.drv;\n    ItlIwm *that = container_of(sc, ItlIwm, com);\n\n    if (is_legacy(rate)) {\n        /* No column to downgrade from Legacy */\n        return;\n    } else if (is_siso(rate)) {\n        /* Downgrade to Legacy if we were in SISO */\n        if (lq_sta->band == NL80211_BAND_5GHZ)\n            rate->type = LQ_LEGACY_A;\n        else\n            rate->type = LQ_LEGACY_G;\n\n        rate->bw = RATE_MCS_CHAN_WIDTH_20;\n\n        if (WARN_ON_ONCE(rate->index < IWL_RATE_MCS_0_INDEX))\n            rate->index = rs_ht_to_legacy[IWL_RATE_MCS_0_INDEX];\n        else if (WARN_ON_ONCE(rate->index > IWL_RATE_MCS_9_INDEX))\n            rate->index = rs_ht_to_legacy[IWL_RATE_MCS_9_INDEX];\n        else\n            rate->index = rs_ht_to_legacy[rate->index];\n\n        rate->ldpc = false;\n    } else {\n        /* Downgrade to SISO with same MCS if in MIMO  */\n        rate->type = is_vht_mimo2(rate) ?\n            LQ_VHT_SISO : LQ_HT_SISO;\n    }\n\n    if (that->iwm_num_of_ant(rate->ant) > 1)\n        rate->ant = first_antenna(that->iwm_fw_valid_tx_ant(sc));\n\n    /* Relevant in both switching to SISO or Legacy */\n    rate->sgi = false;\n\n    if (!rs_rate_supported(lq_sta, rate))\n        rs_get_lower_rate_in_column(lq_sta, rate);\n}\n\n/* Check if both rates share the same column */\nstatic inline bool rs_rate_column_match(struct rs_rate *a,\n                    struct rs_rate *b)\n{\n    bool ant_match;\n\n    if (a->stbc || a->bfer)\n        ant_match = (b->ant == ANT_A || b->ant == ANT_B);\n    else\n        ant_match = (a->ant == b->ant);\n\n    return (a->type == b->type) && (a->bw == b->bw) && (a->sgi == b->sgi)\n        && ant_match;\n}\n\nstatic inline enum rs_column rs_get_column_from_rate(struct rs_rate *rate)\n{\n    if (is_legacy(rate)) {\n        if (rate->ant == ANT_A)\n            return RS_COLUMN_LEGACY_ANT_A;\n\n        if (rate->ant == ANT_B)\n            return RS_COLUMN_LEGACY_ANT_B;\n\n        goto err;\n    }\n\n    if (is_siso(rate)) {\n        if (rate->ant == ANT_A || rate->stbc || rate->bfer)\n            return rate->sgi ? RS_COLUMN_SISO_ANT_A_SGI :\n                RS_COLUMN_SISO_ANT_A;\n\n        if (rate->ant == ANT_B)\n            return rate->sgi ? RS_COLUMN_SISO_ANT_B_SGI :\n                RS_COLUMN_SISO_ANT_B;\n\n        goto err;\n    }\n\n    if (is_mimo(rate))\n        return rate->sgi ? RS_COLUMN_MIMO2_SGI : RS_COLUMN_MIMO2;\n\nerr:\n    return RS_COLUMN_INVALID;\n}\n\n/*\n * mac80211 sends us Tx status\n */\nvoid rs_drv_mac80211_tx_status(struct iwm_softc *sc,\n                                      struct ieee80211_node *sta,\n                      struct ieee80211_tx_info *info, int tid, uint16_t fc, int ssn)\n{\n    if (!ieee80211_is_data(fc) ||\n        info->flags & IEEE80211_TX_CTL_NO_ACK)\n        return;\n\n    iwl_mvm_rs_tx_status(sc, sta, tid, info,\n                 false);\n}\n\n/*\n * Begin a period of staying with a selected modulation mode.\n * Set \"stay_in_tbl\" flag to prevent any mode switches.\n * Set frame tx success limits according to legacy vs. high-throughput,\n * and reset overall (spanning all rates) tx success history statistics.\n * These control how long we stay using same modulation mode before\n * searching for a new mode.\n */\nstatic void rs_set_stay_in_table(struct iwm_softc *mvm, u8 is_legacy,\n                 struct iwl_lq_sta *lq_sta)\n{\n    IWL_DEBUG_RATE(mvm, \"Moving to RS_STATE_STAY_IN_COLUMN\\n\");\n    lq_sta->rs_state = RS_STATE_STAY_IN_COLUMN;\n    if (is_legacy) {\n        lq_sta->table_count_limit = IWL_MVM_RS_LEGACY_TABLE_COUNT;\n        lq_sta->max_failure_limit = IWL_MVM_RS_LEGACY_FAILURE_LIMIT;\n        lq_sta->max_success_limit = IWL_MVM_RS_LEGACY_SUCCESS_LIMIT;\n    } else {\n        lq_sta->table_count_limit = IWL_MVM_RS_NON_LEGACY_TABLE_COUNT;\n        lq_sta->max_failure_limit = IWL_MVM_RS_NON_LEGACY_FAILURE_LIMIT;\n        lq_sta->max_success_limit = IWL_MVM_RS_NON_LEGACY_SUCCESS_LIMIT;\n    }\n    lq_sta->table_count = 0;\n    lq_sta->total_failed = 0;\n    lq_sta->total_success = 0;\n    lq_sta->flush_timer = ticks;\n    lq_sta->visited_columns = 0;\n}\n\nstatic inline int rs_get_max_rate_from_mask(unsigned long rate_mask)\n{\n    if (rate_mask)\n        return find_last_bit(&rate_mask, BITS_PER_LONG);\n    return IWL_RATE_INVALID;\n}\n\nstatic int rs_get_max_allowed_rate(struct iwl_lq_sta *lq_sta,\n                   const struct rs_tx_column *column)\n{\n    switch (column->mode) {\n    case RS_LEGACY:\n        return lq_sta->max_legacy_rate_idx;\n    case RS_SISO:\n        return lq_sta->max_siso_rate_idx;\n    case RS_MIMO2:\n        return lq_sta->max_mimo2_rate_idx;\n    default:\n        WARN_ON_ONCE(1);\n    }\n\n    return lq_sta->max_legacy_rate_idx;\n}\n\nstatic const u16 *rs_get_expected_tpt_table(struct iwl_lq_sta *lq_sta,\n                        const struct rs_tx_column *column,\n                        u32 bw)\n{\n    /* Used to choose among HT tables */\n    const u16 (*ht_tbl_pointer)[IWL_RATE_COUNT];\n\n    if (WARN_ON_ONCE(column->mode != RS_LEGACY &&\n             column->mode != RS_SISO &&\n             column->mode != RS_MIMO2))\n        return expected_tpt_legacy;\n\n    /* Legacy rates have only one table */\n    if (column->mode == RS_LEGACY)\n        return expected_tpt_legacy;\n\n    ht_tbl_pointer = expected_tpt_mimo2_20MHz;\n    /* Choose among many HT tables depending on number of streams\n     * (SISO/MIMO2), channel width (20/40/80), SGI, and aggregation\n     * status */\n    if (column->mode == RS_SISO) {\n        switch (bw) {\n        case RATE_MCS_CHAN_WIDTH_20:\n            ht_tbl_pointer = expected_tpt_siso_20MHz;\n            break;\n        case RATE_MCS_CHAN_WIDTH_40:\n            ht_tbl_pointer = expected_tpt_siso_40MHz;\n            break;\n        case RATE_MCS_CHAN_WIDTH_80:\n            ht_tbl_pointer = expected_tpt_siso_80MHz;\n            break;\n        case RATE_MCS_CHAN_WIDTH_160:\n            ht_tbl_pointer = expected_tpt_siso_160MHz;\n            break;\n        default:\n            WARN_ON_ONCE(1);\n        }\n    } else if (column->mode == RS_MIMO2) {\n        switch (bw) {\n        case RATE_MCS_CHAN_WIDTH_20:\n            ht_tbl_pointer = expected_tpt_mimo2_20MHz;\n            break;\n        case RATE_MCS_CHAN_WIDTH_40:\n            ht_tbl_pointer = expected_tpt_mimo2_40MHz;\n            break;\n        case RATE_MCS_CHAN_WIDTH_80:\n            ht_tbl_pointer = expected_tpt_mimo2_80MHz;\n            break;\n        case RATE_MCS_CHAN_WIDTH_160:\n            ht_tbl_pointer = expected_tpt_mimo2_160MHz;\n            break;\n        default:\n            WARN_ON_ONCE(1);\n        }\n    } else {\n        WARN_ON_ONCE(1);\n    }\n\n    if (!column->sgi && !lq_sta->is_agg)        /* Normal */\n        return ht_tbl_pointer[0];\n    else if (column->sgi && !lq_sta->is_agg)        /* SGI */\n        return ht_tbl_pointer[1];\n    else if (!column->sgi && lq_sta->is_agg)        /* AGG */\n        return ht_tbl_pointer[2];\n    else                        /* AGG+SGI */\n        return ht_tbl_pointer[3];\n}\n\nstatic void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta,\n                      struct iwl_scale_tbl_info *tbl)\n{\n    struct rs_rate *rate = &tbl->rate;\n    const struct rs_tx_column *column = &rs_tx_columns[tbl->column];\n\n    tbl->expected_tpt = rs_get_expected_tpt_table(lq_sta, column, rate->bw);\n}\n\n/* rs uses two tables, one is active and the second is for searching better\n * configuration. This function, according to the index of the currently\n * active table returns the search table, which is located at the\n * index complementary to 1 according to the active table (active = 1,\n * search = 0 or active = 0, search = 1).\n * Since lq_info is an arary of size 2, make sure index cannot be out of bounds.\n */\nstatic inline u8 rs_search_tbl(u8 active_tbl)\n{\n    return (active_tbl ^ 1) & 1;\n}\n\nstatic s32 rs_get_best_rate(struct iwm_softc *sc,\n                struct iwl_lq_sta *lq_sta,\n                struct iwl_scale_tbl_info *tbl,    /* \"search\" */\n                unsigned long rate_mask, s8 index)\n{\n    struct iwl_scale_tbl_info *active_tbl =\n        &(lq_sta->lq_info[lq_sta->active_tbl]);\n    s32 success_ratio = active_tbl->win[index].success_ratio;\n    u16 expected_current_tpt = active_tbl->expected_tpt[index];\n    const u16 *tpt_tbl = tbl->expected_tpt;\n    u16 high_low;\n    u32 target_tpt;\n    int rate_idx;\n\n    if (success_ratio >= RS_PERCENT(IWL_MVM_RS_SR_NO_DECREASE)) {\n        target_tpt = 100 * expected_current_tpt;\n        IWL_DEBUG_RATE(mvm,\n                   \"SR %d high. Find rate exceeding EXPECTED_CURRENT %d\\n\",\n                   success_ratio, target_tpt);\n    } else {\n        target_tpt = lq_sta->last_tpt;\n        IWL_DEBUG_RATE(mvm,\n                   \"SR %d not that good. Find rate exceeding ACTUAL_TPT %d\\n\",\n                   success_ratio, target_tpt);\n    }\n\n    rate_idx = find_first_bit(&rate_mask, BITS_PER_LONG);\n\n    while (rate_idx != IWL_RATE_INVALID) {\n        if (target_tpt < (100 * tpt_tbl[rate_idx]))\n            break;\n\n        high_low = rs_get_adjacent_rate(sc, rate_idx, rate_mask,\n                        tbl->rate.type);\n\n        rate_idx = (high_low >> 8) & 0xff;\n    }\n\n    IWL_DEBUG_RATE(mvm, \"Best rate found %d target_tp %d expected_new %d\\n\",\n               rate_idx, target_tpt,\n               rate_idx != IWL_RATE_INVALID ?\n               100 * tpt_tbl[rate_idx] : IWL_INVALID_VALUE);\n\n    return rate_idx;\n}\n\nstatic u32 rs_bw_from_sta_bw(struct ieee80211_node *ni)\n{\n    struct ieee80211_vht_cap vht_cap = {\n        .vht_cap_info = cpu_to_le32(ni->ni_vhtcaps),\n        .supp_mcs = ni->ni_vht_mcsinfo,\n    };\n    \n    if (ni->ni_chw == IEEE80211_CHAN_WIDTH_40 &&\n        IEEE80211_IS_CHAN_2GHZ(ni->ni_chan))\n        return RATE_MCS_CHAN_WIDTH_20;\n\n    switch (ni->ni_chw) {\n    case IEEE80211_CHAN_WIDTH_160:\n        /*\n         * Don't use 160 MHz if VHT extended NSS support\n         * says we cannot use 2 streams, we don't want to\n         * deal with this.\n         * We only check MCS 0 - they will support that if\n         * we got here at all and we don't care which MCS,\n         * we want to determine a more global state.\n         */\n        if (ieee80211_get_vht_max_nss(&vht_cap,\n                          IEEE80211_VHT_CHANWIDTH_160MHZ,\n                          0, true,\n                          ni->ni_rx_nss) < ni->ni_rx_nss)\n            return RATE_MCS_CHAN_WIDTH_80;\n        return RATE_MCS_CHAN_WIDTH_160;\n    case IEEE80211_CHAN_WIDTH_80:\n        return RATE_MCS_CHAN_WIDTH_80;\n    case IEEE80211_CHAN_WIDTH_40:\n        return RATE_MCS_CHAN_WIDTH_40;\n    case IEEE80211_CHAN_WIDTH_20:\n    default:\n        return RATE_MCS_CHAN_WIDTH_20;\n    }\n}\n\n/*\n * Check whether we should continue using same modulation mode, or\n * begin search for a new mode, based on:\n * 1) # tx successes or failures while using this mode\n * 2) # times calling this function\n * 3) elapsed time in this mode (not used, for now)\n */\nstatic void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search)\n{\n    struct iwl_scale_tbl_info *tbl;\n    int active_tbl;\n    int flush_interval_passed = 0;\n    struct iwm_softc *sc;\n\n    sc = lq_sta->pers.drv;\n    active_tbl = lq_sta->active_tbl;\n\n    tbl = &(lq_sta->lq_info[active_tbl]);\n\n    /* If we've been disallowing search, see if we should now allow it */\n    if (lq_sta->rs_state == RS_STATE_STAY_IN_COLUMN) {\n        /* Elapsed time using current modulation mode */\n        if (lq_sta->flush_timer)\n            flush_interval_passed =\n                time_after(ticks,\n                       (unsigned long)(lq_sta->flush_timer +\n                               (IWL_MVM_RS_STAY_IN_COLUMN_TIMEOUT * hz)));\n\n        /*\n         * Check if we should allow search for new modulation mode.\n         * If many frames have failed or succeeded, or we've used\n         * this same modulation for a long time, allow search, and\n         * reset history stats that keep track of whether we should\n         * allow a new search.  Also (below) reset all bitmaps and\n         * stats in active history.\n         */\n        if (force_search ||\n            (lq_sta->total_failed > lq_sta->max_failure_limit) ||\n            (lq_sta->total_success > lq_sta->max_success_limit) ||\n            ((!lq_sta->search_better_tbl) &&\n             (lq_sta->flush_timer) && (flush_interval_passed))) {\n            IWL_DEBUG_RATE(mvm,\n                       \"LQ: stay is expired %d %d %d\\n\",\n                     lq_sta->total_failed,\n                     lq_sta->total_success,\n                     flush_interval_passed);\n\n            /* Allow search for new mode */\n            lq_sta->rs_state = RS_STATE_SEARCH_CYCLE_STARTED;\n            IWL_DEBUG_RATE(mvm,\n                       \"Moving to RS_STATE_SEARCH_CYCLE_STARTED\\n\");\n            lq_sta->total_failed = 0;\n            lq_sta->total_success = 0;\n            lq_sta->flush_timer = 0;\n            /* mark the current column as visited */\n            lq_sta->visited_columns = BIT(tbl->column);\n        /*\n         * Else if we've used this modulation mode enough repetitions\n         * (regardless of elapsed time or success/failure), reset\n         * history bitmaps and rate-specific stats for all rates in\n         * active table.\n         */\n        } else {\n            lq_sta->table_count++;\n            if (lq_sta->table_count >=\n                lq_sta->table_count_limit) {\n                lq_sta->table_count = 0;\n\n                IWL_DEBUG_RATE(sc,\n                           \"LQ: stay in table clear win\\n\");\n                rs_rate_scale_clear_tbl_windows(sc, tbl);\n            }\n        }\n\n        /* If transitioning to allow \"search\", reset all history\n         * bitmaps and stats in active table (this will become the new\n         * \"search\" table). */\n        if (lq_sta->rs_state == RS_STATE_SEARCH_CYCLE_STARTED) {\n            rs_rate_scale_clear_tbl_windows(sc, tbl);\n        }\n    }\n}\n\nstatic void rs_set_amsdu_len(struct iwm_softc *sc, struct ieee80211_node *ni,\n                 struct iwl_scale_tbl_info *tbl,\n                 enum rs_action scale_action)\n{\n#if 0\n    struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);\n    int i;\n\n    sta->max_amsdu_len = rs_fw_get_max_amsdu_len(sta);\n\n    /*\n     * In case TLC offload is not active amsdu_enabled is either 0xFFFF\n     * or 0, since there is no per-TID alg.\n     */\n    if ((!is_vht(&tbl->rate) && !is_ht(&tbl->rate)) ||\n        tbl->rate.index < IWL_RATE_MCS_5_INDEX ||\n        scale_action == RS_ACTION_DOWNSCALE)\n        mvmsta->amsdu_enabled = 0;\n    else\n        mvmsta->amsdu_enabled = 0xFFFF;\n\n    if (mvmsta->vif->bss_conf.he_support &&\n        !iwlwifi_mod_params.disable_11ax)\n        mvmsta->max_amsdu_len = sta->max_amsdu_len;\n    else\n        mvmsta->max_amsdu_len = min_t(int, sta->max_amsdu_len, 8500);\n\n    sta->max_rc_amsdu_len = mvmsta->max_amsdu_len;\n\n    for (i = 0; i < IWL_MAX_TID_COUNT; i++) {\n        if (mvmsta->amsdu_enabled)\n            sta->max_tid_amsdu_len[i] =\n                iwl_mvm_max_amsdu_size(mvm, sta, i);\n        else\n            /*\n             * Not so elegant, but this will effectively\n             * prevent AMSDU on this TID\n             */\n            sta->max_tid_amsdu_len[i] = 1;\n    }\n#endif\n}\n\n/**\n * iwl_mvm_send_lq_cmd() - Send link quality command\n * @mvm: Driver data.\n * @lq: Link quality command to send.\n *\n * The link quality command is sent as the last step of station creation.\n * This is the special case in which init is set and we call a callback in\n * this case to clear the state indicating that station creation is in\n * progress.\n */\nint iwl_mvm_send_lq_cmd(struct iwm_softc *sc, struct iwm_lq_cmd *lq)\n{\n    ItlIwm *that = container_of(sc, ItlIwm, com);\n\n    struct iwm_host_cmd cmd = {\n        .id = IWM_LQ_CMD,\n        .len = { sizeof(struct iwm_lq_cmd), },\n        .flags = IWM_CMD_ASYNC,\n        .data = { lq, },\n    };\n\n    return that->iwm_send_cmd(sc, &cmd);;\n}\n\n/*\n * setup rate table in uCode\n */\nstatic void rs_update_rate_tbl(struct iwm_softc *sc,\n                   struct ieee80211_node *ni,\n                   struct iwl_lq_sta *lq_sta,\n                   struct iwl_scale_tbl_info *tbl)\n{\n    rs_fill_lq_cmd(sc, ni, lq_sta, &tbl->rate);\n    iwl_mvm_send_lq_cmd(sc, &lq_sta->lq);\n}\n\nstatic bool rs_tweak_rate_tbl(struct iwm_softc *sc,\n                  struct ieee80211_node *ni,\n                  struct iwl_lq_sta *lq_sta,\n                  struct iwl_scale_tbl_info *tbl,\n                  enum rs_action scale_action)\n{\n    if (rs_bw_from_sta_bw(ni) != RATE_MCS_CHAN_WIDTH_80)\n        return false;\n\n    if (!is_vht_siso(&tbl->rate))\n        return false;\n\n    if ((tbl->rate.bw == RATE_MCS_CHAN_WIDTH_80) &&\n        (tbl->rate.index == IWL_RATE_MCS_0_INDEX) &&\n        (scale_action == RS_ACTION_DOWNSCALE)) {\n        tbl->rate.bw = RATE_MCS_CHAN_WIDTH_20;\n        tbl->rate.index = IWL_RATE_MCS_4_INDEX;\n        IWL_DEBUG_RATE(sc, \"Switch 80Mhz SISO MCS0 -> 20Mhz MCS4\\n\");\n        goto tweaked;\n    }\n\n    /* Go back to 80Mhz MCS1 only if we've established that 20Mhz MCS5 is\n     * sustainable, i.e. we're past the test window. We can't go back\n     * if MCS5 is just tested as this will happen always after switching\n     * to 20Mhz MCS4 because the rate stats are cleared.\n     */\n    if ((tbl->rate.bw == RATE_MCS_CHAN_WIDTH_20) &&\n        (((tbl->rate.index == IWL_RATE_MCS_5_INDEX) &&\n         (scale_action == RS_ACTION_STAY)) ||\n         ((tbl->rate.index > IWL_RATE_MCS_5_INDEX) &&\n          (scale_action == RS_ACTION_UPSCALE)))) {\n        tbl->rate.bw = RATE_MCS_CHAN_WIDTH_80;\n        tbl->rate.index = IWL_RATE_MCS_1_INDEX;\n        IWL_DEBUG_RATE(sc, \"Switch 20Mhz SISO MCS5 -> 80Mhz MCS1\\n\");\n        goto tweaked;\n    }\n\n    return false;\n\ntweaked:\n    rs_set_expected_tpt_table(lq_sta, tbl);\n    rs_rate_scale_clear_tbl_windows(sc, tbl);\n    return true;\n}\n\nstatic enum rs_column rs_get_next_column(struct iwm_softc *sc,\n                     struct iwl_lq_sta *lq_sta,\n                     struct ieee80211_node *ni,\n                     struct iwl_scale_tbl_info *tbl)\n{\n    int i, j, max_rate;\n    enum rs_column next_col_id;\n    const struct rs_tx_column *curr_col = &rs_tx_columns[tbl->column];\n    const struct rs_tx_column *next_col;\n    allow_column_func_t allow_func;\n    ItlIwm *that = container_of(sc, ItlIwm, com);\n    u8 valid_ants = that->iwm_fw_valid_tx_ant(sc);\n    const u16 *expected_tpt_tbl;\n    u16 tpt, max_expected_tpt;\n\n    for (i = 0; i < MAX_NEXT_COLUMNS; i++) {\n        next_col_id = curr_col->next_columns[i];\n\n        if (next_col_id == RS_COLUMN_INVALID)\n            continue;\n\n        if (lq_sta->visited_columns & BIT(next_col_id)) {\n            IWL_DEBUG_RATE(sc, \"Skip already visited column %d\\n\",\n                       next_col_id);\n            continue;\n        }\n\n        next_col = &rs_tx_columns[next_col_id];\n\n        if (!rs_is_valid_ant(valid_ants, next_col->ant)) {\n            IWL_DEBUG_RATE(sc,\n                       \"Skip column %d as ANT config isn't supported by chip. valid_ants 0x%x column ant 0x%x\\n\",\n                       next_col_id, valid_ants, next_col->ant);\n            continue;\n        }\n\n        for (j = 0; j < MAX_COLUMN_CHECKS; j++) {\n            allow_func = next_col->checks[j];\n            if (allow_func && !allow_func(sc, ni, &tbl->rate,\n                              next_col))\n                break;\n        }\n\n        if (j != MAX_COLUMN_CHECKS) {\n            IWL_DEBUG_RATE(sc,\n                       \"Skip column %d: not allowed (check %d failed)\\n\",\n                       next_col_id, j);\n\n            continue;\n        }\n\n        tpt = lq_sta->last_tpt / 100;\n        expected_tpt_tbl = rs_get_expected_tpt_table(lq_sta, next_col,\n                             rs_bw_from_sta_bw(ni));\n        if (WARN_ON_ONCE(!expected_tpt_tbl))\n            continue;\n\n        max_rate = rs_get_max_allowed_rate(lq_sta, next_col);\n        if (max_rate == IWL_RATE_INVALID) {\n            IWL_DEBUG_RATE(sc,\n                       \"Skip column %d: no rate is allowed in this column\\n\",\n                       next_col_id);\n            continue;\n        }\n\n        max_expected_tpt = expected_tpt_tbl[max_rate];\n        if (tpt >= max_expected_tpt) {\n            IWL_DEBUG_RATE(sc,\n                       \"Skip column %d: can't beat current TPT. Max expected %d current %d\\n\",\n                       next_col_id, max_expected_tpt, tpt);\n            continue;\n        }\n\n        IWL_DEBUG_RATE(sc,\n                   \"Found potential column %d. Max expected %d current %d\\n\",\n                   next_col_id, max_expected_tpt, tpt);\n        break;\n    }\n\n    if (i == MAX_NEXT_COLUMNS)\n        return RS_COLUMN_INVALID;\n\n    return next_col_id;\n}\n\nstatic int rs_switch_to_column(struct iwm_softc *sc,\n                   struct iwl_lq_sta *lq_sta,\n                   struct ieee80211_node *ni,\n                   enum rs_column col_id)\n{\n    struct iwl_scale_tbl_info *tbl = &lq_sta->lq_info[lq_sta->active_tbl];\n    struct iwl_scale_tbl_info *search_tbl =\n        &lq_sta->lq_info[rs_search_tbl(lq_sta->active_tbl)];\n    struct rs_rate *rate = &search_tbl->rate;\n    const struct rs_tx_column *column = &rs_tx_columns[col_id];\n    const struct rs_tx_column *curr_column = &rs_tx_columns[tbl->column];\n    unsigned long rate_mask = 0;\n    u32 rate_idx = 0;\n\n    memcpy(search_tbl, tbl, offsetof(struct iwl_scale_tbl_info, win));\n\n    rate->sgi = column->sgi;\n    rate->ant = column->ant;\n\n    if (column->mode == RS_LEGACY) {\n        if (lq_sta->band == NL80211_BAND_5GHZ)\n            rate->type = LQ_LEGACY_A;\n        else\n            rate->type = LQ_LEGACY_G;\n\n        rate->bw = RATE_MCS_CHAN_WIDTH_20;\n        rate->ldpc = false;\n        rate_mask = lq_sta->active_legacy_rate;\n    } else if (column->mode == RS_SISO) {\n        rate->type = lq_sta->is_vht ? LQ_VHT_SISO : LQ_HT_SISO;\n        rate_mask = lq_sta->active_siso_rate;\n    } else if (column->mode == RS_MIMO2) {\n        rate->type = lq_sta->is_vht ? LQ_VHT_MIMO2 : LQ_HT_MIMO2;\n        rate_mask = lq_sta->active_mimo2_rate;\n    } else {\n        WARN_ON(1, \"Bad column mode\");\n    }\n\n    if (column->mode != RS_LEGACY) {\n        rate->bw = rs_bw_from_sta_bw(ni);\n        rate->ldpc = lq_sta->ldpc;\n    }\n\n    search_tbl->column = col_id;\n    rs_set_expected_tpt_table(lq_sta, search_tbl);\n\n    lq_sta->visited_columns |= BIT(col_id);\n\n    /* Get the best matching rate if we're changing modes. e.g.\n     * SISO->MIMO, LEGACY->SISO, MIMO->SISO\n     */\n    if (curr_column->mode != column->mode) {\n        rate_idx = rs_get_best_rate(sc, lq_sta, search_tbl,\n                        rate_mask, rate->index);\n\n        if ((rate_idx == IWL_RATE_INVALID) ||\n            !(BIT(rate_idx) & rate_mask)) {\n            IWL_DEBUG_RATE(sc,\n                       \"can not switch with index %d\"\n                       \" rate mask %lx\\n\",\n                       rate_idx, rate_mask);\n\n            goto err;\n        }\n\n        rate->index = rate_idx;\n    }\n\n    IWL_DEBUG_RATE(sc, \"Switched to column %d: Index %d\\n\",\n               col_id, rate->index);\n\n    return 0;\n\nerr:\n    rate->type = LQ_NONE;\n    return -1;\n}\n\nstatic enum rs_action rs_get_rate_action(struct iwm_softc *sc,\n                     struct iwl_scale_tbl_info *tbl,\n                     s32 sr, int low, int high,\n                     int current_tpt,\n                     int low_tpt, int high_tpt)\n{\n    enum rs_action action = RS_ACTION_STAY;\n\n    if ((sr <= RS_PERCENT(IWL_MVM_RS_SR_FORCE_DECREASE)) ||\n        (current_tpt == 0)) {\n        IWL_DEBUG_RATE(mvm,\n                   \"Decrease rate because of low SR\\n\");\n        return RS_ACTION_DOWNSCALE;\n    }\n\n    if ((low_tpt == IWL_INVALID_VALUE) &&\n        (high_tpt == IWL_INVALID_VALUE) &&\n        (high != IWL_RATE_INVALID)) {\n        IWL_DEBUG_RATE(mvm,\n                   \"No data about high/low rates. Increase rate\\n\");\n        return RS_ACTION_UPSCALE;\n    }\n\n    if ((high_tpt == IWL_INVALID_VALUE) &&\n        (high != IWL_RATE_INVALID) &&\n        (low_tpt != IWL_INVALID_VALUE) &&\n        (low_tpt < current_tpt)) {\n        IWL_DEBUG_RATE(mvm,\n                   \"No data about high rate and low rate is worse. Increase rate\\n\");\n        return RS_ACTION_UPSCALE;\n    }\n\n    if ((high_tpt != IWL_INVALID_VALUE) &&\n        (high_tpt > current_tpt)) {\n        IWL_DEBUG_RATE(mvm,\n                   \"Higher rate is better. Increate rate\\n\");\n        return RS_ACTION_UPSCALE;\n    }\n\n    if ((low_tpt != IWL_INVALID_VALUE) &&\n        (high_tpt != IWL_INVALID_VALUE) &&\n        (low_tpt < current_tpt) &&\n        (high_tpt < current_tpt)) {\n        IWL_DEBUG_RATE(mvm,\n                   \"Both high and low are worse. Maintain rate\\n\");\n        return RS_ACTION_STAY;\n    }\n\n    if ((low_tpt != IWL_INVALID_VALUE) &&\n        (low_tpt > current_tpt)) {\n        IWL_DEBUG_RATE(mvm,\n                   \"Lower rate is better\\n\");\n        action = RS_ACTION_DOWNSCALE;\n        goto out;\n    }\n\n    if ((low_tpt == IWL_INVALID_VALUE) &&\n        (low != IWL_RATE_INVALID)) {\n        IWL_DEBUG_RATE(mvm,\n                   \"No data about lower rate\\n\");\n        action = RS_ACTION_DOWNSCALE;\n        goto out;\n    }\n\n    IWL_DEBUG_RATE(mvm, \"Maintain rate\\n\");\n\nout:\n    if ((action == RS_ACTION_DOWNSCALE) && (low != IWL_RATE_INVALID)) {\n        if (sr >= RS_PERCENT(IWL_MVM_RS_SR_NO_DECREASE)) {\n            IWL_DEBUG_RATE(mvm,\n                       \"SR is above NO DECREASE. Avoid downscale\\n\");\n            action = RS_ACTION_STAY;\n        } else if (current_tpt > (100 * tbl->expected_tpt[low])) {\n            IWL_DEBUG_RATE(mvm,\n                       \"Current TPT is higher than max expected in low rate. Avoid downscale\\n\");\n            action = RS_ACTION_STAY;\n        } else {\n            IWL_DEBUG_RATE(mvm, \"Decrease rate\\n\");\n        }\n    }\n\n    return action;\n}\n\nstatic bool rs_stbc_allow(struct iwm_softc *sc, struct ieee80211_node *ni,\n              struct iwl_lq_sta *lq_sta)\n{\n    /* Our chip supports Tx STBC and the peer is an HT/VHT STA which\n     * supports STBC of at least 1*SS\n     */\n    if (!lq_sta->stbc_capable)\n        return false;\n\n    if (!iwl_mvm_bt_coex_is_mimo_allowed(sc, ni))\n        return false;\n\n    return true;\n}\n\nstatic void rs_get_adjacent_txp(struct iwm_softc *mvm, int index,\n                int *weaker, int *stronger)\n{\n    *weaker = index + IWL_MVM_RS_TPC_TX_POWER_STEP;\n    if (*weaker > TPC_MAX_REDUCTION)\n        *weaker = TPC_INVALID;\n\n    *stronger = index - IWL_MVM_RS_TPC_TX_POWER_STEP;\n    if (*stronger < 0)\n        *stronger = TPC_INVALID;\n}\n\nstatic bool iwl_mvm_bt_coex_is_tpc_allowed(struct iwm_softc *mvm,\n                    enum nl80211_band band)\n{\n    return ItlIwm::iwm_coex_is_tpc_allowed(mvm, band == NL80211_BAND_5GHZ);\n}\n\nstatic bool rs_tpc_allowed(struct iwm_softc *mvm,\n               struct rs_rate *rate, enum nl80211_band band)\n{\n    int index = rate->index;\n    bool cam = /*(iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM)*/ false;\n    bool sta_ps_disabled = /*(vif->type == NL80211_IFTYPE_STATION &&\n                !vif->bss_conf.ps)*/ true;\n\n    IWL_DEBUG_RATE(mvm, \"cam: %d sta_ps_disabled %d\\n\",\n               cam, sta_ps_disabled);\n    /*\n     * allow tpc only if power management is enabled, or bt coex\n     * activity grade allows it and we are on 2.4Ghz.\n     */\n    if ((cam || sta_ps_disabled) &&\n        !iwl_mvm_bt_coex_is_tpc_allowed(mvm, band))\n        return false;\n\n    IWL_DEBUG_RATE(mvm, \"check rate, table type: %d\\n\", rate->type);\n    if (is_legacy(rate))\n        return index == IWL_RATE_54M_INDEX;\n    if (is_ht(rate))\n        return index == IWL_RATE_MCS_7_INDEX;\n    if (is_vht(rate))\n        return index == IWL_RATE_MCS_9_INDEX;\n\n    WARN_ON_ONCE(1);\n    return false;\n}\n\nenum tpc_action {\n    TPC_ACTION_STAY,\n    TPC_ACTION_DECREASE,\n    TPC_ACTION_INCREASE,\n    TPC_ACTION_NO_RESTIRCTION,\n};\n\nstatic enum tpc_action rs_get_tpc_action(struct iwm_softc *mvm,\n                     s32 sr, int weak, int strong,\n                     int current_tpt,\n                     int weak_tpt, int strong_tpt)\n{\n    /* stay until we have valid tpt */\n    if (current_tpt == IWL_INVALID_VALUE) {\n        IWL_DEBUG_RATE(mvm, \"no current tpt. stay.\\n\");\n        return TPC_ACTION_STAY;\n    }\n\n    /* Too many failures, increase txp */\n    if (sr <= RS_PERCENT(IWL_MVM_RS_TPC_SR_FORCE_INCREASE) ||\n        current_tpt == 0) {\n        IWL_DEBUG_RATE(mvm, \"increase txp because of weak SR\\n\");\n        return TPC_ACTION_NO_RESTIRCTION;\n    }\n\n    /* try decreasing first if applicable */\n    if (sr >= RS_PERCENT(IWL_MVM_RS_TPC_SR_NO_INCREASE) &&\n        weak != TPC_INVALID) {\n        if (weak_tpt == IWL_INVALID_VALUE &&\n            (strong_tpt == IWL_INVALID_VALUE ||\n             current_tpt >= strong_tpt)) {\n            IWL_DEBUG_RATE(mvm,\n                       \"no weak txp measurement. decrease txp\\n\");\n            return TPC_ACTION_DECREASE;\n        }\n\n        if (weak_tpt > current_tpt) {\n            IWL_DEBUG_RATE(mvm,\n                       \"lower txp has better tpt. decrease txp\\n\");\n            return TPC_ACTION_DECREASE;\n        }\n    }\n\n    /* next, increase if needed */\n    if (sr < RS_PERCENT(IWL_MVM_RS_TPC_SR_NO_INCREASE) &&\n        strong != TPC_INVALID) {\n        if (weak_tpt == IWL_INVALID_VALUE &&\n            strong_tpt != IWL_INVALID_VALUE &&\n            current_tpt < strong_tpt) {\n            IWL_DEBUG_RATE(mvm,\n                       \"higher txp has better tpt. increase txp\\n\");\n            return TPC_ACTION_INCREASE;\n        }\n\n        if (weak_tpt < current_tpt &&\n            (strong_tpt == IWL_INVALID_VALUE ||\n             strong_tpt > current_tpt)) {\n            IWL_DEBUG_RATE(mvm,\n                       \"lower txp has worse tpt. increase txp\\n\");\n            return TPC_ACTION_INCREASE;\n        }\n    }\n\n    IWL_DEBUG_RATE(mvm, \"no need to increase or decrease txp - stay\\n\");\n    return TPC_ACTION_STAY;\n}\n\nstatic bool rs_tpc_perform(struct iwm_softc *mvm,\n               struct ieee80211_node *ni,\n               struct iwl_lq_sta *lq_sta,\n               struct iwl_scale_tbl_info *tbl)\n{\n    enum nl80211_band band;\n    struct iwl_rate_scale_data *window;\n    struct rs_rate *rate = &tbl->rate;\n    enum tpc_action action;\n    s32 sr;\n    u8 cur = lq_sta->lq.reduced_tpc;\n    int current_tpt;\n    int weak, strong;\n    int weak_tpt = IWL_INVALID_VALUE, strong_tpt = IWL_INVALID_VALUE;\n\n    if (WARN_ON(!ni->ni_chan))\n        band = NUM_NL80211_BANDS;\n    else\n        band = IEEE80211_IS_CHAN_2GHZ(ni->ni_chan) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ;\n\n    if (!rs_tpc_allowed(mvm, rate, band)) {\n        IWL_DEBUG_RATE(mvm,\n                   \"tpc is not allowed. remove txp restrictions\\n\");\n        lq_sta->lq.reduced_tpc = TPC_NO_REDUCTION;\n        return cur != TPC_NO_REDUCTION;\n    }\n\n    rs_get_adjacent_txp(mvm, cur, &weak, &strong);\n\n    /* Collect measured throughputs for current and adjacent rates */\n    window = tbl->tpc_win;\n    sr = window[cur].success_ratio;\n    current_tpt = window[cur].average_tpt;\n    if (weak != TPC_INVALID)\n        weak_tpt = window[weak].average_tpt;\n    if (strong != TPC_INVALID)\n        strong_tpt = window[strong].average_tpt;\n\n    IWL_DEBUG_RATE(mvm,\n               \"(TPC: %d): cur_tpt %d SR %d weak %d strong %d weak_tpt %d strong_tpt %d\\n\",\n               cur, current_tpt, sr, weak, strong,\n               weak_tpt, strong_tpt);\n\n    action = rs_get_tpc_action(mvm, sr, weak, strong,\n                   current_tpt, weak_tpt, strong_tpt);\n\n    /* override actions if we are on the edge */\n    if (weak == TPC_INVALID && action == TPC_ACTION_DECREASE) {\n        IWL_DEBUG_RATE(mvm, \"already in lowest txp, stay\\n\");\n        action = TPC_ACTION_STAY;\n    } else if (strong == TPC_INVALID &&\n           (action == TPC_ACTION_INCREASE ||\n            action == TPC_ACTION_NO_RESTIRCTION)) {\n        IWL_DEBUG_RATE(mvm, \"already in highest txp, stay\\n\");\n        action = TPC_ACTION_STAY;\n    }\n\n    switch (action) {\n    case TPC_ACTION_DECREASE:\n        lq_sta->lq.reduced_tpc = weak;\n        return true;\n    case TPC_ACTION_INCREASE:\n        lq_sta->lq.reduced_tpc = strong;\n        return true;\n    case TPC_ACTION_NO_RESTIRCTION:\n        lq_sta->lq.reduced_tpc = TPC_NO_REDUCTION;\n        return true;\n    case TPC_ACTION_STAY:\n        /* do nothing */\n        break;\n    }\n    return false;\n}\n\n/*\n * Do rate scaling and search for new modulation mode.\n */\nstatic void rs_rate_scale_perform(struct iwm_softc *mvm,\n                  struct ieee80211_node *ni,\n                  struct iwl_lq_sta *lq_sta,\n                  int tid, bool ndp)\n{\n    int low = IWL_RATE_INVALID;\n    int high = IWL_RATE_INVALID;\n    int index;\n    struct iwl_rate_scale_data *window = NULL;\n    int current_tpt = IWL_INVALID_VALUE;\n    int low_tpt = IWL_INVALID_VALUE;\n    int high_tpt = IWL_INVALID_VALUE;\n    u32 fail_count;\n    enum rs_action scale_action = RS_ACTION_STAY;\n    u16 rate_mask;\n    u8 update_lq = 0;\n    struct iwl_scale_tbl_info *tbl, *tbl1;\n    u8 active_tbl = 0;\n    u8 done_search = 0;\n    u16 high_low;\n    s32 sr;\n    u8 prev_agg = lq_sta->is_agg;\n    struct rs_rate *rate;\n    int i;\n    \n    lq_sta->is_agg = false;\n    for (i = 0; i <= IWM_MAX_TID_COUNT; i++) {\n        if (mvm->sc_tx_ba[i].wn != NULL) {\n            lq_sta->is_agg = true;\n            break;\n        }\n    }\n\n    /*\n     * Select rate-scale / modulation-mode table to work with in\n     * the rest of this function:  \"search\" if searching for better\n     * modulation mode, or \"active\" if doing rate scaling within a mode.\n     */\n    if (!lq_sta->search_better_tbl)\n        active_tbl = lq_sta->active_tbl;\n    else\n        active_tbl = rs_search_tbl(lq_sta->active_tbl);\n\n    tbl = &(lq_sta->lq_info[active_tbl]);\n    rate = &tbl->rate;\n\n    if (prev_agg != lq_sta->is_agg) {\n        XYLog(\"Aggregation changed: prev %d current %d. Update expected TPT table\\n\",\n                   prev_agg, lq_sta->is_agg);\n        rs_set_expected_tpt_table(lq_sta, tbl);\n        rs_rate_scale_clear_tbl_windows(mvm, tbl);\n    }\n\n    /* current tx rate */\n    index = rate->index;\n\n    /* rates available for this association, and for modulation mode */\n    rate_mask = rs_get_supported_rates(lq_sta, rate);\n\n    if (!(BIT(index) & rate_mask)) {\n        IWL_ERR(mvm, \"Current Rate is not valid\\n\");\n        if (lq_sta->search_better_tbl) {\n            /* revert to active table if search table is not valid*/\n            rate->type = LQ_NONE;\n            lq_sta->search_better_tbl = 0;\n            tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);\n            rs_update_rate_tbl(mvm, ni, lq_sta, tbl);\n        }\n        return;\n    }\n\n    /* Get expected throughput table and history window for current rate */\n    if (!tbl->expected_tpt) {\n        IWL_ERR(mvm, \"tbl->expected_tpt is NULL\\n\");\n        return;\n    }\n\n    /* TODO: handle rate_idx_mask and rate_idx_mcs_mask */\n    window = &(tbl->win[index]);\n\n    /*\n     * If there is not enough history to calculate actual average\n     * throughput, keep analyzing results of more tx frames, without\n     * changing rate or mode (bypass most of the rest of this function).\n     * Set up new rate table in uCode only if old rate is not supported\n     * in current association (use new rate found above).\n     */\n    fail_count = window->counter - window->success_counter;\n    if ((fail_count < IWL_MVM_RS_RATE_MIN_FAILURE_TH) &&\n        (window->success_counter < IWL_MVM_RS_RATE_MIN_SUCCESS_TH)) {\n        IWL_DEBUG_RATE(mvm,\n                   \"%s: Test Window: succ %d total %d\\n\",\n                   rs_pretty_rate(rate),\n                   window->success_counter, window->counter);\n\n        /* Can't calculate this yet; not enough history */\n        window->average_tpt = IWL_INVALID_VALUE;\n\n        /* Should we stay with this modulation mode,\n         * or search for a new one? */\n        rs_stay_in_table(lq_sta, false);\n\n        return;\n    }\n\n    /* If we are searching for better modulation mode, check success. */\n    if (lq_sta->search_better_tbl) {\n        /* If good success, continue using the \"search\" mode;\n         * no need to send new link quality command, since we're\n         * continuing to use the setup that we've been trying. */\n        if (window->average_tpt > lq_sta->last_tpt) {\n            IWL_DEBUG_RATE(mvm,\n                       \"SWITCHING TO NEW TABLE SR: %d \"\n                       \"cur-tpt %d old-tpt %d\\n\",\n                       window->success_ratio,\n                       window->average_tpt,\n                       lq_sta->last_tpt);\n\n            /* Swap tables; \"search\" becomes \"active\" */\n            lq_sta->active_tbl = active_tbl;\n            current_tpt = window->average_tpt;\n        /* Else poor success; go back to mode in \"active\" table */\n        } else {\n            IWL_DEBUG_RATE(mvm,\n                       \"GOING BACK TO THE OLD TABLE: SR %d \"\n                       \"cur-tpt %d old-tpt %d\\n\",\n                       window->success_ratio,\n                       window->average_tpt,\n                       lq_sta->last_tpt);\n\n            /* Nullify \"search\" table */\n            rate->type = LQ_NONE;\n\n            /* Revert to \"active\" table */\n            active_tbl = lq_sta->active_tbl;\n            tbl = &(lq_sta->lq_info[active_tbl]);\n\n            /* Revert to \"active\" rate and throughput info */\n            index = tbl->rate.index;\n            current_tpt = lq_sta->last_tpt;\n\n            /* Need to set up a new rate table in uCode */\n            update_lq = 1;\n        }\n\n        /* Either way, we've made a decision; modulation mode\n         * search is done, allow rate adjustment next time. */\n        lq_sta->search_better_tbl = 0;\n        done_search = 1;    /* Don't switch modes below! */\n        goto lq_update;\n    }\n\n    /* (Else) not in search of better modulation mode, try for better\n     * starting rate, while staying in this mode. */\n    high_low = rs_get_adjacent_rate(mvm, index, rate_mask, rate->type);\n    low = high_low & 0xff;\n    high = (high_low >> 8) & 0xff;\n\n    /* TODO: handle rate_idx_mask and rate_idx_mcs_mask */\n\n    sr = window->success_ratio;\n\n    /* Collect measured throughputs for current and adjacent rates */\n    current_tpt = window->average_tpt;\n    if (low != IWL_RATE_INVALID)\n        low_tpt = tbl->win[low].average_tpt;\n    if (high != IWL_RATE_INVALID)\n        high_tpt = tbl->win[high].average_tpt;\n\n    IWL_DEBUG_RATE(mvm,\n               \"%s: cur_tpt %d SR %d low %d high %d low_tpt %d high_tpt %d\\n\",\n               rs_pretty_rate(rate), current_tpt, sr,\n               low, high, low_tpt, high_tpt);\n\n    scale_action = rs_get_rate_action(mvm, tbl, sr, low, high,\n                      current_tpt, low_tpt, high_tpt);\n\n    /* Force a search in case BT doesn't like us being in MIMO */\n    if (is_mimo(rate) &&\n        !iwl_mvm_bt_coex_is_mimo_allowed(mvm, ni)) {\n        IWL_DEBUG_RATE(mvm,\n                   \"BT Coex forbids MIMO. Search for new config\\n\");\n        rs_stay_in_table(lq_sta, true);\n        goto lq_update;\n    }\n\n    switch (scale_action) {\n    case RS_ACTION_DOWNSCALE:\n        /* Decrease starting rate, update uCode's rate table */\n        if (low != IWL_RATE_INVALID) {\n            update_lq = 1;\n            index = low;\n        } else {\n            IWL_DEBUG_RATE(mvm,\n                       \"At the bottom rate. Can't decrease\\n\");\n        }\n\n        break;\n    case RS_ACTION_UPSCALE:\n        /* Increase starting rate, update uCode's rate table */\n        if (high != IWL_RATE_INVALID) {\n            update_lq = 1;\n            index = high;\n        } else {\n            IWL_DEBUG_RATE(mvm,\n                       \"At the top rate. Can't increase\\n\");\n        }\n\n        break;\n    case RS_ACTION_STAY:\n        /* No change */\n        if (lq_sta->rs_state == RS_STATE_STAY_IN_COLUMN)\n            update_lq = rs_tpc_perform(mvm, ni, lq_sta, tbl);\n        break;\n    default:\n        break;\n    }\n\nlq_update:\n    /* Replace uCode's rate table for the destination station. */\n    if (update_lq) {\n        tbl->rate.index = index;\n        if (IWL_MVM_RS_80_20_FAR_RANGE_TWEAK)\n            rs_tweak_rate_tbl(mvm, ni, lq_sta, tbl, scale_action);\n        rs_set_amsdu_len(mvm, ni, tbl, scale_action);\n        rs_update_rate_tbl(mvm, ni, lq_sta, tbl);\n    }\n\n    rs_stay_in_table(lq_sta, false);\n\n    /*\n     * Search for new modulation mode if we're:\n     * 1)  Not changing rates right now\n     * 2)  Not just finishing up a search\n     * 3)  Allowing a new search\n     */\n    if (!update_lq && !done_search &&\n        lq_sta->rs_state == RS_STATE_SEARCH_CYCLE_STARTED\n        && window->counter) {\n        enum rs_column next_column;\n\n        /* Save current throughput to compare with \"search\" throughput*/\n        lq_sta->last_tpt = current_tpt;\n\n        IWL_DEBUG_RATE(mvm,\n                   \"Start Search: update_lq %d done_search %d rs_state %d win->counter %d\\n\",\n                   update_lq, done_search, lq_sta->rs_state,\n                   window->counter);\n\n        next_column = rs_get_next_column(mvm, lq_sta, ni, tbl);\n        if (next_column != RS_COLUMN_INVALID) {\n            int ret = rs_switch_to_column(mvm, lq_sta, ni,\n                              next_column);\n            if (!ret)\n                lq_sta->search_better_tbl = 1;\n        } else {\n            IWL_DEBUG_RATE(mvm,\n                       \"No more columns to explore in search cycle. Go to RS_STATE_SEARCH_CYCLE_ENDED\\n\");\n            lq_sta->rs_state = RS_STATE_SEARCH_CYCLE_ENDED;\n        }\n\n        /* If new \"search\" mode was selected, set up in uCode table */\n        if (lq_sta->search_better_tbl) {\n            /* Access the \"search\" table, clear its history. */\n            tbl = &lq_sta->lq_info[rs_search_tbl(lq_sta->active_tbl)];\n            rs_rate_scale_clear_tbl_windows(mvm, tbl);\n\n            /* Use new \"search\" start rate */\n            index = tbl->rate.index;\n\n            rs_dump_rate(mvm, &tbl->rate,\n                     \"Switch to SEARCH TABLE:\");\n            rs_update_rate_tbl(mvm, ni, lq_sta, tbl);\n        } else {\n            done_search = 1;\n        }\n    }\n\n    if (!ndp)\n        rs_tl_turn_on_agg(mvm, tid, lq_sta, ni);\n\n    if (done_search && lq_sta->rs_state == RS_STATE_SEARCH_CYCLE_ENDED) {\n        tbl1 = &(lq_sta->lq_info[lq_sta->active_tbl]);\n        rs_set_stay_in_table(mvm, is_legacy(&tbl1->rate), lq_sta);\n    }\n}\n\nstruct rs_init_rate_info {\n    s8 rssi;\n    u8 rate_idx;\n};\n\nstatic const struct rs_init_rate_info rs_optimal_rates_24ghz_legacy[] = {\n    { -60, IWL_RATE_54M_INDEX },\n    { -64, IWL_RATE_48M_INDEX },\n    { -68, IWL_RATE_36M_INDEX },\n    { -80, IWL_RATE_24M_INDEX },\n    { -84, IWL_RATE_18M_INDEX },\n    { -85, IWL_RATE_12M_INDEX },\n    { -86, IWL_RATE_11M_INDEX },\n    { -88, IWL_RATE_5M_INDEX  },\n    { -90, IWL_RATE_2M_INDEX  },\n    { S8_MIN, IWL_RATE_1M_INDEX },\n};\n\nstatic const struct rs_init_rate_info rs_optimal_rates_5ghz_legacy[] = {\n    { -60, IWL_RATE_54M_INDEX },\n    { -64, IWL_RATE_48M_INDEX },\n    { -72, IWL_RATE_36M_INDEX },\n    { -80, IWL_RATE_24M_INDEX },\n    { -84, IWL_RATE_18M_INDEX },\n    { -85, IWL_RATE_12M_INDEX },\n    { -87, IWL_RATE_9M_INDEX  },\n    { S8_MIN, IWL_RATE_6M_INDEX },\n};\n\nstatic const struct rs_init_rate_info rs_optimal_rates_ht[] = {\n    { -60, IWL_RATE_MCS_7_INDEX },\n    { -64, IWL_RATE_MCS_6_INDEX },\n    { -68, IWL_RATE_MCS_5_INDEX },\n    { -72, IWL_RATE_MCS_4_INDEX },\n    { -80, IWL_RATE_MCS_3_INDEX },\n    { -84, IWL_RATE_MCS_2_INDEX },\n    { -85, IWL_RATE_MCS_1_INDEX },\n    { S8_MIN, IWL_RATE_MCS_0_INDEX},\n};\n\n/* MCS index 9 is not valid for 20MHz VHT channel width,\n * but is ok for 40, 80 and 160MHz channels.\n */\nstatic const struct rs_init_rate_info rs_optimal_rates_vht_20mhz[] = {\n    { -60, IWL_RATE_MCS_8_INDEX },\n    { -64, IWL_RATE_MCS_7_INDEX },\n    { -68, IWL_RATE_MCS_6_INDEX },\n    { -72, IWL_RATE_MCS_5_INDEX },\n    { -80, IWL_RATE_MCS_4_INDEX },\n    { -84, IWL_RATE_MCS_3_INDEX },\n    { -85, IWL_RATE_MCS_2_INDEX },\n    { -87, IWL_RATE_MCS_1_INDEX },\n    { S8_MIN, IWL_RATE_MCS_0_INDEX},\n};\n\nstatic const struct rs_init_rate_info rs_optimal_rates_vht[] = {\n    { -60, IWL_RATE_MCS_9_INDEX },\n    { -64, IWL_RATE_MCS_8_INDEX },\n    { -68, IWL_RATE_MCS_7_INDEX },\n    { -72, IWL_RATE_MCS_6_INDEX },\n    { -80, IWL_RATE_MCS_5_INDEX },\n    { -84, IWL_RATE_MCS_4_INDEX },\n    { -85, IWL_RATE_MCS_3_INDEX },\n    { -87, IWL_RATE_MCS_2_INDEX },\n    { -88, IWL_RATE_MCS_1_INDEX },\n    { S8_MIN, IWL_RATE_MCS_0_INDEX },\n};\n\n#define IWL_RS_LOW_RSSI_THRESHOLD (-76) /* dBm */\n\n/* Init the optimal rate based on STA caps\n * This combined with rssi is used to report the last tx rate\n * to userspace when we haven't transmitted enough frames.\n */\nstatic void rs_init_optimal_rate(struct iwm_softc *mvm,\n                 struct ieee80211_node *sta,\n                 struct iwl_lq_sta *lq_sta)\n{\n    struct rs_rate *rate = &lq_sta->optimal_rate;\n\n    if (lq_sta->max_mimo2_rate_idx != IWL_RATE_INVALID)\n        rate->type = lq_sta->is_vht ? LQ_VHT_MIMO2 : LQ_HT_MIMO2;\n    else if (lq_sta->max_siso_rate_idx != IWL_RATE_INVALID)\n        rate->type = lq_sta->is_vht ? LQ_VHT_SISO : LQ_HT_SISO;\n    else if (lq_sta->band == NL80211_BAND_5GHZ)\n        rate->type = LQ_LEGACY_A;\n    else\n        rate->type = LQ_LEGACY_G;\n\n    rate->bw = rs_bw_from_sta_bw(sta);\n    rate->sgi = rs_sgi_allow(mvm, sta, rate, NULL);\n\n    /* ANT/LDPC/STBC aren't relevant for the rate reported to userspace */\n\n    if (is_mimo(rate)) {\n        lq_sta->optimal_rate_mask = lq_sta->active_mimo2_rate;\n    } else if (is_siso(rate)) {\n        lq_sta->optimal_rate_mask = lq_sta->active_siso_rate;\n    } else {\n        lq_sta->optimal_rate_mask = lq_sta->active_legacy_rate;\n\n        if (lq_sta->band == NL80211_BAND_5GHZ) {\n            lq_sta->optimal_rates = rs_optimal_rates_5ghz_legacy;\n            lq_sta->optimal_nentries =\n                ARRAY_SIZE(rs_optimal_rates_5ghz_legacy);\n        } else {\n            lq_sta->optimal_rates = rs_optimal_rates_24ghz_legacy;\n            lq_sta->optimal_nentries =\n                ARRAY_SIZE(rs_optimal_rates_24ghz_legacy);\n        }\n    }\n\n    if (is_vht(rate)) {\n        if (rate->bw == RATE_MCS_CHAN_WIDTH_20) {\n            lq_sta->optimal_rates = rs_optimal_rates_vht_20mhz;\n            lq_sta->optimal_nentries =\n                ARRAY_SIZE(rs_optimal_rates_vht_20mhz);\n        } else {\n            lq_sta->optimal_rates = rs_optimal_rates_vht;\n            lq_sta->optimal_nentries =\n                ARRAY_SIZE(rs_optimal_rates_vht);\n        }\n    } else if (is_ht(rate)) {\n        lq_sta->optimal_rates = rs_optimal_rates_ht;\n        lq_sta->optimal_nentries = ARRAY_SIZE(rs_optimal_rates_ht);\n    }\n}\n\n/* Compute the optimal rate index based on RSSI */\nstatic struct rs_rate *rs_get_optimal_rate(struct iwm_softc *mvm,\n                       struct iwl_lq_sta *lq_sta)\n{\n    struct rs_rate *rate = &lq_sta->optimal_rate;\n    int i;\n\n    rate->index = find_first_bit(&lq_sta->optimal_rate_mask,\n                     BITS_PER_LONG);\n\n    for (i = 0; i < lq_sta->optimal_nentries; i++) {\n        int rate_idx = lq_sta->optimal_rates[i].rate_idx;\n\n        if ((lq_sta->pers.last_rssi >= lq_sta->optimal_rates[i].rssi) &&\n            (BIT(rate_idx) & lq_sta->optimal_rate_mask)) {\n            rate->index = rate_idx;\n            break;\n        }\n    }\n\n    return rate;\n}\n\n/* Choose an initial legacy rate and antenna to use based on the RSSI\n * of last Rx\n */\nstatic void rs_get_initial_rate(struct iwm_softc *mvm,\n                struct ieee80211_node *sta,\n                struct iwl_lq_sta *lq_sta,\n                enum nl80211_band band,\n                struct rs_rate *rate)\n{\n    int i, nentries;\n    unsigned long active_rate;\n    s8 best_rssi = S8_MIN;\n    u8 best_ant = ANT_NONE;\n    ItlIwm *that = container_of(mvm, ItlIwm, com);\n    u8 valid_tx_ant = that->iwm_fw_valid_tx_ant(mvm);\n    const struct rs_init_rate_info *initial_rates;\n\n    for (i = 0; i < ARRAY_SIZE(lq_sta->pers.chain_signal); i++) {\n        if (!(lq_sta->pers.chains & BIT(i)))\n            continue;\n\n        if (lq_sta->pers.chain_signal[i] > best_rssi) {\n            best_rssi = lq_sta->pers.chain_signal[i];\n            best_ant = BIT(i);\n        }\n    }\n\n    IWL_DEBUG_RATE(mvm, \"Best ANT: %s Best RSSI: %d\\n\",\n               rs_pretty_ant(best_ant), best_rssi);\n\n    if (best_ant != ANT_A && best_ant != ANT_B)\n        rate->ant = first_antenna(valid_tx_ant);\n    else\n        rate->ant = best_ant;\n\n    rate->sgi = false;\n    rate->ldpc = false;\n    rate->bw = RATE_MCS_CHAN_WIDTH_20;\n\n    rate->index = find_first_bit(&lq_sta->active_legacy_rate,\n                     BITS_PER_LONG);\n\n    if (band == NL80211_BAND_5GHZ) {\n        rate->type = LQ_LEGACY_A;\n        initial_rates = rs_optimal_rates_5ghz_legacy;\n        nentries = ARRAY_SIZE(rs_optimal_rates_5ghz_legacy);\n    } else {\n        rate->type = LQ_LEGACY_G;\n        initial_rates = rs_optimal_rates_24ghz_legacy;\n        nentries = ARRAY_SIZE(rs_optimal_rates_24ghz_legacy);\n    }\n\n    if (!IWL_MVM_RS_RSSI_BASED_INIT_RATE)\n        goto out;\n\n    /* Start from a higher rate if the corresponding debug capability\n     * is enabled. The rate is chosen according to AP capabilities.\n     * In case of VHT/HT when the rssi is low fallback to the case of\n     * legacy rates.\n     */\n    if (ieee80211_node_supports_vht(sta) &&\n        best_rssi > IWL_RS_LOW_RSSI_THRESHOLD) {\n        /*\n         * In AP mode, when a new station associates, rs is initialized\n         * immediately upon association completion, before the phy\n         * context is updated with the association parameters, so the\n         * sta bandwidth might be wider than the phy context allows.\n         * To avoid this issue, always initialize rs with 20mhz\n         * bandwidth rate, and after authorization, when the phy context\n         * is already up-to-date, re-init rs with the correct bw.\n         */\n        u32 bw = mvm->sc_ic.ic_state < IEEE80211_S_RUN ?\n                RATE_MCS_CHAN_WIDTH_20 : rs_bw_from_sta_bw(sta);\n\n        switch (bw) {\n        case RATE_MCS_CHAN_WIDTH_40:\n        case RATE_MCS_CHAN_WIDTH_80:\n        case RATE_MCS_CHAN_WIDTH_160:\n            initial_rates = rs_optimal_rates_vht;\n            nentries = ARRAY_SIZE(rs_optimal_rates_vht);\n            break;\n        case RATE_MCS_CHAN_WIDTH_20:\n            initial_rates = rs_optimal_rates_vht_20mhz;\n            nentries = ARRAY_SIZE(rs_optimal_rates_vht_20mhz);\n            break;\n        default:\n            IWL_ERR(mvm, \"Invalid BW %d\\n\", sta->ni_chw);\n            goto out;\n        }\n\n        active_rate = lq_sta->active_siso_rate;\n        rate->type = LQ_VHT_SISO;\n        rate->bw = bw;\n    } else if (ieee80211_node_supports_ht(sta) &&\n           best_rssi > IWL_RS_LOW_RSSI_THRESHOLD) {\n        initial_rates = rs_optimal_rates_ht;\n        nentries = ARRAY_SIZE(rs_optimal_rates_ht);\n        active_rate = lq_sta->active_siso_rate;\n        rate->type = LQ_HT_SISO;\n    } else {\n        active_rate = lq_sta->active_legacy_rate;\n    }\n\n    for (i = 0; i < nentries; i++) {\n        int rate_idx = initial_rates[i].rate_idx;\n\n        if ((best_rssi >= initial_rates[i].rssi) &&\n            (BIT(rate_idx) & active_rate)) {\n            rate->index = rate_idx;\n            break;\n        }\n    }\n\nout:\n    rs_dump_rate(mvm, rate, \"INITIAL\");\n}\n\n/* Save info about RSSI of last Rx */\nvoid rs_update_last_rssi(struct iwm_softc *mvm,\n             struct ieee80211_rx_status *rx_status)\n{\n    struct iwl_lq_sta *lq_sta = &mvm->lq_sta.rs_drv;\n    int i;\n\n    lq_sta->pers.chains = rx_status->chains;\n    lq_sta->pers.chain_signal[0] = rx_status->chain_signal[0];\n    lq_sta->pers.chain_signal[1] = rx_status->chain_signal[1];\n    lq_sta->pers.chain_signal[2] = rx_status->chain_signal[2];\n    lq_sta->pers.last_rssi = S8_MIN;\n\n    for (i = 0; i < ARRAY_SIZE(lq_sta->pers.chain_signal); i++) {\n        if (!(lq_sta->pers.chains & BIT(i)))\n            continue;\n\n        if (lq_sta->pers.chain_signal[i] > lq_sta->pers.last_rssi)\n            lq_sta->pers.last_rssi = lq_sta->pers.chain_signal[i];\n    }\n}\n\n/*\n * rs_initialize_lq - Initialize a station's hardware rate table\n *\n * The uCode's station table contains a table of fallback rates\n * for automatic fallback during transmission.\n *\n * NOTE: This sets up a default set of values.  These will be replaced later\n *       if the driver's iwl-agn-rs rate scaling algorithm is used, instead of\n *       rc80211_simple.\n *\n * NOTE: Run REPLY_ADD_STA command to set up station table entry, before\n *       calling this function (which runs REPLY_TX_LINK_QUALITY_CMD,\n *       which requires station table entry to exist).\n */\nstatic void rs_initialize_lq(struct iwm_softc *mvm,\n                 struct ieee80211_node *sta,\n                 struct iwl_lq_sta *lq_sta,\n                 enum nl80211_band band)\n{\n    struct iwl_scale_tbl_info *tbl;\n    struct rs_rate *rate;\n    u8 active_tbl = 0;\n\n    if (!sta || !lq_sta)\n        return;\n\n    if (!lq_sta->search_better_tbl)\n        active_tbl = lq_sta->active_tbl;\n    else\n        active_tbl = rs_search_tbl(lq_sta->active_tbl);\n\n    tbl = &(lq_sta->lq_info[active_tbl]);\n    rate = &tbl->rate;\n\n    rs_get_initial_rate(mvm, sta, lq_sta, band, rate);\n    rs_init_optimal_rate(mvm, sta, lq_sta);\n\n    WARN_ON(rate->ant != ANT_A && rate->ant != ANT_B,\n          \"ant: 0x%x, chains 0x%x, fw tx ant: 0x%x, nvm tx ant: 0x%x\\n\",\n          rate->ant, lq_sta->pers.chains, mvm->fw->valid_tx_ant,\n          mvm->nvm_data ? mvm->nvm_data->valid_tx_ant : ANT_INVALID);\n\n    tbl->column = rs_get_column_from_rate(rate);\n\n    rs_set_expected_tpt_table(lq_sta, tbl);\n    rs_fill_lq_cmd(mvm, sta, lq_sta, rate);\n    /* TODO restore station should remember the lq cmd */\n    iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq);\n}\n\nstatic void rs_drv_get_rate(struct iwm_softc *mvm, struct ieee80211_node *sta,\n                struct ieee80211_tx_rate *r)\n{\n    struct iwl_lq_sta *lq_sta;\n    struct rs_rate *optimal_rate;\n    u32 last_ucode_rate;\n\n    if (!sta)\n        return;\n\n    lq_sta = &mvm->lq_sta.rs_drv;\n    \n    IOSimpleLockLock(mvm->lq_sta.rs_drv.pers.lock);\n    iwl_mvm_hwrate_to_tx_rate(lq_sta->last_rate_n_flags,\n                  IEEE80211_IS_CHAN_2GHZ(sta->ni_chan) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ, r);\n\n    /* Report the optimal rate based on rssi and STA caps if we haven't\n     * converged yet (too little traffic) or exploring other modulations\n     */\n    if (lq_sta->rs_state != RS_STATE_STAY_IN_COLUMN) {\n        optimal_rate = rs_get_optimal_rate(mvm, lq_sta);\n        last_ucode_rate = ucode_rate_from_rs_rate(mvm,\n                              optimal_rate);\n        iwl_mvm_hwrate_to_tx_rate(last_ucode_rate, IEEE80211_IS_CHAN_2GHZ(sta->ni_chan) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ,\n                      r);\n    }\n    IOSimpleLockUnlock(mvm->lq_sta.rs_drv.pers.lock);\n}\n\nvoid *rs_drv_alloc_sta(iwm_softc *sc, struct ieee80211_node *ni)\n{\n    struct iwl_lq_sta *lq_sta = &sc->lq_sta.rs_drv;\n\n    IWL_DEBUG_RATE(mvm, \"create station rate scale window\\n\");\n\n    lq_sta->pers.drv = sc;\n    lq_sta->pers.chains = 0;\n    memset(lq_sta->pers.chain_signal, 0, sizeof(lq_sta->pers.chain_signal));\n    lq_sta->pers.last_rssi = S8_MIN;\n\n    return lq_sta;\n}\n\nvoid rs_drv_free_sta(iwm_softc *sc, struct ieee80211_node *ni)\n{}\n\nstatic int rs_vht_highest_rx_mcs_index(struct ieee80211_node *sta,\n                       int nss)\n{\n    u16 rx_mcs = le16_to_cpu(sta->ni_vht_mcsinfo.rx_mcs_map) &\n        (0x3 << (2 * (nss - 1)));\n    rx_mcs >>= (2 * (nss - 1));\n\n    if (rx_mcs == IEEE80211_VHT_MCS_SUPPORT_0_7)\n        return IWL_RATE_MCS_7_INDEX;\n    else if (rx_mcs == IEEE80211_VHT_MCS_SUPPORT_0_8)\n        return IWL_RATE_MCS_8_INDEX;\n    else if (rx_mcs == IEEE80211_VHT_MCS_SUPPORT_0_9)\n        return IWL_RATE_MCS_9_INDEX;\n\n    WARN_ON_ONCE(rx_mcs != IEEE80211_VHT_MCS_NOT_SUPPORTED);\n    return -1;\n}\n\nstatic void rs_vht_set_enabled_rates(struct ieee80211_node *sta,\n                     struct iwl_lq_sta *lq_sta)\n{\n    int i;\n    int highest_mcs = rs_vht_highest_rx_mcs_index(sta, 1);\n\n    if (highest_mcs >= IWL_RATE_MCS_0_INDEX) {\n        for (i = IWL_RATE_MCS_0_INDEX; i <= highest_mcs; i++) {\n            if (i == IWL_RATE_9M_INDEX)\n                continue;\n\n            /* VHT MCS9 isn't valid for 20Mhz for NSS=1,2 */\n            if (i == IWL_RATE_MCS_9_INDEX &&\n                sta->ni_chw == IEEE80211_CHAN_WIDTH_20)\n                continue;\n\n            lq_sta->active_siso_rate |= BIT(i);\n        }\n    }\n\n    if (sta->ni_rx_nss < 2)\n        return;\n\n    highest_mcs = rs_vht_highest_rx_mcs_index(sta, 2);\n    if (highest_mcs >= IWL_RATE_MCS_0_INDEX) {\n        for (i = IWL_RATE_MCS_0_INDEX; i <= highest_mcs; i++) {\n            if (i == IWL_RATE_9M_INDEX)\n                continue;\n\n            /* VHT MCS9 isn't valid for 20Mhz for NSS=1,2 */\n            if (i == IWL_RATE_MCS_9_INDEX &&\n                sta->ni_chw == IEEE80211_CHAN_WIDTH_20)\n                continue;\n\n            lq_sta->active_mimo2_rate |= BIT(i);\n        }\n    }\n}\n\nstatic void rs_ht_init(struct iwm_softc *mvm,\n               struct ieee80211_node *sta,\n               struct iwl_lq_sta *lq_sta)\n{\n    ItlIwm *that = container_of(mvm, ItlIwm, com);\n    /* active_siso_rate mask includes 9 MBits (bit 5),\n     * and CCK (bits 0-3), supp_rates[] does not;\n     * shift to convert format, force 9 MBits off.\n     */\n    lq_sta->active_siso_rate = sta->ni_rxmcs[0] << 1;\n    lq_sta->active_siso_rate |= sta->ni_rxmcs[0] & 0x1;\n    lq_sta->active_siso_rate &= ~((u16)0x2);\n    lq_sta->active_siso_rate <<= IWL_FIRST_OFDM_RATE;\n\n    lq_sta->active_mimo2_rate = sta->ni_rxmcs[1] << 1;\n    lq_sta->active_mimo2_rate |= sta->ni_rxmcs[1] & 0x1;\n    lq_sta->active_mimo2_rate &= ~((u16)0x2);\n    lq_sta->active_mimo2_rate <<= IWL_FIRST_OFDM_RATE;\n\n    if ((sta->ni_htcaps & IEEE80211_HTCAP_LDPC) &&\n        mvm->support_ldpc)\n        lq_sta->ldpc = true;\n\n    if ((that->iwm_num_of_ant(that->iwm_fw_valid_tx_ant(mvm)) > 1) &&\n        (sta->ni_htcaps & IEEE80211_HTCAP_RXSTBC_MASK))\n        lq_sta->stbc_capable = true;\n\n    lq_sta->is_vht = false;\n}\n\nstatic void rs_vht_init(struct iwm_softc *mvm,\n            struct ieee80211_node *sta,\n            struct iwl_lq_sta *lq_sta)\n{\n    ItlIwm *that = container_of(mvm, ItlIwm, com);\n    rs_vht_set_enabled_rates(sta, lq_sta);\n\n    if ((sta->ni_vhtcaps & IEEE80211_VHTCAP_RXLDPC) &&\n        mvm->support_ldpc)\n        lq_sta->ldpc = true;\n\n    if ((that->iwm_num_of_ant(that->iwm_fw_valid_tx_ant(mvm)) > 1) &&\n        (sta->ni_vhtcaps & IEEE80211_VHTCAP_RXSTBC_MASK))\n        lq_sta->stbc_capable = true;\n\n#if 0\n    if (isset(mvm->sc_enabled_capa, IWM_UCODE_TLV_CAPA_BEAMFORMER) &&\n        (that->iwm_num_of_ant(that->iwm_fw_valid_tx_ant(mvm)) > 1) &&\n        (sta->ni_vhtcaps & IEEE80211_VHTCAP_SU_BEAMFORMEE_CAPABLE))\n        lq_sta->bfer_capable = true;\n#endif\n\n    lq_sta->is_vht = true;\n}\n\nstatic u8 iwl_mvm_bt_coex_get_single_ant_msk(struct iwm_softc *mvm, u8 enabled_ants)\n{\n    if (isset(&mvm->sc_enabled_capa, IWM_UCODE_TLV_CAPA_COEX_SCHEMA_2) &&\n        (mvm->non_shared_ant & enabled_ants))\n        return mvm->non_shared_ant;\n\n    return first_antenna(enabled_ants);\n}\n\n/**\n * struct ieee80211_rate - bitrate definition\n *\n * This structure describes a bitrate that an 802.11 PHY can\n * operate with. The two values @hw_value and @hw_value_short\n * are only for driver use when pointers to this structure are\n * passed around.\n *\n * @flags: rate-specific flags\n * @bitrate: bitrate in units of 100 Kbps\n * @hw_value: driver/hardware value for this rate\n * @hw_value_short: driver/hardware value for this rate when\n *    short preamble is used\n */\nstruct ieee80211_rate {\n    u32 flags;\n    u16 bitrate;\n    u16 hw_value, hw_value_short;\n};\n\n/**\n * enum ieee80211_rate_flags - rate flags\n *\n * Hardware/specification flags for rates. These are structured\n * in a way that allows using the same bitrate structure for\n * different bands/PHY modes.\n *\n * @IEEE80211_RATE_SHORT_PREAMBLE: Hardware can send with short\n *    preamble on this bitrate; only relevant in 2.4GHz band and\n *    with CCK rates.\n * @IEEE80211_RATE_MANDATORY_A: This bitrate is a mandatory rate\n *    when used with 802.11a (on the 5 GHz band); filled by the\n *    core code when registering the wiphy.\n * @IEEE80211_RATE_MANDATORY_B: This bitrate is a mandatory rate\n *    when used with 802.11b (on the 2.4 GHz band); filled by the\n *    core code when registering the wiphy.\n * @IEEE80211_RATE_MANDATORY_G: This bitrate is a mandatory rate\n *    when used with 802.11g (on the 2.4 GHz band); filled by the\n *    core code when registering the wiphy.\n * @IEEE80211_RATE_ERP_G: This is an ERP rate in 802.11g mode.\n * @IEEE80211_RATE_SUPPORTS_5MHZ: Rate can be used in 5 MHz mode\n * @IEEE80211_RATE_SUPPORTS_10MHZ: Rate can be used in 10 MHz mode\n */\nenum ieee80211_rate_flags {\n    IEEE80211_RATE_SHORT_PREAMBLE    = 1<<0,\n    IEEE80211_RATE_MANDATORY_A    = 1<<1,\n    IEEE80211_RATE_MANDATORY_B    = 1<<2,\n    IEEE80211_RATE_MANDATORY_G    = 1<<3,\n    IEEE80211_RATE_ERP_G        = 1<<4,\n    IEEE80211_RATE_SUPPORTS_5MHZ    = 1<<5,\n    IEEE80211_RATE_SUPPORTS_10MHZ    = 1<<6,\n};\n\n/*\n * Called after adding a new station to initialize rate scaling\n */\nstatic void rs_drv_rate_init(struct iwm_softc *mvm, struct ieee80211_node *sta,\n                 enum nl80211_band band)\n{\n    int i, j;\n    struct iwl_lq_sta *lq_sta = &mvm->lq_sta.rs_drv;\n    ItlIwm *that = container_of(mvm, ItlIwm, com);\n    uint8_t rate;\n\n//    lockdep_assert_held(&mvmsta->lq_sta.rs_drv.pers.lock);\n\n    /* clear all non-persistent lq data */\n    memset(lq_sta, 0, offsetof(typeof(*lq_sta), pers));\n\n    lq_sta->lq.sta_id = IWM_STATION_ID;\n#if 0\n    mvm->amsdu_enabled = 0;\n    mvm->max_amsdu_len = sta->max_amsdu_len;\n#endif\n\n    for (j = 0; j < LQ_SIZE; j++)\n        rs_rate_scale_clear_tbl_windows(mvm, &lq_sta->lq_info[j]);\n\n    lq_sta->flush_timer = 0;\n    lq_sta->last_tx = ticks;\n\n    IWL_DEBUG_RATE(mvm,\n               \"LQ: *** rate scale station global init for station %d ***\\n\",\n               IWM_STATION_ID);\n    /* TODO: what is a good starting rate for STA? About middle? Maybe not\n     * the lowest or the highest rate.. Could consider using RSSI from\n     * previous packets? Need to have IEEE 802.1X auth succeed immediately\n     * after assoc.. */\n\n    lq_sta->missed_rate_counter = IWL_MVM_RS_MISSED_RATE_MAX;\n    lq_sta->band = band;\n    /*\n     * active legacy rates as per supported rates bitmap\n     */\n    lq_sta->active_legacy_rate = 0;\n    for (i = 0; i < ieee80211_std_rateset_11g.rs_nrates; i++) {\n        for (j = 0; j < sta->ni_rates.rs_nrates; j++) {\n            if (ieee80211_std_rateset_11g.rs_rates[i] ==\n                (sta->ni_rates.rs_rates[j] & IEEE80211_RATE_VAL)) {\n                lq_sta->active_legacy_rate |= BIT(i);\n                break;\n            }\n        }\n    }\n\n    /* TODO: should probably account for rx_highest for both HT/VHT */\n    if ((sta->ni_flags & IEEE80211_NODE_VHT) == 0)\n        rs_ht_init(mvm, sta, lq_sta);\n    else\n        rs_vht_init(mvm, sta, lq_sta);\n\n    lq_sta->max_legacy_rate_idx =\n        rs_get_max_rate_from_mask(lq_sta->active_legacy_rate);\n    lq_sta->max_siso_rate_idx =\n        rs_get_max_rate_from_mask(lq_sta->active_siso_rate);\n    lq_sta->max_mimo2_rate_idx =\n        rs_get_max_rate_from_mask(lq_sta->active_mimo2_rate);\n\n    XYLog(\"LEGACY=%lX SISO=%lX MIMO2=%lX VHT=%d LDPC=%d STBC=%d BFER=%d\\n\",\n               lq_sta->active_legacy_rate,\n               lq_sta->active_siso_rate,\n               lq_sta->active_mimo2_rate,\n               lq_sta->is_vht, lq_sta->ldpc, lq_sta->stbc_capable,\n               lq_sta->bfer_capable);\n    XYLog(\"MAX RATE: LEGACY=%d SISO=%d MIMO2=%d\\n\",\n               lq_sta->max_legacy_rate_idx,\n               lq_sta->max_siso_rate_idx,\n               lq_sta->max_mimo2_rate_idx);\n\n    /* These values will be overridden later */\n    lq_sta->lq.single_stream_ant_msk =\n        iwl_mvm_bt_coex_get_single_ant_msk(mvm, that->iwm_fw_valid_tx_ant(mvm));\n    lq_sta->lq.dual_stream_ant_msk = ANT_AB;\n\n    /* as default allow aggregation for all tids */\n    lq_sta->tx_agg_tid_en = IWL_AGG_ALL_TID;\n    lq_sta->is_agg = 0;\n    rs_initialize_lq(mvm, sta, lq_sta, band);\n}\n\nvoid rs_drv_rate_update(struct iwm_softc *mvm,\n                   struct ieee80211_node *sta,\n                   enum nl80211_band band, u32 changed)\n{\n    /* Stop any ongoing aggregations as rs starts off assuming no agg */\n    ieee80211_stop_ampdu_tx(&mvm->sc_ic, sta, 0);\n\n    iwl_mvm_rs_rate_init(mvm, sta, band, true);\n}\n\nstatic void __iwl_mvm_rs_tx_status(struct iwm_softc *mvm,\n                   struct ieee80211_node *sta,\n                   int tid, struct ieee80211_tx_info *info,\n                   bool ndp)\n{\n    int legacy_success;\n    int retries;\n    int i;\n    struct iwm_lq_cmd *table;\n    u32 lq_hwrate;\n    uint32_t last_rate;\n    struct rs_rate lq_rate, tx_resp_rate;\n    struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl;\n    u32 tlc_info = (u32)(uintptr_t)info->status.status_driver_data[0];\n    u8 reduced_txp = tlc_info & RS_DRV_DATA_TXP_MSK;\n    u8 lq_color = RS_DRV_DATA_LQ_COLOR_GET(tlc_info);\n    u32 tx_resp_hwrate = (u32)(uintptr_t)info->status.status_driver_data[1];\n    struct iwl_lq_sta *lq_sta = &mvm->lq_sta.rs_drv;\n    char pretty_rate[100];\n\n    if (!lq_sta->pers.drv) {\n        IWL_DEBUG_RATE(mvm, \"Rate scaling not initialized yet.\\n\");\n        return;\n    }\n\n    /* This packet was aggregated but doesn't carry status info */\n    if ((info->flags & IEEE80211_TX_CTL_AMPDU) &&\n        !(info->flags & IEEE80211_TX_STAT_AMPDU))\n        return;\n\n    if (rs_rate_from_ucode_rate(tx_resp_hwrate, (enum nl80211_band)info->band,\n                    &tx_resp_rate)) {\n        WARN_ON_ONCE(1);\n        return;\n    }\n\n    if (time_after(ticks,\n               (unsigned long)(lq_sta->last_tx +\n                       (IWL_MVM_RS_IDLE_TIMEOUT * hz)))) {\n        IWL_DEBUG_RATE(mvm, \"Tx idle for too long. reinit rs\\n\");\n        /* reach here only in case of driver RS, call directly\n         * the unlocked version\n         */\n        rs_drv_rate_init(mvm, sta, (nl80211_band)info->band);\n        return;\n    }\n    lq_sta->last_tx = ticks;\n\n    /* Ignore this Tx frame response if its initial rate doesn't match\n     * that of latest Link Quality command.  There may be stragglers\n     * from a previous Link Quality command, but we're no longer interested\n     * in those; they're either from the \"active\" mode while we're trying\n     * to check \"search\" mode, or a prior \"search\" mode after we've moved\n     * to a new \"search\" mode (which might become the new \"active\" mode).\n     */\n    table = &lq_sta->lq;\n    lq_hwrate = le32_to_cpu(table->rs_table[0]);\n    if (rs_rate_from_ucode_rate(lq_hwrate, (enum nl80211_band)info->band, &lq_rate)) {\n        WARN_ON_ONCE(1);\n        return;\n    }\n\n    /* Here we actually compare this rate to the latest LQ command */\n    if (lq_color != LQ_FLAG_COLOR_GET(table->flags)) {\n        IWL_DEBUG_RATE(mvm,\n                   \"tx resp color 0x%x does not match 0x%x\\n\",\n                   lq_color, LQ_FLAG_COLOR_GET(table->flags));\n\n        /* Since rates mis-match, the last LQ command may have failed.\n         * After IWL_MISSED_RATE_MAX mis-matches, resync the uCode with\n         * ... driver.\n         */\n        lq_sta->missed_rate_counter++;\n        if (lq_sta->missed_rate_counter > IWL_MVM_RS_MISSED_RATE_MAX) {\n            lq_sta->missed_rate_counter = 0;\n            IWL_DEBUG_RATE(mvm,\n                       \"Too many rates mismatch. Send sync LQ. rs_state %d\\n\",\n                       lq_sta->rs_state);\n            iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq);\n        }\n        /* Regardless, ignore this status info for outdated rate */\n        return;\n    }\n\n    /* Rate did match, so reset the missed_rate_counter */\n    lq_sta->missed_rate_counter = 0;\n\n    if (!lq_sta->search_better_tbl) {\n        curr_tbl = &lq_sta->lq_info[lq_sta->active_tbl];\n        other_tbl = &lq_sta->lq_info[rs_search_tbl(lq_sta->active_tbl)];\n    } else {\n        curr_tbl = &lq_sta->lq_info[rs_search_tbl(lq_sta->active_tbl)];\n        other_tbl = &lq_sta->lq_info[lq_sta->active_tbl];\n    }\n\n    if (WARN_ON_ONCE(!rs_rate_column_match(&lq_rate, &curr_tbl->rate))) {\n        IWL_DEBUG_RATE(mvm,\n                   \"Neither active nor search matches tx rate\\n\");\n        tmp_tbl = &lq_sta->lq_info[lq_sta->active_tbl];\n        rs_dump_rate(mvm, &tmp_tbl->rate, \"ACTIVE\");\n        tmp_tbl = &lq_sta->lq_info[rs_search_tbl(lq_sta->active_tbl)];\n        rs_dump_rate(mvm, &tmp_tbl->rate, \"SEARCH\");\n        rs_dump_rate(mvm, &lq_rate, \"ACTUAL\");\n\n        /* no matching table found, let's by-pass the data collection\n         * and continue to perform rate scale to find the rate table\n         */\n        rs_stay_in_table(lq_sta, true);\n        goto done;\n    }\n\n    /* Updating the frame history depends on whether packets were\n     * aggregated.\n     *\n     * For aggregation, all packets were transmitted at the same rate, the\n     * first index into rate scale table.\n     */\n    if (info->flags & IEEE80211_TX_STAT_AMPDU) {\n        rs_collect_tpc_data(mvm, lq_sta, curr_tbl, tx_resp_rate.index,\n                    info->status.ampdu_len,\n                    info->status.ampdu_ack_len,\n                    reduced_txp);\n\n        /* ampdu_ack_len = 0 marks no BA was received. For TLC, treat\n         * it as a single frame loss as we don't want the success ratio\n         * to dip too quickly because a BA wasn't received.\n         * For TPC, there's no need for this optimisation since we want\n         * to recover very quickly from a bad power reduction and,\n         * therefore we'd like the success ratio to get an immediate hit\n         * when failing to get a BA, so we'd switch back to a lower or\n         * zero power reduction. When FW transmits agg with a rate\n         * different from the initial rate, it will not use reduced txp\n         * and will send BA notification twice (one empty with reduced\n         * txp equal to the value from LQ and one with reduced txp 0).\n         * We need to update counters for each txp level accordingly.\n         */\n        if (info->status.ampdu_ack_len == 0)\n            info->status.ampdu_len = 1;\n\n        rs_collect_tlc_data(mvm, tid, curr_tbl,\n                    tx_resp_rate.index,\n                    info->status.ampdu_len,\n                    info->status.ampdu_ack_len);\n\n        /* Update success/fail counts if not searching for new mode */\n        if (lq_sta->rs_state == RS_STATE_STAY_IN_COLUMN) {\n            lq_sta->total_success += info->status.ampdu_ack_len;\n            lq_sta->total_failed += (info->status.ampdu_len -\n                    info->status.ampdu_ack_len);\n        }\n    } else {\n        /* For legacy, update frame history with for each Tx retry. */\n        retries = info->status.rates[0].count - 1;\n        /* HW doesn't send more than 15 retries */\n        retries = min(retries, 15);\n\n        /* The last transmission may have been successful */\n        legacy_success = !!(info->flags & IEEE80211_TX_STAT_ACK);\n        /* Collect data for each rate used during failed TX attempts */\n        for (i = 0; i <= retries; ++i) {\n            lq_hwrate = le32_to_cpu(table->rs_table[i]);\n            if (rs_rate_from_ucode_rate(lq_hwrate, (enum nl80211_band)info->band,\n                            &lq_rate)) {\n                WARN_ON_ONCE(1);\n                return;\n            }\n\n            /* Only collect stats if retried rate is in the same RS\n             * table as active/search.\n             */\n            if (rs_rate_column_match(&lq_rate, &curr_tbl->rate))\n                tmp_tbl = curr_tbl;\n            else if (rs_rate_column_match(&lq_rate,\n                              &other_tbl->rate))\n                tmp_tbl = other_tbl;\n            else\n                continue;\n\n            rs_collect_tpc_data(mvm, lq_sta, tmp_tbl,\n                        tx_resp_rate.index, 1,\n                        i < retries ? 0 : legacy_success,\n                        reduced_txp);\n            rs_collect_tlc_data(mvm, tid, tmp_tbl,\n                        tx_resp_rate.index, 1,\n                        i < retries ? 0 : legacy_success);\n        }\n\n        /* Update success/fail counts if not searching for new mode */\n        if (lq_sta->rs_state == RS_STATE_STAY_IN_COLUMN) {\n            lq_sta->total_success += legacy_success;\n            lq_sta->total_failed += retries + (1 - legacy_success);\n        }\n    }\n    /* The last TX rate is cached in lq_sta; it's set in if/else above */\n    last_rate = lq_sta->last_rate_n_flags;\n    lq_sta->last_rate_n_flags = lq_hwrate;\n    if (last_rate != lq_hwrate) {\n        rs_pretty_print_rate(pretty_rate, sizeof(pretty_rate), lq_sta->last_rate_n_flags);\n        XYLog(\"%s new rate: %s\\n\", __FUNCTION__, pretty_rate);\n    }\n    if ((lq_sta->last_rate_n_flags & RATE_MCS_VHT_MSK) || (lq_sta->last_rate_n_flags & RATE_MCS_HE_MSK)) {\n        sta->ni_txmcs = (lq_sta->last_rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK);\n    } else if (lq_sta->last_rate_n_flags & RATE_MCS_HT_MSK) {\n        sta->ni_txmcs = (lq_sta->last_rate_n_flags &\n                        (RATE_HT_MCS_RATE_CODE_MSK |\n                         RATE_HT_MCS_NSS_MSK));\n    } else {\n        int index = iwl_mvm_legacy_rate_to_mac80211_idx(lq_sta->last_rate_n_flags, (enum nl80211_band)info->band);\n        if (index < 0 || index >= ieee80211_std_rateset_11g.rs_nrates)\n            goto done;\n        \n        sta->ni_txrate = ieee80211_std_rateset_11g.rs_rates[index] / 2;\n    }\n    IWL_DEBUG_RATE(mvm, \"reduced txpower: %d\\n\", reduced_txp);\ndone:\n    /* See if there's a better rate or modulation mode to try. */\n    if (/*sta->supp_rates[info->band]*/ true)\n        rs_rate_scale_perform(mvm, sta, lq_sta, tid, ndp);\n}\n\nvoid iwl_mvm_rs_tx_status(struct iwm_softc *mvm, struct ieee80211_node *sta,\n              int tid, struct ieee80211_tx_info *info, bool ndp)\n{\n    /* If it's locked we are in middle of init flow\n     * just wait for next tx status to update the lq_sta data\n     */\n    if (!IOSimpleLockTryLock(mvm->lq_sta.rs_drv.pers.lock))\n        return;\n\n    __iwl_mvm_rs_tx_status(mvm, sta, tid, info, ndp);\n    IOSimpleLockUnlock(mvm->lq_sta.rs_drv.pers.lock);\n}\n\nstatic void rs_fill_rates_for_column(struct iwm_softc *mvm,\n                     struct iwl_lq_sta *lq_sta,\n                     struct rs_rate *rate,\n                     __le32 *rs_table, int *rs_table_index,\n                     int num_rates, int num_retries,\n                     u8 valid_tx_ant, bool toggle_ant)\n{\n    int i, j;\n    __le32 ucode_rate;\n    bool bottom_reached = false;\n    int prev_rate_idx = rate->index;\n    int end = LINK_QUAL_MAX_RETRY_NUM;\n    int index = *rs_table_index;\n\n    for (i = 0; i < num_rates && index < end; i++) {\n        for (j = 0; j < num_retries && index < end; j++, index++) {\n            ucode_rate = cpu_to_le32(ucode_rate_from_rs_rate(mvm,\n                                     rate));\n            rs_table[index] = ucode_rate;\n            if (toggle_ant)\n                rs_toggle_antenna(valid_tx_ant, rate);\n        }\n\n        prev_rate_idx = rate->index;\n        bottom_reached = rs_get_lower_rate_in_column(lq_sta, rate);\n        if (bottom_reached && !is_legacy(rate))\n            break;\n    }\n\n    if (!bottom_reached && !is_legacy(rate))\n        rate->index = prev_rate_idx;\n\n    *rs_table_index = index;\n}\n\n/* Building the rate table is non trivial. When we're in MIMO2/VHT/80Mhz/SGI\n * column the rate table should look like this:\n *\n * rate[0] 0x400F019 VHT | ANT: AB BW: 80Mhz MCS: 9 NSS: 2 SGI\n * rate[1] 0x400F019 VHT | ANT: AB BW: 80Mhz MCS: 9 NSS: 2 SGI\n * rate[2] 0x400F018 VHT | ANT: AB BW: 80Mhz MCS: 8 NSS: 2 SGI\n * rate[3] 0x400F018 VHT | ANT: AB BW: 80Mhz MCS: 8 NSS: 2 SGI\n * rate[4] 0x400F017 VHT | ANT: AB BW: 80Mhz MCS: 7 NSS: 2 SGI\n * rate[5] 0x400F017 VHT | ANT: AB BW: 80Mhz MCS: 7 NSS: 2 SGI\n * rate[6] 0x4005007 VHT | ANT: A BW: 80Mhz MCS: 7 NSS: 1 NGI\n * rate[7] 0x4009006 VHT | ANT: B BW: 80Mhz MCS: 6 NSS: 1 NGI\n * rate[8] 0x4005005 VHT | ANT: A BW: 80Mhz MCS: 5 NSS: 1 NGI\n * rate[9] 0x800B Legacy | ANT: B Rate: 36 Mbps\n * rate[10] 0x4009 Legacy | ANT: A Rate: 24 Mbps\n * rate[11] 0x8007 Legacy | ANT: B Rate: 18 Mbps\n * rate[12] 0x4005 Legacy | ANT: A Rate: 12 Mbps\n * rate[13] 0x800F Legacy | ANT: B Rate: 9 Mbps\n * rate[14] 0x400D Legacy | ANT: A Rate: 6 Mbps\n * rate[15] 0x800D Legacy | ANT: B Rate: 6 Mbps\n */\nstatic void rs_build_rates_table(struct iwm_softc *mvm,\n                 struct ieee80211_node *sta,\n                 struct iwl_lq_sta *lq_sta,\n                 const struct rs_rate *initial_rate)\n{\n    struct rs_rate rate;\n    int num_rates, num_retries, index = 0;\n    u8 valid_tx_ant = 0;\n    struct iwm_lq_cmd *lq_cmd = &lq_sta->lq;\n    bool toggle_ant = false;\n    u32 color;\n    ItlIwm *that = container_of(mvm, ItlIwm, com);\n\n    memcpy(&rate, initial_rate, sizeof(rate));\n\n    valid_tx_ant = that->iwm_fw_valid_tx_ant(mvm);\n\n    /* TODO: remove old API when min FW API hits 14 */\n    if (!isset(&mvm->sc_ucode_api, IWM_UCODE_TLV_API_LQ_SS_PARAMS) &&\n        rs_stbc_allow(mvm, sta, lq_sta))\n        rate.stbc = true;\n\n    if (is_siso(&rate)) {\n        num_rates = IWL_MVM_RS_INITIAL_SISO_NUM_RATES;\n        num_retries = IWL_MVM_RS_HT_VHT_RETRIES_PER_RATE;\n    } else if (is_mimo(&rate)) {\n        num_rates = IWL_MVM_RS_INITIAL_MIMO_NUM_RATES;\n        num_retries = IWL_MVM_RS_HT_VHT_RETRIES_PER_RATE;\n    } else {\n        num_rates = IWL_MVM_RS_INITIAL_LEGACY_NUM_RATES;\n        num_retries = IWL_MVM_RS_INITIAL_LEGACY_RETRIES;\n        toggle_ant = true;\n    }\n\n    rs_fill_rates_for_column(mvm, lq_sta, &rate, (__le32 *)lq_cmd->rs_table, &index,\n                 num_rates, num_retries, valid_tx_ant,\n                 toggle_ant);\n\n    rs_get_lower_rate_down_column(lq_sta, &rate);\n\n    if (is_siso(&rate)) {\n        num_rates = IWL_MVM_RS_SECONDARY_SISO_NUM_RATES;\n        num_retries = IWL_MVM_RS_SECONDARY_SISO_RETRIES;\n        lq_cmd->mimo_delim = index;\n    } else if (is_legacy(&rate)) {\n        num_rates = IWL_MVM_RS_SECONDARY_LEGACY_NUM_RATES;\n        num_retries = IWL_MVM_RS_SECONDARY_LEGACY_RETRIES;\n    } else {\n        WARN_ON_ONCE(1);\n    }\n\n    toggle_ant = true;\n\n    rs_fill_rates_for_column(mvm, lq_sta, &rate, (__le32 *)lq_cmd->rs_table, &index,\n                 num_rates, num_retries, valid_tx_ant,\n                 toggle_ant);\n\n    rs_get_lower_rate_down_column(lq_sta, &rate);\n\n    num_rates = IWL_MVM_RS_SECONDARY_LEGACY_NUM_RATES;\n    num_retries = IWL_MVM_RS_SECONDARY_LEGACY_RETRIES;\n\n    rs_fill_rates_for_column(mvm, lq_sta, &rate, (__le32 *)lq_cmd->rs_table, &index,\n                 num_rates, num_retries, valid_tx_ant,\n                 toggle_ant);\n\n    /* update the color of the LQ command (as a counter at bits 1-3) */\n    color = LQ_FLAGS_COLOR_INC(LQ_FLAG_COLOR_GET(lq_cmd->flags));\n    lq_cmd->flags = LQ_FLAG_COLOR_SET(lq_cmd->flags, color);\n}\n\n#if 0\nstruct rs_bfer_active_iter_data {\n    struct ieee80211_node *exclude_sta;\n    struct ieee80211_node *bfer_mvmsta;\n};\n\nstatic void rs_bfer_active_iter(void *_data,\n                struct ieee80211_node *sta)\n{\n    struct rs_bfer_active_iter_data *data = (struct rs_bfer_active_iter_data *)_data;\n    struct iwm_lq_cmd *lq_cmd = &sta->ni_ic->lq_sta.rs_drv.lq;\n    u32 ss_params = le32_to_cpu(lq_cmd->ss_params);\n\n    if (sta == data->exclude_sta)\n        return;\n\n    /* The current sta has BFER allowed */\n    if (ss_params & LQ_SS_BFER_ALLOWED) {\n        WARN_ON_ONCE(data->bfer_mvmsta != NULL);\n\n        data->bfer_mvmsta = mvmsta;\n    }\n}\n\nstatic int rs_bfer_priority(struct ieee80211_node *sta)\n{\n    return 1;\n}\n\n/* Returns >0 if sta1 has a higher BFER priority compared to sta2 */\nstatic int rs_bfer_priority_cmp(struct ieee80211_node *sta1,\n                struct ieee80211_node *sta2)\n{\n    int prio1 = rs_bfer_priority(sta1);\n    int prio2 = rs_bfer_priority(sta2);\n\n    if (prio1 > prio2)\n        return 1;\n    if (prio1 < prio2)\n        return -1;\n    return 0;\n}\n\nstatic inline void ieee80211_iterate_stations_atomic(struct iwm_softc *hw,\n            void (*iterator)(void *data,\n                     struct ieee80211_node *sta),\n            void *data)\n{\n    iterator(data, hw->sc_ic.ic_bss);\n}\n\n#endif\n\nstatic void rs_set_lq_ss_params(struct iwm_softc *mvm,\n                struct ieee80211_node *sta,\n                struct iwl_lq_sta *lq_sta,\n                const struct rs_rate *initial_rate)\n{\n    struct iwm_lq_cmd *lq_cmd = &lq_sta->lq;\n#if 0\n    struct rs_bfer_active_iter_data data = {\n        .exclude_sta = sta,\n        .bfer_mvmsta = NULL,\n    };\n#endif\n    u32 ss_params = LQ_SS_PARAMS_VALID;\n\n    if (!iwl_mvm_bt_coex_is_mimo_allowed(mvm, sta))\n        goto out;\n\n    if (lq_sta->stbc_capable)\n        ss_params |= LQ_SS_STBC_1SS_ALLOWED;\n\n#if 0\n    if (!lq_sta->bfer_capable)\n        goto out;\n\n    ieee80211_iterate_stations_atomic(mvm,\n                      rs_bfer_active_iter,\n                      &data);\n    bfer_mvmsta = data.bfer_mvmsta;\n\n    /* This code is safe as it doesn't run concurrently for different\n     * stations. This is guaranteed by the fact that calls to\n     * ieee80211_tx_status wouldn't run concurrently for a single HW.\n     */\n    if (!bfer_mvmsta) {\n        IWL_DEBUG_RATE(mvm, \"No sta with BFER allowed found. Allow\\n\");\n\n        ss_params |= LQ_SS_BFER_ALLOWED;\n        goto out;\n    }\n\n    IWL_DEBUG_RATE(mvm, \"Found existing sta %d with BFER activated\\n\",\n               bfer_mvmsta->sta_id);\n\n    /* Disallow BFER on another STA if active and we're a higher priority */\n    if (rs_bfer_priority_cmp(mvmsta, bfer_mvmsta) > 0) {\n        struct iwm_lq_cmd *bfersta_lq_cmd =\n            &bfer_mvmsta->lq_sta.rs_drv.lq;\n        u32 bfersta_ss_params = le32_to_cpu(bfersta_lq_cmd->ss_params);\n\n        bfersta_ss_params &= ~LQ_SS_BFER_ALLOWED;\n        bfersta_lq_cmd->ss_params = cpu_to_le32(bfersta_ss_params);\n        iwl_mvm_send_lq_cmd(mvm, bfersta_lq_cmd);\n\n        ss_params |= LQ_SS_BFER_ALLOWED;\n        IWL_DEBUG_RATE(mvm,\n                   \"Lower priority BFER sta found (%d). Switch BFER\\n\",\n                   bfer_mvmsta->sta_id);\n    }\n#else\n    if (lq_sta->bfer_capable)\n        ss_params |= LQ_SS_BFER_ALLOWED;\n#endif\nout:\n    lq_cmd->ss_params = cpu_to_le32(ss_params);\n}\n\nstatic void rs_fill_lq_cmd(struct iwm_softc *mvm,\n               struct ieee80211_node *sta,\n               struct iwl_lq_sta *lq_sta,\n               const struct rs_rate *initial_rate)\n{\n    struct iwm_lq_cmd *lq_cmd = &lq_sta->lq;\n    ItlIwm *that = container_of(mvm, ItlIwm, com);\n\n    lq_cmd->agg_disable_start_th = IWL_MVM_RS_AGG_DISABLE_START;\n    lq_cmd->agg_time_limit =\n        cpu_to_le16(IWL_MVM_RS_AGG_TIME_LIMIT);\n\n    if (WARN_ON_ONCE(!sta || !initial_rate))\n        return;\n\n    rs_build_rates_table(mvm, sta, lq_sta, initial_rate);\n\n    if (isset(&mvm->sc_ucode_api, IWM_UCODE_TLV_API_LQ_SS_PARAMS))\n        rs_set_lq_ss_params(mvm, sta, lq_sta, initial_rate);\n\n    if (!isset(&mvm->sc_enabled_capa, IWM_UCODE_TLV_CAPA_COEX_SCHEMA_2) &&\n        that->iwm_num_of_ant(initial_rate->ant) == 1)\n        lq_cmd->single_stream_ant_msk = initial_rate->ant;\n\n    lq_cmd->agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_DEF;\n\n#if 0\n    if (mvmsta->vif->p2p)\n        lq_cmd->flags |= LQ_FLAG_USE_RTS_MSK;\n#endif\n\n    lq_cmd->agg_time_limit =\n            cpu_to_le16(that->iwm_coex_agg_time_limit(mvm, sta));\n}\n\nint rs_pretty_print_rate(char *buf, int bufsz, const u32 rate)\n{\n\n    char *type, *bw;\n    u8 mcs = 0, nss = 0;\n    u8 ant = (rate & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS;\n\n    if (!(rate & RATE_MCS_HT_MSK) &&\n        !(rate & RATE_MCS_VHT_MSK) &&\n        !(rate & RATE_MCS_HE_MSK)) {\n        int index = iwl_hwrate_to_plcp_idx(rate);\n\n        return snprintf(buf, bufsz, \"Legacy | ANT: %s Rate: %s Mbps\",\n                 rs_pretty_ant(ant),\n                 index == IWL_RATE_INVALID ? \"BAD\" :\n                 iwl_rate_mcs[index].mbps);\n    }\n\n    if (rate & RATE_MCS_VHT_MSK) {\n        type = \"VHT\";\n        mcs = rate & RATE_VHT_MCS_RATE_CODE_MSK;\n        nss = ((rate & RATE_VHT_MCS_NSS_MSK)\n               >> RATE_VHT_MCS_NSS_POS) + 1;\n    } else if (rate & RATE_MCS_HT_MSK) {\n        type = \"HT\";\n        mcs = rate & RATE_HT_MCS_INDEX_MSK;\n        nss = ((rate & RATE_HT_MCS_NSS_MSK)\n               >> RATE_HT_MCS_NSS_POS) + 1;\n    } else if (rate & RATE_MCS_HE_MSK) {\n        type = \"HE\";\n        mcs = rate & RATE_VHT_MCS_RATE_CODE_MSK;\n        nss = ((rate & RATE_VHT_MCS_NSS_MSK)\n               >> RATE_VHT_MCS_NSS_POS) + 1;\n    } else {\n        type = \"Unknown\"; /* shouldn't happen */\n    }\n\n    switch (rate & RATE_MCS_CHAN_WIDTH_MSK) {\n    case RATE_MCS_CHAN_WIDTH_20:\n        bw = \"20Mhz\";\n        break;\n    case RATE_MCS_CHAN_WIDTH_40:\n        bw = \"40Mhz\";\n        break;\n    case RATE_MCS_CHAN_WIDTH_80:\n        bw = \"80Mhz\";\n        break;\n    case RATE_MCS_CHAN_WIDTH_160:\n        bw = \"160Mhz\";\n        break;\n    default:\n        bw = \"BAD BW\";\n    }\n\n    return snprintf(buf, bufsz,\n             \"0x%x: %s | ANT: %s BW: %s MCS: %d NSS: %d %s%s%s%s%s\",\n             rate, type, rs_pretty_ant(ant), bw, mcs, nss,\n             (rate & RATE_MCS_SGI_MSK) ? \"SGI \" : \"NGI \",\n             (rate & RATE_MCS_STBC_MSK) ? \"STBC \" : \"\",\n             (rate & RATE_MCS_LDPC_MSK) ? \"LDPC \" : \"\",\n             (rate & RATE_HE_DUAL_CARRIER_MODE_MSK) ? \"DCM \" : \"\",\n             (rate & RATE_MCS_BF_MSK) ? \"BF \" : \"\");\n}\n\nvoid iwl_mvm_rs_rate_init(struct iwm_softc *mvm, struct ieee80211_node *sta,\n              enum nl80211_band band, bool update)\n{\n    IOSimpleLockLock(mvm->lq_sta.rs_drv.pers.lock);\n    rs_drv_rate_init(mvm, sta, band);\n    IOSimpleLockUnlock(mvm->lq_sta.rs_drv.pers.lock);\n}\n\nstatic int rs_drv_tx_protection(struct iwm_softc *mvm,\n                bool enable)\n{\n    struct iwm_lq_cmd *lq = &mvm->lq_sta.rs_drv.lq;\n\n    if (enable) {\n        if (mvm->tx_protection == 0)\n            lq->flags |= LQ_FLAG_USE_RTS_MSK;\n        mvm->tx_protection++;\n    } else {\n        mvm->tx_protection--;\n        if (mvm->tx_protection == 0)\n            lq->flags &= ~LQ_FLAG_USE_RTS_MSK;\n    }\n\n    return iwl_mvm_send_lq_cmd(mvm, lq);\n}\n\n/**\n * iwl_mvm_tx_protection - ask FW to enable RTS/CTS protection\n * @mvm: The mvm component\n * @mvmsta: The station\n * @enable: Enable Tx protection?\n */\nint iwl_mvm_tx_protection(struct iwm_softc *mvm,\n              bool enable)\n{\n    return rs_drv_tx_protection(mvm, enable);\n}\n\nvoid\niwm_rs_alloc(struct iwm_softc *sc)\n{\n    sc->lq_sta.rs_drv.pers.lock = IOSimpleLockAlloc();\n}\n\nvoid iwm_rs_free(struct iwm_softc *sc)\n{\n    if (sc->lq_sta.rs_drv.pers.lock) {\n        IOSimpleLockFree(sc->lq_sta.rs_drv.pers.lock);\n        sc->lq_sta.rs_drv.pers.lock = NULL;\n    }\n}\n"
  },
  {
    "path": "itlwm/hal_iwm/rs.h",
    "content": "//\n//  rs.hpp\n//  itlwm\n//\n//  Created by zxystd on 2021/8/27.\n//  Copyright © 2021 钟先耀. All rights reserved.\n//\n\n#ifndef rs_hpp\n#define rs_hpp\n\n#include <sys/param.h>\n#include <sys/conf.h>\n#include <sys/kernel.h>\n#include <sys/malloc.h>\n#include <sys/mbuf.h>\n#include <sys/proc.h>\n#include <sys/socket.h>\n#include <sys/sockio.h>\n#include <sys/systm.h>\n#include <sys/endian.h>\n#include <sys/kpi_mbuf.h>\n\n#include <linux/types.h>\n#include <sys/pcireg.h>\n\n#include <net80211/ieee80211_var.h>\n\n#define IWL_DEBUG_RATE(sc, fmt, x...)\n//#define IWL_DEBUG_RATE(sc, fmt, x...)\\\n//do\\\n//{\\\n//XYLog(\"%s: \" fmt, \"RATE\", ##x);\\\n//}while(0)\n\n#define IWL_ERR(sc, fmt, x...)\\\ndo\\\n{\\\nXYLog(\"RS %s: \" fmt, \"ERR\", ##x);\\\n}while(0)\n\n/**\n * enum nl80211_band - Frequency band\n * @NL80211_BAND_2GHZ: 2.4 GHz ISM band\n * @NL80211_BAND_5GHZ: around 5 GHz band (4.9 - 5.7 GHz)\n * @NUM_NL80211_BANDS: number of bands, avoid using this in userspace\n *    since newer kernel versions may support more bands\n */\nenum nl80211_band {\n    NL80211_BAND_2GHZ,\n    NL80211_BAND_5GHZ,\n\n    NUM_NL80211_BANDS,\n};\n\n/**\n * enum mac80211_tx_info_flags - flags to describe transmission information/status\n *\n * These flags are used with the @flags member of &ieee80211_tx_info.\n *\n * @IEEE80211_TX_CTL_REQ_TX_STATUS: require TX status callback for this frame.\n * @IEEE80211_TX_CTL_ASSIGN_SEQ: The driver has to assign a sequence\n *    number to this frame, taking care of not overwriting the fragment\n *    number and increasing the sequence number only when the\n *    IEEE80211_TX_CTL_FIRST_FRAGMENT flag is set. mac80211 will properly\n *    assign sequence numbers to QoS-data frames but cannot do so correctly\n *    for non-QoS-data and management frames because beacons need them from\n *    that counter as well and mac80211 cannot guarantee proper sequencing.\n *    If this flag is set, the driver should instruct the hardware to\n *    assign a sequence number to the frame or assign one itself. Cf. IEEE\n *    802.11-2007 7.1.3.4.1 paragraph 3. This flag will always be set for\n *    beacons and always be clear for frames without a sequence number field.\n * @IEEE80211_TX_CTL_NO_ACK: tell the low level not to wait for an ack\n * @IEEE80211_TX_CTL_CLEAR_PS_FILT: clear powersave filter for destination\n *    station\n * @IEEE80211_TX_CTL_FIRST_FRAGMENT: this is a first fragment of the frame\n * @IEEE80211_TX_CTL_SEND_AFTER_DTIM: send this frame after DTIM beacon\n * @IEEE80211_TX_CTL_AMPDU: this frame should be sent as part of an A-MPDU\n * @IEEE80211_TX_CTL_INJECTED: Frame was injected, internal to mac80211.\n * @IEEE80211_TX_STAT_TX_FILTERED: The frame was not transmitted\n *    because the destination STA was in powersave mode. Note that to\n *    avoid race conditions, the filter must be set by the hardware or\n *    firmware upon receiving a frame that indicates that the station\n *    went to sleep (must be done on device to filter frames already on\n *    the queue) and may only be unset after mac80211 gives the OK for\n *    that by setting the IEEE80211_TX_CTL_CLEAR_PS_FILT (see above),\n *    since only then is it guaranteed that no more frames are in the\n *    hardware queue.\n * @IEEE80211_TX_STAT_ACK: Frame was acknowledged\n * @IEEE80211_TX_STAT_AMPDU: The frame was aggregated, so status\n *     is for the whole aggregation.\n * @IEEE80211_TX_STAT_AMPDU_NO_BACK: no block ack was returned,\n *     so consider using block ack request (BAR).\n * @IEEE80211_TX_CTL_RATE_CTRL_PROBE: internal to mac80211, can be\n *    set by rate control algorithms to indicate probe rate, will\n *    be cleared for fragmented frames (except on the last fragment)\n * @IEEE80211_TX_INTFL_OFFCHAN_TX_OK: Internal to mac80211. Used to indicate\n *    that a frame can be transmitted while the queues are stopped for\n *    off-channel operation.\n * @IEEE80211_TX_CTL_HW_80211_ENCAP: This frame uses hardware encapsulation\n *    (header conversion)\n * @IEEE80211_TX_INTFL_RETRIED: completely internal to mac80211,\n *    used to indicate that a frame was already retried due to PS\n * @IEEE80211_TX_INTFL_DONT_ENCRYPT: completely internal to mac80211,\n *    used to indicate frame should not be encrypted\n * @IEEE80211_TX_CTL_NO_PS_BUFFER: This frame is a response to a poll\n *    frame (PS-Poll or uAPSD) or a non-bufferable MMPDU and must\n *    be sent although the station is in powersave mode.\n * @IEEE80211_TX_CTL_MORE_FRAMES: More frames will be passed to the\n *    transmit function after the current frame, this can be used\n *    by drivers to kick the DMA queue only if unset or when the\n *    queue gets full.\n * @IEEE80211_TX_INTFL_RETRANSMISSION: This frame is being retransmitted\n *    after TX status because the destination was asleep, it must not\n *    be modified again (no seqno assignment, crypto, etc.)\n * @IEEE80211_TX_INTFL_MLME_CONN_TX: This frame was transmitted by the MLME\n *    code for connection establishment, this indicates that its status\n *    should kick the MLME state machine.\n * @IEEE80211_TX_INTFL_NL80211_FRAME_TX: Frame was requested through nl80211\n *    MLME command (internal to mac80211 to figure out whether to send TX\n *    status to user space)\n * @IEEE80211_TX_CTL_LDPC: tells the driver to use LDPC for this frame\n * @IEEE80211_TX_CTL_STBC: Enables Space-Time Block Coding (STBC) for this\n *    frame and selects the maximum number of streams that it can use.\n * @IEEE80211_TX_CTL_TX_OFFCHAN: Marks this packet to be transmitted on\n *    the off-channel channel when a remain-on-channel offload is done\n *    in hardware -- normal packets still flow and are expected to be\n *    handled properly by the device.\n * @IEEE80211_TX_INTFL_TKIP_MIC_FAILURE: Marks this packet to be used for TKIP\n *    testing. It will be sent out with incorrect Michael MIC key to allow\n *    TKIP countermeasures to be tested.\n * @IEEE80211_TX_CTL_NO_CCK_RATE: This frame will be sent at non CCK rate.\n *    This flag is actually used for management frame especially for P2P\n *    frames not being sent at CCK rate in 2GHz band.\n * @IEEE80211_TX_STATUS_EOSP: This packet marks the end of service period,\n *    when its status is reported the service period ends. For frames in\n *    an SP that mac80211 transmits, it is already set; for driver frames\n *    the driver may set this flag. It is also used to do the same for\n *    PS-Poll responses.\n * @IEEE80211_TX_CTL_USE_MINRATE: This frame will be sent at lowest rate.\n *    This flag is used to send nullfunc frame at minimum rate when\n *    the nullfunc is used for connection monitoring purpose.\n * @IEEE80211_TX_CTL_DONTFRAG: Don't fragment this packet even if it\n *    would be fragmented by size (this is optional, only used for\n *    monitor injection).\n * @IEEE80211_TX_STAT_NOACK_TRANSMITTED: A frame that was marked with\n *    IEEE80211_TX_CTL_NO_ACK has been successfully transmitted without\n *    any errors (like issues specific to the driver/HW).\n *    This flag must not be set for frames that don't request no-ack\n *    behaviour with IEEE80211_TX_CTL_NO_ACK.\n *\n * Note: If you have to add new flags to the enumeration, then don't\n *     forget to update %IEEE80211_TX_TEMPORARY_FLAGS when necessary.\n */\nenum mac80211_tx_info_flags {\n    IEEE80211_TX_CTL_REQ_TX_STATUS        = BIT(0),\n    IEEE80211_TX_CTL_ASSIGN_SEQ        = BIT(1),\n    IEEE80211_TX_CTL_NO_ACK            = BIT(2),\n    IEEE80211_TX_CTL_CLEAR_PS_FILT        = BIT(3),\n    IEEE80211_TX_CTL_FIRST_FRAGMENT        = BIT(4),\n    IEEE80211_TX_CTL_SEND_AFTER_DTIM    = BIT(5),\n    IEEE80211_TX_CTL_AMPDU            = BIT(6),\n    IEEE80211_TX_CTL_INJECTED        = BIT(7),\n    IEEE80211_TX_STAT_TX_FILTERED        = BIT(8),\n    IEEE80211_TX_STAT_ACK            = BIT(9),\n    IEEE80211_TX_STAT_AMPDU            = BIT(10),\n    IEEE80211_TX_STAT_AMPDU_NO_BACK        = BIT(11),\n    IEEE80211_TX_CTL_RATE_CTRL_PROBE    = BIT(12),\n    IEEE80211_TX_INTFL_OFFCHAN_TX_OK    = BIT(13),\n    IEEE80211_TX_CTL_HW_80211_ENCAP        = BIT(14),\n    IEEE80211_TX_INTFL_RETRIED        = BIT(15),\n    IEEE80211_TX_INTFL_DONT_ENCRYPT        = BIT(16),\n    IEEE80211_TX_CTL_NO_PS_BUFFER        = BIT(17),\n    IEEE80211_TX_CTL_MORE_FRAMES        = BIT(18),\n    IEEE80211_TX_INTFL_RETRANSMISSION    = BIT(19),\n    IEEE80211_TX_INTFL_MLME_CONN_TX        = BIT(20),\n    IEEE80211_TX_INTFL_NL80211_FRAME_TX    = BIT(21),\n    IEEE80211_TX_CTL_LDPC            = BIT(22),\n    IEEE80211_TX_CTL_STBC            = BIT(23) | BIT(24),\n    IEEE80211_TX_CTL_TX_OFFCHAN        = BIT(25),\n    IEEE80211_TX_INTFL_TKIP_MIC_FAILURE    = BIT(26),\n    IEEE80211_TX_CTL_NO_CCK_RATE        = BIT(27),\n    IEEE80211_TX_STATUS_EOSP        = BIT(28),\n    IEEE80211_TX_CTL_USE_MINRATE        = BIT(29),\n    IEEE80211_TX_CTL_DONTFRAG        = BIT(30),\n    IEEE80211_TX_STAT_NOACK_TRANSMITTED    = BIT(31),\n};\n\n/**\n * enum mac80211_rate_control_flags - per-rate flags set by the\n *    Rate Control algorithm.\n *\n * These flags are set by the Rate control algorithm for each rate during tx,\n * in the @flags member of struct ieee80211_tx_rate.\n *\n * @IEEE80211_TX_RC_USE_RTS_CTS: Use RTS/CTS exchange for this rate.\n * @IEEE80211_TX_RC_USE_CTS_PROTECT: CTS-to-self protection is required.\n *    This is set if the current BSS requires ERP protection.\n * @IEEE80211_TX_RC_USE_SHORT_PREAMBLE: Use short preamble.\n * @IEEE80211_TX_RC_MCS: HT rate.\n * @IEEE80211_TX_RC_VHT_MCS: VHT MCS rate, in this case the idx field is split\n *    into a higher 4 bits (Nss) and lower 4 bits (MCS number)\n * @IEEE80211_TX_RC_GREEN_FIELD: Indicates whether this rate should be used in\n *    Greenfield mode.\n * @IEEE80211_TX_RC_40_MHZ_WIDTH: Indicates if the Channel Width should be 40 MHz.\n * @IEEE80211_TX_RC_80_MHZ_WIDTH: Indicates 80 MHz transmission\n * @IEEE80211_TX_RC_160_MHZ_WIDTH: Indicates 160 MHz transmission\n *    (80+80 isn't supported yet)\n * @IEEE80211_TX_RC_DUP_DATA: The frame should be transmitted on both of the\n *    adjacent 20 MHz channels, if the current channel type is\n *    NL80211_CHAN_HT40MINUS or NL80211_CHAN_HT40PLUS.\n * @IEEE80211_TX_RC_SHORT_GI: Short Guard interval should be used for this rate.\n */\nenum mac80211_rate_control_flags {\n    IEEE80211_TX_RC_USE_RTS_CTS        = BIT(0),\n    IEEE80211_TX_RC_USE_CTS_PROTECT        = BIT(1),\n    IEEE80211_TX_RC_USE_SHORT_PREAMBLE    = BIT(2),\n\n    /* rate index is an HT/VHT MCS instead of an index */\n    IEEE80211_TX_RC_MCS            = BIT(3),\n    IEEE80211_TX_RC_GREEN_FIELD        = BIT(4),\n    IEEE80211_TX_RC_40_MHZ_WIDTH        = BIT(5),\n    IEEE80211_TX_RC_DUP_DATA        = BIT(6),\n    IEEE80211_TX_RC_SHORT_GI        = BIT(7),\n    IEEE80211_TX_RC_VHT_MCS            = BIT(8),\n    IEEE80211_TX_RC_80_MHZ_WIDTH        = BIT(9),\n    IEEE80211_TX_RC_160_MHZ_WIDTH        = BIT(10),\n};\n\n/**\n * struct ieee80211_rx_status - receive status\n *\n * The low-level driver should provide this information (the subset\n * supported by hardware) to the 802.11 code with each received\n * frame, in the skb's control buffer (cb).\n *\n * @mactime: value in microseconds of the 64-bit Time Synchronization Function\n *     (TSF) timer when the first data symbol (MPDU) arrived at the hardware.\n * @boottime_ns: CLOCK_BOOTTIME timestamp the frame was received at, this is\n *    needed only for beacons and probe responses that update the scan cache.\n * @device_timestamp: arbitrary timestamp for the device, mac80211 doesn't use\n *    it but can store it and pass it back to the driver for synchronisation\n * @band: the active band when this frame was received\n * @freq: frequency the radio was tuned to when receiving this frame, in MHz\n *    This field must be set for management frames, but isn't strictly needed\n *    for data (other) frames - for those it only affects radiotap reporting.\n * @freq_offset: @freq has a positive offset of 500Khz.\n * @signal: signal strength when receiving this frame, either in dBm, in dB or\n *    unspecified depending on the hardware capabilities flags\n *    @IEEE80211_HW_SIGNAL_*\n * @chains: bitmask of receive chains for which separate signal strength\n *    values were filled.\n * @chain_signal: per-chain signal strength, in dBm (unlike @signal, doesn't\n *    support dB or unspecified units)\n * @antenna: antenna used\n * @rate_idx: index of data rate into band's supported rates or MCS index if\n *    HT or VHT is used (%RX_FLAG_HT/%RX_FLAG_VHT)\n * @nss: number of streams (VHT and HE only)\n * @flag: %RX_FLAG_\\*\n * @encoding: &enum mac80211_rx_encoding\n * @bw: &enum rate_info_bw\n * @enc_flags: uses bits from &enum mac80211_rx_encoding_flags\n * @he_ru: HE RU, from &enum nl80211_he_ru_alloc\n * @he_gi: HE GI, from &enum nl80211_he_gi\n * @he_dcm: HE DCM value\n * @rx_flags: internal RX flags for mac80211\n * @ampdu_reference: A-MPDU reference number, must be a different value for\n *    each A-MPDU but the same for each subframe within one A-MPDU\n * @ampdu_delimiter_crc: A-MPDU delimiter CRC\n * @zero_length_psdu_type: radiotap type of the 0-length PSDU\n */\nstruct ieee80211_rx_status {\n//    u64 mactime;\n//    u64 boottime_ns;\n//    u32 device_timestamp;\n//    u32 ampdu_reference;\n//    u32 flag;\n//    u16 freq: 13, freq_offset: 1;\n//    u8 enc_flags;\n//    u8 encoding:2, bw:3, he_ru:3;\n//    u8 he_gi:2, he_dcm:1;\n//    u8 rate_idx;\n//    u8 nss;\n//    u8 rx_flags;\n//    u8 band;\n//    u8 antenna;\n    s8 signal;\n    u8 chains;\n    s8 chain_signal[4];\n//    u8 ampdu_delimiter_crc;\n//    u8 zero_length_psdu_type;\n};\n\n/**\n * struct ieee80211_tx_rate - rate selection/status\n *\n * @idx: rate index to attempt to send with\n * @flags: rate control flags (&enum mac80211_rate_control_flags)\n * @count: number of tries in this rate before going to the next rate\n *\n * A value of -1 for @idx indicates an invalid rate and, if used\n * in an array of retry rates, that no more rates should be tried.\n *\n * When used for transmit status reporting, the driver should\n * always report the rate along with the flags it used.\n *\n * &struct ieee80211_tx_info contains an array of these structs\n * in the control information, and it will be filled by the rate\n * control algorithm according to what should be sent. For example,\n * if this array contains, in the format { <idx>, <count> } the\n * information::\n *\n *    { 3, 2 }, { 2, 2 }, { 1, 4 }, { -1, 0 }, { -1, 0 }\n *\n * then this means that the frame should be transmitted\n * up to twice at rate 3, up to twice at rate 2, and up to four\n * times at rate 1 if it doesn't get acknowledged. Say it gets\n * acknowledged by the peer after the fifth attempt, the status\n * information should then contain::\n *\n *   { 3, 2 }, { 2, 2 }, { 1, 1 }, { -1, 0 } ...\n *\n * since it was transmitted twice at rate 3, twice at rate 2\n * and once at rate 1 after which we received an acknowledgement.\n */\nstruct ieee80211_tx_rate {\n    s8 idx;\n    u16 count:5,\n        flags:11;\n} __packed;\n\nstruct ieee80211_tx_info {\n    /* common information */\n    u32 flags;\n    u32 band:3,\n        ack_frame_id:13,\n        hw_queue:4,\n        tx_time_est:10;\n    /* 2 free bits */\n\n    union {\n        struct {\n            struct ieee80211_tx_rate rates[4];\n            s32 ack_signal;\n            u8 ampdu_ack_len;\n            u8 ampdu_len;\n            u8 antenna;\n            u16 tx_time;\n            bool is_valid_ack_signal;\n            void *status_driver_data[19 / sizeof(void *)];\n        } status;\n    };\n};\n\n/**\n * struct ieee80211_mcs_info - MCS information\n * @rx_mask: RX mask\n * @rx_highest: highest supported RX rate. If set represents\n *    the highest supported RX data rate in units of 1 Mbps.\n *    If this field is 0 this value should not be used to\n *    consider the highest RX data rate supported.\n * @tx_params: TX parameters\n */\nstruct ieee80211_mcs_info {\n    u8 rx_mask[10];\n    __le16 rx_highest;\n    u8 tx_params;\n    u8 reserved[3];\n} __packed;\n\n/**\n * struct ieee80211_sta_ht_cap - STA's HT capabilities\n *\n * This structure describes most essential parameters needed\n * to describe 802.11n HT capabilities for an STA.\n *\n * @ht_supported: is HT supported by the STA\n * @cap: HT capabilities map as described in 802.11n spec\n * @ampdu_factor: Maximum A-MPDU length factor\n * @ampdu_density: Minimum A-MPDU spacing\n * @mcs: Supported MCS rates\n */\nstruct ieee80211_sta_ht_cap {\n    u16 cap; /* use IEEE80211_HT_CAP_ */\n    bool ht_supported;\n    u8 ampdu_factor;\n    u8 ampdu_density;\n    struct ieee80211_mcs_info mcs;\n};\n\n/**\n * struct ieee80211_sta_vht_cap - STA's VHT capabilities\n *\n * This structure describes most essential parameters needed\n * to describe 802.11ac VHT capabilities for an STA.\n *\n * @vht_supported: is VHT supported by the STA\n * @cap: VHT capabilities map as described in 802.11ac spec\n * @vht_mcs: Supported VHT MCS rates\n */\nstruct ieee80211_sta_vht_cap {\n    bool vht_supported;\n    u32 cap; /* use IEEE80211_VHT_CAP_ */\n    struct ieee80211_vht_mcs_info vht_mcs;\n};\n\n/**\n * struct ieee80211_vht_cap - VHT capabilities\n *\n * This structure is the \"VHT capabilities element\" as\n * described in 802.11ac D3.0 8.4.2.160\n * @vht_cap_info: VHT capability info\n * @supp_mcs: VHT MCS supported rates\n */\nstruct ieee80211_vht_cap {\n    __le32 vht_cap_info;\n    struct ieee80211_vht_mcs_info supp_mcs;\n} __packed;\n\nstatic inline int ieee80211_get_vht_max_nss(struct ieee80211_vht_cap *cap,\n                  int bw,\n                  int mcs, bool ext_nss_bw_capable,\n                  unsigned int max_vht_nss)\n{\n    u16 map = le16_to_cpu(cap->supp_mcs.rx_mcs_map);\n    int ext_nss_bw;\n    int supp_width;\n    int i, mcs_encoding;\n\n    if (map == 0xffff)\n        return 0;\n\n    if (WARN_ON(mcs > 9 || max_vht_nss > 8))\n        return 0;\n    if (mcs <= 7)\n        mcs_encoding = 0;\n    else if (mcs == 8)\n        mcs_encoding = 1;\n    else\n        mcs_encoding = 2;\n\n    if (!max_vht_nss) {\n        /* find max_vht_nss for the given MCS */\n        for (i = 7; i >= 0; i--) {\n            int supp = (map >> (2 * i)) & 3;\n\n            if (supp == 3)\n                continue;\n\n            if (supp >= mcs_encoding) {\n                max_vht_nss = i + 1;\n                break;\n            }\n        }\n    }\n\n    if (!(cap->supp_mcs.tx_mcs_map &\n            cpu_to_le16(IEEE80211_VHT_EXT_NSS_BW_CAPABLE)))\n        return max_vht_nss;\n\n    ext_nss_bw = le32_get_bits(cap->vht_cap_info,\n                   IEEE80211_VHTCAP_EXT_NSS_BW_MASK);\n    supp_width = le32_get_bits(cap->vht_cap_info,\n                   IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_MASK);\n\n    /* if not capable, treat ext_nss_bw as 0 */\n    if (!ext_nss_bw_capable)\n        ext_nss_bw = 0;\n\n    /* This is invalid */\n    if (supp_width == 3)\n        return 0;\n\n    /* This is an invalid combination so pretend nothing is supported */\n    if (supp_width == 2 && (ext_nss_bw == 1 || ext_nss_bw == 2))\n        return 0;\n\n    /*\n     * Cover all the special cases according to IEEE 802.11-2016\n     * Table 9-250. All other cases are either factor of 1 or not\n     * valid/supported.\n     */\n    switch (bw) {\n    case IEEE80211_VHT_CHANWIDTH_USE_HT:\n    case IEEE80211_VHT_CHANWIDTH_80MHZ:\n        if ((supp_width == 1 || supp_width == 2) &&\n            ext_nss_bw == 3)\n            return 2 * max_vht_nss;\n        break;\n    case IEEE80211_VHT_CHANWIDTH_160MHZ:\n        if (supp_width == 0 &&\n            (ext_nss_bw == 1 || ext_nss_bw == 2))\n            return max_vht_nss / 2;\n        if (supp_width == 0 &&\n            ext_nss_bw == 3)\n            return (3 * max_vht_nss) / 4;\n        if (supp_width == 1 &&\n            ext_nss_bw == 3)\n            return 2 * max_vht_nss;\n        break;\n    case IEEE80211_VHT_CHANWIDTH_80P80MHZ:\n        if (supp_width == 0 && ext_nss_bw == 1)\n            return 0; /* not possible */\n        if (supp_width == 0 &&\n            ext_nss_bw == 2)\n            return max_vht_nss / 2;\n        if (supp_width == 0 &&\n            ext_nss_bw == 3)\n            return (3 * max_vht_nss) / 4;\n        if (supp_width == 1 &&\n            ext_nss_bw == 0)\n            return 0; /* not possible */\n        if (supp_width == 1 &&\n            ext_nss_bw == 1)\n            return max_vht_nss / 2;\n        if (supp_width == 1 &&\n            ext_nss_bw == 2)\n            return (3 * max_vht_nss) / 4;\n        break;\n    }\n\n    /* not covered or invalid combination received */\n    return max_vht_nss;\n}\n\n#define IWL_MVM_UAPSD_NOAGG_BSSIDS_NUM        20\n\n#define IWL_MVM_DEFAULT_PS_TX_DATA_TIMEOUT    (100 * USEC_PER_MSEC)\n#define IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT    (100 * USEC_PER_MSEC)\n#define IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT    (10 * USEC_PER_MSEC)\n#define IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT    (10 * USEC_PER_MSEC)\n#define IWL_MVM_SHORT_PS_TX_DATA_TIMEOUT    (2 * 1024) /* defined in TU */\n#define IWL_MVM_SHORT_PS_RX_DATA_TIMEOUT    (40 * 1024) /* defined in TU */\n#define IWL_MVM_P2P_LOWLATENCY_PS_ENABLE    0\n#define IWL_MVM_UAPSD_RX_DATA_TIMEOUT        (50 * USEC_PER_MSEC)\n#define IWL_MVM_UAPSD_TX_DATA_TIMEOUT        (50 * USEC_PER_MSEC)\n#define IWL_MVM_UAPSD_QUEUES        (IEEE80211_WMM_IE_STA_QOSINFO_AC_VO |\\\n                     IEEE80211_WMM_IE_STA_QOSINFO_AC_VI |\\\n                     IEEE80211_WMM_IE_STA_QOSINFO_AC_BK |\\\n                     IEEE80211_WMM_IE_STA_QOSINFO_AC_BE)\n#define IWL_MVM_PS_HEAVY_TX_THLD_PACKETS    20\n#define IWL_MVM_PS_HEAVY_RX_THLD_PACKETS    8\n#define IWL_MVM_PS_SNOOZE_HEAVY_TX_THLD_PACKETS    30\n#define IWL_MVM_PS_SNOOZE_HEAVY_RX_THLD_PACKETS    20\n#define IWL_MVM_PS_HEAVY_TX_THLD_PERCENT    50\n#define IWL_MVM_PS_HEAVY_RX_THLD_PERCENT    50\n#define IWL_MVM_PS_SNOOZE_INTERVAL        25\n#define IWL_MVM_PS_SNOOZE_WINDOW        50\n#define IWL_MVM_WOWLAN_PS_SNOOZE_WINDOW        25\n#define IWL_MVM_LOWLAT_QUOTA_MIN_PERCENT    64\n#define IWL_MVM_BT_COEX_EN_RED_TXP_THRESH    62\n#define IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH    65\n#define IWL_MVM_BT_COEX_SYNC2SCO        1\n#define IWL_MVM_BT_COEX_MPLUT            1\n#define IWL_MVM_BT_COEX_RRC            1\n#define IWL_MVM_BT_COEX_TTC            1\n#define IWL_MVM_BT_COEX_MPLUT_REG0        0x22002200\n#define IWL_MVM_BT_COEX_MPLUT_REG1        0x11118451\n#define IWL_MVM_BT_COEX_ANTENNA_COUPLING_THRS    30\n#define IWL_MVM_FW_MCAST_FILTER_PASS_ALL    0\n#define IWL_MVM_FW_BCAST_FILTER_PASS_ALL    0\n#define IWL_MVM_QUOTA_THRESHOLD            4\n#define IWL_MVM_RS_RSSI_BASED_INIT_RATE         0\n#define IWL_MVM_RS_80_20_FAR_RANGE_TWEAK    1\n#define IWL_MVM_TOF_IS_RESPONDER        0\n#define IWL_MVM_HW_CSUM_DISABLE            0\n#define IWL_MVM_PARSE_NVM            0\n#define IWL_MVM_ADWELL_ENABLE            1\n#define IWL_MVM_ADWELL_MAX_BUDGET        0\n#define IWL_MVM_TCM_LOAD_MEDIUM_THRESH        10 /* percentage */\n#define IWL_MVM_TCM_LOAD_HIGH_THRESH        50 /* percentage */\n#define IWL_MVM_TCM_LOWLAT_ENABLE_THRESH    100 /* packets/10 seconds */\n#define IWL_MVM_UAPSD_NONAGG_PERIOD        5000 /* msecs */\n#define IWL_MVM_UAPSD_NOAGG_LIST_LEN        IWL_MVM_UAPSD_NOAGG_BSSIDS_NUM\n#define IWL_MVM_NON_TRANSMITTING_AP        0\n#define IWL_MVM_RS_NUM_TRY_BEFORE_ANT_TOGGLE    1\n#define IWL_MVM_RS_HT_VHT_RETRIES_PER_RATE      2\n#define IWL_MVM_RS_HT_VHT_RETRIES_PER_RATE_TW   1\n#define IWL_MVM_RS_INITIAL_MIMO_NUM_RATES       3\n#define IWL_MVM_RS_INITIAL_SISO_NUM_RATES       3\n#define IWL_MVM_RS_INITIAL_LEGACY_NUM_RATES     2\n#define IWL_MVM_RS_INITIAL_LEGACY_RETRIES       2\n#define IWL_MVM_RS_SECONDARY_LEGACY_RETRIES    1\n#define IWL_MVM_RS_SECONDARY_LEGACY_NUM_RATES   16\n#define IWL_MVM_RS_SECONDARY_SISO_NUM_RATES     3\n#define IWL_MVM_RS_SECONDARY_SISO_RETRIES       1\n#define IWL_MVM_RS_RATE_MIN_FAILURE_TH        3\n#define IWL_MVM_RS_RATE_MIN_SUCCESS_TH        8\n#define IWL_MVM_RS_STAY_IN_COLUMN_TIMEOUT    5    /* Seconds */\n#define IWL_MVM_RS_IDLE_TIMEOUT            5    /* Seconds */\n#define IWL_MVM_RS_MISSED_RATE_MAX        15\n#define IWL_MVM_RS_LEGACY_FAILURE_LIMIT        160\n#define IWL_MVM_RS_LEGACY_SUCCESS_LIMIT        480\n#define IWL_MVM_RS_LEGACY_TABLE_COUNT        160\n#define IWL_MVM_RS_NON_LEGACY_FAILURE_LIMIT    400\n#define IWL_MVM_RS_NON_LEGACY_SUCCESS_LIMIT    4500\n#define IWL_MVM_RS_NON_LEGACY_TABLE_COUNT    1500\n#define IWL_MVM_RS_SR_FORCE_DECREASE        15    /* percent */\n#define IWL_MVM_RS_SR_NO_DECREASE        85    /* percent */\n#define IWL_MVM_RS_AGG_TIME_LIMIT            4000    /* 4 msecs. valid 100-8000 */\n#define IWL_MVM_RS_AGG_DISABLE_START            3\n#define IWL_MVM_RS_AGG_START_THRESHOLD            10    /* num frames per second */\n#define IWL_MVM_RS_TPC_SR_FORCE_INCREASE    75    /* percent */\n#define IWL_MVM_RS_TPC_SR_NO_INCREASE        85    /* percent */\n#define IWL_MVM_RS_TPC_TX_POWER_STEP        3\n#define IWL_MVM_ENABLE_EBS            1\n#define IWL_MVM_FTM_INITIATOR_ALGO        IWL_TOF_ALGO_TYPE_MAX_LIKE\n#define IWL_MVM_FTM_INITIATOR_DYNACK        true\n#define IWL_MVM_FTM_R2I_MAX_REP            7\n#define IWL_MVM_FTM_I2R_MAX_REP            7\n#define IWL_MVM_FTM_R2I_MAX_STS            1\n#define IWL_MVM_FTM_I2R_MAX_STS            1\n#define IWL_MVM_FTM_R2I_MAX_TOTAL_LTF        3\n#define IWL_MVM_FTM_I2R_MAX_TOTAL_LTF        3\n#define IWL_MVM_FTM_INITIATOR_SECURE_LTF    false\n#define IWL_MVM_FTM_RESP_NDP_SUPPORT        true\n#define IWL_MVM_FTM_RESP_LMR_FEEDBACK_SUPPORT    true\n#define IWL_MVM_D3_DEBUG            false\n#define IWL_MVM_USE_TWT                true\n#define IWL_MVM_AMPDU_CONSEC_DROPS_DELBA    10\n#define IWL_MVM_USE_NSSN_SYNC            0\n#define IWL_MVM_PHY_FILTER_CHAIN_A        0\n#define IWL_MVM_PHY_FILTER_CHAIN_B        0\n#define IWL_MVM_PHY_FILTER_CHAIN_C        0\n#define IWL_MVM_PHY_FILTER_CHAIN_D        0\n#define IWL_MVM_FTM_INITIATOR_ENABLE_SMOOTH     false\n#define IWL_MVM_FTM_INITIATOR_SMOOTH_ALPHA      40\n/*  20016 pSec is 6 meter RTT, meaning 3 meter range */\n#define IWL_MVM_FTM_INITIATOR_SMOOTH_UNDERSHOOT 20016\n#define IWL_MVM_FTM_INITIATOR_SMOOTH_OVERSHOOT  20016\n#define IWL_MVM_FTM_INITIATOR_SMOOTH_AGE_SEC    2\n#define IWL_MVM_DISABLE_AP_FILS            false\n#define IWL_MVM_6GHZ_PASSIVE_SCAN_TIMEOUT       3000 /* in seconds */\n#define IWL_MVM_6GHZ_PASSIVE_SCAN_ASSOC_TIMEOUT 60   /* in seconds */\n\n#define IWL_MAX_TID_COUNT    8\n#define IWL_MGMT_TID        15\n#define IWL_FRAME_LIMIT    64\n#define IWL_MAX_RX_HW_QUEUES    16\n#define IWL_9000_MAX_RX_HW_QUEUES    6\n\n/* Antenna presence definitions */\n#define    ANT_NONE    0x0\n#define    ANT_INVALID    0xff\n#define    ANT_A        BIT(0)\n#define    ANT_B        BIT(1)\n#define ANT_C        BIT(2)\n#define    ANT_AB        (ANT_A | ANT_B)\n#define    ANT_AC        (ANT_A | ANT_C)\n#define ANT_BC        (ANT_B | ANT_C)\n#define ANT_ABC        (ANT_A | ANT_B | ANT_C)\n#define MAX_ANT_NUM 3\n\n#define IWL_RATE_BIT_MSK(r) BIT(IWL_RATE_##r##M_INDEX)\n\n/* fw API values for legacy bit rates, both OFDM and CCK */\nenum {\n    IWL_RATE_6M_PLCP  = 13,\n    IWL_RATE_9M_PLCP  = 15,\n    IWL_RATE_12M_PLCP = 5,\n    IWL_RATE_18M_PLCP = 7,\n    IWL_RATE_24M_PLCP = 9,\n    IWL_RATE_36M_PLCP = 11,\n    IWL_RATE_48M_PLCP = 1,\n    IWL_RATE_54M_PLCP = 3,\n    IWL_RATE_1M_PLCP  = 10,\n    IWL_RATE_2M_PLCP  = 20,\n    IWL_RATE_5M_PLCP  = 55,\n    IWL_RATE_11M_PLCP = 110,\n    IWL_RATE_INVM_PLCP = 0xff,\n};\n\n/*\n * Returns the first antenna as ANT_[ABC], as defined in iwl-config.h.\n * The parameter should also be a combination of ANT_[ABC].\n */\nstatic inline u8 first_antenna(u8 mask)\n{\n    BUILD_BUG_ON(ANT_A != BIT(0)); /* using ffs is wrong if not */\n    if (WARN_ON_ONCE(!mask)) /* ffs will return 0 if mask is zeroed */\n        return BIT(0);\n    return BIT(ffs(mask) - 1);\n}\n\n/*\n * These serve as indexes into\n * struct iwl_rate_info fw_rate_idx_to_plcp[IWL_RATE_COUNT];\n * TODO: avoid overlap between legacy and HT rates\n */\nenum {\n    IWL_RATE_1M_INDEX = 0,\n    IWL_FIRST_CCK_RATE = IWL_RATE_1M_INDEX,\n    IWL_RATE_2M_INDEX,\n    IWL_RATE_5M_INDEX,\n    IWL_RATE_11M_INDEX,\n    IWL_LAST_CCK_RATE = IWL_RATE_11M_INDEX,\n    IWL_RATE_6M_INDEX,\n    IWL_FIRST_OFDM_RATE = IWL_RATE_6M_INDEX,\n    IWL_RATE_MCS_0_INDEX = IWL_RATE_6M_INDEX,\n    IWL_FIRST_HT_RATE = IWL_RATE_MCS_0_INDEX,\n    IWL_FIRST_VHT_RATE = IWL_RATE_MCS_0_INDEX,\n    IWL_RATE_9M_INDEX,\n    IWL_RATE_12M_INDEX,\n    IWL_RATE_MCS_1_INDEX = IWL_RATE_12M_INDEX,\n    IWL_RATE_18M_INDEX,\n    IWL_RATE_MCS_2_INDEX = IWL_RATE_18M_INDEX,\n    IWL_RATE_24M_INDEX,\n    IWL_RATE_MCS_3_INDEX = IWL_RATE_24M_INDEX,\n    IWL_RATE_36M_INDEX,\n    IWL_RATE_MCS_4_INDEX = IWL_RATE_36M_INDEX,\n    IWL_RATE_48M_INDEX,\n    IWL_RATE_MCS_5_INDEX = IWL_RATE_48M_INDEX,\n    IWL_RATE_54M_INDEX,\n    IWL_RATE_MCS_6_INDEX = IWL_RATE_54M_INDEX,\n    IWL_LAST_NON_HT_RATE = IWL_RATE_54M_INDEX,\n    IWL_RATE_60M_INDEX,\n    IWL_RATE_MCS_7_INDEX = IWL_RATE_60M_INDEX,\n    IWL_LAST_HT_RATE = IWL_RATE_MCS_7_INDEX,\n    IWL_RATE_MCS_8_INDEX,\n    IWL_RATE_MCS_9_INDEX,\n    IWL_LAST_VHT_RATE = IWL_RATE_MCS_9_INDEX,\n    IWL_RATE_MCS_10_INDEX,\n    IWL_RATE_MCS_11_INDEX,\n    IWL_LAST_HE_RATE = IWL_RATE_MCS_11_INDEX,\n    IWL_RATE_COUNT_LEGACY = IWL_LAST_NON_HT_RATE + 1,\n    IWL_RATE_COUNT = IWL_LAST_HE_RATE + 1,\n};\n\n/*\n * rate_n_flags bit fields\n *\n * The 32-bit value has different layouts in the low 8 bites depending on the\n * format. There are three formats, HT, VHT and legacy (11abg, with subformats\n * for CCK and OFDM).\n *\n * High-throughput (HT) rate format\n *    bit 8 is 1, bit 26 is 0, bit 9 is 0 (OFDM)\n * Very High-throughput (VHT) rate format\n *    bit 8 is 0, bit 26 is 1, bit 9 is 0 (OFDM)\n * Legacy OFDM rate format for bits 7:0\n *    bit 8 is 0, bit 26 is 0, bit 9 is 0 (OFDM)\n * Legacy CCK rate format for bits 7:0:\n *    bit 8 is 0, bit 26 is 0, bit 9 is 1 (CCK)\n */\n\n/* Bit 8: (1) HT format, (0) legacy or VHT format */\n#define RATE_MCS_HT_POS 8\n#define RATE_MCS_HT_MSK (1 << RATE_MCS_HT_POS)\n\n/* Bit 9: (1) CCK, (0) OFDM.  HT (bit 8) must be \"0\" for this bit to be valid */\n#define RATE_MCS_CCK_POS 9\n#define RATE_MCS_CCK_MSK (1 << RATE_MCS_CCK_POS)\n\n/* Bit 26: (1) VHT format, (0) legacy format in bits 8:0 */\n#define RATE_MCS_VHT_POS 26\n#define RATE_MCS_VHT_MSK (1 << RATE_MCS_VHT_POS)\n\n\n/*\n * High-throughput (HT) rate format for bits 7:0\n *\n *  2-0:  MCS rate base\n *        0)   6 Mbps\n *        1)  12 Mbps\n *        2)  18 Mbps\n *        3)  24 Mbps\n *        4)  36 Mbps\n *        5)  48 Mbps\n *        6)  54 Mbps\n *        7)  60 Mbps\n *  4-3:  0)  Single stream (SISO)\n *        1)  Dual stream (MIMO)\n *        2)  Triple stream (MIMO)\n *    5:  Value of 0x20 in bits 7:0 indicates 6 Mbps HT40 duplicate data\n *  (bits 7-6 are zero)\n *\n * Together the low 5 bits work out to the MCS index because we don't\n * support MCSes above 15/23, and 0-7 have one stream, 8-15 have two\n * streams and 16-23 have three streams. We could also support MCS 32\n * which is the duplicate 20 MHz MCS (bit 5 set, all others zero.)\n */\n#define RATE_HT_MCS_RATE_CODE_MSK    0x7\n#define RATE_HT_MCS_NSS_POS             3\n#define RATE_HT_MCS_NSS_MSK             (3 << RATE_HT_MCS_NSS_POS)\n\n/* Bit 10: (1) Use Green Field preamble */\n#define RATE_HT_MCS_GF_POS        10\n#define RATE_HT_MCS_GF_MSK        (1 << RATE_HT_MCS_GF_POS)\n\n#define RATE_HT_MCS_INDEX_MSK        0x3f\n\n/*\n * Very High-throughput (VHT) rate format for bits 7:0\n *\n *  3-0:  VHT MCS (0-9)\n *  5-4:  number of streams - 1:\n *        0)  Single stream (SISO)\n *        1)  Dual stream (MIMO)\n *        2)  Triple stream (MIMO)\n */\n\n/* Bit 4-5: (0) SISO, (1) MIMO2 (2) MIMO3 */\n#define RATE_VHT_MCS_RATE_CODE_MSK    0xf\n#define RATE_VHT_MCS_NSS_POS        4\n#define RATE_VHT_MCS_NSS_MSK        (3 << RATE_VHT_MCS_NSS_POS)\n\n/*\n * Legacy OFDM rate format for bits 7:0\n *\n *  3-0:  0xD)   6 Mbps\n *        0xF)   9 Mbps\n *        0x5)  12 Mbps\n *        0x7)  18 Mbps\n *        0x9)  24 Mbps\n *        0xB)  36 Mbps\n *        0x1)  48 Mbps\n *        0x3)  54 Mbps\n * (bits 7-4 are 0)\n *\n * Legacy CCK rate format for bits 7:0:\n * bit 8 is 0, bit 26 is 0, bit 9 is 1 (CCK):\n *\n *  6-0:   10)  1 Mbps\n *         20)  2 Mbps\n *         55)  5.5 Mbps\n *        110)  11 Mbps\n * (bit 7 is 0)\n */\n#define RATE_LEGACY_RATE_MSK 0xff\n\n/* Bit 10 - OFDM HE */\n#define RATE_MCS_HE_POS        10\n#define RATE_MCS_HE_MSK        BIT(RATE_MCS_HE_POS)\n\n/*\n * Bit 11-12: (0) 20MHz, (1) 40MHz, (2) 80MHz, (3) 160MHz\n * 0 and 1 are valid for HT and VHT, 2 and 3 only for VHT\n */\n#define RATE_MCS_CHAN_WIDTH_POS        11\n#define RATE_MCS_CHAN_WIDTH_MSK        (3 << RATE_MCS_CHAN_WIDTH_POS)\n#define RATE_MCS_CHAN_WIDTH_20        (0 << RATE_MCS_CHAN_WIDTH_POS)\n#define RATE_MCS_CHAN_WIDTH_40        (1 << RATE_MCS_CHAN_WIDTH_POS)\n#define RATE_MCS_CHAN_WIDTH_80        (2 << RATE_MCS_CHAN_WIDTH_POS)\n#define RATE_MCS_CHAN_WIDTH_160        (3 << RATE_MCS_CHAN_WIDTH_POS)\n\n/* Bit 13: (1) Short guard interval (0.4 usec), (0) normal GI (0.8 usec) */\n#define RATE_MCS_SGI_POS        13\n#define RATE_MCS_SGI_MSK        (1 << RATE_MCS_SGI_POS)\n\n/* Bit 14-16: Antenna selection (1) Ant A, (2) Ant B, (4) Ant C */\n#define RATE_MCS_ANT_POS        14\n#define RATE_MCS_ANT_A_MSK        (1 << RATE_MCS_ANT_POS)\n#define RATE_MCS_ANT_B_MSK        (2 << RATE_MCS_ANT_POS)\n#define RATE_MCS_ANT_C_MSK        (4 << RATE_MCS_ANT_POS)\n#define RATE_MCS_ANT_AB_MSK        (RATE_MCS_ANT_A_MSK | \\\n                     RATE_MCS_ANT_B_MSK)\n#define RATE_MCS_ANT_ABC_MSK        (RATE_MCS_ANT_AB_MSK | \\\n                     RATE_MCS_ANT_C_MSK)\n#define RATE_MCS_ANT_MSK        RATE_MCS_ANT_ABC_MSK\n\n/* Bit 17: (0) SS, (1) SS*2 */\n#define RATE_MCS_STBC_POS        17\n#define RATE_MCS_STBC_MSK        BIT(RATE_MCS_STBC_POS)\n\n/* Bit 18: OFDM-HE dual carrier mode */\n#define RATE_HE_DUAL_CARRIER_MODE    18\n#define RATE_HE_DUAL_CARRIER_MODE_MSK    BIT(RATE_HE_DUAL_CARRIER_MODE)\n\n/* Bit 19: (0) Beamforming is off, (1) Beamforming is on */\n#define RATE_MCS_BF_POS            19\n#define RATE_MCS_BF_MSK            (1 << RATE_MCS_BF_POS)\n\n/*\n * Bit 20-21: HE LTF type and guard interval\n * HE (ext) SU:\n *    0            1xLTF+0.8us\n *    1            2xLTF+0.8us\n *    2            2xLTF+1.6us\n *    3 & SGI (bit 13) clear    4xLTF+3.2us\n *    3 & SGI (bit 13) set    4xLTF+0.8us\n * HE MU:\n *    0            4xLTF+0.8us\n *    1            2xLTF+0.8us\n *    2            2xLTF+1.6us\n *    3            4xLTF+3.2us\n * HE TRIG:\n *    0            1xLTF+1.6us\n *    1            2xLTF+1.6us\n *    2            4xLTF+3.2us\n *    3            (does not occur)\n */\n#define RATE_MCS_HE_GI_LTF_POS        20\n#define RATE_MCS_HE_GI_LTF_MSK        (3 << RATE_MCS_HE_GI_LTF_POS)\n\n/* Bit 22-23: HE type. (0) SU, (1) SU_EXT, (2) MU, (3) trigger based */\n#define RATE_MCS_HE_TYPE_POS        22\n#define RATE_MCS_HE_TYPE_SU        (0 << RATE_MCS_HE_TYPE_POS)\n#define RATE_MCS_HE_TYPE_EXT_SU        (1 << RATE_MCS_HE_TYPE_POS)\n#define RATE_MCS_HE_TYPE_MU        (2 << RATE_MCS_HE_TYPE_POS)\n#define RATE_MCS_HE_TYPE_TRIG        (3 << RATE_MCS_HE_TYPE_POS)\n#define RATE_MCS_HE_TYPE_MSK        (3 << RATE_MCS_HE_TYPE_POS)\n\n/* Bit 24-25: (0) 20MHz (no dup), (1) 2x20MHz, (2) 4x20MHz, 3 8x20MHz */\n#define RATE_MCS_DUP_POS        24\n#define RATE_MCS_DUP_MSK        (3 << RATE_MCS_DUP_POS)\n\n/* Bit 27: (1) LDPC enabled, (0) LDPC disabled */\n#define RATE_MCS_LDPC_POS        27\n#define RATE_MCS_LDPC_MSK        (1 << RATE_MCS_LDPC_POS)\n\n/* Bit 28: (1) 106-tone RX (8 MHz RU), (0) normal bandwidth */\n#define RATE_MCS_HE_106T_POS        28\n#define RATE_MCS_HE_106T_MSK        (1 << RATE_MCS_HE_106T_POS)\n\n/* Bit 30-31: (1) RTS, (2) CTS */\n#define RATE_MCS_RTS_REQUIRED_POS  (30)\n#define RATE_MCS_RTS_REQUIRED_MSK  (0x1 << RATE_MCS_RTS_REQUIRED_POS)\n\n#define RATE_MCS_CTS_REQUIRED_POS  (31)\n#define RATE_MCS_CTS_REQUIRED_MSK  (0x1 << RATE_MCS_CTS_REQUIRED_POS)\n\n/* Link Quality definitions */\n\n/* Link quality command flags bit fields */\n\n/* Bit 0: (0) Don't use RTS (1) Use RTS */\n#define LQ_FLAG_USE_RTS_POS             0\n#define LQ_FLAG_USE_RTS_MSK            (1 << LQ_FLAG_USE_RTS_POS)\n\n/* Bit 1-3: LQ command color. Used to match responses to LQ commands */\n#define LQ_FLAG_COLOR_POS               1\n#define LQ_FLAG_COLOR_MSK               (7 << LQ_FLAG_COLOR_POS)\n#define LQ_FLAG_COLOR_GET(_f)        (((_f) & LQ_FLAG_COLOR_MSK) >>\\\n                     LQ_FLAG_COLOR_POS)\n#define LQ_FLAGS_COLOR_INC(_c)        ((((_c) + 1) << LQ_FLAG_COLOR_POS) &\\\n                     LQ_FLAG_COLOR_MSK)\n#define LQ_FLAG_COLOR_SET(_f, _c)    ((_c) | ((_f) & ~LQ_FLAG_COLOR_MSK))\n\n/* Bit 4-5: Tx RTS BW Signalling\n * (0) No RTS BW signalling\n * (1) Static BW signalling\n * (2) Dynamic BW signalling\n */\n#define LQ_FLAG_RTS_BW_SIG_POS          4\n#define LQ_FLAG_RTS_BW_SIG_NONE         (0 << LQ_FLAG_RTS_BW_SIG_POS)\n#define LQ_FLAG_RTS_BW_SIG_STATIC       (1 << LQ_FLAG_RTS_BW_SIG_POS)\n#define LQ_FLAG_RTS_BW_SIG_DYNAMIC      (2 << LQ_FLAG_RTS_BW_SIG_POS)\n\n/* Bit 6: (0) No dynamic BW selection (1) Allow dynamic BW selection\n * Dyanmic BW selection allows Tx with narrower BW then requested in rates\n */\n#define LQ_FLAG_DYNAMIC_BW_POS          6\n#define LQ_FLAG_DYNAMIC_BW_MSK          (1 << LQ_FLAG_DYNAMIC_BW_POS)\n\n/* Single Stream Tx Parameters (lq_cmd->ss_params)\n * Flags to control a smart FW decision about whether BFER/STBC/SISO will be\n * used for single stream Tx.\n */\n\n/* Bit 0-1: Max STBC streams allowed. Can be 0-3.\n * (0) - No STBC allowed\n * (1) - 2x1 STBC allowed (HT/VHT)\n * (2) - 4x2 STBC allowed (HT/VHT)\n * (3) - 3x2 STBC allowed (HT only)\n * All our chips are at most 2 antennas so only (1) is valid for now.\n */\n#define LQ_SS_STBC_ALLOWED_POS          0\n#define LQ_SS_STBC_ALLOWED_MSK        (3 << LQ_SS_STBC_ALLOWED_MSK)\n\n/* 2x1 STBC is allowed */\n#define LQ_SS_STBC_1SS_ALLOWED        (1 << LQ_SS_STBC_ALLOWED_POS)\n\n/* Bit 2: Beamformer (VHT only) is allowed */\n#define LQ_SS_BFER_ALLOWED_POS        2\n#define LQ_SS_BFER_ALLOWED        (1 << LQ_SS_BFER_ALLOWED_POS)\n\n/* Bit 3: Force BFER or STBC for testing\n * If this is set:\n * If BFER is allowed then force the ucode to choose BFER else\n * If STBC is allowed then force the ucode to choose STBC over SISO\n */\n#define LQ_SS_FORCE_POS            3\n#define LQ_SS_FORCE            (1 << LQ_SS_FORCE_POS)\n\n/* Bit 31: ss_params field is valid. Used for FW backward compatibility\n * with other drivers which don't support the ss_params API yet\n */\n#define LQ_SS_PARAMS_VALID_POS        31\n#define LQ_SS_PARAMS_VALID        (1 << LQ_SS_PARAMS_VALID_POS)\n\nstruct iwl_rs_rate_info {\n    u8 plcp;      /* uCode API:  IWL_RATE_6M_PLCP, etc. */\n    u8 plcp_ht_siso;  /* uCode API:  IWL_RATE_SISO_6M_PLCP, etc. */\n    u8 plcp_ht_mimo2; /* uCode API:  IWL_RATE_MIMO2_6M_PLCP, etc. */\n    u8 plcp_vht_siso;\n    u8 plcp_vht_mimo2;\n    u8 prev_rs;      /* previous rate used in rs algo */\n    u8 next_rs;      /* next rate used in rs algo */\n};\n\nextern struct iwl_rs_rate_info iwl_rates[IWL_RATE_COUNT];\n\n#define IWL_RATE_60M_PLCP 3\n\nenum {\n    IWL_RATE_INVM_INDEX = IWL_RATE_COUNT,\n    IWL_RATE_INVALID = IWL_RATE_COUNT,\n};\n\n#define LINK_QUAL_MAX_RETRY_NUM 16\n\nenum {\n    IWL_RATE_6M_INDEX_TABLE = 0,\n    IWL_RATE_9M_INDEX_TABLE,\n    IWL_RATE_12M_INDEX_TABLE,\n    IWL_RATE_18M_INDEX_TABLE,\n    IWL_RATE_24M_INDEX_TABLE,\n    IWL_RATE_36M_INDEX_TABLE,\n    IWL_RATE_48M_INDEX_TABLE,\n    IWL_RATE_54M_INDEX_TABLE,\n    IWL_RATE_1M_INDEX_TABLE,\n    IWL_RATE_2M_INDEX_TABLE,\n    IWL_RATE_5M_INDEX_TABLE,\n    IWL_RATE_11M_INDEX_TABLE,\n    IWL_RATE_INVM_INDEX_TABLE = IWL_RATE_INVM_INDEX - 1,\n};\n\n/* #define vs. enum to keep from defaulting to 'large integer' */\n#define    IWL_RATE_6M_MASK   (1 << IWL_RATE_6M_INDEX)\n#define    IWL_RATE_9M_MASK   (1 << IWL_RATE_9M_INDEX)\n#define    IWL_RATE_12M_MASK  (1 << IWL_RATE_12M_INDEX)\n#define    IWL_RATE_18M_MASK  (1 << IWL_RATE_18M_INDEX)\n#define    IWL_RATE_24M_MASK  (1 << IWL_RATE_24M_INDEX)\n#define    IWL_RATE_36M_MASK  (1 << IWL_RATE_36M_INDEX)\n#define    IWL_RATE_48M_MASK  (1 << IWL_RATE_48M_INDEX)\n#define    IWL_RATE_54M_MASK  (1 << IWL_RATE_54M_INDEX)\n#define IWL_RATE_60M_MASK  (1 << IWL_RATE_60M_INDEX)\n#define    IWL_RATE_1M_MASK   (1 << IWL_RATE_1M_INDEX)\n#define    IWL_RATE_2M_MASK   (1 << IWL_RATE_2M_INDEX)\n#define    IWL_RATE_5M_MASK   (1 << IWL_RATE_5M_INDEX)\n#define    IWL_RATE_11M_MASK  (1 << IWL_RATE_11M_INDEX)\n\n\n/* uCode API values for HT/VHT bit rates */\nenum {\n    IWL_RATE_HT_SISO_MCS_0_PLCP = 0,\n    IWL_RATE_HT_SISO_MCS_1_PLCP = 1,\n    IWL_RATE_HT_SISO_MCS_2_PLCP = 2,\n    IWL_RATE_HT_SISO_MCS_3_PLCP = 3,\n    IWL_RATE_HT_SISO_MCS_4_PLCP = 4,\n    IWL_RATE_HT_SISO_MCS_5_PLCP = 5,\n    IWL_RATE_HT_SISO_MCS_6_PLCP = 6,\n    IWL_RATE_HT_SISO_MCS_7_PLCP = 7,\n    IWL_RATE_HT_MIMO2_MCS_0_PLCP = 0x8,\n    IWL_RATE_HT_MIMO2_MCS_1_PLCP = 0x9,\n    IWL_RATE_HT_MIMO2_MCS_2_PLCP = 0xA,\n    IWL_RATE_HT_MIMO2_MCS_3_PLCP = 0xB,\n    IWL_RATE_HT_MIMO2_MCS_4_PLCP = 0xC,\n    IWL_RATE_HT_MIMO2_MCS_5_PLCP = 0xD,\n    IWL_RATE_HT_MIMO2_MCS_6_PLCP = 0xE,\n    IWL_RATE_HT_MIMO2_MCS_7_PLCP = 0xF,\n    IWL_RATE_VHT_SISO_MCS_0_PLCP = 0,\n    IWL_RATE_VHT_SISO_MCS_1_PLCP = 1,\n    IWL_RATE_VHT_SISO_MCS_2_PLCP = 2,\n    IWL_RATE_VHT_SISO_MCS_3_PLCP = 3,\n    IWL_RATE_VHT_SISO_MCS_4_PLCP = 4,\n    IWL_RATE_VHT_SISO_MCS_5_PLCP = 5,\n    IWL_RATE_VHT_SISO_MCS_6_PLCP = 6,\n    IWL_RATE_VHT_SISO_MCS_7_PLCP = 7,\n    IWL_RATE_VHT_SISO_MCS_8_PLCP = 8,\n    IWL_RATE_VHT_SISO_MCS_9_PLCP = 9,\n    IWL_RATE_VHT_MIMO2_MCS_0_PLCP = 0x10,\n    IWL_RATE_VHT_MIMO2_MCS_1_PLCP = 0x11,\n    IWL_RATE_VHT_MIMO2_MCS_2_PLCP = 0x12,\n    IWL_RATE_VHT_MIMO2_MCS_3_PLCP = 0x13,\n    IWL_RATE_VHT_MIMO2_MCS_4_PLCP = 0x14,\n    IWL_RATE_VHT_MIMO2_MCS_5_PLCP = 0x15,\n    IWL_RATE_VHT_MIMO2_MCS_6_PLCP = 0x16,\n    IWL_RATE_VHT_MIMO2_MCS_7_PLCP = 0x17,\n    IWL_RATE_VHT_MIMO2_MCS_8_PLCP = 0x18,\n    IWL_RATE_VHT_MIMO2_MCS_9_PLCP = 0x19,\n    IWL_RATE_HT_SISO_MCS_INV_PLCP,\n    IWL_RATE_HT_MIMO2_MCS_INV_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP,\n    IWL_RATE_VHT_SISO_MCS_INV_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP,\n    IWL_RATE_VHT_MIMO2_MCS_INV_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP,\n    IWL_RATE_HT_SISO_MCS_8_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP,\n    IWL_RATE_HT_SISO_MCS_9_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP,\n    IWL_RATE_HT_MIMO2_MCS_8_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP,\n    IWL_RATE_HT_MIMO2_MCS_9_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP,\n};\n\n#define IWL_RATES_MASK ((1 << IWL_RATE_COUNT) - 1)\n\n#define IWL_INVALID_VALUE    0xff\n\n#define TPC_MAX_REDUCTION        15\n#define TPC_NO_REDUCTION        0\n#define TPC_INVALID            0xff\n\n#define LINK_QUAL_AGG_FRAME_LIMIT_DEF    (63)\n#define LINK_QUAL_AGG_FRAME_LIMIT_MAX    (63)\n/*\n * FIXME - various places in firmware API still use u8,\n * e.g. LQ command and SCD config command.\n * This should be 256 instead.\n */\n#define LINK_QUAL_AGG_FRAME_LIMIT_GEN2_DEF    (255)\n#define LINK_QUAL_AGG_FRAME_LIMIT_GEN2_MAX    (255)\n#define LINK_QUAL_AGG_FRAME_LIMIT_MIN    (0)\n\n#define LQ_SIZE        2    /* 2 mode tables:  \"Active\" and \"Search\" */\n\n/* load per tid defines for A-MPDU activation */\n#define IWL_AGG_TPT_THREHOLD    0\n#define IWL_AGG_ALL_TID        0xff\n\nenum iwl_table_type {\n    LQ_NONE,\n    LQ_LEGACY_G,    /* legacy types */\n    LQ_LEGACY_A,\n    LQ_HT_SISO,    /* HT types */\n    LQ_HT_MIMO2,\n    LQ_VHT_SISO,    /* VHT types */\n    LQ_VHT_MIMO2,\n    LQ_HE_SISO,     /* HE types */\n    LQ_HE_MIMO2,\n    LQ_MAX,\n};\n\nstruct rs_rate {\n    int index;\n    enum iwl_table_type type;\n    u8 ant;\n    u32 bw;\n    bool sgi;\n    bool ldpc;\n    bool stbc;\n    bool bfer;\n};\n\n#define is_type_legacy(type) (((type) == LQ_LEGACY_G) || \\\n                  ((type) == LQ_LEGACY_A))\n#define is_type_ht_siso(type) ((type) == LQ_HT_SISO)\n#define is_type_ht_mimo2(type) ((type) == LQ_HT_MIMO2)\n#define is_type_vht_siso(type) ((type) == LQ_VHT_SISO)\n#define is_type_vht_mimo2(type) ((type) == LQ_VHT_MIMO2)\n#define is_type_he_siso(type) ((type) == LQ_HE_SISO)\n#define is_type_he_mimo2(type) ((type) == LQ_HE_MIMO2)\n#define is_type_siso(type) (is_type_ht_siso(type) || is_type_vht_siso(type) || \\\n                is_type_he_siso(type))\n#define is_type_mimo2(type) (is_type_ht_mimo2(type) || \\\n                 is_type_vht_mimo2(type) || is_type_he_mimo2(type))\n#define is_type_mimo(type) (is_type_mimo2(type))\n#define is_type_ht(type) (is_type_ht_siso(type) || is_type_ht_mimo2(type))\n#define is_type_vht(type) (is_type_vht_siso(type) || is_type_vht_mimo2(type))\n#define is_type_he(type) (is_type_he_siso(type) || is_type_he_mimo2(type))\n#define is_type_a_band(type) ((type) == LQ_LEGACY_A)\n#define is_type_g_band(type) ((type) == LQ_LEGACY_G)\n\n#define is_legacy(rate)       is_type_legacy((rate)->type)\n#define is_ht_siso(rate)      is_type_ht_siso((rate)->type)\n#define is_ht_mimo2(rate)     is_type_ht_mimo2((rate)->type)\n#define is_vht_siso(rate)     is_type_vht_siso((rate)->type)\n#define is_vht_mimo2(rate)    is_type_vht_mimo2((rate)->type)\n#define is_siso(rate)         is_type_siso((rate)->type)\n#define is_mimo2(rate)        is_type_mimo2((rate)->type)\n#define is_mimo(rate)         is_type_mimo((rate)->type)\n#define is_ht(rate)           is_type_ht((rate)->type)\n#define is_vht(rate)          is_type_vht((rate)->type)\n#define is_he(rate)           is_type_he((rate)->type)\n#define is_a_band(rate)       is_type_a_band((rate)->type)\n#define is_g_band(rate)       is_type_g_band((rate)->type)\n\n#define is_ht20(rate)         ((rate)->bw == RATE_MCS_CHAN_WIDTH_20)\n#define is_ht40(rate)         ((rate)->bw == RATE_MCS_CHAN_WIDTH_40)\n#define is_ht80(rate)         ((rate)->bw == RATE_MCS_CHAN_WIDTH_80)\n#define is_ht160(rate)        ((rate)->bw == RATE_MCS_CHAN_WIDTH_160)\n\n#define IWL_MAX_MCS_DISPLAY_SIZE    12\n\nstruct iwl_rate_mcs_info {\n    char    mbps[IWL_MAX_MCS_DISPLAY_SIZE];\n    char    mcs[IWL_MAX_MCS_DISPLAY_SIZE];\n};\n\n/**\n * struct iwl_lq_sta_rs_fw - rate and related statistics for RS in FW\n * @last_rate_n_flags: last rate reported by FW\n * @sta_id: the id of the station\n#ifdef CONFIG_MAC80211_DEBUGFS\n * @dbg_fixed_rate: for debug, use fixed rate if not 0\n * @dbg_agg_frame_count_lim: for debug, max number of frames in A-MPDU\n#endif\n * @chains: bitmask of chains reported in %chain_signal\n * @chain_signal: per chain signal strength\n * @last_rssi: last rssi reported\n * @drv: pointer back to the driver data\n */\n\nstruct iwl_lq_sta_rs_fw {\n    /* last tx rate_n_flags */\n    u32 last_rate_n_flags;\n\n    /* persistent fields - initialized only once - keep last! */\n    struct lq_sta_pers_rs_fw {\n        u32 sta_id;\n        u8 chains;\n        s8 chain_signal[4];\n        s8 last_rssi;\n        struct iwm_softc *drv;\n    } pers;\n};\n\n/**\n * struct iwl_rate_scale_data -- tx success history for one rate\n */\nstruct iwl_rate_scale_data {\n    u64 data;        /* bitmap of successful frames */\n    s32 success_counter;    /* number of frames successful */\n    s32 success_ratio;    /* per-cent * 128  */\n    s32 counter;        /* number of frames attempted */\n    s32 average_tpt;    /* success ratio * expected throughput */\n};\n\n/* Possible Tx columns\n * Tx Column = a combo of legacy/siso/mimo x antenna x SGI\n */\nenum rs_column {\n    RS_COLUMN_LEGACY_ANT_A = 0,\n    RS_COLUMN_LEGACY_ANT_B,\n    RS_COLUMN_SISO_ANT_A,\n    RS_COLUMN_SISO_ANT_B,\n    RS_COLUMN_SISO_ANT_A_SGI,\n    RS_COLUMN_SISO_ANT_B_SGI,\n    RS_COLUMN_MIMO2,\n    RS_COLUMN_MIMO2_SGI,\n\n    RS_COLUMN_LAST = RS_COLUMN_MIMO2_SGI,\n    RS_COLUMN_COUNT = RS_COLUMN_LAST + 1,\n    RS_COLUMN_INVALID,\n};\n\nenum rs_ss_force_opt {\n    RS_SS_FORCE_NONE = 0,\n    RS_SS_FORCE_STBC,\n    RS_SS_FORCE_BFER,\n    RS_SS_FORCE_SISO,\n};\n\n/* Packet stats per rate */\nstruct rs_rate_stats {\n    u64 success;\n    u64 total;\n};\n\n/**\n * struct iwl_scale_tbl_info -- tx params and success history for all rates\n *\n * There are two of these in struct iwl_lq_sta,\n * one for \"active\", and one for \"search\".\n */\nstruct iwl_scale_tbl_info {\n    struct rs_rate rate;\n    enum rs_column column;\n    const u16 *expected_tpt;    /* throughput metrics; expected_tpt_G, etc. */\n    struct iwl_rate_scale_data win[IWL_RATE_COUNT]; /* rate histories */\n    /* per txpower-reduction history */\n    struct iwl_rate_scale_data tpc_win[TPC_MAX_REDUCTION + 1];\n};\n\nenum {\n    RS_STATE_SEARCH_CYCLE_STARTED,\n    RS_STATE_SEARCH_CYCLE_ENDED,\n    RS_STATE_STAY_IN_COLUMN,\n};\n\nstruct lq_sta_pers {\n    u8 chains;\n    s8 chain_signal[4];\n    s8 last_rssi;\n    struct rs_rate_stats tx_stats[RS_COLUMN_COUNT][IWL_RATE_COUNT];\n    struct iwm_softc *drv;\n    IOSimpleLock *lock; /* for races in reinit/update table */\n};\n\n/**\n * struct iwl_lq_sta -- driver's rate scaling private structure\n *\n * Pointer to this gets passed back and forth between driver and mac80211.\n */\nstruct iwl_lq_sta {\n    u8 active_tbl;        /* index of active table, range 0-1 */\n    u8 rs_state;            /* RS_STATE_* */\n    u8 search_better_tbl;    /* 1: currently trying alternate mode */\n    s32 last_tpt;\n\n    /* The following determine when to search for a new mode */\n    u32 table_count_limit;\n    u32 max_failure_limit;    /* # failed frames before new search */\n    u32 max_success_limit;    /* # successful frames before new search */\n    u32 table_count;\n    u32 total_failed;    /* total failed frames, any/all rates */\n    u32 total_success;    /* total successful frames, any/all rates */\n    u64 flush_timer;    /* time staying in mode before new search */\n\n    u32 visited_columns;    /* Bitmask marking which Tx columns were\n                 * explored during a search cycle\n                 */\n    u64 last_tx;\n    bool is_vht;\n    bool ldpc;              /* LDPC Rx is supported by the STA */\n    bool stbc_capable;      /* Tx STBC is supported by chip and Rx by STA */\n    bool bfer_capable;      /* Remote supports beamformee and we BFer */\n\n    enum nl80211_band band;\n\n    /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */\n    unsigned long active_legacy_rate;\n    unsigned long active_siso_rate;\n    unsigned long active_mimo2_rate;\n\n    /* Highest rate per Tx mode */\n    u8 max_legacy_rate_idx;\n    u8 max_siso_rate_idx;\n    u8 max_mimo2_rate_idx;\n\n    /* Optimal rate based on RSSI and STA caps.\n     * Used only to reflect link speed to userspace.\n     */\n    struct rs_rate optimal_rate;\n    unsigned long optimal_rate_mask;\n    const struct rs_init_rate_info *optimal_rates;\n    int optimal_nentries;\n\n    u8 missed_rate_counter;\n\n    struct iwm_lq_cmd lq;\n    struct iwl_scale_tbl_info lq_info[LQ_SIZE]; /* \"active\", \"search\" */\n    u8 tx_agg_tid_en;\n\n    /* last tx rate_n_flags */\n    u32 last_rate_n_flags;\n    /* packets destined for this STA are aggregated */\n    u8 is_agg;\n\n    /* tx power reduce for this sta */\n    int tpc_reduce;\n\n    /* persistent fields - initialized only once - keep last! */\n    struct lq_sta_pers pers;\n};\n\n/* ieee80211_tx_info's status_driver_data[0] is packed with lq color and txp\n * Note, it's iwlmvm <-> mac80211 interface.\n * bits 0-7: reduced tx power\n * bits 8-10: LQ command's color\n */\n#define RS_DRV_DATA_TXP_MSK 0xff\n#define RS_DRV_DATA_LQ_COLOR_POS 8\n#define RS_DRV_DATA_LQ_COLOR_MSK (7 << RS_DRV_DATA_LQ_COLOR_POS)\n#define RS_DRV_DATA_LQ_COLOR_GET(_f) (((_f) & RS_DRV_DATA_LQ_COLOR_MSK) >>\\\n                      RS_DRV_DATA_LQ_COLOR_POS)\n#define RS_DRV_DATA_PACK(_c, _p) ((void *)(uintptr_t)\\\n                  (((uintptr_t)_p) |\\\n                   ((_c) << RS_DRV_DATA_LQ_COLOR_POS)))\n\n#define IWL_DECLARE_RATE_INFO(r) \\\n    [IWL_RATE_##r##M_INDEX] = IWL_RATE_##r##M_PLCP\n\n/*\n * Translate from fw_rate_index (IWL_RATE_XXM_INDEX) to PLCP\n */\nstatic const u8 fw_rate_idx_to_plcp[IWL_RATE_COUNT] = {\n    IWL_DECLARE_RATE_INFO(1),\n    IWL_DECLARE_RATE_INFO(2),\n    IWL_DECLARE_RATE_INFO(5),\n    IWL_DECLARE_RATE_INFO(11),\n    IWL_DECLARE_RATE_INFO(6),\n    IWL_DECLARE_RATE_INFO(9),\n    IWL_DECLARE_RATE_INFO(12),\n    IWL_DECLARE_RATE_INFO(18),\n    IWL_DECLARE_RATE_INFO(24),\n    IWL_DECLARE_RATE_INFO(36),\n    IWL_DECLARE_RATE_INFO(48),\n    IWL_DECLARE_RATE_INFO(54),\n};\n\n#undef IWL_DECLARE_RATE_INFO\n\n/* Convert an MCS index into an iwm_rates[] index. */\nconst int iwm_mcs2ridx[] = {\n    IWL_RATE_6M_INDEX,\n    IWL_RATE_12M_INDEX,\n    IWL_RATE_12M_INDEX,\n    IWL_RATE_18M_INDEX,\n    IWL_RATE_24M_INDEX,\n    IWL_RATE_36M_INDEX,\n    IWL_RATE_48M_INDEX,\n    IWL_RATE_54M_INDEX,\n    IWL_RATE_54M_INDEX,\n    IWL_RATE_54M_INDEX,\n};\n\nstatic inline int iwl_mvm_legacy_rate_to_mac80211_idx(u32 rate_n_flags,\n                    enum nl80211_band band)\n{\n    int rate = rate_n_flags & RATE_LEGACY_RATE_MSK;\n    int idx;\n    int band_offset = 0;\n\n    /* Legacy rate format, search for match in table */\n    if (band != NL80211_BAND_2GHZ)\n        band_offset = IWL_FIRST_OFDM_RATE;\n    for (idx = band_offset; idx < IWL_RATE_COUNT_LEGACY; idx++)\n        if (fw_rate_idx_to_plcp[idx] == rate)\n            return idx - band_offset;\n\n    return -1;\n}\n\nstatic inline u8 iwl_mvm_mac80211_idx_to_hwrate(int rate_idx)\n{\n    /* Get PLCP rate for tx_cmd->rate_n_flags */\n    return fw_rate_idx_to_plcp[rate_idx];\n}\n\nstatic inline void ieee80211_rate_set_vht(struct ieee80211_tx_rate *rate,\n                      u8 mcs, u8 nss)\n{\n    WARN_ON(mcs & ~0xF);\n    WARN_ON((nss - 1) & ~0x7);\n    rate->idx = ((nss - 1) << 4) | mcs;\n}\n\nstatic inline void iwl_mvm_hwrate_to_tx_rate(u32 rate_n_flags,\n                   enum nl80211_band band,\n                   struct ieee80211_tx_rate *r)\n{\n    if (rate_n_flags & RATE_HT_MCS_GF_MSK)\n        r->flags |= IEEE80211_TX_RC_GREEN_FIELD;\n    switch (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK) {\n    case RATE_MCS_CHAN_WIDTH_20:\n        break;\n    case RATE_MCS_CHAN_WIDTH_40:\n        r->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;\n        break;\n    case RATE_MCS_CHAN_WIDTH_80:\n        r->flags |= IEEE80211_TX_RC_80_MHZ_WIDTH;\n        break;\n    case RATE_MCS_CHAN_WIDTH_160:\n        r->flags |= IEEE80211_TX_RC_160_MHZ_WIDTH;\n        break;\n    }\n    if (rate_n_flags & RATE_MCS_SGI_MSK)\n        r->flags |= IEEE80211_TX_RC_SHORT_GI;\n    if (rate_n_flags & RATE_MCS_HT_MSK) {\n        r->flags |= IEEE80211_TX_RC_MCS;\n        r->idx = rate_n_flags & RATE_HT_MCS_INDEX_MSK;\n    } else if (rate_n_flags & RATE_MCS_VHT_MSK) {\n        ieee80211_rate_set_vht(\n            r, rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK,\n            ((rate_n_flags & RATE_VHT_MCS_NSS_MSK) >>\n                        RATE_VHT_MCS_NSS_POS) + 1);\n        r->flags |= IEEE80211_TX_RC_VHT_MCS;\n    } else {\n        r->idx = iwl_mvm_legacy_rate_to_mac80211_idx(rate_n_flags,\n                                 band);\n    }\n}\n\n/*\n * translate ucode response to mac80211 tx status control values\n */\nstatic inline void iwl_mvm_hwrate_to_tx_status(u32 rate_n_flags,\n                    struct ieee80211_tx_info *info)\n{\n    struct ieee80211_tx_rate *r = &info->status.rates[0];\n\n    info->status.antenna =\n        ((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS);\n    iwl_mvm_hwrate_to_tx_rate(rate_n_flags, (enum nl80211_band)info->band, r);\n}\n\nint iwl_mvm_send_lq_cmd(struct iwm_softc *sc, struct iwm_lq_cmd *lq);\n\n/* Initialize station's rate scaling information after adding station */\nvoid iwl_mvm_rs_rate_init(struct iwm_softc *mvm, struct ieee80211_node *sta,\n              enum nl80211_band band, bool init);\n\n/* Notify RS about Tx status */\nvoid iwl_mvm_rs_tx_status(struct iwm_softc *mvm, struct ieee80211_node *sta,\n              int tid, struct ieee80211_tx_info *info, bool ndp);\n\nvoid rs_drv_mac80211_tx_status(struct iwm_softc *sc,\n                struct ieee80211_node *sta,\n                               struct ieee80211_tx_info *info, int tid, uint16_t fc, int ssn);\n\nvoid rs_update_last_rssi(struct iwm_softc *mvm,\n                         struct ieee80211_rx_status *rx_status);\n\nint rs_pretty_print_rate(char *buf, int bufsz, const u32 rate);\n\nvoid rs_drv_rate_update(struct iwm_softc *mvm,\n                        struct ieee80211_node *sta,\n                        enum nl80211_band band, u32 changed);\n\nvoid *rs_drv_alloc_sta(iwm_softc *sc, struct ieee80211_node *ni);\n\nvoid rs_drv_free_sta(iwm_softc *sc, struct ieee80211_node *ni);\n\nvoid iwm_rs_alloc(struct iwm_softc *sc);\n\nvoid iwm_rs_free(struct iwm_softc *sc);\n\n#endif /* rs_hpp */\n"
  },
  {
    "path": "itlwm/hal_iwm/rx.cpp",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n/*    $OpenBSD: if_iwm.c,v 1.316 2020/12/07 20:09:24 tobhe Exp $    */\n\n/*\n * Copyright (c) 2014, 2016 genua gmbh <info@genua.de>\n *   Author: Stefan Sperling <stsp@openbsd.org>\n * Copyright (c) 2014 Fixup Software Ltd.\n * Copyright (c) 2017 Stefan Sperling <stsp@openbsd.org>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n/*-\n * Based on BSD-licensed source modules in the Linux iwlwifi driver,\n * which were used as the reference documentation for this implementation.\n *\n ***********************************************************************\n *\n * This file is provided under a dual BSD/GPLv2 license.  When using or\n * redistributing this file, you may do so under either license.\n *\n * GPL LICENSE SUMMARY\n *\n * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.\n * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH\n * Copyright(c) 2016 Intel Deutschland GmbH\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of version 2 of the GNU General Public License as\n * published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful, but\n * WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,\n * USA\n *\n * The full GNU General Public License is included in this distribution\n * in the file called COPYING.\n *\n * Contact Information:\n *  Intel Linux Wireless <ilw@linux.intel.com>\n * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497\n *\n *\n * BSD LICENSE\n *\n * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.\n * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH\n * Copyright(c) 2016 Intel Deutschland GmbH\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in\n *    the documentation and/or other materials provided with the\n *    distribution.\n *  * Neither the name Intel Corporation nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*-\n * Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n#include \"ItlIwm.hpp\"\n#include <net80211/ieee80211_priv.h>\n\nvoid ItlIwm::\niwm_disable_rx_dma(struct iwm_softc *sc)\n{\n    int ntries;\n    \n    if (iwm_nic_lock(sc)) {\n        if (sc->sc_mqrx_supported) {\n            iwm_write_prph(sc, IWM_RFH_RXF_DMA_CFG, 0);\n            for (ntries = 0; ntries < 1000; ntries++) {\n                if (iwm_read_prph(sc, IWM_RFH_GEN_STATUS) &\n                    IWM_RXF_DMA_IDLE)\n                    break;\n                DELAY(10);\n            }\n        } else {\n            IWM_WRITE(sc, IWM_FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);\n            for (ntries = 0; ntries < 1000; ntries++) {\n                if (IWM_READ(sc, IWM_FH_MEM_RSSR_RX_STATUS_REG)&\n                    IWM_FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE)\n                    break;\n                DELAY(10);\n            }\n        }\n        iwm_nic_unlock(sc);\n    }\n}\n\nvoid ItlIwm::\niwm_reset_rx_ring(struct iwm_softc *sc, struct iwm_rx_ring *ring)\n{\n    ring->cur = 0;\n    //    bus_dmamap_sync(sc->sc_dmat, ring->stat_dma.map, 0,\n    //        ring->stat_dma.size, BUS_DMASYNC_PREWRITE);\n    memset(ring->stat, 0, sizeof(*ring->stat));\n    //    bus_dmamap_sync(sc->sc_dmat, ring->stat_dma.map, 0,\n    //        ring->stat_dma.size, BUS_DMASYNC_POSTWRITE);\n    \n}\n\nvoid ItlIwm::\niwm_free_rx_ring(struct iwm_softc *sc, struct iwm_rx_ring *ring)\n{\n    int count, i;\n    \n    iwm_dma_contig_free(&ring->free_desc_dma);\n    iwm_dma_contig_free(&ring->stat_dma);\n    iwm_dma_contig_free(&ring->used_desc_dma);\n    \n    if (sc->sc_mqrx_supported)\n        count = IWM_RX_MQ_RING_COUNT;\n    else\n        count = IWM_RX_RING_COUNT;\n    \n    for (i = 0; i < count; i++) {\n        struct iwm_rx_data *data = &ring->data[i];\n        \n        if (data->m != NULL) {\n            //            bus_dmamap_sync(sc->sc_dmat, data->map, 0,\n            //                data->map->dm_mapsize, BUS_DMASYNC_POSTREAD);\n            //            bus_dmamap_unload(sc->sc_dmat, data->map);\n            mbuf_freem(data->m);\n            data->m = NULL;\n        }\n        if (data->map != NULL) {\n            bus_dmamap_destroy(sc->sc_dmat, data->map);\n            data->map = NULL;\n        }\n    }\n}\n\nint ItlIwm::\niwm_alloc_rx_ring(struct iwm_softc *sc, struct iwm_rx_ring *ring)\n{\n    bus_size_t size;\n    size_t descsz;\n    int count, i, err;\n    \n    ring->cur = 0;\n    \n    if (sc->sc_mqrx_supported) {\n        count = IWM_RX_MQ_RING_COUNT;\n        descsz = sizeof(uint64_t);\n    } else {\n        count = IWM_RX_RING_COUNT;\n        descsz = sizeof(uint32_t);\n    }\n    \n    /* Allocate RX descriptors (256-byte aligned). */\n    size = count * descsz;\n    err = iwm_dma_contig_alloc(sc->sc_dmat, &ring->free_desc_dma, size, 256);\n    if (err) {\n        XYLog(\"%s: could not allocate RX ring DMA memory\\n\",\n            DEVNAME(sc));\n        goto fail;\n    }\n    ring->desc = ring->free_desc_dma.vaddr;\n\n    /* Allocate RX status area (16-byte aligned). */\n    err = iwm_dma_contig_alloc(sc->sc_dmat, &ring->stat_dma,\n        sizeof(*ring->stat), 16);\n    if (err) {\n        XYLog(\"%s: could not allocate RX status DMA memory\\n\",\n            DEVNAME(sc));\n        goto fail;\n    }\n    ring->stat = (struct iwm_rb_status *)ring->stat_dma.vaddr;\n\n    if (sc->sc_mqrx_supported) {\n        size = count * sizeof(uint32_t);\n        err = iwm_dma_contig_alloc(sc->sc_dmat, &ring->used_desc_dma,\n            size, 256);\n        if (err) {\n            XYLog(\"%s: could not allocate RX ring DMA memory\\n\",\n                DEVNAME(sc));\n            goto fail;\n        }\n    }\n    \n    for (i = 0; i < count; i++) {\n        struct iwm_rx_data *data = &ring->data[i];\n        \n        memset(data, 0, sizeof(*data));\n        err = bus_dmamap_create(sc->sc_dmat, IWM_RBUF_SIZE, 1,\n                                IWM_RBUF_SIZE, 0, BUS_DMA_NOWAIT,\n                                &data->map);\n        if (err) {\n            XYLog(\"%s: could not create RX buf DMA map\\n\",\n                  DEVNAME(sc));\n            goto fail;\n        }\n        \n        err = iwm_rx_addbuf(sc, IWM_RBUF_SIZE, i);\n        if (err)\n            goto fail;\n    }\n    return 0;\n    \nfail:    iwm_free_rx_ring(sc, ring);\n    return err;\n}\n\nint ItlIwm::\niwm_rx_addbuf(struct iwm_softc *sc, int size, int idx)\n{\n    struct iwm_rx_ring *ring = &sc->rxq;\n    struct iwm_rx_data *data = &ring->data[idx];\n    mbuf_t m;\n    int err;\n    int fatal = 0;\n    unsigned int maxChunks = 1;\n    IOPhysicalSegment seg;\n    \n//    mbuf_allocpacket(MBUF_WAITOK, size, NULL, &m);\n    \n    m = getController()->allocatePacket(size);\n//\n    if (m == NULL) {\n        XYLog(\"%s allocatePacket==NULL\\n\", __FUNCTION__);\n        return ENOMEM;\n    }\n//        mbuf_gethdr(MBUF_DONTWAIT, MT_DATA, &m);\n//        if (m == NULL)\n//            return ENOBUFS;\n//\n//        if (size <= MCLBYTES) {\n//            mbuf_mclget(MBUF_DONTWAIT, MT_DATA, &m);\n//        } else {\n//            mbuf_getcluster(MBUF_DONTWAIT, MT_DATA, IWM_RBUF_SIZE, &m);\n//        }\n//        if ((mbuf_flags(m) & MBUF_EXT) == 0) {\n//            mbuf_freem(m);\n//            return ENOBUFS;\n//        }\n//\n//        if (data->m != NULL) {\n//    //        bus_dmamap_unload(sc->sc_dmat, data->map);\n//            fatal = 1;\n//        }\n    \n//        mbuf_setlen(m, size);\n//        mbuf_pkthdr_setlen(m, size);\n    //    m->m_len = m->m_pkthdr.len = m->m_ext.ext_size;\n//    err = bus_dmamap_load(data->map, m);\n    data->map->dm_nsegs = data->map->cursor->getPhysicalSegments(m, &seg, 1);\n//    XYLog(\"map rx dm_nsegs=%d\\n\", data->map->dm_nsegs);\n    if (data->map->dm_nsegs == 0) {\n        XYLog(\"RX Map new address FAIL!!!!\\n\");\n        /* XXX */\n        if (fatal)\n            panic(\"iwm: could not load RX mbuf\");\n        mbuf_freem(m);\n        return ENOMEM;\n    }\n    data->m = m;\n    //    bus_dmamap_sync(sc->sc_dmat, data->map, 0, size, BUS_DMASYNC_PREREAD);\n    \n    /* Update RX descriptor. */\n    if (sc->sc_mqrx_supported) {\n        ((uint64_t *)ring->desc)[idx] =\n        htole64(seg.location);\n        //        bus_dmamap_sync(sc->sc_dmat, ring->free_desc_dma.map,\n        //            idx * sizeof(uint64_t), sizeof(uint64_t),\n        //            BUS_DMASYNC_PREWRITE);\n    } else {\n        ((uint32_t *)ring->desc)[idx] =\n        htole32(seg.location >> 8);\n        //        bus_dmamap_sync(sc->sc_dmat, ring->free_desc_dma.map,\n        //            idx * sizeof(uint32_t), sizeof(uint32_t),\n        //            BUS_DMASYNC_PREWRITE);\n    }\n    \n    return 0;\n}\n\nvoid ItlIwm::\niwm_rx_rx_phy_cmd(struct iwm_softc *sc, struct iwm_rx_packet *pkt,\n                  struct iwm_rx_data *data)\n{\n    struct iwm_rx_phy_info *phy_info = (struct iwm_rx_phy_info *)pkt->data;\n    \n    //    bus_dmamap_sync(sc->sc_dmat, data->map, sizeof(*pkt),\n    //        sizeof(*phy_info), BUS_DMASYNC_POSTREAD);\n    \n    memcpy(&sc->sc_last_phy_info, phy_info, sizeof(sc->sc_last_phy_info));\n}\n\nvoid ItlIwm::\niwm_rx_mpdu(struct iwm_softc *sc, mbuf_t m, void *pktdata,\n            size_t maxlen, struct mbuf_list *ml)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct ieee80211_rxinfo rxi;\n    struct ieee80211_rx_status rx_status;\n    struct iwm_rx_phy_info *phy_info;\n    struct iwm_rx_mpdu_res_start *rx_res;\n    int device_timestamp;\n    uint16_t phy_flags;\n    uint32_t len;\n    uint32_t rx_pkt_status;\n    int rssi, chanidx, rate_n_flags;\n    \n    memset(&rxi, 0, sizeof(rxi));\n    memset(&rx_status, 0, sizeof(struct ieee80211_rx_status));\n    \n    phy_info = &sc->sc_last_phy_info;\n    rx_res = (struct iwm_rx_mpdu_res_start *)pktdata;\n    len = le16toh(rx_res->byte_count);\n    if (ic->ic_opmode == IEEE80211_M_MONITOR) {\n        /* Allow control frames in monitor mode. */\n        if (len < sizeof(struct ieee80211_frame_cts)) {\n            ic->ic_stats.is_rx_tooshort++;\n            IC2IFP(ic)->netStat->inputErrors++;\n            mbuf_freem(m);\n            return;\n        }\n    } else if (len < sizeof(struct ieee80211_frame)) {\n        ic->ic_stats.is_rx_tooshort++;\n        IC2IFP(ic)->netStat->inputErrors++;\n        mbuf_freem(m);\n        return;\n    }\n    if (len > maxlen - sizeof(*rx_res)) {\n        IC2IFP(ic)->netStat->inputErrors++;\n        mbuf_freem(m);\n        return;\n    }\n    \n    if (phy_info->cfg_phy_cnt > 20) {\n        mbuf_freem(m);\n        return;\n    }\n    \n    rx_pkt_status = le32toh(*(uint32_t *)((uint8_t*)pktdata + sizeof(*rx_res) + len));\n    if (!(rx_pkt_status & IWM_RX_MPDU_RES_STATUS_CRC_OK) ||\n        !(rx_pkt_status & IWM_RX_MPDU_RES_STATUS_OVERRUN_OK)) {\n        mbuf_freem(m);\n        return; /* drop */\n    }\n    \n    //    m->m_data = pktdata + sizeof(*rx_res);\n    //    m->m_pkthdr.len = m->m_len = len;\n    mbuf_setdata(m, ((uint8_t*)pktdata + sizeof(*rx_res)), len);\n    mbuf_pkthdr_setlen(m, len);\n    mbuf_setlen(m, len);\n    \n    if (iwm_rx_hwdecrypt(sc, m, rx_pkt_status, &rxi)) {\n        mbuf_freem(m);\n        return;\n    }\n    \n    chanidx = letoh32(phy_info->channel);\n    device_timestamp = le32toh(phy_info->system_timestamp);\n    phy_flags = letoh16(phy_info->phy_flags);\n    rate_n_flags = le32toh(phy_info->rate_n_flags);\n\n    rssi = iwm_get_signal_strength(sc, &rx_status, phy_info);\n    rs_update_last_rssi(sc, &rx_status);\n    rssi = (0 - IWM_MIN_DBM) + rssi;    /* normalize */\n    rssi = MIN(rssi, ic->ic_max_rssi);    /* clip to max. 100% */\n\n    rxi.rxi_rssi = rssi;\n    rxi.rxi_tstamp = device_timestamp;\n    rxi.rxi_chan = chanidx;\n    \n    iwm_rx_frame(sc, m, chanidx, rx_pkt_status,\n                 (phy_flags & IWM_PHY_INFO_FLAG_SHPREAMBLE),\n                 rate_n_flags, device_timestamp, &rxi, ml);\n}\n\nvoid ItlIwm::\niwm_flip_address(uint8_t *addr)\n{\n    int i;\n    uint8_t mac_addr[ETHER_ADDR_LEN];\n    \n    for (i = 0; i < ETHER_ADDR_LEN; i++)\n        mac_addr[i] = addr[ETHER_ADDR_LEN - i - 1];\n    IEEE80211_ADDR_COPY(addr, mac_addr);\n}\n\n/*\n * Drop duplicate 802.11 retransmissions\n * (IEEE 802.11-2012: 9.3.2.10 \"Duplicate detection and recovery\")\n * and handle pseudo-duplicate frames which result from deaggregation\n * of A-MSDU frames in hardware.\n */\nint ItlIwm::\niwm_detect_duplicate(struct iwm_softc *sc, mbuf_t m,\n                     struct iwm_rx_mpdu_desc *desc, struct ieee80211_rxinfo *rxi)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct iwm_node *in = (struct iwm_node *)ic->ic_bss;\n    struct iwm_rxq_dup_data *dup_data = &in->dup_data;\n    uint8_t tid = IWM_MAX_TID_COUNT, subframe_idx;\n    struct ieee80211_frame *wh = mtod(m, struct ieee80211_frame *);\n    uint8_t type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;\n    uint8_t subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;\n    int hasqos = ieee80211_has_qos(wh);\n    uint16_t seq;\n    \n    if (type == IEEE80211_FC0_TYPE_CTL ||\n        (hasqos && (subtype & IEEE80211_FC0_SUBTYPE_NODATA)) ||\n        IEEE80211_IS_MULTICAST(wh->i_addr1))\n        return 0;\n    \n    if (hasqos) {\n        tid = (ieee80211_get_qos(wh) & IEEE80211_QOS_TID);\n        if (tid > IWM_MAX_TID_COUNT)\n            tid = IWM_MAX_TID_COUNT;\n    }\n    \n    /* If this wasn't a part of an A-MSDU the sub-frame index will be 0 */\n    subframe_idx = desc->amsdu_info &\n    IWM_RX_MPDU_AMSDU_SUBFRAME_IDX_MASK;\n    \n    seq = letoh16(*(u_int16_t *)wh->i_seq) >> IEEE80211_SEQ_SEQ_SHIFT;\n    if ((wh->i_fc[1] & IEEE80211_FC1_RETRY) &&\n        dup_data->last_seq[tid] == seq &&\n        dup_data->last_sub_frame[tid] >= subframe_idx)\n        return 1;\n    \n    /*\n     * Allow the same frame sequence number for all A-MSDU subframes\n     * following the first subframe.\n     * Otherwise these subframes would be discarded as replays.\n     */\n    if (dup_data->last_seq[tid] == seq &&\n        subframe_idx > dup_data->last_sub_frame[tid] &&\n        (desc->mac_flags2 & IWM_RX_MPDU_MFLG2_AMSDU)) {\n        rxi->rxi_flags |= IEEE80211_RXI_SAME_SEQ;\n    }\n    \n    dup_data->last_seq[tid] = seq;\n    dup_data->last_sub_frame[tid] = subframe_idx;\n    \n    return 0;\n}\n\n/*\n * Returns true if sn2 - buffer_size < sn1 < sn2.\n * To be used only in order to compare reorder buffer head with NSSN.\n * We fully trust NSSN unless it is behind us due to reorder timeout.\n * Reorder timeout can only bring us up to buffer_size SNs ahead of NSSN.\n */\nint ItlIwm::\niwm_is_sn_less(uint16_t sn1, uint16_t sn2, uint16_t buffer_size)\n{\n    return SEQ_LT(sn1, sn2) && !SEQ_LT(sn1, sn2 - buffer_size);\n}\n\nvoid ItlIwm::\niwm_release_frames(struct iwm_softc *sc, struct ieee80211_node *ni,\n                   struct iwm_rxba_data *rxba, struct iwm_reorder_buffer *reorder_buf,\n                   uint16_t nssn, struct mbuf_list *ml)\n{\n    struct iwm_reorder_buf_entry *entries = &rxba->entries[0];\n    uint16_t ssn = reorder_buf->head_sn;\n    \n    /* ignore nssn smaller than head sn - this can happen due to timeout */\n    if (iwm_is_sn_less(nssn, ssn, reorder_buf->buf_size))\n        goto set_timer;\n    \n    while (iwm_is_sn_less(ssn, nssn, reorder_buf->buf_size)) {\n        int index = ssn % reorder_buf->buf_size;\n        mbuf_t m;\n        int chanidx, is_shortpre;\n        uint32_t rx_pkt_status, rate_n_flags, device_timestamp;\n        struct ieee80211_rxinfo *rxi;\n        \n        /* This data is the same for all A-MSDU subframes. */\n        chanidx = entries[index].chanidx;\n        rx_pkt_status = entries[index].rx_pkt_status;\n        is_shortpre = entries[index].is_shortpre;\n        rate_n_flags = entries[index].rate_n_flags;\n        device_timestamp = entries[index].device_timestamp;\n        rxi = &entries[index].rxi;\n        \n        /*\n         * Empty the list. Will have more than one frame for A-MSDU.\n         * Empty list is valid as well since nssn indicates frames were\n         * received.\n         */\n        while ((m = ml_dequeue(&entries[index].frames)) != NULL) {\n            iwm_rx_frame(sc, m, chanidx, rx_pkt_status, is_shortpre,\n                         rate_n_flags, device_timestamp, rxi, ml);\n            reorder_buf->num_stored--;\n            \n            /*\n             * Allow the same frame sequence number and CCMP PN for\n             * all A-MSDU subframes following the first subframe.\n             * Otherwise they would be discarded as replays.\n             */\n            rxi->rxi_flags |= IEEE80211_RXI_SAME_SEQ;\n            rxi->rxi_flags |= IEEE80211_RXI_HWDEC_SAME_PN;\n        }\n        \n        ssn = (ssn + 1) & 0xfff;\n    }\n    reorder_buf->head_sn = nssn;\n    \nset_timer:\n    if (reorder_buf->num_stored && !reorder_buf->removed) {\n        timeout_add_usec(&reorder_buf->reorder_timer,\n                         RX_REORDER_BUF_TIMEOUT_MQ_USEC);\n    } else\n        timeout_del(&reorder_buf->reorder_timer);\n}\n\nint ItlIwm::\niwm_oldsn_workaround(struct iwm_softc *sc, struct ieee80211_node *ni, int tid,\n                     struct iwm_reorder_buffer *buffer, uint32_t reorder_data, uint32_t gp2)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    \n    if (gp2 != buffer->consec_oldsn_ampdu_gp2) {\n        /* we have a new (A-)MPDU ... */\n        \n        /*\n         * reset counter to 0 if we didn't have any oldsn in\n         * the last A-MPDU (as detected by GP2 being identical)\n         */\n        if (!buffer->consec_oldsn_prev_drop)\n            buffer->consec_oldsn_drops = 0;\n        \n        /* either way, update our tracking state */\n        buffer->consec_oldsn_ampdu_gp2 = gp2;\n    } else if (buffer->consec_oldsn_prev_drop) {\n        /*\n         * tracking state didn't change, and we had an old SN\n         * indication before - do nothing in this case, we\n         * already noted this one down and are waiting for the\n         * next A-MPDU (by GP2)\n         */\n        return 0;\n    }\n    \n    /* return unless this MPDU has old SN */\n    if (!(reorder_data & IWM_RX_MPDU_REORDER_BA_OLD_SN))\n        return 0;\n    \n    /* update state */\n    buffer->consec_oldsn_prev_drop = 1;\n    buffer->consec_oldsn_drops++;\n    \n    /* if limit is reached, send del BA and reset state */\n    if (buffer->consec_oldsn_drops == IWM_AMPDU_CONSEC_DROPS_DELBA) {\n        XYLog(\"reached %d old SN frames, stopping BA session on TID %d\\n\",\n              IWM_AMPDU_CONSEC_DROPS_DELBA, tid);\n        ieee80211_delba_request(ic, ni, IEEE80211_REASON_UNSPECIFIED,\n                                0, tid);\n        buffer->consec_oldsn_prev_drop = 0;\n        buffer->consec_oldsn_drops = 0;\n        return 1;\n    }\n    \n    return 0;\n}\n\n/*\n * Handle re-ordering of frames which were de-aggregated in hardware.\n * Returns 1 if the MPDU was consumed (buffered or dropped).\n * Returns 0 if the MPDU should be passed to upper layer.\n */\nint ItlIwm::\niwm_rx_reorder(struct iwm_softc *sc, mbuf_t m, int chanidx,\n               struct iwm_rx_mpdu_desc *desc, int is_shortpre, int rate_n_flags,\n               uint32_t device_timestamp, struct ieee80211_rxinfo *rxi,\n               struct mbuf_list *ml)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct ieee80211_frame *wh;\n    struct ieee80211_node *ni;\n    struct iwm_rxba_data *rxba;\n    struct iwm_reorder_buffer *buffer;\n    uint32_t reorder_data = le32toh(desc->reorder_data);\n    int is_amsdu = (desc->mac_flags2 & IWM_RX_MPDU_MFLG2_AMSDU);\n    int last_subframe =\n    (desc->amsdu_info & IWM_RX_MPDU_AMSDU_LAST_SUBFRAME);\n    uint8_t tid;\n    uint8_t subframe_idx = (desc->amsdu_info &\n                            IWM_RX_MPDU_AMSDU_SUBFRAME_IDX_MASK);\n    struct iwm_reorder_buf_entry *entries;\n    int index;\n    uint16_t nssn, sn;\n    uint8_t baid, type, subtype;\n    int hasqos;\n    \n    wh = mtod(m, struct ieee80211_frame *);\n    hasqos = ieee80211_has_qos(wh);\n    tid = hasqos ? ieee80211_get_qos(wh) & IEEE80211_QOS_TID : 0;\n    \n    type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;\n    subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;\n    \n    /*\n     * We are only interested in Block Ack requests and unicast QoS data.\n     */\n    if (IEEE80211_IS_MULTICAST(wh->i_addr1))\n        return 0;\n    if (hasqos) {\n        if (subtype & IEEE80211_FC0_SUBTYPE_NODATA)\n            return 0;\n    } else {\n        if (type != IEEE80211_FC0_TYPE_CTL ||\n            subtype != IEEE80211_FC0_SUBTYPE_BAR)\n            return 0;\n    }\n    \n    baid = (reorder_data & IWM_RX_MPDU_REORDER_BAID_MASK) >>\n    IWM_RX_MPDU_REORDER_BAID_SHIFT;\n    if (baid == IWM_RX_REORDER_DATA_INVALID_BAID ||\n        baid >= nitems(sc->sc_rxba_data))\n        return 0;\n    \n    rxba = &sc->sc_rxba_data[baid];\n    if (rxba->reorder_buf.buf_size == 0 || tid != rxba->tid || rxba->sta_id != IWM_STATION_ID)\n        return 0;\n    \n    if (rxba->timeout != 0)\n        getmicrouptime(&rxba->last_rx);\n    \n    /* Bypass A-MPDU re-ordering in net80211. */\n    rxi->rxi_flags |= IEEE80211_RXI_AMPDU_DONE;\n    \n    nssn = reorder_data & IWM_RX_MPDU_REORDER_NSSN_MASK;\n    sn = (reorder_data & IWM_RX_MPDU_REORDER_SN_MASK) >>\n    IWM_RX_MPDU_REORDER_SN_SHIFT;\n    \n    buffer = &rxba->reorder_buf;\n    entries = &rxba->entries[0];\n    \n    if (!buffer->valid) {\n        if (reorder_data & IWM_RX_MPDU_REORDER_BA_OLD_SN)\n            return 0;\n        buffer->valid = 1;\n    }\n    \n    ni = ieee80211_find_rxnode(ic, wh);\n    if (type == IEEE80211_FC0_TYPE_CTL &&\n        subtype == IEEE80211_FC0_SUBTYPE_BAR) {\n        iwm_release_frames(sc, ni, rxba, buffer, nssn, ml);\n        goto drop;\n    }\n    \n    /*\n     * If there was a significant jump in the nssn - adjust.\n     * If the SN is smaller than the NSSN it might need to first go into\n     * the reorder buffer, in which case we just release up to it and the\n     * rest of the function will take care of storing it and releasing up to\n     * the nssn.\n     */\n    if (!iwm_is_sn_less(nssn, buffer->head_sn + buffer->buf_size,\n                        buffer->buf_size) ||\n        !SEQ_LT(sn, buffer->head_sn + buffer->buf_size)) {\n        uint16_t min_sn = SEQ_LT(sn, nssn) ? sn : nssn;\n        ic->ic_stats.is_ht_rx_frame_above_ba_winend++;\n        iwm_release_frames(sc, ni, rxba, buffer, min_sn, ml);\n    }\n    \n    if (iwm_oldsn_workaround(sc, ni, tid, buffer, reorder_data,\n                             device_timestamp)) {\n        /* BA session will be torn down. */\n        ic->ic_stats.is_ht_rx_ba_window_jump++;\n        goto drop;\n        \n    }\n    \n    /* drop any outdated packets */\n    if (SEQ_LT(sn, buffer->head_sn)) {\n        ic->ic_stats.is_ht_rx_frame_below_ba_winstart++;\n        goto drop;\n    }\n    \n    /* release immediately if allowed by nssn and no stored frames */\n    if (!buffer->num_stored && SEQ_LT(sn, nssn)) {\n        if (iwm_is_sn_less(buffer->head_sn, nssn, buffer->buf_size) &&\n            (!is_amsdu || last_subframe))\n            buffer->head_sn = nssn;\n        ieee80211_release_node(ic, ni);\n        return 0;\n    }\n    \n    /*\n     * release immediately if there are no stored frames, and the sn is\n     * equal to the head.\n     * This can happen due to reorder timer, where NSSN is behind head_sn.\n     * When we released everything, and we got the next frame in the\n     * sequence, according to the NSSN we can't release immediately,\n     * while technically there is no hole and we can move forward.\n     */\n    if (!buffer->num_stored && sn == buffer->head_sn) {\n        if (!is_amsdu || last_subframe)\n            buffer->head_sn = (buffer->head_sn + 1) & 0xfff;\n        ieee80211_release_node(ic, ni);\n        return 0;\n    }\n    \n    index = sn % buffer->buf_size;\n    \n    /*\n     * Check if we already stored this frame\n     * As AMSDU is either received or not as whole, logic is simple:\n     * If we have frames in that position in the buffer and the last frame\n     * originated from AMSDU had a different SN then it is a retransmission.\n     * If it is the same SN then if the subframe index is incrementing it\n     * is the same AMSDU - otherwise it is a retransmission.\n     */\n    if (!ml_empty(&entries[index].frames)) {\n        if (!is_amsdu) {\n            ic->ic_stats.is_ht_rx_ba_no_buf++;\n            goto drop;\n        } else if (sn != buffer->last_amsdu ||\n                   buffer->last_sub_index >= subframe_idx) {\n            ic->ic_stats.is_ht_rx_ba_no_buf++;\n            goto drop;\n        }\n    } else {\n        /* This data is the same for all A-MSDU subframes. */\n        entries[index].chanidx = chanidx;\n        entries[index].is_shortpre = is_shortpre;\n        entries[index].rate_n_flags = rate_n_flags;\n        entries[index].device_timestamp = device_timestamp;\n        memcpy(&entries[index].rxi, rxi, sizeof(entries[index].rxi));\n    }\n    \n    /* put in reorder buffer */\n    ml_enqueue(&entries[index].frames, m);\n    buffer->num_stored++;\n    getmicrouptime(&entries[index].reorder_time);\n    \n    if (is_amsdu) {\n        buffer->last_amsdu = sn;\n        buffer->last_sub_index = subframe_idx;\n    }\n    \n    /*\n     * We cannot trust NSSN for AMSDU sub-frames that are not the last.\n     * The reason is that NSSN advances on the first sub-frame, and may\n     * cause the reorder buffer to advance before all the sub-frames arrive.\n     * Example: reorder buffer contains SN 0 & 2, and we receive AMSDU with\n     * SN 1. NSSN for first sub frame will be 3 with the result of driver\n     * releasing SN 0,1, 2. When sub-frame 1 arrives - reorder buffer is\n     * already ahead and it will be dropped.\n     * If the last sub-frame is not on this queue - we will get frame\n     * release notification with up to date NSSN.\n     */\n    if (!is_amsdu || last_subframe)\n        iwm_release_frames(sc, ni, rxba, buffer, nssn, ml);\n    \n    ieee80211_release_node(ic, ni);\n    return 1;\n    \ndrop:\n    mbuf_freem(m);\n    ieee80211_release_node(ic, ni);\n    return 1;\n}\n\nvoid ItlIwm::\niwm_rx_mpdu_mq(struct iwm_softc *sc, mbuf_t m, void *pktdata,\n               size_t maxlen, struct mbuf_list *ml)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct ieee80211_rxinfo rxi;\n    struct ieee80211_rx_status rx_status;\n    struct iwm_rx_mpdu_desc *desc;\n    uint32_t len, hdrlen, rate_n_flags, device_timestamp;\n    int rssi;\n    uint8_t chanidx;\n    uint16_t phy_info;\n    \n    memset(&rxi, 0, sizeof(rxi));\n    memset(&rx_status, 0, sizeof(struct ieee80211_rx_status));\n    \n    desc = (struct iwm_rx_mpdu_desc *)pktdata;\n    \n    if (!(desc->status & htole16(IWM_RX_MPDU_RES_STATUS_CRC_OK)) ||\n        !(desc->status & htole16(IWM_RX_MPDU_RES_STATUS_OVERRUN_OK))) {\n        mbuf_freem(m);\n        return; /* drop */\n    }\n    \n    len = le16toh(desc->mpdu_len);\n    if (ic->ic_opmode == IEEE80211_M_MONITOR) {\n        /* Allow control frames in monitor mode. */\n        if (len < sizeof(struct ieee80211_frame_cts)) {\n            ic->ic_stats.is_rx_tooshort++;\n            IC2IFP(ic)->netStat->inputErrors++;\n            mbuf_freem(m);\n            return;\n        }\n    } else if (len < sizeof(struct ieee80211_frame)) {\n        ic->ic_stats.is_rx_tooshort++;\n        IC2IFP(ic)->netStat->inputErrors++;\n        mbuf_freem(m);\n        return;\n    }\n    if (len > maxlen - sizeof(*desc)) {\n        IC2IFP(ic)->netStat->inputErrors++;\n        mbuf_freem(m);\n        return;\n    }\n    \n    //    m->m_data = pktdata + sizeof(*desc);\n    //    m->m_pkthdr.len = m->m_len = len;\n    mbuf_setdata(m, (uint8_t*)pktdata + sizeof(*desc), len);\n    mbuf_pkthdr_setlen(m, len);\n    mbuf_setlen(m, len);\n    \n    /* Account for padding following the frame header. */\n    if (desc->mac_flags2 & IWM_RX_MPDU_MFLG2_PAD) {\n        struct ieee80211_frame *wh = mtod(m, struct ieee80211_frame *);\n        int type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;\n        if (type == IEEE80211_FC0_TYPE_CTL) {\n            switch (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) {\n                case IEEE80211_FC0_SUBTYPE_CTS:\n                    hdrlen = sizeof(struct ieee80211_frame_cts);\n                    break;\n                case IEEE80211_FC0_SUBTYPE_ACK:\n                    hdrlen = sizeof(struct ieee80211_frame_ack);\n                    break;\n                default:\n                    hdrlen = sizeof(struct ieee80211_frame_min);\n                    break;\n            }\n        } else\n            hdrlen = ieee80211_get_hdrlen(wh);\n        \n        if ((le16toh(desc->status) &\n             IWM_RX_MPDU_RES_STATUS_SEC_ENC_MSK) ==\n            IWM_RX_MPDU_RES_STATUS_SEC_CCM_ENC) {\n            /* Padding is inserted after the IV. */\n            hdrlen += IEEE80211_CCMP_HDRLEN;\n        }\n        \n        memmove((uint8_t*)mbuf_data(m) + 2, mbuf_data(m), hdrlen);\n        mbuf_adj(m, 2);\n    }\n    \n    /*\n     * Hardware de-aggregates A-MSDUs and copies the same MAC header\n     * in place for each subframe. But it leaves the 'A-MSDU present'\n     * bit set in the frame header. We need to clear this bit ourselves.\n     *\n     * And we must allow the same CCMP PN for subframes following the\n     * first subframe. Otherwise they would be discarded as replays.\n     */\n    if (desc->mac_flags2 & IWM_RX_MPDU_MFLG2_AMSDU) {\n        struct ieee80211_frame *wh = mtod(m, struct ieee80211_frame *);\n        uint8_t subframe_idx = (desc->amsdu_info &\n                                IWM_RX_MPDU_AMSDU_SUBFRAME_IDX_MASK);\n        if (subframe_idx > 0)\n            rxi.rxi_flags |= IEEE80211_RXI_HWDEC_SAME_PN;\n        if (ieee80211_has_qos(wh) && ieee80211_has_addr4(wh) &&\n            mbuf_len(m) >= sizeof(struct ieee80211_qosframe_addr4)) {\n            struct ieee80211_qosframe_addr4 *qwh4 = mtod(m,\n                                                         struct ieee80211_qosframe_addr4 *);\n            qwh4->i_qos[0] &= htole16(~IEEE80211_QOS_AMSDU);\n            \n            /* HW reverses addr3 and addr4. */\n            iwm_flip_address(qwh4->i_addr3);\n            iwm_flip_address(qwh4->i_addr4);\n        } else if (ieee80211_has_qos(wh) &&\n                   mbuf_len(m) >= sizeof(struct ieee80211_qosframe)) {\n            struct ieee80211_qosframe *qwh = mtod(m,\n                                                  struct ieee80211_qosframe *);\n            qwh->i_qos[0] &= htole16(~IEEE80211_QOS_AMSDU);\n            \n            /* HW reverses addr3. */\n            iwm_flip_address(qwh->i_addr3);\n        }\n    }\n    \n    /*\n     * Verify decryption before duplicate detection. The latter uses\n     * the TID supplied in QoS frame headers and this TID is implicitly\n     * verified as part of the CCMP nonce.\n     */\n    if (iwm_rx_hwdecrypt(sc, m, le16toh(desc->status), &rxi)) {\n        mbuf_freem(m);\n        return;\n    }\n    \n    if (iwm_detect_duplicate(sc, m, desc, &rxi)) {\n        mbuf_freem(m);\n        return;\n    }\n    \n    phy_info = le16toh(desc->phy_info);\n    rate_n_flags = le32toh(desc->v1.rate_n_flags);\n    chanidx = desc->v1.channel;\n    device_timestamp = desc->v1.gp2_on_air_rise;\n    \n    rssi = iwm_rxmq_get_signal_strength(sc, &rx_status, rate_n_flags, desc);\n    rs_update_last_rssi(sc, &rx_status);\n    rssi = (0 - IWM_MIN_DBM) + rssi;    /* normalize */\n    rssi = MIN(rssi, ic->ic_max_rssi);    /* clip to max. 100% */\n    \n    rxi.rxi_rssi = rssi;\n    rxi.rxi_tstamp = le64toh(desc->v1.tsf_on_air_rise);\n    rxi.rxi_chan = chanidx;\n    \n    if (iwm_rx_reorder(sc, m, chanidx, desc,\n                       (phy_info & IWM_RX_MPDU_PHY_SHORT_PREAMBLE),\n                       rate_n_flags, device_timestamp, &rxi, ml))\n        return;\n    \n    iwm_rx_frame(sc, m, chanidx, le16toh(desc->status),\n                 (phy_info & IWM_RX_MPDU_PHY_SHORT_PREAMBLE),\n                 rate_n_flags, device_timestamp, &rxi, ml);\n}\n\nint ItlIwm::\niwm_rx_pkt_valid(struct iwm_rx_packet *pkt)\n{\n    int qid, idx, code;\n    \n    qid = pkt->hdr.qid & ~0x80;\n    idx = pkt->hdr.idx;\n    code = IWM_WIDE_ID(pkt->hdr.flags, pkt->hdr.code);\n    \n    return (!(qid == 0 && idx == 0 && code == 0) &&\n            pkt->len_n_flags != htole32(IWM_FH_RSCSR_FRAME_INVALID));\n}\n\n#define SYNC_RESP_STRUCT(_var_, _pkt_, t)                    \\\ndo {                                    \\\nbus_dmamap_sync(sc->sc_dmat, data->map, sizeof(*(_pkt_)),    \\\nsizeof(*(_var_)), BUS_DMASYNC_POSTREAD);            \\\n_var_ = (t)((_pkt_)+1);                    \\\n} while (/*CONSTCOND*/0)\n\nvoid ItlIwm::\niwm_rx_pkt(struct iwm_softc *sc, struct iwm_rx_data *data, struct mbuf_list *ml)\n{\n    struct _ifnet *ifp = IC2IFP(&sc->sc_ic);\n    struct iwm_rx_packet *pkt, *nextpkt;\n    uint32_t offset = 0, nextoff = 0, nmpdu = 0, len;\n    mbuf_t m0, m = NULL;\n    const size_t minsz = sizeof(pkt->len_n_flags) + sizeof(pkt->hdr);\n    int qid, idx, code, handled = 1;\n    \n    //    bus_dmamap_sync(sc->sc_dmat, data->map, 0, IWM_RBUF_SIZE,\n    //        BUS_DMASYNC_POSTREAD);\n    m0 = data->m;\n    while (m0 && offset + minsz < IWM_RBUF_SIZE) {\n        pkt = (struct iwm_rx_packet *)((uint8_t*)mbuf_data(m0) + offset);\n        qid = pkt->hdr.qid;\n        idx = pkt->hdr.idx;\n        \n        code = IWM_WIDE_ID(pkt->hdr.flags, pkt->hdr.code);\n        \n        if (!iwm_rx_pkt_valid(pkt))\n            break;\n        \n        len = sizeof(pkt->len_n_flags) + iwm_rx_packet_len(pkt);\n        if (len < minsz || len > (IWM_RBUF_SIZE - offset))\n            break;\n        \n        if (code == IWM_REPLY_RX_MPDU_CMD && ++nmpdu == 1) {\n            /* Take mbuf m0 off the RX ring. */\n            if (iwm_rx_addbuf(sc, IWM_RBUF_SIZE, sc->rxq.cur)) {\n                ifp->netStat->inputErrors++;\n                break;\n            }\n            \n//            KASSERT(data->m != m0, \"data->m != m0\");\n        }\n        \n        switch (code) {\n            case IWM_REPLY_RX_PHY_CMD:\n                iwm_rx_rx_phy_cmd(sc, pkt, data);\n                break;\n                \n            case IWM_REPLY_RX_MPDU_CMD: {\n                size_t maxlen = IWM_RBUF_SIZE - offset - minsz;\n                nextoff = offset +\n                roundup(len, IWM_FH_RSCSR_FRAME_ALIGN);\n                nextpkt = (struct iwm_rx_packet *)\n                ((uint8_t*)mbuf_data(m0) + nextoff);\n                if (nextoff + minsz >= IWM_RBUF_SIZE ||\n                    !iwm_rx_pkt_valid(nextpkt)) {\n                    /* No need to copy last frame in buffer. */\n                    if (offset > 0)\n                        mbuf_adj(m0, offset);\n                    if (sc->sc_mqrx_supported)\n                        iwm_rx_mpdu_mq(sc, m0, pkt->data,\n                                       maxlen, ml);\n                    else\n                        iwm_rx_mpdu(sc, m0, pkt->data,\n                                    maxlen, ml);\n                    m0 = NULL; /* stack owns m0 now; abort loop */\n                } else {\n                    /*\n                     * Create an mbuf which points to the current\n                     * packet. Always copy from offset zero to\n                     * preserve m_pkthdr.\n                     */\n                    mbuf_copym(m0, 0, MBUF_COPYALL, MBUF_DONTWAIT, &m);\n                    //                m = m_copym(m0, 0, M_COPYALL, M_DONTWAIT);\n                    if (m == NULL) {\n                        ifp->netStat->inputErrors++;\n                        mbuf_freem(m0);\n                        m0 = NULL;\n                        break;\n                    }\n                    mbuf_adj(m, offset);\n                    if (sc->sc_mqrx_supported)\n                        iwm_rx_mpdu_mq(sc, m, pkt->data,\n                                       maxlen, ml);\n                    else\n                        iwm_rx_mpdu(sc, m, pkt->data,\n                                    maxlen, ml);\n                }\n                \n                break;\n            }\n                \n            case IWM_TX_CMD:\n                iwm_rx_tx_cmd(sc, pkt, data);\n                break;\n            case IWM_BA_NOTIF:\n                iwm_rx_tx_ba_notif(sc, pkt, data);\n                break;\n                \n            case IWM_MISSED_BEACONS_NOTIFICATION:\n                iwm_rx_bmiss(sc, pkt, data);\n                break;\n                \n            case IWM_MFUART_LOAD_NOTIFICATION:\n                break;\n                \n            case IWM_ALIVE: {\n                struct iwm_alive_resp_v1 *resp1;\n                struct iwm_alive_resp_v2 *resp2;\n                struct iwm_alive_resp_v3 *resp3;\n\n//                XYLog(\"%s: firmware alive, size=%d\\n\", __FUNCTION__, iwm_rx_packet_payload_len(pkt));\n\n                if (iwm_rx_packet_payload_len(pkt) == sizeof(*resp1)) {\n                    SYNC_RESP_STRUCT(resp1, pkt, struct iwm_alive_resp_v1 *);\n                    sc->sc_uc.uc_error_event_table\n                    = le32toh(resp1->error_event_table_ptr);\n                    sc->sc_uc.uc_log_event_table\n                    = le32toh(resp1->log_event_table_ptr);\n                    sc->sched_base = le32toh(resp1->scd_base_ptr);\n                    if (resp1->status == IWM_ALIVE_STATUS_OK)\n                        sc->sc_uc.uc_ok = 1;\n                    else\n                        sc->sc_uc.uc_ok = 0;\n                }\n                \n                if (iwm_rx_packet_payload_len(pkt) == sizeof(*resp2)) {\n                    SYNC_RESP_STRUCT(resp2, pkt, struct iwm_alive_resp_v2 *);\n                    sc->sc_uc.uc_error_event_table\n                    = le32toh(resp2->error_event_table_ptr);\n                    sc->sc_uc.uc_log_event_table\n                    = le32toh(resp2->log_event_table_ptr);\n                    sc->sched_base = le32toh(resp2->scd_base_ptr);\n                    sc->sc_uc.uc_umac_error_event_table\n                    = le32toh(resp2->error_info_addr);\n                    if (resp2->status == IWM_ALIVE_STATUS_OK)\n                        sc->sc_uc.uc_ok = 1;\n                    else\n                        sc->sc_uc.uc_ok = 0;\n                }\n                \n                if (iwm_rx_packet_payload_len(pkt) == sizeof(*resp3)) {\n                    SYNC_RESP_STRUCT(resp3, pkt, struct iwm_alive_resp_v3 *);\n                    sc->sc_uc.uc_error_event_table\n                    = le32toh(resp3->error_event_table_ptr);\n                    sc->sc_uc.uc_log_event_table\n                    = le32toh(resp3->log_event_table_ptr);\n                    sc->sched_base = le32toh(resp3->scd_base_ptr);\n                    sc->sc_uc.uc_umac_error_event_table\n                    = le32toh(resp3->error_info_addr);\n                    if (resp3->status == IWM_ALIVE_STATUS_OK)\n                        sc->sc_uc.uc_ok = 1;\n                    else\n                        sc->sc_uc.uc_ok = 0;\n                }\n                \n                sc->sc_uc.uc_intr = 1;\n                wakeupOn(&sc->sc_uc);\n                break;\n            }\n                \n            case IWM_CALIB_RES_NOTIF_PHY_DB: {\n                struct iwm_calib_res_notif_phy_db *phy_db_notif;\n                SYNC_RESP_STRUCT(phy_db_notif, pkt, struct iwm_calib_res_notif_phy_db *);\n                iwm_phy_db_set_section(sc, phy_db_notif);\n                sc->sc_init_complete |= IWM_CALIB_COMPLETE;\n                //                wakeupOn(&sc->sc_init_complete);\n                break;\n            }\n                \n            case IWM_STATISTICS_NOTIFICATION: {\n                struct iwm_notif_statistics *stats;\n                SYNC_RESP_STRUCT(stats, pkt, struct iwm_notif_statistics *);\n                memcpy(&sc->sc_stats, stats, sizeof(sc->sc_stats));\n                sc->sc_noise = iwm_get_noise(&stats->rx.general);\n                break;\n            }\n                \n            case IWM_MCC_CHUB_UPDATE_CMD: {\n                struct iwm_mcc_chub_notif *notif;\n                SYNC_RESP_STRUCT(notif, pkt, struct iwm_mcc_chub_notif *);\n                iwm_mcc_update(sc, notif);\n                break;\n            }\n                \n            case IWM_DTS_MEASUREMENT_NOTIFICATION:\n            case IWM_WIDE_ID(IWM_PHY_OPS_GROUP,\n                             IWM_DTS_MEASUREMENT_NOTIF_WIDE):\n            case IWM_WIDE_ID(IWM_PHY_OPS_GROUP,\n                             IWM_TEMP_REPORTING_THRESHOLDS_CMD):\n                break;\n\n            case IWM_WIDE_ID(IWM_PHY_OPS_GROUP,\n                             IWM_CT_KILL_NOTIFICATION): {\n                struct iwm_ct_kill_notif *notif;\n                SYNC_RESP_STRUCT(notif, pkt, struct iwm_ct_kill_notif *);\n                XYLog(\"%s: device at critical temperature (%u degC), \"\n                       \"stopping device\\n\",\n                       DEVNAME(sc), le16toh(notif->temperature));\n                sc->sc_flags |= IWM_FLAG_HW_ERR;\n                task_add(systq, &sc->init_task);\n                break;\n            }\n                \n            case IWM_ADD_STA_KEY:\n            case IWM_PHY_CONFIGURATION_CMD:\n            case IWM_TX_ANT_CONFIGURATION_CMD:\n            case IWM_ADD_STA:\n            case IWM_MAC_CONTEXT_CMD:\n            case IWM_REPLY_SF_CFG_CMD:\n            case IWM_POWER_TABLE_CMD:\n            case IWM_LTR_CONFIG:\n            case IWM_PHY_CONTEXT_CMD:\n            case IWM_BINDING_CONTEXT_CMD:\n            case IWM_WIDE_ID(IWM_LONG_GROUP, IWM_SCAN_CFG_CMD):\n            case IWM_WIDE_ID(IWM_LONG_GROUP, IWM_SCAN_REQ_UMAC):\n            case IWM_WIDE_ID(IWM_LONG_GROUP, IWM_SCAN_ABORT_UMAC):\n            case IWM_SCAN_OFFLOAD_REQUEST_CMD:\n            case IWM_SCAN_OFFLOAD_ABORT_CMD:\n            case IWM_REPLY_BEACON_FILTERING_CMD:\n            case IWM_MAC_PM_POWER_TABLE:\n            case IWM_TIME_QUOTA_CMD:\n            case IWM_REMOVE_STA:\n            case IWM_TXPATH_FLUSH:\n            case IWM_LQ_CMD:\n            case IWM_WIDE_ID(IWM_LONG_GROUP,\n                             IWM_FW_PAGING_BLOCK_CMD):\n            case IWM_BT_CONFIG:\n            case IWM_REPLY_THERMAL_MNG_BACKOFF:\n            case IWM_NVM_ACCESS_CMD:\n            case IWM_MCC_UPDATE_CMD:\n            case IWM_TIME_EVENT_CMD: {\n                size_t pkt_len;\n                \n                if (sc->sc_cmd_resp_pkt[idx] == NULL)\n                    break;\n                \n                //            bus_dmamap_sync(sc->sc_dmat, data->map, 0,\n                //                sizeof(*pkt), BUS_DMASYNC_POSTREAD);\n                \n                pkt_len = sizeof(pkt->len_n_flags) +\n                iwm_rx_packet_len(pkt);\n                \n                if ((pkt->hdr.flags & IWM_CMD_FAILED_MSK) ||\n                    pkt_len < sizeof(*pkt) ||\n                    pkt_len > sc->sc_cmd_resp_len[idx]) {\n                    ::free(sc->sc_cmd_resp_pkt[idx]);\n                    sc->sc_cmd_resp_pkt[idx] = NULL;\n                    break;\n                }\n                \n                //            bus_dmamap_sync(sc->sc_dmat, data->map, sizeof(*pkt),\n                //                pkt_len - sizeof(*pkt), BUS_DMASYNC_POSTREAD);\n                memcpy(sc->sc_cmd_resp_pkt[idx], pkt, pkt_len);\n                break;\n            }\n                \n                /* ignore */\n            case IWM_PHY_DB_CMD:\n                break;\n                \n            case IWM_INIT_COMPLETE_NOTIF:\n                sc->sc_init_complete |= IWM_INIT_COMPLETE;\n                wakeupOn(&sc->sc_init_complete);\n                break;\n                \n            case IWM_SCAN_OFFLOAD_COMPLETE: {\n                struct iwm_periodic_scan_complete *notif;\n                SYNC_RESP_STRUCT(notif, pkt, struct iwm_periodic_scan_complete *);\n                break;\n            }\n                \n            case IWM_SCAN_ITERATION_COMPLETE: {\n                struct iwm_lmac_scan_complete_notif *notif;\n                SYNC_RESP_STRUCT(notif, pkt, struct iwm_lmac_scan_complete_notif *);\n                iwm_endscan(sc);\n                break;\n            }\n                \n            case IWM_SCAN_COMPLETE_UMAC: {\n                struct iwm_umac_scan_complete *notif;\n                SYNC_RESP_STRUCT(notif, pkt, struct iwm_umac_scan_complete *);\n                iwm_endscan(sc);\n                break;\n            }\n                \n            case IWM_SCAN_ITERATION_COMPLETE_UMAC: {\n                struct iwm_umac_scan_iter_complete_notif *notif;\n                SYNC_RESP_STRUCT(notif, pkt, struct iwm_umac_scan_iter_complete_notif *);\n                iwm_endscan(sc);\n                break;\n            }\n                \n            case IWM_REPLY_ERROR: {\n                struct iwm_error_resp *resp;\n                SYNC_RESP_STRUCT(resp, pkt, struct iwm_error_resp *);\n                XYLog(\"%s: firmware error 0x%x, cmd 0x%x\\n\",\n                      DEVNAME(sc), le32toh(resp->error_type),\n                      resp->cmd_id);\n                break;\n            }\n                \n            case IWM_TIME_EVENT_NOTIFICATION: {\n                struct iwm_time_event_notif *notif;\n                uint32_t action;\n                SYNC_RESP_STRUCT(notif, pkt, struct iwm_time_event_notif *);\n                \n                if (sc->sc_time_event_uid != le32toh(notif->unique_id))\n                    break;\n                action = le32toh(notif->action);\n                if (action & IWM_TE_V2_NOTIF_HOST_EVENT_END)\n                    sc->sc_flags &= ~IWM_FLAG_TE_ACTIVE;\n                break;\n            }\n                \n            case IWM_WIDE_ID(IWM_SYSTEM_GROUP,\n                             IWM_FSEQ_VER_MISMATCH_NOTIFICATION):\n                break;\n                \n                /*\n                 * Firmware versions 21 and 22 generate some DEBUG_LOG_MSG\n                 * messages. Just ignore them for now.\n                 */\n            case IWM_DEBUG_LOG_MSG:\n                break;\n                \n            case IWM_MCAST_FILTER_CMD:\n                break;\n                \n            case IWM_SCD_QUEUE_CFG: {\n                struct iwm_scd_txq_cfg_rsp *rsp;\n                SYNC_RESP_STRUCT(rsp, pkt, struct iwm_scd_txq_cfg_rsp *);\n                \n                break;\n            }\n                \n            case IWM_WIDE_ID(IWM_DATA_PATH_GROUP, IWM_DQA_ENABLE_CMD):\n                break;\n\n            case IWM_WIDE_ID(IWM_SYSTEM_GROUP, IWM_SOC_CONFIGURATION_CMD):\n                break;\n                \n            default:\n                handled = 0;\n                XYLog(\"%s: unhandled firmware response 0x%x/0x%x \"\n                      \"rx ring %d[%d]\\n\",\n                      DEVNAME(sc), code, pkt->len_n_flags,\n                      (qid & ~0x80), idx);\n                break;\n        }\n        \n        /*\n         * uCode sets bit 0x80 when it originates the notification,\n         * i.e. when the notification is not a direct response to a\n         * command sent by the driver.\n         * For example, uCode issues IWM_REPLY_RX when it sends a\n         * received frame to the driver.\n         */\n        if (handled && !(qid & (1 << 7))) {\n            iwm_cmd_done(sc, qid, idx, code);\n        }\n        \n        offset += roundup(len, IWM_FH_RSCSR_FRAME_ALIGN);\n    }\n    \n    if (m0 && m0 != data->m && mbuf_type(m0) != MBUF_TYPE_FREE) {\n        mbuf_freem(m0);\n    }\n}\n"
  },
  {
    "path": "itlwm/hal_iwm/scan.cpp",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n/*    $OpenBSD: if_iwm.c,v 1.316 2020/12/07 20:09:24 tobhe Exp $    */\n\n/*\n * Copyright (c) 2014, 2016 genua gmbh <info@genua.de>\n *   Author: Stefan Sperling <stsp@openbsd.org>\n * Copyright (c) 2014 Fixup Software Ltd.\n * Copyright (c) 2017 Stefan Sperling <stsp@openbsd.org>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n/*-\n * Based on BSD-licensed source modules in the Linux iwlwifi driver,\n * which were used as the reference documentation for this implementation.\n *\n ***********************************************************************\n *\n * This file is provided under a dual BSD/GPLv2 license.  When using or\n * redistributing this file, you may do so under either license.\n *\n * GPL LICENSE SUMMARY\n *\n * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.\n * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH\n * Copyright(c) 2016 Intel Deutschland GmbH\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of version 2 of the GNU General Public License as\n * published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful, but\n * WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,\n * USA\n *\n * The full GNU General Public License is included in this distribution\n * in the file called COPYING.\n *\n * Contact Information:\n *  Intel Linux Wireless <ilw@linux.intel.com>\n * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497\n *\n *\n * BSD LICENSE\n *\n * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.\n * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH\n * Copyright(c) 2016 Intel Deutschland GmbH\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in\n *    the documentation and/or other materials provided with the\n *    distribution.\n *  * Neither the name Intel Corporation nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*-\n * Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n#include \"ItlIwm.hpp\"\n#include \"rs.h\"\n\nuint16_t ItlIwm::\niwm_scan_rx_chain(struct iwm_softc *sc)\n{\n    uint16_t rx_chain;\n    uint8_t rx_ant;\n    \n    rx_ant = iwm_fw_valid_rx_ant(sc);\n    rx_chain = rx_ant << IWM_PHY_RX_CHAIN_VALID_POS;\n    rx_chain |= rx_ant << IWM_PHY_RX_CHAIN_FORCE_MIMO_SEL_POS;\n    rx_chain |= rx_ant << IWM_PHY_RX_CHAIN_FORCE_SEL_POS;\n    rx_chain |= 0x1 << IWM_PHY_RX_CHAIN_DRIVER_FORCE_POS;\n    return htole16(rx_chain);\n}\n\nuint32_t ItlIwm::\niwm_scan_rate_n_flags(struct iwm_softc *sc, int flags, int no_cck)\n{\n    uint32_t tx_ant;\n    int i, ind;\n    \n    for (i = 0, ind = sc->sc_scan_last_antenna;\n         i < IWM_RATE_MCS_ANT_NUM; i++) {\n        ind = (ind + 1) % IWM_RATE_MCS_ANT_NUM;\n        if (iwm_fw_valid_tx_ant(sc) & (1 << ind)) {\n            sc->sc_scan_last_antenna = ind;\n            break;\n        }\n    }\n    tx_ant = (1 << sc->sc_scan_last_antenna) << IWM_RATE_MCS_ANT_POS;\n    \n    if ((flags & IEEE80211_CHAN_2GHZ) && !no_cck)\n        return htole32(IWL_RATE_1M_PLCP | RATE_MCS_CCK_MSK |\n                       tx_ant);\n    else\n        return htole32(IWL_RATE_6M_PLCP | tx_ant);\n}\n\nuint8_t ItlIwm::\niwm_lmac_scan_fill_channels(struct iwm_softc *sc,\n                            struct iwm_scan_channel_cfg_lmac *chan, int n_ssids, int bgscan)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct ieee80211_channel *c;\n    uint8_t nchan;\n    \n    for (nchan = 0, c = &ic->ic_channels[1];\n         c <= &ic->ic_channels[IEEE80211_CHAN_MAX] &&\n         nchan < sc->sc_capa_n_scan_channels;\n         c++) {\n        if (c->ic_flags == 0)\n            continue;\n        \n        chan->channel_num = htole16(ieee80211_mhz2ieee(c->ic_freq, 0));\n        chan->iter_count = htole16(1);\n        chan->iter_interval = 0;\n        chan->flags = htole32(IWM_UNIFIED_SCAN_CHANNEL_PARTIAL);\n        if (n_ssids != 0 && !bgscan)\n            chan->flags |= htole32(1 << 1); /* select SSID 0 */\n        chan++;\n        nchan++;\n    }\n    \n    return nchan;\n}\n\nuint8_t ItlIwm::\niwm_umac_scan_fill_channels(struct iwm_softc *sc,\n                            struct iwm_scan_channel_cfg_umac *chan, int n_ssids, int bgscan)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct ieee80211_channel *c;\n    uint8_t nchan;\n    \n    for (nchan = 0, c = &ic->ic_channels[1];\n         c <= &ic->ic_channels[IEEE80211_CHAN_MAX] &&\n         nchan < sc->sc_capa_n_scan_channels;\n         c++) {\n        if (c->ic_flags == 0)\n            continue;\n        \n        chan->channel_num = ieee80211_mhz2ieee(c->ic_freq, 0);\n        chan->iter_count = 1;\n        chan->iter_interval = htole16(0);\n        if (n_ssids != 0 && !bgscan)\n            chan->flags = htole32(1 << 0); /* select SSID 0 */\n        chan++;\n        nchan++;\n    }\n    \n    return nchan;\n}\n\nint ItlIwm::\niwm_fill_probe_req_v1(struct iwm_softc *sc, struct iwm_scan_probe_req_v1 *preq1)\n{\n    struct iwm_scan_probe_req preq2;\n    int err, i;\n    \n    err = iwm_fill_probe_req(sc, &preq2);\n    if (err)\n        return err;\n    \n    preq1->mac_header = preq2.mac_header;\n    for (i = 0; i < nitems(preq1->band_data); i++)\n        preq1->band_data[i] = preq2.band_data[i];\n    preq1->common_data = preq2.common_data;\n    memcpy(preq1->buf, preq2.buf, sizeof(preq1->buf));\n    return 0;\n}\n\nint ItlIwm::\niwm_fill_probe_req(struct iwm_softc *sc, struct iwm_scan_probe_req *preq)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct _ifnet *ifp = IC2IFP(ic);\n    struct ieee80211_frame *wh = (struct ieee80211_frame *)preq->buf;\n    struct ieee80211_rateset *rs;\n    size_t remain = sizeof(preq->buf);\n    uint8_t *frm, *pos;\n    \n    memset(preq, 0, sizeof(*preq));\n    \n    if (remain < sizeof(*wh) + 2)\n        return ENOBUFS;\n    \n    /*\n     * Build a probe request frame.  Most of the following code is a\n     * copy & paste of what is done in net80211.\n     */\n    wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT |\n    IEEE80211_FC0_SUBTYPE_PROBE_REQ;\n    wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;\n    //        IEEE80211_ADDR_COPY(ic->ic_myaddr, LLADDR(ifp->if_sadl));\n    IEEE80211_ADDR_COPY(wh->i_addr1, etherbroadcastaddr);\n    IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_myaddr);\n    IEEE80211_ADDR_COPY(wh->i_addr3, etherbroadcastaddr);\n    *(uint16_t *)&wh->i_dur[0] = 0;    /* filled by HW */\n    *(uint16_t *)&wh->i_seq[0] = 0;    /* filled by HW */\n    \n    frm = (uint8_t *)(wh + 1);\n    *frm++ = IEEE80211_ELEMID_SSID;\n    *frm++ = 0;\n    /* hardware inserts SSID */\n    \n    /* Tell firmware where the MAC header and SSID IE are. */\n    preq->mac_header.offset = 0;\n    preq->mac_header.len = htole16(frm - (uint8_t *)wh);\n    remain -= frm - (uint8_t *)wh;\n    \n    /* Fill in 2GHz IEs and tell firmware where they are. */\n    rs = &ic->ic_sup_rates[IEEE80211_MODE_11G];\n    if (rs->rs_nrates > IEEE80211_RATE_SIZE) {\n        if (remain < 4 + rs->rs_nrates)\n            return ENOBUFS;\n    } else if (remain < 2 + rs->rs_nrates)\n        return ENOBUFS;\n    preq->band_data[0].offset = htole16(frm - (uint8_t *)wh);\n    pos = frm;\n    frm = ieee80211_add_rates(frm, rs);\n    if (rs->rs_nrates > IEEE80211_RATE_SIZE)\n        frm = ieee80211_add_xrates(frm, rs);\n    remain -= frm - pos;\n    \n    if (isset(sc->sc_enabled_capa,\n              IWM_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT)) {\n        if (remain < 3)\n            return ENOBUFS;\n        *frm++ = IEEE80211_ELEMID_DSPARMS;\n        *frm++ = 1;\n        *frm++ = 0;\n        remain -= 3;\n    }\n    preq->band_data[0].len = htole16(frm - pos);\n    \n    if (sc->sc_nvm.sku_cap_band_52GHz_enable) {\n        /* Fill in 5GHz IEs. */\n        rs = &ic->ic_sup_rates[IEEE80211_MODE_11A];\n        if (rs->rs_nrates > IEEE80211_RATE_SIZE) {\n            if (remain < 4 + rs->rs_nrates)\n                return ENOBUFS;\n        } else if (remain < 2 + rs->rs_nrates)\n            return ENOBUFS;\n        preq->band_data[1].offset = htole16(frm - (uint8_t *)wh);\n        pos = frm;\n        frm = ieee80211_add_rates(frm, rs);\n        if (rs->rs_nrates > IEEE80211_RATE_SIZE)\n            frm = ieee80211_add_xrates(frm, rs);\n        preq->band_data[1].len = htole16(frm - pos);\n        remain -= frm - pos;\n        if (ic->ic_flags & IEEE80211_F_VHTON) {\n            if (remain < sizeof(struct ieee80211_ie_vhtcap))\n                return ENOBUFS;\n            frm = ieee80211_add_vhtcaps(frm, ic);\n            remain -= frm - pos;\n        }\n    }\n    \n    /* Send 11n IEs on both 2GHz and 5GHz bands. */\n    preq->common_data.offset = htole16(frm - (uint8_t *)wh);\n    pos = frm;\n    if (ic->ic_flags & IEEE80211_F_HTON) {\n        if (remain < sizeof(struct ieee80211_ie_htcap))\n            return ENOBUFS;\n        frm = ieee80211_add_htcaps(frm, ic);\n        /* XXX add WME info? */\n    }\n\n    preq->common_data.len = htole16(frm - pos);\n    \n    return 0;\n}\n\nint ItlIwm::\niwm_lmac_scan(struct iwm_softc *sc, int bgscan)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct iwm_host_cmd hcmd = {\n        .id = IWM_SCAN_OFFLOAD_REQUEST_CMD,\n        .len = { 0, },\n        .data = { NULL, },\n        .flags = 0,\n    };\n    struct iwm_scan_req_lmac *req;\n    struct iwm_scan_probe_req_v1 *preq;\n    size_t req_len;\n    int err, async = bgscan;\n    \n    req_len = sizeof(struct iwm_scan_req_lmac) +\n    (sizeof(struct iwm_scan_channel_cfg_lmac) *\n     sc->sc_capa_n_scan_channels) + sizeof(struct iwm_scan_probe_req_v1);\n    if (req_len > IWM_MAX_CMD_PAYLOAD_SIZE)\n        return ENOMEM;\n    req = (struct iwm_scan_req_lmac*)malloc(req_len, M_DEVBUF, M_NOWAIT);\n    if (req == NULL)\n        return ENOMEM;\n    bzero(req, req_len);\n    \n    hcmd.len[0] = (uint16_t)req_len;\n    hcmd.data[0] = (void *)req;\n    hcmd.flags |= async ? IWM_CMD_ASYNC : 0;\n    \n    /* These timings correspond to iwlwifi's UNASSOC scan. */\n    req->active_dwell = 10;\n    req->passive_dwell = 110;\n    req->fragmented_dwell = 44;\n    req->extended_dwell = 90;\n    if (bgscan) {\n        req->max_out_time = htole32(120);\n        req->suspend_time = htole32(120);\n    } else {\n        req->max_out_time = htole32(0);\n        req->suspend_time = htole32(0);\n    }\n    req->scan_prio = htole32(IWM_SCAN_PRIORITY_HIGH);\n    req->rx_chain_select = iwm_scan_rx_chain(sc);\n    req->iter_num = htole32(1);\n    req->delay = 0;\n    \n    req->scan_flags = htole32(IWM_LMAC_SCAN_FLAG_PASS_ALL |\n                              IWM_LMAC_SCAN_FLAG_ITER_COMPLETE |\n                              IWM_LMAC_SCAN_FLAG_EXTENDED_DWELL);\n    if (ic->ic_des_esslen == 0)\n        req->scan_flags |= htole32(IWM_LMAC_SCAN_FLAG_PASSIVE);\n    else\n        req->scan_flags |=\n        htole32(IWM_LMAC_SCAN_FLAG_PRE_CONNECTION);\n    if (isset(sc->sc_enabled_capa,\n              IWM_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT) &&\n              isset(sc->sc_enabled_capa,\n              IWM_UCODE_TLV_CAPA_WFA_TPC_REP_IE_SUPPORT))\n        req->scan_flags |= htole32(IWM_LMAC_SCAN_FLAGS_RRM_ENABLED);\n    \n    req->flags = htole32(IWM_PHY_BAND_24);\n    if (sc->sc_nvm.sku_cap_band_52GHz_enable)\n        req->flags |= htole32(IWM_PHY_BAND_5);\n    req->filter_flags =\n    htole32(IWM_MAC_FILTER_ACCEPT_GRP | IWM_MAC_FILTER_IN_BEACON);\n    \n    /* Tx flags 2 GHz. */\n    req->tx_cmd[0].tx_flags = htole32(IWM_TX_CMD_FLG_SEQ_CTL |\n                                      IWM_TX_CMD_FLG_BT_DIS);\n    req->tx_cmd[0].rate_n_flags =\n    iwm_scan_rate_n_flags(sc, IEEE80211_CHAN_2GHZ, 1/*XXX*/);\n    req->tx_cmd[0].sta_id = IWM_AUX_STA_ID;\n    \n    /* Tx flags 5 GHz. */\n    req->tx_cmd[1].tx_flags = htole32(IWM_TX_CMD_FLG_SEQ_CTL |\n                                      IWM_TX_CMD_FLG_BT_DIS);\n    req->tx_cmd[1].rate_n_flags =\n    iwm_scan_rate_n_flags(sc, IEEE80211_CHAN_5GHZ, 1/*XXX*/);\n    req->tx_cmd[1].sta_id = IWM_AUX_STA_ID;\n    \n    /* Check if we're doing an active directed scan. */\n    if (ic->ic_des_esslen != 0) {\n        req->direct_scan[0].id = IEEE80211_ELEMID_SSID;\n        req->direct_scan[0].len = ic->ic_des_esslen;\n        memcpy(req->direct_scan[0].ssid, ic->ic_des_essid,\n               ic->ic_des_esslen);\n    }\n    \n    req->n_channels = iwm_lmac_scan_fill_channels(sc,\n                                                  (struct iwm_scan_channel_cfg_lmac *)req->data,\n                                                  ic->ic_des_esslen != 0, bgscan);\n    \n    preq = (struct iwm_scan_probe_req_v1 *)(req->data +\n                                            (sizeof(struct iwm_scan_channel_cfg_lmac) *\n                                             sc->sc_capa_n_scan_channels));\n    err = iwm_fill_probe_req_v1(sc, preq);\n    if (err) {\n        ::free(req);\n        return err;\n    }\n    \n    /* Specify the scan plan: We'll do one iteration. */\n    req->schedule[0].iterations = 1;\n    req->schedule[0].full_scan_mul = 1;\n    \n    /* Disable EBS. */\n    req->channel_opt[0].non_ebs_ratio = 1;\n    req->channel_opt[1].non_ebs_ratio = 1;\n    \n    err = iwm_send_cmd(sc, &hcmd);\n    ::free(req);\n    return err;\n}\n\nint ItlIwm::\niwm_config_umac_scan(struct iwm_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct iwm_scan_config *scan_config;\n    int err, nchan;\n    size_t cmd_size;\n    struct ieee80211_channel *c;\n    struct iwm_host_cmd hcmd = {\n        .id = iwm_cmd_id(IWM_SCAN_CFG_CMD, IWM_LONG_GROUP, 0),\n        .flags = 0,\n    };\n    static const uint32_t rates = (IWM_SCAN_CONFIG_RATE_1M |\n                                   IWM_SCAN_CONFIG_RATE_2M | IWM_SCAN_CONFIG_RATE_5M |\n                                   IWM_SCAN_CONFIG_RATE_11M | IWM_SCAN_CONFIG_RATE_6M |\n                                   IWM_SCAN_CONFIG_RATE_9M | IWM_SCAN_CONFIG_RATE_12M |\n                                   IWM_SCAN_CONFIG_RATE_18M | IWM_SCAN_CONFIG_RATE_24M |\n                                   IWM_SCAN_CONFIG_RATE_36M | IWM_SCAN_CONFIG_RATE_48M |\n                                   IWM_SCAN_CONFIG_RATE_54M);\n    \n    cmd_size = sizeof(*scan_config) + sc->sc_capa_n_scan_channels;\n    \n    scan_config = (struct iwm_scan_config*)malloc(cmd_size, M_DEVBUF, M_WAIT);\n    if (scan_config == NULL)\n        return ENOMEM;\n    bzero(scan_config, cmd_size);\n    \n    scan_config->tx_chains = htole32(iwm_fw_valid_tx_ant(sc));\n    scan_config->rx_chains = htole32(iwm_fw_valid_rx_ant(sc));\n    scan_config->legacy_rates = htole32(rates |\n                                        IWM_SCAN_CONFIG_SUPPORTED_RATE(rates));\n    \n    /* These timings correspond to iwlwifi's UNASSOC scan. */\n    scan_config->dwell_active = 10;\n    scan_config->dwell_passive = 110;\n    scan_config->dwell_fragmented = 44;\n    scan_config->dwell_extended = 90;\n    scan_config->out_of_channel_time = htole32(0);\n    scan_config->suspend_time = htole32(0);\n    \n    IEEE80211_ADDR_COPY(scan_config->mac_addr, sc->sc_ic.ic_myaddr);\n    \n    scan_config->bcast_sta_id = IWM_AUX_STA_ID;\n    scan_config->channel_flags = 0;\n    \n    for (c = &ic->ic_channels[1], nchan = 0;\n         c <= &ic->ic_channels[IEEE80211_CHAN_MAX] &&\n         nchan < sc->sc_capa_n_scan_channels; c++) {\n        if (c->ic_flags == 0)\n            continue;\n        scan_config->channel_array[nchan++] =\n        ieee80211_mhz2ieee(c->ic_freq, 0);\n    }\n    \n    scan_config->flags = htole32(IWM_SCAN_CONFIG_FLAG_ACTIVATE |\n                                 IWM_SCAN_CONFIG_FLAG_ALLOW_CHUB_REQS |\n                                 IWM_SCAN_CONFIG_FLAG_SET_TX_CHAINS |\n                                 IWM_SCAN_CONFIG_FLAG_SET_RX_CHAINS |\n                                 IWM_SCAN_CONFIG_FLAG_SET_AUX_STA_ID |\n                                 IWM_SCAN_CONFIG_FLAG_SET_ALL_TIMES |\n                                 IWM_SCAN_CONFIG_FLAG_SET_LEGACY_RATES |\n                                 IWM_SCAN_CONFIG_FLAG_SET_MAC_ADDR |\n                                 IWM_SCAN_CONFIG_FLAG_SET_CHANNEL_FLAGS|\n                                 IWM_SCAN_CONFIG_N_CHANNELS(nchan) |\n                                 IWM_SCAN_CONFIG_FLAG_CLEAR_FRAGMENTED);\n    \n    hcmd.data[0] = scan_config;\n    hcmd.len[0] = cmd_size;\n    \n    err = iwm_send_cmd(sc, &hcmd);\n    ::free(scan_config);\n    return err;\n}\n\nint ItlIwm::\niwm_umac_scan_size(struct iwm_softc *sc)\n{\n    int base_size = IWM_SCAN_REQ_UMAC_SIZE_V1;\n    int tail_size;\n    \n    if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_ADAPTIVE_DWELL_V2))\n        base_size = IWM_SCAN_REQ_UMAC_SIZE_V8;\n    else if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_ADAPTIVE_DWELL))\n        base_size = IWM_SCAN_REQ_UMAC_SIZE_V7;\n    if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_SCAN_EXT_CHAN_VER))\n        tail_size = sizeof(struct iwm_scan_req_umac_tail_v2);\n    else\n        tail_size = sizeof(struct iwm_scan_req_umac_tail_v1);\n    \n    return base_size + sizeof(struct iwm_scan_channel_cfg_umac) *\n    sc->sc_capa_n_scan_channels + tail_size;\n}\n\nstruct iwm_scan_umac_chan_param *ItlIwm::\niwm_get_scan_req_umac_chan_param(struct iwm_softc *sc,\n                                 struct iwm_scan_req_umac *req)\n{\n    if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_ADAPTIVE_DWELL_V2))\n        return &req->v8.channel;\n    \n    if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_ADAPTIVE_DWELL))\n        return &req->v7.channel;\n    return &req->v1.channel;\n}\n\nvoid *ItlIwm::\niwm_get_scan_req_umac_data(struct iwm_softc *sc, struct iwm_scan_req_umac *req)\n{\n    if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_ADAPTIVE_DWELL_V2))\n        return (void *)&req->v8.data;\n    \n    if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_ADAPTIVE_DWELL))\n        return (void *)&req->v7.data;\n    return (void *)&req->v1.data;\n    \n}\n\n/* adaptive dwell max budget time [TU] for full scan */\n#define IWM_SCAN_ADWELL_MAX_BUDGET_FULL_SCAN 300\n/* adaptive dwell max budget time [TU] for directed scan */\n#define IWM_SCAN_ADWELL_MAX_BUDGET_DIRECTED_SCAN 100\n/* adaptive dwell default high band APs number */\n#define IWM_SCAN_ADWELL_DEFAULT_HB_N_APS 8\n/* adaptive dwell default low band APs number */\n#define IWM_SCAN_ADWELL_DEFAULT_LB_N_APS 2\n/* adaptive dwell default APs number in social channels (1, 6, 11) */\n#define IWM_SCAN_ADWELL_DEFAULT_N_APS_SOCIAL 10\n\nint ItlIwm::\niwm_umac_scan(struct iwm_softc *sc, int bgscan)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct iwm_host_cmd hcmd = {\n        .id = iwm_cmd_id(IWM_SCAN_REQ_UMAC, IWM_LONG_GROUP, 0),\n        .len = { 0, },\n        .data = { NULL, },\n        .flags = 0,\n    };\n    struct iwm_scan_req_umac *req;\n    void *cmd_data, *tail_data;\n    struct iwm_scan_req_umac_tail_v2 *tail;\n    struct iwm_scan_req_umac_tail_v1 *tailv1;\n    struct iwm_scan_umac_chan_param *chanparam;\n    size_t req_len;\n    int err, async = bgscan;\n    \n    req_len = iwm_umac_scan_size(sc);\n    if ((req_len < IWM_SCAN_REQ_UMAC_SIZE_V1 +\n         sizeof(struct iwm_scan_req_umac_tail_v1)) ||\n        req_len > IWM_MAX_CMD_PAYLOAD_SIZE)\n        return ERANGE;\n    req = (struct iwm_scan_req_umac*)malloc(req_len, M_DEVBUF, M_NOWAIT);\n    if (req == NULL)\n        return ENOMEM;\n    bzero(req, req_len);\n    \n    hcmd.len[0] = (uint16_t)req_len;\n    hcmd.data[0] = (void *)req;\n    hcmd.flags |= async ? IWM_CMD_ASYNC : 0;\n    \n    if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_ADAPTIVE_DWELL)) {\n        req->v7.adwell_default_n_aps_social =\n        IWM_SCAN_ADWELL_DEFAULT_N_APS_SOCIAL;\n        req->v7.adwell_default_n_aps =\n        IWM_SCAN_ADWELL_DEFAULT_LB_N_APS;\n        \n        if (ic->ic_des_esslen != 0)\n            req->v7.adwell_max_budget =\n            htole16(IWM_SCAN_ADWELL_MAX_BUDGET_DIRECTED_SCAN);\n        else\n            req->v7.adwell_max_budget =\n            htole16(IWM_SCAN_ADWELL_MAX_BUDGET_FULL_SCAN);\n        \n        req->v7.scan_priority = htole32(IWM_SCAN_PRIORITY_HIGH);\n        req->v7.max_out_time[IWM_SCAN_LB_LMAC_IDX] = 0;\n        req->v7.suspend_time[IWM_SCAN_LB_LMAC_IDX] = 0;\n        \n        if (isset(sc->sc_ucode_api,\n                  IWM_UCODE_TLV_API_ADAPTIVE_DWELL_V2)) {\n            req->v8.active_dwell[IWM_SCAN_LB_LMAC_IDX] = 10;\n            req->v8.passive_dwell[IWM_SCAN_LB_LMAC_IDX] = 110;\n        } else {\n            req->v7.active_dwell = 10;\n            req->v7.passive_dwell = 110;\n            req->v7.fragmented_dwell = 44;\n        }\n    } else {\n        /* These timings correspond to iwlwifi's UNASSOC scan. */\n        req->v1.active_dwell = 10;\n        req->v1.passive_dwell = 110;\n        req->v1.fragmented_dwell = 44;\n        req->v1.extended_dwell = 90;\n\n        req->v1.scan_priority = htole32(IWM_SCAN_PRIORITY_HIGH);\n    }\n    \n    if (bgscan) {\n        const uint32_t timeout = htole32(120);\n        if (isset(sc->sc_ucode_api,\n                  IWM_UCODE_TLV_API_ADAPTIVE_DWELL_V2)) {\n            req->v8.max_out_time[IWM_SCAN_LB_LMAC_IDX] = timeout;\n            req->v8.suspend_time[IWM_SCAN_LB_LMAC_IDX] = timeout;\n        } else if (isset(sc->sc_ucode_api,\n                         IWM_UCODE_TLV_API_ADAPTIVE_DWELL)) {\n            req->v7.max_out_time[IWM_SCAN_LB_LMAC_IDX] = timeout;\n            req->v7.suspend_time[IWM_SCAN_LB_LMAC_IDX] = timeout;\n        } else {\n            req->v1.max_out_time = timeout;\n            req->v1.suspend_time = timeout;\n        }\n    }\n\n    req->ooc_priority = htole32(IWM_SCAN_PRIORITY_HIGH);\n    \n    cmd_data = iwm_get_scan_req_umac_data(sc, req);\n    chanparam = iwm_get_scan_req_umac_chan_param(sc, req);\n    chanparam->count = iwm_umac_scan_fill_channels(sc,\n                                                   (struct iwm_scan_channel_cfg_umac *)cmd_data,\n                                                   ic->ic_des_esslen != 0, bgscan);\n    chanparam->flags = 0;\n    \n    tail_data = (uint8_t*)cmd_data + sizeof(struct iwm_scan_channel_cfg_umac) *\n    sc->sc_capa_n_scan_channels;\n    tail = (struct iwm_scan_req_umac_tail_v2*)((uint8_t*)tail_data);\n    /* tail v1 layout differs in preq and direct_scan member fields. */\n    tailv1 = (struct iwm_scan_req_umac_tail_v1*)((uint8_t*)tail_data);\n    \n    req->general_flags = htole32(IWM_UMAC_SCAN_GEN_FLAGS_PASS_ALL |\n                                 IWM_UMAC_SCAN_GEN_FLAGS_ITER_COMPLETE);\n    if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_ADAPTIVE_DWELL_V2)) {\n        req->v8.general_flags2 =\n        IWM_UMAC_SCAN_GEN_FLAGS2_ALLOW_CHNL_REORDER;\n    }\n    \n    /* Check if we're doing an active directed scan. */\n    if (ic->ic_des_esslen != 0) {\n        if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_SCAN_EXT_CHAN_VER)) {\n            tail->direct_scan[0].id = IEEE80211_ELEMID_SSID;\n            tail->direct_scan[0].len = ic->ic_des_esslen;\n            memcpy(tail->direct_scan[0].ssid, ic->ic_des_essid,\n                   ic->ic_des_esslen);\n        } else {\n            tailv1->direct_scan[0].id = IEEE80211_ELEMID_SSID;\n            tailv1->direct_scan[0].len = ic->ic_des_esslen;\n            memcpy(tailv1->direct_scan[0].ssid, ic->ic_des_essid,\n                   ic->ic_des_esslen);\n        }\n        req->general_flags |=\n        htole32(IWM_UMAC_SCAN_GEN_FLAGS_PRE_CONNECT);\n    } else\n        req->general_flags |= htole32(IWM_UMAC_SCAN_GEN_FLAGS_PASSIVE);\n    \n    if (isset(sc->sc_enabled_capa,\n              IWM_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT) &&\n              isset(sc->sc_enabled_capa,\n              IWM_UCODE_TLV_CAPA_WFA_TPC_REP_IE_SUPPORT))\n        req->general_flags |=\n        htole32(IWM_UMAC_SCAN_GEN_FLAGS_RRM_ENABLED);\n    \n    if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_ADAPTIVE_DWELL)) {\n        req->general_flags |=\n        htole32(IWM_UMAC_SCAN_GEN_FLAGS_ADAPTIVE_DWELL);\n    } else {\n        req->general_flags |=\n        htole32(IWM_UMAC_SCAN_GEN_FLAGS_EXTENDED_DWELL);\n    }\n    \n    if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_SCAN_EXT_CHAN_VER))\n        err = iwm_fill_probe_req(sc, &tail->preq);\n    else\n        err = iwm_fill_probe_req_v1(sc, &tailv1->preq);\n    if (err) {\n        ::free(req);\n        return err;\n    }\n    \n    /* Specify the scan plan: We'll do one iteration. */\n    tail->schedule[0].interval = 0;\n    tail->schedule[0].iter_count = 1;\n    \n    err = iwm_send_cmd(sc, &hcmd);\n    ::free(req);\n    return err;\n}\n\nvoid ItlIwm::\niwm_mcc_update(struct iwm_softc *sc, struct iwm_mcc_chub_notif *notif)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct _ifnet *ifp = IC2IFP(ic);\n    \n    snprintf(sc->sc_fw_mcc, sizeof(sc->sc_fw_mcc), \"%c%c\",\n             (le16toh(notif->mcc) & 0xff00) >> 8, le16toh(notif->mcc) & 0xff);\n    if (sc->sc_fw_mcc_int != notif->mcc && sc->sc_ic.ic_event_handler) {\n        (*sc->sc_ic.ic_event_handler)(&sc->sc_ic, IEEE80211_EVT_COUNTRY_CODE_UPDATE, NULL);\n    }\n    sc->sc_fw_mcc_int = notif->mcc;\n    \n    if (ifp->if_flags & IFF_DEBUG) {\n        DPRINTFN(3, (\"%s: firmware has detected regulatory domain '%s' \"\n               \"(0x%x)\\n\", DEVNAME(sc), sc->sc_fw_mcc, le16toh(notif->mcc)));\n    }\n    \n    /* TODO: Schedule a task to send MCC_UPDATE_CMD? */\n}\n\nuint8_t ItlIwm::\niwm_ridx2rate(struct ieee80211_rateset *rs, int ridx)\n{\n    int i;\n    uint8_t rval;\n    \n    for (i = 0; i < rs->rs_nrates; i++) {\n        rval = (rs->rs_rates[i] & IEEE80211_RATE_VAL);\n        if (rval == ieee80211_std_rateset_11g.rs_rates[ridx])\n            return rs->rs_rates[i];\n    }\n    \n    return 0;\n}\n\nvoid ItlIwm::\niwm_ack_rates(struct iwm_softc *sc, struct iwm_node *in, int *cck_rates,\n              int *ofdm_rates)\n{\n    struct ieee80211_node *ni = &in->in_ni;\n    struct ieee80211_rateset *rs = &ni->ni_rates;\n    int lowest_present_ofdm = -1;\n    int lowest_present_cck = -1;\n    uint8_t cck = 0;\n    uint8_t ofdm = 0;\n    int i;\n    \n    if (ni->ni_chan == IEEE80211_CHAN_ANYC ||\n        IEEE80211_IS_CHAN_2GHZ(ni->ni_chan)) {\n        for (i = IWL_FIRST_CCK_RATE; i < IWL_FIRST_OFDM_RATE; i++) {\n            if ((iwm_ridx2rate(rs, i) & IEEE80211_RATE_BASIC) == 0)\n                continue;\n            cck |= (1 << i);\n            if (lowest_present_cck == -1 || lowest_present_cck > i)\n                lowest_present_cck = i;\n        }\n    }\n    for (i = IWL_FIRST_OFDM_RATE; i <= IWL_LAST_NON_HT_RATE; i++) {\n        if ((iwm_ridx2rate(rs, i) & IEEE80211_RATE_BASIC) == 0)\n            continue;\n        ofdm |= (1 << (i - IWL_FIRST_OFDM_RATE));\n        if (lowest_present_ofdm == -1 || lowest_present_ofdm > i)\n            lowest_present_ofdm = i;\n    }\n    \n    /*\n     * Now we've got the basic rates as bitmaps in the ofdm and cck\n     * variables. This isn't sufficient though, as there might not\n     * be all the right rates in the bitmap. E.g. if the only basic\n     * rates are 5.5 Mbps and 11 Mbps, we still need to add 1 Mbps\n     * and 6 Mbps because the 802.11-2007 standard says in 9.6:\n     *\n     *    [...] a STA responding to a received frame shall transmit\n     *    its Control Response frame [...] at the highest rate in the\n     *    BSSBasicRateSet parameter that is less than or equal to the\n     *    rate of the immediately previous frame in the frame exchange\n     *    sequence ([...]) and that is of the same modulation class\n     *    ([...]) as the received frame. If no rate contained in the\n     *    BSSBasicRateSet parameter meets these conditions, then the\n     *    control frame sent in response to a received frame shall be\n     *    transmitted at the highest mandatory rate of the PHY that is\n     *    less than or equal to the rate of the received frame, and\n     *    that is of the same modulation class as the received frame.\n     *\n     * As a consequence, we need to add all mandatory rates that are\n     * lower than all of the basic rates to these bitmaps.\n     */\n    \n    if (IWL_RATE_24M_INDEX < lowest_present_ofdm)\n        ofdm |= IWL_RATE_BIT_MSK(24) >> IWL_FIRST_OFDM_RATE;\n    if (IWL_RATE_12M_INDEX < lowest_present_ofdm)\n        ofdm |= IWL_RATE_BIT_MSK(12) >> IWL_FIRST_OFDM_RATE;\n    /* 6M already there or needed so always add */\n    ofdm |= IWL_RATE_BIT_MSK(6) >> IWL_FIRST_OFDM_RATE;\n    \n    /*\n     * CCK is a bit more complex with DSSS vs. HR/DSSS vs. ERP.\n     * Note, however:\n     *  - if no CCK rates are basic, it must be ERP since there must\n     *    be some basic rates at all, so they're OFDM => ERP PHY\n     *    (or we're in 5 GHz, and the cck bitmap will never be used)\n     *  - if 11M is a basic rate, it must be ERP as well, so add 5.5M\n     *  - if 5.5M is basic, 1M and 2M are mandatory\n     *  - if 2M is basic, 1M is mandatory\n     *  - if 1M is basic, that's the only valid ACK rate.\n     * As a consequence, it's not as complicated as it sounds, just add\n     * any lower rates to the ACK rate bitmap.\n     */\n    if (IWL_RATE_11M_INDEX < lowest_present_cck)\n        cck |= IWL_RATE_BIT_MSK(11) >> IWL_FIRST_CCK_RATE;\n    if (IWL_RATE_5M_INDEX < lowest_present_cck)\n        cck |= IWL_RATE_BIT_MSK(5) >> IWL_FIRST_CCK_RATE;\n    if (IWL_RATE_2M_INDEX < lowest_present_cck)\n        cck |= IWL_RATE_BIT_MSK(2) >> IWL_FIRST_CCK_RATE;\n    /* 1M already there or needed so always add */\n    cck |= IWL_RATE_BIT_MSK(1) >> IWL_FIRST_CCK_RATE;\n    \n    *cck_rates = cck;\n    *ofdm_rates = ofdm;\n}\n\nint ItlIwm::\niwm_scan(struct iwm_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct _ifnet *ifp = IC2IFP(ic);\n    int err;\n    \n    if (sc->sc_flags & IWM_FLAG_BGSCAN) {\n        err = iwm_scan_abort(sc);\n        if (err) {\n            XYLog(\"%s: could not abort background scan\\n\",\n                  DEVNAME(sc));\n            return err;\n        }\n    }\n    \n    if (isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_UMAC_SCAN))\n        err = iwm_umac_scan(sc, 0);\n    else\n        err = iwm_lmac_scan(sc, 0);\n    if (err && err != 1) {\n        XYLog(\"%s: %d could not initiate scan, err=%d\\n\", DEVNAME(sc), __LINE__, err);\n        return err;\n    }\n    \n    /*\n     * The current mode might have been fixed during association.\n     * Ensure all channels get scanned.\n     */\n    if (IFM_MODE(ic->ic_media.ifm_cur->ifm_media) == IFM_AUTO)\n        ieee80211_setmode(ic, IEEE80211_MODE_AUTO);\n    \n    sc->sc_flags |= IWM_FLAG_SCANNING;\n    if (ifp->if_flags & IFF_DEBUG)\n        XYLog(\"%s: %s -> %s\\n\", ifp->if_xname,\n              ieee80211_state_name[ic->ic_state],\n              ieee80211_state_name[IEEE80211_S_SCAN]);\n    if ((sc->sc_flags & IWM_FLAG_BGSCAN) == 0) {\n        ieee80211_set_link_state(ic, LINK_STATE_DOWN);\n        ieee80211_node_cleanup(ic, ic->ic_bss);\n    }\n    ic->ic_state = IEEE80211_S_SCAN;\n    iwm_led_blink_start(sc);\n    wakeupOn(&ic->ic_state); /* wake iwm_init() */\n    \n    return 0;\n}\n\nint ItlIwm::\niwm_bgscan(struct ieee80211com *ic)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwm_softc *sc = (struct iwm_softc *)IC2IFP(ic)->if_softc;\n    ItlIwm *that = container_of(sc, ItlIwm, com);\n    int err;\n    \n    if (sc->sc_flags & IWM_FLAG_SCANNING)\n        return 0;\n    \n    if (isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_UMAC_SCAN))\n        err = that->iwm_umac_scan(sc, 1);\n    else\n        err = that->iwm_lmac_scan(sc, 1);\n    if (err && err != 1) {\n        XYLog(\"%s: could not initiate scan\\n\", DEVNAME(sc));\n        return err;\n    }\n    \n    sc->sc_flags |= IWM_FLAG_BGSCAN;\n    return 0;\n}\n\nint ItlIwm::\niwm_umac_scan_abort(struct iwm_softc *sc)\n{\n    struct iwm_umac_scan_abort cmd = { 0 };\n    \n    return iwm_send_cmd_pdu(sc,\n                            IWM_WIDE_ID(IWM_LONG_GROUP, IWM_SCAN_ABORT_UMAC),\n                            0, sizeof(cmd), &cmd);\n}\n\nint ItlIwm::\niwm_lmac_scan_abort(struct iwm_softc *sc)\n{\n    struct iwm_host_cmd cmd = {\n        .id = IWM_SCAN_OFFLOAD_ABORT_CMD,\n    };\n    int err;\n    uint32_t status;\n    \n    err = iwm_send_cmd_status(sc, &cmd, &status);\n    if (err)\n        return err;\n    \n    if (status != IWM_CAN_ABORT_STATUS) {\n        /*\n         * The scan abort will return 1 for success or\n         * 2 for \"failure\".  A failure condition can be\n         * due to simply not being in an active scan which\n         * can occur if we send the scan abort before the\n         * microcode has notified us that a scan is completed.\n         */\n        return EBUSY;\n    }\n    \n    return 0;\n}\n\nint ItlIwm::\niwm_scan_abort(struct iwm_softc *sc)\n{\n    int err;\n    \n    if (isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_UMAC_SCAN))\n        err = iwm_umac_scan_abort(sc);\n    else\n        err = iwm_lmac_scan_abort(sc);\n    \n    if (err == 0)\n        sc->sc_flags &= ~(IWM_FLAG_SCANNING | IWM_FLAG_BGSCAN);\n    return err;\n}\n"
  },
  {
    "path": "itlwm/hal_iwm/tx.cpp",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n/*    $OpenBSD: if_iwm.c,v 1.316 2020/12/07 20:09:24 tobhe Exp $    */\n\n/*\n * Copyright (c) 2014, 2016 genua gmbh <info@genua.de>\n *   Author: Stefan Sperling <stsp@openbsd.org>\n * Copyright (c) 2014 Fixup Software Ltd.\n * Copyright (c) 2017 Stefan Sperling <stsp@openbsd.org>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n/*-\n * Based on BSD-licensed source modules in the Linux iwlwifi driver,\n * which were used as the reference documentation for this implementation.\n *\n ***********************************************************************\n *\n * This file is provided under a dual BSD/GPLv2 license.  When using or\n * redistributing this file, you may do so under either license.\n *\n * GPL LICENSE SUMMARY\n *\n * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.\n * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH\n * Copyright(c) 2016 Intel Deutschland GmbH\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of version 2 of the GNU General Public License as\n * published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful, but\n * WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,\n * USA\n *\n * The full GNU General Public License is included in this distribution\n * in the file called COPYING.\n *\n * Contact Information:\n *  Intel Linux Wireless <ilw@linux.intel.com>\n * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497\n *\n *\n * BSD LICENSE\n *\n * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.\n * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH\n * Copyright(c) 2016 Intel Deutschland GmbH\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in\n *    the documentation and/or other materials provided with the\n *    distribution.\n *  * Neither the name Intel Corporation nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*-\n * Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n#include \"ItlIwm.hpp\"\n\nvoid ItlIwm::\niwm_free_tx_ring(iwm_softc *sc, struct iwm_tx_ring *ring)\n{\n    int i;\n    \n    iwm_dma_contig_free(&ring->desc_dma);\n    iwm_dma_contig_free(&ring->cmd_dma);\n    \n    for (i = 0; i < IWM_TX_RING_COUNT; i++) {\n        struct iwm_tx_data *data = &ring->data[i];\n        \n        if (data->m != NULL) {\n            mbuf_freem(data->m);\n            data->m = NULL;\n        }\n        if (data->map != NULL) {\n            bus_dmamap_destroy(sc->sc_dmat, data->map);\n            data->map = NULL;\n        }\n    }\n}\n\nvoid ItlIwm::\niwm_reset_tx_ring(struct iwm_softc *sc, struct iwm_tx_ring *ring)\n{\n    int i;\n    \n    for (i = 0; i < IWM_TX_RING_COUNT; i++) {\n        struct iwm_tx_data *data = &ring->data[i];\n\n        if (data->m != NULL) {\n//            bus_dmamap_sync(sc->sc_dmat, data->map, 0,\n//                data->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);\n//            bus_dmamap_unload(sc->sc_dmat, data->map);\n            mbuf_freem(data->m);\n            data->m = NULL;\n        }\n    }\n    /* Clear TX descriptors. */\n    memset(ring->desc, 0, ring->desc_dma.size);\n//    bus_dmamap_sync(sc->sc_dmat, ring->desc_dma.map, 0,\n//        ring->desc_dma.size, BUS_DMASYNC_PREWRITE);\n    sc->qfullmsk &= ~(1 << ring->qid);\n    /* 7000 family NICs are locked while commands are in progress. */\n    if (ring->qid == sc->cmdqid && ring->queued > 0) {\n        if (sc->sc_device_family == IWM_DEVICE_FAMILY_7000)\n            iwm_nic_unlock(sc);\n    }\n    ring->queued = 0;\n    ring->cur = 0;\n    ring->tail = 0;\n}\n\nint ItlIwm::\niwm_alloc_tx_ring(iwm_softc *sc, struct iwm_tx_ring *ring, int qid)\n{\n    bus_addr_t paddr;\n    bus_size_t size;\n    int i, err;\n    int nsegments;\n    \n    ring->qid = qid;\n    ring->queued = 0;\n    ring->cur = 0;\n    ring->tail = 0;\n    \n    /* We are using 10:17 for DQA tx agg */\n    if (qid > IWM_LAST_AGG_TX_QUEUE)\n        return 0;\n    \n    /* Allocate TX descriptors (256-byte aligned). */\n    size = IWM_TX_RING_COUNT * sizeof (struct iwm_tfd);\n    err = iwm_dma_contig_alloc(sc->sc_dmat, &ring->desc_dma, size, 256);\n    if (err) {\n        XYLog(\"%s: could not allocate TX ring DMA memory\\n\",\n              DEVNAME(sc));\n        goto fail;\n    }\n    ring->desc = (struct iwm_tfd *)ring->desc_dma.vaddr;\n    \n    size = IWM_TX_RING_COUNT * sizeof(struct iwm_device_cmd);\n    err = iwm_dma_contig_alloc(sc->sc_dmat, &ring->cmd_dma, size, 4);\n    if (err) {\n        XYLog(\"%s: could not allocate cmd DMA memory\\n\", DEVNAME(sc));\n        goto fail;\n    }\n    ring->cmd = (struct iwm_device_cmd*)ring->cmd_dma.vaddr;\n    \n    paddr = ring->cmd_dma.paddr;\n    for (i = 0; i < IWM_TX_RING_COUNT; i++) {\n        struct iwm_tx_data *data = &ring->data[i];\n        size_t mapsize;\n\n        data->cmd_paddr = paddr;\n        data->scratch_paddr = paddr + sizeof(struct iwm_cmd_header)\n            + offsetof(struct iwm_tx_cmd, scratch);\n        paddr += sizeof(struct iwm_device_cmd);\n\n        /* FW commands may require more mapped space than packets. */\n        if (qid == IWM_CMD_QUEUE || qid == IWM_DQA_CMD_QUEUE) {\n            mapsize = (sizeof(struct iwm_cmd_header) + IWM_MAX_CMD_PAYLOAD_SIZE);\n            nsegments = 1;\n        } else {\n            mapsize = MCLBYTES;\n            nsegments = IWM_NUM_OF_TBS - 2;\n        }\n        err = bus_dmamap_create(sc->sc_dmat, mapsize,\n                                nsegments, mapsize, 0, BUS_DMA_NOWAIT,\n                                &data->map);\n        if (err) {\n            XYLog(\"%s: could not create TX buf DMA map\\n\",\n                  DEVNAME(sc));\n            goto fail;\n        }\n    }\n    KASSERT(paddr == ring->cmd_dma.paddr + size, \"\");\n    return 0;\n    \nfail:    iwm_free_tx_ring(sc, ring);\n    return err;\n}\n\nint ItlIwm::\niwm_enable_ac_txq(struct iwm_softc *sc, int qid, int fifo)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    iwm_nic_assert_locked(sc);\n    \n    IWM_WRITE(sc, IWM_HBUS_TARG_WRPTR, qid << 8 | 0);\n    \n    iwm_write_prph(sc, IWM_SCD_QUEUE_STATUS_BITS(qid),\n                   (0 << IWM_SCD_QUEUE_STTS_REG_POS_ACTIVE)\n                   | (1 << IWM_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN));\n    \n    iwm_clear_bits_prph(sc, IWM_SCD_AGGR_SEL, (1 << qid));\n    \n    iwm_write_prph(sc, IWM_SCD_QUEUE_RDPTR(qid), 0);\n    \n    iwm_write_mem32(sc,\n                    sc->sched_base + IWM_SCD_CONTEXT_QUEUE_OFFSET(qid), 0);\n    \n    /* Set scheduler window size and frame limit. */\n    iwm_write_mem32(sc,\n                    sc->sched_base + IWM_SCD_CONTEXT_QUEUE_OFFSET(qid) +\n                    sizeof(uint32_t),\n                    ((IWM_FRAME_LIMIT << IWM_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) &\n                     IWM_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) |\n                    ((IWM_FRAME_LIMIT\n                      << IWM_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) &\n                     IWM_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK));\n    \n    iwm_write_prph(sc, IWM_SCD_QUEUE_STATUS_BITS(qid),\n                   (1 << IWM_SCD_QUEUE_STTS_REG_POS_ACTIVE) |\n                   (fifo << IWM_SCD_QUEUE_STTS_REG_POS_TXF) |\n                   (1 << IWM_SCD_QUEUE_STTS_REG_POS_WSL) |\n                   IWM_SCD_QUEUE_STTS_REG_MSK);\n    \n    if (qid == sc->cmdqid)\n        iwm_write_prph(sc, IWM_SCD_EN_CTRL,\n                       iwm_read_prph(sc, IWM_SCD_EN_CTRL) | (1 << qid));\n    \n    return 0;\n}\n\nint ItlIwm::\niwm_enable_txq(struct iwm_softc *sc, int sta_id, int qid, int fifo, int ssn, int tid, int agg)\n{\n    XYLog(\"%s qid=%d tid=%d agg=%d\\n\", __FUNCTION__, qid, tid, agg);\n    struct iwm_scd_txq_cfg_cmd cmd;\n    int err = 0;\n    uint16_t idx;\n    struct iwm_tx_ring *ring = &sc->txq[qid];\n    bool scd_bug = false;\n    \n    if (agg &&\n        (sc->agg_queue_mask & (1 << qid)))\n        return 0;\n    \n    iwm_nic_assert_locked(sc);\n    \n    /*\n     * If we need to move the SCD write pointer by steps of\n     * 0x40, 0x80 or 0xc0, it gets stuck. Avoids this and let\n     * the op_mode know by returning true later.\n     * Do this only in case cfg is NULL since this trick can\n     * be done only if we have DQA enabled which is true for mvm\n     * only. And mvm never sets a cfg pointer.\n     * This is really ugly, but this is the easiest way out for\n     * this sad hardware issue.\n     * This bug has been fixed on devices 9000 and up.\n     */\n    scd_bug = !sc->sc_mqrx_supported &&\n    !((ssn - ring->cur) & 0x3f) &&\n    (ssn != ring->cur);\n    if (scd_bug)\n        ssn = (ssn + 1) & 0xfff;\n    \n    idx = IWM_AGG_SSN_TO_TXQ_IDX(ssn);\n    ring->cur = ring->read = idx;\n    ring->tail = idx;\n    IWM_WRITE(sc, IWM_HBUS_TARG_WRPTR, (qid << 8) | idx);\n    \n    memset(&cmd, 0, sizeof(cmd));\n    cmd.scd_queue = qid;\n    cmd.enable = IWM_SCD_CFG_ENABLE_QUEUE;\n    cmd.window = IWM_FRAME_LIMIT;\n    cmd.sta_id = sta_id;\n    cmd.ssn = htole16(ssn);\n    cmd.tx_fifo = fifo;\n    cmd.aggregate = agg;\n    cmd.tid = tid;\n\n    iwm_write_prph(sc, IWM_SCD_QUEUE_RDPTR(qid), ssn);\n\n    iwm_write_mem32(sc,\n                    sc->sched_base + IWM_SCD_CONTEXT_QUEUE_OFFSET(qid), 0);\n\n    /* Set scheduler window size and frame limit. */\n    iwm_write_mem32(sc,\n                    sc->sched_base + IWM_SCD_CONTEXT_QUEUE_OFFSET(qid) +\n                    sizeof(uint32_t),\n                    ((IWM_FRAME_LIMIT << IWM_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) &\n                     IWM_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) |\n                    ((IWM_FRAME_LIMIT\n                      << IWM_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) &\n                     IWM_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK));\n\n    iwm_write_prph(sc, IWM_SCD_QUEUE_STATUS_BITS(qid),\n                   (1 << IWM_SCD_QUEUE_STTS_REG_POS_ACTIVE) |\n                   (fifo << IWM_SCD_QUEUE_STTS_REG_POS_TXF) |\n                   (1 << IWM_SCD_QUEUE_STTS_REG_POS_WSL) |\n                   IWM_SCD_QUEUE_STTS_REG_MSK);\n\n    if (qid == sc->cmdqid)\n        iwm_write_prph(sc, IWM_SCD_EN_CTRL,\n                       iwm_read_prph(sc, IWM_SCD_EN_CTRL) | (1 << qid));\n\n    err = iwm_send_cmd_pdu(sc, IWM_SCD_QUEUE_CFG, 0,\n                           sizeof(cmd), &cmd);\n    if (err)\n        XYLog(\"%s failed error=%d\\n\", __FUNCTION__, err);\n    \n    return err;\n}\n\nint ItlIwm::\niwm_disable_txq(struct iwm_softc *sc, uint8_t qid, uint8_t tid, uint8_t flags)\n{\n    int err;\n    struct iwm_scd_txq_cfg_cmd cmd = {\n        .scd_queue = qid,\n        .enable = IWM_SCD_CFG_DISABLE_QUEUE,\n        .sta_id = IWM_STATION_ID,\n        .tid = tid,\n    };\n    \n    err = iwm_send_cmd_pdu(sc, IWM_SCD_QUEUE_CFG, flags,\n                               sizeof(struct iwm_scd_txq_cfg_cmd), &cmd);\n    return err;\n}\n\nint ItlIwm::\niwm_send_soc_conf(struct iwm_softc *sc)\n{\n    struct iwm_soc_configuration_cmd cmd;\n    int err;\n    uint32_t cmd_id, flags = 0;\n    \n    memset(&cmd, 0, sizeof(cmd));\n    \n    /*\n     * In VER_1 of this command, the discrete value is considered\n     * an integer; In VER_2, it's a bitmask.  Since we have only 2\n     * values in VER_1, this is backwards-compatible with VER_2,\n     * as long as we don't set any other flag bits.\n     */\n    if (!sc->sc_integrated) { /* VER_1 */\n        flags = IWM_SOC_CONFIG_CMD_FLAGS_DISCRETE;\n    } else { /* VER_2 */\n        uint8_t scan_cmd_ver;\n        if (sc->sc_ltr_delay != IWM_SOC_FLAGS_LTR_APPLY_DELAY_NONE)\n            flags |= (sc->sc_ltr_delay &\n                      IWM_SOC_FLAGS_LTR_APPLY_DELAY_MASK);\n        scan_cmd_ver = iwm_lookup_cmd_ver(sc, IWM_LONG_GROUP,\n                                          IWM_SCAN_REQ_UMAC);\n        if (scan_cmd_ver != IWM_FW_CMD_VER_UNKNOWN &&\n            scan_cmd_ver >= 2 && sc->sc_low_latency_xtal)\n            flags |= IWM_SOC_CONFIG_CMD_FLAGS_LOW_LATENCY;\n    }\n    cmd.flags = htole32(flags);\n    \n    cmd.latency = htole32(sc->sc_xtal_latency);\n    \n    cmd_id = iwm_cmd_id(IWM_SOC_CONFIGURATION_CMD, IWM_SYSTEM_GROUP, 0);\n    err = iwm_send_cmd_pdu(sc, cmd_id, 0, sizeof(cmd), &cmd);\n    if (err)\n        printf(\"%s: failed to set soc latency: %d\\n\", DEVNAME(sc), err);\n    return err;\n}\n\nint ItlIwm::\niwm_send_update_mcc_cmd(struct iwm_softc *sc, const char *alpha2)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwm_mcc_update_cmd mcc_cmd;\n    struct iwm_host_cmd hcmd = {\n        .id = IWM_MCC_UPDATE_CMD,\n        .flags = IWM_CMD_WANT_RESP,\n        .resp_pkt_len = IWM_CMD_RESP_MAX,\n        .data = { &mcc_cmd },\n    };\n    struct iwm_rx_packet *pkt;\n    size_t resp_len;\n    int err;\n    int resp_v3 = isset(sc->sc_enabled_capa,\n                        IWM_UCODE_TLV_CAPA_LAR_SUPPORT_V3);\n    \n    if (sc->sc_device_family == IWM_DEVICE_FAMILY_8000 &&\n        !sc->sc_nvm.lar_enabled) {\n        return 0;\n    }\n    \n    memset(&mcc_cmd, 0, sizeof(mcc_cmd));\n    mcc_cmd.mcc = htole16(alpha2[0] << 8 | alpha2[1]);\n    if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_WIFI_MCC_UPDATE) ||\n        isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_LAR_MULTI_MCC))\n        mcc_cmd.source_id = IWM_MCC_SOURCE_GET_CURRENT;\n    else\n        mcc_cmd.source_id = IWM_MCC_SOURCE_OLD_FW;\n    \n    if (resp_v3) { /* same size as resp_v2 */\n        hcmd.len[0] = sizeof(struct iwm_mcc_update_cmd);\n    } else {\n        hcmd.len[0] = sizeof(struct iwm_mcc_update_cmd_v1);\n    }\n    \n    err = iwm_send_cmd(sc, &hcmd);\n    if (err)\n        return err;\n    \n    pkt = hcmd.resp_pkt;\n    if (!pkt || (pkt->hdr.flags & IWM_CMD_FAILED_MSK)) {\n        err = EIO;\n        goto out;\n    }\n    \n    if (resp_v3) {\n        struct iwm_mcc_update_resp_v3 *resp;\n        resp_len = iwm_rx_packet_payload_len(pkt);\n        if (resp_len < sizeof(*resp)) {\n            err = EIO;\n            goto out;\n        }\n        \n        resp = (struct iwm_mcc_update_resp_v3 *)pkt->data;\n        if (resp_len != sizeof(*resp) +\n            resp->n_channels * sizeof(resp->channels[0])) {\n            err = EIO;\n            goto out;\n        }\n    } else {\n        struct iwm_mcc_update_resp_v1 *resp_v1;\n        resp_len = iwm_rx_packet_payload_len(pkt);\n        if (resp_len < sizeof(*resp_v1)) {\n            err = EIO;\n            goto out;\n        }\n        \n        resp_v1 = (struct iwm_mcc_update_resp_v1 *)pkt->data;\n        if (resp_len != sizeof(*resp_v1) +\n            resp_v1->n_channels * sizeof(resp_v1->channels[0])) {\n            err = EIO;\n            goto out;\n        }\n    }\nout:\n    iwm_free_resp(sc, &hcmd);\n    return err;\n}\n\nint ItlIwm::\niwm_send_temp_report_ths_cmd(struct iwm_softc *sc)\n{\n    struct iwm_temp_report_ths_cmd cmd;\n    int err;\n    \n    /*\n     * In order to give responsibility for critical-temperature-kill\n     * and TX backoff to FW we need to send an empty temperature\n     * reporting command at init time.\n     */\n    memset(&cmd, 0, sizeof(cmd));\n    \n    err = iwm_send_cmd_pdu(sc,\n                           IWM_WIDE_ID(IWM_PHY_OPS_GROUP, IWM_TEMP_REPORTING_THRESHOLDS_CMD),\n                           0, sizeof(cmd), &cmd);\n    if (err)\n        printf(\"%s: TEMP_REPORT_THS_CMD command failed (error %d)\\n\",\n               DEVNAME(sc), err);\n    \n    return err;\n}\n\nvoid ItlIwm::\niwm_tt_tx_backoff(struct iwm_softc *sc, uint32_t backoff)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwm_host_cmd cmd = {\n        .id = IWM_REPLY_THERMAL_MNG_BACKOFF,\n        .len = { sizeof(uint32_t), },\n        .data = { &backoff, },\n    };\n    \n    iwm_send_cmd(sc, &cmd);\n}\n\nvoid ItlIwm::\niwm_free_fw_paging(struct iwm_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    int i;\n    \n    if (sc->fw_paging_db[0].fw_paging_block.vaddr == NULL)\n        return;\n    \n    for (i = 0; i < IWM_NUM_OF_FW_PAGING_BLOCKS; i++) {\n        iwm_dma_contig_free(&sc->fw_paging_db[i].fw_paging_block);\n    }\n    \n    memset(sc->fw_paging_db, 0, sizeof(sc->fw_paging_db));\n}\n\nint ItlIwm::\niwm_fill_paging_mem(struct iwm_softc *sc, const struct iwm_fw_sects *image)\n{\n    int sec_idx, idx;\n    uint32_t offset = 0;\n    \n    /*\n     * find where is the paging image start point:\n     * if CPU2 exist and it's in paging format, then the image looks like:\n     * CPU1 sections (2 or more)\n     * CPU1_CPU2_SEPARATOR_SECTION delimiter - separate between CPU1 to CPU2\n     * CPU2 sections (not paged)\n     * PAGING_SEPARATOR_SECTION delimiter - separate between CPU2\n     * non paged to CPU2 paging sec\n     * CPU2 paging CSS\n     * CPU2 paging image (including instruction and data)\n     */\n    for (sec_idx = 0; sec_idx < IWM_UCODE_SECT_MAX; sec_idx++) {\n        if (image->fw_sect[sec_idx].fws_devoff ==\n            IWM_PAGING_SEPARATOR_SECTION) {\n            sec_idx++;\n            break;\n        }\n    }\n    \n    /*\n     * If paging is enabled there should be at least 2 more sections left\n     * (one for CSS and one for Paging data)\n     */\n    if (sec_idx >= nitems(image->fw_sect) - 1) {\n        XYLog(\"%s: Paging: Missing CSS and/or paging sections\\n\",\n              DEVNAME(sc));\n        iwm_free_fw_paging(sc);\n        return EINVAL;\n    }\n    \n    /* copy the CSS block to the dram */\n    XYLog(\"%s: Paging: load paging CSS to FW, sec = %d\\n\",\n          DEVNAME(sc), sec_idx);\n    \n    memcpy(sc->fw_paging_db[0].fw_paging_block.vaddr,\n           image->fw_sect[sec_idx].fws_data,\n           sc->fw_paging_db[0].fw_paging_size);\n    \n    XYLog(\"%s: Paging: copied %d CSS bytes to first block\\n\",\n          DEVNAME(sc), sc->fw_paging_db[0].fw_paging_size);\n    \n    sec_idx++;\n    \n    /*\n     * copy the paging blocks to the dram\n     * loop index start from 1 since that CSS block already copied to dram\n     * and CSS index is 0.\n     * loop stop at num_of_paging_blk since that last block is not full.\n     */\n    for (idx = 1; idx < sc->num_of_paging_blk; idx++) {\n        memcpy(sc->fw_paging_db[idx].fw_paging_block.vaddr,\n               (const char *)image->fw_sect[sec_idx].fws_data + offset,\n               sc->fw_paging_db[idx].fw_paging_size);\n        \n        XYLog(\"%s: Paging: copied %d paging bytes to block %d\\n\",\n              DEVNAME(sc), sc->fw_paging_db[idx].fw_paging_size, idx);\n        \n        offset += sc->fw_paging_db[idx].fw_paging_size;\n    }\n    \n    /* copy the last paging block */\n    if (sc->num_of_pages_in_last_blk > 0) {\n        memcpy(sc->fw_paging_db[idx].fw_paging_block.vaddr,\n               (const char *)image->fw_sect[sec_idx].fws_data + offset,\n               IWM_FW_PAGING_SIZE * sc->num_of_pages_in_last_blk);\n        \n        XYLog(\"%s: Paging: copied %d pages in the last block %d\\n\",\n              DEVNAME(sc), sc->num_of_pages_in_last_blk, idx);\n    }\n    \n    return 0;\n}\n\nint ItlIwm::\niwm_alloc_fw_paging_mem(struct iwm_softc *sc, const struct iwm_fw_sects *image)\n{\n    int blk_idx = 0;\n    int error, num_of_pages;\n    \n    if (sc->fw_paging_db[0].fw_paging_block.vaddr != NULL) {\n        //        int i;\n        //        /* Device got reset, and we setup firmware paging again */\n        //        bus_dmamap_sync(sc->sc_dmat,\n        //            sc->fw_paging_db[0].fw_paging_block.map,\n        //            0, IWM_FW_PAGING_SIZE,\n        //            BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);\n        //        for (i = 1; i < sc->num_of_paging_blk + 1; i++) {\n        //            bus_dmamap_sync(sc->sc_dmat,\n        //                sc->fw_paging_db[i].fw_paging_block.map,\n        //                0, IWM_PAGING_BLOCK_SIZE,\n        //                BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);\n        //        }\n        return 0;\n    }\n    \n    /* ensure IWM_BLOCK_2_EXP_SIZE is power of 2 of IWM_PAGING_BLOCK_SIZE */\n#if (1 << IWM_BLOCK_2_EXP_SIZE) != IWM_PAGING_BLOCK_SIZE\n#error IWM_BLOCK_2_EXP_SIZE must be power of 2 of IWM_PAGING_BLOCK_SIZE\n#endif\n    \n    num_of_pages = image->paging_mem_size / IWM_FW_PAGING_SIZE;\n    sc->num_of_paging_blk =\n        ((num_of_pages - 1) / IWM_NUM_OF_PAGE_PER_GROUP) + 1;\n\n    sc->num_of_pages_in_last_blk =\n        num_of_pages -\n        IWM_NUM_OF_PAGE_PER_GROUP * (sc->num_of_paging_blk - 1);\n\n    XYLog(\"%s: Paging: allocating mem for %d paging blocks, each block\"\n        \" holds 8 pages, last block holds %d pages\\n\", DEVNAME(sc),\n        sc->num_of_paging_blk,\n        sc->num_of_pages_in_last_blk);\n\n    /* allocate block of 4Kbytes for paging CSS */\n    error = iwm_dma_contig_alloc(sc->sc_dmat,\n        &sc->fw_paging_db[blk_idx].fw_paging_block, IWM_FW_PAGING_SIZE,\n        4096);\n    if (error) {\n        /* free all the previous pages since we failed */\n        iwm_free_fw_paging(sc);\n        return ENOMEM;\n    }\n\n    sc->fw_paging_db[blk_idx].fw_paging_size = IWM_FW_PAGING_SIZE;\n\n    XYLog(\"%s: Paging: allocated 4K(CSS) bytes for firmware paging.\\n\",\n        DEVNAME(sc));\n\n    /*\n     * allocate blocks in dram.\n     * since that CSS allocated in fw_paging_db[0] loop start from index 1\n     */\n    for (blk_idx = 1; blk_idx < sc->num_of_paging_blk + 1; blk_idx++) {\n        /* allocate block of IWM_PAGING_BLOCK_SIZE (32K) */\n        /* XXX Use iwm_dma_contig_alloc for allocating */\n        error = iwm_dma_contig_alloc(sc->sc_dmat,\n             &sc->fw_paging_db[blk_idx].fw_paging_block,\n            IWM_PAGING_BLOCK_SIZE, 4096);\n        if (error) {\n            /* free all the previous pages since we failed */\n            iwm_free_fw_paging(sc);\n            return ENOMEM;\n        }\n\n        sc->fw_paging_db[blk_idx].fw_paging_size =\n            IWM_PAGING_BLOCK_SIZE;\n\n        XYLog(\n            \"%s: Paging: allocated 32K bytes for firmware paging.\\n\",\n            DEVNAME(sc));\n    }\n\n    return 0;\n}\n\nint ItlIwm::\niwm_save_fw_paging(struct iwm_softc *sc, const struct iwm_fw_sects *fw)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    int ret;\n    \n    ret = iwm_alloc_fw_paging_mem(sc, fw);\n    if (ret)\n        return ret;\n    \n    return iwm_fill_paging_mem(sc, fw);\n}\n\n/* send paging cmd to FW in case CPU2 has paging image */\nint ItlIwm::\niwm_send_paging_cmd(struct iwm_softc *sc, const struct iwm_fw_sects *fw)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    int blk_idx;\n    uint32_t dev_phy_addr;\n    struct iwm_fw_paging_cmd fw_paging_cmd = {\n        .flags =\n        htole32(IWM_PAGING_CMD_IS_SECURED |\n                IWM_PAGING_CMD_IS_ENABLED |\n                (sc->num_of_pages_in_last_blk <<\n                 IWM_PAGING_CMD_NUM_OF_PAGES_IN_LAST_GRP_POS)),\n        .block_size = htole32(IWM_BLOCK_2_EXP_SIZE),\n        .block_num = htole32(sc->num_of_paging_blk),\n    };\n    \n    /* loop for for all paging blocks + CSS block */\n    for (blk_idx = 0; blk_idx < sc->num_of_paging_blk + 1; blk_idx++) {\n        dev_phy_addr = htole32(\n                               sc->fw_paging_db[blk_idx].fw_paging_block.paddr >>\n                               IWM_PAGE_2_EXP_SIZE);\n        fw_paging_cmd.device_phy_addr[blk_idx] = dev_phy_addr;\n        //        bus_dmamap_sync(sc->sc_dmat,\n        //            sc->fw_paging_db[blk_idx].fw_paging_block.map, 0,\n        //            blk_idx == 0 ? IWM_FW_PAGING_SIZE : IWM_PAGING_BLOCK_SIZE,\n        //            BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);\n    }\n    \n    return iwm_send_cmd_pdu(sc, iwm_cmd_id(IWM_FW_PAGING_BLOCK_CMD,\n                                           IWM_LONG_GROUP, 0),\n                            0, sizeof(fw_paging_cmd), &fw_paging_cmd);\n}\n"
  },
  {
    "path": "itlwm/hal_iwm/utils.cpp",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n/*    $OpenBSD: if_iwm.c,v 1.316 2020/12/07 20:09:24 tobhe Exp $    */\n\n/*\n * Copyright (c) 2014, 2016 genua gmbh <info@genua.de>\n *   Author: Stefan Sperling <stsp@openbsd.org>\n * Copyright (c) 2014 Fixup Software Ltd.\n * Copyright (c) 2017 Stefan Sperling <stsp@openbsd.org>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n/*-\n * Based on BSD-licensed source modules in the Linux iwlwifi driver,\n * which were used as the reference documentation for this implementation.\n *\n ***********************************************************************\n *\n * This file is provided under a dual BSD/GPLv2 license.  When using or\n * redistributing this file, you may do so under either license.\n *\n * GPL LICENSE SUMMARY\n *\n * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.\n * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH\n * Copyright(c) 2016 Intel Deutschland GmbH\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of version 2 of the GNU General Public License as\n * published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful, but\n * WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,\n * USA\n *\n * The full GNU General Public License is included in this distribution\n * in the file called COPYING.\n *\n * Contact Information:\n *  Intel Linux Wireless <ilw@linux.intel.com>\n * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497\n *\n *\n * BSD LICENSE\n *\n * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.\n * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH\n * Copyright(c) 2016 Intel Deutschland GmbH\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in\n *    the documentation and/or other materials provided with the\n *    distribution.\n *  * Neither the name Intel Corporation nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*-\n * Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n#include \"ItlIwm.hpp\"\n#include <IOKit/IOLib.h>\n\nint ItlIwm::\niwm_send_bt_init_conf(struct iwm_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwm_bt_coex_cmd bt_cmd;\n    \n    bt_cmd.mode = htole32(IWM_BT_COEX_NW);\n    bt_cmd.enabled_modules = htole32(IWM_BT_COEX_HIGH_BAND_RET | IWM_BT_COEX_SYNC2SCO_ENABLED);\n    \n    if (isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT))\n        bt_cmd.enabled_modules |= IWM_BT_COEX_MPLUT_ENABLED;\n    \n    return iwm_send_cmd_pdu(sc, IWM_BT_CONFIG, 0, sizeof(bt_cmd),\n                            &bt_cmd);\n}\n"
  },
  {
    "path": "itlwm/hal_iwn/ItlIwn.cpp",
    "content": "/*\n * Copyright (C) 2020  pigworlds\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n */\n/*    $OpenBSD: if_iwn.c,v 1.243 2020/11/12 15:16:18 krw Exp $    */\n\n/*-\n * Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n/*\n * Driver for Intel WiFi Link 4965 and 1000/5000/6000 Series 802.11 network\n * adapters.\n */\n\n#include \"ItlIwn.hpp\"\n#include <linux/types.h>\n#include <linux/kernel.h>\n#include <FwData.h>\n#include <crypto/sha1.h>\n\n#include <IOKit/IOInterruptController.h>\n#include <IOKit/IOCommandGate.h>\n#include <IOKit/network/IONetworkMedium.h>\n#include <net/ethernet.h>\n\n#include <sys/_task.h>\n#include <sys/pcireg.h>\n\n#define super ItlHalService\nOSDefineMetaClassAndStructors(ItlIwn, ItlHalService)\n\n#define DEVNAME(_s)    ((_s)->sc_dev.dv_xname)\n\n#define IC2IFP(_ic_) (&(_ic_)->ic_if)\n\n#define IWN_DEBUG\n\n#ifdef IWN_DEBUG\n#define DPRINTF(x)    do { if (iwn_debug > 0) XYLog x; } while (0)\n#define DPRINTFN(n, x)    do { if (iwn_debug >= (n)) XYLog x; } while (0)\nint iwn_debug = 1;\n#else\n#define DPRINTF(x)    do { ; } while (0)\n#define DPRINTFN(n, x)    do { ; } while (0)\n#endif\n\n#define M_DEVBUF 2\n\n#ifdef DELAY\n#undef DELAY\n#define DELAY IODelay\n#endif\n\nbool ItlIwn::attach(IOPCIDevice *device)\n{\n    pci.pa_tag = device;\n    pci.workloop = getMainWorkLoop();\n    if (!iwn_attach(&com, &pci)) {\n        detach(device);\n        releaseAll();\n        return false;\n    }\n    return true;\n}\n\nvoid ItlIwn::\ndetach(IOPCIDevice *device)\n{\n    struct _ifnet *ifp = &com.sc_ic.ic_ac.ac_if;\n    struct iwn_softc *sc = &com;\n    \n    for (int txq_i = 0; txq_i < nitems(sc->txq); txq_i++)\n        iwn_free_tx_ring(sc, &sc->txq[txq_i]);\n    iwn_free_rx_ring(sc, &sc->rxq);\n    iwn_free_sched(sc);\n    iwn_free_ict(sc);\n    iwn_free_kw(sc);\n    iwn_free_fwmem(sc);\n    ieee80211_ifdetach(ifp);\n    taskq_destroy(systq);\n    releaseAll();\n}\n\nvoid ItlIwn::\nreleaseAll()\n{\n    pci_intr_handle *intrHandler = com.ih;\n    \n    if (com.calib_to) {\n        timeout_del(&com.calib_to);\n        timeout_free(&com.calib_to);\n    }\n    if (intrHandler) {\n        if (intrHandler->intr && intrHandler->workloop) {\n//            intrHandler->intr->disable();\n            intrHandler->workloop->removeEventSource(intrHandler->intr);\n            intrHandler->intr->release();\n        }\n        intrHandler->intr = NULL;\n        intrHandler->workloop = NULL;\n        intrHandler->arg = NULL;\n        intrHandler->dev = NULL;\n        intrHandler->func = NULL;\n        intrHandler->release();\n        com.ih = NULL;\n    }\n    pci.pa_tag = NULL;\n    pci.workloop = NULL;\n}\n\nvoid ItlIwn::free()\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    super::free();\n}\n\nItlDriverInfo *ItlIwn::\ngetDriverInfo()\n{\n    return this;\n}\n\nItlDriverController *ItlIwn::\ngetDriverController()\n{\n    return this;\n}\n\nIOReturn ItlIwn::enable(IONetworkInterface *netif)\n{\n    XYLog(\"%s\\n\", __PRETTY_FUNCTION__);\n    struct _ifnet *ifp = &com.sc_ic.ic_ac.ac_if;\n    if (ifp->if_flags & IFF_UP) {\n        XYLog(\"%s already in activating state\\n\", __FUNCTION__);\n        return kIOReturnSuccess;\n    }\n    ifp->if_flags |= IFF_UP;\n    iwn_activate(&com, DVACT_RESUME);\n    iwn_activate(&com, DVACT_WAKEUP);\n    return kIOReturnSuccess;\n}\n\nIOReturn ItlIwn::disable(IONetworkInterface *netif)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct _ifnet *ifp = &com.sc_ic.ic_ac.ac_if;\n    if (!(ifp->if_flags & IFF_UP)) {\n        XYLog(\"%s already in diactivating state\\n\", __FUNCTION__);\n        return kIOReturnSuccess;\n    }\n    ifp->if_flags &= ~IFF_UP;\n    iwn_activate(&com, DVACT_QUIESCE);\n    return kIOReturnSuccess;\n}\n\nvoid ItlIwn::\nclearScanningFlags()\n{\n    com.sc_flags &= ~(IWN_FLAG_SCANNING | IWN_FLAG_BGSCAN);\n}\n\nIOReturn ItlIwn::\nsetMulticastList(IOEthernetAddress *addr, int count)\n{\n    return kIOReturnSuccess;\n}\n\nconst char *ItlIwn::\ngetFirmwareVersion()\n{\n    return com.fwname;\n}\n\nconst char *ItlIwn::\ngetFirmwareName()\n{\n    return com.fwname;\n}\n\nUInt32 ItlIwn::\nsupportedFeatures()\n{\n    return kIONetworkFeatureMultiPages;\n}\n\nconst char *ItlIwn::\ngetFirmwareCountryCode()\n{\n    return \"ZZ\";\n}\n\nuint32_t ItlIwn::\ngetTxQueueSize()\n{\n    return IWN_TX_RING_COUNT;\n}\n\nint16_t ItlIwn::\ngetBSSNoise()\n{\n    return com.noise;\n}\n\nbool ItlIwn::\nis5GBandSupport()\n{\n    return com.sc_flags & IWN_FLAG_HAS_5GHZ;\n}\n\nint ItlIwn::\ngetTxNSS()\n{\n    return com.ntxchains;\n}\n\nstruct ieee80211com *ItlIwn::\nget80211Controller()\n{\n    return &com.sc_ic;\n}\n\n#define    PCI_VENDOR_INTEL    0x8086        /* Intel */\n#define    PCI_PRODUCT_INTEL_WL_4965_1    0x4229        /* Wireless WiFi Link 4965 */\n#define    PCI_PRODUCT_INTEL_WL_6300_1    0x422b        /* Centrino Ultimate-N 6300 */\n#define    PCI_PRODUCT_INTEL_WL_6200_1    0x422c        /* Centrino Advanced-N 6200 */\n#define    PCI_PRODUCT_INTEL_WL_4965_2    0x4230        /* Wireless WiFi Link 4965 */\n#define    PCI_PRODUCT_INTEL_WL_5100_1    0x4232        /* WiFi Link 5100 */\n#define    PCI_PRODUCT_INTEL_WL_5300_1    0x4235        /* WiFi Link 5300 */\n#define    PCI_PRODUCT_INTEL_WL_5300_2    0x4236        /* WiFi Link 5300 */\n#define    PCI_PRODUCT_INTEL_WL_5100_2    0x4237        /* WiFi Link 5100 */\n#define    PCI_PRODUCT_INTEL_WL_6300_2    0x4238        /* Centrino Ultimate-N 6300 */\n#define    PCI_PRODUCT_INTEL_WL_6200_2    0x4239        /* Centrino Advanced-N 6200 */\n#define    PCI_PRODUCT_INTEL_WL_5350_1    0x423a        /* WiFi Link 5350 */\n#define    PCI_PRODUCT_INTEL_WL_5350_2    0x423b        /* WiFi Link 5350 */\n#define    PCI_PRODUCT_INTEL_WL_5150_1    0x423c        /* WiFi Link 5150 */\n#define    PCI_PRODUCT_INTEL_WL_5150_2    0x423d        /* WiFi Link 5150 */\n#define    PCI_PRODUCT_INTEL_WL_6005_1    0x0082        /* Centrino Advanced-N 6205 */\n#define    PCI_PRODUCT_INTEL_WL_1000_1    0x0083        /* WiFi Link 1000 */\n#define    PCI_PRODUCT_INTEL_WL_1000_2    0x0084        /* WiFi Link 1000 */\n#define    PCI_PRODUCT_INTEL_WL_6005_2    0x0085        /* Centrino Advanced-N 6205 */\n#define    PCI_PRODUCT_INTEL_WL_6050_1    0x0087        /* Centrino Advanced-N 6250 */\n#define    PCI_PRODUCT_INTEL_WL_6050_2    0x0089        /* Centrino Advanced-N 6250 */\n#define    PCI_PRODUCT_INTEL_WL_1030_1    0x008a        /* WiFi Link 1030 */\n#define    PCI_PRODUCT_INTEL_WL_1030_2    0x008b        /* WiFi Link 1030 */\n#define    PCI_PRODUCT_INTEL_WL_6030_1    0x0090        /* Centrino Advanced-N 6030 */\n#define    PCI_PRODUCT_INTEL_WL_6030_2    0x0091        /* Centrino Advanced-N 6030 */\n#define    PCI_PRODUCT_INTEL_WL_135_1    0x0892        /* Centrino Wireless-N 135 */\n#define    PCI_PRODUCT_INTEL_WL_135_2    0x0893        /* Centrino Wireless-N 135 */\n#define    PCI_PRODUCT_INTEL_WL_105_1    0x0894        /* Centrino Wireless-N 105 */\n#define    PCI_PRODUCT_INTEL_WL_105_2    0x0895        /* Centrino Wireless-N 105 */\n#define    PCI_PRODUCT_INTEL_WL_130_1    0x0896        /* Centrino Wireless-N 130 */\n#define    PCI_PRODUCT_INTEL_WL_130_2    0x0897        /* Centrino Wireless-N 130 */\n#define    PCI_PRODUCT_INTEL_WL_100_1    0x08ae        /* Centrino Wireless-N 100 */\n#define    PCI_PRODUCT_INTEL_WL_100_2    0x08af        /* Centrino Wireless-N 100 */\n#define    PCI_PRODUCT_INTEL_WL_6235_1    0x088e        /* Centrino Advanced-N 6235 */\n#define    PCI_PRODUCT_INTEL_WL_6235_2    0x088f        /* Centrino Advanced-N 6235 */\n#define    PCI_PRODUCT_INTEL_WL_2200_1    0x0890        /* Centrino Wireless-N 2200 */\n#define    PCI_PRODUCT_INTEL_WL_2200_2    0x0891        /* Centrino Wireless-N 2200 */\n#define    PCI_PRODUCT_INTEL_WL_6150_1    0x0885        /* Centrino Wireless-N 6150 */\n#define    PCI_PRODUCT_INTEL_WL_6150_2    0x0886        /* Centrino Wireless-N 6150 */\n#define    PCI_PRODUCT_INTEL_WL_2230_1    0x0887        /* Centrino Wireless-N 2230 */\n#define    PCI_PRODUCT_INTEL_WL_2230_2    0x0888        /* Centrino Wireless-N 2230 */\n\nstatic const struct pci_matchid iwn_devices[] = {\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_4965_1 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_4965_2 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_5100_1 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_5100_2 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_5150_1 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_5150_2 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_5300_1 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_5300_2 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_5350_1 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_5350_2 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_1000_1 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_1000_2 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_6300_1 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_6300_2 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_6200_1 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_6200_2 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_6050_1 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_6050_2 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_6005_1 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_6005_2 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_6030_1 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_6030_2 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_1030_1 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_1030_2 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_100_1 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_100_2 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_130_1 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_130_2 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_6235_1 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_6235_2 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_2230_1 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_2230_2 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_2200_1 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_2200_2 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_135_1 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_135_2 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_105_1 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_105_2 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_6150_1 },\n    { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_6150_2 },\n};\n\nint ItlIwn::\niwn_match(struct IOPCIDevice *device)\n{\n    int devId = device->configRead16(kIOPCIConfigDeviceID);\n    return pci_matchbyid(PCI_VENDOR_INTEL, devId, iwn_devices,\n                         nitems(iwn_devices));\n}\n\nbool ItlIwn::\nintrFilter(OSObject *object, IOFilterInterruptEventSource *src)\n{\n    ItlIwn *that = (ItlIwn*)object;\n    IWN_WRITE(&that->com, IWN_INT_MASK, 0);\n    return true;\n}\n\nbool ItlIwn::\niwn_attach(struct iwn_softc *sc, struct pci_attach_args *pa)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct _ifnet *ifp = &ic->ic_if;\n    pcireg_t memtype, reg;\n    int i, error;\n\n    sc->sc_pct = pa->pa_pc;\n    sc->sc_pcitag = pa->pa_tag;\n    sc->sc_dmat = pa->pa_dmat;\n\n    /*\n     * Get the offset of the PCI Express Capability Structure in PCI\n     * Configuration Space.\n     */\n    error = pci_get_capability(sc->sc_pct, sc->sc_pcitag,\n        PCI_CAP_PCIEXPRESS, &sc->sc_cap_off, NULL);\n    if (error == 0) {\n        XYLog(\": PCIe capability structure not found!\\n\");\n        return false;\n    }\n\n    /* Clear device-specific \"PCI retry timeout\" register (41h). */\n    reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0x40);\n    if (reg & 0xff00)\n        pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, reg & ~0xff00);\n\n    /* Hardware bug workaround. */\n    reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, PCI_COMMAND_STATUS_REG);\n    if (reg & PCI_COMMAND_INTERRUPT_DISABLE) {\n        DPRINTF((\"PCIe INTx Disable set\\n\"));\n        reg &= ~PCI_COMMAND_INTERRUPT_DISABLE;\n        pci_conf_write(sc->sc_pct, sc->sc_pcitag,\n            PCI_COMMAND_STATUS_REG, reg);\n    }\n\n    memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, IWN_PCI_BAR0);\n    error = pci_mapreg_map(pa, IWN_PCI_BAR0, memtype, 0, &sc->sc_st,\n        &sc->sc_sh, NULL, &sc->sc_sz, 0);\n    if (error != 0) {\n        XYLog(\": can't map mem space\\n\");\n        return false;\n    }\n\n    /* Install interrupt handler. */\n    if (pci_intr_map_msi(pa, &sc->ih) != 0) {\n        XYLog(\": can't map interrupt\\n\");\n        return false;\n    }\n\n    int msiIntrIndex = -1;\n    for (int index = 0; ; index++)\n    {\n        int interruptType;\n        int ret = pa->pa_tag->getInterruptType(index, &interruptType);\n        if (ret != kIOReturnSuccess)\n            break;\n        if (interruptType & kIOInterruptTypePCIMessaged)\n        {\n            msiIntrIndex = index;\n            break;\n        }\n    }\n    if (msiIntrIndex == -1) {\n        XYLog(\"%s: can't find MSI interrupt controller\\n\", DEVNAME(sc));\n        return false;\n    }\n\n    sc->sc_ih = IOFilterInterruptEventSource::filterInterruptEventSource(this,\n                                                                         (IOInterruptEventSource::Action)&ItlIwn::iwn_intr, &ItlIwn::intrFilter\n                                                                         ,pa->pa_tag, msiIntrIndex);\n    if (sc->sc_ih == NULL || pa->workloop->addEventSource(sc->sc_ih) != kIOReturnSuccess) {\n        XYLog(\"%s: can't establish interrupt\\n\", DEVNAME(sc));\n        return false;\n    }\n    sc->sc_ih->enable();\n\n    /* Read hardware revision and attach. */\n    sc->hw_type = (IWN_READ(sc, IWN_HW_REV) >> 4) & 0x1f;\n    int pa_id = pa->pa_tag->configRead16(kIOPCIConfigDeviceID);\n    if (sc->hw_type == IWN_HW_REV_TYPE_4965)\n        error = iwn4965_attach(sc, pa_id);\n    else\n        error = iwn5000_attach(sc, pa_id);\n    if (error != 0) {\n        XYLog(\": could not attach device\\n\");\n        return false;\n    }\n\n    if ((error = iwn_hw_prepare(sc)) != 0) {\n        XYLog(\": hardware not ready\\n\");\n        return false;\n    }\n\n    /* Read MAC address, channels, etc from EEPROM. */\n    if ((error = iwn_read_eeprom(sc)) != 0) {\n        XYLog(\": could not read EEPROM\\n\");\n        return false;\n    }\n\n    /* Allocate DMA memory for firmware transfers. */\n    if ((error = iwn_alloc_fwmem(sc)) != 0) {\n        XYLog(\": could not allocate memory for firmware\\n\");\n        return false;\n    }\n\n    /* Allocate \"Keep Warm\" page. */\n    if ((error = iwn_alloc_kw(sc)) != 0) {\n        XYLog(\": could not allocate keep warm page\\n\");\n        goto fail1;\n    }\n\n    /* Allocate ICT table for 5000 Series. */\n    if (sc->hw_type != IWN_HW_REV_TYPE_4965 &&\n        (error = iwn_alloc_ict(sc)) != 0) {\n        XYLog(\": could not allocate ICT table\\n\");\n        goto fail2;\n    }\n\n    /* Allocate TX scheduler \"rings\". */\n    if ((error = iwn_alloc_sched(sc)) != 0) {\n        XYLog(\": could not allocate TX scheduler rings\\n\");\n        goto fail3;\n    }\n\n    /* Allocate TX rings (16 on 4965AGN, 20 on >=5000). */\n    for (i = 0; i < sc->ntxqs; i++) {\n        if ((error = iwn_alloc_tx_ring(sc, &sc->txq[i], i)) != 0) {\n            XYLog(\": could not allocate TX ring %d\\n\", i);\n            goto fail4;\n        }\n    }\n\n    /* Allocate RX ring. */\n    if ((error = iwn_alloc_rx_ring(sc, &sc->rxq)) != 0) {\n        XYLog(\": could not allocate RX ring\\n\");\n        goto fail4;\n    }\n\n    /* Clear pending interrupts. */\n    IWN_WRITE(sc, IWN_INT, 0xffffffff);\n\n    /* Count the number of available chains. */\n    sc->ntxchains =\n        ((sc->txchainmask >> 2) & 1) +\n        ((sc->txchainmask >> 1) & 1) +\n        ((sc->txchainmask >> 0) & 1);\n    sc->nrxchains =\n        ((sc->rxchainmask >> 2) & 1) +\n        ((sc->rxchainmask >> 1) & 1) +\n        ((sc->rxchainmask >> 0) & 1);\n    XYLog(\", MIMO %dT%dR, %.4s, address %s\\n\", sc->ntxchains,\n        sc->nrxchains, sc->eeprom_domain, ether_sprintf(ic->ic_myaddr));\n\n    taskq_init();\n    \n    ic->ic_phytype = IEEE80211_T_OFDM;    /* not only, but not used */\n    ic->ic_opmode = IEEE80211_M_STA;    /* default to BSS mode */\n    ic->ic_state = IEEE80211_S_INIT;\n\n    /* Set device capabilities. */\n    ic->ic_caps =\n        IEEE80211_C_WEP |        /* WEP */\n        IEEE80211_C_RSN |        /* WPA/RSN */\n        IEEE80211_C_SCANALL |    /* device scans all channels at once */\n        IEEE80211_C_SCANALLBAND |    /* driver scans all bands at once */\n        IEEE80211_C_MONITOR |    /* monitor mode supported */\n        IEEE80211_C_SHSLOT |    /* short slot time supported */\n        IEEE80211_C_SHPREAMBLE |    /* short preamble supported */\n        IEEE80211_C_PMGT;        /* power saving supported */\n\n    /* No optional HT features supported for now, */\n    ic->ic_htcaps = 0;\n    ic->ic_htxcaps = 0;\n    ic->ic_txbfcaps = 0;\n    ic->ic_aselcaps = 0;\n    ic->ic_ampdu_params = (IEEE80211_AMPDU_PARAM_SS_4 | 0x3 /* 64k */);\n    if (sc->sc_flags & IWN_FLAG_HAS_11N) {\n        ic->ic_caps |= (IEEE80211_C_QOS | IEEE80211_C_TX_AMPDU | IEEE80211_C_AMSDU_IN_AMPDU);\n        /* Set HT capabilities. */\n        ic->ic_htcaps = IEEE80211_HTCAP_SGI20;\n        /* 6200 devices have issues with SGI40 for some reason. */\n        if ((sc->sc_flags & IWN_FLAG_INTERNAL_PA) == 0)\n            ic->ic_htcaps |= IEEE80211_HTCAP_SGI40;\n        ic->ic_htcaps |= IEEE80211_HTCAP_CBW20_40;\n#if IWN_RBUF_SIZE == 8192\n        ic->ic_htcaps |=\n            IEEE80211_HTCAP_AMSDU7935;\n#endif\n#ifdef notyet\n        if (sc->hw_type != IWN_HW_REV_TYPE_4965)\n            ic->ic_htcaps |= IEEE80211_HTCAP_GF;\n#endif\n        if (sc->hw_type == IWN_HW_REV_TYPE_6050)\n            ic->ic_htcaps |= IEEE80211_HTCAP_SMPS_DYN << IEEE80211_HTCAP_SMPS_SHIFT;\n        else\n            ic->ic_htcaps |= IEEE80211_HTCAP_SMPS_DIS << IEEE80211_HTCAP_SMPS_SHIFT;\n    }\n\n    /* Set supported legacy rates. */\n    ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b;\n    ic->ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_std_rateset_11g;\n    if (sc->sc_flags & IWN_FLAG_HAS_5GHZ) {\n        ic->ic_sup_rates[IEEE80211_MODE_11A] =\n            ieee80211_std_rateset_11a;\n    }\n    if (sc->sc_flags & IWN_FLAG_HAS_11N) {\n        /* Set supported HT rates. */\n        if (ic->ic_userflags & IEEE80211_F_NOMIMO)\n            sc->ntxchains = sc->nrxchains = 1;\n\n        int ntxstreams = sc->ntxchains;\n        int nrxstreams = sc->nrxchains;\n\n        ic->ic_sup_mcs[0] = 0xff;        /* MCS 0-7 */\n        if (nrxstreams > 1)\n            ic->ic_sup_mcs[1] = 0xff;    /* MCS 8-15 */\n        if (nrxstreams > 2)\n            ic->ic_sup_mcs[2] = 0xff;    /* MCS 16-23 */\n\n        ic->ic_tx_mcs_set = IEEE80211_TX_MCS_SET_DEFINED;\n        if (ntxstreams != nrxstreams) {\n            ic->ic_tx_mcs_set |= IEEE80211_TX_RX_MCS_NOT_EQUAL;\n            ic->ic_tx_mcs_set |= (ntxstreams - 1) << 2;\n        }\n    }\n\n    /* IBSS channel undefined for now. */\n    ic->ic_ibss_chan = &ic->ic_channels[0];\n    \n    ic->ic_max_rssi = IWN_MAX_DBM - IWN_MIN_DBM;\n\n    ifp->if_softc = sc;\n    ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST | IFF_DEBUG;\n    ifp->if_ioctl = iwn_ioctl;\n    ifp->if_start = iwn_start;\n    ifp->if_watchdog = iwn_watchdog;\n    memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);\n\n    if_attach(ifp);\n    ieee80211_ifattach(ifp, getController());\n    ic->ic_node_alloc = iwn_node_alloc;\n    ic->ic_bgscan_start = iwn_bgscan;\n    ic->ic_newassoc = iwn_newassoc;\n    ic->ic_updateedca = iwn_updateedca;\n    ic->ic_set_key = iwn_set_key;\n    ic->ic_delete_key = iwn_delete_key;\n    ic->ic_updateprot = iwn_updateprot;\n    ic->ic_updateslot = iwn_updateslot;\n    ic->ic_ampdu_rx_start = iwn_ampdu_rx_start;\n    ic->ic_ampdu_rx_stop = iwn_ampdu_rx_stop;\n    ic->ic_ampdu_tx_start = iwn_ampdu_tx_start;\n    ic->ic_ampdu_tx_stop = iwn_ampdu_tx_stop;\n    ic->ic_update_chw = iwn_update_chw;\n\n    /* Override 802.11 state transition machine. */\n    sc->sc_newstate = ic->ic_newstate;\n    ic->ic_newstate = iwn_newstate;\n    ieee80211_media_init(ifp);\n\n    sc->amrr.amrr_min_success_threshold =  1;\n    sc->amrr.amrr_max_success_threshold = 15;\n\n#if NBPFILTER > 0\n    iwn_radiotap_attach(sc);\n#endif\n    timeout_set(&sc->calib_to, iwn_calib_timeout, sc);\n//    rw_init(&sc->sc_rwlock, \"iwnlock\");\n    task_set(&sc->init_task, iwn_init_task, sc, \"iwn_init_task\");\n    return true;\n\n    /* Free allocated memory if something failed during attachment. */\nfail4:    while (--i >= 0)\n        iwn_free_tx_ring(sc, &sc->txq[i]);\n    iwn_free_sched(sc);\nfail3:    if (sc->ict != NULL)\n        iwn_free_ict(sc);\nfail2:    iwn_free_kw(sc);\nfail1:    iwn_free_fwmem(sc);\n    return false;\n}\n\nint ItlIwn::\niwn4965_attach(struct iwn_softc *sc, pci_product_id_t pid)\n{\n    struct iwn_ops *ops = &sc->ops;\n\n    ops->load_firmware = iwn4965_load_firmware;\n    ops->read_eeprom = iwn4965_read_eeprom;\n    ops->post_alive = iwn4965_post_alive;\n    ops->nic_config = iwn4965_nic_config;\n    ops->reset_sched = iwn4965_reset_sched;\n    ops->update_sched = iwn4965_update_sched;\n    ops->update_rxon = iwn4965_update_rxon;\n    ops->get_temperature = iwn4965_get_temperature;\n    ops->get_rssi = iwn4965_get_rssi;\n    ops->set_txpower = iwn4965_set_txpower;\n    ops->init_gains = iwn4965_init_gains;\n    ops->set_gains = iwn4965_set_gains;\n    ops->add_node = iwn4965_add_node;\n    ops->tx_done = iwn4965_tx_done;\n    ops->ampdu_tx_start = iwn4965_ampdu_tx_start;\n    ops->ampdu_tx_stop = iwn4965_ampdu_tx_stop;\n    sc->ntxqs = IWN4965_NTXQUEUES;\n    sc->first_agg_txq = IWN4965_FIRST_AGG_TXQUEUE;\n    sc->ndmachnls = IWN4965_NDMACHNLS;\n    sc->broadcast_id = IWN4965_ID_BROADCAST;\n    sc->rxonsz = IWN4965_RXONSZ;\n    sc->schedsz = IWN4965_SCHEDSZ;\n    sc->fw_text_maxsz = IWN4965_FW_TEXT_MAXSZ;\n    sc->fw_data_maxsz = IWN4965_FW_DATA_MAXSZ;\n    sc->fwsz = IWN4965_FWSZ;\n    sc->sched_txfact_addr = IWN4965_SCHED_TXFACT;\n    sc->limits = &iwn4965_sensitivity_limits;\n    sc->fwname = \"iwn-4965\";\n    /* Override chains masks, ROM is known to be broken. */\n    sc->txchainmask = IWN_ANT_AB;\n    sc->rxchainmask = IWN_ANT_ABC;\n\n    return 0;\n}\n\nint ItlIwn::\niwn5000_attach(struct iwn_softc *sc, pci_product_id_t pid)\n{\n    struct iwn_ops *ops = &sc->ops;\n\n    ops->load_firmware = iwn5000_load_firmware;\n    ops->read_eeprom = iwn5000_read_eeprom;\n    ops->post_alive = iwn5000_post_alive;\n    ops->nic_config = iwn5000_nic_config;\n    ops->reset_sched = iwn5000_reset_sched;\n    ops->update_sched = iwn5000_update_sched;\n    ops->update_rxon = iwn5000_update_rxon;\n    ops->get_temperature = iwn5000_get_temperature;\n    ops->get_rssi = iwn5000_get_rssi;\n    ops->set_txpower = iwn5000_set_txpower;\n    ops->init_gains = iwn5000_init_gains;\n    ops->set_gains = iwn5000_set_gains;\n    ops->add_node = iwn5000_add_node;\n    ops->tx_done = iwn5000_tx_done;\n    ops->ampdu_tx_start = iwn5000_ampdu_tx_start;\n    ops->ampdu_tx_stop = iwn5000_ampdu_tx_stop;\n    sc->ntxqs = IWN5000_NTXQUEUES;\n    sc->first_agg_txq = IWN5000_FIRST_AGG_TXQUEUE;\n    sc->ndmachnls = IWN5000_NDMACHNLS;\n    sc->broadcast_id = IWN5000_ID_BROADCAST;\n    sc->rxonsz = IWN5000_RXONSZ;\n    sc->schedsz = IWN5000_SCHEDSZ;\n    sc->fw_text_maxsz = IWN5000_FW_TEXT_MAXSZ;\n    sc->fw_data_maxsz = IWN5000_FW_DATA_MAXSZ;\n    sc->fwsz = IWN5000_FWSZ;\n    sc->sched_txfact_addr = IWN5000_SCHED_TXFACT;\n\n    switch (sc->hw_type) {\n    case IWN_HW_REV_TYPE_5100:\n        sc->limits = &iwn5000_sensitivity_limits;\n        sc->fwname = \"iwn-5000\";\n        /* Override chains masks, ROM is known to be broken. */\n        sc->txchainmask = IWN_ANT_B;\n        sc->rxchainmask = IWN_ANT_AB;\n        break;\n    case IWN_HW_REV_TYPE_5150:\n        sc->limits = &iwn5150_sensitivity_limits;\n        sc->fwname = \"iwn-5150\";\n        break;\n    case IWN_HW_REV_TYPE_5300:\n    case IWN_HW_REV_TYPE_5350:\n        sc->limits = &iwn5000_sensitivity_limits;\n        sc->fwname = \"iwn-5000\";\n        break;\n    case IWN_HW_REV_TYPE_1000:\n        sc->limits = &iwn1000_sensitivity_limits;\n        sc->fwname = \"iwn-1000\";\n        break;\n    case IWN_HW_REV_TYPE_6000:\n        sc->limits = &iwn6000_sensitivity_limits;\n        sc->fwname = \"iwn-6000\";\n        if (pid == PCI_PRODUCT_INTEL_WL_6200_1 ||\n            pid == PCI_PRODUCT_INTEL_WL_6200_2) {\n            sc->sc_flags |= IWN_FLAG_INTERNAL_PA;\n            /* Override chains masks, ROM is known to be broken. */\n            sc->txchainmask = IWN_ANT_BC;\n            sc->rxchainmask = IWN_ANT_BC;\n        }\n        break;\n    case IWN_HW_REV_TYPE_6050:\n        sc->limits = &iwn6000_sensitivity_limits;\n        sc->fwname = \"iwn-6050\";\n        break;\n    case IWN_HW_REV_TYPE_6005:\n        sc->limits = &iwn6000_sensitivity_limits;\n        if (pid != PCI_PRODUCT_INTEL_WL_6005_1 &&\n            pid != PCI_PRODUCT_INTEL_WL_6005_2) {\n            sc->fwname = \"iwn-6030\";\n            sc->sc_flags |= IWN_FLAG_ADV_BT_COEX;\n        } else\n            sc->fwname = \"iwn-6005\";\n        break;\n    case IWN_HW_REV_TYPE_2030:\n        sc->limits = &iwn2000_sensitivity_limits;\n        sc->fwname = \"iwn-2030\";\n        sc->sc_flags |= IWN_FLAG_ADV_BT_COEX;\n        break;\n    case IWN_HW_REV_TYPE_2000:\n        sc->limits = &iwn2000_sensitivity_limits;\n        sc->fwname = \"iwn-2000\";\n        break;\n    case IWN_HW_REV_TYPE_135:\n        sc->limits = &iwn2000_sensitivity_limits;\n        sc->fwname = \"iwn-135\";\n        sc->sc_flags |= IWN_FLAG_ADV_BT_COEX;\n        break;\n    case IWN_HW_REV_TYPE_105:\n        sc->limits = &iwn2000_sensitivity_limits;\n        sc->fwname = \"iwn-105\";\n        break;\n    default:\n        XYLog(\": adapter type %d not supported\\n\", sc->hw_type);\n        return ENOTSUP;\n    }\n    return 0;\n}\n\n#if NBPFILTER > 0\n/*\n * Attach the interface to 802.11 radiotap.\n */\nvoid ItlIwn::\niwn_radiotap_attach(struct iwn_softc *sc)\n{\n    bpfattach(&sc->sc_drvbpf, &sc->sc_ic.ic_if, DLT_IEEE802_11_RADIO,\n        sizeof (struct ieee80211_frame) + IEEE80211_RADIOTAP_HDRLEN);\n\n    sc->sc_rxtap_len = sizeof sc->sc_rxtapu;\n    sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);\n    sc->sc_rxtap.wr_ihdr.it_present = htole32(IWN_RX_RADIOTAP_PRESENT);\n\n    sc->sc_txtap_len = sizeof sc->sc_txtapu;\n    sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);\n    sc->sc_txtap.wt_ihdr.it_present = htole32(IWN_TX_RADIOTAP_PRESENT);\n}\n#endif\n\nint ItlIwn::\niwn_activate(struct iwn_softc *sc, int act)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct _ifnet *ifp = &sc->sc_ic.ic_if;\n\n    switch (act) {\n    case DVACT_QUIESCE:\n        if (ifp->if_flags & IFF_RUNNING)\n            iwn_stop(ifp);\n        break;\n    case DVACT_WAKEUP:\n        iwn_wakeup(sc);\n        break;\n    }\n\n    return 0;\n}\n\nvoid ItlIwn::\niwn_wakeup(struct iwn_softc *sc)\n{\n    pcireg_t reg;\n\n    /* Clear device-specific \"PCI retry timeout\" register (41h). */\n    reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0x40);\n    if (reg & 0xff00)\n        pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, reg & ~0xff00);\n    task_add(systq, &sc->init_task);\n}\n\nvoid ItlIwn::\niwn_init_task(void *arg1)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwn_softc *sc = (struct iwn_softc *)arg1;\n    struct _ifnet *ifp = &sc->sc_ic.ic_if;\n    ItlIwn *that = container_of(sc, ItlIwn, com);\n    int s;\n\n//    rw_enter_write(&sc->sc_rwlock);\n    s = splnet();\n\n    if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == IFF_UP)\n        that->iwn_init(ifp);\n\n    splx(s);\n//    rw_exit_write(&sc->sc_rwlock);\n}\n\nint\niwn_nic_lock(struct iwn_softc *sc)\n{\n    int ntries;\n\n    /* Request exclusive access to NIC. */\n    IWN_SETBITS(sc, IWN_GP_CNTRL, IWN_GP_CNTRL_MAC_ACCESS_REQ);\n\n    /* Spin until we actually get the lock. */\n    for (ntries = 0; ntries < 1000; ntries++) {\n        if ((IWN_READ(sc, IWN_GP_CNTRL) &\n             (IWN_GP_CNTRL_MAC_ACCESS_ENA | IWN_GP_CNTRL_SLEEP)) ==\n            IWN_GP_CNTRL_MAC_ACCESS_ENA)\n            return 0;\n        DELAY(10);\n    }\n    \n    XYLog(\"%s acquiring device failed.\", __FUNCTION__);\n    return ETIMEDOUT;\n}\n\nvoid\niwn_nic_unlock(struct iwn_softc *sc)\n{\n    IWN_CLRBITS(sc, IWN_GP_CNTRL, IWN_GP_CNTRL_MAC_ACCESS_REQ);\n}\n\nuint32_t\niwn_prph_read(struct iwn_softc *sc, uint32_t addr)\n{\n    IWN_WRITE(sc, IWN_PRPH_RADDR, IWN_PRPH_DWORD | addr);\n    IWN_BARRIER_READ_WRITE(sc);\n    return IWN_READ(sc, IWN_PRPH_RDATA);\n}\n\nvoid\niwn_prph_write(struct iwn_softc *sc, uint32_t addr, uint32_t data)\n{\n    IWN_WRITE(sc, IWN_PRPH_WADDR, IWN_PRPH_DWORD | addr);\n    IWN_BARRIER_WRITE(sc);\n    IWN_WRITE(sc, IWN_PRPH_WDATA, data);\n}\n\nvoid\niwn_prph_setbits(struct iwn_softc *sc, uint32_t addr, uint32_t mask)\n{\n    iwn_prph_write(sc, addr, iwn_prph_read(sc, addr) | mask);\n}\n\nvoid\niwn_prph_clrbits(struct iwn_softc *sc, uint32_t addr, uint32_t mask)\n{\n    iwn_prph_write(sc, addr, iwn_prph_read(sc, addr) & ~mask);\n}\n\nvoid\niwn_prph_write_region_4(struct iwn_softc *sc, uint32_t addr,\n    const uint32_t *data, int count)\n{\n    for (; count > 0; count--, data++, addr += 4)\n        iwn_prph_write(sc, addr, *data);\n}\n\nuint32_t\niwn_mem_read(struct iwn_softc *sc, uint32_t addr)\n{\n    IWN_WRITE(sc, IWN_MEM_RADDR, addr);\n    IWN_BARRIER_READ_WRITE(sc);\n    return IWN_READ(sc, IWN_MEM_RDATA);\n}\n\nvoid\niwn_mem_write(struct iwn_softc *sc, uint32_t addr, uint32_t data)\n{\n    IWN_WRITE(sc, IWN_MEM_WADDR, addr);\n    IWN_BARRIER_WRITE(sc);\n    IWN_WRITE(sc, IWN_MEM_WDATA, data);\n}\n\nvoid\niwn_mem_write_2(struct iwn_softc *sc, uint32_t addr, uint16_t data)\n{\n    uint32_t tmp;\n\n    tmp = iwn_mem_read(sc, addr & ~3);\n    if (addr & 3)\n        tmp = (tmp & 0x0000ffff) | data << 16;\n    else\n        tmp = (tmp & 0xffff0000) | data;\n    iwn_mem_write(sc, addr & ~3, tmp);\n}\n\n#ifdef IWN_DEBUG\n\nvoid\niwn_mem_read_region_4(struct iwn_softc *sc, uint32_t addr, uint32_t *data,\n    int count)\n{\n    for (; count > 0; count--, addr += 4)\n        *data++ = iwn_mem_read(sc, addr);\n}\n\n#endif\n\nvoid\niwn_mem_set_region_4(struct iwn_softc *sc, uint32_t addr, uint32_t val,\n    int count)\n{\n    for (; count > 0; count--, addr += 4)\n        iwn_mem_write(sc, addr, val);\n}\n\nint ItlIwn::\niwn_eeprom_lock(struct iwn_softc *sc)\n{\n    int i, ntries;\n\n    for (i = 0; i < 100; i++) {\n        /* Request exclusive access to EEPROM. */\n        IWN_SETBITS(sc, IWN_HW_IF_CONFIG,\n            IWN_HW_IF_CONFIG_EEPROM_LOCKED);\n\n        /* Spin until we actually get the lock. */\n        for (ntries = 0; ntries < 100; ntries++) {\n            if (IWN_READ(sc, IWN_HW_IF_CONFIG) &\n                IWN_HW_IF_CONFIG_EEPROM_LOCKED)\n                return 0;\n            DELAY(10);\n        }\n    }\n    return ETIMEDOUT;\n}\n\nvoid\niwn_eeprom_unlock(struct iwn_softc *sc)\n{\n    IWN_CLRBITS(sc, IWN_HW_IF_CONFIG, IWN_HW_IF_CONFIG_EEPROM_LOCKED);\n}\n\n/*\n * Initialize access by host to One Time Programmable ROM.\n * NB: This kind of ROM can be found on 1000 or 6000 Series only.\n */\nint ItlIwn::\niwn_init_otprom(struct iwn_softc *sc)\n{\n    uint16_t prev, base, next;\n    int count, error;\n\n    /* Wait for clock stabilization before accessing prph. */\n    if ((error = iwn_clock_wait(sc)) != 0)\n        return error;\n\n    if ((error = iwn_nic_lock(sc)) != 0)\n        return error;\n    iwn_prph_setbits(sc, IWN_APMG_PS, IWN_APMG_PS_RESET_REQ);\n    DELAY(5);\n    iwn_prph_clrbits(sc, IWN_APMG_PS, IWN_APMG_PS_RESET_REQ);\n    iwn_nic_unlock(sc);\n\n    /* Set auto clock gate disable bit for HW with OTP shadow RAM. */\n    if (sc->hw_type != IWN_HW_REV_TYPE_1000) {\n        IWN_SETBITS(sc, IWN_DBG_LINK_PWR_MGMT,\n            IWN_RESET_LINK_PWR_MGMT_DIS);\n    }\n    IWN_CLRBITS(sc, IWN_EEPROM_GP, IWN_EEPROM_GP_IF_OWNER);\n    /* Clear ECC status. */\n    IWN_SETBITS(sc, IWN_OTP_GP,\n        IWN_OTP_GP_ECC_CORR_STTS | IWN_OTP_GP_ECC_UNCORR_STTS);\n\n    /*\n     * Find the block before last block (contains the EEPROM image)\n     * for HW without OTP shadow RAM.\n     */\n    if (sc->hw_type == IWN_HW_REV_TYPE_1000) {\n        /* Switch to absolute addressing mode. */\n        IWN_CLRBITS(sc, IWN_OTP_GP, IWN_OTP_GP_RELATIVE_ACCESS);\n        base = 0;\n        for (count = 0; count < IWN1000_OTP_NBLOCKS; count++) {\n            error = iwn_read_prom_data(sc, base, &next, 2);\n            if (error != 0)\n                return error;\n            if (next == 0)    /* End of linked-list. */\n                break;\n            prev = base;\n            base = letoh16(next);\n        }\n        if (count == 0 || count == IWN1000_OTP_NBLOCKS)\n            return EIO;\n        /* Skip \"next\" word. */\n        sc->prom_base = prev + 1;\n    }\n    return 0;\n}\n\nint ItlIwn::\niwn_read_prom_data(struct iwn_softc *sc, uint32_t addr, void *data, int count)\n{\n    uint8_t *out = (uint8_t *)data;\n    uint32_t val, tmp;\n    int ntries;\n\n    addr += sc->prom_base;\n    for (; count > 0; count -= 2, addr++) {\n        IWN_WRITE(sc, IWN_EEPROM, addr << 2);\n        for (ntries = 0; ntries < 10; ntries++) {\n            val = IWN_READ(sc, IWN_EEPROM);\n            if (val & IWN_EEPROM_READ_VALID)\n                break;\n            DELAY(5);\n        }\n        if (ntries == 10) {\n            XYLog(\"%s: timeout reading ROM at 0x%x\\n\",\n                sc->sc_dev.dv_xname, addr);\n            return ETIMEDOUT;\n        }\n        if (sc->sc_flags & IWN_FLAG_HAS_OTPROM) {\n            /* OTPROM, check for ECC errors. */\n            tmp = IWN_READ(sc, IWN_OTP_GP);\n            if (tmp & IWN_OTP_GP_ECC_UNCORR_STTS) {\n                XYLog(\"%s: OTPROM ECC error at 0x%x\\n\",\n                    sc->sc_dev.dv_xname, addr);\n                return EIO;\n            }\n            if (tmp & IWN_OTP_GP_ECC_CORR_STTS) {\n                /* Correctable ECC error, clear bit. */\n                IWN_SETBITS(sc, IWN_OTP_GP,\n                    IWN_OTP_GP_ECC_CORR_STTS);\n            }\n        }\n        *out++ = val >> 16;\n        if (count > 1)\n            *out++ = val >> 24;\n    }\n    return 0;\n}\n\nbool allocDmaMemory2(struct iwn_dma_info *dma, size_t size, int alignment)\n{\n    IOBufferMemoryDescriptor *bmd;\n    IODMACommand::Segment64 seg;\n    UInt64 ofs = 0;\n    UInt32 numSegs = 1;\n    \n    bmd = IOBufferMemoryDescriptor::inTaskWithPhysicalMask(kernel_task, kIODirectionInOut | kIOMemoryPhysicallyContiguous | kIOMapInhibitCache, size, DMA_BIT_MASK(64));\n    \n    if (bmd == NULL) {\n        XYLog(\"%s alloc DMA memory failed.\\n\", __FUNCTION__);\n        return false;\n    }\n    \n    bmd->prepare();\n    IODMACommand *cmd = IODMACommand::withSpecification(kIODMACommandOutputHost64, 64, 0, IODMACommand::kMapped, 0, alignment);\n    \n    if (cmd == NULL) {\n        XYLog(\"%s alloc IODMACommand memory failed.\\n\", __FUNCTION__);\n        bmd->complete();\n        bmd->release();\n        return false;\n    }\n    \n    cmd->setMemoryDescriptor(bmd);\n\n    if (cmd->gen64IOVMSegments(&ofs, &seg, &numSegs) != kIOReturnSuccess) {\n        cmd->release();\n        cmd = NULL;\n        bmd->complete();\n        bmd->release();\n        bmd = NULL;\n        return false;\n    }\n    dma->paddr = seg.fIOVMAddr;\n    dma->vaddr = bmd->getBytesNoCopy();\n    dma->size = size;\n    dma->buffer = bmd;\n    dma->cmd = cmd;\n    memset(dma->vaddr, 0, dma->size);\n    return true;\n}\n\nint ItlIwn::\niwn_dma_contig_alloc(bus_dma_tag_t tag, struct iwn_dma_info *dma,\n                     void** kvap, bus_size_t size, bus_size_t alignment)\n{\n    if (!allocDmaMemory2(dma, size, alignment)) {\n        return 1;\n    }\n    \n    if (kvap != NULL)\n        *kvap = dma->vaddr;\n\n    return 0;\n}\n\nvoid ItlIwn::\niwn_dma_contig_free(struct iwn_dma_info *dma)\n{\n    if (dma == NULL || dma->cmd == NULL)\n        return;\n    if (dma->vaddr == NULL)\n        return;\n    dma->cmd->clearMemoryDescriptor();\n    dma->cmd->release();\n    dma->cmd = NULL;\n    dma->buffer->complete();\n    dma->buffer->release();\n    dma->buffer = NULL;\n    dma->vaddr = NULL;\n}\n\nint ItlIwn::\niwn_alloc_sched(struct iwn_softc *sc)\n{\n    /* TX scheduler rings must be aligned on a 1KB boundary. */\n    return iwn_dma_contig_alloc(sc->sc_dmat, &sc->sched_dma,\n        (void **)&sc->sched, sc->schedsz, 1024);\n}\n\nvoid ItlIwn::\niwn_free_sched(struct iwn_softc *sc)\n{\n    iwn_dma_contig_free(&sc->sched_dma);\n}\n\nint ItlIwn::\niwn_alloc_kw(struct iwn_softc *sc)\n{\n    /* \"Keep Warm\" page must be aligned on a 4KB boundary. */\n    return iwn_dma_contig_alloc(sc->sc_dmat, &sc->kw_dma, NULL, 4096,\n        4096);\n}\n\nvoid ItlIwn::\niwn_free_kw(struct iwn_softc *sc)\n{\n    iwn_dma_contig_free(&sc->kw_dma);\n}\n\nint ItlIwn::\niwn_alloc_ict(struct iwn_softc *sc)\n{\n    /* ICT table must be aligned on a 4KB boundary. */\n    return iwn_dma_contig_alloc(sc->sc_dmat, &sc->ict_dma,\n        (void **)&sc->ict, IWN_ICT_SIZE, 4096);\n}\n\nvoid ItlIwn::\niwn_free_ict(struct iwn_softc *sc)\n{\n    iwn_dma_contig_free(&sc->ict_dma);\n}\n\nint ItlIwn::\niwn_alloc_fwmem(struct iwn_softc *sc)\n{\n    /* Must be aligned on a 16-byte boundary. */\n    return iwn_dma_contig_alloc(sc->sc_dmat, &sc->fw_dma, NULL,\n        sc->fwsz, 16);\n}\n\nvoid ItlIwn::\niwn_free_fwmem(struct iwn_softc *sc)\n{\n    iwn_dma_contig_free(&sc->fw_dma);\n}\n\nint ItlIwn::\niwn_alloc_rx_ring(struct iwn_softc *sc, struct iwn_rx_ring *ring)\n{\n    bus_size_t size;\n    int i, error;\n    mbuf_t m;\n\n    ring->cur = 0;\n\n    /* Allocate RX descriptors (256-byte aligned). */\n    size = IWN_RX_RING_COUNT * sizeof (uint32_t);\n    error = iwn_dma_contig_alloc(sc->sc_dmat, &ring->desc_dma,\n        (void **)&ring->desc, size, 256);\n    if (error != 0) {\n        XYLog(\"%s: could not allocate RX ring DMA memory\\n\",\n            sc->sc_dev.dv_xname);\n        goto fail;\n    }\n\n    /* Allocate RX status area (16-byte aligned). */\n    error = iwn_dma_contig_alloc(sc->sc_dmat, &ring->stat_dma,\n        (void **)&ring->stat, sizeof (struct iwn_rx_status), 16);\n    if (error != 0) {\n        XYLog(\"%s: could not allocate RX status DMA memory\\n\",\n            sc->sc_dev.dv_xname);\n        goto fail;\n    }\n\n    /*\n     * Allocate and map RX buffers.\n     */\n    for (i = 0; i < IWN_RX_RING_COUNT; i++) {\n        struct iwn_rx_data *data = &ring->data[i];\n\n        error = bus_dmamap_create(sc->sc_dmat, IWN_RBUF_SIZE, 1,\n            IWN_RBUF_SIZE, 0, BUS_DMA_NOWAIT,\n            &data->map);\n        if (error != 0) {\n            XYLog(\"%s: could not create RX buf DMA map\\n\",\n                sc->sc_dev.dv_xname);\n            goto fail;\n        }\n\n        m = getController()->allocatePacket(IWN_RBUF_SIZE);\n        if (m == NULL) {\n            XYLog(\"could not allocate RX mbuf\\n\");\n            error = ENOBUFS;\n            goto fail;\n        }\n        data->map->dm_nsegs = data->map->cursor->getPhysicalSegments(m, &data->map->dm_segs[0], 1);\n        if (data->map->dm_nsegs == 0) {\n            mbuf_freem(m);\n            error = ENOMEM;\n            goto fail;\n        }\n        \n        data->m = m;\n        \n//        data->m = MCLGETI(NULL, M_DONTWAIT, NULL, IWN_RBUF_SIZE);\n//        if (data->m == NULL) {\n//            XYLog(\"%s: could not allocate RX mbuf\\n\",\n//                sc->sc_dev.dv_xname);\n//            error = ENOBUFS;\n//            goto fail;\n//        }\n//\n//        error = bus_dmamap_load(sc->sc_dmat, data->map,\n//            mtod(data->m, void *), IWN_RBUF_SIZE, NULL,\n//            BUS_DMA_NOWAIT | BUS_DMA_READ);\n//        if (error != 0) {\n//            XYLog(\"%s: can't map mbuf (error %d)\\n\",\n//                sc->sc_dev.dv_xname, error);\n//            goto fail;\n//        }\n\n        /* Set physical address of RX buffer (256-byte aligned). */\n        ring->desc[i] = htole32(data->map->dm_segs[0].location >> 8);\n    }\n\n//    bus_dmamap_sync(sc->sc_dmat, ring->desc_dma.map, 0, size,\n//        BUS_DMASYNC_PREWRITE);\n\n    return 0;\n\nfail:    iwn_free_rx_ring(sc, ring);\n    return error;\n}\n\nvoid ItlIwn::\niwn_reset_rx_ring(struct iwn_softc *sc, struct iwn_rx_ring *ring)\n{\n    int ntries;\n\n    if (iwn_nic_lock(sc) == 0) {\n        IWN_WRITE(sc, IWN_FH_RX_CONFIG, 0);\n        for (ntries = 0; ntries < 1000; ntries++) {\n            if (IWN_READ(sc, IWN_FH_RX_STATUS) &\n                IWN_FH_RX_STATUS_IDLE)\n                break;\n            DELAY(10);\n        }\n        iwn_nic_unlock(sc);\n    }\n    ring->cur = 0;\n    sc->last_rx_valid = 0;\n}\n\nvoid ItlIwn::\niwn_free_rx_ring(struct iwn_softc *sc, struct iwn_rx_ring *ring)\n{\n    int i;\n\n    iwn_dma_contig_free(&ring->desc_dma);\n    iwn_dma_contig_free(&ring->stat_dma);\n\n    for (i = 0; i < IWN_RX_RING_COUNT; i++) {\n        struct iwn_rx_data *data = &ring->data[i];\n\n        if (data->m != NULL) {\n//            bus_dmamap_sync(sc->sc_dmat, data->map, 0,\n//                data->map->dm_mapsize, BUS_DMASYNC_POSTREAD);\n//            bus_dmamap_unload(sc->sc_dmat, data->map);\n            mbuf_freem(data->m);\n            data->m = NULL;\n        }\n        if (data->map != NULL) {\n            bus_dmamap_destroy(sc->sc_dmat, data->map);\n            data->map = NULL;\n        }\n    }\n}\n\nint ItlIwn::\niwn_alloc_tx_ring(struct iwn_softc *sc, struct iwn_tx_ring *ring, int qid)\n{\n    bus_addr_t paddr;\n    bus_size_t size;\n    int i, error;\n\n    ring->qid = qid;\n    ring->queued = 0;\n    ring->cur = 0;\n\n    /* Allocate TX descriptors (256-byte aligned). */\n    size = IWN_TX_RING_COUNT * sizeof (struct iwn_tx_desc);\n    error = iwn_dma_contig_alloc(sc->sc_dmat, &ring->desc_dma,\n        (void **)&ring->desc, size, 256);\n    if (error != 0) {\n        XYLog(\"%s: could not allocate TX ring DMA memory\\n\",\n            sc->sc_dev.dv_xname);\n        goto fail;\n    }\n\n    size = IWN_TX_RING_COUNT * sizeof (struct iwn_tx_cmd);\n    error = iwn_dma_contig_alloc(sc->sc_dmat, &ring->cmd_dma,\n        (void **)&ring->cmd, size, 4);\n    if (error != 0) {\n        XYLog(\"%s: could not allocate TX cmd DMA memory\\n\",\n            sc->sc_dev.dv_xname);\n        goto fail;\n    }\n\n    paddr = ring->cmd_dma.paddr;\n    for (i = 0; i < IWN_TX_RING_COUNT; i++) {\n        struct iwn_tx_data *data = &ring->data[i];\n\n        data->cmd_paddr = paddr;\n        data->scratch_paddr = paddr + 12;\n        paddr += sizeof (struct iwn_tx_cmd);\n\n        error = bus_dmamap_create(sc->sc_dmat, MCLBYTES,\n            IWN_MAX_SCATTER - 1, MCLBYTES, 0, BUS_DMA_NOWAIT,\n            &data->map);\n        if (error != 0) {\n            XYLog(\"%s: could not create TX buf DMA map\\n\",\n                sc->sc_dev.dv_xname);\n            goto fail;\n        }\n    }\n    return 0;\n\nfail:    iwn_free_tx_ring(sc, ring);\n    return error;\n}\n\nvoid ItlIwn::\niwn_reset_tx_ring(struct iwn_softc *sc, struct iwn_tx_ring *ring)\n{\n    int i;\n\n    for (i = 0; i < IWN_TX_RING_COUNT; i++) {\n        struct iwn_tx_data *data = &ring->data[i];\n\n        if (data->m != NULL) {\n//            bus_dmamap_sync(sc->sc_dmat, data->map, 0,\n//                data->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);\n//            bus_dmamap_unload(sc->sc_dmat, data->map);\n            mbuf_freem(data->m);\n            data->m = NULL;\n        }\n    }\n    /* Clear TX descriptors. */\n    memset(ring->desc, 0, ring->desc_dma.size);\n//    bus_dmamap_sync(sc->sc_dmat, ring->desc_dma.map, 0,\n//        ring->desc_dma.size, BUS_DMASYNC_PREWRITE);\n    sc->qfullmsk &= ~(1 << ring->qid);\n    ring->queued = 0;\n    ring->cur = 0;\n}\n\nvoid ItlIwn::\niwn_free_tx_ring(struct iwn_softc *sc, struct iwn_tx_ring *ring)\n{\n    int i;\n\n    iwn_dma_contig_free(&ring->desc_dma);\n    iwn_dma_contig_free(&ring->cmd_dma);\n\n    for (i = 0; i < IWN_TX_RING_COUNT; i++) {\n        struct iwn_tx_data *data = &ring->data[i];\n\n        if (data->m != NULL) {\n//            bus_dmamap_sync(sc->sc_dmat, data->map, 0,\n//                data->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);\n//            bus_dmamap_unload(sc->sc_dmat, data->map);\n            mbuf_freem(data->m);\n            data->m = NULL;\n        }\n        if (data->map != NULL) {\n            bus_dmamap_destroy(sc->sc_dmat, data->map);\n            data->map = NULL;\n        }\n    }\n}\n\nvoid ItlIwn::\niwn5000_ict_reset(struct iwn_softc *sc)\n{\n    /* Disable interrupts. */\n    IWN_WRITE(sc, IWN_INT_MASK, 0);\n\n    /* Reset ICT table. */\n    memset(sc->ict, 0, IWN_ICT_SIZE);\n    sc->ict_cur = 0;\n\n    /* Set physical address of ICT table (4KB aligned). */\n    DPRINTF((\"enabling ICT\\n\"));\n    IWN_WRITE(sc, IWN_DRAM_INT_TBL, IWN_DRAM_INT_TBL_ENABLE |\n        IWN_DRAM_INT_TBL_WRAP_CHECK | sc->ict_dma.paddr >> 12);\n\n    /* Enable periodic RX interrupt. */\n    sc->int_mask |= IWN_INT_RX_PERIODIC;\n    /* Switch to ICT interrupt mode in driver. */\n    sc->sc_flags |= IWN_FLAG_USE_ICT;\n\n    /* Re-enable interrupts. */\n    IWN_WRITE(sc, IWN_INT, 0xffffffff);\n    IWN_WRITE(sc, IWN_INT_MASK, sc->int_mask);\n}\n\nint ItlIwn::\niwn_read_eeprom(struct iwn_softc *sc)\n{\n    struct iwn_ops *ops = &sc->ops;\n    struct ieee80211com *ic = &sc->sc_ic;\n    uint16_t val;\n    int error;\n\n    /* Check whether adapter has an EEPROM or an OTPROM. */\n    if (sc->hw_type >= IWN_HW_REV_TYPE_1000 &&\n        (IWN_READ(sc, IWN_OTP_GP) & IWN_OTP_GP_DEV_SEL_OTP))\n        sc->sc_flags |= IWN_FLAG_HAS_OTPROM;\n    DPRINTF((\"%s found\\n\", (sc->sc_flags & IWN_FLAG_HAS_OTPROM) ?\n        \"OTPROM\" : \"EEPROM\"));\n\n    /* Adapter has to be powered on for EEPROM access to work. */\n    if ((error = iwn_apm_init(sc)) != 0) {\n        XYLog(\"%s: could not power ON adapter\\n\",\n            sc->sc_dev.dv_xname);\n        return error;\n    }\n\n    if ((IWN_READ(sc, IWN_EEPROM_GP) & 0x7) == 0) {\n        XYLog(\"%s: bad ROM signature\\n\", sc->sc_dev.dv_xname);\n        return EIO;\n    }\n    if ((error = iwn_eeprom_lock(sc)) != 0) {\n        XYLog(\"%s: could not lock ROM (error=%d)\\n\",\n            sc->sc_dev.dv_xname, error);\n        return error;\n    }\n    if (sc->sc_flags & IWN_FLAG_HAS_OTPROM) {\n        if ((error = iwn_init_otprom(sc)) != 0) {\n            XYLog(\"%s: could not initialize OTPROM\\n\",\n                sc->sc_dev.dv_xname);\n            return error;\n        }\n    }\n\n    iwn_read_prom_data(sc, IWN_EEPROM_SKU_CAP, &val, 2);\n    DPRINTF((\"SKU capabilities=0x%04x\\n\", letoh16(val)));\n    /* Check if HT support is bonded out. */\n    if (val & htole16(IWN_EEPROM_SKU_CAP_11N))\n        sc->sc_flags |= IWN_FLAG_HAS_11N;\n\n    iwn_read_prom_data(sc, IWN_EEPROM_RFCFG, &val, 2);\n    sc->rfcfg = letoh16(val);\n    DPRINTF((\"radio config=0x%04x\\n\", sc->rfcfg));\n    /* Read Tx/Rx chains from ROM unless it's known to be broken. */\n    if (sc->txchainmask == 0)\n        sc->txchainmask = IWN_RFCFG_TXANTMSK(sc->rfcfg);\n    if (sc->rxchainmask == 0)\n        sc->rxchainmask = IWN_RFCFG_RXANTMSK(sc->rfcfg);\n\n    /* Read MAC address. */\n    iwn_read_prom_data(sc, IWN_EEPROM_MAC, ic->ic_myaddr, 6);\n\n    /* Read adapter-specific information from EEPROM. */\n    ops->read_eeprom(sc);\n\n    iwn_apm_stop(sc);    /* Power OFF adapter. */\n\n    iwn_eeprom_unlock(sc);\n    return 0;\n}\n\nvoid ItlIwn::\niwn4965_read_eeprom(struct iwn_softc *sc)\n{\n    ItlIwn *that = container_of(sc, ItlIwn, com);\n    \n    uint32_t addr;\n    uint16_t val;\n    int i;\n\n    /* Read regulatory domain (4 ASCII characters). */\n    that->iwn_read_prom_data(sc, IWN4965_EEPROM_DOMAIN, sc->eeprom_domain, 4);\n\n    /* Read the list of authorized channels. */\n    for (i = 0; i < 7; i++) {\n        addr = iwn4965_regulatory_bands[i];\n        that->iwn_read_eeprom_channels(sc, i, addr);\n    }\n\n    /* Read maximum allowed TX power for 2GHz and 5GHz bands. */\n    that->iwn_read_prom_data(sc, IWN4965_EEPROM_MAXPOW, &val, 2);\n    sc->maxpwr2GHz = val & 0xff;\n    sc->maxpwr5GHz = val >> 8;\n    /* Check that EEPROM values are within valid range. */\n    if (sc->maxpwr5GHz < 20 || sc->maxpwr5GHz > 50)\n        sc->maxpwr5GHz = 38;\n    if (sc->maxpwr2GHz < 20 || sc->maxpwr2GHz > 50)\n        sc->maxpwr2GHz = 38;\n    DPRINTF((\"maxpwr 2GHz=%d 5GHz=%d\\n\", sc->maxpwr2GHz, sc->maxpwr5GHz));\n\n    /* Read samples for each TX power group. */\n    that->iwn_read_prom_data(sc, IWN4965_EEPROM_BANDS, sc->bands,\n        sizeof sc->bands);\n\n    /* Read voltage at which samples were taken. */\n    that->iwn_read_prom_data(sc, IWN4965_EEPROM_VOLTAGE, &val, 2);\n    sc->eeprom_voltage = (int16_t)letoh16(val);\n    DPRINTF((\"voltage=%d (in 0.3V)\\n\", sc->eeprom_voltage));\n\n#ifdef IWN_DEBUG\n    /* Print samples. */\n    if (iwn_debug > 0) {\n        for (i = 0; i < IWN_NBANDS; i++)\n            that->iwn4965_print_power_group(sc, i);\n    }\n#endif\n}\n\n#ifdef IWN_DEBUG\nvoid ItlIwn::\niwn4965_print_power_group(struct iwn_softc *sc, int i)\n{\n    struct iwn4965_eeprom_band *band = &sc->bands[i];\n    struct iwn4965_eeprom_chan_samples *chans = band->chans;\n    int j, c;\n\n    XYLog(\"===band %d===\\n\", i);\n    XYLog(\"chan lo=%d, chan hi=%d\\n\", band->lo, band->hi);\n    XYLog(\"chan1 num=%d\\n\", chans[0].num);\n    for (c = 0; c < 2; c++) {\n        for (j = 0; j < IWN_NSAMPLES; j++) {\n            XYLog(\"chain %d, sample %d: temp=%d gain=%d \"\n                \"power=%d pa_det=%d\\n\", c, j,\n                chans[0].samples[c][j].temp,\n                chans[0].samples[c][j].gain,\n                chans[0].samples[c][j].power,\n                chans[0].samples[c][j].pa_det);\n        }\n    }\n    XYLog(\"chan2 num=%d\\n\", chans[1].num);\n    for (c = 0; c < 2; c++) {\n        for (j = 0; j < IWN_NSAMPLES; j++) {\n            XYLog(\"chain %d, sample %d: temp=%d gain=%d \"\n                \"power=%d pa_det=%d\\n\", c, j,\n                chans[1].samples[c][j].temp,\n                chans[1].samples[c][j].gain,\n                chans[1].samples[c][j].power,\n                chans[1].samples[c][j].pa_det);\n        }\n    }\n}\n#endif\n\nvoid ItlIwn::\niwn5000_read_eeprom(struct iwn_softc *sc)\n{\n    ItlIwn *that = container_of(sc, ItlIwn, com);\n    struct iwn5000_eeprom_calib_hdr hdr;\n    int32_t volt;\n    uint32_t base, addr;\n    uint16_t val;\n    int i;\n\n    /* Read regulatory domain (4 ASCII characters). */\n    that->iwn_read_prom_data(sc, IWN5000_EEPROM_REG, &val, 2);\n    base = letoh16(val);\n    that->iwn_read_prom_data(sc, base + IWN5000_EEPROM_DOMAIN,\n        sc->eeprom_domain, 4);\n\n    /* Read the list of authorized channels. */\n    for (i = 0; i < 7; i++) {\n        addr = base + iwn5000_regulatory_bands[i];\n        that->iwn_read_eeprom_channels(sc, i, addr);\n    }\n\n    /* Read enhanced TX power information for 6000 Series. */\n    if (sc->hw_type >= IWN_HW_REV_TYPE_6000)\n        that->iwn_read_eeprom_enhinfo(sc);\n\n    that->iwn_read_prom_data(sc, IWN5000_EEPROM_CAL, &val, 2);\n    base = letoh16(val);\n    that->iwn_read_prom_data(sc, base, &hdr, sizeof hdr);\n    DPRINTF((\"calib version=%u pa type=%u voltage=%u\\n\",\n        hdr.version, hdr.pa_type, letoh16(hdr.volt)));\n    sc->calib_ver = hdr.version;\n\n    if (sc->hw_type == IWN_HW_REV_TYPE_2030 ||\n        sc->hw_type == IWN_HW_REV_TYPE_2000 ||\n        sc->hw_type == IWN_HW_REV_TYPE_135 ||\n        sc->hw_type == IWN_HW_REV_TYPE_105) {\n        sc->eeprom_voltage = letoh16(hdr.volt);\n        that->iwn_read_prom_data(sc, base + IWN5000_EEPROM_TEMP, &val, 2);\n        sc->eeprom_temp = letoh16(val);\n        that->iwn_read_prom_data(sc, base + IWN2000_EEPROM_RAWTEMP, &val, 2);\n        sc->eeprom_rawtemp = letoh16(val);\n    }\n\n    if (sc->hw_type == IWN_HW_REV_TYPE_5150) {\n        /* Compute temperature offset. */\n        that->iwn_read_prom_data(sc, base + IWN5000_EEPROM_TEMP, &val, 2);\n        sc->eeprom_temp = letoh16(val);\n        that->iwn_read_prom_data(sc, base + IWN5000_EEPROM_VOLT, &val, 2);\n        volt = letoh16(val);\n        sc->temp_off = sc->eeprom_temp - (volt / -5);\n        DPRINTF((\"temp=%d volt=%d offset=%dK\\n\",\n            sc->eeprom_temp, volt, sc->temp_off));\n    } else {\n        /* Read crystal calibration. */\n        that->iwn_read_prom_data(sc, base + IWN5000_EEPROM_CRYSTAL,\n            &sc->eeprom_crystal, sizeof (uint32_t));\n        DPRINTF((\"crystal calibration 0x%08x\\n\",\n            letoh32(sc->eeprom_crystal)));\n    }\n}\n\nvoid ItlIwn::\niwn_read_eeprom_channels(struct iwn_softc *sc, int n, uint32_t addr)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    const struct iwn_chan_band *band = &iwn_bands[n];\n    struct iwn_eeprom_chan channels[IWN_MAX_CHAN_PER_BAND];\n    uint8_t chan;\n    int i;\n\n    iwn_read_prom_data(sc, addr, channels,\n        band->nchan * sizeof (struct iwn_eeprom_chan));\n\n    for (i = 0; i < band->nchan; i++) {\n        if (!(channels[i].flags & IWN_EEPROM_CHAN_VALID))\n            continue;\n\n        chan = band->chan[i];\n\n        if (n == 0) {    /* 2GHz band */\n            ic->ic_channels[chan].ic_freq =\n                ieee80211_ieee2mhz(chan, IEEE80211_CHAN_2GHZ);\n            ic->ic_channels[chan].ic_flags =\n                IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |\n                IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;\n\n        } else if (n < 5) {    /* 5GHz band */\n            /*\n             * Some adapters support channels 7, 8, 11 and 12\n             * both in the 2GHz and 4.9GHz bands.\n             * Because of limitations in our net80211 layer,\n             * we don't support them in the 4.9GHz band.\n             */\n            if (chan <= 14)\n                continue;\n\n            ic->ic_channels[chan].ic_freq =\n                ieee80211_ieee2mhz(chan, IEEE80211_CHAN_5GHZ);\n            ic->ic_channels[chan].ic_flags = IEEE80211_CHAN_A;\n            /* We have at least one valid 5GHz channel. */\n            sc->sc_flags |= IWN_FLAG_HAS_5GHZ;\n        } else  { /* 40 MHz */\n            sc->maxpwr40[chan] = channels[i].maxpwr;\n            ic->ic_channels[chan].ic_flags |= IEEE80211_CHAN_HT40;\n        }\n\n        /* Is active scan allowed on this channel? */\n        if (n < 5) {\n            /* Is active scan allowed on this channel? */\n            if (!(channels[i].flags & IWN_EEPROM_CHAN_ACTIVE)) {\n                ic->ic_channels[chan].ic_flags |=\n                IEEE80211_CHAN_PASSIVE;\n            }\n\n            /* Save maximum allowed TX power for this channel. */\n            sc->maxpwr[chan] = channels[i].maxpwr;\n\n            if (sc->sc_flags & IWN_FLAG_HAS_11N)\n                ic->ic_channels[chan].ic_flags |=\n                IEEE80211_CHAN_HT;\n        }\n\n        DPRINTF((\"adding chan %d flags=0x%x maxpwr=%d maxpwr40=%d\\n\",\n                 chan, channels[i].flags, sc->maxpwr[chan],\n                 sc->maxpwr40[chan]));\n    }\n}\n\nvoid ItlIwn::\niwn_read_eeprom_enhinfo(struct iwn_softc *sc)\n{\n    struct iwn_eeprom_enhinfo enhinfo[35];\n    uint16_t val, base;\n    int8_t maxpwr;\n    int i;\n\n    iwn_read_prom_data(sc, IWN5000_EEPROM_REG, &val, 2);\n    base = letoh16(val);\n    iwn_read_prom_data(sc, base + IWN6000_EEPROM_ENHINFO,\n        enhinfo, sizeof enhinfo);\n\n    memset(sc->enh_maxpwr, 0, sizeof sc->enh_maxpwr);\n    for (i = 0; i < nitems(enhinfo); i++) {\n        if ((enhinfo[i].flags & IWN_TXP_VALID) == 0)\n            continue;    /* Skip invalid entries. */\n\n        maxpwr = 0;\n        if (sc->txchainmask & IWN_ANT_A)\n            maxpwr = MAX(maxpwr, enhinfo[i].chain[0]);\n        if (sc->txchainmask & IWN_ANT_B)\n            maxpwr = MAX(maxpwr, enhinfo[i].chain[1]);\n        if (sc->txchainmask & IWN_ANT_C)\n            maxpwr = MAX(maxpwr, enhinfo[i].chain[2]);\n        if (sc->ntxchains == 2)\n            maxpwr = MAX(maxpwr, enhinfo[i].mimo2);\n        else if (sc->ntxchains == 3)\n            maxpwr = MAX(maxpwr, enhinfo[i].mimo3);\n        maxpwr /= 2;    /* Convert half-dBm to dBm. */\n\n        DPRINTF((\"enhinfo %d, maxpwr=%d\\n\", i, maxpwr));\n        sc->enh_maxpwr[i] = maxpwr;\n    }\n}\n\nstruct ieee80211_node * ItlIwn::\niwn_node_alloc(struct ieee80211com *ic)\n{\n    return (ieee80211_node *)malloc(sizeof (struct iwn_node), M_DEVBUF, M_NOWAIT | M_ZERO);\n}\n\nvoid ItlIwn::\niwn_newassoc(struct ieee80211com *ic, struct ieee80211_node *ni, int isnew)\n{\n    struct iwn_softc *sc = (struct iwn_softc *)ic->ic_if.if_softc;\n    struct iwn_node *wn = (struct iwn_node *)ni;\n    uint8_t rate;\n    int ridx, i;\n\n    if ((ni->ni_flags & IEEE80211_NODE_HT) == 0)\n        ieee80211_amrr_node_init(&sc->amrr, &wn->amn);\n\n    /* Start at lowest available bit-rate, AMRR/MiRA will raise. */\n    ni->ni_txrate = 0;\n    ni->ni_txmcs = 0;\n\n    for (i = 0; i < ni->ni_rates.rs_nrates; i++) {\n        rate = ni->ni_rates.rs_rates[i] & IEEE80211_RATE_VAL;\n        /* Map 802.11 rate to HW rate index. */\n        for (ridx = 0; ridx <= IWN_RIDX_MAX; ridx++) {\n            if (iwn_rates[ridx].plcp != IWN_RATE_INVM_PLCP &&\n                iwn_rates[ridx].rate == rate)\n                break;\n        }\n        wn->ridx[i] = ridx;\n    }\n}\n\nint ItlIwn::\niwn_media_change(struct _ifnet *ifp)\n{\n    struct iwn_softc *sc = (struct iwn_softc *)ifp->if_softc;\n    struct ieee80211com *ic = &sc->sc_ic;\n    uint8_t rate, ridx;\n    int error;\n\n    error = ieee80211_media_change(ifp);\n    if (error != ENETRESET)\n        return error;\n\n    if (ic->ic_fixed_mcs != -1)\n        sc->fixed_ridx = iwn_mcs2ridx[ic->ic_fixed_mcs];\n    if (ic->ic_fixed_rate != -1) {\n        rate = ic->ic_sup_rates[ic->ic_curmode].\n            rs_rates[ic->ic_fixed_rate] & IEEE80211_RATE_VAL;\n        /* Map 802.11 rate to HW rate index. */\n        for (ridx = 0; ridx <= IWN_RIDX_MAX; ridx++)\n            if (iwn_rates[ridx].plcp != IWN_RATE_INVM_PLCP &&\n                iwn_rates[ridx].rate == rate)\n                break;\n        sc->fixed_ridx = ridx;\n    }\n\n    if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==\n        (IFF_UP | IFF_RUNNING)) {\n        iwn_stop(ifp);\n        error = iwn_init(ifp);\n    }\n    return error;\n}\n\nint ItlIwn::\niwn_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)\n{\n    XYLog(\"%s nstate=%d\\n\", __FUNCTION__, nstate);\n    struct _ifnet *ifp = &ic->ic_if;\n    struct iwn_softc *sc = (struct iwn_softc *)ifp->if_softc;\n    struct ieee80211_node *ni = ic->ic_bss;\n    ItlIwn *that = container_of(sc, ItlIwn, com);\n    int error;\n\n    if (ic->ic_state == IEEE80211_S_RUN) {\n        if (nstate == IEEE80211_S_SCAN) {\n            /*\n             * During RUN->SCAN we don't call sc_newstate() so\n             * we must stop A-MPDU Tx ourselves in this case.\n             */\n            ieee80211_stop_ampdu_tx(ic, ni, -1);\n            ieee80211_ba_del(ni);\n        }\n        timeout_del(&sc->calib_to);\n        sc->calib.state = IWN_CALIB_STATE_INIT;\n        if (sc->sc_flags & IWN_FLAG_BGSCAN)\n            that->iwn_scan_abort(sc);\n    }\n\n    if (ic->ic_state == IEEE80211_S_SCAN) {\n        if (nstate == IEEE80211_S_SCAN) {\n            if (sc->sc_flags & IWN_FLAG_SCANNING)\n                return 0;\n        } else\n            sc->sc_flags &= ~IWN_FLAG_SCANNING;\n        /* Turn LED off when leaving scan state. */\n        that->iwn_set_led(sc, IWN_LED_LINK, 1, 0);\n    }\n\n    if (ic->ic_state >= IEEE80211_S_ASSOC &&\n        nstate <= IEEE80211_S_ASSOC) {\n        /* Reset state to handle re- and disassociations. */\n        sc->rxon.associd = 0;\n        sc->rxon.filter &= ~htole32(IWN_FILTER_BSS);\n        sc->rxon.flags &= ~htole32(IWN_RXON_HT_CHANMODE_MIXED2040 |\n                                   IWN_RXON_HT_CHANMODE_PURE40 | IWN_RXON_HT_HT40MINUS);\n        sc->calib.state = IWN_CALIB_STATE_INIT;\n        sc->agg_queue_mask = 0;\n        error = that->iwn_cmd(sc, IWN_CMD_RXON, &sc->rxon, sc->rxonsz, 1);\n        if (error != 0)\n            XYLog(\"%s: RXON command failed\\n\",\n                sc->sc_dev.dv_xname);\n    }\n\n    switch (nstate) {\n    case IEEE80211_S_SCAN:\n        /* Make the link LED blink while we're scanning. */\n        that->iwn_set_led(sc, IWN_LED_LINK, 10, 10);\n\n        if ((sc->sc_flags & IWN_FLAG_BGSCAN) == 0) {\n            ieee80211_set_link_state(ic, LINK_STATE_DOWN);\n            ieee80211_node_cleanup(ic, ic->ic_bss);\n        }\n        if (ifp->if_flags & IFF_DEBUG)\n            XYLog(\"%s: %s -> %s\\n\", ifp->if_xname,\n                ieee80211_state_name[ic->ic_state],\n                ieee80211_state_name[nstate]);\n        ic->ic_state = nstate;\n        if ((error = that->iwn_scan(sc, IEEE80211_CHAN_2GHZ, 0)) != 0) {\n            printf(\"%s: could not initiate scan\\n\",\n                sc->sc_dev.dv_xname);\n        }\n        return error;\n\n    case IEEE80211_S_ASSOC:\n        if (ic->ic_state != IEEE80211_S_RUN)\n            break;\n        /* FALLTHROUGH */\n    case IEEE80211_S_AUTH:\n        if ((error = that->iwn_auth(sc, arg)) != 0) {\n            XYLog(\"%s: could not move to auth state\\n\",\n                sc->sc_dev.dv_xname);\n            return error;\n        }\n        break;\n\n    case IEEE80211_S_RUN:\n        if ((error = that->iwn_run(sc)) != 0) {\n            XYLog(\"%s: could not move to run state\\n\",\n                sc->sc_dev.dv_xname);\n            return error;\n        }\n        break;\n\n    case IEEE80211_S_INIT:\n        sc->calib.state = IWN_CALIB_STATE_INIT;\n        break;\n    }\n\n    return sc->sc_newstate(ic, nstate, arg);\n}\n\nvoid ItlIwn::\niwn_iter_func(void *arg, struct ieee80211_node *ni)\n{\n    struct iwn_softc *sc = (struct iwn_softc*)arg;\n    struct iwn_node *wn = (struct iwn_node*)ni;\n    ItlIwn *that = container_of(sc, ItlIwn, com);\n\n    if ((ni->ni_flags & IEEE80211_NODE_HT) == 0) {\n        int old_txrate = ni->ni_txrate;\n        ieee80211_amrr_choose(&sc->amrr, ni, &wn->amn);\n        if (old_txrate != ni->ni_txrate)\n            that->iwn_set_link_quality(sc, ni);\n    }\n}\n\nvoid ItlIwn::\niwn_calib_timeout(void *arg)\n{\n    struct iwn_softc *sc = (struct iwn_softc *)arg;\n    struct ieee80211com *ic = &sc->sc_ic;\n    ItlIwn *that = container_of(sc, ItlIwn, com);\n    int s;\n\n    s = splnet();\n    if (ic->ic_fixed_rate == -1) {\n        if (ic->ic_opmode == IEEE80211_M_STA)\n            that->iwn_iter_func(sc, ic->ic_bss);\n        else\n            ieee80211_iterate_nodes(ic, iwn_iter_func, sc);\n    }\n    /* Force automatic TX power calibration every 60 secs. */\n    if (++sc->calib_cnt >= 120) {\n        uint32_t flags = 0;\n\n        DPRINTFN(2, (\"sending request for statistics\\n\"));\n        (void)that->iwn_cmd(sc, IWN_CMD_GET_STATISTICS, &flags,\n            sizeof flags, 1);\n        sc->calib_cnt = 0;\n    }\n    splx(s);\n\n    /* Automatic rate control triggered every 500ms. */\n    timeout_add_msec(&sc->calib_to, 500);\n}\n\nint ItlIwn::\niwn_ccmp_decap(struct iwn_softc *sc, mbuf_t m, struct ieee80211_node *ni)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct ieee80211_key *k = &ni->ni_pairwise_key;\n    struct ieee80211_frame *wh;\n    uint64_t pn, *prsc;\n    uint8_t *ivp;\n    uint8_t tid;\n    int hdrlen, hasqos;\n\n    wh = mtod(m, struct ieee80211_frame *);\n    hdrlen = ieee80211_get_hdrlen(wh);\n    ivp = (uint8_t *)wh + hdrlen;\n\n    /* Check that ExtIV bit is set. */\n    if (!(ivp[3] & IEEE80211_WEP_EXTIV)) {\n        DPRINTF((\"CCMP decap ExtIV not set\\n\"));\n        return 1;\n    }\n    hasqos = ieee80211_has_qos(wh);\n    tid = hasqos ? ieee80211_get_qos(wh) & IEEE80211_QOS_TID : 0;\n    prsc = &k->k_rsc[tid];\n\n    /* Extract the 48-bit PN from the CCMP header. */\n    pn = (uint64_t)ivp[0]       |\n         (uint64_t)ivp[1] <<  8 |\n         (uint64_t)ivp[4] << 16 |\n         (uint64_t)ivp[5] << 24 |\n         (uint64_t)ivp[6] << 32 |\n         (uint64_t)ivp[7] << 40;\n    if (pn <= *prsc) {\n        ic->ic_stats.is_ccmp_replays++;\n        return 1;\n    }\n    /* Last seen packet number is updated in ieee80211_inputm(). */\n\n    /* Strip MIC. IV will be stripped by ieee80211_inputm(). */\n    mbuf_adj(m, -IEEE80211_CCMP_MICLEN);\n    return 0;\n}\n\n/*\n * Process an RX_PHY firmware notification.  This is usually immediately\n * followed by an MPDU_RX_DONE notification.\n */\nvoid ItlIwn::\niwn_rx_phy(struct iwn_softc *sc, struct iwn_rx_desc *desc,\n    struct iwn_rx_data *data)\n{\n    struct iwn_rx_stat *stat = (struct iwn_rx_stat *)(desc + 1);\n\n    DPRINTFN(2, (\"received PHY stats\\n\"));\n    bus_dmamap_sync(sc->sc_dmat, data->map, sizeof (*desc),\n        sizeof (*stat), BUS_DMASYNC_POSTREAD);\n\n    /* Save RX statistics, they will be used on MPDU_RX_DONE. */\n    memcpy(&sc->last_rx_stat, stat, sizeof (*stat));\n    sc->last_rx_valid = IWN_LAST_RX_VALID;\n    /*\n     * The firmware does not send separate RX_PHY\n     * notifications for A-MPDU subframes.\n     */\n    if (stat->flags & htole16(IWN_STAT_FLAG_AGG))\n        sc->last_rx_valid |= IWN_LAST_RX_AMPDU;\n}\n\n/*\n * Process an RX_DONE (4965AGN only) or MPDU_RX_DONE firmware notification.\n * Each MPDU_RX_DONE notification must be preceded by an RX_PHY one.\n */\nvoid ItlIwn::\niwn_rx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc,\n    struct iwn_rx_data *data, struct mbuf_list *ml)\n{\n    struct iwn_ops *ops = &sc->ops;\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct _ifnet *ifp = &ic->ic_if;\n    struct iwn_rx_ring *ring = &sc->rxq;\n    struct ieee80211_frame *wh;\n    struct ieee80211_rxinfo rxi;\n    struct ieee80211_node *ni;\n    mbuf_t m, m1;\n    struct iwn_rx_stat *stat;\n    caddr_t head;\n    uint32_t flags;\n    int error, len, rssi;\n    uint16_t chan;\n\n    if (desc->type == IWN_MPDU_RX_DONE) {\n        /* Check for prior RX_PHY notification. */\n        if (!sc->last_rx_valid) {\n            DPRINTF((\"missing RX_PHY\\n\"));\n            return;\n        }\n        sc->last_rx_valid &= ~IWN_LAST_RX_VALID;\n        stat = &sc->last_rx_stat;\n        if ((sc->last_rx_valid & IWN_LAST_RX_AMPDU) &&\n            (stat->flags & htole16(IWN_STAT_FLAG_AGG)) == 0) {\n            DPRINTF((\"missing RX_PHY (expecting A-MPDU)\\n\"));\n            return;\n        }\n        if ((sc->last_rx_valid & IWN_LAST_RX_AMPDU) == 0 &&\n            (stat->flags & htole16(IWN_STAT_FLAG_AGG))) {\n            DPRINTF((\"missing RX_PHY (unexpected A-MPDU)\\n\"));\n            return;\n        }\n    } else\n        stat = (struct iwn_rx_stat *)(desc + 1);\n\n    bus_dmamap_sync(sc->sc_dmat, data->map, 0, IWN_RBUF_SIZE,\n        BUS_DMASYNC_POSTREAD);\n\n    if (stat->cfg_phy_len > IWN_STAT_MAXLEN) {\n        XYLog(\"%s: invalid RX statistic header\\n\",\n            sc->sc_dev.dv_xname);\n        return;\n    }\n    if (desc->type == IWN_MPDU_RX_DONE) {\n        struct iwn_rx_mpdu *mpdu = (struct iwn_rx_mpdu *)(desc + 1);\n        head = (caddr_t)(mpdu + 1);\n        len = letoh16(mpdu->len);\n    } else {\n        head = (caddr_t)(stat + 1) + stat->cfg_phy_len;\n        len = letoh16(stat->len);\n    }\n\n    flags = letoh32(*(uint32_t *)(head + len));\n\n    /* Discard frames with a bad FCS early. */\n    if ((flags & IWN_RX_NOERROR) != IWN_RX_NOERROR) {\n        DPRINTFN(2, (\"RX flags error %x\\n\", flags));\n        ifp->netStat->inputErrors++;\n        return;\n    }\n    /* Discard frames that are too short. */\n    if (ic->ic_opmode == IEEE80211_M_MONITOR) {\n        /* Allow control frames in monitor mode. */\n        if (len < sizeof (struct ieee80211_frame_cts)) {\n            ic->ic_stats.is_rx_tooshort++;\n            ifp->netStat->inputErrors++;\n            return;\n        }\n    } else if (len < sizeof (*wh)) {\n        ic->ic_stats.is_rx_tooshort++;\n        ifp->netStat->inputErrors++;\n        return;\n    }\n    \n    m1 = getController()->allocatePacket(IWN_RBUF_SIZE);\n    if (m1 == NULL) {\n        XYLog(\"could not allocate RX mbuf\\n\");\n        ic->ic_stats.is_rx_nombuf++;\n        ifp->netStat->inputErrors++;\n        return;\n    }\n    data->map->dm_nsegs = data->map->cursor->getPhysicalSegments(m1, &data->map->dm_segs[0], 1);\n    if (data->map->dm_nsegs == 0) {\n        XYLog(\"could not map RX mbuf\\n\");\n        mbuf_freem(m1);\n        ifp->netStat->inputErrors++;\n        return;\n    }\n    \n//    m1 = MCLGETI(NULL, M_DONTWAIT, NULL, IWN_RBUF_SIZE);\n//    if (m1 == NULL) {\n//        ic->ic_stats.is_rx_nombuf++;\n//        ifp->netStat->inputErrors++;\n//        return;\n//    }\n//    bus_dmamap_unload(sc->sc_dmat, data->map);\n//\n//    error = bus_dmamap_load(sc->sc_dmat, data->map, mtod(m1, void *),\n//        IWN_RBUF_SIZE, NULL, BUS_DMA_NOWAIT | BUS_DMA_READ);\n//    if (error != 0) {\n//        mbuf_freem(m1);\n//\n//        /* Try to reload the old mbuf. */\n//        error = bus_dmamap_load(sc->sc_dmat, data->map,\n//            mtod(data->m, void *), IWN_RBUF_SIZE, NULL,\n//            BUS_DMA_NOWAIT | BUS_DMA_READ);\n//        if (error != 0) {\n//            panic(\"%s: could not load old RX mbuf\",\n//                sc->sc_dev.dv_xname);\n//        }\n//        /* Physical address may have changed. */\n//        ring->desc[ring->cur] =\n//            htole32(data->map->dm_segs[0].ds_addr >> 8);\n//        bus_dmamap_sync(sc->sc_dmat, ring->desc_dma.map,\n//            ring->cur * sizeof (uint32_t), sizeof (uint32_t),\n//            BUS_DMASYNC_PREWRITE);\n//        ifp->netStat->inputErrors++;\n//        return;\n//    }\n\n    m = data->m;\n    data->m = m1;\n    /* Update RX descriptor. */\n    ring->desc[ring->cur] = htole32(data->map->dm_segs[0].location >> 8);\n//    bus_dmamap_sync(sc->sc_dmat, ring->desc_dma.map,\n//        ring->cur * sizeof (uint32_t), sizeof (uint32_t),\n//        BUS_DMASYNC_PREWRITE);\n\n    /* Finalize mbuf. */\n//    m->m_data = pktdata + sizeof(*desc);\n//    m->m_pkthdr.len = m->m_len = len;\n    mbuf_setdata(m, head, len);\n    mbuf_pkthdr_setlen(m, len);\n    mbuf_setlen(m, len);\n\n    /*\n     * Grab a reference to the source node. Note that control frames are\n     * shorter than struct ieee80211_frame but ieee80211_find_rxnode()\n     * is being careful about control frames.\n     */\n    wh = mtod(m, struct ieee80211_frame *);\n    if (len < sizeof (*wh) &&\n       (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_CTL) {\n        ic->ic_stats.is_rx_tooshort++;\n        ifp->netStat->inputErrors++;\n        mbuf_freem(m);\n        return;\n    }\n    ni = ieee80211_find_rxnode(ic, wh);\n\n    memset(&rxi, 0, sizeof(rxi));\n    if (((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_CTL)\n        && (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) &&\n        !IEEE80211_IS_MULTICAST(wh->i_addr1) &&\n        (ni->ni_flags & IEEE80211_NODE_RXPROT) &&\n        ni->ni_pairwise_key.k_cipher == IEEE80211_CIPHER_CCMP) {\n        if ((flags & IWN_RX_CIPHER_MASK) != IWN_RX_CIPHER_CCMP) {\n            ic->ic_stats.is_ccmp_dec_errs++;\n            ifp->netStat->inputErrors++;\n            mbuf_freem(m);\n            ieee80211_release_node(ic, ni);\n            return;\n        }\n        /* Check whether decryption was successful or not. */\n        if ((desc->type == IWN_MPDU_RX_DONE &&\n             (flags & (IWN_RX_MPDU_DEC | IWN_RX_MPDU_MIC_OK)) !=\n              (IWN_RX_MPDU_DEC | IWN_RX_MPDU_MIC_OK)) ||\n            (desc->type != IWN_MPDU_RX_DONE &&\n             (flags & IWN_RX_DECRYPT_MASK) != IWN_RX_DECRYPT_OK)) {\n            DPRINTF((\"CCMP decryption failed 0x%x\\n\", flags));\n            ic->ic_stats.is_ccmp_dec_errs++;\n            ifp->netStat->inputErrors++;\n            mbuf_freem(m);\n            ieee80211_release_node(ic, ni);\n            return;\n        }\n        if (iwn_ccmp_decap(sc, m, ni) != 0) {\n            ifp->netStat->inputErrors++;\n            mbuf_freem(m);\n            ieee80211_release_node(ic, ni);\n            return;\n        }\n        rxi.rxi_flags |= IEEE80211_RXI_HWDEC;\n    }\n\n    rssi = ops->get_rssi(stat);\n    rssi = (0 - IWN_MIN_DBM) + rssi;    /* normalize */\n    rssi = MIN(rssi, ic->ic_max_rssi);    /* clip to max. 100% */\n\n    chan = stat->chan;\n    if (chan > IEEE80211_CHAN_MAX)\n        chan = IEEE80211_CHAN_MAX;\n\n#if NBPFILTER > 0\n    if (sc->sc_drvbpf != NULL) {\n        struct iwn_rx_radiotap_header *tap = &sc->sc_rxtap;\n        uint16_t chan_flags;\n\n        tap->wr_flags = 0;\n        if (stat->flags & htole16(IWN_STAT_FLAG_SHPREAMBLE))\n            tap->wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;\n        tap->wr_chan_freq = htole16(ic->ic_channels[chan].ic_freq);\n        chan_flags = ic->ic_channels[chan].ic_flags;\n        if (ic->ic_curmode != IEEE80211_MODE_11N)\n            chan_flags &= ~IEEE80211_CHAN_HT;\n        tap->wr_chan_flags = htole16(chan_flags);\n        tap->wr_dbm_antsignal = (int8_t)rssi;\n        tap->wr_dbm_antnoise = (int8_t)sc->noise;\n        tap->wr_tsft = stat->tstamp;\n        if (stat->rflags & IWN_RFLAG_MCS) {\n            tap->wr_rate = (0x80 | stat->rate); /* HT MCS index */\n        } else {\n            switch (stat->rate) {\n            /* CCK rates. */\n            case  10: tap->wr_rate =   2; break;\n            case  20: tap->wr_rate =   4; break;\n            case  55: tap->wr_rate =  11; break;\n            case 110: tap->wr_rate =  22; break;\n            /* OFDM rates. */\n            case 0xd: tap->wr_rate =  12; break;\n            case 0xf: tap->wr_rate =  18; break;\n            case 0x5: tap->wr_rate =  24; break;\n            case 0x7: tap->wr_rate =  36; break;\n            case 0x9: tap->wr_rate =  48; break;\n            case 0xb: tap->wr_rate =  72; break;\n            case 0x1: tap->wr_rate =  96; break;\n            case 0x3: tap->wr_rate = 108; break;\n            /* Unknown rate: should not happen. */\n            default:  tap->wr_rate =  0;\n            }\n        }\n\n        bpf_mtap_hdr(sc->sc_drvbpf, tap, sc->sc_rxtap_len,\n            m, BPF_DIRECTION_IN);\n    }\n#endif\n\n    /* Send the frame to the 802.11 layer. */\n    rxi.rxi_rssi = rssi;\n    rxi.rxi_chan = chan;\n    ieee80211_inputm(ifp, m, ni, &rxi, ml);\n\n    /* Node is no longer needed. */\n    ieee80211_release_node(ic, ni);\n}\n\nvoid ItlIwn::\niwn_ra_choose(struct iwn_softc *sc, struct ieee80211_node *ni)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct iwn_node *wn = (struct iwn_node *)ni;\n    int old_txmcs = ni->ni_txmcs;\n\n    ieee80211_ra_choose(&wn->rn, ic, ni);\n\n    /* Update firmware's LQ retry table if RA has chosen a new MCS. */\n    if (ni->ni_txmcs != old_txmcs)\n        iwn_set_link_quality(sc, ni);\n}\n\nvoid ItlIwn::\niwn_ampdu_rate_control(struct iwn_softc *sc, struct ieee80211_node *ni,\n    struct iwn_tx_ring *txq, uint16_t seq, uint16_t ssn)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct iwn_node *wn = (struct iwn_node *)ni;\n    int idx, end_idx;\n\n    /*\n     * Update Tx rate statistics for A-MPDUs before firmware's BA window.\n     */\n    idx = IWN_AGG_SSN_TO_TXQ_IDX(seq);\n    end_idx = IWN_AGG_SSN_TO_TXQ_IDX(ssn);\n    while (idx != end_idx) {\n        struct iwn_tx_data *txdata = &txq->data[idx];\n        if (txdata->m != NULL && txdata->ampdu_nframes > 1) {\n            /*\n             * We can assume that this subframe has been ACKed\n             * because ACK failures come as single frames and\n             * before failing an A-MPDU subframe the firmware\n             * sends it as a single frame at least once.\n             */\n            ieee80211_ra_add_stats_ht(&wn->rn, ic, ni,\n                                      txdata->ampdu_txmcs, 1, 0);\n            \n            /* Report this frame only once. */\n            txdata->ampdu_nframes = 0;\n        }\n        \n        idx = (idx + 1) % IWN_TX_RING_COUNT;\n    }\n    \n    iwn_ra_choose(sc, ni);\n}\n\nvoid ItlIwn::\niwn_ht_single_rate_control(struct iwn_softc *sc, struct ieee80211_node *ni,\n    uint8_t rate, uint8_t rflags, uint8_t ackfailcnt, int txfail)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct iwn_node *wn = (struct iwn_node *)ni;\n    int mcs = rate;\n    const struct ieee80211_ra_rate *rs;\n    unsigned int retries = 0, i;\n    \n    /*\n     * Ignore Tx reports which don't match our last LQ command.\n     */\n    if (rate != ni->ni_txmcs) {\n        if (++wn->lq_rate_mismatch > 15) {\n            /* Try to sync firmware with driver. */\n            iwn_set_link_quality(sc, ni);\n            wn->lq_rate_mismatch = 0;\n        }\n        return;\n    }\n    \n    wn->lq_rate_mismatch = 0;\n    \n    rs = ieee80211_ra_get_rateset(&wn->rn, ic, ni, rate);\n    /*\n     * Firmware has attempted rates in this rate set in sequence.\n     * Retries at a basic rate are counted against the minimum MCS.\n     */\n    for (i = 0; i < ackfailcnt; i++) {\n        if (mcs > rs->min_mcs) {\n            ieee80211_ra_add_stats_ht(&wn->rn, ic, ni, mcs, 1, 1);\n            mcs--;\n        } else\n            retries++;\n    }\n    \n    if (txfail && ackfailcnt == 0)\n        ieee80211_ra_add_stats_ht(&wn->rn, ic, ni, mcs, 1, 1);\n    else\n        ieee80211_ra_add_stats_ht(&wn->rn, ic, ni, mcs, retries + 1, retries);\n    \n    iwn_ra_choose(sc, ni);\n}\n\n/*\n * Process an incoming Compressed BlockAck.\n * Note that these block ack notifications are generated by firmware and do\n * not necessarily correspond to contents of block ack frames seen on the air.\n */\nvoid ItlIwn::\niwn_rx_compressed_ba(struct iwn_softc *sc, struct iwn_rx_desc *desc,\n    struct iwn_rx_data *data)\n{\n    struct iwn_compressed_ba *cba = (struct iwn_compressed_ba *)(desc + 1);\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct ieee80211_node *ni;\n    struct ieee80211_tx_ba *ba;\n    struct iwn_tx_ring *txq;\n    uint16_t seq, ssn;\n    int qid;\n\n    if (ic->ic_state != IEEE80211_S_RUN)\n        return;\n\n    bus_dmamap_sync(sc->sc_dmat, data->map, sizeof (*desc), sizeof (*cba),\n        BUS_DMASYNC_POSTREAD);\n\n    if (!IEEE80211_ADDR_EQ(ic->ic_bss->ni_macaddr, cba->macaddr))\n        return;\n\n    ni = ic->ic_bss;\n\n    qid = le16toh(cba->qid);\n    if (qid < sc->first_agg_txq || qid >= sc->ntxqs)\n        return;\n\n    txq = &sc->txq[qid];\n\n    /* Protect against a firmware bug where the queue/TID are off. */\n    if (qid != sc->first_agg_txq + cba->tid)\n        return;\n\n    ba = &ni->ni_tx_ba[cba->tid];\n    if (ba->ba_state != IEEE80211_BA_AGREED)\n        return;\n\n    /*\n     * The first bit in cba->bitmap corresponds to the sequence number\n     * stored in the sequence control field cba->seq.\n     * Multiple BA notifications in a row may be using this number, with\n     * additional bits being set in cba->bitmap. It is unclear how the\n     * firmware decides to shift this window forward.\n     * We rely on ba->ba_winstart instead.\n     */\n    seq = le16toh(cba->seq) >> IEEE80211_SEQ_SEQ_SHIFT;\n\n    /*\n     * The firmware's new BA window starting sequence number\n     * corresponds to the first hole in cba->bitmap, implying\n     * that all frames between 'seq' and 'ssn' (non-inclusive)\n     * have been acked.\n     */\n    ssn = le16toh(cba->ssn);\n    \n    if (SEQ_LT(ssn, ba->ba_winstart))\n        return;\n\n    /* Skip rate control if our Tx rate is fixed. */\n    if (ic->ic_fixed_mcs == -1)\n        iwn_ampdu_rate_control(sc, ni, txq, ba->ba_winstart, ssn);\n\n    /*\n     * SSN corresponds to the first (perhaps not yet transmitted) frame\n     * in firmware's BA window. Firmware is not going to retransmit any\n     * frames before its BA window so mark them all as done.\n     */\n    ieee80211_output_ba_move_window(ic, ni, cba->tid, ssn);\n    iwn_ampdu_txq_advance(sc, txq, qid,\n                          IWN_AGG_SSN_TO_TXQ_IDX(ssn));\n    iwn_clear_oactive(sc, txq);\n}\n\n/*\n * Process a CALIBRATION_RESULT notification sent by the initialization\n * firmware on response to a CMD_CALIB_CONFIG command (5000 only).\n */\nvoid ItlIwn::\niwn5000_rx_calib_results(struct iwn_softc *sc, struct iwn_rx_desc *desc,\n    struct iwn_rx_data *data)\n{\n    struct iwn_phy_calib *calib = (struct iwn_phy_calib *)(desc + 1);\n    int len, idx = -1;\n\n    /* Runtime firmware should not send such a notification. */\n    if (sc->sc_flags & IWN_FLAG_CALIB_DONE)\n        return;\n\n    len = (letoh32(desc->len) & IWN_RX_DESC_LEN_MASK) - 4;\n    bus_dmamap_sync(sc->sc_dmat, data->map, sizeof (*desc), len,\n        BUS_DMASYNC_POSTREAD);\n\n    switch (calib->code) {\n    case IWN5000_PHY_CALIB_DC:\n        if (sc->hw_type == IWN_HW_REV_TYPE_5150 ||\n            sc->hw_type == IWN_HW_REV_TYPE_2030 ||\n            sc->hw_type == IWN_HW_REV_TYPE_2000 ||\n            sc->hw_type == IWN_HW_REV_TYPE_135 ||\n            sc->hw_type == IWN_HW_REV_TYPE_105)\n            idx = 0;\n        break;\n    case IWN5000_PHY_CALIB_LO:\n        idx = 1;\n        break;\n    case IWN5000_PHY_CALIB_TX_IQ:\n        idx = 2;\n        break;\n    case IWN5000_PHY_CALIB_TX_IQ_PERIODIC:\n        if (sc->hw_type < IWN_HW_REV_TYPE_6000 &&\n            sc->hw_type != IWN_HW_REV_TYPE_5150)\n            idx = 3;\n        break;\n    case IWN5000_PHY_CALIB_BASE_BAND:\n        idx = 4;\n        break;\n    }\n    if (idx == -1)    /* Ignore other results. */\n        return;\n\n    /* Save calibration result. */\n    if (sc->calibcmd[idx].buf != NULL)\n        ::free(sc->calibcmd[idx].buf);\n    sc->calibcmd[idx].buf = (uint8_t *)malloc(len, M_DEVBUF, M_NOWAIT);\n    if (sc->calibcmd[idx].buf == NULL) {\n        DPRINTF((\"not enough memory for calibration result %d\\n\",\n            calib->code));\n        return;\n    }\n    DPRINTF((\"saving calibration result code=%d len=%d\\n\",\n        calib->code, len));\n    sc->calibcmd[idx].len = len;\n    memcpy(sc->calibcmd[idx].buf, calib, len);\n}\n\n/*\n * Process an RX_STATISTICS or BEACON_STATISTICS firmware notification.\n * The latter is sent by the firmware after each received beacon.\n */\nvoid ItlIwn::\niwn_rx_statistics(struct iwn_softc *sc, struct iwn_rx_desc *desc,\n    struct iwn_rx_data *data)\n{\n    struct iwn_ops *ops = &sc->ops;\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct iwn_calib_state *calib = &sc->calib;\n    struct iwn_stats *stats = (struct iwn_stats *)(desc + 1);\n    int temp;\n\n    /* Ignore statistics received during a scan. */\n    if (ic->ic_state != IEEE80211_S_RUN)\n        return;\n\n    bus_dmamap_sync(sc->sc_dmat, data->map, sizeof (*desc),\n        sizeof (*stats), BUS_DMASYNC_POSTREAD);\n\n    DPRINTFN(3, (\"received statistics (cmd=%d)\\n\", desc->type));\n    sc->calib_cnt = 0;    /* Reset TX power calibration timeout. */\n    \n    sc->rx_stats_flags = htole32(stats->flags);\n\n    /* Test if temperature has changed. */\n    if (stats->general.temp != sc->rawtemp) {\n        /* Convert \"raw\" temperature to degC. */\n        sc->rawtemp = stats->general.temp;\n        temp = ops->get_temperature(sc);\n        DPRINTFN(2, (\"temperature=%dC\\n\", temp));\n\n        /* Update TX power if need be (4965AGN only). */\n        if (sc->hw_type == IWN_HW_REV_TYPE_4965)\n            iwn4965_power_calibration(sc, temp);\n    }\n\n    if (desc->type != IWN_BEACON_STATISTICS)\n        return;    /* Reply to a statistics request. */\n\n    sc->noise = iwn_get_noise(&stats->rx.general);\n\n    /* Test that RSSI and noise are present in stats report. */\n    if (sc->noise == -127)\n        return;\n\n    if (letoh32(stats->rx.general.flags) != 1) {\n        DPRINTF((\"received statistics without RSSI\\n\"));\n        return;\n    }\n\n    /*\n     * XXX Differential gain calibration makes the 6005 firmware\n     * crap out, so skip it for now.  This effectively disables\n     * sensitivity tuning as well.\n     */\n    if (sc->hw_type == IWN_HW_REV_TYPE_6005)\n        return;\n\n    if (calib->state == IWN_CALIB_STATE_ASSOC)\n        iwn_collect_noise(sc, &stats->rx.general);\n    else if (calib->state == IWN_CALIB_STATE_RUN)\n        iwn_tune_sensitivity(sc, &stats->rx);\n}\n\nvoid ItlIwn::\niwn_ampdu_txq_advance(struct iwn_softc *sc, struct iwn_tx_ring *txq, int qid,\n    int idx)\n{\n    struct iwn_ops *ops = &sc->ops;\n\n    DPRINTFN(3, (\"%s: txq->cur=%d txq->read=%d txq->queued=%d qid=%d \"\n        \"idx=%d\\n\", __func__, txq->cur, txq->read, txq->queued, qid, idx));\n\n    while (txq->read != idx) {\n        struct iwn_tx_data *txdata = &txq->data[txq->read];\n        if (txdata->m != NULL) {\n            ops->reset_sched(sc, qid, txq->read);\n            iwn_tx_done_free_txdata(sc, txdata);\n            txq->queued--;\n        }\n        txq->read = (txq->read + 1) % IWN_TX_RING_COUNT;\n    }\n}\n\n/*\n * Handle A-MPDU Tx queue status report.\n * Tx failures come as single frames (perhaps out of order), and before failing\n * an A-MPDU subframe the firmware transmits it as a single frame at least once.\n * Frames successfully transmitted in an A-MPDU are completed when a compressed\n * block ack notification is received.\n */\nvoid ItlIwn::\niwn_ampdu_tx_done(struct iwn_softc *sc, struct iwn_tx_ring *txq,\n    struct iwn_rx_desc *desc, uint16_t status, uint8_t ackfailcnt,\n    uint8_t rate, uint8_t rflags, int nframes, uint32_t ssn,\n    struct iwn_txagg_status *agg_status)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct _ifnet *ifp = &ic->ic_if;\n    int tid = desc->qid - sc->first_agg_txq;\n    struct iwn_tx_data *txdata = &txq->data[desc->idx];\n    struct ieee80211_node *ni = txdata->ni;\n    int txfail = (status != IWN_TX_STATUS_SUCCESS &&\n        status != IWN_TX_STATUS_DIRECT_DONE);\n    struct ieee80211_tx_ba *ba;\n    uint16_t seq;\n\n    sc->sc_tx_timer = 0;\n\n    if (ic->ic_state != IEEE80211_S_RUN)\n        return;\n\n    if (nframes > 1) {\n        int i;\n        \n        /*\n         * Collect information about this A-MPDU.\n         */\n        for (i = 0; i < nframes; i++) {\n            uint8_t qid = agg_status[i].qid;\n            uint8_t idx = agg_status[i].idx;\n            uint16_t txstatus = (le16toh(agg_status[i].status) &\n                                 IWN_AGG_TX_STATUS_MASK);\n            \n            if (txstatus != IWN_AGG_TX_STATE_TRANSMITTED)\n                continue;\n            \n            if (qid != desc->qid)\n                continue;\n            \n            txdata = &txq->data[idx];\n            if (txdata->ni == NULL)\n                continue;\n            \n            /* The Tx rate was the same for all subframes. */\n            txdata->ampdu_txmcs = rate;\n            txdata->ampdu_nframes = nframes;\n        }\n        return;\n    }\n\n    if (ni == NULL)\n        return;\n\n    ba = &ni->ni_tx_ba[tid];\n    if (ba->ba_state != IEEE80211_BA_AGREED)\n        return;\n    if (SEQ_LT(ssn, ba->ba_winstart))\n        return;\n\n    /* This was a final single-frame Tx attempt for frame SSN-1. */\n    seq = (ssn - 1) & 0xfff;\n\n    /*\n     * Skip rate control if our Tx rate is fixed.\n     */\n    if (ic->ic_fixed_mcs == -1) {\n        if (txdata->ampdu_nframes > 1) {\n            struct iwn_node *wn = (struct iwn_node *)ni;\n            /*\n             * This frame was once part of an A-MPDU.\n             * Report one failed A-MPDU Tx attempt.\n             * The firmware might have made several such\n             * attempts but we don't keep track of this.\n             */\n            ieee80211_ra_add_stats_ht(&wn->rn, ic, ni,\n                                      txdata->ampdu_txmcs, 1, 1);\n        }\n        \n        /* Report the final single-frame Tx attempt. */\n        if (rflags & IWN_RFLAG_MCS)\n            iwn_ht_single_rate_control(sc, ni, rate, rflags,\n                                       ackfailcnt, txfail);\n    }\n\n    if (txfail)\n        ieee80211_tx_compressed_bar(ic, ni, tid, ssn);\n\n    /*\n     * SSN corresponds to the first (perhaps not yet transmitted) frame\n     * in firmware's BA window. Firmware is not going to retransmit any\n     * frames before its BA window so mark them all as done.\n     */\n    ieee80211_output_ba_move_window(ic, ni, tid, ssn);\n    iwn_ampdu_txq_advance(sc, txq, desc->qid, IWN_AGG_SSN_TO_TXQ_IDX(ssn));\n    iwn_clear_oactive(sc, txq);\n}\n\n/*\n * Process a TX_DONE firmware notification.  Unfortunately, the 4965AGN\n * and 5000 adapters have different incompatible TX status formats.\n */\nvoid ItlIwn::\niwn4965_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc,\n    struct iwn_rx_data *data)\n{\n    ItlIwn *that = container_of(sc, ItlIwn, com);\n    struct iwn4965_tx_stat *stat = (struct iwn4965_tx_stat *)(desc + 1);\n    struct iwn_tx_ring *ring;\n    size_t len = (letoh32(desc->len) & IWN_RX_DESC_LEN_MASK);\n    uint16_t status = letoh32(stat->stat.status) & 0xff;\n    uint32_t ssn;\n\n    if (desc->qid > IWN4965_NTXQUEUES)\n        return;\n\n    ring = &sc->txq[desc->qid];\n\n    bus_dmamap_sync(sc->sc_dmat, data->map, sizeof (*desc),\n        len, BUS_DMASYNC_POSTREAD);\n\n    /* Sanity checks. */\n    if (sizeof(*stat) > len)\n        return;\n    if (stat->nframes < 1 || stat->nframes > IWN_AMPDU_MAX)\n        return;\n    if (desc->qid < sc->first_agg_txq && stat->nframes > 1)\n        return;\n    if (desc->qid >= sc->first_agg_txq && sizeof(*stat) + sizeof(ssn) +\n        stat->nframes * sizeof(stat->stat) > len)\n        return;\n\n    if (desc->qid < sc->first_agg_txq) {\n        /* XXX 4965 does not report byte count */\n        struct iwn_tx_data *txdata = &ring->data[desc->idx];\n        uint16_t framelen = txdata->totlen + IEEE80211_CRC_LEN;\n        int txfail = (status != IWN_TX_STATUS_SUCCESS &&\n                      status != IWN_TX_STATUS_DIRECT_DONE);\n\n        that->iwn_tx_done(sc, desc, stat->ackfailcnt, stat->rate,\n                          stat->rflags, txfail, desc->qid, framelen);\n    } else {\n        memcpy(&ssn, &stat->stat.status + stat->nframes, sizeof(ssn));\n        ssn = le32toh(ssn) & 0xfff;\n        that->iwn_ampdu_tx_done(sc, ring, desc, status, stat->ackfailcnt,\n            stat->rate, stat->rflags, stat->nframes, ssn,\n            stat->stat.agg_status);\n    }\n}\n\nvoid ItlIwn::\niwn5000_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc,\n    struct iwn_rx_data *data)\n{\n    ItlIwn *that = container_of(sc, ItlIwn, com);\n    struct iwn5000_tx_stat *stat = (struct iwn5000_tx_stat *)(desc + 1);\n    struct iwn_tx_ring *ring;\n    size_t len = (letoh32(desc->len) & IWN_RX_DESC_LEN_MASK);\n    uint16_t status = letoh32(stat->stat.status) & 0xff;\n    uint32_t ssn;\n\n    if (desc->qid > IWN5000_NTXQUEUES)\n        return;\n\n    ring = &sc->txq[desc->qid];\n\n    bus_dmamap_sync(sc->sc_dmat, data->map, sizeof (*desc),\n        sizeof (*stat), BUS_DMASYNC_POSTREAD);\n\n    /* Sanity checks. */\n    if (sizeof(*stat) > len)\n        return;\n    if (stat->nframes < 1 || stat->nframes > IWN_AMPDU_MAX)\n        return;\n    if (desc->qid < sc->first_agg_txq && stat->nframes > 1)\n        return;\n    if (desc->qid >= sc->first_agg_txq && sizeof(*stat) + sizeof(ssn) +\n        stat->nframes * sizeof(stat->stat) > len)\n        return;\n\n    /* If this was not an aggregated frame, complete it now. */\n    if (desc->qid < sc->first_agg_txq) {\n        int txfail = (status != IWN_TX_STATUS_SUCCESS &&\n                      status != IWN_TX_STATUS_DIRECT_DONE);\n        /* Reset TX scheduler slot. */\n        iwn5000_reset_sched(sc, desc->qid, desc->idx);\n\n        that->iwn_tx_done(sc, desc, stat->ackfailcnt, stat->rate,\n                          stat->rflags, txfail, desc->qid, letoh16(stat->len));\n    } else {\n        memcpy(&ssn, &stat->stat.status + stat->nframes, sizeof(ssn));\n        ssn = le32toh(ssn) & 0xfff;\n        that->iwn_ampdu_tx_done(sc, ring, desc, status, stat->ackfailcnt,\n            stat->rate, stat->rflags, stat->nframes, ssn,\n            stat->stat.agg_status);\n    }\n}\n\nvoid ItlIwn::\niwn_tx_done_free_txdata(struct iwn_softc *sc, struct iwn_tx_data *data)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n\n//    bus_dmamap_sync(sc->sc_dmat, data->map, 0, data->map->dm_mapsize,\n//        BUS_DMASYNC_POSTWRITE);\n//    bus_dmamap_unload(sc->sc_dmat, data->map);\n    mbuf_freem(data->m);\n    data->m = NULL;\n    ieee80211_release_node(ic, data->ni);\n    data->ni = NULL;\n    data->totlen = 0;\n    data->ampdu_nframes = 0;\n    data->ampdu_txmcs = 0;\n}\n\nvoid ItlIwn::\niwn_clear_oactive(struct iwn_softc *sc, struct iwn_tx_ring *ring)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct _ifnet *ifp = &ic->ic_if;\n\n    if (ring->queued < IWN_TX_RING_LOMARK) {\n        sc->qfullmsk &= ~(1 << ring->qid);\n        if (sc->qfullmsk == 0 && ifq_is_oactive(&ifp->if_snd)) {\n            ifq_clr_oactive(&ifp->if_snd);\n            (*ifp->if_start)(ifp);\n        }\n#ifdef __PRIVATE_SPI__\n        ifp->iface->signalOutputThread();\n#endif\n    }\n}\n\n/*\n * Adapter-independent backend for TX_DONE firmware notifications.\n * This handles Tx status for non-aggregation queues.\n */\nvoid ItlIwn::\niwn_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc,\n    uint8_t ackfailcnt, uint8_t rate, uint8_t rflags, int txfail,\n    int qid, uint16_t len)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct _ifnet *ifp = &ic->ic_if;\n    struct iwn_tx_ring *ring = &sc->txq[qid];\n    struct iwn_tx_data *data = &ring->data[desc->idx];\n    struct iwn_node *wn = (struct iwn_node *)data->ni;\n\n    if (data->ni == NULL)\n        return;\n\n    if (data->ni->ni_flags & IEEE80211_NODE_HT) {\n        if (ic->ic_state == IEEE80211_S_RUN &&\n            ic->ic_fixed_mcs == -1 && (rflags & IWN_RFLAG_MCS)) {\n            iwn_ht_single_rate_control(sc, data->ni, rate, rflags,\n                                       ackfailcnt, txfail);\n        }\n    } else {\n        if (rate != data->ni->ni_txrate) {\n            if (++wn->lq_rate_mismatch > 15) {\n                /* Try to sync firmware with driver. */\n                iwn_set_link_quality(sc, data->ni);\n                wn->lq_rate_mismatch = 0;\n            }\n        } else {\n            wn->lq_rate_mismatch = 0;\n            \n            wn->amn.amn_txcnt++;\n            if (ackfailcnt > 0)\n                wn->amn.amn_retrycnt++;\n            if (txfail)\n                wn->amn.amn_retrycnt++;\n        }\n    }\n    if (txfail) {\n        ifp->netStat->outputErrors++;\n    }\n\n    iwn_tx_done_free_txdata(sc, data);\n\n    sc->sc_tx_timer = 0;\n    ring->queued--;\n    iwn_clear_oactive(sc, ring);\n}\n\n/*\n * Process a \"command done\" firmware notification.  This is where we wakeup\n * processes waiting for a synchronous command completion.\n */\nvoid ItlIwn::\niwn_cmd_done(struct iwn_softc *sc, struct iwn_rx_desc *desc)\n{\n    struct iwn_tx_ring *ring = &sc->txq[4];\n    struct iwn_tx_data *data;\n\n    if ((desc->qid & 0xf) != 4)\n        return;    /* Not a command ack. */\n\n    data = &ring->data[desc->idx];\n\n    /* If the command was mapped in an mbuf, free it. */\n    if (data->m != NULL) {\n//        bus_dmamap_sync(sc->sc_dmat, data->map, 0,\n//            data->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);\n//        bus_dmamap_unload(sc->sc_dmat, data->map);\n        mbuf_freem(data->m);\n        data->m = NULL;\n    }\n    wakeupOn(&ring->desc[desc->idx]);\n}\n\n/*\n * Process an INT_FH_RX or INT_SW_RX interrupt.\n */\nvoid ItlIwn::\niwn_notif_intr(struct iwn_softc *sc)\n{\n    struct mbuf_list ml = MBUF_LIST_INITIALIZER();\n    struct iwn_ops *ops = &sc->ops;\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct _ifnet *ifp = &ic->ic_if;\n    uint16_t hw;\n\n//    bus_dmamap_sync(sc->sc_dmat, sc->rxq.stat_dma.map,\n//        0, sc->rxq.stat_dma.size, BUS_DMASYNC_POSTREAD);\n\n    hw = letoh16(sc->rxq.stat->closed_count) & 0xfff;\n    while (sc->rxq.cur != hw) {\n        struct iwn_rx_data *data = &sc->rxq.data[sc->rxq.cur];\n        struct iwn_rx_desc *desc;\n\n        bus_dmamap_sync(sc->sc_dmat, data->map, 0, sizeof (*desc),\n            BUS_DMASYNC_POSTREAD);\n        desc = mtod(data->m, struct iwn_rx_desc *);\n\n        DPRINTFN(4, (\"notification qid=%d idx=%d flags=%x type=%d\\n\",\n            desc->qid & 0xf, desc->idx, desc->flags, desc->type));\n\n        if (!(desc->qid & 0x80))    /* Reply to a command. */\n            iwn_cmd_done(sc, desc);\n\n        switch (desc->type) {\n        case IWN_RX_PHY:\n            iwn_rx_phy(sc, desc, data);\n            break;\n\n        case IWN_RX_DONE:        /* 4965AGN only. */\n        case IWN_MPDU_RX_DONE:\n            /* An 802.11 frame has been received. */\n            iwn_rx_done(sc, desc, data, &ml);\n            break;\n        case IWN_RX_COMPRESSED_BA:\n            /* A Compressed BlockAck has been received. */\n            iwn_rx_compressed_ba(sc, desc, data);\n            break;\n        case IWN_TX_DONE:\n            /* An 802.11 frame has been transmitted. */\n            ops->tx_done(sc, desc, data);\n            break;\n\n        case IWN_RX_STATISTICS:\n        case IWN_BEACON_STATISTICS:\n            iwn_rx_statistics(sc, desc, data);\n            break;\n\n        case IWN_BEACON_MISSED:\n        {\n            struct iwn_beacon_missed *miss =\n                (struct iwn_beacon_missed *)(desc + 1);\n            uint32_t missed;\n\n            if ((ic->ic_opmode != IEEE80211_M_STA) ||\n                (ic->ic_state != IEEE80211_S_RUN))\n                break;\n\n            bus_dmamap_sync(sc->sc_dmat, data->map, sizeof (*desc),\n                sizeof (*miss), BUS_DMASYNC_POSTREAD);\n            missed = letoh32(miss->consecutive);\n\n            /*\n             * If more than 5 consecutive beacons are missed,\n             * reinitialize the sensitivity state machine.\n             */\n            if (missed > 5)\n                (void)iwn_init_sensitivity(sc);\n\n            /*\n             * Rather than go directly to scan state, try to send a\n             * directed probe request first. If that fails then the\n             * state machine will drop us into scanning after timing\n             * out waiting for a probe response.\n             */\n            if (missed > ic->ic_bmissthres && !ic->ic_mgt_timer) {\n                if (ic->ic_if.if_flags & IFF_DEBUG)\n                    XYLog(\"%s: receiving no beacons from \"\n                        \"%s; checking if this AP is still \"\n                        \"responding to probe requests\\n\",\n                        sc->sc_dev.dv_xname, ether_sprintf(\n                        ic->ic_bss->ni_macaddr));\n                IEEE80211_SEND_MGMT(ic, ic->ic_bss,\n                    IEEE80211_FC0_SUBTYPE_PROBE_REQ, 0);\n            }\n            break;\n        }\n        case IWN_UC_READY:\n        {\n            struct iwn_ucode_info *uc =\n                (struct iwn_ucode_info *)(desc + 1);\n\n            /* The microcontroller is ready. */\n            bus_dmamap_sync(sc->sc_dmat, data->map, sizeof (*desc),\n                sizeof (*uc), BUS_DMASYNC_POSTREAD);\n            DPRINTF((\"microcode alive notification version=%d.%d \"\n                \"subtype=%x alive=%x\\n\", uc->major, uc->minor,\n                uc->subtype, letoh32(uc->valid)));\n\n            if (letoh32(uc->valid) != 1) {\n                XYLog(\"%s: microcontroller initialization \"\n                    \"failed\\n\", sc->sc_dev.dv_xname);\n                break;\n            }\n            if (uc->subtype == IWN_UCODE_INIT) {\n                /* Save microcontroller report. */\n                memcpy(&sc->ucode_info, uc, sizeof (*uc));\n            }\n            /* Save the address of the error log in SRAM. */\n            sc->errptr = letoh32(uc->errptr);\n            break;\n        }\n        case IWN_STATE_CHANGED:\n        {\n            uint32_t *status = (uint32_t *)(desc + 1);\n\n            /* Enabled/disabled notification. */\n            bus_dmamap_sync(sc->sc_dmat, data->map, sizeof (*desc),\n                sizeof (*status), BUS_DMASYNC_POSTREAD);\n            DPRINTF((\"state changed to %x\\n\", letoh32(*status)));\n\n            if (letoh32(*status) & 1) {\n                /* Radio transmitter is off, power down. */\n                iwn_stop(ifp);\n                return;    /* No further processing. */\n            }\n            break;\n        }\n        case IWN_START_SCAN:\n        {\n            struct iwn_start_scan *scan =\n                (struct iwn_start_scan *)(desc + 1);\n\n            bus_dmamap_sync(sc->sc_dmat, data->map, sizeof (*desc),\n                sizeof (*scan), BUS_DMASYNC_POSTREAD);\n            DPRINTFN(2, (\"scan start: chan %d status %x\\n\",\n                scan->chan, letoh32(scan->status)));\n\n            if (sc->sc_flags & IWN_FLAG_BGSCAN)\n                break;\n\n            /* Fix current channel. */\n            ic->ic_bss->ni_chan = &ic->ic_channels[scan->chan];\n            break;\n        }\n        case IWN_STOP_SCAN:\n        {\n            struct iwn_stop_scan *scan =\n                (struct iwn_stop_scan *)(desc + 1);\n\n            bus_dmamap_sync(sc->sc_dmat, data->map, sizeof (*desc),\n                sizeof (*scan), BUS_DMASYNC_POSTREAD);\n            DPRINTFN(2, (\"scan stop: nchan=%d status=%d chan=%d\\n\",\n                scan->nchan, scan->status, scan->chan));\n\n            if (scan->status == 1 && scan->chan <= 14 &&\n                (sc->sc_flags & IWN_FLAG_HAS_5GHZ)) {\n                    int error;\n                /*\n                 * We just finished scanning 2GHz channels,\n                 * start scanning 5GHz ones.\n                 */\n                error = iwn_scan(sc, IEEE80211_CHAN_5GHZ,\n                    (sc->sc_flags & IWN_FLAG_BGSCAN) ? 1 : 0);\n                if (error == 0)\n                    break;\n            }\n            sc->sc_flags &= ~IWN_FLAG_SCANNING;\n            sc->sc_flags &= ~IWN_FLAG_BGSCAN;\n            ieee80211_end_scan(ifp);\n            break;\n        }\n        case IWN5000_CALIBRATION_RESULT:\n            iwn5000_rx_calib_results(sc, desc, data);\n            break;\n\n        case IWN5000_CALIBRATION_DONE:\n            sc->sc_flags |= IWN_FLAG_CALIB_DONE;\n            wakeupOn(sc);\n            break;\n        }\n\n        sc->rxq.cur = (sc->rxq.cur + 1) % IWN_RX_RING_COUNT;\n    }\n    if_input(&sc->sc_ic.ic_if, &ml);\n\n    /* Tell the firmware what we have processed. */\n    hw = (hw == 0) ? IWN_RX_RING_COUNT - 1 : hw - 1;\n    IWN_WRITE(sc, IWN_FH_RX_WPTR, hw & ~7);\n}\n\n/*\n * Process an INT_WAKEUP interrupt raised when the microcontroller wakes up\n * from power-down sleep mode.\n */\nvoid ItlIwn::\niwn_wakeup_intr(struct iwn_softc *sc)\n{\n    int qid;\n\n    DPRINTF((\"ucode wakeup from power-down sleep\\n\"));\n\n    /* Wakeup RX and TX rings. */\n    IWN_WRITE(sc, IWN_FH_RX_WPTR, sc->rxq.cur & ~7);\n    for (qid = 0; qid < sc->ntxqs; qid++) {\n        struct iwn_tx_ring *ring = &sc->txq[qid];\n        IWN_WRITE(sc, IWN_HBUS_TARG_WRPTR, qid << 8 | ring->cur);\n    }\n}\n\n#ifdef IWN_DEBUG\n/*\n * Dump the error log of the firmware when a firmware panic occurs.  Although\n * we can't debug the firmware because it is neither open source nor free, it\n * can help us to identify certain classes of problems.\n */\nvoid ItlIwn::\niwn_fatal_intr(struct iwn_softc *sc)\n{\n    struct iwn_fw_dump dump;\n    int i;\n\n    /* Check that the error log address is valid. */\n    if (sc->errptr < IWN_FW_DATA_BASE ||\n        sc->errptr + sizeof (dump) >\n        IWN_FW_DATA_BASE + sc->fw_data_maxsz) {\n        XYLog(\"%s: bad firmware error log address 0x%08x\\n\",\n            sc->sc_dev.dv_xname, sc->errptr);\n        return;\n    }\n    if (iwn_nic_lock(sc) != 0) {\n        XYLog(\"%s: could not read firmware error log\\n\",\n            sc->sc_dev.dv_xname);\n        return;\n    }\n    /* Read firmware error log from SRAM. */\n    iwn_mem_read_region_4(sc, sc->errptr, (uint32_t *)&dump,\n        sizeof (dump) / sizeof (uint32_t));\n    iwn_nic_unlock(sc);\n\n    if (dump.valid == 0) {\n        XYLog(\"%s: firmware error log is empty\\n\",\n            sc->sc_dev.dv_xname);\n        return;\n    }\n    XYLog(\"firmware error log:\\n\");\n    XYLog(\"  error type      = \\\"%s\\\" (0x%08X)\\n\",\n        (dump.id < nitems(iwn_fw_errmsg)) ?\n        iwn_fw_errmsg[dump.id] : \"UNKNOWN\",\n        dump.id);\n    XYLog(\"  program counter = 0x%08X\\n\", dump.pc);\n    XYLog(\"  source line     = 0x%08X\\n\", dump.src_line);\n    XYLog(\"  error data      = 0x%08X%08X\\n\",\n        dump.error_data[0], dump.error_data[1]);\n    XYLog(\"  branch link     = 0x%08X%08X\\n\",\n        dump.branch_link[0], dump.branch_link[1]);\n    XYLog(\"  interrupt link  = 0x%08X%08X\\n\",\n        dump.interrupt_link[0], dump.interrupt_link[1]);\n    XYLog(\"  time            = %u\\n\", dump.time[0]);\n\n    /* Dump driver status (TX and RX rings) while we're here. */\n    XYLog(\"driver status:\\n\");\n    for (i = 0; i < sc->ntxqs; i++) {\n        struct iwn_tx_ring *ring = &sc->txq[i];\n        XYLog(\"  tx ring %2d: qid=%-2d cur=%-3d queued=%-3d\\n\",\n            i, ring->qid, ring->cur, ring->queued);\n    }\n    XYLog(\"  rx ring: cur=%d\\n\", sc->rxq.cur);\n    XYLog(\"  802.11 state %d\\n\", sc->sc_ic.ic_state);\n}\n#endif\n\nint ItlIwn::\niwn_intr(OSObject *object, IOInterruptEventSource* sender, int count)\n{\n    ItlIwn *that = (ItlIwn*)object;\n    struct iwn_softc *sc = &that->com;\n    struct _ifnet *ifp = &sc->sc_ic.ic_if;\n    uint32_t r1, r2, tmp;\n\n//    IWN_WRITE(sc, IWN_INT_MASK, 0);\n\n    /* Read interrupts from ICT (fast) or from registers (slow). */\n    if (sc->sc_flags & IWN_FLAG_USE_ICT) {\n        tmp = 0;\n        while (sc->ict[sc->ict_cur] != 0) {\n            tmp |= sc->ict[sc->ict_cur];\n            sc->ict[sc->ict_cur] = 0;    /* Acknowledge. */\n            sc->ict_cur = (sc->ict_cur + 1) % IWN_ICT_COUNT;\n        }\n        tmp = letoh32(tmp);\n        if (tmp == 0xffffffff)    /* Shouldn't happen. */\n            tmp = 0;\n        else if (tmp & 0xc0000)    /* Workaround a HW bug. */\n            tmp |= 0x8000;\n        r1 = (tmp & 0xff00) << 16 | (tmp & 0xff);\n        r2 = 0;    /* Unused. */\n    } else {\n        r1 = IWN_READ(sc, IWN_INT);\n        if (r1 == 0xffffffff || (r1 & 0xfffffff0) == 0xa5a5a5a0)\n            return 0;    /* Hardware gone! */\n        r2 = IWN_READ(sc, IWN_FH_INT);\n    }\n    if (r1 == 0 && r2 == 0) {\n        if (ifp->if_flags & IFF_UP)\n            IWN_WRITE(sc, IWN_INT_MASK, sc->int_mask);\n        return 0;    /* Interrupt not for us. */\n    }\n\n    /* Acknowledge interrupts. */\n    IWN_WRITE(sc, IWN_INT, r1);\n    if (!(sc->sc_flags & IWN_FLAG_USE_ICT))\n        IWN_WRITE(sc, IWN_FH_INT, r2);\n\n    if (r1 & IWN_INT_RF_TOGGLED) {\n        tmp = IWN_READ(sc, IWN_GP_CNTRL) & IWN_GP_CNTRL_RFKILL;\n        XYLog(\"%s: RF switch: radio %s\\n\", sc->sc_dev.dv_xname,\n            tmp ? \"enabled\" : \"disabled\");\n        if (tmp)\n            task_add(systq, &sc->init_task);\n    }\n    if (r1 & IWN_INT_CT_REACHED) {\n        XYLog(\"%s: critical temperature reached!\\n\",\n            sc->sc_dev.dv_xname);\n    }\n    if (r1 & (IWN_INT_SW_ERR | IWN_INT_HW_ERR)) {\n        XYLog(\"%s: fatal firmware error\\n\", sc->sc_dev.dv_xname);\n\n        /* Force a complete recalibration on next init. */\n        sc->sc_flags &= ~IWN_FLAG_CALIB_DONE;\n\n        /* Dump firmware error log and stop. */\n#ifdef IWN_DEBUG\n        that->iwn_fatal_intr(sc);\n#endif\n        that->iwn_stop(ifp);\n        task_add(systq, &sc->init_task);\n        return 1;\n    }\n    if ((r1 & (IWN_INT_FH_RX | IWN_INT_SW_RX | IWN_INT_RX_PERIODIC)) ||\n        (r2 & IWN_FH_INT_RX)) {\n        if (sc->sc_flags & IWN_FLAG_USE_ICT) {\n            if (r1 & (IWN_INT_FH_RX | IWN_INT_SW_RX))\n                IWN_WRITE(sc, IWN_FH_INT, IWN_FH_INT_RX);\n            IWN_WRITE_1(sc, IWN_INT_PERIODIC,\n                IWN_INT_PERIODIC_DIS);\n            that->iwn_notif_intr(sc);\n            if (r1 & (IWN_INT_FH_RX | IWN_INT_SW_RX)) {\n                IWN_WRITE_1(sc, IWN_INT_PERIODIC,\n                    IWN_INT_PERIODIC_ENA);\n            }\n        } else\n            that->iwn_notif_intr(sc);\n    }\n\n    if ((r1 & IWN_INT_FH_TX) || (r2 & IWN_FH_INT_TX)) {\n        if (sc->sc_flags & IWN_FLAG_USE_ICT)\n            IWN_WRITE(sc, IWN_FH_INT, IWN_FH_INT_TX);\n        that->wakeupOn(sc);    /* FH DMA transfer completed. */\n    }\n\n    if (r1 & IWN_INT_ALIVE)\n        that->wakeupOn(sc);    /* Firmware is alive. */\n\n    if (r1 & IWN_INT_WAKEUP)\n        that->iwn_wakeup_intr(sc);\n\n    /* Re-enable interrupts. */\n    if (ifp->if_flags & IFF_UP)\n        IWN_WRITE(sc, IWN_INT_MASK, sc->int_mask);\n\n    return 1;\n}\n\n/*\n * Update TX scheduler ring when transmitting an 802.11 frame (4965AGN and\n * 5000 adapters use a slightly different format).\n */\nvoid ItlIwn::\niwn4965_update_sched(struct iwn_softc *sc, int qid, int idx, uint8_t id,\n    uint16_t len)\n{\n    uint16_t *w = &sc->sched[qid * IWN4965_SCHED_COUNT + idx];\n\n    *w = htole16(len + 8);\n//    bus_dmamap_sync(sc->sc_dmat, sc->sched_dma.map,\n//        (caddr_t)w - sc->sched_dma.vaddr, sizeof (uint16_t),\n//        BUS_DMASYNC_PREWRITE);\n    if (idx < IWN_SCHED_WINSZ) {\n        *(w + IWN_TX_RING_COUNT) = *w;\n//        bus_dmamap_sync(sc->sc_dmat, sc->sched_dma.map,\n//            (caddr_t)(w + IWN_TX_RING_COUNT) - sc->sched_dma.vaddr,\n//            sizeof (uint16_t), BUS_DMASYNC_PREWRITE);\n    }\n}\n\nvoid ItlIwn::\niwn4965_reset_sched(struct iwn_softc *sc, int qid, int idx)\n{\n    /* TBD */\n}\n\nvoid ItlIwn::\niwn5000_update_sched(struct iwn_softc *sc, int qid, int idx, uint8_t id,\n    uint16_t len)\n{\n    uint16_t *w = &sc->sched[qid * IWN5000_SCHED_COUNT + idx];\n\n    *w = htole16(id << 12 | (len + 8));\n//    bus_dmamap_sync(sc->sc_dmat, sc->sched_dma.map,\n//        (caddr_t)w - sc->sched_dma.vaddr, sizeof (uint16_t),\n//        BUS_DMASYNC_PREWRITE);\n    if (idx < IWN_SCHED_WINSZ) {\n        *(w + IWN_TX_RING_COUNT) = *w;\n//        bus_dmamap_sync(sc->sc_dmat, sc->sched_dma.map,\n//            (caddr_t)(w + IWN_TX_RING_COUNT) - sc->sched_dma.vaddr,\n//            sizeof (uint16_t), BUS_DMASYNC_PREWRITE);\n    }\n}\n\nvoid ItlIwn::\niwn5000_reset_sched(struct iwn_softc *sc, int qid, int idx)\n{\n    uint16_t *w = &sc->sched[qid * IWN5000_SCHED_COUNT + idx];\n\n    *w = (*w & htole16(0xf000)) | htole16(1);\n//    bus_dmamap_sync(sc->sc_dmat, sc->sched_dma.map,\n//        (caddr_t)w - sc->sched_dma.vaddr, sizeof (uint16_t),\n//        BUS_DMASYNC_PREWRITE);\n    if (idx < IWN_SCHED_WINSZ) {\n        *(w + IWN_TX_RING_COUNT) = *w;\n//        bus_dmamap_sync(sc->sc_dmat, sc->sched_dma.map,\n//            (caddr_t)(w + IWN_TX_RING_COUNT) - sc->sched_dma.vaddr,\n//            sizeof (uint16_t), BUS_DMASYNC_PREWRITE);\n    }\n}\n\nint ItlIwn::\niwn_rval2ridx(int rval)\n{\n    int ridx;\n\n    for (ridx = 0; ridx < nitems(iwn_rates); ridx++) {\n        if (rval == iwn_rates[ridx].rate)\n            break;\n    }\n\n    return ridx;\n}\n\nstatic int\niwn_is_mimo_ht_plcp(uint8_t ht_plcp)\n{\n    return (ht_plcp != IWN_RATE_HT_SISO_MCS_INV_PLCP &&\n            (ht_plcp & IWN_RATE_HT_MCS_NSS_MSK));\n}\n\nstatic int\niwn_is_mimo_mcs(int mcs)\n{\n    int ridx = iwn_mcs2ridx[mcs];\n    return iwn_is_mimo_ht_plcp(iwn_rates[ridx].ht_plcp);\n    \n}\n\nint ItlIwn::\niwn_tx(struct iwn_softc *sc, mbuf_t m, struct ieee80211_node *ni)\n{\n    struct iwn_ops *ops = &sc->ops;\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct iwn_node *wn = (struct iwn_node *)ni;\n    struct iwn_tx_ring *ring;\n    struct iwn_tx_desc *desc;\n    struct iwn_tx_data *data;\n    struct iwn_tx_cmd *cmd;\n    struct iwn_cmd_data *tx;\n    const struct iwn_rate *rinfo;\n    struct ieee80211_frame *wh;\n    struct ieee80211_key *k = NULL;\n    enum ieee80211_edca_ac ac;\n    int qid;\n    uint32_t flags;\n    uint16_t qos;\n    u_int hdrlen;\n    IOPhysicalSegment *seg;\n    IOPhysicalSegment segs[IWN_MAX_SCATTER - 1];\n    int nsegs = 0;\n    uint8_t *ivp, tid, ridx, txant, type, subtype;\n    int i, totlen, hasqos, error, pad;\n\n    wh = mtod(m, struct ieee80211_frame *);\n    type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;\n    subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;\n    if (type == IEEE80211_FC0_TYPE_CTL)\n        hdrlen = sizeof(struct ieee80211_frame_min);\n    else\n        hdrlen = ieee80211_get_hdrlen(wh);\n\n    if ((hasqos = ieee80211_has_qos(wh))) {\n        /* Select EDCA Access Category and TX ring for this frame. */\n        struct ieee80211_tx_ba *ba;\n        qos = ieee80211_get_qos(wh);\n        tid = qos & IEEE80211_QOS_TID;\n        ac = ieee80211_up_to_ac(ic, tid);\n        qid = ac;\n\n        /* If possible, put this frame on an aggregation queue. */\n        if (sc->sc_tx_ba[tid].wn == wn) {\n            ba = &ni->ni_tx_ba[tid];\n            if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&\n                ba->ba_state == IEEE80211_BA_AGREED) {\n                qid = sc->first_agg_txq + tid;\n                if (sc->qfullmsk & (1 << qid)) {\n                    mbuf_freem(m);\n                    return ENOBUFS;\n                }\n            }\n        }\n    } else {\n        qos = 0;\n        tid = IWN_NONQOS_TID;\n        ac = EDCA_AC_BE;\n        qid = ac;\n    }\n\n    ring = &sc->txq[qid];\n    desc = &ring->desc[ring->cur];\n    data = &ring->data[ring->cur];\n\n    /* Choose a TX rate index. */\n    if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||\n        type != IEEE80211_FC0_TYPE_DATA)\n        ridx = iwn_rval2ridx(ieee80211_min_basic_rate(ic));\n    else if (ic->ic_fixed_mcs != -1)\n        ridx = sc->fixed_ridx;\n    else if (ic->ic_fixed_rate != -1)\n        ridx = sc->fixed_ridx;\n    else {\n        if (ni->ni_flags & IEEE80211_NODE_HT)\n            ridx = iwn_mcs2ridx[ni->ni_txmcs];\n        else\n            ridx = wn->ridx[ni->ni_txrate];\n    }\n    rinfo = &iwn_rates[ridx];\n#if NBPFILTER > 0\n    if (sc->sc_drvbpf != NULL) {\n        struct iwn_tx_radiotap_header *tap = &sc->sc_txtap;\n        uint16_t chan_flags;\n\n        tap->wt_flags = 0;\n        tap->wt_chan_freq = htole16(ni->ni_chan->ic_freq);\n        chan_flags = ni->ni_chan->ic_flags;\n        if (ic->ic_curmode != IEEE80211_MODE_11N)\n            chan_flags &= ~IEEE80211_CHAN_HT;\n        tap->wt_chan_flags = htole16(chan_flags);\n        if ((ni->ni_flags & IEEE80211_NODE_HT) &&\n            !IEEE80211_IS_MULTICAST(wh->i_addr1) &&\n            type == IEEE80211_FC0_TYPE_DATA) {\n            tap->wt_rate = (0x80 | ni->ni_txmcs);\n        } else\n            tap->wt_rate = rinfo->rate;\n        if ((ic->ic_flags & IEEE80211_F_WEPON) &&\n            (wh->i_fc[1] & IEEE80211_FC1_PROTECTED))\n            tap->wt_flags |= IEEE80211_RADIOTAP_F_WEP;\n\n        bpf_mtap_hdr(sc->sc_drvbpf, tap, sc->sc_txtap_len,\n            m, BPF_DIRECTION_OUT);\n    }\n#endif\n\n    //    totlen = m->m_pkthdr.len;\n    totlen = mbuf_pkthdr_len(m);\n\n    /* Encrypt the frame if need be. */\n    if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {\n        /* Retrieve key for TX. */\n        k = ieee80211_get_txkey(ic, wh, ni);\n        if (k->k_cipher != IEEE80211_CIPHER_CCMP) {\n            /* Do software encryption. */\n            if ((m = ieee80211_encrypt(ic, m, k)) == NULL)\n                return ENOBUFS;\n            /* 802.11 header may have moved. */\n            wh = mtod(m, struct ieee80211_frame *);\n            //    totlen = m->m_pkthdr.len;\n            totlen = mbuf_pkthdr_len(m);\n\n        } else    /* HW appends CCMP MIC. */\n            totlen += IEEE80211_CCMP_HDRLEN;\n    }\n\n    data->totlen = totlen;\n\n    /* Prepare TX firmware command. */\n    cmd = &ring->cmd[ring->cur];\n    cmd->code = IWN_CMD_TX_DATA;\n    cmd->flags = 0;\n    cmd->qid = ring->qid;\n    cmd->idx = ring->cur;\n\n    tx = (struct iwn_cmd_data *)cmd->data;\n    /* NB: No need to clear tx, all fields are reinitialized here. */\n    tx->scratch = 0;    /* clear \"scratch\" area */\n\n    flags = 0;\n    if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {\n        /* Unicast frame, check if an ACK is expected. */\n        if (!hasqos || (qos & IEEE80211_QOS_ACK_POLICY_MASK) !=\n            IEEE80211_QOS_ACK_POLICY_NOACK)\n            flags |= IWN_TX_NEED_ACK;\n    }\n    if (type == IEEE80211_FC0_TYPE_CTL &&\n        subtype == IEEE80211_FC0_SUBTYPE_BAR) {\n        struct ieee80211_frame_min *mwh;\n        uint8_t *barfrm;\n        uint16_t ctl;\n        mwh = mtod(m, struct ieee80211_frame_min *);\n        barfrm = (uint8_t *)&mwh[1];\n        ctl = LE_READ_2(barfrm);\n        tid = (ctl & IEEE80211_BA_TID_INFO_MASK) >>\n            IEEE80211_BA_TID_INFO_SHIFT;\n        flags |= (IWN_TX_NEED_ACK | IWN_TX_IMM_BA);\n    }\n\n    if (wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG)\n        flags |= IWN_TX_MORE_FRAG;    /* Cannot happen yet. */\n\n    /* Check if frame must be protected using RTS/CTS or CTS-to-self. */\n    if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {\n        /* NB: Group frames are sent using CCK in 802.11b/g/n (2GHz). */\n        if (totlen + IEEE80211_CRC_LEN > ic->ic_rtsthreshold) {\n            flags |= IWN_TX_NEED_RTS;\n        } else if ((ic->ic_flags & IEEE80211_F_USEPROT) &&\n            IWN_RIDX_IS_OFDM(ridx)) {\n            if (ic->ic_protmode == IEEE80211_PROT_CTSONLY)\n                flags |= IWN_TX_NEED_CTS;\n            else if (ic->ic_protmode == IEEE80211_PROT_RTSCTS)\n                flags |= IWN_TX_NEED_RTS;\n        }\n\n        if (flags & (IWN_TX_NEED_RTS | IWN_TX_NEED_CTS)) {\n            if (sc->hw_type != IWN_HW_REV_TYPE_4965) {\n                /* 5000 autoselects RTS/CTS or CTS-to-self. */\n                flags &= ~(IWN_TX_NEED_RTS | IWN_TX_NEED_CTS);\n                flags |= IWN_TX_NEED_PROTECTION;\n            } else\n                flags |= IWN_TX_FULL_TXOP;\n        }\n    }\n\n    if (type == IEEE80211_FC0_TYPE_CTL &&\n        subtype == IEEE80211_FC0_SUBTYPE_BAR)\n        tx->id = wn->id;\n    else if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||\n        type != IEEE80211_FC0_TYPE_DATA)\n        tx->id = sc->broadcast_id;\n    else\n        tx->id = wn->id;\n\n    if (type == IEEE80211_FC0_TYPE_MGT) {\n#ifndef IEEE80211_STA_ONLY\n        /* Tell HW to set timestamp in probe responses. */\n        if (subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP)\n            flags |= IWN_TX_INSERT_TSTAMP;\n#endif\n        if (subtype == IEEE80211_FC0_SUBTYPE_ASSOC_REQ ||\n            subtype == IEEE80211_FC0_SUBTYPE_REASSOC_REQ)\n            tx->timeout = htole16(3);\n        else\n            tx->timeout = htole16(2);\n    } else\n        tx->timeout = htole16(0);\n\n    if (hdrlen & 3) {\n        /* First segment length must be a multiple of 4. */\n        flags |= IWN_TX_NEED_PADDING;\n        pad = 4 - (hdrlen & 3);\n    } else\n        pad = 0;\n\n    tx->len = htole16(totlen);\n    tx->tid = tid;\n    tx->rts_ntries = 60;\n    tx->data_ntries = 15;\n    tx->lifetime = htole32(IWN_LIFETIME_INFINITE);\n\n    if ((ni->ni_flags & IEEE80211_NODE_HT) &&\n        tx->id != sc->broadcast_id &&\n        rinfo->ht_plcp != IWN_RATE_HT_SISO_MCS_INV_PLCP) {\n        tx->plcp = rinfo->ht_plcp;\n        tx->rflags = IWN_RFLAG_MCS;\n        if (ieee80211_node_supports_ht_sgi20(ni))\n            tx->rflags |= IWN_RFLAG_SGI;\n        if (iwn_rxon_ht40_enabled(sc)) {\n            tx->rflags |= IWN_RFLAG_HT40;\n            if (ieee80211_node_supports_ht_sgi40(ni)) {\n                tx->rflags |= IWN_RFLAG_SGI;\n            }\n        }\n        if (iwn_is_mimo_ht_plcp(rinfo->ht_plcp))\n            tx->rflags |= IWN_RFLAG_ANT(sc->txchainmask);\n        else\n            tx->rflags |= IWN_RFLAG_ANT(IWN_LSB(sc->txchainmask));\n    }\n    else {\n        tx->plcp = rinfo->plcp;\n        if (IWN_RIDX_IS_CCK(ridx))\n            tx->rflags = IWN_RFLAG_CCK;\n        else\n            tx->rflags = 0;\n    }\n    if (tx->id == sc->broadcast_id || ic->ic_fixed_mcs != -1 ||\n        ic->ic_fixed_rate != -1) {\n        /* Group or management frame, or fixed Tx rate. */\n        tx->linkq = 0;\n        /* XXX Alternate between antenna A and B? */\n        txant = IWN_LSB(sc->txchainmask);\n        tx->rflags |= IWN_RFLAG_ANT(txant);\n    } else {\n        tx->linkq = 0; /* initial index into firmware LQ retry table */\n        flags |= IWN_TX_LINKQ;    /* enable multi-rate retry */\n    }\n    /* Set physical address of \"scratch area\". */\n    tx->loaddr = htole32(IWN_LOADDR(data->scratch_paddr));\n    tx->hiaddr = IWN_HIADDR(data->scratch_paddr);\n\n    /* Copy 802.11 header in TX command. */\n    memcpy((uint8_t *)(tx + 1), wh, hdrlen);\n\n    if (k != NULL && k->k_cipher == IEEE80211_CIPHER_CCMP) {\n        /* Trim 802.11 header and prepend CCMP IV. */\n        mbuf_adj(m, hdrlen - IEEE80211_CCMP_HDRLEN);\n        ivp = mtod(m, uint8_t *);\n        k->k_tsc++;\n        ivp[0] = k->k_tsc;\n        ivp[1] = k->k_tsc >> 8;\n        ivp[2] = 0;\n        ivp[3] = k->k_id << 6 | IEEE80211_WEP_EXTIV;\n        ivp[4] = k->k_tsc >> 16;\n        ivp[5] = k->k_tsc >> 24;\n        ivp[6] = k->k_tsc >> 32;\n        ivp[7] = k->k_tsc >> 40;\n\n        tx->security = IWN_CIPHER_CCMP;\n        if (qid >= sc->first_agg_txq)\n            flags |= IWN_TX_AMPDU_CCMP;\n        memcpy(tx->key, k->k_key, k->k_len);\n\n        /* TX scheduler includes CCMP MIC len w/5000 Series. */\n        if (sc->hw_type != IWN_HW_REV_TYPE_4965)\n            totlen += IEEE80211_CCMP_MICLEN;\n    } else {\n        /* Trim 802.11 header. */\n        mbuf_adj(m, hdrlen);\n        tx->security = 0;\n    }\n    tx->flags = htole32(flags);\n\n    nsegs = data->map->cursor->getPhysicalSegmentsWithCoalesce(m, &segs[0], IWN_MAX_SCATTER - 1);\n    if (nsegs == 0) {\n        XYLog(\"%s: can't map mbuf (error %d)\\n\", DEVNAME(sc),\n              nsegs);\n        mbuf_freem(m);\n        return ENOMEM;\n    }\n\n    data->m = m;\n    data->ni = ni;\n    data->ampdu_txmcs = ni->ni_txmcs; /* updated upon Tx interrupt */\n\n    DPRINTFN(4, (\"sending data: qid=%d idx=%d len=%d nsegs=%d\\n\",\n        ring->qid, ring->cur, mbuf_pkthdr_len(m), nsegs));\n\n    /* Fill TX descriptor. */\n    desc->nsegs = 1 + nsegs;\n    /* First DMA segment is used by the TX command. */\n    desc->segs[0].addr = htole32(IWN_LOADDR(data->cmd_paddr));\n    desc->segs[0].len  = htole16(IWN_HIADDR(data->cmd_paddr) |\n        (4 + sizeof (*tx) + hdrlen + pad) << 4);\n    /* Other DMA segments are for data payload. */\n    for (i = 0; i < nsegs; i++) {\n        seg = &segs[i];\n        desc->segs[i + 1].addr = htole32(IWN_LOADDR(seg->location));\n        desc->segs[i + 1].len  = htole16(IWN_HIADDR(seg->location) |\n            seg->length << 4);\n//        XYLog(\"DMA segments index=%d location=0x%llx length=%llu\", i, seg->location, seg->length);\n    }\n//    XYLog(\"----------end sending data------\\n\");\n\n//    bus_dmamap_sync(sc->sc_dmat, data->map, 0, data->map->dm_mapsize,\n//        BUS_DMASYNC_PREWRITE);\n//    bus_dmamap_sync(sc->sc_dmat, ring->cmd_dma.map,\n//        (caddr_t)cmd - ring->cmd_dma.vaddr, sizeof (*cmd),\n//        BUS_DMASYNC_PREWRITE);\n//    bus_dmamap_sync(sc->sc_dmat, ring->desc_dma.map,\n//        (caddr_t)desc - ring->desc_dma.vaddr, sizeof (*desc),\n//        BUS_DMASYNC_PREWRITE);\n\n    /* Update TX scheduler. */\n    ops->update_sched(sc, ring->qid, ring->cur, tx->id, totlen);\n\n    /* Kick TX ring. */\n    ring->cur = (ring->cur + 1) % IWN_TX_RING_COUNT;\n    IWN_WRITE(sc, IWN_HBUS_TARG_WRPTR, ring->qid << 8 | ring->cur);\n\n    /* Mark TX ring as full if we reach a certain threshold. */\n    if (++ring->queued > IWN_TX_RING_HIMARK) {\n//        XYLog(\"%s sc->qfullmsk is FULL qid=%d ring->cur=%d ring->queued=%d\\n\", __FUNCTION__, ring->qid, ring->cur, ring->queued);\n        sc->qfullmsk |= 1 << ring->qid;\n    }\n\n    return 0;\n}\n\nvoid ItlIwn::\niwn_start(struct _ifnet *ifp)\n{\n    struct iwn_softc *sc = (struct iwn_softc*)ifp->if_softc;\n    ItlIwn *that = container_of(sc, ItlIwn, com);\n    that->getMainCommandGate()->attemptAction(_iwn_start_task, &that->com.sc_ic.ic_ac.ac_if);\n}\n\nIOReturn ItlIwn::\n_iwn_start_task(OSObject *target, void *arg0, void *arg1, void *arg2, void *arg3)\n{\n    struct _ifnet *ifp = (struct _ifnet *)arg0;\n    struct iwn_softc *sc = (struct iwn_softc *)ifp->if_softc;\n    ItlIwn *that = container_of(sc, ItlIwn, com);\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct ieee80211_node *ni;\n    mbuf_t m;\n\n    if (!(ifp->if_flags & IFF_RUNNING) || ifq_is_oactive(&ifp->if_snd))\n        return kIOReturnError;\n\n    for (;;) {\n        if (sc->qfullmsk != 0) {\n            ifq_set_oactive(&ifp->if_snd);\n            break;\n        }\n\n        /* Send pending management frames first. */\n        m = mq_dequeue(&ic->ic_mgtq);\n        if (m != NULL) {\n//            ni = m->m_pkthdr.ph_cookie;\n            ni = (struct ieee80211_node *)mbuf_pkthdr_rcvif(m);\n            goto sendit;\n        }\n        if (\n#ifndef AIRPORT\n            ic->ic_state != IEEE80211_S_RUN ||\n#endif\n            (ic->ic_xflags & IEEE80211_F_TX_MGMT_ONLY))\n            break;\n\n        /* Encapsulate and send data frames. */\n        m = ifq_dequeue(&ifp->if_snd);\n        if (m == NULL)\n            break;\n#if NBPFILTER > 0\n        if (ifp->if_bpf != NULL)\n            bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);\n#endif\n        if ((m = ieee80211_encap(ifp, m, &ni)) == NULL)\n            continue;\nsendit:\n#if NBPFILTER > 0\n        if (ic->ic_rawbpf != NULL)\n            bpf_mtap(ic->ic_rawbpf, m, BPF_DIRECTION_OUT);\n#endif\n        if (that->iwn_tx(sc, m, ni) != 0) {\n            ieee80211_release_node(ic, ni);\n            ifp->netStat->outputErrors++;\n            continue;\n        }\n        ifp->netStat->outputPackets++;\n\n        sc->sc_tx_timer = 5;\n        ifp->if_timer = 1;\n    }\n    \n    return kIOReturnSuccess;\n}\n\nvoid ItlIwn::\niwn_watchdog(struct _ifnet *ifp)\n{\n    struct iwn_softc *sc = (struct iwn_softc *)ifp->if_softc;\n    ItlIwn *that = container_of(sc, ItlIwn, com);\n\n    ifp->if_timer = 0;\n\n    if (sc->sc_tx_timer > 0) {\n        if (--sc->sc_tx_timer == 0) {\n            XYLog(\"%s: device timeout\\n\", sc->sc_dev.dv_xname);\n            that->iwn_stop(ifp);\n            task_add(systq, &sc->init_task);\n            ifp->netStat->outputErrors++;\n            return;\n        }\n        ifp->if_timer = 1;\n    }\n\n    ieee80211_watchdog(ifp);\n}\n\nint ItlIwn::\niwn_ioctl(struct _ifnet *ifp, u_long cmd, caddr_t data)\n{\n    struct iwn_softc *sc = (struct iwn_softc *)ifp->if_softc;\n    struct ieee80211com *ic = &sc->sc_ic;\n    ItlIwn *that = container_of(sc, ItlIwn, com);\n    int s, error = 0;\n\n//    error = rw_enter(&sc->sc_rwlock, RW_WRITE | RW_INTR);\n    if (error)\n        return error;\n    s = splnet();\n\n    switch (cmd) {\n    case SIOCSIFADDR:\n        ifp->if_flags |= IFF_UP;\n        /* FALLTHROUGH */\n    case SIOCSIFFLAGS:\n        if (ifp->if_flags & IFF_UP) {\n            if (!(ifp->if_flags & IFF_RUNNING))\n                error = that->iwn_init(ifp);\n        } else {\n            if (ifp->if_flags & IFF_RUNNING)\n                that->iwn_stop(ifp);\n        }\n        break;\n\n    case SIOCS80211POWER:\n        error = ieee80211_ioctl(ifp, cmd, data);\n        if (error != ENETRESET)\n            break;\n        if (ic->ic_state == IEEE80211_S_RUN &&\n            sc->calib.state == IWN_CALIB_STATE_RUN) {\n            if (ic->ic_flags & IEEE80211_F_PMGTON)\n                error = that->iwn_set_pslevel(sc, 0, 3, 0);\n            else    /* back to CAM */\n                error = that->iwn_set_pslevel(sc, 0, 0, 0);\n        } else {\n            /* Defer until transition to IWN_CALIB_STATE_RUN. */\n            error = 0;\n        }\n        break;\n\n    default:\n        error = ieee80211_ioctl(ifp, cmd, data);\n    }\n\n    if (error == ENETRESET) {\n        error = 0;\n        if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==\n            (IFF_UP | IFF_RUNNING)) {\n            that->iwn_stop(ifp);\n            error = that->iwn_init(ifp);\n        }\n    }\n\n    splx(s);\n//    rw_exit_write(&sc->sc_rwlock);\n    return error;\n}\n\n/*\n * Send a command to the firmware.\n */\nint ItlIwn::\niwn_cmd(struct iwn_softc *sc, int code, const void *buf, int size, int async)\n{\n    DPRINTFN(2, (\"%s code=%d size=%d\\n\", __FUNCTION__, code, size));\n    struct iwn_ops *ops = &sc->ops;\n    struct iwn_tx_ring *ring = &sc->txq[4];\n    struct iwn_tx_desc *desc;\n    struct iwn_tx_data *data;\n    struct iwn_tx_cmd *cmd;\n    mbuf_t m;\n    bus_addr_t paddr;\n    int totlen, error = 0;\n    unsigned int max_chunks = 1;\n    IOPhysicalSegment seg;\n\n    desc = &ring->desc[ring->cur];\n    data = &ring->data[ring->cur];\n    totlen = 4 + size;\n\n    if (size > sizeof cmd->data) {\n        /* Command is too large to fit in a descriptor. */\n        if (totlen > MCLBYTES)\n            return EINVAL;\n//        MGETHDR(m, M_DONTWAIT, MT_DATA);\n//        if (totlen > MHLEN) {\n//            MCLGET(m, M_DONTWAIT);\n//            if (!(m->m_flags & M_EXT)) {\n//                mbuf_freem(m);\n//                return ENOMEM;\n//            }\n//        }\n        mbuf_allocpacket(MBUF_WAITOK, totlen, &max_chunks, &m);\n        if (m == NULL) {\n            XYLog(\"%s: could not get fw cmd mbuf (%zd bytes)\\n\",\n                  DEVNAME(sc), totlen);\n            return ENOMEM;\n        }\n        mbuf_setlen(m, totlen);\n        mbuf_pkthdr_setlen(m, totlen);\n\n        cmd = mtod(m, struct iwn_tx_cmd *);\n//        error = bus_dmamap_load(sc->sc_dmat, data->map, cmd, totlen,\n//            NULL, BUS_DMA_NOWAIT | BUS_DMA_WRITE);\n//        if (error != 0) {\n//            mbuf_freem(m);\n//            return error;\n//        }\n        data->map->dm_nsegs = data->map->cursor->getPhysicalSegmentsWithCoalesce(m, &seg, 1);\n        if (data->map->dm_nsegs == 0) {\n            XYLog(\"%s: could not load fw cmd mbuf (%zd bytes)\\n\",\n                  DEVNAME(sc), totlen);\n            mbuf_freem(m);\n            return ENOMEM;\n        }\n        data->m = m;\n        paddr = seg.location;\n    } else {\n        cmd = &ring->cmd[ring->cur];\n        paddr = data->cmd_paddr;\n    }\n\n    cmd->code = code;\n    cmd->flags = 0;\n    cmd->qid = ring->qid;\n    cmd->idx = ring->cur;\n    memcpy(cmd->data, buf, size);\n\n    desc->nsegs = 1;\n    desc->segs[0].addr = htole32(IWN_LOADDR(paddr));\n    desc->segs[0].len  = htole16(IWN_HIADDR(paddr) | totlen << 4);\n\n//    if (size > sizeof cmd->data) {\n//        bus_dmamap_sync(sc->sc_dmat, data->map, 0, totlen,\n//            BUS_DMASYNC_PREWRITE);\n//    } else {\n//        bus_dmamap_sync(sc->sc_dmat, ring->cmd_dma.map,\n//            (caddr_t)cmd - ring->cmd_dma.vaddr, totlen,\n//            BUS_DMASYNC_PREWRITE);\n//    }\n//    bus_dmamap_sync(sc->sc_dmat, ring->desc_dma.map,\n//        (caddr_t)desc - ring->desc_dma.vaddr, sizeof (*desc),\n//        BUS_DMASYNC_PREWRITE);\n\n    /* Update TX scheduler. */\n    ops->update_sched(sc, ring->qid, ring->cur, 0, 0);\n\n    /* Kick command ring. */\n    ring->cur = (ring->cur + 1) % IWN_TX_RING_COUNT;\n    IWN_WRITE(sc, IWN_HBUS_TARG_WRPTR, ring->qid << 8 | ring->cur);\n\n    return async ? 0 : tsleep_nsec(desc, PCATCH, \"iwncmd\", SEC_TO_NSEC(1));\n}\n\nint ItlIwn::\niwn4965_add_node(struct iwn_softc *sc, struct iwn_node_info *node, int async)\n{\n    ItlIwn *that = container_of(sc, ItlIwn, com);\n    struct iwn4965_node_info hnode;\n    caddr_t src, dst;\n\n    /*\n     * We use the node structure for 5000 Series internally (it is\n     * a superset of the one for 4965AGN). We thus copy the common\n     * fields before sending the command.\n     */\n    src = (caddr_t)node;\n    dst = (caddr_t)&hnode;\n    memcpy(dst, src, 48);\n    /* Skip TSC, RX MIC and TX MIC fields from ``src''. */\n    memcpy(dst + 48, src + 72, 20);\n    return that->iwn_cmd(sc, IWN_CMD_ADD_NODE, &hnode, sizeof hnode, async);\n}\n\nint ItlIwn::\niwn5000_add_node(struct iwn_softc *sc, struct iwn_node_info *node, int async)\n{\n    ItlIwn *that = container_of(sc, ItlIwn, com);\n    \n    /* Direct mapping. */\n    return that->iwn_cmd(sc, IWN_CMD_ADD_NODE, node, sizeof (*node), async);\n}\n\nint ItlIwn::\niwn_set_link_quality(struct iwn_softc *sc, struct ieee80211_node *ni)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct iwn_node *wn = (struct iwn_node *)ni;\n    struct iwn_cmd_link_quality linkq;\n    struct ieee80211_rateset *rs = &ni->ni_rates;\n    uint8_t txant;\n    int i, ridx, ridx_min, ridx_max, j, mimo, tab = 0, rflags = 0;\n\n    /* Use the first valid TX antenna. */\n    txant = IWN_LSB(sc->txchainmask);\n\n    memset(&linkq, 0, sizeof linkq);\n    linkq.id = wn->id;\n    linkq.antmsk_1stream = txant;\n    linkq.antmsk_2stream = IWN_ANT_AB;\n    linkq.ampdu_max = IWN_AMPDU_MAX;\n    linkq.ampdu_threshold = 3;\n    linkq.ampdu_limit = htole16(4000);    /* 4ms */\n\n#if 0 // RTS/CTS protection not yet tested\n    if (ni->ni_flags & IEEE80211_NODE_HT &&\n        sc->agg_queue_mask > 0 &&\n        ic->ic_flags & IEEE80211_F_USEPROT)\n        if (sc->hw_type != IWN_HW_REV_TYPE_4965 &&\n            sc->hw_type != IWN_HW_REV_TYPE_5300 &&\n            sc->hw_type != IWN_HW_REV_TYPE_5150 &&\n            sc->hw_type != IWN_HW_REV_TYPE_5350 &&\n            sc->hw_type != IWN_HW_REV_TYPE_5100)\n            linkq.flags |= IWN_LINK_QUAL_FLAGS_SET_STA_TLC_RTS;\n#endif\n    \n    /*\n     * Fill the LQ rate selection table with legacy and/or HT rates\n     * in descending order, i.e. with the node's current TX rate first.\n     * In cases where throughput of an HT rate corresponds to a legacy\n     * rate it makes no sense to add both. We rely on the fact that\n     * iwn_rates is laid out such that equivalent HT/legacy rates share\n     * the same IWN_RATE_*_INDEX value. Also, rates not applicable to\n     * legacy/HT are assumed to be marked with an 'invalid' PLCP value.\n     */\n    j = 0;\n    ridx_min = iwn_rval2ridx(ieee80211_min_basic_rate(ic));\n    mimo = iwn_is_mimo_mcs(ni->ni_txmcs);\n    ridx_max = (mimo ? IWN_LAST_HT_RATE : IWN_LAST_HT_SISO_RATE);\n    for (ridx = ridx_max; ridx >= ridx_min; ridx--) {\n        uint8_t plcp = iwn_rates[ridx].plcp;\n        uint8_t ht_plcp = iwn_rates[ridx].ht_plcp;\n        \n        if (j >= IWN_MAX_TX_RETRIES)\n            break;\n        tab = 0;\n        rflags = 0;\n        if (ni->ni_flags & IEEE80211_NODE_HT) {\n            if (ht_plcp == IWN_RATE_HT_SISO_MCS_INV_PLCP)\n                continue;\n            /* Do not mix SISO and MIMO HT rates. */\n            if ((mimo && !iwn_is_mimo_ht_plcp(ht_plcp)) ||\n                (!mimo && iwn_is_mimo_ht_plcp(ht_plcp)))\n                continue;\n            for (i = ni->ni_txmcs; i >= 0; i--) {\n                if (ic->ic_tx_mcs_set == IEEE80211_TX_MCS_SET_DEFINED &&\n                    isclr(ni->ni_rxmcs, i))\n                    continue;\n                if (ridx != iwn_mcs2ridx[i])\n                    continue;\n                tab = ht_plcp;\n                rflags |= IWN_RFLAG_MCS;\n                /* First two Tx attempts may use 40MHz/SGI. */\n                if (j > 1)\n                    break;\n                if (iwn_rxon_ht40_enabled(sc))\n                    rflags |= IWN_RFLAG_HT40;\n                if (ieee80211_ra_use_ht_sgi(ni))\n                    rflags |= IWN_RFLAG_SGI;\n            }\n        } else if (plcp != IWN_RATE_INVM_PLCP) {\n            for (i = ni->ni_txrate; i >= 0; i--) {\n                if (iwn_rates[ridx].rate == (rs->rs_rates[i] &\n                                             IEEE80211_RATE_VAL)) {\n                    tab = plcp;\n                    break;\n                }\n            }\n        }\n        \n        if (tab == 0 && rflags == 0)\n            continue;\n        \n        if (iwn_is_mimo_ht_plcp(ht_plcp))\n            rflags |= IWN_RFLAG_ANT(sc->txchainmask);\n        else\n            rflags |= IWN_RFLAG_ANT(txant);\n        \n        if (IWN_RIDX_IS_CCK(ridx))\n            rflags |= IWN_RFLAG_CCK;\n\n        DPRINTFN(2, (\"lq.retry[%d].plcp = 0x%x, lq.retry[i].rflags = 0x%x\\n\", j, tab, rflags));\n        linkq.retry[j].plcp = tab;\n        linkq.retry[j].rflags = rflags;\n        j++;\n    }\n    \n    linkq.mimo = (mimo ? j : 0);\n    \n    /* Fill the rest with the lowest possible rate */\n    while (j < IWN_MAX_TX_RETRIES) {\n        tab = iwn_rates[ridx_min].plcp;\n        rflags = 0;\n        if (IWN_RIDX_IS_CCK(ridx_min))\n            rflags |= IWN_RFLAG_CCK;\n        rflags |= IWN_RFLAG_ANT(txant);\n        DPRINTFN(2, (\"lq.retry[%d].plcp = 0x%x, lq.retry[i].rflags = 0x%x\\n\", j, tab, rflags));\n        linkq.retry[j].plcp = tab;\n        linkq.retry[j].rflags = rflags;\n        j++;\n    }\n\n    return iwn_cmd(sc, IWN_CMD_LINK_QUALITY, &linkq, sizeof linkq, 1);\n}\n\n/*\n * Broadcast node is used to send group-addressed and management frames.\n */\nint ItlIwn::\niwn_add_broadcast_node(struct iwn_softc *sc, int async, int ridx)\n{\n    struct iwn_ops *ops = &sc->ops;\n    struct iwn_node_info node;\n    struct iwn_cmd_link_quality linkq;\n    const struct iwn_rate *rinfo;\n    uint8_t txant;\n    int i, error;\n\n    memset(&node, 0, sizeof node);\n    IEEE80211_ADDR_COPY(node.macaddr, etherbroadcastaddr);\n    node.id = sc->broadcast_id;\n    DPRINTF((\"adding broadcast node\\n\"));\n    if ((error = ops->add_node(sc, &node, async)) != 0)\n        return error;\n\n    /* Use the first valid TX antenna. */\n    txant = IWN_LSB(sc->txchainmask);\n\n    memset(&linkq, 0, sizeof linkq);\n    linkq.id = sc->broadcast_id;\n    linkq.antmsk_1stream = txant;\n    linkq.antmsk_2stream = IWN_ANT_AB;\n    linkq.ampdu_max = IWN_AMPDU_MAX_NO_AGG;\n    linkq.ampdu_threshold = 3;\n    linkq.ampdu_limit = htole16(4000);    /* 4ms */\n\n    /* Use lowest mandatory bit-rate. */\n    rinfo = &iwn_rates[ridx];\n    linkq.retry[0].plcp = rinfo->plcp;\n    if (IWN_RIDX_IS_CCK(ridx))\n        linkq.retry[0].rflags = IWN_RFLAG_CCK;\n    linkq.retry[0].rflags |= IWN_RFLAG_ANT(txant);\n    /* Use same bit-rate for all TX retries. */\n    for (i = 1; i < IWN_MAX_TX_RETRIES; i++) {\n        linkq.retry[i].plcp = linkq.retry[0].plcp;\n        linkq.retry[i].rflags = linkq.retry[0].rflags;\n    }\n    return iwn_cmd(sc, IWN_CMD_LINK_QUALITY, &linkq, sizeof linkq, async);\n}\n\nvoid ItlIwn::\niwn_updateedca(struct ieee80211com *ic)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n\n#define IWN_EXP2(x)    ((1 << (x)) - 1)    /* CWmin = 2^ECWmin - 1 */\n    struct iwn_softc *sc = (struct iwn_softc *)ic->ic_softc;\n    struct ieee80211_node *ni = ic->ic_bss;\n    ItlIwn *that = container_of(sc, ItlIwn, com);\n    struct iwn_edca_params cmd;\n    int aci;\n\n    memset(&cmd, 0, sizeof cmd);\n    for (aci = 0; aci < EDCA_NUM_AC; aci++) {\n        const struct ieee80211_edca_ac_params *ac =\n            &ic->ic_edca_ac[aci];\n        cmd.ac[aci].aifsn = ac->ac_aifsn;\n        cmd.ac[aci].cwmin = htole16(IWN_EXP2(ac->ac_ecwmin));\n        cmd.ac[aci].cwmax = htole16(IWN_EXP2(ac->ac_ecwmax));\n        cmd.ac[aci].txoplimit =\n            htole16(IEEE80211_TXOP_TO_US(ac->ac_txoplimit));\n    }\n    if (ni->ni_flags & IEEE80211_NODE_QOS)\n        cmd.flags |= htole32(IWN_EDCA_UPDATE);\n\n    if (ni->ni_flags & IEEE80211_NODE_HT)\n        cmd.flags |= htole32(IWN_EDCA_FLG_TGN);\n\n    (void)that->iwn_cmd(sc, IWN_CMD_EDCA_PARAMS, &cmd, sizeof cmd, 1);\n#undef IWN_EXP2\n}\n\nvoid ItlIwn::\niwn_set_led(struct iwn_softc *sc, uint8_t which, uint8_t off, uint8_t on)\n{\n    struct iwn_cmd_led led;\n\n    /* Clear microcode LED ownership. */\n    IWN_CLRBITS(sc, IWN_LED, IWN_LED_BSM_CTRL);\n\n    led.which = which;\n    led.unit = htole32(10000);    /* on/off in unit of 100ms */\n    led.off = off;\n    led.on = on;\n    (void)iwn_cmd(sc, IWN_CMD_SET_LED, &led, sizeof led, 1);\n}\n\n/*\n * Set the critical temperature at which the firmware will stop the radio\n * and notify us.\n */\nint ItlIwn::\niwn_set_critical_temp(struct iwn_softc *sc)\n{\n    struct iwn_critical_temp crit;\n    int32_t temp;\n\n    IWN_WRITE(sc, IWN_UCODE_GP1_CLR, IWN_UCODE_GP1_CTEMP_STOP_RF);\n\n    if (sc->hw_type == IWN_HW_REV_TYPE_5150)\n        temp = (IWN_CTOK(110) - sc->temp_off) * -5;\n    else if (sc->hw_type == IWN_HW_REV_TYPE_4965)\n        temp = IWN_CTOK(110);\n    else\n        temp = 110;\n    memset(&crit, 0, sizeof crit);\n    crit.tempR = htole32(temp);\n    DPRINTF((\"setting critical temperature to %d\\n\", temp));\n    return iwn_cmd(sc, IWN_CMD_SET_CRITICAL_TEMP, &crit, sizeof crit, 0);\n}\n\nint ItlIwn::\niwn_set_timing(struct iwn_softc *sc, struct ieee80211_node *ni)\n{\n    struct iwn_cmd_timing cmd;\n    uint64_t val, mod;\n\n    memset(&cmd, 0, sizeof cmd);\n    memcpy(&cmd.tstamp, ni->ni_tstamp, sizeof (uint64_t));\n    cmd.bintval = htole16(ni->ni_intval);\n    cmd.lintval = htole16(10);\n\n    /* Compute remaining time until next beacon. */\n    val = (uint64_t)ni->ni_intval * IEEE80211_DUR_TU;\n    mod = letoh64(cmd.tstamp) % val;\n    cmd.binitval = htole32((uint32_t)(val - mod));\n\n    DPRINTF((\"timing bintval=%u, tstamp=%llu, init=%u\\n\",\n        ni->ni_intval, letoh64(cmd.tstamp), (uint32_t)(val - mod)));\n\n    return iwn_cmd(sc, IWN_CMD_TIMING, &cmd, sizeof cmd, 1);\n}\n\nvoid ItlIwn::\niwn4965_power_calibration(struct iwn_softc *sc, int temp)\n{\n    /* Adjust TX power if need be (delta >= 3 degC). */\n    DPRINTF((\"temperature %d->%d\\n\", sc->temp, temp));\n    if (abs(temp - sc->temp) >= 3) {\n        /* Record temperature of last calibration. */\n        sc->temp = temp;\n        (void)iwn4965_set_txpower(sc, 1);\n    }\n}\n\n/*\n * Set TX power for current channel (each rate has its own power settings).\n * This function takes into account the regulatory information from EEPROM,\n * the current temperature and the current voltage.\n */\nint ItlIwn::\niwn4965_set_txpower(struct iwn_softc *sc, int async)\n{\n/* Fixed-point arithmetic division using a n-bit fractional part. */\n#define fdivround(a, b, n)    \\\n    ((((1 << n) * (a)) / (b) + (1 << n) / 2) / (1 << n))\n/* Linear interpolation. */\n#define interpolate(x, x1, y1, x2, y2, n)    \\\n    ((y1) + fdivround(((int)(x) - (x1)) * ((y2) - (y1)), (x2) - (x1), n))\n\n    static const int tdiv[IWN_NATTEN_GROUPS] = { 9, 8, 8, 8, 6 };\n    struct ieee80211com *ic = &sc->sc_ic;\n    ItlIwn *that = container_of(sc, ItlIwn, com);\n    struct iwn_ucode_info *uc = &sc->ucode_info;\n    struct ieee80211_channel *ch;\n    struct iwn4965_cmd_txpower cmd;\n    struct iwn4965_eeprom_chan_samples *chans;\n    const uint8_t *rf_gain, *dsp_gain;\n    int32_t vdiff, tdiff;\n    int i, c, grp, maxpwr, is_ht40 = 0;\n    uint8_t chan, ext_chan;\n\n    /* Retrieve current channel from last RXON. */\n    chan = sc->rxon.chan;\n    DPRINTF((\"setting TX power for channel %d\\n\", chan));\n    ch = &ic->ic_channels[chan];\n\n    memset(&cmd, 0, sizeof cmd);\n    cmd.band = IEEE80211_IS_CHAN_5GHZ(ch) ? 0 : 1;\n    cmd.chan = chan;\n\n    if (IEEE80211_IS_CHAN_5GHZ(ch)) {\n        maxpwr   = sc->maxpwr5GHz;\n        rf_gain  = iwn4965_rf_gain_5ghz;\n        dsp_gain = iwn4965_dsp_gain_5ghz;\n    } else {\n        maxpwr   = sc->maxpwr2GHz;\n        rf_gain  = iwn4965_rf_gain_2ghz;\n        dsp_gain = iwn4965_dsp_gain_2ghz;\n    }\n\n    /* Compute voltage compensation. */\n    vdiff = ((int32_t)letoh32(uc->volt) - sc->eeprom_voltage) / 7;\n    if (vdiff > 0)\n        vdiff *= 2;\n    if (abs(vdiff) > 2)\n        vdiff = 0;\n    DPRINTF((\"voltage compensation=%d (UCODE=%d, EEPROM=%d)\\n\",\n        vdiff, letoh32(uc->volt), sc->eeprom_voltage));\n\n    /* Get channel attenuation group. */\n    if (chan <= 20)        /* 1-20 */\n        grp = 4;\n    else if (chan <= 43)    /* 34-43 */\n        grp = 0;\n    else if (chan <= 70)    /* 44-70 */\n        grp = 1;\n    else if (chan <= 124)    /* 71-124 */\n        grp = 2;\n    else            /* 125-200 */\n        grp = 3;\n    DPRINTF((\"chan %d, attenuation group=%d\\n\", chan, grp));\n\n    /* Get channel sub-band. */\n    for (i = 0; i < IWN_NBANDS; i++)\n        if (sc->bands[i].lo != 0 &&\n            sc->bands[i].lo <= chan && chan <= sc->bands[i].hi)\n            break;\n    if (i == IWN_NBANDS)    /* Can't happen in real-life. */\n        return EINVAL;\n    chans = sc->bands[i].chans;\n    DPRINTF((\"chan %d sub-band=%d\\n\", chan, i));\n    \n    if (that->iwn_rxon_ht40_enabled(sc)) {\n        is_ht40 = 1;\n        if (le32toh(sc->rxon.flags) & IWN_RXON_HT_HT40MINUS)\n            ext_chan = chan - 2;\n        else\n            ext_chan = chan + 2;\n    } else\n        ext_chan = chan;\n\n    for (c = 0; c < 2; c++) {\n        uint8_t power, gain, temp;\n        int maxchpwr, pwr, ridx, idx;\n\n        power = interpolate(ext_chan,\n            chans[0].num, chans[0].samples[c][1].power,\n            chans[1].num, chans[1].samples[c][1].power, 1);\n        gain  = interpolate(ext_chan,\n            chans[0].num, chans[0].samples[c][1].gain,\n            chans[1].num, chans[1].samples[c][1].gain, 1);\n        temp  = interpolate(ext_chan,\n            chans[0].num, chans[0].samples[c][1].temp,\n            chans[1].num, chans[1].samples[c][1].temp, 1);\n        DPRINTF((\"TX chain %d: power=%d gain=%d temp=%d\\n\",\n            c, power, gain, temp));\n\n        /* Compute temperature compensation. */\n        tdiff = ((sc->temp - temp) * 2) / tdiv[grp];\n        DPRINTF((\"temperature compensation=%d (current=%d, \"\n            \"EEPROM=%d)\\n\", tdiff, sc->temp, temp));\n\n        for (ridx = 0; ridx <= IWN_RIDX_MAX; ridx++) {\n            /* Convert dBm to half-dBm. */\n            if (is_ht40)\n                maxchpwr = sc->maxpwr40[chan] * 2;\n            else\n                maxchpwr = sc->maxpwr[chan] * 2;\n#ifdef notyet\n            if (ridx > iwn_mcs2ridx[7] && ridx < iwn_mcs2ridx[16])\n                maxchpwr -= 6;    /* MIMO 2T: -3dB */\n#endif\n\n            pwr = maxpwr;\n\n            /* Adjust TX power based on rate. */\n            if ((ridx % 8) == 5)\n                pwr -= 15;    /* OFDM48: -7.5dB */\n            else if ((ridx % 8) == 6)\n                pwr -= 17;    /* OFDM54: -8.5dB */\n            else if ((ridx % 8) == 7)\n                pwr -= 20;    /* OFDM60: -10dB */\n            else\n                pwr -= 10;    /* Others: -5dB */\n\n            /* Do not exceed channel max TX power. */\n            if (pwr > maxchpwr)\n                pwr = maxchpwr;\n\n            idx = gain - (pwr - power) - tdiff - vdiff;\n            if (ridx > iwn_mcs2ridx[7]) /* MIMO */\n                idx += (int32_t)letoh32(uc->atten[grp][c]);\n\n            if (cmd.band == 0)\n                idx += 9;    /* 5GHz */\n            if (ridx == IWN_RIDX_MAX)\n                idx += 5;    /* CCK */\n\n            /* Make sure idx stays in a valid range. */\n            if (idx < 0)\n                idx = 0;\n            else if (idx > IWN4965_MAX_PWR_INDEX)\n                idx = IWN4965_MAX_PWR_INDEX;\n\n            DPRINTF((\"TX chain %d, rate idx %d: power=%d\\n\",\n                c, ridx, idx));\n            cmd.power[ridx].rf_gain[c] = rf_gain[idx];\n            cmd.power[ridx].dsp_gain[c] = dsp_gain[idx];\n        }\n    }\n\n    DPRINTF((\"setting TX power for chan %d\\n\", chan));\n    return that->iwn_cmd(sc, IWN_CMD_TXPOWER, &cmd, sizeof cmd, async);\n\n#undef interpolate\n#undef fdivround\n}\n\nint ItlIwn::\niwn5000_set_txpower(struct iwn_softc *sc, int async)\n{\n    ItlIwn *that = container_of(sc, ItlIwn, com);\n    struct iwn5000_cmd_txpower cmd;\n\n    /*\n     * TX power calibration is handled automatically by the firmware\n     * for 5000 Series.\n     */\n    memset(&cmd, 0, sizeof cmd);\n    cmd.global_limit = 2 * IWN5000_TXPOWER_MAX_DBM;    /* 16 dBm */\n    cmd.flags = IWN5000_TXPOWER_NO_CLOSED;\n    cmd.srv_limit = IWN5000_TXPOWER_AUTO;\n    DPRINTF((\"setting TX power\\n\"));\n    return that->iwn_cmd(sc, IWN_CMD_TXPOWER_DBM, &cmd, sizeof cmd, async);\n}\n\n/*\n * Retrieve the maximum RSSI (in dBm) among receivers.\n */\nint ItlIwn::\niwn4965_get_rssi(const struct iwn_rx_stat *stat)\n{\n    struct iwn4965_rx_phystat *phy = (struct iwn4965_rx_phystat *)stat->phybuf;\n    uint8_t mask, agc;\n    int rssi;\n\n    mask = (letoh16(phy->antenna) >> 4) & IWN_ANT_ABC;\n    agc  = (letoh16(phy->agc) >> 7) & 0x7f;\n\n    rssi = 0;\n    if (mask & IWN_ANT_A)\n        rssi = MAX(rssi, phy->rssi[0]);\n    if (mask & IWN_ANT_B)\n        rssi = MAX(rssi, phy->rssi[2]);\n    if (mask & IWN_ANT_C)\n        rssi = MAX(rssi, phy->rssi[4]);\n\n    return rssi - agc - IWN_RSSI_TO_DBM;\n}\n\nint ItlIwn::\niwn5000_get_rssi(const struct iwn_rx_stat *stat)\n{\n    struct iwn5000_rx_phystat *phy = (struct iwn5000_rx_phystat *)stat->phybuf;\n    uint8_t agc;\n    int rssi;\n\n    agc = (letoh32(phy->agc) >> 9) & 0x7f;\n\n    rssi = MAX(letoh16(phy->rssi[0]) & 0xff,\n           letoh16(phy->rssi[1]) & 0xff);\n    rssi = MAX(letoh16(phy->rssi[2]) & 0xff, rssi);\n\n    return rssi - agc - IWN_RSSI_TO_DBM;\n}\n\n/*\n * Retrieve the average noise (in dBm) among receivers.\n */\nint ItlIwn::\niwn_get_noise(const struct iwn_rx_general_stats *stats)\n{\n    int i, total, nbant, noise;\n\n    total = nbant = 0;\n    for (i = 0; i < 3; i++) {\n        if ((noise = letoh32(stats->noise[i]) & 0xff) == 0)\n            continue;\n        total += noise;\n        nbant++;\n    }\n    /* There should be at least one antenna but check anyway. */\n    return (nbant == 0) ? -127 : (total / nbant) - 107;\n}\n\n/*\n * Compute temperature (in degC) from last received statistics.\n */\nint ItlIwn::\niwn4965_get_temperature(struct iwn_softc *sc)\n{\n    struct iwn_ucode_info *uc = &sc->ucode_info;\n    int32_t r1, r2, r3, r4, temp;\n\n    if (sc->rx_stats_flags & IWN_STATS_FLAGS_BAND_HT40) {\n        r1 = letoh32(uc->temp[0].chan40MHz);\n        r2 = letoh32(uc->temp[1].chan40MHz);\n        r3 = letoh32(uc->temp[2].chan40MHz);\n    } else {\n        r1 = letoh32(uc->temp[0].chan20MHz);\n        r2 = letoh32(uc->temp[1].chan20MHz);\n        r3 = letoh32(uc->temp[2].chan20MHz);\n    }\n    r4 = letoh32(sc->rawtemp);\n\n    if (r1 == r3)    /* Prevents division by 0 (should not happen). */\n        return 0;\n\n    /* Sign-extend 23-bit R4 value to 32-bit. */\n    r4 = ((r4 & 0xffffff) ^ 0x800000) - 0x800000;\n    /* Compute temperature in Kelvin. */\n    temp = (259 * (r4 - r2)) / (r3 - r1);\n    temp = (temp * 97) / 100 + 8;\n\n    DPRINTF((\"temperature %dK/%dC\\n\", temp, IWN_KTOC(temp)));\n    return IWN_KTOC(temp);\n}\n\nint ItlIwn::\niwn5000_get_temperature(struct iwn_softc *sc)\n{\n    int32_t temp;\n\n    /*\n     * Temperature is not used by the driver for 5000 Series because\n     * TX power calibration is handled by firmware.\n     */\n    temp = letoh32(sc->rawtemp);\n    if (sc->hw_type == IWN_HW_REV_TYPE_5150) {\n        temp = (temp / -5) + sc->temp_off;\n        temp = IWN_KTOC(temp);\n    }\n    return temp;\n}\n\n/*\n * Initialize sensitivity calibration state machine.\n */\nint ItlIwn::\niwn_init_sensitivity(struct iwn_softc *sc)\n{\n    struct iwn_ops *ops = &sc->ops;\n    struct iwn_calib_state *calib = &sc->calib;\n    uint32_t flags;\n    int error;\n\n    /* Reset calibration state machine. */\n    memset(calib, 0, sizeof (*calib));\n    calib->state = IWN_CALIB_STATE_INIT;\n    calib->cck_state = IWN_CCK_STATE_HIFA;\n    /* Set initial correlation values. */\n    calib->ofdm_x1     = sc->limits->min_ofdm_x1;\n    calib->ofdm_mrc_x1 = sc->limits->min_ofdm_mrc_x1;\n    calib->ofdm_x4     = sc->limits->min_ofdm_x4;\n    calib->ofdm_mrc_x4 = sc->limits->min_ofdm_mrc_x4;\n    calib->cck_x4      = 125;\n    calib->cck_mrc_x4  = sc->limits->min_cck_mrc_x4;\n    calib->energy_cck  = sc->limits->energy_cck;\n\n    /* Write initial sensitivity. */\n    if ((error = iwn_send_sensitivity(sc)) != 0)\n        return error;\n\n    /* Write initial gains. */\n    if ((error = ops->init_gains(sc)) != 0)\n        return error;\n\n    /* Request statistics at each beacon interval. */\n    flags = 0;\n    DPRINTFN(2, (\"sending request for statistics\\n\"));\n    return iwn_cmd(sc, IWN_CMD_GET_STATISTICS, &flags, sizeof flags, 1);\n}\n\n/*\n * Collect noise and RSSI statistics for the first 20 beacons received\n * after association and use them to determine connected antennas and\n * to set differential gains.\n */\nvoid ItlIwn::\niwn_collect_noise(struct iwn_softc *sc,\n    const struct iwn_rx_general_stats *stats)\n{\n    struct iwn_ops *ops = &sc->ops;\n    struct iwn_calib_state *calib = &sc->calib;\n    uint32_t val;\n    int i;\n\n    /* Accumulate RSSI and noise for all 3 antennas. */\n    for (i = 0; i < 3; i++) {\n        calib->rssi[i] += letoh32(stats->rssi[i]) & 0xff;\n        calib->noise[i] += letoh32(stats->noise[i]) & 0xff;\n    }\n    /* NB: We update differential gains only once after 20 beacons. */\n    if (++calib->nbeacons < 20)\n        return;\n\n    /* Determine highest average RSSI. */\n    val = MAX(calib->rssi[0], calib->rssi[1]);\n    val = MAX(calib->rssi[2], val);\n\n    /* Determine which antennas are connected. */\n    sc->chainmask = sc->rxchainmask;\n    for (i = 0; i < 3; i++)\n        if (val - calib->rssi[i] > 15 * 20)\n            sc->chainmask &= ~(1 << i);\n    DPRINTF((\"RX chains mask: theoretical=0x%x, actual=0x%x\\n\",\n        sc->rxchainmask, sc->chainmask));\n\n    /* If none of the TX antennas are connected, keep at least one. */\n    if ((sc->chainmask & sc->txchainmask) == 0)\n        sc->chainmask |= IWN_LSB(sc->txchainmask);\n\n    (void)ops->set_gains(sc);\n    calib->state = IWN_CALIB_STATE_RUN;\n\n#ifdef notyet\n    /* XXX Disable RX chains with no antennas connected. */\n    sc->rxon.rxchain = htole16(IWN_RXCHAIN_SEL(sc->chainmask));\n    (void)iwn_cmd(sc, IWN_CMD_RXON, &sc->rxon, sc->rxonsz, 1);\n#endif\n\n    /* Enable power-saving mode if requested by user. */\n    if (sc->sc_ic.ic_flags & IEEE80211_F_PMGTON)\n        (void)iwn_set_pslevel(sc, 0, 3, 1);\n}\n\nint ItlIwn::\niwn4965_init_gains(struct iwn_softc *sc)\n{\n    ItlIwn *that = container_of(sc, ItlIwn, com);\n    struct iwn_phy_calib_gain cmd;\n\n    memset(&cmd, 0, sizeof cmd);\n    cmd.code = IWN4965_PHY_CALIB_DIFF_GAIN;\n    /* Differential gains initially set to 0 for all 3 antennas. */\n    DPRINTF((\"setting initial differential gains\\n\"));\n    return that->iwn_cmd(sc, IWN_CMD_PHY_CALIB, &cmd, sizeof cmd, 1);\n}\n\nint ItlIwn::\niwn5000_init_gains(struct iwn_softc *sc)\n{\n    ItlIwn *that = container_of(sc, ItlIwn, com);\n    struct iwn_phy_calib cmd;\n\n    memset(&cmd, 0, sizeof cmd);\n    cmd.code = sc->reset_noise_gain;\n    cmd.ngroups = 1;\n    cmd.isvalid = 1;\n    DPRINTF((\"setting initial differential gains\\n\"));\n    return that->iwn_cmd(sc, IWN_CMD_PHY_CALIB, &cmd, sizeof cmd, 1);\n}\n\nint ItlIwn::\niwn4965_set_gains(struct iwn_softc *sc)\n{\n    ItlIwn *that = container_of(sc, ItlIwn, com);\n    struct iwn_calib_state *calib = &sc->calib;\n    struct iwn_phy_calib_gain cmd;\n    int i, delta, noise;\n\n    /* Get minimal noise among connected antennas. */\n    noise = INT_MAX;    /* NB: There's at least one antenna. */\n    for (i = 0; i < 3; i++)\n        if (sc->chainmask & (1 << i))\n            noise = MIN(calib->noise[i], noise);\n\n    memset(&cmd, 0, sizeof cmd);\n    cmd.code = IWN4965_PHY_CALIB_DIFF_GAIN;\n    /* Set differential gains for connected antennas. */\n    for (i = 0; i < 3; i++) {\n        if (sc->chainmask & (1 << i)) {\n            /* Compute attenuation (in unit of 1.5dB). */\n            delta = (noise - (int32_t)calib->noise[i]) / 30;\n            /* NB: delta <= 0 */\n            /* Limit to [-4.5dB,0]. */\n            cmd.gain[i] = MIN(abs(delta), 3);\n            if (delta < 0)\n                cmd.gain[i] |= 1 << 2;    /* sign bit */\n        }\n    }\n    DPRINTF((\"setting differential gains Ant A/B/C: %x/%x/%x (%x)\\n\",\n        cmd.gain[0], cmd.gain[1], cmd.gain[2], sc->chainmask));\n    return that->iwn_cmd(sc, IWN_CMD_PHY_CALIB, &cmd, sizeof cmd, 1);\n}\n\nint ItlIwn::\niwn5000_set_gains(struct iwn_softc *sc)\n{\n    ItlIwn *that = container_of(sc, ItlIwn, com);\n    struct iwn_calib_state *calib = &sc->calib;\n    struct iwn_phy_calib_gain cmd;\n    int i, ant, div, delta;\n\n    /* We collected 20 beacons and !=6050 need a 1.5 factor. */\n    div = (sc->hw_type == IWN_HW_REV_TYPE_6050) ? 20 : 30;\n\n    memset(&cmd, 0, sizeof cmd);\n    cmd.code = sc->noise_gain;\n    cmd.ngroups = 1;\n    cmd.isvalid = 1;\n    /*\n     * Get first available RX antenna as referential.\n     * IWN_LSB() return values start with 1, but antenna gain array\n     * cmd.gain[] and noise array calib->noise[] start with 0.\n     */\n    ant = IWN_LSB(sc->rxchainmask) - 1;\n\n    /* Set differential gains for other antennas. */\n    for (i = ant + 1; i < 3; i++) {\n        if (sc->chainmask & (1 << i)) {\n            /* The delta is relative to antenna \"ant\". */\n            delta = ((int32_t)calib->noise[ant] -\n                (int32_t)calib->noise[i]) / div;\n            DPRINTF((\"Ant[%d] vs. Ant[%d]: delta %d\\n\", ant, i, delta));\n            /* Limit to [-4.5dB,+4.5dB]. */\n            cmd.gain[i] = MIN(abs(delta), 3);\n            if (delta < 0)\n                cmd.gain[i] |= 1 << 2;    /* sign bit */\n            DPRINTF((\"Setting differential gains for antenna %d: %x\\n\",\n                i, cmd.gain[i]));\n        }\n    }\n    return that->iwn_cmd(sc, IWN_CMD_PHY_CALIB, &cmd, sizeof cmd, 1);\n}\n\n/*\n * Tune RF RX sensitivity based on the number of false alarms detected\n * during the last beacon period.\n */\nvoid ItlIwn::\niwn_tune_sensitivity(struct iwn_softc *sc, const struct iwn_rx_stats *stats)\n{\n#define inc(val, inc, max)            \\\n    if ((val) < (max)) {            \\\n        if ((val) < (max) - (inc))    \\\n            (val) += (inc);        \\\n        else                \\\n            (val) = (max);        \\\n        needs_update = 1;        \\\n    }\n#define dec(val, dec, min)            \\\n    if ((val) > (min)) {            \\\n        if ((val) > (min) + (dec))    \\\n            (val) -= (dec);        \\\n        else                \\\n            (val) = (min);        \\\n        needs_update = 1;        \\\n    }\n\n    const struct iwn_sensitivity_limits *limits = sc->limits;\n    struct iwn_calib_state *calib = &sc->calib;\n    uint32_t val, rxena, fa;\n    uint32_t energy[3], energy_min;\n    uint8_t noise[3], noise_ref;\n    int i, needs_update = 0;\n\n    /* Check that we've been enabled long enough. */\n    if ((rxena = letoh32(stats->general.load)) == 0)\n        return;\n\n    /* Compute number of false alarms since last call for OFDM. */\n    fa  = letoh32(stats->ofdm.bad_plcp) - calib->bad_plcp_ofdm;\n    fa += letoh32(stats->ofdm.fa) - calib->fa_ofdm;\n    fa *= 200 * IEEE80211_DUR_TU;    /* 200TU */\n\n    /* Save counters values for next call. */\n    calib->bad_plcp_ofdm = letoh32(stats->ofdm.bad_plcp);\n    calib->fa_ofdm = letoh32(stats->ofdm.fa);\n\n    if (fa > 50 * rxena) {\n        /* High false alarm count, decrease sensitivity. */\n        DPRINTFN(2, (\"OFDM high false alarm count: %u\\n\", fa));\n        inc(calib->ofdm_x1,     1, limits->max_ofdm_x1);\n        inc(calib->ofdm_mrc_x1, 1, limits->max_ofdm_mrc_x1);\n        inc(calib->ofdm_x4,     1, limits->max_ofdm_x4);\n        inc(calib->ofdm_mrc_x4, 1, limits->max_ofdm_mrc_x4);\n\n    } else if (fa < 5 * rxena) {\n        /* Low false alarm count, increase sensitivity. */\n        DPRINTFN(2, (\"OFDM low false alarm count: %u\\n\", fa));\n        dec(calib->ofdm_x1,     1, limits->min_ofdm_x1);\n        dec(calib->ofdm_mrc_x1, 1, limits->min_ofdm_mrc_x1);\n        dec(calib->ofdm_x4,     1, limits->min_ofdm_x4);\n        dec(calib->ofdm_mrc_x4, 1, limits->min_ofdm_mrc_x4);\n    }\n\n    /* Compute maximum noise among 3 receivers. */\n    for (i = 0; i < 3; i++)\n        noise[i] = (letoh32(stats->general.noise[i]) >> 8) & 0xff;\n    val = MAX(noise[0], noise[1]);\n    val = MAX(noise[2], val);\n    /* Insert it into our samples table. */\n    calib->noise_samples[calib->cur_noise_sample] = val;\n    calib->cur_noise_sample = (calib->cur_noise_sample + 1) % 20;\n\n    /* Compute maximum noise among last 20 samples. */\n    noise_ref = calib->noise_samples[0];\n    for (i = 1; i < 20; i++)\n        noise_ref = MAX(noise_ref, calib->noise_samples[i]);\n\n    /* Compute maximum energy among 3 receivers. */\n    for (i = 0; i < 3; i++)\n        energy[i] = letoh32(stats->general.energy[i]);\n    val = MIN(energy[0], energy[1]);\n    val = MIN(energy[2], val);\n    /* Insert it into our samples table. */\n    calib->energy_samples[calib->cur_energy_sample] = val;\n    calib->cur_energy_sample = (calib->cur_energy_sample + 1) % 10;\n\n    /* Compute minimum energy among last 10 samples. */\n    energy_min = calib->energy_samples[0];\n    for (i = 1; i < 10; i++)\n        energy_min = MAX(energy_min, calib->energy_samples[i]);\n    energy_min += 6;\n\n    /* Compute number of false alarms since last call for CCK. */\n    fa  = letoh32(stats->cck.bad_plcp) - calib->bad_plcp_cck;\n    fa += letoh32(stats->cck.fa) - calib->fa_cck;\n    fa *= 200 * IEEE80211_DUR_TU;    /* 200TU */\n\n    /* Save counters values for next call. */\n    calib->bad_plcp_cck = letoh32(stats->cck.bad_plcp);\n    calib->fa_cck = letoh32(stats->cck.fa);\n\n    if (fa > 50 * rxena) {\n        /* High false alarm count, decrease sensitivity. */\n        DPRINTFN(2, (\"CCK high false alarm count: %u\\n\", fa));\n        calib->cck_state = IWN_CCK_STATE_HIFA;\n        calib->low_fa = 0;\n\n        if (calib->cck_x4 > 160) {\n            calib->noise_ref = noise_ref;\n            if (calib->energy_cck > 2)\n                dec(calib->energy_cck, 2, energy_min);\n        }\n        if (calib->cck_x4 < 160) {\n            calib->cck_x4 = 161;\n            needs_update = 1;\n        } else\n            inc(calib->cck_x4, 3, limits->max_cck_x4);\n\n        inc(calib->cck_mrc_x4, 3, limits->max_cck_mrc_x4);\n\n    } else if (fa < 5 * rxena) {\n        /* Low false alarm count, increase sensitivity. */\n        DPRINTFN(2, (\"CCK low false alarm count: %u\\n\", fa));\n        calib->cck_state = IWN_CCK_STATE_LOFA;\n        calib->low_fa++;\n\n        if (calib->cck_state != IWN_CCK_STATE_INIT &&\n            (((int32_t)calib->noise_ref - (int32_t)noise_ref) > 2 ||\n             calib->low_fa > 100)) {\n            inc(calib->energy_cck, 2, limits->min_energy_cck);\n            dec(calib->cck_x4,     3, limits->min_cck_x4);\n            dec(calib->cck_mrc_x4, 3, limits->min_cck_mrc_x4);\n        }\n    } else {\n        /* Not worth to increase or decrease sensitivity. */\n        DPRINTFN(2, (\"CCK normal false alarm count: %u\\n\", fa));\n        calib->low_fa = 0;\n        calib->noise_ref = noise_ref;\n\n        if (calib->cck_state == IWN_CCK_STATE_HIFA) {\n            /* Previous interval had many false alarms. */\n            dec(calib->energy_cck, 8, energy_min);\n        }\n        calib->cck_state = IWN_CCK_STATE_INIT;\n    }\n\n    if (needs_update)\n        (void)iwn_send_sensitivity(sc);\n#undef dec\n#undef inc\n}\n\nint ItlIwn::\niwn_send_sensitivity(struct iwn_softc *sc)\n{\n    struct iwn_calib_state *calib = &sc->calib;\n    struct iwn_enhanced_sensitivity_cmd cmd;\n    int len;\n\n    memset(&cmd, 0, sizeof cmd);\n    len = sizeof (struct iwn_sensitivity_cmd);\n    cmd.which = IWN_SENSITIVITY_WORKTBL;\n    /* OFDM modulation. */\n    cmd.corr_ofdm_x1       = htole16(calib->ofdm_x1);\n    cmd.corr_ofdm_mrc_x1   = htole16(calib->ofdm_mrc_x1);\n    cmd.corr_ofdm_x4       = htole16(calib->ofdm_x4);\n    cmd.corr_ofdm_mrc_x4   = htole16(calib->ofdm_mrc_x4);\n    cmd.energy_ofdm        = htole16(sc->limits->energy_ofdm);\n    cmd.energy_ofdm_th     = htole16(62);\n    /* CCK modulation. */\n    cmd.corr_cck_x4        = htole16(calib->cck_x4);\n    cmd.corr_cck_mrc_x4    = htole16(calib->cck_mrc_x4);\n    cmd.energy_cck         = htole16(calib->energy_cck);\n    /* Barker modulation: use default values. */\n    cmd.corr_barker        = htole16(190);\n    cmd.corr_barker_mrc    = htole16(390);\n    if (!(sc->sc_flags & IWN_FLAG_ENH_SENS))\n        goto send;\n    /* Enhanced sensitivity settings. */\n    len = sizeof (struct iwn_enhanced_sensitivity_cmd);\n    cmd.ofdm_det_slope_mrc = htole16(668);\n    cmd.ofdm_det_icept_mrc = htole16(4);\n    cmd.ofdm_det_slope     = htole16(486);\n    cmd.ofdm_det_icept     = htole16(37);\n    cmd.cck_det_slope_mrc  = htole16(853);\n    cmd.cck_det_icept_mrc  = htole16(4);\n    cmd.cck_det_slope      = htole16(476);\n    cmd.cck_det_icept      = htole16(99);\nsend:\n    return iwn_cmd(sc, IWN_CMD_SET_SENSITIVITY, &cmd, len, 1);\n}\n\n/*\n * Set STA mode power saving level (between 0 and 5).\n * Level 0 is CAM (Continuously Aware Mode), 5 is for maximum power saving.\n */\nint ItlIwn::\niwn_set_pslevel(struct iwn_softc *sc, int dtim, int level, int async)\n{\n    struct iwn_pmgt_cmd cmd;\n    const struct iwn_pmgt *pmgt;\n    uint32_t max, skip_dtim;\n    pcireg_t reg;\n    int i;\n\n    /* Select which PS parameters to use. */\n    if (dtim <= 2)\n        pmgt = &iwn_pmgt[0][level];\n    else if (dtim <= 10)\n        pmgt = &iwn_pmgt[1][level];\n    else\n        pmgt = &iwn_pmgt[2][level];\n\n    memset(&cmd, 0, sizeof cmd);\n    if (level != 0)    /* not CAM */\n        cmd.flags |= htole16(IWN_PS_ALLOW_SLEEP);\n    if (level == 5)\n        cmd.flags |= htole16(IWN_PS_FAST_PD);\n    /* Retrieve PCIe Active State Power Management (ASPM). */\n    reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag,\n        sc->sc_cap_off + PCI_PCIE_LCSR);\n    if (!(reg & PCI_PCIE_LCSR_ASPM_L0S))    /* L0s Entry disabled. */\n        cmd.flags |= htole16(IWN_PS_PCI_PMGT);\n    cmd.rxtimeout = htole32(pmgt->rxtimeout * 1024);\n    cmd.txtimeout = htole32(pmgt->txtimeout * 1024);\n\n    if (dtim == 0) {\n        dtim = 1;\n        skip_dtim = 0;\n    } else\n        skip_dtim = pmgt->skip_dtim;\n    if (skip_dtim != 0) {\n        cmd.flags |= htole16(IWN_PS_SLEEP_OVER_DTIM);\n        max = pmgt->intval[4];\n        if (max == (uint32_t)-1)\n            max = dtim * (skip_dtim + 1);\n        else if (max > dtim)\n            max = (max / dtim) * dtim;\n    } else\n        max = dtim;\n    for (i = 0; i < 5; i++)\n        cmd.intval[i] = htole32(MIN(max, pmgt->intval[i]));\n\n    DPRINTF((\"setting power saving level to %d\\n\", level));\n    return iwn_cmd(sc, IWN_CMD_SET_POWER_MODE, &cmd, sizeof cmd, async);\n}\n\nint ItlIwn::\niwn_send_btcoex(struct iwn_softc *sc)\n{\n    struct iwn_bluetooth cmd;\n\n    memset(&cmd, 0, sizeof cmd);\n    cmd.flags = IWN_BT_COEX_CHAN_ANN | IWN_BT_COEX_BT_PRIO;\n    cmd.lead_time = IWN_BT_LEAD_TIME_DEF;\n    cmd.max_kill = IWN_BT_MAX_KILL_DEF;\n    DPRINTF((\"configuring bluetooth coexistence\\n\"));\n    return iwn_cmd(sc, IWN_CMD_BT_COEX, &cmd, sizeof(cmd), 0);\n}\n\nint ItlIwn::\niwn_send_advanced_btcoex(struct iwn_softc *sc)\n{\n    static const uint32_t btcoex_3wire[12] = {\n        0xaaaaaaaa, 0xaaaaaaaa, 0xaeaaaaaa, 0xaaaaaaaa,\n        0xcc00ff28, 0x0000aaaa, 0xcc00aaaa, 0x0000aaaa,\n        0xc0004000, 0x00004000, 0xf0005000, 0xf0005000,\n    };\n    struct iwn_btcoex_priotable btprio;\n    struct iwn_btcoex_prot btprot;\n    int error, i;\n\n    if (sc->hw_type == IWN_HW_REV_TYPE_2030 ||\n        sc->hw_type == IWN_HW_REV_TYPE_135) {\n        struct iwn2000_btcoex_config btconfig;\n\n        memset(&btconfig, 0, sizeof btconfig);\n        btconfig.flags = IWN_BT_COEX6000_CHAN_INHIBITION |\n            (IWN_BT_COEX6000_MODE_3W << IWN_BT_COEX6000_MODE_SHIFT) |\n            IWN_BT_SYNC_2_BT_DISABLE;\n        btconfig.max_kill = 5;\n        btconfig.bt3_t7_timer = 1;\n        btconfig.kill_ack = htole32(0xffff0000);\n        btconfig.kill_cts = htole32(0xffff0000);\n        btconfig.sample_time = 2;\n        btconfig.bt3_t2_timer = 0xc;\n        for (i = 0; i < 12; i++)\n            btconfig.lookup_table[i] = htole32(btcoex_3wire[i]);\n        btconfig.valid = htole16(0xff);\n        btconfig.prio_boost = htole32(0xf0);\n        DPRINTF((\"configuring advanced bluetooth coexistence\\n\"));\n        error = iwn_cmd(sc, IWN_CMD_BT_COEX, &btconfig,\n            sizeof(btconfig), 1);\n        if (error != 0)\n            return (error);\n    } else {\n        struct iwn6000_btcoex_config btconfig;\n\n        memset(&btconfig, 0, sizeof btconfig);\n        btconfig.flags = IWN_BT_COEX6000_CHAN_INHIBITION |\n            (IWN_BT_COEX6000_MODE_3W << IWN_BT_COEX6000_MODE_SHIFT) |\n            IWN_BT_SYNC_2_BT_DISABLE;\n        btconfig.max_kill = 5;\n        btconfig.bt3_t7_timer = 1;\n        btconfig.kill_ack = htole32(0xffff0000);\n        btconfig.kill_cts = htole32(0xffff0000);\n        btconfig.sample_time = 2;\n        btconfig.bt3_t2_timer = 0xc;\n        for (i = 0; i < 12; i++)\n            btconfig.lookup_table[i] = htole32(btcoex_3wire[i]);\n        btconfig.valid = htole16(0xff);\n        btconfig.prio_boost = 0xf0;\n        DPRINTF((\"configuring advanced bluetooth coexistence\\n\"));\n        error = iwn_cmd(sc, IWN_CMD_BT_COEX, &btconfig,\n            sizeof(btconfig), 1);\n        if (error != 0)\n            return (error);\n    }\n\n    memset(&btprio, 0, sizeof btprio);\n    btprio.calib_init1 = 0x6;\n    btprio.calib_init2 = 0x7;\n    btprio.calib_periodic_low1 = 0x2;\n    btprio.calib_periodic_low2 = 0x3;\n    btprio.calib_periodic_high1 = 0x4;\n    btprio.calib_periodic_high2 = 0x5;\n    btprio.dtim = 0x6;\n    btprio.scan52 = 0x8;\n    btprio.scan24 = 0xa;\n    error = iwn_cmd(sc, IWN_CMD_BT_COEX_PRIOTABLE, &btprio, sizeof(btprio),\n        1);\n    if (error != 0)\n        return (error);\n\n    /* Force BT state machine change */\n    memset(&btprot, 0, sizeof btprot);\n    btprot.open = 1;\n    btprot.type = 1;\n    error = iwn_cmd(sc, IWN_CMD_BT_COEX_PROT, &btprot, sizeof(btprot), 1);\n    if (error != 0)\n        return (error);\n\n    btprot.open = 0;\n    return (iwn_cmd(sc, IWN_CMD_BT_COEX_PROT, &btprot, sizeof(btprot), 1));\n}\n\nint ItlIwn::\niwn5000_runtime_calib(struct iwn_softc *sc)\n{\n    struct iwn5000_calib_config cmd;\n\n    memset(&cmd, 0, sizeof cmd);\n    cmd.ucode.once.enable = 0xffffffff;\n    cmd.ucode.once.start = IWN5000_CALIB_DC;\n    DPRINTF((\"configuring runtime calibration\\n\"));\n    return iwn_cmd(sc, IWN5000_CMD_CALIB_CONFIG, &cmd, sizeof(cmd), 0);\n}\n\nint ItlIwn::\niwn_config(struct iwn_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwn_ops *ops = &sc->ops;\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct _ifnet *ifp = &ic->ic_if;\n    uint32_t txmask;\n    uint16_t rxchain;\n    int error, ridx;\n\n    /* Set radio temperature sensor offset. */\n    if (sc->hw_type == IWN_HW_REV_TYPE_6005) {\n        error = iwn6000_temp_offset_calib(sc);\n        if (error != 0) {\n            XYLog(\"%s: could not set temperature offset\\n\",\n                sc->sc_dev.dv_xname);\n            return error;\n        }\n    }\n\n    if (sc->hw_type == IWN_HW_REV_TYPE_2030 ||\n        sc->hw_type == IWN_HW_REV_TYPE_2000 ||\n        sc->hw_type == IWN_HW_REV_TYPE_135 ||\n        sc->hw_type == IWN_HW_REV_TYPE_105) {\n        error = iwn2000_temp_offset_calib(sc);\n        if (error != 0) {\n            XYLog(\"%s: could not set temperature offset\\n\",\n                sc->sc_dev.dv_xname);\n            return error;\n        }\n    }\n\n    if (sc->hw_type == IWN_HW_REV_TYPE_6050 ||\n        sc->hw_type == IWN_HW_REV_TYPE_6005) {\n        /* Configure runtime DC calibration. */\n        error = iwn5000_runtime_calib(sc);\n        if (error != 0) {\n            XYLog(\"%s: could not configure runtime calibration\\n\",\n                sc->sc_dev.dv_xname);\n            return error;\n        }\n    }\n\n    /* Configure valid TX chains for >=5000 Series. */\n    if (sc->hw_type != IWN_HW_REV_TYPE_4965) {\n        txmask = htole32(sc->txchainmask);\n        DPRINTF((\"configuring valid TX chains 0x%x\\n\", txmask));\n        error = iwn_cmd(sc, IWN5000_CMD_TX_ANT_CONFIG, &txmask,\n            sizeof txmask, 0);\n        if (error != 0) {\n            XYLog(\"%s: could not configure valid TX chains\\n\",\n                sc->sc_dev.dv_xname);\n            return error;\n        }\n    }\n\n    /* Configure bluetooth coexistence. */\n    if (sc->sc_flags & IWN_FLAG_ADV_BT_COEX)\n        error = iwn_send_advanced_btcoex(sc);\n    else\n        error = iwn_send_btcoex(sc);\n    if (error != 0) {\n        XYLog(\"%s: could not configure bluetooth coexistence\\n\",\n            sc->sc_dev.dv_xname);\n        return error;\n    }\n\n    /* Set mode, channel, RX filter and enable RX. */\n    memset(&sc->rxon, 0, sizeof (struct iwn_rxon));\n//    IEEE80211_ADDR_COPY(ic->ic_myaddr, LLADDR(ifp->if_sadl));\n    IEEE80211_ADDR_COPY(sc->rxon.myaddr, ic->ic_myaddr);\n    IEEE80211_ADDR_COPY(sc->rxon.wlap, ic->ic_myaddr);\n    sc->rxon.chan = ieee80211_chan2ieee(ic, ic->ic_ibss_chan);\n    sc->rxon.flags = htole32(IWN_RXON_TSF | IWN_RXON_CTS_TO_SELF);\n    if (IEEE80211_IS_CHAN_2GHZ(ic->ic_ibss_chan)) {\n        sc->rxon.flags |= htole32(IWN_RXON_AUTO | IWN_RXON_24GHZ);\n        if (ic->ic_flags & IEEE80211_F_USEPROT)\n            sc->rxon.flags |= htole32(IWN_RXON_TGG_PROT);\n        DPRINTF((\"%s: 2ghz prot 0x%x\\n\", __func__,\n            le32toh(sc->rxon.flags)));\n    }\n    switch (ic->ic_opmode) {\n    case IEEE80211_M_STA:\n        sc->rxon.mode = IWN_MODE_STA;\n        sc->rxon.filter = htole32(IWN_FILTER_MULTICAST);\n        break;\n    case IEEE80211_M_MONITOR:\n        sc->rxon.mode = IWN_MODE_MONITOR;\n        sc->rxon.filter = htole32(IWN_FILTER_MULTICAST |\n            IWN_FILTER_CTL | IWN_FILTER_PROMISC);\n        break;\n    default:\n        /* Should not get there. */\n        break;\n    }\n    sc->rxon.cck_mask  = 0x0f;    /* not yet negotiated */\n    sc->rxon.ofdm_mask = 0xff;    /* not yet negotiated */\n    sc->rxon.ht_single_mask = 0xff;\n    sc->rxon.ht_dual_mask = 0xff;\n    sc->rxon.ht_triple_mask = 0xff;\n    rxchain =\n        IWN_RXCHAIN_VALID(sc->rxchainmask) |\n        IWN_RXCHAIN_MIMO_COUNT(sc->nrxchains) |\n        IWN_RXCHAIN_IDLE_COUNT(sc->nrxchains);\n    if (ic->ic_opmode == IEEE80211_M_MONITOR) {\n        rxchain |= IWN_RXCHAIN_FORCE_SEL(sc->rxchainmask);\n        rxchain |= IWN_RXCHAIN_FORCE_MIMO_SEL(sc->rxchainmask);\n            rxchain |= (IWN_RXCHAIN_DRIVER_FORCE | IWN_RXCHAIN_MIMO_FORCE);\n    }\n    sc->rxon.rxchain = htole16(rxchain);\n    DPRINTF((\"setting configuration\\n\"));\n    DPRINTF((\"%s: rxon chan %d flags %x cck %x ofdm %x rxchain %x\\n\",\n        __func__, sc->rxon.chan, le32toh(sc->rxon.flags), sc->rxon.cck_mask,\n        sc->rxon.ofdm_mask, sc->rxon.rxchain));\n    error = iwn_cmd(sc, IWN_CMD_RXON, &sc->rxon, sc->rxonsz, 0);\n    if (error != 0) {\n        XYLog(\"%s: RXON command failed\\n\", sc->sc_dev.dv_xname);\n        return error;\n    }\n\n    ridx = (sc->sc_ic.ic_curmode == IEEE80211_MODE_11A) ?\n        IWN_RIDX_OFDM : IWN_RIDX_CCK;\n    if ((error = iwn_add_broadcast_node(sc, 0, ridx)) != 0) {\n        XYLog(\"%s: could not add broadcast node\\n\",\n            sc->sc_dev.dv_xname);\n        return error;\n    }\n\n    /* Configuration has changed, set TX power accordingly. */\n    if ((error = ops->set_txpower(sc, 0)) != 0) {\n        XYLog(\"%s: could not set TX power\\n\", sc->sc_dev.dv_xname);\n        return error;\n    }\n\n    if ((error = iwn_set_critical_temp(sc)) != 0) {\n        XYLog(\"%s: could not set critical temperature\\n\",\n            sc->sc_dev.dv_xname);\n        return error;\n    }\n\n    /* Set power saving level to CAM during initialization. */\n    if ((error = iwn_set_pslevel(sc, 0, 0, 0)) != 0) {\n        XYLog(\"%s: could not set power saving level\\n\",\n            sc->sc_dev.dv_xname);\n        return error;\n    }\n    return 0;\n}\n\nuint16_t ItlIwn::\niwn_get_active_dwell_time(struct iwn_softc *sc,\n    uint16_t flags, uint8_t n_probes)\n{\n    /* No channel? Default to 2GHz settings */\n    if (flags & IEEE80211_CHAN_2GHZ) {\n        return (IWN_ACTIVE_DWELL_TIME_2GHZ +\n        IWN_ACTIVE_DWELL_FACTOR_2GHZ * (n_probes + 1));\n    }\n\n    /* 5GHz dwell time */\n    return (IWN_ACTIVE_DWELL_TIME_5GHZ +\n        IWN_ACTIVE_DWELL_FACTOR_5GHZ * (n_probes + 1));\n}\n\n/*\n * Limit the total dwell time to 85% of the beacon interval.\n *\n * Returns the dwell time in milliseconds.\n */\nuint16_t ItlIwn::\niwn_limit_dwell(struct iwn_softc *sc, uint16_t dwell_time)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct ieee80211_node *ni = ic->ic_bss;\n    int bintval = 0;\n\n    /* bintval is in TU (1.024mS) */\n    if (ni != NULL)\n        bintval = ni->ni_intval;\n\n    /*\n     * If it's non-zero, we should calculate the minimum of\n     * it and the DWELL_BASE.\n     *\n     * XXX Yes, the math should take into account that bintval\n     * is 1.024mS, not 1mS..\n     */\n    if (ic->ic_state == IEEE80211_S_RUN && bintval > 0)\n        return (MIN(IWN_PASSIVE_DWELL_BASE, ((bintval * 85) / 100)));\n\n    /* No association context? Default */\n    return dwell_time;\n}\n\nuint16_t ItlIwn::\niwn_get_passive_dwell_time(struct iwn_softc *sc, uint16_t flags)\n{\n    uint16_t passive;\n    if (flags & IEEE80211_CHAN_2GHZ) {\n        passive = IWN_PASSIVE_DWELL_BASE + IWN_PASSIVE_DWELL_TIME_2GHZ;\n    } else {\n        passive = IWN_PASSIVE_DWELL_BASE + IWN_PASSIVE_DWELL_TIME_5GHZ;\n    }\n\n    /* Clamp to the beacon interval if we're associated */\n    return (iwn_limit_dwell(sc, passive));\n}\n\nint ItlIwn::\niwn_scan(struct iwn_softc *sc, uint16_t flags, int bgscan)\n{\n    XYLog(\"%s flags=%d bgscan=%d\\n\", __FUNCTION__, flags, bgscan);\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct iwn_scan_hdr *hdr;\n    struct iwn_cmd_data *tx;\n    struct iwn_scan_essid *essid;\n    struct iwn_scan_chan *chan;\n    struct ieee80211_frame *wh;\n    struct ieee80211_rateset *rs;\n    struct ieee80211_channel *c;\n    uint8_t *buf, *frm;\n    uint16_t rxchain, dwell_active, dwell_passive;\n    uint8_t txant;\n    int buflen, error, is_active;\n\n    buf = (uint8_t *)malloc(IWN_SCAN_MAXSZ, M_DEVBUF, M_NOWAIT | M_ZERO);\n    if (buf == NULL) {\n        XYLog(\"%s: could not allocate buffer for scan command\\n\",\n            sc->sc_dev.dv_xname);\n        return ENOMEM;\n    }\n    hdr = (struct iwn_scan_hdr *)buf;\n    /*\n     * Move to the next channel if no frames are received within 10ms\n     * after sending the probe request.\n     */\n    hdr->quiet_time = htole16(10);        /* timeout in milliseconds */\n    hdr->quiet_threshold = htole16(1);    /* min # of packets */\n\n    if (bgscan) {\n        int bintval;\n\n        /* Set maximum off-channel time. */\n        hdr->max_out = htole32(200 * 1024);\n\n        /* Configure scan pauses which service on-channel traffic. */\n        bintval = ic->ic_bss->ni_intval ? ic->ic_bss->ni_intval : 100;\n        hdr->pause_scan = htole32(((100 / bintval) << 22) |\n            ((100 % bintval) * 1024));\n    }\n\n    /* Select antennas for scanning. */\n    rxchain =\n        IWN_RXCHAIN_VALID(sc->rxchainmask) |\n        IWN_RXCHAIN_FORCE_MIMO_SEL(sc->rxchainmask) |\n        IWN_RXCHAIN_DRIVER_FORCE;\n    if ((flags & IEEE80211_CHAN_5GHZ) &&\n        sc->hw_type == IWN_HW_REV_TYPE_4965) {\n        /*\n         * On 4965 ant A and C must be avoided in 5GHz because of a\n         * HW bug which causes very weak RSSI values being reported.\n         */\n        rxchain |= IWN_RXCHAIN_FORCE_SEL(IWN_ANT_B);\n    } else    /* Use all available RX antennas. */\n        rxchain |= IWN_RXCHAIN_FORCE_SEL(sc->rxchainmask);\n    hdr->rxchain = htole16(rxchain);\n    hdr->filter = htole32(IWN_FILTER_MULTICAST | IWN_FILTER_BEACON);\n\n    tx = (struct iwn_cmd_data *)(hdr + 1);\n    tx->flags = htole32(IWN_TX_AUTO_SEQ);\n    tx->id = sc->broadcast_id;\n    tx->lifetime = htole32(IWN_LIFETIME_INFINITE);\n\n    if (flags & IEEE80211_CHAN_5GHZ) {\n        /* Send probe requests at 6Mbps. */\n        tx->plcp = iwn_rates[IWN_RATE_6M_INDEX].plcp;\n        rs = &ic->ic_sup_rates[IEEE80211_MODE_11A];\n    } else {\n        hdr->flags = htole32(IWN_RXON_24GHZ | IWN_RXON_AUTO);\n        if (bgscan && sc->hw_type == IWN_HW_REV_TYPE_4965 &&\n            sc->rxon.chan > 14) {\n            /*\n             * 4965 firmware can crash when sending probe requests\n             * with CCK rates while associated to a 5GHz AP.\n             * Send probe requests at 6Mbps OFDM as a workaround.\n             */\n            tx->plcp = iwn_rates[IWN_RATE_6M_INDEX].plcp;\n        } else {\n            /* Send probe requests at 1Mbps. */\n            tx->plcp = iwn_rates[IWN_RATE_1M_INDEX].plcp;\n            tx->rflags = IWN_RFLAG_CCK;\n        }\n        rs = &ic->ic_sup_rates[IEEE80211_MODE_11G];\n    }\n    /* Use the first valid TX antenna. */\n    txant = IWN_LSB(sc->txchainmask);\n    tx->rflags |= IWN_RFLAG_ANT(txant);\n\n    /*\n     * Only do active scanning if we're announcing a probe request\n     * for a given SSID (or more, if we ever add it to the driver.)\n     */\n    is_active = 0;\n\n    /*\n     * If we're scanning for a specific SSID, add it to the command.\n     */\n    essid = (struct iwn_scan_essid *)(tx + 1);\n    if (ic->ic_des_esslen != 0) {\n        essid[0].id = IEEE80211_ELEMID_SSID;\n        essid[0].len = ic->ic_des_esslen;\n        memcpy(essid[0].data, ic->ic_des_essid, ic->ic_des_esslen);\n\n        is_active = 1;\n    }\n    /*\n     * Build a probe request frame.  Most of the following code is a\n     * copy & paste of what is done in net80211.\n     */\n    wh = (struct ieee80211_frame *)(essid + 20);\n    wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT |\n        IEEE80211_FC0_SUBTYPE_PROBE_REQ;\n    wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;\n    IEEE80211_ADDR_COPY(wh->i_addr1, etherbroadcastaddr);\n    IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_myaddr);\n    IEEE80211_ADDR_COPY(wh->i_addr3, etherbroadcastaddr);\n    *(uint16_t *)&wh->i_dur[0] = 0;    /* filled by HW */\n    *(uint16_t *)&wh->i_seq[0] = 0;    /* filled by HW */\n\n    frm = (uint8_t *)(wh + 1);\n    frm = ieee80211_add_ssid(frm, NULL, 0);\n    frm = ieee80211_add_rates(frm, rs);\n    if (rs->rs_nrates > IEEE80211_RATE_SIZE)\n        frm = ieee80211_add_xrates(frm, rs);\n    if (ic->ic_flags & IEEE80211_F_HTON)\n        frm = ieee80211_add_htcaps(frm, ic);\n\n    /* Set length of probe request. */\n    tx->len = htole16(frm - (uint8_t *)wh);\n\n    /*\n     * If active scanning is requested but a certain channel is\n     * marked passive, we can do active scanning if we detect\n     * transmissions.\n     *\n     * There is an issue with some firmware versions that triggers\n     * a sysassert on a \"good CRC threshold\" of zero (== disabled),\n     * on a radar channel even though this means that we should NOT\n     * send probes.\n     *\n     * The \"good CRC threshold\" is the number of frames that we\n     * need to receive during our dwell time on a channel before\n     * sending out probes -- setting this to a huge value will\n     * mean we never reach it, but at the same time work around\n     * the aforementioned issue. Thus use IWN_GOOD_CRC_TH_NEVER\n     * here instead of IWN_GOOD_CRC_TH_DISABLED.\n     *\n     * This was fixed in later versions along with some other\n     * scan changes, and the threshold behaves as a flag in those\n     * versions.\n     */\n\n    /*\n     * If we're doing active scanning, set the crc_threshold\n     * to a suitable value.  This is different to active veruss\n     * passive scanning depending upon the channel flags; the\n     * firmware will obey that particular check for us.\n     */\n    if (sc->tlv_feature_flags & IWN_UCODE_TLV_FLAGS_NEWSCAN)\n        hdr->crc_threshold = is_active ?\n            IWN_GOOD_CRC_TH_DEFAULT : IWN_GOOD_CRC_TH_DISABLED;\n    else\n        hdr->crc_threshold = is_active ?\n            IWN_GOOD_CRC_TH_DEFAULT : IWN_GOOD_CRC_TH_NEVER;\n\n    chan = (struct iwn_scan_chan *)frm;\n    for (c  = &ic->ic_channels[1];\n         c <= &ic->ic_channels[IEEE80211_CHAN_MAX]; c++) {\n        if ((c->ic_flags & flags) != flags)\n            continue;\n\n        chan->chan = htole16(ieee80211_chan2ieee(ic, c));\n        DPRINTFN(2, (\"adding channel %d\\n\", chan->chan));\n        chan->flags = 0;\n        if (ic->ic_des_esslen != 0)\n            chan->flags |= htole32(IWN_CHAN_NPBREQS(1));\n\n        if (c->ic_flags & IEEE80211_CHAN_PASSIVE)\n            chan->flags |= htole32(IWN_CHAN_PASSIVE);\n        else\n            chan->flags |= htole32(IWN_CHAN_ACTIVE);\n\n        /*\n         * Calculate the active/passive dwell times.\n         */\n\n        dwell_active = iwn_get_active_dwell_time(sc, flags, is_active);\n        dwell_passive = iwn_get_passive_dwell_time(sc, flags);\n\n        /* Make sure they're valid */\n        if (dwell_passive <= dwell_active)\n            dwell_passive = dwell_active + 1;\n\n        chan->active = htole16(dwell_active);\n        chan->passive = htole16(dwell_passive);\n\n        chan->dsp_gain = 0x6e;\n        if (IEEE80211_IS_CHAN_5GHZ(c)) {\n            chan->rf_gain = 0x3b;\n        } else {\n            chan->rf_gain = 0x28;\n        }\n        hdr->nchan++;\n        chan++;\n    }\n\n    buflen = (uint8_t *)chan - buf;\n    hdr->len = htole16(buflen);\n\n    error = iwn_cmd(sc, IWN_CMD_SCAN, buf, buflen, 1);\n    if (error == 0) {\n        /*\n         * The current mode might have been fixed during association.\n         * Ensure all channels get scanned.\n         */\n        if (IFM_MODE(ic->ic_media.ifm_cur->ifm_media) == IFM_AUTO)\n            ieee80211_setmode(ic, IEEE80211_MODE_AUTO);\n\n        sc->sc_flags |= IWN_FLAG_SCANNING;\n        if (bgscan)\n            sc->sc_flags |= IWN_FLAG_BGSCAN;\n    }\n    ::free(buf);\n    return error;\n}\n\nvoid ItlIwn::\niwn_scan_abort(struct iwn_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    iwn_cmd(sc, IWN_CMD_SCAN_ABORT, NULL, 0, 1);\n\n    /* XXX Cannot wait for status response in interrupt context. */\n    DELAY(100);\n\n    sc->sc_flags &= ~IWN_FLAG_SCANNING;\n    sc->sc_flags &= ~IWN_FLAG_BGSCAN;\n}\n\nint ItlIwn::\niwn_bgscan(struct ieee80211com *ic)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwn_softc *sc = (struct iwn_softc *)ic->ic_softc;\n    ItlIwn *that = container_of(sc, ItlIwn, com);\n    int error;\n\n    if (sc->sc_flags & IWN_FLAG_SCANNING)\n        return 0;\n\n    error = that->iwn_scan(sc, IEEE80211_CHAN_2GHZ, 1);\n    if (error)\n        XYLog(\"%s: could not initiate background scan\\n\",\n            sc->sc_dev.dv_xname);\n    return error;\n}\n\nvoid ItlIwn::\niwn_rxon_configure_ht40(struct ieee80211com *ic, struct ieee80211_node *ni)\n{\n    struct iwn_softc *sc = (struct iwn_softc *)ic->ic_softc;\n    uint8_t sco = (ni->ni_htop0 & IEEE80211_HTOP0_SCO_MASK);\n    int htprot = (ni->ni_htop1 &\n                  IEEE80211_HTOP1_PROT_MASK);\n    \n    sc->rxon.flags &= ~htole32(IWN_RXON_HT_CHANMODE_MIXED2040 |\n                               IWN_RXON_HT_CHANMODE_PURE40 | IWN_RXON_HT_HT40MINUS);\n    \n    if (ieee80211_node_supports_ht_chan40(ni) &&\n        (sco == IEEE80211_HTOP0_SCO_SCA ||\n         sco == IEEE80211_HTOP0_SCO_SCB)) {\n        if (sco == IEEE80211_HTOP0_SCO_SCB)\n            sc->rxon.flags |= htole32(IWN_RXON_HT_HT40MINUS);\n        if (htprot == IEEE80211_HTPROT_20MHZ)\n            sc->rxon.flags |= htole32(IWN_RXON_HT_CHANMODE_PURE40);\n        else\n            sc->rxon.flags |= htole32(\n                                      IWN_RXON_HT_CHANMODE_MIXED2040);\n    }\n}\n\nint ItlIwn::\niwn_rxon_ht40_enabled(struct iwn_softc *sc)\n{\n    return ((le32toh(sc->rxon.flags) & IWN_RXON_HT_CHANMODE_MIXED2040) ||\n            (le32toh(sc->rxon.flags) & IWN_RXON_HT_CHANMODE_PURE40)) ? 1 : 0;\n}\n\nint ItlIwn::\niwn_auth(struct iwn_softc *sc, int arg)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwn_ops *ops = &sc->ops;\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct ieee80211_node *ni = ic->ic_bss;\n    int error, ridx;\n    int bss_switch =\n        (!IEEE80211_ADDR_EQ(sc->bss_node_addr, etheranyaddr) &&\n        !IEEE80211_ADDR_EQ(sc->bss_node_addr, ni->ni_macaddr));\n\n    /* Update adapter configuration. */\n    IEEE80211_ADDR_COPY(sc->rxon.bssid, ni->ni_bssid);\n    sc->rxon.chan = ieee80211_chan2ieee(ic, ni->ni_chan);\n    sc->rxon.flags = htole32(IWN_RXON_TSF | IWN_RXON_CTS_TO_SELF);\n    if (IEEE80211_IS_CHAN_2GHZ(ni->ni_chan)) {\n        sc->rxon.flags |= htole32(IWN_RXON_AUTO | IWN_RXON_24GHZ);\n        if (ic->ic_flags & IEEE80211_F_USEPROT)\n            sc->rxon.flags |= htole32(IWN_RXON_TGG_PROT);\n        DPRINTF((\"%s: 2ghz prot 0x%x\\n\", __func__,\n            le32toh(sc->rxon.flags)));\n    }\n    if (ic->ic_flags & IEEE80211_F_SHSLOT)\n        sc->rxon.flags |= htole32(IWN_RXON_SHSLOT);\n    else\n        sc->rxon.flags &= ~htole32(IWN_RXON_SHSLOT);\n    if (ic->ic_flags & IEEE80211_F_SHPREAMBLE)\n        sc->rxon.flags |= htole32(IWN_RXON_SHPREAMBLE);\n    else\n        sc->rxon.flags &= ~htole32(IWN_RXON_SHPREAMBLE);\n    switch (ic->ic_curmode) {\n    case IEEE80211_MODE_11A:\n        sc->rxon.cck_mask  = 0;\n        sc->rxon.ofdm_mask = 0x15;\n        break;\n    case IEEE80211_MODE_11B:\n        sc->rxon.cck_mask  = 0x03;\n        sc->rxon.ofdm_mask = 0;\n        break;\n    default:    /* Assume 802.11b/g/n. */\n        sc->rxon.cck_mask  = 0x0f;\n        sc->rxon.ofdm_mask = 0x15;\n    }\n    /* Configure 40MHz early to avoid problems on 6205 devices. */\n    iwn_rxon_configure_ht40(ic, ni);\n    DPRINTF((\"%s: rxon chan %d flags %x cck %x ofdm %x\\n\", __func__,\n        sc->rxon.chan, le32toh(sc->rxon.flags), sc->rxon.cck_mask,\n        sc->rxon.ofdm_mask));\n    error = iwn_cmd(sc, IWN_CMD_RXON, &sc->rxon, sc->rxonsz, 1);\n    if (error != 0) {\n        XYLog(\"%s: RXON command failed\\n\", sc->sc_dev.dv_xname);\n        return error;\n    }\n\n    /* Configuration has changed, set TX power accordingly. */\n    if ((error = ops->set_txpower(sc, 1)) != 0) {\n        XYLog(\"%s: could not set TX power\\n\", sc->sc_dev.dv_xname);\n        return error;\n    }\n    /*\n     * Reconfiguring RXON clears the firmware nodes table so we must\n     * add the broadcast node again.\n     */\n    ridx = IEEE80211_IS_CHAN_5GHZ(ni->ni_chan) ?\n        IWN_RIDX_OFDM : IWN_RIDX_CCK;\n    if ((error = iwn_add_broadcast_node(sc, 1, ridx)) != 0) {\n        XYLog(\"%s: could not add broadcast node\\n\",\n            sc->sc_dev.dv_xname);\n        return error;\n    }\n\n    /*\n     * Make sure the firmware gets to see a beacon before we send\n     * the auth request. Otherwise the Tx attempt can fail due to\n     * the firmware's built-in regulatory domain enforcement.\n     * Delaying here for every incoming deauth frame can result in a DoS.\n     * Don't delay if we're here because of an incoming frame (arg != -1)\n     * or if we're already waiting for a response (ic_mgt_timer != 0).\n     * If we are switching APs after a background scan then net80211 has\n     * just faked the reception of a deauth frame from our old AP, so it\n     * is safe to delay in that case.\n     */\n    if ((arg == -1 || bss_switch) && ic->ic_mgt_timer == 0)\n        DELAY(ni->ni_intval * 3 * IEEE80211_DUR_TU);\n\n    /* We can now clear the cached address of our previous AP. */\n    memset(sc->bss_node_addr, 0, sizeof(sc->bss_node_addr));\n\n    return 0;\n}\n\nint ItlIwn::\niwn_run(struct iwn_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwn_ops *ops = &sc->ops;\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct ieee80211_node *ni = ic->ic_bss;\n    struct iwn_node *wn = (struct iwn_node *)ni;\n    struct iwn_node_info node;\n    int error;\n\n    if (ic->ic_opmode == IEEE80211_M_MONITOR) {\n        /* Link LED blinks while monitoring. */\n        iwn_set_led(sc, IWN_LED_LINK, 50, 50);\n        return 0;\n    }\n    if ((error = iwn_set_timing(sc, ni)) != 0) {\n        XYLog(\"%s: could not set timing\\n\", sc->sc_dev.dv_xname);\n        return error;\n    }\n\n    /* Update adapter configuration. */\n    sc->rxon.associd = htole16(IEEE80211_AID(ni->ni_associd));\n    /* Short preamble and slot time are negotiated when associating. */\n    sc->rxon.flags &= ~htole32(IWN_RXON_SHPREAMBLE | IWN_RXON_SHSLOT);\n    if (ic->ic_flags & IEEE80211_F_SHSLOT)\n        sc->rxon.flags |= htole32(IWN_RXON_SHSLOT);\n    if (ic->ic_flags & IEEE80211_F_SHPREAMBLE)\n        sc->rxon.flags |= htole32(IWN_RXON_SHPREAMBLE);\n    sc->rxon.filter |= htole32(IWN_FILTER_BSS);\n\n    /* HT is negotiated when associating. */\n    if (ni->ni_flags & IEEE80211_NODE_HT) {\n        enum ieee80211_htprot htprot =\n            (ieee80211_htprot)(ni->ni_htop1 & IEEE80211_HTOP1_PROT_MASK);\n        DPRINTF((\"%s: htprot = %d\\n\", __func__, htprot));\n        sc->rxon.flags |= htole32(IWN_RXON_HT_PROTMODE(htprot));\n    } else\n        sc->rxon.flags &= ~htole32(IWN_RXON_HT_PROTMODE(3));\n    iwn_rxon_configure_ht40(ic, ni);\n\n    if (IEEE80211_IS_CHAN_5GHZ(ni->ni_chan)) {\n        /* 11a or 11n 5GHz */\n        sc->rxon.cck_mask  = 0;\n        sc->rxon.ofdm_mask = 0x15;\n    } else if (ni->ni_flags & IEEE80211_NODE_HT) {\n        /* 11n 2GHz */\n        sc->rxon.cck_mask  = 0x0f;\n        sc->rxon.ofdm_mask = 0x15;\n    } else {\n        if (ni->ni_rates.rs_nrates == 4) {\n            /* 11b */\n            sc->rxon.cck_mask  = 0x03;\n            sc->rxon.ofdm_mask = 0;\n        } else {\n            /* assume 11g */\n            sc->rxon.cck_mask  = 0x0f;\n            sc->rxon.ofdm_mask = 0x15;\n        }\n    }\n    DPRINTF((\"%s: rxon chan %d flags %x cck %x ofdm %x\\n\", __func__,\n        sc->rxon.chan, le32toh(sc->rxon.flags), sc->rxon.cck_mask,\n        sc->rxon.ofdm_mask));\n    error = iwn_cmd(sc, IWN_CMD_RXON, &sc->rxon, sc->rxonsz, 1);\n    if (error != 0) {\n        XYLog(\"%s: could not update configuration\\n\",\n            sc->sc_dev.dv_xname);\n        return error;\n    }\n\n    /* Configuration has changed, set TX power accordingly. */\n    if ((error = ops->set_txpower(sc, 1)) != 0) {\n        XYLog(\"%s: could not set TX power\\n\", sc->sc_dev.dv_xname);\n        return error;\n    }\n\n    /* Fake a join to initialize the TX rate. */\n    ((struct iwn_node *)ni)->id = IWN_ID_BSS;\n    iwn_newassoc(ic, ni, 1);\n\n    /* Add BSS node. */\n    memset(&node, 0, sizeof node);\n    IEEE80211_ADDR_COPY(node.macaddr, ni->ni_macaddr);\n    node.id = IWN_ID_BSS;\n    if (ni->ni_flags & IEEE80211_NODE_HT) {\n        node.htmask = (IWN_AMDPU_SIZE_FACTOR_MASK |\n            IWN_AMDPU_DENSITY_MASK);\n        node.htflags = htole32(\n            IWN_AMDPU_SIZE_FACTOR(\n            (ic->ic_ampdu_params & IEEE80211_AMPDU_PARAM_LE)) |\n            IWN_AMDPU_DENSITY(\n            (ic->ic_ampdu_params & IEEE80211_AMPDU_PARAM_SS) >> 2));\n        \n        if (iwn_rxon_ht40_enabled(sc))\n            node.htflags |= htole32(IWN_40MHZ_ENABLE);\n    }\n    DPRINTF((\"adding BSS node\\n\"));\n    error = ops->add_node(sc, &node, 1);\n    if (error != 0) {\n        XYLog(\"%s: could not add BSS node\\n\", sc->sc_dev.dv_xname);\n        return error;\n    }\n\n    /* Cache address of AP in case it changes after a background scan. */\n    IEEE80211_ADDR_COPY(sc->bss_node_addr, ni->ni_macaddr);\n\n    DPRINTF((\"setting link quality for node %d\\n\", node.id));\n    if ((error = iwn_set_link_quality(sc, ni)) != 0) {\n        XYLog(\"%s: could not setup link quality for node %d\\n\",\n            sc->sc_dev.dv_xname, node.id);\n        return error;\n    }\n\n    if ((error = iwn_init_sensitivity(sc)) != 0) {\n        XYLog(\"%s: could not set sensitivity\\n\",\n            sc->sc_dev.dv_xname);\n        return error;\n    }\n    /* Start periodic calibration timer. */\n    sc->calib.state = IWN_CALIB_STATE_ASSOC;\n    sc->calib_cnt = 0;\n    timeout_add_msec(&sc->calib_to, 500);\n\n    ieee80211_ra_node_init(ic, &wn->rn, &wn->ni);\n\n    /* Link LED always on while associated. */\n    iwn_set_led(sc, IWN_LED_LINK, 0, 1);\n    return 0;\n}\n\n/*\n * We support CCMP hardware encryption/decryption of unicast frames only.\n * HW support for TKIP really sucks.  We should let TKIP die anyway.\n */\nint ItlIwn::\niwn_set_key(struct ieee80211com *ic, struct ieee80211_node *ni,\n    struct ieee80211_key *k)\n{\n    struct iwn_softc *sc = (struct iwn_softc *)ic->ic_softc;\n    struct iwn_ops *ops = &sc->ops;\n    struct iwn_node *wn = (iwn_node *)ni;\n    struct iwn_node_info node;\n    uint16_t kflags;\n\n    if ((k->k_flags & IEEE80211_KEY_GROUP) ||\n        k->k_cipher != IEEE80211_CIPHER_CCMP)\n        return ieee80211_set_key(ic, ni, k);\n\n    kflags = IWN_KFLAG_CCMP | IWN_KFLAG_MAP | IWN_KFLAG_KID(k->k_id);\n    if (k->k_flags & IEEE80211_KEY_GROUP)\n        kflags |= IWN_KFLAG_GROUP;\n\n    memset(&node, 0, sizeof node);\n    node.id = (k->k_flags & IEEE80211_KEY_GROUP) ?\n        sc->broadcast_id : wn->id;\n    node.control = IWN_NODE_UPDATE;\n    node.flags = IWN_FLAG_SET_KEY;\n    node.kflags = htole16(kflags);\n    node.kid = k->k_id;\n    memcpy(node.key, k->k_key, k->k_len);\n    DPRINTF((\"set key id=%d for node %d\\n\", k->k_id, node.id));\n    return ops->add_node(sc, &node, 1);\n}\n\nvoid ItlIwn::\niwn_delete_key(struct ieee80211com *ic, struct ieee80211_node *ni,\n    struct ieee80211_key *k)\n{\n    struct iwn_softc *sc = (struct iwn_softc *)ic->ic_softc;\n    struct iwn_ops *ops = &sc->ops;\n    struct iwn_node *wn = (struct iwn_node *)ni;\n    struct iwn_node_info node;\n\n    if ((k->k_flags & IEEE80211_KEY_GROUP) ||\n        k->k_cipher != IEEE80211_CIPHER_CCMP) {\n        /* See comment about other ciphers above. */\n        ieee80211_delete_key(ic, ni, k);\n        return;\n    }\n    if (ic->ic_state != IEEE80211_S_RUN)\n        return;    /* Nothing to do. */\n    memset(&node, 0, sizeof node);\n    node.id = (k->k_flags & IEEE80211_KEY_GROUP) ?\n        sc->broadcast_id : wn->id;\n    node.control = IWN_NODE_UPDATE;\n    node.flags = IWN_FLAG_SET_KEY;\n    node.kflags = htole16(IWN_KFLAG_INVALID);\n    node.kid = 0xff;\n    DPRINTF((\"delete keys for node %d\\n\", node.id));\n    (void)ops->add_node(sc, &node, 1);\n}\n\nvoid ItlIwn::\niwn_update_chw(struct ieee80211com *ic)\n{\n    XYLog(\"%s update channel info\\n\", __FUNCTION__);\n    struct iwn_softc *sc = (struct iwn_softc *)ic->ic_softc;\n    ItlIwn *that = container_of(sc, ItlIwn, com);\n    \n    if (ic->ic_state != IEEE80211_S_RUN)\n        return;\n    \n    that->iwn_rxon_configure_ht40(ic, ic->ic_bss);\n    sc->ops.update_rxon(sc);\n    that->iwn_set_link_quality(sc, ic->ic_bss);\n}\n\nvoid ItlIwn::\niwn_updateprot(struct ieee80211com *ic)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwn_softc *sc = (struct iwn_softc *)ic->ic_softc;\n    enum ieee80211_htprot htprot;\n    \n    if (ic->ic_state != IEEE80211_S_RUN)\n        return;\n    \n    /* Update ERP protection setting. */\n    if (ic->ic_flags & IEEE80211_F_USEPROT)\n        sc->rxon.flags |= htole32(IWN_RXON_TGG_PROT);\n    else\n        sc->rxon.flags &= ~htole32(IWN_RXON_TGG_PROT);\n\n    /* Update HT protection mode setting. */\n    htprot = (enum ieee80211_htprot)((ic->ic_bss->ni_htop1 & IEEE80211_HTOP1_PROT_MASK) >>\n        IEEE80211_HTOP1_PROT_SHIFT);\n    sc->rxon.flags &= ~htole32(IWN_RXON_HT_PROTMODE(3));\n    sc->rxon.flags |= htole32(IWN_RXON_HT_PROTMODE(htprot));\n\n    sc->ops.update_rxon(sc);\n}\n\nvoid ItlIwn::\niwn_updateslot(struct ieee80211com *ic)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwn_softc *sc = (struct iwn_softc *)ic->ic_softc;\n    \n    if (ic->ic_state != IEEE80211_S_RUN)\n        return;\n    \n    if (ic->ic_flags & IEEE80211_F_SHSLOT)\n        sc->rxon.flags |= htole32(IWN_RXON_SHSLOT);\n    else\n        sc->rxon.flags &= ~htole32(IWN_RXON_SHSLOT);\n    \n    if (ic->ic_flags & IEEE80211_F_SHPREAMBLE)\n        sc->rxon.flags |= htole32(IWN_RXON_SHPREAMBLE);\n    else\n        sc->rxon.flags &= ~htole32(IWN_RXON_SHPREAMBLE);\n    \n    sc->ops.update_rxon(sc);\n}\n\nvoid ItlIwn::\niwn_update_rxon_restore_power(struct iwn_softc *sc)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct iwn_ops *ops = &sc->ops;\n    int error;\n    \n    DELAY(100);\n    \n    /* All RXONs wipe the firmware's txpower table. Restore it. */\n    error = ops->set_txpower(sc, 1);\n    if (error != 0)\n        printf(\"%s: could not set TX power\\n\", sc->sc_dev.dv_xname);\n    \n    DELAY(100);\n    \n    /* Restore power saving level */\n    if (ic->ic_flags & IEEE80211_F_PMGTON)\n        error = iwn_set_pslevel(sc, 0, 3, 1);\n    else\n        error = iwn_set_pslevel(sc, 0, 0, 1);\n    if (error != 0)\n        printf(\"%s: could not set PS level\\n\", sc->sc_dev.dv_xname);\n}\n\nvoid ItlIwn::\niwn5000_update_rxon(struct iwn_softc *sc)\n{\n    ItlIwn *that = container_of(sc, ItlIwn, com);\n    struct iwn_rxon_assoc rxon_assoc;\n    int s, error;\n    \n    /* Update RXON config. */\n    memset(&rxon_assoc, 0, sizeof(rxon_assoc));\n    rxon_assoc.flags = sc->rxon.flags;\n    rxon_assoc.filter = sc->rxon.filter;\n    rxon_assoc.ofdm_mask = sc->rxon.ofdm_mask;\n    rxon_assoc.cck_mask = sc->rxon.cck_mask;\n    rxon_assoc.ht_single_mask = sc->rxon.ht_single_mask;\n    rxon_assoc.ht_dual_mask = sc->rxon.ht_dual_mask;\n    rxon_assoc.ht_triple_mask = sc->rxon.ht_triple_mask;\n    rxon_assoc.rxchain = sc->rxon.rxchain;\n    rxon_assoc.acquisition = sc->rxon.acquisition;\n    \n    s = splnet();\n    \n    error = that->iwn_cmd(sc, IWN_CMD_RXON_ASSOC, &rxon_assoc, sizeof(rxon_assoc), 1);\n    if (error != 0)\n        printf(\"%s: RXON_ASSOC command failed\\n\", sc->sc_dev.dv_xname);\n    \n    that->iwn_update_rxon_restore_power(sc);\n    \n    splx(s);\n}\n\nvoid ItlIwn::\niwn4965_update_rxon(struct iwn_softc *sc)\n{\n    ItlIwn *that = container_of(sc, ItlIwn, com);\n    struct iwn4965_rxon_assoc rxon_assoc;\n    int s, error;\n    \n    /* Update RXON config. */\n    memset(&rxon_assoc, 0, sizeof(rxon_assoc));\n    rxon_assoc.flags = sc->rxon.flags;\n    rxon_assoc.filter = sc->rxon.filter;\n    rxon_assoc.ofdm_mask = sc->rxon.ofdm_mask;\n    rxon_assoc.cck_mask = sc->rxon.cck_mask;\n    rxon_assoc.ht_single_mask = sc->rxon.ht_single_mask;\n    rxon_assoc.ht_dual_mask = sc->rxon.ht_dual_mask;\n    rxon_assoc.rxchain = sc->rxon.rxchain;\n    \n    s = splnet();\n    \n    error = that->iwn_cmd(sc, IWN_CMD_RXON_ASSOC, &rxon_assoc, sizeof(rxon_assoc), 1);\n    if (error != 0)\n        printf(\"%s: RXON_ASSOC command failed\\n\", sc->sc_dev.dv_xname);\n    \n    that->iwn_update_rxon_restore_power(sc);\n    \n    splx(s);\n}\n\n/*\n * This function is called by upper layer when an ADDBA request is received\n * from another STA and before the ADDBA response is sent.\n */\nint ItlIwn::\niwn_ampdu_rx_start(struct ieee80211com *ic, struct ieee80211_node *ni,\n    uint8_t tid)\n{\n    struct ieee80211_rx_ba *ba = &ni->ni_rx_ba[tid];\n    struct iwn_softc *sc = (struct iwn_softc *)ic->ic_softc;\n    struct iwn_ops *ops = &sc->ops;\n    struct iwn_node *wn = (struct iwn_node *)ni;\n    struct iwn_node_info node;\n\n    memset(&node, 0, sizeof node);\n    node.id = wn->id;\n    node.control = IWN_NODE_UPDATE;\n    node.flags = IWN_FLAG_SET_ADDBA;\n    node.addba_tid = tid;\n    node.addba_ssn = htole16(ba->ba_winstart);\n    DPRINTF((\"ADDBA RA=%d TID=%d SSN=%d\\n\", wn->id, tid,\n        ba->ba_winstart));\n    /* XXX async command, so firmware may still fail to add BA agreement */\n    return ops->add_node(sc, &node, 1);\n}\n\n/*\n * This function is called by upper layer on teardown of an HT-immediate\n * Block Ack agreement (eg. uppon receipt of a DELBA frame).\n */\nvoid ItlIwn::\niwn_ampdu_rx_stop(struct ieee80211com *ic, struct ieee80211_node *ni,\n    uint8_t tid)\n{\n    struct iwn_softc *sc = (struct iwn_softc *)ic->ic_softc;\n    struct iwn_ops *ops = &sc->ops;\n    struct iwn_node *wn = (struct iwn_node *)ni;\n    struct iwn_node_info node;\n\n    memset(&node, 0, sizeof node);\n    node.id = wn->id;\n    node.control = IWN_NODE_UPDATE;\n    node.flags = IWN_FLAG_SET_DELBA;\n    node.delba_tid = tid;\n    DPRINTF((\"DELBA RA=%d TID=%d\\n\", wn->id, tid));\n    (void)ops->add_node(sc, &node, 1);\n}\n\n/*\n * This function is called by upper layer when an ADDBA response is received\n * from another STA.\n */\nint ItlIwn::\niwn_ampdu_tx_start(struct ieee80211com *ic, struct ieee80211_node *ni,\n    uint8_t tid)\n{\n    struct ieee80211_tx_ba *ba = &ni->ni_tx_ba[tid];\n    struct iwn_softc *sc = (struct iwn_softc *)ic->ic_softc;\n    struct iwn_ops *ops = &sc->ops;\n    struct iwn_node *wn = (struct iwn_node *)ni;\n    struct iwn_node_info node;\n    int qid = sc->first_agg_txq + tid;\n    int error;\n\n    /* Ensure we can map this TID to an aggregation queue. */\n    if (tid >= IWN_NUM_AMPDU_TID || ba->ba_winsize > IWN_SCHED_WINSZ ||\n        qid > sc->ntxqs || (sc->agg_queue_mask & (1 << qid)))\n        return ENOSPC;\n\n    /* Enable TX for the specified RA/TID. */\n    wn->disable_tid &= ~(1 << tid);\n    memset(&node, 0, sizeof node);\n    node.id = wn->id;\n    node.control = IWN_NODE_UPDATE;\n    node.flags = IWN_FLAG_SET_DISABLE_TID;\n    node.disable_tid = htole16(wn->disable_tid);\n    error = ops->add_node(sc, &node, 1);\n    if (error != 0)\n        return error;\n\n    if ((error = iwn_nic_lock(sc)) != 0)\n        return error;\n    ops->ampdu_tx_start(sc, ni, tid, ba->ba_winstart);\n    iwn_nic_unlock(sc);\n\n    sc->agg_queue_mask |= (1 << qid);\n    sc->sc_tx_ba[tid].wn = wn;\n    ba->ba_bitmap = 0;\n\n    return 0;\n}\n\nvoid ItlIwn::\niwn_ampdu_tx_stop(struct ieee80211com *ic, struct ieee80211_node *ni,\n    uint8_t tid)\n{\n    struct ieee80211_tx_ba *ba = (struct ieee80211_tx_ba *)&ni->ni_tx_ba[tid];\n    struct iwn_softc *sc = (struct iwn_softc *)ic->ic_softc;\n    ItlIwn *that = container_of(sc, ItlIwn, com);\n    struct iwn_ops *ops = &sc->ops;\n    int qid = sc->first_agg_txq + tid;\n    struct iwn_node *wn = (struct iwn_node *)ni;\n    struct iwn_node_info node;\n\n    /* Discard all frames in the current window. */\n    that->iwn_ampdu_txq_advance(sc, &sc->txq[qid], qid,\n        IWN_AGG_SSN_TO_TXQ_IDX(ba->ba_winend));\n\n    if (iwn_nic_lock(sc) != 0)\n        return;\n    ops->ampdu_tx_stop(sc, tid, ba->ba_winstart);\n    iwn_nic_unlock(sc);\n\n    sc->agg_queue_mask &= ~(1 << qid);\n    sc->sc_tx_ba[tid].wn = NULL;\n    ba->ba_bitmap = 0;\n\n    /* Disable TX for the specified RA/TID. */\n    wn->disable_tid |= (1 << tid);\n    memset(&node, 0, sizeof node);\n    node.id = wn->id;\n    node.control = IWN_NODE_UPDATE;\n    node.flags = IWN_FLAG_SET_DISABLE_TID;\n    node.disable_tid = htole16(wn->disable_tid);\n    ops->add_node(sc, &node, 1);\n}\n\nvoid ItlIwn::\niwn4965_ampdu_tx_start(struct iwn_softc *sc, struct ieee80211_node *ni,\n    uint8_t tid, uint16_t ssn)\n{\n    struct iwn_node *wn = (struct iwn_node *)ni;\n    int qid = IWN4965_FIRST_AGG_TXQUEUE + tid;\n    uint16_t idx = IWN_AGG_SSN_TO_TXQ_IDX(ssn);\n\n    /* Stop TX scheduler while we're changing its configuration. */\n    iwn_prph_write(sc, IWN4965_SCHED_QUEUE_STATUS(qid),\n        IWN4965_TXQ_STATUS_CHGACT);\n\n    /* Assign RA/TID translation to the queue. */\n    iwn_mem_write_2(sc, sc->sched_base + IWN4965_SCHED_TRANS_TBL(qid),\n        wn->id << 4 | tid);\n\n    /* Enable chain-building mode for the queue. */\n    iwn_prph_setbits(sc, IWN4965_SCHED_QCHAIN_SEL, 1 << qid);\n\n    /* Set starting sequence number from the ADDBA request. */\n    sc->txq[qid].cur = sc->txq[qid].read = idx;\n    IWN_WRITE(sc, IWN_HBUS_TARG_WRPTR, qid << 8 | idx);\n    iwn_prph_write(sc, IWN4965_SCHED_QUEUE_RDPTR(qid), ssn);\n\n    /* Set scheduler window size. */\n    iwn_mem_write(sc, sc->sched_base + IWN4965_SCHED_QUEUE_OFFSET(qid),\n        IWN_SCHED_WINSZ);\n    /* Set scheduler frame limit. */\n    iwn_mem_write(sc, sc->sched_base + IWN4965_SCHED_QUEUE_OFFSET(qid) + 4,\n        IWN_SCHED_LIMIT << 16);\n\n    /* Enable interrupts for the queue. */\n    iwn_prph_setbits(sc, IWN4965_SCHED_INTR_MASK, 1 << qid);\n\n    /* Mark the queue as active. */\n    iwn_prph_write(sc, IWN4965_SCHED_QUEUE_STATUS(qid),\n        IWN4965_TXQ_STATUS_ACTIVE | IWN4965_TXQ_STATUS_AGGR_ENA |\n        iwn_tid2fifo[tid] << 1);\n}\n\nvoid ItlIwn::\niwn4965_ampdu_tx_stop(struct iwn_softc *sc, uint8_t tid, uint16_t ssn)\n{\n    int qid = IWN4965_FIRST_AGG_TXQUEUE + tid;\n    uint16_t idx = IWN_AGG_SSN_TO_TXQ_IDX(ssn);\n\n    /* Stop TX scheduler while we're changing its configuration. */\n    iwn_prph_write(sc, IWN4965_SCHED_QUEUE_STATUS(qid),\n        IWN4965_TXQ_STATUS_CHGACT);\n\n    /* Set starting sequence number from the ADDBA request. */\n    sc->txq[qid].cur = sc->txq[qid].read = idx;\n    IWN_WRITE(sc, IWN_HBUS_TARG_WRPTR, qid << 8 | idx);\n    iwn_prph_write(sc, IWN4965_SCHED_QUEUE_RDPTR(qid), ssn);\n\n    /* Disable interrupts for the queue. */\n    iwn_prph_clrbits(sc, IWN4965_SCHED_INTR_MASK, 1 << qid);\n\n    /* Mark the queue as inactive. */\n    iwn_prph_write(sc, IWN4965_SCHED_QUEUE_STATUS(qid),\n        IWN4965_TXQ_STATUS_INACTIVE | iwn_tid2fifo[tid] << 1);\n}\n\nvoid ItlIwn::\niwn5000_ampdu_tx_start(struct iwn_softc *sc, struct ieee80211_node *ni,\n    uint8_t tid, uint16_t ssn)\n{\n    int qid = IWN5000_FIRST_AGG_TXQUEUE + tid;\n    int idx = IWN_AGG_SSN_TO_TXQ_IDX(ssn);\n    struct iwn_node *wn = (struct iwn_node *)ni;\n\n    /* Stop TX scheduler while we're changing its configuration. */\n    iwn_prph_write(sc, IWN5000_SCHED_QUEUE_STATUS(qid),\n        IWN5000_TXQ_STATUS_CHGACT);\n\n    /* Assign RA/TID translation to the queue. */\n    iwn_mem_write_2(sc, sc->sched_base + IWN5000_SCHED_TRANS_TBL(qid),\n        wn->id << 4 | tid);\n\n    /* Enable chain-building mode for the queue. */\n    iwn_prph_setbits(sc, IWN5000_SCHED_QCHAIN_SEL, 1 << qid);\n\n    /* Enable aggregation for the queue. */\n    iwn_prph_setbits(sc, IWN5000_SCHED_AGGR_SEL, 1 << qid);\n\n    /* Set starting sequence number from the ADDBA request. */\n    sc->txq[qid].cur = sc->txq[qid].read = idx;\n    IWN_WRITE(sc, IWN_HBUS_TARG_WRPTR, qid << 8 | idx);\n    iwn_prph_write(sc, IWN5000_SCHED_QUEUE_RDPTR(qid), ssn);\n\n    /* Set scheduler window size and frame limit. */\n    iwn_mem_write(sc, sc->sched_base + IWN5000_SCHED_QUEUE_OFFSET(qid) + 4,\n        IWN_SCHED_LIMIT << 16 | IWN_SCHED_WINSZ);\n\n    /* Enable interrupts for the queue. */\n    iwn_prph_setbits(sc, IWN5000_SCHED_INTR_MASK, 1 << qid);\n\n    /* Mark the queue as active. */\n    iwn_prph_write(sc, IWN5000_SCHED_QUEUE_STATUS(qid),\n        IWN5000_TXQ_STATUS_ACTIVE | iwn_tid2fifo[tid]);\n}\n\nvoid ItlIwn::\niwn5000_ampdu_tx_stop(struct iwn_softc *sc, uint8_t tid, uint16_t ssn)\n{\n    int qid = IWN5000_FIRST_AGG_TXQUEUE + tid;\n    int idx = IWN_AGG_SSN_TO_TXQ_IDX(ssn);\n\n    /* Stop TX scheduler while we're changing its configuration. */\n    iwn_prph_write(sc, IWN5000_SCHED_QUEUE_STATUS(qid),\n        IWN5000_TXQ_STATUS_CHGACT);\n\n    /* Disable aggregation for the queue. */\n    iwn_prph_clrbits(sc, IWN5000_SCHED_AGGR_SEL, 1 << qid);\n\n    /* Set starting sequence number from the ADDBA request. */\n    sc->txq[qid].cur = sc->txq[qid].read = idx;\n    IWN_WRITE(sc, IWN_HBUS_TARG_WRPTR, qid << 8 | idx);\n    iwn_prph_write(sc, IWN5000_SCHED_QUEUE_RDPTR(qid), ssn);\n\n    /* Disable interrupts for the queue. */\n    iwn_prph_clrbits(sc, IWN5000_SCHED_INTR_MASK, 1 << qid);\n\n    /* Mark the queue as inactive. */\n    iwn_prph_write(sc, IWN5000_SCHED_QUEUE_STATUS(qid),\n        IWN5000_TXQ_STATUS_INACTIVE | iwn_tid2fifo[tid]);\n}\n\n/*\n * Query calibration tables from the initialization firmware.  We do this\n * only once at first boot.  Called from a process context.\n */\nint ItlIwn::\niwn5000_query_calibration(struct iwn_softc *sc)\n{\n    ItlIwn *that = container_of(sc, ItlIwn, com);\n    struct iwn5000_calib_config cmd;\n    int error;\n\n    memset(&cmd, 0, sizeof cmd);\n    cmd.ucode.once.enable = 0xffffffff;\n    cmd.ucode.once.start  = 0xffffffff;\n    cmd.ucode.once.send   = 0xffffffff;\n    cmd.ucode.flags       = 0xffffffff;\n    DPRINTF((\"sending calibration query\\n\"));\n    error = that->iwn_cmd(sc, IWN5000_CMD_CALIB_CONFIG, &cmd, sizeof cmd, 0);\n    if (error != 0)\n        return error;\n\n    /* Wait at most two seconds for calibration to complete. */\n    if (!(sc->sc_flags & IWN_FLAG_CALIB_DONE))\n        error = that->tsleep_nsec(sc, PCATCH, \"iwncal\", SEC_TO_NSEC(2));\n    return error;\n}\n\n/*\n * Send calibration results to the runtime firmware.  These results were\n * obtained on first boot from the initialization firmware.\n */\nint ItlIwn::\niwn5000_send_calibration(struct iwn_softc *sc)\n{\n    ItlIwn *that = container_of(sc, ItlIwn, com);\n    int idx, error;\n\n    for (idx = 0; idx < 5; idx++) {\n        if (sc->calibcmd[idx].buf == NULL)\n            continue;    /* No results available. */\n        DPRINTF((\"send calibration result idx=%d len=%d\\n\",\n            idx, sc->calibcmd[idx].len));\n        error = that->iwn_cmd(sc, IWN_CMD_PHY_CALIB, sc->calibcmd[idx].buf,\n            sc->calibcmd[idx].len, 0);\n        if (error != 0) {\n            XYLog(\"%s: could not send calibration result\\n\",\n                sc->sc_dev.dv_xname);\n            return error;\n        }\n    }\n    return 0;\n}\n\nint ItlIwn::\niwn5000_send_wimax_coex(struct iwn_softc *sc)\n{\n    ItlIwn *that = container_of(sc, ItlIwn, com);\n    struct iwn5000_wimax_coex wimax;\n\n#ifdef notyet\n    if (sc->hw_type == IWN_HW_REV_TYPE_6050) {\n        /* Enable WiMAX coexistence for combo adapters. */\n        wimax.flags =\n            IWN_WIMAX_COEX_ASSOC_WA_UNMASK |\n            IWN_WIMAX_COEX_UNASSOC_WA_UNMASK |\n            IWN_WIMAX_COEX_STA_TABLE_VALID |\n            IWN_WIMAX_COEX_ENABLE;\n        memcpy(wimax.events, iwn6050_wimax_events,\n            sizeof iwn6050_wimax_events);\n    } else\n#endif\n    {\n        /* Disable WiMAX coexistence. */\n        wimax.flags = 0;\n        memset(wimax.events, 0, sizeof wimax.events);\n    }\n    DPRINTF((\"Configuring WiMAX coexistence\\n\"));\n    return that->iwn_cmd(sc, IWN5000_CMD_WIMAX_COEX, &wimax, sizeof wimax, 0);\n}\n\nint ItlIwn::\niwn5000_crystal_calib(struct iwn_softc *sc)\n{\n    ItlIwn *that = container_of(sc, ItlIwn, com);\n    struct iwn5000_phy_calib_crystal cmd;\n\n    memset(&cmd, 0, sizeof cmd);\n    cmd.code = IWN5000_PHY_CALIB_CRYSTAL;\n    cmd.ngroups = 1;\n    cmd.isvalid = 1;\n    cmd.cap_pin[0] = letoh32(sc->eeprom_crystal) & 0xff;\n    cmd.cap_pin[1] = (letoh32(sc->eeprom_crystal) >> 16) & 0xff;\n    DPRINTF((\"sending crystal calibration %d, %d\\n\",\n        cmd.cap_pin[0], cmd.cap_pin[1]));\n    return that->iwn_cmd(sc, IWN_CMD_PHY_CALIB, &cmd, sizeof cmd, 0);\n}\n\nint ItlIwn::\niwn6000_temp_offset_calib(struct iwn_softc *sc)\n{\n    ItlIwn *that = container_of(sc, ItlIwn, com);\n    struct iwn6000_phy_calib_temp_offset cmd;\n\n    memset(&cmd, 0, sizeof cmd);\n    cmd.code = IWN6000_PHY_CALIB_TEMP_OFFSET;\n    cmd.ngroups = 1;\n    cmd.isvalid = 1;\n    if (sc->eeprom_temp != 0)\n        cmd.offset = htole16(sc->eeprom_temp);\n    else\n        cmd.offset = htole16(IWN_DEFAULT_TEMP_OFFSET);\n    DPRINTF((\"setting radio sensor offset to %d\\n\", letoh16(cmd.offset)));\n    return that->iwn_cmd(sc, IWN_CMD_PHY_CALIB, &cmd, sizeof cmd, 0);\n}\n\nint ItlIwn::\niwn2000_temp_offset_calib(struct iwn_softc *sc)\n{\n    ItlIwn *that = container_of(sc, ItlIwn, com);\n    struct iwn2000_phy_calib_temp_offset cmd;\n\n    memset(&cmd, 0, sizeof cmd);\n    cmd.code = IWN2000_PHY_CALIB_TEMP_OFFSET;\n    cmd.ngroups = 1;\n    cmd.isvalid = 1;\n    if (sc->eeprom_rawtemp != 0) {\n        cmd.offset_low = htole16(sc->eeprom_rawtemp);\n        cmd.offset_high = htole16(sc->eeprom_temp);\n    } else {\n        cmd.offset_low = htole16(IWN_DEFAULT_TEMP_OFFSET);\n        cmd.offset_high = htole16(IWN_DEFAULT_TEMP_OFFSET);\n    }\n    cmd.burnt_voltage_ref = htole16(sc->eeprom_voltage);\n    DPRINTF((\"setting radio sensor offset to %d:%d, voltage to %d\\n\",\n        letoh16(cmd.offset_low), letoh16(cmd.offset_high),\n        letoh16(cmd.burnt_voltage_ref)));\n    return that->iwn_cmd(sc, IWN_CMD_PHY_CALIB, &cmd, sizeof cmd, 0);\n}\n\n/*\n * This function is called after the runtime firmware notifies us of its\n * readiness (called in a process context).\n */\nint ItlIwn::\niwn4965_post_alive(struct iwn_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    int error, qid;\n\n    if ((error = iwn_nic_lock(sc)) != 0)\n        return error;\n\n    /* Clear TX scheduler state in SRAM. */\n    sc->sched_base = iwn_prph_read(sc, IWN_SCHED_SRAM_ADDR);\n    iwn_mem_set_region_4(sc, sc->sched_base + IWN4965_SCHED_CTX_OFF, 0,\n        IWN4965_SCHED_CTX_LEN / sizeof (uint32_t));\n\n    /* Set physical address of TX scheduler rings (1KB aligned). */\n    iwn_prph_write(sc, IWN4965_SCHED_DRAM_ADDR, sc->sched_dma.paddr >> 10);\n\n    IWN_SETBITS(sc, IWN_FH_TX_CHICKEN, IWN_FH_TX_CHICKEN_SCHED_RETRY);\n\n    /* Disable chain mode for all our 16 queues. */\n    iwn_prph_write(sc, IWN4965_SCHED_QCHAIN_SEL, 0);\n\n    for (qid = 0; qid < IWN4965_NTXQUEUES; qid++) {\n        iwn_prph_write(sc, IWN4965_SCHED_QUEUE_RDPTR(qid), 0);\n        IWN_WRITE(sc, IWN_HBUS_TARG_WRPTR, qid << 8 | 0);\n\n        /* Set scheduler window size. */\n        iwn_mem_write(sc, sc->sched_base +\n            IWN4965_SCHED_QUEUE_OFFSET(qid), IWN_SCHED_WINSZ);\n        /* Set scheduler frame limit. */\n        iwn_mem_write(sc, sc->sched_base +\n            IWN4965_SCHED_QUEUE_OFFSET(qid) + 4,\n            IWN_SCHED_LIMIT << 16);\n    }\n\n    /* Enable interrupts for all our 16 queues. */\n    iwn_prph_write(sc, IWN4965_SCHED_INTR_MASK, 0xffff);\n    /* Identify TX FIFO rings (0-7). */\n    iwn_prph_write(sc, IWN4965_SCHED_TXFACT, 0xff);\n\n    /* Mark TX rings (4 EDCA + cmd + 2 HCCA) as active. */\n    for (qid = 0; qid < 7; qid++) {\n        static uint8_t qid2fifo[] = { 3, 2, 1, 0, 4, 5, 6 };\n        iwn_prph_write(sc, IWN4965_SCHED_QUEUE_STATUS(qid),\n            IWN4965_TXQ_STATUS_ACTIVE | qid2fifo[qid] << 1);\n    }\n    iwn_nic_unlock(sc);\n    return 0;\n}\n\n/*\n * This function is called after the initialization or runtime firmware\n * notifies us of its readiness (called in a process context).\n */\nint ItlIwn::\niwn5000_post_alive(struct iwn_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    ItlIwn *that = container_of(sc, ItlIwn, com);\n    int error, qid;\n\n    /* Switch to using ICT interrupt mode. */\n    that->iwn5000_ict_reset(sc);\n\n    if ((error = iwn_nic_lock(sc)) != 0)\n        return error;\n\n    /* Clear TX scheduler state in SRAM. */\n    sc->sched_base = iwn_prph_read(sc, IWN_SCHED_SRAM_ADDR);\n    iwn_mem_set_region_4(sc, sc->sched_base + IWN5000_SCHED_CTX_OFF, 0,\n        IWN5000_SCHED_CTX_LEN / sizeof (uint32_t));\n\n    /* Set physical address of TX scheduler rings (1KB aligned). */\n    iwn_prph_write(sc, IWN5000_SCHED_DRAM_ADDR, sc->sched_dma.paddr >> 10);\n\n    /* Disable scheduler chain extension (enabled by default in HW). */\n    iwn_prph_write(sc, IWN5000_SCHED_CHAINEXT_EN, 0);\n\n    IWN_SETBITS(sc, IWN_FH_TX_CHICKEN, IWN_FH_TX_CHICKEN_SCHED_RETRY);\n\n    /* Enable chain mode for all queues, except command queue. */\n    iwn_prph_write(sc, IWN5000_SCHED_QCHAIN_SEL, 0xfffef);\n    iwn_prph_write(sc, IWN5000_SCHED_AGGR_SEL, 0);\n\n    for (qid = 0; qid < IWN5000_NTXQUEUES; qid++) {\n        iwn_prph_write(sc, IWN5000_SCHED_QUEUE_RDPTR(qid), 0);\n        IWN_WRITE(sc, IWN_HBUS_TARG_WRPTR, qid << 8 | 0);\n\n        iwn_mem_write(sc, sc->sched_base +\n            IWN5000_SCHED_QUEUE_OFFSET(qid), 0);\n        /* Set scheduler window size and frame limit. */\n        iwn_mem_write(sc, sc->sched_base +\n            IWN5000_SCHED_QUEUE_OFFSET(qid) + 4,\n            IWN_SCHED_LIMIT << 16 | IWN_SCHED_WINSZ);\n    }\n\n    /* Enable interrupts for all our 20 queues. */\n    iwn_prph_write(sc, IWN5000_SCHED_INTR_MASK, 0xfffff);\n    /* Identify TX FIFO rings (0-7). */\n    iwn_prph_write(sc, IWN5000_SCHED_TXFACT, 0xff);\n\n    /* Mark TX rings (4 EDCA + cmd + 2 HCCA) as active. */\n    for (qid = 0; qid < 7; qid++) {\n        static uint8_t qid2fifo[] = { 3, 2, 1, 0, 7, 5, 6 };\n        iwn_prph_write(sc, IWN5000_SCHED_QUEUE_STATUS(qid),\n            IWN5000_TXQ_STATUS_ACTIVE | qid2fifo[qid]);\n    }\n    iwn_nic_unlock(sc);\n\n    /* Configure WiMAX coexistence for combo adapters. */\n    error = iwn5000_send_wimax_coex(sc);\n    if (error != 0) {\n        XYLog(\"%s: could not configure WiMAX coexistence\\n\",\n            sc->sc_dev.dv_xname);\n        return error;\n    }\n    if (sc->hw_type != IWN_HW_REV_TYPE_5150) {\n        /* Perform crystal calibration. */\n        error = iwn5000_crystal_calib(sc);\n        if (error != 0) {\n            XYLog(\"%s: crystal calibration failed\\n\",\n                sc->sc_dev.dv_xname);\n            return error;\n        }\n    }\n    if (!(sc->sc_flags & IWN_FLAG_CALIB_DONE)) {\n        /* Query calibration from the initialization firmware. */\n        if ((error = iwn5000_query_calibration(sc)) != 0) {\n            XYLog(\"%s: could not query calibration\\n\",\n                sc->sc_dev.dv_xname);\n            return error;\n        }\n        /*\n         * We have the calibration results now, reboot with the\n         * runtime firmware (call ourselves recursively!)\n         */\n        that->iwn_hw_stop(sc);\n        error = that->iwn_hw_init(sc);\n    } else {\n        /* Send calibration results to runtime firmware. */\n        error = iwn5000_send_calibration(sc);\n    }\n    return error;\n}\n\n/*\n * The firmware boot code is small and is intended to be copied directly into\n * the NIC internal memory (no DMA transfer).\n */\nint ItlIwn::\niwn4965_load_bootcode(struct iwn_softc *sc, const uint8_t *ucode, int size)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    int error, ntries;\n\n    size /= sizeof (uint32_t);\n\n    if ((error = iwn_nic_lock(sc)) != 0)\n        return error;\n\n    /* Copy microcode image into NIC memory. */\n    iwn_prph_write_region_4(sc, IWN_BSM_SRAM_BASE,\n        (const uint32_t *)ucode, size);\n\n    iwn_prph_write(sc, IWN_BSM_WR_MEM_SRC, 0);\n    iwn_prph_write(sc, IWN_BSM_WR_MEM_DST, IWN_FW_TEXT_BASE);\n    iwn_prph_write(sc, IWN_BSM_WR_DWCOUNT, size);\n\n    /* Start boot load now. */\n    iwn_prph_write(sc, IWN_BSM_WR_CTRL, IWN_BSM_WR_CTRL_START);\n\n    /* Wait for transfer to complete. */\n    for (ntries = 0; ntries < 1000; ntries++) {\n        if (!(iwn_prph_read(sc, IWN_BSM_WR_CTRL) &\n            IWN_BSM_WR_CTRL_START))\n            break;\n        DELAY(10);\n    }\n    if (ntries == 1000) {\n        XYLog(\"%s: could not load boot firmware\\n\",\n            sc->sc_dev.dv_xname);\n        iwn_nic_unlock(sc);\n        return ETIMEDOUT;\n    }\n\n    /* Enable boot after power up. */\n    iwn_prph_write(sc, IWN_BSM_WR_CTRL, IWN_BSM_WR_CTRL_START_EN);\n\n    iwn_nic_unlock(sc);\n    return 0;\n}\n\nint ItlIwn::\niwn4965_load_firmware(struct iwn_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    ItlIwn *that = container_of(sc, ItlIwn, com);\n    struct iwn_fw_info *fw = &sc->fw;\n    struct iwn_dma_info *dma = &sc->fw_dma;\n    int error;\n\n    /* Copy initialization sections into pre-allocated DMA-safe memory. */\n    memcpy(dma->vaddr, fw->init.data, fw->init.datasz);\n//    bus_dmamap_sync(sc->sc_dmat, dma->map, 0, fw->init.datasz,\n//        BUS_DMASYNC_PREWRITE);\n    memcpy((uint8_t *)dma->vaddr + IWN4965_FW_DATA_MAXSZ,\n        fw->init.text, fw->init.textsz);\n//    bus_dmamap_sync(sc->sc_dmat, dma->map, IWN4965_FW_DATA_MAXSZ,\n//        fw->init.textsz, BUS_DMASYNC_PREWRITE);\n\n    /* Tell adapter where to find initialization sections. */\n    if ((error = iwn_nic_lock(sc)) != 0)\n        return error;\n    iwn_prph_write(sc, IWN_BSM_DRAM_DATA_ADDR, dma->paddr >> 4);\n    iwn_prph_write(sc, IWN_BSM_DRAM_DATA_SIZE, fw->init.datasz);\n    iwn_prph_write(sc, IWN_BSM_DRAM_TEXT_ADDR,\n        (dma->paddr + IWN4965_FW_DATA_MAXSZ) >> 4);\n    iwn_prph_write(sc, IWN_BSM_DRAM_TEXT_SIZE, fw->init.textsz);\n    iwn_nic_unlock(sc);\n\n    /* Load firmware boot code. */\n    error = iwn4965_load_bootcode(sc, fw->boot.text, fw->boot.textsz);\n    if (error != 0) {\n        XYLog(\"%s: could not load boot firmware\\n\",\n            sc->sc_dev.dv_xname);\n        return error;\n    }\n    /* Now press \"execute\". */\n    IWN_WRITE(sc, IWN_RESET, 0);\n\n    /* Wait at most one second for first alive notification. */\n    if ((error = that->tsleep_nsec(sc, PCATCH, \"iwninit\", SEC_TO_NSEC(1))) != 0) {\n        XYLog(\"%s: timeout waiting for adapter to initialize\\n\",\n            sc->sc_dev.dv_xname);\n        return error;\n    }\n\n    /* Retrieve current temperature for initial TX power calibration. */\n    sc->rawtemp = sc->ucode_info.temp[3].chan20MHz;\n    sc->temp = iwn4965_get_temperature(sc);\n\n    /* Copy runtime sections into pre-allocated DMA-safe memory. */\n    memcpy(dma->vaddr, fw->main.data, fw->main.datasz);\n//    bus_dmamap_sync(sc->sc_dmat, dma->map, 0, fw->main.datasz,\n//        BUS_DMASYNC_PREWRITE);\n    memcpy((uint8_t *)dma->vaddr + IWN4965_FW_DATA_MAXSZ,\n        fw->main.text, fw->main.textsz);\n//    bus_dmamap_sync(sc->sc_dmat, dma->map, IWN4965_FW_DATA_MAXSZ,\n//        fw->main.textsz, BUS_DMASYNC_PREWRITE);\n\n    /* Tell adapter where to find runtime sections. */\n    if ((error = iwn_nic_lock(sc)) != 0)\n        return error;\n    iwn_prph_write(sc, IWN_BSM_DRAM_DATA_ADDR, dma->paddr >> 4);\n    iwn_prph_write(sc, IWN_BSM_DRAM_DATA_SIZE, fw->main.datasz);\n    iwn_prph_write(sc, IWN_BSM_DRAM_TEXT_ADDR,\n        (dma->paddr + IWN4965_FW_DATA_MAXSZ) >> 4);\n    iwn_prph_write(sc, IWN_BSM_DRAM_TEXT_SIZE,\n        IWN_FW_UPDATED | fw->main.textsz);\n    iwn_nic_unlock(sc);\n\n    return 0;\n}\n\nint ItlIwn::\niwn5000_load_firmware_section(struct iwn_softc *sc, uint32_t dst,\n    const uint8_t *section, int size)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    ItlIwn *that = container_of(sc, ItlIwn, com);\n    struct iwn_dma_info *dma = &sc->fw_dma;\n    int error;\n\n    /* Copy firmware section into pre-allocated DMA-safe memory. */\n    memcpy(dma->vaddr, section, size);\n//    bus_dmamap_sync(sc->sc_dmat, dma->map, 0, size, BUS_DMASYNC_PREWRITE);\n\n    if ((error = iwn_nic_lock(sc)) != 0)\n        return error;\n\n    IWN_WRITE(sc, IWN_FH_TX_CONFIG(IWN_SRVC_DMACHNL),\n        IWN_FH_TX_CONFIG_DMA_PAUSE);\n\n    IWN_WRITE(sc, IWN_FH_SRAM_ADDR(IWN_SRVC_DMACHNL), dst);\n    IWN_WRITE(sc, IWN_FH_TFBD_CTRL0(IWN_SRVC_DMACHNL),\n        IWN_LOADDR(dma->paddr));\n    IWN_WRITE(sc, IWN_FH_TFBD_CTRL1(IWN_SRVC_DMACHNL),\n        IWN_HIADDR(dma->paddr) << 28 | size);\n    IWN_WRITE(sc, IWN_FH_TXBUF_STATUS(IWN_SRVC_DMACHNL),\n        IWN_FH_TXBUF_STATUS_TBNUM(1) |\n        IWN_FH_TXBUF_STATUS_TBIDX(1) |\n        IWN_FH_TXBUF_STATUS_TFBD_VALID);\n\n    /* Kick Flow Handler to start DMA transfer. */\n    IWN_WRITE(sc, IWN_FH_TX_CONFIG(IWN_SRVC_DMACHNL),\n        IWN_FH_TX_CONFIG_DMA_ENA | IWN_FH_TX_CONFIG_CIRQ_HOST_ENDTFD);\n\n    iwn_nic_unlock(sc);\n\n    /* Wait at most five seconds for FH DMA transfer to complete. */\n    return that->tsleep_nsec(sc, PCATCH, \"iwninit\", SEC_TO_NSEC(5));\n}\n\nint ItlIwn::\niwn5000_load_firmware(struct iwn_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwn_fw_part *fw;\n    int error;\n\n    /* Load the initialization firmware on first boot only. */\n    fw = (sc->sc_flags & IWN_FLAG_CALIB_DONE) ?\n        &sc->fw.main : &sc->fw.init;\n\n    error = iwn5000_load_firmware_section(sc, IWN_FW_TEXT_BASE,\n        fw->text, fw->textsz);\n    if (error != 0) {\n        XYLog(\"%s: could not load firmware %s section\\n\",\n            sc->sc_dev.dv_xname, \".text\");\n        return error;\n    }\n    error = iwn5000_load_firmware_section(sc, IWN_FW_DATA_BASE,\n        fw->data, fw->datasz);\n    if (error != 0) {\n        XYLog(\"%s: could not load firmware %s section\\n\",\n            sc->sc_dev.dv_xname, \".data\");\n        return error;\n    }\n\n    /* Now press \"execute\". */\n    IWN_WRITE(sc, IWN_RESET, 0);\n    return 0;\n}\n\n/*\n * Extract text and data sections from a legacy firmware image.\n */\nint ItlIwn::\niwn_read_firmware_leg(struct iwn_softc *sc, struct iwn_fw_info *fw)\n{\n    const uint32_t *ptr;\n    size_t hdrlen = 24;\n    uint32_t rev;\n\n    ptr = (const uint32_t *)fw->data;\n    rev = letoh32(*ptr++);\n\n    /* Check firmware API version. */\n    if (IWN_FW_API(rev) <= 1) {\n        XYLog(\"%s: bad firmware, need API version >=2\\n\",\n            sc->sc_dev.dv_xname);\n        return EINVAL;\n    }\n    if (IWN_FW_API(rev) >= 3) {\n        /* Skip build number (version 2 header). */\n        hdrlen += 4;\n        ptr++;\n    }\n    if (fw->size < hdrlen) {\n        XYLog(\"%s: firmware too short: %zu bytes\\n\",\n            sc->sc_dev.dv_xname, fw->size);\n        return EINVAL;\n    }\n    fw->main.textsz = letoh32(*ptr++);\n    fw->main.datasz = letoh32(*ptr++);\n    fw->init.textsz = letoh32(*ptr++);\n    fw->init.datasz = letoh32(*ptr++);\n    fw->boot.textsz = letoh32(*ptr++);\n\n    /* Check that all firmware sections fit. */\n    if (fw->size < hdrlen + fw->main.textsz + fw->main.datasz +\n        fw->init.textsz + fw->init.datasz + fw->boot.textsz) {\n        XYLog(\"%s: firmware too short: %zu bytes\\n\",\n            sc->sc_dev.dv_xname, fw->size);\n        return EINVAL;\n    }\n\n    /* Get pointers to firmware sections. */\n    fw->main.text = (const uint8_t *)ptr;\n    fw->main.data = fw->main.text + fw->main.textsz;\n    fw->init.text = fw->main.data + fw->main.datasz;\n    fw->init.data = fw->init.text + fw->init.textsz;\n    fw->boot.text = fw->init.data + fw->init.datasz;\n    return 0;\n}\n\n/*\n * Extract text and data sections from a TLV firmware image.\n */\nint ItlIwn::\niwn_read_firmware_tlv(struct iwn_softc *sc, struct iwn_fw_info *fw,\n    uint16_t alt)\n{\n    const struct iwn_fw_tlv_hdr *hdr;\n    const struct iwn_fw_tlv *tlv;\n    const uint8_t *ptr, *end;\n    uint64_t altmask;\n    uint32_t len;\n\n    if (fw->size < sizeof (*hdr)) {\n        XYLog(\"%s: firmware too short: %zu bytes\\n\",\n            sc->sc_dev.dv_xname, fw->size);\n        return EINVAL;\n    }\n    hdr = (const struct iwn_fw_tlv_hdr *)fw->data;\n    if (hdr->signature != htole32(IWN_FW_SIGNATURE)) {\n        XYLog(\"%s: bad firmware signature 0x%08x\\n\",\n            sc->sc_dev.dv_xname, letoh32(hdr->signature));\n        return EINVAL;\n    }\n    DPRINTF((\"FW: \\\"%.64s\\\", build 0x%x\\n\", hdr->descr,\n        letoh32(hdr->build)));\n\n    /*\n     * Select the closest supported alternative that is less than\n     * or equal to the specified one.\n     */\n    altmask = letoh64(hdr->altmask);\n    while (alt > 0 && !(altmask & (1ULL << alt)))\n        alt--;    /* Downgrade. */\n    DPRINTF((\"using alternative %d\\n\", alt));\n\n    ptr = (const uint8_t *)(hdr + 1);\n    end = (const uint8_t *)(fw->data + fw->size);\n\n    /* Parse type-length-value fields. */\n    while (ptr + sizeof (*tlv) <= end) {\n        tlv = (const struct iwn_fw_tlv *)ptr;\n        len = letoh32(tlv->len);\n\n        ptr += sizeof (*tlv);\n        if (ptr + len > end) {\n            XYLog(\"%s: firmware too short: %zu bytes\\n\",\n                sc->sc_dev.dv_xname, fw->size);\n            return EINVAL;\n        }\n        /* Skip other alternatives. */\n        if (tlv->alt != 0 && tlv->alt != htole16(alt))\n            goto next;\n\n        switch (letoh16(tlv->type)) {\n        case IWN_FW_TLV_MAIN_TEXT:\n            fw->main.text = ptr;\n            fw->main.textsz = len;\n            break;\n        case IWN_FW_TLV_MAIN_DATA:\n            fw->main.data = ptr;\n            fw->main.datasz = len;\n            break;\n        case IWN_FW_TLV_INIT_TEXT:\n            fw->init.text = ptr;\n            fw->init.textsz = len;\n            break;\n        case IWN_FW_TLV_INIT_DATA:\n            fw->init.data = ptr;\n            fw->init.datasz = len;\n            break;\n        case IWN_FW_TLV_BOOT_TEXT:\n            fw->boot.text = ptr;\n            fw->boot.textsz = len;\n            break;\n        case IWN_FW_TLV_ENH_SENS:\n            if (len !=  0) {\n                XYLog(\"%s: TLV type %d has invalid size %u\\n\",\n                    sc->sc_dev.dv_xname, letoh16(tlv->type),\n                    len);\n                goto next;\n            }\n            sc->sc_flags |= IWN_FLAG_ENH_SENS;\n            break;\n        case IWN_FW_TLV_PHY_CALIB:\n            if (len != sizeof(uint32_t)) {\n                XYLog(\"%s: TLV type %d has invalid size %u\\n\",\n                    sc->sc_dev.dv_xname, letoh16(tlv->type),\n                    len);\n                goto next;\n            }\n            if (letoh32(*ptr) <= IWN5000_PHY_CALIB_MAX) {\n                sc->reset_noise_gain = letoh32(*ptr);\n                sc->noise_gain = letoh32(*ptr) + 1;\n            }\n            break;\n        case IWN_FW_TLV_FLAGS:\n            if (len < sizeof(uint32_t))\n                break;\n            if (len % sizeof(uint32_t))\n                break;\n            sc->tlv_feature_flags = letoh32(*ptr);\n            DPRINTF((\"feature: 0x%08x\\n\", sc->tlv_feature_flags));\n            break;\n        default:\n            DPRINTF((\"TLV type %d not handled\\n\",\n                letoh16(tlv->type)));\n            break;\n        }\n next:        /* TLV fields are 32-bit aligned. */\n        ptr += (len + 3) & ~3;\n    }\n    return 0;\n}\n\nint ItlIwn::\niwn_read_firmware(struct iwn_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwn_fw_info *fw = &sc->fw;\n    int error = 0;\n    OSData *fwData = NULL;\n\n    /*\n     * Some PHY calibration commands are firmware-dependent; these\n     * are the default values that will be overridden if\n     * necessary.\n     */\n    sc->reset_noise_gain = IWN5000_PHY_CALIB_RESET_NOISE_GAIN;\n    sc->noise_gain = IWN5000_PHY_CALIB_NOISE_GAIN;\n\n    memset(fw, 0, sizeof (*fw));\n\n    /* Read firmware image from filesystem. */\n//    if ((error = loadfirmware(sc->fwname, &fw->data, &fw->size)) != 0) {\n//        XYLog(\"%s: could not read firmware %s (error %d)\\n\",\n//            sc->sc_dev.dv_xname, sc->fwname, error);\n//        return error;\n//    }\n    fwData = getFWDescByName(sc->fwname);\n    if (fwData == NULL) {\n        error = EINVAL;\n        XYLog(\"%s resource load fail.\\n\", sc->fwname);\n        return error;\n    }\n    fw->size = fwData->getLength() * 4;\n    fw->data = (u_char *)malloc(fw->size, 1, 1);\n    uncompressFirmware((u_char *)fw->data, (uint *)&fw->size, (u_char *)fwData->getBytesNoCopy(), fwData->getLength());\n    XYLog(\"load firmware %s done\\n\", sc->fwname);\n    OSSafeReleaseNULL(fwData);\n    \n    if (fw->size < sizeof (uint32_t)) {\n        XYLog(\"%s: firmware too short: %zu bytes\\n\",\n            sc->sc_dev.dv_xname, fw->size);\n        ::free(fw->data);\n        return EINVAL;\n    }\n\n    /* Retrieve text and data sections. */\n    if (*(const uint32_t *)fw->data != 0)    /* Legacy image. */\n        error = iwn_read_firmware_leg(sc, fw);\n    else\n        error = iwn_read_firmware_tlv(sc, fw, 1);\n    if (error != 0) {\n        XYLog(\"%s: could not read firmware sections\\n\",\n            sc->sc_dev.dv_xname);\n        ::free(fw->data);\n        return error;\n    }\n\n    /* Make sure text and data sections fit in hardware memory. */\n    if (fw->main.textsz > sc->fw_text_maxsz ||\n        fw->main.datasz > sc->fw_data_maxsz ||\n        fw->init.textsz > sc->fw_text_maxsz ||\n        fw->init.datasz > sc->fw_data_maxsz ||\n        fw->boot.textsz > IWN_FW_BOOT_TEXT_MAXSZ ||\n        (fw->boot.textsz & 3) != 0) {\n        XYLog(\"%s: firmware sections too large\\n\",\n            sc->sc_dev.dv_xname);\n        ::free(fw->data);\n        return EINVAL;\n    }\n  \n    /* We can proceed with loading the firmware. */\n    return 0;\n}\n\nint ItlIwn::\niwn_clock_wait(struct iwn_softc *sc)\n{\n    int ntries;\n\n    /* Set \"initialization complete\" bit. */\n    IWN_SETBITS(sc, IWN_GP_CNTRL, IWN_GP_CNTRL_INIT_DONE);\n\n    /* Wait for clock stabilization. */\n    for (ntries = 0; ntries < 2500; ntries++) {\n        if (IWN_READ(sc, IWN_GP_CNTRL) & IWN_GP_CNTRL_MAC_CLOCK_READY)\n            return 0;\n        DELAY(10);\n    }\n    XYLog(\"%s: timeout waiting for clock stabilization\\n\",\n        sc->sc_dev.dv_xname);\n    return ETIMEDOUT;\n}\n\nint ItlIwn::\niwn_apm_init(struct iwn_softc *sc)\n{\n    pcireg_t reg;\n    int error;\n\n    /* Disable L0s exit timer (NMI bug workaround). */\n    IWN_SETBITS(sc, IWN_GIO_CHICKEN, IWN_GIO_CHICKEN_DIS_L0S_TIMER);\n    /* Don't wait for ICH L0s (ICH bug workaround). */\n    IWN_SETBITS(sc, IWN_GIO_CHICKEN, IWN_GIO_CHICKEN_L1A_NO_L0S_RX);\n\n    /* Set FH wait threshold to max (HW bug under stress workaround). */\n    IWN_SETBITS(sc, IWN_DBG_HPET_MEM, 0xffff0000);\n\n    /* Enable HAP INTA to move adapter from L1a to L0s. */\n    IWN_SETBITS(sc, IWN_HW_IF_CONFIG, IWN_HW_IF_CONFIG_HAP_WAKE_L1A);\n\n    /* Retrieve PCIe Active State Power Management (ASPM). */\n    reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag,\n        sc->sc_cap_off + PCI_PCIE_LCSR);\n    /* Workaround for HW instability in PCIe L0->L0s->L1 transition. */\n    if (reg & PCI_PCIE_LCSR_ASPM_L1)    /* L1 Entry enabled. */\n        IWN_SETBITS(sc, IWN_GIO, IWN_GIO_L0S_ENA);\n    else\n        IWN_CLRBITS(sc, IWN_GIO, IWN_GIO_L0S_ENA);\n\n    if (sc->hw_type != IWN_HW_REV_TYPE_4965 &&\n        sc->hw_type <= IWN_HW_REV_TYPE_1000)\n        IWN_SETBITS(sc, IWN_ANA_PLL, IWN_ANA_PLL_INIT);\n\n    /* Wait for clock stabilization before accessing prph. */\n    if ((error = iwn_clock_wait(sc)) != 0)\n        return error;\n\n    if ((error = iwn_nic_lock(sc)) != 0)\n        return error;\n    if (sc->hw_type == IWN_HW_REV_TYPE_4965) {\n        /* Enable DMA and BSM (Bootstrap State Machine). */\n        iwn_prph_write(sc, IWN_APMG_CLK_EN,\n            IWN_APMG_CLK_CTRL_DMA_CLK_RQT |\n            IWN_APMG_CLK_CTRL_BSM_CLK_RQT);\n    } else {\n        /* Enable DMA. */\n        iwn_prph_write(sc, IWN_APMG_CLK_EN,\n            IWN_APMG_CLK_CTRL_DMA_CLK_RQT);\n    }\n    DELAY(20);\n    /* Disable L1-Active. */\n    iwn_prph_setbits(sc, IWN_APMG_PCI_STT, IWN_APMG_PCI_STT_L1A_DIS);\n    iwn_nic_unlock(sc);\n\n    return 0;\n}\n\nvoid ItlIwn::\niwn_apm_stop_master(struct iwn_softc *sc)\n{\n    int ntries;\n\n    /* Stop busmaster DMA activity. */\n    IWN_SETBITS(sc, IWN_RESET, IWN_RESET_STOP_MASTER);\n    for (ntries = 0; ntries < 100; ntries++) {\n        if (IWN_READ(sc, IWN_RESET) & IWN_RESET_MASTER_DISABLED)\n            return;\n        DELAY(10);\n    }\n    XYLog(\"%s: timeout waiting for master\\n\", sc->sc_dev.dv_xname);\n}\n\nvoid ItlIwn::\niwn_apm_stop(struct iwn_softc *sc)\n{\n    iwn_apm_stop_master(sc);\n\n    /* Reset the entire device. */\n    IWN_SETBITS(sc, IWN_RESET, IWN_RESET_SW);\n    DELAY(10);\n    /* Clear \"initialization complete\" bit. */\n    IWN_CLRBITS(sc, IWN_GP_CNTRL, IWN_GP_CNTRL_INIT_DONE);\n}\n\nint ItlIwn::\niwn4965_nic_config(struct iwn_softc *sc)\n{\n    if (IWN_RFCFG_TYPE(sc->rfcfg) == 1) {\n        /*\n         * I don't believe this to be correct but this is what the\n         * vendor driver is doing. Probably the bits should not be\n         * shifted in IWN_RFCFG_*.\n         */\n        IWN_SETBITS(sc, IWN_HW_IF_CONFIG,\n            IWN_RFCFG_TYPE(sc->rfcfg) |\n            IWN_RFCFG_STEP(sc->rfcfg) |\n            IWN_RFCFG_DASH(sc->rfcfg));\n    }\n    IWN_SETBITS(sc, IWN_HW_IF_CONFIG,\n        IWN_HW_IF_CONFIG_RADIO_SI | IWN_HW_IF_CONFIG_MAC_SI);\n    return 0;\n}\n\nint ItlIwn::\niwn5000_nic_config(struct iwn_softc *sc)\n{\n    uint32_t tmp;\n    int error;\n\n    if (IWN_RFCFG_TYPE(sc->rfcfg) < 3) {\n        IWN_SETBITS(sc, IWN_HW_IF_CONFIG,\n            IWN_RFCFG_TYPE(sc->rfcfg) |\n            IWN_RFCFG_STEP(sc->rfcfg) |\n            IWN_RFCFG_DASH(sc->rfcfg));\n    }\n    IWN_SETBITS(sc, IWN_HW_IF_CONFIG,\n        IWN_HW_IF_CONFIG_RADIO_SI | IWN_HW_IF_CONFIG_MAC_SI);\n\n    if ((error = iwn_nic_lock(sc)) != 0)\n        return error;\n    iwn_prph_setbits(sc, IWN_APMG_PS, IWN_APMG_PS_EARLY_PWROFF_DIS);\n\n    if (sc->hw_type == IWN_HW_REV_TYPE_1000) {\n        /*\n         * Select first Switching Voltage Regulator (1.32V) to\n         * solve a stability issue related to noisy DC2DC line\n         * in the silicon of 1000 Series.\n         */\n        tmp = iwn_prph_read(sc, IWN_APMG_DIGITAL_SVR);\n        tmp &= ~IWN_APMG_DIGITAL_SVR_VOLTAGE_MASK;\n        tmp |= IWN_APMG_DIGITAL_SVR_VOLTAGE_1_32;\n        iwn_prph_write(sc, IWN_APMG_DIGITAL_SVR, tmp);\n    }\n    iwn_nic_unlock(sc);\n\n    if (sc->sc_flags & IWN_FLAG_INTERNAL_PA) {\n        /* Use internal power amplifier only. */\n        IWN_WRITE(sc, IWN_GP_DRIVER, IWN_GP_DRIVER_RADIO_2X2_IPA);\n    }\n    if ((sc->hw_type == IWN_HW_REV_TYPE_6050 ||\n         sc->hw_type == IWN_HW_REV_TYPE_6005) && sc->calib_ver >= 6) {\n        /* Indicate that ROM calibration version is >=6. */\n        IWN_SETBITS(sc, IWN_GP_DRIVER, IWN_GP_DRIVER_CALIB_VER6);\n    }\n    if (sc->hw_type == IWN_HW_REV_TYPE_6005)\n        IWN_SETBITS(sc, IWN_GP_DRIVER, IWN_GP_DRIVER_6050_1X2);\n    if (sc->hw_type == IWN_HW_REV_TYPE_2030 ||\n        sc->hw_type == IWN_HW_REV_TYPE_2000 ||\n        sc->hw_type == IWN_HW_REV_TYPE_135 ||\n        sc->hw_type == IWN_HW_REV_TYPE_105)\n        IWN_SETBITS(sc, IWN_GP_DRIVER, IWN_GP_DRIVER_RADIO_IQ_INVERT);\n    return 0;\n}\n\n/*\n * Take NIC ownership over Intel Active Management Technology (AMT).\n */\nint ItlIwn::\niwn_hw_prepare(struct iwn_softc *sc)\n{\n    int ntries;\n\n    /* Check if hardware is ready. */\n    IWN_SETBITS(sc, IWN_HW_IF_CONFIG, IWN_HW_IF_CONFIG_NIC_READY);\n    for (ntries = 0; ntries < 5; ntries++) {\n        if (IWN_READ(sc, IWN_HW_IF_CONFIG) &\n            IWN_HW_IF_CONFIG_NIC_READY)\n            return 0;\n        DELAY(10);\n    }\n\n    /* Hardware not ready, force into ready state. */\n    IWN_SETBITS(sc, IWN_HW_IF_CONFIG, IWN_HW_IF_CONFIG_PREPARE);\n    for (ntries = 0; ntries < 15000; ntries++) {\n        if (!(IWN_READ(sc, IWN_HW_IF_CONFIG) &\n            IWN_HW_IF_CONFIG_PREPARE_DONE))\n            break;\n        DELAY(10);\n    }\n    if (ntries == 15000)\n        return ETIMEDOUT;\n\n    /* Hardware should be ready now. */\n    IWN_SETBITS(sc, IWN_HW_IF_CONFIG, IWN_HW_IF_CONFIG_NIC_READY);\n    for (ntries = 0; ntries < 5; ntries++) {\n        if (IWN_READ(sc, IWN_HW_IF_CONFIG) &\n            IWN_HW_IF_CONFIG_NIC_READY)\n            return 0;\n        DELAY(10);\n    }\n    return ETIMEDOUT;\n}\n\nint ItlIwn::\niwn_hw_init(struct iwn_softc *sc)\n{\n    struct iwn_ops *ops = &sc->ops;\n    int error, chnl, qid;\n\n    /* Clear pending interrupts. */\n    IWN_WRITE(sc, IWN_INT, 0xffffffff);\n\n    if ((error = iwn_apm_init(sc)) != 0) {\n        XYLog(\"%s: could not power on adapter\\n\",\n            sc->sc_dev.dv_xname);\n        return error;\n    }\n\n    /* Select VMAIN power source. */\n    if ((error = iwn_nic_lock(sc)) != 0)\n        return error;\n    iwn_prph_clrbits(sc, IWN_APMG_PS, IWN_APMG_PS_PWR_SRC_MASK);\n    iwn_nic_unlock(sc);\n\n    /* Perform adapter-specific initialization. */\n    if ((error = ops->nic_config(sc)) != 0)\n        return error;\n\n    /* Initialize RX ring. */\n    if ((error = iwn_nic_lock(sc)) != 0)\n        return error;\n    IWN_WRITE(sc, IWN_FH_RX_CONFIG, 0);\n    IWN_WRITE(sc, IWN_FH_RX_WPTR, 0);\n    /* Set physical address of RX ring (256-byte aligned). */\n    IWN_WRITE(sc, IWN_FH_RX_BASE, sc->rxq.desc_dma.paddr >> 8);\n    /* Set physical address of RX status (16-byte aligned). */\n    IWN_WRITE(sc, IWN_FH_STATUS_WPTR, sc->rxq.stat_dma.paddr >> 4);\n    /* Enable RX. */\n    IWN_WRITE(sc, IWN_FH_RX_CONFIG,\n        IWN_FH_RX_CONFIG_ENA           |\n        IWN_FH_RX_CONFIG_IGN_RXF_EMPTY |    /* HW bug workaround */\n        IWN_FH_RX_CONFIG_IRQ_DST_HOST  |\n        IWN_FH_RX_CONFIG_SINGLE_FRAME  |\n        IWN_FH_RX_CONFIG_RB_TIMEOUT(0x11) | /* about 1/2 msec */\n        IWN_FH_RX_CONFIG_NRBD(IWN_RX_RING_COUNT_LOG));\n    iwn_nic_unlock(sc);\n    IWN_WRITE(sc, IWN_FH_RX_WPTR, (IWN_RX_RING_COUNT - 1) & ~7);\n\n    if ((error = iwn_nic_lock(sc)) != 0)\n        return error;\n\n    /* Initialize TX scheduler. */\n    iwn_prph_write(sc, sc->sched_txfact_addr, 0);\n\n    /* Set physical address of \"keep warm\" page (16-byte aligned). */\n    IWN_WRITE(sc, IWN_FH_KW_ADDR, sc->kw_dma.paddr >> 4);\n\n    /* Initialize TX rings. */\n    for (qid = 0; qid < sc->ntxqs; qid++) {\n        struct iwn_tx_ring *txq = &sc->txq[qid];\n\n        /* Set physical address of TX ring (256-byte aligned). */\n        IWN_WRITE(sc, IWN_FH_CBBC_QUEUE(qid),\n            txq->desc_dma.paddr >> 8);\n    }\n    iwn_nic_unlock(sc);\n\n    /* Enable DMA channels. */\n    for (chnl = 0; chnl < sc->ndmachnls; chnl++) {\n        IWN_WRITE(sc, IWN_FH_TX_CONFIG(chnl),\n            IWN_FH_TX_CONFIG_DMA_ENA |\n            IWN_FH_TX_CONFIG_DMA_CREDIT_ENA);\n    }\n\n    /* Clear \"radio off\" and \"commands blocked\" bits. */\n    IWN_WRITE(sc, IWN_UCODE_GP1_CLR, IWN_UCODE_GP1_RFKILL);\n    IWN_WRITE(sc, IWN_UCODE_GP1_CLR, IWN_UCODE_GP1_CMD_BLOCKED);\n\n    /* Clear pending interrupts. */\n    IWN_WRITE(sc, IWN_INT, 0xffffffff);\n    /* Enable interrupt coalescing. */\n    IWN_WRITE(sc, IWN_INT_COALESCING, 512 / 8);\n    /* Enable interrupts. */\n    IWN_WRITE(sc, IWN_INT_MASK, sc->int_mask);\n\n    /* _Really_ make sure \"radio off\" bit is cleared! */\n    IWN_WRITE(sc, IWN_UCODE_GP1_CLR, IWN_UCODE_GP1_RFKILL);\n    IWN_WRITE(sc, IWN_UCODE_GP1_CLR, IWN_UCODE_GP1_RFKILL);\n\n    /* Enable shadow registers. */\n    if (sc->hw_type >= IWN_HW_REV_TYPE_6000)\n        IWN_SETBITS(sc, IWN_SHADOW_REG_CTRL, 0x800fffff);\n\n    if ((error = ops->load_firmware(sc)) != 0) {\n        XYLog(\"%s: could not load firmware\\n\", sc->sc_dev.dv_xname);\n        return error;\n    }\n    /* Wait at most one second for firmware alive notification. */\n    if ((error = tsleep_nsec(sc, PCATCH, \"iwninit\", SEC_TO_NSEC(1))) != 0) {\n        XYLog(\"%s: timeout waiting for adapter to initialize\\n\",\n            sc->sc_dev.dv_xname);\n        return error;\n    }\n    /* Do post-firmware initialization. */\n    return ops->post_alive(sc);\n}\n\nvoid ItlIwn::\niwn_hw_stop(struct iwn_softc *sc)\n{\n    int chnl, qid, ntries;\n\n    IWN_WRITE(sc, IWN_RESET, IWN_RESET_NEVO);\n\n    /* Disable interrupts. */\n    IWN_WRITE(sc, IWN_INT_MASK, 0);\n    IWN_WRITE(sc, IWN_INT, 0xffffffff);\n    IWN_WRITE(sc, IWN_FH_INT, 0xffffffff);\n    sc->sc_flags &= ~IWN_FLAG_USE_ICT;\n\n    /* Make sure we no longer hold the NIC lock. */\n    iwn_nic_unlock(sc);\n\n    /* Stop TX scheduler. */\n    iwn_prph_write(sc, sc->sched_txfact_addr, 0);\n\n    /* Stop all DMA channels. */\n    if (iwn_nic_lock(sc) == 0) {\n        for (chnl = 0; chnl < sc->ndmachnls; chnl++) {\n            IWN_WRITE(sc, IWN_FH_TX_CONFIG(chnl), 0);\n            for (ntries = 0; ntries < 200; ntries++) {\n                if (IWN_READ(sc, IWN_FH_TX_STATUS) &\n                    IWN_FH_TX_STATUS_IDLE(chnl))\n                    break;\n                DELAY(10);\n            }\n        }\n        iwn_nic_unlock(sc);\n    }\n\n    /* Stop RX ring. */\n    iwn_reset_rx_ring(sc, &sc->rxq);\n\n    /* Reset all TX rings. */\n    for (qid = 0; qid < sc->ntxqs; qid++)\n        iwn_reset_tx_ring(sc, &sc->txq[qid]);\n\n    if (iwn_nic_lock(sc) == 0) {\n        iwn_prph_write(sc, IWN_APMG_CLK_DIS,\n            IWN_APMG_CLK_CTRL_DMA_CLK_RQT);\n        iwn_nic_unlock(sc);\n    }\n    DELAY(5);\n    /* Power OFF adapter. */\n    iwn_apm_stop(sc);\n}\n\nint ItlIwn::\niwn_init(struct _ifnet *ifp)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwn_softc *sc = (struct iwn_softc *)ifp->if_softc;\n    struct ieee80211com *ic = &sc->sc_ic;\n    int error;\n\n    memset(sc->bss_node_addr, 0, sizeof(sc->bss_node_addr));\n    sc->agg_queue_mask = 0;\n    memset(sc->sc_tx_ba, 0, sizeof(sc->sc_tx_ba));\n\n    if ((error = iwn_hw_prepare(sc)) != 0) {\n        XYLog(\"%s: hardware not ready\\n\", sc->sc_dev.dv_xname);\n        goto fail;\n    }\n\n    /* Initialize interrupt mask to default value. */\n    sc->int_mask = IWN_INT_MASK_DEF;\n    sc->sc_flags &= ~IWN_FLAG_USE_ICT;\n\n    /* Check that the radio is not disabled by hardware switch. */\n    if (!(IWN_READ(sc, IWN_GP_CNTRL) & IWN_GP_CNTRL_RFKILL)) {\n        XYLog(\"%s: radio is disabled by hardware switch\\n\",\n            sc->sc_dev.dv_xname);\n        error = EPERM;    /* :-) */\n        /* Re-enable interrupts. */\n        IWN_WRITE(sc, IWN_INT, 0xffffffff);\n        IWN_WRITE(sc, IWN_INT_MASK, sc->int_mask);\n        return error;\n    }\n\n    /* Read firmware images from the filesystem. */\n    if ((error = iwn_read_firmware(sc)) != 0) {\n        XYLog(\"%s: could not read firmware\\n\", sc->sc_dev.dv_xname);\n        goto fail;\n    }\n\n    /* Initialize hardware and upload firmware. */\n    error = iwn_hw_init(sc);\n    ::free(sc->fw.data);\n    if (error != 0) {\n        XYLog(\"%s: could not initialize hardware\\n\",\n            sc->sc_dev.dv_xname);\n        goto fail;\n    }\n\n    /* Configure adapter now that it is ready. */\n    if ((error = iwn_config(sc)) != 0) {\n        XYLog(\"%s: could not configure device\\n\",\n            sc->sc_dev.dv_xname);\n        goto fail;\n    }\n\n    ifq_clr_oactive(&ifp->if_snd);\n    ifp->if_flags |= IFF_RUNNING;\n\n    if (ic->ic_opmode != IEEE80211_M_MONITOR)\n        ieee80211_begin_scan(ifp);\n    else\n        ieee80211_new_state(ic, IEEE80211_S_RUN, -1);\n\n    return 0;\n\nfail:    iwn_stop(ifp);\n    return error;\n}\n\nvoid ItlIwn::\niwn_stop(struct _ifnet *ifp)\n{\n    struct iwn_softc *sc = (struct iwn_softc *)ifp->if_softc;\n    struct ieee80211com *ic = &sc->sc_ic;\n\n    timeout_del(&sc->calib_to);\n    ifp->if_timer = sc->sc_tx_timer = 0;\n    ifp->if_flags &= ~IFF_RUNNING;\n    ifq_clr_oactive(&ifp->if_snd);\n\n    ieee80211_new_state(ic, IEEE80211_S_INIT, -1);\n\n    /* Power OFF hardware. */\n    iwn_hw_stop(sc);\n}\n"
  },
  {
    "path": "itlwm/hal_iwn/ItlIwn.hpp",
    "content": "/*\n * Copyright (C) 2020  pigworlds\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n */\n/*    $OpenBSD: if_iwn.c,v 1.243 2020/11/12 15:16:18 krw Exp $    */\n\n/*-\n * Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n/*\n * Driver for Intel WiFi Link 4965 and 1000/5000/6000 Series 802.11 network\n * adapters.\n */\n\n#ifndef ItlIwn_hpp\n#define ItlIwn_hpp\n#include <compat.h>\n#include <linux/kernel.h>\n\n#include <sys/param.h>\n#include <sys/conf.h>\n#include <sys/kernel.h>\n#include <sys/malloc.h>\n#include <sys/mbuf.h>\n#include <sys/proc.h>\n#include <sys/socket.h>\n#include <sys/sockio.h>\n#include <sys/systm.h>\n#include <sys/endian.h>\n#include <sys/kpi_mbuf.h>\n\n#include \"if_iwnreg.h\"\n#include \"if_iwnvar.h\"\n#include <sys/pcireg.h>\n\n#include <IOKit/network/IOEthernetController.h>\n#include <IOKit/IOWorkLoop.h>\n#include <IOKit/network/IOGatedOutputQueue.h>\n#include <libkern/c++/OSString.h>\n#include <IOKit/IOService.h>\n#include <IOKit/pci/IOPCIDevice.h>\n#include <IOKit/IOLib.h>\n#include <libkern/OSKextLib.h>\n#include <libkern/c++/OSMetaClass.h>\n#include <IOKit/IOFilterInterruptEventSource.h>\n\n#include <HAL/ItlHalService.hpp>\n#include <HAL/ItlDriverInfo.hpp>\n#include <HAL/ItlDriverController.hpp>\n\nclass ItlIwn : public ItlHalService, ItlDriverInfo, ItlDriverController {\n    OSDeclareDefaultStructors(ItlIwn)\n    \npublic:\n    \n    //kext\n    void free() override;\n    virtual bool attach(IOPCIDevice *device) override;\n    virtual void detach(IOPCIDevice *device) override;\n    IOReturn enable(IONetworkInterface *netif) override;\n    IOReturn disable(IONetworkInterface *netif) override;\n    virtual struct ieee80211com *get80211Controller() override;\n    \n    static bool intrFilter(OSObject *object, IOFilterInterruptEventSource *src);\n    static IOReturn _iwn_start_task(OSObject *target, void *arg0, void *arg1, void *arg2, void *arg3);\n    \n    virtual ItlDriverInfo *getDriverInfo() override;\n    \n    virtual ItlDriverController *getDriverController() override;\n    \n    //driver info\n    virtual const char *getFirmwareVersion() override;\n    \n    virtual int16_t getBSSNoise() override;\n    \n    virtual bool is5GBandSupport() override;\n    \n    virtual int getTxNSS() override;\n    \n    virtual const char *getFirmwareName() override;\n    \n    virtual UInt32 supportedFeatures() override;\n\n    virtual const char *getFirmwareCountryCode() override;\n    \n    virtual uint32_t getTxQueueSize() override;\n    \n    //driver controller\n    virtual void clearScanningFlags() override;\n    \n    virtual IOReturn setMulticastList(IOEthernetAddress *addr, int count) override;\n    \n    void releaseAll();\n    void joinSSID(const char *ssid, const char *pwd);\n    \n    //utils\n    static void *mallocarray(size_t, size_t, int, int);\n    \n    static int        iwn_match(struct IOPCIDevice *device);\n    bool       iwn_attach(struct iwn_softc *sc, struct pci_attach_args *pa);\n    int        iwn4965_attach(struct iwn_softc *, pci_product_id_t);\n    int        iwn5000_attach(struct iwn_softc *, pci_product_id_t);\n    #if NBPFILTER > 0\n    void        iwn_radiotap_attach(struct iwn_softc *);\n    #endif\n    int        iwn_activate(struct iwn_softc *sc, int);\n    void       iwn_wakeup(struct iwn_softc *);\n    static void        iwn_init_task(void *);\n    int        iwn_eeprom_lock(struct iwn_softc *);\n    int        iwn_init_otprom(struct iwn_softc *);\n    int        iwn_read_prom_data(struct iwn_softc *, uint32_t, void *, int);\n    int        iwn_dma_contig_alloc(bus_dma_tag_t, struct iwn_dma_info *,\n                void **, bus_size_t, bus_size_t);\n    void        iwn_dma_contig_free(struct iwn_dma_info *);\n    int        iwn_alloc_sched(struct iwn_softc *);\n    void        iwn_free_sched(struct iwn_softc *);\n    int        iwn_alloc_kw(struct iwn_softc *);\n    void        iwn_free_kw(struct iwn_softc *);\n    int        iwn_alloc_ict(struct iwn_softc *);\n    void        iwn_free_ict(struct iwn_softc *);\n    int        iwn_alloc_fwmem(struct iwn_softc *);\n    void        iwn_free_fwmem(struct iwn_softc *);\n    int        iwn_alloc_rx_ring(struct iwn_softc *, struct iwn_rx_ring *);\n    void        iwn_reset_rx_ring(struct iwn_softc *, struct iwn_rx_ring *);\n    void        iwn_free_rx_ring(struct iwn_softc *, struct iwn_rx_ring *);\n    int        iwn_alloc_tx_ring(struct iwn_softc *, struct iwn_tx_ring *,\n                int);\n    void        iwn_reset_tx_ring(struct iwn_softc *, struct iwn_tx_ring *);\n    void        iwn_free_tx_ring(struct iwn_softc *, struct iwn_tx_ring *);\n    void        iwn5000_ict_reset(struct iwn_softc *);\n    int        iwn_read_eeprom(struct iwn_softc *);\n    static void        iwn4965_read_eeprom(struct iwn_softc *);\n    void        iwn4965_print_power_group(struct iwn_softc *, int);\n    static void        iwn5000_read_eeprom(struct iwn_softc *);\n    void        iwn_read_eeprom_channels(struct iwn_softc *, int, uint32_t);\n    void        iwn_read_eeprom_enhinfo(struct iwn_softc *);\n    static struct        ieee80211_node *iwn_node_alloc(struct ieee80211com *);\n    static void        iwn_newassoc(struct ieee80211com *, struct ieee80211_node *,\n                int);\n    int        iwn_media_change(struct _ifnet *);\n    static int        iwn_newstate(struct ieee80211com *, enum ieee80211_state, int);\n    static void        iwn_iter_func(void *, struct ieee80211_node *);\n    static void        iwn_calib_timeout(void *);\n    int        iwn_ccmp_decap(struct iwn_softc *, mbuf_t,\n                struct ieee80211_node *);\n    void        iwn_rx_phy(struct iwn_softc *, struct iwn_rx_desc *,\n                struct iwn_rx_data *);\n    void        iwn_rx_done(struct iwn_softc *, struct iwn_rx_desc *,\n                struct iwn_rx_data *, struct mbuf_list *);\n    void        iwn_ra_choose(struct iwn_softc *, struct ieee80211_node *);\n    void        iwn_ampdu_rate_control(struct iwn_softc *, struct ieee80211_node *,\n                struct iwn_tx_ring *, uint16_t, uint16_t);\n    void        iwn_ht_single_rate_control(struct iwn_softc *,\n                struct ieee80211_node *, uint8_t, uint8_t, uint8_t, int);\n    void        iwn_rx_compressed_ba(struct iwn_softc *, struct iwn_rx_desc *,\n                struct iwn_rx_data *);\n    void        iwn5000_rx_calib_results(struct iwn_softc *,\n                struct iwn_rx_desc *, struct iwn_rx_data *);\n    void        iwn_rx_statistics(struct iwn_softc *, struct iwn_rx_desc *,\n                struct iwn_rx_data *);\n    void        iwn_ampdu_txq_advance(struct iwn_softc *, struct iwn_tx_ring *,\n                int, int);\n    void        iwn_ampdu_tx_done(struct iwn_softc *, struct iwn_tx_ring *,\n                struct iwn_rx_desc *, uint16_t, uint8_t, uint8_t, uint8_t,\n                int, uint32_t, struct iwn_txagg_status *);\n    static void        iwn4965_tx_done(struct iwn_softc *, struct iwn_rx_desc *,\n                struct iwn_rx_data *);\n    static void        iwn5000_tx_done(struct iwn_softc *, struct iwn_rx_desc *,\n                struct iwn_rx_data *);\n    void        iwn_tx_done_free_txdata(struct iwn_softc *,\n                struct iwn_tx_data *);\n    void        iwn_clear_oactive(struct iwn_softc *, struct iwn_tx_ring *);\n    void        iwn_tx_done(struct iwn_softc *, struct iwn_rx_desc *,\n                uint8_t, uint8_t, uint8_t, int, int, uint16_t);\n    void        iwn_cmd_done(struct iwn_softc *, struct iwn_rx_desc *);\n    void        iwn_notif_intr(struct iwn_softc *);\n    void        iwn_wakeup_intr(struct iwn_softc *);\n    void        iwn_fatal_intr(struct iwn_softc *);\n    static int        iwn_intr(OSObject *object, IOInterruptEventSource* sender, int count);\n    static void        iwn4965_update_sched(struct iwn_softc *, int, int, uint8_t,\n                uint16_t);\n    static void        iwn4965_reset_sched(struct iwn_softc *, int, int);\n    static void        iwn5000_update_sched(struct iwn_softc *, int, int, uint8_t,\n                uint16_t);\n    static void        iwn5000_reset_sched(struct iwn_softc *, int, int);\n    int        iwn_tx(struct iwn_softc *, mbuf_t,\n                struct ieee80211_node *);\n    int        iwn_rval2ridx(int);\n    static void        iwn_start(struct _ifnet *);\n    static void        iwn_watchdog(struct _ifnet *);\n    static int        iwn_ioctl(struct _ifnet *, u_long, caddr_t);\n    int        iwn_cmd(struct iwn_softc *, int, const void *, int, int);\n    static int        iwn4965_add_node(struct iwn_softc *, struct iwn_node_info *,\n                int);\n    static int        iwn5000_add_node(struct iwn_softc *, struct iwn_node_info *,\n                int);\n    int        iwn_set_link_quality(struct iwn_softc *,\n                struct ieee80211_node *);\n    int        iwn_add_broadcast_node(struct iwn_softc *, int, int);\n    static void        iwn_updateedca(struct ieee80211com *);\n    void        iwn_set_led(struct iwn_softc *, uint8_t, uint8_t, uint8_t);\n    int        iwn_set_critical_temp(struct iwn_softc *);\n    int        iwn_set_timing(struct iwn_softc *, struct ieee80211_node *);\n    static void        iwn4965_power_calibration(struct iwn_softc *, int);\n    static int        iwn4965_set_txpower(struct iwn_softc *, int);\n    static int        iwn5000_set_txpower(struct iwn_softc *, int);\n    static int        iwn4965_get_rssi(const struct iwn_rx_stat *);\n    static int        iwn5000_get_rssi(const struct iwn_rx_stat *);\n    int        iwn_get_noise(const struct iwn_rx_general_stats *);\n    static int        iwn4965_get_temperature(struct iwn_softc *);\n    static int        iwn5000_get_temperature(struct iwn_softc *);\n    int        iwn_init_sensitivity(struct iwn_softc *);\n    void        iwn_collect_noise(struct iwn_softc *,\n                const struct iwn_rx_general_stats *);\n    static int        iwn4965_init_gains(struct iwn_softc *);\n    static int        iwn5000_init_gains(struct iwn_softc *);\n    static int        iwn4965_set_gains(struct iwn_softc *);\n    static int        iwn5000_set_gains(struct iwn_softc *);\n    void        iwn_tune_sensitivity(struct iwn_softc *,\n                const struct iwn_rx_stats *);\n    int        iwn_send_sensitivity(struct iwn_softc *);\n    int        iwn_set_pslevel(struct iwn_softc *, int, int, int);\n    int        iwn_send_temperature_offset(struct iwn_softc *);\n    int        iwn_send_btcoex(struct iwn_softc *);\n    int        iwn_send_advanced_btcoex(struct iwn_softc *);\n    int        iwn5000_runtime_calib(struct iwn_softc *);\n    int        iwn_config(struct iwn_softc *);\n    uint16_t    iwn_get_active_dwell_time(struct iwn_softc *, uint16_t, uint8_t);\n    uint16_t    iwn_limit_dwell(struct iwn_softc *, uint16_t);\n    uint16_t    iwn_get_passive_dwell_time(struct iwn_softc *, uint16_t);\n    int        iwn_scan(struct iwn_softc *, uint16_t, int);\n    void        iwn_scan_abort(struct iwn_softc *);\n    static int        iwn_bgscan(struct ieee80211com *);\n    void       iwn_rxon_configure_ht40(struct ieee80211com *,\n                                        struct ieee80211_node *);\n    int        iwn_rxon_ht40_enabled(struct iwn_softc *);\n    int        iwn_auth(struct iwn_softc *, int);\n    int        iwn_run(struct iwn_softc *);\n    static int        iwn_set_key(struct ieee80211com *, struct ieee80211_node *,\n                struct ieee80211_key *);\n    static void        iwn_delete_key(struct ieee80211com *, struct ieee80211_node *,\n                struct ieee80211_key *);\n    static void        iwn_updateprot(struct ieee80211com *);\n    static void        iwn_updateslot(struct ieee80211com *);\n    void        iwn_update_rxon_restore_power(struct iwn_softc *);\n    static void        iwn5000_update_rxon(struct iwn_softc *);\n    static void        iwn4965_update_rxon(struct iwn_softc *);\n    static int        iwn_ampdu_rx_start(struct ieee80211com *,\n                struct ieee80211_node *, uint8_t);\n    static void        iwn_ampdu_rx_stop(struct ieee80211com *,\n                struct ieee80211_node *, uint8_t);\n    static int        iwn_ampdu_tx_start(struct ieee80211com *,\n                struct ieee80211_node *, uint8_t);\n    static void        iwn_ampdu_tx_stop(struct ieee80211com *,\n                struct ieee80211_node *, uint8_t);\n    static void        iwn4965_ampdu_tx_start(struct iwn_softc *,\n                struct ieee80211_node *, uint8_t, uint16_t);\n    static void        iwn4965_ampdu_tx_stop(struct iwn_softc *,\n                uint8_t, uint16_t);\n    static void        iwn5000_ampdu_tx_start(struct iwn_softc *,\n                struct ieee80211_node *, uint8_t, uint16_t);\n    static void        iwn5000_ampdu_tx_stop(struct iwn_softc *,\n                uint8_t, uint16_t);\n    static void        iwn_update_chw(struct ieee80211com *);\n    static int        iwn5000_query_calibration(struct iwn_softc *);\n    static int        iwn5000_send_calibration(struct iwn_softc *);\n    static int        iwn5000_send_wimax_coex(struct iwn_softc *);\n    static int        iwn5000_crystal_calib(struct iwn_softc *);\n    static int        iwn6000_temp_offset_calib(struct iwn_softc *);\n    static int        iwn2000_temp_offset_calib(struct iwn_softc *);\n    static int        iwn4965_post_alive(struct iwn_softc *);\n    static int        iwn5000_post_alive(struct iwn_softc *);\n    static int        iwn4965_load_bootcode(struct iwn_softc *, const uint8_t *,\n                int);\n    static int        iwn4965_load_firmware(struct iwn_softc *);\n    static int        iwn5000_load_firmware_section(struct iwn_softc *, uint32_t,\n                const uint8_t *, int);\n    static int        iwn5000_load_firmware(struct iwn_softc *);\n    int        iwn_read_firmware_leg(struct iwn_softc *,\n                struct iwn_fw_info *);\n    int        iwn_read_firmware_tlv(struct iwn_softc *,\n                struct iwn_fw_info *, uint16_t);\n    int        iwn_read_firmware(struct iwn_softc *);\n    int        iwn_clock_wait(struct iwn_softc *);\n    int        iwn_apm_init(struct iwn_softc *);\n    void        iwn_apm_stop_master(struct iwn_softc *);\n    void        iwn_apm_stop(struct iwn_softc *);\n    static int        iwn4965_nic_config(struct iwn_softc *);\n    static int        iwn5000_nic_config(struct iwn_softc *);\n    int        iwn_hw_prepare(struct iwn_softc *);\n    int        iwn_hw_init(struct iwn_softc *);\n    void        iwn_hw_stop(struct iwn_softc *);\n    int        iwn_init(struct _ifnet *);\n    void        iwn_stop(struct _ifnet *);\n    \npublic:\n    IOInterruptEventSource* fInterrupt;\n    struct pci_attach_args pci;\n    struct iwn_softc com;\n};\n\n#endif\n"
  },
  {
    "path": "itlwm/hal_iwn/if_iwnreg.h",
    "content": "/*\n * Copyright (C) 2020  pigworlds\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n */\n/*    $OpenBSD: if_iwnreg.h,v 1.59 2021/11/12 11:41:04 stsp Exp    */\n\n/*-\n * Copyright (c) 2007, 2008\n *    Damien Bergamini <damien.bergamini@free.fr>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n#define IWN_TX_RING_COUNT    256\n#define IWN_TX_RING_LOMARK    192\n#define IWN_TX_RING_HIMARK    224\n#define IWN_RX_RING_COUNT_LOG    6\n#define IWN_RX_RING_COUNT    (1 << IWN_RX_RING_COUNT_LOG)\n\n#define IWN4965_NTXQUEUES        16\n#define IWN4965_FIRST_AGG_TXQUEUE    7\n#define IWN5000_NTXQUEUES        20\n#define IWN5000_FIRST_AGG_TXQUEUE    10\n\n#define IWN4965_NDMACHNLS    7\n#define IWN5000_NDMACHNLS    8\n\n#define IWN_SRVC_DMACHNL    9\n\n#define IWN_ICT_SIZE        4096\n#define IWN_ICT_COUNT        (IWN_ICT_SIZE / sizeof (uint32_t))\n\n/* Maximum number of DMA segments for TX. */\n#define IWN_MAX_SCATTER    20\n\n/* RX buffers must be large enough to hold a full 4K A-MPDU. */\n#define IWN_RBUF_SIZE    (4 * 1024)\n\n#if defined(__LP64__)\n/* HW supports 36-bit DMA addresses. */\n#define IWN_LOADDR(paddr)    ((uint32_t)(paddr))\n#define IWN_HIADDR(paddr)    (((paddr) >> 32) & 0xf)\n#else\n#define IWN_LOADDR(paddr)    (paddr)\n#define IWN_HIADDR(paddr)    (0)\n#endif\n\n/* Base Address Register. */\n#define IWN_PCI_BAR0    PCI_MAPREG_START\n\n/*\n * Control and status registers.\n */\n#define IWN_HW_IF_CONFIG    0x000\n#define IWN_INT_COALESCING    0x004\n#define IWN_INT_PERIODIC    0x005    /* use IWN_WRITE_1 */\n#define IWN_INT            0x008\n#define IWN_INT_MASK        0x00c\n#define IWN_FH_INT        0x010\n#define IWN_RESET        0x020\n#define IWN_GP_CNTRL        0x024\n#define IWN_HW_REV        0x028\n#define IWN_EEPROM        0x02c\n#define IWN_EEPROM_GP        0x030\n#define IWN_OTP_GP        0x034\n#define IWN_GIO            0x03c\n#define IWN_GP_DRIVER        0x050\n#define IWN_UCODE_GP1_CLR    0x05c\n#define IWN_LED            0x094\n#define IWN_DRAM_INT_TBL    0x0a0\n#define IWN_SHADOW_REG_CTRL    0x0a8\n#define IWN_GIO_CHICKEN        0x100\n#define IWN_ANA_PLL        0x20c\n#define IWN_HW_REV_WA        0x22c\n#define IWN_DBG_HPET_MEM    0x240\n#define IWN_DBG_LINK_PWR_MGMT    0x250\n#define IWN_MEM_RADDR        0x40c\n#define IWN_MEM_WADDR        0x410\n#define IWN_MEM_WDATA        0x418\n#define IWN_MEM_RDATA        0x41c\n#define IWN_PRPH_WADDR      0x444\n#define IWN_PRPH_RADDR       0x448\n#define IWN_PRPH_WDATA      0x44c\n#define IWN_PRPH_RDATA       0x450\n#define IWN_HBUS_TARG_WRPTR    0x460\n\n/*\n * Flow-Handler registers.\n */\n#define IWN_FH_TFBD_CTRL0(qid)        (0x1900 + (qid) * 8)\n#define IWN_FH_TFBD_CTRL1(qid)        (0x1904 + (qid) * 8)\n#define IWN_FH_KW_ADDR            0x197c\n#define IWN_FH_SRAM_ADDR(qid)        (0x19a4 + (qid) * 4)\n#define IWN_FH_CBBC_QUEUE(qid)        (0x19d0 + (qid) * 4)\n#define IWN_FH_STATUS_WPTR        0x1bc0\n#define IWN_FH_RX_BASE            0x1bc4\n#define IWN_FH_RX_WPTR            0x1bc8\n#define IWN_FH_RX_CONFIG        0x1c00\n#define IWN_FH_RX_STATUS        0x1c44\n#define IWN_FH_TX_CONFIG(qid)        (0x1d00 + (qid) * 32)\n#define IWN_FH_TXBUF_STATUS(qid)    (0x1d08 + (qid) * 32)\n#define IWN_FH_TX_CHICKEN        0x1e98\n#define IWN_FH_TX_STATUS        0x1eb0\n\n/*\n * TX scheduler registers.\n */\n#define IWN_SCHED_BASE            0xa02c00\n#define IWN_SCHED_SRAM_ADDR        (IWN_SCHED_BASE + 0x000)\n#define IWN5000_SCHED_DRAM_ADDR        (IWN_SCHED_BASE + 0x008)\n#define IWN4965_SCHED_DRAM_ADDR        (IWN_SCHED_BASE + 0x010)\n#define IWN5000_SCHED_TXFACT        (IWN_SCHED_BASE + 0x010)\n#define IWN4965_SCHED_TXFACT        (IWN_SCHED_BASE + 0x01c)\n#define IWN4965_SCHED_QUEUE_RDPTR(qid)    (IWN_SCHED_BASE + 0x064 + (qid) * 4)\n#define IWN5000_SCHED_QUEUE_RDPTR(qid)    (IWN_SCHED_BASE + 0x068 + (qid) * 4)\n#define IWN4965_SCHED_QCHAIN_SEL    (IWN_SCHED_BASE + 0x0d0)\n#define IWN4965_SCHED_INTR_MASK        (IWN_SCHED_BASE + 0x0e4)\n#define IWN5000_SCHED_QCHAIN_SEL    (IWN_SCHED_BASE + 0x0e8)\n#define IWN4965_SCHED_QUEUE_STATUS(qid)    (IWN_SCHED_BASE + 0x104 + (qid) * 4)\n#define IWN5000_SCHED_INTR_MASK        (IWN_SCHED_BASE + 0x108)\n#define IWN5000_SCHED_QUEUE_STATUS(qid)    (IWN_SCHED_BASE + 0x10c + (qid) * 4)\n#define IWN5000_SCHED_CHAINEXT_EN    (IWN_SCHED_BASE + 0x244)\n#define IWN5000_SCHED_AGGR_SEL        (IWN_SCHED_BASE + 0x248)\n\n/*\n * Offsets in TX scheduler's SRAM.\n */\n#define IWN4965_SCHED_CTX_OFF        0x380\n#define IWN4965_SCHED_CTX_LEN        416\n#define IWN4965_SCHED_QUEUE_OFFSET(qid)    (0x380 + (qid) * 8)\n#define IWN4965_SCHED_TRANS_TBL(qid)    (0x500 + (qid) * 2)\n#define IWN5000_SCHED_CTX_OFF        0x600\n#define IWN5000_SCHED_CTX_LEN        520\n#define IWN5000_SCHED_QUEUE_OFFSET(qid)    (0x600 + (qid) * 8)\n#define IWN5000_SCHED_TRANS_TBL(qid)    (0x7e0 + (qid) * 2)\n\n/*\n * NIC internal memory offsets.\n */\n#define IWN_APMG_CLK_CTRL    0x3000\n#define IWN_APMG_CLK_EN        0x3004\n#define IWN_APMG_CLK_DIS    0x3008\n#define IWN_APMG_PS        0x300c\n#define IWN_APMG_DIGITAL_SVR    0x3058\n#define IWN_APMG_ANALOG_SVR    0x306c\n#define IWN_APMG_PCI_STT    0x3010\n#define IWN_BSM_WR_CTRL        0x3400\n#define IWN_BSM_WR_MEM_SRC    0x3404\n#define IWN_BSM_WR_MEM_DST    0x3408\n#define IWN_BSM_WR_DWCOUNT    0x340c\n#define IWN_BSM_DRAM_TEXT_ADDR    0x3490\n#define IWN_BSM_DRAM_TEXT_SIZE    0x3494\n#define IWN_BSM_DRAM_DATA_ADDR    0x3498\n#define IWN_BSM_DRAM_DATA_SIZE    0x349c\n#define IWN_BSM_SRAM_BASE    0x3800\n\n/* Possible flags for register IWN_HW_IF_CONFIG. */\n#define IWN_HW_IF_CONFIG_4965_R        (1 <<  4)\n#define IWN_HW_IF_CONFIG_MAC_SI        (1 <<  8)\n#define IWN_HW_IF_CONFIG_RADIO_SI    (1 <<  9)\n#define IWN_HW_IF_CONFIG_EEPROM_LOCKED    (1 << 21)\n#define IWN_HW_IF_CONFIG_NIC_READY    (1 << 22)\n#define IWN_HW_IF_CONFIG_HAP_WAKE_L1A    (1 << 23)\n#define IWN_HW_IF_CONFIG_PREPARE_DONE    (1 << 25)\n#define IWN_HW_IF_CONFIG_PREPARE    (1 << 27)\n\n/* Possible values for register IWN_INT_PERIODIC. */\n#define IWN_INT_PERIODIC_DIS    0x00\n#define IWN_INT_PERIODIC_ENA    0xff\n\n/* Possible flags for registers IWN_PRPH_RADDR/IWN_PRPH_WADDR. */\n#define IWN_PRPH_DWORD    ((sizeof (uint32_t) - 1) << 24)\n\n/* Possible values for IWN_BSM_WR_MEM_DST. */\n#define IWN_FW_TEXT_BASE    0x00000000\n#define IWN_FW_DATA_BASE    0x00800000\n\n/* Possible flags for register IWN_RESET. */\n#define IWN_RESET_NEVO            (1U << 0)\n#define IWN_RESET_SW            (1U << 7)\n#define IWN_RESET_MASTER_DISABLED    (1U << 8)\n#define IWN_RESET_STOP_MASTER        (1U << 9)\n#define IWN_RESET_LINK_PWR_MGMT_DIS    (1U << 31)\n\n/* Possible flags for register IWN_GP_CNTRL. */\n#define IWN_GP_CNTRL_MAC_ACCESS_ENA    (1 << 0)\n#define IWN_GP_CNTRL_MAC_CLOCK_READY    (1 << 0)\n#define IWN_GP_CNTRL_INIT_DONE        (1 << 2)\n#define IWN_GP_CNTRL_MAC_ACCESS_REQ    (1 << 3)\n#define IWN_GP_CNTRL_SLEEP        (1 << 4)\n#define IWN_GP_CNTRL_RFKILL        (1 << 27)\n\n/* Possible flags for register IWN_HW_REV. */\n#define IWN_HW_REV_TYPE_SHIFT    4\n#define IWN_HW_REV_TYPE_MASK    0x000001f0\n#define IWN_HW_REV_TYPE_4965    0\n#define IWN_HW_REV_TYPE_5300    2\n#define IWN_HW_REV_TYPE_5350    3\n#define IWN_HW_REV_TYPE_5150    4\n#define IWN_HW_REV_TYPE_5100    5\n#define IWN_HW_REV_TYPE_1000    6\n#define IWN_HW_REV_TYPE_6000    7\n#define IWN_HW_REV_TYPE_6050    8\n#define IWN_HW_REV_TYPE_6005    11\n#define IWN_HW_REV_TYPE_2030    12\n#define IWN_HW_REV_TYPE_2000    16\n#define IWN_HW_REV_TYPE_105    17\n#define IWN_HW_REV_TYPE_135    18\n\n\n/* Possible flags for register IWN_GIO_CHICKEN. */\n#define IWN_GIO_CHICKEN_L1A_NO_L0S_RX    (1 << 23)\n#define IWN_GIO_CHICKEN_DIS_L0S_TIMER    (1 << 29)\n\n/* Possible flags for register IWN_GIO. */\n#define IWN_GIO_L0S_ENA        (1 << 1)\n\n/* Possible flags for register IWN_GP_DRIVER. */\n#define IWN_GP_DRIVER_RADIO_3X3_HYB    (0 << 0)\n#define IWN_GP_DRIVER_RADIO_2X2_HYB    (1 << 0)\n#define IWN_GP_DRIVER_RADIO_2X2_IPA    (2 << 0)\n#define IWN_GP_DRIVER_CALIB_VER6    (1 << 2)\n#define IWN_GP_DRIVER_6050_1X2        (1 << 3)\n#define IWN_GP_DRIVER_RADIO_IQ_INVERT    (1 << 7)\n\n/* Possible flags for register IWN_UCODE_GP1_CLR. */\n#define IWN_UCODE_GP1_RFKILL        (1 << 1)\n#define IWN_UCODE_GP1_CMD_BLOCKED    (1 << 2)\n#define IWN_UCODE_GP1_CTEMP_STOP_RF    (1 << 3)\n\n/* Possible flags/values for register IWN_LED. */\n#define IWN_LED_BSM_CTRL    (1 << 5)\n#define IWN_LED_OFF        0x00000038\n#define IWN_LED_ON        0x00000078\n\n/* Possible flags for register IWN_DRAM_INT_TBL. */\n#define IWN_DRAM_INT_TBL_WRAP_CHECK    (1U << 27)\n#define IWN_DRAM_INT_TBL_ENABLE        (1U << 31)\n\n/* Possible values for register IWN_ANA_PLL. */\n#define IWN_ANA_PLL_INIT    0x00880300\n\n/* Possible flags for register IWN_FH_RX_STATUS. */\n#define IWN_FH_RX_STATUS_IDLE    (1 << 24)\n\n/* Possible flags for register IWN_BSM_WR_CTRL. */\n#define IWN_BSM_WR_CTRL_START_EN    (1U << 30)\n#define IWN_BSM_WR_CTRL_START        (1U << 31)\n\n/* Possible flags for register IWN_INT. */\n#define IWN_INT_ALIVE        (1U <<  0)\n#define IWN_INT_WAKEUP        (1U <<  1)\n#define IWN_INT_SW_RX        (1U <<  3)\n#define IWN_INT_CT_REACHED    (1U <<  6)\n#define IWN_INT_RF_TOGGLED    (1U <<  7)\n#define IWN_INT_SW_ERR        (1U << 25)\n#define IWN_INT_SCHED        (1U << 26)\n#define IWN_INT_FH_TX        (1U << 27)\n#define IWN_INT_RX_PERIODIC    (1U << 28)\n#define IWN_INT_HW_ERR        (1U << 29)\n#define IWN_INT_FH_RX        (1U << 31)\n\n/* Shortcut. */\n#define IWN_INT_MASK_DEF                        \\\n    (IWN_INT_SW_ERR | IWN_INT_HW_ERR | IWN_INT_FH_TX |        \\\n     IWN_INT_FH_RX | IWN_INT_ALIVE | IWN_INT_WAKEUP |        \\\n     IWN_INT_SW_RX | IWN_INT_CT_REACHED | IWN_INT_RF_TOGGLED)\n\n/* Possible flags for register IWN_FH_INT. */\n#define IWN_FH_INT_TX_CHNL(x)    (1 << (x))\n#define IWN_FH_INT_RX_CHNL(x)    (1 << ((x) + 16))\n#define IWN_FH_INT_HI_PRIOR    (1 << 30)\n/* Shortcuts for the above. */\n#define IWN_FH_INT_TX                            \\\n    (IWN_FH_INT_TX_CHNL(0) | IWN_FH_INT_TX_CHNL(1))\n#define IWN_FH_INT_RX                            \\\n    (IWN_FH_INT_RX_CHNL(0) | IWN_FH_INT_RX_CHNL(1) | IWN_FH_INT_HI_PRIOR)\n\n/* Possible flags/values for register IWN_FH_TX_CONFIG. */\n#define IWN_FH_TX_CONFIG_DMA_PAUSE        0\n#define IWN_FH_TX_CONFIG_DMA_ENA        (1U << 31)\n#define IWN_FH_TX_CONFIG_CIRQ_HOST_ENDTFD    (1U << 20)\n\n/* Possible flags/values for register IWN_FH_TXBUF_STATUS. */\n#define IWN_FH_TXBUF_STATUS_TBNUM(x)    ((x) << 20)\n#define IWN_FH_TXBUF_STATUS_TBIDX(x)    ((x) << 12)\n#define IWN_FH_TXBUF_STATUS_TFBD_VALID    3\n\n/* Possible flags for register IWN_FH_TX_CHICKEN. */\n#define IWN_FH_TX_CHICKEN_SCHED_RETRY    (1 << 1)\n\n/* Possible flags for register IWN_FH_TX_STATUS. */\n#define IWN_FH_TX_STATUS_IDLE(chnl)    (1 << ((chnl) + 16))\n\n/* Possible flags for register IWN_FH_RX_CONFIG. */\n#define IWN_FH_RX_CONFIG_ENA        (1U << 31)\n#define IWN_FH_RX_CONFIG_NRBD(x)    ((x) << 20)\n#define IWN_FH_RX_CONFIG_RB_SIZE_8K    (1U << 16)\n#define IWN_FH_RX_CONFIG_SINGLE_FRAME    (1U << 15)\n#define IWN_FH_RX_CONFIG_IRQ_DST_HOST    (1U << 12)\n#define IWN_FH_RX_CONFIG_RB_TIMEOUT(x)    ((x) << 4) /* units 32 usec */\n#define IWN_FH_RX_CONFIG_IGN_RXF_EMPTY    (1U <<  2)\n\n/* Possible flags for register IWN_FH_TX_CONFIG. */\n#define IWN_FH_TX_CONFIG_DMA_ENA    (1U << 31)\n#define IWN_FH_TX_CONFIG_DMA_CREDIT_ENA    (1U <<  3)\n\n/* Possible flags for register IWN_EEPROM. */\n#define IWN_EEPROM_READ_VALID    (1 << 0)\n#define IWN_EEPROM_CMD        (1 << 1)\n\n/* Possible flags for register IWN_EEPROM_GP. */\n#define IWN_EEPROM_GP_IF_OWNER    0x00000180\n\n/* Possible flags for register IWN_OTP_GP. */\n#define IWN_OTP_GP_DEV_SEL_OTP        (1 << 16)\n#define IWN_OTP_GP_RELATIVE_ACCESS    (1 << 17)\n#define IWN_OTP_GP_ECC_CORR_STTS    (1 << 20)\n#define IWN_OTP_GP_ECC_UNCORR_STTS    (1 << 21)\n\n/* Possible flags for register IWN_SCHED_QUEUE_STATUS. */\n#define IWN4965_TXQ_STATUS_ACTIVE    0x0007fc01\n#define IWN4965_TXQ_STATUS_INACTIVE    0x0007fc00\n#define IWN4965_TXQ_STATUS_AGGR_ENA    (1 << 5 | 1 << 8)\n#define IWN4965_TXQ_STATUS_CHGACT    (1 << 10)\n#define IWN5000_TXQ_STATUS_ACTIVE    0x00ff0018\n#define IWN5000_TXQ_STATUS_INACTIVE    0x00ff0010\n#define IWN5000_TXQ_STATUS_CHGACT    (1 << 19)\n\n/* Possible flags for registers IWN_APMG_CLK_*. */\n#define IWN_APMG_CLK_CTRL_DMA_CLK_RQT    (1 <<  9)\n#define IWN_APMG_CLK_CTRL_BSM_CLK_RQT    (1 << 11)\n\n/* Possible flags for register IWN_APMG_PS. */\n#define IWN_APMG_PS_EARLY_PWROFF_DIS    (1 << 22)\n#define IWN_APMG_PS_PWR_SRC(x)        ((x) << 24)\n#define IWN_APMG_PS_PWR_SRC_VMAIN    0\n#define IWN_APMG_PS_PWR_SRC_VAUX    2\n#define IWN_APMG_PS_PWR_SRC_MASK    IWN_APMG_PS_PWR_SRC(3)\n#define IWN_APMG_PS_RESET_REQ        (1 << 26)\n\n/* Possible flags for register IWN_APMG_DIGITAL_SVR. */\n#define IWN_APMG_DIGITAL_SVR_VOLTAGE(x)        (((x) & 0xf) << 5)\n#define IWN_APMG_DIGITAL_SVR_VOLTAGE_MASK    \\\n    IWN_APMG_DIGITAL_SVR_VOLTAGE(0xf)\n#define IWN_APMG_DIGITAL_SVR_VOLTAGE_1_32    \\\n    IWN_APMG_DIGITAL_SVR_VOLTAGE(3)\n\n/* Possible flags for IWN_APMG_PCI_STT. */\n#define IWN_APMG_PCI_STT_L1A_DIS    (1 << 11)\n\n/* Possible flags for register IWN_BSM_DRAM_TEXT_SIZE. */\n#define IWN_FW_UPDATED    (1U << 31)\n\n#define IWN_SCHED_WINSZ        64\n#define IWN_SCHED_LIMIT        64\n#define IWN4965_SCHED_COUNT    512\n#define IWN5000_SCHED_COUNT    (IWN_TX_RING_COUNT + IWN_SCHED_WINSZ)\n#define IWN4965_SCHEDSZ        (IWN4965_NTXQUEUES * IWN4965_SCHED_COUNT * 2)\n#define IWN5000_SCHEDSZ        (IWN5000_NTXQUEUES * IWN5000_SCHED_COUNT * 2)\n\nstruct iwn_tx_desc {\n    uint8_t        reserved1[3];\n    uint8_t        nsegs;\n    struct {\n        uint32_t    addr;\n        uint16_t    len;\n    } __packed    segs[IWN_MAX_SCATTER];\n    /* Pad to 128 bytes. */\n    uint32_t    reserved2;\n} __packed;\n\nstruct iwn_rx_status {\n    uint16_t    closed_count;\n    uint16_t    closed_rx_count;\n    uint16_t    finished_count;\n    uint16_t    finished_rx_count;\n    uint32_t    reserved[2];\n} __packed;\n\nstruct iwn_rx_desc {\n    uint32_t    len;\n#define IWN_RX_DESC_LEN_MASK        0x00003fff\n#define IWN_RX_DESC_LEN_SHIFT        0\n#define IWN_RX_DESC_FLAG_FLUSH_RB_REQ    0x80000000\n#define IWN_RX_DESC_FLAG_IGNORE_TC    0x40000000\n#define IWN_RX_DESC_FLAG_FAST_IRQ    0x20000000\n\n    uint8_t        type;\n#define IWN_UC_READY              1\n#define IWN_ADD_NODE_DONE         24\n#define IWN_TX_DONE             28\n#define IWN5000_CALIBRATION_RESULT    102\n#define IWN5000_CALIBRATION_DONE    103\n#define IWN_START_SCAN            130\n#define IWN_STOP_SCAN            132\n#define IWN_RX_STATISTICS        156\n#define IWN_BEACON_STATISTICS        157\n#define IWN_STATE_CHANGED        161\n#define IWN_BEACON_MISSED        162\n#define IWN_RX_PHY            192\n#define IWN_MPDU_RX_DONE        193\n#define IWN_RX_DONE            195\n#define IWN_RX_COMPRESSED_BA        197\n\n    uint8_t        flags; /* XXX iwlwifi calls this \"group_id\" */\n    uint8_t        idx;\n    uint8_t        qid;\n} __packed;\n\n/* Possible RX status flags. */\n#define IWN_RX_NO_CRC_ERR    (1 <<  0)\n#define IWN_RX_NO_OVFL_ERR    (1 <<  1)\n/* Shortcut for the above. */\n#define IWN_RX_NOERROR    (IWN_RX_NO_CRC_ERR | IWN_RX_NO_OVFL_ERR)\n#define IWN_RX_MPDU_MIC_OK    (1 <<  6)\n#define IWN_RX_CIPHER_MASK    (7 <<  8)\n#define IWN_RX_CIPHER_CCMP    (2 <<  8)\n#define IWN_RX_MPDU_DEC        (1 << 11)\n#define IWN_RX_DECRYPT_MASK    (3 << 11)\n#define IWN_RX_DECRYPT_OK    (3 << 11)\n\nstruct iwn_tx_cmd {\n    uint8_t    code;\n#define IWN_CMD_RXON             16\n#define IWN_CMD_RXON_ASSOC         17\n#define IWN_CMD_EDCA_PARAMS         19\n#define IWN_CMD_TIMING             20\n#define IWN_CMD_ADD_NODE         24\n#define IWN_CMD_TX_DATA             28\n#define IWN_CMD_LINK_QUALITY         78\n#define IWN_CMD_SET_LED             72\n#define IWN5000_CMD_WIMAX_COEX         90\n#define IWN5000_CMD_CALIB_CONFIG    101\n#define IWN_CMD_SET_POWER_MODE        119\n#define IWN_CMD_SCAN            128\n#define IWN_CMD_SCAN_ABORT        129\n#define IWN_CMD_TXPOWER_DBM        149\n#define IWN_CMD_TXPOWER            151\n#define IWN5000_CMD_TX_ANT_CONFIG    152\n#define IWN_CMD_BT_COEX            155\n#define IWN_CMD_GET_STATISTICS        156\n#define IWN_CMD_SET_CRITICAL_TEMP    164\n#define IWN_CMD_SET_SENSITIVITY        168\n#define IWN_CMD_PHY_CALIB        176\n#define IWN_CMD_BT_COEX_PRIOTABLE    204\n#define IWN_CMD_BT_COEX_PROT        205\n\n    uint8_t    flags;\n    uint8_t    idx;\n    uint8_t    qid;\n    uint8_t    data[136];\n} __packed;\n\n/* Antenna flags, used in various commands. */\n#define IWN_ANT_A    (1 << 0)\n#define IWN_ANT_B    (1 << 1)\n#define IWN_ANT_C    (1 << 2)\n/* Shortcuts. */\n#define IWN_ANT_AB    (IWN_ANT_A | IWN_ANT_B)\n#define IWN_ANT_BC    (IWN_ANT_B | IWN_ANT_C)\n#define IWN_ANT_ABC    (IWN_ANT_A | IWN_ANT_B | IWN_ANT_C)\n\n/* Structure for command IWN_CMD_RXON. */\nstruct iwn_rxon {\n    uint8_t        myaddr[IEEE80211_ADDR_LEN];\n    uint16_t    reserved1;\n    uint8_t        bssid[IEEE80211_ADDR_LEN];\n    uint16_t    reserved2;\n    uint8_t        wlap[IEEE80211_ADDR_LEN];\n    uint16_t    reserved3;\n    uint8_t        mode;\n#define IWN_MODE_HOSTAP        1\n#define IWN_MODE_STA        3\n#define IWN_MODE_IBSS        4\n#define IWN_MODE_MONITOR    6\n\n    uint8_t        air;\n    uint16_t    rxchain;\n#define IWN_RXCHAIN_DRIVER_FORCE    (1 << 0)\n#define IWN_RXCHAIN_VALID(x)        (((x) & IWN_ANT_ABC) << 1)\n#define IWN_RXCHAIN_FORCE_SEL(x)    (((x) & IWN_ANT_ABC) << 4)\n#define IWN_RXCHAIN_FORCE_MIMO_SEL(x)    (((x) & IWN_ANT_ABC) << 7)\n#define IWN_RXCHAIN_IDLE_COUNT(x)    ((x) << 10)\n#define IWN_RXCHAIN_MIMO_COUNT(x)    ((x) << 12)\n#define IWN_RXCHAIN_MIMO_FORCE        (1 << 14)\n\n    uint8_t        ofdm_mask;\n    uint8_t        cck_mask;\n    uint16_t    associd;\n    uint32_t    flags;\n#define IWN_RXON_24GHZ        (1 <<  0)\n#define IWN_RXON_CCK        (1 <<  1)\n#define IWN_RXON_AUTO        (1 <<  2)\n#define IWN_RXON_TGG_PROT    (1 <<  3)\n#define IWN_RXON_SHSLOT        (1 <<  4)\n#define IWN_RXON_SHPREAMBLE    (1 <<  5)\n#define IWN_RXON_NODIVERSITY    (1 <<  7)\n#define IWN_RXON_ANTENNA_A    (1 <<  8)\n#define IWN_RXON_ANTENNA_B    (1 <<  9)\n#define IWN_RXON_TSF        (1 << 15)\n#define IWN_RXON_HT_HT40MINUS    (1 << 22)\n#define IWN_RXON_HT_PROTMODE(x)    ((x) << 23) /* 2 bits */\n#define IWN_RXON_HT_CHANMODE_PURE40    (1 << 25)\n#define IWN_RXON_HT_CHANMODE_MIXED2040    (2 << 25)\n#define IWN_RXON_CTS_TO_SELF    (1 << 30)\n\n    uint32_t    filter;\n#define IWN_FILTER_PROMISC    (1 << 0)\n#define IWN_FILTER_CTL        (1 << 1)\n#define IWN_FILTER_MULTICAST    (1 << 2)\n#define IWN_FILTER_NODECRYPT    (1 << 3)\n#define IWN_FILTER_BSS        (1 << 5)\n#define IWN_FILTER_BEACON    (1 << 6)\n\n    uint8_t        chan;\n    uint8_t        reserved4;\n    uint8_t        ht_single_mask;\n    uint8_t        ht_dual_mask;\n    /* The following fields are for >=5000 Series only. */\n    uint8_t        ht_triple_mask;\n    uint8_t        reserved5;\n    uint16_t    acquisition;\n    uint16_t    reserved6;\n} __packed;\n\n/* Structure for command IWN_CMD_RXON_ASSOC. */\nstruct iwn_rxon_assoc {\n    uint32_t flags;\n    uint32_t filter;\n    uint8_t ofdm_mask;\n    uint8_t cck_mask;\n    uint16_t reserved1;\n    uint8_t ht_single_mask;\n    uint8_t ht_dual_mask;\n    uint8_t ht_triple_mask;\n    uint8_t reserved2;\n    uint16_t rxchain;\n    uint16_t acquisition;\n    uint32_t reserved3;\n} __packed;\n\nstruct iwn4965_rxon_assoc {\n    uint32_t flags;\n    uint32_t filter;\n    uint8_t ofdm_mask;\n    uint8_t cck_mask;\n    uint8_t ht_single_mask;\n    uint8_t ht_dual_mask;\n    uint16_t rxchain;\n    uint16_t reserved;\n};\n\n#define IWN4965_RXONSZ    (sizeof (struct iwn_rxon) - 6)\n#define IWN5000_RXONSZ    (sizeof (struct iwn_rxon))\n\n/* Structure for command IWN_CMD_ASSOCIATE. */\nstruct iwn_assoc {\n    uint32_t    flags;\n    uint32_t    filter;\n    uint8_t        ofdm_mask;\n    uint8_t        cck_mask;\n    uint16_t    reserved;\n} __packed;\n\n/* Structure for command IWN_CMD_EDCA_PARAMS. */\nstruct iwn_edca_params {\n    uint32_t    flags;\n#define IWN_EDCA_UPDATE    (1 << 0)\n#define IWN_EDCA_FLG_TGN    (1 << 1)\n#define IWN_EDCA_TXOP    (1 << 4)\n\n    struct {\n        uint16_t    cwmin;\n        uint16_t    cwmax;\n        uint8_t        aifsn;\n        uint8_t        reserved;\n        uint16_t    txoplimit;\n    } __packed    ac[EDCA_NUM_AC];\n} __packed;\n\n/* Structure for command IWN_CMD_TIMING. */\nstruct iwn_cmd_timing {\n    uint64_t    tstamp;\n    uint16_t    bintval;\n    uint16_t    atim;\n    uint32_t    binitval;\n    uint16_t    lintval;\n    uint16_t    reserved;\n} __packed;\n\n/* Structure for command IWN_CMD_ADD_NODE. */\nstruct iwn_node_info {\n    uint8_t        control;\n#define IWN_NODE_UPDATE        (1 << 0)\n\n    uint8_t        reserved1[3];\n\n    uint8_t        macaddr[IEEE80211_ADDR_LEN];\n    uint16_t    reserved2;\n    uint8_t        id;\n#define IWN_ID_BSS         0\n#define IWN5000_ID_BROADCAST    15\n#define IWN4965_ID_BROADCAST    31\n\n    uint8_t        flags;\n#define IWN_FLAG_SET_KEY        (1 << 0)\n#define IWN_FLAG_SET_DISABLE_TID    (1 << 1)\n#define IWN_FLAG_SET_TXRATE        (1 << 2)\n#define IWN_FLAG_SET_ADDBA        (1 << 3)\n#define IWN_FLAG_SET_DELBA        (1 << 4)\n\n    uint16_t    reserved3;\n    uint16_t    kflags;\n#define IWN_KFLAG_CCMP        (1 <<  1)\n#define IWN_KFLAG_MAP        (1 <<  3)\n#define IWN_KFLAG_KID(kid)    ((kid) << 8)\n#define IWN_KFLAG_INVALID    (1 << 11)\n#define IWN_KFLAG_GROUP        (1 << 14)\n\n    uint8_t        tsc2;    /* TKIP TSC2 */\n    uint8_t        reserved4;\n    uint16_t    ttak[5];\n    uint8_t        kid;\n    uint8_t        reserved5;\n    uint8_t        key[16];\n    /* The following 3 fields are for 5000 Series only. */\n    uint64_t    tsc;\n    uint8_t        rxmic[IEEE80211_TKIP_MICLEN];\n    uint8_t        txmic[IEEE80211_TKIP_MICLEN];\n\n    uint32_t    htflags;\n#define IWN_AMDPU_SIZE_FACTOR(x)    ((x) << 19)\n#define IWN_AMDPU_SIZE_FACTOR_MASK    ((0x3) << 19)\n#define IWN_40MHZ_ENABLE        (1 << 21)\n#define IWN_MIMO_DISABLE        (1 << 22)\n#define IWN_AMDPU_DENSITY(x)        ((x) << 23)\n#define IWN_AMDPU_DENSITY_MASK        ((0x7) << 23)\n\n    uint32_t    htmask;\n    uint16_t    disable_tid;\n    uint16_t    reserved6;\n    uint8_t        addba_tid;\n    uint8_t        delba_tid;\n    uint16_t    addba_ssn;\n    uint32_t    reserved7;\n} __packed;\n\nstruct iwn4965_node_info {\n    uint8_t        control;\n    uint8_t        reserved1[3];\n    uint8_t        macaddr[IEEE80211_ADDR_LEN];\n    uint16_t    reserved2;\n    uint8_t        id;\n    uint8_t        flags;\n    uint16_t    reserved3;\n    uint16_t    kflags;\n    uint8_t        tsc2;    /* TKIP TSC2 */\n    uint8_t        reserved4;\n    uint16_t    ttak[5];\n    uint8_t        kid;\n    uint8_t        reserved5;\n    uint8_t        key[16];\n    uint32_t    htflags;\n    uint32_t    htmask;\n    uint16_t    disable_tid;\n    uint16_t    reserved6;\n    uint8_t        addba_tid;\n    uint8_t        delba_tid;\n    uint16_t    addba_ssn;\n    uint32_t    reserved7;\n} __packed;\n\n#define IWN_RFLAG_MCS        (1 << 0)\n#define IWN_RFLAG_CCK        (1 << 1)\n#define IWN_RFLAG_GREENFIELD    (1 << 2)\n#define IWN_RFLAG_HT40        (1 << 3)\n#define IWN_RFLAG_DUPLICATE    (1 << 4)\n#define IWN_RFLAG_SGI        (1 << 5)\n#define IWN_RFLAG_ANT(x)    ((x) << 6)\n\n/* Structure for command IWN_CMD_TX_DATA. */\nstruct iwn_cmd_data {\n    uint16_t    len;\n    uint16_t    lnext;\n    uint32_t    flags;\n#define IWN_TX_NEED_PROTECTION    (1 <<  0)    /* 5000 only */\n#define IWN_TX_NEED_RTS        (1 <<  1)\n#define IWN_TX_NEED_CTS        (1 <<  2)\n#define IWN_TX_NEED_ACK        (1 <<  3)\n#define IWN_TX_LINKQ        (1 <<  4)\n#define IWN_TX_IMM_BA        (1 <<  6)\n#define IWN_TX_FULL_TXOP    (1 <<  7)\n#define IWN_TX_BT_DISABLE    (1 << 12)    /* bluetooth coexistence */\n#define IWN_TX_AUTO_SEQ        (1 << 13)\n#define IWN_TX_MORE_FRAG    (1 << 14)\n#define IWN_TX_INSERT_TSTAMP    (1 << 16)\n#define IWN_TX_NEED_PADDING    (1 << 20)\n#define IWN_TX_AMPDU_CCMP    (1 << 22)\n\n    uint32_t    scratch;\n    uint8_t        plcp;\n    uint8_t        rflags;\n    uint16_t    xrflags;\n\n    uint8_t        id;\n    uint8_t        security;\n#define IWN_CIPHER_WEP40    1\n#define IWN_CIPHER_CCMP        2\n#define IWN_CIPHER_TKIP        3\n#define IWN_CIPHER_WEP104    9\n\n    uint8_t        linkq;\n    uint8_t        reserved2;\n    uint8_t        key[16];\n    uint16_t    fnext;\n    uint16_t    reserved3;\n    uint32_t    lifetime;\n#define IWN_LIFETIME_INFINITE    0xffffffff\n\n    uint32_t    loaddr;\n    uint8_t        hiaddr;\n    uint8_t        rts_ntries;\n    uint8_t        data_ntries;\n    uint8_t        tid;\n    uint16_t    timeout;\n    uint16_t    txop;\n} __packed;\n\n/* Structure for command IWN_CMD_LINK_QUALITY. */\n#define IWN_MAX_TX_RETRIES    16\nstruct iwn_cmd_link_quality {\n    uint8_t        id;\n    uint8_t        reserved1;\n    uint16_t    ctl;\n    uint8_t        flags;\n#define IWN_LINK_QUAL_FLAGS_SET_STA_TLC_RTS    (1 << 0)\n    uint8_t        mimo;\n    uint8_t        antmsk_1stream;\n    uint8_t        antmsk_2stream;\n    uint8_t        ridx[EDCA_NUM_AC];\n    uint16_t    ampdu_limit;\n    uint8_t        ampdu_threshold;\n    uint8_t        ampdu_max;\n#define IWN_AMPDU_MAX_UNLIMITED    0\n#define IWN_AMPDU_MAX_NO_AGG    1\n#define IWN_AMPDU_MAX        63\n    uint32_t    reserved2;\n    struct {\n        uint8_t        plcp;\n        uint8_t        rflags;\n        uint16_t    xrflags;\n    } __packed    retry[IWN_MAX_TX_RETRIES];\n    uint32_t    reserved3;\n} __packed;\n\n/* Structure for command IWN_CMD_SET_LED. */\nstruct iwn_cmd_led {\n    uint32_t    unit;    /* multiplier (in usecs) */\n    uint8_t        which;\n#define IWN_LED_ACTIVITY    1\n#define IWN_LED_LINK        2\n\n    uint8_t        off;\n    uint8_t        on;\n    uint8_t        reserved;\n} __packed;\n\n/* Structure for command IWN5000_CMD_WIMAX_COEX. */\nstruct iwn5000_wimax_event {\n    uint8_t    request;\n    uint8_t    window;\n    uint8_t    reserved;\n    uint8_t    flags;\n} __packed;\n\nstruct iwn5000_wimax_coex {\n    uint32_t    flags;\n#define IWN_WIMAX_COEX_STA_TABLE_VALID        (1 << 0)\n#define IWN_WIMAX_COEX_UNASSOC_WA_UNMASK    (1 << 2)\n#define IWN_WIMAX_COEX_ASSOC_WA_UNMASK        (1 << 3)\n#define IWN_WIMAX_COEX_ENABLE            (1 << 7)\n\n    struct iwn5000_wimax_event events[16];\n} __packed;\n\n/* Structures for command IWN5000_CMD_CALIB_CONFIG. */\nstruct iwn5000_calib_elem {\n    uint32_t    enable;\n    uint32_t    start;\n#define IWN5000_CALIB_DC    (1 << 1)\n\n    uint32_t    send;\n    uint32_t    apply;\n    uint32_t    reserved;\n} __packed;\n\nstruct iwn5000_calib_status {\n    struct iwn5000_calib_elem    once;\n    struct iwn5000_calib_elem    perd;\n    uint32_t            flags;\n} __packed;\n\nstruct iwn5000_calib_config {\n    struct iwn5000_calib_status    ucode;\n    struct iwn5000_calib_status    driver;\n    uint32_t            reserved;\n} __packed;\n\n/* Structure for command IWN_CMD_SET_POWER_MODE. */\n struct iwn_pmgt_cmd {\n     uint16_t    flags;\n #define IWN_PS_ALLOW_SLEEP    (1 << 0)\n #define IWN_PS_NOTIFY        (1 << 1)\n #define IWN_PS_SLEEP_OVER_DTIM    (1 << 2)\n #define IWN_PS_PCI_PMGT        (1 << 3)\n #define IWN_PS_FAST_PD        (1 << 4)\n\n     uint8_t        keepalive;\n     uint8_t        debug;\n     uint32_t    rxtimeout;\n     uint32_t    txtimeout;\n     uint32_t    intval[5];\n     uint32_t    beacons;\n } __packed;\n\n/* Structures for command IWN_CMD_SCAN. */\nstruct iwn_scan_essid {\n    uint8_t    id;\n    uint8_t    len;\n    uint8_t    data[IEEE80211_NWID_LEN];\n} __packed;\n\nstruct iwn_scan_hdr {\n    uint16_t    len;\n    uint8_t        reserved1;\n    uint8_t        nchan;\n    uint16_t    quiet_time;\n    uint16_t    quiet_threshold;\n    uint16_t    crc_threshold;\n    uint16_t    rxchain;\n    uint32_t    max_out;    /* (in usec) background scans */\n    uint32_t    pause_scan;    /* (in usec) background scans */\n    uint32_t    flags;\n    uint32_t    filter;\n\n    /* Followed by a struct iwn_cmd_data. */\n    /* Followed by an array of 20 structs iwn_scan_essid. */\n    /* Followed by probe request body. */\n    /* Followed by an array of ``nchan'' structs iwn_scan_chan. */\n} __packed;\n\nstruct iwn_scan_chan {\n    uint32_t    flags;\n#define IWN_CHAN_PASSIVE    (0 << 0)\n#define IWN_CHAN_ACTIVE        (1 << 0)\n#define IWN_CHAN_NPBREQS(x)    (((1 << (x)) - 1) << 1)\n\n    uint16_t    chan;\n    uint8_t        rf_gain;\n    uint8_t        dsp_gain;\n    uint16_t    active;        /* msecs */\n    uint16_t    passive;    /* msecs */\n} __packed;\n\n/* Maximum size of a scan command. */\n#define IWN_SCAN_MAXSZ    (MCLBYTES - 4)\n\n/*\n * For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after\n * sending probe req.  This should be set long enough to hear probe responses\n * from more than one AP.\n */\n#define IWN_ACTIVE_DWELL_TIME_2GHZ    (30)    /* all times in msec */\n#define IWN_ACTIVE_DWELL_TIME_5GHZ    (20)\n#define IWN_ACTIVE_DWELL_FACTOR_2GHZ    (3)\n#define IWN_ACTIVE_DWELL_FACTOR_5GHZ    (2)\n\n/*\n * For passive scan, listen PASSIVE_DWELL_TIME (msec) on each channel.\n * Must be set longer than active dwell time.\n * For the most reliable scan, set > AP beacon interval (typically 100msec).\n */\n#define IWN_PASSIVE_DWELL_TIME_2GHZ    (20)    /* all times in msec */\n#define IWN_PASSIVE_DWELL_TIME_5GHZ    (10)\n#define IWN_PASSIVE_DWELL_BASE        (100)\n#define IWN_CHANNEL_TUNE_TIME        (5)\n\n/*\n * If active scanning is requested but a certain channel is\n * marked passive, we can do active scanning if we detect\n * transmissions.\n *\n * There is an issue with some firmware versions that triggers\n * a sysassert on a \"good CRC threshold\" of zero (== disabled),\n * on a radar channel even though this means that we should NOT\n * send probes.\n *\n * The \"good CRC threshold\" is the number of frames that we\n * need to receive during our dwell time on a channel before\n * sending out probes -- setting this to a huge value will\n * mean we never reach it, but at the same time work around\n * the aforementioned issue. Thus use IWN_GOOD_CRC_TH_NEVER\n * here instead of IWN_GOOD_CRC_TH_DISABLED.\n *\n * This was fixed in later versions along with some other\n * scan changes, and the threshold behaves as a flag in those\n * versions.\n */\n#define IWN_GOOD_CRC_TH_DISABLED    0\n#define IWN_GOOD_CRC_TH_DEFAULT        htole16(1)\n#define IWN_GOOD_CRC_TH_NEVER        htole16(0xffff)\n\n/* Structure for command IWN_CMD_TXPOWER (4965AGN only.) */\n#define IWN_RIDX_MAX    32\nstruct iwn4965_cmd_txpower {\n    uint8_t        band;\n    uint8_t        reserved1;\n    uint8_t        chan;\n    uint8_t        reserved2;\n    struct {\n        uint8_t    rf_gain[2];\n        uint8_t    dsp_gain[2];\n    } __packed    power[IWN_RIDX_MAX + 1];\n} __packed;\n\n/* Structure for command IWN_CMD_TXPOWER_DBM (5000 Series only.) */\nstruct iwn5000_cmd_txpower {\n    int8_t    global_limit;    /* in half-dBm */\n#define IWN5000_TXPOWER_AUTO        0x7f\n#define IWN5000_TXPOWER_MAX_DBM        16\n\n    uint8_t    flags;\n#define IWN5000_TXPOWER_NO_CLOSED    (1 << 6)\n\n    int8_t    srv_limit;    /* in half-dBm */\n    uint8_t    reserved;\n} __packed;\n\n/* Structures for command IWN_CMD_BLUETOOTH. */\nstruct iwn_bluetooth {\n    uint8_t        flags;\n#define IWN_BT_COEX_CHAN_ANN    (1 << 0)\n#define IWN_BT_COEX_BT_PRIO    (1 << 1)\n#define IWN_BT_COEX_2_WIRE    (1 << 2)\n\n    uint8_t        lead_time;\n#define IWN_BT_LEAD_TIME_DEF    30\n\n    uint8_t        max_kill;\n#define IWN_BT_MAX_KILL_DEF    5\n\n    uint8_t        reserved;\n    uint32_t    kill_ack;\n    uint32_t    kill_cts;\n} __packed;\n\nstruct iwn6000_btcoex_config {\n    uint8_t        flags;\n#define IWN_BT_COEX6000_CHAN_INHIBITION    1\n#define IWN_BT_COEX6000_MODE_MASK    ((1 << 3) | (1 << 4) | (1 << 5))\n#define IWN_BT_COEX6000_MODE_SHIFT    3\n#define IWN_BT_COEX6000_MODE_DISABLED    0\n#define IWN_BT_COEX6000_MODE_LEGACY_2W    1\n#define IWN_BT_COEX6000_MODE_3W        2\n#define IWN_BT_COEX6000_MODE_4W        3\n#define IWN_BT_UCODE_DEFAULT        (1<<6)\n#define IWN_BT_SYNC_2_BT_DISABLE    (1<<7)\n\n    uint8_t        lead_time;\n    uint8_t        max_kill;\n    uint8_t        bt3_t7_timer;\n    uint32_t    kill_ack;\n    uint32_t    kill_cts;\n    uint8_t        sample_time;\n    uint8_t        bt3_t2_timer;\n    uint16_t    bt4_reaction;\n    uint32_t    lookup_table[12];\n    uint16_t    bt4_decision;\n    uint16_t    valid;\n    uint8_t        prio_boost;\n    uint8_t        tx_prio_boost;\n    uint16_t    rx_prio_boost;\n} __packed;\n\nstruct iwn2000_btcoex_config {\n    uint8_t        flags;        /* same as in iwn6000_btcoex_config */\n    uint8_t        lead_time;\n    uint8_t        max_kill;\n    uint8_t        bt3_t7_timer;\n    uint32_t    kill_ack;\n    uint32_t    kill_cts;\n    uint8_t        sample_time;\n    uint8_t        bt3_t2_timer;\n    uint16_t    bt4_reaction;\n    uint32_t    lookup_table[12];\n    uint16_t    bt4_decision;\n    uint16_t    valid;\n        uint32_t    prio_boost;\n    uint8_t        reserved;\n    uint8_t        tx_prio_boost;\n    uint16_t    rx_prio_boost;\n} __packed;\n\n/* Structure for command IWN_CMD_BT_COEX_PRIOTABLE */\nstruct iwn_btcoex_priotable {\n    uint8_t        calib_init1;\n    uint8_t        calib_init2;\n    uint8_t        calib_periodic_low1;\n    uint8_t        calib_periodic_low2;\n    uint8_t        calib_periodic_high1;\n    uint8_t        calib_periodic_high2;\n    uint8_t        dtim;\n    uint8_t        scan52;\n    uint8_t        scan24;\n    uint8_t        reserved[7];\n} __packed;\n\n/* Structure for command IWN_CMD_BT_COEX_PROT */\nstruct iwn_btcoex_prot {\n    uint8_t        open;\n    uint8_t        type;\n    uint8_t        reserved[2];\n} __packed;\n\n/* Structure for command IWN_CMD_SET_CRITICAL_TEMP. */\nstruct iwn_critical_temp {\n    uint32_t    reserved;\n    uint32_t    tempM;\n    uint32_t    tempR;\n/* degK <-> degC conversion macros. */\n#define IWN_CTOK(c)    ((c) + 273)\n#define IWN_KTOC(k)    ((k) - 273)\n#define IWN_CTOMUK(c)    (((c) * 1000000) + 273150000)\n} __packed;\n\n/* Structures for command IWN_CMD_SET_SENSITIVITY. */\nstruct iwn_sensitivity_cmd {\n    uint16_t    which;\n#define IWN_SENSITIVITY_DEFAULTTBL    0\n#define IWN_SENSITIVITY_WORKTBL        1\n\n    uint16_t    energy_cck;\n    uint16_t    energy_ofdm;\n    uint16_t    corr_ofdm_x1;\n    uint16_t    corr_ofdm_mrc_x1;\n    uint16_t    corr_cck_mrc_x4;\n    uint16_t    corr_ofdm_x4;\n    uint16_t    corr_ofdm_mrc_x4;\n    uint16_t    corr_barker;\n    uint16_t    corr_barker_mrc;\n    uint16_t    corr_cck_x4;\n    uint16_t    energy_ofdm_th;\n} __packed;\n\nstruct iwn_enhanced_sensitivity_cmd {\n    uint16_t    which;\n    uint16_t    energy_cck;\n    uint16_t    energy_ofdm;\n    uint16_t    corr_ofdm_x1;\n    uint16_t    corr_ofdm_mrc_x1;\n    uint16_t    corr_cck_mrc_x4;\n    uint16_t    corr_ofdm_x4;\n    uint16_t    corr_ofdm_mrc_x4;\n    uint16_t    corr_barker;\n    uint16_t    corr_barker_mrc;\n    uint16_t    corr_cck_x4;\n    uint16_t    energy_ofdm_th;\n    /* \"Enhanced\" part. */\n    uint16_t    ina_det_ofdm;\n    uint16_t    ina_det_cck;\n    uint16_t    corr_11_9_en;\n    uint16_t    ofdm_det_slope_mrc;\n    uint16_t    ofdm_det_icept_mrc;\n    uint16_t    ofdm_det_slope;\n    uint16_t    ofdm_det_icept;\n    uint16_t    cck_det_slope_mrc;\n    uint16_t    cck_det_icept_mrc;\n    uint16_t    cck_det_slope;\n    uint16_t    cck_det_icept;\n    uint16_t    reserved;\n} __packed;\n\n/* Structures for command IWN_CMD_PHY_CALIB. */\nstruct iwn_phy_calib {\n    uint8_t    code;\n#define IWN4965_PHY_CALIB_DIFF_GAIN         7\n#define IWN5000_PHY_CALIB_DC             8\n#define IWN5000_PHY_CALIB_LO             9\n#define IWN5000_PHY_CALIB_TX_IQ            11\n#define IWN5000_PHY_CALIB_CRYSTAL        15\n#define IWN5000_PHY_CALIB_BASE_BAND        16\n#define IWN5000_PHY_CALIB_TX_IQ_PERIODIC    17\n#define IWN5000_PHY_CALIB_RESET_NOISE_GAIN    18\n#define IWN5000_PHY_CALIB_NOISE_GAIN        19\n\n#define IWN6000_PHY_CALIB_TEMP_OFFSET        18\n#define IWN2000_PHY_CALIB_TEMP_OFFSET        18\n\n#define IWN5000_PHY_CALIB_MAX            253\n\n    uint8_t    group;\n    uint8_t    ngroups;\n    uint8_t    isvalid;\n} __packed;\n\nstruct iwn5000_phy_calib_crystal {\n    uint8_t    code;\n    uint8_t    group;\n    uint8_t    ngroups;\n    uint8_t    isvalid;\n\n    uint8_t    cap_pin[2];\n    uint8_t    reserved[2];\n} __packed;\n\nstruct iwn6000_phy_calib_temp_offset {\n    uint8_t        code;\n    uint8_t        group;\n    uint8_t        ngroups;\n    uint8_t        isvalid;\n    int16_t        offset;\n#define IWN_DEFAULT_TEMP_OFFSET    2700\n\n    uint16_t    reserved;\n} __packed;\n\nstruct iwn2000_phy_calib_temp_offset {\n    uint8_t        code;\n    uint8_t        group;\n    uint8_t        ngroups;\n    uint8_t        isvalid;\n    int16_t        offset_high;\n    int16_t        offset_low;\n    int16_t        burnt_voltage_ref;\n    int16_t        reserved;\n} __packed;\n\nstruct iwn_phy_calib_gain {\n    uint8_t    code;\n    uint8_t    group;\n    uint8_t    ngroups;\n    uint8_t    isvalid;\n\n    int8_t    gain[3];\n    uint8_t    reserved;\n} __packed;\n\n/* Structure for command IWN_CMD_SPECTRUM_MEASUREMENT. */\nstruct iwn_spectrum_cmd {\n    uint16_t    len;\n    uint8_t        token;\n    uint8_t        id;\n    uint8_t        origin;\n    uint8_t        periodic;\n    uint16_t    timeout;\n    uint32_t    start;\n    uint32_t    reserved1;\n    uint32_t    flags;\n    uint32_t    filter;\n    uint16_t    nchan;\n    uint16_t    reserved2;\n    struct {\n        uint32_t    duration;\n        uint8_t        chan;\n        uint8_t        type;\n#define IWN_MEASUREMENT_BASIC        (1 << 0)\n#define IWN_MEASUREMENT_CCA        (1 << 1)\n#define IWN_MEASUREMENT_RPI_HISTOGRAM    (1 << 2)\n#define IWN_MEASUREMENT_NOISE_HISTOGRAM    (1 << 3)\n#define IWN_MEASUREMENT_FRAME        (1 << 4)\n#define IWN_MEASUREMENT_IDLE        (1 << 7)\n\n        uint16_t    reserved;\n    } __packed    chan[10];\n} __packed;\n\n/* Structure for IWN_UC_READY notification. */\n#define IWN_NATTEN_GROUPS    5\nstruct iwn_ucode_info {\n    uint8_t        minor;\n    uint8_t        major;\n    uint16_t    reserved1;\n    uint8_t        revision[8];\n    uint8_t        type;\n    uint8_t        subtype;\n#define IWN_UCODE_RUNTIME    0\n#define IWN_UCODE_INIT        9\n\n    uint16_t    reserved2;\n    uint32_t    logptr;\n    uint32_t    errptr;\n    uint32_t    tstamp;\n    uint32_t    valid;\n\n    /* The following fields are for UCODE_INIT only. */\n    int32_t        volt;\n    struct {\n        int32_t    chan20MHz;\n        int32_t    chan40MHz;\n    } __packed    temp[4];\n    int32_t        atten[IWN_NATTEN_GROUPS][2];\n} __packed;\n\n/* Structures for IWN_TX_DONE notification. */\n\n/* Tx status for aggregated frames (A-MPDU). */\nstruct iwn_txagg_status {\n    uint16_t status;\n#define IWN_AGG_TX_STATE_TRANSMITTED        0x0000\n#define IWN_AGG_TX_STATE_UNDERRUN        0x0001\n#define IWN_AGG_TX_STATE_BT_PRIO        0x0002\n#define IWN_AGG_TX_STATE_FEW_BYTES        0x0004\n#define IWN_AGG_TX_STATE_ABORT            0x0008\n#define IWN_AGG_TX_STATE_LAST_SENT_TTL        0x0010\n#define IWN_AGG_TX_STATE_LAST_SENT_TRY_CNT    0x0020\n#define IWN_AGG_TX_STATE_LAST_SENT_BT_KILL    0x0040\n#define IWN_AGG_TX_STATE_SCD_QUERY        0x0080\n#define IWN_AGG_TX_STATE_TEST_BAD_CRC32        0x0100\n#define IWN_AGG_TX_STATE_RESPONSE_MASK        0x01ff\n#define IWN_AGG_TX_STATE_DUMP_TX        0x0200\n#define IWN_AGG_TX_STATE_DELAY_TX        0x0400\n#define IWN_AGG_TX_STATUS_MASK            0x0fff\n/* Number of TX attempts for first frame in aggregation: */\n#define IWN_AGG_TX_TRY                0xf000\n#define IWN_AGG_TX_TRY_SHIFT            12\n\n    /* Copied from Tx command we have sent to the firmware. */\n    uint8_t    idx;\n    uint8_t    qid;\n} __packed;\n\n/* For aggregation queues, index must be aligned to frame sequence number. */\n#define IWN_AGG_SSN_TO_TXQ_IDX(x)    ((x) & (IWN_TX_RING_COUNT - 1))\n\n/* Tx status codes for non-aggregated frames. */\n#define IWN_TX_STATUS_SUCCESS            0x01\n#define IWN_TX_STATUS_DIRECT_DONE        0x02\n#define IWN_TX_STATUS_POSTPONE_DELAY        0x40\n#define IWN_TX_STATUS_POSTPONE_FEW_BYTES    0x41\n#define IWN_TX_STATUS_POSTPONE_BT_PRIO        0x42\n#define IWN_TX_STATUS_POSTPONE_QUIET_PERIOD    0x43\n#define IWN_TX_STATUS_POSTPONE_CALC_TTAK    0x44\n#define IWN_TX_STATUS_FAIL_CROSSED_RETRY    0x81\n#define IWN_TX_STATUS_FAIL_SHORT_LIMIT        0x82\n#define IWN_TX_STATUS_FAIL_LONG_LIMIT        0x83\n#define IWN_TX_STATUS_FAIL_FIFO_UNDERRUN    0x84\n#define IWN_TX_STATUS_FAIL_DRAIN_FLOW        0x85\n#define IWN_TX_STATUS_FAIL_RFKILL_FLUSH        0x86\n#define IWN_TX_STATUS_FAIL_LIFE_EXPIRE        0x87\n#define IWN_TX_STATUS_FAIL_DEST_PS        0x88\n#define IWN_TX_STATUS_FAIL_HOST_ABORTED        0x89\n#define IWN_TX_STATUS_FAIL_BT_RETRY        0x8a\n#define IWN_TX_STATUS_FAIL_STA_INVALID        0x8b\n#define IWN_TX_STATUS_FAIL_FRAG_DROPPED        0x8c\n#define IWN_TX_STATUS_FAIL_TID_DISABLE        0x8d\n#define IWN_TX_STATUS_FAIL_FIFO_FLUSHED        0x8e\n#define IWN_TX_STATUS_FAIL_INSUFFICIENT_CF_POLL    0x8f\n#define IWN_TX_STATUS_FAIL_PASSIVE_NO_RX    0x90\n#define IWN_TX_STATUS_FAIL_NO_BEACON_ON_RADAR    0x91\n\nstruct iwn4965_tx_stat {\n    uint8_t        nframes;\n    uint8_t        btkillcnt;\n    uint8_t        rtsfailcnt;\n    uint8_t        ackfailcnt;\n    uint8_t        rate;\n    uint8_t        rflags;\n    uint16_t    xrflags;\n    uint16_t    duration;\n    uint16_t    reserved;\n    uint32_t    power[2];\n    union {\n        uint32_t        status;        /* if nframes == 1 */\n        struct iwn_txagg_status agg_status[0];    /* nframes elements */\n    } stat;\n    /* Followed by current scheduler SSN (uint32_t). */\n} __packed;\n\nstruct iwn5000_tx_stat {\n    uint8_t        nframes;\n    uint8_t        btkillcnt;\n    uint8_t        rtsfailcnt;\n    uint8_t        ackfailcnt;\n    uint8_t        rate;\n    uint8_t        rflags;\n    uint16_t    xrflags;\n    uint16_t    duration;\n    uint16_t    reserved;\n    uint32_t    power[2];\n    uint32_t    info;\n    uint16_t    seq;\n    uint16_t    len;\n    uint8_t        tlc;\n    uint8_t        ratid;\n#define IWN_TX_RES_TID_SHIFT    0\n#define IWN_TX_RES_TID        0x0f\n#define IWN_TX_RES_RA_SHIFT    4\n#define IWN_TX_RES_RA        0xf0\n    uint8_t        fc[2];\n    union {\n        uint32_t        status;        /* if nframes == 1 */\n        struct iwn_txagg_status agg_status[0];    /* nframes elements */\n    } stat;\n    /* Followed by current scheduler SSN (uint32_t). */\n} __packed;\n\n/* Structure for IWN_BEACON_MISSED notification. */\nstruct iwn_beacon_missed {\n    uint32_t    consecutive;\n    uint32_t    total;\n    uint32_t    expected;\n    uint32_t    received;\n} __packed;\n\n/* Structure for IWN_MPDU_RX_DONE notification. */\nstruct iwn_rx_mpdu {\n    uint16_t    len;\n    uint16_t    reserved;\n} __packed;\n\n/* Structures for IWN_RX_DONE and IWN_MPDU_RX_DONE notifications. */\nstruct iwn4965_rx_phystat {\n    uint16_t    antenna;\n    uint16_t    agc;\n    uint8_t        rssi[6];\n} __packed;\n\nstruct iwn5000_rx_phystat {\n    uint32_t    reserved1;\n    uint32_t    agc;\n    uint16_t    rssi[3];\n} __packed;\n\nstruct iwn_rx_stat {\n    uint8_t        phy_len;\n    uint8_t        cfg_phy_len;\n#define IWN_STAT_MAXLEN    20\n\n    uint8_t        id;\n    uint8_t        reserved1;\n    uint64_t    tstamp;\n    uint32_t    beacon;\n    uint16_t    flags;\n#define IWN_STAT_FLAG_24GHZ        (1 << 0)\n#define IWN_STAT_FLAG_MOD_CCK        (1 << 1)\n#define IWN_STAT_FLAG_SHPREAMBLE    (1 << 2)\n#define IWN_STAT_FLAG_NARROW_BAND    (1 << 3)\n#define IWN_STAT_FLAG_ANT(x)        ((x) << 4) /* 3 bits */\n#define IWN_STAT_FLAG_AGG        (1 << 7)\n\n    uint16_t    chan;\n    uint8_t        phybuf[32];\n    uint8_t        rate;\n    uint8_t        rflags;\n    uint16_t    xrflags;\n    uint16_t    len;\n    uint16_t    reserve3;\n} __packed;\n\n#define IWN_RSSI_TO_DBM    44\n\n/* Structure for IWN_RX_COMPRESSED_BA notification. */\nstruct iwn_compressed_ba {\n    uint8_t        macaddr[IEEE80211_ADDR_LEN];\n    uint16_t    reserved;\n    uint8_t        id;\n    uint8_t        tid;\n    uint16_t    seq;\n    uint64_t    bitmap;\n    uint16_t    qid;\n    uint16_t    ssn;\n    uint8_t        nframes_sent;\n    uint8_t        nframes_acked;\n    uint16_t    reserved2;\n} __packed;\n\n/* Structure for IWN_START_SCAN notification. */\nstruct iwn_start_scan {\n    uint64_t    tstamp;\n    uint32_t    tbeacon;\n    uint8_t        chan;\n    uint8_t        band;\n    uint16_t    reserved;\n    uint32_t    status;\n} __packed;\n\n/* Structure for IWN_STOP_SCAN notification. */\nstruct iwn_stop_scan {\n    uint8_t        nchan;\n    uint8_t        status;\n    uint8_t        reserved;\n    uint8_t        chan;\n    uint64_t    tsf;\n} __packed;\n\n/* Structure for IWN_SPECTRUM_MEASUREMENT notification. */\nstruct iwn_spectrum_notif {\n    uint8_t        id;\n    uint8_t        token;\n    uint8_t        idx;\n    uint8_t        state;\n#define IWN_MEASUREMENT_START    0\n#define IWN_MEASUREMENT_STOP    1\n\n    uint32_t    start;\n    uint8_t        band;\n    uint8_t        chan;\n    uint8_t        type;\n    uint8_t        reserved1;\n    uint32_t    cca_ofdm;\n    uint32_t    cca_cck;\n    uint32_t    cca_time;\n    uint8_t        basic;\n    uint8_t        reserved2[3];\n    uint32_t    ofdm[8];\n    uint32_t    cck[8];\n    uint32_t    stop;\n    uint32_t    status;\n#define IWN_MEASUREMENT_OK        0\n#define IWN_MEASUREMENT_CONCURRENT    1\n#define IWN_MEASUREMENT_CSA_CONFLICT    2\n#define IWN_MEASUREMENT_TGH_CONFLICT    3\n#define IWN_MEASUREMENT_STOPPED        6\n#define IWN_MEASUREMENT_TIMEOUT        7\n#define IWN_MEASUREMENT_FAILED        8\n} __packed;\n\n/* Structures for IWN_{RX,BEACON}_STATISTICS notification. */\nstruct iwn_rx_phy_stats {\n    uint32_t    ina;\n    uint32_t    fina;\n    uint32_t    bad_plcp;\n    uint32_t    bad_crc32;\n    uint32_t    overrun;\n    uint32_t    eoverrun;\n    uint32_t    good_crc32;\n    uint32_t    fa;\n    uint32_t    bad_fina_sync;\n    uint32_t    sfd_timeout;\n    uint32_t    fina_timeout;\n    uint32_t    no_rts_ack;\n    uint32_t    rxe_limit;\n    uint32_t    ack;\n    uint32_t    cts;\n    uint32_t    ba_resp;\n    uint32_t    dsp_kill;\n    uint32_t    bad_mh;\n    uint32_t    rssi_sum;\n    uint32_t    reserved;\n} __packed;\n\nstruct iwn_rx_general_stats {\n    uint32_t    bad_cts;\n    uint32_t    bad_ack;\n    uint32_t    not_bss;\n    uint32_t    filtered;\n    uint32_t    bad_chan;\n    uint32_t    beacons;\n    uint32_t    missed_beacons;\n    uint32_t    adc_saturated;    /* time in 0.8us */\n    uint32_t    ina_searched;    /* time in 0.8us */\n    uint32_t    noise[3];\n    uint32_t    flags;\n    uint32_t    load;\n    uint32_t    fa;\n    uint32_t    rssi[3];\n    uint32_t    energy[3];\n} __packed;\n\nstruct iwn_rx_ht_phy_stats {\n    uint32_t    bad_plcp;\n    uint32_t    overrun;\n    uint32_t    eoverrun;\n    uint32_t    good_crc32;\n    uint32_t    bad_crc32;\n    uint32_t    bad_mh;\n    uint32_t    good_ampdu_crc32;\n    uint32_t    ampdu;\n    uint32_t    fragment;\n    uint32_t    reserved;\n} __packed;\n\nstruct iwn_rx_stats {\n    struct iwn_rx_phy_stats        ofdm;\n    struct iwn_rx_phy_stats        cck;\n    struct iwn_rx_general_stats    general;\n    struct iwn_rx_ht_phy_stats    ht;\n} __packed;\n\nstruct iwn_tx_stats {\n    uint32_t    preamble;\n    uint32_t    rx_detected;\n    uint32_t    bt_defer;\n    uint32_t    bt_kill;\n    uint32_t    short_len;\n    uint32_t    cts_timeout;\n    uint32_t    ack_timeout;\n    uint32_t    exp_ack;\n    uint32_t    ack;\n    uint32_t    msdu;\n    uint32_t    busrt_err1;\n    uint32_t    burst_err2;\n    uint32_t    cts_collision;\n    uint32_t    ack_collision;\n    uint32_t    ba_timeout;\n    uint32_t    ba_resched;\n    uint32_t    query_ampdu;\n    uint32_t    query;\n    uint32_t    query_ampdu_frag;\n    uint32_t    query_mismatch;\n    uint32_t    not_ready;\n    uint32_t    underrun;\n    uint32_t    bt_ht_kill;\n    uint32_t    rx_ba_resp;\n    uint32_t    reserved[2];\n} __packed;\n\nstruct iwn_general_stats {\n    uint32_t    temp;\n    uint32_t    temp_m;\n    uint32_t    burst_check;\n    uint32_t    burst;\n    uint32_t    reserved1[4];\n    uint32_t    sleep;\n    uint32_t    slot_out;\n    uint32_t    slot_idle;\n    uint32_t    ttl_tstamp;\n    uint32_t    tx_ant_a;\n    uint32_t    tx_ant_b;\n    uint32_t    exec;\n    uint32_t    probe;\n    uint32_t    reserved2[2];\n    uint32_t    rx_enabled;\n    uint32_t    reserved3[3];\n} __packed;\n\nstruct iwn_stats {\n    uint32_t            flags;\n#define IWN_STATS_FLAGS_BAND_24G    0x02\n#define IWN_STATS_FLAGS_BAND_HT40    0x08\n    struct iwn_rx_stats        rx;\n    struct iwn_tx_stats        tx;\n    struct iwn_general_stats    general;\n} __packed;\n\n\n/* Firmware error dump. */\nstruct iwn_fw_dump {\n    uint32_t    valid;\n    uint32_t    id;\n    uint32_t    pc;\n    uint32_t    branch_link[2];\n    uint32_t    interrupt_link[2];\n    uint32_t    error_data[2];\n    uint32_t    src_line;\n    uint32_t    tsf;\n    uint32_t    time[2];\n} __packed;\n\n/* TLV firmware header. */\nstruct iwn_fw_tlv_hdr {\n    uint32_t    zero;    /* Always 0, to differentiate from legacy. */\n    uint32_t    signature;\n#define IWN_FW_SIGNATURE    0x0a4c5749    /* \"IWL\\n\" */\n\n    uint8_t        descr[64];\n    uint32_t    rev;\n#define IWN_FW_API(x)    (((x) >> 8) & 0xff)\n\n    uint32_t    build;\n    uint64_t    altmask;\n} __packed;\n\n/* TLV header. */\nstruct iwn_fw_tlv {\n    uint16_t    type;\n#define IWN_FW_TLV_MAIN_TEXT        1\n#define IWN_FW_TLV_MAIN_DATA        2\n#define IWN_FW_TLV_INIT_TEXT        3\n#define IWN_FW_TLV_INIT_DATA        4\n#define IWN_FW_TLV_BOOT_TEXT        5\n#define IWN_FW_TLV_PBREQ_MAXLEN        6\n#define IWN_FW_TLV_ENH_SENS        14\n#define IWN_FW_TLV_PHY_CALIB        15\n#define IWN_FW_TLV_FLAGS        18\n\n    uint16_t    alt;\n    uint32_t    len;\n} __packed;\n\n#define IWN4965_FW_TEXT_MAXSZ    ( 96 * 1024)\n#define IWN4965_FW_DATA_MAXSZ    ( 40 * 1024)\n#define IWN5000_FW_TEXT_MAXSZ    (256 * 1024)\n#define IWN5000_FW_DATA_MAXSZ    ( 80 * 1024)\n#define IWN_FW_BOOT_TEXT_MAXSZ    1024\n#define IWN4965_FWSZ        (IWN4965_FW_TEXT_MAXSZ + IWN4965_FW_DATA_MAXSZ)\n#define IWN5000_FWSZ        IWN5000_FW_TEXT_MAXSZ\n\n/*\n * Microcode flags TLV (18.)\n */\n\n/**\n * enum iwn_ucode_tlv_flag - ucode API flags\n * @IWN_UCODE_TLV_FLAGS_PAN: This is PAN capable microcode; this previously\n *      was a separate TLV but moved here to save space.\n * @IWN_UCODE_TLV_FLAGS_NEWSCAN: new uCode scan behaviour on hidden SSID,\n *      treats good CRC threshold as a boolean\n * @IWN_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w).\n * @IWN_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P.\n * @IWN_UCODE_TLV_FLAGS_DW_BC_TABLE: The SCD byte count table is in DWORDS\n * @IWN_UCODE_TLV_FLAGS_UAPSD: This uCode image supports uAPSD\n * @IWN_UCODE_TLV_FLAGS_SHORT_BL: 16 entries of black list instead of 64 in scan\n *      offload profile config command.\n * @IWN_UCODE_TLV_FLAGS_RX_ENERGY_API: supports rx signal strength api\n * @IWN_UCODE_TLV_FLAGS_TIME_EVENT_API_V2: using the new time event API.\n * @IWN_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS: D3 image supports up to six\n *      (rather than two) IPv6 addresses\n * @IWN_UCODE_TLV_FLAGS_BF_UPDATED: new beacon filtering API\n * @IWN_UCODE_TLV_FLAGS_NO_BASIC_SSID: not sending a probe with the SSID element\n *      from the probe request template.\n * @IWN_UCODE_TLV_FLAGS_D3_CONTINUITY_API: modified D3 API to allow keeping\n *      connection when going back to D0\n * @IWN_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL: new NS offload (small version)\n * @IWN_UCODE_TLV_FLAGS_NEW_NSOFFL_LARGE: new NS offload (large version)\n * @IWN_UCODE_TLV_FLAGS_SCHED_SCAN: this uCode image supports scheduled scan.\n * @IWN_UCODE_TLV_FLAGS_STA_KEY_CMD: new ADD_STA and ADD_STA_KEY command API\n * @IWN_UCODE_TLV_FLAGS_DEVICE_PS_CMD: support device wide power command\n *      containing CAM (Continuous Active Mode) indication.\n */\nenum iwn_ucode_tlv_flag {\n    IWN_UCODE_TLV_FLAGS_PAN            = (1 << 0),\n    IWN_UCODE_TLV_FLAGS_NEWSCAN        = (1 << 1),\n    IWN_UCODE_TLV_FLAGS_MFP            = (1 << 2),\n    IWN_UCODE_TLV_FLAGS_P2P            = (1 << 3),\n    IWN_UCODE_TLV_FLAGS_DW_BC_TABLE        = (1 << 4),\n    IWN_UCODE_TLV_FLAGS_NEWBT_COEX        = (1 << 5),\n    IWN_UCODE_TLV_FLAGS_UAPSD        = (1 << 6),\n    IWN_UCODE_TLV_FLAGS_SHORT_BL        = (1 << 7),\n    IWN_UCODE_TLV_FLAGS_RX_ENERGY_API    = (1 << 8),\n    IWN_UCODE_TLV_FLAGS_TIME_EVENT_API_V2    = (1 << 9),\n    IWN_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS    = (1 << 10),\n    IWN_UCODE_TLV_FLAGS_BF_UPDATED        = (1 << 11),\n    IWN_UCODE_TLV_FLAGS_NO_BASIC_SSID    = (1 << 12),\n    IWN_UCODE_TLV_FLAGS_D3_CONTINUITY_API    = (1 << 14),\n    IWN_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL    = (1 << 15),\n    IWN_UCODE_TLV_FLAGS_NEW_NSOFFL_LARGE    = (1 << 16),\n    IWN_UCODE_TLV_FLAGS_SCHED_SCAN        = (1 << 17),\n    IWN_UCODE_TLV_FLAGS_STA_KEY_CMD        = (1 << 19),\n    IWN_UCODE_TLV_FLAGS_DEVICE_PS_CMD    = (1 << 20),\n};\n\n/*\n * Offsets into EEPROM.\n */\n#define IWN_EEPROM_MAC        0x015\n#define IWN_EEPROM_SKU_CAP    0x045\n#define IWN_EEPROM_RFCFG    0x048\n#define IWN4965_EEPROM_DOMAIN    0x060\n#define IWN4965_EEPROM_BAND1    0x063\n#define IWN5000_EEPROM_REG    0x066\n#define IWN5000_EEPROM_CAL    0x067\n#define IWN4965_EEPROM_BAND2    0x072\n#define IWN4965_EEPROM_BAND3    0x080\n#define IWN4965_EEPROM_BAND4    0x08d\n#define IWN4965_EEPROM_BAND5    0x099\n#define IWN4965_EEPROM_BAND6    0x0a0\n#define IWN4965_EEPROM_BAND7    0x0a8\n#define IWN4965_EEPROM_MAXPOW    0x0e8\n#define IWN4965_EEPROM_VOLTAGE    0x0e9\n#define IWN4965_EEPROM_BANDS    0x0ea\n/* Indirect offsets. */\n#define IWN5000_EEPROM_DOMAIN    0x001\n#define IWN5000_EEPROM_BAND1    0x004\n#define IWN5000_EEPROM_BAND2    0x013\n#define IWN5000_EEPROM_BAND3    0x021\n#define IWN5000_EEPROM_BAND4    0x02e\n#define IWN5000_EEPROM_BAND5    0x03a\n#define IWN5000_EEPROM_BAND6    0x041\n#define IWN5000_EEPROM_BAND7    0x049\n#define IWN6000_EEPROM_ENHINFO    0x054\n#define IWN5000_EEPROM_CRYSTAL    0x128\n#define IWN5000_EEPROM_TEMP    0x12a\n#define IWN5000_EEPROM_VOLT    0x12b\n#define IWN2000_EEPROM_RAWTEMP    0x12b\n\n/* Possible flags for IWN_EEPROM_SKU_CAP. */\n#define IWN_EEPROM_SKU_CAP_11N    (1 << 6)\n#define IWN_EEPROM_SKU_CAP_AMT    (1 << 7)\n#define IWN_EEPROM_SKU_CAP_IPAN    (1 << 8)\n\n/* Possible flags for IWN_EEPROM_RFCFG. */\n#define IWN_RFCFG_TYPE(x)    (((x) >>  0) & 0x3)\n#define IWN_RFCFG_STEP(x)    (((x) >>  2) & 0x3)\n#define IWN_RFCFG_DASH(x)    (((x) >>  4) & 0x3)\n#define IWN_RFCFG_TXANTMSK(x)    (((x) >>  8) & 0xf)\n#define IWN_RFCFG_RXANTMSK(x)    (((x) >> 12) & 0xf)\n\nstruct iwn_eeprom_chan {\n    uint8_t    flags;\n#define IWN_EEPROM_CHAN_VALID    (1 << 0)\n#define IWN_EEPROM_CHAN_IBSS    (1 << 1)\n#define IWN_EEPROM_CHAN_ACTIVE    (1 << 3)\n#define IWN_EEPROM_CHAN_RADAR    (1 << 4)\n\n    int8_t    maxpwr;\n} __packed;\n\nstruct iwn_eeprom_enhinfo {\n    uint8_t        flags;\n#define IWN_TXP_VALID        (1 << 0)\n#define IWN_TXP_BAND_52G    (1 << 1)\n#define IWN_TXP_OFDM        (1 << 2)\n#define IWN_TXP_40MHZ        (1 << 3)\n#define IWN_TXP_HT_AP        (1 << 4)\n#define IWN_TXP_RES1        (1 << 5)\n#define IWN_TXP_RES2        (1 << 6)\n#define IWN_TXP_COMMON_TYPE    (1 << 7)\n    uint8_t        chan;\n    int8_t        chain[3];    /* max power in half-dBm */\n    uint8_t        delta_20_in_40;\n    int8_t        mimo2;        /* max power in half-dBm */\n    int8_t        mimo3;        /* max power in half-dBm */\n} __packed;\n\nstruct iwn5000_eeprom_calib_hdr {\n    uint8_t        version;\n    uint8_t        pa_type;\n    uint16_t    volt;\n} __packed;\n\n#define IWN_NSAMPLES    3\nstruct iwn4965_eeprom_chan_samples {\n    uint8_t    num;\n    struct {\n        uint8_t temp;\n        uint8_t    gain;\n        uint8_t    power;\n        int8_t    pa_det;\n    }    samples[2][IWN_NSAMPLES];\n} __packed;\n\n#define IWN_NBANDS    8\nstruct iwn4965_eeprom_band {\n    uint8_t    lo;    /* low channel number */\n    uint8_t    hi;    /* high channel number */\n    struct    iwn4965_eeprom_chan_samples chans[2];\n} __packed;\n\n/*\n * Offsets of channels descriptions in EEPROM.\n */\nstatic const uint32_t iwn4965_regulatory_bands[IWN_NBANDS] = {\n    IWN4965_EEPROM_BAND1,\n    IWN4965_EEPROM_BAND2,\n    IWN4965_EEPROM_BAND3,\n    IWN4965_EEPROM_BAND4,\n    IWN4965_EEPROM_BAND5,\n    IWN4965_EEPROM_BAND6,\n    IWN4965_EEPROM_BAND7\n};\n\nstatic const uint32_t iwn5000_regulatory_bands[IWN_NBANDS] = {\n    IWN5000_EEPROM_BAND1,\n    IWN5000_EEPROM_BAND2,\n    IWN5000_EEPROM_BAND3,\n    IWN5000_EEPROM_BAND4,\n    IWN5000_EEPROM_BAND5,\n    IWN5000_EEPROM_BAND6,\n    IWN5000_EEPROM_BAND7\n};\n\n#define IWN_CHAN_BANDS_COUNT     7\n#define IWN_MAX_CHAN_PER_BAND    14\nstatic const struct iwn_chan_band {\n    uint8_t    nchan;\n    uint8_t    chan[IWN_MAX_CHAN_PER_BAND];\n} iwn_bands[] = {\n    /* 20MHz channels, 2GHz band. */\n    { 14, { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 } },\n    /* 20MHz channels, 5GHz band. */\n    { 13, { 183, 184, 185, 187, 188, 189, 192, 196, 7, 8, 11, 12, 16 } },\n    { 12, { 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64 } },\n    { 11, { 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 } },\n    {  6, { 145, 149, 153, 157, 161, 165 } },\n    /* 40MHz channels (primary channels), 2GHz band. */\n    {  7, { 1, 2, 3, 4, 5, 6, 7 } },\n    /* 40MHz channels (primary channels), 5GHz band. */\n    { 11, { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157 } }\n};\n\n#define IWN1000_OTP_NBLOCKS    3\n#define IWN6000_OTP_NBLOCKS    4\n#define IWN6050_OTP_NBLOCKS    7\n\n/* fw API values for legacy bit rates, both OFDM and CCK */\n#define IWN_RATE_6M_PLCP     13\n#define IWN_RATE_9M_PLCP     15\n#define IWN_RATE_12M_PLCP    5\n#define IWN_RATE_18M_PLCP    7\n#define IWN_RATE_24M_PLCP    9\n#define IWN_RATE_36M_PLCP    11\n#define IWN_RATE_48M_PLCP    1\n#define IWN_RATE_54M_PLCP    3\n#define IWN_RATE_1M_PLCP     10\n#define IWN_RATE_2M_PLCP     20\n#define IWN_RATE_5M_PLCP     55\n#define IWN_RATE_11M_PLCP    110\n#define IWN_RATE_INVM_PLCP   0xff\n\n/* uCode API values for HT/VHT bit rates */\n#define IWN_RATE_HT_SISO_MCS_0_PLCP    0\n#define IWN_RATE_HT_SISO_MCS_1_PLCP    1\n#define IWN_RATE_HT_SISO_MCS_2_PLCP    2\n#define IWN_RATE_HT_SISO_MCS_3_PLCP    3\n#define IWN_RATE_HT_SISO_MCS_4_PLCP    4\n#define IWN_RATE_HT_SISO_MCS_5_PLCP    5\n#define IWN_RATE_HT_SISO_MCS_6_PLCP    6\n#define IWN_RATE_HT_SISO_MCS_7_PLCP    7\n#define IWN_RATE_HT_MIMO2_MCS_8_PLCP   0x8\n#define IWN_RATE_HT_MIMO2_MCS_9_PLCP   0x9\n#define IWN_RATE_HT_MIMO2_MCS_10_PLCP  0xA\n#define IWN_RATE_HT_MIMO2_MCS_11_PLCP  0xB\n#define IWN_RATE_HT_MIMO2_MCS_12_PLCP  0xC\n#define IWN_RATE_HT_MIMO2_MCS_13_PLCP  0xD\n#define IWN_RATE_HT_MIMO2_MCS_14_PLCP  0xE\n#define IWN_RATE_HT_MIMO2_MCS_15_PLCP  0xF\n#define IWN_RATE_HT_SISO_MCS_INV_PLCP  0x1A\n#define IWN_RATE_HT_MIMO2_MCS_INV_PLCP IWN_RATE_HT_SISO_MCS_INV_PLCP\n#define IWN_RATE_HT_SISO_MCS_8_PLCP    IWN_RATE_HT_SISO_MCS_INV_PLCP\n#define IWN_RATE_HT_SISO_MCS_9_PLCP    IWN_RATE_HT_SISO_MCS_INV_PLCP\n\n#define IWN_RATE_HT_MCS_RATE_CODE_MSK  0x7\n#define IWN_RATE_HT_MCS_NSS_POS        3\n#define IWN_RATE_HT_MCS_NSS_MSK        (3 << IWN_RATE_HT_MCS_NSS_POS)\n\n/*\n * These serve as indexes into struct iwn_rate iwn_rates[IWN_RIDX_MAX].\n */\nenum {\n    IWN_RATE_1M_INDEX = 0,\n    IWN_FIRST_CCK_RATE = IWN_RATE_1M_INDEX,\n    IWN_RATE_2M_INDEX,\n    IWN_RATE_5M_INDEX,\n    IWN_RATE_11M_INDEX,\n    IWN_LAST_CCK_RATE = IWN_RATE_11M_INDEX,\n    IWN_RATE_6M_INDEX,\n    IWN_FIRST_OFDM_RATE = IWN_RATE_6M_INDEX,\n    IWN_RATE_MCS_0_INDEX = IWN_RATE_6M_INDEX,\n    IWN_FIRST_HT_RATE = IWN_RATE_MCS_0_INDEX,\n    IWN_FIRST_VHT_RATE = IWN_RATE_MCS_0_INDEX,\n    IWN_RATE_9M_INDEX,\n    IWN_RATE_12M_INDEX,\n    IWN_RATE_MCS_1_INDEX = IWN_RATE_12M_INDEX,\n    IWN_RATE_MCS_8_INDEX,\n    IWN_FIRST_HT_MIMO2_RATE = IWN_RATE_MCS_8_INDEX,\n    IWN_RATE_18M_INDEX,\n    IWN_RATE_MCS_2_INDEX = IWN_RATE_18M_INDEX,\n    IWN_RATE_24M_INDEX,\n    IWN_RATE_MCS_3_INDEX = IWN_RATE_24M_INDEX,\n    IWN_RATE_MCS_9_INDEX,\n    IWN_RATE_36M_INDEX,\n    IWN_RATE_MCS_4_INDEX = IWN_RATE_36M_INDEX,\n    IWN_RATE_MCS_10_INDEX,\n    IWN_RATE_48M_INDEX,\n    IWN_RATE_MCS_5_INDEX = IWN_RATE_48M_INDEX,\n    IWN_RATE_MCS_11_INDEX,\n    IWN_RATE_54M_INDEX,\n    IWN_RATE_MCS_6_INDEX = IWN_RATE_54M_INDEX,\n    IWN_LAST_NON_HT_RATE = IWN_RATE_54M_INDEX,\n    IWN_RATE_MCS_7_INDEX,\n    IWN_LAST_HT_SISO_RATE = IWN_RATE_MCS_7_INDEX,\n    IWN_RATE_MCS_12_INDEX,\n    IWN_RATE_MCS_13_INDEX,\n    IWN_RATE_MCS_14_INDEX,\n    IWN_RATE_MCS_15_INDEX,\n    IWN_LAST_HT_RATE = IWN_RATE_MCS_15_INDEX,\n    IWN_LAST_VHT_RATE = IWN_RATE_MCS_9_INDEX,\n    IWN_RATE_COUNT_LEGACY = IWN_LAST_NON_HT_RATE + 1,\n    IWN_RATE_COUNT = IWN_LAST_HT_RATE + 1,\n};\n\nstatic const struct iwn_rate {\n    uint16_t    rate;\n    uint8_t    plcp;\n    uint8_t    ht_plcp;\n} iwn_rates[IWN_RIDX_MAX + 1] = {\n               /* Legacy */                /* HT */\n    {   2,    IWN_RATE_1M_PLCP,   IWN_RATE_HT_SISO_MCS_INV_PLCP,}, // 0\n    {   4,    IWN_RATE_2M_PLCP,   IWN_RATE_HT_SISO_MCS_INV_PLCP,}, // 1\n    {  11,    IWN_RATE_5M_PLCP,   IWN_RATE_HT_SISO_MCS_INV_PLCP,}, // 2\n    {  22,    IWN_RATE_11M_PLCP,  IWN_RATE_HT_SISO_MCS_INV_PLCP,}, // 3\n    {  12,    IWN_RATE_6M_PLCP,   IWN_RATE_HT_SISO_MCS_0_PLCP,  }, // 4\n    {  18,    IWN_RATE_9M_PLCP,   IWN_RATE_HT_SISO_MCS_INV_PLCP,}, // 5\n    {  24,    IWN_RATE_12M_PLCP,  IWN_RATE_HT_SISO_MCS_1_PLCP,  }, // 6\n    {  26,    IWN_RATE_INVM_PLCP, IWN_RATE_HT_MIMO2_MCS_8_PLCP, }, // 7\n    {  36,    IWN_RATE_18M_PLCP,  IWN_RATE_HT_SISO_MCS_2_PLCP,  }, // 8\n    {  48,    IWN_RATE_24M_PLCP,  IWN_RATE_HT_SISO_MCS_3_PLCP,  }, // 9\n    {  52,    IWN_RATE_INVM_PLCP, IWN_RATE_HT_MIMO2_MCS_9_PLCP, }, // 10\n    {  72,    IWN_RATE_36M_PLCP,  IWN_RATE_HT_SISO_MCS_4_PLCP,  }, // 11\n    {  78,    IWN_RATE_INVM_PLCP, IWN_RATE_HT_MIMO2_MCS_10_PLCP,}, // 12\n    {  96,    IWN_RATE_48M_PLCP,  IWN_RATE_HT_SISO_MCS_5_PLCP,  }, // 13\n    { 104,    IWN_RATE_INVM_PLCP, IWN_RATE_HT_MIMO2_MCS_11_PLCP,}, // 14\n    { 108,    IWN_RATE_54M_PLCP,  IWN_RATE_HT_SISO_MCS_6_PLCP,  }, // 15\n    { 128,    IWN_RATE_INVM_PLCP, IWN_RATE_HT_SISO_MCS_7_PLCP,  }, // 16\n    { 156,    IWN_RATE_INVM_PLCP, IWN_RATE_HT_MIMO2_MCS_12_PLCP,}, // 17\n    { 208,    IWN_RATE_INVM_PLCP, IWN_RATE_HT_MIMO2_MCS_13_PLCP,}, // 18\n    { 234,    IWN_RATE_INVM_PLCP, IWN_RATE_HT_MIMO2_MCS_14_PLCP,}, // 19\n    { 260,    IWN_RATE_INVM_PLCP, IWN_RATE_HT_MIMO2_MCS_15_PLCP,}, // 20\n};\n\n#define IWN_RIDX_CCK    0\n#define IWN_RIDX_OFDM    4\n#define IWN_RIDX_IS_CCK(_i_) ((_i_) < IWN_RIDX_OFDM)\n#define IWN_RIDX_IS_OFDM(_i_) ((_i_) >= IWN_RIDX_OFDM)\n#define IWN_RVAL_IS_OFDM(_i_) ((_i_) >= 12 && (_i_) != 22)\n\n/* Convert an MCS index into an iwn_rates[] index. */\nconst int iwn_mcs2ridx[] = {\n    IWN_RATE_MCS_0_INDEX,\n    IWN_RATE_MCS_1_INDEX,\n    IWN_RATE_MCS_2_INDEX,\n    IWN_RATE_MCS_3_INDEX,\n    IWN_RATE_MCS_4_INDEX,\n    IWN_RATE_MCS_5_INDEX,\n    IWN_RATE_MCS_6_INDEX,\n    IWN_RATE_MCS_7_INDEX,\n    IWN_RATE_MCS_8_INDEX,\n    IWN_RATE_MCS_9_INDEX,\n    IWN_RATE_MCS_10_INDEX,\n    IWN_RATE_MCS_11_INDEX,\n    IWN_RATE_MCS_12_INDEX,\n    IWN_RATE_MCS_13_INDEX,\n    IWN_RATE_MCS_14_INDEX,\n    IWN_RATE_MCS_15_INDEX,\n};\n\n#define IWN4965_MAX_PWR_INDEX    107\n\n/*\n * RF Tx gain values from highest to lowest power (values obtained from\n * the reference driver.)\n */\nstatic const uint8_t iwn4965_rf_gain_2ghz[IWN4965_MAX_PWR_INDEX + 1] = {\n    0x3f, 0x3f, 0x3f, 0x3e, 0x3e, 0x3e, 0x3d, 0x3d, 0x3d, 0x3c, 0x3c,\n    0x3c, 0x3b, 0x3b, 0x3b, 0x3a, 0x3a, 0x3a, 0x39, 0x39, 0x39, 0x38,\n    0x38, 0x38, 0x37, 0x37, 0x37, 0x36, 0x36, 0x36, 0x35, 0x35, 0x35,\n    0x34, 0x34, 0x34, 0x33, 0x33, 0x33, 0x32, 0x32, 0x32, 0x31, 0x31,\n    0x31, 0x30, 0x30, 0x30, 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x04,\n    0x04, 0x04, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00\n};\n\nstatic const uint8_t iwn4965_rf_gain_5ghz[IWN4965_MAX_PWR_INDEX + 1] = {\n    0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3e, 0x3e, 0x3e, 0x3d, 0x3d, 0x3d,\n    0x3c, 0x3c, 0x3c, 0x3b, 0x3b, 0x3b, 0x3a, 0x3a, 0x3a, 0x39, 0x39,\n    0x39, 0x38, 0x38, 0x38, 0x37, 0x37, 0x37, 0x36, 0x36, 0x36, 0x35,\n    0x35, 0x35, 0x34, 0x34, 0x34, 0x33, 0x33, 0x33, 0x32, 0x32, 0x32,\n    0x31, 0x31, 0x31, 0x30, 0x30, 0x30, 0x25, 0x25, 0x25, 0x24, 0x24,\n    0x24, 0x23, 0x23, 0x23, 0x22, 0x18, 0x18, 0x17, 0x17, 0x17, 0x16,\n    0x16, 0x16, 0x15, 0x15, 0x15, 0x14, 0x14, 0x14, 0x13, 0x13, 0x13,\n    0x12, 0x08, 0x08, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06, 0x05, 0x05,\n    0x05, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x01,\n    0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00\n};\n\n/*\n * DSP pre-DAC gain values from highest to lowest power (values obtained\n * from the reference driver.)\n */\nstatic const uint8_t iwn4965_dsp_gain_2ghz[IWN4965_MAX_PWR_INDEX + 1] = {\n    0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68,\n    0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e,\n    0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62,\n    0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68,\n    0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e,\n    0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62,\n    0x6e, 0x68, 0x62, 0x61, 0x60, 0x5f, 0x5e, 0x5d, 0x5c, 0x5b, 0x5a,\n    0x59, 0x58, 0x57, 0x56, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f,\n    0x4e, 0x4d, 0x4c, 0x4b, 0x4a, 0x49, 0x48, 0x47, 0x46, 0x45, 0x44,\n    0x43, 0x42, 0x41, 0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0x3b\n};\n\nstatic const uint8_t iwn4965_dsp_gain_5ghz[IWN4965_MAX_PWR_INDEX + 1] = {\n    0x7b, 0x75, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62,\n    0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68,\n    0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e,\n    0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62,\n    0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68,\n    0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e,\n    0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62,\n    0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68,\n    0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e,\n    0x68, 0x62, 0x6e, 0x68, 0x62, 0x5d, 0x58, 0x53, 0x4e\n};\n\n/*\n * Power saving settings (values obtained from the reference driver.)\n */\n #define IWN_NDTIMRANGES        3\n #define IWN_NPOWERLEVELS    6\n static const struct iwn_pmgt {\n     uint32_t    rxtimeout;\n     uint32_t    txtimeout;\n     uint32_t    intval[5];\n     int        skip_dtim;\n } iwn_pmgt[IWN_NDTIMRANGES][IWN_NPOWERLEVELS] = {\n     /* DTIM <= 2 */\n     {\n     {   0,   0, {  0,  0,  0,  0,  0 }, 0 },    /* CAM */\n     { 200, 500, {  1,  2,  2,  2, (uint32_t)-1 }, 0 },    /* PS level 1 */\n     { 200, 300, {  1,  2,  2,  2, (uint32_t)-1 }, 0 },    /* PS level 2 */\n     {  50, 100, {  2,  2,  2,  2, (uint32_t)-1 }, 0 },    /* PS level 3 */\n     {  50,  25, {  2,  2,  4,  4, (uint32_t)-1 }, 1 },    /* PS level 4 */\n     {  25,  25, {  2,  2,  4,  6, (uint32_t)-1 }, 2 }        /* PS level 5 */\n     },\n     /* 3 <= DTIM <= 10 */\n     {\n     {   0,   0, {  0,  0,  0,  0,  0 }, 0 },    /* CAM */\n     { 200, 500, {  1,  2,  3,  4,  4 }, 0 },    /* PS level 1 */\n     { 200, 300, {  1,  2,  3,  4,  7 }, 0 },    /* PS level 2 */\n     {  50, 100, {  2,  4,  6,  7,  9 }, 0 },    /* PS level 3 */\n     {  50,  25, {  2,  4,  6,  9, 10 }, 1 },    /* PS level 4 */\n     {  25,  25, {  2,  4,  7, 10, 10 }, 2 }        /* PS level 5 */\n     },\n     /* DTIM >= 11 */\n     {\n     {   0,   0, {  0,  0,  0,  0,  0 }, 0 },    /* CAM */\n     { 200, 500, {  1,  2,  3,  4, (uint32_t)-1 }, 0 },    /* PS level 1 */\n     { 200, 300, {  2,  4,  6,  7, (uint32_t)-1 }, 0 },    /* PS level 2 */\n     {  50, 100, {  2,  7,  9,  9, (uint32_t)-1 }, 0 },    /* PS level 3 */\n     {  50,  25, {  2,  7,  9,  9, (uint32_t)-1 }, 0 },    /* PS level 4 */\n     {  25,  25, {  4,  7, 10, 10, (uint32_t)-1 }, 0 }        /* PS level 5 */\n     }\n };\n\nstruct iwn_sensitivity_limits {\n    uint32_t    min_ofdm_x1;\n    uint32_t    max_ofdm_x1;\n    uint32_t    min_ofdm_mrc_x1;\n    uint32_t    max_ofdm_mrc_x1;\n    uint32_t    min_ofdm_x4;\n    uint32_t    max_ofdm_x4;\n    uint32_t    min_ofdm_mrc_x4;\n    uint32_t    max_ofdm_mrc_x4;\n    uint32_t    min_cck_x4;\n    uint32_t    max_cck_x4;\n    uint32_t    min_cck_mrc_x4;\n    uint32_t    max_cck_mrc_x4;\n    uint32_t    min_energy_cck;\n    uint32_t    energy_cck;\n    uint32_t    energy_ofdm;\n};\n\n/*\n * RX sensitivity limits (values obtained from the reference driver.)\n */\nstatic const struct iwn_sensitivity_limits iwn4965_sensitivity_limits = {\n    105, 140,\n    220, 270,\n     85, 120,\n    170, 210,\n    125, 200,\n    200, 400,\n     97,\n    100,\n    100\n};\n\nstatic const struct iwn_sensitivity_limits iwn5000_sensitivity_limits = {\n    120, 120,    /* min = max for performance bug in DSP. */\n    240, 240,    /* min = max for performance bug in DSP. */\n     90, 120,\n    170, 210,\n    125, 200,\n    170, 400,\n     95,\n     95,\n     95\n};\n\nstatic const struct iwn_sensitivity_limits iwn5150_sensitivity_limits = {\n    105, 105,    /* min = max for performance bug in DSP. */\n    220, 220,    /* min = max for performance bug in DSP. */\n     90, 120,\n    170, 210,\n    125, 200,\n    170, 400,\n     95,\n     95,\n     95\n};\n\nstatic const struct iwn_sensitivity_limits iwn1000_sensitivity_limits = {\n    120, 155,\n    240, 290,\n     90, 120,\n    170, 210,\n    125, 200,\n    170, 400,\n     95,\n     95,\n     95\n};\n\nstatic const struct iwn_sensitivity_limits iwn6000_sensitivity_limits = {\n    105, 110,\n    192, 232,\n     80, 145,\n    128, 232,\n    125, 175,\n    160, 310,\n     97,\n     97,\n    100\n};\n\nstatic const struct iwn_sensitivity_limits iwn2000_sensitivity_limits = {\n    105, 110,\n    192, 232,\n     80, 145,\n    128, 232,\n    125, 175,\n    160, 310,\n     97,\n     97,\n    100\n};\n\n/* Map TID to TX scheduler's FIFO. */\n#define IWN_NUM_AMPDU_TID    8\n#define IWN_NONQOS_TID    IWN_NUM_AMPDU_TID\n#define IWN_TX_FIFO_BK    0\n#define IWN_TX_FIFO_BE    1\n#define IWN_TX_FIFO_VI    2\n#define IWN_TX_FIFO_VO    3\nstatic const uint8_t iwn_tid2fifo[IWN_NUM_AMPDU_TID] = {\n    IWN_TX_FIFO_VO, IWN_TX_FIFO_VI, IWN_TX_FIFO_BE, IWN_TX_FIFO_BK,\n    IWN_TX_FIFO_VO, IWN_TX_FIFO_VI, IWN_TX_FIFO_BE, IWN_TX_FIFO_BK\n};\n\n/* WiFi/WiMAX coexist event priority table for 6050. */\nstatic const struct iwn5000_wimax_event iwn6050_wimax_events[] = {\n    { 0x04, 0x03, 0x00, 0x00 },\n    { 0x04, 0x03, 0x00, 0x03 },\n    { 0x04, 0x03, 0x00, 0x03 },\n    { 0x04, 0x03, 0x00, 0x03 },\n    { 0x04, 0x03, 0x00, 0x00 },\n    { 0x04, 0x03, 0x00, 0x07 },\n    { 0x04, 0x03, 0x00, 0x00 },\n    { 0x04, 0x03, 0x00, 0x03 },\n    { 0x04, 0x03, 0x00, 0x03 },\n    { 0x04, 0x03, 0x00, 0x00 },\n    { 0x06, 0x03, 0x00, 0x07 },\n    { 0x04, 0x03, 0x00, 0x00 },\n    { 0x06, 0x06, 0x00, 0x03 },\n    { 0x04, 0x03, 0x00, 0x07 },\n    { 0x04, 0x03, 0x00, 0x00 },\n    { 0x04, 0x03, 0x00, 0x00 }\n};\n\n/* Firmware errors. */\nstatic const char * const iwn_fw_errmsg[] = {\n    \"OK\",\n    \"FAIL\",\n    \"BAD_PARAM\",\n    \"BAD_CHECKSUM\",\n    \"NMI_INTERRUPT_WDG\",\n    \"SYSASSERT\",\n    \"FATAL_ERROR\",\n    \"BAD_COMMAND\",\n    \"HW_ERROR_TUNE_LOCK\",\n    \"HW_ERROR_TEMPERATURE\",\n    \"ILLEGAL_CHAN_FREQ\",\n    \"VCC_NOT_STABLE\",\n    \"FH_ERROR\",\n    \"NMI_INTERRUPT_HOST\",\n    \"NMI_INTERRUPT_ACTION_PT\",\n    \"NMI_INTERRUPT_UNKNOWN\",\n    \"UCODE_VERSION_MISMATCH\",\n    \"HW_ERROR_ABS_LOCK\",\n    \"HW_ERROR_CAL_LOCK_FAIL\",\n    \"NMI_INTERRUPT_INST_ACTION_PT\",\n    \"NMI_INTERRUPT_DATA_ACTION_PT\",\n    \"NMI_TRM_HW_ER\",\n    \"NMI_INTERRUPT_TRM\",\n    \"NMI_INTERRUPT_BREAKPOINT\",\n    \"DEBUG_0\",\n    \"DEBUG_1\",\n    \"DEBUG_2\",\n    \"DEBUG_3\",\n    \"ADVANCED_SYSASSERT\"\n};\n\n/* Find least significant bit that is set. */\n#define IWN_LSB(x)    ((((x) - 1) & (x)) ^ (x))\n\n#define IWN_READ(sc, reg)                        \\\n    bus_space_read_4((sc)->sc_st, (sc)->sc_sh, (reg))\n\n#define IWN_WRITE(sc, reg, val)                        \\\n    bus_space_write_4((sc)->sc_st, (sc)->sc_sh, (reg), (val))\n\n#define IWN_WRITE_1(sc, reg, val)                    \\\n    bus_space_write_1((sc)->sc_st, (sc)->sc_sh, (reg), (val))\n\n#define IWN_SETBITS(sc, reg, mask)                    \\\n    IWN_WRITE(sc, reg, IWN_READ(sc, reg) | (mask))\n\n#define IWN_CLRBITS(sc, reg, mask)                    \\\n    IWN_WRITE(sc, reg, IWN_READ(sc, reg) & ~(mask))\n\n#define IWN_BARRIER_WRITE(sc)                        \\\n    bus_space_barrier((sc)->sc_st, (sc)->sc_sh, 0, (sc)->sc_sz,    \\\n        BUS_SPACE_BARRIER_WRITE)\n\n#define IWN_BARRIER_READ_WRITE(sc)                    \\\n    bus_space_barrier((sc)->sc_st, (sc)->sc_sh, 0, (sc)->sc_sz,    \\\n        BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE)\n\n#define IWN_MIN_DBM    -100\n#define IWN_MAX_DBM    -33    /* realistic guess */\n"
  },
  {
    "path": "itlwm/hal_iwn/if_iwnvar.h",
    "content": "/*\n * Copyright (C) 2020  pigworlds\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n */\n/*    $OpenBSD: if_iwnvar.h,v 1.42 2021/11/12 11:41:04 stsp Exp $    */\n\n/*-\n * Copyright (c) 2007, 2008\n *    Damien Bergamini <damien.bergamini@free.fr>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n#include <net80211/ieee80211_var.h>\n#include <net80211/ieee80211_amrr.h>\n#include <net80211/ieee80211_ra.h>\n#include <net80211/ieee80211_radiotap.h>\n#include <net80211/ieee80211_priv.h>\n\n#include <IOKit/network/IOMbufMemoryCursor.h>\n#include <IOKit/IODMACommand.h>\n\nstruct iwn_rx_radiotap_header {\n    struct ieee80211_radiotap_header wr_ihdr;\n    uint64_t    wr_tsft;\n    uint8_t        wr_flags;\n    uint8_t        wr_rate;\n    uint16_t    wr_chan_freq;\n    uint16_t    wr_chan_flags;\n    int8_t        wr_dbm_antsignal;\n    int8_t        wr_dbm_antnoise;\n} __packed;\n\n#define IWN_RX_RADIOTAP_PRESENT                        \\\n    ((1 << IEEE80211_RADIOTAP_TSFT) |                \\\n     (1 << IEEE80211_RADIOTAP_FLAGS) |                \\\n     (1 << IEEE80211_RADIOTAP_RATE) |                \\\n     (1 << IEEE80211_RADIOTAP_CHANNEL) |                \\\n     (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) |            \\\n     (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE))\n\nstruct iwn_tx_radiotap_header {\n    struct ieee80211_radiotap_header wt_ihdr;\n    uint8_t        wt_flags;\n    uint8_t        wt_rate;\n    uint16_t    wt_chan_freq;\n    uint16_t    wt_chan_flags;\n} __packed;\n\n#define IWN_TX_RADIOTAP_PRESENT                        \\\n    ((1 << IEEE80211_RADIOTAP_FLAGS) |                \\\n     (1 << IEEE80211_RADIOTAP_RATE) |                \\\n     (1 << IEEE80211_RADIOTAP_CHANNEL))\n\nstruct iwn_dma_info {\n    IOBufferMemoryDescriptor* buffer;\n    bus_addr_t        paddr;\n    void             *vaddr;\n    bus_size_t        size;\n    IOBufferMemoryDescriptor *bmd;\n    IODMACommand *cmd;\n};\n\nstruct iwn_tx_data {\n    bus_dmamap_t        map;\n    bus_addr_t        cmd_paddr;\n    bus_addr_t        scratch_paddr;\n    mbuf_t        m;\n    struct ieee80211_node    *ni;\n    int totlen;\n\n    /* A-MPDU subframes */\n    int ampdu_txmcs;\n    int ampdu_nframes;\n};\n\nstruct iwn_tx_ring {\n    struct iwn_dma_info    desc_dma;\n    struct iwn_dma_info    cmd_dma;\n    struct iwn_tx_desc    *desc;\n    struct iwn_tx_cmd    *cmd;\n    struct iwn_tx_data    data[IWN_TX_RING_COUNT];\n    int            qid;\n    int            queued;\n    int            cur;\n    int            read;\n};\n\nstruct iwn_softc;\n\nstruct iwn_rx_data {\n    mbuf_t   m;\n    bus_dmamap_t    map;\n};\n\nstruct iwn_rx_ring {\n    struct iwn_dma_info    desc_dma;\n    struct iwn_dma_info    stat_dma;\n    uint32_t        *desc;\n    struct iwn_rx_status    *stat;\n    struct iwn_rx_data    data[IWN_RX_RING_COUNT];\n    int            cur;\n};\n\nstruct iwn_node {\n    struct    ieee80211_node        ni;    /* must be the first */\n    struct    ieee80211_amrr_node    amn;\n    struct    ieee80211_ra_node    rn;\n    uint16_t            disable_tid;\n    uint8_t                id;\n    uint8_t                ridx[IEEE80211_RATE_MAXSIZE];\n    uint32_t            next_ampdu_id;\n    int                lq_rate_mismatch;\n};\n\nstruct iwn_calib_state {\n    uint8_t        state;\n#define IWN_CALIB_STATE_INIT    0\n#define IWN_CALIB_STATE_ASSOC    1\n#define IWN_CALIB_STATE_RUN    2\n\n    u_int        nbeacons;\n    uint32_t    noise[3];\n    uint32_t    rssi[3];\n    uint32_t    ofdm_x1;\n    uint32_t    ofdm_mrc_x1;\n    uint32_t    ofdm_x4;\n    uint32_t    ofdm_mrc_x4;\n    uint32_t    cck_x4;\n    uint32_t    cck_mrc_x4;\n    uint32_t    bad_plcp_ofdm;\n    uint32_t    fa_ofdm;\n    uint32_t    bad_plcp_cck;\n    uint32_t    fa_cck;\n    uint32_t    low_fa;\n    uint8_t        cck_state;\n#define IWN_CCK_STATE_INIT    0\n#define IWN_CCK_STATE_LOFA    1\n#define IWN_CCK_STATE_HIFA    2\n\n    uint8_t        noise_samples[20];\n    u_int        cur_noise_sample;\n    uint8_t        noise_ref;\n    uint32_t    energy_samples[10];\n    u_int        cur_energy_sample;\n    uint32_t    energy_cck;\n};\n\nstruct iwn_calib_info {\n    uint8_t        *buf;\n    u_int        len;\n};\n\nstruct iwn_fw_part {\n    const uint8_t    *text;\n    uint32_t    textsz;\n    const uint8_t    *data;\n    uint32_t    datasz;\n};\n\nstruct iwn_fw_info {\n    u_char            *data;\n    size_t            size;\n    struct iwn_fw_part    init;\n    struct iwn_fw_part    main;\n    struct iwn_fw_part    boot;\n};\n\nstruct iwn_ops {\n    int        (*load_firmware)(struct iwn_softc *);\n    void        (*read_eeprom)(struct iwn_softc *);\n    int        (*post_alive)(struct iwn_softc *);\n    int        (*nic_config)(struct iwn_softc *);\n    void        (*reset_sched)(struct iwn_softc *, int, int);\n    void        (*update_sched)(struct iwn_softc *, int, int, uint8_t,\n                uint16_t);\n    void        (*update_rxon)(struct iwn_softc *);\n    int        (*get_temperature)(struct iwn_softc *);\n    int        (*get_rssi)(const struct iwn_rx_stat *);\n    int        (*set_txpower)(struct iwn_softc *, int);\n    int        (*init_gains)(struct iwn_softc *);\n    int        (*set_gains)(struct iwn_softc *);\n    int        (*add_node)(struct iwn_softc *, struct iwn_node_info *,\n                int);\n    void        (*tx_done)(struct iwn_softc *, struct iwn_rx_desc *,\n                struct iwn_rx_data *);\n    void        (*ampdu_tx_start)(struct iwn_softc *,\n                struct ieee80211_node *, uint8_t, uint16_t);\n    void        (*ampdu_tx_stop)(struct iwn_softc *, uint8_t,\n                uint16_t);\n};\n\nstruct iwn_tx_ba {\n    struct iwn_node *    wn;\n};\n\nstruct iwn_softc {\n    struct device        sc_dev;\n\n    struct ieee80211com    sc_ic;\n    int            (*sc_newstate)(struct ieee80211com *,\n                    enum ieee80211_state, int);\n    \n    pci_intr_handle_t ih;\n\n    struct ieee80211_amrr    amrr;\n    uint8_t            fixed_ridx;\n\n    bus_dma_tag_t        sc_dmat;\n\n//    struct rwlock        sc_rwlock;\n    u_int            sc_flags;\n#define IWN_FLAG_HAS_5GHZ    (1 << 0)\n#define IWN_FLAG_HAS_OTPROM    (1 << 1)\n#define IWN_FLAG_CALIB_DONE    (1 << 2)\n#define IWN_FLAG_USE_ICT    (1 << 3)\n#define IWN_FLAG_INTERNAL_PA    (1 << 4)\n#define IWN_FLAG_HAS_11N    (1 << 6)\n#define IWN_FLAG_ENH_SENS    (1 << 7)\n#define IWN_FLAG_ADV_BT_COEX    (1 << 8)\n#define IWN_FLAG_BGSCAN        (1 << 9)\n#define IWN_FLAG_SCANNING    (1 << 10)\n\n    uint8_t         hw_type;\n\n    struct iwn_ops        ops;\n    const char        *fwname;\n    const struct iwn_sensitivity_limits\n                *limits;\n    int            ntxqs;\n    int            first_agg_txq;\n    int            agg_queue_mask;\n    int            ndmachnls;\n    uint8_t            broadcast_id;\n    int            rxonsz;\n    int            schedsz;\n    uint32_t        fw_text_maxsz;\n    uint32_t        fw_data_maxsz;\n    uint32_t        fwsz;\n    bus_size_t        sched_txfact_addr;\n\n    /* TX scheduler rings. */\n    struct iwn_dma_info    sched_dma;\n    uint16_t        *sched;\n    uint32_t        sched_base;\n\n    /* \"Keep Warm\" page. */\n    struct iwn_dma_info    kw_dma;\n\n    /* Firmware DMA transfer. */\n    struct iwn_dma_info    fw_dma;\n\n    /* ICT table. */\n    struct iwn_dma_info    ict_dma;\n    uint32_t        *ict;\n    int            ict_cur;\n\n    /* TX/RX rings. */\n    struct iwn_tx_ring    txq[IWN5000_NTXQUEUES];\n    struct iwn_rx_ring    rxq;\n\n    bus_space_tag_t        sc_st;\n    bus_space_handle_t    sc_sh;\n    IOInterruptEventSource *sc_ih;\n    pci_chipset_tag_t    sc_pct;\n    pcitag_t        sc_pcitag;\n    bus_size_t        sc_sz;\n    int            sc_cap_off;    /* PCIe Capabilities. */\n\n    CTimeout *     calib_to;\n    int            calib_cnt;\n    struct iwn_calib_state    calib;\n\n    struct task        init_task;\n\n    struct iwn_fw_info    fw;\n    struct iwn_calib_info    calibcmd[5];\n    uint32_t        errptr;\n\n    uint8_t            bss_node_addr[IEEE80211_ADDR_LEN];\n\n    struct iwn_rx_stat    last_rx_stat;\n    int            last_rx_valid;\n#define IWN_LAST_RX_VALID    0x01\n#define IWN_LAST_RX_AMPDU    0x02\n    struct iwn_ucode_info    ucode_info;\n    struct iwn_rxon        rxon;\n    uint32_t        rx_stats_flags;\n    uint32_t        rawtemp;\n    int            temp;\n    int            noise;\n    uint32_t        qfullmsk;\n\n    uint32_t        prom_base;\n    struct iwn4965_eeprom_band\n                bands[IWN_NBANDS];\n    uint16_t        rfcfg;\n    uint8_t            calib_ver;\n    char            eeprom_domain[4];\n    uint32_t        eeprom_crystal;\n    int16_t            eeprom_temp;\n    int16_t            eeprom_voltage;\n    int16_t            eeprom_rawtemp;\n    int8_t            maxpwr2GHz;\n    int8_t            maxpwr5GHz;\n    int8_t            maxpwr[IEEE80211_CHAN_MAX];\n    int8_t            maxpwr40[IEEE80211_CHAN_MAX];\n    int8_t            enh_maxpwr[35];\n\n    uint8_t            reset_noise_gain;\n    uint8_t            noise_gain;\n\n    uint32_t        tlv_feature_flags;\n\n    int32_t            temp_off;\n    uint32_t        int_mask;\n    uint8_t            ntxchains;\n    uint8_t            nrxchains;\n    uint8_t            txchainmask;\n    uint8_t            rxchainmask;\n    uint8_t            chainmask;\n\n    int            sc_tx_timer;\n\n    struct iwn_tx_ba    sc_tx_ba[IEEE80211_NUM_TID];\n\n#if NBPFILTER > 0\n    caddr_t            sc_drvbpf;\n\n    union {\n        struct iwn_rx_radiotap_header th;\n        uint8_t    pad[IEEE80211_RADIOTAP_HDRLEN];\n    } sc_rxtapu;\n#define sc_rxtap    sc_rxtapu.th\n    int            sc_rxtap_len;\n\n    union {\n        struct iwn_tx_radiotap_header th;\n        uint8_t    pad[IEEE80211_RADIOTAP_HDRLEN];\n    } sc_txtapu;\n#define sc_txtap    sc_txtapu.th\n    int            sc_txtap_len;\n#endif\n};\n"
  },
  {
    "path": "itlwm/hal_iwx/ItlIwx.cpp",
    "content": "/*\n * Copyright (C) 2020  钟先耀\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n */\n/*    $OpenBSD: if_iwx.c,v 1.45 2020/10/11 07:05:28 mpi Exp $    */\n\n/*\n * Copyright (c) 2014, 2016 genua gmbh <info@genua.de>\n *   Author: Stefan Sperling <stsp@openbsd.org>\n * Copyright (c) 2014 Fixup Software Ltd.\n * Copyright (c) 2017, 2019, 2020 Stefan Sperling <stsp@openbsd.org>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n/*-\n * Based on BSD-licensed source modules in the Linux iwlwifi driver,\n * which were used as the reference documentation for this implementation.\n *\n ******************************************************************************\n *\n * This file is provided under a dual BSD/GPLv2 license.  When using or\n * redistributing this file, you may do so under either license.\n *\n * GPL LICENSE SUMMARY\n *\n * Copyright(c) 2017 Intel Deutschland GmbH\n * Copyright(c) 2018 - 2019 Intel Corporation\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of version 2 of the GNU General Public License as\n * published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful, but\n * WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * General Public License for more details.\n *\n * BSD LICENSE\n *\n * Copyright(c) 2017 Intel Deutschland GmbH\n * Copyright(c) 2018 - 2019 Intel Corporation\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in\n *    the documentation and/or other materials provided with the\n *    distribution.\n *  * Neither the name Intel Corporation nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n *****************************************************************************\n */\n\n/*-\n * Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n#include \"ItlIwx.hpp\"\n#include <linux/types.h>\n#include <linux/kernel.h>\n#include <FwData.h>\n#include <crypto/sha1.h>\n\n#include <IOKit/IOInterruptController.h>\n#include <IOKit/IOCommandGate.h>\n#include <IOKit/network/IONetworkMedium.h>\n#include <net/ethernet.h>\n\n#include <sys/_task.h>\n#include <sys/pcireg.h>\n#include <net80211/ieee80211_priv.h>\n\n#define super ItlHalService\nOSDefineMetaClassAndStructors(ItlIwx, ItlHalService)\n\n#define DEVNAME(_s)    ((_s)->sc_dev.dv_xname)\n\n#define IC2IFP(_ic_) (&(_ic_)->ic_if)\n\n#define IWX_DEBUG\n\n#ifdef IWX_DEBUG\n#define DPRINTF(x)    do { if (iwx_debug > 0) XYLog x; } while (0)\n#define DPRINTFN(n, x)    do { if (iwx_debug >= (n)) XYLog x; } while (0)\nint iwx_debug = 1;\n#else\n#define DPRINTF(x)    do { ; } while (0)\n#define DPRINTFN(n, x)    do { ; } while (0)\n#endif\n\nbool ItlIwx::attach(IOPCIDevice *device)\n{\n    pci.pa_tag = device;\n    pci.workloop = getMainWorkLoop();\n    if (!iwx_attach(&com, &pci)) {\n        detach(device);\n        releaseAll();\n        return false;\n    }\n    return true;\n}\n\nvoid ItlIwx::\ndetach(IOPCIDevice *device)\n{\n    struct _ifnet *ifp = &com.sc_ic.ic_ac.ac_if;\n    struct iwx_softc *sc = &com;\n    \n    for (int txq_i = 0; txq_i < nitems(sc->txq); txq_i++)\n        iwx_free_tx_ring(sc, &sc->txq[txq_i]);\n    iwx_free_rx_ring(sc, &sc->rxq);\n    iwx_dma_contig_free(&sc->ict_dma);\n    iwx_dma_contig_free(&com.ctxt_info_dma);\n    ieee80211_ifdetach(ifp);\n    taskq_destroy(systq);\n    taskq_destroy(com.sc_nswq);\n    releaseAll();\n}\n\nvoid ItlIwx::\nreleaseAll()\n{\n    pci_intr_handle *intrHandler = com.ih;\n    \n    if (intrHandler) {\n        if (intrHandler->intr && intrHandler->workloop) {\n//            intrHandler->intr->disable();\n            intrHandler->workloop->removeEventSource(intrHandler->intr);\n            intrHandler->intr->release();\n        }\n        intrHandler->intr = NULL;\n        intrHandler->workloop = NULL;\n        intrHandler->arg = NULL;\n        intrHandler->dev = NULL;\n        intrHandler->func = NULL;\n        intrHandler->release();\n        com.ih = NULL;\n    }\n    pci.pa_tag = NULL;\n    pci.workloop = NULL;\n}\n\nvoid ItlIwx::free()\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    super::free();\n}\n\nItlDriverInfo *ItlIwx::\ngetDriverInfo()\n{\n    return this;\n}\n\nItlDriverController *ItlIwx::\ngetDriverController()\n{\n    return this;\n}\n\nIOReturn ItlIwx::enable(IONetworkInterface *netif)\n{\n    XYLog(\"%s\\n\", __PRETTY_FUNCTION__);\n    struct _ifnet *ifp = &com.sc_ic.ic_ac.ac_if;\n    if (ifp->if_flags & IFF_UP) {\n        XYLog(\"%s already in activating state\\n\", __FUNCTION__);\n        return kIOReturnSuccess;\n    }\n    ifp->if_flags |= IFF_UP;\n    iwx_activate(&com, DVACT_RESUME);\n    iwx_activate(&com, DVACT_WAKEUP);\n    return kIOReturnSuccess;\n}\n\nIOReturn ItlIwx::disable(IONetworkInterface *netif)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct _ifnet *ifp = &com.sc_ic.ic_ac.ac_if;\n    if (!(ifp->if_flags & IFF_UP)) {\n        XYLog(\"%s already in diactivating state\\n\", __FUNCTION__);\n        return kIOReturnSuccess;\n    }\n    ifp->if_flags &= ~IFF_UP;\n    iwx_activate(&com, DVACT_QUIESCE);\n    return kIOReturnSuccess;\n}\n\nvoid ItlIwx::\nclearScanningFlags()\n{\n    com.sc_flags &= ~(IWX_FLAG_SCANNING | IWX_FLAG_BGSCAN);\n}\n\nIOReturn ItlIwx::\nsetMulticastList(IOEthernetAddress *addr, int count)\n{\n    struct ieee80211com *ic = &com.sc_ic;\n    struct iwx_mcast_filter_cmd *cmd;\n    int len;\n    uint8_t addr_count;\n    int err;\n    \n    if (ic->ic_state != IEEE80211_S_RUN || ic->ic_bss == NULL)\n        return kIOReturnError;\n    addr_count = count;\n    if (count > IWX_MAX_MCAST_FILTERING_ADDRESSES)\n        addr_count = 0;\n    if (addr == NULL)\n        addr_count = 0;\n    len = roundup(sizeof(struct iwx_mcast_filter_cmd) + addr_count * ETHER_ADDR_LEN, 4);\n    XYLog(\"%s multicast count=%d bssid=%s\\n\", __FUNCTION__, count, ether_sprintf(ic->ic_bss->ni_bssid));\n    cmd = (struct iwx_mcast_filter_cmd *)malloc(len, 0, 0);\n    if (!cmd)\n        return kIOReturnError;\n    cmd->pass_all = addr_count == 0;\n    cmd->count = addr_count;\n    cmd->port_id = 0;\n    IEEE80211_ADDR_COPY(cmd->bssid, ic->ic_bss->ni_bssid);\n    if (addr_count > 0)\n        memcpy(cmd->addr_list,\n               addr->bytes, ETHER_ADDR_LEN * cmd->count);\n    err = iwx_send_cmd_pdu(&com, IWX_MCAST_FILTER_CMD, IWX_CMD_ASYNC, len,\n                     cmd);\n    ::free(cmd);\n    return err ? kIOReturnError : kIOReturnSuccess;\n}\n\nconst char *ItlIwx::\ngetFirmwareVersion()\n{\n    return com.sc_fwver;\n}\n\nconst char *ItlIwx::\ngetFirmwareName()\n{\n    return com.sc_fwname;\n}\n\nUInt32 ItlIwx::\nsupportedFeatures()\n{\n    return kIONetworkFeatureMultiPages;\n}\n\nconst char *ItlIwx::\ngetFirmwareCountryCode()\n{\n    return com.sc_fw_mcc;\n}\n\nuint32_t ItlIwx::\ngetTxQueueSize()\n{\n    return com.sc_device_family >= IWX_DEVICE_FAMILY_AX210 ? IWX_TFD_QUEUE_SIZE_MAX_GEN3 : IWX_DEFAULT_QUEUE_SIZE;\n}\n\nint16_t ItlIwx::\ngetBSSNoise()\n{\n    return com.sc_noise;\n}\n\nbool ItlIwx::\nis5GBandSupport()\n{\n    return com.sc_nvm.sku_cap_band_52GHz_enable;\n}\n\nint ItlIwx::\ngetTxNSS()\n{\n    return iwx_mimo_enabled(&com) && \n    (com.sc_ic.ic_bss != NULL && com.sc_ic.ic_bss->ni_rx_nss > 1) ? 2 : 1;\n}\n\nstruct ieee80211com *ItlIwx::\nget80211Controller()\n{\n    return &com.sc_ic;\n}\n\n#define MUL_NO_OVERFLOW    (1UL << (sizeof(size_t) * 4))\n\n#define    M_CANFAIL    0x0004\nvoid *ItlIwx::\nmallocarray(size_t nmemb, size_t size, int type, int flags)\n{\n    if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&\n        nmemb > 0 && SIZE_MAX / nmemb < size) {\n        if (flags & M_CANFAIL)\n            return (NULL);\n        panic(\"mallocarray: overflow %zu * %zu\", nmemb, size);\n    }\n    return (malloc(size * nmemb, type, flags));\n}\n\nconst uint8_t iwx_nvm_channels_8000[] = {\n    /* 2.4 GHz */\n    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,\n    /* 5 GHz */\n    36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92,\n    96, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144,\n    149, 153, 157, 161, 165, 169, 173, 177, 181\n};\n\nstatic const uint8_t iwx_nvm_channels_uhb[] = {\n   /* 2.4 GHz */\n   1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,\n   /* 5 GHz */\n   36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92,\n   96, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144,\n   149, 153, 157, 161, 165, 169, 173, 177, 181,\n#ifdef notyet\n   /* 6-7 GHz */\n   1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69,\n   73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129,\n   133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185,\n   189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233\n#endif\n};\n\n#define IWX_NUM_2GHZ_CHANNELS    14\n#define IWX_FIRST_2GHZ_HT_MINUS        5\n#define IWX_LAST_2GHZ_HT_PLUS        9\n\nconst struct iwx_rate {\n    uint16_t rate;\n    uint8_t plcp;\n    uint8_t ht_plcp;\n} iwx_rates[] = {\n    /* Legacy */        /* HT */\n    {   2,    IWX_RATE_1M_PLCP,    IWX_RATE_HT_SISO_MCS_INV_PLCP  },\n    {   4,    IWX_RATE_2M_PLCP,    IWX_RATE_HT_SISO_MCS_INV_PLCP },\n    {  11,    IWX_RATE_5M_PLCP,    IWX_RATE_HT_SISO_MCS_INV_PLCP  },\n    {  22,    IWX_RATE_11M_PLCP,    IWX_RATE_HT_SISO_MCS_INV_PLCP },\n    {  12,    IWX_RATE_6M_PLCP,    IWX_RATE_HT_SISO_MCS_0_PLCP },\n    {  18,    IWX_RATE_9M_PLCP,    IWX_RATE_HT_SISO_MCS_INV_PLCP  },\n    {  24,    IWX_RATE_12M_PLCP,    IWX_RATE_HT_SISO_MCS_1_PLCP },\n    {  26,    IWX_RATE_12M_PLCP,    IWX_RATE_HT_MIMO2_MCS_8_PLCP },\n    {  36,    IWX_RATE_18M_PLCP,    IWX_RATE_HT_SISO_MCS_2_PLCP },\n    {  48,    IWX_RATE_24M_PLCP,    IWX_RATE_HT_SISO_MCS_3_PLCP },\n    {  52,    IWX_RATE_24M_PLCP,    IWX_RATE_HT_MIMO2_MCS_9_PLCP },\n    {  72,    IWX_RATE_36M_PLCP,    IWX_RATE_HT_SISO_MCS_4_PLCP },\n    {  78,    IWX_RATE_36M_PLCP,    IWX_RATE_HT_MIMO2_MCS_10_PLCP },\n    {  96,    IWX_RATE_48M_PLCP,    IWX_RATE_HT_SISO_MCS_5_PLCP },\n    { 104,    IWX_RATE_48M_PLCP,    IWX_RATE_HT_MIMO2_MCS_11_PLCP },\n    { 108,    IWX_RATE_54M_PLCP,    IWX_RATE_HT_SISO_MCS_6_PLCP },\n    { 128,    IWX_RATE_54M_PLCP,    IWX_RATE_HT_SISO_MCS_7_PLCP },\n    { 156,    IWX_RATE_54M_PLCP,    IWX_RATE_HT_MIMO2_MCS_12_PLCP },\n    { 208,    IWX_RATE_54M_PLCP,    IWX_RATE_HT_MIMO2_MCS_13_PLCP },\n    { 234,    IWX_RATE_54M_PLCP,    IWX_RATE_HT_MIMO2_MCS_14_PLCP },\n    { 260,    IWX_RATE_54M_PLCP,    IWX_RATE_HT_MIMO2_MCS_15_PLCP },\n};\n#define IWX_RIDX_CCK    0\n#define IWX_RIDX_OFDM    4\n#define IWX_RIDX_MAX    (nitems(iwx_rates)-1)\n#define IWX_RIDX_IS_CCK(_i_) ((_i_) < IWX_RIDX_OFDM)\n#define IWX_RIDX_IS_OFDM(_i_) ((_i_) >= IWX_RIDX_OFDM)\n#define IWX_RVAL_IS_OFDM(_i_) ((_i_) >= 12 && (_i_) != 22)\n\n/* Convert an MCS index into an iwx_rates[] index. */\nconst int iwx_mcs2ridx[] = {\n    IWX_RATE_MCS_0_INDEX,\n    IWX_RATE_MCS_1_INDEX,\n    IWX_RATE_MCS_2_INDEX,\n    IWX_RATE_MCS_3_INDEX,\n    IWX_RATE_MCS_4_INDEX,\n    IWX_RATE_MCS_5_INDEX,\n    IWX_RATE_MCS_6_INDEX,\n    IWX_RATE_MCS_7_INDEX,\n    IWX_RATE_MCS_8_INDEX,\n    IWX_RATE_MCS_9_INDEX,\n    IWX_RATE_MCS_10_INDEX,\n    IWX_RATE_MCS_11_INDEX,\n    IWX_RATE_MCS_12_INDEX,\n    IWX_RATE_MCS_13_INDEX,\n    IWX_RATE_MCS_14_INDEX,\n    IWX_RATE_MCS_15_INDEX,\n};\n#define IWX_LAST_HE_RATE IWX_RATE_MCS_11_INDEX\n#define IWL_RATE_COUNT IWX_LAST_HE_RATE\n#define IWX_MAX_MCS_DISPLAY_SIZE    12\n\n#define IWL_RATE_60M_PLCP 3\n\nenum {\n    IWX_RATE_INVM_INDEX = IWX_RATE_COUNT,\n    IWX_RATE_INVALID = IWX_RATE_COUNT,\n};\n\nstruct iwx_rate_mcs_info {\n    char    mbps[IWX_MAX_MCS_DISPLAY_SIZE];\n    char    mcs[IWX_MAX_MCS_DISPLAY_SIZE];\n};\n\n/* mbps, mcs */\nstatic const struct iwx_rate_mcs_info iwx_rate_mcs[IWX_RATE_COUNT] = {\n    {  \"1\", \"BPSK DSSS\"},\n    {  \"2\", \"QPSK DSSS\"},\n    {\"5.5\", \"BPSK CCK\"},\n    { \"11\", \"QPSK CCK\"},\n    {  \"6\", \"BPSK 1/2\"},\n    {  \"9\", \"BPSK 1/2\"},\n    { \"12\", \"QPSK 1/2\"},\n    { \"18\", \"QPSK 3/4\"},\n    { \"24\", \"16QAM 1/2\"},\n    { \"36\", \"16QAM 3/4\"},\n    { \"48\", \"64QAM 2/3\"},\n    { \"54\", \"64QAM 3/4\"},\n    { \"60\", \"64QAM 5/6\"},\n};\n\n#define IWX_MCS_INDEX_PER_STREAM    (8)\n\nstatic const char *iwx_rs_pretty_ant(u8 ant)\n{\n    static const char * const ant_name[] = {\n        [IWX_ANT_NONE] = \"None\",\n        [IWX_ANT_A]    = \"A\",\n        [IWX_ANT_B]    = \"B\",\n        [IWX_ANT_AB]   = \"AB\",\n    };\n\n    if (ant > ARRAY_SIZE(ant_name))\n        return \"UNKNOWN\";\n\n    return ant_name[ant];\n}\n\nstatic const char *iwx_rs_pretty_bw(u8 bw)\n{\n    static const char * const pretty_bw[] = {\n        \"20Mhz\",\n        \"40Mhz\",\n        \"80Mhz\",\n        \"160 Mhz\",\n        \"320Mhz\",\n    };\n\n    if (bw > ARRAY_SIZE(pretty_bw))\n        return \"UNKNOWN\";\n\n    return pretty_bw[bw];\n}\n\nstatic uint8_t iwx_rs_extract_rate(uint32_t rate_n_flags)\n{\n    /* also works for HT because bits 7:6 are zero there */\n    return (uint8_t)(rate_n_flags & IWX_RATE_LEGACY_RATE_MSK_V1);\n}\n\nstatic int iwx_hwrate_to_plcp_idx(uint32_t rate_n_flags)\n{\n    int idx = 0;\n\n    if (rate_n_flags & IWX_RATE_MCS_HT_MSK_V1) {\n        idx = rate_n_flags & IWX_RATE_HT_MCS_RATE_CODE_MSK_V1;\n        idx += IWX_RATE_MCS_0_INDEX;\n\n        /* skip 9M not supported in HT*/\n        if (idx >= IWX_RATE_9M_INDEX)\n            idx += 1;\n        if ((idx >= IWX_FIRST_HT_RATE) && (idx <= IWX_LAST_HT_RATE))\n            return idx;\n    } else if (rate_n_flags & IWX_RATE_MCS_VHT_MSK_V1 ||\n           rate_n_flags & IWX_RATE_MCS_HE_MSK_V1) {\n        idx = rate_n_flags & IWX_RATE_VHT_MCS_RATE_CODE_MSK;\n        idx += IWX_RATE_MCS_0_INDEX;\n\n        /* skip 9M not supported in VHT*/\n        if (idx >= IWX_RATE_9M_INDEX)\n            idx++;\n        if ((idx >= IWX_FIRST_VHT_RATE) && (idx <= IWX_LAST_VHT_RATE))\n            return idx;\n        if ((rate_n_flags & IWX_RATE_MCS_HE_MSK_V1) &&\n            (idx <= IWX_LAST_HE_RATE))\n            return idx;\n    } else {\n        /* legacy rate format, search for match in table */\n\n        uint8_t legacy_rate = iwx_rs_extract_rate(rate_n_flags);\n        for (idx = 0; idx < ARRAY_SIZE(iwx_rates); idx++)\n            if (iwx_rates[idx].plcp == legacy_rate)\n                return idx;\n    }\n\n    return IWX_RATE_INVALID;\n}\n\nstatic int iwx_rs_pretty_print_rate_v1(char *buf, int bufsz, const u32 rate)\n{\n    char *type;\n    uint8_t mcs = 0, nss = 0;\n    uint8_t ant = (rate & IWX_RATE_MCS_ANT_AB_MSK) >> IWX_RATE_MCS_ANT_POS;\n    uint32_t bw = (rate & IWX_RATE_MCS_CHAN_WIDTH_MSK_V1) >>\n        IWX_RATE_MCS_CHAN_WIDTH_POS;\n\n    if (!(rate & IWX_RATE_MCS_HT_MSK_V1) &&\n        !(rate & IWX_RATE_MCS_VHT_MSK_V1) &&\n        !(rate & IWX_RATE_MCS_HE_MSK_V1)) {\n        int index = iwx_hwrate_to_plcp_idx(rate);\n\n        return snprintf(buf, bufsz, \"Legacy | ANT: %s Rate: %s Mbps\",\n                 iwx_rs_pretty_ant(ant),\n                 index == IWX_RATE_INVALID ? \"BAD\" :\n                 iwx_rate_mcs[index].mbps);\n    }\n\n    if (rate & IWX_RATE_MCS_VHT_MSK_V1) {\n        type = \"VHT\";\n        mcs = rate & IWX_RATE_VHT_MCS_RATE_CODE_MSK;\n        nss = ((rate & IWX_RATE_VHT_MCS_NSS_MSK)\n               >> IWX_RATE_VHT_MCS_NSS_POS) + 1;\n    } else if (rate & IWX_RATE_MCS_HT_MSK_V1) {\n        type = \"HT\";\n        mcs = rate & IWX_RATE_HT_MCS_INDEX_MSK_V1;\n        nss = ((rate & IWX_RATE_HT_MCS_NSS_MSK_V1)\n               >> IWX_RATE_HT_MCS_NSS_POS_V1) + 1;\n    } else if (rate & IWX_RATE_MCS_HE_MSK_V1) {\n        type = \"HE\";\n        mcs = rate & IWX_RATE_VHT_MCS_RATE_CODE_MSK;\n        nss = ((rate & IWX_RATE_VHT_MCS_NSS_MSK)\n               >> IWX_RATE_VHT_MCS_NSS_POS) + 1;\n    } else {\n        type = \"Unknown\"; /* shouldn't happen */\n    }\n\n    return snprintf(buf, bufsz,\n             \"0x%x: %s | ANT: %s BW: %s MCS: %d NSS: %d %s%s%s%s%s\",\n             rate, type, iwx_rs_pretty_ant(ant), iwx_rs_pretty_bw(bw), mcs, nss,\n             (rate & IWX_RATE_MCS_SGI_MSK_V1) ? \"SGI \" : \"NGI \",\n             (rate & IWX_RATE_MCS_STBC_MSK) ? \"STBC \" : \"\",\n             (rate & IWX_RATE_MCS_LDPC_MSK_V1) ? \"LDPC \" : \"\",\n             (rate & IWX_RATE_HE_DUAL_CARRIER_MODE_MSK) ? \"DCM \" : \"\",\n             (rate & IWX_RATE_MCS_BF_MSK) ? \"BF \" : \"\");\n}\n\nstatic bool iwx_he_is_sgi(u32 rate_n_flags)\n{\n    u32 type = rate_n_flags & IWX_RATE_MCS_HE_TYPE_MSK;\n    u32 ltf_gi = rate_n_flags & IWX_RATE_MCS_HE_GI_LTF_MSK;\n\n    if (type == IWX_RATE_MCS_HE_TYPE_SU ||\n        type == IWX_RATE_MCS_HE_TYPE_EXT_SU)\n        return ltf_gi == IWX_RATE_MCS_HE_SU_4_LTF_08_GI;\n    return false;\n}\n\nstatic int iwx_rs_pretty_print_rate(char *buf, int bufsz, const uint32_t rate)\n{\n    char *type;\n    u8 mcs = 0, nss = 0;\n    u8 ant = (rate & IWX_RATE_MCS_ANT_AB_MSK) >> IWX_RATE_MCS_ANT_POS;\n    u32 bw = (rate & IWX_RATE_MCS_CHAN_WIDTH_MSK) >>\n        IWX_RATE_MCS_CHAN_WIDTH_POS;\n    u32 format = rate & IWX_RATE_MCS_MOD_TYPE_MSK;\n    bool sgi;\n\n    if (format == IWX_RATE_MCS_CCK_MSK ||\n        format == IWX_RATE_MCS_LEGACY_OFDM_MSK) {\n        int legacy_rate = rate & IWX_RATE_LEGACY_RATE_MSK;\n        int index = format == IWX_RATE_MCS_CCK_MSK ?\n            legacy_rate :\n            legacy_rate + IWX_FIRST_OFDM_RATE;\n\n        return snprintf(buf, bufsz, \"Legacy | ANT: %s Rate: %s Mbps\",\n                 iwx_rs_pretty_ant(ant),\n                 index == IWX_RATE_INVALID ? \"BAD\" :\n                 iwx_rate_mcs[index].mbps);\n    }\n\n    if (format ==  IWX_RATE_MCS_VHT_MSK)\n        type = \"VHT\";\n    else if (format == IWX_RATE_MCS_HT_MSK)\n        type = \"HT\";\n    else if (format == IWX_RATE_MCS_HE_MSK)\n        type = \"HE\";\n    else if (format == IWX_RATE_MCS_EHT_MSK)\n        type = \"EHT\";\n    else\n        type = \"Unknown\"; /* shouldn't happen */\n\n    mcs = format == IWX_RATE_MCS_HT_MSK ?\n        IWX_RATE_HT_MCS_INDEX(rate) :\n        rate & IWX_RATE_MCS_CODE_MSK;\n    nss = ((rate & IWX_RATE_MCS_NSS_MSK)\n           >> IWX_RATE_MCS_NSS_POS) + 1;\n    sgi = format == IWX_RATE_MCS_HE_MSK ?\n        iwx_he_is_sgi(rate) :\n        rate & IWX_RATE_MCS_SGI_MSK;\n\n    return snprintf(buf, bufsz,\n             \"0x%x: %s | ANT: %s BW: %s MCS: %d NSS: %d %s%s%s%s%s\",\n             rate, type, iwx_rs_pretty_ant(ant), iwx_rs_pretty_bw(bw), mcs, nss,\n             (sgi) ? \"SGI \" : \"NGI \",\n             (rate & IWX_RATE_MCS_STBC_MSK) ? \"STBC \" : \"\",\n             (rate & IWX_RATE_MCS_LDPC_MSK) ? \"LDPC \" : \"\",\n             (rate & IWX_RATE_HE_DUAL_CARRIER_MODE_MSK) ? \"DCM \" : \"\",\n             (rate & IWX_RATE_MCS_BF_MSK) ? \"BF \" : \"\");\n}\n\n#if NBPFILTER > 0\nvoid    iwx_radiotap_attach(struct iwx_softc *);\n#endif\n\nuint8_t ItlIwx::\niwx_lookup_cmd_ver(struct iwx_softc *sc, uint8_t grp, uint8_t cmd)\n{\n    const struct iwx_fw_cmd_version *entry;\n    int i;\n    \n    for (i = 0; i < sc->n_cmd_versions; i++) {\n        entry = &sc->cmd_versions[i];\n        if (entry->group == grp && entry->cmd == cmd)\n            return entry->cmd_ver;\n    }\n    \n    return IWX_FW_CMD_VER_UNKNOWN;\n}\n\nuint8_t ItlIwx::\niwx_lookup_notif_ver(struct iwx_softc *sc, uint8_t grp, uint8_t cmd)\n{\n    const struct iwx_fw_cmd_version *entry;\n    int i;\n    \n    for (i = 0; i < sc->n_cmd_versions; i++) {\n        entry = &sc->cmd_versions[i];\n        if (entry->group == grp && entry->cmd == cmd)\n            return entry->notif_ver;\n    }\n    \n    return IWX_FW_CMD_VER_UNKNOWN;\n}\n\nuint32_t ItlIwx::\niwx_lmac_id(struct iwx_softc *sc, ieee80211_channel *chan)\n{\n    if (!isset(sc->sc_enabled_capa, IWX_UCODE_TLV_CAPA_CDB_SUPPORT) ||\n        IEEE80211_IS_CHAN_2GHZ(chan))\n        return IWX_LMAC_24G_INDEX;\n    return IWX_LMAC_5G_INDEX;\n}\n\nint ItlIwx::\niwx_store_cscheme(struct iwx_softc *sc, uint8_t *data, size_t dlen)\n{\n    struct iwx_fw_cscheme_list *l = (struct iwx_fw_cscheme_list *)data;\n    \n    if (dlen < sizeof(*l) ||\n        dlen < sizeof(l->size) + l->size * sizeof(*l->cs))\n        return EINVAL;\n    \n    /* we don't actually store anything for now, always use s/w crypto */\n    \n    return 0;\n}\n\nint ItlIwx::\niwx_ctxt_info_alloc_dma(struct iwx_softc *sc,\n                        const struct iwx_fw_onesect *sec, struct iwx_dma_info *dram)\n{\n    int err = iwx_dma_contig_alloc(sc->sc_dmat, dram, sec->fws_len, 0);\n    if (err) {\n        XYLog(\"%s: could not allocate context info DMA memory\\n\",\n              DEVNAME(sc));\n        return err;\n    }\n    \n    memcpy(dram->vaddr, sec->fws_data, sec->fws_len);\n    \n    return 0;\n}\n\nvoid ItlIwx::\niwx_ctxt_info_free_paging(struct iwx_softc *sc)\n{\n    struct iwx_self_init_dram *dram = &sc->init_dram;\n    int i;\n    \n    if (!dram->paging)\n        return;\n    \n    /* free paging*/\n    for (i = 0; i < dram->paging_cnt; i++)\n        iwx_dma_contig_free(&dram->paging[i]);\n    \n    IOFree(dram->paging, dram->paging_cnt * sizeof(*dram->paging));\n    dram->paging_cnt = 0;\n    dram->paging = NULL;\n}\n\nint ItlIwx::\niwx_get_num_sections(const struct iwx_fw_sects *fws, int start)\n{\n    int i = 0;\n    \n    while (start < fws->fw_count &&\n           fws->fw_sect[start].fws_devoff != IWX_CPU1_CPU2_SEPARATOR_SECTION &&\n           fws->fw_sect[start].fws_devoff != IWX_PAGING_SEPARATOR_SECTION) {\n        start++;\n        i++;\n    }\n    \n    return i;\n}\n\nint ItlIwx::\niwx_init_fw_sec(struct iwx_softc *sc, const struct iwx_fw_sects *fws,\n                struct iwx_context_info_dram *ctxt_dram)\n{\n    struct iwx_self_init_dram *dram = &sc->init_dram;\n    int i, ret, fw_cnt = 0;\n    \n    KASSERT(dram->paging == NULL, \"dram->paging == NULL\");\n    \n    dram->lmac_cnt = iwx_get_num_sections(fws, 0);\n    /* add 1 due to separator */\n    dram->umac_cnt = iwx_get_num_sections(fws, dram->lmac_cnt + 1);\n    /* add 2 due to separators */\n    dram->paging_cnt = iwx_get_num_sections(fws,\n    dram->lmac_cnt + dram->umac_cnt + 2);\n    \n    dram->fw = (struct iwx_dma_info *)kcalloc(dram->umac_cnt + dram->lmac_cnt, sizeof(*dram->fw));\n    if (!dram->fw) {\n        XYLog(\"%s: could not allocate memory for firmware sections\\n\",\n        DEVNAME(sc));\n        return ENOMEM;\n    }\n    dram->paging = (struct iwx_dma_info *)kcalloc(dram->paging_cnt, sizeof(*dram->paging));\n    if (!dram->paging) {\n        XYLog(\"%s: could not allocate memory for firmware paging\\n\",\n        DEVNAME(sc));\n        return ENOMEM;\n    }\n    \n    /* initialize lmac sections */\n    for (i = 0; i < dram->lmac_cnt; i++) {\n        ret = iwx_ctxt_info_alloc_dma(sc, &fws->fw_sect[i],\n                           &dram->fw[fw_cnt]);\n        if (ret)\n            return ret;\n        ctxt_dram->lmac_img[i] =\n            htole64(dram->fw[fw_cnt].paddr);\n        DPRINTFN(3, (\"%s: firmware LMAC section %d at 0x%llx size %lld\\n\", __func__, i,\n            (unsigned long long)dram->fw[fw_cnt].paddr,\n            (unsigned long long)dram->fw[fw_cnt].size));\n        fw_cnt++;\n    }\n\n    /* initialize umac sections */\n    for (i = 0; i < dram->umac_cnt; i++) {\n        /* access FW with +1 to make up for lmac separator */\n        ret = iwx_ctxt_info_alloc_dma(sc,\n            &fws->fw_sect[fw_cnt + 1], &dram->fw[fw_cnt]);\n        if (ret)\n            return ret;\n        ctxt_dram->umac_img[i] =\n            htole64(dram->fw[fw_cnt].paddr);\n        DPRINTFN(3, (\"%s: firmware UMAC section %d at 0x%llx size %lld\\n\", __func__, i,\n            (unsigned long long)dram->fw[fw_cnt].paddr,\n            (unsigned long long)dram->fw[fw_cnt].size));\n        fw_cnt++;\n    }\n\n    /*\n     * Initialize paging.\n     * Paging memory isn't stored in dram->fw as the umac and lmac - it is\n     * stored separately.\n     * This is since the timing of its release is different -\n     * while fw memory can be released on alive, the paging memory can be\n     * freed only when the device goes down.\n     * Given that, the logic here in accessing the fw image is a bit\n     * different - fw_cnt isn't changing so loop counter is added to it.\n     */\n    for (i = 0; i < dram->paging_cnt; i++) {\n        /* access FW with +2 to make up for lmac & umac separators */\n        int fw_idx = fw_cnt + i + 2;\n\n        ret = iwx_ctxt_info_alloc_dma(sc,\n            &fws->fw_sect[fw_idx], &dram->paging[i]);\n        if (ret)\n            return ret;\n\n        ctxt_dram->virtual_img[i] = htole64(dram->paging[i].paddr);\n        DPRINTFN(3, (\"%s: firmware paging section %d at 0x%llx size %lld\\n\", __func__, i,\n            (unsigned long long)dram->paging[i].paddr,\n            (unsigned long long)dram->paging[i].size));\n    }\n\n    return 0;\n}\n\nvoid ItlIwx::\niwx_fw_version_str(char *buf, size_t bufsize,\n                   uint32_t major, uint32_t minor, uint32_t api)\n{\n    /*\n     * Starting with major version 35 the Linux driver prints the minor\n     * version in hexadecimal.\n     */\n    if (major >= 35)\n        snprintf(buf, bufsize, \"%u.%08x.%u\", major, minor, api);\n    else\n        snprintf(buf, bufsize, \"%u.%u.%u\", major, minor, api);\n}\n\nint ItlIwx::\niwx_alloc_fw_monitor_block(struct iwx_softc *sc, uint8_t max_power,\n                           uint8_t min_power)\n{\n    struct iwx_dma_info *fw_mon = &sc->fw_mon;\n    uint32_t size = 0;\n    uint8_t power;\n    int err = 0;\n    \n    if (fw_mon->size)\n        return 0;\n    \n    for (power = max_power; power >= min_power; power--) {\n        size = (1 << power);\n        \n        err = iwx_dma_contig_alloc(sc->sc_dmat, fw_mon, size, 0);\n        if (err)\n            continue;\n        \n        DPRINTF((\"%s: allocated 0x%08x bytes for firmware monitor.\\n\",\n                 DEVNAME(sc), size));\n        break;\n    }\n    \n    if (err) {\n        fw_mon->size = 0;\n        return err;\n    }\n    \n    if (power != max_power)\n        DPRINTF((\"%s: Sorry - debug buffer is only %luK while you requested %luK\\n\",\n                 DEVNAME(sc), (unsigned long)(1 << (power - 10)),\n                 (unsigned long)(1 << (max_power - 10))));\n    \n    return 0;\n}\n\nint ItlIwx::\niwx_alloc_fw_monitor(struct iwx_softc *sc, uint8_t max_power)\n{\n    if (!max_power) {\n        /* default max_power is maximum */\n        max_power = 26;\n    } else {\n        max_power += 11;\n    }\n    \n    if (max_power > 26) {\n        DPRINTF((\"%s: External buffer size for monitor is too big %d, \"\n                 \"check the FW TLV\\n\", DEVNAME(sc), max_power));\n        return 0;\n    }\n    \n    if (sc->fw_mon.size)\n        return 0;\n    \n    return iwx_alloc_fw_monitor_block(sc, max_power, 11);\n}\n\nint ItlIwx::\niwx_apply_debug_destination(struct iwx_softc *sc)\n{\n    struct iwx_fw_dbg_dest_tlv_v1 *dest_v1;\n    int i, err;\n    uint8_t mon_mode, size_power, base_shift, end_shift;\n    uint32_t base_reg, end_reg;\n    \n    dest_v1 = sc->sc_fw.dbg_dest_tlv_v1;\n    mon_mode = dest_v1->monitor_mode;\n    size_power = dest_v1->size_power;\n    base_reg = le32toh(dest_v1->base_reg);\n    end_reg = le32toh(dest_v1->end_reg);\n    base_shift = dest_v1->base_shift;\n    end_shift = dest_v1->end_shift;\n    \n    DPRINTF((\"%s: applying debug destination %d\\n\", DEVNAME(sc), mon_mode));\n    \n    if (mon_mode == EXTERNAL_MODE) {\n        err = iwx_alloc_fw_monitor(sc, size_power);\n        if (err)\n            return err;\n    }\n    \n    if (!iwx_nic_lock(sc))\n        return EBUSY;\n    \n    for (i = 0; i < sc->sc_fw.n_dest_reg; i++) {\n        uint32_t addr, val;\n        uint8_t op;\n        \n        addr = le32toh(dest_v1->reg_ops[i].addr);\n        val = le32toh(dest_v1->reg_ops[i].val);\n        op = dest_v1->reg_ops[i].op;\n        \n        DPRINTF((\"%s: op=%u addr=%u val=%u\\n\", __func__, op, addr, val));\n        switch (op) {\n            case CSR_ASSIGN:\n                IWX_WRITE(sc, addr, val);\n                break;\n            case CSR_SETBIT:\n                IWX_SETBITS(sc, addr, (1 << val));\n                break;\n            case CSR_CLEARBIT:\n                IWX_CLRBITS(sc, addr, (1 << val));\n                break;\n            case PRPH_ASSIGN:\n                iwx_write_prph(sc, addr, val);\n                break;\n            case PRPH_SETBIT:\n                iwx_set_bits_prph(sc, addr, (1 << val));\n                break;\n            case PRPH_CLEARBIT:\n                iwx_clear_bits_prph(sc, addr, (1 << val));\n                break;\n            case PRPH_BLOCKBIT:\n                if (iwx_read_prph(sc, addr) & (1 << val))\n                    goto monitor;\n                break;\n            default:\n                DPRINTF((\"%s: FW debug - unknown OP %d\\n\",\n                         DEVNAME(sc), op));\n                break;\n        }\n    }\n    \nmonitor:\n    if (mon_mode == EXTERNAL_MODE && sc->fw_mon.size) {\n        iwx_write_prph(sc, le32toh(base_reg),\n                       sc->fw_mon.paddr >> base_shift);\n        iwx_write_prph(sc, end_reg,\n                       (sc->fw_mon.paddr + sc->fw_mon.size - 256)\n                       >> end_shift);\n    }\n    \n    iwx_nic_unlock(sc);\n    return 0;\n}\n\nvoid ItlIwx::\niwx_set_ltr(struct iwx_softc *sc)\n{\n    uint32_t ltr_val = IWX_CSR_LTR_LONG_VAL_AD_NO_SNOOP_REQ |\n                    u32_encode_bits(IWX_CSR_LTR_LONG_VAL_AD_SCALE_USEC,\n                    IWX_CSR_LTR_LONG_VAL_AD_NO_SNOOP_SCALE) |\n                    u32_encode_bits(250,\n                    IWX_CSR_LTR_LONG_VAL_AD_NO_SNOOP_VAL) |\n                    IWX_CSR_LTR_LONG_VAL_AD_SNOOP_REQ |\n                    u32_encode_bits(IWX_CSR_LTR_LONG_VAL_AD_SCALE_USEC,\n                    IWX_CSR_LTR_LONG_VAL_AD_SNOOP_SCALE) |\n                    u32_encode_bits(250, IWX_CSR_LTR_LONG_VAL_AD_SNOOP_VAL);\n    \n    /*\n     * To workaround hardware latency issues during the boot process,\n     * initialize the LTR to ~250 usec (see ltr_val above).\n     * The firmware initializes this again later (to a smaller value).\n     */\n    if ((sc->sc_device_family == IWX_DEVICE_FAMILY_AX210 ||\n         sc->sc_device_family == IWX_DEVICE_FAMILY_22000) &&\n        !sc->sc_integrated) {\n        IWX_WRITE(sc, IWX_CSR_LTR_LONG_VAL_AD, ltr_val);\n    } else if (sc->sc_integrated &&\n           sc->sc_device_family == IWX_DEVICE_FAMILY_22000) {\n        if (iwx_nic_lock(sc)) {\n            iwx_write_prph(sc, IWX_HPM_MAC_LTR_CSR, IWX_HPM_MAC_LRT_ENABLE_ALL);\n            iwx_write_prph(sc, IWX_HPM_UMAC_LTR, ltr_val);\n            iwx_nic_unlock(sc);\n        }\n    }\n}\n\nint ItlIwx::\niwx_ctxt_info_init(struct iwx_softc *sc, const struct iwx_fw_sects *fws)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwx_context_info *ctxt_info;\n    struct iwx_context_info_rbd_cfg *rx_cfg;\n    uint32_t control_flags = 0, rb_size;\n    int err;\n    \n    ctxt_info = (struct iwx_context_info *)sc->ctxt_info_dma.vaddr;\n    \n    ctxt_info->version.version = 0;\n    ctxt_info->version.mac_id =\n    htole16((uint16_t)IWX_READ(sc, IWX_CSR_HW_REV));\n    /* size is in DWs */\n    ctxt_info->version.size = htole16(sizeof(*ctxt_info) / 4);\n    \n    rb_size = IWX_CTXT_INFO_RB_SIZE_4K;\n    \n    KASSERT(IWX_RX_QUEUE_CB_SIZE(IWX_MQ_RX_TABLE_SIZE) < 0xF, \"IWX_RX_QUEUE_CB_SIZE(IWX_MQ_RX_TABLE_SIZE) < 0xF\");\n    control_flags = IWX_CTXT_INFO_TFD_FORMAT_LONG |\n    (IWX_RX_QUEUE_CB_SIZE(IWX_MQ_RX_TABLE_SIZE) <<\n     IWX_CTXT_INFO_RB_CB_SIZE_POS) |\n    (rb_size << IWX_CTXT_INFO_RB_SIZE_POS);\n    ctxt_info->control.control_flags = htole32(control_flags);\n    \n    /* initialize RX default queue */\n    rx_cfg = &ctxt_info->rbd_cfg;\n    rx_cfg->free_rbd_addr = htole64(sc->rxq.free_desc_dma.paddr);\n    rx_cfg->used_rbd_addr = htole64(sc->rxq.used_desc_dma.paddr);\n    rx_cfg->status_wr_ptr = htole64(sc->rxq.stat_dma.paddr);\n    \n    /* initialize TX command queue */\n    ctxt_info->hcmd_cfg.cmd_queue_addr =\n    htole64(sc->txq[IWX_DQA_CMD_QUEUE].desc_dma.paddr);\n    ctxt_info->hcmd_cfg.cmd_queue_size =\n    IWX_TFD_QUEUE_CB_SIZE(IWX_CMD_QUEUE_SIZE);\n    \n    /* allocate ucode sections in dram and set addresses */\n    err = iwx_init_fw_sec(sc, fws, &ctxt_info->dram);\n    if (err) {\n        iwx_ctxt_info_free_fw_img(sc);\n        return err;\n    }\n    \n    //zxystd: I don't know if it is necessary, but it is also works without the debug info, comment it to avoid DMA memory leak\n#if 0\n    /* Configure debug, if exists */\n    if (sc->sc_fw.dbg_dest_tlv_v1) {\n        err = iwx_apply_debug_destination(sc);\n        if (err) {\n            iwx_ctxt_info_free_fw_img(sc);\n            return err;\n        }\n    }\n#endif\n    \n    iwx_enable_fwload_interrupt(sc);\n    \n    IWX_WRITE64(sc, IWX_CSR_CTXT_INFO_BA, sc->ctxt_info_dma.paddr);\n    \n    iwx_set_ltr(sc);\n    \n    /* kick FW self load */\n    if (!iwx_nic_lock(sc)) {\n        iwx_ctxt_info_free_fw_img(sc);\n        return EBUSY;\n    }\n    iwx_write_prph(sc, IWX_UREG_CPU_INIT_RUN, 1);\n    iwx_nic_unlock(sc);\n    \n    /* Context info will be released upon alive or failure to get one */\n    \n    return 0;\n}\n\nint ItlIwx::\niwx_ctxt_info_gen3_init(struct iwx_softc *sc, const struct iwx_fw_sects *fws)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwx_context_info_gen3 *ctxt_info_gen3;\n    struct iwx_prph_scratch *prph_scratch;\n    struct iwx_prph_scratch_ctrl_cfg *prph_sc_ctrl;\n    uint32_t control_flags = 0;\n    int err;\n    \n    /* Allocate prph scratch. */\n    err = iwx_dma_contig_alloc(sc->sc_dmat, &sc->prph_scratch_dma,\n                               sizeof(struct iwx_prph_scratch), 0);\n    if (err) {\n        XYLog(\"%s: could not allocate prph scratch\\n\", DEVNAME(sc));\n        return false;\n    }\n    \n    prph_scratch = (struct iwx_prph_scratch *)sc->prph_scratch_dma.vaddr;\n    \n    prph_sc_ctrl = &prph_scratch->ctrl_cfg;\n    prph_sc_ctrl->version.version = 0;\n    prph_sc_ctrl->version.mac_id =\n        htole16((uint16_t)IWX_READ(sc, IWX_CSR_HW_REV));\n    prph_sc_ctrl->version.size = htole16(sizeof(*prph_scratch) / 4);\n    \n    control_flags = IWX_PRPH_SCRATCH_RB_SIZE_4K;\n    control_flags |= IWX_PRPH_SCRATCH_MTR_MODE;\n    control_flags |= IWX_PRPH_MTR_FORMAT_256B & IWX_PRPH_SCRATCH_MTR_FORMAT;\n    \n    /* initialize RX default queue */\n    prph_sc_ctrl->rbd_cfg.free_rbd_addr =\n        htole64(sc->rxq.free_desc_dma.paddr);\n    \n    prph_sc_ctrl->control.control_flags = htole32(control_flags);\n    \n    /* allocate ucode sections in dram and set addresses */\n    err = iwx_init_fw_sec(sc, fws, &prph_scratch->dram);\n    if (err) {\n        iwx_ctxt_info_free_fw_img(sc);\n        return err;\n    }\n    \n    /* Allocate prph information. */\n    err = iwx_dma_contig_alloc(sc->sc_dmat, &sc->prph_info_dma,\n                               PAGE_SIZE, 0);\n    if (err) {\n        XYLog(\"%s: could not allocate prph information\\n\", DEVNAME(sc));\n        goto fail0;\n    }\n    \n    ctxt_info_gen3 = (struct iwx_context_info_gen3 *)sc->ctxt_info_dma.vaddr;\n    \n    ctxt_info_gen3->prph_info_base_addr =\n        htole64(sc->prph_info_dma.paddr);\n    ctxt_info_gen3->prph_scratch_base_addr =\n        htole64(sc->prph_scratch_dma.paddr);\n    ctxt_info_gen3->prph_scratch_size =\n        htole32(sizeof(*prph_scratch));\n    ctxt_info_gen3->cr_head_idx_arr_base_addr =\n        htole64(sc->rxq.stat_dma.paddr);\n    ctxt_info_gen3->tr_tail_idx_arr_base_addr =\n        htole64((uint8_t *)sc->prph_info_dma.paddr + PAGE_SIZE / 2);\n    ctxt_info_gen3->cr_tail_idx_arr_base_addr =\n        htole64((uint8_t *)sc->prph_info_dma.paddr + 3 * PAGE_SIZE / 4);\n    ctxt_info_gen3->mtr_base_addr =\n        htole64(sc->txq[IWX_DQA_CMD_QUEUE].desc_dma.paddr);\n    ctxt_info_gen3->mcr_base_addr =\n        htole64(sc->rxq.used_desc_dma.paddr);\n    ctxt_info_gen3->mtr_size =\n        htole16(IWX_TFD_QUEUE_CB_SIZE(IWX_CMD_QUEUE_SIZE_GEN3));\n    ctxt_info_gen3->mcr_size =\n        htole16(IWX_RX_QUEUE_CB_SIZE(IWX_RX_MQ_RING_COUNT));\n    \n    /* Allocate IML. */\n    err = iwx_dma_contig_alloc(sc->sc_dmat, &sc->iml_dma,\n                               IWX_IML_MAX_LEN, 0);\n    if (err) {\n        XYLog(\"%s: could not allocate IML\\n\", DEVNAME(sc));\n        goto fail1;\n    }\n    \n    memcpy(sc->iml_dma.vaddr, sc->sc_iml, sc->sc_iml_len);\n    \n    iwx_enable_fwload_interrupt(sc);\n    \n    /* kick FW self load */\n    IWX_WRITE64(sc, IWX_CSR_CTXT_INFO_ADDR,\n            sc->ctxt_info_dma.paddr);\n    IWX_WRITE64(sc, IWX_CSR_IML_DATA_ADDR,\n            sc->iml_dma.paddr);\n    IWX_WRITE(sc, IWX_CSR_IML_SIZE_ADDR, sc->sc_iml_len);\n\n    IWX_SETBITS(sc, IWX_CSR_CTXT_INFO_BOOT_CTRL,\n            IWX_CSR_AUTO_FUNC_BOOT_ENA);\n    \n    iwx_set_ltr(sc);\n    \n    if (!iwx_nic_lock(sc))\n        return EBUSY;\n    iwx_write_umac_prph(sc, IWX_UREG_CPU_INIT_RUN, 1);\n    iwx_nic_unlock(sc);\n    \n    return 0;\n    \nfail1:\n    iwx_dma_contig_free(&sc->iml_dma);\nfail0:\n    iwx_dma_contig_free(&sc->prph_info_dma);\n    iwx_dma_contig_free(&sc->prph_scratch_dma);\n    return ENOMEM;\n}\n\nvoid ItlIwx::\niwx_force_power_gating(struct iwx_softc *sc)\n{\n   iwx_set_bits_prph(sc, IWX_HPM_HIPM_GEN_CFG,\n       IWX_HPM_HIPM_GEN_CFG_CR_FORCE_ACTIVE);\n   DELAY(20);\n   iwx_set_bits_prph(sc, IWX_HPM_HIPM_GEN_CFG,\n       IWX_HPM_HIPM_GEN_CFG_CR_PG_EN |\n       IWX_HPM_HIPM_GEN_CFG_CR_SLP_EN);\n   DELAY(20);\n   iwx_clear_bits_prph(sc, IWX_HPM_HIPM_GEN_CFG,\n       IWX_HPM_HIPM_GEN_CFG_CR_FORCE_ACTIVE);\n}\n\nvoid ItlIwx::\niwx_clear_persistence_bit(struct iwx_softc *sc)\n{\n    uint32_t hpm, wprot;\n    \n    if (sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210)\n        return;\n    \n    wprot = IWX_PREG_PRPH_WPROT_22000;\n    hpm = iwx_read_prph_unlocked(sc, IWX_HPM_DEBUG);\n    if (hpm != 0xa5a5a5a0 && (hpm & IWX_PERSISTENCE_BIT)) {\n        uint32_t wprot_val = iwx_read_prph_unlocked(sc, wprot);\n        \n        if (wprot_val & IWX_PREG_WFPM_ACCESS) {\n            XYLog(\"Error, can not clear persistence bit\\n\");\n            return;\n        }\n        iwx_write_prph_unlocked(sc, IWX_HPM_DEBUG,\n                                hpm & ~IWX_PERSISTENCE_BIT);\n    }\n}\n\nvoid ItlIwx::\niwx_ctxt_info_free_fw_img(struct iwx_softc *sc)\n{\n    struct iwx_self_init_dram *dram = &sc->init_dram;\n    int i;\n    \n    if (!dram->fw)\n        return;\n\n    for (i = 0; i < dram->lmac_cnt + dram->umac_cnt; i++)\n        iwx_dma_contig_free(&dram->fw[i]);\n\n    IOFree(dram->fw,\n        (dram->lmac_cnt + dram->umac_cnt) * sizeof(*dram->fw));\n    dram->lmac_cnt = 0;\n    dram->umac_cnt = 0;\n    dram->fw = NULL;\n}\n\nint ItlIwx::\niwx_firmware_store_section(struct iwx_softc *sc, enum iwx_ucode_type type,\n                           uint8_t *data, size_t dlen)\n{\n    struct iwx_fw_sects *fws;\n    struct iwx_fw_onesect *fwone;\n    \n    if (type >= IWX_UCODE_TYPE_MAX)\n        return EINVAL;\n    if (dlen < sizeof(uint32_t))\n        return EINVAL;\n    \n    fws = &sc->sc_fw.fw_sects[type];\n    DPRINTFN(3, (\"%s: ucode type %d section %d\\n\", DEVNAME(sc), type, fws->fw_count));\n    if (fws->fw_count >= IWX_UCODE_SECT_MAX)\n        return EINVAL;\n    \n    fwone = &fws->fw_sect[fws->fw_count];\n    \n    /* first 32bit are device load offset */\n    memcpy(&fwone->fws_devoff, data, sizeof(uint32_t));\n    \n    /* rest is data */\n    fwone->fws_data = data + sizeof(uint32_t);\n    fwone->fws_len = dlen - sizeof(uint32_t);\n    \n    fws->fw_count++;\n    fws->fw_totlen += fwone->fws_len;\n    \n    return 0;\n}\n\n#define IWX_DEFAULT_SCAN_CHANNELS    40\n/* Newer firmware might support more channels. Raise this value if needed. */\n#define IWX_MAX_SCAN_CHANNELS        256 /* as of 8265-34 firmware image */\n#define IWX_STATION_COUNT_MAX        16\n\nstruct iwx_tlv_calib_data {\n    uint32_t ucode_type;\n    struct iwx_tlv_calib_ctrl calib;\n} __packed;\n\nint ItlIwx::\niwx_set_default_calib(struct iwx_softc *sc, const void *data)\n{\n    const struct iwx_tlv_calib_data *def_calib = (const struct iwx_tlv_calib_data *)data;\n    uint32_t ucode_type = le32toh(def_calib->ucode_type);\n    \n    if (ucode_type >= IWX_UCODE_TYPE_MAX)\n        return EINVAL;\n    \n    sc->sc_default_calib[ucode_type].flow_trigger =\n    def_calib->calib.flow_trigger;\n    sc->sc_default_calib[ucode_type].event_trigger =\n    def_calib->calib.event_trigger;\n    \n    return 0;\n}\n\nvoid ItlIwx::\niwx_fw_info_free(struct iwx_fw_info *fw)\n{\n    ::free(fw->fw_rawdata);\n    fw->fw_rawdata = NULL;\n    fw->fw_rawsize = 0;\n    /* don't touch fw->fw_status */\n    memset(fw->fw_sects, 0, sizeof(fw->fw_sects));\n}\n\nvoid ItlIwx::\niwx_pnvm_free(struct iwx_fw_info *fw)\n{\n    if (fw->pnvm_rawdata) {\n        ::free(fw->pnvm_rawdata);\n        fw->pnvm_rawdata = NULL;\n        fw->pnvm_rawsize = 0;\n    }\n}\n\n#define IWX_FW_ADDR_CACHE_CONTROL 0xC0000000\n\n//void ItlIwx::\n//onLoadFW(OSKextRequestTag requestTag, OSReturn result, const void *resourceData, uint32_t resourceDataLength, void *context)\n//{\n//    XYLog(\"onLoadFW callback ret=0x%08x length=%d\", result, resourceDataLength);\n//    ResourceCallbackContext *resourceContxt = (ResourceCallbackContext*)context;\n//    IOLockLock(resourceContxt->context->_fwLoadLock);\n//    if (resourceDataLength > 0) {\n//        XYLog(\"onLoadFW return success\");\n//        resourceContxt->resource = OSData::withBytes(resourceData, resourceDataLength);\n//    }\n//    IOLockUnlock(resourceContxt->context->_fwLoadLock);\n//    IOLockWakeup(resourceContxt->context->_fwLoadLock, resourceContxt->context, false);\n//    XYLog(\"onLoadFW wakeupOn\");\n//}\n\nint ItlIwx::\niwx_read_firmware(struct iwx_softc *sc)\n{\n    struct iwx_fw_info *fw = &sc->sc_fw;\n    struct iwx_tlv_ucode_header *uhdr;\n    struct iwx_ucode_tlv tlv;\n    uint32_t tlv_type = 0;\n    uint8_t *data;\n    int err = 0;\n    size_t len;\n    OSData *fwData = NULL;\n    \n    if (fw->fw_status == IWX_FW_STATUS_DONE)\n        return 0;\n    \n    while (fw->fw_status == IWX_FW_STATUS_INPROGRESS)\n        tsleep_nsec(&sc->sc_fw, 0, \"iwxfwp\", INFSLP);\n    fw->fw_status = IWX_FW_STATUS_INPROGRESS;\n    \n    if (fw->fw_rawdata != NULL)\n        iwx_fw_info_free(fw);\n    \n//    IOLockLock(_fwLoadLock);\n//    ResourceCallbackContext context =\n//    {\n//        .context = this,\n//        .resource = NULL\n//    };\n//\n//    //here leaks\n//    IOReturn ret = OSKextRequestResource(OSKextGetCurrentIdentifier(), sc->sc_fwname, onLoadFW, &context, NULL);\n//    IOLockSleep(_fwLoadLock, this, 0);\n//    IOLockUnlock(_fwLoadLock);\n//    if (context.resource == NULL) {\n//        XYLog(\"%s resource load fail.\\n\", sc->sc_fwname);\n//        goto out;\n//    }\n//    fw->fw_rawdata = malloc(context.resource->getLength(), 1, 1);\n//    memcpy(fw->fw_rawdata, context.resource->getBytesNoCopy(), context.resource->getLength());\n//    fw->fw_rawsize = context.resource->getLength();\n    fwData = getFWDescByName(sc->sc_fwname);\n    if (fwData == NULL) {\n        err = EINVAL;\n        XYLog(\"%s resource load fail.\\n\", sc->sc_fwname);\n        goto out;\n    }\n    fw->fw_rawsize = fwData->getLength() * 4;\n    fw->fw_rawdata = malloc(fw->fw_rawsize, 1, 1);\n    uncompressFirmware((u_char *)fw->fw_rawdata, (uint *)&fw->fw_rawsize, (u_char *)fwData->getBytesNoCopy(), fwData->getLength());\n    XYLog(\"load firmware %s done\\n\", sc->sc_fwname);\n    \n    sc->sc_capaflags = 0;\n    sc->sc_capa_n_scan_channels = IWX_DEFAULT_SCAN_CHANNELS;\n    memset(sc->sc_enabled_capa, 0, sizeof(sc->sc_enabled_capa));\n    memset(sc->sc_ucode_api, 0, sizeof(sc->sc_ucode_api));\n    sc->n_cmd_versions = 0;\n    memcpy(sc->sc_fw_mcc, \"ZZ\", sizeof(sc->sc_fw_mcc));\n    sc->sc_fw_mcc_int = 0x3030;\n    \n    uhdr = (struct iwx_tlv_ucode_header *)fw->fw_rawdata;\n    if (*(uint32_t *)fw->fw_rawdata != 0\n        || le32toh(uhdr->magic) != IWX_TLV_UCODE_MAGIC) {\n        XYLog(\"%s: invalid firmware %s\\n\",\n              DEVNAME(sc), sc->sc_fwname);\n        err = EINVAL;\n        goto out;\n    }\n    \n    iwx_fw_version_str(sc->sc_fwver, sizeof(sc->sc_fwver),\n             IWX_UCODE_MAJOR(le32toh(uhdr->ver)),\n             IWX_UCODE_MINOR(le32toh(uhdr->ver)),\n             IWX_UCODE_API(le32toh(uhdr->ver)));\n    data = uhdr->data;\n    len = fw->fw_rawsize - sizeof(*uhdr);\n    \n    XYLog(\"parsing firmware %s\\n\", sc->sc_fwname);\n    while (len >= sizeof(tlv)) {\n        size_t tlv_len;\n        void *tlv_data;\n        \n        memcpy(&tlv, data, sizeof(tlv));\n        tlv_len = le32toh(tlv.length);\n        tlv_type = le32toh(tlv.type);\n        \n        len -= sizeof(tlv);\n        data += sizeof(tlv);\n        tlv_data = data;\n        \n        if (len < tlv_len) {\n            XYLog(\"%s: firmware too short: %zu bytes\\n\",\n                  DEVNAME(sc), len);\n            err = EINVAL;\n            goto parse_out;\n        }\n        \n        switch (tlv_type) {\n            case IWX_UCODE_TLV_PROBE_MAX_LEN:\n                if (tlv_len < sizeof(uint32_t)) {\n                    err = EINVAL;\n                    goto parse_out;\n                }\n                sc->sc_capa_max_probe_len\n                = le32toh(*(uint32_t *)tlv_data);\n                if (sc->sc_capa_max_probe_len >\n                    IWX_SCAN_OFFLOAD_PROBE_REQ_SIZE) {\n                    err = EINVAL;\n                    goto parse_out;\n                }\n                break;\n            case IWX_UCODE_TLV_PAN:\n                if (tlv_len) {\n                    err = EINVAL;\n                    goto parse_out;\n                }\n                sc->sc_capaflags |= IWX_UCODE_TLV_FLAGS_PAN;\n                break;\n            case IWX_UCODE_TLV_FLAGS:\n                if (tlv_len < sizeof(uint32_t)) {\n                    err = EINVAL;\n                    goto parse_out;\n                }\n                /*\n                 * Apparently there can be many flags, but Linux driver\n                 * parses only the first one, and so do we.\n                 *\n                 * XXX: why does this override IWX_UCODE_TLV_PAN?\n                 * Intentional or a bug?  Observations from\n                 * current firmware file:\n                 *  1) TLV_PAN is parsed first\n                 *  2) TLV_FLAGS contains TLV_FLAGS_PAN\n                 * ==> this resets TLV_PAN to itself... hnnnk\n                 */\n                sc->sc_capaflags = le32toh(*(uint32_t *)tlv_data);\n                break;\n            case IWX_UCODE_TLV_CSCHEME:\n                err = iwx_store_cscheme(sc, (uint8_t *)tlv_data, tlv_len);\n                if (err)\n                    goto parse_out;\n                break;\n            case IWX_UCODE_TLV_NUM_OF_CPU: {\n                uint32_t num_cpu;\n                if (tlv_len != sizeof(uint32_t)) {\n                    err = EINVAL;\n                    goto parse_out;\n                }\n                num_cpu = le32toh(*(uint32_t *)tlv_data);\n                if (num_cpu < 1 || num_cpu > 2) {\n                    err = EINVAL;\n                    goto parse_out;\n                }\n                break;\n            }\n            case IWX_UCODE_TLV_SEC_RT:\n                err = iwx_firmware_store_section(sc,\n                                                 IWX_UCODE_TYPE_REGULAR, (uint8_t *)tlv_data, tlv_len);\n                if (err)\n                    goto parse_out;\n                break;\n            case IWX_UCODE_TLV_SEC_INIT:\n                err = iwx_firmware_store_section(sc,\n                                                 IWX_UCODE_TYPE_INIT, (uint8_t *)tlv_data, tlv_len);\n                if (err)\n                    goto parse_out;\n                break;\n            case IWX_UCODE_TLV_SEC_WOWLAN:\n                err = iwx_firmware_store_section(sc,\n                                                 IWX_UCODE_TYPE_WOW, (uint8_t *)tlv_data, tlv_len);\n                if (err)\n                    goto parse_out;\n                break;\n            case IWX_UCODE_TLV_DEF_CALIB:\n                if (tlv_len != sizeof(struct iwx_tlv_calib_data)) {\n                    err = EINVAL;\n                    goto parse_out;\n                }\n                err = iwx_set_default_calib(sc, tlv_data);\n                if (err)\n                    goto parse_out;\n                break;\n            case IWX_UCODE_TLV_PHY_SKU:\n                if (tlv_len != sizeof(uint32_t)) {\n                    err = EINVAL;\n                    goto parse_out;\n                }\n                sc->sc_fw_phy_config = le32toh(*(uint32_t *)tlv_data);\n                break;\n                \n            case IWX_UCODE_TLV_API_CHANGES_SET: {\n                struct iwx_ucode_api *api;\n                int idx, i;\n                if (tlv_len != sizeof(*api)) {\n                    err = EINVAL;\n                    goto parse_out;\n                }\n                api = (struct iwx_ucode_api *)tlv_data;\n                idx = le32toh(api->api_index);\n                if (idx >= howmany(IWX_NUM_UCODE_TLV_API, 32)) {\n                    err = EINVAL;\n                    goto parse_out;\n                }\n                for (i = 0; i < 32; i++) {\n                    if ((le32toh(api->api_flags) & (1 << i)) == 0)\n                        continue;\n                    setbit(sc->sc_ucode_api, i + (32 * idx));\n                }\n                break;\n            }\n                \n            case IWX_UCODE_TLV_ENABLED_CAPABILITIES: {\n                struct iwx_ucode_capa *capa;\n                int idx, i;\n                if (tlv_len != sizeof(*capa)) {\n                    err = EINVAL;\n                    goto parse_out;\n                }\n                capa = (struct iwx_ucode_capa *)tlv_data;\n                idx = le32toh(capa->api_index);\n                if (idx >= howmany(IWX_NUM_UCODE_TLV_CAPA, 32)) {\n                    goto parse_out;\n                }\n                for (i = 0; i < 32; i++) {\n                    if ((le32toh(capa->api_capa) & (1 << i)) == 0)\n                        continue;\n                    setbit(sc->sc_enabled_capa, i + (32 * idx));\n                }\n                break;\n            }\n                \n            case IWX_UCODE_TLV_SDIO_ADMA_ADDR:\n            case IWX_UCODE_TLV_FW_GSCAN_CAPA:\n                /* ignore, not used by current driver */\n                break;\n                \n            case IWX_UCODE_TLV_SEC_RT_USNIFFER:\n                err = iwx_firmware_store_section(sc,\n                                                 IWX_UCODE_TYPE_REGULAR_USNIFFER, (uint8_t *)tlv_data,\n                                                 tlv_len);\n                if (err)\n                    goto parse_out;\n                break;\n                \n            case IWX_UCODE_TLV_PAGING:\n                if (tlv_len != sizeof(uint32_t)) {\n                    err = EINVAL;\n                    goto parse_out;\n                }\n                break;\n                \n            case IWX_UCODE_TLV_N_SCAN_CHANNELS:\n                if (tlv_len != sizeof(uint32_t)) {\n                    err = EINVAL;\n                    goto parse_out;\n                }\n                sc->sc_capa_n_scan_channels =\n                le32toh(*(uint32_t *)tlv_data);\n                if (sc->sc_capa_n_scan_channels > IWX_MAX_SCAN_CHANNELS) {\n                    err = ERANGE;\n                    goto parse_out;\n                }\n                break;\n                \n            case IWX_UCODE_TLV_FW_VERSION:\n                if (tlv_len != sizeof(uint32_t) * 3) {\n                    err = EINVAL;\n                    goto parse_out;\n                }\n                iwx_fw_version_str(sc->sc_fwver, sizeof(sc->sc_fwver),\n                         le32toh(((uint32_t *)tlv_data)[0]),\n                         le32toh(((uint32_t *)tlv_data)[1]),\n                         le32toh(((uint32_t *)tlv_data)[2]));\n                break;\n                \n            case IWX_UCODE_TLV_FW_DBG_DEST: {\n                struct iwx_fw_dbg_dest_tlv_v1 *dest_v1 = NULL;\n                \n                fw->dbg_dest_ver = (uint8_t *)tlv_data;\n                if (*fw->dbg_dest_ver != 0) {\n                    err = EINVAL;\n                    goto parse_out;\n                }\n                \n                if (fw->dbg_dest_tlv_init)\n                    break;\n                fw->dbg_dest_tlv_init = true;\n                \n                dest_v1 = (struct iwx_fw_dbg_dest_tlv_v1 *)tlv_data;\n                fw->dbg_dest_tlv_v1 = dest_v1;\n                fw->n_dest_reg = tlv_len -\n                offsetof(struct iwx_fw_dbg_dest_tlv_v1, reg_ops);\n                fw->n_dest_reg /= sizeof(dest_v1->reg_ops[0]);\n                DPRINTF((\"%s: found debug dest; n_dest_reg=%d\\n\", __func__, fw->n_dest_reg));\n                break;\n            }\n                \n            case IWX_UCODE_TLV_FW_DBG_CONF: {\n                struct iwx_fw_dbg_conf_tlv *conf = (struct iwx_fw_dbg_conf_tlv *)tlv_data;\n                \n                if (!fw->dbg_dest_tlv_init ||\n                    conf->id >= nitems(fw->dbg_conf_tlv) ||\n                    fw->dbg_conf_tlv[conf->id] != NULL)\n                    break;\n                \n                DPRINTF((\"Found debug configuration: %d\\n\", conf->id));\n                fw->dbg_conf_tlv[conf->id] = conf;\n                fw->dbg_conf_tlv_len[conf->id] = tlv_len;\n                break;\n            }\n                \n            case IWX_UCODE_TLV_UMAC_DEBUG_ADDRS: {\n                struct iwx_umac_debug_addrs *dbg_ptrs =\n                (struct iwx_umac_debug_addrs *)tlv_data;\n                \n                if (tlv_len != sizeof(*dbg_ptrs)) {\n                    err = EINVAL;\n                    goto parse_out;\n                }\n                if (sc->sc_device_family < IWX_DEVICE_FAMILY_22000)\n                    break;\n                sc->sc_uc.uc_umac_error_event_table =\n                le32toh(dbg_ptrs->error_info_addr) &\n                ~IWX_FW_ADDR_CACHE_CONTROL;\n                sc->sc_uc.error_event_table_tlv_status |=\n                IWX_ERROR_EVENT_TABLE_UMAC;\n                break;\n            }\n                \n            case IWX_UCODE_TLV_LMAC_DEBUG_ADDRS: {\n                struct iwx_lmac_debug_addrs *dbg_ptrs =\n                (struct iwx_lmac_debug_addrs *)tlv_data;\n                \n                if (tlv_len != sizeof(*dbg_ptrs)) {\n                    err = EINVAL;\n                    goto parse_out;\n                }\n                if (sc->sc_device_family < IWX_DEVICE_FAMILY_22000)\n                    break;\n                sc->sc_uc.uc_lmac_error_event_table[0] =\n                le32toh(dbg_ptrs->error_event_table_ptr) &\n                ~IWX_FW_ADDR_CACHE_CONTROL;\n                sc->sc_uc.error_event_table_tlv_status |=\n                IWX_ERROR_EVENT_TABLE_LMAC1;\n                break;\n            }\n                \n            case IWX_UCODE_TLV_FW_MEM_SEG:\n                break;\n                \n            case IWX_UCODE_TLV_IML:\n                if (sizeof(sc->sc_iml) < tlv_len) {\n                    XYLog(\"IML max len mismatch. len1: %zu len2: %zu\\n\", sizeof(sc->sc_iml), tlv_len);\n                    err = EINVAL;\n                    goto parse_out;\n                }\n                sc->sc_iml_len = (uint32_t)tlv_len;\n                memcpy(sc->sc_iml, tlv_data, sc->sc_iml_len);\n                break;\n                \n            case IWX_UCODE_TLV_CMD_VERSIONS:\n                if (tlv_len % sizeof(struct iwx_fw_cmd_version)) {\n                    tlv_len /= sizeof(struct iwx_fw_cmd_version);\n                    tlv_len *= sizeof(struct iwx_fw_cmd_version);\n                }\n                if (sc->n_cmd_versions != 0) {\n                    err = EINVAL;\n                    goto parse_out;\n                }\n                if (tlv_len > sizeof(sc->cmd_versions)) {\n                    err = EINVAL;\n                    goto parse_out;\n                }\n                memcpy(&sc->cmd_versions[0], tlv_data, tlv_len);\n                sc->n_cmd_versions = tlv_len / sizeof(struct iwx_fw_cmd_version);\n                break;\n                \n            case IWX_UCODE_TLV_FW_RECOVERY_INFO:\n                break;\n                \n            case IWX_UCODE_TLV_FW_FSEQ_VERSION: {\n                struct sfseq_ver {\n                    uint8_t version[32];\n                    uint8_t sha1[20];\n                };\n                sfseq_ver *seq_ver = (sfseq_ver *)tlv_data;\n                if (tlv_len != sizeof(struct sfseq_ver)) {\n                    err = EINVAL;\n                    goto parse_out;\n                }\n                XYLog(\"TLV_FW_FSEQ_VERSION: %s\\n\", seq_ver->version);\n            }\n                break;\n                \n            case IWX_UCODE_PHY_INTEGRATION_VERSION:\n                break;\n            case IWX_UCODE_TLV_FW_NUM_STATIONS:\n                if (tlv_len != sizeof(uint32_t)) {\n                    err = EINVAL;\n                    goto parse_out;\n                }\n                sc->sc_capa_num_stations = le32toh(*(uint32_t *)tlv_data);\n                if (sc->sc_capa_num_stations > IWX_STATION_COUNT_MAX) {\n                    XYLog(\"%d is an invalid number of station\\n\",\n                          sc->sc_capa_num_stations);\n                    err = EINVAL;\n                    goto parse_out;\n                }\n                break;\n                \n                /* undocumented TLVs found in iwx-cc-a0-48 image */\n            case 58:\n            case 0x1000003:\n            case 0x1000004:\n                break;\n                \n                /* undocumented TLVs found in iwx-cc-a0-48 image */\n            case 0x1000000:\n            case 0x1000002:\n            case IWX_UCODE_TLV_TYPE_DEBUG_INFO:\n            case IWX_UCODE_TLV_TYPE_BUFFER_ALLOCATION:\n            case IWX_UCODE_TLV_TYPE_HCMD:\n            case IWX_UCODE_TLV_TYPE_REGIONS:\n            case IWX_UCODE_TLV_TYPE_TRIGGERS:\n            case IWX_UCODE_TLV_TYPE_CONF_SET:\n                break;\n\n                /* undocumented TLV found in iwx-cc-a0-67 image */\n            case 0x100000b:\n                break;\n                \n            default:\n                //            err = EINVAL;\n                //            goto parse_out;\n                XYLog(\"%s unhandle section type= %d\\n\", __FUNCTION__, tlv_type);\n                break;\n        }\n        \n        /*\n         * Check for size_t overflow and ignore missing padding at\n         * end of firmware file.\n         */\n        if (roundup(tlv_len, 4) > len)\n            break;\n        \n        len -= roundup(tlv_len, 4);\n        data += roundup(tlv_len, 4);\n    }\n    \n    KASSERT(err == 0, \"err == 0\");\n    \n    XYLog(\"firmware parse done\\n\");\n    \nparse_out:\n    if (err) {\n        XYLog(\"%s: firmware parse error %d, \"\n              \"section type %d\\n\", DEVNAME(sc), err, tlv_type);\n    }\n    \nout:\n    if (err) {\n        fw->fw_status = IWX_FW_STATUS_NONE;\n        if (fw->fw_rawdata != NULL)\n            iwx_fw_info_free(fw);\n    } else\n        fw->fw_status = IWX_FW_STATUS_DONE;\n    wakeupOn(&sc->sc_fw);\n\n    OSSafeReleaseNULL(fwData);\n    \n    return err;\n}\n\nstruct iwx_pnvm_section {\n    uint32_t offset;\n    const uint8_t data[];\n} __packed;\n\nint ItlIwx::\niwx_pnvm_handle_section(struct iwx_softc *sc, const uint8_t *data, size_t len)\n{\n    struct iwx_ucode_tlv *tlv;\n    uint32_t sha1 = 0;\n    uint16_t mac_type = 0, rf_id = 0;\n    uint8_t *pnvm_data = NULL, *tmp;\n    bool hw_match = false;\n    uint32_t size = 0;\n    int err = 0;\n    struct iwx_prph_scratch_ctrl_cfg *prph_sc_ctrl;\n    \n    XYLog(\"Handling PNVM section\\n\");\n    \n    while (len >= sizeof(*tlv)) {\n        uint32_t tlv_len, tlv_type;\n        \n        len -= sizeof(*tlv);\n        tlv = (struct iwx_ucode_tlv *)data;\n        \n        tlv_len = le32toh(tlv->length);\n        tlv_type = le32toh(tlv->type);\n        \n        if (len < tlv_len) {\n            XYLog(\"invalid TLV len: %zd/%u\\n\",\n                  len, tlv_len);\n            err = -EINVAL;\n            goto out;\n        }\n        \n        data += sizeof(*tlv);\n        \n        switch (tlv_type) {\n            case IWX_UCODE_TLV_PNVM_VERSION:\n                if (tlv_len < sizeof(__le32)) {\n                    XYLog(\"Invalid size for IWL_UCODE_TLV_PNVM_VERSION (expected %zd, got %d)\\n\",\n                          sizeof(__le32), tlv_len);\n                    break;\n                }\n                \n                sha1 = le32_to_cpup((__le32 *)data);\n                \n                XYLog(\"Got IWL_UCODE_TLV_PNVM_VERSION %0x\\n\",\n                      sha1);\n                break;\n            case IWX_UCODE_TLV_HW_TYPE:\n                if (tlv_len < 2 * sizeof(__le16)) {\n                    XYLog(\"Invalid size for IWL_UCODE_TLV_HW_TYPE (expected %zd, got %d)\\n\",\n                          2 * sizeof(__le16), tlv_len);\n                    break;\n                }\n                \n                if (hw_match)\n                    break;\n\n                mac_type = le16_to_cpup((__le16 *)data);\n                rf_id = le16_to_cpup((__le16 *)(data + sizeof(__le16)));\n                \n                XYLog(\"Got IWL_UCODE_TLV_HW_TYPE mac_type 0x%0x rf_id 0x%0x\\n\",\n                      mac_type, rf_id);\n                \n                if (mac_type == CSR_HW_REV_TYPE(sc->sc_hw_rev) &&\n                    rf_id == CSR_HW_RFID_TYPE(sc->sc_hw_rf_id))\n                    hw_match = true;\n                break;\n            case IWX_UCODE_TLV_SEC_RT: {\n                struct iwx_pnvm_section *section = (struct iwx_pnvm_section *)data;\n                u32 data_len = tlv_len - sizeof(*section);\n                \n                XYLog(\"Got IWL_UCODE_TLV_SEC_RT len %d\\n\",\n                      tlv_len);\n                \n                /* TODO: remove, this is a deprecated separator */\n                if (le32_to_cpup((__le32 *)data) == 0xddddeeee) {\n                    XYLog(\"Ignoring separator.\\n\");\n                    break;\n                }\n                \n                XYLog(\"Adding data (size %d)\\n\",\n                      data_len);\n                \n                tmp = (uint8_t *)malloc(size + data_len, 0, 0);\n                if (!tmp) {\n                    XYLog(\"Couldn't allocate (more) pnvm_data\\n\");\n                    \n                    err = -ENOMEM;\n                    goto out;\n                }\n                if (pnvm_data && size > 0) {\n                    memcpy(tmp, pnvm_data, size);\n                    ::free(pnvm_data);\n                }\n                \n                pnvm_data = tmp;\n                \n                memcpy(pnvm_data + size, section->data, data_len);\n                \n                size += data_len;\n                \n                break;\n            }\n            case IWX_UCODE_TLV_PNVM_SKU:\n                XYLog(\"New PNVM section started, stop parsing.\\n\");\n                goto done;\n            default:\n                XYLog(\"Found TLV 0x%0x, len %d\\n\",\n                      tlv_type, tlv_len);\n                break;\n        }\n        \n        if (roundup(tlv_len, 4) > len)\n            break;\n        \n        len -= roundup(tlv_len, 4);\n        data += roundup(tlv_len, 4);\n    }\n    \ndone:\n    if (!hw_match) {\n        XYLog(\"HW mismatch, skipping PNVM section (need mac_type 0x%x rf_id 0x%x)\\n\",\n                 CSR_HW_REV_TYPE(sc->sc_hw_rev),\n                 CSR_HW_RFID_TYPE(sc->sc_hw_rf_id));\n        err = -ENOENT;\n        goto out;\n    }\n\n    if (!size) {\n        XYLog(\"Empty PNVM, skipping.\\n\");\n        err = -ENOENT;\n        goto out;\n    }\n    \n    XYLog(\"loaded PNVM version %08x\\n\", sha1);\n    \n    prph_sc_ctrl = &((struct iwx_prph_scratch *)sc->prph_scratch_dma.vaddr)->ctrl_cfg;\n    \n    iwx_dma_contig_free(&sc->pnvm_dram);\n    err = iwx_dma_contig_alloc(sc->sc_dmat, &sc->pnvm_dram, size, 0);\n    if (err) {\n        XYLog(\"%s: could not allocate context info DMA memory\\n\",\n              DEVNAME(sc));\n        goto out;\n    }\n    \n    memcpy(sc->pnvm_dram.vaddr, pnvm_data, size);\n    \n    prph_sc_ctrl->pnvm_cfg.pnvm_base_addr =\n        htole64(sc->pnvm_dram.paddr);\n    prph_sc_ctrl->pnvm_cfg.pnvm_size =\n        htole32(sc->pnvm_dram.size);\n    \nout:\n    ::free(pnvm_data);\n    \n    return err;\n}\n\nint ItlIwx::\niwx_read_pnvm(struct iwx_softc *sc)\n{\n    int err = 0;\n    OSData *fwData = NULL;\n    struct iwx_fw_info *fw = &sc->sc_fw;\n    char fwname_copy[64];\n    char pnvm_name[64];\n    struct iwx_ucode_tlv *tlv;\n    uint8_t *data;\n    size_t len;\n    const char *find;\n    \n    if (fw->pnvm_rawdata != NULL)\n        iwx_pnvm_free(fw);\n    /*\n     * The prefix unfortunately includes a hyphen at the end, so\n     * don't add the dot here...\n     */\n    memcpy(fwname_copy, sc->sc_fwname, sizeof(fwname_copy));\n    find = strrchr(sc->sc_fwname, '-');\n    if (!find)\n        goto out;\n    if (find - sc->sc_fwname - 1 <= 0)\n        goto out;\n    fwname_copy[find - sc->sc_fwname - 1] = '\\0';\n    \n    snprintf(pnvm_name, sizeof(pnvm_name), \"%s.pnvm\",\n         fwname_copy);\n    \n    fwData = getFWDescByName(pnvm_name);\n\n    if (fwData == NULL) {\n        err = EINVAL;\n        XYLog(\"%s resource load fail.\\n\", pnvm_name);\n        goto out;\n    }\n    fw->pnvm_rawsize = fwData->getLength() * 20;\n    fw->pnvm_rawdata = malloc(fw->pnvm_rawsize, 1, 1);\n    uncompressFirmware((u_char *)fw->pnvm_rawdata, (uint *)&fw->pnvm_rawsize, (u_char *)fwData->getBytesNoCopy(), fwData->getLength());\n    XYLog(\"load firmware %s done %zu\\n\", pnvm_name, fw->pnvm_rawsize);\n    \n    XYLog(\"Parsing PNVM file\\n\");\n    \n    data = (uint8_t *)fw->pnvm_rawdata;\n    len = fw->pnvm_rawsize;\n    \n    while (len >= sizeof(*tlv)) {\n        uint32_t tlv_len, tlv_type;\n\n        len -= sizeof(*tlv);\n        tlv = (struct iwx_ucode_tlv *)data;\n\n        tlv_len = le32toh(tlv->length);\n        tlv_type = le32toh(tlv->type);\n\n        if (len < tlv_len || roundup(tlv_len, 4) > len) {\n            XYLog(\"invalid TLV len: %zd/%u\\n\",\n                len, tlv_len);\n            err = -EINVAL;\n            goto out;\n        }\n\n        if (tlv_type == IWX_UCODE_TLV_PNVM_SKU) {\n            struct iwx_sku_id *sku_id =\n                (struct iwx_sku_id *)(data + sizeof(*tlv));\n\n            XYLog(\"Got IWL_UCODE_TLV_PNVM_SKU len %d\\n\",\n                     tlv_len);\n            XYLog(\"sku_id 0x%0x 0x%0x 0x%0x\\n\",\n                     le32toh(sku_id->data[0]),\n                     le32toh(sku_id->data[1]),\n                     le32toh(sku_id->data[2]));\n\n            data += sizeof(*tlv) + roundup(tlv_len, 4);\n            len -= roundup(tlv_len, 4);\n\n            if (sc->sku_id[0] == le32toh(sku_id->data[0]) &&\n                sc->sku_id[1] == le32toh(sku_id->data[1]) &&\n                sc->sku_id[2] == le32toh(sku_id->data[2])) {\n\n                err = iwx_pnvm_handle_section(sc, data, len);\n                if (!err)\n                    goto out;\n            } else {\n                XYLog(\"SKU ID didn't match!\\n\");\n            }\n        } else {\n            data += sizeof(*tlv) + roundup(tlv_len, 4);\n            len -= roundup(tlv_len, 4);\n        }\n    }\n    \n    XYLog(\"PNVM parse done\\n\");\n    \nout:\n    OSSafeReleaseNULL(fwData);\n    \n    return err;\n}\n\nint ItlIwx::\niwx_load_pnvm(struct iwx_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    int err;\n    \n    /* if the SKU_ID is empty, there's nothing to do */\n    if (!sc->sku_id[0] && !sc->sku_id[1] && !sc->sku_id[2])\n        return 0;\n    \n    if (!iwx_read_pnvm(sc)) {\n        goto out;\n    };\n    \nout:\n    /* kick the doorbell */\n    if (iwx_nic_lock(sc)) {\n        iwx_write_umac_prph(sc, IWX_UREG_DOORBELL_TO_ISR6,\n        IWX_UREG_DOORBELL_TO_ISR6_PNVM);\n        iwx_nic_unlock(sc);\n    }\n    \n    err = tsleep_nsec(&sc->sc_init_complete, 0, \"iwxinit\", SEC_TO_NSEC(2));\n    \n    iwx_pnvm_free(&sc->sc_fw);\n    \n    return err;\n}\n\nstatic uint32_t iwx_prph_msk(struct iwx_softc *sc)\n{\n    if (sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210)\n        return 0x00FFFFFF;\n    else\n        return 0x000FFFFF;\n}\n\nuint32_t ItlIwx::\niwx_read_prph_unlocked(struct iwx_softc *sc, uint32_t addr)\n{\n    IWX_WRITE(sc,\n              IWX_HBUS_TARG_PRPH_RADDR, ((addr & iwx_prph_msk(sc)) | (3 << 24)));\n    IWX_BARRIER_READ_WRITE(sc);\n    return IWX_READ(sc, IWX_HBUS_TARG_PRPH_RDAT);\n}\n\nuint32_t ItlIwx::\niwx_read_prph(struct iwx_softc *sc, uint32_t addr)\n{\n    iwx_nic_assert_locked(sc);\n    return iwx_read_prph_unlocked(sc, addr);\n}\n\nuint32_t ItlIwx::\niwx_read_umac_prph(struct iwx_softc *sc, uint32_t addr)\n{\n    int off = 0;\n    if (sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210)\n        off = GEN3_UMAC_PRPH_OFFSET;\n    return iwx_read_prph(sc, off + addr);\n}\n\nvoid ItlIwx::\niwx_write_prph_unlocked(struct iwx_softc *sc, uint32_t addr, uint32_t val)\n{\n    IWX_WRITE(sc,\n              IWX_HBUS_TARG_PRPH_WADDR, ((addr & iwx_prph_msk(sc)) | (3 << 24)));\n    IWX_BARRIER_WRITE(sc);\n    IWX_WRITE(sc, IWX_HBUS_TARG_PRPH_WDAT, val);\n}\n\nvoid ItlIwx::\niwx_write_umac_prph(struct iwx_softc *sc, uint32_t addr, uint32_t val)\n{\n    int off = 0;\n    if (sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210)\n        off = GEN3_UMAC_PRPH_OFFSET;\n    iwx_write_prph(sc, off + addr, val);\n}\n\nvoid ItlIwx::\niwx_write_prph(struct iwx_softc *sc, uint32_t addr, uint32_t val)\n{\n    iwx_nic_assert_locked(sc);\n    iwx_write_prph_unlocked(sc, addr, val);\n}\n\nvoid ItlIwx::\niwx_write_prph64(struct iwx_softc *sc, uint64_t addr, uint64_t val)\n{\n    iwx_write_prph(sc, (uint32_t)addr, val & 0xffffffff);\n    iwx_write_prph(sc, (uint32_t)addr + 4, val >> 32);\n}\n\nint ItlIwx::\niwx_read_mem(struct iwx_softc *sc, uint32_t addr, void *buf, int dwords)\n{\n    int offs, err = 0;\n    uint32_t *vals = (uint32_t *)buf;\n    \n    if (iwx_nic_lock(sc)) {\n        IWX_WRITE(sc, IWX_HBUS_TARG_MEM_RADDR, addr);\n        for (offs = 0; offs < dwords; offs++)\n            vals[offs] = le32toh(IWX_READ(sc, IWX_HBUS_TARG_MEM_RDAT));\n        iwx_nic_unlock(sc);\n    } else {\n        err = EBUSY;\n    }\n    return err;\n}\n\nint ItlIwx::\niwx_write_mem(struct iwx_softc *sc, uint32_t addr, const void *buf, int dwords)\n{\n    int offs;\n    const uint32_t *vals = (const uint32_t *)buf;\n    \n    if (iwx_nic_lock(sc)) {\n        IWX_WRITE(sc, IWX_HBUS_TARG_MEM_WADDR, addr);\n        /* WADDR auto-increments */\n        for (offs = 0; offs < dwords; offs++) {\n            uint32_t val = vals ? vals[offs] : 0;\n            IWX_WRITE(sc, IWX_HBUS_TARG_MEM_WDAT, val);\n        }\n        iwx_nic_unlock(sc);\n    } else {\n        return EBUSY;\n    }\n    return 0;\n}\n\nint ItlIwx::\niwx_write_mem32(struct iwx_softc *sc, uint32_t addr, uint32_t val)\n{\n    return iwx_write_mem(sc, addr, &val, 1);\n}\n\nint ItlIwx::\niwx_poll_bit(struct iwx_softc *sc, int reg, uint32_t bits, uint32_t mask,\n             int timo)\n{\n    for (;;) {\n        if ((IWX_READ(sc, reg) & mask) == (bits & mask)) {\n            return 1;\n        }\n        if (timo < 10) {\n            return 0;\n        }\n        timo -= 10;\n        DELAY(10);\n    }\n}\n\nint ItlIwx::\niwx_nic_lock(struct iwx_softc *sc)\n{\n    if (sc->sc_nic_locks > 0) {\n        iwx_nic_assert_locked(sc);\n        sc->sc_nic_locks++;\n        return 1; /* already locked */\n    }\n    \n    IWX_SETBITS(sc, IWX_CSR_GP_CNTRL,\n                IWX_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);\n    \n    DELAY(2);\n    \n    if (iwx_poll_bit(sc, IWX_CSR_GP_CNTRL,\n                     IWX_CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,\n                     IWX_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY\n                     | IWX_CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP, 150000)) {\n        sc->sc_nic_locks++;\n        return 1;\n    }\n    \n    XYLog(\"%s: acquiring device failed\\n\", DEVNAME(sc));\n    return 0;\n}\n\nvoid ItlIwx::\niwx_nic_assert_locked(struct iwx_softc *sc)\n{\n    if (sc->sc_nic_locks <= 0)\n        panic(\"%s: nic locks counter %d\", DEVNAME(sc), sc->sc_nic_locks);\n}\n\nvoid ItlIwx::\niwx_nic_unlock(struct iwx_softc *sc)\n{\n    if (sc->sc_nic_locks > 0) {\n        if (--sc->sc_nic_locks == 0)\n            IWX_CLRBITS(sc, IWX_CSR_GP_CNTRL,\n                        IWX_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);\n    } else\n        XYLog(\"%s: NIC already unlocked\\n\", DEVNAME(sc));\n}\n\nvoid ItlIwx::\niwx_set_bits_mask_prph(struct iwx_softc *sc, uint32_t reg, uint32_t bits,\n                       uint32_t mask)\n{\n    uint32_t val;\n    \n    /* XXX: no error path? */\n    if (iwx_nic_lock(sc)) {\n        val = iwx_read_prph(sc, reg) & mask;\n        val |= bits;\n        iwx_write_prph(sc, reg, val);\n        iwx_nic_unlock(sc);\n    }\n}\n\nvoid ItlIwx::\niwx_set_bits_prph(struct iwx_softc *sc, uint32_t reg, uint32_t bits)\n{\n    iwx_set_bits_mask_prph(sc, reg, bits, ~0);\n}\n\nvoid ItlIwx::\niwx_clear_bits_prph(struct iwx_softc *sc, uint32_t reg, uint32_t bits)\n{\n    iwx_set_bits_mask_prph(sc, reg, 0, ~bits);\n}\n\nbool allocDmaMemory2(struct iwx_dma_info *dma, size_t size, int alignment)\n{\n    IOBufferMemoryDescriptor *bmd;\n    IODMACommand::Segment64 seg;\n    UInt64 ofs = 0;\n    UInt32 numSegs = 1;\n    \n    bmd = IOBufferMemoryDescriptor::inTaskWithPhysicalMask(kernel_task, kIODirectionInOut | kIOMemoryPhysicallyContiguous | kIOMapInhibitCache, size, DMA_BIT_MASK(64));\n    \n    if (bmd == NULL) {\n        XYLog(\"%s alloc DMA memory failed.\\n\", __FUNCTION__);\n        return false;\n    }\n    \n    if (bmd->prepare() != kIOReturnSuccess) {\n        XYLog(\"%s prepare DMA memory failed.\\n\", __FUNCTION__);\n        bmd->release();\n        bmd = NULL;\n        return false;\n    }\n    IODMACommand *cmd = IODMACommand::withSpecification(kIODMACommandOutputHost64, 64, 0, IODMACommand::kMapped, 0, alignment);\n    \n    if (cmd == NULL) {\n        XYLog(\"%s alloc IODMACommand memory failed.\\n\", __FUNCTION__);\n        bmd->complete();\n        bmd->release();\n        return false;\n    }\n\n    if (cmd->setMemoryDescriptor(bmd) != kIOReturnSuccess\n        || cmd->gen64IOVMSegments(&ofs, &seg, &numSegs) != kIOReturnSuccess) {\n        cmd->release();\n        cmd = NULL;\n        bmd->complete();\n        bmd->release();\n        bmd = NULL;\n        return false;\n    }\n    dma->paddr = seg.fIOVMAddr;\n    dma->vaddr = bmd->getBytesNoCopy();\n    dma->size = size;\n    dma->buffer = bmd;\n    dma->cmd = cmd;\n    memset(dma->vaddr, 0, dma->size);\n    return true;\n}\n\nint ItlIwx::\niwx_dma_contig_alloc(bus_dma_tag_t tag, struct iwx_dma_info *dma,\n                     bus_size_t size, bus_size_t alignment)\n{\n    if (!allocDmaMemory2(dma, size, alignment)) {\n        return 1;\n    }\n    \n    return 0;\n}\n\nvoid ItlIwx::\niwx_dma_contig_free(struct iwx_dma_info *dma)\n{\n    if (dma == NULL || dma->cmd == NULL)\n        return;\n    if (dma->vaddr == NULL)\n        return;\n    dma->cmd->clearMemoryDescriptor();\n    dma->cmd->release();\n    dma->cmd = NULL;\n    dma->buffer->complete();\n    dma->buffer->release();\n    dma->buffer = NULL;\n    dma->vaddr = NULL;\n}\n\n/**\n * struct iwl_rx_transfer_desc - transfer descriptor\n * @addr: ptr to free buffer start address\n * @rbid: unique tag of the buffer\n * @reserved: reserved\n */\nstruct iwx_rx_transfer_desc {\n    uint16_t rbid;\n    uint16_t reserved[3];\n    uint64_t addr;\n} __packed;\n\nint ItlIwx::\niwx_alloc_rx_ring(struct iwx_softc *sc, struct iwx_rx_ring *ring)\n{\n    bus_size_t size;\n    int i, err;\n    int rb_stts_size = sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210 ? sizeof(uint16_t) : sizeof(iwx_rb_status);\n    int rb_stts_align = sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210 ? 0 : 16;\n    \n    ring->cur = 0;\n    \n    /* Allocate RX descriptors (256-byte aligned). */\n    size = IWX_RX_MQ_RING_COUNT * (sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210 ? sizeof(struct iwx_rx_transfer_desc) : sizeof(uint64_t));\n    err = iwx_dma_contig_alloc(sc->sc_dmat, &ring->free_desc_dma, size, 256);\n    if (err) {\n        XYLog(\"%s: could not allocate RX ring DMA memory\\n\",\n              DEVNAME(sc));\n        goto fail;\n    }\n    ring->desc = ring->free_desc_dma.vaddr;\n    \n    /* Allocate RX status area (16-byte aligned). */\n    err = iwx_dma_contig_alloc(sc->sc_dmat, &ring->stat_dma,\n                               rb_stts_size, rb_stts_align);\n    if (err) {\n        XYLog(\"%s: could not allocate RX status DMA memory\\n\",\n              DEVNAME(sc));\n        goto fail;\n    }\n    ring->stat = ring->stat_dma.vaddr;\n    \n    size = IWX_RX_MQ_RING_COUNT * (sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210 ? sizeof(struct iwx_rx_completion_desc) : sizeof(uint32_t));\n    err = iwx_dma_contig_alloc(sc->sc_dmat, &ring->used_desc_dma,\n                               size, 256);\n    if (err) {\n        XYLog(\"%s: could not allocate RX ring DMA memory\\n\",\n              DEVNAME(sc));\n        goto fail;\n    }\n    \n    for (i = 0; i < IWX_RX_MQ_RING_COUNT; i++) {\n        struct iwx_rx_data *data = &ring->data[i];\n        \n        memset(data, 0, sizeof(*data));\n        err = bus_dmamap_create(sc->sc_dmat, IWX_RBUF_SIZE, 1,\n                                IWX_RBUF_SIZE, 0, BUS_DMA_NOWAIT,\n                                &data->map);\n        if (err) {\n            XYLog(\"%s: could not create RX buf DMA map\\n\",\n                  DEVNAME(sc));\n            goto fail;\n        }\n        \n        err = iwx_rx_addbuf(sc, IWX_RBUF_SIZE, i);\n        if (err)\n            goto fail;\n    }\n    return 0;\n    \nfail:    iwx_free_rx_ring(sc, ring);\n    return err;\n}\n\nvoid ItlIwx::\niwx_disable_rx_dma(struct iwx_softc *sc)\n{\n    int ntries;\n    \n    if (iwx_nic_lock(sc)) {\n        if (sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210) {\n            iwx_write_umac_prph(sc, IWX_RFH_RXF_DMA_CFG_GEN3, 0);\n            for (ntries = 0; ntries < 1000; ntries++) {\n                if (iwx_read_umac_prph(sc, IWX_RFH_GEN_STATUS_GEN3) &\n                    IWX_RXF_DMA_IDLE)\n                    break;\n                DELAY(10);\n            }\n        } else {\n            iwx_write_prph(sc, IWX_RFH_RXF_DMA_CFG, 0);\n            for (ntries = 0; ntries < 1000; ntries++) {\n                if (iwx_read_prph(sc, IWX_RFH_GEN_STATUS) &\n                    IWX_RXF_DMA_IDLE)\n                    break;\n                DELAY(10);\n            }\n        }\n        iwx_nic_unlock(sc);\n    }\n}\n\nvoid ItlIwx::\niwx_reset_rx_ring(struct iwx_softc *sc, struct iwx_rx_ring *ring)\n{\n    ring->cur = 0;\n    //    bus_dmamap_sync(sc->sc_dmat, ring->stat_dma.map, 0,\n    //        ring->stat_dma.size, BUS_DMASYNC_PREWRITE);\n    if (sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210)\n        memset(ring->stat, 0, sizeof(uint16_t));\n    else\n        memset(ring->stat, 0, sizeof(struct iwx_rb_status));\n    //    bus_dmamap_sync(sc->sc_dmat, ring->stat_dma.map, 0,\n    //        ring->stat_dma.size, BUS_DMASYNC_POSTWRITE);\n    \n}\n\nvoid ItlIwx::\niwx_free_rx_ring(struct iwx_softc *sc, struct iwx_rx_ring *ring)\n{\n    int i;\n    \n    iwx_dma_contig_free(&ring->free_desc_dma);\n    iwx_dma_contig_free(&ring->stat_dma);\n    iwx_dma_contig_free(&ring->used_desc_dma);\n    \n    for (i = 0; i < IWX_RX_MQ_RING_COUNT; i++) {\n        struct iwx_rx_data *data = &ring->data[i];\n        \n        if (data->m != NULL) {\n            //            bus_dmamap_sync(sc->sc_dmat, data->map, 0,\n            //                data->map->dm_mapsize, BUS_DMASYNC_POSTREAD);\n            //            bus_dmamap_unload(sc->sc_dmat, data->map);\n            mbuf_freem(data->m);\n            data->m = NULL;\n        }\n        if (data->map != NULL) {\n            bus_dmamap_destroy(sc->sc_dmat, data->map);\n            data->map = NULL;\n        }\n    }\n}\n\nvoid ItlIwx::\niwx_tx_ring_init(struct iwx_softc *sc, struct iwx_tx_ring *ring, int size)\n{\n    int low_mark, high_mark;\n\n    ring->ring_count = size;\n    low_mark = ring->ring_count / 4;\n    if (low_mark < 4)\n        low_mark = 4;\n    ring->low_mark = ring->ring_count - low_mark;\n\n    high_mark = ring->ring_count / 8;\n    if (high_mark < 2)\n        high_mark = 2;\n    ring->hi_mark = ring->ring_count - high_mark;\n    ring->queued = 0;\n    ring->cur = 0;\n    ring->tail = 0;\n}\n\nint ItlIwx::\niwx_alloc_tx_ring(struct iwx_softc *sc, struct iwx_tx_ring *ring, int qid)\n{\n    bus_addr_t paddr;\n    bus_size_t size;\n    int i, err;\n\n    /* 0:CMD 2:MGMT */\n    if (qid > IWX_QID_MGMT) {\n        ring->qid = IWX_INVALID_QUEUE;\n        return 0;\n    }\n    \n    if (sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210) {\n        if (qid == IWX_DQA_CMD_QUEUE)\n            size = IWX_CMD_QUEUE_SIZE_GEN3;\n        else\n            size = IWX_MIN_256_BA_QUEUE_SIZE_GEN3;\n    }\n    else {\n        if (qid == IWX_DQA_CMD_QUEUE)\n            size = IWX_CMD_QUEUE_SIZE;\n        else\n            size = IWX_DEFAULT_QUEUE_SIZE;\n    }\n    iwx_tx_ring_init(sc, ring, size);\n    ring->qid = qid;\n    /* Allocate TX descriptors (256-byte aligned). */\n    size = ring->ring_count * sizeof (struct iwx_tfh_tfd);\n    err = iwx_dma_contig_alloc(sc->sc_dmat, &ring->desc_dma, size, 256);\n    if (err) {\n        XYLog(\"%s: could not allocate TX ring DMA memory\\n\",\n              DEVNAME(sc));\n        goto fail;\n    }\n    ring->desc = (struct iwx_tfh_tfd*)ring->desc_dma.vaddr;\n\n    if (sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210)\n        err = iwx_dma_contig_alloc(sc->sc_dmat, &ring->bc_tbl,\n                                   sizeof(struct iwx_gen3_bc_tbl), 0);\n    else\n        err = iwx_dma_contig_alloc(sc->sc_dmat, &ring->bc_tbl,\n                                   sizeof(struct iwx_agn_scd_bc_tbl), 0);\n    if (err) {\n        XYLog(\"%s: could not allocate byte count table DMA memory\\n\",\n              DEVNAME(sc));\n        goto fail;\n    }\n    \n    size = ring->ring_count * sizeof(struct iwx_device_cmd);\n    err = iwx_dma_contig_alloc(sc->sc_dmat, &ring->cmd_dma, size,\n                               IWX_FIRST_TB_SIZE_ALIGN);\n    if (err) {\n        XYLog(\"%s: could not allocate cmd DMA memory\\n\", DEVNAME(sc));\n        goto fail;\n    }\n    ring->cmd = (struct iwx_device_cmd*)ring->cmd_dma.vaddr;\n    \n    paddr = ring->cmd_dma.paddr;\n    for (i = 0; i < ring->ring_count; i++) {\n        struct iwx_tx_data *data = &ring->data[i];\n        size_t mapsize;\n        \n        data->cmd_paddr = paddr;\n        paddr += sizeof(struct iwx_device_cmd);\n        \n        /* FW commands may require more mapped space than packets. */\n        if (qid == IWX_DQA_CMD_QUEUE)\n            mapsize = (sizeof(struct iwx_cmd_header) +\n                       IWX_MAX_CMD_PAYLOAD_SIZE);\n        else\n            mapsize = MCLBYTES;\n        err = bus_dmamap_create(sc->sc_dmat, mapsize,\n                                IWX_TFH_NUM_TBS - 2, mapsize, 0, BUS_DMA_NOWAIT,\n                                &data->map);\n        if (err) {\n            XYLog(\"%s: could not create TX buf DMA map\\n\",\n                  DEVNAME(sc));\n            goto fail;\n        }\n    }\n    KASSERT(paddr == ring->cmd_dma.paddr + size, \"paddr == ring->cmd_dma.paddr + size\");\n    return 0;\n    \nfail:    iwx_free_tx_ring(sc, ring);\n    return err;\n}\n\nvoid ItlIwx::\niwx_reset_tx_ring(struct iwx_softc *sc, struct iwx_tx_ring *ring)\n{\n    int i;\n    \n    for (i = 0; i < ring->ring_count; i++) {\n        struct iwx_tx_data *data = &ring->data[i];\n        \n        if (data->m != NULL) {\n            //            bus_dmamap_sync(sc->sc_dmat, data->map, 0,\n            //                data->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);\n            //            bus_dmamap_unload(sc->sc_dmat, data->map);\n            mbuf_freem(data->m);\n            data->m = NULL;\n        }\n    }\n\n    if (ring->qid == IWX_INVALID_QUEUE || !ring->desc) {\n        return;\n    }\n    \n    /* Clear byte count table. */\n    memset(ring->bc_tbl.vaddr, 0, ring->bc_tbl.size);\n    \n    /* Clear TX descriptors. */\n    memset(ring->desc, 0, ring->desc_dma.size);\n    //    bus_dmamap_sync(sc->sc_dmat, ring->desc_dma.map, 0,\n    //        ring->desc_dma.size, BUS_DMASYNC_PREWRITE);\n    sc->qfullmsk &= ~(1 << ring->qid);\n    ring->queued = 0;\n    ring->cur = 0;\n    ring->tail = 0;\n}\n\nvoid ItlIwx::\niwx_free_tx_ring(struct iwx_softc *sc, struct iwx_tx_ring *ring)\n{\n    int i;\n    \n    iwx_dma_contig_free(&ring->desc_dma);\n    iwx_dma_contig_free(&ring->cmd_dma);\n    iwx_dma_contig_free(&ring->bc_tbl);\n    \n    for (i = 0; i < ring->ring_count; i++) {\n        struct iwx_tx_data *data = &ring->data[i];\n        \n        if (data->m != NULL) {\n            //            bus_dmamap_sync(sc->sc_dmat, data->map, 0,\n            //                data->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);\n            //            bus_dmamap_unload(sc->sc_dmat, data->map);\n            mbuf_freem(data->m);\n            data->m = NULL;\n        }\n        if (data->map != NULL) {\n            bus_dmamap_destroy(sc->sc_dmat, data->map);\n            data->map = NULL;\n        }\n    }\n    ring->qid = IWX_INVALID_QUEUE;\n    ring->hi_mark = 0;\n    ring->low_mark = 0;\n    ring->ring_count = 0;\n}\n\nvoid ItlIwx::\niwx_enable_rfkill_int(struct iwx_softc *sc)\n{\n    if (!sc->sc_msix) {\n        sc->sc_intmask = IWX_CSR_INT_BIT_RF_KILL;\n        IWX_WRITE(sc, IWX_CSR_INT_MASK, sc->sc_intmask);\n    } else {\n        IWX_WRITE(sc, IWX_CSR_MSIX_FH_INT_MASK_AD,\n                  sc->sc_fh_init_mask);\n        IWX_WRITE(sc, IWX_CSR_MSIX_HW_INT_MASK_AD,\n                  ~IWX_MSIX_HW_INT_CAUSES_REG_RF_KILL);\n        sc->sc_hw_mask = IWX_MSIX_HW_INT_CAUSES_REG_RF_KILL;\n    }\n    \n    IWX_SETBITS(sc, IWX_CSR_GP_CNTRL,\n                IWX_CSR_GP_CNTRL_REG_FLAG_RFKILL_WAKE_L1A_EN);\n}\n\nint ItlIwx::\niwx_check_rfkill(struct iwx_softc *sc)\n{\n    uint32_t v;\n    int s;\n    int rv;\n    \n    s = splnet();\n    \n    /*\n     * \"documentation\" is not really helpful here:\n     *  27:    HW_RF_KILL_SW\n     *    Indicates state of (platform's) hardware RF-Kill switch\n     *\n     * But apparently when it's off, it's on ...\n     */\n    v = IWX_READ(sc, IWX_CSR_GP_CNTRL);\n    rv = (v & IWX_CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) == 0;\n    if (rv) {\n        sc->sc_flags |= IWX_FLAG_RFKILL;\n    } else {\n        sc->sc_flags &= ~IWX_FLAG_RFKILL;\n    }\n    \n    XYLog(\"%s RF_KILL hw: %d\\n\", __FUNCTION__, rv);\n\n    splx(s);\n    return rv;\n}\n\nvoid ItlIwx::\niwx_enable_interrupts(struct iwx_softc *sc)\n{\n    if (!sc->sc_msix) {\n        sc->sc_intmask = IWX_CSR_INI_SET_MASK;\n        IWX_WRITE(sc, IWX_CSR_INT_MASK, sc->sc_intmask);\n    } else {\n        /*\n         * fh/hw_mask keeps all the unmasked causes.\n         * Unlike msi, in msix cause is enabled when it is unset.\n         */\n        sc->sc_hw_mask = sc->sc_hw_init_mask;\n        sc->sc_fh_mask = sc->sc_fh_init_mask;\n        IWX_WRITE(sc, IWX_CSR_MSIX_FH_INT_MASK_AD,\n                  ~sc->sc_fh_mask);\n        IWX_WRITE(sc, IWX_CSR_MSIX_HW_INT_MASK_AD,\n                  ~sc->sc_hw_mask);\n    }\n}\n\nvoid ItlIwx::\niwx_enable_fwload_interrupt(struct iwx_softc *sc)\n{\n    \n    XYLog(\"%s\\n\", __FUNCTION__);\n    if (!sc->sc_msix) {\n        sc->sc_intmask = IWX_CSR_INT_BIT_ALIVE | IWX_CSR_INT_BIT_FH_RX;\n        IWX_WRITE(sc, IWX_CSR_INT_MASK, sc->sc_intmask);\n    } else {\n        IWX_WRITE(sc, IWX_CSR_MSIX_HW_INT_MASK_AD,\n                  ~IWX_MSIX_HW_INT_CAUSES_REG_ALIVE);\n        sc->sc_hw_mask = IWX_MSIX_HW_INT_CAUSES_REG_ALIVE;\n        /*\n         * Leave all the FH causes enabled to get the ALIVE\n         * notification.\n         */\n        IWX_WRITE(sc, IWX_CSR_MSIX_FH_INT_MASK_AD,\n                  ~sc->sc_fh_init_mask);\n        sc->sc_fh_mask = sc->sc_fh_init_mask;\n    }\n}\n\nvoid ItlIwx::\niwx_restore_interrupts(struct iwx_softc *sc)\n{\n    IWX_WRITE(sc, IWX_CSR_INT_MASK, sc->sc_intmask);\n}\n\nvoid ItlIwx::\niwx_disable_interrupts(struct iwx_softc *sc)\n{\n    int s = splnet();\n    \n    if (!sc->sc_msix) {\n        IWX_WRITE(sc, IWX_CSR_INT_MASK, 0);\n        \n        /* acknowledge all interrupts */\n        IWX_WRITE(sc, IWX_CSR_INT, ~0);\n        IWX_WRITE(sc, IWX_CSR_FH_INT_STATUS, ~0);\n    } else {\n        IWX_WRITE(sc, IWX_CSR_MSIX_FH_INT_MASK_AD,\n                  sc->sc_fh_init_mask);\n        IWX_WRITE(sc, IWX_CSR_MSIX_HW_INT_MASK_AD,\n                  sc->sc_hw_init_mask);\n    }\n    \n    splx(s);\n}\n\nvoid ItlIwx::\niwx_ict_reset(struct iwx_softc *sc)\n{\n    iwx_disable_interrupts(sc);\n    \n    memset(sc->ict_dma.vaddr, 0, IWX_ICT_SIZE);\n    sc->ict_cur = 0;\n    \n    /* Set physical address of ICT (4KB aligned). */\n    IWX_WRITE(sc, IWX_CSR_DRAM_INT_TBL_REG,\n              IWX_CSR_DRAM_INT_TBL_ENABLE\n              | IWX_CSR_DRAM_INIT_TBL_WRAP_CHECK\n              | IWX_CSR_DRAM_INIT_TBL_WRITE_POINTER\n              | sc->ict_dma.paddr >> IWX_ICT_PADDR_SHIFT);\n    \n    /* Switch to ICT interrupt mode in driver. */\n    sc->sc_flags |= IWX_FLAG_USE_ICT;\n    \n    IWX_WRITE(sc, IWX_CSR_INT, sc->sc_intmask);\n    iwx_enable_interrupts(sc);\n}\n\n#define IWX_HW_READY_TIMEOUT 50\nint ItlIwx::\niwx_set_hw_ready(struct iwx_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    int ready;\n    \n    IWX_SETBITS(sc, IWX_CSR_HW_IF_CONFIG_REG,\n                IWX_CSR_HW_IF_CONFIG_REG_BIT_NIC_READY);\n    \n    ready = iwx_poll_bit(sc, IWX_CSR_HW_IF_CONFIG_REG,\n                         IWX_CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,\n                         IWX_CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,\n                         IWX_HW_READY_TIMEOUT);\n    if (ready)\n        IWX_SETBITS(sc, IWX_CSR_MBOX_SET_REG,\n                    IWX_CSR_MBOX_SET_REG_OS_ALIVE);\n    \n    return ready;\n}\n#undef IWX_HW_READY_TIMEOUT\n\nint ItlIwx::\niwx_prepare_card_hw(struct iwx_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    int t = 0;\n    int ntries;\n    \n    if (iwx_set_hw_ready(sc))\n        return 0;\n    \n    IWX_SETBITS(sc, IWX_CSR_DBG_LINK_PWR_MGMT_REG,\n                IWX_CSR_RESET_LINK_PWR_MGMT_DISABLED);\n    DELAY(1000);\n    \n    \n    for (ntries = 0; ntries < 10; ntries++) {\n        /* If HW is not ready, prepare the conditions to check again */\n        IWX_SETBITS(sc, IWX_CSR_HW_IF_CONFIG_REG,\n                    IWX_CSR_HW_IF_CONFIG_REG_PREPARE);\n        \n        do {\n            if (iwx_set_hw_ready(sc))\n                return 0;\n            DELAY(200);\n            t += 200;\n        } while (t < 150000);\n        DELAY(25000);\n    }\n    \n    return ETIMEDOUT;\n}\n\nvoid ItlIwx::\niwx_apm_config(struct iwx_softc *sc)\n{\n    pcireg_t lctl, cap;\n    \n    /*\n     * L0S states have been found to be unstable with our devices\n     * and in newer hardware they are not officially supported at\n     * all, so we must always set the L0S_DISABLED bit.\n     */\n    IWX_SETBITS(sc, IWX_CSR_GIO_REG, IWX_CSR_GIO_REG_VAL_L0S_DISABLED);\n    lctl = pci_conf_read(sc->sc_pct, sc->sc_pcitag,\n                         sc->sc_cap_off + PCI_PCIE_LCSR);\n    /*\n     * Disable L0s and L1s in PCIE register because we don't support ASPM now.\n     */\n    lctl &= ~(PCI_PCIE_LCSR_ASPM_L0S | PCI_PCIE_LCSR_ASPM_L1);\n    pci_conf_write(sc->sc_pct, sc->sc_pcitag, sc->sc_cap_off + PCI_PCIE_LCSR, lctl);\n    lctl = pci_conf_read(sc->sc_pct, sc->sc_pcitag, sc->sc_cap_off + PCI_PCIE_LCSR);\n    \n    cap = pci_conf_read(sc->sc_pct, sc->sc_pcitag,\n                        sc->sc_cap_off + PCI_PCIE_DCSR2);\n    sc->sc_ltr_enabled = (cap & PCI_PCIE_DCSR2_LTREN) ? 1 : 0;\n    DPRINTF((\"%s: L1 %sabled - LTR %sabled\\n\",\n             DEVNAME(sc),\n             (lctl & PCI_PCIE_LCSR_ASPM_L1) ? \"En\" : \"Dis\",\n             sc->sc_ltr_enabled ? \"En\" : \"Dis\"));\n}\n\n/*\n * Start up NIC's basic functionality after it has been reset\n * e.g. after platform boot or shutdown.\n * NOTE:  This does not load uCode nor start the embedded processor\n */\nint ItlIwx::\niwx_apm_init(struct iwx_softc *sc)\n{\n    int err = 0;\n    \n    /*\n     * Disable L0s without affecting L1;\n     *  don't wait for ICH L0s (ICH bug W/A)\n     */\n    IWX_SETBITS(sc, IWX_CSR_GIO_CHICKEN_BITS,\n                IWX_CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX);\n    \n    /* Set FH wait threshold to maximum (HW error during stress W/A) */\n    IWX_SETBITS(sc, IWX_CSR_DBG_HPET_MEM_REG, IWX_CSR_DBG_HPET_MEM_REG_VAL);\n    \n    /*\n     * Enable HAP INTA (interrupt from management bus) to\n     * wake device's PCI Express link L1a -> L0s\n     */\n    IWX_SETBITS(sc, IWX_CSR_HW_IF_CONFIG_REG,\n                IWX_CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A);\n    \n    iwx_apm_config(sc);\n    \n    /*\n     * Set \"initialization complete\" bit to move adapter from\n     * D0U* --> D0A* (powered-up active) state.\n     */\n    IWX_SETBITS(sc, IWX_CSR_GP_CNTRL, IWX_CSR_GP_CNTRL_REG_FLAG_INIT_DONE);\n    \n    /*\n     * Wait for clock stabilization; once stabilized, access to\n     * device-internal resources is supported, e.g. iwx_write_prph()\n     * and accesses to uCode SRAM.\n     */\n    if (!iwx_poll_bit(sc, IWX_CSR_GP_CNTRL,\n                      IWX_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,\n                      IWX_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000)) {\n        XYLog(\"%s: timeout waiting for clock stabilization\\n\",\n              DEVNAME(sc));\n        err = ETIMEDOUT;\n        goto out;\n    }\nout:\n    if (err)\n        XYLog(\"%s: apm init error %d\\n\", DEVNAME(sc), err);\n    return err;\n}\n\nvoid ItlIwx::\niwx_apm_stop(struct iwx_softc *sc)\n{\n    IWX_SETBITS(sc, IWX_CSR_DBG_LINK_PWR_MGMT_REG,\n                IWX_CSR_RESET_LINK_PWR_MGMT_DISABLED);\n    IWX_SETBITS(sc, IWX_CSR_HW_IF_CONFIG_REG,\n                IWX_CSR_HW_IF_CONFIG_REG_PREPARE |\n                IWX_CSR_HW_IF_CONFIG_REG_ENABLE_PME);\n    DELAY(1000);\n    IWX_CLRBITS(sc, IWX_CSR_DBG_LINK_PWR_MGMT_REG,\n                IWX_CSR_RESET_LINK_PWR_MGMT_DISABLED);\n    DELAY(5000);\n    \n    /* stop device's busmaster DMA activity */\n    IWX_SETBITS(sc, IWX_CSR_RESET, IWX_CSR_RESET_REG_FLAG_STOP_MASTER);\n    \n    if (!iwx_poll_bit(sc, IWX_CSR_RESET,\n                      IWX_CSR_RESET_REG_FLAG_MASTER_DISABLED,\n                      IWX_CSR_RESET_REG_FLAG_MASTER_DISABLED, 100))\n        XYLog(\"%s: timeout waiting for master\\n\", DEVNAME(sc));\n    \n    /*\n     * Clear \"initialization complete\" bit to move adapter from\n     * D0A* (powered-up Active) --> D0U* (Uninitialized) state.\n     */\n    IWX_CLRBITS(sc, IWX_CSR_GP_CNTRL,\n                IWX_CSR_GP_CNTRL_REG_FLAG_INIT_DONE);\n}\n\nvoid ItlIwx::\niwx_init_msix_hw(struct iwx_softc *sc)\n{\n    iwx_conf_msix_hw(sc, 0);\n    \n    if (!sc->sc_msix)\n        return;\n    \n    sc->sc_fh_init_mask = ~IWX_READ(sc, IWX_CSR_MSIX_FH_INT_MASK_AD);\n    sc->sc_fh_mask = sc->sc_fh_init_mask;\n    sc->sc_hw_init_mask = ~IWX_READ(sc, IWX_CSR_MSIX_HW_INT_MASK_AD);\n    sc->sc_hw_mask = sc->sc_hw_init_mask;\n}\n\nvoid ItlIwx::\niwx_conf_msix_hw(struct iwx_softc *sc, int stopped)\n{\n    int vector = 0;\n    \n    if (!sc->sc_msix) {\n        /* Newer chips default to MSIX. */\n        if (!stopped && iwx_nic_lock(sc)) {\n            iwx_write_umac_prph(sc, IWX_UREG_CHICK,\n                           IWX_UREG_CHICK_MSI_ENABLE);\n            iwx_nic_unlock(sc);\n        }\n        return;\n    }\n    \n    if (!stopped && iwx_nic_lock(sc)) {\n        iwx_write_umac_prph(sc, IWX_UREG_CHICK, IWX_UREG_CHICK_MSIX_ENABLE);\n        iwx_nic_unlock(sc);\n    }\n    \n    /* Disable all interrupts */\n    IWX_WRITE(sc, IWX_CSR_MSIX_FH_INT_MASK_AD, ~0);\n    IWX_WRITE(sc, IWX_CSR_MSIX_HW_INT_MASK_AD, ~0);\n    \n    /* Map fallback-queue (command/mgmt) to a single vector */\n    IWX_WRITE_1(sc, IWX_CSR_MSIX_RX_IVAR(0),\n                vector | IWX_MSIX_NON_AUTO_CLEAR_CAUSE);\n    /* Map RSS queue (data) to the same vector */\n    IWX_WRITE_1(sc, IWX_CSR_MSIX_RX_IVAR(1),\n                vector | IWX_MSIX_NON_AUTO_CLEAR_CAUSE);\n    \n    /* Enable the RX queues cause interrupts */\n    IWX_CLRBITS(sc, IWX_CSR_MSIX_FH_INT_MASK_AD,\n                IWX_MSIX_FH_INT_CAUSES_Q0 | IWX_MSIX_FH_INT_CAUSES_Q1);\n    \n    /* Map non-RX causes to the same vector */\n    IWX_WRITE_1(sc, IWX_CSR_MSIX_IVAR(IWX_MSIX_IVAR_CAUSE_D2S_CH0_NUM),\n                vector | IWX_MSIX_NON_AUTO_CLEAR_CAUSE);\n    IWX_WRITE_1(sc, IWX_CSR_MSIX_IVAR(IWX_MSIX_IVAR_CAUSE_D2S_CH1_NUM),\n                vector | IWX_MSIX_NON_AUTO_CLEAR_CAUSE);\n    IWX_WRITE_1(sc, IWX_CSR_MSIX_IVAR(IWX_MSIX_IVAR_CAUSE_S2D),\n                vector | IWX_MSIX_NON_AUTO_CLEAR_CAUSE);\n    IWX_WRITE_1(sc, IWX_CSR_MSIX_IVAR(IWX_MSIX_IVAR_CAUSE_FH_ERR),\n                vector | IWX_MSIX_NON_AUTO_CLEAR_CAUSE);\n    IWX_WRITE_1(sc, IWX_CSR_MSIX_IVAR(IWX_MSIX_IVAR_CAUSE_REG_ALIVE),\n                vector | IWX_MSIX_NON_AUTO_CLEAR_CAUSE);\n    IWX_WRITE_1(sc, IWX_CSR_MSIX_IVAR(IWX_MSIX_IVAR_CAUSE_REG_WAKEUP),\n                vector | IWX_MSIX_NON_AUTO_CLEAR_CAUSE);\n    IWX_WRITE_1(sc, IWX_CSR_MSIX_IVAR(IWX_MSIX_IVAR_CAUSE_REG_IML),\n                vector | IWX_MSIX_NON_AUTO_CLEAR_CAUSE);\n    IWX_WRITE_1(sc, IWX_CSR_MSIX_IVAR(IWX_MSIX_IVAR_CAUSE_REG_CT_KILL),\n                vector | IWX_MSIX_NON_AUTO_CLEAR_CAUSE);\n    IWX_WRITE_1(sc, IWX_CSR_MSIX_IVAR(IWX_MSIX_IVAR_CAUSE_REG_RF_KILL),\n                vector | IWX_MSIX_NON_AUTO_CLEAR_CAUSE);\n    IWX_WRITE_1(sc, IWX_CSR_MSIX_IVAR(IWX_MSIX_IVAR_CAUSE_REG_PERIODIC),\n                vector | IWX_MSIX_NON_AUTO_CLEAR_CAUSE);\n    IWX_WRITE_1(sc, IWX_CSR_MSIX_IVAR(IWX_MSIX_IVAR_CAUSE_REG_SW_ERR),\n                vector | IWX_MSIX_NON_AUTO_CLEAR_CAUSE);\n    IWX_WRITE_1(sc, IWX_CSR_MSIX_IVAR(IWX_MSIX_IVAR_CAUSE_REG_SCD),\n                vector | IWX_MSIX_NON_AUTO_CLEAR_CAUSE);\n    IWX_WRITE_1(sc, IWX_CSR_MSIX_IVAR(IWX_MSIX_IVAR_CAUSE_REG_FH_TX),\n                vector | IWX_MSIX_NON_AUTO_CLEAR_CAUSE);\n    IWX_WRITE_1(sc, IWX_CSR_MSIX_IVAR(IWX_MSIX_IVAR_CAUSE_REG_HW_ERR),\n                vector | IWX_MSIX_NON_AUTO_CLEAR_CAUSE);\n    IWX_WRITE_1(sc, IWX_CSR_MSIX_IVAR(IWX_MSIX_IVAR_CAUSE_REG_HAP),\n                vector | IWX_MSIX_NON_AUTO_CLEAR_CAUSE);\n    \n    /* Enable non-RX causes interrupts */\n    IWX_CLRBITS(sc, IWX_CSR_MSIX_FH_INT_MASK_AD,\n                IWX_MSIX_FH_INT_CAUSES_D2S_CH0_NUM |\n                IWX_MSIX_FH_INT_CAUSES_D2S_CH1_NUM |\n                IWX_MSIX_FH_INT_CAUSES_S2D |\n                IWX_MSIX_FH_INT_CAUSES_FH_ERR);\n    IWX_CLRBITS(sc, IWX_CSR_MSIX_HW_INT_MASK_AD,\n                IWX_MSIX_HW_INT_CAUSES_REG_ALIVE |\n                IWX_MSIX_HW_INT_CAUSES_REG_WAKEUP |\n                IWX_MSIX_HW_INT_CAUSES_REG_IML |\n                IWX_MSIX_HW_INT_CAUSES_REG_CT_KILL |\n                IWX_MSIX_HW_INT_CAUSES_REG_RF_KILL |\n                IWX_MSIX_HW_INT_CAUSES_REG_PERIODIC |\n                IWX_MSIX_HW_INT_CAUSES_REG_SW_ERR |\n                IWX_MSIX_HW_INT_CAUSES_REG_SCD |\n                IWX_MSIX_HW_INT_CAUSES_REG_FH_TX |\n                IWX_MSIX_HW_INT_CAUSES_REG_HW_ERR |\n                IWX_MSIX_HW_INT_CAUSES_REG_HAP);\n}\n\nint ItlIwx::\niwx_start_hw(struct iwx_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    int err;\n    \n    err = iwx_prepare_card_hw(sc);\n    if (err)\n        return err;\n    \n    iwx_clear_persistence_bit(sc);\n    \n    /* Reset the entire device */\n    IWX_SETBITS(sc, IWX_CSR_RESET, IWX_CSR_RESET_REG_FLAG_SW_RESET);\n    DELAY(5000);\n    \n    if (sc->sc_device_family == IWX_DEVICE_FAMILY_22000 && sc->sc_integrated) {\n        IWX_SETBITS(sc, IWX_CSR_GP_CNTRL,\n                    IWX_CSR_GP_CNTRL_REG_FLAG_INIT_DONE);\n        DELAY(20);\n        if (!iwx_poll_bit(sc, IWX_CSR_GP_CNTRL,\n                          IWX_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,\n                          IWX_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000)) {\n            XYLog(\"%s: timeout waiting for clock stabilization\\n\",\n                  DEVNAME(sc));\n            return ETIMEDOUT;\n        }\n        \n        iwx_force_power_gating(sc);\n        \n        /* Reset the entire device */\n        IWX_SETBITS(sc, IWX_CSR_RESET, IWX_CSR_RESET_REG_FLAG_SW_RESET);\n        DELAY(5000);\n    }\n    \n    err = iwx_apm_init(sc);\n    if (err)\n        return err;\n    \n    iwx_init_msix_hw(sc);\n    \n    iwx_enable_rfkill_int(sc);\n    iwx_check_rfkill(sc);\n    \n    return 0;\n}\n\n\nvoid ItlIwx::\niwx_stop_device(struct iwx_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    int qid;\n    \n    iwx_disable_interrupts(sc);\n    sc->sc_flags &= ~IWX_FLAG_USE_ICT;\n    \n    iwx_disable_rx_dma(sc);\n    iwx_reset_rx_ring(sc, &sc->rxq);\n    for (qid = 0; qid < nitems(sc->txq); qid++)\n        iwx_reset_tx_ring(sc, &sc->txq[qid]);\n    \n    /* Make sure (redundant) we've released our request to stay awake */\n    IWX_CLRBITS(sc, IWX_CSR_GP_CNTRL,\n                IWX_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);\n    if (sc->sc_nic_locks > 0)\n        XYLog(\"%s: %d active NIC locks forcefully cleared\\n\",\n              DEVNAME(sc), sc->sc_nic_locks);\n    sc->sc_nic_locks = 0;\n    \n    /* Stop the device, and put it in low power state */\n    iwx_apm_stop(sc);\n    \n    /* Reset the on-board processor. */\n    IWX_SETBITS(sc, IWX_CSR_RESET, IWX_CSR_RESET_REG_FLAG_SW_RESET);\n    DELAY(5000);\n    \n    /*\n     * Upon stop, the IVAR table gets erased, so msi-x won't\n     * work. This causes a bug in RF-KILL flows, since the interrupt\n     * that enables radio won't fire on the correct irq, and the\n     * driver won't be able to handle the interrupt.\n     * Configure the IVAR table again after reset.\n     */\n    iwx_conf_msix_hw(sc, 1);\n    \n    /*\n     * Upon stop, the APM issues an interrupt if HW RF kill is set.\n     * Clear the interrupt again.\n     */\n    iwx_disable_interrupts(sc);\n    \n    /* Even though we stop the HW we still want the RF kill interrupt. */\n    iwx_enable_rfkill_int(sc);\n    iwx_check_rfkill(sc);\n    \n    iwx_prepare_card_hw(sc);\n    \n    iwx_ctxt_info_free_paging(sc);\n    /* free gen3 devices related firmware DMA resource */\n    iwx_dma_contig_free(&sc->prph_info_dma);\n    iwx_dma_contig_free(&sc->prph_scratch_dma);\n    iwx_dma_contig_free(&sc->iml_dma);\n    iwx_dma_contig_free(&sc->pnvm_dram);\n}\n\nvoid ItlIwx::\niwx_nic_config(struct iwx_softc *sc)\n{\n    uint8_t radio_cfg_type, radio_cfg_step, radio_cfg_dash;\n    uint32_t mask, val, reg_val = 0;\n    \n    radio_cfg_type = (sc->sc_fw_phy_config & IWX_FW_PHY_CFG_RADIO_TYPE) >>\n    IWX_FW_PHY_CFG_RADIO_TYPE_POS;\n    radio_cfg_step = (sc->sc_fw_phy_config & IWX_FW_PHY_CFG_RADIO_STEP) >>\n    IWX_FW_PHY_CFG_RADIO_STEP_POS;\n    radio_cfg_dash = (sc->sc_fw_phy_config & IWX_FW_PHY_CFG_RADIO_DASH) >>\n    IWX_FW_PHY_CFG_RADIO_DASH_POS;\n    \n    reg_val |= IWX_CSR_HW_REV_STEP(sc->sc_hw_rev) <<\n    IWX_CSR_HW_IF_CONFIG_REG_POS_MAC_STEP;\n    reg_val |= IWX_CSR_HW_REV_DASH(sc->sc_hw_rev) <<\n    IWX_CSR_HW_IF_CONFIG_REG_POS_MAC_DASH;\n    \n    /* radio configuration */\n    reg_val |= radio_cfg_type << IWX_CSR_HW_IF_CONFIG_REG_POS_PHY_TYPE;\n    reg_val |= radio_cfg_step << IWX_CSR_HW_IF_CONFIG_REG_POS_PHY_STEP;\n    reg_val |= radio_cfg_dash << IWX_CSR_HW_IF_CONFIG_REG_POS_PHY_DASH;\n    \n    mask = IWX_CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH |\n    IWX_CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP |\n    IWX_CSR_HW_IF_CONFIG_REG_MSK_PHY_STEP |\n    IWX_CSR_HW_IF_CONFIG_REG_MSK_PHY_DASH |\n    IWX_CSR_HW_IF_CONFIG_REG_MSK_PHY_TYPE |\n    IWX_CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |\n    IWX_CSR_HW_IF_CONFIG_REG_BIT_MAC_SI;\n    \n    val = IWX_READ(sc, IWX_CSR_HW_IF_CONFIG_REG);\n    val &= ~mask;\n    val |= reg_val;\n    IWX_WRITE(sc, IWX_CSR_HW_IF_CONFIG_REG, val);\n    \n    XYLog(\"%s Radio type=0x%x-0x%x-0x%x\\n\", __FUNCTION__, radio_cfg_type,\n          radio_cfg_step, radio_cfg_dash);\n}\n\nint ItlIwx::\niwx_nic_rx_init(struct iwx_softc *sc)\n{\n    IWX_WRITE_1(sc, IWX_CSR_INT_COALESCING, IWX_HOST_INT_TIMEOUT_DEF);\n    \n    /*\n     * We don't configure the RFH; the firmware will do that.\n     * Rx descriptors are set when firmware sends an ALIVE interrupt.\n     */\n    return 0;\n}\n\nint ItlIwx::\niwx_nic_init(struct iwx_softc *sc)\n{\n    int err;\n    \n    iwx_apm_init(sc);\n    iwx_nic_config(sc);\n    \n    err = iwx_nic_rx_init(sc);\n    if (err)\n        return err;\n    \n    IWX_SETBITS(sc, IWX_CSR_MAC_SHADOW_REG_CTRL, 0x800fffff);\n    \n    return 0;\n}\n\n/* Map ieee80211_edca_ac categories to firmware Tx FIFO. */\nconst uint8_t iwx_ac_to_tx_fifo[] = {\n    IWX_GEN2_EDCA_TX_FIFO_BE,\n    IWX_GEN2_EDCA_TX_FIFO_BK,\n    IWX_GEN2_EDCA_TX_FIFO_VI,\n    IWX_GEN2_EDCA_TX_FIFO_VO,\n};\n\nint ItlIwx::\niwx_enable_txq(struct iwx_softc *sc, int sta_id, int qid, int tid,\n               int num_slots)\n{\n    \n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwx_tx_queue_cfg_cmd cmd;\n    struct iwx_rx_packet *pkt;\n    struct iwx_tx_queue_cfg_rsp *resp;\n    struct iwx_host_cmd hcmd = {\n        .id = IWX_SCD_QUEUE_CFG,\n        .flags = IWX_CMD_WANT_RESP,\n        .resp_pkt_len = sizeof(*pkt) + sizeof(*resp),\n    };\n    struct iwx_tx_ring *ring = &sc->txq[qid];\n    int err, fwqid;\n    uint32_t wr_idx;\n    size_t resp_len;\n    \n    iwx_reset_tx_ring(sc, ring);\n    \n    memset(&cmd, 0, sizeof(cmd));\n    cmd.sta_id = sta_id;\n    cmd.tid = tid;\n    cmd.flags = htole16(IWX_TX_QUEUE_CFG_ENABLE_QUEUE);\n    cmd.cb_size = htole32(IWX_TFD_QUEUE_CB_SIZE(num_slots));\n    cmd.byte_cnt_addr = htole64(ring->bc_tbl.paddr);\n    cmd.tfdq_addr = htole64(ring->desc_dma.paddr);\n    \n    hcmd.data[0] = &cmd;\n    hcmd.len[0] = sizeof(cmd);\n    \n    err = iwx_send_cmd(sc, &hcmd);\n    if (err)\n        return err;\n    \n    pkt = hcmd.resp_pkt;\n    if (!pkt || (pkt->hdr.group_id & IWX_CMD_FAILED_MSK)) {\n        DPRINTF((\"SCD_QUEUE_CFG command failed\\n\"));\n        err = EIO;\n        goto out;\n    }\n    \n    resp_len = iwx_rx_packet_payload_len(pkt);\n    if (resp_len != sizeof(*resp)) {\n        DPRINTF((\"SCD_QUEUE_CFG returned %zu bytes, expected %zu bytes\\n\", resp_len, sizeof(*resp)));\n        err = EIO;\n        goto out;\n    }\n    \n    resp = (struct iwx_tx_queue_cfg_rsp *)pkt->data;\n    fwqid = le16toh(resp->queue_number);\n    wr_idx = le16toh(resp->write_pointer);\n    \n    /* Unlike iwlwifi, we do not support dynamic queue ID assignment. */\n    if (fwqid != qid) {\n        DPRINTF((\"requested qid %d but %d was assigned\\n\", qid, fwqid));\n        err = EIO;\n        goto out;\n    }\n    \n    if (wr_idx != ring->cur) {\n        DPRINTF((\"fw write index is %d but ring is %d\\n\", wr_idx, ring->cur));\n        err = EIO;\n        goto out;\n    }\nout:\n    iwx_free_resp(sc, &hcmd);\n    return err;\n}\n\nint ItlIwx::\niwx_tvqm_alloc_txq(struct iwx_softc *sc, int tid, int ssn)\n{\n    int queue;\n    //TODO: Here is a bug, for gen3 devices which support 256 frame aggregate into 1 A-MPDU like ax210, if the TfDs count larger than 256 than it would trigger system freeze on macOS, don't know why but Linux can do this. Still need to dig deep into the code or optimize the DMA memory allocation, here I just limit the size to 256 as the temporary solution.\n#ifdef notyet\n    int size = sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210 ? IWX_MIN_256_BA_QUEUE_SIZE_GEN3 : IWX_DEFAULT_QUEUE_SIZE;\n#else\n    int size = IWX_DEFAULT_QUEUE_SIZE;\n#endif\n    \n    do {\n        queue = iwx_tvqm_enable_txq(sc, tid, ssn, size);\n        if (queue < 0)\n            XYLog(\"Failed allocating TXQ of size %d for sta %d tid %d, ret: %d\\n\",\n                  size, IWX_STATION_ID, tid, queue);\n        size /= 2;\n    } while (queue < 0 && size >= 16);\n    \n    if (queue < 0)\n        return queue;\n    sc->sc_tid_data[tid].qid = queue;\n    return queue;\n}\n\nint ItlIwx::\niwx_tvqm_enable_txq(struct iwx_softc *sc, int tid, int ssn, uint32_t size)\n{\n    int err = -1;\n    int i = 0;\n    bus_addr_t paddr;\n    int fwqid;\n    uint32_t wr_idx;\n    size_t resp_len;\n    struct iwx_tx_queue_cfg_cmd cmd = {\n        .flags = htole16(IWX_TX_QUEUE_CFG_ENABLE_QUEUE),\n        .sta_id = IWX_STATION_ID,\n        .tid = (uint8_t)tid,\n    };\n    struct iwx_rx_packet *pkt;\n    struct iwx_tx_queue_cfg_rsp *resp;\n    struct iwx_host_cmd hcmd = {\n        .id = IWX_SCD_QUEUE_CFG,\n        .flags = IWX_CMD_WANT_RESP,\n        .resp_pkt_len = sizeof(*pkt) + sizeof(*resp),\n    };\n    struct iwx_tx_ring *ring = &sc->sc_tvqm_ring;\n    \n    memset(ring, 0, sizeof(*ring));\n    iwx_tx_ring_init(sc, ring, size);\n    /* Allocate TX descriptors (256-byte aligned). */\n    err = iwx_dma_contig_alloc(sc->sc_dmat, &ring->desc_dma, ring->ring_count * sizeof (struct iwx_tfh_tfd), 256);\n    if (err) {\n        XYLog(\"%s: could not allocate TX ring DMA memory\\n\",\n              DEVNAME(sc));\n        err = -ENOMEM;\n        goto fail;\n    }\n    ring->desc = (struct iwx_tfh_tfd*)ring->desc_dma.vaddr;\n    if (sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210)\n        err = iwx_dma_contig_alloc(sc->sc_dmat, &ring->bc_tbl,\n                                   sizeof(struct iwx_gen3_bc_tbl), 0);\n    else\n        err = iwx_dma_contig_alloc(sc->sc_dmat, &ring->bc_tbl,\n                                   sizeof(struct iwx_agn_scd_bc_tbl), 0);\n    if (err) {\n        XYLog(\"%s: could not allocate byte count table DMA memory\\n\",\n              DEVNAME(sc));\n        err = -ENOMEM;\n        goto fail;\n    }\n\n    err = iwx_dma_contig_alloc(sc->sc_dmat, &ring->cmd_dma, ring->ring_count * sizeof(struct iwx_device_cmd), IWX_FIRST_TB_SIZE_ALIGN);\n    if (err) {\n        XYLog(\"%s: could not allocate cmd DMA memory\\n\", DEVNAME(sc));\n        err = -ENOMEM;\n        goto fail;\n    }\n    ring->cmd = (struct iwx_device_cmd*)ring->cmd_dma.vaddr;\n\n    paddr = ring->cmd_dma.paddr;\n    for (i = 0; i < ring->ring_count; i++) {\n        struct iwx_tx_data *data = &ring->data[i];\n\n        data->cmd_paddr = paddr;\n        paddr += sizeof(struct iwx_device_cmd);\n        err = bus_dmamap_create(sc->sc_dmat, MCLBYTES,\n                                IWX_TFH_NUM_TBS - 2, MCLBYTES, 0, BUS_DMA_NOWAIT,\n                                &data->map);\n        if (err) {\n            XYLog(\"%s: could not create TX buf DMA map\\n\",\n                  DEVNAME(sc));\n            err = -EIO;\n            goto fail;\n        }\n    }\n    cmd.cb_size = htole32(IWX_TFD_QUEUE_CB_SIZE(ring->ring_count));\n    cmd.byte_cnt_addr = htole64(ring->bc_tbl.paddr);\n    cmd.tfdq_addr = htole64(ring->desc_dma.paddr);\n\n    hcmd.data[0] = &cmd;\n    hcmd.len[0] = sizeof(cmd);\n\n    err = iwx_send_cmd(sc, &hcmd);\n    if (err)\n        return err;\n\n    pkt = hcmd.resp_pkt;\n    if (!pkt || (pkt->hdr.group_id & IWX_CMD_FAILED_MSK)) {\n        XYLog(\"SCD_QUEUE_CFG command failed\\n\");\n        err = -EIO;\n        goto fail;\n    }\n\n    resp_len = iwx_rx_packet_payload_len(pkt);\n    if (resp_len != sizeof(*resp)) {\n        XYLog(\"SCD_QUEUE_CFG returned %zu bytes, expected %zu bytes\\n\", resp_len, sizeof(*resp));\n        err = -EIO;\n        goto fail;\n    }\n\n    resp = (struct iwx_tx_queue_cfg_rsp *)pkt->data;\n    fwqid = le16toh(resp->queue_number);\n    wr_idx = le16toh(resp->write_pointer);\n    if (fwqid >= ARRAY_SIZE(sc->txq)) {\n        XYLog(\"queue index %d unsupported\", fwqid);\n        err = -EIO;\n        goto fail;\n    }\n    ring->cur = wr_idx;\n    ring->qid = fwqid;\n    iwx_reset_tx_ring(sc, &sc->txq[fwqid]);\n    iwx_free_tx_ring(sc, &sc->txq[fwqid]);\n    memcpy(&sc->txq[fwqid], ring, sizeof(*ring));\n    return fwqid;\nfail:\n    iwx_reset_tx_ring(sc, ring);\n    iwx_free_tx_ring(sc, ring);\n    return err;\n}\n\nvoid ItlIwx::\niwx_post_alive(struct iwx_softc *sc)\n{\n    \n    XYLog(\"%s\\n\", __FUNCTION__);\n    iwx_ict_reset(sc);\n    \n    /*\n     * Re-enable all the interrupts, including the RF-Kill one, now that\n     * the firmware is alive.\n     */\n    iwx_enable_interrupts(sc);\n}\n\n/*\n * For the high priority TE use a time event type that has similar priority to\n * the FW's action scan priority.\n */\n#define IWX_ROC_TE_TYPE_NORMAL IWX_TE_P2P_DEVICE_DISCOVERABLE\n#define IWX_ROC_TE_TYPE_MGMT_TX IWX_TE_P2P_CLIENT_ASSOC\n\nint ItlIwx::\niwx_send_time_event_cmd(struct iwx_softc *sc,\n                        const struct iwx_time_event_cmd *cmd)\n{\n    struct iwx_rx_packet *pkt;\n    struct iwx_time_event_resp *resp;\n    struct iwx_host_cmd hcmd = {\n        .id = IWX_TIME_EVENT_CMD,\n        .flags = IWX_CMD_WANT_RESP,\n        .resp_pkt_len = sizeof(*pkt) + sizeof(*resp),\n    };\n    uint32_t resp_len;\n    int err;\n    \n    hcmd.data[0] = cmd;\n    hcmd.len[0] = sizeof(*cmd);\n    err = iwx_send_cmd(sc, &hcmd);\n    if (err)\n        return err;\n    \n    pkt = hcmd.resp_pkt;\n    if (!pkt || (pkt->hdr.group_id & IWX_CMD_FAILED_MSK)) {\n        err = EIO;\n        goto out;\n    }\n    \n    resp_len = iwx_rx_packet_payload_len(pkt);\n    if (resp_len != sizeof(*resp)) {\n        err = EIO;\n        goto out;\n    }\n    \n    resp = (struct iwx_time_event_resp *)pkt->data;\n    if (le32toh(resp->status) == 0)\n        sc->sc_time_event_uid = le32toh(resp->unique_id);\n    else\n        err = EIO;\nout:\n    iwx_free_resp(sc, &hcmd);\n    return err;\n}\n\nvoid ItlIwx::\niwx_protect_session(struct iwx_softc *sc, struct iwx_node *in,\n                    uint32_t duration, uint32_t max_delay)\n{\n    struct iwx_time_event_cmd time_cmd;\n    \n    /* Do nothing if a time event is already scheduled. */\n    if (sc->sc_flags & IWX_FLAG_TE_ACTIVE)\n        return;\n    \n    memset(&time_cmd, 0, sizeof(time_cmd));\n    \n    time_cmd.action = htole32(IWX_FW_CTXT_ACTION_ADD);\n    time_cmd.id_and_color =\n    htole32(IWX_FW_CMD_ID_AND_COLOR(in->in_id, in->in_color));\n    time_cmd.id = htole32(IWX_TE_BSS_STA_AGGRESSIVE_ASSOC);\n    \n    time_cmd.apply_time = htole32(0);\n    \n    time_cmd.max_frags = IWX_TE_V2_FRAG_NONE;\n    time_cmd.max_delay = htole32(max_delay);\n    /* TODO: why do we need to interval = bi if it is not periodic? */\n    time_cmd.interval = htole32(1);\n    time_cmd.duration = htole32(duration);\n    time_cmd.repeat = 1;\n    time_cmd.policy\n    = htole16(IWX_TE_V2_NOTIF_HOST_EVENT_START |\n              IWX_TE_V2_NOTIF_HOST_EVENT_END |\n              IWX_T2_V2_START_IMMEDIATELY);\n    \n    if (iwx_send_time_event_cmd(sc, &time_cmd) == 0)\n        sc->sc_flags |= IWX_FLAG_TE_ACTIVE;\n    \n    DELAY(100);\n}\n\nint ItlIwx::\niwx_schedule_protect_session(struct iwx_softc *sc, struct iwx_node *in,\n                    uint32_t duration)\n{\n    struct iwx_session_prot_cmd cmd = {\n        .id_and_color =\n            htole32(IWX_FW_CMD_ID_AND_COLOR(in->in_id, in->in_color)),\n        .action = htole32(IWX_FW_CTXT_ACTION_ADD),\n        .duration_tu = htole32(duration * IEEE80211_DUR_TU),\n    };\n    int err;\n    \n    cmd.conf_id = IWX_SESSION_PROTECT_CONF_ASSOC;\n    \n    DPRINTFN(1, (\"Add new session protection, duration %d TU\\n\",\n             htole32(cmd.duration_tu)));\n    \n    err = iwx_send_cmd_pdu(sc, iwx_cmd_id(IWX_SESSION_PROTECTION_CMD, IWX_MAC_CONF_GROUP, 0), 0, sizeof(cmd), &cmd);\n    if (err)\n        XYLog(\"Couldn't send the SESSION_PROTECTION_CMD %d\\n\", err);\n    return err;\n}\n\nint ItlIwx::\niwx_cancel_session_protection(struct iwx_softc *sc, struct iwx_node *in)\n{\n    struct iwx_session_prot_cmd cmd = {\n        .id_and_color =\n            htole32(IWX_FW_CMD_ID_AND_COLOR(in->in_id, in->in_color)),\n        .action = htole32(IWX_FW_CTXT_ACTION_REMOVE),\n        .conf_id = IWX_SESSION_PROTECT_CONF_ASSOC,\n    };\n    int err;\n    \n    DPRINTFN(1, (\"Remove session protection\\n\"));\n    \n    err = iwx_send_cmd_pdu(sc, iwx_cmd_id(IWX_SESSION_PROTECTION_CMD, IWX_MAC_CONF_GROUP, 0), 0, sizeof(cmd), &cmd);\n    if (err)\n        XYLog(\"Couldn't send the Cancel SESSION_PROTECTION_CMD %d\\n\", err);\n    return err;\n}\n\nvoid ItlIwx::\niwx_unprotect_session(struct iwx_softc *sc, struct iwx_node *in)\n{\n    struct iwx_time_event_cmd time_cmd;\n    \n    /* Do nothing if the time event has already ended. */\n    if ((sc->sc_flags & IWX_FLAG_TE_ACTIVE) == 0)\n        return;\n    \n    memset(&time_cmd, 0, sizeof(time_cmd));\n    \n    time_cmd.action = htole32(IWX_FW_CTXT_ACTION_REMOVE);\n    time_cmd.id_and_color =\n    htole32(IWX_FW_CMD_ID_AND_COLOR(in->in_id, in->in_color));\n    time_cmd.id = htole32(sc->sc_time_event_uid);\n    \n    if (iwx_send_time_event_cmd(sc, &time_cmd) == 0)\n        sc->sc_flags &= ~IWX_FLAG_TE_ACTIVE;\n    \n    DELAY(100);\n}\n\n/*\n * NVM read access and content parsing.  We do not support\n * external NVM or writing NVM.\n */\n\nuint8_t ItlIwx::\niwx_fw_valid_tx_ant(struct iwx_softc *sc)\n{\n    uint8_t tx_ant;\n    \n    tx_ant = ((sc->sc_fw_phy_config & IWX_FW_PHY_CFG_TX_CHAIN)\n              >> IWX_FW_PHY_CFG_TX_CHAIN_POS);\n    \n    if (sc->sc_nvm.valid_tx_ant)\n        tx_ant &= sc->sc_nvm.valid_tx_ant;\n    \n    return tx_ant;\n}\n\nuint8_t ItlIwx::\niwx_fw_valid_rx_ant(struct iwx_softc *sc)\n{\n    uint8_t rx_ant;\n    \n    rx_ant = ((sc->sc_fw_phy_config & IWX_FW_PHY_CFG_RX_CHAIN)\n              >> IWX_FW_PHY_CFG_RX_CHAIN_POS);\n    \n    if (sc->sc_nvm.valid_rx_ant)\n        rx_ant &= sc->sc_nvm.valid_rx_ant;\n    \n    return rx_ant;\n}\n\nvoid ItlIwx::\niwx_init_channel_map(struct iwx_softc *sc, uint16_t *channel_profile_v3,\nuint32_t *channel_profile_v4, int nchan_profile)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct iwx_nvm_data *data = &sc->sc_nvm;\n    int ch_idx;\n    struct ieee80211_channel *channel;\n    uint32_t ch_flags;\n    int is_5ghz;\n    int flags, hw_value;\n    int nchan;\n    const uint8_t *nvm_channels;\n\n    if (sc->sc_uhb_supported) {\n        nchan = nitems(iwx_nvm_channels_uhb);\n        nvm_channels = iwx_nvm_channels_uhb;\n    } else {\n        nchan = nitems(iwx_nvm_channels_8000);\n        nvm_channels = iwx_nvm_channels_8000;\n    }\n\n    for (ch_idx = 0; ch_idx < nchan && ch_idx < nchan_profile; ch_idx++) {\n        if (channel_profile_v4)\n            ch_flags = le32_to_cpup(channel_profile_v4 + ch_idx);\n        else\n            ch_flags = le16_to_cpup(channel_profile_v3 + ch_idx);\n\n        is_5ghz = ch_idx >= IWX_NUM_2GHZ_CHANNELS;\n        if (is_5ghz && !data->sku_cap_band_52GHz_enable)\n            ch_flags &= ~IWX_NVM_CHANNEL_VALID;\n        \n        if (ch_flags & IWX_NVM_CHANNEL_160MHZ)\n            data->vht160_supported = true;\n\n        hw_value = nvm_channels[ch_idx];\n        channel = &ic->ic_channels[hw_value];\n\n        if (!(ch_flags & IWX_NVM_CHANNEL_VALID)) {\n            channel->ic_freq = 0;\n            channel->ic_flags = 0;\n            continue;\n        }\n\n        if (!is_5ghz) {\n            flags = IEEE80211_CHAN_2GHZ;\n            channel->ic_flags\n                = IEEE80211_CHAN_CCK\n                | IEEE80211_CHAN_OFDM\n                | IEEE80211_CHAN_DYN\n                | IEEE80211_CHAN_2GHZ;\n        } else {\n            flags = IEEE80211_CHAN_5GHZ;\n            channel->ic_flags =\n                IEEE80211_CHAN_A;\n        }\n\n        if (!(ch_flags & IWX_NVM_CHANNEL_ACTIVE))\n            channel->ic_flags |= IEEE80211_CHAN_PASSIVE;\n\n        if (data->sku_cap_11n_enable)\n            channel->ic_flags |= IEEE80211_CHAN_HT20;\n\n        if (!is_5ghz && (ch_flags & IWX_NVM_CHANNEL_40MHZ)) {\n            if (hw_value <= IWX_LAST_2GHZ_HT_PLUS) {\n                channel->ic_flags |= IEEE80211_CHAN_HT40U;\n            }\n            if (hw_value >= IWX_FIRST_2GHZ_HT_MINUS) {\n                channel->ic_flags |= IEEE80211_CHAN_HT40D;\n            }\n        } else if (ch_flags & IWX_NVM_CHANNEL_40MHZ) {\n            if ((ch_idx - IWX_NUM_2GHZ_CHANNELS) % 2 == 0) {\n                channel->ic_flags |= IEEE80211_CHAN_HT40U;\n            } else {\n                channel->ic_flags |= IEEE80211_CHAN_HT40D;\n            }\n        }\n\n        if (data->sku_cap_11ac_enable) {\n            if (ch_flags & IWX_NVM_CHANNEL_80MHZ) {\n                channel->ic_flags |= IEEE80211_CHAN_VHT80;\n            }\n            if (ch_flags & IWX_NVM_CHANNEL_160MHZ) {\n                channel->ic_flags |= IEEE80211_CHAN_VHT160;\n            }\n        }\n\n        if (ch_flags & IWX_NVM_CHANNEL_DFS) {\n            channel->ic_flags |= IEEE80211_CHAN_DFS;\n        }\n\n        channel->ic_freq = ieee80211_ieee2mhz(hw_value, flags);\n        \n        DPRINTFN(3, (\"Ch. %d Flags %x [%sGHz] - No traffic\\n\",\n              hw_value,\n              channel->ic_flags,\n              (!IEEE80211_IS_CHAN_2GHZ(channel)) ? \"5.2\" : \"2.4\"));\n    }\n}\n\nint ItlIwx::\niwx_mimo_enabled(struct iwx_softc *sc)\n{\n   struct ieee80211com *ic = &sc->sc_ic;\n\n   return !sc->sc_nvm.sku_cap_mimo_disable &&\n       (ic->ic_userflags & IEEE80211_F_NOMIMO) == 0;\n}\n\nvoid ItlIwx::\niwx_setup_ht_rates(struct iwx_softc *sc)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    uint8_t rx_ant;\n    \n    /* TX is supported with the same MCS as RX. */\n    ic->ic_tx_mcs_set = IEEE80211_TX_MCS_SET_DEFINED;\n    \n    memset(ic->ic_sup_mcs, 0, sizeof(ic->ic_sup_mcs));\n    ic->ic_sup_mcs[0] = 0xff;        /* MCS 0-7 */\n    \n    if (!iwx_mimo_enabled(sc))\n        return;\n    \n    rx_ant = iwx_fw_valid_rx_ant(sc);\n    if ((rx_ant & IWX_ANT_AB) == IWX_ANT_AB ||\n        (rx_ant & IWX_ANT_BC) == IWX_ANT_BC)\n        ic->ic_sup_mcs[1] = 0xff;    /* MCS 8-15 */\n}\n\nvoid ItlIwx::\niwx_init_reorder_buffer(struct iwx_reorder_buffer *reorder_buf,\n                        uint16_t ssn, uint16_t buf_size)\n{\n    reorder_buf->head_sn = ssn;\n    reorder_buf->num_stored = 0;\n    reorder_buf->buf_size = buf_size;\n    reorder_buf->last_amsdu = 0;\n    reorder_buf->last_sub_index = 0;\n    reorder_buf->removed = 0;\n    reorder_buf->valid = 0;\n    reorder_buf->consec_oldsn_drops = 0;\n    reorder_buf->consec_oldsn_ampdu_gp2 = 0;\n    reorder_buf->consec_oldsn_prev_drop = 0;\n}\n\nvoid ItlIwx::\niwx_clear_reorder_buffer(struct iwx_softc *sc, struct iwx_rxba_data *rxba)\n{\n    int i;\n    struct iwx_reorder_buffer *reorder_buf = &rxba->reorder_buf;\n    struct iwx_reorder_buf_entry *entry;\n    \n    for (i = 0; i < reorder_buf->buf_size; i++) {\n        entry = &rxba->entries[i];\n        ml_purge(&entry->frames);\n        timerclear(&entry->reorder_time);\n    }\n    \n    reorder_buf->removed = 1;\n    timeout_del(&reorder_buf->reorder_timer);\n    timeout_free(&reorder_buf->reorder_timer);\n    timerclear(&rxba->last_rx);\n    timeout_del(&rxba->session_timer);\n    timeout_free(&rxba->session_timer);\n    rxba->baid = IWX_RX_REORDER_DATA_INVALID_BAID;\n}\n\n#define RX_REORDER_BUF_TIMEOUT_MQ_USEC (100000ULL)\n\nvoid ItlIwx::\niwx_rx_ba_session_expired(void *arg)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwx_rxba_data *rxba = (struct iwx_rxba_data *)arg;\n    struct iwx_softc *sc = rxba->sc;\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct ieee80211_node *ni = ic->ic_bss;\n    struct timeval now, timeout, expiry;\n    int s;\n    \n    s = splnet();\n    if ((sc->sc_flags & IWX_FLAG_SHUTDOWN) == 0 &&\n        ic->ic_state == IEEE80211_S_RUN &&\n        rxba->baid != IWX_RX_REORDER_DATA_INVALID_BAID) {\n        getmicrouptime(&now);\n        USEC_TO_TIMEVAL(RX_REORDER_BUF_TIMEOUT_MQ_USEC, &timeout);\n        timeradd(&rxba->last_rx, &timeout, &expiry);\n        if (timercmp(&now, &expiry, <)) {\n            timeout_add_usec(&rxba->session_timer, rxba->timeout);\n        } else {\n            ic->ic_stats.is_ht_rx_ba_timeout++;\n            ieee80211_delba_request(ic, ni,\n                                    IEEE80211_REASON_TIMEOUT, 0, rxba->tid);\n        }\n    }\n    splx(s);\n}\n\nvoid ItlIwx::\niwx_reorder_timer_expired(void *arg)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct mbuf_list ml = MBUF_LIST_INITIALIZER();\n    struct iwx_reorder_buffer *buf = (struct iwx_reorder_buffer *)arg;\n    struct iwx_rxba_data *rxba = iwx_rxba_data_from_reorder_buf(buf);\n    struct iwx_reorder_buf_entry *entries = &rxba->entries[0];\n    struct iwx_softc *sc = rxba->sc;\n    ItlIwx *that = container_of(sc, ItlIwx, com);\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct ieee80211_node *ni = ic->ic_bss;\n    int i, s;\n    uint16_t sn = 0, index = 0;\n    int expired = 0;\n    int cont = 0;\n    struct timeval now, timeout, expiry;\n    \n    if (!buf->num_stored || buf->removed)\n        return;\n    \n    s = splnet();\n    getmicrouptime(&now);\n    USEC_TO_TIMEVAL(RX_REORDER_BUF_TIMEOUT_MQ_USEC, &timeout);\n    \n    for (i = 0; i < buf->buf_size ; i++) {\n        index = (buf->head_sn + i) % buf->buf_size;\n        \n        if (ml_empty(&entries[index].frames)) {\n            /*\n             * If there is a hole and the next frame didn't expire\n             * we want to break and not advance SN.\n             */\n            cont = 0;\n            continue;\n        }\n        timeradd(&entries[index].reorder_time, &timeout, &expiry);\n        if (!cont && timercmp(&now, &expiry, <))\n            break;\n        \n        expired = 1;\n        /* continue until next hole after this expired frame */\n        cont = 1;\n        sn = (buf->head_sn + (i + 1)) & 0xfff;\n    }\n    \n    if (expired) {\n        /* SN is set to the last expired frame + 1 */\n        that->iwx_release_frames(sc, ni, rxba, buf, sn, &ml);\n        if_input(&sc->sc_ic.ic_if, &ml);\n        ic->ic_stats.is_ht_rx_ba_window_gap_timeout++;\n    } else {\n        /*\n         * If no frame expired and there are stored frames, index is now\n         * pointing to the first unexpired frame - modify reorder timeout\n         * accordingly.\n         */\n        timeout_add_usec(&buf->reorder_timer,\n                         RX_REORDER_BUF_TIMEOUT_MQ_USEC);\n    }\n    \n    splx(s);\n}\n\nstatic inline uint8_t iwx_num_of_ant(uint8_t mask)\n{\n    return  !!((mask) & IWX_ANT_A) +\n        !!((mask) & IWX_ANT_B) +\n        !!((mask) & IWX_ANT_C);\n}\n\nvoid ItlIwx::\niwx_setup_vht_rates(struct iwx_softc *sc)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    uint8_t rx_ant, tx_ant;\n    unsigned int max_ampdu_exponent = IEEE80211_VHTCAP_MAX_AMPDU_1024K;\n    \n    if (ic->ic_userflags & IEEE80211_F_NOVHT)\n        return;\n    \n    /* enable 11ac support */\n    ic->ic_flags |= IEEE80211_F_VHTON;\n    \n    rx_ant = iwx_num_of_ant(iwx_fw_valid_rx_ant(sc));\n    tx_ant = iwx_num_of_ant(iwx_fw_valid_tx_ant(sc));\n    \n    ic->ic_vhtcaps = IEEE80211_VHTCAP_SHORT_GI_80 |\n    IEEE80211_VHTCAP_RXSTBC_1 |\n    IEEE80211_VHTCAP_SU_BEAMFORMEE_CAPABLE | \n    3 << IEEE80211_VHTCAP_BEAMFORMEE_STS_SHIFT |\n    max_ampdu_exponent << IEEE80211_VHTCAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT |\n    IEEE80211_VHTCAP_MU_BEAMFORMEE_CAPABLE;\n    \n    if (sc->sc_nvm.vht160_supported)\n        ic->ic_vhtcaps |= IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_160MHZ |\n                IEEE80211_VHTCAP_SHORT_GI_160;\n    \n    if (!iwx_mimo_enabled(sc)) {\n        rx_ant = 1;\n        tx_ant = 1;\n    }\n    \n    ic->ic_vhtcaps |= IEEE80211_VHTCAP_RXLDPC;\n    if (tx_ant > 1)\n        ic->ic_vhtcaps |= IEEE80211_VHTCAP_TXSTBC;\n    else\n        ic->ic_vhtcaps |= IEEE80211_VHTCAP_TX_ANTENNA_PATTERN;\n    \n    ic->ic_vht_rx_mcs_map =\n        htole16(IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 |\n                IEEE80211_VHT_MCS_SUPPORT_0_9 << 2 |\n                IEEE80211_VHT_MCS_NOT_SUPPORTED << 4 |\n                IEEE80211_VHT_MCS_NOT_SUPPORTED << 6 |\n                IEEE80211_VHT_MCS_NOT_SUPPORTED << 8 |\n                IEEE80211_VHT_MCS_NOT_SUPPORTED << 10 |\n                IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 |\n                IEEE80211_VHT_MCS_NOT_SUPPORTED << 14);\n    if (rx_ant == 1) {\n        ic->ic_vhtcaps |= IEEE80211_VHTCAP_RX_ANTENNA_PATTERN;\n        /* this works because NOT_SUPPORTED == 3 */\n        ic->ic_vht_rx_mcs_map |=\n            htole16(IEEE80211_VHT_MCS_NOT_SUPPORTED << 2);\n    }\n    ic->ic_vht_tx_mcs_map = ic->ic_vht_rx_mcs_map;\n\n    ic->ic_vht_tx_highest |=\n        htole16(IEEE80211_VHT_EXT_NSS_BW_CAPABLE);\n    ic->ic_vht_rx_highest = 0;\n    \n    memset(ic->ic_vht_sup_mcs, 0, sizeof(ic->ic_vht_sup_mcs));\n    ic->ic_vht_sup_mcs[0] = 0x03FF;        /* MCS 0-9 */\n    \n    if (!iwx_mimo_enabled(sc))\n        return;\n    \n    ic->ic_vht_sup_mcs[1] = 0x03FF;         /* MCS 0-9 */\n}\n\nvoid ItlIwx::\niwx_setup_he_rates(struct iwx_softc *sc)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    \n    /* enable 11ax support */\n//    ic->ic_flags |= IEEE80211_F_HEON;\n    \n    ic->ic_he_cap_elem = {\n        .mac_cap_info[0] =\n            IEEE80211_HE_MAC_CAP0_HTC_HE |\n            IEEE80211_HE_MAC_CAP0_TWT_REQ,\n        .mac_cap_info[1] =\n            IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US |\n            IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_8,\n        .mac_cap_info[2] =\n            IEEE80211_HE_MAC_CAP2_32BIT_BA_BITMAP,\n        .mac_cap_info[3] =\n            IEEE80211_HE_MAC_CAP3_OMI_CONTROL |\n            IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_VHT_2,\n        .mac_cap_info[4] =\n            IEEE80211_HE_MAC_CAP4_AMDSU_IN_AMPDU |\n            IEEE80211_HE_MAC_CAP4_MULTI_TID_AGG_TX_QOS_B39,\n        .mac_cap_info[5] =\n            IEEE80211_HE_MAC_CAP5_MULTI_TID_AGG_TX_QOS_B40 |\n            IEEE80211_HE_MAC_CAP5_MULTI_TID_AGG_TX_QOS_B41 |\n            IEEE80211_HE_MAC_CAP5_UL_2x996_TONE_RU |\n            IEEE80211_HE_MAC_CAP5_HE_DYNAMIC_SM_PS |\n            IEEE80211_HE_MAC_CAP5_HT_VHT_TRIG_FRAME_RX,\n        .phy_cap_info[1] =\n            IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_MASK |\n            IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A |\n            IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD,\n        .phy_cap_info[2] =\n            IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US,\n        .phy_cap_info[3] =\n            IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_NO_DCM |\n            IEEE80211_HE_PHY_CAP3_DCM_MAX_TX_NSS_1 |\n            IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_NO_DCM |\n            IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_1,\n        .phy_cap_info[4] =\n            IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE |\n            IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_8 |\n            IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_8,\n        .phy_cap_info[5] =\n            IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_2 |\n            IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_2,\n        .phy_cap_info[6] =\n            IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMER_FB |\n            IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMER_FB |\n            IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT,\n        .phy_cap_info[7] =\n            IEEE80211_HE_PHY_CAP7_POWER_BOOST_FACTOR_AR |\n            IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI |\n            IEEE80211_HE_PHY_CAP7_MAX_NC_1,\n        .phy_cap_info[8] =\n            IEEE80211_HE_PHY_CAP8_HE_ER_SU_PPDU_4XLTF_AND_08_US_GI |\n            IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G |\n            IEEE80211_HE_PHY_CAP8_20MHZ_IN_160MHZ_HE_PPDU |\n            IEEE80211_HE_PHY_CAP8_80MHZ_IN_160MHZ_HE_PPDU |\n            IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_2x996,\n        .phy_cap_info[9] =\n            IEEE80211_HE_PHY_CAP9_NON_TRIGGERED_CQI_FEEDBACK |\n            IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB |\n            IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB |\n            IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_RESERVED,\n    };\n    \n    /*\n     * Set default Tx/Rx HE MCS NSS Support field.\n     * Indicate support for up to 2 spatial streams and all\n     * MCS, without any special cases\n     */\n    ic->ic_he_mcs_nss_supp = {\n        .rx_mcs_80 = htole16(0xfffa),\n        .tx_mcs_80 = htole16(0xfffa),\n        .rx_mcs_160 = htole16(0xfffa),\n        .tx_mcs_160 = htole16(0xfffa),\n        .rx_mcs_80p80 = htole16(0xffff),\n        .tx_mcs_80p80 = htole16(0xffff),\n    };\n    \n    /*\n     * Set default PPE thresholds, with PPET16 set to 0,\n     * PPET8 set to 7\n     */\n    uint8_t ppe_thres[] = {0x61, 0x1c, 0xc7, 0x71};\n    memcpy(ic->ic_ppe_thres, ppe_thres, sizeof(ic->ic_ppe_thres));\n}\n\n#define IWX_MAX_RX_BA_SESSIONS 16\n\nvoid ItlIwx::\niwx_sta_rx_agg(struct iwx_softc *sc, struct ieee80211_node *ni, uint8_t tid,\n               uint16_t ssn, uint16_t winsize, int timeout_val, int start)\n{\n    XYLog(\"%s start=%d tid=%d ssn=%d winsize=%d\\n\", __FUNCTION__, start, tid, ssn, winsize);\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct iwx_add_sta_cmd cmd;\n    struct iwx_node *in = (struct iwx_node *)ni;\n    int err, s;\n    uint32_t status;\n    struct iwx_rxba_data *rxba = NULL;\n    uint8_t baid = 0;\n    \n    s = splnet();\n    \n    if (start && sc->sc_rx_ba_sessions >= IWX_MAX_RX_BA_SESSIONS) {\n        ieee80211_addba_req_refuse(ic, ni, tid);\n        splx(s);\n        return;\n    }\n    \n    memset(&cmd, 0, sizeof(cmd));\n    \n    cmd.sta_id = IWX_STATION_ID;\n    cmd.mac_id_n_color\n    = htole32(IWX_FW_CMD_ID_AND_COLOR(in->in_id, in->in_color));\n    cmd.add_modify = IWX_STA_MODE_MODIFY;\n    \n    if (start) {\n        cmd.add_immediate_ba_tid = (uint8_t)tid;\n        cmd.add_immediate_ba_ssn = htole16(ssn);\n        cmd.rx_ba_window = htole16(winsize);\n    } else {\n        cmd.remove_immediate_ba_tid = (uint8_t)tid;\n    }\n    cmd.modify_mask = start ? IWX_STA_MODIFY_ADD_BA_TID :\n    IWX_STA_MODIFY_REMOVE_BA_TID;\n    \n    status = IWX_ADD_STA_SUCCESS;\n    err = iwx_send_cmd_pdu_status(sc, IWX_ADD_STA, sizeof(cmd), &cmd,\n                                  &status);\n    \n    if (err || (status & IWX_ADD_STA_STATUS_MASK) != IWX_ADD_STA_SUCCESS) {\n        if (start)\n            ieee80211_addba_req_refuse(ic, ni, tid);\n        splx(s);\n        return;\n    }\n    \n    /* Deaggregation is done in hardware. */\n    if (start) {\n        if (!(status & IWX_ADD_STA_BAID_VALID_MASK)) {\n            ieee80211_addba_req_refuse(ic, ni, tid);\n            splx(s);\n            return;\n        }\n        baid = (status & IWX_ADD_STA_BAID_MASK) >>\n        IWX_ADD_STA_BAID_SHIFT;\n        if (baid == IWX_RX_REORDER_DATA_INVALID_BAID ||\n            baid >= nitems(sc->sc_rxba_data)) {\n            ieee80211_addba_req_refuse(ic, ni, tid);\n            splx(s);\n            return;\n        }\n        rxba = &sc->sc_rxba_data[baid];\n        if (rxba->baid != IWX_RX_REORDER_DATA_INVALID_BAID) {\n            ieee80211_addba_req_refuse(ic, ni, tid);\n            splx(s);\n            return;\n        }\n        rxba->sta_id = IWX_STATION_ID;\n        rxba->tid = tid;\n        rxba->baid = baid;\n        rxba->timeout = timeout_val;\n        getmicrouptime(&rxba->last_rx);\n        iwx_init_reorder_buffer(&rxba->reorder_buf, ssn,\n                                winsize);\n        if (timeout_val != 0) {\n            struct ieee80211_rx_ba *ba;\n            timeout_add_usec(&rxba->session_timer,\n                             timeout_val);\n            /* XXX disable net80211's BA timeout handler */\n            ba = &ni->ni_rx_ba[tid];\n            ba->ba_timeout_val = 0;\n        }\n    } else {\n        int i;\n        for (i = 0; i < nitems(sc->sc_rxba_data); i++) {\n            rxba = &sc->sc_rxba_data[i];\n            if (rxba->baid ==\n                IWX_RX_REORDER_DATA_INVALID_BAID)\n                continue;\n            if (rxba->tid != tid)\n                continue;\n            iwx_clear_reorder_buffer(sc, rxba);\n            break;\n        }\n    }\n    \n    if (start) {\n        sc->sc_rx_ba_sessions++;\n        ieee80211_addba_req_accept(ic, ni, tid);\n    } else if (sc->sc_rx_ba_sessions > 0)\n        sc->sc_rx_ba_sessions--;\n\n    splx(s);\n}\n\nvoid ItlIwx::\niwx_mac_ctxt_task(void *arg)\n{\n    struct iwx_softc *sc = (struct iwx_softc *)arg;\n    struct ieee80211com *ic = &sc->sc_ic;\n    ItlIwx *that = container_of(sc, ItlIwx, com);\n    struct iwx_node *in = (struct iwx_node *)ic->ic_bss;\n    int err, s = splnet();\n    \n    if (sc->sc_flags & IWX_FLAG_SHUTDOWN ||\n        ic->ic_state != IEEE80211_S_RUN ||\n        in->in_phyctxt == NULL) {\n        //        refcnt_rele_wake(&sc->task_refs);\n        splx(s);\n        return;\n    }\n    \n    err = that->iwx_mac_ctxt_cmd(sc, in, IWX_FW_CTXT_ACTION_MODIFY, 1);\n    if (err)\n        printf(\"%s: failed to update MAC\\n\", DEVNAME(sc));\n    \n    if (!isset(sc->sc_enabled_capa, IWX_UCODE_TLV_CAPA_SESSION_PROT_CMD))\n        that->iwx_unprotect_session(sc, in);\n    \n    //    refcnt_rele_wake(&sc->task_refs);\n    splx(s);\n}\n\nvoid ItlIwx::\niwx_chan_ctxt_task(void *arg)\n{\n    struct iwx_softc *sc = (struct iwx_softc *)arg;\n    struct ieee80211com *ic = &sc->sc_ic;\n    ItlIwx *that = container_of(sc, ItlIwx, com);\n    struct iwx_node *in = (struct iwx_node *)ic->ic_bss;\n    int chains = that->iwx_mimo_enabled(sc) ? 2 : 1;\n    int err, s = splnet();\n    \n    if (sc->sc_flags & IWX_FLAG_SHUTDOWN ||\n        ic->ic_state != IEEE80211_S_RUN ||\n        in->in_phyctxt == NULL) {\n        //        refcnt_rele_wake(&sc->task_refs);\n        splx(s);\n        return;\n    }\n    \n    err = that->iwx_phy_ctxt_update(sc, in->in_phyctxt,\n                                    in->in_phyctxt->channel, chains, chains, 0);\n    if (err) {\n        XYLog(\"%s: failed to update PHY (error %d)\\n\",\n              __FUNCTION__, err);\n        //        refcnt_rele_wake(&sc->task_refs);\n        splx(s);\n        return;\n    }\n    err = that->iwx_rs_init(sc, in, true);\n    if (err) {\n        XYLog(\"%s: could not update rate scaling (error %d)\\n\",\n              __FUNCTION__, err);\n        //        refcnt_rele_wake(&sc->task_refs);\n        splx(s);\n        return;\n    }\n    \n    //    refcnt_rele_wake(&sc->task_refs);\n    splx(s);\n}\n\nvoid ItlIwx::\niwx_update_chw(struct ieee80211com *ic)\n{\n    struct iwx_softc *sc = (struct iwx_softc *)ic->ic_softc;\n    ItlIwx *that = container_of(sc, ItlIwx, com);\n    \n    if (ic->ic_state == IEEE80211_S_RUN && (sc->sc_flags & IWX_FLAG_STA_ACTIVE))\n        that->iwx_add_task(sc, systq, &sc->chan_ctxt_task);\n}\n\nvoid ItlIwx::\niwx_updateprot(struct ieee80211com *ic)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwx_softc *sc = (struct iwx_softc *)ic->ic_softc;\n    ItlIwx *that = container_of(sc, ItlIwx, com);\n    \n    if (ic->ic_state == IEEE80211_S_RUN && (sc->sc_flags & IWX_FLAG_STA_ACTIVE))\n        that->iwx_add_task(sc, systq, &sc->mac_ctxt_task);\n}\n\nvoid ItlIwx::\niwx_updateslot(struct ieee80211com *ic)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwx_softc *sc = (struct iwx_softc *)ic->ic_softc;\n    ItlIwx *that = container_of(sc, ItlIwx, com);\n    \n    if (ic->ic_state == IEEE80211_S_RUN && (sc->sc_flags & IWX_FLAG_STA_ACTIVE))\n        that->iwx_add_task(sc, systq, &sc->mac_ctxt_task);\n}\n\nvoid ItlIwx::\niwx_updateedca(struct ieee80211com *ic)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwx_softc *sc = (struct iwx_softc *)ic->ic_softc;\n    ItlIwx *that = container_of(sc, ItlIwx, com);\n    \n    if (ic->ic_state == IEEE80211_S_RUN && (sc->sc_flags & IWX_FLAG_STA_ACTIVE))\n        that->iwx_add_task(sc, systq, &sc->mac_ctxt_task);\n}\n\nvoid ItlIwx::\niwx_updatedtim(struct ieee80211com *ic)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwx_softc *sc = (struct iwx_softc *)ic->ic_softc;\n    ItlIwx *that = container_of(sc, ItlIwx, com);\n    \n    if (ic->ic_state == IEEE80211_S_RUN && (sc->sc_flags & IWX_FLAG_STA_ACTIVE))\n        that->iwx_add_task(sc, systq, &sc->mac_ctxt_task);\n}\n\nvoid ItlIwx::\niwx_ba_task(void *arg)\n{\n    struct iwx_softc *sc = (struct iwx_softc *)arg;\n    struct ieee80211com *ic = &sc->sc_ic;\n    ItlIwx *that = container_of(sc, ItlIwx, com);\n    struct ieee80211_node *ni = ic->ic_bss;\n    struct ieee80211_tx_ba *ba;\n    struct iwx_tx_ring *ring;\n    int s = splnet();\n    int err = 0;\n    int qid = 0;\n    int tid;\n    \n    if (sc->sc_flags & IWX_FLAG_SHUTDOWN) {\n        //        refcnt_rele_wake(&sc->task_refs);\n        splx(s);\n        return;\n    }\n\n    for (tid = 0; tid < IWX_MAX_TID_COUNT; tid++) {\n        if (sc->sc_flags & IWX_FLAG_SHUTDOWN)\n            break;\n        if (sc->ba_rx.start_tidmask & (1 << tid)) {\n            struct ieee80211_rx_ba *ba = &ni->ni_rx_ba[tid];\n            XYLog(\"%s ba_rx_start tid=%d, ssn=%d\\n\", __FUNCTION__, tid, ba->ba_winstart);\n            that->iwx_sta_rx_agg(sc, ni, tid, ba->ba_winstart,\n                                 ba->ba_winsize, ba->ba_timeout_val, 1);\n            sc->ba_rx.start_tidmask &= ~(1 << tid);\n        } else if (sc->ba_rx.stop_tidmask & (1 << tid)) {\n            that->iwx_sta_rx_agg(sc, ni, tid, 0, 0, 0, 0);\n            sc->ba_rx.stop_tidmask &= ~(1 << tid);\n        }\n    }\n    \n    for (tid = 0; tid < IWX_MAX_TID_COUNT; tid++) {\n        if (sc->sc_flags & IWX_FLAG_SHUTDOWN)\n            break;\n        if (sc->ba_tx.start_tidmask & (1 << tid)) {\n            ba = &ni->ni_tx_ba[tid];\n            XYLog(\"%s ba_tx_start tid=%d, ssn=%d\\n\", __FUNCTION__, tid, ba->ba_winstart);\n            if (!that->iwx_nic_lock(sc)) {\n                err = -1;\n                goto out;\n            }\n            if ((qid = that->iwx_tvqm_alloc_txq(sc, tid, ba->ba_winstart)) < 0) {\n                err = -1;\n                goto out;\n            }\n            ring = &sc->txq[qid];\n            ba->ba_winstart = IWX_AGG_SSN_TO_TXQ_IDX(ring->cur, ring->ring_count);\n            ba->ba_winend = (ba->ba_winstart + ba->ba_winsize - 1) & 0xfff;\n            ba->ba_timeout_val = 0;\n            ieee80211_addba_resp_accept(ic, ni, tid);\n            XYLog(\"%s tx queue alloc succeed qid=%d ssn=%d\\n\", __FUNCTION__, qid, ba->ba_winstart);\n        out:\n            that->iwx_nic_unlock(sc);\n            if (err)\n                ieee80211_addba_resp_refuse(ic, ni, tid,\n                                            IEEE80211_STATUS_UNSPECIFIED);\n            sc->ba_tx.start_tidmask &= ~(1 << tid);\n        }\n    }\n    \n    //    refcnt_rele_wake(&sc->task_refs);\n    splx(s);\n}\n\n/*\n * This function is called by upper layer when an ADDBA request is received\n * from another STA and before the ADDBA response is sent.\n */\nint ItlIwx::\niwx_ampdu_rx_start(struct ieee80211com *ic, struct ieee80211_node *ni,\n                   uint8_t tid)\n{\n    struct iwx_softc *sc = (struct iwx_softc *)IC2IFP(ic)->if_softc;\n    ItlIwx *that = container_of(sc, ItlIwx, com);\n    \n    if (sc->sc_rx_ba_sessions >= IWX_MAX_RX_BA_SESSIONS ||\n        tid >= IWX_MAX_TID_COUNT)\n        return ENOSPC;\n    \n    if (ic->ic_state != IEEE80211_S_RUN)\n        return ENOSPC;\n    \n    if (sc->ba_rx.start_tidmask & (1 << tid))\n        return EBUSY;\n\n    sc->ba_rx.start_tidmask |= (1 << tid);\n    that->iwx_add_task(sc, systq, &sc->ba_task);\n    \n    return EBUSY;\n}\n\n/*\n * This function is called by upper layer on teardown of an HT-immediate\n * Block Ack agreement (eg. upon receipt of a DELBA frame).\n */\nvoid ItlIwx::\niwx_ampdu_rx_stop(struct ieee80211com *ic, struct ieee80211_node *ni,\n                  uint8_t tid)\n{\n    struct iwx_softc *sc = (struct iwx_softc *)IC2IFP(ic)->if_softc;\n    ItlIwx *that = container_of(sc, ItlIwx, com);\n    \n    if (tid >= IWX_MAX_TID_COUNT || sc->ba_rx.stop_tidmask & (1 << tid))\n        return;\n    \n    if (ic->ic_state != IEEE80211_S_RUN)\n        return;\n\n    sc->ba_rx.stop_tidmask |= (1 << tid);\n    that->iwx_add_task(sc, systq, &sc->ba_task);\n}\n\nint ItlIwx::\niwx_ampdu_tx_start(struct ieee80211com *ic, struct ieee80211_node *ni, uint8_t tid)\n{\n    struct ieee80211_tx_ba *ba = &ni->ni_tx_ba[tid];\n    struct iwx_softc *sc = (struct iwx_softc *)ic->ic_softc;\n    ItlIwx *that = container_of(sc, ItlIwx, com);\n\n    XYLog(\"%s tid=%d ssn=%d\\n\", __FUNCTION__, tid, ba->ba_winstart);\n\n    if (tid < 0 || tid >= IWX_MAX_TID_COUNT) {\n        XYLog(\"%s tx agg refused. tid=%d\\n\", __FUNCTION__, tid);\n        return ENOSPC;\n    }\n    \n    if (sc->ba_tx.start_tidmask & (1 << tid)) {\n        XYLog(\"%s tid %d is pending to agg\\n\", __FUNCTION__, tid);\n        return EBUSY;\n    }\n    \n    sc->ba_tx.start_tidmask |= (1 << tid);\n    that->iwx_add_task(sc, systq, &sc->ba_task);\n    return EBUSY;\n}\n\nvoid ItlIwx::\niwx_ampdu_tx_stop(struct ieee80211com *ic, struct ieee80211_node *ni, uint8_t tid)\n{\n    struct ieee80211_tx_ba *ba = &ni->ni_tx_ba[tid];\n    struct iwx_softc *sc = (struct iwx_softc *)IC2IFP(ic)->if_softc;\n    ItlIwx *that = container_of(sc, ItlIwx, com);\n\n    XYLog(\"%s tid=%d\\n\", __FUNCTION__, tid);\n\n    if (ba->ba_state != IEEE80211_BA_AGREED) {\n        return;\n    }\n\n    sc->sc_tid_data[tid].qid = IWX_INVALID_QUEUE;\n    ic->ic_stats.is_ht_tx_ba_agreements--;\n}\n\nstatic void iwx_flip_hw_address(uint32_t mac_addr0, uint32_t mac_addr1, uint8_t *dest)\n{\n    const u8 *hw_addr;\n\n    hw_addr = (const u8 *)&mac_addr0;\n    dest[0] = hw_addr[3];\n    dest[1] = hw_addr[2];\n    dest[2] = hw_addr[1];\n    dest[3] = hw_addr[0];\n\n    hw_addr = (const u8 *)&mac_addr1;\n    dest[4] = hw_addr[1];\n    dest[5] = hw_addr[0];\n}\n\nint ItlIwx::\niwx_set_mac_addr_from_csr(struct iwx_softc *sc, struct iwx_nvm_data *data)\n{\n    uint32_t mac_addr0, mac_addr1;\n    \n    if (!iwx_nic_lock(sc))\n        return EBUSY;\n    \n    mac_addr0 = htole32(IWX_READ(sc, IWX_CSR_MAC_ADDR0_STRAP));\n    mac_addr1 = htole32(IWX_READ(sc, IWX_CSR_MAC_ADDR1_STRAP));\n    \n    iwx_flip_hw_address(mac_addr0, mac_addr1, data->hw_addr);\n    \n    /*\n     * If the OEM fused a valid address, use it instead of the one in the\n     * OTP\n     */\n    if (iwx_is_valid_mac_addr(data->hw_addr))\n        goto done;\n    \n    mac_addr0 = htole32(IWX_READ(sc, IWX_CSR_MAC_ADDR0_OTP));\n    mac_addr1 = htole32(IWX_READ(sc, IWX_CSR_MAC_ADDR1_OTP));\n    \n    iwx_flip_hw_address(mac_addr0, mac_addr1, data->hw_addr);\n    \ndone:\n    \n    iwx_nic_unlock(sc);\n    return 0;\n}\n\nint ItlIwx::\niwx_is_valid_mac_addr(const uint8_t *addr)\n{\n    return (memcmp(etherbroadcastaddr, addr, sizeof(etherbroadcastaddr)) != 0 &&\n            memcmp(etheranyaddr, addr, sizeof(etheranyaddr)) != 0 &&\n            !ETHER_IS_MULTICAST(addr));\n}\n\nint ItlIwx::\niwx_nvm_get(struct iwx_softc *sc)\n{\n    struct iwx_nvm_get_info cmd = {};\n    struct iwx_nvm_data *nvm = &sc->sc_nvm;\n    struct iwx_host_cmd hcmd = {\n        .flags = IWX_CMD_WANT_RESP | IWX_CMD_SEND_IN_RFKILL,\n        .data = { &cmd, },\n        .len = { sizeof(cmd) },\n        .id = IWX_WIDE_ID(IWX_REGULATORY_AND_NVM_GROUP,\n                          IWX_NVM_GET_INFO)\n    };\n    int err;\n    uint32_t mac_flags;\n    /*\n     * All the values in iwx_nvm_get_info_rsp v4 are the same as\n     * in v3, except for the channel profile part of the\n     * regulatory.  So we can just access the new struct, with the\n     * exception of the latter.\n     */\n    struct iwx_nvm_get_info_rsp *rsp;\n    struct iwx_nvm_get_info_rsp_v3 *rsp_v3;\n    int v4 = isset(sc->sc_ucode_api, IWX_UCODE_TLV_API_REGULATORY_NVM_INFO);\n    size_t resp_len = v4 ? sizeof(*rsp) : sizeof(*rsp_v3);\n    \n    hcmd.resp_pkt_len = sizeof(struct iwx_rx_packet) + resp_len;\n    err = iwx_send_cmd(sc, &hcmd);\n    if (err)\n        return err;\n    \n    if (iwx_rx_packet_payload_len(hcmd.resp_pkt) != resp_len) {\n        err = EIO;\n        goto out;\n    }\n    \n    memset(nvm, 0, sizeof(*nvm));\n    \n    iwx_set_mac_addr_from_csr(sc, nvm);\n    if (!iwx_is_valid_mac_addr(nvm->hw_addr)) {\n        XYLog(\"%s: no valid mac address was found\\n\", DEVNAME(sc));\n        err = EINVAL;\n        goto out;\n    }\n    \n    rsp = (struct iwx_nvm_get_info_rsp *)hcmd.resp_pkt->data;\n    \n    /* Initialize general data */\n    nvm->nvm_version = le16toh(rsp->general.nvm_version);\n    nvm->n_hw_addrs = rsp->general.n_hw_addrs;\n    \n    /* Initialize MAC sku data */\n    mac_flags = le32toh(rsp->mac_sku.mac_sku_flags);\n    nvm->sku_cap_11ac_enable =\n    !!(mac_flags & IWX_NVM_MAC_SKU_FLAGS_802_11AC_ENABLED);\n    nvm->sku_cap_11n_enable =\n    !!(mac_flags & IWX_NVM_MAC_SKU_FLAGS_802_11N_ENABLED);\n    nvm->sku_cap_11ax_enable =\n    !!(mac_flags & IWX_NVM_MAC_SKU_FLAGS_802_11AX_ENABLED);\n    nvm->sku_cap_band_24GHz_enable =\n    !!(mac_flags & IWX_NVM_MAC_SKU_FLAGS_BAND_2_4_ENABLED);\n    nvm->sku_cap_band_52GHz_enable =\n    !!(mac_flags & IWX_NVM_MAC_SKU_FLAGS_BAND_5_2_ENABLED);\n    nvm->sku_cap_mimo_disable =\n    !!(mac_flags & IWX_NVM_MAC_SKU_FLAGS_MIMO_DISABLED);\n    \n    /* Initialize PHY sku data */\n    nvm->valid_tx_ant = (uint8_t)le32toh(rsp->phy_sku.tx_chains);\n    nvm->valid_rx_ant = (uint8_t)le32toh(rsp->phy_sku.rx_chains);\n    \n    if (le32toh(rsp->regulatory.lar_enabled) &&\n        isset(sc->sc_enabled_capa, IWX_UCODE_TLV_CAPA_LAR_SUPPORT)) {\n        nvm->lar_enabled = 1;\n    }\n    \n    if (v4) {\n        iwx_init_channel_map(sc, NULL,\n                             rsp->regulatory.channel_profile, IWX_NUM_CHANNELS);\n    } else {\n        rsp_v3 = (struct iwx_nvm_get_info_rsp_v3 *)rsp;\n        iwx_init_channel_map(sc, rsp_v3->regulatory.channel_profile,\n                             NULL, IWX_NUM_CHANNELS_V1);\n    }\nout:\n    iwx_free_resp(sc, &hcmd);\n    return err;\n}\n\nint ItlIwx::\niwx_load_firmware(struct iwx_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwx_fw_sects *fws;\n    int err/*, w*/;\n\n    sc->sc_uc.uc_intr = 0;\n    \n    fws = &sc->sc_fw.fw_sects[IWX_UCODE_TYPE_REGULAR];\n    if (sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210)\n        err = iwx_ctxt_info_gen3_init(sc, fws);\n    else\n        err = iwx_ctxt_info_init(sc, fws);\n    if (err) {\n        XYLog(\"%s: could not init context info\\n\", DEVNAME(sc));\n        return err;\n    }\n    \n    /* wait for the firmware to load */\n//    for (w = 0; !sc->sc_uc.uc_intr && w < 10; w++) {\n//        err = tsleep_nsec(&sc->sc_uc, 0, \"iwxuc\", MSEC_TO_NSEC(100));\n//    }\n    err = tsleep_nsec(&sc->sc_uc, 0, \"iwxuc\", SEC_TO_NSEC(1));\n    if (err || !sc->sc_uc.uc_ok) {\n        if (iwx_nic_lock(sc)) {\n            XYLog(\"SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x\\n\",\n                  iwx_read_umac_prph(sc, IWX_UMAG_SB_CPU_1_STATUS),\n                  iwx_read_umac_prph(sc, IWX_UMAG_SB_CPU_2_STATUS));\n            XYLog(\"UMAC PC: 0x%x\\n\",\n                  iwx_read_umac_prph(sc,\n                                     IWX_UREG_UMAC_CURRENT_PC));\n            XYLog(\"LMAC PC: 0x%x\\n\",\n                  iwx_read_umac_prph(sc,\n                                     IWX_UREG_LMAC1_CURRENT_PC));\n            iwx_nic_unlock(sc);\n        }\n        iwx_ctxt_info_free_paging(sc);\n        XYLog(\"%s: could not load firmware\\n\", DEVNAME(sc));\n    }\n    \n    iwx_ctxt_info_free_fw_img(sc);\n    \n    iwx_dma_contig_free(&sc->iml_dma);\n    \n    if (!sc->sc_uc.uc_ok)\n        return EINVAL;\n    \n    XYLog(\"%s: load firmware ok\\n\", DEVNAME(sc));\n    \n    return err;\n}\n\nint ItlIwx::\niwx_start_fw(struct iwx_softc *sc)\n{\n    \n    XYLog(\"%s\\n\", __FUNCTION__);\n    int err;\n    \n    err = iwx_prepare_card_hw(sc);\n    if (err) {\n        XYLog(\"%s: could not initialize hardware\\n\", DEVNAME(sc));\n        return err;\n    }\n    \n    iwx_enable_rfkill_int(sc);\n    \n    IWX_WRITE(sc, IWX_CSR_INT, 0xFFFFFFFF);\n    \n    iwx_disable_interrupts(sc);\n    \n    /* make sure rfkill handshake bits are cleared */\n    IWX_WRITE(sc, IWX_CSR_UCODE_DRV_GP1_CLR, IWX_CSR_UCODE_SW_BIT_RFKILL);\n    IWX_WRITE(sc, IWX_CSR_UCODE_DRV_GP1_CLR,\n              IWX_CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);\n    \n    /* clear (again), then enable firwmare load interrupt */\n    IWX_WRITE(sc, IWX_CSR_INT, ~0);\n    \n    err = iwx_nic_init(sc);\n    if (err) {\n        XYLog(\"%s: unable to init nic\\n\", DEVNAME(sc));\n        return err;\n    }\n    \n    return iwx_load_firmware(sc);\n}\n\nint ItlIwx::\niwx_send_tx_ant_cfg(struct iwx_softc *sc, uint8_t valid_tx_ant)\n{\n    struct iwx_tx_ant_cfg_cmd tx_ant_cmd = {\n        .valid = htole32(valid_tx_ant),\n    };\n    \n    XYLog(\"%s select valid tx ant: %u\\n\", __FUNCTION__, valid_tx_ant);\n    return iwx_send_cmd_pdu(sc, IWX_TX_ANT_CONFIGURATION_CMD,\n                            0, sizeof(tx_ant_cmd), &tx_ant_cmd);\n}\n\nint ItlIwx::\niwx_send_phy_cfg_cmd(struct iwx_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwx_phy_cfg_cmd_v3 phy_cfg_cmd;\n    uint8_t cmdver;\n    \n    phy_cfg_cmd.phy_cfg = htole32(sc->sc_fw_phy_config);\n    phy_cfg_cmd.calib_control.event_trigger =\n    sc->sc_default_calib[IWX_UCODE_TYPE_REGULAR].event_trigger;\n    phy_cfg_cmd.calib_control.flow_trigger =\n    sc->sc_default_calib[IWX_UCODE_TYPE_REGULAR].flow_trigger;\n    \n    cmdver = iwx_lookup_cmd_ver(sc, IWX_LONG_GROUP, IWX_PHY_CONFIGURATION_CMD);\n    \n    return iwx_send_cmd_pdu(sc, IWX_PHY_CONFIGURATION_CMD, 0,\n                            (cmdver == 3) ? sizeof(struct iwx_phy_cfg_cmd_v3) :\n                            sizeof(struct iwx_phy_cfg_cmd_v1), &phy_cfg_cmd);\n}\n\nint ItlIwx::\niwx_send_dqa_cmd(struct iwx_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwx_dqa_enable_cmd dqa_cmd = {\n        .cmd_queue = htole32(IWX_DQA_CMD_QUEUE),\n    };\n    uint32_t cmd_id;\n    \n    cmd_id = iwx_cmd_id(IWX_DQA_ENABLE_CMD, IWX_DATA_PATH_GROUP, 0);\n    return iwx_send_cmd_pdu(sc, cmd_id, 0, sizeof(dqa_cmd), &dqa_cmd);\n}\n\nint ItlIwx::\niwx_load_ucode_wait_alive(struct iwx_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    int err;\n    \n    err = iwx_read_firmware(sc);\n    if (err)\n        return err;\n    \n    err = iwx_start_fw(sc);\n    if (err)\n        return err;\n    \n    err = iwx_load_pnvm(sc);\n    if (err)\n        return err;\n    \n    iwx_post_alive(sc);\n    \n    return 0;\n}\n\nint ItlIwx::\niwx_run_init_mvm_ucode(struct iwx_softc *sc, int readnvm)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    const int wait_flags = IWX_INIT_COMPLETE;\n    struct iwx_nvm_access_complete_cmd nvm_complete = {};\n    struct iwx_init_extended_cfg_cmd init_cfg = {\n        .init_flags = htole32(IWX_INIT_NVM),\n    };\n    int err;\n\n    if ((sc->sc_flags & IWX_FLAG_RFKILL) && !readnvm) {\n        XYLog(\"%s: radio is disabled by hardware switch\\n\",\n            DEVNAME(sc));\n        return EPERM;\n    }\n\n    sc->sc_init_complete = 0;\n    err = iwx_load_ucode_wait_alive(sc);\n    if (err) {\n        XYLog(\"%s: failed to load init firmware\\n\", DEVNAME(sc));\n        return err;\n    }\n    \n    if (sc->sc_tx_with_siso_diversity)\n        init_cfg.init_flags |= htole32(IWX_INIT_PHY);\n\n    /*\n     * Send init config command to mark that we are sending NVM\n     * access commands\n     */\n    err = iwx_send_cmd_pdu(sc, IWX_WIDE_ID(IWX_SYSTEM_GROUP,\n                                           IWX_INIT_EXTENDED_CFG_CMD), IWX_CMD_SEND_IN_RFKILL, sizeof(init_cfg), &init_cfg);\n    if (err)\n        return err;\n\n    err = iwx_send_cmd_pdu(sc, IWX_WIDE_ID(IWX_REGULATORY_AND_NVM_GROUP,\n                                           IWX_NVM_ACCESS_COMPLETE), IWX_CMD_SEND_IN_RFKILL, sizeof(nvm_complete), &nvm_complete);\n    if (err)\n        return err;\n\n    /* Wait for the init complete notification from the firmware. */\n//    while ((sc->sc_init_complete & wait_flags) != wait_flags) {\n//        err = tsleep_nsec(&sc->sc_init_complete, 0, \"iwxinit\",\n//            SEC_TO_NSEC(2));\n//        if (err)\n//            return err;\n//    }\n    err = tsleep_nsec(&sc->sc_init_complete, 0, \"iwxinit\", SEC_TO_NSEC(2));\n    if (err) {\n        return err;\n    }\n\n    if (readnvm) {\n        err = iwx_nvm_get(sc);\n        if (err) {\n            XYLog(\"%s: failed to read nvm\\n\", DEVNAME(sc));\n            return err;\n        }\n        if (IEEE80211_ADDR_EQ(etheranyaddr, sc->sc_ic.ic_myaddr))\n            IEEE80211_ADDR_COPY(sc->sc_ic.ic_myaddr,\n                sc->sc_nvm.hw_addr);\n        \n    }\n    return 0;\n}\n\nint ItlIwx::\niwx_config_ltr(struct iwx_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwx_ltr_config_cmd cmd = {\n        .flags = htole32(IWX_LTR_CFG_FLAG_FEATURE_ENABLE),\n    };\n    \n    if (!sc->sc_ltr_enabled)\n        return 0;\n    \n    return iwx_send_cmd_pdu(sc, IWX_LTR_CONFIG, 0, sizeof(cmd), &cmd);\n}\n\nvoid ItlIwx::\niwx_update_rx_desc(struct iwx_softc *sc, struct iwx_rx_ring *ring, int idx)\n{\n    struct iwx_rx_data *data = &ring->data[idx];\n    \n    if (sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210) {\n        struct iwx_rx_transfer_desc *bd = (struct iwx_rx_transfer_desc *)ring->desc;\n        \n        bd[idx].addr = htole64(data->map->dm_segs[0].location);\n        bd[idx].rbid = htole16(idx & 0x0fff);\n    } else\n        ((uint64_t *)ring->desc)[idx] =\n        htole64(data->map->dm_segs[0].location | (idx & 0x0fff));\n    //    bus_dmamap_sync(sc->sc_dmat, ring->free_desc_dma.map,\n    //        idx * sizeof(uint64_t), sizeof(uint64_t),\n    //        BUS_DMASYNC_PREWRITE);\n}\n\nint ItlIwx::\niwx_rx_addbuf(struct iwx_softc *sc, int size, int idx)\n{\n    struct iwx_rx_ring *ring = &sc->rxq;\n    struct iwx_rx_data *data = &ring->data[idx];\n    mbuf_t m;\n    int err;\n    int fatal = 0;\n    \n    m = getController()->allocatePacket(size);\n    \n    //    m = m_gethdr(M_DONTWAIT, MT_DATA);\n    //    if (m == NULL)\n    //        return ENOBUFS;\n    //\n    //    if (size <= MCLBYTES) {\n    //        MCLGET(m, M_DONTWAIT);\n    //    } else {\n    //        MCLGETI(m, M_DONTWAIT, NULL, IWX_RBUF_SIZE);\n    //    }\n    //    if ((m->m_flags & M_EXT) == 0) {\n    //        m_freem(m);\n    //        return ENOBUFS;\n    //    }\n    //\n    //    if (data->m != NULL) {\n    //        bus_dmamap_unload(sc->sc_dmat, data->map);\n    //        fatal = 1;\n    //    }\n    //\n    //    m->m_len = m->m_pkthdr.len = m->m_ext.ext_size;\n    //    err = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, m,\n    //        BUS_DMA_READ|BUS_DMA_NOWAIT);\n    if (m == NULL) {\n        XYLog(\"could not allocate RX mbuf\\n\");\n        return ENOMEM;\n    }\n    data->map->dm_nsegs = data->map->cursor->getPhysicalSegments(m, &data->map->dm_segs[0], 1);\n    if (data->map->dm_nsegs == 0) {\n        /* XXX */\n        if (fatal)\n            panic(\"%s: could not load RX mbuf\", DEVNAME(sc));\n        mbuf_freem(m);\n        return ENOMEM;\n    }\n    data->m = m;\n    //    bus_dmamap_sync(sc->sc_dmat, data->map, 0, size, BUS_DMASYNC_PREREAD);\n    \n    /* Update RX descriptor. */\n    iwx_update_rx_desc(sc, ring, idx);\n    \n    return 0;\n}\n\nint ItlIwx::\niwx_rxmq_get_signal_strength(struct iwx_softc *sc,\n                             struct iwx_rx_mpdu_desc *desc)\n{\n    int energy_a, energy_b;\n    \n    if (sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210) {\n        energy_a = desc->v3.energy_a;\n        energy_b = desc->v3.energy_b;\n    } else {\n        energy_a = desc->v1.energy_a;\n        energy_b = desc->v1.energy_b;\n    }\n    energy_a = energy_a ? -energy_a : -256;\n    energy_b = energy_b ? -energy_b : -256;\n    return MAX(energy_a, energy_b);\n}\n\nvoid ItlIwx::\niwx_rx_rx_phy_cmd(struct iwx_softc *sc, struct iwx_rx_packet *pkt,\n                  struct iwx_rx_data *data)\n{\n    struct iwx_rx_phy_info *phy_info = (struct iwx_rx_phy_info *)pkt->data;\n    \n    //    bus_dmamap_sync(sc->sc_dmat, data->map, sizeof(*pkt),\n    //        sizeof(*phy_info), BUS_DMASYNC_POSTREAD);\n    \n    memcpy(&sc->sc_last_phy_info, phy_info, sizeof(sc->sc_last_phy_info));\n}\n\n/*\n * Retrieve the average noise (in dBm) among receivers.\n */\nint ItlIwx::\niwx_get_noise(const uint8_t *beacon_silence_rssi)\n{\n    int i, total, nbant, noise;\n    \n    total = nbant = noise = 0;\n    for (i = 0; i < 3; i++) {\n        noise = letoh32(beacon_silence_rssi[i]) & 0xff;\n        if (noise) {\n            total += noise;\n            nbant++;\n        }\n    }\n    \n    /* There should be at least one antenna but check anyway. */\n    return (nbant == 0) ? -127 : (total / nbant) - 107;\n}\n\nint ItlIwx::\niwx_ccmp_decap(struct iwx_softc *sc, mbuf_t m, struct ieee80211_node *ni,\n    struct ieee80211_rxinfo *rxi)\n{\n   struct ieee80211com *ic = &sc->sc_ic;\n   struct ieee80211_key *k;\n   struct ieee80211_frame *wh;\n   uint64_t pn, *prsc;\n   uint8_t *ivp;\n   uint8_t tid;\n   int hdrlen, hasqos;\n\n   wh = mtod(m, struct ieee80211_frame *);\n   hdrlen = ieee80211_get_hdrlen(wh);\n   ivp = (uint8_t *)wh + hdrlen;\n    \n   /* find key for decryption */\n   k = ieee80211_get_rxkey(ic, m, ni);\n   if (k == NULL || k->k_cipher != IEEE80211_CIPHER_CCMP)\n       return 1;\n\n   /* Check that ExtIV bit is be set. */\n   if (!(ivp[3] & IEEE80211_WEP_EXTIV))\n       return 1;\n\n   hasqos = ieee80211_has_qos(wh);\n   tid = hasqos ? ieee80211_get_qos(wh) & IEEE80211_QOS_TID : 0;\n   prsc = &k->k_rsc[tid];\n\n   /* Extract the 48-bit PN from the CCMP header. */\n   pn = (uint64_t)ivp[0]       |\n        (uint64_t)ivp[1] <<  8 |\n        (uint64_t)ivp[4] << 16 |\n        (uint64_t)ivp[5] << 24 |\n        (uint64_t)ivp[6] << 32 |\n        (uint64_t)ivp[7] << 40;\n    if (rxi->rxi_flags & IEEE80211_RXI_HWDEC_SAME_PN) {\n        if (pn < *prsc) {\n            ic->ic_stats.is_ccmp_replays++;\n            return 1;\n        }\n    } else if (pn <= *prsc) {\n       ic->ic_stats.is_ccmp_replays++;\n       return 1;\n   }\n   /* Last seen packet number is updated in ieee80211_inputm(). */\n\n   /*\n    * Some firmware versions strip the MIC, and some don't. It is not\n    * clear which of the capability flags could tell us what to expect.\n    * For now, keep things simple and just leave the MIC in place if\n    * it is present.\n    *\n    * The IV will be stripped by ieee80211_inputm().\n    */\n   return 0;\n}\n\nint ItlIwx::\niwx_rx_hwdecrypt(struct iwx_softc *sc, mbuf_t m, uint32_t rx_pkt_status,\n                 struct ieee80211_rxinfo *rxi)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct _ifnet *ifp = IC2IFP(ic);\n    struct ieee80211_frame *wh;\n    struct ieee80211_node *ni;\n    int ret = 0;\n    uint8_t type, subtype;\n    \n    wh = mtod(m, struct ieee80211_frame *);\n    \n    type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;\n    if (type == IEEE80211_FC0_TYPE_CTL)\n        return 0;\n    \n    subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;\n    if (ieee80211_has_qos(wh) && (subtype & IEEE80211_FC0_SUBTYPE_NODATA))\n        return 0;\n    \n    ni = ieee80211_find_rxnode(ic, wh);\n    /* Handle hardware decryption. */\n    if (((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_CTL)\n        && (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) &&\n        (ni->ni_flags & IEEE80211_NODE_RXPROT) &&\n        ((!IEEE80211_IS_MULTICAST(wh->i_addr1) &&\n          ni->ni_rsncipher == IEEE80211_CIPHER_CCMP) ||\n         (IEEE80211_IS_MULTICAST(wh->i_addr1) &&\n          ni->ni_rsngroupcipher == IEEE80211_CIPHER_CCMP))) {\n        if ((rx_pkt_status & IWX_RX_MPDU_RES_STATUS_SEC_ENC_MSK) !=\n            IWX_RX_MPDU_RES_STATUS_SEC_CCM_ENC) {\n            ic->ic_stats.is_ccmp_dec_errs++;\n            ret = 1;\n            goto out;\n        }\n        /* Check whether decryption was successful or not. */\n        if ((rx_pkt_status &\n             (IWX_RX_MPDU_RES_STATUS_DEC_DONE |\n              IWX_RX_MPDU_RES_STATUS_MIC_OK)) !=\n            (IWX_RX_MPDU_RES_STATUS_DEC_DONE |\n             IWX_RX_MPDU_RES_STATUS_MIC_OK)) {\n            ic->ic_stats.is_ccmp_dec_errs++;\n            ret = 1;\n            goto out;\n        }\n        rxi->rxi_flags |= IEEE80211_RXI_HWDEC;\n    }\nout:\n    if (ret)\n        ifp->netStat->inputErrors++;\n    ieee80211_release_node(ic, ni);\n    return ret;\n}\n\nvoid ItlIwx::\niwx_rx_frame(struct iwx_softc *sc, mbuf_t m, int chanidx,\n             uint32_t rx_pkt_status, int is_shortpre, int rate_n_flags,\n             uint32_t device_timestamp, struct ieee80211_rxinfo *rxi,\n             struct mbuf_list *ml)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct ieee80211_frame *wh;\n    struct ieee80211_node *ni;\n    struct _ifnet *ifp = IC2IFP(ic);\n    \n    if (chanidx < 0 || chanidx >= nitems(ic->ic_channels))\n        chanidx = ieee80211_chan2ieee(ic, ic->ic_ibss_chan);\n    \n    wh = mtod(m, struct ieee80211_frame *);\n    ni = ieee80211_find_rxnode(ic, wh);\n    if ((rxi->rxi_flags & IEEE80211_RXI_HWDEC) &&\n        iwx_ccmp_decap(sc, m, ni, rxi) != 0) {\n        ifp->netStat->inputErrors++;\n        mbuf_freem(m);\n        ieee80211_release_node(ic, ni);\n        return;\n    }\n    \n#if NBPFILTER > 0\n    if (sc->sc_drvbpf != NULL) {\n        struct iwx_rx_radiotap_header *tap = &sc->sc_rxtap;\n        uint16_t chan_flags;\n        \n        tap->wr_flags = 0;\n        if (is_shortpre)\n            tap->wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;\n        tap->wr_chan_freq =\n        htole16(ic->ic_channels[chanidx].ic_freq);\n        chan_flags = ic->ic_channels[chanidx].ic_flags;\n        if (ic->ic_curmode != IEEE80211_MODE_11N)\n            chan_flags &= ~IEEE80211_CHAN_HT;\n        tap->wr_chan_flags = htole16(chan_flags);\n        tap->wr_dbm_antsignal = (int8_t)rxi->rxi_rssi;\n        tap->wr_dbm_antnoise = (int8_t)sc->sc_noise;\n        tap->wr_tsft = device_timestamp;\n        if (rate_n_flags & IWX_RATE_MCS_HT_MSK) {\n            uint8_t mcs = (rate_n_flags &\n                           (IWX_RATE_HT_MCS_RATE_CODE_MSK |\n                            IWX_RATE_HT_MCS_NSS_MSK));\n            tap->wr_rate = (0x80 | mcs);\n        } else {\n            uint8_t rate = (rate_n_flags &\n                            IWX_RATE_LEGACY_RATE_MSK);\n            switch (rate) {\n                    /* CCK rates. */\n                case  10: tap->wr_rate =   2; break;\n                case  20: tap->wr_rate =   4; break;\n                case  55: tap->wr_rate =  11; break;\n                case 110: tap->wr_rate =  22; break;\n                    /* OFDM rates. */\n                case 0xd: tap->wr_rate =  12; break;\n                case 0xf: tap->wr_rate =  18; break;\n                case 0x5: tap->wr_rate =  24; break;\n                case 0x7: tap->wr_rate =  36; break;\n                case 0x9: tap->wr_rate =  48; break;\n                case 0xb: tap->wr_rate =  72; break;\n                case 0x1: tap->wr_rate =  96; break;\n                case 0x3: tap->wr_rate = 108; break;\n                    /* Unknown rate: should not happen. */\n                default:  tap->wr_rate =   0;\n            }\n        }\n        \n        bpf_mtap_hdr(sc->sc_drvbpf, tap, sc->sc_rxtap_len,\n                     m, BPF_DIRECTION_IN);\n    }\n#endif\n    ieee80211_inputm(IC2IFP(ic), m, ni, rxi, ml);\n    ieee80211_release_node(ic, ni);\n}\n\nvoid ItlIwx::\niwx_flip_address(uint8_t *addr)\n{\n    int i;\n    uint8_t mac_addr[ETHER_ADDR_LEN];\n\n    for (i = 0; i < ETHER_ADDR_LEN; i++)\n        mac_addr[i] = addr[ETHER_ADDR_LEN - i - 1];\n    IEEE80211_ADDR_COPY(addr, mac_addr);\n}\n\n/*\n * Drop duplicate 802.11 retransmissions\n * (IEEE 802.11-2012: 9.3.2.10 \"Duplicate detection and recovery\")\n * and handle pseudo-duplicate frames which result from deaggregation\n * of A-MSDU frames in hardware.\n */\nint ItlIwx::\niwx_detect_duplicate(struct iwx_softc *sc, mbuf_t m,\n    struct iwx_rx_mpdu_desc *desc, struct ieee80211_rxinfo *rxi)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct iwx_node *in = (struct iwx_node *)ic->ic_bss;\n    struct iwx_rxq_dup_data *dup_data = &in->dup_data;\n    uint8_t tid = IWX_MAX_TID_COUNT, subframe_idx;\n    struct ieee80211_frame *wh = mtod(m, struct ieee80211_frame *);\n    uint8_t type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;\n    uint8_t subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;\n    int hasqos = ieee80211_has_qos(wh);\n    uint16_t seq;\n\n    if (type == IEEE80211_FC0_TYPE_CTL ||\n        (hasqos && (subtype & IEEE80211_FC0_SUBTYPE_NODATA)) ||\n        IEEE80211_IS_MULTICAST(wh->i_addr1))\n        return 0;\n\n    if (hasqos) {\n        tid = (ieee80211_get_qos(wh) & IEEE80211_QOS_TID);\n        if (tid > IWX_MAX_TID_COUNT)\n            tid = IWX_MAX_TID_COUNT;\n    }\n\n    /* If this wasn't a part of an A-MSDU the sub-frame index will be 0 */\n    subframe_idx = desc->amsdu_info &\n        IWX_RX_MPDU_AMSDU_SUBFRAME_IDX_MASK;\n\n    seq = letoh16(*(u_int16_t *)wh->i_seq) >> IEEE80211_SEQ_SEQ_SHIFT;\n    if ((wh->i_fc[1] & IEEE80211_FC1_RETRY) &&\n        dup_data->last_seq[tid] == seq &&\n        dup_data->last_sub_frame[tid] >= subframe_idx)\n        return 1;\n\n    /*\n     * Allow the same frame sequence number for all A-MSDU subframes\n     * following the first subframe.\n     * Otherwise these subframes would be discarded as replays.\n     */\n    if (dup_data->last_seq[tid] == seq &&\n        subframe_idx > dup_data->last_sub_frame[tid] &&\n        (desc->mac_flags2 & IWX_RX_MPDU_MFLG2_AMSDU)) {\n        rxi->rxi_flags |= IEEE80211_RXI_SAME_SEQ;\n    }\n\n    dup_data->last_seq[tid] = seq;\n    dup_data->last_sub_frame[tid] = subframe_idx;\n\n    return 0;\n}\n\n/*\n * Returns true if sn2 - buffer_size < sn1 < sn2.\n * To be used only in order to compare reorder buffer head with NSSN.\n * We fully trust NSSN unless it is behind us due to reorder timeout.\n * Reorder timeout can only bring us up to buffer_size SNs ahead of NSSN.\n */\nint ItlIwx::\niwx_is_sn_less(uint16_t sn1, uint16_t sn2, uint16_t buffer_size)\n{\n    return SEQ_LT(sn1, sn2) && !SEQ_LT(sn1, sn2 - buffer_size);\n}\n\nvoid ItlIwx::\niwx_release_frames(struct iwx_softc *sc, struct ieee80211_node *ni,\n    struct iwx_rxba_data *rxba, struct iwx_reorder_buffer *reorder_buf,\n    uint16_t nssn, struct mbuf_list *ml)\n{\n    struct iwx_reorder_buf_entry *entries = &rxba->entries[0];\n    uint16_t ssn = reorder_buf->head_sn;\n\n    /* ignore nssn smaller than head sn - this can happen due to timeout */\n    if (iwx_is_sn_less(nssn, ssn, reorder_buf->buf_size))\n        goto set_timer;\n\n    while (iwx_is_sn_less(ssn, nssn, reorder_buf->buf_size)) {\n        int index = ssn % reorder_buf->buf_size;\n        mbuf_t m;\n        int chanidx, is_shortpre;\n        uint32_t rx_pkt_status, rate_n_flags, device_timestamp;\n        struct ieee80211_rxinfo *rxi;\n\n        /* This data is the same for all A-MSDU subframes. */\n        chanidx = entries[index].chanidx;\n        rx_pkt_status = entries[index].rx_pkt_status;\n        is_shortpre = entries[index].is_shortpre;\n        rate_n_flags = entries[index].rate_n_flags;\n        device_timestamp = entries[index].device_timestamp;\n        rxi = &entries[index].rxi;\n\n        /*\n         * Empty the list. Will have more than one frame for A-MSDU.\n         * Empty list is valid as well since nssn indicates frames were\n         * received.\n         */\n        while ((m = ml_dequeue(&entries[index].frames)) != NULL) {\n            iwx_rx_frame(sc, m, chanidx, rx_pkt_status, is_shortpre,\n                rate_n_flags, device_timestamp, rxi, ml);\n            reorder_buf->num_stored--;\n\n            /*\n             * Allow the same frame sequence number and CCMP PN for\n             * all A-MSDU subframes following the first subframe.\n             * Otherwise they would be discarded as replays.\n             */\n            rxi->rxi_flags |= IEEE80211_RXI_SAME_SEQ;\n            rxi->rxi_flags |= IEEE80211_RXI_HWDEC_SAME_PN;\n        }\n\n        ssn = (ssn + 1) & 0xfff;\n    }\n    reorder_buf->head_sn = nssn;\n\nset_timer:\n    if (reorder_buf->num_stored && !reorder_buf->removed) {\n        timeout_add_usec(&reorder_buf->reorder_timer,\n            RX_REORDER_BUF_TIMEOUT_MQ_USEC);\n    } else\n        timeout_del(&reorder_buf->reorder_timer);\n}\n\nint ItlIwx::\niwx_oldsn_workaround(struct iwx_softc *sc, struct ieee80211_node *ni, int tid,\n    struct iwx_reorder_buffer *buffer, uint32_t reorder_data, uint32_t gp2)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n\n    if (gp2 != buffer->consec_oldsn_ampdu_gp2) {\n        /* we have a new (A-)MPDU ... */\n\n        /*\n         * reset counter to 0 if we didn't have any oldsn in\n         * the last A-MPDU (as detected by GP2 being identical)\n         */\n        if (!buffer->consec_oldsn_prev_drop)\n            buffer->consec_oldsn_drops = 0;\n\n        /* either way, update our tracking state */\n        buffer->consec_oldsn_ampdu_gp2 = gp2;\n    } else if (buffer->consec_oldsn_prev_drop) {\n        /*\n         * tracking state didn't change, and we had an old SN\n         * indication before - do nothing in this case, we\n         * already noted this one down and are waiting for the\n         * next A-MPDU (by GP2)\n         */\n        return 0;\n    }\n\n    /* return unless this MPDU has old SN */\n    if (!(reorder_data & IWX_RX_MPDU_REORDER_BA_OLD_SN))\n        return 0;\n\n    /* update state */\n    buffer->consec_oldsn_prev_drop = 1;\n    buffer->consec_oldsn_drops++;\n\n    /* if limit is reached, send del BA and reset state */\n    if (buffer->consec_oldsn_drops == IWX_AMPDU_CONSEC_DROPS_DELBA) {\n        XYLog(\"reached %d old SN frames, stopping BA session on TID %d\\n\",\n              IWX_AMPDU_CONSEC_DROPS_DELBA, tid);\n        ieee80211_delba_request(ic, ni, IEEE80211_REASON_UNSPECIFIED,\n            0, tid);\n        buffer->consec_oldsn_prev_drop = 0;\n        buffer->consec_oldsn_drops = 0;\n        return 1;\n    }\n\n    return 0;\n}\n\n/*\n * Handle re-ordering of frames which were de-aggregated in hardware.\n * Returns 1 if the MPDU was consumed (buffered or dropped).\n * Returns 0 if the MPDU should be passed to upper layer.\n */\nint ItlIwx::\niwx_rx_reorder(struct iwx_softc *sc, mbuf_t m, int chanidx,\n    struct iwx_rx_mpdu_desc *desc, int is_shortpre, int rate_n_flags,\n    uint32_t device_timestamp, struct ieee80211_rxinfo *rxi,\n    struct mbuf_list *ml)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct ieee80211_frame *wh;\n    struct ieee80211_node *ni;\n    struct iwx_rxba_data *rxba;\n    struct iwx_reorder_buffer *buffer;\n    uint32_t reorder_data = le32toh(desc->reorder_data);\n    int is_amsdu = (desc->mac_flags2 & IWX_RX_MPDU_MFLG2_AMSDU);\n    int last_subframe =\n        (desc->amsdu_info & IWX_RX_MPDU_AMSDU_LAST_SUBFRAME);\n    uint8_t tid;\n    uint8_t subframe_idx = (desc->amsdu_info &\n        IWX_RX_MPDU_AMSDU_SUBFRAME_IDX_MASK);\n    struct iwx_reorder_buf_entry *entries;\n    int index;\n    uint16_t nssn, sn;\n    uint8_t baid, type, subtype;\n    int hasqos;\n\n    wh = mtod(m, struct ieee80211_frame *);\n    hasqos = ieee80211_has_qos(wh);\n    tid = hasqos ? ieee80211_get_qos(wh) & IEEE80211_QOS_TID : 0;\n\n    type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;\n    subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;\n\n    /*\n     * We are only interested in Block Ack requests and unicast QoS data.\n     */\n    if (IEEE80211_IS_MULTICAST(wh->i_addr1))\n        return 0;\n    if (hasqos) {\n        if (subtype & IEEE80211_FC0_SUBTYPE_NODATA)\n            return 0;\n    } else {\n        if (type != IEEE80211_FC0_TYPE_CTL ||\n            subtype != IEEE80211_FC0_SUBTYPE_BAR)\n            return 0;\n    }\n\n    baid = (reorder_data & IWX_RX_MPDU_REORDER_BAID_MASK) >>\n    IWX_RX_MPDU_REORDER_BAID_SHIFT;\n    if (baid == IWX_RX_REORDER_DATA_INVALID_BAID ||\n        baid >= nitems(sc->sc_rxba_data))\n        return 0;\n\n    rxba = &sc->sc_rxba_data[baid];\n    if (rxba->reorder_buf.buf_size == 0 || tid != rxba->tid || rxba->sta_id != IWX_STATION_ID)\n        return 0;\n    \n    if (rxba->timeout != 0)\n        getmicrouptime(&rxba->last_rx);\n\n    /* Bypass A-MPDU re-ordering in net80211. */\n    rxi->rxi_flags |= IEEE80211_RXI_AMPDU_DONE;\n\n    nssn = reorder_data & IWX_RX_MPDU_REORDER_NSSN_MASK;\n    sn = (reorder_data & IWX_RX_MPDU_REORDER_SN_MASK) >>\n        IWX_RX_MPDU_REORDER_SN_SHIFT;\n\n    buffer = &rxba->reorder_buf;\n    entries = &rxba->entries[0];\n\n    if (!buffer->valid) {\n        if (reorder_data & IWX_RX_MPDU_REORDER_BA_OLD_SN)\n            return 0;\n        buffer->valid = 1;\n    }\n\n    ni = ieee80211_find_rxnode(ic, wh);\n    if (type == IEEE80211_FC0_TYPE_CTL &&\n        subtype == IEEE80211_FC0_SUBTYPE_BAR) {\n        iwx_release_frames(sc, ni, rxba, buffer, nssn, ml);\n        goto drop;\n    }\n\n    /*\n     * If there was a significant jump in the nssn - adjust.\n     * If the SN is smaller than the NSSN it might need to first go into\n     * the reorder buffer, in which case we just release up to it and the\n     * rest of the function will take care of storing it and releasing up to\n     * the nssn.\n     */\n    if (!iwx_is_sn_less(nssn, buffer->head_sn + buffer->buf_size,\n        buffer->buf_size) ||\n        !SEQ_LT(sn, buffer->head_sn + buffer->buf_size)) {\n        uint16_t min_sn = SEQ_LT(sn, nssn) ? sn : nssn;\n        ic->ic_stats.is_ht_rx_frame_above_ba_winend++;\n        iwx_release_frames(sc, ni, rxba, buffer, min_sn, ml);\n    }\n\n    if (iwx_oldsn_workaround(sc, ni, tid, buffer, reorder_data,\n        device_timestamp)) {\n         /* BA session will be torn down. */\n        ic->ic_stats.is_ht_rx_ba_window_jump++;\n        goto drop;\n\n    }\n\n    /* drop any outdated packets */\n    if (SEQ_LT(sn, buffer->head_sn)) {\n        ic->ic_stats.is_ht_rx_frame_below_ba_winstart++;\n        goto drop;\n    }\n\n    /* release immediately if allowed by nssn and no stored frames */\n    if (!buffer->num_stored && SEQ_LT(sn, nssn)) {\n        if (iwx_is_sn_less(buffer->head_sn, nssn, buffer->buf_size) &&\n           (!is_amsdu || last_subframe))\n            buffer->head_sn = nssn;\n        ieee80211_release_node(ic, ni);\n        return 0;\n    }\n\n    /*\n     * release immediately if there are no stored frames, and the sn is\n     * equal to the head.\n     * This can happen due to reorder timer, where NSSN is behind head_sn.\n     * When we released everything, and we got the next frame in the\n     * sequence, according to the NSSN we can't release immediately,\n     * while technically there is no hole and we can move forward.\n     */\n    if (!buffer->num_stored && sn == buffer->head_sn) {\n        if (!is_amsdu || last_subframe)\n            buffer->head_sn = (buffer->head_sn + 1) & 0xfff;\n        ieee80211_release_node(ic, ni);\n        return 0;\n    }\n\n    index = sn % buffer->buf_size;\n\n    /*\n     * Check if we already stored this frame\n     * As AMSDU is either received or not as whole, logic is simple:\n     * If we have frames in that position in the buffer and the last frame\n     * originated from AMSDU had a different SN then it is a retransmission.\n     * If it is the same SN then if the subframe index is incrementing it\n     * is the same AMSDU - otherwise it is a retransmission.\n     */\n    if (!ml_empty(&entries[index].frames)) {\n        if (!is_amsdu) {\n            ic->ic_stats.is_ht_rx_ba_no_buf++;\n            goto drop;\n        } else if (sn != buffer->last_amsdu ||\n            buffer->last_sub_index >= subframe_idx) {\n            ic->ic_stats.is_ht_rx_ba_no_buf++;\n            goto drop;\n        }\n    } else {\n        /* This data is the same for all A-MSDU subframes. */\n        entries[index].chanidx = chanidx;\n        entries[index].is_shortpre = is_shortpre;\n        entries[index].rate_n_flags = rate_n_flags;\n        entries[index].device_timestamp = device_timestamp;\n        memcpy(&entries[index].rxi, rxi, sizeof(entries[index].rxi));\n    }\n\n    /* put in reorder buffer */\n    ml_enqueue(&entries[index].frames, m);\n    buffer->num_stored++;\n    getmicrouptime(&entries[index].reorder_time);\n\n    if (is_amsdu) {\n        buffer->last_amsdu = sn;\n        buffer->last_sub_index = subframe_idx;\n    }\n\n    /*\n     * We cannot trust NSSN for AMSDU sub-frames that are not the last.\n     * The reason is that NSSN advances on the first sub-frame, and may\n     * cause the reorder buffer to advance before all the sub-frames arrive.\n     * Example: reorder buffer contains SN 0 & 2, and we receive AMSDU with\n     * SN 1. NSSN for first sub frame will be 3 with the result of driver\n     * releasing SN 0,1, 2. When sub-frame 1 arrives - reorder buffer is\n     * already ahead and it will be dropped.\n     * If the last sub-frame is not on this queue - we will get frame\n     * release notification with up to date NSSN.\n     */\n    if (!is_amsdu || last_subframe)\n        iwx_release_frames(sc, ni, rxba, buffer, nssn, ml);\n\n    ieee80211_release_node(ic, ni);\n    return 1;\n\ndrop:\n    mbuf_freem(m);\n    ieee80211_release_node(ic, ni);\n    return 1;\n}\n\nvoid ItlIwx::\niwx_rx_mpdu_mq(struct iwx_softc *sc, mbuf_t m, void *pktdata,\n               size_t maxlen, struct mbuf_list *ml)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct ieee80211_rxinfo rxi;\n    struct iwx_rx_mpdu_desc *desc;\n    uint32_t len, hdrlen, rate_n_flags, device_timestamp;\n    int rssi;\n    uint8_t chanidx;\n    uint16_t phy_info;\n    size_t desc_size;\n    \n    desc = (struct iwx_rx_mpdu_desc *)pktdata;\n    if (sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210)\n        desc_size = sizeof(struct iwx_rx_mpdu_desc);\n    else\n        desc_size = IWX_RX_DESC_SIZE_V1;\n    \n    if (!(desc->status & htole16(IWX_RX_MPDU_RES_STATUS_CRC_OK)) ||\n        !(desc->status & htole16(IWX_RX_MPDU_RES_STATUS_OVERRUN_OK))) {\n        mbuf_freem(m);\n        return; /* drop */\n    }\n    \n    len = le16toh(desc->mpdu_len);\n    if (ic->ic_opmode == IEEE80211_M_MONITOR) {\n        /* Allow control frames in monitor mode. */\n        if (len < sizeof(struct ieee80211_frame_cts)) {\n            ic->ic_stats.is_rx_tooshort++;\n            IC2IFP(ic)->netStat->inputErrors++;\n            mbuf_freem(m);\n            return;\n        }\n    } else if (len < sizeof(struct ieee80211_frame)) {\n        ic->ic_stats.is_rx_tooshort++;\n        IC2IFP(ic)->netStat->inputErrors++;\n        mbuf_freem(m);\n        return;\n    }\n    if (len > maxlen - desc_size) {\n        IC2IFP(ic)->netStat->inputErrors++;\n        mbuf_freem(m);\n        return;\n    }\n    \n    //    m->m_data = pktdata + sizeof(*desc);\n    //    m->m_pkthdr.len = m->m_len = len;\n    mbuf_setdata(m, (uint8_t*)pktdata + desc_size, len);\n    mbuf_pkthdr_setlen(m, len);\n    mbuf_setlen(m, len);\n    \n    /* Account for padding following the frame header. */\n    if (desc->mac_flags2 & IWX_RX_MPDU_MFLG2_PAD) {\n        struct ieee80211_frame *wh = mtod(m, struct ieee80211_frame *);\n        int type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;\n        if (type == IEEE80211_FC0_TYPE_CTL) {\n            switch (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) {\n                case IEEE80211_FC0_SUBTYPE_CTS:\n                    hdrlen = sizeof(struct ieee80211_frame_cts);\n                    break;\n                case IEEE80211_FC0_SUBTYPE_ACK:\n                    hdrlen = sizeof(struct ieee80211_frame_ack);\n                    break;\n                default:\n                    hdrlen = sizeof(struct ieee80211_frame_min);\n                    break;\n            }\n        } else\n            hdrlen = ieee80211_get_hdrlen(wh);\n        \n        if ((le16toh(desc->status) &\n             IWX_RX_MPDU_RES_STATUS_SEC_ENC_MSK) ==\n            IWX_RX_MPDU_RES_STATUS_SEC_CCM_ENC) {\n            /* Padding is inserted after the IV. */\n            hdrlen += IEEE80211_CCMP_HDRLEN;\n        }\n        \n        //        memmove(m->m_data + 2, m->m_data, hdrlen);\n        memmove((uint8_t*)mbuf_data(m) + 2, mbuf_data(m), hdrlen);\n        mbuf_adj(m, 2);\n    }\n    \n    memset(&rxi, 0, sizeof(rxi));\n    \n    /*\n     * Hardware de-aggregates A-MSDUs and copies the same MAC header\n     * in place for each subframe. But it leaves the 'A-MSDU present'\n     * bit set in the frame header. We need to clear this bit ourselves.\n     * (XXX This workaround is not required on AX200/AX201 devices that\n     * have been tested by me, but it's unclear when this problem was\n     * fixed in the hardware. It definitely affects the 9k generation.\n     * Leaving this in place for now since some 9k/AX200 hybrids seem\n     * to exist that we may eventually add support for.)\n     *\n     * And we must allow the same CCMP PN for subframes following the\n     * first subframe. Otherwise they would be discarded as replays.\n     */\n    if (desc->mac_flags2 & IWX_RX_MPDU_MFLG2_AMSDU) {\n        struct ieee80211_frame *wh = mtod(m, struct ieee80211_frame *);\n        uint8_t subframe_idx = (desc->amsdu_info &\n                                IWX_RX_MPDU_AMSDU_SUBFRAME_IDX_MASK);\n        if (subframe_idx > 0)\n            rxi.rxi_flags |= IEEE80211_RXI_HWDEC_SAME_PN;\n        if (ieee80211_has_qos(wh) && ieee80211_has_addr4(wh) &&\n            mbuf_len(m) >= sizeof(struct ieee80211_qosframe_addr4)) {\n            struct ieee80211_qosframe_addr4 *qwh4 = mtod(m,\n                                                         struct ieee80211_qosframe_addr4 *);\n            qwh4->i_qos[0] &= htole16(~IEEE80211_QOS_AMSDU);\n        } else if (ieee80211_has_qos(wh) &&\n                   mbuf_len(m) >= sizeof(struct ieee80211_qosframe)) {\n            struct ieee80211_qosframe *qwh = mtod(m,\n                                                  struct ieee80211_qosframe *);\n            qwh->i_qos[0] &= htole16(~IEEE80211_QOS_AMSDU);\n        }    \n    }\n    \n    /*\n     * Verify decryption before duplicate detection. The latter uses\n     * the TID supplied in QoS frame headers and this TID is implicitly\n     * verified as part of the CCMP nonce.\n     */\n    if (iwx_rx_hwdecrypt(sc, m, le16toh(desc->status), &rxi)) {\n        mbuf_freem(m);\n        return;\n    }\n    \n    if (iwx_detect_duplicate(sc, m, desc, &rxi)) {\n        mbuf_freem(m);\n        return;\n    }\n    \n    rssi = iwx_rxmq_get_signal_strength(sc, desc);\n    rssi = (0 - IWX_MIN_DBM) + rssi;    /* normalize */\n    rssi = MIN(rssi, ic->ic_max_rssi);    /* clip to max. 100% */\n    \n    rxi.rxi_rssi = rssi;\n    \n    phy_info = le16toh(desc->phy_info);\n    if (sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210) {\n        rate_n_flags = le32toh(desc->v3.rate_n_flags);\n        chanidx = desc->v3.channel;\n        device_timestamp = desc->v3.gp2_on_air_rise;\n        rxi.rxi_tstamp = (uint32_t)le64toh(desc->v3.tsf_on_air_rise);\n    } else {\n        rate_n_flags = le32toh(desc->v1.rate_n_flags);\n        chanidx = desc->v1.channel;\n        device_timestamp = desc->v1.gp2_on_air_rise;\n        rxi.rxi_tstamp = (uint32_t)le64toh(desc->v1.tsf_on_air_rise);\n    }\n    rxi.rxi_chan = chanidx;\n    \n    if (iwx_rx_reorder(sc, m, chanidx, desc,\n                       (phy_info & IWX_RX_MPDU_PHY_SHORT_PREAMBLE),\n                       rate_n_flags, device_timestamp, &rxi, ml))\n        return;\n    \n    iwx_rx_frame(sc, m, chanidx, le16toh(desc->status),\n                 (phy_info & IWX_RX_MPDU_PHY_SHORT_PREAMBLE),\n                 rate_n_flags, device_timestamp, &rxi, ml);\n}\n\nvoid ItlIwx::\niwx_rx_tx_cmd_single(struct iwx_softc *sc, struct iwx_rx_packet *pkt,\n                     struct iwx_tx_data *txd)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct _ifnet *ifp = IC2IFP(ic);\n    struct iwx_tx_resp *tx_resp = (struct iwx_tx_resp *)pkt->data;\n    int status = le16toh(tx_resp->status.status) & IWX_TX_STATUS_MSK;\n    int txfail;\n    \n    KASSERT(tx_resp->frame_count == 1, \"tx_resp->frame_count == 1\");\n    \n    txfail = (status != IWX_TX_STATUS_SUCCESS);\n    \n    if (txfail) {\n        XYLog(\"%s %d OUTPUT_ERROR type=%d status=%d\\n\", __FUNCTION__, __LINE__, txd->type, status);\n        ifp->netStat->outputErrors++;\n        if (txd->type == IEEE80211_FC0_TYPE_MGT)\n            iwx_toggle_tx_ant(sc, &sc->sc_mgmt_last_antenna_idx);\n    }\n}\n\nvoid\niwx_clear_tx_desc(struct iwx_softc *sc, struct iwx_tx_ring *ring, int idx)\n{\n    struct iwx_tfh_tfd *desc = &ring->desc[idx];\n    uint8_t num_tbs = le16toh(desc->num_tbs) & 0x1f;\n    int i;\n    \n    /* First TB is never cleared - it is bidirectional DMA data. */\n    for (i = 1; i < num_tbs; i++) {\n        struct iwx_tfh_tb *tb = &desc->tbs[i];\n        memset(tb, 0, sizeof(*tb));\n    }\n    desc->num_tbs = 0;\n    \n//    bus_dmamap_sync(sc->sc_dmat, ring->desc_dma.map,\n//                    (char *)(void *)desc - (char *)(void *)ring->desc_dma.vaddr,\n//                    sizeof(*desc), BUS_DMASYNC_PREWRITE);\n}\n\nvoid ItlIwx::\niwx_txd_done(struct iwx_softc *sc, struct iwx_tx_data *txd)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    \n    //    bus_dmamap_sync(sc->sc_dmat, txd->map, 0, txd->map->dm_mapsize,\n    //        BUS_DMASYNC_POSTWRITE);\n    //    bus_dmamap_unload(sc->sc_dmat, txd->map);\n    mbuf_freem(txd->m);\n    txd->m = NULL;\n    \n    KASSERT(txd->in, \"txd->in\");\n    ieee80211_release_node(ic, &txd->in->in_ni);\n    txd->in = NULL;\n}\n\nvoid ItlIwx::\niwx_clear_oactive(struct iwx_softc *sc, struct iwx_tx_ring *ring)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct _ifnet *ifp = &ic->ic_if;\n\n    if (ring->queued < ring->low_mark) {\n        sc->qfullmsk &= ~(1 << ring->qid);\n        if (sc->qfullmsk == 0 && ifq_is_oactive(&ifp->if_snd)) {\n            ifq_clr_oactive(&ifp->if_snd);\n            (*ifp->if_start)(ifp);\n        }\n#ifdef __PRIVATE_SPI__\n        ifp->iface->signalOutputThread();\n#endif\n    }\n}\n\nvoid ItlIwx::\niwx_rx_tx_ba_notif(struct iwx_softc *sc, struct iwx_rx_packet *pkt, struct iwx_rx_data *data)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct iwx_compressed_ba_notif *ba_res = (struct iwx_compressed_ba_notif *)pkt->data;\n    uint8_t tid;\n    uint8_t qid;\n    int i;\n    struct iwx_tx_ring *ring;\n\n    sc->sc_tx_timer = 0;\n\n    if (le32toh(ba_res->flags) != IWX_BA_RESP_TX_BAR && le32toh(ba_res->flags) != IWX_BA_RESP_TX_AGG){\n        DPRINTFN(3, (\"BA_NOTIFICATION flags %x, sent:%d, acked:%d, tfd_cnt:%d, query_frame_cnt:%d, retry_cnt:%d\\n\",\n              le32toh(ba_res->flags),\n              le16toh(ba_res->txed),\n              le16toh(ba_res->done),\n                     le16toh(ba_res->tfd_cnt),\n              ba_res->query_frame_cnt,\n              ba_res->retry_cnt));\n    }\n\n    if (ic->ic_state != IEEE80211_S_RUN)\n        return;\n\n    if (!le16toh(ba_res->tfd_cnt))\n        return;\n\n    /* Free per TID */\n    for (i = 0; i < le16toh(ba_res->tfd_cnt); i++) {\n        struct iwx_compressed_ba_tfd *ba_tfd = &ba_res->tfd[i];\n\n        tid = ba_tfd->tid;\n\n        qid = le16toh(ba_tfd->q_num);\n        ring = &sc->txq[qid];\n\n        sc->sc_tx_timer = 0;\n\n        iwx_ampdu_txq_advance(sc, ring, IWX_AGG_SSN_TO_TXQ_IDX(le16toh(ba_tfd->tfd_index), ring->ring_count));\n        iwx_clear_oactive(sc, ring);\n    }\n}\n\nvoid ItlIwx::\niwx_ampdu_txq_advance(struct iwx_softc *sc, struct iwx_tx_ring *ring, int idx)\n{\n    struct iwx_tx_data *txd;\n\n    while (ring->tail != idx) {\n        txd = &ring->data[ring->tail];\n        if (txd->m != NULL) {\n            iwx_txd_done(sc, txd);\n            iwx_clear_tx_desc(sc, ring, ring->tail);\n            ring->queued--;\n        }\n        ring->tail = (ring->tail + 1) % ring->ring_count;\n    }\n}\n\n#define IWX_AGG_TX_STATE_(x) case IWX_AGG_TX_STATE_ ## x: return #x\nstatic const char *iwx_get_agg_tx_status(uint16_t status)\n{\n    switch (status & IWX_AGG_TX_STATE_STATUS_MSK) {\n            IWX_AGG_TX_STATE_(TRANSMITTED);\n            IWX_AGG_TX_STATE_(UNDERRUN);\n            IWX_AGG_TX_STATE_(BT_PRIO);\n            IWX_AGG_TX_STATE_(FEW_BYTES);\n            IWX_AGG_TX_STATE_(ABORT);\n            IWX_AGG_TX_STATE_(TX_ON_AIR_DROP);\n            IWX_AGG_TX_STATE_(LAST_SENT_TRY_CNT);\n            IWX_AGG_TX_STATE_(LAST_SENT_BT_KILL);\n            IWX_AGG_TX_STATE_(SCD_QUERY);\n            IWX_AGG_TX_STATE_(TEST_BAD_CRC32);\n            IWX_AGG_TX_STATE_(RESPONSE);\n            IWX_AGG_TX_STATE_(DUMP_TX);\n            IWX_AGG_TX_STATE_(DELAY_TX);\n    }\n\n    return \"UNKNOWN\";\n}\n\nvoid ItlIwx::\niwx_rx_tx_cmd(struct iwx_softc *sc, struct iwx_rx_packet *pkt,\n              struct iwx_rx_data *data)\n{\n    uint32_t ssn;\n    int idx;\n    int tid;\n    struct iwx_tx_resp *tx_resp = (struct iwx_tx_resp *)pkt->data;\n    int qid = tx_resp->tx_queue;\n    struct iwx_tx_ring *ring = &sc->txq[qid];\n    struct iwx_tx_data *txd;\n\n    bus_dmamap_sync(sc->sc_dmat, data->map, 0, IWX_RBUF_SIZE,\n                    BUS_DMASYNC_POSTREAD);\n    \n    sc->sc_tx_timer = 0;\n\n    if (tx_resp->frame_count > 1) {\n        for (int i = 0; i < tx_resp->frame_count; i++) {\n            uint16_t fstatus = le16_to_cpu((&tx_resp->status)[i].status);\n\n            XYLog(\"status %s (0x%04x), try-count (%d) qid (%d) seq (0x%x)\\n\",\n                         iwx_get_agg_tx_status(fstatus),\n                         fstatus & IWX_AGG_TX_STATE_STATUS_MSK,\n                         (fstatus & IWX_AGG_TX_STATE_TRY_CNT_MSK) >>\n                         IWX_AGG_TX_STATE_TRY_CNT_POS,\n                         qid,\n                         le16_to_cpu((&tx_resp->status)[i].sequence));\n        }\n    } else {\n        tid = tx_resp->ra_tid & 0x0f;\n        memcpy(&ssn, &tx_resp->status + tx_resp->frame_count, sizeof(ssn));\n        ssn = le32toh(ssn) & 0xfff;\n        idx = IWX_AGG_SSN_TO_TXQ_IDX(ssn, ring->ring_count);\n        txd = &ring->data[idx];\n        iwx_rx_tx_cmd_single(sc, pkt, txd);\n        DPRINTFN(3, (\"%s tid=%d ssn=%d idx=%d\\n\", __FUNCTION__, tid, ssn, idx));\n        iwx_ampdu_txq_advance(sc, ring, idx);\n        iwx_clear_oactive(sc, ring);\n    }\n}\n\nvoid ItlIwx::\niwx_rx_bmiss(struct iwx_softc *sc, struct iwx_rx_packet *pkt,\n             struct iwx_rx_data *data)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct iwx_missed_beacons_notif *mbn = (struct iwx_missed_beacons_notif *)pkt->data;\n    uint32_t missed;\n    \n    if ((ic->ic_opmode != IEEE80211_M_STA) ||\n        (ic->ic_state != IEEE80211_S_RUN))\n        return;\n    \n    //    bus_dmamap_sync(sc->sc_dmat, data->map, sizeof(*pkt),\n    //        sizeof(*mbn), BUS_DMASYNC_POSTREAD);\n    \n    missed = le32toh(mbn->consec_missed_beacons_since_last_rx);\n    if (missed > ic->ic_bmissthres && ic->ic_mgt_timer == 0) {\n        if (ic->ic_if.if_flags & IFF_DEBUG) {\n            XYLog(\"%s: receiving no beacons from %s; checking if \"\n                  \"this AP is still responding to probe requests\\n\",\n                  DEVNAME(sc), ether_sprintf(ic->ic_bss->ni_macaddr));\n            /* Dump driver status (TX and RX rings) while we're here. */\n            XYLog(\"%s driver queue status:\\n\", __FUNCTION__);\n            for (int i = 0; i < IWX_MAX_QUEUES; i++) {\n                struct iwx_tx_ring *ring = &sc->txq[i];\n                XYLog(\"  tx ring %2d: qid=%-2d cur=%-3d \"\n                      \"queued=%-3d\\n\",\n                      i, ring->qid, ring->cur, ring->queued);\n            }\n            XYLog(\"  rx ring: cur=%d\\n\", sc->rxq.cur);\n            XYLog(\"  802.11 state %s\\n\",\n                  ieee80211_state_name[sc->sc_ic.ic_state]);\n        }\n        /*\n         * Rather than go directly to scan state, try to send a\n         * directed probe request first. If that fails then the\n         * state machine will drop us into scanning after timing\n         * out waiting for a probe response.\n         */\n        IEEE80211_SEND_MGMT(ic, ic->ic_bss,\n                            IEEE80211_FC0_SUBTYPE_PROBE_REQ, 0);\n    }\n    \n}\n\nint ItlIwx::\niwx_binding_cmd(struct iwx_softc *sc, struct iwx_node *in, uint32_t action)\n{\n    struct iwx_binding_cmd cmd;\n    struct iwx_phy_ctxt *phyctxt = in->in_phyctxt;\n    uint32_t mac_id = IWX_FW_CMD_ID_AND_COLOR(in->in_id, in->in_color);\n    int i, err, active = (sc->sc_flags & IWX_FLAG_BINDING_ACTIVE);\n    uint32_t status;\n    \n    if (action == IWX_FW_CTXT_ACTION_ADD && active) {\n        XYLog(\"binding already added\\n\");\n        return 0;\n    }\n    if (action == IWX_FW_CTXT_ACTION_REMOVE && !active) {\n        XYLog(\"binding already removed\\n\");\n        return 0;\n    }\n    \n    if (phyctxt == NULL) /* XXX race with iwx_stop() */\n        return EINVAL;\n    \n    memset(&cmd, 0, sizeof(cmd));\n    \n    cmd.id_and_color\n    = htole32(IWX_FW_CMD_ID_AND_COLOR(phyctxt->id, phyctxt->color));\n    cmd.action = htole32(action);\n    cmd.phy = htole32(IWX_FW_CMD_ID_AND_COLOR(phyctxt->id, phyctxt->color));\n    \n    cmd.macs[0] = htole32(mac_id);\n    for (i = 1; i < IWX_MAX_MACS_IN_BINDING; i++)\n        cmd.macs[i] = htole32(IWX_FW_CTXT_INVALID);\n    \n    if (IEEE80211_IS_CHAN_2GHZ(phyctxt->channel) ||\n        !isset(sc->sc_enabled_capa, IWX_UCODE_TLV_CAPA_CDB_SUPPORT))\n        cmd.lmac_id = htole32(IWX_LMAC_24G_INDEX);\n    else\n        cmd.lmac_id = htole32(IWX_LMAC_5G_INDEX);\n    \n    status = 0;\n    err = iwx_send_cmd_pdu_status(sc, IWX_BINDING_CONTEXT_CMD, sizeof(cmd),\n                                  &cmd, &status);\n    if (err == 0 && status != 0)\n        err = EIO;\n    \n    return err;\n}\n\nstatic uint8_t\niwx_get_channel_width(struct ieee80211com *ic, struct ieee80211_channel *c)\n{\n    uint8_t ret = IWX_PHY_VHT_CHANNEL_MODE20;\n    if (ic->ic_bss == NULL || ic->ic_state < IEEE80211_S_ASSOC) {\n        return ret;\n    }\n    switch (ic->ic_bss->ni_chw) {\n        case IEEE80211_CHAN_WIDTH_20_NOHT:\n        case IEEE80211_CHAN_WIDTH_20:\n            return IWX_PHY_VHT_CHANNEL_MODE20;\n        case IEEE80211_CHAN_WIDTH_40:\n            return IWX_PHY_VHT_CHANNEL_MODE40;\n        case IEEE80211_CHAN_WIDTH_80:\n            return IWX_PHY_VHT_CHANNEL_MODE80;\n        case IEEE80211_CHAN_WIDTH_160:\n            return IWX_PHY_VHT_CHANNEL_MODE160;\n        default:\n            XYLog(\"Invalid channel width=%u\\n\", ic->ic_bss->ni_chw);\n            return ret;\n    }\n}\n\nstatic uint8_t\niwx_get_ctrl_pos(struct ieee80211com *ic, struct ieee80211_channel *c)\n{\n    if (ic->ic_bss == NULL || ic->ic_state < IEEE80211_S_ASSOC || iwx_get_channel_width(ic, c) == IWX_PHY_VHT_CHANNEL_MODE20)\n        return IWX_PHY_VHT_CTRL_POS_1_BELOW;\n\n    signed int offset = ic->ic_bss->ni_chan->ic_freq - ic->ic_bss->ni_chan->ic_center_freq1;\n    switch (offset) {\n        case -70:\n            return IWX_PHY_VHT_CTRL_POS_4_BELOW;\n        case -50:\n            return IWX_PHY_VHT_CTRL_POS_3_BELOW;\n        case -30:\n            return IWX_PHY_VHT_CTRL_POS_2_BELOW;\n        case -10:\n            return IWX_PHY_VHT_CTRL_POS_1_BELOW;\n        case  10:\n            return IWX_PHY_VHT_CTRL_POS_1_ABOVE;\n        case  30:\n            return IWX_PHY_VHT_CTRL_POS_2_ABOVE;\n        case  50:\n            return IWX_PHY_VHT_CTRL_POS_3_ABOVE;\n        case  70:\n            return IWX_PHY_VHT_CTRL_POS_4_ABOVE;\n        default:\n            XYLog(\"Invalid channel definition freq=%d %d\\n\", ic->ic_bss->ni_chan->ic_freq, offset);\n            /* fall through */\n        case 0:\n            /*\n             * The FW is expected to check the control channel position only\n             * when in HT/VHT and the channel width is not 20MHz. Return\n             * this value as the default one.\n             */\n            return IWX_PHY_VHT_CTRL_POS_1_BELOW;\n    }\n}\n\nint ItlIwx::\niwx_phy_ctxt_cmd_v3(struct iwx_softc *sc, struct iwx_phy_ctxt *ctxt,\n    uint8_t chains_static, uint8_t chains_dynamic, uint32_t action,\n    uint32_t apply_time)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct iwx_phy_context_cmd cmd;\n    uint8_t active_cnt, idle_cnt;\n    struct ieee80211_channel *chan = ctxt->channel;\n    memset(&cmd, 0, sizeof(cmd));\n    cmd.id_and_color = htole32(IWX_FW_CMD_ID_AND_COLOR(ctxt->id,\n                                                       ctxt->color));\n    cmd.action = htole32(action);\n    cmd.lmac_id = htole32(iwx_lmac_id(sc, chan));\n    \n    cmd.ci.band = IEEE80211_IS_CHAN_2GHZ(chan) ?\n    IWX_PHY_BAND_24 : IWX_PHY_BAND_5;\n    cmd.ci.channel = htole32(ieee80211_chan2ieee(ic, chan));\n    cmd.ci.width = iwx_get_channel_width(ic, chan);\n    cmd.ci.ctrl_pos = iwx_get_ctrl_pos(ic, chan);\n\n    XYLog(\"%s: 2ghz=%d, channel=%d, channel_width=%d pos=%d chains static=0x%x, dynamic=0x%x, \"\n          \"rx_ant=0x%x, tx_ant=0x%x\\n\",\n          __FUNCTION__,\n          cmd.ci.band,\n          cmd.ci.channel,\n          cmd.ci.width,\n          cmd.ci.ctrl_pos,\n          chains_static,\n          chains_dynamic,\n          iwx_fw_valid_rx_ant(sc),\n          iwx_fw_valid_tx_ant(sc));\n    \n    idle_cnt = chains_static;\n    active_cnt = chains_dynamic;\n    \n    /* In scenarios where we only ever use a single-stream rates,\n     * i.e. legacy 11b/g/a associations, single-stream APs or even\n     * static SMPS, enable both chains to get diversity, improving\n     * the case where we're far enough from the AP that attenuation\n     * between the two antennas is sufficiently different to impact\n     * performance.\n     */\n    if (active_cnt == 1 && iwx_num_of_ant(iwx_fw_valid_rx_ant(sc)) != 1) {\n        idle_cnt = 2;\n        active_cnt = 2;\n    }\n    \n    cmd.rxchain_info = htole32(iwx_fw_valid_rx_ant(sc) <<\n                               IWX_PHY_RX_CHAIN_VALID_POS);\n    cmd.rxchain_info |= htole32(idle_cnt << IWX_PHY_RX_CHAIN_CNT_POS);\n    cmd.rxchain_info |= htole32(active_cnt <<\n                                IWX_PHY_RX_CHAIN_MIMO_CNT_POS);\n    return iwx_send_cmd_pdu(sc, IWX_PHY_CONTEXT_CMD, 0, sizeof(cmd), &cmd);\n}\n\nint ItlIwx::\niwx_phy_ctxt_cmd_uhb(struct iwx_softc *sc, struct iwx_phy_ctxt *ctxt,\n    uint8_t chains_static, uint8_t chains_dynamic, uint32_t action,\n    uint32_t apply_time)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct iwx_phy_context_cmd_uhb cmd;\n    uint8_t active_cnt, idle_cnt;\n    struct ieee80211_channel *chan = ctxt->channel;\n    memset(&cmd, 0, sizeof(cmd));\n    cmd.id_and_color = htole32(IWX_FW_CMD_ID_AND_COLOR(ctxt->id,\n                                                       ctxt->color));\n    cmd.action = htole32(action);\n    cmd.apply_time = htole32(apply_time);\n    \n    cmd.ci.band = IEEE80211_IS_CHAN_2GHZ(chan) ?\n    IWX_PHY_BAND_24 : IWX_PHY_BAND_5;\n    cmd.ci.channel = htole32(ieee80211_chan2ieee(ic, chan));\n    cmd.ci.width = iwx_get_channel_width(ic, chan);\n    cmd.ci.ctrl_pos = iwx_get_ctrl_pos(ic, chan);\n\n    XYLog(\"%s: [%s:%s] 2ghz=%d, channel=%d, channel_width=%d pos=%d chains static=0x%x, dynamic=0x%x, \"\n          \"rx_ant=0x%x, tx_ant=0x%x\\n\",\n          __FUNCTION__,\n          ic->ic_bss == NULL ? \"\" : (const char *)ic->ic_bss->ni_essid,\n          ic->ic_bss == NULL ? \"\" : ether_sprintf(ic->ic_bss->ni_bssid),\n          cmd.ci.band,\n          cmd.ci.channel,\n          cmd.ci.width,\n          cmd.ci.ctrl_pos,\n          chains_static,\n          chains_dynamic,\n          iwx_fw_valid_rx_ant(sc),\n          iwx_fw_valid_tx_ant(sc));\n    \n    idle_cnt = chains_static;\n    active_cnt = chains_dynamic;\n    \n    cmd.rxchain_info = htole32(iwx_fw_valid_rx_ant(sc) <<\n                               IWX_PHY_RX_CHAIN_VALID_POS);\n    cmd.rxchain_info |= htole32(idle_cnt << IWX_PHY_RX_CHAIN_CNT_POS);\n    cmd.rxchain_info |= htole32(active_cnt <<\n                                IWX_PHY_RX_CHAIN_MIMO_CNT_POS);\n    cmd.txchain_info = htole32(iwx_fw_valid_tx_ant(sc));\n    return iwx_send_cmd_pdu(sc, IWX_PHY_CONTEXT_CMD, 0, sizeof(cmd), &cmd);\n}\n\nint ItlIwx::\niwx_phy_ctxt_cmd(struct iwx_softc *sc, struct iwx_phy_ctxt *ctxt,\n                 uint8_t chains_static, uint8_t chains_dynamic, uint32_t action,\n                 uint32_t apply_time)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct iwx_phy_context_cmd_v1 cmd;\n    uint8_t active_cnt, idle_cnt;\n    struct ieee80211_channel *chan = ctxt->channel;\n    \n    if (iwx_lookup_cmd_ver(sc, IWX_LONG_GROUP, IWX_PHY_CONTEXT_CMD) == 3)\n        return iwx_phy_ctxt_cmd_v3(sc, ctxt, chains_static,\n                                   chains_dynamic, action, apply_time);\n    \n    /*\n     * Intel increased the size of the fw_channel_info struct and neglected\n     * to bump the phy_context_cmd struct, which contains an fw_channel_info\n     * member in the middle.\n     * To keep things simple we use a separate function to handle the larger\n     * variant of the phy context command.\n     */\n    if (isset(sc->sc_enabled_capa, IWX_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS))\n        return iwx_phy_ctxt_cmd_uhb(sc, ctxt, chains_static,\n                                    chains_dynamic, action, apply_time);\n    \n    memset(&cmd, 0, sizeof(cmd));\n    cmd.id_and_color = htole32(IWX_FW_CMD_ID_AND_COLOR(ctxt->id,\n                                                       ctxt->color));\n    cmd.action = htole32(action);\n    cmd.apply_time = htole32(apply_time);\n    \n    cmd.ci.band = IEEE80211_IS_CHAN_2GHZ(chan) ?\n    IWX_PHY_BAND_24 : IWX_PHY_BAND_5;\n    cmd.ci.channel = ieee80211_chan2ieee(ic, chan);\n    cmd.ci.width = iwx_get_channel_width(ic, chan);\n    cmd.ci.ctrl_pos = iwx_get_ctrl_pos(ic, chan);\n    \n    idle_cnt = chains_static;\n    active_cnt = chains_dynamic;\n    cmd.rxchain_info = htole32(iwx_fw_valid_rx_ant(sc) <<\n                               IWX_PHY_RX_CHAIN_VALID_POS);\n    cmd.rxchain_info |= htole32(idle_cnt << IWX_PHY_RX_CHAIN_CNT_POS);\n    cmd.rxchain_info |= htole32(active_cnt <<\n                                IWX_PHY_RX_CHAIN_MIMO_CNT_POS);\n    cmd.txchain_info = htole32(iwx_fw_valid_tx_ant(sc));\n    \n    return iwx_send_cmd_pdu(sc, IWX_PHY_CONTEXT_CMD, 0, sizeof(cmd), &cmd);\n}\n\nint ItlIwx::\niwx_send_cmd(struct iwx_softc *sc, struct iwx_host_cmd *hcmd)\n{\n    struct iwx_tx_ring *ring = &sc->txq[IWX_DQA_CMD_QUEUE];\n    struct iwx_tfh_tfd *desc;\n    struct iwx_tx_data *txdata;\n    struct iwx_device_cmd *cmd;\n    mbuf_t m;\n    bus_addr_t paddr;\n    uint64_t addr;\n    int err = 0, i, paylen, off, s;\n    int idx, code, async, group_id;\n    size_t hdrlen, datasz;\n    uint8_t *data;\n    int generation = sc->sc_generation;\n    unsigned int max_chunks = 1;\n    IOPhysicalSegment seg;\n    \n    code = hcmd->id;\n    async = hcmd->flags & IWX_CMD_ASYNC;\n    idx = (ring->cur & (ring->ring_count - 1));\n    \n    for (i = 0, paylen = 0; i < nitems(hcmd->len); i++) {\n        paylen += hcmd->len[i];\n    }\n    \n    /* If this command waits for a response, allocate response buffer. */\n    hcmd->resp_pkt = NULL;\n    if (hcmd->flags & IWX_CMD_WANT_RESP) {\n        uint8_t *resp_buf;\n        //        KASSERT(!async);\n        //        KASSERT(hcmd->resp_pkt_len >= sizeof(struct iwx_rx_packet));\n        //        KASSERT(hcmd->resp_pkt_len <= IWX_CMD_RESP_MAX);\n        if (sc->sc_cmd_resp_pkt[idx] != NULL)\n            return ENOSPC;\n        resp_buf = (uint8_t *)malloc(hcmd->resp_pkt_len, 0,\n                                     M_NOWAIT | M_ZERO);\n        if (resp_buf == NULL)\n            return ENOMEM;\n        bzero(resp_buf, hcmd->resp_pkt_len);\n        sc->sc_cmd_resp_pkt[idx] = resp_buf;\n        sc->sc_cmd_resp_len[idx] = hcmd->resp_pkt_len;\n    } else {\n        sc->sc_cmd_resp_pkt[idx] = NULL;\n    }\n    \n    s = splnet();\n    \n    desc = &ring->desc[idx];\n    txdata = &ring->data[idx];\n    \n    /*\n     * XXX Intel inside (tm)\n     * Firmware API versions >= 50 reject old-style commands in\n     * group 0 with a \"BAD_COMMAND\" firmware error. We must pretend\n     * that such commands were in the LONG_GROUP instead in order\n     * for firmware to accept them.\n     */\n    if (iwx_cmd_groupid(code) == 0) {\n        code = IWX_WIDE_ID(IWX_LONG_GROUP, code);\n        txdata->flags |= IWX_TXDATA_FLAG_CMD_IS_NARROW;\n    } else\n        txdata->flags &= ~IWX_TXDATA_FLAG_CMD_IS_NARROW;\n    \n    group_id = iwx_cmd_groupid(code);\n    hdrlen = sizeof(cmd->hdr_wide);\n    datasz = sizeof(cmd->data_wide);\n    \n    if (paylen > datasz) {\n                /* Command is too large to fit in pre-allocated space. */\n        size_t totlen = hdrlen + paylen;\n        if (paylen > IWX_MAX_CMD_PAYLOAD_SIZE) {\n            XYLog(\"%s: firmware command too long (%zd bytes)\\n\",\n                  DEVNAME(sc), totlen);\n            err = EINVAL;\n            goto out;\n        }\n        mbuf_allocpacket(MBUF_WAITOK, totlen, &max_chunks, &m);\n        if (m == NULL) {\n            XYLog(\"%s: could not get fw cmd mbuf (%zd bytes)\\n\",\n                  DEVNAME(sc), totlen);\n            err = ENOMEM;\n            goto out;\n        }\n        mbuf_setlen(m, totlen);\n        mbuf_pkthdr_setlen(m, totlen);\n        cmd = mtod(m, struct iwx_device_cmd *);\n        txdata->map->dm_nsegs = txdata->map->cursor->getPhysicalSegmentsWithCoalesce(m, &seg, 1);\n        if (txdata->map->dm_nsegs == 0) {\n            XYLog(\"%s: could not load fw cmd mbuf (%zd bytes)\\n\",\n                  DEVNAME(sc), totlen);\n            mbuf_freem(m);\n            goto out;\n        }\n//                XYLog(\"map fw cmd dm_nsegs=%d\\n\", txdata->map->dm_nsegs);\n        txdata->m = m; /* mbuf will be freed in iwm_cmd_done() */\n        paddr = seg.location;\n    } else {\n        cmd = &ring->cmd[idx];\n        paddr = txdata->cmd_paddr;\n    }\n    \n    cmd->hdr_wide.cmd = iwx_cmd_opcode(code);\n    cmd->hdr_wide.group_id = group_id;\n    cmd->hdr_wide.qid = ring->qid;\n    cmd->hdr_wide.idx = idx;\n    cmd->hdr_wide.length = htole16(paylen);\n    cmd->hdr_wide.reserved = htole16(0);\n    cmd->hdr_wide.version = iwx_cmd_version(code);\n    data = cmd->data_wide;\n    \n    for (i = 0, off = 0; i < nitems(hcmd->data); i++) {\n        if (hcmd->len[i] == 0)\n            continue;\n        memcpy(data + off, hcmd->data[i], hcmd->len[i]);\n        off += hcmd->len[i];\n    }\n    KASSERT(off == paylen, \"off == paylen\");\n    \n    desc->tbs[0].tb_len = htole16(MIN(hdrlen + paylen, IWX_FIRST_TB_SIZE));\n    addr = htole64(paddr);\n    memcpy(&desc->tbs[0].addr, &addr, sizeof(addr));\n    if (hdrlen + paylen > IWX_FIRST_TB_SIZE) {\n        desc->tbs[1].tb_len = htole16(hdrlen + paylen -\n                                      IWX_FIRST_TB_SIZE);\n        addr = htole64(paddr + IWX_FIRST_TB_SIZE);\n        memcpy(&desc->tbs[1].addr, &addr, sizeof(addr));\n        desc->num_tbs = htole16(2);\n    } else\n        desc->num_tbs = htole16(1);\n    \n    \n    //    if (paylen > datasz) {\n    //        bus_dmamap_sync(sc->sc_dmat, txdata->map, 0,\n    //            hdrlen + paylen, BUS_DMASYNC_PREWRITE);\n    //    } else {\n    //        bus_dmamap_sync(sc->sc_dmat, ring->cmd_dma.map,\n    //            (char *)(void *)cmd - (char *)(void *)ring->cmd_dma.vaddr,\n    //            hdrlen + paylen, BUS_DMASYNC_PREWRITE);\n    //    }\n    //    bus_dmamap_sync(sc->sc_dmat, ring->desc_dma.map,\n    //        (char *)(void *)desc - (char *)(void *)ring->desc_dma.vaddr,\n    //        sizeof (*desc), BUS_DMASYNC_PREWRITE);\n    /* Kick command ring. */\n    DPRINTF((\"%s: Sending command (%.2x.%.2x), %d bytes at [%d]:%d ver: %d\\n\", __func__, group_id, cmd->hdr.cmd, cmd->hdr_wide.length, cmd->hdr.idx, cmd->hdr.qid, cmd->hdr_wide.version));\n    ring->queued++;\n    ring->cur = (ring->cur + 1) % getTxQueueSize();\n    IWX_WRITE(sc, IWX_HBUS_TARG_WRPTR, ring->qid << 16 | ring->cur);\n    \n    if (!async) {\n        err = tsleep_nsec(desc, PCATCH, \"iwxcmd\", SEC_TO_NSEC(1));\n        if (err == 0) {\n            /* if hardware is no longer up, return error */\n            if (generation != sc->sc_generation) {\n                err = ENXIO;\n                goto out;\n            }\n            \n            /* Response buffer will be freed in iwx_free_resp(). */\n            hcmd->resp_pkt = (struct iwx_rx_packet *)sc->sc_cmd_resp_pkt[idx];\n            sc->sc_cmd_resp_pkt[idx] = NULL;\n        } else if (generation == sc->sc_generation) {\n            ::free(sc->sc_cmd_resp_pkt[idx]);\n            sc->sc_cmd_resp_pkt[idx] = NULL;\n        }\n    }\nout:\n    splx(s);\n    \n    return err;\n}\n\nint ItlIwx::\niwx_send_cmd_pdu(struct iwx_softc *sc, uint32_t id, uint32_t flags,\n                 uint16_t len, const void *data)\n{\n    struct iwx_host_cmd cmd = {\n        .id = id,\n        .len = { len, },\n        .data = { data, },\n        .flags = flags,\n    };\n    \n    return iwx_send_cmd(sc, &cmd);\n}\n\nint ItlIwx::\niwx_send_cmd_status(struct iwx_softc *sc, struct iwx_host_cmd *cmd,\n                    uint32_t *status)\n{\n    struct iwx_rx_packet *pkt;\n    struct iwx_cmd_response *resp;\n    int err, resp_len;\n    \n    KASSERT((cmd->flags & IWX_CMD_WANT_RESP) == 0, \"(cmd->flags & IWX_CMD_WANT_RESP) == 0\");\n    cmd->flags |= IWX_CMD_WANT_RESP;\n    cmd->resp_pkt_len = sizeof(*pkt) + sizeof(*resp);\n    \n    err = iwx_send_cmd(sc, cmd);\n    if (err)\n        return err;\n    \n    pkt = cmd->resp_pkt;\n    if (pkt == NULL || (pkt->hdr.group_id & IWX_CMD_FAILED_MSK))\n        return EIO;\n    \n    resp_len = iwx_rx_packet_payload_len(pkt);\n    if (resp_len != sizeof(*resp)) {\n        iwx_free_resp(sc, cmd);\n        return EIO;\n    }\n    \n    resp = (struct iwx_cmd_response *)pkt->data;\n    *status = le32toh(resp->status);\n    iwx_free_resp(sc, cmd);\n    return err;\n}\n\nint ItlIwx::\niwx_send_cmd_pdu_status(struct iwx_softc *sc, uint32_t id, uint16_t len,\n                        const void *data, uint32_t *status)\n{\n    struct iwx_host_cmd cmd = {\n        .id = id,\n        .len = { len, },\n        .data = { data, },\n    };\n    \n    return iwx_send_cmd_status(sc, &cmd, status);\n}\n\nvoid ItlIwx::\niwx_free_resp(struct iwx_softc *sc, struct iwx_host_cmd *hcmd)\n{\n    KASSERT((hcmd->flags & (IWX_CMD_WANT_RESP)) == IWX_CMD_WANT_RESP, \"(hcmd->flags & (IWX_CMD_WANT_RESP)) == IWX_CMD_WANT_RESP\");\n    ::free(hcmd->resp_pkt);\n    hcmd->resp_pkt = NULL;\n}\n\nvoid ItlIwx::\niwx_cmd_done(struct iwx_softc *sc, int qid, int idx, int code)\n{\n    struct iwx_tx_ring *ring = &sc->txq[IWX_DQA_CMD_QUEUE];\n    struct iwx_tx_data *data;\n    \n    if (qid != IWX_DQA_CMD_QUEUE) {\n        return;    /* Not a command ack. */\n    }\n    \n    data = &ring->data[idx];\n    \n    if (data->m != NULL) {\n        //        bus_dmamap_sync(sc->sc_dmat, data->map, 0,\n        //            data->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);\n        //        bus_dmamap_unload(sc->sc_dmat, data->map);\n        mbuf_freem(data->m);\n        data->m = NULL;\n    }\n    wakeupOn(&ring->desc[idx]);\n    \n    DPRINTF((\"%s: command 0x%x done\\n\", __func__, code));\n    if (ring->queued == 0) {\n        DPRINTF((\"%s: unexpected firmware response to command 0x%x\\n\",\n                 DEVNAME(sc), code));\n    } else if (ring->queued > 0)\n        ring->queued--;\n}\n\nuint32_t ItlIwx::\niwx_get_tx_ant(struct iwx_softc *sc, struct ieee80211_node *ni,\n                               const struct iwx_rate *rinfo, int type, struct ieee80211_frame *wh)\n{\n    return ((1 << sc->sc_mgmt_last_antenna_idx) << IWX_RATE_MCS_ANT_POS);\n}\n\nvoid ItlIwx::\niwx_toggle_tx_ant(struct iwx_softc *sc, uint8_t *ant)\n{\n    uint8_t valid = iwx_fw_valid_tx_ant(sc);\n    int i;\n    uint8_t ind = *ant; \n    \n    for (i = 0; i < IWX_RATE_MCS_ANT_NUM; i++) {\n        ind = (ind + 1) % IWX_RATE_MCS_ANT_NUM;\n        if (valid & (1 << ind)) {\n            *ant = ind;\n            break;\n        }\n    }\n}\n\n/*\n * Fill in various bit for management frames, and leave them\n * unfilled for data frames (firmware takes care of that).\n * Return the selected TX rate.\n */\nconst struct iwx_rate *ItlIwx::\niwx_tx_fill_cmd(struct iwx_softc *sc, struct iwx_node *in,\n                struct ieee80211_frame *wh, uint32_t *flags, uint32_t *rate_n_flags)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct ieee80211_node *ni = &in->in_ni;\n    struct ieee80211_rateset *rs = &ni->ni_rates;\n    const struct iwx_rate *rinfo;\n    int type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;\n    int min_ridx = iwx_rval2ridx(ieee80211_min_basic_rate(ic));\n    int ridx, rate_flags;\n    uint8_t cmdver;\n    uint8_t hwrate;\n\n    *flags = 0;\n    if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||\n        type != IEEE80211_FC0_TYPE_DATA) {\n        /* for non-data, use the lowest supported rate */\n        ridx = min_ridx;\n        *flags |= IWX_TX_FLAGS_CMD_RATE;\n    } else if (ic->ic_fixed_mcs != -1) {\n        ridx = sc->sc_fixed_ridx;\n        *flags |= IWX_TX_FLAGS_CMD_RATE;\n    } else if (ic->ic_fixed_rate != -1) {\n        ridx = sc->sc_fixed_ridx;\n        *flags |= IWX_TX_FLAGS_CMD_RATE;\n    } else if (ni->ni_flags & IEEE80211_NODE_HT) {\n        ridx = iwx_mcs2ridx[ni->ni_txmcs];\n        return &iwx_rates[ridx];\n    } else {\n        uint8_t rval;\n        rval = (rs->rs_rates[ni->ni_txrate] & IEEE80211_RATE_VAL);\n        ridx = iwx_rval2ridx(rval);\n        if (ridx < min_ridx)\n            ridx = min_ridx;\n        return &iwx_rates[ridx];\n    }\n    \n    rinfo = &iwx_rates[ridx];\n    \n    rate_flags = iwx_get_tx_ant(sc, ni, rinfo, type, wh);\n    \n    hwrate = rinfo->plcp;\n    cmdver = iwx_lookup_cmd_ver(sc, IWX_LONG_GROUP, IWX_TX_CMD);\n    if (cmdver > 8 && cmdver != IWX_FW_CMD_VER_UNKNOWN) {\n        if (IWX_RIDX_IS_CCK(ridx)) {\n            rate_flags |= IWX_RATE_MCS_CCK_MSK;\n            hwrate = ridx;\n        } else {\n            rate_flags |= IWX_RATE_MCS_LEGACY_OFDM_MSK;\n            hwrate = iwx_rate2idx(iwx_ridx2rate(rs, ridx) & IEEE80211_RATE_VAL);\n        }\n    } else if (IWX_RIDX_IS_CCK(ridx))\n        rate_flags |= IWX_RATE_MCS_CCK_MSK_V1;\n    XYLog(\"%s hwrate: %d ridx: %d rate: %d minrate: %d\\n\", __FUNCTION__, hwrate, ridx, iwx_ridx2rate(rs, ridx) & IEEE80211_RATE_VAL, ieee80211_min_basic_rate(ic));\n    *rate_n_flags = htole32(rate_flags | hwrate);\n    \n    return rinfo;\n}\n\nvoid ItlIwx::\niwx_tx_update_byte_tbl(struct iwx_softc *sc, struct iwx_tx_ring *txq, int idx, uint16_t byte_cnt,\n                       uint16_t num_tbs)\n{\n    uint8_t filled_tfd_size, num_fetch_chunks;\n    uint16_t len = byte_cnt;\n    uint16_t bc_ent;\n    \n    filled_tfd_size = offsetof(struct iwx_tfh_tfd, tbs) +\n    num_tbs * sizeof(struct iwx_tfh_tb);\n    /*\n     * filled_tfd_size contains the number of filled bytes in the TFD.\n     * Dividing it by 64 will give the number of chunks to fetch\n     * to SRAM- 0 for one chunk, 1 for 2 and so on.\n     * If, for example, TFD contains only 3 TBs then 32 bytes\n     * of the TFD are used, and only one chunk of 64 bytes should\n     * be fetched\n     */\n    num_fetch_chunks = howmany(filled_tfd_size, 64) - 1;\n    \n    if (sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210) {\n        struct iwx_gen3_bc_tbl *scd_bc_tbl_gen3 = (struct iwx_gen3_bc_tbl *)txq->bc_tbl.vaddr;\n        \n        /* Starting from AX210, the HW expects bytes */\n        bc_ent = htole16(len | (num_fetch_chunks << 14));\n        scd_bc_tbl_gen3->tfd_offset[idx] = bc_ent;\n    } else {\n        struct iwx_agn_scd_bc_tbl *scd_bc_tbl = (struct iwx_agn_scd_bc_tbl *)txq->bc_tbl.vaddr;\n        \n        /* Before AX210, the HW expects DW */\n        len = howmany(len, 4);\n        bc_ent = htole16(len | (num_fetch_chunks << 12));\n        scd_bc_tbl->tfd_offset[idx] = bc_ent;\n    }\n}\n\nint ItlIwx::\niwx_tx(struct iwx_softc *sc, mbuf_t m, struct ieee80211_node *ni, int ac)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct iwx_node *in = (struct iwx_node *)ni;\n    struct iwx_tx_ring *ring;\n    struct iwx_tx_data *data;\n    struct iwx_tfh_tfd *desc;\n    struct iwx_device_cmd *cmd;\n    struct iwx_tx_cmd_gen2 *tx_gen2;\n    struct iwx_tx_cmd_gen3 *tx_gen3;\n    struct ieee80211_frame *wh;\n    struct ieee80211_key *k = NULL;\n    const struct iwx_rate *rinfo;\n    uint64_t paddr;\n    u_int hdrlen;\n    IOPhysicalSegment *seg;\n    IOPhysicalSegment segs[IWX_TFH_NUM_TBS - 2];\n    int nsegs = 0;\n    uint32_t flags = 0, rate_n_flags = 0;\n    uint16_t offload_assist = 0;\n    uint16_t cmd_size = 0;\n\n    uint16_t num_tbs;\n    uint8_t tid, type, subtype;\n    int i, totlen;\n    int qid = IWX_INVALID_QUEUE;\n    int idx;\n\n    wh = mtod(m, struct ieee80211_frame *);\n    type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;\n    subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;\n    if (type == IEEE80211_FC0_TYPE_CTL)\n        hdrlen = sizeof(struct ieee80211_frame_min);\n    else\n        hdrlen = ieee80211_get_hdrlen(wh);\n    \n    tid = IWX_MGMT_TID;\n    qid = sc->first_data_qid;\n\n    /* Put QoS frames on the data queue which maps to their TID. */\n    if (ieee80211_has_qos(wh)) {\n        struct ieee80211_tx_ba *ba;\n        uint16_t qos = ieee80211_get_qos(wh);\n        uint8_t tid = qos & IEEE80211_QOS_TID;\n\n        ba = &ni->ni_tx_ba[tid];\n        if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&\n            type == IEEE80211_FC0_TYPE_DATA &&\n            subtype != IEEE80211_FC0_SUBTYPE_NODATA &&\n            sc->sc_tid_data[tid].qid != 0 &&\n            sc->sc_tid_data[tid].qid != IWX_INVALID_QUEUE &&\n            ba->ba_state == IEEE80211_BA_AGREED) {\n            qid = sc->sc_tid_data[tid].qid;\n        }\n    }\n\n    ring = &sc->txq[qid];\n    if (ring->ring_count == 0) {\n        mbuf_freem(m);\n        return EINVAL;\n    }\n    idx = (ring->cur & (ring->ring_count - 1));\n    desc = &ring->desc[idx];\n    memset(desc, 0, sizeof(*desc));\n    data = &ring->data[idx];\n    \n    cmd = &ring->cmd[idx];\n    cmd->hdr.cmd = IWX_TX_CMD;\n    cmd->hdr.group_id = 0;\n    cmd->hdr.qid = ring->qid;\n    cmd->hdr.idx = idx;\n    \n    rinfo = iwx_tx_fill_cmd(sc, in, wh, &flags, &rate_n_flags);\n    \n#if NBPFILTER > 0\n    if (sc->sc_drvbpf != NULL) {\n        struct iwx_tx_radiotap_header *tap = &sc->sc_txtap;\n        uint16_t chan_flags;\n        \n        tap->wt_flags = 0;\n        tap->wt_chan_freq = htole16(ni->ni_chan->ic_freq);\n        chan_flags = ni->ni_chan->ic_flags;\n        if (ic->ic_curmode != IEEE80211_MODE_11N)\n            chan_flags &= ~IEEE80211_CHAN_HT;\n        tap->wt_chan_flags = htole16(chan_flags);\n        if ((ni->ni_flags & IEEE80211_NODE_HT) &&\n            !IEEE80211_IS_MULTICAST(wh->i_addr1) &&\n            type == IEEE80211_FC0_TYPE_DATA &&\n            rinfo->ht_plcp != IWX_RATE_HT_SISO_MCS_INV_PLCP) {\n            tap->wt_rate = (0x80 | rinfo->ht_plcp);\n        } else\n            tap->wt_rate = rinfo->rate;\n        if ((ic->ic_flags & IEEE80211_F_WEPON) &&\n            (wh->i_fc[1] & IEEE80211_FC1_PROTECTED))\n            tap->wt_flags |= IEEE80211_RADIOTAP_F_WEP;\n        \n        bpf_mtap_hdr(sc->sc_drvbpf, tap, sc->sc_txtap_len,\n                     m, BPF_DIRECTION_OUT);\n    }\n#endif\n    \n    if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {\n        k = ieee80211_get_txkey(ic, wh, ni);\n        if (k->k_cipher != IEEE80211_CIPHER_CCMP) {\n            if ((m = ieee80211_encrypt(ic, m, k)) == NULL)\n                return ENOBUFS;\n            /* 802.11 header may have moved. */\n            wh = mtod(m, struct ieee80211_frame *);\n            flags |= htole32(IWX_TX_FLAGS_ENCRYPT_DIS);\n        } else {\n            k->k_tsc++;\n            /* Hardware increments PN internally and adds IV. */\n        }\n    } else\n        flags |= htole32(IWX_TX_FLAGS_ENCRYPT_DIS);\n    //    totlen = m->m_pkthdr.len;\n    totlen = mbuf_pkthdr_len(m);\n    \n    if (hdrlen % 4)\n        offload_assist |= IWX_TX_CMD_OFFLD_PAD;\n    \n    if (sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210) {\n        tx_gen3 = (struct iwx_tx_cmd_gen3 *)cmd->data;\n        \n        cmd_size = sizeof(*tx_gen3);\n        memset(tx_gen3, 0, cmd_size);\n        \n        tx_gen3->len = htole16(totlen);\n        tx_gen3->offload_assist = htole32(offload_assist);\n        /* Copy 802.11 header in TX command. */\n        memcpy(((uint8_t *)tx_gen3) + sizeof(*tx_gen3), wh, hdrlen);\n        tx_gen3->flags = htole16(flags);\n        tx_gen3->rate_n_flags = htole32(rate_n_flags);\n    } else {\n        tx_gen2 = (struct iwx_tx_cmd_gen2 *)cmd->data;\n        \n        cmd_size = sizeof(*tx_gen2);\n        memset(tx_gen2, 0, cmd_size);\n        tx_gen2->len = htole16(totlen);\n        tx_gen2->offload_assist = htole16(offload_assist);\n        /* Copy 802.11 header in TX command. */\n        memcpy(((uint8_t *)tx_gen2) + sizeof(*tx_gen2), wh, hdrlen);\n        tx_gen2->flags = htole32(flags);\n        tx_gen2->rate_n_flags = htole32(rate_n_flags);\n    }\n    \n    /* Trim 802.11 header. */\n    mbuf_adj(m, hdrlen);\n    \n    nsegs = data->map->cursor->getPhysicalSegmentsWithCoalesce(m, &segs[0], IWX_TFH_NUM_TBS - 2);\n    if (nsegs == 0) {\n        XYLog(\"%s: can't map mbuf (error %d)\\n\", DEVNAME(sc),\n              nsegs);\n        mbuf_freem(m);\n        return ENOMEM;\n    }\n    data->m = m;\n    data->in = in;\n    data->type = type;\n\n    DPRINTFN(3, (\"sending data: 嘤嘤嘤 tid=%d qid=%d idx=%d queued=%d len=%d nsegs=%d flags=0x%08x rate_n_flags=0x%08x offload_assist=%u\\n\",\n          tid, ring->qid, ring->cur, ring->queued, totlen, nsegs, le32toh(flags),\n          le32toh(rate_n_flags), offload_assist));\n    \n    /* Fill TX descriptor. */\n    num_tbs = 2 + nsegs;\n    desc->num_tbs = htole16(num_tbs);\n    \n    desc->tbs[0].tb_len = htole16(IWX_FIRST_TB_SIZE);\n    paddr = htole64(data->cmd_paddr);\n    memcpy(&desc->tbs[0].addr, &paddr, sizeof(paddr));\n    if (data->cmd_paddr >> 32 != (data->cmd_paddr + le32toh(desc->tbs[0].tb_len)) >> 32)\n        DPRINTF((\"%s: TB0 crosses 32bit boundary\\n\", __func__));\n    desc->tbs[1].tb_len = htole16(_ALIGN(sizeof(struct iwx_cmd_header) +\n                                  cmd_size + hdrlen - IWX_FIRST_TB_SIZE, 4));\n    paddr = htole64(data->cmd_paddr + IWX_FIRST_TB_SIZE);\n    memcpy(&desc->tbs[1].addr, &paddr, sizeof(paddr));\n    \n    if (data->cmd_paddr >> 32 != (data->cmd_paddr + le32toh(desc->tbs[1].tb_len)) >> 32)\n        DPRINTF((\"%s: TB1 crosses 32bit boundary\\n\", __func__));\n    \n    /* Other DMA segments are for data payload. */\n    for (i = 0; i < nsegs; i++) {\n        seg = &segs[i];\n        desc->tbs[i + 2].tb_len = htole16(seg->length);\n        paddr = htole64(seg->location);\n        memcpy(&desc->tbs[i + 2].addr, &paddr, sizeof(paddr));\n        if (data->cmd_paddr >> 32 != (data->cmd_paddr + le32toh(desc->tbs[i + 2].tb_len)) >> 32)\n            DPRINTF((\"%s: TB%d crosses 32bit boundary\\n\", __func__, i + 2));\n//        XYLog(\"DMA segments index=%d location=0x%llx length=%llu\", i, seg->location, seg->length);\n    }\n    \n    //    bus_dmamap_sync(sc->sc_dmat, data->map, 0, data->map->dm_mapsize,\n    //        BUS_DMASYNC_PREWRITE);\n    //    bus_dmamap_sync(sc->sc_dmat, ring->cmd_dma.map,\n    //        (char *)(void *)cmd - (char *)(void *)ring->cmd_dma.vaddr,\n    //        sizeof (*cmd), BUS_DMASYNC_PREWRITE);\n    //    bus_dmamap_sync(sc->sc_dmat, ring->desc_dma.map,\n    //        (char *)(void *)desc - (char *)(void *)ring->desc_dma.vaddr,\n    //        sizeof (*desc), BUS_DMASYNC_PREWRITE);\n    \n    iwx_tx_update_byte_tbl(sc, ring, idx, totlen, num_tbs);\n    \n    /* Kick TX ring. */\n    ring->cur = (ring->cur + 1) % getTxQueueSize();\n    IWX_WRITE(sc, IWX_HBUS_TARG_WRPTR, ring->qid << 16 | ring->cur);\n    \n    /* Mark TX ring as full if we reach a certain threshold. */\n    if (++ring->queued > ring->hi_mark) {\n//        XYLog(\"%s sc->qfullmsk is FULL qid=%d ring->cur=%d ring->queued=%d\\n\", __FUNCTION__, ring->qid, ring->cur, ring->queued);\n        sc->qfullmsk |= 1 << ring->qid;\n    }\n    \n    return 0;\n}\n\nint ItlIwx::\niwx_flush_sta_tids(struct iwx_softc *sc, int sta_id, uint16_t tids)\n{\n    struct iwx_rx_packet *pkt;\n    struct iwx_tx_path_flush_cmd_rsp *resp;\n    struct iwx_tx_path_flush_cmd flush_cmd = {\n        .sta_id = htole32(sta_id),\n        .tid_mask = htole16(tids),\n    };\n    struct iwx_host_cmd hcmd = {\n        .id = IWX_TXPATH_FLUSH,\n        .len = { sizeof(flush_cmd), },\n        .data = { &flush_cmd, },\n        .flags = IWX_CMD_WANT_RESP,\n        .resp_pkt_len = sizeof(*pkt) + sizeof(*resp),\n    };\n    int err, resp_len, i, num_flushed_queues;\n    \n    err = iwx_send_cmd(sc, &hcmd);\n    if (err)\n        return err;\n    \n    pkt = hcmd.resp_pkt;\n    if (!pkt || (pkt->hdr.group_id & IWX_CMD_FAILED_MSK)) {\n        err = EIO;\n        goto out;\n    }\n    \n    resp_len = iwx_rx_packet_payload_len(pkt);\n    /* Some firmware versions don't provide a response. */\n    if (resp_len == 0)\n        goto out;\n    else if (resp_len != sizeof(*resp)) {\n        err = EIO;\n        goto out;\n    }\n    \n    resp = (struct iwx_tx_path_flush_cmd_rsp *)pkt->data;\n    \n    if (le16toh(resp->sta_id) != sta_id) {\n        err = EIO;\n        goto out;\n    }\n    \n    num_flushed_queues = le16toh(resp->num_flushed_queues);\n    if (num_flushed_queues > IWX_TX_FLUSH_QUEUE_RSP) {\n        err = EIO;\n        goto out;\n    }\n    \n    for (i = 0; i < num_flushed_queues; i++) {\n        struct iwx_flush_queue_info *queue_info = &resp->queues[i];\n        uint16_t tid = le16toh(queue_info->tid);\n        uint16_t read_after = le16toh(queue_info->read_after_flush);\n        uint16_t qid = le16toh(queue_info->queue_num);\n        struct iwx_tx_ring *txq;\n        \n        if (qid >= nitems(sc->txq))\n            continue;\n\n        if (sc->sc_tid_data[tid].qid != qid)\n            continue;\n        txq = &sc->txq[qid];\n        \n        iwx_ampdu_txq_advance(sc, txq, IWX_AGG_SSN_TO_TXQ_IDX(read_after, txq->ring_count));\n    }\nout:\n    iwx_free_resp(sc, &hcmd);\n    return err;\n}\n\nint ItlIwx::\niwx_flush_sta(struct iwx_softc *sc, struct iwx_node *in)\n{\n    int err;\n    \n    splassert(IPL_NET);\n    \n    sc->sc_flags |= IWX_FLAG_TXFLUSH;\n    \n    err = iwx_drain_sta(sc, in, 1);\n    \n    if (err == ENXIO)\n        goto done;\n    \n    err = iwx_flush_sta_tids(sc, IWX_STATION_ID, 0xffff);\n    if (err) {\n        XYLog(\"%s: could not flush Tx path (error %d)\\n\",\n               __FUNCTION__, err);\n        goto done;\n    }\n    \n    err = iwx_drain_sta(sc, in, 0);\n    if (err == ENXIO)\n        goto done;\n    else\n        err = 0;\ndone:\n    sc->sc_flags &= ~IWX_FLAG_TXFLUSH;\n    return err;\n}\n\nint ItlIwx::\niwx_drain_sta(struct iwx_softc *sc, struct iwx_node* in, int drain)\n{\n    struct iwx_add_sta_cmd cmd;\n    int err;\n    uint32_t status;\n    \n    memset(&cmd, 0, sizeof(cmd));\n    cmd.mac_id_n_color = htole32(IWX_FW_CMD_ID_AND_COLOR(in->in_id,\n                                                         in->in_color));\n    cmd.sta_id = IWX_STATION_ID;\n    cmd.add_modify = IWX_STA_MODE_MODIFY;\n    cmd.station_flags = drain ? htole32(IWX_STA_FLG_DRAIN_FLOW) : 0;\n    cmd.station_flags_msk = htole32(IWX_STA_FLG_DRAIN_FLOW);\n    \n    status = IWX_ADD_STA_SUCCESS;\n    err = iwx_send_cmd_pdu_status(sc, IWX_ADD_STA,\n                                  sizeof(cmd), &cmd, &status);\n    if (err) {\n        printf(\"%s: could not update sta (error %d)\\n\",\n               DEVNAME(sc), err);\n        return err;\n    }\n    \n    switch (status & IWX_ADD_STA_STATUS_MASK) {\n        case IWX_ADD_STA_SUCCESS:\n            break;\n        default:\n            err = EIO;\n            printf(\"%s: Couldn't %s draining for station\\n\",\n                   DEVNAME(sc), drain ? \"enable\" : \"disable\");\n            break;\n    }\n    \n    return err;\n}\n\n#define IWX_POWER_KEEP_ALIVE_PERIOD_SEC    25\n\nint ItlIwx::\niwx_beacon_filter_send_cmd(struct iwx_softc *sc,\n                           struct iwx_beacon_filter_cmd *cmd)\n{\n    size_t len;\n    \n    if (isset(sc->sc_ucode_api, IWX_UCODE_TLV_API_BEACON_FILTER_V4))\n        len = sizeof(struct iwx_beacon_filter_cmd);\n    else\n        len = offsetof(struct iwx_beacon_filter_cmd,\n                       bf_threshold_absolute_low);\n    return iwx_send_cmd_pdu(sc, IWX_REPLY_BEACON_FILTERING_CMD,\n                            0, len, cmd);\n}\n\nint ItlIwx::\niwx_update_beacon_abort(struct iwx_softc *sc, struct iwx_node *in, int enable)\n{\n    struct iwx_beacon_filter_cmd cmd = {\n        IWX_BF_CMD_CONFIG_DEFAULTS,\n        .bf_enable_beacon_filter = htole32(1),\n        .ba_enable_beacon_abort = htole32(enable),\n    };\n    \n    if (!sc->sc_bf.bf_enabled)\n        return 0;\n    \n    sc->sc_bf.ba_enabled = enable;\n    return iwx_beacon_filter_send_cmd(sc, &cmd);\n}\n\nvoid ItlIwx::\niwx_power_build_cmd(struct iwx_softc *sc, struct iwx_node *in,\n                    struct iwx_mac_power_cmd *cmd)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct ieee80211_node *ni = &in->in_ni;\n    int dtim_period, dtim_msec, keep_alive;\n    \n    cmd->id_and_color = htole32(IWX_FW_CMD_ID_AND_COLOR(in->in_id,\n                                                        in->in_color));\n    if (ni->ni_dtimperiod)\n        dtim_period = ni->ni_dtimperiod;\n    else\n        dtim_period = 1;\n    \n    /*\n     * Regardless of power management state the driver must set\n     * keep alive period. FW will use it for sending keep alive NDPs\n     * immediately after association. Check that keep alive period\n     * is at least 3 * DTIM.\n     */\n    dtim_msec = dtim_period * ni->ni_intval;\n    keep_alive = MAX(3 * dtim_msec, 1000 * IWX_POWER_KEEP_ALIVE_PERIOD_SEC);\n    keep_alive = roundup(keep_alive, 1000) / 1000;\n    cmd->keep_alive_seconds = htole16(keep_alive);\n    \n    if (ic->ic_opmode != IEEE80211_M_MONITOR)\n        cmd->flags = htole16(IWX_POWER_FLAGS_POWER_SAVE_ENA_MSK);\n}\n\nint ItlIwx::\niwx_power_mac_update_mode(struct iwx_softc *sc, struct iwx_node *in)\n{\n    int err;\n    int ba_enable;\n    struct iwx_mac_power_cmd cmd;\n    \n    memset(&cmd, 0, sizeof(cmd));\n    \n    iwx_power_build_cmd(sc, in, &cmd);\n    \n    err = iwx_send_cmd_pdu(sc, IWX_MAC_PM_POWER_TABLE, 0,\n                           sizeof(cmd), &cmd);\n    if (err != 0)\n        return err;\n    \n    ba_enable = !!(cmd.flags &\n                   htole16(IWX_POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK));\n    return iwx_update_beacon_abort(sc, in, ba_enable);\n}\n\nint ItlIwx::\niwx_power_update_device(struct iwx_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwx_device_power_cmd cmd = { };\n    struct ieee80211com *ic = &sc->sc_ic;\n    \n    if (ic->ic_opmode != IEEE80211_M_MONITOR)\n        cmd.flags = htole16(IWX_DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK);\n    \n    return iwx_send_cmd_pdu(sc,\n                            IWX_POWER_TABLE_CMD, 0, sizeof(cmd), &cmd);\n}\n\nint ItlIwx::\niwx_enable_beacon_filter(struct iwx_softc *sc, struct iwx_node *in)\n{\n    struct iwx_beacon_filter_cmd cmd = {\n        IWX_BF_CMD_CONFIG_DEFAULTS,\n        .bf_enable_beacon_filter = htole32(1),\n        .ba_enable_beacon_abort = htole32(sc->sc_bf.ba_enabled),\n    };\n    int err;\n    \n    err = iwx_beacon_filter_send_cmd(sc, &cmd);\n    if (err == 0)\n        sc->sc_bf.bf_enabled = 1;\n    \n    return err;\n}\n\nint ItlIwx::\niwx_disable_beacon_filter(struct iwx_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwx_beacon_filter_cmd cmd;\n    int err;\n    \n    memset(&cmd, 0, sizeof(cmd));\n    \n    err = iwx_beacon_filter_send_cmd(sc, &cmd);\n    if (err == 0)\n        sc->sc_bf.bf_enabled = 0;\n    \n    return err;\n}\n\nint ItlIwx::\niwx_add_sta_cmd(struct iwx_softc *sc, struct iwx_node *in, int update)\n{\n    struct iwx_add_sta_cmd add_sta_cmd;\n    int err;\n    uint32_t status, agg_size = 0;\n    uint32_t max_aggsize = (IWX_STA_FLG_MAX_AGG_SIZE_4M >> IWX_STA_FLG_MAX_AGG_SIZE_SHIFT);\n    struct ieee80211com *ic = &sc->sc_ic;\n    \n    if (!update && (sc->sc_flags & IWX_FLAG_STA_ACTIVE)) {\n        XYLog(\"STA already added\\n\");\n        return 0;\n    }\n    \n    memset(&add_sta_cmd, 0, sizeof(add_sta_cmd));\n    \n    if (ic->ic_opmode == IEEE80211_M_MONITOR) {\n        add_sta_cmd.sta_id = IWX_MONITOR_STA_ID;\n        add_sta_cmd.station_type = IWX_STA_GENERAL_PURPOSE;\n    } else {\n        add_sta_cmd.sta_id = IWX_STATION_ID;\n        add_sta_cmd.station_type = IWX_STA_LINK;\n    }\n    add_sta_cmd.mac_id_n_color\n    = htole32(IWX_FW_CMD_ID_AND_COLOR(in->in_id, in->in_color));\n    if (!update) {\n        if (ic->ic_opmode == IEEE80211_M_MONITOR)\n            IEEE80211_ADDR_COPY(&add_sta_cmd.addr,\n                                etheranyaddr);\n        else\n            IEEE80211_ADDR_COPY(&add_sta_cmd.addr,\n                                in->in_macaddr);\n    }\n    add_sta_cmd.add_modify = update ? 1 : 0;\n    add_sta_cmd.station_flags_msk\n    |= htole32(IWX_STA_FLG_FAT_EN_MSK | IWX_STA_FLG_MIMO_EN_MSK);\n    add_sta_cmd.tid_disable_tx = htole16(0xffff);\n        \n    if ((in->in_ni.ni_flags & IEEE80211_NODE_HT) ||\n        (in->in_ni.ni_flags & IEEE80211_NODE_VHT) ||\n        (in->in_ni.ni_flags & IEEE80211_NODE_HE)) {\n        add_sta_cmd.station_flags_msk\n        |= htole32(IWX_STA_FLG_MAX_AGG_SIZE_MSK |\n                   IWX_STA_FLG_AGG_MPDU_DENS_MSK);\n        \n        if (ic->ic_state >= IEEE80211_S_ASSOC) {\n            switch (in->in_ni.ni_chw) {\n                case IEEE80211_CHAN_WIDTH_80P80:\n                case IEEE80211_CHAN_WIDTH_160:\n                    add_sta_cmd.station_flags |= htole32(IWX_STA_FLG_FAT_EN_160MHZ);\n                case IEEE80211_CHAN_WIDTH_80:\n                    add_sta_cmd.station_flags |= htole32(IWX_STA_FLG_FAT_EN_80MHZ);\n                case IEEE80211_CHAN_WIDTH_40:\n                    add_sta_cmd.station_flags |= htole32(IWX_STA_FLG_FAT_EN_40MHZ);\n                case IEEE80211_CHAN_WIDTH_20:\n                default:\n                    add_sta_cmd.station_flags |= htole32(IWX_STA_FLG_FAT_EN_20MHZ);\n                    break;\n            }\n        }\n        \n        if (iwx_mimo_enabled(sc) && ic->ic_bss->ni_rx_nss > 1)\n            add_sta_cmd.station_flags |= htole32(IWX_STA_FLG_MIMO_EN_MIMO2);\n        else\n            add_sta_cmd.station_flags |= htole32(IWX_STA_FLG_MIMO_EN_SISO);\n        \n        if (in->in_ni.ni_flags & IEEE80211_NODE_HE) {\n            agg_size = in->in_ni.ni_vhtcaps &\n            IEEE80211_VHTCAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;\n            agg_size >>=\n            IEEE80211_VHTCAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT;\n            agg_size += u8_get_bits(in->in_ni.ni_he_cap_elem.mac_cap_info[3],\n                                    IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_MASK);\n            add_sta_cmd.station_flags |=\n            htole32(min(max_aggsize, agg_size) << IWX_STA_FLG_MAX_AGG_SIZE_SHIFT);\n        } else if (in->in_ni.ni_flags & IEEE80211_NODE_VHT) {\n            agg_size = in->in_ni.ni_vhtcaps &\n            IEEE80211_VHTCAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;\n            agg_size >>=\n            IEEE80211_VHTCAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT;\n            add_sta_cmd.station_flags |=\n            htole32(min(max_aggsize, agg_size) << IWX_STA_FLG_MAX_AGG_SIZE_SHIFT);\n        } else if (in->in_ni.ni_flags & IEEE80211_NODE_HT)\n            add_sta_cmd.station_flags |= htole32(IWX_STA_FLG_MAX_AGG_SIZE_64K);\n        \n        switch (ic->ic_ampdu_params & IEEE80211_AMPDU_PARAM_SS) {\n            case IEEE80211_AMPDU_PARAM_SS_2:\n                add_sta_cmd.station_flags\n                |= htole32(IWX_STA_FLG_AGG_MPDU_DENS_2US);\n                break;\n            case IEEE80211_AMPDU_PARAM_SS_4:\n                add_sta_cmd.station_flags\n                |= htole32(IWX_STA_FLG_AGG_MPDU_DENS_4US);\n                break;\n            case IEEE80211_AMPDU_PARAM_SS_8:\n                add_sta_cmd.station_flags\n                |= htole32(IWX_STA_FLG_AGG_MPDU_DENS_8US);\n                break;\n            case IEEE80211_AMPDU_PARAM_SS_16:\n                add_sta_cmd.station_flags\n                |= htole32(IWX_STA_FLG_AGG_MPDU_DENS_16US);\n                break;\n            default:\n                break;\n        }\n    }\n    \n    status = IWX_ADD_STA_SUCCESS;\n    err = iwx_send_cmd_pdu_status(sc, IWX_ADD_STA, sizeof(add_sta_cmd),\n                                  &add_sta_cmd, &status);\n    if (!err && (status & IWX_ADD_STA_STATUS_MASK) != IWX_ADD_STA_SUCCESS)\n        err = EIO;\n    else\n        sc->sc_flags |= IWX_FLAG_STA_ACTIVE;\n\n    return err;\n}\n\nint ItlIwx::\niwx_add_aux_sta(struct iwx_softc *sc)\n{\n    \n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwx_add_sta_cmd cmd;\n    int err, qid = IWX_DQA_AUX_QUEUE;\n    uint32_t status;\n    uint8_t cmdver;\n    \n    /*\n     * Add auxiliary station for scanning.\n     * Newer versions of this command implies that the fw uses\n     * internal aux station for all aux activities that don't\n     * requires a dedicated data queue.\n     * In old version the aux station uses mac id like other\n     * station and not lmac id\n     */\n    cmdver = iwx_lookup_cmd_ver(sc, IWX_LONG_GROUP, IWX_ADD_STA);\n    if (cmdver != IWX_FW_CMD_VER_UNKNOWN && cmdver >= 12)\n        return 0;\n    \n    memset(&cmd, 0, sizeof(cmd));\n    cmd.sta_id = IWX_AUX_STA_ID;\n    cmd.station_type = IWX_STA_AUX_ACTIVITY;\n    cmd.mac_id_n_color =\n    htole32(IWX_FW_CMD_ID_AND_COLOR(IWX_MAC_INDEX_AUX, 0));\n    cmd.tid_disable_tx = htole16(0xffff);\n    \n    status = IWX_ADD_STA_SUCCESS;\n    err = iwx_send_cmd_pdu_status(sc, IWX_ADD_STA, sizeof(cmd), &cmd,\n                                  &status);\n    if (!err && (status & IWX_ADD_STA_STATUS_MASK) != IWX_ADD_STA_SUCCESS)\n        return EIO;\n    \n    return iwx_enable_txq(sc, IWX_AUX_STA_ID, qid, IWX_MGMT_TID,\n                          sc->txq[qid].ring_count);\n    return 0;\n}\n\nint ItlIwx::\niwx_rm_sta_cmd(struct iwx_softc *sc, struct iwx_node *in)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct iwx_rm_sta_cmd rm_sta_cmd;\n    int err;\n    \n    if ((sc->sc_flags & IWX_FLAG_STA_ACTIVE) == 0) {\n        XYLog(\"sta already removed\\n\");\n        return 0;\n    }\n    \n    memset(&rm_sta_cmd, 0, sizeof(rm_sta_cmd));\n    if (ic->ic_opmode == IEEE80211_M_MONITOR)\n        rm_sta_cmd.sta_id = IWX_MONITOR_STA_ID;\n    else\n        rm_sta_cmd.sta_id = IWX_STATION_ID;\n    \n    err = iwx_send_cmd_pdu(sc, IWX_REMOVE_STA, 0, sizeof(rm_sta_cmd),\n                           &rm_sta_cmd);\n    \n    sc->sc_flags &= ~IWX_FLAG_STA_ACTIVE;\n\n    return err;\n}\n\nint ItlIwx::\niwx_rm_sta(struct iwx_softc *sc, struct iwx_node *in)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct ieee80211_node *ni = &in->in_ni;\n    int err, i;\n\n    err = iwx_flush_sta(sc, in);\n    if (err) {\n        XYLog(\"%s: could not flush Tx path (error %d)\\n\",\n            __FUNCTION__, err);\n        return err;\n    }\n    err = iwx_rm_sta_cmd(sc, in);\n    if (err) {\n        printf(\"%s: could not remove STA (error %d)\\n\",\n            DEVNAME(sc), err);\n        return err;\n    }\n\n    sc->sc_rx_ba_sessions = 0;\n    sc->ba_rx.start_tidmask = 0;\n    sc->ba_rx.stop_tidmask = 0;\n    sc->ba_tx.start_tidmask = 0;\n    sc->ba_tx.stop_tidmask = 0;\n    for (i = 0; i < IEEE80211_NUM_TID; i++) {\n        struct ieee80211_tx_ba *ba = &ni->ni_tx_ba[i];\n        if (ba->ba_state != IEEE80211_BA_AGREED)\n            continue;\n        ieee80211_delba_request(ic, ni, 0, 1, i);\n    }\n\n    return 0;\n}\n\nuint8_t ItlIwx::\niwx_umac_scan_fill_channels(struct iwx_softc *sc,\n                            struct iwx_scan_channel_cfg_umac *chan, int n_ssids, int bgscan)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct ieee80211_channel *c;\n    uint8_t nchan;\n    \n    for (nchan = 0, c = &ic->ic_channels[1];\n         c <= &ic->ic_channels[IEEE80211_CHAN_MAX] &&\n         nchan < sc->sc_capa_n_scan_channels;\n         c++) {\n        uint8_t channel_num;\n        \n        if (c->ic_flags == 0)\n            continue;\n        \n        channel_num = ieee80211_mhz2ieee(c->ic_freq, 0);\n        if (isset(sc->sc_ucode_api,\n                  IWX_UCODE_TLV_API_SCAN_EXT_CHAN_VER)) {\n            chan->v2.channel_num = channel_num;\n            if (IEEE80211_IS_CHAN_2GHZ(c))\n                chan->v2.band = IWX_PHY_BAND_24;\n            else\n                chan->v2.band = IWX_PHY_BAND_5;\n            chan->v2.iter_count = 1;\n            chan->v2.iter_interval = 0;\n        } else {\n            chan->v1.channel_num = channel_num;\n            chan->v1.iter_count = 1;\n            chan->v1.iter_interval = htole16(0);\n        }\n        \n        if (n_ssids != 0 && !bgscan)\n            chan->flags = htole32(1 << 0); /* select SSID 0 */\n        chan++;\n        nchan++;\n    }\n    \n    return nchan;\n}\n\nint ItlIwx::\niwx_fill_probe_req_v1(struct iwx_softc *sc, struct iwx_scan_probe_req_v1 *preq1)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwx_scan_probe_req preq2;\n    int err, i;\n    \n    err = iwx_fill_probe_req(sc, &preq2);\n    if (err)\n        return err;\n    \n    preq1->mac_header = preq2.mac_header;\n    for (i = 0; i < nitems(preq1->band_data); i++)\n        preq1->band_data[i] = preq2.band_data[i];\n    preq1->common_data = preq2.common_data;\n    memcpy(preq1->buf, preq2.buf, sizeof(preq1->buf));\n    return 0;\n}\n\nint ItlIwx::\niwx_fill_probe_req(struct iwx_softc *sc, struct iwx_scan_probe_req *preq)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct _ifnet *ifp = IC2IFP(ic);\n    struct ieee80211_frame *wh = (struct ieee80211_frame *)preq->buf;\n    struct ieee80211_rateset *rs;\n    size_t remain = sizeof(preq->buf);\n    uint8_t *frm, *pos;\n    \n    memset(preq, 0, sizeof(*preq));\n    \n    if (remain < sizeof(*wh) + 2)\n        return ENOBUFS;\n    \n    /*\n     * Build a probe request frame.  Most of the following code is a\n     * copy & paste of what is done in net80211.\n     */\n    wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT |\n    IEEE80211_FC0_SUBTYPE_PROBE_REQ;\n    wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;\n//    IEEE80211_ADDR_COPY(ic->ic_myaddr, LLADDR(ifp->if_sadl));\n    IEEE80211_ADDR_COPY(wh->i_addr1, etherbroadcastaddr);\n    IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_myaddr);\n    IEEE80211_ADDR_COPY(wh->i_addr3, etherbroadcastaddr);\n    *(uint16_t *)&wh->i_dur[0] = 0;    /* filled by HW */\n    *(uint16_t *)&wh->i_seq[0] = 0;    /* filled by HW */\n    \n    frm = (uint8_t *)(wh + 1);\n    *frm++ = IEEE80211_ELEMID_SSID;\n    *frm++ = 0;\n    /* hardware inserts SSID */\n    \n    /* Tell the firmware where the MAC header is. */\n    preq->mac_header.offset = 0;\n    preq->mac_header.len = htole16(frm - (uint8_t *)wh);\n    remain -= frm - (uint8_t *)wh;\n    \n    /* Fill in 2GHz IEs and tell firmware where they are. */\n    rs = &ic->ic_sup_rates[IEEE80211_MODE_11G];\n    if (rs->rs_nrates > IEEE80211_RATE_SIZE) {\n        if (remain < 4 + rs->rs_nrates)\n            return ENOBUFS;\n    } else if (remain < 2 + rs->rs_nrates)\n        return ENOBUFS;\n    preq->band_data[0].offset = htole16(frm - (uint8_t *)wh);\n    pos = frm;\n    frm = ieee80211_add_rates(frm, rs);\n    if (rs->rs_nrates > IEEE80211_RATE_SIZE)\n        frm = ieee80211_add_xrates(frm, rs);\n    remain -= frm - pos;\n    \n    if (isset(sc->sc_enabled_capa,\n              IWX_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT)) {\n        if (remain < 3)\n            return ENOBUFS;\n        *frm++ = IEEE80211_ELEMID_DSPARMS;\n        *frm++ = 1;\n        *frm++ = 0;\n        remain -= 3;\n    }\n    preq->band_data[0].len = htole16(frm - pos);\n    \n    if (sc->sc_nvm.sku_cap_band_52GHz_enable) {\n        /* Fill in 5GHz IEs. */\n        rs = &ic->ic_sup_rates[IEEE80211_MODE_11A];\n        if (rs->rs_nrates > IEEE80211_RATE_SIZE) {\n            if (remain < 4 + rs->rs_nrates)\n                return ENOBUFS;\n        } else if (remain < 2 + rs->rs_nrates)\n            return ENOBUFS;\n        preq->band_data[1].offset = htole16(frm - (uint8_t *)wh);\n        pos = frm;\n        frm = ieee80211_add_rates(frm, rs);\n        if (rs->rs_nrates > IEEE80211_RATE_SIZE)\n            frm = ieee80211_add_xrates(frm, rs);\n        preq->band_data[1].len = htole16(frm - pos);\n        remain -= frm - pos;\n        if (ic->ic_flags & IEEE80211_F_VHTON) {\n            if (remain < sizeof(struct ieee80211_ie_vhtcap))\n                return ENOBUFS;\n            frm = ieee80211_add_vhtcaps(frm, ic);\n            remain -= frm - pos;\n        }\n    }\n    \n    /* Send 11n IEs on both 2GHz and 5GHz bands. */\n    preq->common_data.offset = htole16(frm - (uint8_t *)wh);\n    pos = frm;\n    if (ic->ic_flags & IEEE80211_F_HTON) {\n        if (remain < sizeof(struct ieee80211_ie_htcap))\n            return ENOBUFS;\n        frm = ieee80211_add_htcaps(frm, ic);\n        /* XXX add WME info? */\n    }\n\n    preq->common_data.len = htole16(frm - pos);\n    \n    return 0;\n}\n\nint ItlIwx::\niwx_config_umac_scan(struct iwx_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwx_scan_config *scan_config;\n    int err;\n    size_t cmd_size;\n    struct iwx_host_cmd hcmd = {\n        .id = iwx_cmd_id(IWX_SCAN_CFG_CMD, IWX_LONG_GROUP, 0),\n        .flags = 0,\n    };\n    uint8_t cmdver;\n    \n    if (!isset(sc->sc_ucode_api, IWX_UCODE_TLV_API_REDUCED_SCAN_CONFIG))\n        return iwx_config_legacy_umac_scan(sc);\n    \n    cmd_size = sizeof(*scan_config);\n    \n    scan_config = (struct iwx_scan_config *)malloc(cmd_size, 0, M_ZERO);\n    if (scan_config == NULL)\n        return ENOMEM;\n    \n    scan_config->tx_chains = htole32(iwx_fw_valid_tx_ant(sc));\n    scan_config->rx_chains = htole32(iwx_fw_valid_rx_ant(sc));\n    \n    cmdver = iwx_lookup_cmd_ver(sc, IWX_LONG_GROUP, IWX_ADD_STA);\n    if (cmdver == IWX_FW_CMD_VER_UNKNOWN || cmdver < 12)\n        scan_config->bcast_sta_id = IWX_AUX_STA_ID;\n    else if (cmdver == IWX_FW_CMD_VER_UNKNOWN || cmdver < 5)\n        scan_config->bcast_sta_id = 0xFF;\n    \n    hcmd.data[0] = scan_config;\n    hcmd.len[0] = cmd_size;\n    \n    err = iwx_send_cmd(sc, &hcmd);\n    ::free(scan_config);\n    return err;\n}\n\nint ItlIwx::\niwx_config_legacy_umac_scan(struct iwx_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwx_scan_config_v2 *scan_config;\n    struct ieee80211com *ic = &sc->sc_ic;\n    int err, nchan;\n    struct ieee80211_channel *c;\n    size_t cmd_size;\n    struct iwx_host_cmd hcmd = {\n        .id = iwx_cmd_id(IWX_SCAN_CFG_CMD, IWX_LONG_GROUP, 0),\n        .flags = 0,\n    };\n    static const uint32_t rates = (IWX_SCAN_CONFIG_RATE_1M |\n                                   IWX_SCAN_CONFIG_RATE_2M | IWX_SCAN_CONFIG_RATE_5M |\n                                   IWX_SCAN_CONFIG_RATE_11M | IWX_SCAN_CONFIG_RATE_6M |\n                                   IWX_SCAN_CONFIG_RATE_9M | IWX_SCAN_CONFIG_RATE_12M |\n                                   IWX_SCAN_CONFIG_RATE_18M | IWX_SCAN_CONFIG_RATE_24M |\n                                   IWX_SCAN_CONFIG_RATE_36M | IWX_SCAN_CONFIG_RATE_48M |\n                                   IWX_SCAN_CONFIG_RATE_54M);\n    \n    cmd_size = sizeof(*scan_config) + sc->sc_capa_n_scan_channels;\n    \n    scan_config = (struct iwx_scan_config_v2 *)malloc(cmd_size, 0, M_ZERO);\n    if (scan_config == NULL)\n        return ENOMEM;\n    \n    scan_config->tx_chains = htole32(iwx_fw_valid_tx_ant(sc));\n    scan_config->rx_chains = htole32(iwx_fw_valid_rx_ant(sc));\n    scan_config->legacy_rates = htole32(rates |\n                                        IWX_SCAN_CONFIG_SUPPORTED_RATE(rates));\n    \n    /* These timings correspond to iwlwifi's UNASSOC scan. */\n    scan_config->dwell.active = 10;\n    scan_config->dwell.passive = 110;\n    scan_config->dwell.fragmented = 44;\n    scan_config->dwell.extended = 90;\n    scan_config->out_of_channel_time[IWX_SCAN_LB_LMAC_IDX] = htole32(0);\n    scan_config->out_of_channel_time[IWX_SCAN_HB_LMAC_IDX] = htole32(0);\n    scan_config->suspend_time[IWX_SCAN_LB_LMAC_IDX] = htole32(0);\n    scan_config->suspend_time[IWX_SCAN_HB_LMAC_IDX] = htole32(0);\n    \n    IEEE80211_ADDR_COPY(scan_config->mac_addr, sc->sc_ic.ic_myaddr);\n    \n    scan_config->bcast_sta_id = IWX_AUX_STA_ID;\n    scan_config->channel_flags = 0;\n    \n    for (c = &ic->ic_channels[1], nchan = 0;\n         c <= &ic->ic_channels[IEEE80211_CHAN_MAX] &&\n         nchan < sc->sc_capa_n_scan_channels; c++) {\n        if (c->ic_flags == 0)\n            continue;\n        scan_config->channel_array[nchan++] =\n        ieee80211_mhz2ieee(c->ic_freq, 0);\n    }\n    \n    scan_config->flags = htole32(IWX_SCAN_CONFIG_FLAG_ACTIVATE |\n                                 IWX_SCAN_CONFIG_FLAG_ALLOW_CHUB_REQS |\n                                 IWX_SCAN_CONFIG_FLAG_SET_TX_CHAINS |\n                                 IWX_SCAN_CONFIG_FLAG_SET_RX_CHAINS |\n                                 IWX_SCAN_CONFIG_FLAG_SET_AUX_STA_ID |\n                                 IWX_SCAN_CONFIG_FLAG_SET_ALL_TIMES |\n                                 IWX_SCAN_CONFIG_FLAG_SET_LEGACY_RATES |\n                                 IWX_SCAN_CONFIG_FLAG_SET_MAC_ADDR |\n                                 IWX_SCAN_CONFIG_FLAG_SET_CHANNEL_FLAGS|\n                                 IWX_SCAN_CONFIG_N_CHANNELS(nchan) |\n                                 IWX_SCAN_CONFIG_FLAG_CLEAR_FRAGMENTED);\n    \n    scan_config->channel_flags = IWX_CHANNEL_FLAG_EBS | \n    IWX_CHANNEL_FLAG_ACCURATE_EBS |\n    IWX_CHANNEL_FLAG_EBS_ADD |\n    IWX_CHANNEL_FLAG_PRE_SCAN_PASSIVE2ACTIVE;\n    \n    hcmd.data[0] = scan_config;\n    hcmd.len[0] = cmd_size;\n    \n    err = iwx_send_cmd(sc, &hcmd);\n    ::free(scan_config);\n    return err;\n}\n\nint ItlIwx::\niwx_umac_scan_size(struct iwx_softc *sc)\n{\n    int base_size = IWX_SCAN_REQ_UMAC_SIZE_V1;\n    int tail_size;\n    uint8_t scan_ver = iwx_lookup_cmd_ver(sc, IWX_LONG_GROUP, IWX_SCAN_REQ_UMAC);\n    \n    if (scan_ver == 12)\n        return sizeof(iwx_scan_req_umac_v12);\n    else if (scan_ver == 14)\n        return sizeof(iwx_scan_req_umac_v14);\n    \n    if (isset(sc->sc_ucode_api, IWX_UCODE_TLV_API_ADAPTIVE_DWELL_V2))\n        base_size = IWX_SCAN_REQ_UMAC_SIZE_V8;\n    else if (isset(sc->sc_ucode_api, IWX_UCODE_TLV_API_ADAPTIVE_DWELL))\n        base_size = IWX_SCAN_REQ_UMAC_SIZE_V7;\n    else\n        base_size = IWX_SCAN_REQ_UMAC_SIZE_V6;\n    \n    if (isset(sc->sc_ucode_api, IWX_UCODE_TLV_API_SCAN_EXT_CHAN_VER))\n        tail_size = sizeof(struct iwx_scan_req_umac_tail_v2);\n    else\n        tail_size = sizeof(struct iwx_scan_req_umac_tail_v1);\n    \n    return base_size + sizeof(struct iwx_scan_channel_cfg_umac) *\n    sc->sc_capa_n_scan_channels + tail_size;\n}\n\nstruct iwx_scan_umac_chan_param *ItlIwx::\niwx_get_scan_req_umac_chan_param(struct iwx_softc *sc,\n                                 struct iwx_scan_req_umac *req)\n{\n    if (isset(sc->sc_ucode_api, IWX_UCODE_TLV_API_ADAPTIVE_DWELL_V2))\n        return &req->v8.channel;\n    \n    if (isset(sc->sc_ucode_api, IWX_UCODE_TLV_API_ADAPTIVE_DWELL))\n        return &req->v7.channel;\n\n    return &req->v6.channel;\n}\n\nvoid *ItlIwx::\niwx_get_scan_req_umac_data(struct iwx_softc *sc, struct iwx_scan_req_umac *req)\n{\n    if (isset(sc->sc_ucode_api, IWX_UCODE_TLV_API_ADAPTIVE_DWELL_V2))\n        return (void *)&req->v8.data;\n    \n    if (isset(sc->sc_ucode_api, IWX_UCODE_TLV_API_ADAPTIVE_DWELL))\n        return (void *)&req->v7.data;\n    \n    return (void *)&req->v6.data;\n}\n\n#define IWL_SCAN_DWELL_ACTIVE        10\n#define IWL_SCAN_DWELL_PASSIVE        110\n#define IWL_SCAN_DWELL_FRAGMENTED    44\n#define IWL_SCAN_DWELL_EXTENDED        90\n#define IWL_SCAN_NUM_OF_FRAGS        3\n#define IWL_SCAN_LAST_2_4_CHN        14\n\n/* adaptive dwell max budget time [TU] for full scan */\n#define IWX_SCAN_ADWELL_MAX_BUDGET_FULL_SCAN 300\n/* adaptive dwell max budget time [TU] for directed scan */\n#define IWX_SCAN_ADWELL_MAX_BUDGET_DIRECTED_SCAN 100\n/* adaptive dwell default high band APs number */\n#define IWX_SCAN_ADWELL_DEFAULT_HB_N_APS 8\n/* adaptive dwell default low band APs number */\n#define IWX_SCAN_ADWELL_DEFAULT_LB_N_APS 2\n/* adaptive dwell default APs number in social channels (1, 6, 11) */\n#define IWX_SCAN_ADWELL_DEFAULT_N_APS_SOCIAL 10\n/* number of scan channels */\n#define IWX_SCAN_NUM_CHANNELS 112\n/* adaptive dwell number of APs override mask for p2p friendly GO */\n#define IWX_SCAN_ADWELL_N_APS_GO_FRIENDLY_BIT (1 << 20)\n/* adaptive dwell number of APs override mask for social channels */\n#define IWX_SCAN_ADWELL_N_APS_SOCIAL_CHS_BIT (1 << 21)\n/* adaptive dwell number of APs override for p2p friendly GO channels */\n#define IWX_SCAN_ADWELL_N_APS_GO_FRIENDLY 10\n/* adaptive dwell number of APs override for social channels */\n#define IWX_SCAN_ADWELL_N_APS_SOCIAL_CHS 2\n\n/* minimal number of 2GHz and 5GHz channels in the regular scan request */\n#define IWX_MVM_6GHZ_PASSIVE_SCAN_MIN_CHANS 4\n\nint ItlIwx::\niwx_umac_scan(struct iwx_softc *sc, int bgscan)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct iwx_host_cmd hcmd = {\n        .id = iwx_cmd_id(IWX_SCAN_REQ_UMAC, IWX_LONG_GROUP, 0),\n        .len = { 0, },\n        .data = { NULL, },\n        .flags = 0,\n    };\n    struct iwx_scan_req_umac *req;\n    void *cmd_data, *tail_data;\n    struct iwx_scan_req_umac_tail_v2 *tail;\n    struct iwx_scan_req_umac_tail_v1 *tailv1;\n    struct iwx_scan_umac_chan_param *chanparam;\n    size_t req_len;\n    int err, async = bgscan;\n    const uint32_t timeout = bgscan ?  htole32(120) : htole32(0);\n    uint8_t scan_ver = iwx_lookup_cmd_ver(sc, IWX_LONG_GROUP, IWX_SCAN_REQ_UMAC);\n    \n    if (scan_ver == 12)\n        return iwx_umac_scan_v12(sc, bgscan);\n    else if (scan_ver == 14)\n        return iwx_umac_scan_v14(sc, bgscan);\n    \n    req_len = iwx_umac_scan_size(sc);\n    if ((req_len < IWX_SCAN_REQ_UMAC_SIZE_V1 +\n         sizeof(struct iwx_scan_req_umac_tail_v1)) ||\n        req_len > IWX_MAX_CMD_PAYLOAD_SIZE)\n        return ERANGE;\n    req = (struct iwx_scan_req_umac *)malloc(req_len, 0,\n                                             (async ? M_NOWAIT : M_WAITOK) | M_ZERO);\n    if (req == NULL)\n        return ENOMEM;\n    \n    hcmd.len[0] = (uint16_t)req_len;\n    hcmd.data[0] = (void *)req;\n    hcmd.flags |= async ? IWX_CMD_ASYNC : 0;\n    \n    if (isset(sc->sc_ucode_api, IWX_UCODE_TLV_API_ADAPTIVE_DWELL)) {\n        req->v7.adwell_default_n_aps_social =\n        IWX_SCAN_ADWELL_DEFAULT_N_APS_SOCIAL;\n        req->v7.adwell_default_n_aps =\n        IWX_SCAN_ADWELL_DEFAULT_LB_N_APS;\n        \n        if (isset(sc->sc_ucode_api, IWX_UCODE_TLV_API_ADWELL_HB_DEF_N_AP))\n            req->v9.adwell_default_hb_n_aps = IWX_SCAN_ADWELL_DEFAULT_HB_N_APS;\n        \n        if (ic->ic_des_esslen != 0 && !bgscan)\n            req->v7.adwell_max_budget =\n            htole16(IWX_SCAN_ADWELL_MAX_BUDGET_DIRECTED_SCAN);\n        else\n            req->v7.adwell_max_budget =\n            htole16(IWX_SCAN_ADWELL_MAX_BUDGET_FULL_SCAN);\n        \n        req->v7.scan_priority = htole32(IWX_SCAN_PRIORITY_EXT_6);\n        req->v7.max_out_time[IWX_SCAN_LB_LMAC_IDX] = timeout;\n        req->v7.suspend_time[IWX_SCAN_LB_LMAC_IDX] = timeout;\n        \n        if (isset(sc->sc_enabled_capa, IWX_UCODE_TLV_CAPA_CDB_SUPPORT)) {\n            req->v7.max_out_time[IWX_SCAN_HB_LMAC_IDX] =\n                timeout;\n            req->v7.suspend_time[IWX_SCAN_HB_LMAC_IDX] =\n                timeout;\n        }\n        \n        if (isset(sc->sc_ucode_api,\n                  IWX_UCODE_TLV_API_ADAPTIVE_DWELL_V2)) {\n            req->v8.active_dwell[IWX_SCAN_LB_LMAC_IDX] = IWL_SCAN_DWELL_ACTIVE;\n            req->v8.passive_dwell[IWX_SCAN_LB_LMAC_IDX] = IWL_SCAN_DWELL_PASSIVE;\n            if (isset(sc->sc_enabled_capa, IWX_UCODE_TLV_CAPA_CDB_SUPPORT)) {\n                req->v8.active_dwell[IWX_SCAN_HB_LMAC_IDX] =\n                    IWL_SCAN_DWELL_ACTIVE;\n                req->v8.passive_dwell[IWX_SCAN_HB_LMAC_IDX] =\n                    IWL_SCAN_DWELL_PASSIVE;\n            }\n        } else {\n            req->v7.active_dwell = IWL_SCAN_DWELL_ACTIVE;\n            req->v7.passive_dwell = IWL_SCAN_DWELL_PASSIVE;\n            req->v7.fragmented_dwell = IWL_SCAN_DWELL_FRAGMENTED;\n        }\n    } else {\n        /* These timings correspond to iwlwifi's UNASSOC scan. */\n        req->v1.active_dwell = IWL_SCAN_DWELL_ACTIVE;\n        req->v1.passive_dwell = IWL_SCAN_DWELL_PASSIVE;\n        req->v1.fragmented_dwell = IWL_SCAN_DWELL_FRAGMENTED;\n        req->v1.extended_dwell = IWL_SCAN_DWELL_EXTENDED;\n        \n        if (isset(sc->sc_enabled_capa, IWX_UCODE_TLV_CAPA_CDB_SUPPORT)) {\n            req->v6.max_out_time[IWX_SCAN_HB_LMAC_IDX] =\n                timeout;\n            req->v6.suspend_time[IWX_SCAN_HB_LMAC_IDX] =\n                timeout;\n        }\n        \n        req->v6.scan_priority =\n            htole32(IWX_SCAN_PRIORITY_EXT_6);\n        req->v6.max_out_time[IWX_SCAN_LB_LMAC_IDX] =\n            timeout;\n        req->v6.suspend_time[IWX_SCAN_LB_LMAC_IDX] =\n            timeout;\n    }\n    \n    req->ooc_priority = htole32(IWX_SCAN_PRIORITY_EXT_6);\n    \n    cmd_data = iwx_get_scan_req_umac_data(sc, req);\n    chanparam = iwx_get_scan_req_umac_chan_param(sc, req);\n    chanparam->count = iwx_umac_scan_fill_channels(sc,\n                                                   (struct iwx_scan_channel_cfg_umac *)cmd_data,\n                                                   ic->ic_des_esslen != 0, bgscan);\n    chanparam->flags = 0;\n    \n    tail_data = (uint8_t*)cmd_data + sizeof(struct iwx_scan_channel_cfg_umac) *\n    sc->sc_capa_n_scan_channels;\n    tail = (struct iwx_scan_req_umac_tail_v2 *)tail_data;\n    /* tail v1 layout differs in preq and direct_scan member fields. */\n    tailv1 = (struct iwx_scan_req_umac_tail_v1 *)tail_data;\n    \n    req->general_flags = htole32(IWX_UMAC_SCAN_GEN_FLAGS_PASS_ALL |\n                                 IWX_UMAC_SCAN_GEN_FLAGS_ITER_COMPLETE);\n    if (isset(sc->sc_ucode_api, IWX_UCODE_TLV_API_ADAPTIVE_DWELL_V2)) {\n        req->v8.general_flags2 =\n        IWX_UMAC_SCAN_GEN_FLAGS2_ALLOW_CHNL_REORDER;\n    }\n    \n    /* Check if we're doing an active directed scan. */\n    if (ic->ic_des_esslen != 0 && !bgscan) {\n        if (isset(sc->sc_ucode_api, IWX_UCODE_TLV_API_SCAN_EXT_CHAN_VER)) {\n            tail->direct_scan[0].id = IEEE80211_ELEMID_SSID;\n            tail->direct_scan[0].len = ic->ic_des_esslen;\n            memcpy(tail->direct_scan[0].ssid, ic->ic_des_essid,\n                   ic->ic_des_esslen);\n        } else {\n            tailv1->direct_scan[0].id = IEEE80211_ELEMID_SSID;\n            tailv1->direct_scan[0].len = ic->ic_des_esslen;\n            memcpy(tailv1->direct_scan[0].ssid, ic->ic_des_essid,\n                   ic->ic_des_esslen);\n        }\n        req->general_flags |=\n        htole32(IWX_UMAC_SCAN_GEN_FLAGS_PRE_CONNECT);\n    } else\n        req->general_flags |= htole32(IWX_UMAC_SCAN_GEN_FLAGS_PASSIVE);\n    \n    if (isset(sc->sc_enabled_capa, IWX_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT) &&\n        isset(sc->sc_enabled_capa, IWX_UCODE_TLV_CAPA_WFA_TPC_REP_IE_SUPPORT))\n        req->general_flags |=\n        htole32(IWX_UMAC_SCAN_GEN_FLAGS_RRM_ENABLED);\n    \n    if (isset(sc->sc_ucode_api, IWX_UCODE_TLV_API_ADAPTIVE_DWELL)) {\n        req->general_flags |=\n        htole32(IWX_UMAC_SCAN_GEN_FLAGS_ADAPTIVE_DWELL);\n    } else {\n        req->general_flags |=\n        htole32(IWX_UMAC_SCAN_GEN_FLAGS_EXTENDED_DWELL);\n    }\n    \n    if (isset(sc->sc_ucode_api, IWX_UCODE_TLV_API_SCAN_EXT_CHAN_VER))\n        err = iwx_fill_probe_req(sc, &tail->preq);\n    else\n        err = iwx_fill_probe_req_v1(sc, &tailv1->preq);\n    if (err) {\n        ::free(req);\n        return err;\n    }\n    \n    /* Specify the scan plan: We'll do one iteration. */\n    tail->schedule[0].interval = 0;\n    tail->schedule[0].iter_count = 1;\n    \n    err = iwx_send_cmd(sc, &hcmd);\n    ::free(req);\n    return err;\n}\n\nint ItlIwx::\niwx_umac_scan_v12(struct iwx_softc *sc, int bgscan)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct ieee80211com *ic = &sc->sc_ic;\n    int err = 0, async = bgscan;\n    struct iwx_scan_req_umac_v12 *req;\n    size_t req_len;\n    uint16_t gen_flags = 0;\n    const uint32_t timeout = bgscan ?  htole32(120) : htole32(0);\n    struct iwx_scan_general_params_v10 *general_params;\n    struct iwx_scan_channel_params_v4 *cp;\n    struct iwx_host_cmd hcmd = {\n        .id = iwx_cmd_id(IWX_SCAN_REQ_UMAC, IWX_LONG_GROUP, 0),\n        .len = { 0, },\n        .data = { NULL, },\n        .flags = 0,\n    };\n    \n    req_len = iwx_umac_scan_size(sc);\n    req = (struct iwx_scan_req_umac_v12 *)malloc(req_len, 0,\n                                             (async ? M_NOWAIT : M_WAITOK) | M_ZERO);\n    if (req == NULL)\n        return ENOMEM;\n    \n    hcmd.len[0] = (uint16_t)req_len;\n    hcmd.data[0] = (void *)req;\n    hcmd.flags |= async ? IWX_CMD_ASYNC : 0;\n    \n    general_params = &req->scan_params.general_params;\n    \n    req->ooc_priority = htole32(IWX_SCAN_PRIORITY_EXT_6);\n    \n    if (ic->ic_des_esslen == 0 || bgscan)\n        gen_flags |= IWX_UMAC_SCAN_GEN_FLAGS_V2_FORCE_PASSIVE;\n    \n    gen_flags |= IWX_UMAC_SCAN_GEN_FLAGS_V2_PASS_ALL |\n    IWX_UMAC_SCAN_GEN_FLAGS_V2_ADAPTIVE_DWELL;\n    \n    req->scan_params.general_params.flags = gen_flags;\n    \n    general_params->adwell_default_social_chn =\n        IWX_SCAN_ADWELL_DEFAULT_N_APS_SOCIAL;\n    general_params->adwell_default_2g = IWX_SCAN_ADWELL_DEFAULT_LB_N_APS;\n    general_params->adwell_default_5g = IWX_SCAN_ADWELL_DEFAULT_HB_N_APS;\n\n    if (ic->ic_des_esslen != 0 && !bgscan)\n        general_params->adwell_max_budget =\n            cpu_to_le16(IWX_SCAN_ADWELL_MAX_BUDGET_DIRECTED_SCAN);\n    else\n        general_params->adwell_max_budget =\n            cpu_to_le16(IWX_SCAN_ADWELL_MAX_BUDGET_FULL_SCAN);\n    \n    general_params->scan_priority = htole32(IWX_SCAN_PRIORITY_EXT_6);\n    general_params->max_out_of_time[IWX_SCAN_LB_LMAC_IDX] =\n        timeout;\n    general_params->suspend_time[IWX_SCAN_LB_LMAC_IDX] =\n        timeout;\n    \n    general_params->max_out_of_time[IWX_SCAN_HB_LMAC_IDX] =\n        timeout;\n    general_params->suspend_time[IWX_SCAN_HB_LMAC_IDX] =\n        timeout;\n\n    general_params->active_dwell[IWX_SCAN_LB_LMAC_IDX] = IWL_SCAN_DWELL_ACTIVE;\n    general_params->passive_dwell[IWX_SCAN_LB_LMAC_IDX] = IWL_SCAN_DWELL_PASSIVE;\n    general_params->active_dwell[IWX_SCAN_HB_LMAC_IDX] = IWL_SCAN_DWELL_ACTIVE;\n    general_params->passive_dwell[IWX_SCAN_HB_LMAC_IDX] = IWL_SCAN_DWELL_PASSIVE;\n    \n    /* Specify the scan plan: We'll do one iteration. */\n    req->scan_params.periodic_params.schedule[0].interval = 0;\n    req->scan_params.periodic_params.schedule[0].iter_count = 1;\n    \n    err = iwx_fill_probe_req(sc, &req->scan_params.probe_params.preq);\n    if (err)\n        return err;\n\n    if (ic->ic_des_esslen != 0 && !bgscan) {\n        req->scan_params.probe_params.ssid_num = 1;\n        req->scan_params.probe_params.direct_scan[0].id = IEEE80211_ELEMID_SSID;\n        req->scan_params.probe_params.direct_scan[0].len = ic->ic_des_esslen;\n        memcpy(req->scan_params.probe_params.direct_scan[0].ssid, ic->ic_des_essid,\n               ic->ic_des_esslen);\n    } else\n        req->scan_params.probe_params.ssid_num = 0;\n    \n    cp = &req->scan_params.channel_params;\n    \n    cp->flags = IWX_SCAN_CHANNEL_FLAG_ENABLE_CHAN_ORDER;\n    cp->count = iwx_umac_scan_fill_channels(sc,\n                                            (struct iwx_scan_channel_cfg_umac *)cp->channel_config,\n                                            ic->ic_des_esslen != 0, bgscan);\n    cp->num_of_aps_override = IWX_SCAN_ADWELL_N_APS_GO_FRIENDLY;\n    \n    err = iwx_send_cmd(sc, &hcmd);\n    ::free(req);\n    return err;\n}\n\nint ItlIwx::\niwx_umac_scan_v14(struct iwx_softc *sc, int bgscan)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct ieee80211com *ic = &sc->sc_ic;\n    int err = 0, async = bgscan;\n    struct iwx_scan_req_umac_v14 *req;\n    size_t req_len;\n    uint16_t gen_flags = 0;\n    struct iwx_scan_general_params_v10 *general_params;\n    struct iwx_scan_channel_params_v6 *cp;\n    const uint32_t timeout = bgscan ?  htole32(120) : htole32(0);\n    struct iwx_host_cmd hcmd = {\n        .id = iwx_cmd_id(IWX_SCAN_REQ_UMAC, IWX_LONG_GROUP, 0),\n        .len = { 0, },\n        .data = { NULL, },\n        .flags = 0,\n    };\n    \n    req_len = iwx_umac_scan_size(sc);\n    req = (struct iwx_scan_req_umac_v14 *)malloc(req_len, 0,\n                                             (async ? M_NOWAIT : M_WAITOK) | M_ZERO);\n    if (req == NULL)\n        return ENOMEM;\n    \n    hcmd.len[0] = (uint16_t)req_len;\n    hcmd.data[0] = (void *)req;\n    hcmd.flags |= async ? IWX_CMD_ASYNC : 0;\n    \n    general_params = &req->scan_params.general_params;\n    \n    req->ooc_priority = htole32(IWX_SCAN_PRIORITY_EXT_6);\n    \n    if (ic->ic_des_esslen == 0 || bgscan)\n        gen_flags |= IWX_UMAC_SCAN_GEN_FLAGS_V2_FORCE_PASSIVE;\n    \n    gen_flags |= IWX_UMAC_SCAN_GEN_FLAGS_V2_PASS_ALL |\n    IWX_UMAC_SCAN_GEN_FLAGS_V2_ADAPTIVE_DWELL;\n    \n    req->scan_params.general_params.flags = gen_flags;\n    \n    general_params->adwell_default_social_chn =\n        IWX_SCAN_ADWELL_DEFAULT_N_APS_SOCIAL;\n    general_params->adwell_default_2g = IWX_SCAN_ADWELL_DEFAULT_LB_N_APS;\n    general_params->adwell_default_5g = IWX_SCAN_ADWELL_DEFAULT_HB_N_APS;\n    if (ic->ic_des_esslen != 0 && !bgscan)\n        general_params->adwell_max_budget =\n            cpu_to_le16(IWX_SCAN_ADWELL_MAX_BUDGET_DIRECTED_SCAN);\n    else\n        general_params->adwell_max_budget =\n            cpu_to_le16(IWX_SCAN_ADWELL_MAX_BUDGET_FULL_SCAN);\n    \n    general_params->scan_priority = htole32(IWX_SCAN_PRIORITY_EXT_6);\n    general_params->max_out_of_time[IWX_SCAN_LB_LMAC_IDX] =\n        timeout;\n    general_params->suspend_time[IWX_SCAN_LB_LMAC_IDX] =\n        timeout;\n    \n    general_params->max_out_of_time[IWX_SCAN_HB_LMAC_IDX] =\n        timeout;\n    general_params->suspend_time[IWX_SCAN_HB_LMAC_IDX] =\n        timeout;\n\n    general_params->active_dwell[IWX_SCAN_LB_LMAC_IDX] = IWL_SCAN_DWELL_ACTIVE;\n    general_params->passive_dwell[IWX_SCAN_LB_LMAC_IDX] = IWL_SCAN_DWELL_PASSIVE;\n    general_params->active_dwell[IWX_SCAN_HB_LMAC_IDX] = IWL_SCAN_DWELL_ACTIVE;\n    general_params->passive_dwell[IWX_SCAN_HB_LMAC_IDX] = IWL_SCAN_DWELL_PASSIVE;\n    \n    /* Specify the scan plan: We'll do one iteration. */\n    req->scan_params.periodic_params.schedule[0].interval = 0;\n    req->scan_params.periodic_params.schedule[0].iter_count = 1;\n    \n    err = iwx_fill_probe_req(sc, &req->scan_params.probe_params.preq);\n    if (err)\n        return err;\n    if (ic->ic_des_esslen != 0 && !bgscan) {\n        req->scan_params.probe_params.direct_scan[0].id = IEEE80211_ELEMID_SSID;\n        req->scan_params.probe_params.direct_scan[0].len = ic->ic_des_esslen;\n        memcpy(req->scan_params.probe_params.direct_scan[0].ssid, ic->ic_des_essid,\n               ic->ic_des_esslen);\n    }\n    \n    cp = &req->scan_params.channel_params;\n    \n    cp->flags = IWX_SCAN_CHANNEL_FLAG_ENABLE_CHAN_ORDER;\n    cp->count = iwx_umac_scan_fill_channels(sc,\n                                            (struct iwx_scan_channel_cfg_umac *)cp->channel_config,\n                                            ic->ic_des_esslen != 0, bgscan);\n    cp->n_aps_override[0] = IWX_SCAN_ADWELL_N_APS_GO_FRIENDLY;\n    cp->n_aps_override[1] = IWX_SCAN_ADWELL_N_APS_SOCIAL_CHS;\n    \n    err = iwx_send_cmd(sc, &hcmd);\n    ::free(req);\n    return err;\n}\n\nvoid ItlIwx::\niwx_mcc_update(struct iwx_softc *sc, struct iwx_mcc_chub_notif *notif)\n{\n   struct ieee80211com *ic = &sc->sc_ic;\n   struct _ifnet *ifp = IC2IFP(ic);\n\n    snprintf(sc->sc_fw_mcc, sizeof(sc->sc_fw_mcc), \"%c%c\",\n             (le16toh(notif->mcc) & 0xff00) >> 8, le16toh(notif->mcc) & 0xff);\n    if (sc->sc_fw_mcc_int != notif->mcc && sc->sc_ic.ic_event_handler) {\n        (*sc->sc_ic.ic_event_handler)(&sc->sc_ic, IEEE80211_EVT_COUNTRY_CODE_UPDATE, NULL);\n    }\n    sc->sc_fw_mcc_int = notif->mcc;\n\n    if (ifp->if_flags & IFF_DEBUG) {\n        DPRINTFN(3, (\"%s: firmware has detected regulatory domain '%s' \"\n               \"(0x%x)\\n\", DEVNAME(sc), sc->sc_fw_mcc, le16toh(notif->mcc)));\n    }\n\n   /* TODO: Schedule a task to send MCC_UPDATE_CMD? */\n}\n\nuint8_t ItlIwx::\niwx_ridx2rate(struct ieee80211_rateset *rs, int ridx)\n{\n    int i;\n    uint8_t rval;\n    \n    for (i = 0; i < rs->rs_nrates; i++) {\n        rval = (rs->rs_rates[i] & IEEE80211_RATE_VAL);\n        if (rval == iwx_rates[ridx].rate)\n            return rs->rs_rates[i];\n    }\n    \n    return 0;\n}\n\nint ItlIwx::\niwx_rval2ridx(int rval)\n{\n    int ridx;\n    \n    for (ridx = 0; ridx < nitems(iwx_rates); ridx++) {\n        if (iwx_rates[ridx].plcp == IWX_RATE_INVM_PLCP)\n            continue;\n        if (rval == iwx_rates[ridx].rate)\n            break;\n    }\n    \n    return ridx;\n}\n\nint ItlIwx::\niwx_rate2idx(int rate)\n{\n    const struct ieee80211_rateset *rs = &ieee80211_std_rateset_11a;\n    int idx;\n    \n    for (idx = 0; idx < rs->rs_nrates; idx++) {\n        if (rs->rs_rates[idx] == rate)\n            return idx;\n    }\n    \n    return 0;\n}\n\nvoid ItlIwx::\niwx_ack_rates(struct iwx_softc *sc, struct iwx_node *in, int *cck_rates,\n              int *ofdm_rates)\n{\n    struct ieee80211_node *ni = &in->in_ni;\n    struct ieee80211_rateset *rs = &ni->ni_rates;\n    int lowest_present_ofdm = -1;\n    int lowest_present_cck = -1;\n    uint8_t cck = 0;\n    uint8_t ofdm = 0;\n    int i;\n    \n    if (ni->ni_chan == IEEE80211_CHAN_ANYC ||\n        IEEE80211_IS_CHAN_2GHZ(ni->ni_chan)) {\n        for (i = IWX_FIRST_CCK_RATE; i < IWX_FIRST_OFDM_RATE; i++) {\n            if ((iwx_ridx2rate(rs, i) & IEEE80211_RATE_BASIC) == 0)\n                continue;\n            cck |= (1 << i);\n            if (lowest_present_cck == -1 || lowest_present_cck > i)\n                lowest_present_cck = i;\n        }\n    }\n    for (i = IWX_FIRST_OFDM_RATE; i <= IWX_LAST_NON_HT_RATE; i++) {\n        if ((iwx_ridx2rate(rs, i) & IEEE80211_RATE_BASIC) == 0)\n            continue;\n        ofdm |= (1 << (i - IWX_FIRST_OFDM_RATE));\n        if (lowest_present_ofdm == -1 || lowest_present_ofdm > i)\n            lowest_present_ofdm = i;\n    }\n    \n    /*\n     * Now we've got the basic rates as bitmaps in the ofdm and cck\n     * variables. This isn't sufficient though, as there might not\n     * be all the right rates in the bitmap. E.g. if the only basic\n     * rates are 5.5 Mbps and 11 Mbps, we still need to add 1 Mbps\n     * and 6 Mbps because the 802.11-2007 standard says in 9.6:\n     *\n     *    [...] a STA responding to a received frame shall transmit\n     *    its Control Response frame [...] at the highest rate in the\n     *    BSSBasicRateSet parameter that is less than or equal to the\n     *    rate of the immediately previous frame in the frame exchange\n     *    sequence ([...]) and that is of the same modulation class\n     *    ([...]) as the received frame. If no rate contained in the\n     *    BSSBasicRateSet parameter meets these conditions, then the\n     *    control frame sent in response to a received frame shall be\n     *    transmitted at the highest mandatory rate of the PHY that is\n     *    less than or equal to the rate of the received frame, and\n     *    that is of the same modulation class as the received frame.\n     *\n     * As a consequence, we need to add all mandatory rates that are\n     * lower than all of the basic rates to these bitmaps.\n     */\n    \n    if (IWX_RATE_24M_INDEX < lowest_present_ofdm)\n        ofdm |= IWX_RATE_BIT_MSK(24) >> IWX_FIRST_OFDM_RATE;\n    if (IWX_RATE_12M_INDEX < lowest_present_ofdm)\n        ofdm |= IWX_RATE_BIT_MSK(12) >> IWX_FIRST_OFDM_RATE;\n    /* 6M already there or needed so always add */\n    ofdm |= IWX_RATE_BIT_MSK(6) >> IWX_FIRST_OFDM_RATE;\n    \n    /*\n     * CCK is a bit more complex with DSSS vs. HR/DSSS vs. ERP.\n     * Note, however:\n     *  - if no CCK rates are basic, it must be ERP since there must\n     *    be some basic rates at all, so they're OFDM => ERP PHY\n     *    (or we're in 5 GHz, and the cck bitmap will never be used)\n     *  - if 11M is a basic rate, it must be ERP as well, so add 5.5M\n     *  - if 5.5M is basic, 1M and 2M are mandatory\n     *  - if 2M is basic, 1M is mandatory\n     *  - if 1M is basic, that's the only valid ACK rate.\n     * As a consequence, it's not as complicated as it sounds, just add\n     * any lower rates to the ACK rate bitmap.\n     */\n    if (IWX_RATE_11M_INDEX < lowest_present_cck)\n        cck |= IWX_RATE_BIT_MSK(11) >> IWX_FIRST_CCK_RATE;\n    if (IWX_RATE_5M_INDEX < lowest_present_cck)\n        cck |= IWX_RATE_BIT_MSK(5) >> IWX_FIRST_CCK_RATE;\n    if (IWX_RATE_2M_INDEX < lowest_present_cck)\n        cck |= IWX_RATE_BIT_MSK(2) >> IWX_FIRST_CCK_RATE;\n    /* 1M already there or needed so always add */\n    cck |= IWX_RATE_BIT_MSK(1) >> IWX_FIRST_CCK_RATE;\n    \n    *cck_rates = cck;\n    *ofdm_rates = ofdm;\n}\n\nstatic uint8_t iwx_mvm_mac80211_ac_to_ucode_ac(enum ieee80211_edca_ac ac)\n{\n   static const uint8_t mac80211_ac_to_ucode_ac[] = {\n       IWX_AC_BE,\n       IWX_AC_BK,\n       IWX_AC_VI,\n       IWX_AC_VO\n   };\n\n   return mac80211_ac_to_ucode_ac[ac];\n}\n\nvoid ItlIwx::\niwx_mac_ctxt_cmd_common(struct iwx_softc *sc, struct iwx_node *in,\n                        struct iwx_mac_ctx_cmd *cmd, uint32_t action)\n{\n#define IWX_EXP2(x)    ((1 << (x)) - 1)    /* CWmin = 2^ECWmin - 1 */\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct ieee80211_node *ni = ic->ic_bss;\n    int cck_ack_rates, ofdm_ack_rates;\n    int i;\n    \n    cmd->id_and_color = htole32(IWX_FW_CMD_ID_AND_COLOR(in->in_id,\n                                                        in->in_color));\n    cmd->action = htole32(action);\n\n    if (action == IWX_FW_CTXT_ACTION_REMOVE)\n        return;\n\n    if (ic->ic_opmode == IEEE80211_M_MONITOR)\n        cmd->mac_type = htole32(IWX_FW_MAC_TYPE_LISTENER);\n    else if (ic->ic_opmode == IEEE80211_M_STA)\n        cmd->mac_type = htole32(IWX_FW_MAC_TYPE_BSS_STA);\n    else\n        panic(\"unsupported operating mode %d\\n\", ic->ic_opmode);\n    cmd->tsf_id = htole32(IWX_TSF_ID_A);\n    \n    IEEE80211_ADDR_COPY(cmd->node_addr, ic->ic_myaddr);\n    if (ic->ic_opmode == IEEE80211_M_MONITOR) {\n        IEEE80211_ADDR_COPY(cmd->bssid_addr, etherbroadcastaddr);\n        return;\n    }\n    \n    IEEE80211_ADDR_COPY(cmd->bssid_addr, in->in_macaddr);\n    iwx_ack_rates(sc, in, &cck_ack_rates, &ofdm_ack_rates);\n    cmd->cck_rates = htole32(cck_ack_rates);\n    cmd->ofdm_rates = htole32(ofdm_ack_rates);\n    \n    cmd->cck_short_preamble\n    = htole32((ic->ic_flags & IEEE80211_F_SHPREAMBLE)\n              ? IWX_MAC_FLG_SHORT_PREAMBLE : 0);\n    cmd->short_slot\n    = htole32((ic->ic_flags & IEEE80211_F_SHSLOT)\n              ? IWX_MAC_FLG_SHORT_SLOT : 0);\n    \n    for (i = 0; i < EDCA_NUM_AC; i++) {\n        struct ieee80211_edca_ac_params *ac = &ic->ic_edca_ac[i];\n        int txf = iwx_ac_to_tx_fifo[i];\n        uint8_t ucode_ac = iwx_mvm_mac80211_ac_to_ucode_ac((enum ieee80211_edca_ac)i);\n        \n        cmd->ac[ucode_ac].cw_min = htole16(IWX_EXP2(ac->ac_ecwmin));\n        cmd->ac[ucode_ac].cw_max = htole16(IWX_EXP2(ac->ac_ecwmax));\n        cmd->ac[ucode_ac].aifsn = ac->ac_aifsn;\n        cmd->ac[ucode_ac].fifos_mask = (1 << txf);\n        cmd->ac[ucode_ac].edca_txop = htole16(ac->ac_txoplimit * 32);\n    }\n    if (ni->ni_flags & IEEE80211_NODE_QOS)\n        cmd->qos_flags |= htole32(IWX_MAC_QOS_FLG_UPDATE_EDCA);\n    \n    if (ni->ni_flags & IEEE80211_NODE_HT) {\n        enum ieee80211_htprot htprot =\n        (enum ieee80211_htprot)(ni->ni_htop1 & IEEE80211_HTOP1_PROT_MASK);\n        \n        /* The fw does not distinguish between ht and fat */\n        uint32_t ht_flag = IWX_MAC_PROT_FLG_HT_PROT | IWX_MAC_PROT_FLG_FAT_PROT;\n        \n        /*\n         * See section 9.23.3.1 of IEEE 80211-2012.\n         * Nongreenfield HT STAs Present is not supported.\n         */\n        switch (htprot) {\n            case IEEE80211_HTPROT_NONE:\n                break;\n            case IEEE80211_HTPROT_NONMEMBER:\n            case IEEE80211_HTPROT_NONHT_MIXED:\n                cmd->protection_flags = htole32(ht_flag);\n                break;\n            case IEEE80211_HTPROT_20MHZ:\n                /* Protect when channel wider than 20MHz */\n                if (ni->ni_chw > IEEE80211_CHAN_WIDTH_20)\n                    cmd->protection_flags = htole32(ht_flag);\n                break;\n            default:\n                XYLog(\"Illegal protection mode %d\\n\", htprot);\n                break;\n        }\n        \n        cmd->qos_flags |= htole32(IWX_MAC_QOS_FLG_TGN);\n    }\n    if (ic->ic_flags & IEEE80211_F_USEPROT)\n        cmd->protection_flags |= htole32(IWX_MAC_PROT_FLG_TGG_PROTECT);\n    \n    cmd->filter_flags = htole32(IWX_MAC_FILTER_ACCEPT_GRP);\n#undef IWX_EXP2\n}\n\nvoid ItlIwx::\niwx_mac_ctxt_cmd_fill_sta(struct iwx_softc *sc, struct iwx_node *in,\n                          struct iwx_mac_data_sta *sta, int assoc)\n{\n    struct ieee80211_node *ni = &in->in_ni;\n    uint32_t dtim_off;\n    uint64_t tsf;\n    \n    dtim_off = ni->ni_dtimcount * ni->ni_intval * IEEE80211_DUR_TU;\n    memcpy(&tsf, ni->ni_tstamp, sizeof(tsf));\n    tsf = letoh64(tsf);\n    \n    sta->is_assoc = htole32(assoc);\n    sta->dtim_time = htole32(ni->ni_rstamp + dtim_off);\n    sta->dtim_tsf = htole64(tsf + dtim_off);\n    sta->bi = htole32(ni->ni_intval);\n    sta->bi_reciprocal = htole32(iwx_reciprocal(ni->ni_intval));\n    sta->dtim_interval = htole32(ni->ni_intval * ni->ni_dtimperiod);\n    sta->dtim_reciprocal = htole32(iwx_reciprocal(sta->dtim_interval));\n    sta->listen_interval = htole32(10);\n    sta->assoc_id = htole32(ni->ni_associd);\n    sta->assoc_beacon_arrive_time = htole32(ni->ni_rstamp);\n}\n\nint ItlIwx::\niwx_mac_ctxt_cmd(struct iwx_softc *sc, struct iwx_node *in, uint32_t action,\n                 int assoc)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct ieee80211_node *ni = &in->in_ni;\n    struct iwx_mac_ctx_cmd cmd;\n    int active = (sc->sc_flags & IWX_FLAG_MAC_ACTIVE);\n    \n    if (action == IWX_FW_CTXT_ACTION_ADD && active) {\n        XYLog(\"MAC already added\\n\");\n        return 0;\n    }\n    if (action == IWX_FW_CTXT_ACTION_REMOVE && !active) {\n        XYLog(\"MAC already removed\\n\");\n        return 0;\n    }\n    \n    memset(&cmd, 0, sizeof(cmd));\n    \n    iwx_mac_ctxt_cmd_common(sc, in, &cmd, action);\n\n    if (action == IWX_FW_CTXT_ACTION_REMOVE) {\n        return iwx_send_cmd_pdu(sc, IWX_MAC_CONTEXT_CMD, 0,\n                                sizeof(cmd), &cmd);\n    }\n\n    if (ic->ic_opmode == IEEE80211_M_MONITOR) {\n        cmd.filter_flags |= htole32(IWX_MAC_FILTER_IN_PROMISC |\n                                    IWX_MAC_FILTER_IN_CONTROL_AND_MGMT |\n                                    IWX_MAC_FILTER_ACCEPT_GRP |\n                                    IWX_MAC_FILTER_IN_BEACON |\n                                    IWX_MAC_FILTER_IN_PROBE_REQUEST |\n                                    IWX_MAC_FILTER_IN_CRC32);\n    } else if (!assoc || !ni->ni_associd || !ni->ni_dtimperiod)\n    /*\n     * Allow beacons to pass through as long as we are not\n     * associated or we do not have dtim period information.\n     */\n        cmd.filter_flags |= htole32(IWX_MAC_FILTER_IN_BEACON);\n    else\n        iwx_mac_ctxt_cmd_fill_sta(sc, in, &cmd.sta, assoc);\n    \n    if (ni->ni_flags & IEEE80211_NODE_HE) {\n        cmd.filter_flags |= htole32(IWX_MAC_FILTER_IN_11AX);\n    }\n    \n    return iwx_send_cmd_pdu(sc, IWX_MAC_CONTEXT_CMD, 0, sizeof(cmd), &cmd);\n}\n\nint ItlIwx::\niwx_clear_statistics(struct iwx_softc *sc)\n{\n    struct iwx_statistics_cmd scmd = {\n        .flags = htole32(IWX_STATISTICS_FLG_CLEAR)\n    };\n    struct iwx_host_cmd cmd = {\n        .id = IWX_STATISTICS_CMD,\n        .len[0] = sizeof(scmd),\n        .data[0] = &scmd,\n        .flags = IWX_CMD_WANT_RESP,\n        .resp_pkt_len = sizeof(struct iwx_notif_statistics),\n    };\n    int err;\n    \n    err = iwx_send_cmd(sc, &cmd);\n    if (err)\n        return err;\n    \n    iwx_free_resp(sc, &cmd);\n    return 0;\n}\n\nint ItlIwx::\niwx_update_quotas(struct iwx_softc *sc, struct iwx_node *in, int running)\n{\n    struct iwx_time_quota_cmd cmd;\n    int i, idx, num_active_macs, quota, quota_rem;\n    int colors[IWX_MAX_BINDINGS] = { -1, -1, -1, -1, };\n    int n_ifs[IWX_MAX_BINDINGS] = {0, };\n    uint16_t id;\n    \n    memset(&cmd, 0, sizeof(cmd));\n    \n    /* currently, PHY ID == binding ID */\n    if (in && in->in_phyctxt) {\n        id = in->in_phyctxt->id;\n        KASSERT(id < IWX_MAX_BINDINGS, \"id < IWX_MAX_BINDINGS\");\n        colors[id] = in->in_phyctxt->color;\n        if (running)\n            n_ifs[id] = 1;\n    }\n    \n    /*\n     * The FW's scheduling session consists of\n     * IWX_MAX_QUOTA fragments. Divide these fragments\n     * equally between all the bindings that require quota\n     */\n    num_active_macs = 0;\n    for (i = 0; i < IWX_MAX_BINDINGS; i++) {\n        cmd.quotas[i].id_and_color = htole32(IWX_FW_CTXT_INVALID);\n        num_active_macs += n_ifs[i];\n    }\n    \n    quota = 0;\n    quota_rem = 0;\n    if (num_active_macs) {\n        quota = IWX_MAX_QUOTA / num_active_macs;\n        quota_rem = IWX_MAX_QUOTA % num_active_macs;\n    }\n    \n    for (idx = 0, i = 0; i < IWX_MAX_BINDINGS; i++) {\n        if (colors[i] < 0)\n            continue;\n        \n        cmd.quotas[idx].id_and_color =\n        htole32(IWX_FW_CMD_ID_AND_COLOR(i, colors[i]));\n        \n        if (n_ifs[i] <= 0) {\n            cmd.quotas[idx].quota = htole32(0);\n            cmd.quotas[idx].max_duration = htole32(0);\n        } else {\n            cmd.quotas[idx].quota = htole32(quota * n_ifs[i]);\n            cmd.quotas[idx].max_duration = htole32(0);\n        }\n        idx++;\n    }\n    \n    /* Give the remainder of the session to the first binding */\n    cmd.quotas[0].quota = htole32(le32toh(cmd.quotas[0].quota) + quota_rem);\n    \n    return iwx_send_cmd_pdu(sc, IWX_TIME_QUOTA_CMD, 0,\n                            sizeof(cmd), &cmd);\n}\n\nvoid ItlIwx::\niwx_add_task(struct iwx_softc *sc, struct taskq *taskq, struct task *task)\n{\n    XYLog(\"%s %s\\n\", __FUNCTION__, task->name);\n    int s = splnet();\n    \n    if (sc->sc_flags & IWX_FLAG_SHUTDOWN) {\n        XYLog(\"%s %s sc->sc_flags & IWX_FLAG_SHUTDOWN\\n\", __FUNCTION__, task->name);\n        splx(s);\n        return;\n    }\n    \n    //    refcnt_take(&sc->task_refs);\n    if (!task_add(taskq, task)) {\n        //        refcnt_rele_wake(&sc->task_refs);\n    }\n    splx(s);\n}\n\nvoid ItlIwx::\niwx_del_task(struct iwx_softc *sc, struct taskq *taskq, struct task *task)\n{\n    XYLog(\"%s %s\\n\", __FUNCTION__, task->name);\n    if (task_del(taskq, task)) {\n        //        refcnt_rele(&sc->task_refs);\n    }\n}\n\nint ItlIwx::\niwx_scan(struct iwx_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct _ifnet *ifp = IC2IFP(ic);\n    int err;\n    \n    if (sc->sc_flags & IWX_FLAG_BGSCAN) {\n        err = iwx_scan_abort(sc);\n        if (err) {\n            XYLog(\"%s: could not abort background scan\\n\",\n                  DEVNAME(sc));\n            return err;\n        }\n    }\n    \n    err = iwx_umac_scan(sc, 0);\n    if (err) {\n        XYLog(\"%s: could not initiate scan\\n\", DEVNAME(sc));\n        return err;\n    }\n    \n    /*\n     * The current mode might have been fixed during association.\n     * Ensure all channels get scanned.\n     */\n    if (IFM_MODE(ic->ic_media.ifm_cur->ifm_media) == IFM_AUTO)\n        ieee80211_setmode(ic, IEEE80211_MODE_AUTO);\n    \n    sc->sc_flags |= IWX_FLAG_SCANNING;\n    if (ifp->if_flags & IFF_DEBUG)\n        XYLog(\"%s: %s -> %s\\n\", ifp->if_xname,\n              ieee80211_state_name[ic->ic_state],\n              ieee80211_state_name[IEEE80211_S_SCAN]);\n    if ((sc->sc_flags & IWX_FLAG_BGSCAN) == 0) {\n        ieee80211_set_link_state(ic, LINK_STATE_DOWN);\n        ieee80211_node_cleanup(ic, ic->ic_bss);\n    }\n    ic->ic_state = IEEE80211_S_SCAN;\n    wakeupOn(&ic->ic_state); /* wake iwx_init() */\n    \n    return 0;\n}\n\nint ItlIwx::\niwx_bgscan(struct ieee80211com *ic)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwx_softc *sc = (struct iwx_softc *)IC2IFP(ic)->if_softc;\n    ItlIwx *that = container_of(sc, ItlIwx, com);\n    int err;\n    \n    if (sc->sc_flags & IWX_FLAG_SCANNING)\n        return 0;\n    \n    err = that->iwx_umac_scan(sc, 1);\n    if (err) {\n        XYLog(\"%s: could not initiate scan\\n\", DEVNAME(sc));\n        return err;\n    }\n    \n    sc->sc_flags |= IWX_FLAG_BGSCAN;\n    return 0;\n}\n\nint ItlIwx::\niwx_umac_scan_abort(struct iwx_softc *sc)\n{\n    struct iwx_umac_scan_abort cmd = { 0 };\n    \n    return iwx_send_cmd_pdu(sc,\n                            IWX_WIDE_ID(IWX_LONG_GROUP, IWX_SCAN_ABORT_UMAC),\n                            0, sizeof(cmd), &cmd);\n}\n\nint ItlIwx::\niwx_scan_abort(struct iwx_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    int err;\n    \n    err = iwx_umac_scan_abort(sc);\n    if (err == 0)\n        sc->sc_flags &= ~(IWX_FLAG_SCANNING | IWX_FLAG_BGSCAN);\n    return err;\n}\n\nint ItlIwx::\niwx_enable_mgmt_queue(struct iwx_softc *sc)\n{\n    int err;\n    int cmdver;\n\n    cmdver = iwx_lookup_cmd_ver(sc, IWX_LONG_GROUP, IWX_ADD_STA);\n    if (cmdver != IWX_FW_CMD_VER_UNKNOWN && cmdver >= 12)\n        sc->first_data_qid = IWX_QID_MGMT - 1;\n    else\n        sc->first_data_qid = IWX_QID_MGMT;\n    err = iwx_enable_txq(sc, IWX_STATION_ID,\n                         sc->first_data_qid, IWX_MGMT_TID,\n                         sc->txq[sc->first_data_qid].ring_count);\n    if (err) {\n        XYLog(\"%s: could not enable MGMT Tx queue %d (error %d)\\n\",\n              DEVNAME(sc), sc->first_data_qid, err);\n        return err;\n    }\n    \n    return 0;\n}\n\nint ItlIwx::\niwx_rs_rval2idx(uint8_t rval)\n{\n   /* Firmware expects indices which match our 11g rate set. */\n   const struct ieee80211_rateset *rs = &ieee80211_std_rateset_11g;\n   int i;\n\n   for (i = 0; i < rs->rs_nrates; i++) {\n       if ((rs->rs_rates[i] & IEEE80211_RATE_VAL) == rval)\n           return i;\n   }\n\n   return -1;\n}\n\nuint16_t ItlIwx::\niwx_rs_ht_rates(struct iwx_softc *sc, struct ieee80211_node *ni, int rsidx)\n{\n   struct ieee80211com *ic = &sc->sc_ic;\n   const struct ieee80211_ht_rateset *rs;\n   uint16_t htrates = 0;\n   int mcs;\n\n   rs = &ieee80211_std_ratesets_11n[rsidx];\n   for (mcs = rs->min_mcs; mcs <= rs->max_mcs; mcs++) {\n       if (!isset(ni->ni_rxmcs, mcs) ||\n           !isset(ic->ic_sup_mcs, mcs))\n           continue;\n       htrates |= (1 << (mcs - rs->min_mcs));\n   }\n\n   return htrates;\n}\n\nstatic uint8_t iwx_rs_fw_bw_from_sta_bw(uint8_t bw)\n{\n    uint8_t fw_bw;\n    switch (bw) {\n        case IEEE80211_CHAN_WIDTH_20:\n            fw_bw = IWX_TLC_MNG_CH_WIDTH_20MHZ;\n            break;\n        case IEEE80211_CHAN_WIDTH_40:\n            fw_bw = IWX_TLC_MNG_CH_WIDTH_40MHZ;\n            break;\n        case IEEE80211_CHAN_WIDTH_80:\n            fw_bw = IWX_TLC_MNG_CH_WIDTH_80MHZ;\n            break;\n        case IEEE80211_CHAN_WIDTH_80P80:\n        case IEEE80211_CHAN_WIDTH_160:\n            fw_bw = IWX_TLC_MNG_CH_WIDTH_160MHZ;\n            break;\n        default:\n            fw_bw = IWX_TLC_MNG_CH_WIDTH_20MHZ;\n            break;\n    }\n    return fw_bw;\n}\n\nuint16_t ItlIwx::\niwx_rs_fw_get_config_flags(struct iwx_softc *sc)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct ieee80211_node *ni = ic->ic_bss;\n    uint16_t flags = 0;\n    \n    if (ic->ic_state < IEEE80211_S_ASSOC) {\n        return flags;\n    }\n    \n    if (iwx_num_of_ant(iwx_fw_valid_tx_ant(sc)) > 1) {\n        if ((ni->ni_flags & IEEE80211_NODE_HE) &&\n            ni->ni_he_cap_elem.phy_cap_info[2] &\n            IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ) {\n            flags |= IWX_TLC_MNG_CFG_FLAGS_STBC_MSK;\n        } else if (ni->ni_vhtcaps & IEEE80211_VHTCAP_RXSTBC_MASK)\n            flags |= IWX_TLC_MNG_CFG_FLAGS_STBC_MSK;\n        else if (ni->ni_htcaps & IEEE80211_HTCAP_RXSTBC_MASK)\n            flags |= IWX_TLC_MNG_CFG_FLAGS_STBC_MSK;\n    }\n    \n    if (((ni->ni_htcaps & IEEE80211_HTCAP_LDPC) ||\n         ((ic->ic_flags & IEEE80211_F_VHTON) && (ni->ni_vhtcaps & IEEE80211_VHTCAP_RXLDPC))))\n        flags |= IWX_TLC_MNG_CFG_FLAGS_LDPC_MSK;\n    \n    /* consider LDPC support in case of HE */\n    if ((ni->ni_flags & IEEE80211_NODE_HE) &&\n        (ni->ni_he_cap_elem.phy_cap_info[1] &\n        IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD))\n        flags |= IWX_TLC_MNG_CFG_FLAGS_LDPC_MSK;\n    \n    if ((ni->ni_flags & IEEE80211_NODE_HE) &&\n        !(ni->ni_he_cap_elem.phy_cap_info[1] &\n         IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD))\n        flags &= ~IWX_TLC_MNG_CFG_FLAGS_LDPC_MSK;\n\n    if ((ni->ni_flags & IEEE80211_NODE_HE) &&\n        (ni->ni_he_cap_elem.phy_cap_info[3] &\n         IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_MASK))\n        flags |= IWX_TLC_MNG_CFG_FLAGS_HE_DCM_NSS_1_MSK;\n    \n    return flags;\n}\n\nstatic\nint rs_fw_vht_highest_rx_mcs_index(struct iwx_softc *sc,\n                   int nss)\n{\n    uint16_t rx_mcs = le16toh(sc->sc_ic.ic_bss->ni_vht_mcsinfo.rx_mcs_map) &\n        (0x3 << (2 * (nss - 1)));\n    rx_mcs >>= (2 * (nss - 1));\n\n    switch (rx_mcs) {\n    case IEEE80211_VHT_MCS_SUPPORT_0_7:\n        return IWX_TLC_MNG_HT_RATE_MCS7;\n    case IEEE80211_VHT_MCS_SUPPORT_0_8:\n        return IWX_TLC_MNG_HT_RATE_MCS8;\n    case IEEE80211_VHT_MCS_SUPPORT_0_9:\n        return IWX_TLC_MNG_HT_RATE_MCS9;\n    default:\n        WARN_ON_ONCE(1);\n        break;\n    }\n\n    return 0;\n}\n\nstatic void\niwx_rs_fw_vht_set_enabled_rates(struct iwx_softc *sc,\n                struct iwx_tlc_config_cmd_v4 *cmd)\n{\n    uint16_t supp;\n    int i, highest_mcs;\n    struct ieee80211com *ic = &sc->sc_ic;\n\n    for (i = 0; i < IWX_TLC_NSS_MAX && i < ic->ic_bss->ni_rx_nss; i++) {\n        highest_mcs = rs_fw_vht_highest_rx_mcs_index(sc, i + 1);\n        if (!highest_mcs)\n            continue;\n\n        supp = (1 << (highest_mcs + 1)) - 1;\n        if (ic->ic_bss->ni_chw == IEEE80211_CHAN_WIDTH_20)\n            supp &= ~(1 << IWX_TLC_MNG_HT_RATE_MCS9);\n\n        cmd->ht_rates[i][IWX_TLC_MCS_PER_BW_80] = htole16(supp);\n        if (ic->ic_bss->ni_chw == IEEE80211_CHAN_WIDTH_80P80 || ic->ic_bss->ni_chw == IEEE80211_CHAN_WIDTH_160)\n            cmd->ht_rates[i][1] = cmd->ht_rates[i][0];\n    }\n}\n\nstatic uint16_t rs_fw_he_ieee80211_mcs_to_rs_mcs(uint16_t mcs)\n{\n    switch (mcs) {\n    case IEEE80211_HE_MCS_SUPPORT_0_7:\n        return BIT(IWX_TLC_MNG_HT_RATE_MCS7 + 1) - 1;\n    case IEEE80211_HE_MCS_SUPPORT_0_9:\n        return BIT(IWX_TLC_MNG_HT_RATE_MCS9 + 1) - 1;\n    case IEEE80211_HE_MCS_SUPPORT_0_11:\n        return BIT(IWX_TLC_MNG_HT_RATE_MCS11 + 1) - 1;\n    case IEEE80211_HE_MCS_NOT_SUPPORTED:\n        return 0;\n    }\n\n    XYLog(\"invalid HE MCS %d\\n\", mcs);\n    return 0;\n}\n\nstatic uint8_t iwx_rs_fw_set_active_chains(uint8_t chains)\n{\n    uint8_t fw_chains = 0;\n\n    if (chains & IWX_ANT_A)\n        fw_chains |= IWX_TLC_MNG_CHAIN_A_MSK;\n    if (chains & IWX_ANT_B)\n        fw_chains |= IWX_TLC_MNG_CHAIN_B_MSK;\n\n    return fw_chains;\n}\n\nstatic void\niwx_rs_fw_he_set_enabled_rates(struct iwx_softc *sc,\n                           struct iwx_tlc_config_cmd_v4 *cmd)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    uint16_t mcs_160 = le16toh(ic->ic_he_mcs_nss_supp.rx_mcs_160);\n    uint16_t mcs_80 = le16toh(ic->ic_he_mcs_nss_supp.rx_mcs_80);\n    uint16_t tx_mcs_80 =\n    le16toh(ic->ic_he_mcs_nss_supp.tx_mcs_80);\n    uint16_t tx_mcs_160 =\n    le16toh(ic->ic_he_mcs_nss_supp.tx_mcs_160);\n    int i;\n    uint8_t nss = ic->ic_bss->ni_rx_nss;\n\n    for (i = 0; i < nss && i < IWX_TLC_NSS_MAX; i++) {\n        uint16_t _mcs_160 = (mcs_160 >> (2 * i)) & 0x3;\n        uint16_t _mcs_80 = (mcs_80 >> (2 * i)) & 0x3;\n        uint16_t _tx_mcs_160 = (tx_mcs_160 >> (2 * i)) & 0x3;\n        uint16_t _tx_mcs_80 = (tx_mcs_80 >> (2 * i)) & 0x3;\n\n        /* If one side doesn't support - mark both as not supporting */\n        if (_mcs_80 == IEEE80211_HE_MCS_NOT_SUPPORTED ||\n            _tx_mcs_80 == IEEE80211_HE_MCS_NOT_SUPPORTED) {\n            _mcs_80 = IEEE80211_HE_MCS_NOT_SUPPORTED;\n            _tx_mcs_80 = IEEE80211_HE_MCS_NOT_SUPPORTED;\n        }\n        if (_mcs_80 > _tx_mcs_80)\n            _mcs_80 = _tx_mcs_80;\n        cmd->ht_rates[i][IWX_TLC_MCS_PER_BW_80] =\n            htole16(rs_fw_he_ieee80211_mcs_to_rs_mcs(_mcs_80));\n\n        /* If one side doesn't support - mark both as not supporting */\n        if (_mcs_160 == IEEE80211_HE_MCS_NOT_SUPPORTED ||\n            _tx_mcs_160 == IEEE80211_HE_MCS_NOT_SUPPORTED) {\n            _mcs_160 = IEEE80211_HE_MCS_NOT_SUPPORTED;\n            _tx_mcs_160 = IEEE80211_HE_MCS_NOT_SUPPORTED;\n        }\n        if (_mcs_160 > _tx_mcs_160)\n            _mcs_160 = _tx_mcs_160;\n        cmd->ht_rates[i][IWX_TLC_MCS_PER_BW_160] =\n        htole16(rs_fw_he_ieee80211_mcs_to_rs_mcs(_mcs_160));\n    }\n}\n\nint ItlIwx::\niwx_rs_init(struct iwx_softc *sc, struct iwx_node *in, bool update)\n{\n    struct ieee80211_node *ni = &in->in_ni;\n    struct ieee80211_rateset *rs = &ni->ni_rates;\n    struct iwx_tlc_config_cmd_v4 cfg_cmd;\n    uint32_t cmd_id;\n    int i;\n    uint16_t cmd_size;\n    uint8_t cmdver;\n\n    memset(&cfg_cmd, 0, sizeof(cfg_cmd));\n\n    for (i = 0; i < rs->rs_nrates; i++) {\n        uint8_t rval = rs->rs_rates[i] & IEEE80211_RATE_VAL;\n        int idx = iwx_rs_rval2idx(rval);\n        if (idx == -1)\n            return EINVAL;\n        cfg_cmd.non_ht_rates |= (1 << idx);\n    }\n    if (ni->ni_flags & IEEE80211_NODE_HE) {\n        cfg_cmd.mode = IWX_TLC_MNG_MODE_HE;\n        iwx_rs_fw_he_set_enabled_rates(sc, &cfg_cmd);\n    } else if (ni->ni_flags & IEEE80211_NODE_VHT) {\n        cfg_cmd.mode = IWX_TLC_MNG_MODE_VHT;\n        iwx_rs_fw_vht_set_enabled_rates(sc, &cfg_cmd);\n    } else if (ni->ni_flags & IEEE80211_NODE_HT) {\n        cfg_cmd.mode = IWX_TLC_MNG_MODE_HT;\n        cfg_cmd.ht_rates[IWX_TLC_NSS_1][IWX_TLC_MCS_PER_BW_80] = htole16(iwx_rs_ht_rates(sc, ni, ni->ni_chw == IEEE80211_CHAN_WIDTH_40 ? IEEE80211_HT_RATESET_CBW40_SISO : IEEE80211_HT_RATESET_SISO));\n        if (ni->ni_rx_nss > 1)\n            cfg_cmd.ht_rates[IWX_TLC_NSS_2][IWX_TLC_MCS_PER_BW_80] = htole16(iwx_rs_ht_rates(sc, ni, ni->ni_chw == IEEE80211_CHAN_WIDTH_40 ? IEEE80211_HT_RATESET_CBW40_MIMO2 : IEEE80211_HT_RATESET_MIMO2));\n    } else\n        cfg_cmd.mode = IWX_TLC_MNG_MODE_NON_HT;\n\n    cfg_cmd.sta_id = IWX_STATION_ID;\n    cfg_cmd.max_ch_width = update ? iwx_rs_fw_bw_from_sta_bw(ni->ni_chw) : IWX_RATE_MCS_CHAN_WIDTH_20;\n    cfg_cmd.chains = iwx_rs_fw_set_active_chains(iwx_fw_valid_tx_ant(sc));\n    cfg_cmd.flags = iwx_rs_fw_get_config_flags(sc);\n    if ((ni->ni_flags & IEEE80211_NODE_HE) == 0) {\n        if (ieee80211_node_supports_ht_sgi20(ni))\n            cfg_cmd.sgi_ch_width_supp = (1 << IWX_TLC_MNG_CH_WIDTH_20MHZ);\n\n        if (ieee80211_node_supports_ht_sgi40(ni))\n            cfg_cmd.sgi_ch_width_supp |= (1 << IWX_TLC_MNG_CH_WIDTH_40MHZ);\n        \n        if (ieee80211_node_supports_vht_sgi80(ni)) {\n            cfg_cmd.sgi_ch_width_supp |= (1 << IWX_TLC_MNG_CH_WIDTH_80MHZ);\n        }\n        \n        if (ieee80211_node_supports_vht_sgi160(ni)) {\n            cfg_cmd.sgi_ch_width_supp |= (1 << IWX_TLC_MNG_CH_WIDTH_160MHZ);\n        }\n    }\n\n    cmd_id = iwx_cmd_id(IWX_TLC_MNG_CONFIG_CMD, IWX_DATA_PATH_GROUP, 0);\n    cmdver = iwx_lookup_cmd_ver(sc, IWX_DATA_PATH_GROUP, IWX_TLC_MNG_CONFIG_CMD);\n    XYLog(\"%s cmdver %d\\n\", __FUNCTION__, cmdver);\n    if (cmdver == 4) {\n        return iwx_send_cmd_pdu(sc, cmd_id, IWX_CMD_ASYNC,\n                                sizeof(cfg_cmd), &cfg_cmd);\n    } else if (cmdver < 4 || cmdver == IWX_FW_CMD_VER_UNKNOWN) {\n        struct iwl_tlc_config_cmd_v3 cfg_cmd_v3 = {\n            .sta_id = cfg_cmd.sta_id,\n            .max_ch_width = cfg_cmd.max_ch_width,\n            .mode = cfg_cmd.mode,\n            .chains = cfg_cmd.chains,\n            .amsdu = !!cfg_cmd.max_mpdu_len,\n            .flags = cfg_cmd.flags,\n            .non_ht_rates = cfg_cmd.non_ht_rates,\n            .ht_rates[0][0] = cfg_cmd.ht_rates[0][0],\n            .ht_rates[0][1] = cfg_cmd.ht_rates[0][1],\n            .ht_rates[1][0] = cfg_cmd.ht_rates[1][0],\n            .ht_rates[1][1] = cfg_cmd.ht_rates[1][1],\n            .sgi_ch_width_supp = cfg_cmd.sgi_ch_width_supp,\n            .max_mpdu_len = cfg_cmd.max_mpdu_len,\n        };\n        \n        cmd_size = sizeof(cfg_cmd_v3);\n        \n        /* In old versions of the API the struct is 4 bytes smaller */\n        if (cmdver == IWX_FW_CMD_VER_UNKNOWN || cmdver < 3)\n            cmd_size -= 4;\n        \n        return iwx_send_cmd_pdu(sc, cmd_id, IWX_CMD_ASYNC, cmd_size,\n                                &cfg_cmd_v3);\n    } else {\n        return -EINVAL;\n    }\n}\n\nstatic uint32_t iwx_new_rate_from_v1(uint32_t rate_v1)\n{\n    uint32_t rate_v2 = 0;\n    uint32_t dup = 0;\n    \n    if (rate_v1 == 0)\n        return rate_v1;\n    /* convert rate */\n    if (rate_v1 & IWX_RATE_MCS_HT_MSK_V1) {\n        uint32_t nss = 0;\n        \n        rate_v2 |= IWX_RATE_MCS_HT_MSK;\n        rate_v2 |=\n        rate_v1 & IWX_RATE_HT_MCS_RATE_CODE_MSK_V1;\n        nss = (rate_v1 & IWX_RATE_HT_MCS_MIMO2_MSK) >>\n        IWX_RATE_HT_MCS_NSS_POS_V1;\n        rate_v2 |= nss << IWX_RATE_MCS_NSS_POS;\n    } else if (rate_v1 & IWX_RATE_MCS_VHT_MSK_V1 ||\n               rate_v1 & IWX_RATE_MCS_HE_MSK_V1) {\n        rate_v2 |= rate_v1 & IWX_RATE_VHT_MCS_RATE_CODE_MSK;\n        \n        rate_v2 |= rate_v1 & IWX_RATE_VHT_MCS_MIMO2_MSK;\n        \n        if (rate_v1 & IWX_RATE_MCS_HE_MSK_V1) {\n            uint32_t he_type_bits = rate_v1 & IWX_RATE_MCS_HE_TYPE_MSK_V1;\n            uint32_t he_type = he_type_bits >> IWX_RATE_MCS_HE_TYPE_POS_V1;\n            uint32_t he_106t = (rate_v1 & IWX_RATE_MCS_HE_106T_MSK_V1) >>\n            IWX_RATE_MCS_HE_106T_POS_V1;\n            uint32_t he_gi_ltf = (rate_v1 & IWX_RATE_MCS_HE_GI_LTF_MSK_V1) >>\n            IWX_RATE_MCS_HE_GI_LTF_POS;\n            \n            if ((he_type_bits == IWX_RATE_MCS_HE_TYPE_SU ||\n                 he_type_bits == IWX_RATE_MCS_HE_TYPE_EXT_SU) &&\n                he_gi_ltf == IWX_RATE_MCS_HE_SU_4_LTF)\n            /* the new rate have an additional bit to\n             * represent the value 4 rather then using SGI\n             * bit for this purpose - as it was done in the old\n             * rate */\n                he_gi_ltf += (rate_v1 & IWX_RATE_MCS_SGI_MSK_V1) >>\n                IWX_RATE_MCS_SGI_POS_V1;\n            \n            rate_v2 |= he_gi_ltf << IWX_RATE_MCS_HE_GI_LTF_POS;\n            rate_v2 |= he_type << IWX_RATE_MCS_HE_TYPE_POS;\n            rate_v2 |= he_106t << IWX_RATE_MCS_HE_106T_POS;\n            rate_v2 |= rate_v1 & IWX_RATE_HE_DUAL_CARRIER_MODE_MSK;\n            rate_v2 |= IWX_RATE_MCS_HE_MSK;\n        } else {\n            rate_v2 |= IWX_RATE_MCS_VHT_MSK;\n        }\n        /* if legacy format */\n    } else {\n        uint32_t legacy_rate = iwx_hwrate_to_plcp_idx(rate_v1);\n        \n        WARN_ON(legacy_rate < 0);\n        rate_v2 |= legacy_rate;\n        if (!(rate_v1 & IWX_RATE_MCS_CCK_MSK_V1))\n            rate_v2 |= IWX_RATE_MCS_LEGACY_OFDM_MSK;\n    }\n    \n    /* convert flags */\n    if (rate_v1 & IWX_RATE_MCS_LDPC_MSK_V1)\n        rate_v2 |= IWX_RATE_MCS_LDPC_MSK;\n    rate_v2 |= (rate_v1 & IWX_RATE_MCS_CHAN_WIDTH_MSK_V1) |\n    (rate_v1 & IWX_RATE_MCS_ANT_AB_MSK) |\n    (rate_v1 & IWX_RATE_MCS_STBC_MSK) |\n    (rate_v1 & IWX_RATE_MCS_BF_MSK);\n    \n    dup = (rate_v1 & IWX_RATE_MCS_DUP_MSK_V1) >> IWX_RATE_MCS_DUP_POS_V1;\n    if (dup) {\n        rate_v2 |= IWX_RATE_MCS_DUP_MSK;\n        rate_v2 |= dup << IWX_RATE_MCS_CHAN_WIDTH_POS;\n    }\n    \n    if ((!(rate_v1 & IWX_RATE_MCS_HE_MSK_V1)) &&\n        (rate_v1 & IWX_RATE_MCS_SGI_MSK_V1))\n        rate_v2 |= IWX_RATE_MCS_SGI_MSK;\n    \n    return rate_v2;\n}\n\nvoid ItlIwx::\niwx_rs_update(struct iwx_softc *sc, struct iwx_tlc_update_notif *notif)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct ieee80211_node *ni = ic->ic_bss;\n    struct ieee80211_rateset *rs = &ni->ni_rates;\n    uint32_t rate_n_flags;\n    int i;\n    char pretty_rate[100];\n    uint8_t notifver;\n    uint32_t format;\n\n    if (notif->sta_id != IWX_STATION_ID ||\n        (le32toh(notif->flags) & IWX_TLC_NOTIF_FLAG_RATE) == 0)\n        return;\n\n    rate_n_flags = le32toh(notif->rate);\n    notifver = iwx_lookup_notif_ver(sc, IWX_DATA_PATH_GROUP, IWX_TLC_MNG_UPDATE_NOTIF);\n    if (notifver < 3 || notifver == IWX_FW_CMD_VER_UNKNOWN) {\n        iwx_rs_pretty_print_rate_v1(pretty_rate, sizeof(pretty_rate),\n                                    rate_n_flags);\n        rate_n_flags = iwx_new_rate_from_v1(rate_n_flags);\n    } else {\n        iwx_rs_pretty_print_rate(pretty_rate, sizeof(pretty_rate),\n                                 rate_n_flags);\n    }\n    XYLog(\"%s new rate: %s\\n\", __FUNCTION__, pretty_rate);\n    format = rate_n_flags & IWX_RATE_MCS_MOD_TYPE_MSK;\n    if (format == IWX_RATE_MCS_VHT_MSK ||\n        format == IWX_RATE_MCS_HE_MSK ||\n        format == IWX_RATE_MCS_EHT_MSK) {\n        ni->ni_txmcs = rate_n_flags & IWX_RATE_MCS_CODE_MSK;\n    } else if (format == IWX_RATE_MCS_HT_MSK) {\n        ni->ni_txmcs = IWX_RATE_HT_MCS_INDEX(rate_n_flags);\n    } else {\n        uint8_t plcp = (rate_n_flags & IWX_RATE_LEGACY_RATE_MSK_V1);\n        uint8_t rval = 0;\n        for (i = IWX_RATE_1M_INDEX; i < nitems(iwx_rates); i++) {\n            if (iwx_rates[i].plcp == plcp) {\n                rval = iwx_rates[i].rate;\n                break;\n            }\n        }\n        if (rval) {\n            uint8_t rv;\n            for (i = 0; i < rs->rs_nrates; i++) {\n                rv = rs->rs_rates[i] & IEEE80211_RATE_VAL;\n                if (rv == rval) {\n                    ni->ni_txrate = i;\n                    break;\n                }\n            }\n        }\n    }\n}\n\nint ItlIwx::\niwx_phy_ctxt_update(struct iwx_softc *sc, struct iwx_phy_ctxt *phyctxt,\n                    struct ieee80211_channel *chan, uint8_t chains_static,\n                    uint8_t chains_dynamic, uint32_t apply_time)\n{\n    uint16_t band_flags = (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_5GHZ);\n    int err;\n    \n    if (isset(sc->sc_enabled_capa,\n              IWX_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT) &&\n        (phyctxt->channel->ic_flags & band_flags) !=\n        (chan->ic_flags & band_flags)) {\n        err = iwx_phy_ctxt_cmd(sc, phyctxt, chains_static,\n                               chains_dynamic, IWX_FW_CTXT_ACTION_REMOVE, apply_time);\n        if (err) {\n            printf(\"%s: could not remove PHY context \"\n                   \"(error %d)\\n\", DEVNAME(sc), err);\n            return err;\n        }\n        phyctxt->channel = chan;\n        err = iwx_phy_ctxt_cmd(sc, phyctxt, chains_static,\n                               chains_dynamic, IWX_FW_CTXT_ACTION_ADD, apply_time);\n        if (err) {\n            printf(\"%s: could not add PHY context \"\n                   \"(error %d)\\n\", DEVNAME(sc), err);\n            return err;\n        }\n    } else {\n        phyctxt->channel = chan;\n        err = iwx_phy_ctxt_cmd(sc, phyctxt, chains_static,\n                               chains_dynamic, IWX_FW_CTXT_ACTION_MODIFY, apply_time);\n        if (err) {\n            printf(\"%s: could not update PHY context (error %d)\\n\",\n                   DEVNAME(sc), err);\n            return err;\n        }\n    }\n    \n    return 0;\n}\n\nint ItlIwx::\niwx_auth(struct iwx_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct iwx_node *in = (struct iwx_node *)ic->ic_bss;\n    uint32_t duration;\n    int generation = sc->sc_generation, err = 0;\n    \n    splassert(IPL_NET);\n    \n    in->in_ni.ni_chw = IEEE80211_CHAN_WIDTH_20_NOHT;\n    in->in_ni.ni_flags &= ~(IEEE80211_NODE_HT |\n                            IEEE80211_NODE_QOS |\n                            IEEE80211_NODE_HT_SGI20 |\n                            IEEE80211_NODE_HT_SGI40 |\n                            IEEE80211_NODE_VHT |\n                            IEEE80211_NODE_VHT_SGI80 |\n                            IEEE80211_NODE_VHT_SGI160 |\n                            IEEE80211_NODE_HE);\n    if (ic->ic_opmode == IEEE80211_M_MONITOR) {\n        err = iwx_phy_ctxt_update(sc, &sc->sc_phyctxt[0],\n                                  ic->ic_ibss_chan, 1, 1, 0);\n        if (err)\n            return err;\n    } else {\n        err = iwx_phy_ctxt_update(sc, &sc->sc_phyctxt[0],\n                                  in->in_ni.ni_chan, 1, 1, 0);\n        if (err)\n            return err;\n    }\n    in->in_phyctxt = &sc->sc_phyctxt[0];\n    IEEE80211_ADDR_COPY(in->in_macaddr, in->in_ni.ni_macaddr);\n    \n    err = iwx_mac_ctxt_cmd(sc, in, IWX_FW_CTXT_ACTION_ADD, 0);\n    if (err) {\n        XYLog(\"%s: could not add MAC context (error %d)\\n\",\n              DEVNAME(sc), err);\n        return err;\n    }\n    sc->sc_flags |= IWX_FLAG_MAC_ACTIVE;\n    \n    err = iwx_binding_cmd(sc, in, IWX_FW_CTXT_ACTION_ADD);\n    if (err) {\n        XYLog(\"%s: could not add binding (error %d)\\n\",\n              DEVNAME(sc), err);\n        goto rm_mac_ctxt;\n    }\n    sc->sc_flags |= IWX_FLAG_BINDING_ACTIVE;\n    \n    err = iwx_add_sta_cmd(sc, in, 0);\n    if (err) {\n        XYLog(\"%s: could not add sta (error %d)\\n\",\n              DEVNAME(sc), err);\n        goto rm_binding;\n    }\n    \n    if (ic->ic_opmode == IEEE80211_M_MONITOR) {\n        err = iwx_enable_txq(sc, IWX_MONITOR_STA_ID,\n                             IWX_DQA_INJECT_MONITOR_QUEUE, IWX_MGMT_TID,\n                             sc->txq[IWX_DQA_INJECT_MONITOR_QUEUE].ring_count);\n        if (err)\n            goto rm_sta;\n        return 0;\n    }\n    \n    err = iwx_enable_mgmt_queue(sc);\n    if (err)\n        goto rm_sta;\n    \n    err = iwx_clear_statistics(sc);\n    if (err)\n        goto rm_sta;\n    \n    /*\n     * Prevent the FW from wandering off channel during association\n     * by \"protecting\" the session with a time event.\n     */\n    if (in->in_ni.ni_intval)\n        duration = in->in_ni.ni_intval * 2;\n    else\n        duration = IEEE80211_DUR_TU;\n    \n    /* Try really hard to protect the session and hear a beacon\n     * The new session protection command allows us to protect the\n     * session for a much longer time since the firmware will internally\n     * create two events: a 300TU one with a very high priority that\n     * won't be fragmented which should be enough for 99% of the cases,\n     * and another one (which we configure here to be 900TU long) which\n     * will have a slightly lower priority, but more importantly, can be\n     * fragmented so that it'll allow other activities to run.\n     */\n    if (isset(sc->sc_enabled_capa, IWX_UCODE_TLV_CAPA_SESSION_PROT_CMD))\n        err = iwx_schedule_protect_session(sc, in, duration);\n    else\n        iwx_protect_session(sc, in, duration, in->in_ni.ni_intval / 2);\n    \n    return err;\n    \nrm_sta:\n    if (generation == sc->sc_generation)\n        iwx_rm_sta_cmd(sc, in);\nrm_binding:\n    if (generation == sc->sc_generation) {\n        iwx_binding_cmd(sc, in, IWX_FW_CTXT_ACTION_REMOVE);\n        sc->sc_flags &= ~IWX_FLAG_BINDING_ACTIVE;\n    }\nrm_mac_ctxt:\n    if (generation == sc->sc_generation) {\n        iwx_mac_ctxt_cmd(sc, in, IWX_FW_CTXT_ACTION_REMOVE, 0);\n        sc->sc_flags &= ~IWX_FLAG_MAC_ACTIVE;\n    }\n    return err;\n}\n\nint ItlIwx::\niwx_deauth(struct iwx_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct iwx_node *in = (struct iwx_node *)ic->ic_bss;\n    int err;\n    \n    splassert(IPL_NET);\n    \n    if (!isset(sc->sc_enabled_capa, IWX_UCODE_TLV_CAPA_SESSION_PROT_CMD))\n        iwx_unprotect_session(sc, in);\n    else\n        iwx_cancel_session_protection(sc, in);\n    \n    if (sc->sc_flags & IWX_FLAG_STA_ACTIVE) {\n        err = iwx_rm_sta(sc, in);\n        if (err)\n            return err;\n    }\n    \n    if (sc->sc_flags & IWX_FLAG_BINDING_ACTIVE) {\n        err = iwx_binding_cmd(sc, in, IWX_FW_CTXT_ACTION_REMOVE);\n        if (err) {\n            XYLog(\"%s: could not remove binding (error %d)\\n\",\n                  DEVNAME(sc), err);\n            return err;\n        }\n        sc->sc_flags &= ~IWX_FLAG_BINDING_ACTIVE;\n    }\n    \n    if (sc->sc_flags & IWX_FLAG_MAC_ACTIVE) {\n        err = iwx_mac_ctxt_cmd(sc, in, IWX_FW_CTXT_ACTION_REMOVE, 0);\n        if (err) {\n            XYLog(\"%s: could not remove MAC context (error %d)\\n\",\n                  DEVNAME(sc), err);\n            return err;\n        }\n        sc->sc_flags &= ~IWX_FLAG_MAC_ACTIVE;\n    }\n    \n    in->in_ni.ni_chw = IEEE80211_CHAN_WIDTH_20_NOHT;\n    in->in_ni.ni_flags &= ~(IEEE80211_NODE_HT |\n                            IEEE80211_NODE_QOS |\n                            IEEE80211_NODE_HT_SGI20 |\n                            IEEE80211_NODE_HT_SGI40 |\n                            IEEE80211_NODE_VHT |\n                            IEEE80211_NODE_VHT_SGI80 |\n                            IEEE80211_NODE_VHT_SGI160 |\n                            IEEE80211_NODE_HE);\n    /* Move unused PHY context to a default channel. */\n    err = iwx_phy_ctxt_update(sc, &sc->sc_phyctxt[0],\n                              &ic->ic_channels[1], 1, 1, 0);\n    if (err)\n        return err;\n    \n    return 0;\n}\n\nint ItlIwx::\niwx_run(struct iwx_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct iwx_node *in = (struct iwx_node *)ic->ic_bss;\n    int err;\n    int chains = iwx_mimo_enabled(sc) ? 2 : 1;\n    \n    splassert(IPL_NET);\n    \n    if (ic->ic_opmode == IEEE80211_M_MONITOR) {\n        /* Add a MAC context and a sniffing STA. */\n        err = iwx_auth(sc);\n        if (err)\n            return err;\n    }\n    \n    if (in->in_ni.ni_chw == IEEE80211_CHAN_WIDTH_80P80) {\n        /* Fallback to 20mhz VHT */\n        in->in_ni.ni_chw = IEEE80211_CHAN_WIDTH_20;\n    }\n    \n    /* Configure Rx chains for MIMO. */\n    if ((ic->ic_opmode == IEEE80211_M_MONITOR ||\n         (in->in_ni.ni_flags & IEEE80211_NODE_HT) ||\n         (in->in_ni.ni_flags & IEEE80211_NODE_VHT) ||\n         (in->in_ni.ni_flags & IEEE80211_NODE_HE))) {\n        err = iwx_phy_ctxt_update(sc, &sc->sc_phyctxt[0],\n                                  in->in_ni.ni_chan, chains, chains, 0);\n        if (err) {\n            XYLog(\"%s: failed to update PHY\\n\",\n                  DEVNAME(sc));\n            return err;\n        }\n    }\n    \n    /* We have now been assigned an associd by the AP. */\n    err = iwx_mac_ctxt_cmd(sc, in, IWX_FW_CTXT_ACTION_MODIFY, 1);\n    if (err) {\n        XYLog(\"%s: failed to update MAC\\n\", DEVNAME(sc));\n        return err;\n    }\n    \n    err = iwx_sf_config(sc, IWX_SF_FULL_ON);\n    if (err) {\n        XYLog(\"%s: could not set sf full on (error %d)\\n\",\n              DEVNAME(sc), err);\n        return err;\n    }\n    \n    err = iwx_allow_mcast(sc);\n    if (err) {\n        XYLog(\"%s: could not allow mcast (error %d)\\n\",\n              DEVNAME(sc), err);\n        return err;\n    }\n    \n    err = iwx_power_update_device(sc);\n    if (err) {\n        XYLog(\"%s: could not send power command (error %d)\\n\",\n              DEVNAME(sc), err);\n        return err;\n    }\n#ifdef notyet\n    /*\n     * Disabled for now. Default beacon filter settings\n     * prevent net80211 from getting ERP and HT protection\n     * updates from beacons.\n     */\n    err = iwx_enable_beacon_filter(sc, in);\n    if (err) {\n        XYLog(\"%s: could not enable beacon filter\\n\",\n              DEVNAME(sc));\n        return err;\n    }\n#endif\n    err = iwx_power_mac_update_mode(sc, in);\n    if (err) {\n        XYLog(\"%s: could not update MAC power (error %d)\\n\",\n              DEVNAME(sc), err);\n        return err;\n    }\n    \n    if (!isset(sc->sc_enabled_capa, IWX_UCODE_TLV_CAPA_DYNAMIC_QUOTA)) {\n        err = iwx_update_quotas(sc, in, 1);\n        if (err) {\n            XYLog(\"%s: could not update quotas (error %d)\\n\",\n                  DEVNAME(sc), err);\n            return err;\n        }\n    }\n    \n    if (ic->ic_opmode == IEEE80211_M_MONITOR)\n        return 0;\n    \n    /* Start at lowest available bit-rate. Firmware will raise. */\n    in->in_ni.ni_txrate = 0;\n    in->in_ni.ni_txmcs = 0;\n\n    err = iwx_add_sta_cmd(sc, in, 1);\n    if (err) {\n        XYLog(\"%s: could not update sta (error %d)\\n\",\n              DEVNAME(sc), err);\n        return err;\n    }\n    \n    err = iwx_rs_init(sc, in, true);\n    if (err) {\n        XYLog(\"%s: could not update rate scaling (error %d)\\n\",\n              DEVNAME(sc), err);\n        return err;\n    }\n    return 0;\n}\n\nint ItlIwx::\niwx_run_stop(struct iwx_softc *sc)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct iwx_node *in = (struct iwx_node *)ic->ic_bss;\n    int err, i;\n    \n    splassert(IPL_NET);\n    \n    err = iwx_flush_sta(sc, in);\n    if (err) {\n        XYLog(\"%s: could not flush Tx path (error %d)\\n\",\n              __FUNCTION__, err);\n        return err;\n    }\n    \n    /*\n     * Stop Rx BA sessions now. We cannot rely on the BA task\n     * for this when moving out of RUN state since it runs in a\n     * separate thread.\n     * Note that in->in_ni (struct ieee80211_node) already represents\n     * our new access point in case we are roaming between APs.\n     * This means we cannot rely on struct ieee802111_node to tell\n     * us which BA sessions exist.\n     */\n    for (i = 0; i < nitems(sc->sc_rxba_data); i++) {\n        struct iwx_rxba_data *rxba = &sc->sc_rxba_data[i];\n        if (rxba->baid == IWX_RX_REORDER_DATA_INVALID_BAID)\n            continue;\n        iwx_sta_rx_agg(sc, ic->ic_bss, rxba->tid, 0, 0, 0, 0);\n    }\n    \n    err = iwx_sf_config(sc, IWX_SF_INIT_OFF);\n    if (err)\n        return err;\n    \n    err = iwx_disable_beacon_filter(sc);\n    if (err) {\n        XYLog(\"%s: could not disable beacon filter (error %d)\\n\",\n              DEVNAME(sc), err);\n        return err;\n    }\n    \n    if (!isset(sc->sc_enabled_capa, IWX_UCODE_TLV_CAPA_DYNAMIC_QUOTA)) {\n        err = iwx_update_quotas(sc, in, 0);\n        if (err) {\n            XYLog(\"%s: could not update quotas (error %d)\\n\",\n                  DEVNAME(sc), err);\n            return err;\n        }\n    }\n    \n    err = iwx_mac_ctxt_cmd(sc, in, IWX_FW_CTXT_ACTION_MODIFY, 0);\n    if (err) {\n        XYLog(\"%s: failed to update MAC\\n\", DEVNAME(sc));\n        return err;\n    }\n    \n    /* Reset Tx chains in case MIMO was enabled. */\n    if ((in->in_ni.ni_flags & IEEE80211_NODE_HT) &&\n        iwx_mimo_enabled(sc)) {\n        err = iwx_phy_ctxt_update(sc, &sc->sc_phyctxt[0],\n                                  in->in_ni.ni_chan, 1, 1, 0);\n        if (err) {\n            XYLog(\"%s: failed to update PHY\\n\", DEVNAME(sc));\n            return err;\n        }\n    }\n    \n    return 0;\n}\n\nstruct ieee80211_node *ItlIwx::\niwx_node_alloc(struct ieee80211com *ic)\n{\n    return (struct ieee80211_node *)malloc(sizeof (struct iwx_node), 0, M_NOWAIT | M_ZERO);\n}\n\nint ItlIwx::\niwx_set_key(struct ieee80211com *ic, struct ieee80211_node *ni,\n            struct ieee80211_key *k)\n{\n    struct iwx_softc *sc = (struct iwx_softc *)ic->ic_softc;\n    struct iwx_add_sta_key_cmd cmd;\n    ItlIwx *that = container_of(sc, ItlIwx, com);\n    \n    if (k->k_cipher != IEEE80211_CIPHER_CCMP) {\n        /* Fallback to software crypto for other ciphers. */\n        return (ieee80211_set_key(ic, ni, k));\n    }\n    \n    memset(&cmd, 0, sizeof(cmd));\n    \n    cmd.common.key_flags = htole16(IWX_STA_KEY_FLG_CCM |\n                                   IWX_STA_KEY_FLG_WEP_KEY_MAP |\n                                   ((k->k_id << IWX_STA_KEY_FLG_KEYID_POS) &\n                                    IWX_STA_KEY_FLG_KEYID_MSK));\n    if (k->k_flags & IEEE80211_KEY_GROUP) {\n        cmd.common.key_offset = 1;\n        cmd.common.key_flags |= htole16(IWX_STA_KEY_MULTICAST);\n    } else\n        cmd.common.key_offset = 0;\n    \n    memcpy(cmd.common.key, k->k_key, MIN(sizeof(cmd.common.key), k->k_len));\n    cmd.common.sta_id = IWX_STATION_ID;\n    \n    cmd.transmit_seq_cnt = htole64(k->k_tsc);\n    \n    return that->iwx_send_cmd_pdu(sc, IWX_ADD_STA_KEY, IWX_CMD_ASYNC,\n                            sizeof(cmd), &cmd);\n}\n\nvoid ItlIwx::\niwx_delete_key(struct ieee80211com *ic, struct ieee80211_node *ni,\n               struct ieee80211_key *k)\n{\n    struct iwx_softc *sc = (struct iwx_softc *)ic->ic_softc;\n    struct iwx_add_sta_key_cmd cmd;\n    ItlIwx *that = container_of(sc, ItlIwx, com);\n    \n    if (k->k_cipher != IEEE80211_CIPHER_CCMP) {\n        /* Fallback to software crypto for other ciphers. */\n        ieee80211_delete_key(ic, ni, k);\n        return;\n    }\n    \n    memset(&cmd, 0, sizeof(cmd));\n    \n    cmd.common.key_flags = htole16(IWX_STA_KEY_NOT_VALID |\n                                   IWX_STA_KEY_FLG_NO_ENC | IWX_STA_KEY_FLG_WEP_KEY_MAP |\n                                   ((k->k_id << IWX_STA_KEY_FLG_KEYID_POS) &\n                                    IWX_STA_KEY_FLG_KEYID_MSK));\n    memcpy(cmd.common.key, k->k_key, MIN(sizeof(cmd.common.key), k->k_len));\n    if (k->k_flags & IEEE80211_KEY_GROUP)\n        cmd.common.key_offset = 1;\n    else\n        cmd.common.key_offset = 0;\n    cmd.common.sta_id = IWX_STATION_ID;\n    \n    that->iwx_send_cmd_pdu(sc, IWX_ADD_STA_KEY, IWX_CMD_ASYNC, sizeof(cmd), &cmd);\n}\n\nint ItlIwx::\niwx_media_change(struct _ifnet *ifp)\n{\n    struct iwx_softc *sc = (struct iwx_softc *)ifp->if_softc;\n    struct ieee80211com *ic = &sc->sc_ic;\n    uint8_t rate, ridx;\n    int err;\n    \n    err = ieee80211_media_change(ifp);\n    if (err != ENETRESET)\n        return err;\n    \n    if (ic->ic_fixed_mcs != -1)\n        sc->sc_fixed_ridx = iwx_mcs2ridx[ic->ic_fixed_mcs];\n    else if (ic->ic_fixed_rate != -1) {\n        rate = ic->ic_sup_rates[ic->ic_curmode].\n        rs_rates[ic->ic_fixed_rate] & IEEE80211_RATE_VAL;\n        /* Map 802.11 rate to HW rate index. */\n        for (ridx = 0; ridx <= IWX_RIDX_MAX; ridx++)\n            if (iwx_rates[ridx].rate == rate)\n                break;\n        sc->sc_fixed_ridx = ridx;\n    }\n    \n    if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==\n        (IFF_UP | IFF_RUNNING)) {\n        iwx_stop(ifp);\n        err = iwx_init(ifp);\n    }\n    return err;\n}\n\nvoid ItlIwx::\niwx_newstate_task(void *psc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwx_softc *sc = (struct iwx_softc *)psc;\n    struct ieee80211com *ic = &sc->sc_ic;\n    enum ieee80211_state nstate = sc->ns_nstate;\n    enum ieee80211_state ostate = ic->ic_state;\n    int arg = sc->ns_arg;\n    int err = 0, s = splnet();\n    ItlIwx *that = container_of(sc, ItlIwx, com);\n    \n    XYLog(\"%s sc->sc_flags & IWX_FLAG_SHUTDOWN %s\\n\", __FUNCTION__, sc->sc_flags & IWX_FLAG_SHUTDOWN ? \"true\" : \"false\");\n    if (sc->sc_flags & IWX_FLAG_SHUTDOWN) {\n        /* iwx_stop() is waiting for us. */\n        //        refcnt_rele_wake(&sc->task_refs);\n        splx(s);\n        return;\n    }\n    \n    if (ostate == IEEE80211_S_SCAN) {\n        if (nstate == ostate) {\n            if (sc->sc_flags & IWX_FLAG_SCANNING) {\n                //                refcnt_rele_wake(&sc->task_refs);\n                splx(s);\n                return;\n            }\n            /* Firmware is no longer scanning. Do another scan. */\n            goto next_scan;\n        }\n    }\n    \n    if (nstate <= ostate) {\n        switch (ostate) {\n            case IEEE80211_S_RUN:\n                err = that->iwx_run_stop(sc);\n                if (err)\n                    goto out;\n                /* FALLTHROUGH */\n            case IEEE80211_S_ASSOC:\n            case IEEE80211_S_AUTH:\n                if (nstate <= IEEE80211_S_AUTH) {\n                    err = that->iwx_deauth(sc);\n                    if (err)\n                        goto out;\n                }\n                /* FALLTHROUGH */\n            case IEEE80211_S_SCAN:\n            case IEEE80211_S_INIT:\n                break;\n        }\n        \n        /* Die now if iwx_stop() was called while we were sleeping. */\n        if (sc->sc_flags & IWX_FLAG_SHUTDOWN) {\n            //            refcnt_rele_wake(&sc->task_refs);\n            splx(s);\n            return;\n        }\n    }\n    \n    switch (nstate) {\n        case IEEE80211_S_INIT:\n            break;\n            \n        case IEEE80211_S_SCAN:\n        next_scan:\n            err = that->iwx_scan(sc);\n            if (err)\n                break;\n            //        refcnt_rele_wake(&sc->task_refs);\n            splx(s);\n            return;\n            \n        case IEEE80211_S_AUTH:\n            err = that->iwx_auth(sc);\n            break;\n            \n        case IEEE80211_S_ASSOC:\n            err = that->iwx_rs_init(sc, (iwx_node *)ic->ic_bss, false);\n            if (err) {\n                XYLog(\"%s: could not init rate scaling (error %d)\\n\",\n                      DEVNAME(sc), err);\n                goto out;\n            }\n            break;\n            \n        case IEEE80211_S_RUN:\n            err = that->iwx_run(sc);\n            break;\n    }\n    \nout:\n    if ((sc->sc_flags & IWX_FLAG_SHUTDOWN) == 0) {\n        if (err)\n            task_add(systq, &sc->init_task);\n        else\n            sc->sc_newstate(ic, nstate, arg);\n    }\n    //    refcnt_rele_wake(&sc->task_refs);\n    splx(s);\n}\n\nint ItlIwx::\niwx_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)\n{\n    struct _ifnet *ifp = IC2IFP(ic);\n    struct iwx_softc *sc = (struct iwx_softc *)ifp->if_softc;\n    ItlIwx *that = container_of(sc, ItlIwx, com);\n    struct ieee80211_node *ni = ic->ic_bss;\n    \n    /*\n     * Prevent attemps to transition towards the same state, unless\n     * we are scanning in which case a SCAN -> SCAN transition\n     * triggers another scan iteration. And AUTH -> AUTH is needed\n     * to support band-steering.\n     */\n    if (sc->ns_nstate == nstate && nstate != IEEE80211_S_SCAN &&\n        nstate != IEEE80211_S_AUTH)\n    \n    if (ic->ic_state == IEEE80211_S_RUN) {\n        if (nstate == IEEE80211_S_SCAN) {\n            /*\n             * During RUN->SCAN we don't call sc_newstate() so\n             * we must stop A-MPDU Tx ourselves in this case.\n             */\n            ieee80211_stop_ampdu_tx(ic, ni, -1);\n            ieee80211_ba_del(ni);\n        }\n        that->iwx_del_task(sc, systq, &sc->ba_task);\n        that->iwx_del_task(sc, systq, &sc->mac_ctxt_task);\n        that->iwx_del_task(sc, systq, &sc->chan_ctxt_task);\n    }\n    \n    sc->ns_nstate = nstate;\n    sc->ns_arg = arg;\n    \n    that->iwx_add_task(sc, sc->sc_nswq, &sc->newstate_task);\n    \n    return 0;\n}\n\nvoid ItlIwx::\niwx_endscan(struct iwx_softc *sc)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    \n    struct ieee80211_node *ni, *nextbs;\n    \n//    ni = RB_MIN(ieee80211_tree, &ic->ic_tree);\n//    for (; ni != NULL; ni = nextbs) {\n//        nextbs = RB_NEXT(ieee80211_tree, &ic->ic_tree, ni);\n//        XYLog(\"%s scan_result ssid=%s, bssid=%s, ni_rsnciphers=%d, ni_rsncipher=%d, ni_rsngroupmgmtcipher=%d, ni_rsngroupcipher=%d, ni_rssi=%d,  ni_capinfo=%d, ni_intval=%d, ni_rsnakms=%d, ni_supported_rsnakms=%d, ni_rsnprotos=%d, ni_supported_rsnprotos=%d, ni_rstamp=%d\\n\", __FUNCTION__, ni->ni_essid, ether_sprintf(ni->ni_bssid), ni->ni_rsnciphers, ni->ni_rsncipher, ni->ni_rsngroupmgmtcipher, ni->ni_rsngroupcipher, ni->ni_rssi, ni->ni_capinfo, ni->ni_intval, ni->ni_rsnakms, ni->ni_supported_rsnakms, ni->ni_rsnprotos, ni->ni_supported_rsnprotos, ni->ni_rstamp);\n//    }\n    \n    if ((sc->sc_flags & (IWX_FLAG_SCANNING | IWX_FLAG_BGSCAN)) == 0)\n        return;\n    \n    sc->sc_flags &= ~(IWX_FLAG_SCANNING | IWX_FLAG_BGSCAN);\n    ieee80211_end_scan(&ic->ic_if);\n}\n\n/*\n * Aging and idle timeouts for the different possible scenarios\n * in default configuration\n */\nstatic const uint32_t\niwx_sf_full_timeout_def[IWX_SF_NUM_SCENARIO][IWX_SF_NUM_TIMEOUT_TYPES] = {\n    {\n        htole32(IWX_SF_SINGLE_UNICAST_AGING_TIMER_DEF),\n        htole32(IWX_SF_SINGLE_UNICAST_IDLE_TIMER_DEF)\n    },\n    {\n        htole32(IWX_SF_AGG_UNICAST_AGING_TIMER_DEF),\n        htole32(IWX_SF_AGG_UNICAST_IDLE_TIMER_DEF)\n    },\n    {\n        htole32(IWX_SF_MCAST_AGING_TIMER_DEF),\n        htole32(IWX_SF_MCAST_IDLE_TIMER_DEF)\n    },\n    {\n        htole32(IWX_SF_BA_AGING_TIMER_DEF),\n        htole32(IWX_SF_BA_IDLE_TIMER_DEF)\n    },\n    {\n        htole32(IWX_SF_TX_RE_AGING_TIMER_DEF),\n        htole32(IWX_SF_TX_RE_IDLE_TIMER_DEF)\n    },\n};\n\n/*\n * Aging and idle timeouts for the different possible scenarios\n * in single BSS MAC configuration.\n */\nstatic const uint32_t\niwx_sf_full_timeout[IWX_SF_NUM_SCENARIO][IWX_SF_NUM_TIMEOUT_TYPES] = {\n    {\n        htole32(IWX_SF_SINGLE_UNICAST_AGING_TIMER),\n        htole32(IWX_SF_SINGLE_UNICAST_IDLE_TIMER)\n    },\n    {\n        htole32(IWX_SF_AGG_UNICAST_AGING_TIMER),\n        htole32(IWX_SF_AGG_UNICAST_IDLE_TIMER)\n    },\n    {\n        htole32(IWX_SF_MCAST_AGING_TIMER),\n        htole32(IWX_SF_MCAST_IDLE_TIMER)\n    },\n    {\n        htole32(IWX_SF_BA_AGING_TIMER),\n        htole32(IWX_SF_BA_IDLE_TIMER)\n    },\n    {\n        htole32(IWX_SF_TX_RE_AGING_TIMER),\n        htole32(IWX_SF_TX_RE_IDLE_TIMER)\n    },\n};\n\nvoid ItlIwx::\niwx_fill_sf_command(struct iwx_softc *sc, struct iwx_sf_cfg_cmd *sf_cmd,\n                    struct ieee80211_node *ni)\n{\n    int i, j, watermark;\n    \n    sf_cmd->watermark[IWX_SF_LONG_DELAY_ON] = htole32(IWX_SF_W_MARK_SCAN);\n    \n    /*\n     * If we are in association flow - check antenna configuration\n     * capabilities of the AP station, and choose the watermark accordingly.\n     */\n    if (ni) {\n        if (ni->ni_flags & IEEE80211_NODE_HT || ni->ni_flags & IEEE80211_NODE_VHT || ni->ni_flags & IEEE80211_NODE_HE) {\n            if (ni->ni_rxmcs[1] != 0)\n                watermark = IWX_SF_W_MARK_MIMO2;\n            else\n                watermark = IWX_SF_W_MARK_SISO;\n        } else {\n            watermark = IWX_SF_W_MARK_LEGACY;\n        }\n        /* default watermark value for unassociated mode. */\n    } else {\n        watermark = IWX_SF_W_MARK_MIMO2;\n    }\n    sf_cmd->watermark[IWX_SF_FULL_ON] = htole32(watermark);\n    \n    for (i = 0; i < IWX_SF_NUM_SCENARIO; i++) {\n        for (j = 0; j < IWX_SF_NUM_TIMEOUT_TYPES; j++) {\n            sf_cmd->long_delay_timeouts[i][j] =\n            htole32(IWX_SF_LONG_DELAY_AGING_TIMER);\n        }\n    }\n    \n    if (ni) {\n        memcpy(sf_cmd->full_on_timeouts, iwx_sf_full_timeout,\n               sizeof(iwx_sf_full_timeout));\n    } else {\n        memcpy(sf_cmd->full_on_timeouts, iwx_sf_full_timeout_def,\n               sizeof(iwx_sf_full_timeout_def));\n    }\n    \n}\n\nint ItlIwx::\niwx_sf_config(struct iwx_softc *sc, int new_state)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct iwx_sf_cfg_cmd sf_cmd = {\n        .state = htole32(new_state),\n    };\n    int err = 0;\n    \n    switch (new_state) {\n        case IWX_SF_UNINIT:\n        case IWX_SF_INIT_OFF:\n            iwx_fill_sf_command(sc, &sf_cmd, NULL);\n            break;\n        case IWX_SF_FULL_ON:\n            iwx_fill_sf_command(sc, &sf_cmd, ic->ic_bss);\n            break;\n        default:\n            return EINVAL;\n    }\n    \n    err = iwx_send_cmd_pdu(sc, IWX_REPLY_SF_CFG_CMD, IWX_CMD_ASYNC,\n                           sizeof(sf_cmd), &sf_cmd);\n    return err;\n}\n\nint ItlIwx::\niwx_send_bt_init_conf(struct iwx_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwx_bt_coex_cmd bt_cmd;\n    \n    bt_cmd.mode = htole32(IWX_BT_COEX_WIFI);\n    bt_cmd.enabled_modules = 0;\n    \n    return iwx_send_cmd_pdu(sc, IWX_BT_CONFIG, 0, sizeof(bt_cmd),\n                            &bt_cmd);\n}\n\nint ItlIwx::\niwx_send_soc_conf(struct iwx_softc *sc)\n{\n   struct iwx_soc_configuration_cmd cmd;\n   int err;\n   uint32_t cmd_id, flags = 0;\n\n   memset(&cmd, 0, sizeof(cmd));\n\n   /*\n    * In VER_1 of this command, the discrete value is considered\n    * an integer; In VER_2, it's a bitmask.  Since we have only 2\n    * values in VER_1, this is backwards-compatible with VER_2,\n    * as long as we don't set any other flag bits.\n    */\n   if (!sc->sc_integrated) { /* VER_1 */\n       flags = IWX_SOC_CONFIG_CMD_FLAGS_DISCRETE;\n   } else { /* VER_2 */\n       uint8_t scan_cmd_ver;\n       if (sc->sc_ltr_delay != IWX_SOC_FLAGS_LTR_APPLY_DELAY_NONE)\n           flags |= (sc->sc_ltr_delay &\n               IWX_SOC_FLAGS_LTR_APPLY_DELAY_MASK);\n       scan_cmd_ver = iwx_lookup_cmd_ver(sc, IWX_LONG_GROUP,\n           IWX_SCAN_REQ_UMAC);\n       if (scan_cmd_ver != IWX_FW_CMD_VER_UNKNOWN &&\n           scan_cmd_ver >= 2 && sc->sc_low_latency_xtal)\n           flags |= IWX_SOC_CONFIG_CMD_FLAGS_LOW_LATENCY;\n   }\n   cmd.flags = htole32(flags);\n\n   cmd.latency = htole32(sc->sc_xtal_latency);\n\n   cmd_id = iwx_cmd_id(IWX_SOC_CONFIGURATION_CMD, IWX_SYSTEM_GROUP, 0);\n   err = iwx_send_cmd_pdu(sc, cmd_id, 0, sizeof(cmd), &cmd);\n   if (err)\n       XYLog(\"%s: failed to set soc latency: %d\\n\", DEVNAME(sc), err);\n   return err;\n}\n\nint ItlIwx::\niwx_send_update_mcc_cmd(struct iwx_softc *sc, const char *alpha2)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwx_mcc_update_cmd mcc_cmd;\n    struct iwx_host_cmd hcmd = {\n        .id = IWX_MCC_UPDATE_CMD,\n        .flags = IWX_CMD_WANT_RESP,\n        .data = { &mcc_cmd },\n    };\n    struct iwx_rx_packet *pkt;\n    struct iwx_mcc_update_resp *resp;\n    size_t resp_len;\n    int err;\n    \n    memset(&mcc_cmd, 0, sizeof(mcc_cmd));\n    mcc_cmd.mcc = htole16(alpha2[0] << 8 | alpha2[1]);\n    if (isset(sc->sc_ucode_api, IWX_UCODE_TLV_API_WIFI_MCC_UPDATE) ||\n        isset(sc->sc_enabled_capa, IWX_UCODE_TLV_CAPA_LAR_MULTI_MCC))\n        mcc_cmd.source_id = IWX_MCC_SOURCE_GET_CURRENT;\n    else\n        mcc_cmd.source_id = IWX_MCC_SOURCE_OLD_FW;\n    \n    hcmd.len[0] = sizeof(struct iwx_mcc_update_cmd);\n    hcmd.resp_pkt_len = IWX_CMD_RESP_MAX;\n    \n    err = iwx_send_cmd(sc, &hcmd);\n    if (err)\n        return err;\n    \n    pkt = hcmd.resp_pkt;\n    if (!pkt || (pkt->hdr.group_id & IWX_CMD_FAILED_MSK)) {\n        err = EIO;\n        goto out;\n    }\n    \n    resp_len = iwx_rx_packet_payload_len(pkt);\n    if (resp_len < sizeof(*resp)) {\n        err = EIO;\n        goto out;\n    }\n    \n    resp = (struct iwx_mcc_update_resp *)pkt->data;\n    if (resp_len != sizeof(*resp) +\n        resp->n_channels * sizeof(resp->channels[0])) {\n        err = EIO;\n        goto out;\n    }\n\n    DPRINTF((\"MCC status=0x%x mcc=0x%x cap=0x%x time=0x%x geo_info=0x%x source_id=0x%d n_channels=%u\\n\",\n             resp->status, resp->mcc, resp->cap, resp->time, resp->geo_info, resp->source_id, resp->n_channels));\n\n    /* Update channel map for net80211 and our scan configuration. */\n    iwx_init_channel_map(sc, NULL, resp->channels, resp->n_channels);\n    \nout:\n    iwx_free_resp(sc, &hcmd);\n    \n    return err;\n}\n\nint ItlIwx::\niwx_send_temp_report_ths_cmd(struct iwx_softc *sc)\n{\n    struct iwx_temp_report_ths_cmd cmd;\n    int err;\n    \n    /*\n     * In order to give responsibility for critical-temperature-kill\n     * and TX backoff to FW we need to send an empty temperature\n     * reporting command at init time.\n     */\n    memset(&cmd, 0, sizeof(cmd));\n    \n    err = iwx_send_cmd_pdu(sc,\n                           IWX_WIDE_ID(IWX_PHY_OPS_GROUP, IWX_TEMP_REPORTING_THRESHOLDS_CMD),\n                           0, sizeof(cmd), &cmd);\n    if (err)\n        XYLog(\"%s: TEMP_REPORT_THS_CMD command failed (error %d)\\n\",\n               DEVNAME(sc), err);\n    \n    return err;\n}\n\n#define TX_FIFO_MAX_NUM            15\n#define RX_FIFO_MAX_NUM            2\n#define TX_FIFO_INTERNAL_MAX_NUM    6\n\nint ItlIwx::\niwx_init_hw(struct iwx_softc *sc)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct ieee80211com *ic = &sc->sc_ic;\n    int err, i;\n    \n    err = iwx_preinit(sc);\n    if (err)\n        return err;\n    \n    err = iwx_start_hw(sc);\n    if (err) {\n        XYLog(\"%s: could not initialize hardware\\n\", DEVNAME(sc));\n        return err;\n    }\n    \n    err = iwx_run_init_mvm_ucode(sc, 0);\n    if (err)\n        return err;\n    \n    if (!iwx_nic_lock(sc))\n        return EBUSY;\n    \n    err = iwx_send_tx_ant_cfg(sc, iwx_fw_valid_tx_ant(sc));\n    if (err) {\n        XYLog(\"%s: could not init tx ant config (error %d)\\n\",\n               DEVNAME(sc), err);\n        goto err;\n    }\n    \n    iwx_toggle_tx_ant(sc, &sc->sc_mgmt_last_antenna_idx);\n    \n    if (sc->sc_tx_with_siso_diversity) {\n        err = iwx_send_phy_cfg_cmd(sc);\n        if (err) {\n            XYLog(\"%s: could not send phy config (error %d)\\n\",\n                   DEVNAME(sc), err);\n            goto err;\n        }\n    }\n    \n    err = iwx_send_bt_init_conf(sc);\n    if (err) {\n        XYLog(\"%s: could not init bt coex (error %d)\\n\",\n               DEVNAME(sc), err);\n        return err;\n    }\n    \n    err = iwx_send_soc_conf(sc);\n    if (err)\n        return err;\n    \n    if (isset(sc->sc_enabled_capa, IWX_UCODE_TLV_CAPA_DQA_SUPPORT)){\n        err = iwx_send_dqa_cmd(sc);\n        if (err)\n            return err;\n    }\n    \n    /* Add auxiliary station for scanning */\n    err = iwx_add_aux_sta(sc);\n    if (err) {\n        XYLog(\"%s: could not add aux station (error %d)\\n\",\n              DEVNAME(sc), err);\n        goto err;\n    }\n    \n    for (i = 0; i < IWX_NUM_PHY_CTX; i++) {\n        /*\n         * The channel used here isn't relevant as it's\n         * going to be overwritten in the other flows.\n         * For now use the first channel we have.\n         */\n        sc->sc_phyctxt[i].id = i;\n        sc->sc_phyctxt[i].channel = &ic->ic_channels[1];\n        err = iwx_phy_ctxt_cmd(sc, &sc->sc_phyctxt[i], 1, 1,\n                               IWX_FW_CTXT_ACTION_ADD, 0);\n        if (err) {\n            XYLog(\"%s: could not add phy context %d (error %d)\\n\",\n                   DEVNAME(sc), i, err);\n            goto err;\n        }\n    }\n    \n    if (!isset(sc->sc_enabled_capa, IWX_UCODE_TLV_CAPA_SET_LTR_GEN2)) {\n        err = iwx_config_ltr(sc);\n        if (err) {\n            XYLog(\"%s: PCIe LTR configuration failed (error %d)\\n\",\n                  DEVNAME(sc), err);\n        }\n    }\n    \n    if (isset(sc->sc_enabled_capa, IWX_UCODE_TLV_CAPA_CT_KILL_BY_FW)) {\n        err = iwx_send_temp_report_ths_cmd(sc);\n        if (err)\n            goto err;\n    }\n    \n    err = iwx_power_update_device(sc);\n    if (err) {\n        XYLog(\"%s: could not send power command (error %d)\\n\",\n               DEVNAME(sc), err);\n        goto err;\n    }\n    \n    if (sc->sc_nvm.lar_enabled) {\n        err = iwx_send_update_mcc_cmd(sc, \"ZZ\");\n        if (err) {\n            XYLog(\"%s: could not init LAR (error %d)\\n\",\n                   DEVNAME(sc), err);\n            goto err;\n        }\n    }\n    \n    err = iwx_config_umac_scan(sc);\n    if (err) {\n        XYLog(\"%s: could not configure scan (error %d)\\n\",\n               DEVNAME(sc), err);\n        goto err;\n    }\n    \n    err = iwx_disable_beacon_filter(sc);\n    if (err) {\n        XYLog(\"%s: could not disable beacon filter (error %d)\\n\",\n               DEVNAME(sc), err);\n        goto err;\n    }\n    \nerr:\n    iwx_nic_unlock(sc);\n    return err;\n}\n\n/* Allow multicast from our BSSID. */\nint ItlIwx::\niwx_allow_mcast(struct iwx_softc *sc)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct iwx_node *in = (struct iwx_node *)ic->ic_bss;\n    struct iwx_mcast_filter_cmd *cmd;\n    size_t size;\n    int err;\n    \n    size = roundup(sizeof(*cmd), 4);\n    cmd = (struct iwx_mcast_filter_cmd *)malloc(size, 0, M_NOWAIT | M_ZERO);\n    if (cmd == NULL)\n        return ENOMEM;\n    cmd->filter_own = 1;\n    cmd->port_id = 0;\n    cmd->count = 0;\n    cmd->pass_all = 1;\n    IEEE80211_ADDR_COPY(cmd->bssid, in->in_macaddr);\n    \n    err = iwx_send_cmd_pdu(sc, IWX_MCAST_FILTER_CMD,\n                           0, size, cmd);\n    ::free(cmd);\n    return err;\n}\n\nint ItlIwx::\niwx_init(struct _ifnet *ifp)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwx_softc *sc = (struct iwx_softc *)ifp->if_softc;\n    struct ieee80211com *ic = &sc->sc_ic;\n    int err, generation;\n    int i;\n\n    memset(sc->sc_tid_data, 0, sizeof(sc->sc_tid_data));\n    for (i = 0; i < ARRAY_SIZE(sc->sc_tid_data); i++) {\n        sc->sc_tid_data[i].qid = IWX_INVALID_QUEUE;\n    }\n    \n    //    rw_assert_wrlock(&sc->ioctl_rwl);\n    \n    generation = ++sc->sc_generation;\n    \n    //    KASSERT(sc->task_refs.refs == 0);\n    //    refcnt_init(&sc->task_refs);\n    \n    err = iwx_init_hw(sc);\n    if (err) {\n        if (generation == sc->sc_generation)\n            iwx_stop_device(sc);\n        return err;\n    }\n    \n    if (sc->sc_nvm.sku_cap_11n_enable)\n        iwx_setup_ht_rates(sc);\n    \n    if (sc->sc_nvm.sku_cap_11ac_enable)\n        iwx_setup_vht_rates(sc);\n    \n    if (sc->sc_nvm.sku_cap_11ax_enable)\n        iwx_setup_he_rates(sc);\n    \n    ifq_clr_oactive(&ifp->if_snd);\n    ifq_flush(&ifp->if_snd);\n    ifp->if_flags |= IFF_RUNNING;\n    \n    if (ic->ic_opmode == IEEE80211_M_MONITOR) {\n        ic->ic_bss->ni_chan = ic->ic_ibss_chan;\n        ieee80211_new_state(ic, IEEE80211_S_RUN, -1);\n        return 0;\n    }\n    \n    ieee80211_begin_scan(ifp);\n    \n    /*\n     * ieee80211_begin_scan() ends up scheduling iwx_newstate_task().\n     * Wait until the transition to SCAN state has completed.\n     */\n    do {\n        err = tsleep_nsec(&ic->ic_state, PCATCH, \"iwxinit\",\n            SEC_TO_NSEC(1));\n        if (generation != sc->sc_generation)\n            return ENXIO;\n        if (err) {\n            iwx_stop(ifp);\n            return err;\n        }\n    } while (ic->ic_state != IEEE80211_S_SCAN);\n    \n    return 0;\n}\n\nIOReturn ItlIwx::\n_iwx_start_task(OSObject *target, void *arg0, void *arg1, void *arg2, void *arg3)\n{\n    struct _ifnet *ifp = (struct _ifnet *)arg0;\n    struct iwx_softc *sc = (struct iwx_softc *)ifp->if_softc;\n    ItlIwx *that = container_of(sc, ItlIwx, com);\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct ieee80211_node *ni;\n    struct ether_header *eh;\n    mbuf_t m;\n    int ac = EDCA_AC_BE; /* XXX */\n    \n    if (!(ifp->if_flags & IFF_RUNNING) ||  ifq_is_oactive(&ifp->if_snd)) {\n        return kIOReturnError;\n    }\n    \n    for (;;) {\n        /* why isn't this done per-queue? */\n        if (sc->qfullmsk != 0) {\n            ifq_set_oactive(&ifp->if_snd);\n            break;\n        }\n\n        /* Don't queue additional frames while flushing Tx queues. */\n        if (sc->sc_flags & IWX_FLAG_TXFLUSH)\n            break;\n        \n        /* need to send management frames even if we're not RUNning */\n        m = mq_dequeue(&ic->ic_mgtq);\n        if (m) {\n            //            ni = m->m_pkthdr.ph_cookie;\n            ni = (struct ieee80211_node *)mbuf_pkthdr_rcvif(m);\n            goto sendit;\n        }\n        \n        if (\n#ifndef AIRPORT\n            ic->ic_state != IEEE80211_S_RUN ||\n#endif\n            (ic->ic_xflags & IEEE80211_F_TX_MGMT_ONLY))\n            break;\n        \n        m = ifq_dequeue(&ifp->if_snd);\n        if (!m)\n            break;\n        if (mbuf_len(m) < sizeof (*eh) &&\n            mbuf_pullup(&m, sizeof (*eh)) != 0) {\n            ifp->netStat->outputErrors++;\n            continue;\n        }\n#if NBPFILTER > 0\n        if (ifp->if_bpf != NULL)\n            bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);\n#endif\n        if ((m = ieee80211_encap(ifp, m, &ni)) == NULL) {\n            ifp->netStat->outputErrors++;\n            continue;\n        }\n        \n    sendit:\n#if NBPFILTER > 0\n        if (ic->ic_rawbpf != NULL)\n            bpf_mtap(ic->ic_rawbpf, m, BPF_DIRECTION_OUT);\n#endif\n        if (that->iwx_tx(sc, m, ni, ac) != 0) {\n            ieee80211_release_node(ic, ni);\n            ifp->netStat->outputErrors++;\n            continue;\n        }\n        ifp->netStat->outputPackets++;\n        \n        if (ifp->if_flags & IFF_UP) {\n            sc->sc_tx_timer = 15;\n            ifp->if_timer = 1;\n        }\n    }\n    \n    return kIOReturnSuccess;\n}\n\nvoid ItlIwx::\niwx_start(struct _ifnet *ifp)\n{\n    struct iwx_softc *sc = (struct iwx_softc*)ifp->if_softc;\n    ItlIwx *that = container_of(sc, ItlIwx, com);\n    that->getMainCommandGate()->attemptAction(_iwx_start_task, &that->com.sc_ic.ic_ac.ac_if);\n}\n\nvoid ItlIwx::\niwx_stop(struct _ifnet *ifp)\n{\n    struct iwx_softc *sc = (struct iwx_softc *)ifp->if_softc;\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct iwx_node *in = (struct iwx_node *)ic->ic_bss;\n    int i, s = splnet();\n    \n    //    rw_assert_wrlock(&sc->ioctl_rwl);\n    \n    sc->sc_flags |= IWX_FLAG_SHUTDOWN; /* Disallow new tasks. */\n    \n    /* Cancel scheduled tasks and let any stale tasks finish up. */\n    task_del(systq, &sc->init_task);\n    iwx_del_task(sc, sc->sc_nswq, &sc->newstate_task);\n    iwx_del_task(sc, systq, &sc->ba_task);\n    iwx_del_task(sc, systq, &sc->mac_ctxt_task);\n    iwx_del_task(sc, systq, &sc->chan_ctxt_task);\n    KASSERT(sc->task_refs.refs >= 1, \"sc->task_refs.refs >= 1\");\n    //    refcnt_finalize(&sc->task_refs, \"iwxstop\");\n    \n    iwx_stop_device(sc);\n    \n    /* Reset soft state. */\n    \n    sc->sc_generation++;\n    for (i = 0; i < nitems(sc->sc_cmd_resp_pkt); i++) {\n        ::free(sc->sc_cmd_resp_pkt[i]);\n        sc->sc_cmd_resp_pkt[i] = NULL;\n        sc->sc_cmd_resp_len[i] = 0;\n    }\n    ifp->if_flags &= ~IFF_RUNNING;\n    ifq_clr_oactive(&ifp->if_snd);\n    ifq_flush(&ifp->if_snd);\n    \n    if (in != NULL) {\n        in->in_phyctxt = NULL;\n        in->in_ni.ni_chw = IEEE80211_CHAN_WIDTH_20_NOHT;\n        IEEE80211_ADDR_COPY(in->in_macaddr, etheranyaddr);\n    }\n    \n    sc->sc_flags &= ~(IWX_FLAG_SCANNING | IWX_FLAG_BGSCAN);\n    sc->sc_flags &= ~IWX_FLAG_MAC_ACTIVE;\n    sc->sc_flags &= ~IWX_FLAG_BINDING_ACTIVE;\n    sc->sc_flags &= ~IWX_FLAG_STA_ACTIVE;\n    sc->sc_flags &= ~IWX_FLAG_TE_ACTIVE;\n    sc->sc_flags &= ~IWX_FLAG_HW_ERR;\n    sc->sc_flags &= ~IWX_FLAG_SHUTDOWN;\n    sc->sc_flags &= ~IWX_FLAG_TXFLUSH;\n\n    sc->sc_rx_ba_sessions = 0;\n    sc->ba_rx.start_tidmask = 0;\n    sc->ba_rx.stop_tidmask = 0;\n    sc->ba_tx.start_tidmask = 0;\n    sc->ba_tx.stop_tidmask = 0;\n    \n    sc->sc_newstate(ic, IEEE80211_S_INIT, -1);\n    sc->ns_nstate = IEEE80211_S_INIT;\n    \n    for (i = 0; i < nitems(sc->sc_rxba_data); i++) {\n        struct iwx_rxba_data *rxba = &sc->sc_rxba_data[i];\n        iwx_clear_reorder_buffer(sc, rxba);\n    }\n    \n    ifp->if_timer = sc->sc_tx_timer = 0;\n    \n    splx(s);\n}\n\nvoid ItlIwx::\niwx_watchdog(struct _ifnet *ifp)\n{\n    struct iwx_softc *sc = (struct iwx_softc *)ifp->if_softc;\n    ItlIwx *that = container_of(sc, ItlIwx, com);\n    \n    ifp->if_timer = 0;\n    if (sc->sc_tx_timer > 0) {\n        if (--sc->sc_tx_timer == 0) {\n            XYLog(\"%s: device timeout\\n\", DEVNAME(sc));\n#ifdef IWX_DEBUG\n            int i;\n\n            /* Dump driver status (TX and RX rings) while we're here. */\n            XYLog(\"driver status:\\n\");\n            for (i = 0; i < IWX_MAX_QUEUES; i++) {\n                struct iwx_tx_ring *ring = &sc->txq[i];\n                XYLog(\"  tx ring %2d: qid=%-2d cur=%-3d \"\n                      \"queued=%-3d\\n\",\n                      i, ring->qid, ring->cur, ring->queued);\n            }\n            XYLog(\"  rx ring: cur=%d\\n\", sc->rxq.cur);\n            XYLog(\"  802.11 state %s\\n\",\n                  ieee80211_state_name[sc->sc_ic.ic_state]);\n\n            that->iwx_nic_error(sc);\n#endif\n            if ((sc->sc_flags & IWX_FLAG_SHUTDOWN) == 0)\n                task_add(systq, &sc->init_task);\n            ifp->netStat->outputErrors++;\n            return;\n        }\n        ifp->if_timer = 1;\n    }\n\n    ieee80211_watchdog(ifp);\n}\n\nint ItlIwx::\niwx_ioctl(struct _ifnet *ifp, u_long cmd, caddr_t data)\n{\n    struct iwx_softc *sc = (struct iwx_softc *)ifp->if_softc;\n    int s, err = 0, generation = sc->sc_generation;\n    ItlIwx *that = container_of(sc, ItlIwx, com);\n    \n    /*\n     * Prevent processes from entering this function while another\n     * process is tsleep'ing in it.\n     */\n    //    err = rw_enter(&sc->ioctl_rwl, RW_WRITE | RW_INTR);\n    if (err == 0 && generation != sc->sc_generation) {\n        //        rw_exit(&sc->ioctl_rwl);\n        return ENXIO;\n    }\n    if (err)\n        return err;\n    s = splnet();\n    \n    switch (cmd) {\n        case SIOCSIFADDR:\n            ifp->if_flags |= IFF_UP;\n            /* FALLTHROUGH */\n        case SIOCSIFFLAGS:\n            if (ifp->if_flags & IFF_UP) {\n                if (!(ifp->if_flags & IFF_RUNNING)) {\n                    err = that->iwx_init(ifp);\n                }\n            } else {\n                if (ifp->if_flags & IFF_RUNNING)\n                    that->iwx_stop(ifp);\n            }\n            break;\n            \n        default:\n            err = ieee80211_ioctl(ifp, cmd, data);\n    }\n    \n    if (err == ENETRESET) {\n        err = 0;\n        if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==\n            (IFF_UP | IFF_RUNNING)) {\n            that->iwx_stop(ifp);\n            err = that->iwx_init(ifp);\n        }\n    }\n    \n    splx(s);\n    //    rw_exit(&sc->ioctl_rwl);\n    \n    return err;\n}\n\n#if 1 /* usually #ifdef IWX_DEBUG but always enabled for now */\n/*\n * Note: This structure is read from the device with IO accesses,\n * and the reading already does the endian conversion. As it is\n * read with uint32_t-sized accesses, any members with a different size\n * need to be ordered correctly though!\n */\nstruct iwx_error_event_table {\n    uint32_t valid;        /* (nonzero) valid, (0) log is empty */\n    uint32_t error_id;        /* type of error */\n    uint32_t trm_hw_status0;    /* TRM HW status */\n    uint32_t trm_hw_status1;    /* TRM HW status */\n    uint32_t blink2;        /* branch link */\n    uint32_t ilink1;        /* interrupt link */\n    uint32_t ilink2;        /* interrupt link */\n    uint32_t data1;        /* error-specific data */\n    uint32_t data2;        /* error-specific data */\n    uint32_t data3;        /* error-specific data */\n    uint32_t bcon_time;        /* beacon timer */\n    uint32_t tsf_low;        /* network timestamp function timer */\n    uint32_t tsf_hi;        /* network timestamp function timer */\n    uint32_t gp1;        /* GP1 timer register */\n    uint32_t gp2;        /* GP2 timer register */\n    uint32_t fw_rev_type;    /* firmware revision type */\n    uint32_t major;        /* uCode version major */\n    uint32_t minor;        /* uCode version minor */\n    uint32_t hw_ver;        /* HW Silicon version */\n    uint32_t brd_ver;        /* HW board version */\n    uint32_t log_pc;        /* log program counter */\n    uint32_t frame_ptr;        /* frame pointer */\n    uint32_t stack_ptr;        /* stack pointer */\n    uint32_t hcmd;        /* last host command header */\n    uint32_t isr0;        /* isr status register LMPM_NIC_ISR0:\n                         * rxtx_flag */\n    uint32_t isr1;        /* isr status register LMPM_NIC_ISR1:\n                         * host_flag */\n    uint32_t isr2;        /* isr status register LMPM_NIC_ISR2:\n                         * enc_flag */\n    uint32_t isr3;        /* isr status register LMPM_NIC_ISR3:\n                         * time_flag */\n    uint32_t isr4;        /* isr status register LMPM_NIC_ISR4:\n                         * wico interrupt */\n    uint32_t last_cmd_id;    /* last HCMD id handled by the firmware */\n    uint32_t wait_event;        /* wait event() caller address */\n    uint32_t l2p_control;    /* L2pControlField */\n    uint32_t l2p_duration;    /* L2pDurationField */\n    uint32_t l2p_mhvalid;    /* L2pMhValidBits */\n    uint32_t l2p_addr_match;    /* L2pAddrMatchStat */\n    uint32_t lmpm_pmg_sel;    /* indicate which clocks are turned on\n                             * (LMPM_PMG_SEL) */\n    uint32_t u_timestamp;    /* indicate when the date and time of the\n                             * compilation */\n    uint32_t flow_handler;    /* FH read/write pointers, RX credit */\n} __packed /* LOG_ERROR_TABLE_API_S_VER_3 */;\n\n/*\n * UMAC error struct - relevant starting from family 8000 chip.\n * Note: This structure is read from the device with IO accesses,\n * and the reading already does the endian conversion. As it is\n * read with u32-sized accesses, any members with a different size\n * need to be ordered correctly though!\n */\nstruct iwx_umac_error_event_table {\n    uint32_t valid;        /* (nonzero) valid, (0) log is empty */\n    uint32_t error_id;    /* type of error */\n    uint32_t blink1;    /* branch link */\n    uint32_t blink2;    /* branch link */\n    uint32_t ilink1;    /* interrupt link */\n    uint32_t ilink2;    /* interrupt link */\n    uint32_t data1;        /* error-specific data */\n    uint32_t data2;        /* error-specific data */\n    uint32_t data3;        /* error-specific data */\n    uint32_t umac_major;\n    uint32_t umac_minor;\n    uint32_t frame_pointer;    /* core register 27*/\n    uint32_t stack_pointer;    /* core register 28 */\n    uint32_t cmd_header;    /* latest host cmd sent to UMAC */\n    uint32_t nic_isr_pref;    /* ISR status register */\n} __packed;\n\n#define ERROR_START_OFFSET  (1 * sizeof(uint32_t))\n#define ERROR_ELEM_SIZE     (7 * sizeof(uint32_t))\n\nvoid ItlIwx::\niwx_nic_umac_error(struct iwx_softc *sc)\n{\n    struct iwx_umac_error_event_table table;\n    uint32_t base;\n    \n    base = sc->sc_uc.uc_umac_error_event_table;\n    \n    if (base < 0x400000) {\n        XYLog(\"%s: Invalid error log pointer 0x%08x\\n\",\n              DEVNAME(sc), base);\n        return;\n    }\n    \n    if (iwx_read_mem(sc, base, &table, sizeof(table)/sizeof(uint32_t))) {\n        XYLog(\"%s: reading errlog failed\\n\", DEVNAME(sc));\n        return;\n    }\n    \n    if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) {\n        XYLog(\"%s: Start UMAC Error Log Dump:\\n\", DEVNAME(sc));\n        XYLog(\"%s: Status: 0x%x, count: %d\\n\", DEVNAME(sc),\n              sc->sc_flags, table.valid);\n    }\n    \n    XYLog(\"%s: 0x%08X | %s\\n\", DEVNAME(sc), table.error_id,\n          iwx_desc_lookup(table.error_id));\n    XYLog(\"%s: 0x%08X | umac branchlink1\\n\", DEVNAME(sc), table.blink1);\n    XYLog(\"%s: 0x%08X | umac branchlink2\\n\", DEVNAME(sc), table.blink2);\n    XYLog(\"%s: 0x%08X | umac interruptlink1\\n\", DEVNAME(sc), table.ilink1);\n    XYLog(\"%s: 0x%08X | umac interruptlink2\\n\", DEVNAME(sc), table.ilink2);\n    XYLog(\"%s: 0x%08X | umac data1\\n\", DEVNAME(sc), table.data1);\n    XYLog(\"%s: 0x%08X | umac data2\\n\", DEVNAME(sc), table.data2);\n    XYLog(\"%s: 0x%08X | umac data3\\n\", DEVNAME(sc), table.data3);\n    XYLog(\"%s: 0x%08X | umac major\\n\", DEVNAME(sc), table.umac_major);\n    XYLog(\"%s: 0x%08X | umac minor\\n\", DEVNAME(sc), table.umac_minor);\n    XYLog(\"%s: 0x%08X | frame pointer\\n\", DEVNAME(sc),\n          table.frame_pointer);\n    XYLog(\"%s: 0x%08X | stack pointer\\n\", DEVNAME(sc),\n          table.stack_pointer);\n    XYLog(\"%s: 0x%08X | last host cmd\\n\", DEVNAME(sc), table.cmd_header);\n    XYLog(\"%s: 0x%08X | isr status reg\\n\", DEVNAME(sc),\n          table.nic_isr_pref);\n}\n\n#define IWX_FW_SYSASSERT_CPU_MASK 0xf0000000\nstatic struct {\n    const char *name;\n    uint8_t num;\n} advanced_lookup[] = {\n    { \"NMI_INTERRUPT_WDG\", 0x34 },\n    { \"SYSASSERT\", 0x35 },\n    { \"UCODE_VERSION_MISMATCH\", 0x37 },\n    { \"BAD_COMMAND\", 0x38 },\n    { \"BAD_COMMAND\", 0x39 },\n    { \"NMI_INTERRUPT_DATA_ACTION_PT\", 0x3C },\n    { \"FATAL_ERROR\", 0x3D },\n    { \"NMI_TRM_HW_ERR\", 0x46 },\n    { \"NMI_INTERRUPT_TRM\", 0x4C },\n    { \"NMI_INTERRUPT_BREAK_POINT\", 0x54 },\n    { \"NMI_INTERRUPT_WDG_RXF_FULL\", 0x5C },\n    { \"NMI_INTERRUPT_WDG_NO_RBD_RXF_FULL\", 0x64 },\n    { \"NMI_INTERRUPT_HOST\", 0x66 },\n    { \"NMI_INTERRUPT_LMAC_FATAL\", 0x70 },\n    { \"NMI_INTERRUPT_UMAC_FATAL\", 0x71 },\n    { \"NMI_INTERRUPT_OTHER_LMAC_FATAL\", 0x73 },\n    { \"NMI_INTERRUPT_ACTION_PT\", 0x7C },\n    { \"NMI_INTERRUPT_UNKNOWN\", 0x84 },\n    { \"NMI_INTERRUPT_INST_ACTION_PT\", 0x86 },\n    { \"ADVANCED_SYSASSERT\", 0 },\n};\n\nconst char *ItlIwx::\niwx_desc_lookup(uint32_t num)\n{\n    int i;\n    \n    for (i = 0; i < nitems(advanced_lookup) - 1; i++)\n        if (advanced_lookup[i].num ==\n            (num & ~IWX_FW_SYSASSERT_CPU_MASK))\n            return advanced_lookup[i].name;\n    \n    /* No entry matches 'num', so it is the last: ADVANCED_SYSASSERT */\n    return advanced_lookup[i].name;\n}\n\n/*\n * Support for dumping the error log seemed like a good idea ...\n * but it's mostly hex junk and the only sensible thing is the\n * hw/ucode revision (which we know anyway).  Since it's here,\n * I'll just leave it in, just in case e.g. the Intel guys want to\n * help us decipher some \"ADVANCED_SYSASSERT\" later.\n */\nvoid ItlIwx::\niwx_nic_error(struct iwx_softc *sc)\n{\n    struct iwx_error_event_table table;\n    uint32_t base;\n    \n    XYLog(\"%s: dumping device error log\\n\", DEVNAME(sc));\n    base = sc->sc_uc.uc_lmac_error_event_table[0];\n    if (base < 0x400000) {\n        XYLog(\"%s: Invalid error log pointer 0x%08x\\n\",\n              DEVNAME(sc), base);\n        return;\n    }\n    \n    if (iwx_read_mem(sc, base, &table, sizeof(table)/sizeof(uint32_t))) {\n        XYLog(\"%s: reading errlog failed\\n\", DEVNAME(sc));\n        return;\n    }\n    \n    if (!table.valid) {\n        XYLog(\"%s: errlog not found, skipping\\n\", DEVNAME(sc));\n        return;\n    }\n    \n    if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) {\n        XYLog(\"%s: Start Error Log Dump:\\n\", DEVNAME(sc));\n        XYLog(\"%s: Status: 0x%x, count: %d\\n\", DEVNAME(sc),\n              sc->sc_flags, table.valid);\n    }\n    \n    XYLog(\"%s: 0x%08X | %-28s\\n\", DEVNAME(sc), table.error_id,\n          iwx_desc_lookup(table.error_id));\n    XYLog(\"%s: %08X | trm_hw_status0\\n\", DEVNAME(sc),\n          table.trm_hw_status0);\n    XYLog(\"%s: %08X | trm_hw_status1\\n\", DEVNAME(sc),\n          table.trm_hw_status1);\n    XYLog(\"%s: %08X | branchlink2\\n\", DEVNAME(sc), table.blink2);\n    XYLog(\"%s: %08X | interruptlink1\\n\", DEVNAME(sc), table.ilink1);\n    XYLog(\"%s: %08X | interruptlink2\\n\", DEVNAME(sc), table.ilink2);\n    XYLog(\"%s: %08X | data1\\n\", DEVNAME(sc), table.data1);\n    XYLog(\"%s: %08X | data2\\n\", DEVNAME(sc), table.data2);\n    XYLog(\"%s: %08X | data3\\n\", DEVNAME(sc), table.data3);\n    XYLog(\"%s: %08X | beacon time\\n\", DEVNAME(sc), table.bcon_time);\n    XYLog(\"%s: %08X | tsf low\\n\", DEVNAME(sc), table.tsf_low);\n    XYLog(\"%s: %08X | tsf hi\\n\", DEVNAME(sc), table.tsf_hi);\n    XYLog(\"%s: %08X | time gp1\\n\", DEVNAME(sc), table.gp1);\n    XYLog(\"%s: %08X | time gp2\\n\", DEVNAME(sc), table.gp2);\n    XYLog(\"%s: %08X | uCode revision type\\n\", DEVNAME(sc),\n          table.fw_rev_type);\n    XYLog(\"%s: %08X | uCode version major\\n\", DEVNAME(sc),\n          table.major);\n    XYLog(\"%s: %08X | uCode version minor\\n\", DEVNAME(sc),\n          table.minor);\n    XYLog(\"%s: %08X | hw version\\n\", DEVNAME(sc), table.hw_ver);\n    XYLog(\"%s: %08X | board version\\n\", DEVNAME(sc), table.brd_ver);\n    XYLog(\"%s: %08X | hcmd\\n\", DEVNAME(sc), table.hcmd);\n    XYLog(\"%s: %08X | isr0\\n\", DEVNAME(sc), table.isr0);\n    XYLog(\"%s: %08X | isr1\\n\", DEVNAME(sc), table.isr1);\n    XYLog(\"%s: %08X | isr2\\n\", DEVNAME(sc), table.isr2);\n    XYLog(\"%s: %08X | isr3\\n\", DEVNAME(sc), table.isr3);\n    XYLog(\"%s: %08X | isr4\\n\", DEVNAME(sc), table.isr4);\n    XYLog(\"%s: %08X | last cmd Id\\n\", DEVNAME(sc), table.last_cmd_id);\n    XYLog(\"%s: %08X | wait_event\\n\", DEVNAME(sc), table.wait_event);\n    XYLog(\"%s: %08X | l2p_control\\n\", DEVNAME(sc), table.l2p_control);\n    XYLog(\"%s: %08X | l2p_duration\\n\", DEVNAME(sc), table.l2p_duration);\n    XYLog(\"%s: %08X | l2p_mhvalid\\n\", DEVNAME(sc), table.l2p_mhvalid);\n    XYLog(\"%s: %08X | l2p_addr_match\\n\", DEVNAME(sc), table.l2p_addr_match);\n    XYLog(\"%s: %08X | lmpm_pmg_sel\\n\", DEVNAME(sc), table.lmpm_pmg_sel);\n    XYLog(\"%s: %08X | timestamp\\n\", DEVNAME(sc), table.u_timestamp);\n    XYLog(\"%s: %08X | flow_handler\\n\", DEVNAME(sc), table.flow_handler);\n    \n    if (sc->sc_uc.uc_umac_error_event_table)\n        iwx_nic_umac_error(sc);\n}\n#endif\n\n//#define SYNC_RESP_STRUCT(_var_, _pkt_)                    \\\n//do {                                    \\\n//    bus_dmamap_sync(sc->sc_dmat, data->map, sizeof(*(_pkt_)),    \\\n//        sizeof(*(_var_)), BUS_DMASYNC_POSTREAD);            \\\n//    _var_ = (void *)((_pkt_)+1);                    \\\n//} while (/*CONSTCOND*/0)\n//\n//#define SYNC_RESP_PTR(_ptr_, _len_, _pkt_)                \\\n//do {                                    \\\n//    bus_dmamap_sync(sc->sc_dmat, data->map, sizeof(*(_pkt_)),    \\\n//        sizeof(len), BUS_DMASYNC_POSTREAD);                \\\n//    _ptr_ = (void *)((_pkt_)+1);                    \\\n//} while (/*CONSTCOND*/0)\n\n#define SYNC_RESP_STRUCT(_var_, _pkt_, t)                    \\\ndo {                                    \\\nbus_dmamap_sync(sc->sc_dmat, data->map, sizeof(*(_pkt_)),    \\\nsizeof(*(_var_)), BUS_DMASYNC_POSTREAD);            \\\n_var_ = (t)((_pkt_)+1);                    \\\n} while (/*CONSTCOND*/0)\n\nint ItlIwx::\niwx_rx_pkt_valid(struct iwx_rx_packet *pkt)\n{\n    int qid, idx, code;\n    \n    qid = pkt->hdr.qid & ~0x80;\n    idx = pkt->hdr.idx;\n    code = IWX_WIDE_ID(pkt->hdr.group_id, pkt->hdr.cmd);\n    \n    return (!(qid == 0 && idx == 0 && code == 0) &&\n            pkt->len_n_flags != htole32(IWX_FH_RSCSR_FRAME_INVALID));\n}\n\n/**\n * struct iwl_pnvm_init_complete_ntfy - PNVM initialization complete\n * @status: PNVM image loading status\n */\nstruct iwl_pnvm_init_complete_ntfy {\n    uint32_t status;\n} __packed; /* PNVM_INIT_COMPLETE_NTFY_S_VER_1 */\n\nvoid ItlIwx::\niwx_rx_pkt(struct iwx_softc *sc, struct iwx_rx_data *data, struct mbuf_list *ml)\n{\n    struct _ifnet *ifp = IC2IFP(&sc->sc_ic);\n    struct iwx_rx_packet *pkt, *nextpkt;\n    uint32_t offset = 0, nextoff = 0, nmpdu = 0, len;\n    mbuf_t m0, m;\n    const size_t minsz = sizeof(pkt->len_n_flags) + sizeof(pkt->hdr);\n    int qid, idx, code, handled = 1;\n    \n    //    bus_dmamap_sync(sc->sc_dmat, data->map, 0, IWX_RBUF_SIZE,\n    //        BUS_DMASYNC_POSTREAD);\n    \n    m0 = data->m;\n    while (m0 && offset + minsz < IWX_RBUF_SIZE) {\n        pkt = (struct iwx_rx_packet *)((uint8_t*)mbuf_data(m0) + offset);\n        qid = pkt->hdr.qid;\n        idx = pkt->hdr.idx;\n        \n        code = IWX_WIDE_ID(pkt->hdr.group_id, pkt->hdr.cmd);\n        \n        DPRINTFN(3, (\"%s gid=%d cmd=%d code=0x%02x qid=%d idx=%d packet_len=%d payload_len=%d\\n\", __FUNCTION__, pkt->hdr.group_id, pkt->hdr.cmd, code, qid, idx, iwx_rx_packet_len(pkt), iwx_rx_packet_payload_len(pkt)));\n        \n        if (!iwx_rx_pkt_valid(pkt))\n            break;\n        \n        /*\n         * XXX Intel inside (tm)\n         * Any commands in the LONG_GROUP could actually be in the\n         * LEGACY group. Firmware API versions >= 50 reject commands\n         * in group 0, forcing us to use this hack.\n         */\n        if (iwx_cmd_groupid(code) == IWX_LONG_GROUP) {\n            struct iwx_tx_ring *ring = &sc->txq[qid];\n            struct iwx_tx_data *txdata = &ring->data[idx];\n            if (txdata->flags & IWX_TXDATA_FLAG_CMD_IS_NARROW)\n                code = iwx_cmd_opcode(code);\n        }\n        \n        len = sizeof(pkt->len_n_flags) + iwx_rx_packet_len(pkt);\n        if (len < minsz || len > (IWX_RBUF_SIZE - offset))\n            break;\n        \n        if (code == IWX_REPLY_RX_MPDU_CMD && ++nmpdu == 1) {\n            /* Take mbuf m0 off the RX ring. */\n            if (iwx_rx_addbuf(sc, IWX_RBUF_SIZE, sc->rxq.cur)) {\n                ifp->netStat->inputErrors++;\n                break;\n            }\n            KASSERT(data->m != m0, \"data->m != m0\");\n        }\n        \n        switch (code) {\n            case IWX_REPLY_RX_PHY_CMD:\n                iwx_rx_rx_phy_cmd(sc, pkt, data);\n                break;\n                \n            case IWX_REPLY_RX_MPDU_CMD: {\n                size_t maxlen = IWX_RBUF_SIZE - offset - minsz;\n                nextoff = offset +\n                roundup(len, IWX_FH_RSCSR_FRAME_ALIGN);\n                nextpkt = (struct iwx_rx_packet *)\n                ((uint8_t*)mbuf_data(m0) + nextoff);\n                if (nextoff + minsz >= IWX_RBUF_SIZE ||\n                    !iwx_rx_pkt_valid(nextpkt)) {\n                    /* No need to copy last frame in buffer. */\n                    if (offset > 0)\n                        mbuf_adj(m0, offset);\n                    iwx_rx_mpdu_mq(sc, m0, pkt->data, maxlen, ml);\n                    m0 = NULL; /* stack owns m0 now; abort loop */\n                } else {\n                    /*\n                     * Create an mbuf which points to the current\n                     * packet. Always copy from offset zero to\n                     * preserve m_pkthdr.\n                     */\n                    mbuf_copym(m0, 0, MBUF_COPYALL, MBUF_DONTWAIT, &m);\n                    if (m == NULL) {\n                        ifp->netStat->inputErrors++;\n                        mbuf_freem(m0);\n                        m0 = NULL;\n                        break;\n                    }\n                    mbuf_adj(m, offset);\n                    iwx_rx_mpdu_mq(sc, m, pkt->data, maxlen, ml);\n                }\n                break;\n            }\n            case IWX_BA_NOTIF:\n                iwx_rx_tx_ba_notif(sc, pkt, data);\n                break;\n                \n            case IWX_TX_CMD:\n                iwx_rx_tx_cmd(sc, pkt, data);\n                break;\n                \n            case IWX_MISSED_BEACONS_NOTIFICATION:\n                iwx_rx_bmiss(sc, pkt, data);\n                break;\n                \n            case IWX_MFUART_LOAD_NOTIFICATION:\n                break;\n                \n            case IWX_ALIVE: {\n                struct iwx_alive_resp_v4 *resp4;\n                struct iwx_alive_resp_v5 *resp5;\n                \n                DPRINTF((\"%s: firmware alive, size=%d\\n\", __FUNCTION__, iwx_rx_packet_payload_len(pkt)));\n                if (iwx_rx_packet_payload_len(pkt) == sizeof(*resp4)) {\n                    SYNC_RESP_STRUCT(resp4, pkt, struct iwx_alive_resp_v4 *);\n                    sc->sc_uc.uc_lmac_error_event_table[0] = le32toh(\n                                                                     resp4->lmac_data[0].dbg_ptrs.error_event_table_ptr);\n                    sc->sc_uc.uc_lmac_error_event_table[1] = le32toh(\n                                                                     resp4->lmac_data[1].dbg_ptrs.error_event_table_ptr);\n                    sc->sc_uc.uc_log_event_table = le32toh(\n                                                           resp4->lmac_data[0].dbg_ptrs.log_event_table_ptr);\n                    sc->sc_uc.uc_umac_error_event_table = le32toh(\n                                                                  resp4->umac_data.dbg_ptrs.error_info_addr);\n                    if (resp4->status == IWX_ALIVE_STATUS_OK)\n                        sc->sc_uc.uc_ok = 1;\n                    else\n                        sc->sc_uc.uc_ok = 0;\n                } else {\n                    SYNC_RESP_STRUCT(resp5, pkt, struct iwx_alive_resp_v5 *);\n                    sc->sc_uc.uc_lmac_error_event_table[0] = le32toh(\n                                                                     resp5->lmac_data[0].dbg_ptrs.error_event_table_ptr);\n                    sc->sc_uc.uc_lmac_error_event_table[1] = le32toh(\n                                                                     resp5->lmac_data[1].dbg_ptrs.error_event_table_ptr);\n                    sc->sc_uc.uc_log_event_table = le32toh(\n                                                           resp5->lmac_data[0].dbg_ptrs.log_event_table_ptr);\n                    sc->sc_uc.uc_umac_error_event_table = le32toh(\n                                                                  resp5->umac_data.dbg_ptrs.error_info_addr);\n                    if (resp5->status == IWX_ALIVE_STATUS_OK)\n                        sc->sc_uc.uc_ok = 1;\n                    else\n                        sc->sc_uc.uc_ok = 0;\n                    \n                    sc->sku_id[0] = le32toh(resp5->sku_id.data[0]);\n                    sc->sku_id[1] = le32toh(resp5->sku_id.data[1]);\n                    sc->sku_id[2] = le32toh(resp5->sku_id.data[2]);\n                    \n                    XYLog(\"Got sku_id: 0x0%x 0x0%x 0x0%x\\n\",\n                                 sc->sku_id[0],\n                                 sc->sku_id[1],\n                                 sc->sku_id[2]);\n                }\n                \n                sc->sc_uc.uc_intr = 1;\n                wakeupOn(&sc->sc_uc);\n                break;\n            }\n                \n            case IWX_STATISTICS_NOTIFICATION: {\n                struct iwx_notif_statistics *stats;\n                struct iwx_notif_statistics_v11 *stats_v11;\n                if (isset(sc->sc_ucode_api, IWX_UCODE_TLV_API_NEW_RX_STATS)) {\n                    SYNC_RESP_STRUCT(stats, pkt, struct iwx_notif_statistics *);\n                    sc->sc_noise = iwx_get_noise((uint8_t *)&stats->rx.general.beacon_silence_rssi_a);\n                } else {\n                    SYNC_RESP_STRUCT(stats_v11, pkt, struct iwx_notif_statistics_v11 *);\n                    sc->sc_noise = iwx_get_noise((uint8_t *)&stats_v11->rx.general.beacon_silence_rssi_a);\n                }\n                break;\n            }\n                \n            case IWX_DTS_MEASUREMENT_NOTIFICATION:\n            case IWX_WIDE_ID(IWX_PHY_OPS_GROUP,\n                             IWX_DTS_MEASUREMENT_NOTIF_WIDE):\n            case IWX_WIDE_ID(IWX_PHY_OPS_GROUP,\n                             IWX_TEMP_REPORTING_THRESHOLDS_CMD):\n                break;\n                \n            case IWX_WIDE_ID(IWX_PHY_OPS_GROUP,\n                             IWX_CT_KILL_NOTIFICATION): {\n                struct iwx_ct_kill_notif *notif;\n                SYNC_RESP_STRUCT(notif, pkt, struct iwx_ct_kill_notif *);\n                XYLog(\"%s: device at critical temperature (%u degC), \"\n                       \"stopping device\\n\",\n                       DEVNAME(sc), le16toh(notif->temperature));\n                sc->sc_flags |= IWX_FLAG_HW_ERR;\n                task_add(systq, &sc->init_task);\n                break;\n            }\n                \n            case IWX_WIDE_ID(IWX_REGULATORY_AND_NVM_GROUP,\n                IWX_NVM_GET_INFO):\n            case IWX_ADD_STA_KEY:\n            case IWX_PHY_CONFIGURATION_CMD:\n            case IWX_TX_ANT_CONFIGURATION_CMD:\n            case IWX_ADD_STA:\n            case IWX_MAC_CONTEXT_CMD:\n            case IWX_REPLY_SF_CFG_CMD:\n            case IWX_POWER_TABLE_CMD:\n            case IWX_LTR_CONFIG:\n            case IWX_PHY_CONTEXT_CMD:\n            case IWX_BINDING_CONTEXT_CMD:\n            case IWX_WIDE_ID(IWX_LONG_GROUP, IWX_SCAN_CFG_CMD):\n            case IWX_WIDE_ID(IWX_LONG_GROUP, IWX_SCAN_REQ_UMAC):\n            case IWX_WIDE_ID(IWX_LONG_GROUP, IWX_SCAN_ABORT_UMAC):\n            case IWX_WIDE_ID(IWX_MAC_CONF_GROUP, IWX_SESSION_PROTECTION_CMD):\n            case IWX_REPLY_BEACON_FILTERING_CMD:\n            case IWX_MAC_PM_POWER_TABLE:\n            case IWX_TIME_QUOTA_CMD:\n            case IWX_REMOVE_STA:\n            case IWX_TXPATH_FLUSH:\n            case IWX_BT_CONFIG:\n            case IWX_MCC_UPDATE_CMD:\n            case IWX_TIME_EVENT_CMD:\n            case IWX_STATISTICS_CMD:\n            case IWX_SCD_QUEUE_CFG: {\n                size_t pkt_len;\n                \n                if (sc->sc_cmd_resp_pkt[idx] == NULL)\n                    break;\n                \n                //            bus_dmamap_sync(sc->sc_dmat, data->map, 0,\n                //                sizeof(*pkt), BUS_DMASYNC_POSTREAD);\n                \n                pkt_len = sizeof(pkt->len_n_flags) +\n                iwx_rx_packet_len(pkt);\n                \n                if ((pkt->hdr.group_id & IWX_CMD_FAILED_MSK) ||\n                    pkt_len < sizeof(*pkt) ||\n                    pkt_len > sc->sc_cmd_resp_len[idx]) {\n                    ::free(sc->sc_cmd_resp_pkt[idx]);\n                    sc->sc_cmd_resp_pkt[idx] = NULL;\n                    break;\n                }\n                \n                //            bus_dmamap_sync(sc->sc_dmat, data->map, sizeof(*pkt),\n                //                pkt_len - sizeof(*pkt), BUS_DMASYNC_POSTREAD);\n                memcpy(sc->sc_cmd_resp_pkt[idx], pkt, pkt_len);\n                break;\n            }\n                \n            case IWX_WIDE_ID(IWX_REGULATORY_AND_NVM_GROUP, IWX_PNVM_INIT_COMPLETE_NTFY):\n                wakeupOn(&sc->sc_init_complete);\n                struct iwl_pnvm_init_complete_ntfy *pnvm_ntf;\n                SYNC_RESP_STRUCT(pnvm_ntf, pkt, struct iwl_pnvm_init_complete_ntfy *);\n                XYLog(\"PNVM complete notification received with status 0x%0x\\n\", le32toh(pnvm_ntf->status));\n                break;\n                \n            case IWX_INIT_COMPLETE_NOTIF:\n                sc->sc_init_complete |= IWX_INIT_COMPLETE;\n                wakeupOn(&sc->sc_init_complete);\n                break;\n                \n            case IWX_SCAN_COMPLETE_UMAC: {\n                struct iwx_umac_scan_complete *notif;\n                SYNC_RESP_STRUCT(notif, pkt, struct iwx_umac_scan_complete *);\n                iwx_endscan(sc);\n                break;\n            }\n                \n            case IWX_SCAN_ITERATION_COMPLETE_UMAC: {\n                struct iwx_umac_scan_iter_complete_notif *notif;\n                SYNC_RESP_STRUCT(notif, pkt, struct iwx_umac_scan_iter_complete_notif *);\n                iwx_endscan(sc);\n                break;\n            }\n                \n            case IWX_MCC_CHUB_UPDATE_CMD: {\n                struct iwx_mcc_chub_notif *notif;\n                SYNC_RESP_STRUCT(notif, pkt, struct iwx_mcc_chub_notif *);\n                iwx_mcc_update(sc, notif);\n                break;\n            }\n                \n            case IWX_REPLY_ERROR: {\n                struct iwx_error_resp *resp;\n                SYNC_RESP_STRUCT(resp, pkt, struct iwx_error_resp *);\n                XYLog(\"%s: firmware error 0x%x, cmd 0x%x\\n\",\n                      DEVNAME(sc), le32toh(resp->error_type),\n                      resp->cmd_id);\n                break;\n            }\n                \n            case IWX_TIME_EVENT_NOTIFICATION: {\n                struct iwx_time_event_notif *notif;\n                uint32_t action;\n                SYNC_RESP_STRUCT(notif, pkt, struct iwx_time_event_notif *);\n                \n                if (sc->sc_time_event_uid != le32toh(notif->unique_id))\n                    break;\n                action = le32toh(notif->action);\n                if (action & IWX_TE_V2_NOTIF_HOST_EVENT_END)\n                    sc->sc_flags &= ~IWX_FLAG_TE_ACTIVE;\n                break;\n            }\n                \n            case IWX_WIDE_ID(IWX_SYSTEM_GROUP,\n                             IWX_FSEQ_VER_MISMATCH_NOTIFICATION):\n                break;\n                \n                /*\n                 * Firmware versions 21 and 22 generate some DEBUG_LOG_MSG\n                 * messages. Just ignore them for now.\n                 */\n            case IWX_DEBUG_LOG_MSG:\n                break;\n                \n            case IWX_MCAST_FILTER_CMD:\n                break;\n                \n            case IWX_WIDE_ID(IWX_DATA_PATH_GROUP, IWX_DQA_ENABLE_CMD):\n                break;\n                \n            case IWX_WIDE_ID(IWX_SYSTEM_GROUP, IWX_SOC_CONFIGURATION_CMD):\n                break;\n                \n            case IWX_WIDE_ID(IWX_SYSTEM_GROUP, IWX_INIT_EXTENDED_CFG_CMD):\n                break;\n                \n            case IWX_WIDE_ID(IWX_SYSTEM_GROUP, IWX_SHARED_MEM_CFG_CMD):\n                break;\n                \n            case IWX_WIDE_ID(IWX_REGULATORY_AND_NVM_GROUP,\n                             IWX_NVM_ACCESS_COMPLETE):\n                break;\n                \n            case IWX_WIDE_ID(IWX_DATA_PATH_GROUP, IWX_RX_NO_DATA_NOTIF):\n                break; /* happens in monitor mode; ignore for now */\n            case IWX_WIDE_ID(IWX_DATA_PATH_GROUP, IWX_TLC_MNG_CONFIG_CMD):\n                break;\n                \n            case IWX_WIDE_ID(IWX_DATA_PATH_GROUP,\n                             IWX_TLC_MNG_UPDATE_NOTIF): {\n                struct iwx_tlc_update_notif *notif;\n                SYNC_RESP_STRUCT(notif, pkt, struct iwx_tlc_update_notif *);\n                if (iwx_rx_packet_payload_len(pkt) == sizeof(*notif))\n                    iwx_rs_update(sc, notif);\n                break;\n            }\n                \n            case IWX_WIDE_ID(IWX_MAC_CONF_GROUP, IWX_SESSION_PROTECTION_NOTIF): {\n                struct iwx_session_prot_notif *notif;\n                SYNC_RESP_STRUCT(notif, pkt, struct iwx_session_prot_notif *);\n                if (!notif->status) {\n                    XYLog(\"Session protection failure\\n\");\n                    sc->sc_flags &= ~IWX_FLAG_TE_ACTIVE;\n                    break;\n                }\n                if (!notif->start) {\n                    /*\n                     * By now, we should have finished association\n                     * and know the dtim period.\n                     */\n                    sc->sc_flags &= ~IWX_FLAG_TE_ACTIVE;\n                    XYLog(\"%s finish association\\n\", __FUNCTION__);\n                }\n                break;\n            }\n            \n            case IWX_WIDE_ID(IWX_LEGACY_GROUP, IWX_BAR_FRAME_RELEASE): {\n                struct iwx_bar_frame_release *release;\n                SYNC_RESP_STRUCT(release, pkt, struct iwx_bar_frame_release *);\n                unsigned int baid = le32_get_bits(release->ba_info,\n                                  IWX_BAR_FRAME_RELEASE_BAID_MASK);\n                unsigned int nssn = le32_get_bits(release->ba_info,\n                                  IWX_BAR_FRAME_RELEASE_NSSN_MASK);\n                unsigned int sta_id = le32_get_bits(release->sta_tid,\n                                    IWX_BAR_FRAME_RELEASE_STA_MASK);\n                unsigned int tid = le32_get_bits(release->sta_tid,\n                                 IWX_BAR_FRAME_RELEASE_TID_MASK);\n                struct iwx_rxba_data *baid_data;\n                \n                if (iwx_rx_packet_payload_len(pkt) < sizeof(*release))\n                    break;\n                \n                if (baid == IWX_RX_REORDER_DATA_INVALID_BAID || baid >= IWX_MAX_BAID)\n                    break;\n                \n                baid_data = &sc->sc_rxba_data[baid];\n                \n                if (!baid_data) {\n                    DPRINTFN(1, (\"Got valid BAID %d but not allocated, invalid BAR release!\\n\",\n                     baid));\n                    break;\n                }\n                \n                if (tid != baid_data->tid || sta_id != baid_data->sta_id) {\n                    DPRINTFN(1, (\"baid 0x%x is mapped to sta:%d tid:%d, but BAR release received for sta:%d tid:%d\\n\",\n                                 baid, baid_data->sta_id, baid_data->tid, sta_id,\n                                 tid));\n                    break;\n                }\n                \n                iwx_release_frames(sc, sc->sc_ic.ic_bss, baid_data, &baid_data->reorder_buf, nssn, ml);\n                \n                break;\n            }\n                \n            default:\n                handled = 0;\n                XYLog(\"%s: unhandled firmware response 0x%x/0x%x \"\n                      \"rx ring %d[%d]\\n\",\n                      DEVNAME(sc), code, pkt->len_n_flags,\n                      (qid & ~0x80), idx);\n                break;\n        }\n        \n        /*\n         * uCode sets bit 0x80 when it originates the notification,\n         * i.e. when the notification is not a direct response to a\n         * command sent by the driver.\n         * For example, uCode issues IWX_REPLY_RX when it sends a\n         * received frame to the driver.\n         */\n        if (handled && !(qid & (1 << 7))) {\n            iwx_cmd_done(sc, qid, idx, code);\n        }\n        \n        offset += roundup(len, IWX_FH_RSCSR_FRAME_ALIGN);\n        \n        if (sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210)\n            break;\n    }\n    \n    if (m0 && m0 != data->m && mbuf_type(m0) != MBUF_TYPE_FREE)\n        mbuf_freem(m0);\n}\n\nvoid ItlIwx::\niwx_notif_intr(struct iwx_softc *sc)\n{\n    struct mbuf_list ml = MBUF_LIST_INITIALIZER();\n    uint16_t hw;\n    \n    //    bus_dmamap_sync(sc->sc_dmat, sc->rxq.stat_dma.map,\n    //        0, sc->rxq.stat_dma.size, BUS_DMASYNC_POSTREAD);\n    \n    if (sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210)\n        hw = le16toh(*(uint16_t *)(sc->rxq.stat)) & 0xfff;\n    else\n        hw = le16toh(((struct iwx_rb_status *)sc->rxq.stat)->closed_rb_num) & 0xfff;\n    hw &= (IWX_RX_MQ_RING_COUNT - 1);\n    DPRINTFN(3, (\"%s hw=%d\\n\", __FUNCTION__, hw));\n    while (sc->rxq.cur != hw) {\n        struct iwx_rx_data *data = &sc->rxq.data[sc->rxq.cur];\n        iwx_rx_pkt(sc, data, &ml);\n        sc->rxq.cur = (sc->rxq.cur + 1) % IWX_RX_MQ_RING_COUNT;\n    }\n    if_input(&sc->sc_ic.ic_if, &ml);\n    \n    /*\n     * Tell the firmware what we have processed.\n     * Seems like the hardware gets upset unless we align the write by 8??\n     */\n    hw = (hw == 0) ? IWX_RX_MQ_RING_COUNT - 1 : hw - 1;\n    IWX_WRITE(sc, IWX_RFH_Q0_FRBDCB_WIDX_TRG, hw & ~7);\n}\n\nint ItlIwx::\niwx_intr(OSObject *object, IOInterruptEventSource* sender, int count)\n{\n//    XYLog(\"Interrupt!!!\\n\");\n    ItlIwx *that = (ItlIwx*)object;\n    struct iwx_softc *sc = &that->com;\n    int handled = 0;\n    int r1, r2, rv = 0;\n    \n//    IWX_WRITE(&that->com, IWX_CSR_INT_MASK, 0);\n    \n    if (sc->sc_flags & IWX_FLAG_USE_ICT) {\n        uint32_t *ict = (uint32_t *)sc->ict_dma.vaddr;\n        int tmp;\n        \n        tmp = htole32(ict[sc->ict_cur]);\n        if (!tmp)\n            goto out_ena;\n        \n        /*\n         * ok, there was something.  keep plowing until we have all.\n         */\n        r1 = r2 = 0;\n        while (tmp) {\n            r1 |= tmp;\n            ict[sc->ict_cur] = 0;\n            sc->ict_cur = (sc->ict_cur+1) % IWX_ICT_COUNT;\n            tmp = htole32(ict[sc->ict_cur]);\n        }\n        \n        /* this is where the fun begins.  don't ask */\n        if (r1 == 0xffffffff)\n            r1 = 0;\n        \n        /* i am not expected to understand this */\n        if (r1 & 0xc0000)\n            r1 |= 0x8000;\n        r1 = (0xff & r1) | ((0xff00 & r1) << 16);\n    } else {\n        r1 = IWX_READ(sc, IWX_CSR_INT);\n        if (r1 == 0xffffffff || (r1 & 0xfffffff0) == 0xa5a5a5a0)\n            goto out;\n        r2 = IWX_READ(sc, IWX_CSR_FH_INT_STATUS);\n    }\n    if (r1 == 0 && r2 == 0) {\n        goto out_ena;\n    }\n    \n    IWX_WRITE(sc, IWX_CSR_INT, r1 | ~sc->sc_intmask);\n    \n    if (r1 & IWX_CSR_INT_BIT_ALIVE) {\n        int i;\n        \n        /* Firmware has now configured the RFH. */\n        for (i = 0; i < IWX_RX_MQ_RING_COUNT; i++)\n            that->iwx_update_rx_desc(sc, &sc->rxq, i);\n        IWX_WRITE(sc, IWX_RFH_Q0_FRBDCB_WIDX_TRG, 8);\n    }\n    \n    handled |= (r1 & (IWX_CSR_INT_BIT_ALIVE /*| IWX_CSR_INT_BIT_SCD*/));\n    \n    if (r1 & IWX_CSR_INT_BIT_RF_KILL) {\n        handled |= IWX_CSR_INT_BIT_RF_KILL;\n        XYLog(\"%s RF_KILL has been toggled\\n\", __FUNCTION__);\n        that->iwx_check_rfkill(sc);\n        task_add(systq, &sc->init_task);\n        rv = 1;\n        goto out_ena;\n    }\n    \n    if (r1 & IWX_CSR_INT_BIT_SW_ERR) {\n#if 1 /* usually #ifdef IWX_DEBUG but always enabled for now */\n        int i;\n        \n        that->iwx_nic_error(sc);\n        \n        /* Dump driver status (TX and RX rings) while we're here. */\n        XYLog(\"driver status:\\n\");\n        for (i = 0; i < IWX_MAX_QUEUES; i++) {\n            struct iwx_tx_ring *ring = &sc->txq[i];\n            XYLog(\"  tx ring %2d: qid=%-2d cur=%-3d \"\n                  \"queued=%-3d\\n\",\n                  i, ring->qid, ring->cur, ring->queued);\n        }\n        XYLog(\"  rx ring: cur=%d\\n\", sc->rxq.cur);\n        XYLog(\"  802.11 state %s\\n\",\n              ieee80211_state_name[sc->sc_ic.ic_state]);\n#endif\n        \n        XYLog(\"%s: fatal firmware error\\n\", DEVNAME(sc));\n        if ((sc->sc_flags & IWX_FLAG_SHUTDOWN) == 0)\n            task_add(systq, &sc->init_task);\n        rv = 1;\n        goto out;\n        \n    }\n    \n    if (r1 & IWX_CSR_INT_BIT_HW_ERR) {\n        handled |= IWX_CSR_INT_BIT_HW_ERR;\n        XYLog(\"%s: hardware error, stopping device \\n\", DEVNAME(sc));\n        if ((sc->sc_flags & IWX_FLAG_SHUTDOWN) == 0) {\n            sc->sc_flags |= IWX_FLAG_HW_ERR;\n            task_add(systq, &sc->init_task);\n        }\n        rv = 1;\n        goto out;\n    }\n    \n    /* firmware chunk loaded */\n    if (r1 & IWX_CSR_INT_BIT_FH_TX) {\n        IWX_WRITE(sc, IWX_CSR_FH_INT_STATUS, IWX_CSR_FH_INT_TX_MASK);\n        handled |= IWX_CSR_INT_BIT_FH_TX;\n        \n        sc->sc_fw_chunk_done = 1;\n        that->wakeupOn(&sc->sc_fw);\n    }\n    \n    if (r1 & (IWX_CSR_INT_BIT_FH_RX | IWX_CSR_INT_BIT_SW_RX |\n              IWX_CSR_INT_BIT_RX_PERIODIC)) {\n        if (r1 & (IWX_CSR_INT_BIT_FH_RX | IWX_CSR_INT_BIT_SW_RX)) {\n            handled |= (IWX_CSR_INT_BIT_FH_RX | IWX_CSR_INT_BIT_SW_RX);\n            IWX_WRITE(sc, IWX_CSR_FH_INT_STATUS, IWX_CSR_FH_INT_RX_MASK);\n        }\n        if (r1 & IWX_CSR_INT_BIT_RX_PERIODIC) {\n            handled |= IWX_CSR_INT_BIT_RX_PERIODIC;\n            IWX_WRITE(sc, IWX_CSR_INT, IWX_CSR_INT_BIT_RX_PERIODIC);\n        }\n        \n        /* Disable periodic interrupt; we use it as just a one-shot. */\n        IWX_WRITE_1(sc, IWX_CSR_INT_PERIODIC_REG, IWX_CSR_INT_PERIODIC_DIS);\n        \n        /*\n         * Enable periodic interrupt in 8 msec only if we received\n         * real RX interrupt (instead of just periodic int), to catch\n         * any dangling Rx interrupt.  If it was just the periodic\n         * interrupt, there was no dangling Rx activity, and no need\n         * to extend the periodic interrupt; one-shot is enough.\n         */\n        if (r1 & (IWX_CSR_INT_BIT_FH_RX | IWX_CSR_INT_BIT_SW_RX))\n            IWX_WRITE_1(sc, IWX_CSR_INT_PERIODIC_REG,\n                        IWX_CSR_INT_PERIODIC_ENA);\n        \n        that->iwx_notif_intr(sc);\n    }\n    \n    rv = 1;\n    \nout_ena:\n    that->iwx_restore_interrupts(sc);\nout:\n    return rv;\n}\n\nint ItlIwx::\niwx_intr_msix(OSObject *object, IOInterruptEventSource* sender, int count)\n{\n//    XYLog(\"Interrupt!!!\\n\");\n    ItlIwx *that = (ItlIwx*)object;\n    struct iwx_softc *sc = &that->com;\n    uint32_t inta_fh, inta_hw;\n    int vector = 0;\n    \n    inta_fh = IWX_READ(sc, IWX_CSR_MSIX_FH_INT_CAUSES_AD);\n    inta_hw = IWX_READ(sc, IWX_CSR_MSIX_HW_INT_CAUSES_AD);\n    IWX_WRITE(sc, IWX_CSR_MSIX_FH_INT_CAUSES_AD, inta_fh);\n    IWX_WRITE(sc, IWX_CSR_MSIX_HW_INT_CAUSES_AD, inta_hw);\n    inta_fh &= sc->sc_fh_mask;\n    inta_hw &= sc->sc_hw_mask;\n    \n    if (inta_fh & IWX_MSIX_FH_INT_CAUSES_Q0 ||\n        inta_fh & IWX_MSIX_FH_INT_CAUSES_Q1) {\n        that->iwx_notif_intr(sc);\n    }\n    \n    /* firmware chunk loaded */\n    if (inta_fh & IWX_MSIX_FH_INT_CAUSES_D2S_CH0_NUM) {\n        sc->sc_fw_chunk_done = 1;\n        that->wakeupOn(&sc->sc_fw);\n    }\n    \n    if ((inta_fh & IWX_MSIX_FH_INT_CAUSES_FH_ERR) ||\n        (inta_hw & IWX_MSIX_HW_INT_CAUSES_REG_SW_ERR) ||\n        (inta_hw & IWX_MSIX_HW_INT_CAUSES_REG_SW_ERR_V2)) {\n#if 1 /* usually #ifdef IWX_DEBUG but always enabled for now */\n        int i;\n        \n        that->iwx_nic_error(sc);\n        \n        /* Dump driver status (TX and RX rings) while we're here. */\n        XYLog(\"driver status:\\n\");\n        for (i = 0; i < IWX_MAX_QUEUES; i++) {\n            struct iwx_tx_ring *ring = &sc->txq[i];\n            XYLog(\"  tx ring %2d: qid=%-2d cur=%-3d \"\n                  \"queued=%-3d\\n\",\n                  i, ring->qid, ring->cur, ring->queued);\n        }\n        XYLog(\"  rx ring: cur=%d\\n\", sc->rxq.cur);\n        XYLog(\"  802.11 state %s\\n\",\n              ieee80211_state_name[sc->sc_ic.ic_state]);\n#endif\n        \n        XYLog(\"%s: fatal firmware error\\n\", DEVNAME(sc));\n        if ((sc->sc_flags & IWX_FLAG_SHUTDOWN) == 0)\n            task_add(systq, &sc->init_task);\n        return 1;\n    }\n    \n    if (inta_hw & IWX_MSIX_HW_INT_CAUSES_REG_RF_KILL) {\n        that->iwx_check_rfkill(sc);\n        task_add(systq, &sc->init_task);\n    }\n    \n    if (inta_hw & IWX_MSIX_HW_INT_CAUSES_REG_HW_ERR) {\n        XYLog(\"%s: hardware error, stopping device \\n\", DEVNAME(sc));\n        if ((sc->sc_flags & IWX_FLAG_SHUTDOWN) == 0) {\n            sc->sc_flags |= IWX_FLAG_HW_ERR;\n            task_add(systq, &sc->init_task);\n        }\n        return 1;\n    }\n    \n    if (inta_hw & IWX_MSIX_HW_INT_CAUSES_REG_ALIVE) {\n        int i;\n        \n        /* Firmware has now configured the RFH. */\n        for (i = 0; i < IWX_RX_MQ_RING_COUNT; i++)\n            that->iwx_update_rx_desc(sc, &sc->rxq, i);\n        IWX_WRITE(sc, IWX_RFH_Q0_FRBDCB_WIDX_TRG, 8);\n    }\n    \n    /*\n     * Before sending the interrupt the HW disables it to prevent\n     * a nested interrupt. This is done by writing 1 to the corresponding\n     * bit in the mask register. After handling the interrupt, it should be\n     * re-enabled by clearing this bit. This register is defined as\n     * write 1 clear (W1C) register, meaning that it's being clear\n     * by writing 1 to the bit.\n     */\n    IWX_WRITE(sc, IWX_CSR_MSIX_AUTOMASK_ST_AD, 1 << vector);\n    return 1;\n}\n\n#define PCI_VENDOR_INTEL 0x8086\n\n#define IWL_PCI_DEVICE(dev, subdev, cfg) \\\n.pm_vid = PCI_VENDOR_INTEL,  .pm_pid = (dev), \\\n.pm_sub_vid = PCI_ANY_ID, .pm_sub_dev = (subdev), \\\n.drv_data = (void *)&(cfg)\n\n/*\n * If the device doesn't support HE, no need to have that many buffers.\n * 22000 devices can split multiple frames into a single RB, so fewer are\n * needed; AX210 cannot (but use smaller RBs by default) - these sizes\n * were picked according to 8 MSDUs inside 256 A-MSDUs in an A-MPDU, with\n * additional overhead to account for processing time.\n */\n#define IWL_NUM_RBDS_NON_HE        512\n#define IWL_NUM_RBDS_22000_HE        2048\n#define IWL_NUM_RBDS_AX210_HE        4096\n\n/*\n * A-MPDU buffer sizes\n * According to HT size varies from 8 to 64 frames\n * HE adds the ability to have up to 256 frames.\n */\n#define IEEE80211_MIN_AMPDU_BUF        0x8\n#define IEEE80211_MAX_AMPDU_BUF_HT    0x40\n#define IEEE80211_MAX_AMPDU_BUF        0x100\n\nconst struct iwl_cfg_trans_params iwl_qu_trans_cfg = {\n    .device_family = IWX_DEVICE_FAMILY_22000,\n    .integrated = 1,\n    .xtal_latency = 5000,\n    .ltr_delay = IWX_SOC_FLAGS_LTR_APPLY_DELAY_200,\n};\n\nconst struct iwl_cfg_trans_params iwl_qu_medium_latency_trans_cfg = {\n    .device_family = IWX_DEVICE_FAMILY_22000,\n    .integrated = 1,\n    .xtal_latency = 1820,\n    .ltr_delay = IWX_SOC_FLAGS_LTR_APPLY_DELAY_1820,\n};\n\nconst struct iwl_cfg_trans_params iwl_qu_long_latency_trans_cfg = {\n    .device_family = IWX_DEVICE_FAMILY_22000,\n    .integrated = 1,\n    .xtal_latency = 12000,\n    .low_latency_xtal = true,\n    .ltr_delay = IWX_SOC_FLAGS_LTR_APPLY_DELAY_2500,\n};\n\nconst struct iwl_cfg_trans_params iwl_qnj_trans_cfg = {\n    .device_family = IWX_DEVICE_FAMILY_22000,\n};\n\nconst struct iwl_cfg_trans_params iwl_snj_trans_cfg = {\n    .device_family = IWX_DEVICE_FAMILY_AX210,\n};\n\nconst struct iwl_cfg_trans_params iwl_so_trans_cfg = {\n    .device_family = IWX_DEVICE_FAMILY_AX210,\n    .integrated = 1,\n    .xtal_latency = 500,\n    .ltr_delay = IWX_SOC_FLAGS_LTR_APPLY_DELAY_200,\n};\n\nconst struct iwl_cfg_trans_params iwl_so_long_latency_trans_cfg = {\n    .device_family = IWX_DEVICE_FAMILY_AX210,\n    .integrated = 1,\n    .xtal_latency = 12000,\n    .ltr_delay = IWX_SOC_FLAGS_LTR_APPLY_DELAY_2500,\n};\n\nconst struct iwl_cfg_trans_params iwl_ma_trans_cfg = {\n    .device_family = IWX_DEVICE_FAMILY_AX210,\n    .integrated = 1,\n};\n\nconst struct iwl_cfg_trans_params iwl_ax200_trans_cfg = {\n    .device_family = IWX_DEVICE_FAMILY_22000,\n    .bisr_workaround = 1,\n};\n\nconst struct iwl_cfg iwlax210_2ax_cfg_so_jf_a0 = {\n    .name = \"Intel(R) Wireless-AC 9560 160MHz\",\n    .fwname = \"iwlwifi-so-a0-jf-b0-68.ucode\",\n    .device_family = IWX_DEVICE_FAMILY_AX210,\n    .num_rbds = IWL_NUM_RBDS_NON_HE,\n};\n\nconst struct iwl_cfg iwlax210_2ax_cfg_so_hr_a0 = {\n    .name = \"Intel(R) Wi-Fi 6 AX210 160MHz\",\n    .fwname = \"iwlwifi-so-a0-hr-b0-68.ucode\",\n    .device_family = IWX_DEVICE_FAMILY_AX210,\n    .num_rbds = IWL_NUM_RBDS_AX210_HE,\n};\n\nconst struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0 = {\n    .name = \"Intel(R) Wi-Fi 6 AX211 160MHz\",\n    .fwname = \"iwlwifi-so-a0-gf-a0-68.ucode\",\n    .uhb_supported = 1,\n    .device_family = IWX_DEVICE_FAMILY_AX210,\n    .num_rbds = IWL_NUM_RBDS_AX210_HE,\n};\n\nconst struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0_long = {\n    .name = \"Intel(R) Wi-Fi 6 AX211 160MHz\",\n    .fwname = \"iwlwifi-so-a0-gf-a0-68.ucode\",\n    .uhb_supported = 1,\n    .device_family = IWX_DEVICE_FAMILY_AX210,\n    .trans.xtal_latency = 12000,\n    .trans.low_latency_xtal = 1,\n    .num_rbds = IWL_NUM_RBDS_AX210_HE,\n};\n\nconst struct iwl_cfg iwlax210_2ax_cfg_ty_gf_a0 = {\n    .name = \"Intel(R) Wi-Fi 6 AX210 160MHz\",\n    .fwname = \"iwlwifi-ty-a0-gf-a0-68.ucode\",\n    .uhb_supported = 1,\n    .device_family = IWX_DEVICE_FAMILY_AX210,\n    .num_rbds = IWL_NUM_RBDS_AX210_HE,\n};\n\nconst struct iwl_cfg iwlax411_2ax_cfg_so_gf4_a0 = {\n    .name = \"Intel(R) Wi-Fi 6 AX411 160MHz\",\n    .fwname = \"iwlwifi-so-a0-gf4-a0-68.ucode\",\n    .uhb_supported = 1,\n    .device_family = IWX_DEVICE_FAMILY_AX210,\n    .num_rbds = IWL_NUM_RBDS_AX210_HE,\n};\n\nconst struct iwl_cfg iwlax411_2ax_cfg_so_gf4_a0_long = {\n    .name = \"Intel(R) Wi-Fi 6 AX411 160MHz\",\n    .fwname = \"iwlwifi-so-a0-gf4-a0-68.ucode\",\n    .uhb_supported = 1,\n    .device_family = IWX_DEVICE_FAMILY_AX210,\n    .trans.xtal_latency = 12000,\n    .trans.low_latency_xtal = 1,\n    .num_rbds = IWL_NUM_RBDS_AX210_HE,\n};\n\nconst struct iwl_cfg iwlax411_2ax_cfg_sosnj_gf4_a0 = {\n    .name = \"Intel(R) Wi-Fi 6 AX411 160MHz\",\n    .fwname = \"iwlwifi-SoSnj-a0-gf4-a0-63.ucode\",\n    .uhb_supported = 1,\n    .device_family = IWX_DEVICE_FAMILY_AX210,\n    .num_rbds = IWL_NUM_RBDS_AX210_HE,\n};\n\nconst struct iwl_cfg iwlax211_cfg_snj_gf_a0 = {\n    .name = \"Intel(R) Wi-Fi 6 AX211 160MHz\",\n    .fwname = \"iwlwifi-SoSnj-a0-gf-a0-63.ucode\",\n    .uhb_supported = 1,\n    .device_family = IWX_DEVICE_FAMILY_AX210,\n    .num_rbds = IWL_NUM_RBDS_AX210_HE,\n};\n\nconst struct iwl_cfg iwl_cfg_snj_hr_b0 = {\n    .fwname = \"iwlwifi-SoSnj-a0-hr-b0-63.ucode\",\n    .uhb_supported = 1,\n    .device_family = IWX_DEVICE_FAMILY_AX210,\n    .num_rbds = IWL_NUM_RBDS_AX210_HE,\n};\n\nconst struct iwl_cfg iwl_cfg_snj_a0_jf_b0 = {\n    .fwname = \"iwlwifi-SoSnj-a0-jf-b0-63.ucode\",\n    .uhb_supported = 1,\n    .device_family = IWX_DEVICE_FAMILY_AX210,\n    .num_rbds = IWL_NUM_RBDS_AX210_HE,\n};\n\nconst struct iwl_cfg iwl_cfg_ma_a0_hr_b0 = {\n    .fwname = \"iwlwifi-ma-a0-hr-b0-63.ucode\",\n    .uhb_supported = 1,\n    .device_family = IWX_DEVICE_FAMILY_AX210,\n    .num_rbds = IWL_NUM_RBDS_AX210_HE,\n};\n\nconst struct iwl_cfg iwl_cfg_ma_a0_gf_a0 = {\n    .fwname = \"iwlwifi-ma-a0-gf-a0-63.ucode\",\n    .uhb_supported = 1,\n    .device_family = IWX_DEVICE_FAMILY_AX210,\n    .num_rbds = IWL_NUM_RBDS_AX210_HE,\n};\n\nconst struct iwl_cfg iwl_cfg_ma_a0_gf4_a0 = {\n    .fwname = \"iwlwifi-ma-a0-gf4-a0-63.ucode\",\n    .uhb_supported = 1,\n    .device_family = IWX_DEVICE_FAMILY_AX210,\n    .num_rbds = IWL_NUM_RBDS_AX210_HE,\n};\n\nconst struct iwl_cfg iwl_cfg_ma_a0_mr_a0 = {\n    .fwname = \"iwlwifi-ma-a0-mr-a0-63.ucode\",\n    .uhb_supported = 1,\n    .device_family = IWX_DEVICE_FAMILY_AX210,\n    .num_rbds = IWL_NUM_RBDS_AX210_HE,\n};\n\nconst struct iwl_cfg iwl_cfg_ma_a0_fm_a0 = {\n    .fwname = \"iwlwifi-ma-a0-fm-a0-63.ucode\",\n    .uhb_supported = 1,\n    .device_family = IWX_DEVICE_FAMILY_AX210,\n    .num_rbds = IWL_NUM_RBDS_AX210_HE,\n};\n\nconst struct iwl_cfg iwl_cfg_snj_a0_mr_a0 = {\n    .fwname = \"iwlwifi-SoSnj-a0-mr-a0-63.ucode\",\n    .uhb_supported = 1,\n    .device_family = IWX_DEVICE_FAMILY_AX210,\n    .num_rbds = IWL_NUM_RBDS_AX210_HE,\n};\n\nconst struct iwl_cfg iwl_cfg_so_a0_hr_a0 = {\n    .fwname = \"iwlwifi-so-a0-hr-b0-68.ucode\",\n    .device_family = IWX_DEVICE_FAMILY_AX210,\n    .num_rbds = IWL_NUM_RBDS_AX210_HE,\n};\n\nconst struct iwl_cfg iwl_cfg_quz_a0_hr_b0 = {\n    .fwname = \"iwlwifi-QuZ-a0-hr-b0-68.ucode\",\n    .device_family = IWX_DEVICE_FAMILY_22000,\n    /*\n     * This device doesn't support receiving BlockAck with a large bitmap\n     * so we need to restrict the size of transmitted aggregation to the\n     * HT size; mac80211 would otherwise pick the HE max (256) by default.\n     */\n    .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,\n    .num_rbds = IWL_NUM_RBDS_22000_HE,\n};\n\nstatic const struct pci_matchid iwx_devices[] = {\n    /* Qu devices */\n    {IWL_PCI_DEVICE(0x02F0, PCI_ANY_ID, iwl_qu_trans_cfg)},\n    {IWL_PCI_DEVICE(0x06F0, PCI_ANY_ID, iwl_qu_trans_cfg)},\n\n    {IWL_PCI_DEVICE(0x34F0, PCI_ANY_ID, iwl_qu_medium_latency_trans_cfg)},\n    {IWL_PCI_DEVICE(0x3DF0, PCI_ANY_ID, iwl_qu_medium_latency_trans_cfg)},\n    {IWL_PCI_DEVICE(0x4DF0, PCI_ANY_ID, iwl_qu_medium_latency_trans_cfg)},\n\n    {IWL_PCI_DEVICE(0x43F0, PCI_ANY_ID, iwl_qu_long_latency_trans_cfg)},\n    {IWL_PCI_DEVICE(0xA0F0, PCI_ANY_ID, iwl_qu_long_latency_trans_cfg)},\n\n    {IWL_PCI_DEVICE(0x2720, PCI_ANY_ID, iwl_qnj_trans_cfg)},\n\n    {IWL_PCI_DEVICE(0x2723, PCI_ANY_ID, iwl_ax200_trans_cfg)},\n    \n    /* So devices */\n    {IWL_PCI_DEVICE(0x2725, PCI_ANY_ID, iwl_so_trans_cfg)},\n    {IWL_PCI_DEVICE(0x2726, PCI_ANY_ID, iwl_snj_trans_cfg)},\n    {IWL_PCI_DEVICE(0x7A70, PCI_ANY_ID, iwl_so_long_latency_trans_cfg)},\n    {IWL_PCI_DEVICE(0x7AF0, PCI_ANY_ID, iwl_so_trans_cfg)},\n    {IWL_PCI_DEVICE(0x51F0, PCI_ANY_ID, iwl_so_long_latency_trans_cfg)},\n    {IWL_PCI_DEVICE(0x51F1, PCI_ANY_ID, iwl_so_long_latency_trans_cfg)},\n    {IWL_PCI_DEVICE(0x54F0, PCI_ANY_ID, iwl_so_long_latency_trans_cfg)},\n    {IWL_PCI_DEVICE(0x7F70, PCI_ANY_ID, iwl_so_trans_cfg)},\n    \n    /* Ma devices */\n    {IWL_PCI_DEVICE(0x2729, PCI_ANY_ID, iwl_ma_trans_cfg)},\n    {IWL_PCI_DEVICE(0x7E40, PCI_ANY_ID, iwl_ma_trans_cfg)},\n};\n\nstruct iwl_dev_info {\n    uint16_t device;\n    uint16_t subdevice;\n    uint16_t mac_type;\n    uint16_t rf_type;\n    uint8_t mac_step;\n    uint8_t rf_id;\n    uint8_t no_160;\n    uint8_t cores;\n    uint8_t cdb;\n    const struct iwl_cfg *cfg;\n    const char *name;\n};\n\n#define _IWL_DEV_INFO(_device, _subdevice, _mac_type, _mac_step, _rf_type, \\\n              _rf_id, _no_160, _cores, _cdb, _cfg, _name)           \\\n    { .device = (uint16_t)(_device), .subdevice = (uint16_t)(_subdevice), .cfg = &(_cfg),  \\\n      .name = _name, .mac_type = (uint16_t)_mac_type, .rf_type = (uint16_t)_rf_type,       \\\n      .no_160 = (uint8_t)_no_160, .cores = (uint8_t)_cores, .rf_id = (uint8_t)_rf_id,           \\\n      .mac_step = (uint8_t)_mac_step, .cdb = (uint8_t)_cdb }\n\n#define IWL_DEV_INFO(_device, _subdevice, _cfg, _name) \\\n    _IWL_DEV_INFO(_device, _subdevice, IWL_CFG_ANY, IWL_CFG_ANY,       \\\n              IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,  \\\n              IWL_CFG_NO_CDB, _cfg, _name)\n\nconst char iwl9162_name[] = \"Intel(R) Wireless-AC 9162\";\nconst char iwl9260_name[] = \"Intel(R) Wireless-AC 9260\";\nconst char iwl9260_1_name[] = \"Intel(R) Wireless-AC 9260-1\";\nconst char iwl9270_name[] = \"Intel(R) Wireless-AC 9270\";\nconst char iwl9461_name[] = \"Intel(R) Wireless-AC 9461\";\nconst char iwl9462_name[] = \"Intel(R) Wireless-AC 9462\";\nconst char iwl9560_name[] = \"Intel(R) Wireless-AC 9560\";\nconst char iwl9162_160_name[] = \"Intel(R) Wireless-AC 9162 160MHz\";\nconst char iwl9260_160_name[] = \"Intel(R) Wireless-AC 9260 160MHz\";\nconst char iwl9270_160_name[] = \"Intel(R) Wireless-AC 9270 160MHz\";\nconst char iwl9461_160_name[] = \"Intel(R) Wireless-AC 9461 160MHz\";\nconst char iwl9462_160_name[] = \"Intel(R) Wireless-AC 9462 160MHz\";\nconst char iwl9560_160_name[] = \"Intel(R) Wireless-AC 9560 160MHz\";\n\nconst char iwl9260_killer_1550_name[] =\n    \"Killer (R) Wireless-AC 1550 Wireless Network Adapter (9260NGW) 160MHz\";\nconst char iwl9560_killer_1550i_name[] =\n    \"Killer (R) Wireless-AC 1550i Wireless Network Adapter (9560NGW)\";\nconst char iwl9560_killer_1550i_160_name[] =\n    \"Killer(R) Wireless-AC 1550i Wireless Network Adapter (9560NGW) 160MHz\";\nconst char iwl9560_killer_1550s_name[] =\n    \"Killer (R) Wireless-AC 1550s Wireless Network Adapter (9560NGW)\";\nconst char iwl9560_killer_1550s_160_name[] =\n    \"Killer(R) Wireless-AC 1550s Wireless Network Adapter (9560D2W) 160MHz\";\n\nconst char iwl_ax101_name[] = \"Intel(R) Wi-Fi 6 AX101\";\nconst char iwl_ax200_name[] = \"Intel(R) Wi-Fi 6 AX200 160MHz\";\nconst char iwl_ax201_name[] = \"Intel(R) Wi-Fi 6 AX201 160MHz\";\nconst char iwl_ax203_name[] = \"Intel(R) Wi-Fi 6 AX203\";\nconst char iwl_ax211_name[] = \"Intel(R) Wi-Fi 6E AX211 160MHz\";\nconst char iwl_ax221_name[] = \"Intel(R) Wi-Fi 6E AX221 160MHz\";\nconst char iwl_ax231_name[] = \"Intel(R) Wi-Fi 6E AX231 160MHz\";\nconst char iwl_ax411_name[] = \"Intel(R) Wi-Fi 6E AX411 160MHz\";\nconst char iwl_bz_name[] = \"Intel(R) TBD Bz device\";\n\nconst char iwl_ax200_killer_1650w_name[] =\n    \"Killer(R) Wi-Fi 6 AX1650w 160MHz Wireless Network Adapter (200D2W)\";\nconst char iwl_ax200_killer_1650x_name[] =\n    \"Killer(R) Wi-Fi 6 AX1650x 160MHz Wireless Network Adapter (200NGW)\";\nconst char iwl_ax201_killer_1650s_name[] =\n    \"Killer(R) Wi-Fi 6 AX1650s 160MHz Wireless Network Adapter (201D2W)\";\nconst char iwl_ax201_killer_1650i_name[] =\n    \"Killer(R) Wi-Fi 6 AX1650i 160MHz Wireless Network Adapter (201NGW)\";\nconst char iwl_ax210_killer_1675w_name[] =\n    \"Killer(R) Wi-Fi 6E AX1675w 160MHz Wireless Network Adapter (210D2W)\";\nconst char iwl_ax210_killer_1675x_name[] =\n    \"Killer(R) Wi-Fi 6E AX1675x 160MHz Wireless Network Adapter (210NGW)\";\nconst char iwl_ax211_killer_1675s_name[] =\n    \"Killer(R) Wi-Fi 6E AX1675s 160MHz Wireless Network Adapter (211NGW)\";\nconst char iwl_ax211_killer_1675i_name[] =\n    \"Killer(R) Wi-Fi 6E AX1675i 160MHz Wireless Network Adapter (211NGW)\";\nconst char iwl_ax411_killer_1690s_name[] =\n    \"Killer(R) Wi-Fi 6E AX1690s 160MHz Wireless Network Adapter (411D2W)\";\nconst char iwl_ax411_killer_1690i_name[] =\n    \"Killer(R) Wi-Fi 6E AX1690i 160MHz Wireless Network Adapter (411NGW)\";\n\nconst struct iwl_cfg iwl_ax200_cfg_cc = {\n    .fwname = \"iwlwifi-cc-a0-68.ucode\",\n    .device_family = IWX_DEVICE_FAMILY_22000,\n    .tx_with_siso_diversity = 0,\n    .uhb_supported = 0,\n    /*\n     * This device doesn't support receiving BlockAck with a large bitmap\n     * so we need to restrict the size of transmitted aggregation to the\n     * HT size; mac80211 would otherwise pick the HE max (256) by default.\n     */\n    .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,\n    .num_rbds = IWL_NUM_RBDS_22000_HE,\n};\n\nconst struct iwl_cfg iwl_qnj_b0_hr_b0_cfg = {\n    .fwname = \"iwlwifi-QuQnj-b0-hr-b0-48.ucode\",\n    .device_family = IWX_DEVICE_FAMILY_22000,\n    .tx_with_siso_diversity = 0,\n    .uhb_supported = 0,\n    /*\n     * This device doesn't support receiving BlockAck with a large bitmap\n     * so we need to restrict the size of transmitted aggregation to the\n     * HT size; mac80211 would otherwise pick the HE max (256) by default.\n     */\n    .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,\n    .num_rbds = IWL_NUM_RBDS_22000_HE,\n};\n\nconst struct iwl_cfg iwlax210_2ax_cfg_so_jf_b0 = {\n    .name = \"Intel(R) Wireless-AC 9560 160MHz\",\n    .fwname = \"iwlwifi-so-a0-jf-b0-68.ucode\",\n    .device_family = IWX_DEVICE_FAMILY_AX210,\n    .num_rbds = IWL_NUM_RBDS_NON_HE,\n};\n\nconst struct iwl_cfg iwl_ax201_cfg_qu_hr = {\n    .name = \"Intel(R) Wi-Fi 6 AX201 160MHz\",\n    .fwname = \"iwlwifi-Qu-b0-hr-b0-68.ucode\",\n    .device_family = IWX_DEVICE_FAMILY_22000,\n    .tx_with_siso_diversity = 0,\n    .uhb_supported = 0,\n    /*\n     * This device doesn't support receiving BlockAck with a large bitmap\n     * so we need to restrict the size of transmitted aggregation to the\n     * HT size; mac80211 would otherwise pick the HE max (256) by default.\n     */\n    .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,\n    .num_rbds = IWL_NUM_RBDS_22000_HE,\n};\n\nconst struct iwl_cfg killer1650s_2ax_cfg_qu_b0_hr_b0 = {\n    .name = \"Killer(R) Wi-Fi 6 AX1650s 160MHz Wireless Network Adapter (201NGW)\",\n    .fwname = \"iwlwifi-Qu-b0-hr-b0-68.ucode\",\n    .device_family = IWX_DEVICE_FAMILY_22000,\n    /*\n     * This device doesn't support receiving BlockAck with a large bitmap\n     * so we need to restrict the size of transmitted aggregation to the\n     * HT size; mac80211 would otherwise pick the HE max (256) by default.\n     */\n    .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,\n    .num_rbds = IWL_NUM_RBDS_22000_HE,\n};\n\nconst struct iwl_cfg killer1650i_2ax_cfg_qu_b0_hr_b0 = {\n    .name = \"Killer(R) Wi-Fi 6 AX1650i 160MHz Wireless Network Adapter (201D2W)\",\n    .fwname = \"iwlwifi-Qu-b0-hr-b0-68.ucode\",\n    .device_family = IWX_DEVICE_FAMILY_22000,\n    /*\n     * This device doesn't support receiving BlockAck with a large bitmap\n     * so we need to restrict the size of transmitted aggregation to the\n     * HT size; mac80211 would otherwise pick the HE max (256) by default.\n     */\n    .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,\n    .num_rbds = IWL_NUM_RBDS_22000_HE,\n};\n\nconst struct iwl_cfg killer1650s_2ax_cfg_qu_c0_hr_b0 = {\n    .name = \"Killer(R) Wi-Fi 6 AX1650s 160MHz Wireless Network Adapter (201NGW)\",\n    .fwname = \"iwlwifi-Qu-c0-hr-b0-68.ucode\",\n    .device_family = IWX_DEVICE_FAMILY_22000,\n    /*\n     * This device doesn't support receiving BlockAck with a large bitmap\n     * so we need to restrict the size of transmitted aggregation to the\n     * HT size; mac80211 would otherwise pick the HE max (256) by default.\n     */\n    .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,\n    .num_rbds = IWL_NUM_RBDS_22000_HE,\n};\n\nconst struct iwl_cfg killer1650i_2ax_cfg_qu_c0_hr_b0 = {\n    .name = \"Killer(R) Wi-Fi 6 AX1650i 160MHz Wireless Network Adapter (201D2W)\",\n    .fwname = \"iwlwifi-Qu-c0-hr-b0-68.ucode\",\n    .device_family = IWX_DEVICE_FAMILY_22000,\n    /*\n     * This device doesn't support receiving BlockAck with a large bitmap\n     * so we need to restrict the size of transmitted aggregation to the\n     * HT size; mac80211 would otherwise pick the HE max (256) by default.\n     */\n    .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,\n    .num_rbds = IWL_NUM_RBDS_22000_HE,\n};\n\nconst struct iwl_cfg iwl_ax201_cfg_quz_hr = {\n    .name = \"Intel(R) Wi-Fi 6 AX201 160MHz\",\n    .fwname = \"iwlwifi-QuZ-a0-hr-b0-68.ucode\",\n    .device_family = IWX_DEVICE_FAMILY_22000,\n    .tx_with_siso_diversity = 0,\n    .uhb_supported = 0,\n    /*\n         * This device doesn't support receiving BlockAck with a large bitmap\n         * so we need to restrict the size of transmitted aggregation to the\n         * HT size; mac80211 would otherwise pick the HE max (256) by default.\n         */\n    .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,\n    .num_rbds = IWL_NUM_RBDS_22000_HE,\n};\n\nconst struct iwl_cfg iwl_ax1650s_cfg_quz_hr = {\n    .name = \"Killer(R) Wi-Fi 6 AX1650s 160MHz Wireless Network Adapter (201D2W)\",\n    .fwname = \"iwlwifi-QuZ-a0-hr-b0-68.ucode\",\n    .device_family = IWX_DEVICE_FAMILY_22000,\n    /*\n         * This device doesn't support receiving BlockAck with a large bitmap\n         * so we need to restrict the size of transmitted aggregation to the\n         * HT size; mac80211 would otherwise pick the HE max (256) by default.\n         */\n    .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,\n    .num_rbds = IWL_NUM_RBDS_22000_HE,\n};\n\nconst struct iwl_cfg iwl_ax1650i_cfg_quz_hr = {\n    .name = \"Killer(R) Wi-Fi 6 AX1650i 160MHz Wireless Network Adapter (201NGW)\",\n    .fwname = \"iwlwifi-QuZ-a0-hr-b0-68.ucode\",\n    .device_family = IWX_DEVICE_FAMILY_22000,\n    /*\n         * This device doesn't support receiving BlockAck with a large bitmap\n         * so we need to restrict the size of transmitted aggregation to the\n         * HT size; mac80211 would otherwise pick the HE max (256) by default.\n         */\n    .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,\n    .num_rbds = IWL_NUM_RBDS_22000_HE,\n};\n\n/*\n* All JF radio modules are part of the 9000 series, but the MAC part\n* looks more like 22000.  That's why this device is here, but called\n* 9560 nevertheless.\n*/\nconst struct iwl_cfg iwl9560_qu_b0_jf_b0_cfg = {\n    .fwname = \"iwlwifi-Qu-b0-jf-b0-68.ucode\",\n    .device_family = IWX_DEVICE_FAMILY_22000,\n    .tx_with_siso_diversity = 0,\n    .uhb_supported = 0,\n    .num_rbds = IWL_NUM_RBDS_NON_HE,\n};\n\nconst struct iwl_cfg iwl9560_qu_c0_jf_b0_cfg = {\n    .fwname = \"iwlwifi-Qu-c0-jf-b0-68.ucode\",\n    .device_family = IWX_DEVICE_FAMILY_22000,\n    .tx_with_siso_diversity = 0,\n    .uhb_supported = 0,\n    .num_rbds = IWL_NUM_RBDS_NON_HE,\n};\n\nconst struct iwl_cfg iwl9560_quz_a0_jf_b0_cfg = {\n    .fwname = \"iwlwifi-QuZ-a0-jf-b0-68.ucode\",\n    .device_family = IWX_DEVICE_FAMILY_22000,\n    .tx_with_siso_diversity = 0,\n    .uhb_supported = 0,\n    /*\n     * This device doesn't support receiving BlockAck with a large bitmap\n     * so we need to restrict the size of transmitted aggregation to the\n     * HT size; mac80211 would otherwise pick the HE max (256) by default.\n     */\n    .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,\n    .num_rbds = IWL_NUM_RBDS_NON_HE,\n};\n\nconst struct iwl_cfg iwl9560_qnj_b0_jf_b0_cfg = {\n    .fwname = \"iwlwifi-QuQnj-b0-jf-b0-48.ucode\",\n    .device_family = IWX_DEVICE_FAMILY_22000,\n    .tx_with_siso_diversity = 0,\n    .uhb_supported = 0,\n    /*\n     * This device doesn't support receiving BlockAck with a large bitmap\n     * so we need to restrict the size of transmitted aggregation to the\n     * HT size; mac80211 would otherwise pick the HE max (256) by default.\n     */\n    .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,\n    .num_rbds = IWL_NUM_RBDS_NON_HE,\n};\n\nconst struct iwl_cfg iwl_qu_b0_hr1_b0 = {\n    .fwname = \"iwlwifi-Qu-b0-hr-b0-68.ucode\",\n    .device_family = IWX_DEVICE_FAMILY_22000,\n    .tx_with_siso_diversity = 1,\n    .uhb_supported = 0,\n    /*\n     * This device doesn't support receiving BlockAck with a large bitmap\n     * so we need to restrict the size of transmitted aggregation to the\n     * HT size; mac80211 would otherwise pick the HE max (256) by default.\n     */\n    .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,\n    .num_rbds = IWL_NUM_RBDS_22000_HE,\n};\n\nconst struct iwl_cfg iwl_qu_b0_hr_b0 = {\n    .fwname = \"iwlwifi-Qu-b0-hr-b0-68.ucode\",\n    .device_family = IWX_DEVICE_FAMILY_22000,\n    .uhb_supported = 0,\n    /*\n     * This device doesn't support receiving BlockAck with a large bitmap\n     * so we need to restrict the size of transmitted aggregation to the\n     * HT size; mac80211 would otherwise pick the HE max (256) by default.\n     */\n    .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,\n    .num_rbds = IWL_NUM_RBDS_22000_HE,\n};\n\nconst struct iwl_cfg iwl_qu_c0_hr_b0 = {\n    .fwname = \"iwlwifi-Qu-c0-hr-b0-68.ucode\",\n    .device_family = IWX_DEVICE_FAMILY_22000,\n    .uhb_supported = 0,\n    /*\n     * This device doesn't support receiving BlockAck with a large bitmap\n     * so we need to restrict the size of transmitted aggregation to the\n     * HT size; mac80211 would otherwise pick the HE max (256) by default.\n     */\n    .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,\n    .num_rbds = IWL_NUM_RBDS_22000_HE,\n};\n\nconst struct iwl_cfg iwl_qu_c0_hr1_b0 = {\n    .fwname = \"iwlwifi-Qu-c0-hr-b0-68.ucode\",\n    .device_family = IWX_DEVICE_FAMILY_22000,\n    .tx_with_siso_diversity = 1,\n    .uhb_supported = 0,\n    /*\n     * This device doesn't support receiving BlockAck with a large bitmap\n     * so we need to restrict the size of transmitted aggregation to the\n     * HT size; mac80211 would otherwise pick the HE max (256) by default.\n     */\n    .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,\n    .num_rbds = IWL_NUM_RBDS_22000_HE,\n};\n\nconst struct iwl_cfg iwl_quz_a0_hr1_b0 = {\n    .fwname = \"iwlwifi-QuZ-a0-hr-b0-68.ucode\",\n    .device_family = IWX_DEVICE_FAMILY_22000,\n    .tx_with_siso_diversity = 1,\n    .uhb_supported = 0,\n    /*\n     * This device doesn't support receiving BlockAck with a large bitmap\n     * so we need to restrict the size of transmitted aggregation to the\n     * HT size; mac80211 would otherwise pick the HE max (256) by default.\n     */\n    .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,\n    .num_rbds = IWL_NUM_RBDS_22000_HE,\n};\n\nconst struct iwl_cfg iwl_ax201_cfg_qu_c0_hr_b0 = {\n    .name = \"Intel(R) Wi-Fi 6 AX201 160MHz\",\n    .fwname = \"iwlwifi-Qu-c0-hr-b0-68.ucode\",\n    .device_family = IWX_DEVICE_FAMILY_22000,\n    .tx_with_siso_diversity = 0,\n    .uhb_supported = 0,\n    /*\n     * This device doesn't support receiving BlockAck with a large bitmap\n     * so we need to restrict the size of transmitted aggregation to the\n     * HT size; mac80211 would otherwise pick the HE max (256) by default.\n     */\n    .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,\n    .num_rbds = IWL_NUM_RBDS_22000_HE,\n};\n\nstatic const struct iwl_dev_info iwl_dev_info_table[] = {\n    /* AX200 */\n    IWL_DEV_INFO(0x2723, IWL_CFG_ANY, iwl_ax200_cfg_cc, iwl_ax200_name),\n    IWL_DEV_INFO(0x2723, 0x1653, iwl_ax200_cfg_cc, iwl_ax200_killer_1650w_name),\n    IWL_DEV_INFO(0x2723, 0x1654, iwl_ax200_cfg_cc, iwl_ax200_killer_1650x_name),\n    IWL_DEV_INFO(0x51F0, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name),\n    IWL_DEV_INFO(0x51F0, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name),\n    IWL_DEV_INFO(0x51F1, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name),\n    IWL_DEV_INFO(0x54F0, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name),\n    IWL_DEV_INFO(0x54F0, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name),\n    IWL_DEV_INFO(0x7A70, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name),\n    IWL_DEV_INFO(0x7A70, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name),\n    IWL_DEV_INFO(0x7AF0, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name),\n    IWL_DEV_INFO(0x7AF0, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name),\n    \n    /* Qu with Hr */\n    IWL_DEV_INFO(0x43F0, 0x0070, iwl_ax201_cfg_qu_hr, NULL),\n    IWL_DEV_INFO(0x43F0, 0x0074, iwl_ax201_cfg_qu_hr, NULL),\n    IWL_DEV_INFO(0x43F0, 0x0078, iwl_ax201_cfg_qu_hr, NULL),\n    IWL_DEV_INFO(0x43F0, 0x007C, iwl_ax201_cfg_qu_hr, NULL),\n    IWL_DEV_INFO(0x43F0, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0, iwl_ax201_killer_1650s_name),\n    IWL_DEV_INFO(0x43F0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0, iwl_ax201_killer_1650i_name),\n    IWL_DEV_INFO(0x43F0, 0x2074, iwl_ax201_cfg_qu_hr, NULL),\n    IWL_DEV_INFO(0x43F0, 0x4070, iwl_ax201_cfg_qu_hr, NULL),\n    IWL_DEV_INFO(0xA0F0, 0x0070, iwl_ax201_cfg_qu_hr, NULL),\n    IWL_DEV_INFO(0xA0F0, 0x0074, iwl_ax201_cfg_qu_hr, NULL),\n    IWL_DEV_INFO(0xA0F0, 0x0078, iwl_ax201_cfg_qu_hr, NULL),\n    IWL_DEV_INFO(0xA0F0, 0x007C, iwl_ax201_cfg_qu_hr, NULL),\n    IWL_DEV_INFO(0xA0F0, 0x0A10, iwl_ax201_cfg_qu_hr, NULL),\n    IWL_DEV_INFO(0xA0F0, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0, NULL),\n    IWL_DEV_INFO(0xA0F0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0, NULL),\n    IWL_DEV_INFO(0xA0F0, 0x2074, iwl_ax201_cfg_qu_hr, NULL),\n    IWL_DEV_INFO(0xA0F0, 0x4070, iwl_ax201_cfg_qu_hr, NULL),\n    IWL_DEV_INFO(0xA0F0, 0x6074, iwl_ax201_cfg_qu_hr, NULL),\n    IWL_DEV_INFO(0x02F0, 0x0070, iwl_ax201_cfg_quz_hr, NULL),\n    IWL_DEV_INFO(0x02F0, 0x0074, iwl_ax201_cfg_quz_hr, NULL),\n    IWL_DEV_INFO(0x02F0, 0x6074, iwl_ax201_cfg_quz_hr, NULL),\n    IWL_DEV_INFO(0x02F0, 0x0078, iwl_ax201_cfg_quz_hr, NULL),\n    IWL_DEV_INFO(0x02F0, 0x007C, iwl_ax201_cfg_quz_hr, NULL),\n    IWL_DEV_INFO(0x02F0, 0x0310, iwl_ax201_cfg_quz_hr, NULL),\n    IWL_DEV_INFO(0x02F0, 0x1651, iwl_ax1650s_cfg_quz_hr, NULL),\n    IWL_DEV_INFO(0x02F0, 0x1652, iwl_ax1650i_cfg_quz_hr, NULL),\n    IWL_DEV_INFO(0x02F0, 0x2074, iwl_ax201_cfg_quz_hr, NULL),\n    IWL_DEV_INFO(0x02F0, 0x4070, iwl_ax201_cfg_quz_hr, NULL),\n    IWL_DEV_INFO(0x06F0, 0x0070, iwl_ax201_cfg_quz_hr, NULL),\n    IWL_DEV_INFO(0x06F0, 0x0074, iwl_ax201_cfg_quz_hr, NULL),\n    IWL_DEV_INFO(0x06F0, 0x0078, iwl_ax201_cfg_quz_hr, NULL),\n    IWL_DEV_INFO(0x06F0, 0x007C, iwl_ax201_cfg_quz_hr, NULL),\n    IWL_DEV_INFO(0x06F0, 0x0310, iwl_ax201_cfg_quz_hr, NULL),\n    IWL_DEV_INFO(0x06F0, 0x1651, iwl_ax1650s_cfg_quz_hr, NULL),\n    IWL_DEV_INFO(0x06F0, 0x1652, iwl_ax1650i_cfg_quz_hr, NULL),\n    IWL_DEV_INFO(0x06F0, 0x2074, iwl_ax201_cfg_quz_hr, NULL),\n    IWL_DEV_INFO(0x06F0, 0x4070, iwl_ax201_cfg_quz_hr, NULL),\n    IWL_DEV_INFO(0x34F0, 0x0070, iwl_ax201_cfg_qu_hr, NULL),\n    IWL_DEV_INFO(0x34F0, 0x0074, iwl_ax201_cfg_qu_hr, NULL),\n    IWL_DEV_INFO(0x34F0, 0x0078, iwl_ax201_cfg_qu_hr, NULL),\n    IWL_DEV_INFO(0x34F0, 0x007C, iwl_ax201_cfg_qu_hr, NULL),\n    IWL_DEV_INFO(0x34F0, 0x0310, iwl_ax201_cfg_qu_hr, NULL),\n    IWL_DEV_INFO(0x34F0, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0, NULL),\n    IWL_DEV_INFO(0x34F0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0, NULL),\n    IWL_DEV_INFO(0x34F0, 0x2074, iwl_ax201_cfg_qu_hr, NULL),\n    IWL_DEV_INFO(0x34F0, 0x4070, iwl_ax201_cfg_qu_hr, NULL),\n    \n    IWL_DEV_INFO(0x3DF0, 0x0070, iwl_ax201_cfg_qu_hr, NULL),\n    IWL_DEV_INFO(0x3DF0, 0x0074, iwl_ax201_cfg_qu_hr, NULL),\n    IWL_DEV_INFO(0x3DF0, 0x0078, iwl_ax201_cfg_qu_hr, NULL),\n    IWL_DEV_INFO(0x3DF0, 0x007C, iwl_ax201_cfg_qu_hr, NULL),\n    IWL_DEV_INFO(0x3DF0, 0x0310, iwl_ax201_cfg_qu_hr, NULL),\n    IWL_DEV_INFO(0x3DF0, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0, NULL),\n    IWL_DEV_INFO(0x3DF0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0, NULL),\n    IWL_DEV_INFO(0x3DF0, 0x2074, iwl_ax201_cfg_qu_hr, NULL),\n    IWL_DEV_INFO(0x3DF0, 0x4070, iwl_ax201_cfg_qu_hr, NULL),\n    \n    IWL_DEV_INFO(0x4DF0, 0x0070, iwl_ax201_cfg_qu_hr, NULL),\n    IWL_DEV_INFO(0x4DF0, 0x0074, iwl_ax201_cfg_qu_hr, NULL),\n    IWL_DEV_INFO(0x4DF0, 0x0078, iwl_ax201_cfg_qu_hr, NULL),\n    IWL_DEV_INFO(0x4DF0, 0x007C, iwl_ax201_cfg_qu_hr, NULL),\n    IWL_DEV_INFO(0x4DF0, 0x0310, iwl_ax201_cfg_qu_hr, NULL),\n    IWL_DEV_INFO(0x4DF0, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0, NULL),\n    IWL_DEV_INFO(0x4DF0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0, NULL),\n    IWL_DEV_INFO(0x4DF0, 0x2074, iwl_ax201_cfg_qu_hr, NULL),\n    IWL_DEV_INFO(0x4DF0, 0x4070, iwl_ax201_cfg_qu_hr, NULL),\n    IWL_DEV_INFO(0x4DF0, 0x6074, iwl_ax201_cfg_qu_hr, NULL),\n    \n    /* Qu with JF */\n    IWL_DEV_INFO(0x06f0, 0x1551, iwl9560_quz_a0_jf_b0_cfg, iwl9560_killer_1550s_160_name),\n    IWL_DEV_INFO(0x06f0, 0x1552, iwl9560_quz_a0_jf_b0_cfg, iwl9560_killer_1550i_160_name),\n\n    /* So with HR */\n    IWL_DEV_INFO(0x2725, 0x0090, iwlax211_2ax_cfg_so_gf_a0, NULL),\n    IWL_DEV_INFO(0x2725, 0x0020, iwlax210_2ax_cfg_ty_gf_a0, NULL),\n    IWL_DEV_INFO(0x2725, 0x2020, iwlax210_2ax_cfg_ty_gf_a0, NULL),\n    IWL_DEV_INFO(0x2725, 0x0024, iwlax210_2ax_cfg_ty_gf_a0, NULL),\n    IWL_DEV_INFO(0x2725, 0x0310, iwlax210_2ax_cfg_ty_gf_a0, NULL),\n    IWL_DEV_INFO(0x2725, 0x0510, iwlax210_2ax_cfg_ty_gf_a0, NULL),\n    IWL_DEV_INFO(0x2725, 0x0A10, iwlax210_2ax_cfg_ty_gf_a0, NULL),\n    IWL_DEV_INFO(0x2725, 0xE020, iwlax210_2ax_cfg_ty_gf_a0, NULL),\n    IWL_DEV_INFO(0x2725, 0xE024, iwlax210_2ax_cfg_ty_gf_a0, NULL),\n    IWL_DEV_INFO(0x2725, 0x4020, iwlax210_2ax_cfg_ty_gf_a0, NULL),\n    IWL_DEV_INFO(0x2725, 0x6020, iwlax210_2ax_cfg_ty_gf_a0, NULL),\n    IWL_DEV_INFO(0x2725, 0x6024, iwlax210_2ax_cfg_ty_gf_a0, NULL),\n    IWL_DEV_INFO(0x2725, 0x1673, iwlax210_2ax_cfg_ty_gf_a0, iwl_ax210_killer_1675w_name),\n    IWL_DEV_INFO(0x2725, 0x1674, iwlax210_2ax_cfg_ty_gf_a0, iwl_ax210_killer_1675x_name),\n    IWL_DEV_INFO(0x7A70, 0x0090, iwlax211_2ax_cfg_so_gf_a0_long, NULL),\n    IWL_DEV_INFO(0x7A70, 0x0098, iwlax211_2ax_cfg_so_gf_a0_long, NULL),\n    IWL_DEV_INFO(0x7A70, 0x00B0, iwlax411_2ax_cfg_so_gf4_a0_long, NULL),\n    IWL_DEV_INFO(0x7A70, 0x0310, iwlax211_2ax_cfg_so_gf_a0_long, NULL),\n    IWL_DEV_INFO(0x7A70, 0x0510, iwlax211_2ax_cfg_so_gf_a0_long, NULL),\n    IWL_DEV_INFO(0x7A70, 0x0A10, iwlax211_2ax_cfg_so_gf_a0_long, NULL),\n    IWL_DEV_INFO(0x7AF0, 0x0090, iwlax211_2ax_cfg_so_gf_a0, NULL),\n    IWL_DEV_INFO(0x7AF0, 0x0098, iwlax211_2ax_cfg_so_gf_a0, NULL),\n    IWL_DEV_INFO(0x7AF0, 0x00B0, iwlax411_2ax_cfg_so_gf4_a0, NULL),\n    IWL_DEV_INFO(0x7AF0, 0x0310, iwlax211_2ax_cfg_so_gf_a0, NULL),\n    IWL_DEV_INFO(0x7AF0, 0x0510, iwlax211_2ax_cfg_so_gf_a0, NULL),\n    IWL_DEV_INFO(0x7AF0, 0x0A10, iwlax211_2ax_cfg_so_gf_a0, NULL),\n    \n    /* SnJ with HR */\n    IWL_DEV_INFO(0x2725, 0x00B0, iwlax411_2ax_cfg_sosnj_gf4_a0, NULL),\n    IWL_DEV_INFO(0x2726, 0x0090, iwlax211_cfg_snj_gf_a0, NULL),\n    IWL_DEV_INFO(0x2726, 0x0098, iwlax211_cfg_snj_gf_a0, NULL),\n    IWL_DEV_INFO(0x2726, 0x00B0, iwlax411_2ax_cfg_sosnj_gf4_a0, NULL),\n    IWL_DEV_INFO(0x2726, 0x00B4, iwlax411_2ax_cfg_sosnj_gf4_a0, NULL),\n    IWL_DEV_INFO(0x2726, 0x0510, iwlax211_cfg_snj_gf_a0, NULL),\n    IWL_DEV_INFO(0x2726, 0x1651, iwl_cfg_snj_hr_b0, iwl_ax201_killer_1650s_name),\n    IWL_DEV_INFO(0x2726, 0x1652, iwl_cfg_snj_hr_b0, iwl_ax201_killer_1650i_name),\n    IWL_DEV_INFO(0x2726, 0x1691, iwlax411_2ax_cfg_sosnj_gf4_a0, iwl_ax411_killer_1690s_name),\n    IWL_DEV_INFO(0x2726, 0x1692, iwlax411_2ax_cfg_sosnj_gf4_a0, iwl_ax411_killer_1690i_name),\n    IWL_DEV_INFO(0x7F70, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name),\n    IWL_DEV_INFO(0x7F70, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name),\n    IWL_DEV_INFO(0x7AF0, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name),\n    IWL_DEV_INFO(0x7AF0, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name),\n    /* SO with GF2 */\n    IWL_DEV_INFO(0x2726, 0x1671, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675s_name),\n    IWL_DEV_INFO(0x2726, 0x1672, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675i_name),\n    IWL_DEV_INFO(0x51F0, 0x1671, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675s_name),\n    IWL_DEV_INFO(0x51F0, 0x1672, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675i_name),\n    IWL_DEV_INFO(0x54F0, 0x1671, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675s_name),\n    IWL_DEV_INFO(0x54F0, 0x1672, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675i_name),\n    IWL_DEV_INFO(0x7A70, 0x1671, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675s_name),\n    IWL_DEV_INFO(0x7A70, 0x1672, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675i_name),\n    IWL_DEV_INFO(0x7AF0, 0x1671, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675s_name),\n    IWL_DEV_INFO(0x7AF0, 0x1672, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675i_name),\n    IWL_DEV_INFO(0x7F70, 0x1671, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675s_name),\n    IWL_DEV_INFO(0x7F70, 0x1672, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675i_name),\n\n    /* MA with GF2 */\n    IWL_DEV_INFO(0x7E40, 0x1671, iwl_cfg_ma_a0_gf_a0, iwl_ax211_killer_1675s_name),\n    IWL_DEV_INFO(0x7E40, 0x1672, iwl_cfg_ma_a0_gf_a0, iwl_ax211_killer_1675i_name),\n\n    /* Qu with Jf */\n    /* Qu B step */\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_QU, IWX_SILICON_B_STEP,\n                  IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1,\n                  IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwl9560_qu_b0_jf_b0_cfg, iwl9461_160_name),\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_QU, IWX_SILICON_B_STEP,\n                  IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1,\n                  IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwl9560_qu_b0_jf_b0_cfg, iwl9461_name),\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_QU, IWX_SILICON_B_STEP,\n                  IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV,\n                  IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwl9560_qu_b0_jf_b0_cfg, iwl9462_160_name),\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_QU, IWX_SILICON_B_STEP,\n                  IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV,\n                  IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwl9560_qu_b0_jf_b0_cfg, iwl9462_name),\n    \n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_QU, IWX_SILICON_B_STEP,\n                  IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,\n                  IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwl9560_qu_b0_jf_b0_cfg, iwl9560_160_name),\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_QU, IWX_SILICON_B_STEP,\n                  IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,\n                  IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwl9560_qu_b0_jf_b0_cfg, iwl9560_name),\n    \n    _IWL_DEV_INFO(IWL_CFG_ANY, 0x1551,\n                  IWL_CFG_MAC_TYPE_QU, IWX_SILICON_B_STEP,\n                  IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,\n                  IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwl9560_qu_b0_jf_b0_cfg, iwl9560_killer_1550s_name),\n    _IWL_DEV_INFO(IWL_CFG_ANY, 0x1552,\n                  IWL_CFG_MAC_TYPE_QU, IWX_SILICON_B_STEP,\n                  IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,\n                  IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwl9560_qu_b0_jf_b0_cfg, iwl9560_killer_1550i_name),\n    \n    /* Qu C step */\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_QU, IWX_SILICON_C_STEP,\n                  IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1,\n                  IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwl9560_qu_c0_jf_b0_cfg, iwl9461_160_name),\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_QU, IWX_SILICON_C_STEP,\n                  IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1,\n                  IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwl9560_qu_c0_jf_b0_cfg, iwl9461_name),\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_QU, IWX_SILICON_C_STEP,\n                  IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV,\n                  IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwl9560_qu_c0_jf_b0_cfg, iwl9462_160_name),\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_QU, IWX_SILICON_C_STEP,\n                  IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV,\n                  IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwl9560_qu_c0_jf_b0_cfg, iwl9462_name),\n    \n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_QU, IWX_SILICON_C_STEP,\n                  IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,\n                  IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwl9560_qu_c0_jf_b0_cfg, iwl9560_160_name),\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_QU, IWX_SILICON_C_STEP,\n                  IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,\n                  IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwl9560_qu_c0_jf_b0_cfg, iwl9560_name),\n    \n    _IWL_DEV_INFO(IWL_CFG_ANY, 0x1551,\n                  IWL_CFG_MAC_TYPE_QU, IWX_SILICON_C_STEP,\n                  IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,\n                  IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwl9560_qu_c0_jf_b0_cfg, iwl9560_killer_1550s_name),\n    _IWL_DEV_INFO(IWL_CFG_ANY, 0x1552,\n                  IWL_CFG_MAC_TYPE_QU, IWX_SILICON_C_STEP,\n                  IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,\n                  IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwl9560_qu_c0_jf_b0_cfg, iwl9560_killer_1550i_name),\n    \n    /* QuZ */\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1,\n                  IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwl9560_quz_a0_jf_b0_cfg, iwl9461_160_name),\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1,\n                  IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwl9560_quz_a0_jf_b0_cfg, iwl9461_name),\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV,\n                  IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwl9560_quz_a0_jf_b0_cfg, iwl9462_160_name),\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV,\n                  IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwl9560_quz_a0_jf_b0_cfg, iwl9462_name),\n    \n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,\n                  IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwl9560_quz_a0_jf_b0_cfg, iwl9560_160_name),\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,\n                  IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwl9560_quz_a0_jf_b0_cfg, iwl9560_name),\n    \n    _IWL_DEV_INFO(IWL_CFG_ANY, 0x1551,\n                  IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,\n                  IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwl9560_quz_a0_jf_b0_cfg, iwl9560_killer_1550s_name),\n    _IWL_DEV_INFO(IWL_CFG_ANY, 0x1552,\n                  IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,\n                  IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwl9560_quz_a0_jf_b0_cfg, iwl9560_killer_1550i_name),\n    \n    /* QnJ */\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_QNJ, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1,\n                  IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwl9560_qnj_b0_jf_b0_cfg, iwl9461_160_name),\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_QNJ, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1,\n                  IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwl9560_qnj_b0_jf_b0_cfg, iwl9461_name),\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_QNJ, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV,\n                  IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwl9560_qnj_b0_jf_b0_cfg, iwl9462_160_name),\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_QNJ, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV,\n                  IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwl9560_qnj_b0_jf_b0_cfg, iwl9462_name),\n    \n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_QNJ, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,\n                  IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwl9560_qnj_b0_jf_b0_cfg, iwl9560_160_name),\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_QNJ, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,\n                  IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwl9560_qnj_b0_jf_b0_cfg, iwl9560_name),\n    \n    _IWL_DEV_INFO(IWL_CFG_ANY, 0x1551,\n                  IWL_CFG_MAC_TYPE_QNJ, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,\n                  IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwl9560_qnj_b0_jf_b0_cfg, iwl9560_killer_1550s_name),\n    _IWL_DEV_INFO(IWL_CFG_ANY, 0x1552,\n                  IWL_CFG_MAC_TYPE_QNJ, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,\n                  IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwl9560_qnj_b0_jf_b0_cfg, iwl9560_killer_1550i_name),\n    \n    /* Qu with Hr */\n    /* Qu B step */\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_QU, IWX_SILICON_B_STEP,\n                  IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY,\n                  IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,\n                  iwl_qu_b0_hr1_b0, iwl_ax101_name),\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_QU, IWX_SILICON_B_STEP,\n                  IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY,\n                  IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,\n                  iwl_qu_b0_hr_b0, iwl_ax203_name),\n    \n    /* Qu C step */\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_QU, IWX_SILICON_C_STEP,\n                  IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY,\n                  IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,\n                  iwl_qu_c0_hr1_b0, iwl_ax101_name),\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_QU, IWX_SILICON_C_STEP,\n                  IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY,\n                  IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,\n                  iwl_qu_c0_hr_b0, iwl_ax203_name),\n    \n    /* QuZ */\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY,\n                  IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,\n                  iwl_quz_a0_hr1_b0, iwl_ax101_name),\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_QUZ, IWX_SILICON_B_STEP,\n                  IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY,\n                  IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,\n                  iwl_cfg_quz_a0_hr_b0, iwl_ax203_name),\n    \n    /* QnJ with Hr */\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_QNJ, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY,\n                  IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,\n                  iwl_qnj_b0_hr_b0_cfg, iwl_ax201_name),\n    \n    /* SnJ with Jf */\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1,\n                  IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwl_cfg_snj_a0_jf_b0, iwl9461_160_name),\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1,\n                  IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwl_cfg_snj_a0_jf_b0, iwl9461_name),\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV,\n                  IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwl_cfg_snj_a0_jf_b0, iwl9462_160_name),\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV,\n                  IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwl_cfg_snj_a0_jf_b0, iwl9462_name),\n    \n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,\n                  IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwl_cfg_snj_a0_jf_b0, iwl9560_160_name),\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,\n                  IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwl_cfg_snj_a0_jf_b0, iwl9560_name),\n    \n    /* SnJ with Hr */\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY,\n                  IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,\n                  iwl_cfg_snj_hr_b0, iwl_ax101_name),\n    \n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY,\n                  IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,\n                  iwl_cfg_snj_hr_b0, iwl_ax201_name),\n    \n    /* Ma */\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_MA, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY,\n                  IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,\n                  iwl_cfg_ma_a0_hr_b0, iwl_ax201_name),\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_MA, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY,\n                  IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,\n                  iwl_cfg_ma_a0_gf_a0, iwl_ax211_name),\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_MA, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY,\n                  IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_CDB,\n                  iwl_cfg_ma_a0_gf4_a0, iwl_ax211_name),\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_MA, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_MR, IWL_CFG_ANY,\n                  IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,\n                  iwl_cfg_ma_a0_mr_a0, iwl_ax221_name),\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_MA, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY,\n                  IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,\n                  iwl_cfg_ma_a0_fm_a0, iwl_ax231_name),\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_MR, IWL_CFG_ANY,\n                  IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,\n                  iwl_cfg_snj_a0_mr_a0, iwl_ax221_name),\n    \n    /* So with Hr */\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY,\n                  IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,\n                  iwl_cfg_so_a0_hr_a0, iwl_ax203_name),\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY,\n                  IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,\n                  iwl_cfg_so_a0_hr_a0, iwl_ax101_name),\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY,\n                  IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,\n                  iwl_cfg_so_a0_hr_a0, iwl_ax201_name),\n    \n    /* So-F with Hr */\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY,\n                  IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,\n                  iwl_cfg_so_a0_hr_a0, iwl_ax203_name),\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY,\n                  IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,\n                  iwl_cfg_so_a0_hr_a0, iwl_ax101_name),\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY,\n                  IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,\n                  iwl_cfg_so_a0_hr_a0, iwl_ax201_name),\n    \n    /* So-F with Gf */\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY,\n                  IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,\n                  iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_name),\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY,\n                  IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_CDB,\n                  iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_name),\n    \n    /* SoF with JF2 */\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,\n                  IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwlax210_2ax_cfg_so_jf_b0, iwl9560_160_name),\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,\n                  IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwlax210_2ax_cfg_so_jf_b0, iwl9560_name),\n    \n    /* SoF with JF */\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1,\n                  IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwlax210_2ax_cfg_so_jf_b0, iwl9461_160_name),\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV,\n                  IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwlax210_2ax_cfg_so_jf_b0, iwl9462_160_name),\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1,\n                  IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwlax210_2ax_cfg_so_jf_b0, iwl9461_name),\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV,\n                  IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwlax210_2ax_cfg_so_jf_b0, iwl9462_name),\n    \n    /* So with GF */\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY,\n                  IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,\n                  iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_name),\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY,\n                  IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_CDB,\n                  iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_name),\n    \n    /* So with JF2 */\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,\n                  IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwlax210_2ax_cfg_so_jf_b0, iwl9560_160_name),\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,\n                  IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwlax210_2ax_cfg_so_jf_b0, iwl9560_name),\n    \n    /* So with JF */\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1,\n                  IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwlax210_2ax_cfg_so_jf_b0, iwl9461_160_name),\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV,\n                  IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwlax210_2ax_cfg_so_jf_b0, iwl9462_160_name),\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1,\n                  IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwlax210_2ax_cfg_so_jf_b0, iwl9461_name),\n    _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,\n                  IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,\n                  IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV,\n                  IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,\n                  iwlax210_2ax_cfg_so_jf_b0, iwl9462_name)\n};\n\nint ItlIwx::\niwx_match(IOPCIDevice *device)\n{\n    int devId = device->configRead16(kIOPCIConfigDeviceID);\n    return pci_matchbyid(PCI_VENDOR_INTEL, devId, iwx_devices,\n                         nitems(iwx_devices));\n}\n\nint ItlIwx::\niwx_preinit(struct iwx_softc *sc)\n{\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct _ifnet *ifp = IC2IFP(ic);\n    int err;\n    static int attached;\n    \n    err = iwx_prepare_card_hw(sc);\n    if (err) {\n        XYLog(\"%s: could not initialize hardware\\n\", DEVNAME(sc));\n        return err;\n    }\n    \n    if (attached) {\n        /* Update MAC in case the upper layers changed it. */\n        IEEE80211_ADDR_COPY(sc->sc_ic.ic_myaddr,\n                            ((struct arpcom *)ifp)->ac_enaddr);\n        return 0;\n    }\n    \n    err = iwx_start_hw(sc);\n    if (err) {\n        XYLog(\"%s: could not initialize hardware\\n\", DEVNAME(sc));\n        return err;\n    }\n    \n    err = iwx_run_init_mvm_ucode(sc, 1);\n    iwx_stop_device(sc);\n    if (err)\n        return err;\n    \n    /* Print version info and MAC address on first successful fw load. */\n    attached = 1;\n    XYLog(\"%s: hw rev 0x%x, fw ver %s, address %s\\n\",\n          DEVNAME(sc), sc->sc_hw_rev & IWX_CSR_HW_REV_TYPE_MSK,\n          sc->sc_fwver, ether_sprintf(sc->sc_nvm.hw_addr));\n    \n    if (sc->sc_nvm.sku_cap_11n_enable)\n        iwx_setup_ht_rates(sc);\n    \n    if (sc->sc_nvm.sku_cap_11ac_enable)\n        iwx_setup_vht_rates(sc);\n    \n    if (sc->sc_nvm.sku_cap_11ax_enable)\n        iwx_setup_he_rates(sc);\n    \n    /* not all hardware can do 5GHz band */\n    if (!sc->sc_nvm.sku_cap_band_52GHz_enable)\n        memset(&ic->ic_sup_rates[IEEE80211_MODE_11A], 0,\n               sizeof(ic->ic_sup_rates[IEEE80211_MODE_11A]));\n    \n    /* Configure channel information obtained from firmware. */\n    ieee80211_channel_init(ifp);\n    \n    /* Configure MAC address. */\n    err = if_setlladdr(ifp, ic->ic_myaddr);\n    if (err)\n        XYLog(\"%s: could not set MAC address (error %d)\\n\",\n                DEVNAME(sc), err);\n    \n    ieee80211_media_init(ifp);\n    \n    return 0;\n}\n\nvoid ItlIwx::\niwx_attach_hook(struct device *self)\n{\n    struct iwx_softc *sc = (struct iwx_softc *)self;\n    \n    iwx_preinit(sc);\n}\n\nbool ItlIwx::\nintrFilter(OSObject *object, IOFilterInterruptEventSource *src)\n{\n    ItlIwx *that = (ItlIwx*)object;\n    IWX_WRITE(&that->com, IWX_CSR_INT_MASK, 0);\n    return true;\n}\n\nbool ItlIwx::\niwx_attach(struct iwx_softc *sc, struct pci_attach_args *pa)\n{\n    pcireg_t reg, memtype;\n    struct ieee80211com *ic = &sc->sc_ic;\n    struct _ifnet *ifp = &ic->ic_if;\n    int err;\n    int txq_i, i, j;\n    \n    sc->sc_pct = pa->pa_pc;\n    sc->sc_pcitag = pa->pa_tag;\n    sc->sc_dmat = pa->pa_dmat;\n    \n    //    rw_init(&sc->ioctl_rwl, \"iwxioctl\");\n    \n    err = pci_get_capability(sc->sc_pct, sc->sc_pcitag,\n                             PCI_CAP_PCIEXPRESS, &sc->sc_cap_off, NULL);\n    if (err == 0) {\n        XYLog(\"%s: PCIe capability structure not found!\\n\",\n              DEVNAME(sc));\n        return false;\n    }\n    \n    /* Clear device-specific \"PCI retry timeout\" register (41h). */\n    reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0x40);\n    pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, reg & ~0xff00);\n\n    /* Enable bus-mastering and hardware bug workaround. */\n    reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, PCI_COMMAND_STATUS_REG);\n    reg |= PCI_COMMAND_MASTER_ENABLE;\n    /* if !MSI */\n    if (reg & PCI_COMMAND_INTERRUPT_DISABLE) {\n        reg &= ~PCI_COMMAND_INTERRUPT_DISABLE;\n    }\n    pci_conf_write(sc->sc_pct, sc->sc_pcitag, PCI_COMMAND_STATUS_REG, reg);\n    \n    memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, PCI_MAPREG_START);\n    err = pci_mapreg_map(pa, PCI_MAPREG_START, memtype, 0,\n                         &sc->sc_st, &sc->sc_sh, NULL, &sc->sc_sz, 0);\n    if (err) {\n        XYLog(\"%s: can't map mem space\\n\", DEVNAME(sc));\n        return false;\n    }\n    if (0) {\n        sc->sc_msix = 1;\n        XYLog(\"msix intr mode\\n\");\n    } else if (pci_intr_map_msi(pa, &sc->ih)) {\n        XYLog(\"%s: can't map interrupt\\n\", DEVNAME(sc));\n        return false;\n    }\n    \n    if (!sc->sc_msix) {\n        /* Hardware bug workaround. */\n        reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag,\n            PCI_COMMAND_STATUS_REG);\n        if (reg & PCI_COMMAND_INTERRUPT_DISABLE)\n            reg &= ~PCI_COMMAND_INTERRUPT_DISABLE;\n        pci_conf_write(sc->sc_pct, sc->sc_pcitag,\n            PCI_COMMAND_STATUS_REG, reg);\n    }\n    \n    int msiIntrIndex = -1;\n    for (int index = 0; ; index++)\n    {\n        int interruptType;\n        int ret = pa->pa_tag->getInterruptType(index, &interruptType);\n        if (ret != kIOReturnSuccess)\n            break;\n        if (interruptType & kIOInterruptTypePCIMessaged)\n        {\n            msiIntrIndex = index;\n            break;\n        }\n    }\n    if (msiIntrIndex == -1) {\n        XYLog(\"%s: can't find MSI interrupt controller\\n\", DEVNAME(sc));\n        return false;\n    }\n\n    if (sc->sc_msix)\n        sc->sc_ih =\n        IOFilterInterruptEventSource::filterInterruptEventSource(this,\n                                                                 (IOInterruptEventSource::Action)&ItlIwx::iwx_intr_msix,\n                                                                 &ItlIwx::intrFilter\n                                                                 ,pa->pa_tag, msiIntrIndex);\n    else\n        sc->sc_ih = IOFilterInterruptEventSource::filterInterruptEventSource(this,\n                                                                             (IOInterruptEventSource::Action)&ItlIwx::iwx_intr, &ItlIwx::intrFilter\n                                                                             ,pa->pa_tag, msiIntrIndex);\n    if (sc->sc_ih == NULL || pa->workloop->addEventSource(sc->sc_ih) != kIOReturnSuccess) {\n        XYLog(\"%s: can't establish interrupt\\n\", DEVNAME(sc));\n        return false;\n    }\n    sc->sc_ih->enable();\n    \n    /* Clear pending interrupts. */\n    IWX_WRITE(sc, IWX_CSR_INT_MASK, 0);\n    IWX_WRITE(sc, IWX_CSR_INT, ~0);\n    IWX_WRITE(sc, IWX_CSR_FH_INT_STATUS, ~0);\n    \n    sc->sc_hw_rev = IWX_READ(sc, IWX_CSR_HW_REV);\n    /*\n     * In the 8000 HW family the format of the 4 bytes of CSR_HW_REV have\n     * changed, and now the revision step also includes bit 0-1 (no more\n     * \"dash\" value). To keep hw_rev backwards compatible - we'll store it\n     * in the old format.\n     */\n    sc->sc_hw_rev = (sc->sc_hw_rev & 0xfff0) |\n    (IWX_CSR_HW_REV_STEP(sc->sc_hw_rev << 2) << 2);\n    sc->sc_hw_rf_id = IWX_READ(sc, IWX_CSR_HW_RF_ID);\n    uint16_t device = sc->sc_pcitag->configRead16(kIOPCIConfigDeviceID);\n    uint16_t subsystem_device = sc->sc_pcitag->configRead16(kIOPCIConfigSubSystemID);\n    uint16_t subsystem_vendor = sc->sc_pcitag->configRead16(kIOPCIConfigSubSystemVendorID);\n    sc->sc_hw_id = (device << 16) + subsystem_device;\n    pci_match(PCI_VENDOR_INTEL, device, subsystem_vendor, subsystem_device, iwx_devices,\n              nitems(iwx_devices), (void **)&com.sc_cfg_params);\n    if (!com.sc_cfg_params) {\n        XYLog(\"%s: Why??? unknown adapter type\\n\", DEVNAME(sc));\n        return false;\n    }\n    for (i = 0; i < ARRAY_SIZE(iwl_dev_info_table); i++) {\n        const struct iwl_dev_info *dev_info = &iwl_dev_info_table[i];\n        if ((dev_info->device == (u16)IWL_CFG_ANY ||\n             dev_info->device == device) &&\n            (dev_info->subdevice == (u16)IWL_CFG_ANY ||\n             dev_info->subdevice == subsystem_device) &&\n            (dev_info->mac_type == (u16)IWL_CFG_ANY ||\n             dev_info->mac_type ==\n             CSR_HW_REV_TYPE(sc->sc_hw_rev)) &&\n            (dev_info->mac_step == (u8)IWL_CFG_ANY ||\n             dev_info->mac_step ==\n             IWX_CSR_HW_REV_STEP(sc->sc_hw_rev)) &&\n            (dev_info->rf_type == (u16)IWL_CFG_ANY ||\n             dev_info->rf_type ==\n             CSR_HW_RFID_TYPE(sc->sc_hw_rf_id)) &&\n            (dev_info->cdb == IWL_CFG_NO_CDB ||\n             CSR_HW_RFID_IS_CDB(sc->sc_hw_rf_id)) &&\n            (dev_info->rf_id == (u8)IWL_CFG_ANY ||\n             dev_info->rf_id ==\n             IWL_SUBDEVICE_RF_ID(subsystem_device)) &&\n            (dev_info->no_160 == (u8)IWL_CFG_ANY ||\n             dev_info->no_160 ==\n             IWL_SUBDEVICE_NO_160(subsystem_device)) &&\n            (dev_info->cores == (u8)IWL_CFG_ANY ||\n             dev_info->cores ==\n             IWL_SUBDEVICE_CORES(subsystem_device))) {\n            sc->sc_cfg = dev_info->cfg;\n            if (dev_info->name)\n                XYLog(\"Found device: %s fw: %s index: %d:%zu\\n\", dev_info->name, dev_info->cfg->fwname, i, ARRAY_SIZE(iwl_dev_info_table));\n            else if (dev_info->cfg->name)\n                XYLog(\"Found device cfg: %s fw: %s index: %d:%zu\\n\", dev_info->cfg->name, dev_info->cfg->fwname, i, ARRAY_SIZE(iwl_dev_info_table));\n            else\n                XYLog(\"Found device: No Name fw: %s index: %d:%zu\\n\", dev_info->cfg->fwname, i, ARRAY_SIZE(iwl_dev_info_table));\n        }\n    }\n    /*\n     * Workaround for problematic SnJ device: sometimes when\n     * certain RF modules are connected to SnJ, the device ID\n     * changes to QnJ's ID.  So we are using QnJ's trans_cfg until\n     * here.  But if we detect that the MAC type is actually SnJ,\n     * we should switch to it here to avoid problems later.\n     */\n    if (CSR_HW_REV_TYPE(sc->sc_hw_rev) == IWL_CFG_MAC_TYPE_SNJ)\n        sc->sc_cfg_params = &iwl_so_trans_cfg;\n    \n    /*\n     * This is a hack to switch from Qu B0 to Qu C0.  We need to\n     * do this for all cfgs that use Qu B0, except for those using\n     * Jf, which have already been moved to the new table.  The\n     * rest must be removed once we convert Qu with Hr as well.\n     */\n    if (sc->sc_hw_rev == CSR_HW_REV_TYPE_QU_C0) {\n        if (sc->sc_cfg == &iwl_ax201_cfg_qu_hr)\n            sc->sc_cfg = &iwl_ax201_cfg_qu_c0_hr_b0;\n        else if (sc->sc_cfg == &killer1650s_2ax_cfg_qu_b0_hr_b0)\n            sc->sc_cfg = &killer1650s_2ax_cfg_qu_c0_hr_b0;\n        else if (sc->sc_cfg == &killer1650i_2ax_cfg_qu_b0_hr_b0)\n            sc->sc_cfg = &killer1650i_2ax_cfg_qu_c0_hr_b0;\n    }\n\n    /* same thing for QuZ... */\n    if (sc->sc_hw_rev == CSR_HW_REV_TYPE_QUZ) {\n        if (sc->sc_cfg == &iwl_ax201_cfg_qu_hr)\n            sc->sc_cfg = &iwl_ax201_cfg_quz_hr;\n        else if (sc->sc_cfg == &killer1650s_2ax_cfg_qu_b0_hr_b0)\n            sc->sc_cfg = &iwl_ax1650s_cfg_quz_hr;\n        else if (sc->sc_cfg == &killer1650i_2ax_cfg_qu_b0_hr_b0)\n            sc->sc_cfg = &iwl_ax1650i_cfg_quz_hr;\n    }\n    if (sc->sc_cfg == NULL) {\n        XYLog(\"No config found for PCI dev %04x/%04x, rev=0x%x, rfid=0x%x\\n\",\n              device, subsystem_device,\n              sc->sc_hw_rev, sc->sc_hw_rf_id);\n        return false;\n    }\n    XYLog(\"Found PCI dev %04x/%04x, rev=0x%x, rfid=0x%x fw: %s\\n\",\n          device, subsystem_device,\n          sc->sc_hw_rev, sc->sc_hw_rf_id, sc->sc_cfg->fwname);\n    sc->sc_fwname = sc->sc_cfg->fwname;\n    sc->sc_device_family = sc->sc_cfg->device_family;\n    sc->sc_integrated = sc->sc_cfg_params->integrated;\n    sc->sc_ltr_delay = sc->sc_cfg_params->ltr_delay;\n    sc->sc_low_latency_xtal = sc->sc_cfg_params->low_latency_xtal;\n    sc->sc_xtal_latency = sc->sc_cfg_params->xtal_latency;\n    sc->sc_tx_with_siso_diversity = sc->sc_cfg->tx_with_siso_diversity;\n    sc->sc_uhb_supported = sc->sc_cfg->uhb_supported;\n    \n    /* Allocate DMA memory for loading firmware. */\n    if (sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210)\n        err = iwx_dma_contig_alloc(sc->sc_dmat, &sc->ctxt_info_dma,\n                                   sizeof(struct iwx_context_info_gen3), 0);\n    else\n        err = iwx_dma_contig_alloc(sc->sc_dmat, &sc->ctxt_info_dma,\n                                   sizeof(struct iwx_context_info), 0);\n    if (err) {\n        XYLog(\"%s: could not allocate memory for loading firmware\\n\",\n              DEVNAME(sc));\n        return false;\n    }\n    \n    /* Allocate interrupt cause table (ICT).*/\n    err = iwx_dma_contig_alloc(sc->sc_dmat, &sc->ict_dma,\n                               IWX_ICT_SIZE, 1<<IWX_ICT_PADDR_SHIFT);\n    if (err) {\n        XYLog(\"%s: could not allocate ICT table\\n\", DEVNAME(sc));\n        goto fail0;\n    }\n    \n    for (txq_i = 0; txq_i < nitems(sc->txq); txq_i++) {\n        err = iwx_alloc_tx_ring(sc, &sc->txq[txq_i], txq_i);\n        if (err) {\n            XYLog(\"%s: could not allocate TX ring %d\\n\",\n                  DEVNAME(sc), txq_i);\n            goto fail4;\n        }\n    }\n    \n    err = iwx_alloc_rx_ring(sc, &sc->rxq);\n    if (err) {\n        XYLog(\"%s: could not allocate RX ring\\n\", DEVNAME(sc));\n        goto fail4;\n    }\n    \n    taskq_init();\n    sc->sc_nswq = taskq_create(\"iwxns\", 1, IPL_NET, 0);\n    if (sc->sc_nswq == NULL)\n        goto fail4;\n    \n    ic->ic_phytype = IEEE80211_T_OFDM;    /* not only, but not used */\n    ic->ic_opmode = IEEE80211_M_STA;    /* default to BSS mode */\n    ic->ic_state = IEEE80211_S_INIT;\n    \n    /* Set device capabilities. */\n    ic->ic_caps =\n    IEEE80211_C_WEP |        /* WEP */\n    IEEE80211_C_RSN |        /* WPA/RSN */\n    IEEE80211_C_SCANALL |    /* device scans all channels at once */\n    IEEE80211_C_SCANALLBAND |    /* device scans all bands at once */\n    IEEE80211_C_MONITOR |    /* monitor mode supported */\n    IEEE80211_C_SHSLOT |    /* short slot time supported */\n    IEEE80211_C_SHPREAMBLE;    /* short preamble supported */\n    \n    ic->ic_htcaps = IEEE80211_HTCAP_SGI20;\n    ic->ic_htcaps |=\n    (IEEE80211_HTCAP_SMPS_DIS << IEEE80211_HTCAP_SMPS_SHIFT);\n    ic->ic_htcaps |= (IEEE80211_HTCAP_CBW20_40 | IEEE80211_HTCAP_SGI40);\n    ic->ic_htcaps |= IEEE80211_HTCAP_LDPC;  /* all of the gen2/gen3 cards support LDPC */\n    ic->ic_htxcaps = 0;\n    ic->ic_txbfcaps = 0;\n    ic->ic_aselcaps = 0;\n    ic->ic_ampdu_params = (IEEE80211_AMPDU_PARAM_SS_4 | 0x3 /* 64k */);\n    ic->ic_caps |= (IEEE80211_C_QOS | IEEE80211_C_TX_AMPDU_SETUP_IN_HW | IEEE80211_C_TX_AMPDU | IEEE80211_C_AMSDU_IN_AMPDU);\n    ic->ic_caps |= IEEE80211_C_SUPPORTS_VHT_EXT_NSS_BW;\n    \n    ic->ic_sup_rates[IEEE80211_MODE_11A] = ieee80211_std_rateset_11a;\n    ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b;\n    ic->ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_std_rateset_11g;\n    \n    for (i = 0; i < nitems(sc->sc_phyctxt); i++) {\n        sc->sc_phyctxt[i].id = i;\n    }\n    \n    /* IBSS channel undefined for now. */\n    ic->ic_ibss_chan = &ic->ic_channels[1];\n    \n    ic->ic_max_rssi = IWX_MAX_DBM - IWX_MIN_DBM;\n    \n    ifp->if_softc = sc;\n    ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST | IFF_DEBUG;\n    ifp->if_ioctl = iwx_ioctl;\n    ifp->if_start = iwx_start;\n    ifp->if_watchdog = iwx_watchdog;\n    memcpy(ifp->if_xname, DEVNAME(sc), IFNAMSIZ);\n    \n    if_attach(ifp);\n    ieee80211_ifattach(ifp, getController());\n    ieee80211_media_init(ifp);\n    \n#if NBPFILTER > 0\n    iwx_radiotap_attach(sc);\n#endif\n    for (i = 0; i < nitems(sc->sc_rxba_data); i++) {\n        struct iwx_rxba_data *rxba = &sc->sc_rxba_data[i];\n        rxba->baid = IWX_RX_REORDER_DATA_INVALID_BAID;\n        rxba->sc = sc;\n        timeout_set(&rxba->session_timer, iwx_rx_ba_session_expired,\n                    rxba);\n        timeout_set(&rxba->reorder_buf.reorder_timer,\n                    iwx_reorder_timer_expired, &rxba->reorder_buf);\n        for (j = 0; j < nitems(rxba->entries); j++)\n        ml_init(&rxba->entries[j].frames);\n    }\n    task_set(&sc->init_task, iwx_init_task, sc, \"iwx_init_task\");\n    task_set(&sc->newstate_task, iwx_newstate_task, sc, \"iwx_newstate_task\");\n    task_set(&sc->ba_task, iwx_ba_task, sc, \"iwx_ba_task\");\n    task_set(&sc->mac_ctxt_task, iwx_mac_ctxt_task, sc, \"iwx_mac_ctxt_task\");\n    task_set(&sc->chan_ctxt_task, iwx_chan_ctxt_task, sc, \"iwx_chan_ctxt_task\");\n    \n    ic->ic_node_alloc = iwx_node_alloc;\n    ic->ic_bgscan_start = iwx_bgscan;\n    ic->ic_set_key = iwx_set_key;\n    ic->ic_delete_key = iwx_delete_key;\n    \n    /* Override 802.11 state transition machine. */\n    sc->sc_newstate = ic->ic_newstate;\n    ic->ic_newstate = iwx_newstate;\n    ic->ic_updateprot = iwx_updateprot;\n    ic->ic_updateslot = iwx_updateslot;\n    ic->ic_updateedca = iwx_updateedca;\n    ic->ic_updatedtim = iwx_updatedtim;\n    ic->ic_ampdu_rx_start = iwx_ampdu_rx_start;\n    ic->ic_ampdu_rx_stop = iwx_ampdu_rx_stop;\n    ic->ic_ampdu_tx_start = iwx_ampdu_tx_start;\n    ic->ic_ampdu_tx_stop = iwx_ampdu_tx_stop;\n    ic->ic_update_chw = iwx_update_chw;\n    /*\n     * We cannot read the MAC address without loading the\n     * firmware from disk. Postpone until mountroot is done.\n     */\n    //    config_mountroot(self, iwx_attach_hook);\n    if (iwx_preinit(sc)) {\n        goto fail5;\n    }\n    \n    return true;\n    \nfail5:\n    for (i = 0; i < nitems(sc->sc_rxba_data); i++) {\n        struct iwx_rxba_data *rxba = &sc->sc_rxba_data[i];\n        iwx_clear_reorder_buffer(sc, rxba);\n    }\nfail4:    while (--txq_i >= 0)\n    iwx_free_tx_ring(sc, &sc->txq[txq_i]);\n    iwx_free_rx_ring(sc, &sc->rxq);\nfail3:    if (sc->ict_dma.vaddr != NULL)\n    iwx_dma_contig_free(&sc->ict_dma);\n\nfail0:    iwx_dma_contig_free(&sc->ctxt_info_dma);\n    return false;\n}\n\n#if NBPFILTER > 0\nvoid ItlIwx::\niwx_radiotap_attach(struct iwx_softc *sc)\n{\n    bpfattach(&sc->sc_drvbpf, &sc->sc_ic.ic_if, DLT_IEEE802_11_RADIO,\n              sizeof (struct ieee80211_frame) + IEEE80211_RADIOTAP_HDRLEN);\n    \n    sc->sc_rxtap_len = sizeof sc->sc_rxtapu;\n    sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);\n    sc->sc_rxtap.wr_ihdr.it_present = htole32(IWX_RX_RADIOTAP_PRESENT);\n    \n    sc->sc_txtap_len = sizeof sc->sc_txtapu;\n    sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);\n    sc->sc_txtap.wt_ihdr.it_present = htole32(IWX_TX_RADIOTAP_PRESENT);\n}\n#endif\n\nvoid ItlIwx::\niwx_init_task(void *arg1)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct iwx_softc *sc = (struct iwx_softc *)arg1;\n    struct _ifnet *ifp = &sc->sc_ic.ic_if;\n    ItlIwx *that = container_of(sc, ItlIwx, com);\n    int s = splnet();\n    int generation = sc->sc_generation;\n    int fatal = (sc->sc_flags & (IWX_FLAG_HW_ERR | IWX_FLAG_RFKILL));\n    \n    //    rw_enter_write(&sc->ioctl_rwl);\n    if (generation != sc->sc_generation) {\n        //        rw_exit(&sc->ioctl_rwl);\n        splx(s);\n        return;\n    }\n    \n    if (ifp->if_flags & IFF_RUNNING)\n        that->iwx_stop(ifp);\n    else\n        sc->sc_flags &= ~IWX_FLAG_HW_ERR;\n    \n    if (!fatal && (ifp->if_flags & (IFF_UP | IFF_RUNNING)) == IFF_UP)\n        that->iwx_init(ifp);\n    \n    //    rw_exit(&sc->ioctl_rwl);\n    splx(s);\n}\n\nint ItlIwx::\niwx_resume(struct iwx_softc *sc)\n{\n    pcireg_t reg;\n    \n    /* Clear device-specific \"PCI retry timeout\" register (41h). */\n    reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0x40);\n    pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, reg & ~0xff00);\n    \n    if (!sc->sc_msix) {\n        /* Hardware bug workaround. */\n        reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag,\n                            PCI_COMMAND_STATUS_REG);\n        if (reg & PCI_COMMAND_INTERRUPT_DISABLE)\n            reg &= ~PCI_COMMAND_INTERRUPT_DISABLE;\n        pci_conf_write(sc->sc_pct, sc->sc_pcitag,\n                       PCI_COMMAND_STATUS_REG, reg);\n    }\n\n    iwx_enable_rfkill_int(sc);\n    iwx_check_rfkill(sc);\n\n    return iwx_prepare_card_hw(sc);\n}\n\nint ItlIwx::\niwx_activate(struct iwx_softc *sc, int act)\n{\n    struct _ifnet *ifp = &sc->sc_ic.ic_if;\n    int err = 0;\n    \n    switch (act) {\n        case DVACT_QUIESCE:\n            if (ifp->if_flags & IFF_RUNNING) {\n                //            rw_enter_write(&sc->ioctl_rwl);\n                iwx_stop(ifp);\n                //            rw_exit(&sc->ioctl_rwl);\n            }\n            break;\n        case DVACT_RESUME:\n            err = iwx_resume(sc);\n            if (err)\n                XYLog(\"%s: could not initialize hardware\\n\",\n                      DEVNAME(sc));\n            break;\n        case DVACT_WAKEUP:\n            /* Hardware should be up at this point. */\n            if (iwx_set_hw_ready(sc))\n                task_add(systq, &sc->init_task);\n            break;\n    }\n    \n    return 0;\n}\n"
  },
  {
    "path": "itlwm/hal_iwx/ItlIwx.hpp",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n/*    $OpenBSD: if_iwx.c,v 1.43 2020/08/02 11:11:07 stsp Exp $    */\n\n/*\n * Copyright (c) 2014, 2016 genua gmbh <info@genua.de>\n *   Author: Stefan Sperling <stsp@openbsd.org>\n * Copyright (c) 2014 Fixup Software Ltd.\n * Copyright (c) 2017, 2019, 2020 Stefan Sperling <stsp@openbsd.org>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n/*-\n * Based on BSD-licensed source modules in the Linux iwlwifi driver,\n * which were used as the reference documentation for this implementation.\n *\n ******************************************************************************\n *\n * This file is provided under a dual BSD/GPLv2 license.  When using or\n * redistributing this file, you may do so under either license.\n *\n * GPL LICENSE SUMMARY\n *\n * Copyright(c) 2017 Intel Deutschland GmbH\n * Copyright(c) 2018 - 2019 Intel Corporation\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of version 2 of the GNU General Public License as\n * published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful, but\n * WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * General Public License for more details.\n *\n * BSD LICENSE\n *\n * Copyright(c) 2017 Intel Deutschland GmbH\n * Copyright(c) 2018 - 2019 Intel Corporation\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in\n *    the documentation and/or other materials provided with the\n *    distribution.\n *  * Neither the name Intel Corporation nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n *****************************************************************************\n */\n\n/*-\n * Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n#ifndef _ITLWMX_H\n#define _ITLWMX_H\n#include <compat.h>\n#include <linux/kernel.h>\n\n#include <sys/param.h>\n#include <sys/conf.h>\n#include <sys/kernel.h>\n#include <sys/malloc.h>\n#include <sys/mbuf.h>\n#include <sys/proc.h>\n#include <sys/socket.h>\n#include <sys/sockio.h>\n#include <sys/systm.h>\n#include <sys/endian.h>\n#include <sys/kpi_mbuf.h>\n\n#include \"if_iwxreg.h\"\n#include \"if_iwxvar.h\"\n#include <sys/pcireg.h>\n\n#include <IOKit/network/IOEthernetController.h>\n#include <IOKit/IOWorkLoop.h>\n#include <IOKit/network/IOGatedOutputQueue.h>\n#include <libkern/c++/OSString.h>\n#include <IOKit/IOService.h>\n#include <IOKit/pci/IOPCIDevice.h>\n#include <IOKit/IOLib.h>\n#include <libkern/OSKextLib.h>\n#include <libkern/c++/OSMetaClass.h>\n#include <IOKit/IOFilterInterruptEventSource.h>\n\n#include <HAL/ItlHalService.hpp>\n#include <HAL/ItlDriverInfo.hpp>\n#include <HAL/ItlDriverController.hpp>\n\nclass ItlIwx : public ItlHalService, ItlDriverInfo, ItlDriverController {\n    OSDeclareDefaultStructors(ItlIwx)\n    \npublic:\n    \n    //kext\n    void free() override;\n    virtual bool attach(IOPCIDevice *device) override;\n    virtual void detach(IOPCIDevice *device) override;\n    IOReturn enable(IONetworkInterface *netif) override;\n    IOReturn disable(IONetworkInterface *netif) override;\n    virtual struct ieee80211com *get80211Controller() override;\n    \n    static bool intrFilter(OSObject *object, IOFilterInterruptEventSource *src);\n    static IOReturn _iwx_start_task(OSObject *target, void *arg0, void *arg1, void *arg2, void *arg3);\n    \n    virtual ItlDriverInfo *getDriverInfo() override;\n    \n    virtual ItlDriverController *getDriverController() override;\n    \n    //driver info\n    virtual const char *getFirmwareVersion() override;\n    \n    virtual int16_t getBSSNoise() override;\n    \n    virtual bool is5GBandSupport() override;\n    \n    virtual int getTxNSS() override;\n    \n    virtual const char *getFirmwareName() override;\n    \n    virtual UInt32 supportedFeatures() override;\n\n    virtual const char *getFirmwareCountryCode() override;\n\n    virtual uint32_t getTxQueueSize() override;\n    \n    //driver controller\n    virtual void clearScanningFlags() override;\n    \n    virtual IOReturn setMulticastList(IOEthernetAddress *addr, int count) override;\n    \n    void releaseAll();\n    void joinSSID(const char *ssid, const char *pwd);\n    \n    //utils\n    static void *mallocarray(size_t, size_t, int, int);\n    \n//    static void onLoadFW(OSKextRequestTag requestTag, OSReturn result, const void *resourceData, uint32_t resourceDataLength, void *context);\n    \n    uint8_t    iwx_lookup_cmd_ver(struct iwx_softc *, uint8_t, uint8_t);\n    uint8_t    iwx_lookup_notif_ver(struct iwx_softc *, uint8_t, uint8_t);\n    uint32_t    iwx_lmac_id(struct iwx_softc *, ieee80211_channel *);\n    int    iwx_store_cscheme(struct iwx_softc *, uint8_t *, size_t);\n    int    iwx_alloc_fw_monitor_block(struct iwx_softc *, uint8_t, uint8_t);\n    int    iwx_alloc_fw_monitor(struct iwx_softc *, uint8_t);\n    int    iwx_apply_debug_destination(struct iwx_softc *);\n    int    iwx_ctxt_info_init(struct iwx_softc *, const struct iwx_fw_sects *);\n    int    iwx_ctxt_info_gen3_init(struct iwx_softc *, const struct iwx_fw_sects *);\n    void iwx_ctxt_info_free_fw_img(struct iwx_softc *sc);\n    int iwx_ctxt_info_alloc_dma(struct iwx_softc *sc,\n                                const struct iwx_fw_onesect *sec, struct iwx_dma_info *dram);\n    void    iwx_ctxt_info_free_paging(struct iwx_softc *);\n    int iwx_get_num_sections(const struct iwx_fw_sects *fws, int start);\n    int    iwx_init_fw_sec(struct iwx_softc *, const struct iwx_fw_sects *,\n            struct iwx_context_info_dram *);\n    void    iwx_fw_version_str(char *, size_t, uint32_t, uint32_t, uint32_t);\n    int    iwx_firmware_store_section(struct iwx_softc *, enum iwx_ucode_type,\n            uint8_t *, size_t);\n    int    iwx_set_default_calib(struct iwx_softc *, const void *);\n    void    iwx_fw_info_free(struct iwx_fw_info *);\n    void    iwx_pnvm_free(struct iwx_fw_info *);\n    int    iwx_read_firmware(struct iwx_softc *);\n    int    iwx_read_pnvm(struct iwx_softc *);\n    int     iwx_load_pnvm(struct iwx_softc *);\n    int     iwx_pnvm_handle_section(struct iwx_softc *, const uint8_t *, size_t);\n    uint32_t iwx_read_prph_unlocked(struct iwx_softc *, uint32_t);\n    uint32_t iwx_read_prph(struct iwx_softc *, uint32_t);\n    uint32_t iwx_read_umac_prph(struct iwx_softc *, uint32_t);\n    void    iwx_write_prph(struct iwx_softc *, uint32_t, uint32_t);\n    void    iwx_write_prph_unlocked(struct iwx_softc *, uint32_t, uint32_t);\n    void    iwx_write_umac_prph(struct iwx_softc *, uint32_t, uint32_t);\n    void iwx_write_prph64(struct iwx_softc *sc, uint64_t addr, uint64_t val);\n    int    iwx_read_mem(struct iwx_softc *, uint32_t, void *, int);\n    int    iwx_write_mem(struct iwx_softc *, uint32_t, const void *, int);\n    int    iwx_write_mem32(struct iwx_softc *, uint32_t, uint32_t);\n    int    iwx_poll_bit(struct iwx_softc *, int, uint32_t, uint32_t, int);\n    int    iwx_nic_lock(struct iwx_softc *);\n    void    iwx_nic_assert_locked(struct iwx_softc *);\n    void    iwx_nic_unlock(struct iwx_softc *);\n    void    iwx_set_bits_mask_prph(struct iwx_softc *, uint32_t, uint32_t,\n            uint32_t);\n    void    iwx_set_bits_prph(struct iwx_softc *, uint32_t, uint32_t);\n    void    iwx_clear_bits_prph(struct iwx_softc *, uint32_t, uint32_t);\n    int    iwx_dma_contig_alloc(bus_dma_tag_t, struct iwx_dma_info *, bus_size_t,\n            bus_size_t);\n    void    iwx_dma_contig_free(struct iwx_dma_info *);\n    int    iwx_alloc_rx_ring(struct iwx_softc *, struct iwx_rx_ring *);\n    void    iwx_disable_rx_dma(struct iwx_softc *);\n    void    iwx_reset_rx_ring(struct iwx_softc *, struct iwx_rx_ring *);\n    void    iwx_free_rx_ring(struct iwx_softc *, struct iwx_rx_ring *);\n    void    iwx_tx_ring_init(struct iwx_softc *, struct iwx_tx_ring *, int);\n    int    iwx_alloc_tx_ring(struct iwx_softc *, struct iwx_tx_ring *, int);\n    void    iwx_reset_tx_ring(struct iwx_softc *, struct iwx_tx_ring *);\n    void    iwx_free_tx_ring(struct iwx_softc *, struct iwx_tx_ring *);\n    void    iwx_enable_rfkill_int(struct iwx_softc *);\n    int    iwx_check_rfkill(struct iwx_softc *);\n    void    iwx_enable_interrupts(struct iwx_softc *);\n    void    iwx_enable_fwload_interrupt(struct iwx_softc *);\n    void    iwx_restore_interrupts(struct iwx_softc *);\n    void    iwx_disable_interrupts(struct iwx_softc *);\n    void    iwx_ict_reset(struct iwx_softc *);\n    int    iwx_set_hw_ready(struct iwx_softc *);\n    int    iwx_prepare_card_hw(struct iwx_softc *);\n    void    iwx_force_power_gating(struct iwx_softc *);\n    void    iwx_clear_persistence_bit(struct iwx_softc *);\n    void    iwx_apm_config(struct iwx_softc *);\n    int    iwx_apm_init(struct iwx_softc *);\n    void    iwx_apm_stop(struct iwx_softc *);\n    int    iwx_allow_mcast(struct iwx_softc *);\n    void    iwx_init_msix_hw(struct iwx_softc *);\n    void    iwx_conf_msix_hw(struct iwx_softc *, int);\n    int    iwx_start_hw(struct iwx_softc *);\n    void    iwx_stop_device(struct iwx_softc *);\n    void    iwx_nic_config(struct iwx_softc *);\n    int    iwx_nic_rx_init(struct iwx_softc *);\n    int    iwx_nic_init(struct iwx_softc *);\n    int    iwx_enable_txq(struct iwx_softc *, int, int, int, int);\n    int     iwx_tvqm_alloc_txq(struct iwx_softc *, int, int);\n    int     iwx_tvqm_enable_txq(struct iwx_softc *, int, int, uint32_t);\n    void    iwx_post_alive(struct iwx_softc *);\n    int iwx_send_time_event_cmd(struct iwx_softc *sc,\n                            const struct iwx_time_event_cmd *cmd);\n    void    iwx_protect_session(struct iwx_softc *, struct iwx_node *, uint32_t,\n            uint32_t);\n    int    iwx_schedule_protect_session(struct iwx_softc *, struct iwx_node *, uint32_t);\n    int     iwx_cancel_session_protection(struct iwx_softc *, struct iwx_node *);\n    void    iwx_unprotect_session(struct iwx_softc *, struct iwx_node *);\n    uint8_t iwx_fw_valid_tx_ant(struct iwx_softc *sc);\n    uint8_t iwx_fw_valid_rx_ant(struct iwx_softc *sc);\n    void    iwx_init_channel_map(struct iwx_softc *, uint16_t *, uint32_t *, int);\n    void    iwx_setup_ht_rates(struct iwx_softc *);\n    void    iwx_setup_vht_rates(struct iwx_softc *);\n    void    iwx_setup_he_rates(struct iwx_softc *);\n    int    iwx_mimo_enabled(struct iwx_softc *);\n    static void    iwx_mac_ctxt_task(void *);\n    static void    iwx_chan_ctxt_task(void *);\n    static void    iwx_updateprot(struct ieee80211com *);\n    static void    iwx_updateslot(struct ieee80211com *);\n    static void    iwx_updateedca(struct ieee80211com *);\n    static void    iwx_updatedtim(struct ieee80211com *);\n    void    iwx_init_reorder_buffer(struct iwx_reorder_buffer *, uint16_t,\n            uint16_t);\n    void    iwx_clear_reorder_buffer(struct iwx_softc *, struct iwx_rxba_data *);\n    static int    iwx_ampdu_rx_start(struct ieee80211com *, struct ieee80211_node *,\n            uint8_t);\n    static void    iwx_ampdu_rx_stop(struct ieee80211com *, struct ieee80211_node *,\n            uint8_t);\n    static void    iwx_rx_ba_session_expired(void *);\n    static void    iwx_reorder_timer_expired(void *);\n    static void    iwx_update_chw(struct ieee80211com *);\n    void    iwx_sta_rx_agg(struct iwx_softc *, struct ieee80211_node *, uint8_t,\n                           uint16_t, uint16_t, int, int);\n    static int    iwx_ampdu_tx_start(struct ieee80211com *, struct ieee80211_node *,\n            uint8_t);\n    static void    iwx_ampdu_tx_stop(struct ieee80211com *, struct ieee80211_node *,\n            uint8_t);\n    static void    iwx_ba_task(void *);\n\n    int    iwx_set_mac_addr_from_csr(struct iwx_softc *, struct iwx_nvm_data *);\n    int    iwx_is_valid_mac_addr(const uint8_t *);\n    int    iwx_nvm_get(struct iwx_softc *);\n    int    iwx_load_firmware(struct iwx_softc *);\n    void   iwx_set_ltr(struct iwx_softc *);\n    int    iwx_start_fw(struct iwx_softc *);\n    int    iwx_send_tx_ant_cfg(struct iwx_softc *, uint8_t);\n    int    iwx_send_phy_cfg_cmd(struct iwx_softc *);\n    int    iwx_load_ucode_wait_alive(struct iwx_softc *);\n    int    iwx_send_dqa_cmd(struct iwx_softc *);\n    int    iwx_run_init_mvm_ucode(struct iwx_softc *, int);\n    int    iwx_config_ltr(struct iwx_softc *);\n    void    iwx_update_rx_desc(struct iwx_softc *, struct iwx_rx_ring *, int);\n    int    iwx_rx_addbuf(struct iwx_softc *, int, int);\n    int    iwx_rxmq_get_signal_strength(struct iwx_softc *, struct iwx_rx_mpdu_desc *);\n    void    iwx_rx_rx_phy_cmd(struct iwx_softc *, struct iwx_rx_packet *,\n            struct iwx_rx_data *);\n    int    iwx_get_noise(const uint8_t *);\n    int    iwx_rx_hwdecrypt(struct iwx_softc *, mbuf_t, uint32_t,\n            struct ieee80211_rxinfo *);\n    int    iwx_ccmp_decap(struct iwx_softc *, mbuf_t,\n                          struct ieee80211_node *, struct ieee80211_rxinfo *);\n    void    iwx_rx_frame(struct iwx_softc *, mbuf_t, int, uint32_t, int, int,\n           uint32_t, struct ieee80211_rxinfo *, struct mbuf_list *);\n    void iwx_rx_mpdu_mq(struct iwx_softc *sc, mbuf_t m, void *pktdata,\n                        size_t maxlen, struct mbuf_list *ml);\n    void    iwx_rx_tx_cmd_single(struct iwx_softc *, struct iwx_rx_packet *,\n            struct iwx_tx_data *);\n    void iwx_txd_done(struct iwx_softc *sc, struct iwx_tx_data *txd);\n    void iwx_clear_oactive(struct iwx_softc *sc, struct iwx_tx_ring *ring);\n    void iwx_ampdu_txq_advance(struct iwx_softc *sc, struct iwx_tx_ring *ring, int idx);\n    void iwx_rx_tx_ba_notif(struct iwx_softc *sc, struct iwx_rx_packet *pkt, struct iwx_rx_data *data);\n    void    iwx_rx_tx_cmd(struct iwx_softc *, struct iwx_rx_packet *,\n            struct iwx_rx_data *);\n    void    iwx_rx_bmiss(struct iwx_softc *, struct iwx_rx_packet *,\n            struct iwx_rx_data *);\n    int    iwx_binding_cmd(struct iwx_softc *, struct iwx_node *, uint32_t);\n    int    iwx_phy_ctxt_cmd_uhb(struct iwx_softc *, struct iwx_phy_ctxt *, uint8_t,\n                                uint8_t, uint32_t, uint32_t);\n    int    iwx_phy_ctxt_cmd_v3(struct iwx_softc *, struct iwx_phy_ctxt *, uint8_t,\n                                uint8_t, uint32_t, uint32_t);\n    int    iwx_phy_ctxt_cmd(struct iwx_softc *, struct iwx_phy_ctxt *, uint8_t,\n            uint8_t, uint32_t, uint32_t);\n    int    iwx_send_cmd(struct iwx_softc *, struct iwx_host_cmd *);\n    int    iwx_send_cmd_pdu(struct iwx_softc *, uint32_t, uint32_t, uint16_t,\n            const void *);\n    int    iwx_send_cmd_status(struct iwx_softc *, struct iwx_host_cmd *,\n            uint32_t *);\n    int    iwx_send_cmd_pdu_status(struct iwx_softc *, uint32_t, uint16_t,\n            const void *, uint32_t *);\n    void    iwx_free_resp(struct iwx_softc *, struct iwx_host_cmd *);\n    void    iwx_cmd_done(struct iwx_softc *, int, int, int);\n    const struct iwx_rate *iwx_tx_fill_cmd(struct iwx_softc *, struct iwx_node *,\n            struct ieee80211_frame *, uint32_t *, uint32_t *);\n    uint32_t iwx_get_tx_ant(struct iwx_softc *sc, struct ieee80211_node *ni,\n                            const struct iwx_rate *rinfo, int type, struct ieee80211_frame *wh);\n    void    iwx_toggle_tx_ant(struct iwx_softc *sc, uint8_t *ant);\n    void    iwx_tx_update_byte_tbl(struct iwx_softc *, struct iwx_tx_ring *, int, uint16_t, uint16_t);\n    int    iwx_tx(struct iwx_softc *, mbuf_t, struct ieee80211_node *, int);\n    int    iwx_flush_sta_tids(struct iwx_softc *, int, uint16_t);\n    int    iwx_flush_sta(struct iwx_softc *, struct iwx_node *);\n    int    iwx_drain_sta(struct iwx_softc *sc, struct iwx_node *, int);\n    int    iwx_beacon_filter_send_cmd(struct iwx_softc *,\n            struct iwx_beacon_filter_cmd *);\n    int    iwx_update_beacon_abort(struct iwx_softc *, struct iwx_node *, int);\n    void    iwx_power_build_cmd(struct iwx_softc *, struct iwx_node *,\n            struct iwx_mac_power_cmd *);\n    int    iwx_power_mac_update_mode(struct iwx_softc *, struct iwx_node *);\n    int    iwx_power_update_device(struct iwx_softc *);\n    int    iwx_enable_beacon_filter(struct iwx_softc *, struct iwx_node *);\n    int    iwx_disable_beacon_filter(struct iwx_softc *);\n    int    iwx_add_sta_cmd(struct iwx_softc *, struct iwx_node *, int);\n    int    iwx_add_aux_sta(struct iwx_softc *);\n    int    iwx_rm_sta_cmd(struct iwx_softc *, struct iwx_node *);\n    int    iwx_rm_sta(struct iwx_softc *, struct iwx_node *);\n    uint8_t iwx_umac_scan_fill_channels(struct iwx_softc *sc,\n                                struct iwx_scan_channel_cfg_umac *chan, int n_ssids, int bgscan);\n    int iwx_fill_probe_req_v1(struct iwx_softc *sc, struct iwx_scan_probe_req_v1 *preq1);\n    int    iwx_fill_probe_req(struct iwx_softc *, struct iwx_scan_probe_req *);\n    int    iwx_config_umac_scan(struct iwx_softc *);\n    int    iwx_config_legacy_umac_scan(struct iwx_softc *);\n    int iwx_umac_scan_size(struct iwx_softc *sc);\n    struct iwx_scan_umac_chan_param *iwx_get_scan_req_umac_chan_param(struct iwx_softc *sc, struct iwx_scan_req_umac *req);\n    void *iwx_get_scan_req_umac_data(struct iwx_softc *sc, struct iwx_scan_req_umac *req);\n    int    iwx_umac_scan(struct iwx_softc *, int);\n    int    iwx_umac_scan_v12(struct iwx_softc *, int);\n    int    iwx_umac_scan_v14(struct iwx_softc *, int);\n    void    iwx_mcc_update(struct iwx_softc *, struct iwx_mcc_chub_notif *);\n    uint8_t    iwx_ridx2rate(struct ieee80211_rateset *, int);\n    int    iwx_rval2ridx(int);\n    int    iwx_rate2idx(int);\n    void    iwx_ack_rates(struct iwx_softc *, struct iwx_node *, int *, int *);\n    void    iwx_mac_ctxt_cmd_common(struct iwx_softc *, struct iwx_node *,\n            struct iwx_mac_ctx_cmd *, uint32_t);\n    void    iwx_mac_ctxt_cmd_fill_sta(struct iwx_softc *, struct iwx_node *,\n            struct iwx_mac_data_sta *, int);\n    int    iwx_mac_ctxt_cmd(struct iwx_softc *, struct iwx_node *, uint32_t, int);\n    int    iwx_clear_statistics(struct iwx_softc *);\n    int    iwx_update_quotas(struct iwx_softc *, struct iwx_node *, int);\n    void    iwx_add_task(struct iwx_softc *, struct taskq *, struct task *);\n    void    iwx_del_task(struct iwx_softc *, struct taskq *, struct task *);\n    int    iwx_scan(struct iwx_softc *);\n    static int    iwx_bgscan(struct ieee80211com *);\n    int    iwx_umac_scan_abort(struct iwx_softc *);\n    int    iwx_scan_abort(struct iwx_softc *);\n    int    iwx_rs_rval2idx(uint8_t);\n    uint16_t iwx_rs_ht_rates(struct iwx_softc *, struct ieee80211_node *, int);\n    uint16_t iwx_rs_fw_get_config_flags(struct iwx_softc *sc);\n    int    iwx_rs_init(struct iwx_softc *, struct iwx_node *, bool update);\n    void iwx_rs_update(struct iwx_softc *sc, struct iwx_tlc_update_notif *notif);\n    int    iwx_enable_mgmt_queue(struct iwx_softc *);\n    int    iwx_phy_ctxt_update(struct iwx_softc *, struct iwx_phy_ctxt *,\n                               struct ieee80211_channel *, uint8_t, uint8_t, uint32_t);\n    int    iwx_auth(struct iwx_softc *);\n    int    iwx_deauth(struct iwx_softc *);\n    int    iwx_run(struct iwx_softc *);\n    int    iwx_run_stop(struct iwx_softc *);\n    static struct ieee80211_node *iwx_node_alloc(struct ieee80211com *);\n    static int    iwx_set_key(struct ieee80211com *, struct ieee80211_node *,\n           struct ieee80211_key *);\n    static void    iwx_delete_key(struct ieee80211com *,\n           struct ieee80211_node *, struct ieee80211_key *);\n    int    iwx_media_change(struct _ifnet *);\n    static void    iwx_newstate_task(void *);\n    static int    iwx_newstate(struct ieee80211com *, enum ieee80211_state, int);\n    void    iwx_endscan(struct iwx_softc *);\n    void    iwx_fill_sf_command(struct iwx_softc *, struct iwx_sf_cfg_cmd *,\n            struct ieee80211_node *);\n    int    iwx_sf_config(struct iwx_softc *, int);\n    int    iwx_send_bt_init_conf(struct iwx_softc *);\n    int    iwx_send_soc_conf(struct iwx_softc *);\n    int    iwx_send_update_mcc_cmd(struct iwx_softc *, const char *);\n    int    iwx_send_temp_report_ths_cmd(struct iwx_softc *);\n    int    iwx_init_hw(struct iwx_softc *);\n    int    iwx_init(struct _ifnet *);\n    static void    iwx_start(struct _ifnet *);\n    void    iwx_stop(struct _ifnet *);\n    static void    iwx_watchdog(struct _ifnet *);\n    static int    iwx_ioctl(struct _ifnet *, u_long, caddr_t);\n    const char *iwx_desc_lookup(uint32_t);\n    void    iwx_nic_error(struct iwx_softc *);\n    void    iwx_nic_umac_error(struct iwx_softc *);\n    void    iwx_flip_address(uint8_t *);\n    int    iwx_detect_duplicate(struct iwx_softc *, mbuf_t,\n            struct iwx_rx_mpdu_desc *, struct ieee80211_rxinfo *);\n    int    iwx_is_sn_less(uint16_t, uint16_t, uint16_t);\n    void    iwx_release_frames(struct iwx_softc *, struct ieee80211_node *,\n            struct iwx_rxba_data *, struct iwx_reorder_buffer *, uint16_t,\n            struct mbuf_list *);\n    int    iwx_oldsn_workaround(struct iwx_softc *, struct ieee80211_node *,\n            int, struct iwx_reorder_buffer *, uint32_t, uint32_t);\n    int    iwx_rx_reorder(struct iwx_softc *, mbuf_t, int,\n            struct iwx_rx_mpdu_desc *, int, int, uint32_t,\n            struct ieee80211_rxinfo *, struct mbuf_list *);\n    int    iwx_rx_pkt_valid(struct iwx_rx_packet *);\n    void    iwx_rx_pkt(struct iwx_softc *, struct iwx_rx_data *,\n            struct mbuf_list *);\n    void    iwx_notif_intr(struct iwx_softc *);\n    static int    iwx_intr(OSObject *object, IOInterruptEventSource* sender, int count);\n    static int    iwx_intr_msix(OSObject *object, IOInterruptEventSource* sender, int count);\n    static int    iwx_match(IOPCIDevice *);\n    int    iwx_preinit(struct iwx_softc *);\n    void    iwx_attach_hook(struct device *);\n    bool    iwx_attach(struct iwx_softc *, struct pci_attach_args *);\n    static void    iwx_init_task(void *);\n    int    iwx_activate(struct iwx_softc *, int);\n    int    iwx_resume(struct iwx_softc *);\n    \npublic:\n    IOInterruptEventSource* fInterrupt;\n    struct pci_attach_args pci;\n    struct iwx_softc com;\n};\n\n#endif\n"
  },
  {
    "path": "itlwm/hal_iwx/if_iwxreg.h",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n/*    $OpenBSD: if_iwxreg.h,v 1.17 2020/08/01 16:14:05 stsp Exp $    */\n\n/*-\n * Based on BSD-licensed source modules in the Linux iwlwifi driver,\n * which were used as the reference documentation for this implementation.\n *\n ******************************************************************************\n *\n * This file is provided under a dual BSD/GPLv2 license.  When using or\n * redistributing this file, you may do so under either license.\n *\n * GPL LICENSE SUMMARY\n *\n * Copyright(c) 2017 Intel Deutschland GmbH\n * Copyright(c) 2018 - 2019 Intel Corporation\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of version 2 of the GNU General Public License as\n * published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful, but\n * WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * General Public License for more details.\n *\n * BSD LICENSE\n *\n * Copyright(c) 2017 Intel Deutschland GmbH\n * Copyright(c) 2018 - 2019 Intel Corporation\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in\n *    the documentation and/or other materials provided with the\n *    distribution.\n *  * Neither the name Intel Corporation nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n *****************************************************************************\n */\n\n/* maximmum number of DRAM map entries supported by FW */\n#define IWX_MAX_DRAM_ENTRY    64\n#define IWX_CSR_CTXT_INFO_BA    0x40\n\n#define IWX_CSR_CTXT_INFO_BOOT_CTRL         0x0\n#define IWX_CSR_CTXT_INFO_ADDR              0x118\n#define IWX_CSR_IML_DATA_ADDR               0x120\n#define IWX_CSR_IML_SIZE_ADDR               0x128\n#define IWX_CSR_IML_RESP_ADDR               0x12c\n\n/* Set bit for enabling automatic function boot */\n#define IWX_CSR_AUTO_FUNC_BOOT_ENA          (1 << 1)\n/* Set bit for initiating function boot */\n#define IWX_CSR_AUTO_FUNC_INIT              (1 << 7)\n\n/**\n * enum iwx_context_info_flags - Context information control flags\n * @IWX_CTXT_INFO_AUTO_FUNC_INIT: If set, FW will not wait before interrupting\n *    the init done for driver command that configures several system modes\n * @IWX_CTXT_INFO_EARLY_DEBUG: enable early debug\n * @IWX_CTXT_INFO_ENABLE_CDMP: enable core dump\n * @IWX_CTXT_INFO_RB_CB_SIZE_POS: position of the RBD Cyclic Buffer Size\n *    exponent, the actual size is 2**value, valid sizes are 8-2048.\n *    The value is four bits long. Maximum valid exponent is 12\n * @IWX_CTXT_INFO_TFD_FORMAT_LONG: use long TFD Format (the\n *    default is short format - not supported by the driver)\n * @IWX_CTXT_INFO_RB_SIZE_POS: RB size position\n *    (values are IWX_CTXT_INFO_RB_SIZE_*K)\n * @IWX_CTXT_INFO_RB_SIZE_1K: Value for 1K RB size\n * @IWX_CTXT_INFO_RB_SIZE_2K: Value for 2K RB size\n * @IWX_CTXT_INFO_RB_SIZE_4K: Value for 4K RB size\n * @IWX_CTXT_INFO_RB_SIZE_8K: Value for 8K RB size\n * @IWX_CTXT_INFO_RB_SIZE_12K: Value for 12K RB size\n * @IWX_CTXT_INFO_RB_SIZE_16K: Value for 16K RB size\n * @IWX_CTXT_INFO_RB_SIZE_20K: Value for 20K RB size\n * @IWX_CTXT_INFO_RB_SIZE_24K: Value for 24K RB size\n * @IWX_CTXT_INFO_RB_SIZE_28K: Value for 28K RB size\n * @IWX_CTXT_INFO_RB_SIZE_32K: Value for 32K RB size\n */\nenum iwx_context_info_flags {\n    IWX_CTXT_INFO_AUTO_FUNC_INIT    = (1 << 0),\n    IWX_CTXT_INFO_EARLY_DEBUG    = (1 << 1),\n    IWX_CTXT_INFO_ENABLE_CDMP    = (1 << 2),\n    IWX_CTXT_INFO_RB_CB_SIZE_POS    = 4,\n    IWX_CTXT_INFO_TFD_FORMAT_LONG    = (1 << 8),\n    IWX_CTXT_INFO_RB_SIZE_POS    = 9,\n    IWX_CTXT_INFO_RB_SIZE_1K    = 0x1,\n    IWX_CTXT_INFO_RB_SIZE_2K    = 0x2,\n    IWX_CTXT_INFO_RB_SIZE_4K    = 0x4,\n    IWX_CTXT_INFO_RB_SIZE_8K    = 0x8,\n    IWX_CTXT_INFO_RB_SIZE_12K    = 0x9,\n    IWX_CTXT_INFO_RB_SIZE_16K    = 0xa,\n    IWX_CTXT_INFO_RB_SIZE_20K    = 0xb,\n    IWX_CTXT_INFO_RB_SIZE_24K    = 0xc,\n    IWX_CTXT_INFO_RB_SIZE_28K    = 0xd,\n    IWX_CTXT_INFO_RB_SIZE_32K    = 0xe,\n};\n\n/*\n * struct iwx_context_info_version - version structure\n * @mac_id: SKU and revision id\n * @version: context information version id\n * @size: the size of the context information in DWs\n */\nstruct iwx_context_info_version {\n    uint16_t mac_id;\n    uint16_t version;\n    uint16_t size;\n    uint16_t reserved;\n} __packed;\n\n/*\n * struct iwx_context_info_control - version structure\n * @control_flags: context information flags see &enum iwx_context_info_flags\n */\nstruct iwx_context_info_control {\n    uint32_t control_flags;\n    uint32_t reserved;\n} __packed;\n\n/*\n * struct iwx_context_info_dram - images DRAM map\n * each entry in the map represents a DRAM chunk of up to 32 KB\n * @umac_img: UMAC image DRAM map\n * @lmac_img: LMAC image DRAM map\n * @virtual_img: paged image DRAM map\n */\nstruct iwx_context_info_dram {\n    uint64_t umac_img[IWX_MAX_DRAM_ENTRY];\n    uint64_t lmac_img[IWX_MAX_DRAM_ENTRY];\n    uint64_t virtual_img[IWX_MAX_DRAM_ENTRY];\n} __packed;\n\n/*\n * struct iwx_context_info_rbd_cfg - RBDs configuration\n * @free_rbd_addr: default queue free RB CB base address\n * @used_rbd_addr: default queue used RB CB base address\n * @status_wr_ptr: default queue used RB status write pointer\n */\nstruct iwx_context_info_rbd_cfg {\n    uint64_t free_rbd_addr;\n    uint64_t used_rbd_addr;\n    uint64_t status_wr_ptr;\n} __packed;\n\n/*\n * struct iwx_context_info_hcmd_cfg  - command queue configuration\n * @cmd_queue_addr: address of command queue\n * @cmd_queue_size: number of entries\n */\nstruct iwx_context_info_hcmd_cfg {\n    uint64_t cmd_queue_addr;\n    uint8_t cmd_queue_size;\n    uint8_t reserved[7];\n} __packed;\n\n/*\n * struct iwx_context_info_dump_cfg - Core Dump configuration\n * @core_dump_addr: core dump (debug DRAM address) start address\n * @core_dump_size: size, in DWs\n */\nstruct iwx_context_info_dump_cfg {\n    uint64_t core_dump_addr;\n    uint32_t core_dump_size;\n    uint32_t reserved;\n} __packed;\n\n/*\n * struct iwx_context_info_pnvm_cfg - platform NVM data configuration\n * @platform_nvm_addr: Platform NVM data start address\n * @platform_nvm_size: size in DWs\n */\nstruct iwx_context_info_pnvm_cfg {\n    uint64_t platform_nvm_addr;\n    uint32_t platform_nvm_size;\n    uint32_t reserved;\n} __packed;\n\n/*\n * struct iwx_context_info_early_dbg_cfg - early debug configuration for\n *    dumping DRAM addresses\n * @early_debug_addr: early debug start address\n * @early_debug_size: size in DWs\n */\nstruct iwx_context_info_early_dbg_cfg {\n    uint64_t early_debug_addr;\n    uint32_t early_debug_size;\n    uint32_t reserved;\n} __packed;\n\n/*\n * struct iwx_context_info - device INIT configuration\n * @version: version information of context info and HW\n * @control: control flags of FH configurations\n * @rbd_cfg: default RX queue configuration\n * @hcmd_cfg: command queue configuration\n * @dump_cfg: core dump data\n * @edbg_cfg: early debug configuration\n * @pnvm_cfg: platform nvm configuration\n * @dram: firmware image addresses in DRAM\n */\nstruct iwx_context_info {\n    struct iwx_context_info_version version;\n    struct iwx_context_info_control control;\n    uint64_t reserved0;\n    struct iwx_context_info_rbd_cfg rbd_cfg;\n    struct iwx_context_info_hcmd_cfg hcmd_cfg;\n    uint32_t reserved1[4];\n    struct iwx_context_info_dump_cfg dump_cfg;\n    struct iwx_context_info_early_dbg_cfg edbg_cfg;\n    struct iwx_context_info_pnvm_cfg pnvm_cfg;\n    uint32_t reserved2[16];\n    struct iwx_context_info_dram dram;\n    uint32_t reserved3[16];\n} __packed;\n\n/**\n * enum iwx_prph_scratch_flags - PRPH scratch control flags\n * @IWL_PRPH_SCRATCH_EARLY_DEBUG_EN: enable early debug conf\n * @IWL_PRPH_SCRATCH_EDBG_DEST_DRAM: use DRAM, with size allocated\n *    in hwm config.\n * @IWL_PRPH_SCRATCH_EDBG_DEST_INTERNAL: use buffer on SRAM\n * @IWL_PRPH_SCRATCH_EDBG_DEST_ST_ARBITER: use st arbiter, mainly for\n *    multicomm.\n * @IWL_PRPH_SCRATCH_EDBG_DEST_TB22DTF: route debug data to SoC HW\n * @IWL_PRPH_SCTATCH_RB_SIZE_4K: Use 4K RB size (the default is 2K)\n * @IWL_PRPH_SCRATCH_MTR_MODE: format used for completion - 0: for\n *    completion descriptor, 1 for responses (legacy)\n * @IWL_PRPH_SCRATCH_MTR_FORMAT: a mask for the size of the tfd.\n *    There are 4 optional values: 0: 16 bit, 1: 32 bit, 2: 64 bit,\n *    3: 256 bit.\n * @IWL_PRPH_SCRATCH_RB_SIZE_EXT_MASK: RB size full information, ignored\n *    by older firmware versions, so set IWL_PRPH_SCRATCH_RB_SIZE_4K\n *    appropriately; use the below values for this.\n * @IWL_PRPH_SCRATCH_RB_SIZE_EXT_8K: 8kB RB size\n * @IWL_PRPH_SCRATCH_RB_SIZE_EXT_12K: 12kB RB size\n */\nenum iwx_prph_scratch_flags {\n    IWX_PRPH_SCRATCH_EARLY_DEBUG_EN        = BIT(4),\n    IWX_PRPH_SCRATCH_EDBG_DEST_DRAM        = BIT(8),\n    IWX_PRPH_SCRATCH_EDBG_DEST_INTERNAL    = BIT(9),\n    IWX_PRPH_SCRATCH_EDBG_DEST_ST_ARBITER    = BIT(10),\n    IWX_PRPH_SCRATCH_EDBG_DEST_TB22DTF    = BIT(11),\n    IWX_PRPH_SCRATCH_RB_SIZE_4K        = BIT(16),\n    IWX_PRPH_SCRATCH_MTR_MODE        = BIT(17),\n    IWX_PRPH_SCRATCH_MTR_FORMAT        = BIT(18) | BIT(19),\n    IWX_PRPH_SCRATCH_RB_SIZE_EXT_MASK    = 0xf << 20,\n    IWX_PRPH_SCRATCH_RB_SIZE_EXT_8K        = 8 << 20,\n    IWX_PRPH_SCRATCH_RB_SIZE_EXT_12K    = 9 << 20,\n};\n\n/**\n * enum iwx_ini_cfg_state\n * @IWX_INI_CFG_STATE_NOT_LOADED: no debug cfg was given\n * @IWX_INI_CFG_STATE_LOADED: debug cfg was found and loaded\n * @IWX_INI_CFG_STATE_CORRUPTED: debug cfg was found and some of the TLVs\n *    are corrupted. The rest of the debug TLVs will still be used\n */\nenum iwx_ini_cfg_state {\n    IWX_INI_CFG_STATE_NOT_LOADED,\n    IWX_INI_CFG_STATE_LOADED,\n    IWX_INI_CFG_STATE_CORRUPTED,\n};\n\n/**\n * enum iwx_fw_ini_buffer_location\n *\n * @IWX_FW_INI_LOCATION_INVALID: invalid\n * @IWX_FW_INI_LOCATION_SRAM_PATH: SRAM location\n * @IWX_FW_INI_LOCATION_DRAM_PATH: DRAM location\n * @IWX_FW_INI_LOCATION_NPK_PATH: NPK location\n */\nenum iwx_fw_ini_buffer_location {\n    IWX_FW_INI_LOCATION_INVALID,\n    IWX_FW_INI_LOCATION_SRAM_PATH,\n    IWX_FW_INI_LOCATION_DRAM_PATH,\n    IWX_FW_INI_LOCATION_NPK_PATH,\n    IWX_FW_INI_LOCATION_NUM,\n}; /* FW_DEBUG_TLV_BUFFER_LOCATION_E_VER_1 */\n\n/**\n * enum iwx_prph_scratch_mtr_format - tfd size configuration\n * @IWL_PRPH_MTR_FORMAT_16B: 16 bit tfd\n * @IWL_PRPH_MTR_FORMAT_32B: 32 bit tfd\n * @IWL_PRPH_MTR_FORMAT_64B: 64 bit tfd\n * @IWL_PRPH_MTR_FORMAT_256B: 256 bit tfd\n */\nenum iwx_prph_scratch_mtr_format {\n    IWX_PRPH_MTR_FORMAT_16B = 0x0,\n    IWX_PRPH_MTR_FORMAT_32B = 0x40000,\n    IWX_PRPH_MTR_FORMAT_64B = 0x80000,\n    IWX_PRPH_MTR_FORMAT_256B = 0xC0000,\n};\n\n/*\n * struct iwx_prph_scratch_version - version structure\n * @mac_id: SKU and revision id\n * @version: prph scratch information version id\n * @size: the size of the context information in DWs\n * @reserved: reserved\n */\nstruct iwx_prph_scratch_version {\n    __le16 mac_id;\n    __le16 version;\n    __le16 size;\n    __le16 reserved;\n} __packed; /* PERIPH_SCRATCH_VERSION_S */\n\n/*\n * struct iwx_prph_scratch_control - control structure\n * @control_flags: context information flags see &enum iwl_prph_scratch_flags\n * @reserved: reserved\n */\nstruct iwx_prph_scratch_control {\n    __le32 control_flags;\n    __le32 reserved;\n} __packed; /* PERIPH_SCRATCH_CONTROL_S */\n\n/*\n * struct iwx_prph_scratch_pnvm_cfg - ror config\n * @pnvm_base_addr: PNVM start address\n * @pnvm_size: PNVM size in DWs\n * @reserved: reserved\n */\nstruct iwx_prph_scratch_pnvm_cfg {\n    __le64 pnvm_base_addr;\n    __le32 pnvm_size;\n    __le32 reserved;\n} __packed; /* PERIPH_SCRATCH_PNVM_CFG_S */\n\n/*\n * struct iwx_prph_scratch_hwm_cfg - hwm config\n * @hwm_base_addr: hwm start address\n * @hwm_size: hwm size in DWs\n * @reserved: reserved\n */\nstruct iwx_prph_scratch_hwm_cfg {\n    __le64 hwm_base_addr;\n    __le32 hwm_size;\n    __le32 reserved;\n} __packed; /* PERIPH_SCRATCH_HWM_CFG_S */\n\n/*\n * struct iwx_prph_scratch_rbd_cfg - RBDs configuration\n * @free_rbd_addr: default queue free RB CB base address\n * @reserved: reserved\n */\nstruct iwx_prph_scratch_rbd_cfg {\n    __le64 free_rbd_addr;\n    __le32 reserved;\n} __packed; /* PERIPH_SCRATCH_RBD_CFG_S */\n\n/*\n * struct iwx_prph_scratch_ctrl_cfg - prph scratch ctrl and config\n * @version: version information of context info and HW\n * @control: control flags of FH configurations\n * @pnvm_cfg: ror configuration\n * @hwm_cfg: hwm configuration\n * @rbd_cfg: default RX queue configuration\n */\nstruct iwx_prph_scratch_ctrl_cfg {\n    struct iwx_prph_scratch_version version;\n    struct iwx_prph_scratch_control control;\n    struct iwx_prph_scratch_pnvm_cfg pnvm_cfg;\n    struct iwx_prph_scratch_hwm_cfg hwm_cfg;\n    struct iwx_prph_scratch_rbd_cfg rbd_cfg;\n} __packed; /* PERIPH_SCRATCH_CTRL_CFG_S */\n\n/*\n * struct iwx_prph_scratch - peripheral scratch mapping\n * @ctrl_cfg: control and configuration of prph scratch\n * @dram: firmware images addresses in DRAM\n * @reserved: reserved\n */\nstruct iwx_prph_scratch {\n    struct iwx_prph_scratch_ctrl_cfg ctrl_cfg;\n    __le32 reserved[16];\n    struct iwx_context_info_dram dram;\n} __packed; /* PERIPH_SCRATCH_S */\n\n/*\n * struct iwx_prph_info - peripheral information\n * @boot_stage_mirror: reflects the value in the Boot Stage CSR register\n * @ipc_status_mirror: reflects the value in the IPC Status CSR register\n * @sleep_notif: indicates the peripheral sleep status\n * @reserved: reserved\n */\nstruct iwx_prph_info {\n    __le32 boot_stage_mirror;\n    __le32 ipc_status_mirror;\n    __le32 sleep_notif;\n    __le32 reserved;\n} __packed; /* PERIPH_INFO_S */\n\n/*\n * struct iwx_context_info_gen3 - device INIT configuration\n * @version: version of the context information\n * @size: size of context information in DWs\n * @config: context in which the peripheral would execute - a subset of\n *    capability csr register published by the peripheral\n * @prph_info_base_addr: the peripheral information structure start address\n * @cr_head_idx_arr_base_addr: the completion ring head index array\n *    start address\n * @tr_tail_idx_arr_base_addr: the transfer ring tail index array\n *    start address\n * @cr_tail_idx_arr_base_addr: the completion ring tail index array\n *    start address\n * @tr_head_idx_arr_base_addr: the transfer ring head index array\n *    start address\n * @cr_idx_arr_size: number of entries in the completion ring index array\n * @tr_idx_arr_size: number of entries in the transfer ring index array\n * @mtr_base_addr: the message transfer ring start address\n * @mcr_base_addr: the message completion ring start address\n * @mtr_size: number of entries which the message transfer ring can hold\n * @mcr_size: number of entries which the message completion ring can hold\n * @mtr_doorbell_vec: the doorbell vector associated with the message\n *    transfer ring\n * @mcr_doorbell_vec: the doorbell vector associated with the message\n *    completion ring\n * @mtr_msi_vec: the MSI which shall be generated by the peripheral after\n *    completing a transfer descriptor in the message transfer ring\n * @mcr_msi_vec: the MSI which shall be generated by the peripheral after\n *    completing a completion descriptor in the message completion ring\n * @mtr_opt_header_size: the size of the optional header in the transfer\n *    descriptor associated with the message transfer ring in DWs\n * @mtr_opt_footer_size: the size of the optional footer in the transfer\n *    descriptor associated with the message transfer ring in DWs\n * @mcr_opt_header_size: the size of the optional header in the completion\n *    descriptor associated with the message completion ring in DWs\n * @mcr_opt_footer_size: the size of the optional footer in the completion\n *    descriptor associated with the message completion ring in DWs\n * @msg_rings_ctrl_flags: message rings control flags\n * @prph_info_msi_vec: the MSI which shall be generated by the peripheral\n *    after updating the Peripheral Information structure\n * @prph_scratch_base_addr: the peripheral scratch structure start address\n * @prph_scratch_size: the size of the peripheral scratch structure in DWs\n * @reserved: reserved\n */\nstruct iwx_context_info_gen3 {\n    __le16 version;\n    __le16 size;\n    __le32 config;\n    __le64 prph_info_base_addr;\n    __le64 cr_head_idx_arr_base_addr;\n    __le64 tr_tail_idx_arr_base_addr;\n    __le64 cr_tail_idx_arr_base_addr;\n    __le64 tr_head_idx_arr_base_addr;\n    __le16 cr_idx_arr_size;\n    __le16 tr_idx_arr_size;\n    __le64 mtr_base_addr;\n    __le64 mcr_base_addr;\n    __le16 mtr_size;\n    __le16 mcr_size;\n    __le16 mtr_doorbell_vec;\n    __le16 mcr_doorbell_vec;\n    __le16 mtr_msi_vec;\n    __le16 mcr_msi_vec;\n    u8 mtr_opt_header_size;\n    u8 mtr_opt_footer_size;\n    u8 mcr_opt_header_size;\n    u8 mcr_opt_footer_size;\n    __le16 msg_rings_ctrl_flags;\n    __le16 prph_info_msi_vec;\n    __le64 prph_scratch_base_addr;\n    __le32 prph_scratch_size;\n    __le32 reserved;\n} __packed; /* IPC_CONTEXT_INFO_S */\n\n#define IWX_MQ_RX_TABLE_SIZE    512\n\n/* cb size is the exponent */\n#define IWX_RX_QUEUE_CB_SIZE(x)    ((sizeof(x) <= 4) ? (_fls(x) - 1) : (flsl(x) - 1))\n\n#define GEN3_UMAC_PRPH_OFFSET    0x300000\n\n/**\n * struct iwx_fw_ini_header - Common Header for all ini debug TLV's structures\n *\n * @version: TLV version\n * @domain: domain of the TLV. One of &enum iwl_fw_ini_dbg_domain\n * @data: TLV data\n */\nstruct iwx_fw_ini_header {\n    __le32 version;\n    __le32 domain;\n    u8 data[0];\n} __packed; /* FW_TLV_DEBUG_HEADER_S_VER_1 */\n\n/**\n * struct iwx_fw_ini_allocation_tlv - Allocates DRAM buffers\n *\n * @hdr: debug header\n * @alloc_id: allocation id. One of &enum iwl_fw_ini_allocation_id\n * @buf_location: buffer location. One of &enum iwl_fw_ini_buffer_location\n * @req_size: requested buffer size\n * @max_frags_num: maximum number of fragments\n * @min_size: minimum buffer size\n */\nstruct iwx_fw_ini_allocation_tlv {\n    struct iwx_fw_ini_header hdr;\n    __le32 alloc_id;\n    __le32 buf_location;\n    __le32 req_size;\n    __le32 max_frags_num;\n    __le32 min_size;\n} __packed; /* FW_TLV_DEBUG_BUFFER_ALLOCATION_API_S_VER_1 */\n\n/**\n * enum iwx_fw_ini_allocation_id\n *\n * @IWX_FW_INI_ALLOCATION_INVALID: invalid\n * @IWX_FW_INI_ALLOCATION_ID_DBGC1: allocation meant for DBGC1 configuration\n * @IWX_FW_INI_ALLOCATION_ID_DBGC2: allocation meant for DBGC2 configuration\n * @IWX_FW_INI_ALLOCATION_ID_DBGC3: allocation meant for DBGC3 configuration\n * @IWX_FW_INI_ALLOCATION_ID_INTERNAL: allocation meant for Intreanl SMEM in D3\n * @IWX_FW_INI_ALLOCATION_NUM: number of allocation ids\n*/\nenum iwx_fw_ini_allocation_id {\n    IWX_FW_INI_ALLOCATION_INVALID,\n    IWX_FW_INI_ALLOCATION_ID_DBGC1,\n    IWX_FW_INI_ALLOCATION_ID_DBGC2,\n    IWX_FW_INI_ALLOCATION_ID_DBGC3,\n    IWX_FW_INI_ALLOCATION_ID_INTERNAL,\n    IWX_FW_INI_ALLOCATION_NUM,\n}; /* FW_DEBUG_TLV_ALLOCATION_ID_E_VER_1 */\n\n/*\n * CSR (control and status registers)\n *\n * CSR registers are mapped directly into PCI bus space, and are accessible\n * whenever platform supplies power to device, even when device is in\n * low power states due to driver-invoked device resets\n * (e.g. IWX_CSR_RESET_REG_FLAG_SW_RESET) or uCode-driven power-saving modes.\n *\n * Use iwl_write32() and iwl_read32() family to access these registers;\n * these provide simple PCI bus access, without waking up the MAC.\n * Do not use iwl_write_direct32() family for these registers;\n * no need to \"grab nic access\" via IWX_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ.\n * The MAC (uCode processor, etc.) does not need to be powered up for accessing\n * the CSR registers.\n *\n * NOTE:  Device does need to be awake in order to read this memory\n *        via IWX_CSR_EEPROM and IWX_CSR_OTP registers\n */\n#define IWX_CSR_HW_IF_CONFIG_REG    (0x000) /* hardware interface config */\n#define IWX_CSR_INT_COALESCING      (0x004) /* accum ints, 32-usec units */\n#define IWX_CSR_INT                 (0x008) /* host interrupt status/ack */\n#define IWX_CSR_INT_MASK            (0x00c) /* host interrupt enable */\n#define IWX_CSR_FH_INT_STATUS       (0x010) /* busmaster int status/ack*/\n#define IWX_CSR_GPIO_IN             (0x018) /* read external chip pins */\n#define IWX_CSR_RESET               (0x020) /* busmaster enable, NMI, etc*/\n#define IWX_CSR_GP_CNTRL            (0x024)\n\n/* 2nd byte of IWX_CSR_INT_COALESCING, not accessible via iwl_write32()! */\n#define IWX_CSR_INT_PERIODIC_REG    (0x005)\n\n/*\n * Hardware revision info\n * Bit fields:\n * 31-16:  Reserved\n *  15-4:  Type of device:  see IWX_CSR_HW_REV_TYPE_xxx definitions\n *  3-2:  Revision step:  0 = A, 1 = B, 2 = C, 3 = D\n *  1-0:  \"Dash\" (-) value, as in A-1, etc.\n */\n#define IWX_CSR_HW_REV              (0x028)\n/*\n* RF ID revision info\n* Bit fields:\n* 31:24: Reserved (set to 0x0)\n* 23:12: Type\n* 11:8:  Step (A - 0x0, B - 0x1, etc)\n* 7:4:   Dash\n* 3:0:   Flavor\n*/\n#define IWX_CSR_HW_RF_ID            (0x09c)\n\n#define IWX_CSR_GIO_REG        (0x03C)\n\n/*\n * UCODE-DRIVER GP (general purpose) mailbox registers.\n * SET/CLR registers set/clear bit(s) if \"1\" is written.\n */\n#define IWX_CSR_UCODE_DRV_GP1       (0x054)\n#define IWX_CSR_UCODE_DRV_GP1_SET   (0x058)\n#define IWX_CSR_UCODE_DRV_GP1_CLR   (0x05c)\n#define IWX_CSR_UCODE_DRV_GP2       (0x060)\n\n#define IWX_CSR_MBOX_SET_REG        (0x088)\n#define IWX_CSR_MBOX_SET_REG_OS_ALIVE    0x20\n\n#define IWX_CSR_DRAM_INT_TBL_REG    (0x0A0)\n#define IWX_CSR_MAC_SHADOW_REG_CTRL    (0x0A8) /* 6000 and up */\n\n/* LTR control (since IWL_DEVICE_FAMILY_22000) */\n#define IWX_CSR_LTR_LONG_VAL_AD            0x0D4\n#define IWX_CSR_LTR_LONG_VAL_AD_NO_SNOOP_REQ    0x80000000\n#define IWX_CSR_LTR_LONG_VAL_AD_NO_SNOOP_SCALE    0x1c000000\n#define IWX_CSR_LTR_LONG_VAL_AD_NO_SNOOP_VAL    0x03ff0000\n#define IWX_CSR_LTR_LONG_VAL_AD_SNOOP_REQ        0x00008000\n#define IWX_CSR_LTR_LONG_VAL_AD_SNOOP_SCALE        0x00001c00\n#define IWX_CSR_LTR_LONG_VAL_AD_SNOOP_VAL        0x000003ff\n#define IWX_CSR_LTR_LONG_VAL_AD_SCALE_USEC        2\n\n/* LTR control (Qu only) */\n#define IWX_HPM_MAC_LTR_CSR            0xa0348c\n#define IWX_HPM_MAC_LRT_ENABLE_ALL        0xf\n/* also uses CSR_LTR_* for values */\n#define IWX_HPM_UMAC_LTR            0xa03480\n\n/* GIO Chicken Bits (PCI Express bus link power management) */\n#define IWX_CSR_GIO_CHICKEN_BITS    (0x100)\n\n#define IWX_CSR_DBG_HPET_MEM_REG    (0x240)\n#define IWX_CSR_DBG_LINK_PWR_MGMT_REG    (0x250)\n\n/* Bits for IWX_CSR_HW_IF_CONFIG_REG */\n#define IWX_CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH    (0x00000003)\n#define IWX_CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP    (0x0000000C)\n#define IWX_CSR_HW_IF_CONFIG_REG_MSK_BOARD_VER    (0x000000C0)\n#define IWX_CSR_HW_IF_CONFIG_REG_BIT_MAC_SI    (0x00000100)\n#define IWX_CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI    (0x00000200)\n#define IWX_CSR_HW_IF_CONFIG_REG_MSK_PHY_TYPE    (0x00000C00)\n#define IWX_CSR_HW_IF_CONFIG_REG_MSK_PHY_DASH    (0x00003000)\n#define IWX_CSR_HW_IF_CONFIG_REG_MSK_PHY_STEP    (0x0000C000)\n\n#define IWX_CSR_HW_IF_CONFIG_REG_POS_MAC_DASH    (0)\n#define IWX_CSR_HW_IF_CONFIG_REG_POS_MAC_STEP    (2)\n#define IWX_CSR_HW_IF_CONFIG_REG_POS_BOARD_VER    (6)\n#define IWX_CSR_HW_IF_CONFIG_REG_POS_PHY_TYPE    (10)\n#define IWX_CSR_HW_IF_CONFIG_REG_POS_PHY_DASH    (12)\n#define IWX_CSR_HW_IF_CONFIG_REG_POS_PHY_STEP    (14)\n\n#define IWX_CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A    (0x00080000)\n#define IWX_CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM    (0x00200000)\n#define IWX_CSR_HW_IF_CONFIG_REG_BIT_NIC_READY    (0x00400000) /* PCI_OWN_SEM */\n#define IWX_CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE (0x02000000) /* ME_OWN */\n#define IWX_CSR_HW_IF_CONFIG_REG_PREPARE    (0x08000000) /* WAKE_ME */\n#define IWX_CSR_HW_IF_CONFIG_REG_ENABLE_PME    (0x10000000)\n#define IWX_CSR_HW_IF_CONFIG_REG_PERSIST_MODE    (0x40000000) /* PERSISTENCE */\n\n#define IWX_CSR_INT_PERIODIC_DIS        (0x00) /* disable periodic int*/\n#define IWX_CSR_INT_PERIODIC_ENA        (0xFF) /* 255*32 usec ~ 8 msec*/\n\n/* interrupt flags in INTA, set by uCode or hardware (e.g. dma),\n * acknowledged (reset) by host writing \"1\" to flagged bits. */\n#define IWX_CSR_INT_BIT_FH_RX    (1U << 31) /* Rx DMA, cmd responses, FH_INT[17:16] */\n#define IWX_CSR_INT_BIT_HW_ERR    (1 << 29) /* DMA hardware error FH_INT[31] */\n#define IWX_CSR_INT_BIT_RX_PERIODIC    (1 << 28) /* Rx periodic */\n#define IWX_CSR_INT_BIT_FH_TX    (1 << 27) /* Tx DMA FH_INT[1:0] */\n#define IWX_CSR_INT_BIT_SCD    (1 << 26) /* TXQ pointer advanced */\n#define IWX_CSR_INT_BIT_SW_ERR    (1 << 25) /* uCode error */\n#define IWX_CSR_INT_BIT_RF_KILL    (1 << 7)  /* HW RFKILL switch GP_CNTRL[27] toggled */\n#define IWX_CSR_INT_BIT_CT_KILL    (1 << 6)  /* Critical temp (chip too hot) rfkill */\n#define IWX_CSR_INT_BIT_SW_RX    (1 << 3)  /* Rx, command responses */\n#define IWX_CSR_INT_BIT_WAKEUP    (1 << 1)  /* NIC controller waking up (pwr mgmt) */\n#define IWX_CSR_INT_BIT_ALIVE    (1 << 0)  /* uCode interrupts once it initializes */\n\n#define IWX_CSR_INI_SET_MASK    (IWX_CSR_INT_BIT_FH_RX   | \\\n                 IWX_CSR_INT_BIT_HW_ERR  | \\\n                 IWX_CSR_INT_BIT_FH_TX   | \\\n                 IWX_CSR_INT_BIT_SW_ERR  | \\\n                 IWX_CSR_INT_BIT_RF_KILL | \\\n                 IWX_CSR_INT_BIT_SW_RX   | \\\n                 IWX_CSR_INT_BIT_WAKEUP  | \\\n                 IWX_CSR_INT_BIT_ALIVE   | \\\n                 IWX_CSR_INT_BIT_RX_PERIODIC)\n\n/* interrupt flags in FH (flow handler) (PCI busmaster DMA) */\n#define IWX_CSR_FH_INT_BIT_ERR       (1U << 31) /* Error */\n#define IWX_CSR_FH_INT_BIT_HI_PRIOR  (1 << 30) /* High priority Rx, bypass coalescing */\n#define IWX_CSR_FH_INT_BIT_RX_CHNL1  (1 << 17) /* Rx channel 1 */\n#define IWX_CSR_FH_INT_BIT_RX_CHNL0  (1 << 16) /* Rx channel 0 */\n#define IWX_CSR_FH_INT_BIT_TX_CHNL1  (1 << 1)  /* Tx channel 1 */\n#define IWX_CSR_FH_INT_BIT_TX_CHNL0  (1 << 0)  /* Tx channel 0 */\n\n#define IWX_CSR_FH_INT_RX_MASK    (IWX_CSR_FH_INT_BIT_HI_PRIOR | \\\n                IWX_CSR_FH_INT_BIT_RX_CHNL1 | \\\n                IWX_CSR_FH_INT_BIT_RX_CHNL0)\n\n#define IWX_CSR_FH_INT_TX_MASK    (IWX_CSR_FH_INT_BIT_TX_CHNL1 | \\\n                IWX_CSR_FH_INT_BIT_TX_CHNL0)\n\n/* RESET */\n#define IWX_CSR_RESET_REG_FLAG_NEVO_RESET                (0x00000001)\n#define IWX_CSR_RESET_REG_FLAG_FORCE_NMI                 (0x00000002)\n#define IWX_CSR_RESET_REG_FLAG_SW_RESET                  (0x00000080)\n#define IWX_CSR_RESET_REG_FLAG_MASTER_DISABLED           (0x00000100)\n#define IWX_CSR_RESET_REG_FLAG_STOP_MASTER               (0x00000200)\n#define IWX_CSR_RESET_LINK_PWR_MGMT_DISABLED             (0x80000000)\n\n/*\n * GP (general purpose) CONTROL REGISTER\n * Bit fields:\n *    27:  HW_RF_KILL_SW\n *         Indicates state of (platform's) hardware RF-Kill switch\n * 26-24:  POWER_SAVE_TYPE\n *         Indicates current power-saving mode:\n *         000 -- No power saving\n *         001 -- MAC power-down\n *         010 -- PHY (radio) power-down\n *         011 -- Error\n *   9-6:  SYS_CONFIG\n *         Indicates current system configuration, reflecting pins on chip\n *         as forced high/low by device circuit board.\n *     4:  GOING_TO_SLEEP\n *         Indicates MAC is entering a power-saving sleep power-down.\n *         Not a good time to access device-internal resources.\n *     3:  MAC_ACCESS_REQ\n *         Host sets this to request and maintain MAC wakeup, to allow host\n *         access to device-internal resources.  Host must wait for\n *         MAC_CLOCK_READY (and !GOING_TO_SLEEP) before accessing non-CSR\n *         device registers.\n *     2:  INIT_DONE\n *         Host sets this to put device into fully operational D0 power mode.\n *         Host resets this after SW_RESET to put device into low power mode.\n *     0:  MAC_CLOCK_READY\n *         Indicates MAC (ucode processor, etc.) is powered up and can run.\n *         Internal resources are accessible.\n *         NOTE:  This does not indicate that the processor is actually running.\n *         NOTE:  This does not indicate that device has completed\n *                init or post-power-down restore of internal SRAM memory.\n *                Use IWX_CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP as indication that\n *                SRAM is restored and uCode is in normal operation mode.\n *                Later devices (5xxx/6xxx/1xxx) use non-volatile SRAM, and\n *                do not need to save/restore it.\n *         NOTE:  After device reset, this bit remains \"0\" until host sets\n *                INIT_DONE\n */\n#define IWX_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY        (0x00000001)\n#define IWX_CSR_GP_CNTRL_REG_FLAG_INIT_DONE              (0x00000004)\n#define IWX_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ         (0x00000008)\n#define IWX_CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP         (0x00000010)\n\n#define IWX_CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN           (0x00000001)\n\n#define IWX_CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE         (0x07000000)\n#define IWX_CSR_GP_CNTRL_REG_FLAG_RFKILL_WAKE_L1A_EN     (0x04000000)\n#define IWX_CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW          (0x08000000)\n\n\n/* HW REV */\n#define IWX_CSR_HW_REV_DASH(_val)          (((_val) & 0x0000003) >> 0)\n#define IWX_CSR_HW_REV_STEP(_val)          (((_val) & 0x000000C) >> 2)\n\n#define IWX_CSR_HW_REV_TYPE_MSK        (0x000FFF0)\n\n/* CSR GIO */\n#define IWX_CSR_GIO_REG_VAL_L0S_DISABLED    (0x00000002)\n\n/*\n * UCODE-DRIVER GP (general purpose) mailbox register 1\n * Host driver and uCode write and/or read this register to communicate with\n * each other.\n * Bit fields:\n *     4:  UCODE_DISABLE\n *         Host sets this to request permanent halt of uCode, same as\n *         sending CARD_STATE command with \"halt\" bit set.\n *     3:  CT_KILL_EXIT\n *         Host sets this to request exit from CT_KILL state, i.e. host thinks\n *         device temperature is low enough to continue normal operation.\n *     2:  CMD_BLOCKED\n *         Host sets this during RF KILL power-down sequence (HW, SW, CT KILL)\n *         to release uCode to clear all Tx and command queues, enter\n *         unassociated mode, and power down.\n *         NOTE:  Some devices also use HBUS_TARG_MBX_C register for this bit.\n *     1:  SW_BIT_RFKILL\n *         Host sets this when issuing CARD_STATE command to request\n *         device sleep.\n *     0:  MAC_SLEEP\n *         uCode sets this when preparing a power-saving power-down.\n *         uCode resets this when power-up is complete and SRAM is sane.\n *         NOTE:  device saves internal SRAM data to host when powering down,\n *                and must restore this data after powering back up.\n *                MAC_SLEEP is the best indication that restore is complete.\n *                Later devices (5xxx/6xxx/1xxx) use non-volatile SRAM, and\n *                do not need to save/restore it.\n */\n#define IWX_CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP             (0x00000001)\n#define IWX_CSR_UCODE_SW_BIT_RFKILL                     (0x00000002)\n#define IWX_CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED           (0x00000004)\n#define IWX_CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT      (0x00000008)\n#define IWX_CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE       (0x00000020)\n\n/* GIO Chicken Bits (PCI Express bus link power management) */\n#define IWX_CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX  (0x00800000)\n#define IWX_CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER  (0x20000000)\n\n/* HPET MEM debug */\n#define IWX_CSR_DBG_HPET_MEM_REG_VAL    (0xFFFF0000)\n\n/* DRAM INT TABLE */\n#define IWX_CSR_DRAM_INT_TBL_ENABLE        (1U << 31)\n#define IWX_CSR_DRAM_INIT_TBL_WRITE_POINTER    (1 << 28)\n#define IWX_CSR_DRAM_INIT_TBL_WRAP_CHECK    (1 << 27)\n\n/* 22000 configuration registers */\n\n/*\n * TFH Configuration register.\n *\n * BIT fields:\n *\n * Bits 3:0:\n * Define the maximum number of pending read requests.\n * Maximum configration value allowed is 0xC\n * Bits 9:8:\n * Define the maximum transfer size. (64 / 128 / 256)\n * Bit 10:\n * When bit is set and transfer size is set to 128B, the TFH will enable\n * reading chunks of more than 64B only if the read address is aligned to 128B.\n * In case of DRAM read address which is not aligned to 128B, the TFH will\n * enable transfer size which doesn't cross 64B DRAM address boundary.\n*/\n#define IWX_TFH_TRANSFER_MODE            (0x1F40)\n#define IWX_TFH_TRANSFER_MAX_PENDING_REQ    0xc\n#define IWX_TFH_CHUNK_SIZE_128            (1 << 8)\n#define IWX_TFH_CHUNK_SPLIT_MODE        (1 << 10)\n\n/*\n * Defines the offset address in dwords referring from the beginning of the\n * Tx CMD which will be updated in DRAM.\n * Note that the TFH offset address for Tx CMD update is always referring to\n * the start of the TFD first TB.\n * In case of a DRAM Tx CMD update the TFH will update PN and Key ID\n */\n#define IWX_TFH_TXCMD_UPDATE_CFG        (0x1F48)\n\n/*\n * Controls TX DMA operation\n *\n * BIT fields:\n *\n * Bits 31:30: Enable the SRAM DMA channel.\n * Turning on bit 31 will kick the SRAM2DRAM DMA.\n * Note that the sram2dram may be enabled only after configuring the DRAM and\n * SRAM addresses registers and the byte count register.\n * Bits 25:24: Defines the interrupt target upon dram2sram transfer done. When\n * set to 1 - interrupt is sent to the driver\n * Bit 0: Indicates the snoop configuration\n*/\n#define IWX_TFH_SRV_DMA_CHNL0_CTRL    (0x1F60)\n#define IWX_TFH_SRV_DMA_SNOOP        (1 << 0)\n#define IWX_TFH_SRV_DMA_TO_DRIVER    (1 << 24)\n#define IWX_TFH_SRV_DMA_START        (1U << 31)\n\n/* Defines the DMA SRAM write start address to transfer a data block */\n#define IWX_TFH_SRV_DMA_CHNL0_SRAM_ADDR    (0x1F64)\n\n/* Defines the 64bits DRAM start address to read the DMA data block from */\n#define IWX_TFH_SRV_DMA_CHNL0_DRAM_ADDR    (0x1F68)\n\n/*\n * Defines the number of bytes to transfer from DRAM to SRAM.\n * Note that this register may be configured with non-dword aligned size.\n */\n#define IWX_TFH_SRV_DMA_CHNL0_BC    (0x1F70)\n\n/* 9000 rx series registers */\n\n#define IWX_RFH_Q0_FRBDCB_BA_LSB 0xA08000 /* 64 bit address */\n#define IWX_RFH_Q_FRBDCB_BA_LSB(q) (IWX_RFH_Q0_FRBDCB_BA_LSB + (q) * 8)\n/* Write index table */\n#define IWX_RFH_Q0_FRBDCB_WIDX 0xA08080\n#define IWX_RFH_Q_FRBDCB_WIDX(q) (IWX_RFH_Q0_FRBDCB_WIDX + (q) * 4)\n/* Write index table - shadow registers */\n#define IWX_RFH_Q0_FRBDCB_WIDX_TRG 0x1C80\n#define IWX_RFH_Q_FRBDCB_WIDX_TRG(q) (IWX_RFH_Q0_FRBDCB_WIDX_TRG + (q) * 4)\n/* Read index table */\n#define IWX_RFH_Q0_FRBDCB_RIDX 0xA080C0\n#define IWX_RFH_Q_FRBDCB_RIDX(q) (IWX_RFH_Q0_FRBDCB_RIDX + (q) * 4)\n/* Used list table */\n#define IWX_RFH_Q0_URBDCB_BA_LSB 0xA08100 /* 64 bit address */\n#define IWX_RFH_Q_URBDCB_BA_LSB(q) (IWX_RFH_Q0_URBDCB_BA_LSB + (q) * 8)\n/* Write index table */\n#define IWX_RFH_Q0_URBDCB_WIDX 0xA08180\n#define IWX_RFH_Q_URBDCB_WIDX(q) (IWX_RFH_Q0_URBDCB_WIDX + (q) * 4)\n#define IWX_RFH_Q0_URBDCB_VAID 0xA081C0\n#define IWX_RFH_Q_URBDCB_VAID(q) (IWX_RFH_Q0_URBDCB_VAID + (q) * 4)\n/* stts */\n#define IWX_RFH_Q0_URBD_STTS_WPTR_LSB 0xA08200 /*64 bits address */\n#define IWX_RFH_Q_URBD_STTS_WPTR_LSB(q) (IWX_RFH_Q0_URBD_STTS_WPTR_LSB + (q) * 8)\n\n#define IWX_RFH_Q0_ORB_WPTR_LSB 0xA08280\n#define IWX_RFH_Q_ORB_WPTR_LSB(q) (IWX_RFH_Q0_ORB_WPTR_LSB + (q) * 8)\n#define IWX_RFH_RBDBUF_RBD0_LSB 0xA08300\n#define IWX_RFH_RBDBUF_RBD_LSB(q) (IWX_RFH_RBDBUF_RBD0_LSB + (q) * 8)\n\n/**\n * RFH Status Register\n *\n * Bit fields:\n *\n * Bit 29: RBD_FETCH_IDLE\n * This status flag is set by the RFH when there is no active RBD fetch from\n * DRAM.\n * Once the RFH RBD controller starts fetching (or when there is a pending\n * RBD read response from DRAM), this flag is immediately turned off.\n *\n * Bit 30: SRAM_DMA_IDLE\n * This status flag is set by the RFH when there is no active transaction from\n * SRAM to DRAM.\n * Once the SRAM to DRAM DMA is active, this flag is immediately turned off.\n *\n * Bit 31: RXF_DMA_IDLE\n * This status flag is set by the RFH when there is no active transaction from\n * RXF to DRAM.\n * Once the RXF-to-DRAM DMA is active, this flag is immediately turned off.\n */\n#define IWX_RFH_GEN_STATUS          0xA09808\n#define IWX_RFH_GEN_STATUS_GEN3     0xA07824\n#define IWX_RBD_FETCH_IDLE  (1 << 29)\n#define IWX_SRAM_DMA_IDLE   (1 << 30)\n#define IWX_RXF_DMA_IDLE    (1U << 31)\n\n/* DMA configuration */\n#define IWX_RFH_RXF_DMA_CFG         0xA09820\n#define IWX_RFH_RXF_DMA_CFG_GEN3    0xA07880\n/* RB size */\n#define IWX_RFH_RXF_DMA_RB_SIZE_MASK (0x000F0000) /* bits 16-19 */\n#define IWX_RFH_RXF_DMA_RB_SIZE_POS 16\n#define IWX_RFH_RXF_DMA_RB_SIZE_1K  (0x1 << IWX_RFH_RXF_DMA_RB_SIZE_POS)\n#define IWX_RFH_RXF_DMA_RB_SIZE_2K  (0x2 << IWX_RFH_RXF_DMA_RB_SIZE_POS)\n#define IWX_RFH_RXF_DMA_RB_SIZE_4K  (0x4 << IWX_RFH_RXF_DMA_RB_SIZE_POS)\n#define IWX_RFH_RXF_DMA_RB_SIZE_8K  (0x8 << IWX_RFH_RXF_DMA_RB_SIZE_POS)\n#define IWX_RFH_RXF_DMA_RB_SIZE_12K (0x9 << IWX_RFH_RXF_DMA_RB_SIZE_POS)\n#define IWX_RFH_RXF_DMA_RB_SIZE_16K (0xA << IWX_RFH_RXF_DMA_RB_SIZE_POS)\n#define IWX_RFH_RXF_DMA_RB_SIZE_20K (0xB << IWX_RFH_RXF_DMA_RB_SIZE_POS)\n#define IWX_RFH_RXF_DMA_RB_SIZE_24K (0xC << IWX_RFH_RXF_DMA_RB_SIZE_POS)\n#define IWX_RFH_RXF_DMA_RB_SIZE_28K (0xD << IWX_RFH_RXF_DMA_RB_SIZE_POS)\n#define IWX_RFH_RXF_DMA_RB_SIZE_32K (0xE << IWX_RFH_RXF_DMA_RB_SIZE_POS)\n/* RB Circular Buffer size:defines the table sizes in RBD units */\n#define IWX_RFH_RXF_DMA_RBDCB_SIZE_MASK (0x00F00000) /* bits 20-23 */\n#define IWX_RFH_RXF_DMA_RBDCB_SIZE_POS 20\n#define IWX_RFH_RXF_DMA_RBDCB_SIZE_8        (0x3 << IWX_RFH_RXF_DMA_RBDCB_SIZE_POS)\n#define IWX_RFH_RXF_DMA_RBDCB_SIZE_16       (0x4 << IWX_RFH_RXF_DMA_RBDCB_SIZE_POS)\n#define IWX_RFH_RXF_DMA_RBDCB_SIZE_32       (0x5 << IWX_RFH_RXF_DMA_RBDCB_SIZE_POS)\n#define IWX_RFH_RXF_DMA_RBDCB_SIZE_64       (0x7 << IWX_RFH_RXF_DMA_RBDCB_SIZE_POS)\n#define IWX_RFH_RXF_DMA_RBDCB_SIZE_128      (0x7 << IWX_RFH_RXF_DMA_RBDCB_SIZE_POS)\n#define IWX_RFH_RXF_DMA_RBDCB_SIZE_256      (0x8 << IWX_RFH_RXF_DMA_RBDCB_SIZE_POS)\n#define IWX_RFH_RXF_DMA_RBDCB_SIZE_512      (0x9 << IWX_RFH_RXF_DMA_RBDCB_SIZE_POS)\n#define IWX_RFH_RXF_DMA_RBDCB_SIZE_1024     (0xA << IWX_RFH_RXF_DMA_RBDCB_SIZE_POS)\n#define IWX_RFH_RXF_DMA_RBDCB_SIZE_2048     (0xB << IWX_RFH_RXF_DMA_RBDCB_SIZE_POS)\n#define IWX_RFH_RXF_DMA_MIN_RB_SIZE_MASK    (0x03000000) /* bit 24-25 */\n#define IWX_RFH_RXF_DMA_MIN_RB_SIZE_POS     24\n#define IWX_RFH_RXF_DMA_MIN_RB_4_8          (3 << IWX_RFH_RXF_DMA_MIN_RB_SIZE_POS)\n#define IWX_RFH_RXF_DMA_DROP_TOO_LARGE_MASK (0x04000000) /* bit 26 */\n#define IWX_RFH_RXF_DMA_SINGLE_FRAME_MASK   (0x20000000) /* bit 29 */\n#define IWX_RFH_DMA_EN_MASK                 (0xC0000000) /* bits 30-31*/\n#define IWX_RFH_DMA_EN_ENABLE_VAL           (1U << 31)\n\n#define IWX_RFH_RXF_RXQ_ACTIVE 0xA0980C\n\n#define IWX_RFH_GEN_CFG     0xA09800\n#define IWX_RFH_GEN_CFG_SERVICE_DMA_SNOOP   (1 << 0)\n#define IWX_RFH_GEN_CFG_RFH_DMA_SNOOP       (1 << 1)\n#define IWX_RFH_GEN_CFG_RB_CHUNK_SIZE_128   0x00000010\n#define IWX_RFH_GEN_CFG_RB_CHUNK_SIZE_64    0x00000000\n/* the driver assumes everywhere that the default RXQ is 0 */\n#define IWX_RFH_GEN_CFG_DEFAULT_RXQ_NUM     0xF00\n\n/* end of 9000 rx series registers */\n\n/*\n * This register is writen by driver and is read by uCode during boot flow.\n * Note this address is cleared after MAC reset.\n */\n#define IWX_UREG_UCODE_LOAD_STATUS    (0xa05c40)\n#define IWX_UREG_CPU_INIT_RUN        (0xa05c44)\n\n/*\n * HBUS (Host-side Bus)\n *\n * HBUS registers are mapped directly into PCI bus space, but are used\n * to indirectly access device's internal memory or registers that\n * may be powered-down.\n *\n * Use iwl_write_direct32()/iwl_read_direct32() family for these registers;\n * host must \"grab nic access\" via CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ\n * to make sure the MAC (uCode processor, etc.) is powered up for accessing\n * internal resources.\n *\n * Do not use iwl_write32()/iwl_read32() family to access these registers;\n * these provide only simple PCI bus access, without waking up the MAC.\n */\n#define IWX_HBUS_BASE    (0x400)\n\n/*\n * Registers for accessing device's internal SRAM memory (e.g. SCD SRAM\n * structures, error log, event log, verifying uCode load).\n * First write to address register, then read from or write to data register\n * to complete the job.  Once the address register is set up, accesses to\n * data registers auto-increment the address by one dword.\n * Bit usage for address registers (read or write):\n *  0-31:  memory address within device\n */\n#define IWX_HBUS_TARG_MEM_RADDR     (IWX_HBUS_BASE+0x00c)\n#define IWX_HBUS_TARG_MEM_WADDR     (IWX_HBUS_BASE+0x010)\n#define IWX_HBUS_TARG_MEM_WDAT      (IWX_HBUS_BASE+0x018)\n#define IWX_HBUS_TARG_MEM_RDAT      (IWX_HBUS_BASE+0x01c)\n\n/*\n * Registers for accessing device's internal peripheral registers\n * (e.g. SCD, BSM, etc.).  First write to address register,\n * then read from or write to data register to complete the job.\n * Bit usage for address registers (read or write):\n *  0-15:  register address (offset) within device\n * 24-25:  (# bytes - 1) to read or write (e.g. 3 for dword)\n */\n#define IWX_HBUS_TARG_PRPH_WADDR    (IWX_HBUS_BASE+0x044)\n#define IWX_HBUS_TARG_PRPH_RADDR    (IWX_HBUS_BASE+0x048)\n#define IWX_HBUS_TARG_PRPH_WDAT     (IWX_HBUS_BASE+0x04c)\n#define IWX_HBUS_TARG_PRPH_RDAT     (IWX_HBUS_BASE+0x050)\n\n/* enable the ID buf for read */\n#define IWX_WFPM_PS_CTL_CLR            0xa0300c\n#define IWX_WFMP_MAC_ADDR_0            0xa03080\n#define IWX_WFMP_MAC_ADDR_1            0xa03084\n#define IWX_LMPM_PMG_EN                0xa01cec\n#define IWX_RADIO_REG_SYS_MANUAL_DFT_0        0xad4078\n#define IWX_RFIC_REG_RD                0xad0470\n#define IWX_WFPM_CTRL_REG            0xa03030\n#define IWX_WFPM_AUX_CTL_AUX_IF_MAC_OWNER_MSK    0x08000000\n#define IWX_ENABLE_WFPM                0x80000000\n\n#define IWX_AUX_MISC_MASTER1_EN            0xa20818\n#define IWX_AUX_MISC_MASTER1_EN_SBE_MSK        0x1\n#define IWX_AUX_MISC_MASTER1_SMPHR_STATUS    0xa20800\n#define IWX_RSA_ENABLE                0xa24b08\n#define IWX_PREG_AUX_BUS_WPROT_0        0xa04cc0\n#define IWX_PREG_PRPH_WPROT_9000        0xa04ce0\n#define IWX_PREG_PRPH_WPROT_22000        0xa04d00\n#define IWX_SB_CFG_OVERRIDE_ADDR        0xa26c78\n#define IWX_SB_CFG_OVERRIDE_ENABLE        0x8000\n#define IWX_SB_CFG_BASE_OVERRIDE        0xa20000\n#define IWX_SB_MODIFY_CFG_FLAG            0xa03088\n#define IWX_UMAG_SB_CPU_1_STATUS        0xa038c0\n#define IWX_UMAG_SB_CPU_2_STATUS        0xa038c4\n#define IWX_UMAG_GEN_HW_STATUS        0xA038C8\n#define IWX_UREG_UMAC_CURRENT_PC        0xa05c18\n#define IWX_UREG_LMAC1_CURRENT_PC        0xa05c1c\n#define IWX_UREG_LMAC2_CURRENT_PC        0xa05c20\n\n#define IWX_UREG_CHICK                0xa05c00\n#define IWX_UREG_CHICK_MSI_ENABLE        (1 << 24)\n#define IWX_UREG_CHICK_MSIX_ENABLE        (1 << 25)\n\n#define IWX_HPM_DEBUG            0xa03440\n#define IWX_PERSISTENCE_BIT        (1 << 12)\n#define IWX_PREG_WFPM_ACCESS        (1 << 12)\n\n#define IWX_HPM_HIPM_GEN_CFG            0xa03458\n#define IWX_HPM_HIPM_GEN_CFG_CR_PG_EN        (1 << 0)\n#define IWX_HPM_HIPM_GEN_CFG_CR_SLP_EN        (1 << 1)\n#define IWX_HPM_HIPM_GEN_CFG_CR_FORCE_ACTIVE    (1 << 10)\n\n#define IWX_UREG_DOORBELL_TO_ISR6        0xA05C04\n#define IWX_UREG_DOORBELL_TO_ISR6_NMI_BIT    (1 << 0)\n#define iWX_UREG_DOORBELL_TO_ISR6_RESET_HANDSHAKE ((1 << 0) | (1 << 1))\n#define IWX_UREG_DOORBELL_TO_ISR6_SUSPEND    (1 << 18)\n#define IWX_UREG_DOORBELL_TO_ISR6_RESUME    (1 << 19)\n#define IWX_UREG_DOORBELL_TO_ISR6_PNVM    (1 << 20)\n\n/*\n * Per-Tx-queue write pointer (index, really!)\n * Indicates index to next TFD that driver will fill (1 past latest filled).\n * Bit usage:\n *  0-7:  queue write index\n * 11-8:  queue selector\n */\n#define IWX_HBUS_TARG_WRPTR         (IWX_HBUS_BASE+0x060)\n\n/**********************************************************\n * CSR values\n **********************************************************/\n /*\n * host interrupt timeout value\n * used with setting interrupt coalescing timer\n * the CSR_INT_COALESCING is an 8 bit register in 32-usec unit\n *\n * default interrupt coalescing timer is 64 x 32 = 2048 usecs\n */\n#define IWX_HOST_INT_TIMEOUT_MAX    (0xFF)\n#define IWX_HOST_INT_TIMEOUT_DEF    (0x40)\n#define IWX_HOST_INT_TIMEOUT_MIN    (0x0)\n#define IWX_HOST_INT_OPER_MODE        (1U << 31)\n\n/*****************************************************************************\n *                        MSIX related registers                             *\n *****************************************************************************/\n\n#define IWX_CSR_MSIX_BASE            (0x2000)\n#define IWX_CSR_MSIX_FH_INT_CAUSES_AD        (IWX_CSR_MSIX_BASE + 0x800)\n#define IWX_CSR_MSIX_FH_INT_MASK_AD        (IWX_CSR_MSIX_BASE + 0x804)\n#define IWX_CSR_MSIX_HW_INT_CAUSES_AD        (IWX_CSR_MSIX_BASE + 0x808)\n#define IWX_CSR_MSIX_HW_INT_MASK_AD        (IWX_CSR_MSIX_BASE + 0x80C)\n#define IWX_CSR_MSIX_AUTOMASK_ST_AD        (IWX_CSR_MSIX_BASE + 0x810)\n#define IWX_CSR_MSIX_RX_IVAR_AD_REG        (IWX_CSR_MSIX_BASE + 0x880)\n#define IWX_CSR_MSIX_IVAR_AD_REG        (IWX_CSR_MSIX_BASE + 0x890)\n#define IWX_CSR_MSIX_PENDING_PBA_AD        (IWX_CSR_MSIX_BASE + 0x1000)\n#define IWX_CSR_MSIX_RX_IVAR(cause)        (IWX_CSR_MSIX_RX_IVAR_AD_REG + (cause))\n#define IWX_CSR_MSIX_IVAR(cause)        (IWX_CSR_MSIX_IVAR_AD_REG + (cause))\n\n/*\n * Causes for the FH register interrupts\n */\nenum iwx_msix_fh_int_causes {\n    IWX_MSIX_FH_INT_CAUSES_Q0        = (1 << 0),\n    IWX_MSIX_FH_INT_CAUSES_Q1        = (1 << 1),\n    IWX_MSIX_FH_INT_CAUSES_D2S_CH0_NUM    = (1 << 16),\n    IWX_MSIX_FH_INT_CAUSES_D2S_CH1_NUM    = (1 << 17),\n    IWX_MSIX_FH_INT_CAUSES_S2D        = (1 << 19),\n    IWX_MSIX_FH_INT_CAUSES_FH_ERR        = (1 << 21),\n};\n\n/*\n * Causes for the HW register interrupts\n */\nenum iwx_msix_hw_int_causes {\n    IWX_MSIX_HW_INT_CAUSES_REG_ALIVE    = (1 << 0),\n    IWX_MSIX_HW_INT_CAUSES_REG_WAKEUP    = (1 << 1),\n    IWX_MSIX_HW_INT_CAUSES_REG_IPC        = (1 << 1),\n    IWX_MSIX_HW_INT_CAUSES_REG_IML        = (1 << 2),\n    IWX_MSIX_HW_INT_CAUSES_REG_SW_ERR_V2    = (1 << 5),\n    IWX_MSIX_HW_INT_CAUSES_REG_CT_KILL    = (1 << 6),\n    IWX_MSIX_HW_INT_CAUSES_REG_RF_KILL    = (1 << 7),\n    IWX_MSIX_HW_INT_CAUSES_REG_PERIODIC    = (1 << 8),\n    IWX_MSIX_HW_INT_CAUSES_REG_SW_ERR    = (1 << 25),\n    IWX_MSIX_HW_INT_CAUSES_REG_SCD        = (1 << 26),\n    IWX_MSIX_HW_INT_CAUSES_REG_FH_TX    = (1 << 27),\n    IWX_MSIX_HW_INT_CAUSES_REG_HW_ERR    = (1 << 29),\n    IWX_MSIX_HW_INT_CAUSES_REG_HAP        = (1 << 30),\n};\n\n/*\n * Registers to map causes to vectors\n */\nenum iwx_msix_ivar_for_cause {\n    IWX_MSIX_IVAR_CAUSE_D2S_CH0_NUM        = 0x0,\n    IWX_MSIX_IVAR_CAUSE_D2S_CH1_NUM        = 0x1,\n    IWX_MSIX_IVAR_CAUSE_S2D            = 0x3,\n    IWX_MSIX_IVAR_CAUSE_FH_ERR        = 0x5,\n    IWX_MSIX_IVAR_CAUSE_REG_ALIVE        = 0x10,\n    IWX_MSIX_IVAR_CAUSE_REG_WAKEUP        = 0x11,\n    IWX_MSIX_IVAR_CAUSE_REG_IML        = 0x12,\n    IWX_MSIX_IVAR_CAUSE_REG_CT_KILL        = 0x16,\n    IWX_MSIX_IVAR_CAUSE_REG_RF_KILL        = 0x17,\n    IWX_MSIX_IVAR_CAUSE_REG_PERIODIC    = 0x18,\n    IWX_MSIX_IVAR_CAUSE_REG_SW_ERR        = 0x29,\n    IWX_MSIX_IVAR_CAUSE_REG_SCD        = 0x2a,\n    IWX_MSIX_IVAR_CAUSE_REG_FH_TX        = 0x2b,\n    IWX_MSIX_IVAR_CAUSE_REG_HW_ERR        = 0x2d,\n    IWX_MSIX_IVAR_CAUSE_REG_HAP        = 0x2e,\n};\n\n#define IWX_MSIX_AUTO_CLEAR_CAUSE        (0 << 7)\n#define IWX_MSIX_NON_AUTO_CLEAR_CAUSE        (1 << 7)\n\n/*****************************************************************************\n *                     HW address related registers                          *\n *****************************************************************************/\n\n#define IWX_CSR_ADDR_BASE            (0x380)\n#define IWX_CSR_MAC_ADDR0_OTP        (IWX_CSR_ADDR_BASE)\n#define IWX_CSR_MAC_ADDR1_OTP        (IWX_CSR_ADDR_BASE + 4)\n#define IWX_CSR_MAC_ADDR0_STRAP        (IWX_CSR_ADDR_BASE + 8)\n#define IWX_CSR_MAC_ADDR1_STRAP        (IWX_CSR_ADDR_BASE + 0xC)\n\n/**\n * uCode API flags\n * @IWX_UCODE_TLV_FLAGS_PAN: This is PAN capable microcode; this previously\n *    was a separate TLV but moved here to save space.\n * @IWX_UCODE_TLV_FLAGS_NEWSCAN: new uCode scan behaviour on hidden SSID,\n *    treats good CRC threshold as a boolean\n * @IWX_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w).\n * @IWX_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P.\n * @IWX_UCODE_TLV_FLAGS_DW_BC_TABLE: The SCD byte count table is in DWORDS\n * @IWX_UCODE_TLV_FLAGS_UAPSD: This uCode image supports uAPSD\n * @IWX_UCODE_TLV_FLAGS_SHORT_BL: 16 entries of black list instead of 64 in scan\n *    offload profile config command.\n * @IWX_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS: D3 image supports up to six\n *    (rather than two) IPv6 addresses\n * @IWX_UCODE_TLV_FLAGS_NO_BASIC_SSID: not sending a probe with the SSID element\n *    from the probe request template.\n * @IWX_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL: new NS offload (small version)\n * @IWX_UCODE_TLV_FLAGS_NEW_NSOFFL_LARGE: new NS offload (large version)\n * @IWX_UCODE_TLV_FLAGS_P2P_PS: P2P client power save is supported (only on a\n *    single bound interface).\n * @IWX_UCODE_TLV_FLAGS_UAPSD_SUPPORT: General support for uAPSD\n * @IWX_UCODE_TLV_FLAGS_EBS_SUPPORT: this uCode image supports EBS.\n * @IWX_UCODE_TLV_FLAGS_P2P_PS_UAPSD: P2P client supports uAPSD power save\n * @IWX_UCODE_TLV_FLAGS_BCAST_FILTERING: uCode supports broadcast filtering.\n * @IWX_UCODE_TLV_FLAGS_GO_UAPSD: AP/GO interfaces support uAPSD clients\n *\n */\n#define IWX_UCODE_TLV_FLAGS_PAN            (1 << 0)\n#define IWX_UCODE_TLV_FLAGS_NEWSCAN        (1 << 1)\n#define IWX_UCODE_TLV_FLAGS_MFP            (1 << 2)\n#define IWX_UCODE_TLV_FLAGS_P2P            (1 << 3)\n#define IWX_UCODE_TLV_FLAGS_DW_BC_TABLE        (1 << 4)\n#define IWX_UCODE_TLV_FLAGS_SHORT_BL        (1 << 7)\n#define IWX_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS    (1 << 10)\n#define IWX_UCODE_TLV_FLAGS_NO_BASIC_SSID    (1 << 12)\n#define IWX_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL    (1 << 15)\n#define IWX_UCODE_TLV_FLAGS_NEW_NSOFFL_LARGE    (1 << 16)\n#define IWX_UCODE_TLV_FLAGS_P2P_PS        (1 << 21)\n#define IWX_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM    (1 << 22)\n#define IWX_UCODE_TLV_FLAGS_BSS_P2P_PS_SCM    (1 << 23)\n#define IWX_UCODE_TLV_FLAGS_UAPSD_SUPPORT    (1 << 24)\n#define IWX_UCODE_TLV_FLAGS_EBS_SUPPORT        (1 << 25)\n#define IWX_UCODE_TLV_FLAGS_P2P_PS_UAPSD    (1 << 26)\n#define IWX_UCODE_TLV_FLAGS_BCAST_FILTERING    (1 << 29)\n#define IWX_UCODE_TLV_FLAGS_GO_UAPSD        (1 << 30)\n#define IWX_UCODE_TLV_FLAGS_LTE_COEX        (1U << 31)\n\n#define IWX_UCODE_TLV_FLAG_BITS \\\n    \"\\020\\1PAN\\2NEWSCAN\\3MFP\\4P2P\\5DW_BC_TABLE\\6NEWBT_COEX\\7PM_CMD\\10SHORT_BL\\11RX_ENERGY\\12TIME_EVENT_V2\\13D3_6_IPV6\\14BF_UPDATED\\15NO_BASIC_SSID\\17D3_CONTINUITY\\20NEW_NSOFFL_S\\21NEW_NSOFFL_L\\22SCHED_SCAN\\24STA_KEY_CMD\\25DEVICE_PS_CMD\\26P2P_PS\\27P2P_PS_DCM\\30P2P_PS_SCM\\31UAPSD_SUPPORT\\32EBS\\33P2P_PS_UAPSD\\36BCAST_FILTERING\\37GO_UAPSD\\40LTE_COEX\"\n\n/**\n * uCode TLV api\n * @IWX_UCODE_TLV_API_FRAGMENTED_SCAN: This ucode supports active dwell time\n *    longer than the passive one, which is essential for fragmented scan.\n * @IWX_UCODE_TLV_API_WIFI_MCC_UPDATE: ucode supports MCC updates with source.\n * @IWX_UCODE_TLV_API_WIDE_CMD_HDR: ucode supports wide command header\n * @IWX_UCODE_TLV_API_LQ_SS_PARAMS: Configure STBC/BFER via LQ CMD ss_params\n * @IWX_UCODE_TLV_API_NEW_VERSION: new versioning format\n * @IWX_UCODE_TLV_API_TX_POWER_CHAIN: TX power API has larger command size\n *    (command version 3) that supports per-chain limits\n * @IWX_UCODE_TLV_API_SCAN_TSF_REPORT: Scan start time reported in scan\n *    iteration complete notification, and the timestamp reported for RX\n *    received during scan, are reported in TSF of the mac specified in the\n *    scan request.\n * @IWX_UCODE_TLV_API_TKIP_MIC_KEYS: This ucode supports version 2 of\n *    ADD_MODIFY_STA_KEY_API_S_VER_2.\n * @IWX_UCODE_TLV_API_STA_TYPE: This ucode supports station type assignement.\n * @IWX_UCODE_TLV_API_EXT_SCAN_PRIORITY: scan APIs use 8-level priority\n *    instead of 3.\n * @IWX_UCODE_TLV_API_NEW_RX_STATS: should new RX STATISTICS API be used\n * @IWX_UCODE_TLV_API_REDUCED_SCAN_CONFIG: This ucode supports v3 of\n *  SCAN_CONFIG_DB_CMD_API_S.\n *\n * @IWX_NUM_UCODE_TLV_API: number of bits used\n */\n#define IWX_UCODE_TLV_API_FRAGMENTED_SCAN    8\n#define IWX_UCODE_TLV_API_WIFI_MCC_UPDATE    9\n#define IWX_UCODE_TLV_API_WIDE_CMD_HDR        14\n#define IWX_UCODE_TLV_API_LQ_SS_PARAMS        18\n#define IWX_UCODE_TLV_API_NEW_VERSION        20\n#define IWX_UCODE_TLV_API_EXT_SCAN_PRIORITY    24\n#define IWX_UCODE_TLV_API_TX_POWER_CHAIN    27\n#define IWX_UCODE_TLV_API_SCAN_TSF_REPORT    28\n#define IWX_UCODE_TLV_API_TKIP_MIC_KEYS         29\n#define IWX_UCODE_TLV_API_STA_TYPE        30\n#define IWX_UCODE_TLV_API_NAN2_VER2        31\n#define IWX_UCODE_TLV_API_ADAPTIVE_DWELL    32\n#define IWX_UCODE_TLV_API_NEW_RX_STATS        35\n#define IWX_UCODE_TLV_API_ADAPTIVE_DWELL_V2    42\n#define IWX_UCODE_TLV_API_BEACON_FILTER_V4    47\n#define IWX_UCODE_TLV_API_REGULATORY_NVM_INFO   48\n#define IWX_UCODE_TLV_API_FTM_NEW_RANGE_REQ     49\n#define IWX_UCODE_TLV_API_SCAN_OFFLOAD_CHANS    50\n#define IWX_UCODE_TLV_API_MBSSID_HE             52\n#define IWX_UCODE_TLV_API_WOWLAN_TCP_SYN_WAKE   53\n#define IWX_UCODE_TLV_API_FTM_RTT_ACCURACY      54\n#define IWX_UCODE_TLV_API_SAR_TABLE_VER         55\n#define IWX_UCODE_TLV_API_REDUCED_SCAN_CONFIG   56\n#define IWX_UCODE_TLV_API_ADWELL_HB_DEF_N_AP    57\n#define IWX_UCODE_TLV_API_SCAN_EXT_CHAN_VER    58\n#define IWX_UCODE_TLV_API_BAND_IN_RX_DATA       59\n#define IWX_NUM_UCODE_TLV_API            128\n\n#define IWX_UCODE_TLV_API_BITS \\\n    \"\\020\\10FRAGMENTED_SCAN\\11WIFI_MCC_UPDATE\\16WIDE_CMD_HDR\\22LQ_SS_PARAMS\\30EXT_SCAN_PRIO\\33TX_POWER_CHAIN\\35TKIP_MIC_KEYS\"\n\n/**\n * uCode capabilities\n * @IWX_UCODE_TLV_CAPA_D0I3_SUPPORT: supports D0i3\n * @IWX_UCODE_TLV_CAPA_LAR_SUPPORT: supports Location Aware Regulatory\n * @IWX_UCODE_TLV_CAPA_UMAC_SCAN: supports UMAC scan.\n * @IWX_UCODE_TLV_CAPA_BEAMFORMER: supports Beamformer\n * @IWX_UCODE_TLV_CAPA_TOF_SUPPORT: supports Time of Flight (802.11mc FTM)\n * @IWX_UCODE_TLV_CAPA_TDLS_SUPPORT: support basic TDLS functionality\n * @IWX_UCODE_TLV_CAPA_TXPOWER_INSERTION_SUPPORT: supports insertion of current\n *    tx power value into TPC Report action frame and Link Measurement Report\n *    action frame\n * @IWX_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT: supports updating current\n *    channel in DS parameter set element in probe requests.\n * @IWX_UCODE_TLV_CAPA_WFA_TPC_REP_IE_SUPPORT: supports adding TPC Report IE in\n *    probe requests.\n * @IWX_UCODE_TLV_CAPA_QUIET_PERIOD_SUPPORT: supports Quiet Period requests\n * @IWX_UCODE_TLV_CAPA_DQA_SUPPORT: supports dynamic queue allocation (DQA),\n *    which also implies support for the scheduler configuration command\n * @IWX_UCODE_TLV_CAPA_TDLS_CHANNEL_SWITCH: supports TDLS channel switching\n * @IWX_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG: Consolidated D3-D0 image\n * @IWX_UCODE_TLV_CAPA_HOTSPOT_SUPPORT: supports Hot Spot Command\n * @IWX_UCODE_TLV_CAPA_DC2DC_SUPPORT: supports DC2DC Command\n * @IWX_UCODE_TLV_CAPA_2G_COEX_SUPPORT: supports 2G coex Command\n * @IWX_UCODE_TLV_CAPA_CSUM_SUPPORT: supports TCP Checksum Offload\n * @IWX_UCODE_TLV_CAPA_RADIO_BEACON_STATS: support radio and beacon statistics\n * @IWX_UCODE_TLV_CAPA_P2P_STANDALONE_UAPSD: support p2p standalone U-APSD\n * @IWX_UCODE_TLV_CAPA_BT_COEX_PLCR: enabled BT Coex packet level co-running\n * @IWX_UCODE_TLV_CAPA_LAR_MULTI_MCC: ucode supports LAR updates with different\n *    sources for the MCC. This TLV bit is a future replacement to\n *    IWX_UCODE_TLV_API_WIFI_MCC_UPDATE. When either is set, multi-source LAR\n *    is supported.\n * @IWX_UCODE_TLV_CAPA_BT_COEX_RRC: supports BT Coex RRC\n * @IWX_UCODE_TLV_CAPA_GSCAN_SUPPORT: supports gscan\n * @IWX_UCODE_TLV_CAPA_NAN_SUPPORT: supports NAN\n * @IWX_UCODE_TLV_CAPA_UMAC_UPLOAD: supports upload mode in umac (1=supported,\n *    0=no support)\n * @IWx_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS: firmware supports ultra high band\n *    (6 GHz).\n * @IWX_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE: extended DTS measurement\n * @IWX_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS: supports short PM timeouts\n * @IWX_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT: supports bt-coex Multi-priority LUT\n * @IWX_UCODE_TLV_CAPA_BEACON_ANT_SELECTION: firmware will decide on what\n *    antenna the beacon should be transmitted\n * @IWX_UCODE_TLV_CAPA_BEACON_STORING: firmware will store the latest beacon\n *    from AP and will send it upon d0i3 exit.\n * @IWX_UCODE_TLV_CAPA_LAR_SUPPORT_V2: support LAR API V2\n * @IWX_UCODE_TLV_CAPA_CT_KILL_BY_FW: firmware responsible for CT-kill\n * @IWX_UCODE_TLV_CAPA_TEMP_THS_REPORT_SUPPORT: supports temperature\n *    thresholds reporting\n * @IWX_UCODE_TLV_CAPA_CTDP_SUPPORT: supports cTDP command\n * @IWX_UCODE_TLV_CAPA_USNIFFER_UNIFIED: supports usniffer enabled in\n *    regular image.\n * @IWX_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG: support getting more shared\n *    memory addresses from the firmware.\n * @IWX_UCODE_TLV_CAPA_LQM_SUPPORT: supports Link Quality Measurement\n * @IWX_UCODE_TLV_CAPA_LMAC_UPLOAD: supports upload mode in lmac (1=supported,\n *    0=no support)\n *\n * @IWX_NUM_UCODE_TLV_CAPA: number of bits used\n */\n#define IWX_UCODE_TLV_CAPA_D0I3_SUPPORT            0\n#define IWX_UCODE_TLV_CAPA_LAR_SUPPORT            1\n#define IWX_UCODE_TLV_CAPA_UMAC_SCAN            2\n#define IWX_UCODE_TLV_CAPA_BEAMFORMER            3\n#define IWX_UCODE_TLV_CAPA_TOF_SUPPORT                  5\n#define IWX_UCODE_TLV_CAPA_TDLS_SUPPORT            6\n#define IWX_UCODE_TLV_CAPA_TXPOWER_INSERTION_SUPPORT    8\n#define IWX_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT    9\n#define IWX_UCODE_TLV_CAPA_WFA_TPC_REP_IE_SUPPORT    10\n#define IWX_UCODE_TLV_CAPA_QUIET_PERIOD_SUPPORT        11\n#define IWX_UCODE_TLV_CAPA_DQA_SUPPORT            12\n#define IWX_UCODE_TLV_CAPA_TDLS_CHANNEL_SWITCH        13\n#define IWX_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG        17\n#define IWX_UCODE_TLV_CAPA_HOTSPOT_SUPPORT        18\n#define IWX_UCODE_TLV_CAPA_DC2DC_CONFIG_SUPPORT        19\n#define IWX_UCODE_TLV_CAPA_2G_COEX_SUPPORT        20\n#define IWX_UCODE_TLV_CAPA_CSUM_SUPPORT            21\n#define IWX_UCODE_TLV_CAPA_RADIO_BEACON_STATS        22\n#define IWX_UCODE_TLV_CAPA_P2P_STANDALONE_UAPSD        26\n#define IWX_UCODE_TLV_CAPA_BT_COEX_PLCR            28\n#define IWX_UCODE_TLV_CAPA_LAR_MULTI_MCC        29\n#define IWX_UCODE_TLV_CAPA_BT_COEX_RRC            30\n#define IWX_UCODE_TLV_CAPA_GSCAN_SUPPORT        31\n#define IWX_UCODE_TLV_CAPA_NAN_SUPPORT            34\n#define IWX_UCODE_TLV_CAPA_UMAC_UPLOAD            35\n#define IWX_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT        39\n#define IWX_UCODE_TLV_CAPA_CDB_SUPPORT            40\n#define IWX_UCODE_TLV_CAPA_TLC_OFFLOAD                  43\n#define IWX_UCODE_TLV_CAPA_DYNAMIC_QUOTA                44\n#define IWX_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS        48\n#define IWX_UCODE_TLV_CAPA_CS_MODIFY                49\n#define IWX_UCODE_TLV_CAPA_SET_LTR_GEN2             50\n#define IWX_UCODE_TLV_CAPA_SET_PPAG                 52\n#define IWX_UCODE_TLV_CAPA_SESSION_PROT_CMD         54\n#define IWX_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE        64\n#define IWX_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS        65\n#define IWX_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT        67\n#define IWX_UCODE_TLV_CAPA_MULTI_QUEUE_RX_SUPPORT    68\n#define IWX_UCODE_TLV_CAPA_BEACON_ANT_SELECTION        71\n#define IWX_UCODE_TLV_CAPA_BEACON_STORING        72\n#define IWX_UCODE_TLV_CAPA_LAR_SUPPORT_V2        73\n#define IWX_UCODE_TLV_CAPA_CT_KILL_BY_FW        74\n#define IWX_UCODE_TLV_CAPA_TEMP_THS_REPORT_SUPPORT    75\n#define IWX_UCODE_TLV_CAPA_CTDP_SUPPORT            76\n#define IWX_UCODE_TLV_CAPA_USNIFFER_UNIFIED        77\n#define IWX_UCODE_TLV_CAPA_LMAC_UPLOAD            79\n#define IWX_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG    80\n#define IWX_UCODE_TLV_CAPA_LQM_SUPPORT            81\n#define IWX_UCODE_TLV_CAPA_LED_CMD_SUPPORT        88\n\n#define IWX_NUM_UCODE_TLV_CAPA 128\n\n/*\n * For 16.0 uCode and above, there is no differentiation between sections,\n * just an offset to the HW address.\n */\n#define IWX_CPU1_CPU2_SEPARATOR_SECTION        0xFFFFCCCC\n#define IWX_PAGING_SEPARATOR_SECTION        0xAAAABBBB\n\n/* uCode version contains 4 values: Major/Minor/API/Serial */\n#define IWX_UCODE_MAJOR(ver)    (((ver) & 0xFF000000) >> 24)\n#define IWX_UCODE_MINOR(ver)    (((ver) & 0x00FF0000) >> 16)\n#define IWX_UCODE_API(ver)    (((ver) & 0x0000FF00) >> 8)\n#define IWX_UCODE_SERIAL(ver)    ((ver) & 0x000000FF)\n\n/*\n * Calibration control struct.\n * Sent as part of the phy configuration command.\n * @flow_trigger: bitmap for which calibrations to perform according to\n *        flow triggers.\n * @event_trigger: bitmap for which calibrations to perform according to\n *        event triggers.\n */\nstruct iwx_tlv_calib_ctrl {\n    uint32_t flow_trigger;\n    uint32_t event_trigger;\n} __packed;\n\n#define IWX_FW_PHY_CFG_RADIO_TYPE_POS    0\n#define IWX_FW_PHY_CFG_RADIO_TYPE    (0x3 << IWX_FW_PHY_CFG_RADIO_TYPE_POS)\n#define IWX_FW_PHY_CFG_RADIO_STEP_POS    2\n#define IWX_FW_PHY_CFG_RADIO_STEP    (0x3 << IWX_FW_PHY_CFG_RADIO_STEP_POS)\n#define IWX_FW_PHY_CFG_RADIO_DASH_POS    4\n#define IWX_FW_PHY_CFG_RADIO_DASH    (0x3 << IWX_FW_PHY_CFG_RADIO_DASH_POS)\n#define IWX_FW_PHY_CFG_TX_CHAIN_POS    16\n#define IWX_FW_PHY_CFG_TX_CHAIN        (0xf << IWX_FW_PHY_CFG_TX_CHAIN_POS)\n#define IWX_FW_PHY_CFG_RX_CHAIN_POS    20\n#define IWX_FW_PHY_CFG_RX_CHAIN        (0xf << IWX_FW_PHY_CFG_RX_CHAIN_POS)\n#define IWX_FW_PHY_CFG_CHAIN_SAD_POS    23\n#define IWX_FW_PHY_CFG_CHAIN_SAD_ENABLED (0x1 << IWX_FW_PHY_CFG_CHAIN_SAD_POS)\n#define IWX_FW_PHY_CFG_CHAIN_SAD_ANT_A  (0x2 << IWX_FW_PHY_CFG_CHAIN_SAD_POS)\n#define IWX_FW_PHY_CFG_CHAIN_SAD_ANT_B  (0x4 << IWX_FW_PHY_CFG_CHAIN_SAD_POS)\n#define IWX_FW_PHY_CFG_SHARED_CLK       (1 << 31)\n\n/**\n * struct iwx_fw_cipher_scheme - a cipher scheme supported by FW.\n * @cipher: a cipher suite selector\n * @flags: cipher scheme flags (currently reserved for a future use)\n * @hdr_len: a size of MPDU security header\n * @pn_len: a size of PN\n * @pn_off: an offset of pn from the beginning of the security header\n * @key_idx_off: an offset of key index byte in the security header\n * @key_idx_mask: a bit mask of key_idx bits\n * @key_idx_shift: bit shift needed to get key_idx\n * @mic_len: mic length in bytes\n * @hw_cipher: a HW cipher index used in host commands\n */\nstruct iwx_fw_cipher_scheme {\n    uint32_t cipher;\n    uint8_t flags;\n    uint8_t hdr_len;\n    uint8_t pn_len;\n    uint8_t pn_off;\n    uint8_t key_idx_off;\n    uint8_t key_idx_mask;\n    uint8_t key_idx_shift;\n    uint8_t mic_len;\n    uint8_t hw_cipher;\n} __packed;\n\n/**\n * struct iwx_fw_cscheme_list - a cipher scheme list\n * @size: a number of entries\n * @cs: cipher scheme entries\n */\nstruct iwx_fw_cscheme_list {\n    uint8_t size;\n    struct iwx_fw_cipher_scheme cs[];\n} __packed;\n\n/* v1/v2 uCode file layout */\nstruct iwx_ucode_header {\n    uint32_t ver;    /* major/minor/API/serial */\n    union {\n        struct {\n            uint32_t inst_size;    /* bytes of runtime code */\n            uint32_t data_size;    /* bytes of runtime data */\n            uint32_t init_size;    /* bytes of init code */\n            uint32_t init_data_size;    /* bytes of init data */\n            uint32_t boot_size;    /* bytes of bootstrap code */\n            uint8_t data[0];        /* in same order as sizes */\n        } v1;\n        struct {\n            uint32_t build;        /* build number */\n            uint32_t inst_size;    /* bytes of runtime code */\n            uint32_t data_size;    /* bytes of runtime data */\n            uint32_t init_size;    /* bytes of init code */\n            uint32_t init_data_size;    /* bytes of init data */\n            uint32_t boot_size;    /* bytes of bootstrap code */\n            uint8_t data[0];        /* in same order as sizes */\n        } v2;\n    } u;\n};\n\n/*\n * new TLV uCode file layout\n *\n * The new TLV file format contains TLVs, that each specify\n * some piece of data.\n */\n\n#define IWX_UCODE_TLV_INVALID        0 /* unused */\n#define IWX_UCODE_TLV_INST        1\n#define IWX_UCODE_TLV_DATA        2\n#define IWX_UCODE_TLV_INIT        3\n#define IWX_UCODE_TLV_INIT_DATA        4\n#define IWX_UCODE_TLV_BOOT        5\n#define IWX_UCODE_TLV_PROBE_MAX_LEN    6 /* a uint32_t value */\n#define IWX_UCODE_TLV_PAN        7\n#define IWX_UCODE_TLV_RUNT_EVTLOG_PTR    8\n#define IWX_UCODE_TLV_RUNT_EVTLOG_SIZE    9\n#define IWX_UCODE_TLV_RUNT_ERRLOG_PTR    10\n#define IWX_UCODE_TLV_INIT_EVTLOG_PTR    11\n#define IWX_UCODE_TLV_INIT_EVTLOG_SIZE    12\n#define IWX_UCODE_TLV_INIT_ERRLOG_PTR    13\n#define IWX_UCODE_TLV_ENHANCE_SENS_TBL    14\n#define IWX_UCODE_TLV_PHY_CALIBRATION_SIZE 15\n#define IWX_UCODE_TLV_WOWLAN_INST    16\n#define IWX_UCODE_TLV_WOWLAN_DATA    17\n#define IWX_UCODE_TLV_FLAGS        18\n#define IWX_UCODE_TLV_SEC_RT        19\n#define IWX_UCODE_TLV_SEC_INIT        20\n#define IWX_UCODE_TLV_SEC_WOWLAN    21\n#define IWX_UCODE_TLV_DEF_CALIB        22\n#define IWX_UCODE_TLV_PHY_SKU        23\n#define IWX_UCODE_TLV_SECURE_SEC_RT    24\n#define IWX_UCODE_TLV_SECURE_SEC_INIT    25\n#define IWX_UCODE_TLV_SECURE_SEC_WOWLAN    26\n#define IWX_UCODE_TLV_NUM_OF_CPU    27\n#define IWX_UCODE_TLV_CSCHEME        28\n#define IWX_UCODE_TLV_API_CHANGES_SET    29\n#define IWX_UCODE_TLV_ENABLED_CAPABILITIES 30\n#define IWX_UCODE_TLV_N_SCAN_CHANNELS    31\n#define IWX_UCODE_TLV_PAGING        32\n#define IWX_UCODE_TLV_SEC_RT_USNIFFER    34\n#define IWX_UCODE_TLV_SDIO_ADMA_ADDR    35\n#define IWX_UCODE_TLV_FW_VERSION    36\n#define IWX_UCODE_TLV_FW_DBG_DEST    38\n#define IWX_UCODE_TLV_FW_DBG_CONF    39\n#define IWX_UCODE_TLV_FW_DBG_TRIGGER    40\n#define IWX_UCODE_TLV_CMD_VERSIONS    48\n#define IWX_UCODE_TLV_FW_GSCAN_CAPA    50\n#define IWX_UCODE_TLV_FW_MEM_SEG    51\n#define IWX_UCODE_TLV_IML        52\n#define IWX_UCODE_TLV_FW_FMAC_API_VERSION 53\n#define IWX_UCODE_TLV_UMAC_DEBUG_ADDRS    54\n#define IWX_UCODE_TLV_LMAC_DEBUG_ADDRS    55\n#define IWX_UCODE_TLV_FW_RECOVERY_INFO    57\n#define IWX_UCODE_TLV_HW_TYPE             58\n#define IWX_UCODE_TLV_FW_FMAC_RECOVERY_INFO 59\n#define IWX_UCODE_TLV_FW_FSEQ_VERSION    60\n#define IWX_UCODE_PHY_INTEGRATION_VERSION 61\n#define IWX_UCODE_TLV_PNVM_VERSION        62\n#define IWX_UCODE_TLV_PNVM_SKU            64\n\n#define IWX_UCODE_TLV_DEBUG_BASE    0x1000005\n#define IWX_UCODE_TLV_CONST_BASE    0x100\n#define IWX_UCODE_TLV_FW_NUM_STATIONS       (IWX_UCODE_TLV_CONST_BASE + 0)\n#define IWX_UCODE_TLV_TYPE_DEBUG_INFO        (IWX_UCODE_TLV_DEBUG_BASE + 0)\n#define IWX_UCODE_TLV_TYPE_BUFFER_ALLOCATION    (IWX_UCODE_TLV_DEBUG_BASE + 1)\n#define IWX_UCODE_TLV_TYPE_HCMD            (IWX_UCODE_TLV_DEBUG_BASE + 2)\n#define IWX_UCODE_TLV_TYPE_REGIONS        (IWX_UCODE_TLV_DEBUG_BASE + 3)\n#define IWX_UCODE_TLV_TYPE_TRIGGERS        (IWX_UCODE_TLV_DEBUG_BASE + 4)\n#define IWX_UCODE_TLV_TYPE_CONF_SET        (IWX_UCODE_TLV_DEBUG_BASE + 5)\n#define IWX_UCODE_TLV_DEBUG_MAX IWX_UCODE_TLV_TYPE_CONF_SET\n\n\nstruct iwx_ucode_tlv {\n    uint32_t type;        /* see above */\n    uint32_t length;        /* not including type/length fields */\n    uint8_t data[0];\n};\n\nstruct iwx_ucode_api {\n    uint32_t api_index;\n    uint32_t api_flags;\n} __packed;\n\nstruct iwx_ucode_capa {\n    uint32_t api_index;\n    uint32_t api_capa;\n} __packed;\n\n#define IWX_TLV_UCODE_MAGIC    0x0a4c5749\n\nstruct iwx_tlv_ucode_header {\n    /*\n     * The TLV style ucode header is distinguished from\n     * the v1/v2 style header by first four bytes being\n     * zero, as such is an invalid combination of\n     * major/minor/API/serial versions.\n     */\n    uint32_t zero;\n    uint32_t magic;\n    uint8_t human_readable[64];\n    uint32_t ver;        /* major/minor/API/serial */\n    uint32_t build;\n    uint64_t ignore;\n    /*\n     * The data contained herein has a TLV layout,\n     * see above for the TLV header and types.\n     * Note that each TLV is padded to a length\n     * that is a multiple of 4 for alignment.\n     */\n    uint8_t data[0];\n};\n\n/*\n * Registers in this file are internal, not PCI bus memory mapped.\n * Driver accesses these via IWX_HBUS_TARG_PRPH_* registers.\n */\n#define IWX_PRPH_BASE    (0x00000)\n#define IWX_PRPH_END    (0xFFFFF)\n\n/****************************/\n/* Flow Handler Definitions */\n/****************************/\n\n/**\n * struct iwx_rb_status - receive buffer status\n *     host memory mapped FH registers\n * @closed_rb_num [0:11] - Indicates the index of the RB which was closed\n * @closed_fr_num [0:11] - Indicates the index of the RX Frame which was closed\n * @finished_rb_num [0:11] - Indicates the index of the current RB\n *     in which the last frame was written to\n * @finished_fr_num [0:11] - Indicates the index of the RX Frame\n *     which was transferred\n */\nstruct iwx_rb_status {\n    uint16_t closed_rb_num;\n    uint16_t closed_fr_num;\n    uint16_t finished_rb_num;\n    uint16_t finished_fr_nam;\n    uint32_t unused;\n} __packed;\n\n/**\n * struct iwx_rx_completion_desc - completion descriptor\n * @reserved1: reserved\n * @rbid: unique tag of the received buffer\n * @flags: flags (0: fragmented, all others: reserved)\n * @reserved2: reserved\n */\nstruct iwx_rx_completion_desc {\n    uint32_t reserved1;\n    uint16_t rbid;\n    uint8_t flags;\n    uint8_t reserved2[25];\n} __packed;\n\n\n#define IWX_TFD_QUEUE_SIZE_MAX        (256)\n#define IWX_TFD_QUEUE_SIZE_MAX_GEN3    (65536)\n/* cb size is the exponent - 3 */\n#define IWX_TFD_QUEUE_CB_SIZE(x)    (IWX_RX_QUEUE_CB_SIZE(x) - 3)\n#define IWX_TFD_QUEUE_SIZE_BC_DUP    (64)\n#define IWX_TFD_QUEUE_BC_SIZE        (IWX_TFD_QUEUE_SIZE_MAX + \\\n                    IWX_TFD_QUEUE_SIZE_BC_DUP)\n#define IWX_TFD_QUEUE_BC_SIZE_GEN3    1024\n#define IWX_TFH_NUM_TBS        25\n\n/**\n * struct iwx_tfh_tb transmit buffer descriptor within transmit frame descriptor\n *\n * This structure contains dma address and length of transmission address\n *\n * @tb_len length of the tx buffer\n * @addr 64 bits dma address\n */\nstruct iwx_tfh_tb {\n    uint16_t tb_len;\n    uint64_t addr;\n} __packed;\n\n/**\n * Each Tx queue uses a circular buffer of 256 TFDs stored in host DRAM.\n * Both driver and device share these circular buffers, each of which must be\n * contiguous 256 TFDs.\n * For pre 22000 HW it is 256 x 128 bytes-per-TFD = 32 KBytes\n * For 22000 HW and on it is 256 x 256 bytes-per-TFD = 65 KBytes\n *\n * Each TFD contains pointer/size information for up to 25 data buffers\n * in host DRAM.  These buffers collectively contain the (one) frame described\n * by the TFD.  Each buffer must be a single contiguous block of memory within\n * itself, but buffers may be scattered in host DRAM.  Each buffer has max size\n * of (4K - 4).  The concatenates all of a TFD's buffers into a single\n * Tx frame, up to 8 KBytes in size.\n *\n * A maximum of 255 (not 256!) TFDs may be on a queue waiting for Tx.\n */\n\n/**\n * struct iwx_tfh_tfd - Transmit Frame Descriptor (TFD)\n * @ num_tbs 0-4 number of active tbs\n *         5 -15   reserved\n * @ tbs[25]    transmit frame buffer descriptors\n * @ __pad    padding\n */\nstruct iwx_tfh_tfd {\n    uint16_t num_tbs;\n    struct iwx_tfh_tb tbs[IWX_TFH_NUM_TBS];\n    uint32_t __pad;\n} __packed;\n\n/* Fixed (non-configurable) rx data from phy */\n\n/**\n * struct iwx_agn_schedq_bc_tbl scheduler byte count table\n *    base physical address provided by IWX_SCD_DRAM_BASE_ADDR\n * @tfd_offset  0-12 - tx command byte count\n *           12-16 - station index\n */\nstruct iwx_agn_scd_bc_tbl {\n    uint16_t tfd_offset[IWX_TFD_QUEUE_BC_SIZE];\n} __packed;\n\n/**\n * struct iwx_gen3_bc_tbl scheduler byte count table gen3\n * For 22560 and on:\n * @tfd_offset: 0-12 - tx command byte count\n *        12-13 - number of 64 byte chunks\n *        14-16 - reserved\n */\nstruct iwx_gen3_bc_tbl {\n    uint16_t tfd_offset[IWX_TFD_QUEUE_BC_SIZE_GEN3];\n} __packed;\n\n/* Maximum number of Tx queues. */\n#define IWX_MAX_QUEUES    31\n#define IWX_MAX_TVQM_QUEUES 512\n\n/**\n * DQA - Dynamic Queue Allocation -introduction\n *\n * Dynamic Queue Allocation (AKA \"DQA\") is a feature implemented in iwlwifi\n * to allow dynamic allocation of queues on-demand, rather than allocate them\n * statically ahead of time. Ideally, we would like to allocate one queue\n * per RA/TID, thus allowing an AP - for example - to send BE traffic to STA2\n * even if it also needs to send traffic to a sleeping STA1, without being\n * blocked by the sleeping station.\n *\n * Although the queues in DQA mode are dynamically allocated, there are still\n * some queues that are statically allocated:\n *    TXQ #0 - command queue\n *    TXQ #1 - aux frames\n *    TXQ #2 - P2P device frames\n *    TXQ #3 - P2P GO/SoftAP GCAST/BCAST frames\n *    TXQ #4 - BSS DATA frames queue\n *    TXQ #5-8 - non-QoS data, QoS no-data, and MGMT frames queue pool\n *    TXQ #9 - P2P GO/SoftAP probe responses\n *    TXQ #10-31 - QoS DATA frames queue pool (for Tx aggregation)\n */\n\n/* static DQA Tx queue numbers */\n#define IWX_DQA_CMD_QUEUE        0\n#define IWX_DQA_AUX_QUEUE        1\n#define IWX_DQA_P2P_DEVICE_QUEUE    2\n#define IWX_DQA_INJECT_MONITOR_QUEUE    2\n#define IWX_DQA_GCAST_QUEUE        3\n#define IWX_DQA_BSS_CLIENT_QUEUE    4\n#define IWX_DQA_MIN_MGMT_QUEUE        5\n#define IWX_DQA_MAX_MGMT_QUEUE        8\n#define IWX_DQA_AP_PROBE_RESP_QUEUE    9\n#define IWX_DQA_MIN_DATA_QUEUE        10\n#define IWX_DQA_MAX_DATA_QUEUE        31\n\n#define IWX_TX_FIFO_BK    0\n#define IWX_TX_FIFO_BE    1\n#define IWX_TX_FIFO_VI    2\n#define IWX_TX_FIFO_VO    3\n#define IWX_TX_FIFO_MCAST    5\n#define IWX_TX_FIFO_CMD    7\n\nenum iwx_gen2_tx_fifo {\n    IWX_GEN2_TX_FIFO_CMD = 0,\n    IWX_GEN2_EDCA_TX_FIFO_BK,\n    IWX_GEN2_EDCA_TX_FIFO_BE,\n    IWX_GEN2_EDCA_TX_FIFO_VI,\n    IWX_GEN2_EDCA_TX_FIFO_VO,\n    IWX_GEN2_TRIG_TX_FIFO_BK,\n    IWX_GEN2_TRIG_TX_FIFO_BE,\n    IWX_GEN2_TRIG_TX_FIFO_VI,\n    IWX_GEN2_TRIG_TX_FIFO_VO,\n};\n\n/**\n * TXQ config options\n * @TX_QUEUE_CFG_ENABLE_QUEUE: enable a queue\n * @TX_QUEUE_CFG_TFD_SHORT_FORMAT: use short TFD format\n */\n#define IWX_TX_QUEUE_CFG_ENABLE_QUEUE        (1 << 0)\n#define IWX_TX_QUEUE_CFG_TFD_SHORT_FORMAT    (1 << 1)\n\n#define IWX_DEFAULT_QUEUE_SIZE IWX_TFD_QUEUE_SIZE_MAX\n#define IWX_CMD_QUEUE_SIZE  32\n#define IWX_CMD_QUEUE_SIZE_GEN3 128\n#define IWX_MIN_256_BA_QUEUE_SIZE_GEN3 1024\n\n/**\n * struct iwx_tx_queue_cfg_cmd - txq hw scheduler config command\n * @sta_id: station id\n * @tid: tid of the queue\n * @flags: see &enum iwl_tx_queue_cfg_actions\n * @cb_size: size of TFD cyclic buffer. Value is exponent - 3.\n *    Minimum value 0 (8 TFDs), maximum value 5 (256 TFDs)\n * @byte_cnt_addr: address of byte count table\n * @tfdq_addr: address of TFD circular buffer\n */\nstruct iwx_tx_queue_cfg_cmd {\n    uint8_t sta_id;\n    uint8_t tid;\n    uint16_t flags;\n    uint32_t cb_size;\n    uint64_t byte_cnt_addr;\n    uint64_t tfdq_addr;\n} __packed; /* TX_QUEUE_CFG_CMD_API_S_VER_2 */\n\n/**\n * struct iwx_tx_queue_cfg_rsp - response to txq hw scheduler config\n * @queue_number: queue number assigned to this RA -TID\n * @flags: set on failure\n * @write_pointer: initial value for write pointer\n * @reserved: reserved\n */\nstruct iwx_tx_queue_cfg_rsp {\n    uint16_t queue_number;\n    uint16_t flags;\n    uint16_t write_pointer;\n    uint16_t reserved;\n} __packed; /* TX_QUEUE_CFG_RSP_API_S_VER_2 */\n\n\n/*\n * Commands\n */\n#define IWX_ALIVE        0x1\n#define IWX_REPLY_ERROR        0x2\n#define IWX_INIT_COMPLETE_NOTIF    0x4\n\n/* PHY context commands */\n#define IWX_PHY_CONTEXT_CMD    0x8\n#define IWX_DBG_CFG        0x9\n\n/* UMAC scan commands */\n#define IWX_SCAN_ITERATION_COMPLETE_UMAC    0xb5\n#define IWX_SCAN_CFG_CMD            0xc\n#define IWX_SCAN_REQ_UMAC            0xd\n#define IWX_SCAN_ABORT_UMAC            0xe\n#define IWX_SCAN_COMPLETE_UMAC            0xf\n\n/* station table */\n#define IWX_ADD_STA_KEY    0x17\n#define IWX_ADD_STA    0x18\n#define IWX_REMOVE_STA    0x19\n\n/* TX */\n#define IWX_TX_CMD        0x1c\n#define IWX_TXPATH_FLUSH    0x1e\n#define IWX_MGMT_MCAST_KEY    0x1f\n\n/* scheduler config */\n#define IWX_SCD_QUEUE_CFG    0x1d\n\n/* global key */\n#define IWX_WEP_KEY    0x20\n\n#define IWX_SHARED_MEM_CFG  0x25\n\n/* MAC and Binding commands */\n#define IWX_MAC_CONTEXT_CMD        0x28\n#define IWX_TIME_EVENT_CMD        0x29 /* both CMD and response */\n#define IWX_TIME_EVENT_NOTIFICATION    0x2a\n#define IWX_BINDING_CONTEXT_CMD        0x2b\n#define IWX_TIME_QUOTA_CMD        0x2c\n#define IWX_NON_QOS_TX_COUNTER_CMD    0x2d\n\n/* Calibration */\n#define IWX_TEMPERATURE_NOTIFICATION        0x62\n#define IWX_CALIBRATION_CFG_CMD            0x65\n#define IWX_CALIBRATION_RES_NOTIFICATION    0x66\n#define IWX_CALIBRATION_COMPLETE_NOTIFICATION    0x67\n#define IWX_RADIO_VERSION_NOTIFICATION        0x68\n\n/* Phy */\n#define IWX_PHY_CONFIGURATION_CMD        0x6a\n\n/* Power - legacy power table command */\n#define IWX_POWER_TABLE_CMD                0x77\n#define IWX_PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION    0x78\n#define IWX_LTR_CONFIG                    0xee\n\n/* NVM */\n#define IWX_NVM_ACCESS_CMD    0x88\n\n#define IWX_SET_CALIB_DEFAULT_CMD    0x8e\n\n#define IWX_BEACON_NOTIFICATION        0x90\n#define IWX_BEACON_TEMPLATE_CMD        0x91\n#define IWX_TX_ANT_CONFIGURATION_CMD    0x98\n#define IWX_BT_CONFIG            0x9b\n#define IWX_STATISTICS_CMD        0x9c\n#define IWX_STATISTICS_NOTIFICATION    0x9d\n#define IWX_REDUCE_TX_POWER_CMD        0x9f\n\n/* RF-KILL commands and notifications */\n#define IWX_CARD_STATE_CMD        0xa0\n#define IWX_CARD_STATE_NOTIFICATION    0xa1\n\n#define IWX_MISSED_BEACONS_NOTIFICATION    0xa2\n\n#define IWX_MFUART_LOAD_NOTIFICATION    0xb1\n\n/* Power - new power table command */\n#define IWX_MAC_PM_POWER_TABLE    0xa9\n\n#define IWX_REPLY_RX_PHY_CMD    0xc0\n#define IWX_REPLY_RX_MPDU_CMD    0xc1\n#define IWX_BAR_FRAME_RELEASE   0xc2\n#define IWX_BA_NOTIF        0xc5\n\n/* Location Aware Regulatory */\n#define IWX_MCC_UPDATE_CMD    0xc8\n#define IWX_MCC_CHUB_UPDATE_CMD    0xc9\n\n/* BT Coex */\n#define IWX_BT_COEX_PRIO_TABLE    0xcc\n#define IWX_BT_COEX_PROT_ENV    0xcd\n#define IWX_BT_PROFILE_NOTIFICATION    0xce\n#define IWX_BT_COEX_CI    0x5d\n\n#define IWX_REPLY_SF_CFG_CMD        0xd1\n#define IWX_REPLY_BEACON_FILTERING_CMD    0xd2\n\n/* DTS measurements */\n#define IWX_CMD_DTS_MEASUREMENT_TRIGGER        0xdc\n#define IWX_DTS_MEASUREMENT_NOTIFICATION    0xdd\n\n#define IWX_REPLY_DEBUG_CMD    0xf0\n#define IWX_DEBUG_LOG_MSG    0xf7\n\n#define IWX_MCAST_FILTER_CMD    0xd0\n\n/* D3 commands/notifications */\n#define IWX_D3_CONFIG_CMD        0xd3\n#define IWX_PROT_OFFLOAD_CONFIG_CMD    0xd4\n#define IWX_OFFLOADS_QUERY_CMD        0xd5\n#define IWX_REMOTE_WAKE_CONFIG_CMD    0xd6\n\n/* for WoWLAN in particular */\n#define IWX_WOWLAN_PATTERNS        0xe0\n#define IWX_WOWLAN_CONFIGURATION    0xe1\n#define IWX_WOWLAN_TSC_RSC_PARAM    0xe2\n#define IWX_WOWLAN_TKIP_PARAM        0xe3\n#define IWX_WOWLAN_KEK_KCK_MATERIAL    0xe4\n#define IWX_WOWLAN_GET_STATUSES        0xe5\n#define IWX_WOWLAN_TX_POWER_PER_DB    0xe6\n\n/* and for NetDetect */\n#define IWX_NET_DETECT_CONFIG_CMD        0x54\n#define IWX_NET_DETECT_PROFILES_QUERY_CMD    0x56\n#define IWX_NET_DETECT_PROFILES_CMD        0x57\n#define IWX_NET_DETECT_HOTSPOTS_CMD        0x58\n#define IWX_NET_DETECT_HOTSPOTS_QUERY_CMD    0x59\n\n/* system group command IDs */\n#define IWX_FSEQ_VER_MISMATCH_NOTIFICATION    0xff\n\n#define IWX_REPLY_MAX    0xff\n\n/* PHY_OPS subcommand IDs */\n#define IWX_CMD_DTS_MEASUREMENT_TRIGGER_WIDE    0x0\n#define IWX_CTDP_CONFIG_CMD            0x03\n#define IWX_TEMP_REPORTING_THRESHOLDS_CMD    0x04\n#define IWX_CT_KILL_NOTIFICATION        0xFE\n#define IWX_DTS_MEASUREMENT_NOTIF_WIDE        0xFF\n\n/* command groups */\n#define IWX_LEGACY_GROUP    0x0\n#define IWX_LONG_GROUP        0x1\n#define IWX_SYSTEM_GROUP    0x2\n#define IWX_MAC_CONF_GROUP    0x3\n#define IWX_PHY_OPS_GROUP    0x4\n#define IWX_DATA_PATH_GROUP    0x5\n#define IWX_PROT_OFFLOAD_GROUP    0xb\n#define IWX_REGULATORY_AND_NVM_GROUP    0xc\n\n/* SYSTEM_GROUP group subcommand IDs */\n\n#define IWX_SHARED_MEM_CFG_CMD        0x00\n#define IWX_SOC_CONFIGURATION_CMD    0x01\n#define IWX_INIT_EXTENDED_CFG_CMD    0x03\n#define IWX_FW_ERROR_RECOVERY_CMD    0x07\n\n/* DATA_PATH group subcommand IDs */\n#define IWX_DQA_ENABLE_CMD    0x00\n#define IWX_TLC_MNG_CONFIG_CMD    0x0f\n#define IWX_RX_NO_DATA_NOTIF    0xf5\n#define IWX_TLC_MNG_UPDATE_NOTIF 0xf7\n\n/* REGULATORY_AND_NVM group subcommand IDs */\n#define IWX_NVM_ACCESS_COMPLETE    0x00\n#define IWX_NVM_GET_INFO    0x02\n#define IWX_TAS_CONFIG      0x03\n#define IWX_PNVM_INIT_COMPLETE_NTFY 0xFE\n\n/*\n * struct iwx_dqa_enable_cmd\n * @cmd_queue: the TXQ number of the command queue\n */\nstruct iwx_dqa_enable_cmd {\n    uint32_t cmd_queue;\n} __packed; /* DQA_CONTROL_CMD_API_S_VER_1 */\n\nstruct iwx_sku_id {\n    uint32_t data[3];\n} __packed; /* SKU_ID_API_S_VER_1 */\n\n/**\n * struct iwx_cmd_response - generic response struct for most commands\n * @status: status of the command asked, changes for each one\n */\nstruct iwx_cmd_response {\n    uint32_t status;\n};\n\n/*\n * struct iwx_tx_ant_cfg_cmd\n * @valid: valid antenna configuration\n */\nstruct iwx_tx_ant_cfg_cmd {\n    uint32_t valid;\n} __packed;\n\n/*\n * Calibration control struct.\n * Sent as part of the phy configuration command.\n * @flow_trigger: bitmap for which calibrations to perform according to\n *        flow triggers.\n * @event_trigger: bitmap for which calibrations to perform according to\n *        event triggers.\n */\nstruct iwx_calib_ctrl {\n    uint32_t flow_trigger;\n    uint32_t event_trigger;\n} __packed;\n\n/* This defines the bitmap of various calibrations to enable in both\n * init ucode and runtime ucode through IWX_CALIBRATION_CFG_CMD.\n */\n#define IWX_CALIB_CFG_XTAL_IDX            (1 << 0)\n#define IWX_CALIB_CFG_TEMPERATURE_IDX        (1 << 1)\n#define IWX_CALIB_CFG_VOLTAGE_READ_IDX        (1 << 2)\n#define IWX_CALIB_CFG_PAPD_IDX            (1 << 3)\n#define IWX_CALIB_CFG_TX_PWR_IDX        (1 << 4)\n#define IWX_CALIB_CFG_DC_IDX            (1 << 5)\n#define IWX_CALIB_CFG_BB_FILTER_IDX        (1 << 6)\n#define IWX_CALIB_CFG_LO_LEAKAGE_IDX        (1 << 7)\n#define IWX_CALIB_CFG_TX_IQ_IDX            (1 << 8)\n#define IWX_CALIB_CFG_TX_IQ_SKEW_IDX        (1 << 9)\n#define IWX_CALIB_CFG_RX_IQ_IDX            (1 << 10)\n#define IWX_CALIB_CFG_RX_IQ_SKEW_IDX        (1 << 11)\n#define IWX_CALIB_CFG_SENSITIVITY_IDX        (1 << 12)\n#define IWX_CALIB_CFG_CHAIN_NOISE_IDX        (1 << 13)\n#define IWX_CALIB_CFG_DISCONNECTED_ANT_IDX    (1 << 14)\n#define IWX_CALIB_CFG_ANT_COUPLING_IDX        (1 << 15)\n#define IWX_CALIB_CFG_DAC_IDX            (1 << 16)\n#define IWX_CALIB_CFG_ABS_IDX            (1 << 17)\n#define IWX_CALIB_CFG_AGC_IDX            (1 << 18)\n\n/**\n * struct iwx_phy_specific_cfg - specific PHY filter configuration\n *\n * Sent as part of the phy configuration command (v3) to configure specific FW\n * defined PHY filters that can be applied to each antenna.\n *\n * @filter_cfg_chain_a: filter config id for LMAC1 chain A\n * @filter_cfg_chain_b: filter config id for LMAC1 chain B\n * @filter_cfg_chain_c: filter config id for LMAC2 chain A\n * @filter_cfg_chain_d: filter config id for LMAC2 chain B\n * values: 0 - no filter; 0xffffffff - reserved; otherwise - filter id\n */\nstruct iwx_phy_specific_cfg {\n    uint32_t filter_cfg_chain_a;\n    uint32_t filter_cfg_chain_b;\n    uint32_t filter_cfg_chain_c;\n    uint32_t filter_cfg_chain_d;\n} __packed; /* PHY_SPECIFIC_CONFIGURATION_API_VER_1*/\n\n/**\n * struct iwx_phy_cfg_cmd - Phy configuration command\n *\n * @phy_cfg: PHY configuration value, uses &enum iwx_fw_phy_cfg\n * @calib_control: calibration control data\n */\nstruct iwx_phy_cfg_cmd_v1 {\n    uint32_t    phy_cfg;\n    struct iwx_calib_ctrl calib_control;\n} __packed;\n\n/**\n * struct iwx_phy_cfg_cmd_v3 - Phy configuration command (v3)\n *\n * @phy_cfg: PHY configuration value, uses &enum iwx_fw_phy_cfg\n * @calib_control: calibration control data\n * @phy_specific_cfg: configure predefined PHY filters\n */\nstruct iwx_phy_cfg_cmd_v3 {\n    uint32_t    phy_cfg;\n    struct iwx_calib_ctrl calib_control;\n    struct iwx_phy_specific_cfg phy_specific_cfg;\n} __packed; /* PHY_CONFIGURATION_CMD_API_S_VER_3 */\n\n#define IWX_PHY_CFG_RADIO_TYPE    ((1 << 0) | (1 << 1))\n#define IWX_PHY_CFG_RADIO_STEP    ((1 << 2) | (1 << 3))\n#define IWX_PHY_CFG_RADIO_DASH    ((1 << 4) | (1 << 5))\n#define IWX_PHY_CFG_PRODUCT_NUMBER    ((1 << 6) | (1 << 7))\n#define IWX_PHY_CFG_TX_CHAIN_A    (1 << 8)\n#define IWX_PHY_CFG_TX_CHAIN_B    (1 << 9)\n#define IWX_PHY_CFG_TX_CHAIN_C    (1 << 10)\n#define IWX_PHY_CFG_RX_CHAIN_A    (1 << 12)\n#define IWX_PHY_CFG_RX_CHAIN_B    (1 << 13)\n#define IWX_PHY_CFG_RX_CHAIN_C    (1 << 14)\n\n#define IWX_MAX_DTS_TRIPS    8\n\n/**\n * struct iwx_ct_kill_notif - CT-kill entry notification\n *\n * @temperature: the current temperature in celsius\n * @reserved: reserved\n */\nstruct iwx_ct_kill_notif {\n   uint16_t temperature;\n   uint16_t reserved;\n} __packed; /* GRP_PHY_CT_KILL_NTF */\n\n/**\n * struct iwx_temp_report_ths_cmd - set temperature thresholds\n * (IWX_TEMP_REPORTING_THRESHOLDS_CMD)\n *\n * @num_temps: number of temperature thresholds passed\n * @thresholds: array with the thresholds to be configured\n */\nstruct iwx_temp_report_ths_cmd {\n   uint32_t num_temps;\n   uint16_t thresholds[IWX_MAX_DTS_TRIPS];\n} __packed; /* GRP_PHY_TEMP_REPORTING_THRESHOLDS_CMD */\n\n/*\n * channel flags in NVM\n * @IWX_NVM_CHANNEL_VALID: channel is usable for this SKU/geo\n * @IWX_NVM_CHANNEL_IBSS: usable as an IBSS channel\n * @IWX_NVM_CHANNEL_ACTIVE: active scanning allowed\n * @IWX_NVM_CHANNEL_RADAR: radar detection required\n * @IWX_NVM_CHANNEL_INDOOR_ONLY: only indoor use is allowed\n * @IWX_NVM_CHANNEL_GO_CONCURRENT: GO operation is allowed when connected to BSS\n *    on same channel on 2.4 or same UNII band on 5.2\n * @IWX_NVM_CHANNEL_DFS: dynamic freq selection candidate\n * @IWX_NVM_CHANNEL_WIDE: 20 MHz channel okay (?)\n * @IWX_NVM_CHANNEL_40MHZ: 40 MHz channel okay (?)\n * @IWX_NVM_CHANNEL_80MHZ: 80 MHz channel okay (?)\n * @IWX_NVM_CHANNEL_160MHZ: 160 MHz channel okay (?)\n * @IWX_NVM_CHANNEL_DC_HIGH: DC HIGH required/allowed (?)\n */\n#define IWX_NVM_CHANNEL_VALID    (1 << 0)\n#define IWX_NVM_CHANNEL_IBSS    (1 << 1)\n#define IWX_NVM_CHANNEL_ACTIVE    (1 << 3)\n#define IWX_NVM_CHANNEL_RADAR    (1 << 4)\n#define IWX_NVM_CHANNEL_INDOOR_ONLY    (1 << 5)\n#define IWX_NVM_CHANNEL_GO_CONCURRENT    (1 << 6)\n#define IWX_NVM_CHANNEL_DFS    (1 << 7)\n#define IWX_NVM_CHANNEL_WIDE    (1 << 8)\n#define IWX_NVM_CHANNEL_40MHZ    (1 << 9)\n#define IWX_NVM_CHANNEL_80MHZ    (1 << 10)\n#define IWX_NVM_CHANNEL_160MHZ    (1 << 11)\n#define IWX_NVM_CHANNEL_DC_HIGH    (1 << 12)\n\n/**\n * struct iwx_nvm_access_complete_cmd - NVM_ACCESS commands are completed\n * @reserved: reserved\n */\nstruct iwx_nvm_access_complete_cmd {\n    uint32_t reserved;\n} __packed; /* NVM_ACCESS_COMPLETE_CMD_API_S_VER_1 */\n\n/*\n * struct iwx_nvm_get_info - request to get NVM data\n */\nstruct iwx_nvm_get_info {\n    uint32_t reserved;\n} __packed; /* REGULATORY_NVM_GET_INFO_CMD_API_S_VER_1 */\n\n/**\n * enum iwx_nvm_info_general_flags - flags in NVM_GET_INFO resp\n * @NVM_GENERAL_FLAGS_EMPTY_OTP: 1 if OTP is empty\n */\n#define IWX_NVM_GENERAL_FLAGS_EMPTY_OTP    (1 << 0)\n\n/**\n * struct iwx_nvm_get_info_general - general NVM data\n * @flags: bit 0: 1 - empty, 0 - non-empty\n * @nvm_version: nvm version\n * @board_type: board type\n * @n_hw_addrs: number of reserved MAC addresses\n */\nstruct iwx_nvm_get_info_general {\n    uint32_t flags;\n    uint16_t nvm_version;\n    uint8_t board_type;\n    uint8_t n_hw_addrs;\n} __packed; /* REGULATORY_NVM_GET_INFO_GENERAL_S_VER_2 */\n\n/**\n * iwx_nvm_mac_sku_flags - flags in &iwl_nvm_get_info_sku\n * @NVM_MAC_SKU_FLAGS_BAND_2_4_ENABLED: true if 2.4 band enabled\n * @NVM_MAC_SKU_FLAGS_BAND_5_2_ENABLED: true if 5.2 band enabled\n * @NVM_MAC_SKU_FLAGS_802_11N_ENABLED: true if 11n enabled\n * @NVM_MAC_SKU_FLAGS_802_11AC_ENABLED: true if 11ac enabled\n * @NVM_MAC_SKU_FLAGS_802_11AX_ENABLED: true if 11ax enabled\n * @NVM_MAC_SKU_FLAGS_MIMO_DISABLED: true if MIMO disabled\n * @NVM_MAC_SKU_FLAGS_WAPI_ENABLED: true if WAPI enabled\n * @NVM_MAC_SKU_FLAGS_REG_CHECK_ENABLED: true if regulatory checker enabled\n * @NVM_MAC_SKU_FLAGS_API_LOCK_ENABLED: true if API lock enabled\n */\n#define IWX_NVM_MAC_SKU_FLAGS_BAND_2_4_ENABLED    (1 << 0)\n#define IWX_NVM_MAC_SKU_FLAGS_BAND_5_2_ENABLED    (1 << 1)\n#define IWX_NVM_MAC_SKU_FLAGS_802_11N_ENABLED    (1 << 2)\n#define IWX_NVM_MAC_SKU_FLAGS_802_11AC_ENABLED    (1 << 3)\n#define IWX_NVM_MAC_SKU_FLAGS_802_11AX_ENABLED    (1 << 4)\n#define IWX_NVM_MAC_SKU_FLAGS_MIMO_DISABLED    (1 << 5)\n#define IWX_NVM_MAC_SKU_FLAGS_WAPI_ENABLED    (1 << 8)\n#define IWX_NVM_MAC_SKU_FLAGS_REG_CHECK_ENABLED    (1 << 14)\n#define IWX_NVM_MAC_SKU_FLAGS_API_LOCK_ENABLED    (1 << 15)\n\n/**\n * struct iwx_nvm_get_info_sku - mac information\n * @mac_sku_flags: flags for SKU, see &enum iwl_nvm_mac_sku_flags\n */\nstruct iwx_nvm_get_info_sku {\n    uint32_t mac_sku_flags;\n} __packed; /* REGULATORY_NVM_GET_INFO_MAC_SKU_SECTION_S_VER_2 */\n\n/**\n * struct iwx_nvm_get_info_phy - phy information\n * @tx_chains: BIT 0 chain A, BIT 1 chain B\n * @rx_chains: BIT 0 chain A, BIT 1 chain B\n */\nstruct iwx_nvm_get_info_phy {\n    uint32_t tx_chains;\n    uint32_t rx_chains;\n} __packed; /* REGULATORY_NVM_GET_INFO_PHY_SKU_SECTION_S_VER_1 */\n\n#define IWX_NUM_CHANNELS_V1    51\n#define IWX_NUM_CHANNELS    110\n\n/**\n * struct iwx_nvm_get_info_regulatory - regulatory information\n * @lar_enabled: is LAR enabled\n * @channel_profile: regulatory data of this channel\n * @reserved: reserved\n */\nstruct iwx_nvm_get_info_regulatory_v1 {\n    uint32_t lar_enabled;\n    uint16_t channel_profile[IWX_NUM_CHANNELS_V1];\n    uint16_t reserved;\n} __packed; /* REGULATORY_NVM_GET_INFO_REGULATORY_S_VER_1 */\n\n/**\n * struct iwx_nvm_get_info_regulatory - regulatory information\n * @lar_enabled: is LAR enabled\n * @n_channels: number of valid channels in the array\n * @channel_profile: regulatory data of this channel\n */\nstruct iwx_nvm_get_info_regulatory {\n    uint32_t lar_enabled;\n    uint32_t n_channels;\n    uint32_t channel_profile[IWX_NUM_CHANNELS];\n} __packed; /* REGULATORY_NVM_GET_INFO_REGULATORY_S_VER_2 */\n\n/**\n * struct iwx_nvm_get_info_rsp_v3 - response to get NVM data\n * @general: general NVM data\n * @mac_sku: data relating to MAC sku\n * @phy_sku: data relating to PHY sku\n * @regulatory: regulatory data\n */\nstruct iwx_nvm_get_info_rsp_v3 {\n    struct iwx_nvm_get_info_general general;\n    struct iwx_nvm_get_info_sku mac_sku;\n    struct iwx_nvm_get_info_phy phy_sku;\n    struct iwx_nvm_get_info_regulatory_v1 regulatory;\n} __packed; /* REGULATORY_NVM_GET_INFO_RSP_API_S_VER_3 */\n\n/**\n * struct iwx_nvm_get_info_rsp - response to get NVM data\n * @general: general NVM data\n * @mac_sku: data relating to MAC sku\n * @phy_sku: data relating to PHY sku\n * @regulatory: regulatory data\n */\nstruct iwx_nvm_get_info_rsp {\n    struct iwx_nvm_get_info_general general;\n    struct iwx_nvm_get_info_sku mac_sku;\n    struct iwx_nvm_get_info_phy phy_sku;\n    struct iwx_nvm_get_info_regulatory regulatory;\n} __packed; /* REGULATORY_NVM_GET_INFO_RSP_API_S_VER_4 */\n\n\n#define IWX_ALIVE_STATUS_ERR 0xDEAD\n#define IWX_ALIVE_STATUS_OK 0xCAFE\n\nstruct iwx_lmac_debug_addrs {\n    uint32_t error_event_table_ptr;    /* SRAM address for error log */\n    uint32_t log_event_table_ptr;    /* SRAM address for LMAC event log */\n    uint32_t cpu_register_ptr;\n    uint32_t dbgm_config_ptr;\n    uint32_t alive_counter_ptr;\n    uint32_t scd_base_ptr;        /* SRAM address for SCD */\n    uint32_t st_fwrd_addr;        /* pointer to Store and forward */\n    uint32_t st_fwrd_size;\n} __packed; /* UCODE_DEBUG_ADDRS_API_S_VER_2 */\n\nstruct iwx_lmac_alive {\n    uint32_t ucode_major;\n    uint32_t ucode_minor;\n    uint8_t ver_subtype;\n    uint8_t ver_type;\n    uint8_t mac;\n    uint8_t opt;\n    uint32_t timestamp;\n    struct iwx_lmac_debug_addrs dbg_ptrs;\n} __packed; /* UCODE_ALIVE_NTFY_API_S_VER_3 */\n\nstruct iwx_umac_debug_addrs {\n    uint32_t error_info_addr;        /* SRAM address for UMAC error log */\n    uint32_t dbg_print_buff_addr;\n} __packed; /* UMAC_DEBUG_ADDRS_API_S_VER_1 */\n\nstruct iwx_umac_alive {\n    uint32_t umac_major;        /* UMAC version: major */\n    uint32_t umac_minor;        /* UMAC version: minor */\n    struct iwx_umac_debug_addrs dbg_ptrs;\n} __packed; /* UMAC_ALIVE_DATA_API_S_VER_2 */\n\nstruct iwx_alive_resp_v4 {\n    uint16_t status;\n    uint16_t flags;\n    struct iwx_lmac_alive lmac_data[2];\n    struct iwx_umac_alive umac_data;\n} __packed; /* ALIVE_RES_API_S_VER_4 */\n\nstruct iwx_alive_resp_v5 {\n    uint16_t status;\n    uint16_t flags;\n    struct iwx_lmac_alive lmac_data[2];\n    struct iwx_umac_alive umac_data;\n    struct iwx_sku_id sku_id;\n} __packed; /* UCODE_ALIVE_NTFY_API_S_VER_5 */ \n\n#define IWX_SOC_CONFIG_CMD_FLAGS_DISCRETE    (1 << 0)\n#define IWX_SOC_CONFIG_CMD_FLAGS_LOW_LATENCY    (1 << 1)\n\n#define IWX_SOC_FLAGS_LTR_APPLY_DELAY_MASK        0xc\n#define IWX_SOC_FLAGS_LTR_APPLY_DELAY_NONE        0\n#define IWX_SOC_FLAGS_LTR_APPLY_DELAY_200        1\n#define IWX_SOC_FLAGS_LTR_APPLY_DELAY_2500        2\n#define IWX_SOC_FLAGS_LTR_APPLY_DELAY_1820        3\n\n/**\n * struct iwx_soc_configuration_cmd - Set device stabilization latency\n *\n * @flags: soc settings flags.  In VER_1, we can only set the DISCRETE\n *    flag, because the FW treats the whole value as an integer. In\n *    VER_2, we can set the bits independently.\n * @latency: time for SOC to ensure stable power & XTAL\n */\nstruct iwx_soc_configuration_cmd {\n    uint32_t flags;\n    uint32_t latency;\n} __packed; /*\n         * SOC_CONFIGURATION_CMD_S_VER_1 (see description above)\n         * SOC_CONFIGURATION_CMD_S_VER_2\n         */\n\n/**\n * commands driver may send before finishing init flow\n * @IWX_INIT_DEBUG_CFG: driver is going to send debug config command\n * @IWX_INIT_NVM: driver is going to send NVM_ACCESS commands\n * @IWX_INIT_PHY: driver is going to send PHY_DB commands\n */\n#define IWX_INIT_DEBUG_CFG    (1 << 0)\n#define IWX_INIT_NVM        (1 << 1)\n#define IWX_INIT_PHY        (1 << 2)\n\n/**\n * struct iwx_extended_cfg_cmd - mark what commands ucode should wait for\n * before finishing init flows\n * @init_flags: IWX_INIT_* flag bits\n */\nstruct iwx_init_extended_cfg_cmd {\n    uint32_t init_flags;\n} __packed; /* INIT_EXTENDED_CFG_CMD_API_S_VER_1 */\n\n/* Error response/notification */\n#define IWX_FW_ERR_UNKNOWN_CMD        0x0\n#define IWX_FW_ERR_INVALID_CMD_PARAM    0x1\n#define IWX_FW_ERR_SERVICE        0x2\n#define IWX_FW_ERR_ARC_MEMORY        0x3\n#define IWX_FW_ERR_ARC_CODE        0x4\n#define IWX_FW_ERR_WATCH_DOG        0x5\n#define IWX_FW_ERR_WEP_GRP_KEY_INDX    0x10\n#define IWX_FW_ERR_WEP_KEY_SIZE        0x11\n#define IWX_FW_ERR_OBSOLETE_FUNC    0x12\n#define IWX_FW_ERR_UNEXPECTED        0xFE\n#define IWX_FW_ERR_FATAL        0xFF\n\n/**\n * struct iwx_error_resp - FW error indication\n * ( IWX_REPLY_ERROR = 0x2 )\n * @error_type: one of IWX_FW_ERR_*\n * @cmd_id: the command ID for which the error occured\n * @bad_cmd_seq_num: sequence number of the erroneous command\n * @error_service: which service created the error, applicable only if\n *    error_type = 2, otherwise 0\n * @timestamp: TSF in usecs.\n */\nstruct iwx_error_resp {\n    uint32_t error_type;\n    uint8_t cmd_id;\n    uint8_t reserved1;\n    uint16_t bad_cmd_seq_num;\n    uint32_t error_service;\n    uint64_t timestamp;\n} __packed;\n\nenum iwx_fw_dbg_reg_operator {\n    CSR_ASSIGN,\n    CSR_SETBIT,\n    CSR_CLEARBIT,\n\n    PRPH_ASSIGN,\n    PRPH_SETBIT,\n    PRPH_CLEARBIT,\n\n    INDIRECT_ASSIGN,\n    INDIRECT_SETBIT,\n    INDIRECT_CLEARBIT,\n\n    PRPH_BLOCKBIT,\n};\n\n/**\n * struct iwx_fw_dbg_reg_op - an operation on a register\n *\n * @op: &enum iwx_fw_dbg_reg_operator\n * @addr: offset of the register\n * @val: value\n */\nstruct iwx_fw_dbg_reg_op {\n    uint8_t op;\n    uint8_t reserved[3];\n    uint32_t addr;\n    uint32_t val;\n} __packed;\n\n/**\n * enum iwx_fw_dbg_monitor_mode - available monitor recording modes\n *\n * @SMEM_MODE: monitor stores the data in SMEM\n * @EXTERNAL_MODE: monitor stores the data in allocated DRAM\n * @MARBH_MODE: monitor stores the data in MARBH buffer\n * @MIPI_MODE: monitor outputs the data through the MIPI interface\n */\nenum iwx_fw_dbg_monitor_mode {\n    SMEM_MODE = 0,\n    EXTERNAL_MODE = 1,\n    MARBH_MODE = 2,\n    MIPI_MODE = 3,\n};\n\n/**\n * struct iwx_fw_dbg_mem_seg_tlv - configures the debug data memory segments\n *\n * @data_type: the memory segment type to record\n * @ofs: the memory segment offset\n * @len: the memory segment length, in bytes\n *\n * This parses IWX_UCODE_TLV_FW_MEM_SEG\n */\nstruct iwx_fw_dbg_mem_seg_tlv {\n    uint32_t data_type;\n    uint32_t ofs;\n    uint32_t len;\n} __packed;\n\n/**\n * struct iwx_fw_dbg_dest_tlv_v1 - configures the destination of the debug data\n *\n * @version: version of the TLV - currently 0\n * @monitor_mode: &enum iwx_fw_dbg_monitor_mode\n * @size_power: buffer size will be 2^(size_power + 11)\n * @base_reg: addr of the base addr register (PRPH)\n * @end_reg:  addr of the end addr register (PRPH)\n * @write_ptr_reg: the addr of the reg of the write pointer\n * @wrap_count: the addr of the reg of the wrap_count\n * @base_shift: shift right of the base addr reg\n * @end_shift: shift right of the end addr reg\n * @reg_ops: array of registers operations\n *\n * This parses IWX_UCODE_TLV_FW_DBG_DEST\n */\nstruct iwx_fw_dbg_dest_tlv_v1 {\n    uint8_t version;\n    uint8_t monitor_mode;\n    uint8_t size_power;\n    uint8_t reserved;\n    uint32_t base_reg;\n    uint32_t end_reg;\n    uint32_t write_ptr_reg;\n    uint32_t wrap_count;\n    uint8_t base_shift;\n    uint8_t end_shift;\n    struct iwx_fw_dbg_reg_op reg_ops[0];\n} __packed;\n\n/* Mask of the register for defining the LDBG MAC2SMEM buffer SMEM size */\n#define IWX_LDBG_M2S_BUF_SIZE_MSK    0x0fff0000\n/* Mask of the register for defining the LDBG MAC2SMEM SMEM base address */\n#define IWX_LDBG_M2S_BUF_BA_MSK        0x00000fff\n/* The smem buffer chunks are in units of 256 bits */\n#define IWX_M2S_UNIT_SIZE            0x100\n\nstruct iwx_fw_dbg_dest_tlv {\n    uint8_t version;\n    uint8_t monitor_mode;\n    uint8_t size_power;\n    uint8_t reserved;\n    uint32_t cfg_reg;\n    uint32_t write_ptr_reg;\n    uint32_t wrap_count;\n    uint8_t base_shift;\n    uint8_t size_shift;\n    struct iwx_fw_dbg_reg_op reg_ops[0];\n} __packed;\n\nstruct iwx_fw_dbg_conf_hcmd {\n    uint8_t id;\n    uint8_t reserved;\n    uint16_t len;\n    uint8_t data[0];\n} __packed;\n\n/**\n * enum iwx_fw_dbg_trigger_mode - triggers functionalities\n *\n * @IWX_FW_DBG_TRIGGER_START: when trigger occurs re-conf the dbg mechanism\n * @IWX_FW_DBG_TRIGGER_STOP: when trigger occurs pull the dbg data\n * @IWX_FW_DBG_TRIGGER_MONITOR_ONLY: when trigger occurs trigger is set to\n *    collect only monitor data\n */\nenum iwx_fw_dbg_trigger_mode {\n    IWX_FW_DBG_TRIGGER_START = (1 << 0),\n    IWX_FW_DBG_TRIGGER_STOP = (1 << 1),\n    IWX_FW_DBG_TRIGGER_MONITOR_ONLY = (1 << 2),\n};\n\n/**\n * enum iwx_fw_dbg_trigger_flags - the flags supported by wrt triggers\n * @IWX_FW_DBG_FORCE_RESTART: force a firmware restart\n */\nenum iwx_fw_dbg_trigger_flags {\n    IWX_FW_DBG_FORCE_RESTART = (1 << 0),\n};\n\n/**\n * enum iwx_fw_dbg_trigger_vif_type - define the VIF type for a trigger\n * @IWX_FW_DBG_CONF_VIF_ANY: any vif type\n * @IWX_FW_DBG_CONF_VIF_IBSS: IBSS mode\n * @IWX_FW_DBG_CONF_VIF_STATION: BSS mode\n * @IWX_FW_DBG_CONF_VIF_AP: AP mode\n * @IWX_FW_DBG_CONF_VIF_P2P_CLIENT: P2P Client mode\n * @IWX_FW_DBG_CONF_VIF_P2P_GO: P2P GO mode\n * @IWX_FW_DBG_CONF_VIF_P2P_DEVICE: P2P device\n * @IWX_FW_DBG_CONF_VIF_NAN: NAN device\n */\nenum iwx_fw_dbg_trigger_vif_type {\n    IWX_FW_DBG_CONF_VIF_ANY        = 0,\n    IWX_FW_DBG_CONF_VIF_IBSS    = 1,\n    IWX_FW_DBG_CONF_VIF_STATION    = 2,\n    IWX_FW_DBG_CONF_VIF_AP        = 3,\n    IWX_FW_DBG_CONF_VIF_P2P_CLIENT  = 8,\n    IWX_FW_DBG_CONF_VIF_P2P_GO    = 9,\n    IWX_FW_DBG_CONF_VIF_P2P_DEVICE    = 10,\n    IWX_FW_DBG_CONF_VIF_NAN        = 12,\n};\n\n/**\n * enum iwl_fw_dbg_trigger - triggers available\n *\n * @FW_DBG_TRIGGER_USER: trigger log collection by user\n *    This should not be defined as a trigger to the driver, but a value the\n *    driver should set to indicate that the trigger was initiated by the\n *    user.\n * @FW_DBG_TRIGGER_FW_ASSERT: trigger log collection when the firmware asserts\n * @FW_DBG_TRIGGER_MISSED_BEACONS: trigger log collection when beacons are\n *    missed.\n * @FW_DBG_TRIGGER_CHANNEL_SWITCH: trigger log collection upon channel switch.\n * @FW_DBG_TRIGGER_FW_NOTIF: trigger log collection when the firmware sends a\n *    command response or a notification.\n * @FW_DBG_TRIGGER_MLME: trigger log collection upon MLME event.\n * @FW_DBG_TRIGGER_STATS: trigger log collection upon statistics threshold.\n * @FW_DBG_TRIGGER_RSSI: trigger log collection when the rssi of the beacon\n *    goes below a threshold.\n * @FW_DBG_TRIGGER_TXQ_TIMERS: configures the timers for the Tx queue hang\n *    detection.\n * @FW_DBG_TRIGGER_TIME_EVENT: trigger log collection upon time events related\n *    events.\n * @FW_DBG_TRIGGER_BA: trigger log collection upon BlockAck related events.\n * @FW_DBG_TX_LATENCY: trigger log collection when the tx latency goes above a\n *    threshold.\n * @FW_DBG_TDLS: trigger log collection upon TDLS related events.\n * @FW_DBG_TRIGGER_TX_STATUS: trigger log collection upon tx status when\n *  the firmware sends a tx reply.\n * @FW_DBG_TRIGGER_USER_EXTENDED: trigger log collection upon user space\n *  request.\n * @FW_DBG_TRIGGER_ALIVE_TIMEOUT: trigger log collection if alive flow timeouts\n * @FW_DBG_TRIGGER_DRIVER: trigger log collection upon a flow failure\n *    in the driver.\n */\nenum iwx_fw_dbg_trigger {\n    IWX_FW_DBG_TRIGGER_INVALID = 0,\n    IWX_FW_DBG_TRIGGER_USER,\n    IWX_FW_DBG_TRIGGER_FW_ASSERT,\n    IWX_FW_DBG_TRIGGER_MISSED_BEACONS,\n    IWX_FW_DBG_TRIGGER_CHANNEL_SWITCH,\n    IWX_FW_DBG_TRIGGER_FW_NOTIF,\n    IWX_FW_DBG_TRIGGER_MLME,\n    IWX_FW_DBG_TRIGGER_STATS,\n    IWX_FW_DBG_TRIGGER_RSSI,\n    IWX_FW_DBG_TRIGGER_TXQ_TIMERS,\n    IWX_FW_DBG_TRIGGER_TIME_EVENT,\n    IWX_FW_DBG_TRIGGER_BA,\n    IWX_FW_DBG_TRIGGER_TX_LATENCY,\n    IWX_FW_DBG_TRIGGER_TDLS,\n    IWX_FW_DBG_TRIGGER_TX_STATUS,\n    IWX_FW_DBG_TRIGGER_USER_EXTENDED,\n    IWX_FW_DBG_TRIGGER_ALIVE_TIMEOUT,\n    IWX_FW_DBG_TRIGGER_DRIVER,\n\n    /* must be last */\n    IWX_FW_DBG_TRIGGER_MAX,\n};\n\n\n/**\n * struct iwx_fw_dbg_trigger_tlv - a TLV that describes the trigger\n * @id: &enum iwx_fw_dbg_trigger\n * @vif_type: &enum iwx_fw_dbg_trigger_vif_type\n * @stop_conf_ids: bitmap of configurations this trigger relates to.\n *    if the mode is %IWX_FW_DBG_TRIGGER_STOP, then if the bit corresponding\n *    to the currently running configuration is set, the data should be\n *    collected.\n * @stop_delay: how many milliseconds to wait before collecting the data\n *    after the STOP trigger fires.\n * @mode: &enum iwx_fw_dbg_trigger_mode - can be stop / start of both\n * @start_conf_id: if mode is %IWX_FW_DBG_TRIGGER_START, this defines what\n *    configuration should be applied when the triggers kicks in.\n * @occurrences: number of occurrences. 0 means the trigger will never fire.\n * @trig_dis_ms: the time, in milliseconds, after an occurrence of this\n *    trigger in which another occurrence should be ignored.\n * @flags: &enum iwx_fw_dbg_trigger_flags\n */\nstruct iwx_fw_dbg_trigger_tlv {\n    uint32_t id;\n    uint32_t vif_type;\n    uint32_t stop_conf_ids;\n    uint32_t stop_delay;\n    uint8_t mode;\n    uint8_t start_conf_id;\n    uint16_t occurrences;\n    uint16_t trig_dis_ms;\n    uint8_t flags;\n    uint8_t reserved[5];\n\n    uint8_t data[0];\n} __packed;\n\n#define IWX_FW_DBG_START_FROM_ALIVE    0\n#define IWX_FW_DBG_CONF_MAX        32\n#define IWX_FW_DBG_INVALID        0xff\n\n/**\n * struct iwx_fw_dbg_trigger_missed_bcon - configures trigger for missed beacons\n * @stop_consec_missed_bcon: stop recording if threshold is crossed.\n * @stop_consec_missed_bcon_since_rx: stop recording if threshold is crossed.\n * @start_consec_missed_bcon: start recording if threshold is crossed.\n * @start_consec_missed_bcon_since_rx: start recording if threshold is crossed.\n * @reserved1: reserved\n * @reserved2: reserved\n */\nstruct iwx_fw_dbg_trigger_missed_bcon {\n    uint32_t stop_consec_missed_bcon;\n    uint32_t stop_consec_missed_bcon_since_rx;\n    uint32_t reserved2[2];\n    uint32_t start_consec_missed_bcon;\n    uint32_t start_consec_missed_bcon_since_rx;\n    uint32_t reserved1[2];\n} __packed;\n\n/**\n * struct iwx_fw_dbg_trigger_cmd - configures trigger for messages from FW.\n * cmds: the list of commands to trigger the collection on\n */\nstruct iwx_fw_dbg_trigger_cmd {\n    struct cmd {\n        uint8_t cmd_id;\n        uint8_t group_id;\n    } __packed cmds[16];\n} __packed;\n\n/**\n * iwx_fw_dbg_trigger_stats - configures trigger for statistics\n * @stop_offset: the offset of the value to be monitored\n * @stop_threshold: the threshold above which to collect\n * @start_offset: the offset of the value to be monitored\n * @start_threshold: the threshold above which to start recording\n */\nstruct iwx_fw_dbg_trigger_stats {\n    uint32_t stop_offset;\n    uint32_t stop_threshold;\n    uint32_t start_offset;\n    uint32_t start_threshold;\n} __packed;\n\n/**\n * struct iwx_fw_dbg_trigger_low_rssi - trigger for low beacon RSSI\n * @rssi: RSSI value to trigger at\n */\nstruct iwx_fw_dbg_trigger_low_rssi {\n    uint32_t rssi;\n} __packed;\n\n/**\n * struct iwx_fw_dbg_trigger_mlme - configures trigger for mlme events\n * @stop_auth_denied: number of denied authentication to collect\n * @stop_auth_timeout: number of authentication timeout to collect\n * @stop_rx_deauth: number of Rx deauth before to collect\n * @stop_tx_deauth: number of Tx deauth before to collect\n * @stop_assoc_denied: number of denied association to collect\n * @stop_assoc_timeout: number of association timeout to collect\n * @stop_connection_loss: number of connection loss to collect\n * @start_auth_denied: number of denied authentication to start recording\n * @start_auth_timeout: number of authentication timeout to start recording\n * @start_rx_deauth: number of Rx deauth to start recording\n * @start_tx_deauth: number of Tx deauth to start recording\n * @start_assoc_denied: number of denied association to start recording\n * @start_assoc_timeout: number of association timeout to start recording\n * @start_connection_loss: number of connection loss to start recording\n */\nstruct iwx_fw_dbg_trigger_mlme {\n    uint8_t stop_auth_denied;\n    uint8_t stop_auth_timeout;\n    uint8_t stop_rx_deauth;\n    uint8_t stop_tx_deauth;\n\n    uint8_t stop_assoc_denied;\n    uint8_t stop_assoc_timeout;\n    uint8_t stop_connection_loss;\n    uint8_t reserved;\n\n    uint8_t start_auth_denied;\n    uint8_t start_auth_timeout;\n    uint8_t start_rx_deauth;\n    uint8_t start_tx_deauth;\n\n    uint8_t start_assoc_denied;\n    uint8_t start_assoc_timeout;\n    uint8_t start_connection_loss;\n    uint8_t reserved2;\n} __packed;\n\n/**\n * struct iwx_fw_dbg_trigger_txq_timer - configures the Tx queue's timer\n * @command_queue: timeout for the command queue in ms\n * @bss: timeout for the queues of a BSS (except for TDLS queues) in ms\n * @softap: timeout for the queues of a softAP in ms\n * @p2p_go: timeout for the queues of a P2P GO in ms\n * @p2p_client: timeout for the queues of a P2P client in ms\n * @p2p_device: timeout for the queues of a P2P device in ms\n * @ibss: timeout for the queues of an IBSS in ms\n * @tdls: timeout for the queues of a TDLS station in ms\n */\nstruct iwx_fw_dbg_trigger_txq_timer {\n    uint32_t command_queue;\n    uint32_t bss;\n    uint32_t softap;\n    uint32_t p2p_go;\n    uint32_t p2p_client;\n    uint32_t p2p_device;\n    uint32_t ibss;\n    uint32_t tdls;\n    uint32_t reserved[4];\n} __packed;\n\n/**\n * struct iwx_fw_dbg_trigger_time_event - configures a time event trigger\n * time_Events: a list of tuples <id, action_bitmap>. The driver will issue a\n *    trigger each time a time event notification that relates to time event\n *    id with one of the actions in the bitmap is received and\n *    BIT(notif->status) is set in status_bitmap.\n *\n */\nstruct iwx_fw_dbg_trigger_time_event {\n    struct {\n        uint32_t id;\n        uint32_t action_bitmap;\n        uint32_t status_bitmap;\n    } __packed time_events[16];\n} __packed;\n\n/**\n * struct iwx_fw_dbg_trigger_ba - configures BlockAck related trigger\n * rx_ba_start: tid bitmap to configure on what tid the trigger should occur\n *    when an Rx BlockAck session is started.\n * rx_ba_stop: tid bitmap to configure on what tid the trigger should occur\n *    when an Rx BlockAck session is stopped.\n * tx_ba_start: tid bitmap to configure on what tid the trigger should occur\n *    when a Tx BlockAck session is started.\n * tx_ba_stop: tid bitmap to configure on what tid the trigger should occur\n *    when a Tx BlockAck session is stopped.\n * rx_bar: tid bitmap to configure on what tid the trigger should occur\n *    when a BAR is received (for a Tx BlockAck session).\n * tx_bar: tid bitmap to configure on what tid the trigger should occur\n *    when a BAR is send (for an Rx BlocAck session).\n * frame_timeout: tid bitmap to configure on what tid the trigger should occur\n *    when a frame times out in the reodering buffer.\n */\nstruct iwx_fw_dbg_trigger_ba {\n    uint16_t rx_ba_start;\n    uint16_t rx_ba_stop;\n    uint16_t tx_ba_start;\n    uint16_t tx_ba_stop;\n    uint16_t rx_bar;\n    uint16_t tx_bar;\n    uint16_t frame_timeout;\n} __packed;\n\n/**\n * struct iwx_fw_dbg_trigger_tx_latency - configures tx latency related trigger\n * @thrshold: the wanted threshold.\n * @tid_bitmap: the tid to apply the threshold on\n * @mode: recording mode (Internal buffer or continues recording)\n * @window: the size of the window before collecting.\n * @reserved: reserved.\n */\nstruct iwx_fw_dbg_trigger_tx_latency {\n    uint32_t thrshold;\n    uint16_t tid_bitmap;\n    uint16_t mode;\n    uint32_t window;\n    uint32_t reserved[4];\n} __packed;\n\n/**\n * struct iwx_fw_dbg_trigger_tdls - configures trigger for TDLS events.\n * @action_bitmap: the TDLS action to trigger the collection upon\n * @peer_mode: trigger on specific peer or all\n * @peer: the TDLS peer to trigger the collection on\n */\nstruct iwx_fw_dbg_trigger_tdls {\n    uint8_t action_bitmap;\n    uint8_t peer_mode;\n    uint8_t peer[ETHER_ADDR_LEN];\n    uint8_t reserved[4];\n} __packed;\n\n/**\n * struct iwx_fw_dbg_trigger_tx_status - configures trigger for tx response\n *  status.\n * @statuses: the list of statuses to trigger the collection on\n */\nstruct iwx_fw_dbg_trigger_tx_status {\n    struct tx_status {\n        uint8_t status;\n        uint8_t reserved[3];\n    } __packed statuses[16];\n    uint32_t reserved[2];\n} __packed;\n\n/**\n * struct iwx_fw_dbg_conf_tlv - a TLV that describes a debug configuration.\n * @id: conf id\n * @usniffer: should the uSniffer image be used\n * @num_of_hcmds: how many HCMDs to send are present here\n * @hcmd: a variable length host command to be sent to apply the configuration.\n *    If there is more than one HCMD to send, they will appear one after the\n *    other and be sent in the order that they appear in.\n * This parses IWX_UCODE_TLV_FW_DBG_CONF. The user can add up-to\n * %IWX_FW_DBG_CONF_MAX configuration per run.\n */\nstruct iwx_fw_dbg_conf_tlv {\n    uint8_t id;\n    uint8_t usniffer;\n    uint8_t reserved;\n    uint8_t num_of_hcmds;\n    struct iwx_fw_dbg_conf_hcmd hcmd;\n} __packed;\n\n#define IWX_FW_CMD_VER_UNKNOWN 99\n\n/**\n * struct iwx_fw_cmd_version - firmware command version entry\n * @cmd: command ID\n * @group: group ID\n * @cmd_ver: command version\n * @notif_ver: notification version\n */\nstruct iwx_fw_cmd_version {\n    uint8_t cmd;\n    uint8_t group;\n    uint8_t cmd_ver;\n    uint8_t notif_ver;\n} __packed;\n\n/* Common PHY, MAC and Bindings definitions */\n\n#define IWX_MAX_MACS_IN_BINDING    (3)\n#define IWX_MAX_BINDINGS    (4)\n#define IWX_AUX_BINDING_INDEX    (3)\n#define IWX_MAX_PHYS        (4)\n\n/* Used to extract ID and color from the context dword */\n#define IWX_FW_CTXT_ID_POS    (0)\n#define IWX_FW_CTXT_ID_MSK    (0xff << IWX_FW_CTXT_ID_POS)\n#define IWX_FW_CTXT_COLOR_POS    (8)\n#define IWX_FW_CTXT_COLOR_MSK    (0xff << IWX_FW_CTXT_COLOR_POS)\n#define IWX_FW_CTXT_INVALID    (0xffffffff)\n\n#define IWX_FW_CMD_ID_AND_COLOR(_id, _color) ((_id << IWX_FW_CTXT_ID_POS) |\\\n                      (_color << IWX_FW_CTXT_COLOR_POS))\n\n/* Possible actions on PHYs, MACs and Bindings */\n#define IWX_FW_CTXT_ACTION_STUB        0\n#define IWX_FW_CTXT_ACTION_ADD        1\n#define IWX_FW_CTXT_ACTION_MODIFY    2\n#define IWX_FW_CTXT_ACTION_REMOVE    3\n#define IWX_FW_CTXT_ACTION_NUM        4\n/* COMMON_CONTEXT_ACTION_API_E_VER_1 */\n\n/* Time Events */\n\n/* Time Event types, according to MAC type */\n\n/* BSS Station Events */\n#define IWX_TE_BSS_STA_AGGRESSIVE_ASSOC    0\n#define IWX_TE_BSS_STA_ASSOC        1\n#define IWX_TE_BSS_EAP_DHCP_PROT    2\n#define IWX_TE_BSS_QUIET_PERIOD        3\n\n/* P2P Device Events */\n#define IWX_TE_P2P_DEVICE_DISCOVERABLE    4\n#define IWX_TE_P2P_DEVICE_LISTEN    5\n#define IWX_TE_P2P_DEVICE_ACTION_SCAN    6\n#define IWX_TE_P2P_DEVICE_FULL_SCAN    7\n\n/* P2P Client Events */\n#define IWX_TE_P2P_CLIENT_AGGRESSIVE_ASSOC    8\n#define IWX_TE_P2P_CLIENT_ASSOC            9\n#define IWX_TE_P2P_CLIENT_QUIET_PERIOD        10\n\n/* P2P GO Events */\n#define IWX_TE_P2P_GO_ASSOC_PROT    11\n#define IWX_TE_P2P_GO_REPETITIVE_NOA    12\n#define IWX_TE_P2P_GO_CT_WINDOW        13\n\n/* WiDi Sync Events */\n#define IWX_TE_WIDI_TX_SYNC    14\n\n/* Time event - defines for command API */\n\n/**\n * DOC: Time Events - what is it?\n *\n * Time Events are a fw feature that allows the driver to control the presence\n * of the device on the channel. Since the fw supports multiple channels\n * concurrently, the fw may choose to jump to another channel at any time.\n * In order to make sure that the fw is on a specific channel at a certain time\n * and for a certain duration, the driver needs to issue a time event.\n *\n * The simplest example is for BSS association. The driver issues a time event,\n * waits for it to start, and only then tells mac80211 that we can start the\n * association. This way, we make sure that the association will be done\n * smoothly and won't be interrupted by channel switch decided within the fw.\n */\n\n /**\n * DOC: The flow against the fw\n *\n * When the driver needs to make sure we are in a certain channel, at a certain\n * time and for a certain duration, it sends a Time Event. The flow against the\n * fw goes like this:\n *    1) Driver sends a TIME_EVENT_CMD to the fw\n *    2) Driver gets the response for that command. This response contains the\n *       Unique ID (UID) of the event.\n *    3) The fw sends notification when the event starts.\n *\n * Of course the API provides various options that allow to cover parameters\n * of the flow.\n *    What is the duration of the event?\n *    What is the start time of the event?\n *    Is there an end-time for the event?\n *    How much can the event be delayed?\n *    Can the event be split?\n *    If yes what is the maximal number of chunks?\n *    etc...\n */\n\n/*\n * @IWX_TE_V2_FRAG_NONE: fragmentation of the time event is NOT allowed.\n * @IWX_TE_V2_FRAG_SINGLE: fragmentation of the time event is allowed, but only\n *  the first fragment is scheduled.\n * @IWX_TE_V2_FRAG_DUAL: fragmentation of the time event is allowed, but only\n *  the first 2 fragments are scheduled.\n * @IWX_TE_V2_FRAG_ENDLESS: fragmentation of the time event is allowed, and any\n *  number of fragments are valid.\n *\n * Other than the constant defined above, specifying a fragmentation value 'x'\n * means that the event can be fragmented but only the first 'x' will be\n * scheduled.\n */\n#define IWX_TE_V2_FRAG_NONE        0\n#define IWX_TE_V2_FRAG_SINGLE        1\n#define IWX_TE_V2_FRAG_DUAL        2\n#define IWX_TE_V2_FRAG_MAX        0xfe\n#define IWX_TE_V2_FRAG_ENDLESS        0xff\n\n/* Repeat the time event endlessly (until removed) */\n#define IWX_TE_V2_REPEAT_ENDLESS    0xff\n/* If a Time Event has bounded repetitions, this is the maximal value */\n#define IWX_TE_V2_REPEAT_MAX    0xfe\n\n#define IWX_TE_V2_PLACEMENT_POS    12\n#define IWX_TE_V2_ABSENCE_POS    15\n\n/* Time event policy values\n * A notification (both event and fragment) includes a status indicating weather\n * the FW was able to schedule the event or not. For fragment start/end\n * notification the status is always success. There is no start/end fragment\n * notification for monolithic events.\n *\n * @IWX_TE_V2_DEFAULT_POLICY: independent, social, present, unoticable\n * @IWX_TE_V2_NOTIF_HOST_EVENT_START: request/receive notification on event start\n * @IWX_TE_V2_NOTIF_HOST_EVENT_END:request/receive notification on event end\n * @IWX_TE_V2_NOTIF_INTERNAL_EVENT_START: internal FW use\n * @IWX_TE_V2_NOTIF_INTERNAL_EVENT_END: internal FW use.\n * @IWX_TE_V2_NOTIF_HOST_FRAG_START: request/receive notification on frag start\n * @IWX_TE_V2_NOTIF_HOST_FRAG_END:request/receive notification on frag end\n * @IWX_TE_V2_NOTIF_INTERNAL_FRAG_START: internal FW use.\n * @IWX_TE_V2_NOTIF_INTERNAL_FRAG_END: internal FW use.\n * @IWX_TE_V2_DEP_OTHER: depends on another time event\n * @IWX_TE_V2_DEP_TSF: depends on a specific time\n * @IWX_TE_V2_EVENT_SOCIOPATHIC: can't co-exist with other events of tha same MAC\n * @IWX_TE_V2_ABSENCE: are we present or absent during the Time Event.\n */\n#define IWX_TE_V2_DEFAULT_POLICY        0x0\n\n/* notifications (event start/stop, fragment start/stop) */\n#define IWX_TE_V2_NOTIF_HOST_EVENT_START    (1 << 0)\n#define IWX_TE_V2_NOTIF_HOST_EVENT_END        (1 << 1)\n#define IWX_TE_V2_NOTIF_INTERNAL_EVENT_START    (1 << 2)\n#define IWX_TE_V2_NOTIF_INTERNAL_EVENT_END    (1 << 3)\n\n#define IWX_TE_V2_NOTIF_HOST_FRAG_START        (1 << 4)\n#define IWX_TE_V2_NOTIF_HOST_FRAG_END        (1 << 5)\n#define IWX_TE_V2_NOTIF_INTERNAL_FRAG_START    (1 << 6)\n#define IWX_TE_V2_NOTIF_INTERNAL_FRAG_END    (1 << 7)\n#define IWX_T2_V2_START_IMMEDIATELY        (1 << 11)\n\n#define IWX_TE_V2_NOTIF_MSK    0xff\n\n/* placement characteristics */\n#define IWX_TE_V2_DEP_OTHER        (1 << IWX_TE_V2_PLACEMENT_POS)\n#define IWX_TE_V2_DEP_TSF        (1 << (IWX_TE_V2_PLACEMENT_POS + 1))\n#define IWX_TE_V2_EVENT_SOCIOPATHIC    (1 << (IWX_TE_V2_PLACEMENT_POS + 2))\n\n/* are we present or absent during the Time Event. */\n#define IWX_TE_V2_ABSENCE        (1 << IWX_TE_V2_ABSENCE_POS)\n\n/**\n * struct iwx_time_event_cmd_api - configuring Time Events\n * with struct IWX_MAC_TIME_EVENT_DATA_API_S_VER_2 (see also\n * with version 1. determined by IWX_UCODE_TLV_FLAGS)\n * ( IWX_TIME_EVENT_CMD = 0x29 )\n * @id_and_color: ID and color of the relevant MAC\n * @action: action to perform, one of IWX_FW_CTXT_ACTION_*\n * @id: this field has two meanings, depending on the action:\n *    If the action is ADD, then it means the type of event to add.\n *    For all other actions it is the unique event ID assigned when the\n *    event was added by the FW.\n * @apply_time: When to start the Time Event (in GP2)\n * @max_delay: maximum delay to event's start (apply time), in TU\n * @depends_on: the unique ID of the event we depend on (if any)\n * @interval: interval between repetitions, in TU\n * @duration: duration of event in TU\n * @repeat: how many repetitions to do, can be IWX_TE_REPEAT_ENDLESS\n * @max_frags: maximal number of fragments the Time Event can be divided to\n * @policy: defines whether uCode shall notify the host or other uCode modules\n *    on event and/or fragment start and/or end\n *    using one of IWX_TE_INDEPENDENT, IWX_TE_DEP_OTHER, IWX_TE_DEP_TSF\n *    IWX_TE_EVENT_SOCIOPATHIC\n *    using IWX_TE_ABSENCE and using IWX_TE_NOTIF_*\n */\nstruct iwx_time_event_cmd {\n    /* COMMON_INDEX_HDR_API_S_VER_1 */\n    uint32_t id_and_color;\n    uint32_t action;\n    uint32_t id;\n    /* IWX_MAC_TIME_EVENT_DATA_API_S_VER_2 */\n    uint32_t apply_time;\n    uint32_t max_delay;\n    uint32_t depends_on;\n    uint32_t interval;\n    uint32_t duration;\n    uint8_t repeat;\n    uint8_t max_frags;\n    uint16_t policy;\n} __packed; /* IWX_MAC_TIME_EVENT_CMD_API_S_VER_2 */\n\n/**\n * struct iwx_time_event_resp - response structure to iwx_time_event_cmd\n * @status: bit 0 indicates success, all others specify errors\n * @id: the Time Event type\n * @unique_id: the unique ID assigned (in ADD) or given (others) to the TE\n * @id_and_color: ID and color of the relevant MAC\n */\nstruct iwx_time_event_resp {\n    uint32_t status;\n    uint32_t id;\n    uint32_t unique_id;\n    uint32_t id_and_color;\n} __packed; /* IWX_MAC_TIME_EVENT_RSP_API_S_VER_1 */\n\n/**\n * struct iwx_time_event_notif - notifications of time event start/stop\n * ( IWX_TIME_EVENT_NOTIFICATION = 0x2a )\n * @timestamp: action timestamp in GP2\n * @session_id: session's unique id\n * @unique_id: unique id of the Time Event itself\n * @id_and_color: ID and color of the relevant MAC\n * @action: one of IWX_TE_NOTIF_START or IWX_TE_NOTIF_END\n * @status: true if scheduled, false otherwise (not executed)\n */\nstruct iwx_time_event_notif {\n    uint32_t timestamp;\n    uint32_t session_id;\n    uint32_t unique_id;\n    uint32_t id_and_color;\n    uint32_t action;\n    uint32_t status;\n} __packed; /* IWX_MAC_TIME_EVENT_NTFY_API_S_VER_1 */\n\n#define IWX_SESSION_PROTECTION_CMD      0x5\n#define IWX_SESSION_PROTECTION_NOTIF    0xFB\n\n#define IWX_SESSION_PROTECT_CONF_ASSOC  0\n#define IWX_SESSION_PROTECT_CONF_GO_CLIENT_ASSOC    1\n#define IWX_SESSION_PROTECT_CONF_P2P_DEVICE_DISCOV  2\n#define IWX_SESSION_PROTECT_CONF_P2P_GO_NEGOTIATION 3\n#define IWX_SESSION_PROTECT_CONF_MAX_ID             4\n\n/**\n * struct iwx_session_prot_cmd - configure a session protection\n * @id_and_color: the id and color of the mac for which this session protection\n *    is sent\n * @action: can be either FW_CTXT_ACTION_ADD or FW_CTXT_ACTION_REMOVE\n * @conf_id: see &enum iwl_mvm_session_prot_conf_id\n * @duration_tu: the duration of the whole protection in TUs.\n * @repetition_count: not used\n * @interval: not used\n *\n * Note: the session protection will always be scheduled to start as\n * early as possible, but the maximum delay is configuration dependent.\n * The firmware supports only one concurrent session protection per vif.\n * Adding a new session protection will remove any currently running session.\n */\nstruct iwx_session_prot_cmd {\n    /* COMMON_INDEX_HDR_API_S_VER_1 hdr */\n    uint32_t id_and_color;\n    uint32_t action;\n    uint32_t conf_id;\n    uint32_t duration_tu;\n    uint32_t repetition_count;\n    uint32_t interval;\n} __packed; /* SESSION_PROTECTION_CMD_API_S_VER_1 */\n\n/**\n * struct iwx_session_prot_notif - session protection started / ended\n * @mac_id: the mac id for which the session protection started / ended\n * @status: 1 means success, 0 means failure\n * @start: 1 means the session protection started, 0 means it ended\n * @conf_id: see &enum iwl_mvm_session_prot_conf_id\n *\n * Note that any session protection will always get two notifications: start\n * and end even the firmware could not schedule it.\n */\nstruct iwx_session_prot_notif {\n    uint32_t mac_id;\n    uint32_t status;\n    uint32_t start;\n    uint32_t conf_id;\n} __packed; /* SESSION_PROTECTION_NOTIFICATION_API_S_VER_2 */\n\n\n/* Bindings and Time Quota */\n\n/**\n * struct iwx_binding_cmd - configuring bindings\n * ( IWX_BINDING_CONTEXT_CMD = 0x2b )\n * @id_and_color: ID and color of the relevant Binding\n * @action: action to perform, one of IWX_FW_CTXT_ACTION_*\n * @macs: array of MAC id and colors which belong to the binding\n * @phy: PHY id and color which belongs to the binding\n * @lmac_id: the lmac id the binding belongs to\n */\nstruct iwx_binding_cmd {\n    /* COMMON_INDEX_HDR_API_S_VER_1 */\n    uint32_t id_and_color;\n    uint32_t action;\n    /* IWX_BINDING_DATA_API_S_VER_1 */\n    uint32_t macs[IWX_MAX_MACS_IN_BINDING];\n    uint32_t phy;\n    uint32_t lmac_id;\n} __packed; /* IWX_BINDING_CMD_API_S_VER_2 */\n\n#define IWX_LMAC_24G_INDEX        0\n#define IWX_LMAC_5G_INDEX        1\n\n/* The maximal number of fragments in the FW's schedule session */\n#define IWX_MAX_QUOTA 128\n\n/**\n * struct iwx_time_quota_data - configuration of time quota per binding\n * @id_and_color: ID and color of the relevant Binding\n * @quota: absolute time quota in TU. The scheduler will try to divide the\n *    remainig quota (after Time Events) according to this quota.\n * @max_duration: max uninterrupted context duration in TU\n */\nstruct iwx_time_quota_data {\n    uint32_t id_and_color;\n    uint32_t quota;\n    uint32_t max_duration;\n} __packed; /* IWX_TIME_QUOTA_DATA_API_S_VER_1 */\n\n/**\n * struct iwx_time_quota_cmd - configuration of time quota between bindings\n * ( IWX_TIME_QUOTA_CMD = 0x2c )\n * @quotas: allocations per binding\n */\nstruct iwx_time_quota_cmd {\n    struct iwx_time_quota_data quotas[IWX_MAX_BINDINGS];\n} __packed; /* IWX_TIME_QUOTA_ALLOCATION_CMD_API_S_VER_1 */\n\n\n/* PHY context */\n\n/* Supported bands */\n#define IWX_PHY_BAND_5  (0)\n#define IWX_PHY_BAND_24 (1)\n\n/* Supported channel width, vary if there is VHT support */\n#define IWX_PHY_VHT_CHANNEL_MODE20    (0x0)\n#define IWX_PHY_VHT_CHANNEL_MODE40    (0x1)\n#define IWX_PHY_VHT_CHANNEL_MODE80    (0x2)\n#define IWX_PHY_VHT_CHANNEL_MODE160    (0x3)\n\n/*\n * Control channel position:\n * For legacy set bit means upper channel, otherwise lower.\n * For VHT - bit-2 marks if the control is lower/upper relative to center-freq\n *   bits-1:0 mark the distance from the center freq. for 20Mhz, offset is 0.\n *                                   center_freq\n *                                        |\n * 40Mhz                          |_______|_______|\n * 80Mhz                  |_______|_______|_______|_______|\n * 160Mhz |_______|_______|_______|_______|_______|_______|_______|_______|\n * code      011     010     001     000  |  100     101     110    111\n */\n#define IWX_PHY_VHT_CTRL_POS_1_BELOW  (0x0)\n#define IWX_PHY_VHT_CTRL_POS_2_BELOW  (0x1)\n#define IWX_PHY_VHT_CTRL_POS_3_BELOW  (0x2)\n#define IWX_PHY_VHT_CTRL_POS_4_BELOW  (0x3)\n#define IWX_PHY_VHT_CTRL_POS_1_ABOVE  (0x4)\n#define IWX_PHY_VHT_CTRL_POS_2_ABOVE  (0x5)\n#define IWX_PHY_VHT_CTRL_POS_3_ABOVE  (0x6)\n#define IWX_PHY_VHT_CTRL_POS_4_ABOVE  (0x7)\n\n/*\n * @band: IWX_PHY_BAND_*\n * @channel: channel number\n * @width: PHY_[VHT|LEGACY]_CHANNEL_*\n * @ctrl channel: PHY_[VHT|LEGACY]_CTRL_*\n */\nstruct iwx_fw_channel_info_v1 {\n    uint8_t band;\n    uint8_t channel;\n    uint8_t width;\n    uint8_t ctrl_pos;\n} __packed; /* CHANNEL_CONFIG_API_S_VER_1 */\n\n/*\n * struct iwx_fw_channel_info - channel information\n *\n * @channel: channel number\n * @band: PHY_BAND_*\n * @width: PHY_[VHT|LEGACY]_CHANNEL_*\n * @ctrl channel: PHY_[VHT|LEGACY]_CTRL_*\n * @reserved: for future use and alignment\n */\nstruct iwx_fw_channel_info {\n    uint32_t channel;\n    uint8_t band;\n    uint8_t width;\n    uint8_t ctrl_pos;\n    uint8_t reserved;\n} __packed; /*CHANNEL_CONFIG_API_S_VER_2 */\n\n#define IWX_PHY_RX_CHAIN_DRIVER_FORCE_POS    (0)\n#define IWX_PHY_RX_CHAIN_DRIVER_FORCE_MSK \\\n    (0x1 << IWX_PHY_RX_CHAIN_DRIVER_FORCE_POS)\n#define IWX_PHY_RX_CHAIN_VALID_POS        (1)\n#define IWX_PHY_RX_CHAIN_VALID_MSK \\\n    (0x7 << IWX_PHY_RX_CHAIN_VALID_POS)\n#define IWX_PHY_RX_CHAIN_FORCE_SEL_POS    (4)\n#define IWX_PHY_RX_CHAIN_FORCE_SEL_MSK \\\n    (0x7 << IWX_PHY_RX_CHAIN_FORCE_SEL_POS)\n#define IWX_PHY_RX_CHAIN_FORCE_MIMO_SEL_POS    (7)\n#define IWX_PHY_RX_CHAIN_FORCE_MIMO_SEL_MSK \\\n    (0x7 << IWX_PHY_RX_CHAIN_FORCE_MIMO_SEL_POS)\n#define IWX_PHY_RX_CHAIN_CNT_POS        (10)\n#define IWX_PHY_RX_CHAIN_CNT_MSK \\\n    (0x3 << IWX_PHY_RX_CHAIN_CNT_POS)\n#define IWX_PHY_RX_CHAIN_MIMO_CNT_POS    (12)\n#define IWX_PHY_RX_CHAIN_MIMO_CNT_MSK \\\n    (0x3 << IWX_PHY_RX_CHAIN_MIMO_CNT_POS)\n#define IWX_PHY_RX_CHAIN_MIMO_FORCE_POS    (14)\n#define IWX_PHY_RX_CHAIN_MIMO_FORCE_MSK \\\n    (0x1 << IWX_PHY_RX_CHAIN_MIMO_FORCE_POS)\n\n/* TODO: fix the value, make it depend on firmware at runtime? */\n#define IWX_NUM_PHY_CTX    3\n\n#define IWX_LMAC_24G_INDEX        0\n#define IWX_LMAC_5G_INDEX        1\n\n/* TODO: complete missing documentation */\n/**\n * struct iwx_phy_context_cmd - config of the PHY context\n * ( IWX_PHY_CONTEXT_CMD = 0x8 )\n * @id_and_color: ID and color of the relevant Binding\n * @action: action to perform, one of IWX_FW_CTXT_ACTION_*\n * @apply_time: 0 means immediate apply and context switch.\n *    other value means apply new params after X usecs\n * @tx_param_color: ???\n * @channel_info:\n * @txchain_info: ???\n * @rxchain_info: ???\n * @acquisition_data: ???\n * @dsp_cfg_flags: set to 0\n */\n/*\n * XXX Intel forgot to bump the PHY_CONTEXT command API when they increased\n * the size of fw_channel_info from v1 to v2.\n * To keep things simple we define two versions of this struct, and both\n * are labled as CMD_API_VER_1. (The Linux iwlwifi driver performs dark\n * magic with pointers to struct members instead.)\n */\n/* This version must be used if IWX_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS is set: */\nstruct iwx_phy_context_cmd_uhb {\n    /* COMMON_INDEX_HDR_API_S_VER_1 */\n    uint32_t id_and_color;\n    uint32_t action;\n    /* IWX_PHY_CONTEXT_DATA_API_S_VER_1 */\n    uint32_t apply_time;\n    uint32_t tx_param_color;\n    struct iwx_fw_channel_info ci;\n    uint32_t txchain_info;\n    uint32_t rxchain_info;\n    uint32_t acquisition_data;\n    uint32_t dsp_cfg_flags;\n} __packed; /* IWX_PHY_CONTEXT_CMD_API_VER_1 */\n/* This version must be used otherwise: */\nstruct iwx_phy_context_cmd_v1 {\n    /* COMMON_INDEX_HDR_API_S_VER_1 */\n    uint32_t id_and_color;\n    uint32_t action;\n    /* IWX_PHY_CONTEXT_DATA_API_S_VER_1 */\n    uint32_t apply_time;\n    uint32_t tx_param_color;\n    struct iwx_fw_channel_info_v1 ci;\n    uint32_t txchain_info;\n    uint32_t rxchain_info;\n    uint32_t acquisition_data;\n    uint32_t dsp_cfg_flags;\n} __packed; /* IWX_PHY_CONTEXT_CMD_API_VER_1 */\n\n/**\n * struct iwx_phy_context_cmd - config of the PHY context\n * ( PHY_CONTEXT_CMD = 0x8 )\n * @id_and_color: ID and color of the relevant Binding\n * @action: action to perform, one of FW_CTXT_ACTION_*\n * @lmac_id: the lmac id the phy context belongs to\n * @ci: channel info\n * @rxchain_info: ???\n * @dsp_cfg_flags: set to 0\n * @reserved: reserved to align to 64 bit\n */\nstruct iwx_phy_context_cmd {\n    /* COMMON_INDEX_HDR_API_S_VER_1 */\n    uint32_t id_and_color;\n    uint32_t action;\n    /* PHY_CONTEXT_DATA_API_S_VER_3 */\n    struct iwx_fw_channel_info ci;\n    uint32_t lmac_id;\n    uint32_t rxchain_info;\n    uint32_t dsp_cfg_flags;\n    uint32_t reserved;\n} __packed; /* PHY_CONTEXT_CMD_API_VER_3 */\n\n\n#define IWX_RX_INFO_PHY_CNT 8\n#define IWX_RX_INFO_ENERGY_ANT_ABC_IDX 1\n#define IWX_RX_INFO_ENERGY_ANT_A_MSK 0x000000ff\n#define IWX_RX_INFO_ENERGY_ANT_B_MSK 0x0000ff00\n#define IWX_RX_INFO_ENERGY_ANT_C_MSK 0x00ff0000\n#define IWX_RX_INFO_ENERGY_ANT_A_POS 0\n#define IWX_RX_INFO_ENERGY_ANT_B_POS 8\n#define IWX_RX_INFO_ENERGY_ANT_C_POS 16\n\n#define IWX_RX_INFO_AGC_IDX 1\n#define IWX_RX_INFO_RSSI_AB_IDX 2\n#define IWX_OFDM_AGC_A_MSK 0x0000007f\n#define IWX_OFDM_AGC_A_POS 0\n#define IWX_OFDM_AGC_B_MSK 0x00003f80\n#define IWX_OFDM_AGC_B_POS 7\n#define IWX_OFDM_AGC_CODE_MSK 0x3fe00000\n#define IWX_OFDM_AGC_CODE_POS 20\n#define IWX_OFDM_RSSI_INBAND_A_MSK 0x00ff\n#define IWX_OFDM_RSSI_A_POS 0\n#define IWX_OFDM_RSSI_ALLBAND_A_MSK 0xff00\n#define IWX_OFDM_RSSI_ALLBAND_A_POS 8\n#define IWX_OFDM_RSSI_INBAND_B_MSK 0xff0000\n#define IWX_OFDM_RSSI_B_POS 16\n#define IWX_OFDM_RSSI_ALLBAND_B_MSK 0xff000000\n#define IWX_OFDM_RSSI_ALLBAND_B_POS 24\n\n/**\n * struct iwx_rx_phy_info - phy info\n * (IWX_REPLY_RX_PHY_CMD = 0xc0)\n * @non_cfg_phy_cnt: non configurable DSP phy data byte count\n * @cfg_phy_cnt: configurable DSP phy data byte count\n * @stat_id: configurable DSP phy data set ID\n * @reserved1:\n * @system_timestamp: GP2  at on air rise\n * @timestamp: TSF at on air rise\n * @beacon_time_stamp: beacon at on-air rise\n * @phy_flags: general phy flags: band, modulation, ...\n * @channel: channel number\n * @non_cfg_phy_buf: for various implementations of non_cfg_phy\n * @rate_n_flags: IWX_RATE_MCS_*\n * @byte_count: frame's byte-count\n * @frame_time: frame's time on the air, based on byte count and frame rate\n *    calculation\n * @mac_active_msk: what MACs were active when the frame was received\n *\n * Before each Rx, the device sends this data. It contains PHY information\n * about the reception of the packet.\n */\nstruct iwx_rx_phy_info {\n    uint8_t non_cfg_phy_cnt;\n    uint8_t cfg_phy_cnt;\n    uint8_t stat_id;\n    uint8_t reserved1;\n    uint32_t system_timestamp;\n    uint64_t timestamp;\n    uint32_t beacon_time_stamp;\n    uint16_t phy_flags;\n#define IWX_PHY_INFO_FLAG_SHPREAMBLE    (1 << 2)\n    uint16_t channel;\n    uint32_t non_cfg_phy[IWX_RX_INFO_PHY_CNT];\n    uint32_t rate_n_flags;\n    uint32_t byte_count;\n    uint16_t mac_active_msk;\n    uint16_t frame_time;\n} __packed;\n\nstruct iwx_rx_mpdu_res_start {\n    uint16_t byte_count;\n    uint16_t reserved;\n} __packed;\n\n/**\n * Values to parse %iwx_rx_phy_info phy_flags\n * @IWX_RX_RES_PHY_FLAGS_BAND_24: true if the packet was received on 2.4 band\n * @IWX_RX_RES_PHY_FLAGS_MOD_CCK:\n * @IWX_RX_RES_PHY_FLAGS_SHORT_PREAMBLE: true if packet's preamble was short\n * @IWX_RX_RES_PHY_FLAGS_NARROW_BAND:\n * @IWX_RX_RES_PHY_FLAGS_ANTENNA: antenna on which the packet was received\n * @IWX_RX_RES_PHY_FLAGS_AGG: set if the packet was part of an A-MPDU\n * @IWX_RX_RES_PHY_FLAGS_OFDM_HT: The frame was an HT frame\n * @IWX_RX_RES_PHY_FLAGS_OFDM_GF: The frame used GF preamble\n * @IWX_RX_RES_PHY_FLAGS_OFDM_VHT: The frame was a VHT frame\n */\n#define IWX_RX_RES_PHY_FLAGS_BAND_24        (1 << 0)\n#define IWX_RX_RES_PHY_FLAGS_MOD_CCK        (1 << 1)\n#define IWX_RX_RES_PHY_FLAGS_SHORT_PREAMBLE    (1 << 2)\n#define IWX_RX_RES_PHY_FLAGS_NARROW_BAND    (1 << 3)\n#define IWX_RX_RES_PHY_FLAGS_ANTENNA        (0x7 << 4)\n#define IWX_RX_RES_PHY_FLAGS_ANTENNA_POS    4\n#define IWX_RX_RES_PHY_FLAGS_AGG        (1 << 7)\n#define IWX_RX_RES_PHY_FLAGS_OFDM_HT        (1 << 8)\n#define IWX_RX_RES_PHY_FLAGS_OFDM_GF        (1 << 9)\n#define IWX_RX_RES_PHY_FLAGS_OFDM_VHT        (1 << 10)\n\n/**\n * Values written by fw for each Rx packet\n * @IWX_RX_MPDU_RES_STATUS_CRC_OK: CRC is fine\n * @IWX_RX_MPDU_RES_STATUS_OVERRUN_OK: there was no RXE overflow\n * @IWX_RX_MPDU_RES_STATUS_SRC_STA_FOUND:\n * @IWX_RX_MPDU_RES_STATUS_KEY_VALID:\n * @IWX_RX_MPDU_RES_STATUS_KEY_PARAM_OK:\n * @IWX_RX_MPDU_RES_STATUS_ICV_OK: ICV is fine, if not, the packet is destroyed\n * @IWX_RX_MPDU_RES_STATUS_MIC_OK: used for CCM alg only. TKIP MIC is checked\n *    in the driver.\n * @IWX_RX_MPDU_RES_STATUS_TTAK_OK: TTAK is fine\n * @IWX_RX_MPDU_RES_STATUS_MNG_FRAME_REPLAY_ERR:  valid for alg = CCM_CMAC or\n *    alg = CCM only. Checks replay attack for 11w frames. Relevant only if\n *    %IWX_RX_MPDU_RES_STATUS_ROBUST_MNG_FRAME is set.\n * @IWX_RX_MPDU_RES_STATUS_SEC_NO_ENC: this frame is not encrypted\n * @IWX_RX_MPDU_RES_STATUS_SEC_WEP_ENC: this frame is encrypted using WEP\n * @IWX_RX_MPDU_RES_STATUS_SEC_CCM_ENC: this frame is encrypted using CCM\n * @IWX_RX_MPDU_RES_STATUS_SEC_TKIP_ENC: this frame is encrypted using TKIP\n * @IWX_RX_MPDU_RES_STATUS_SEC_CCM_CMAC_ENC: this frame is encrypted using CCM_CMAC\n * @IWX_RX_MPDU_RES_STATUS_SEC_ENC_ERR: this frame couldn't be decrypted\n * @IWX_RX_MPDU_RES_STATUS_SEC_ENC_MSK: bitmask of the encryption algorithm\n * @IWX_RX_MPDU_RES_STATUS_DEC_DONE: this frame has been successfully decrypted\n * @IWX_RX_MPDU_RES_STATUS_PROTECT_FRAME_BIT_CMP:\n * @IWX_RX_MPDU_RES_STATUS_EXT_IV_BIT_CMP:\n * @IWX_RX_MPDU_RES_STATUS_KEY_ID_CMP_BIT:\n * @IWX_RX_MPDU_RES_STATUS_ROBUST_MNG_FRAME: this frame is an 11w management frame\n * @IWX_RX_MPDU_RES_STATUS_HASH_INDEX_MSK:\n * @IWX_RX_MPDU_RES_STATUS_STA_ID_MSK:\n * @IWX_RX_MPDU_RES_STATUS_RRF_KILL:\n * @IWX_RX_MPDU_RES_STATUS_FILTERING_MSK:\n * @IWX_RX_MPDU_RES_STATUS2_FILTERING_MSK:\n */\n#define IWX_RX_MPDU_RES_STATUS_CRC_OK            (1 << 0)\n#define IWX_RX_MPDU_RES_STATUS_OVERRUN_OK        (1 << 1)\n#define IWX_RX_MPDU_RES_STATUS_SRC_STA_FOUND        (1 << 2)\n#define IWX_RX_MPDU_RES_STATUS_KEY_VALID        (1 << 3)\n#define IWX_RX_MPDU_RES_STATUS_KEY_PARAM_OK        (1 << 4)\n#define IWX_RX_MPDU_RES_STATUS_ICV_OK            (1 << 5)\n#define IWX_RX_MPDU_RES_STATUS_MIC_OK            (1 << 6)\n#define IWX_RX_MPDU_RES_STATUS_TTAK_OK            (1 << 7)\n#define IWX_RX_MPDU_RES_STATUS_MNG_FRAME_REPLAY_ERR    (1 << 7)\n#define IWX_RX_MPDU_RES_STATUS_SEC_NO_ENC        (0 << 8)\n#define IWX_RX_MPDU_RES_STATUS_SEC_WEP_ENC        (1 << 8)\n#define IWX_RX_MPDU_RES_STATUS_SEC_CCM_ENC        (2 << 8)\n#define IWX_RX_MPDU_RES_STATUS_SEC_TKIP_ENC        (3 << 8)\n#define IWX_RX_MPDU_RES_STATUS_SEC_EXT_ENC        (4 << 8)\n#define IWX_RX_MPDU_RES_STATUS_SEC_CCM_CMAC_ENC        (6 << 8)\n#define IWX_RX_MPDU_RES_STATUS_SEC_ENC_ERR        (7 << 8)\n#define IWX_RX_MPDU_RES_STATUS_SEC_ENC_MSK        (7 << 8)\n#define IWX_RX_MPDU_RES_STATUS_DEC_DONE            (1 << 11)\n#define IWX_RX_MPDU_RES_STATUS_PROTECT_FRAME_BIT_CMP    (1 << 12)\n#define IWX_RX_MPDU_RES_STATUS_EXT_IV_BIT_CMP        (1 << 13)\n#define IWX_RX_MPDU_RES_STATUS_KEY_ID_CMP_BIT        (1 << 14)\n#define IWX_RX_MPDU_RES_STATUS_ROBUST_MNG_FRAME        (1 << 15)\n#define IWX_RX_MPDU_RES_STATUS_HASH_INDEX_MSK        (0x3F0000)\n#define IWX_RX_MPDU_RES_STATUS_STA_ID_MSK        (0x1f000000)\n#define IWX_RX_MPDU_RES_STATUS_RRF_KILL            (1 << 29)\n#define IWX_RX_MPDU_RES_STATUS_FILTERING_MSK        (0xc00000)\n#define IWX_RX_MPDU_RES_STATUS2_FILTERING_MSK        (0xc0000000)\n\n#define IWX_RX_MPDU_MFLG1_ADDRTYPE_MASK        0x03\n#define IWX_RX_MPDU_MFLG1_MIC_CRC_LEN_MASK    0xf0\n#define IWX_RX_MPDU_MFLG1_MIC_CRC_LEN_SHIFT    3\n\n#define IWX_RX_MPDU_MFLG2_HDR_LEN_MASK        0x1f\n#define    IWX_RX_MPDU_MFLG2_PAD            0x20\n#define IWX_RX_MPDU_MFLG2_AMSDU            0x40\n\n#define IWX_RX_MPDU_AMSDU_SUBFRAME_IDX_MASK    0x7f\n#define IWX_RX_MPDU_AMSDU_LAST_SUBFRAME        0x80\n\n#define IWX_RX_MPDU_PHY_AMPDU            (1 << 5)\n#define IWX_RX_MPDU_PHY_AMPDU_TOGGLE        (1 << 6)\n#define IWX_RX_MPDU_PHY_SHORT_PREAMBLE        (1 << 7)\n#define IWX_RX_MPDU_PHY_NCCK_ADDTL_NTFY        (1 << 7)\n#define IWX_RX_MPDU_PHY_TSF_OVERLOAD        (1 << 8)\n\n#define IWX_RX_REORDER_DATA_INVALID_BAID    0x7f\n\n#define IWX_RX_MPDU_REORDER_NSSN_MASK        0x00000fff\n#define IWX_RX_MPDU_REORDER_SN_MASK        0x00fff000\n#define IWX_RX_MPDU_REORDER_SN_SHIFT        12\n#define IWX_RX_MPDU_REORDER_BAID_MASK        0x7f000000\n#define IWX_RX_MPDU_REORDER_BAID_SHIFT        24\n#define IWX_RX_MPDU_REORDER_BA_OLD_SN        0x80000000\n\nstruct iwx_rx_mpdu_desc_v1 {\n    union {\n        uint32_t rss_hash;\n        uint32_t phy_data2;\n    };\n    union {\n        uint32_t filter_match;\n        uint32_t phy_data3;\n    };\n    uint32_t rate_n_flags;\n    uint8_t energy_a;\n    uint8_t energy_b;\n    uint8_t channel;\n    uint8_t mac_context;\n    uint32_t gp2_on_air_rise;\n    union {\n        uint64_t tsf_on_air_rise;\n        struct {\n            uint32_t phy_data0;\n            uint32_t phy_data1;\n        };\n    };\n} __packed;\n\n/**\n * struct iwx_rx_mpdu_desc_v3 - RX MPDU descriptor\n */\nstruct iwx_rx_mpdu_desc_v3 {\n    /* DW7 - carries filter_match only when rpa_en == 1 */\n    union {\n        /**\n         * @filter_match: filter match value\n         */\n        __le32 filter_match;\n\n        /**\n         * @phy_data3: depends on info type (see @phy_data1)\n         */\n        __le32 phy_data3;\n    };\n\n    /* DW8 - carries rss_hash only when rpa_en == 1 */\n    union {\n        /**\n         * @rss_hash: RSS hash value\n         */\n        __le32 rss_hash;\n\n        /**\n         * @phy_data2: depends on info type (see @phy_data1)\n         */\n        __le32 phy_data2;\n    };\n    /* DW9 */\n    /**\n     * @partial_hash: 31:0 ip/tcp header hash\n     *    w/o some fields (such as IP SRC addr)\n     */\n    __le32 partial_hash;\n    /* DW10 */\n    /**\n     * @raw_xsum: raw xsum value\n     */\n    __be16 raw_xsum;\n    /**\n     * @reserved_xsum: reserved high bits in the raw checksum\n     */\n    __le16 reserved_xsum;\n    /* DW11 */\n    /**\n     * @rate_n_flags: RX rate/flags encoding\n     */\n    __le32 rate_n_flags;\n    /* DW12 */\n    /**\n     * @energy_a: energy chain A\n     */\n    u8 energy_a;\n    /**\n     * @energy_b: energy chain B\n     */\n    u8 energy_b;\n    /**\n     * @channel: channel number\n     */\n    u8 channel;\n    /**\n     * @mac_context: MAC context mask\n     */\n    u8 mac_context;\n    /* DW13 */\n    /**\n     * @gp2_on_air_rise: GP2 timer value on air rise (INA)\n     */\n    __le32 gp2_on_air_rise;\n    /* DW14 & DW15 */\n    union {\n        /**\n         * @tsf_on_air_rise:\n         * TSF value on air rise (INA), only valid if\n         * %IWL_RX_MPDU_PHY_TSF_OVERLOAD isn't set\n         */\n        __le64 tsf_on_air_rise;\n\n        struct {\n            /**\n             * @phy_data0: depends on info_type, see @phy_data1\n             */\n            __le32 phy_data0;\n            /**\n             * @phy_data1: valid only if\n             * %IWL_RX_MPDU_PHY_TSF_OVERLOAD is set,\n             * see &enum iwl_rx_phy_data1.\n             */\n            __le32 phy_data1;\n        };\n    };\n    /* DW16 & DW17 */\n    /**\n     * @reserved: reserved\n     */\n    __le32 reserved[2];\n} __packed; /* RX_MPDU_RES_START_API_S_VER_3 */\n\n/**\n * struct iwl_rx_mpdu_desc - RX MPDU descriptor\n */\nstruct iwx_rx_mpdu_desc {\n    /* DW2 */\n    /**\n     * @mpdu_len: MPDU length\n     */\n    __le16 mpdu_len;\n    /**\n     * @mac_flags1: &enum iwl_rx_mpdu_mac_flags1\n     */\n    u8 mac_flags1;\n    /**\n     * @mac_flags2: &enum iwl_rx_mpdu_mac_flags2\n     */\n    u8 mac_flags2;\n    /* DW3 */\n    /**\n     * @amsdu_info: &enum iwl_rx_mpdu_amsdu_info\n     */\n    u8 amsdu_info;\n    /**\n     * @phy_info: &enum iwl_rx_mpdu_phy_info\n     */\n    __le16 phy_info;\n    /**\n     * @mac_phy_idx: MAC/PHY index\n     */\n    u8 mac_phy_idx;\n    /* DW4 - carries csum data only when rpa_en == 1 */\n    /**\n     * @raw_csum: raw checksum (alledgedly unreliable)\n     */\n    __le16 raw_csum;\n\n    union {\n        /**\n         * @l3l4_flags: &enum iwl_rx_l3l4_flags\n         */\n        __le16 l3l4_flags;\n\n        /**\n         * @phy_data4: depends on info type, see phy_data1\n         */\n        __le16 phy_data4;\n    };\n    /* DW5 */\n    /**\n     * @status: &enum iwl_rx_mpdu_status\n     */\n    __le32 status;\n\n    /* DW6 */\n    /**\n     * @reorder_data: &enum iwl_rx_mpdu_reorder_data\n     */\n    __le32 reorder_data;\n\n    union {\n        struct iwx_rx_mpdu_desc_v1 v1;\n        struct iwx_rx_mpdu_desc_v3 v3;\n    };\n} __packed; /* RX_MPDU_RES_START_API_S_VER_3 */\n\n#define IWX_RX_DESC_SIZE_V1 offsetofend(struct iwx_rx_mpdu_desc, v1)\n\n#define IWX_RX_NO_DATA_CHAIN_A_POS        0\n#define IWX_RX_NO_DATA_CHAIN_A_MSK        (0xff << IWX_RX_NO_DATA_CHAIN_A_POS)\n#define IWX_RX_NO_DATA_CHAIN_B_POS        8\n#define IWX_RX_NO_DATA_CHAIN_B_MSK        (0xff << IWX_RX_NO_DATA_CHAIN_B_POS)\n#define IWX_RX_NO_DATA_CHANNEL_POS        16\n#define IWX_RX_NO_DATA_CHANNEL_MSK        (0xff << IWX_RX_NO_DATA_CHANNEL_POS)\n\n#define IWX_RX_NO_DATA_INFO_TYPE_POS    0\n#define IWX_RX_NO_DATA_INFO_TYPE_MSK    (0xff << IWX_RX_NO_DATA_INFO_TYPE_POS)\n#define IWX_RX_NO_DATA_INFO_TYPE_NONE    0\n#define IWX_RX_NO_DATA_INFO_TYPE_RX_ERR    1\n#define IWX_RX_NO_DATA_INFO_TYPE_NDP    2\n#define IWX_RX_NO_DATA_INFO_TYPE_MU_UNMATCHED    3\n#define IWX_RX_NO_DATA_INFO_TYPE_HE_TB_UNMATCHED    4\n\n#define IWX_RX_NO_DATA_INFO_ERR_POS        8\n#define IWX_RX_NO_DATA_INFO_ERR_MSK        (0xff << IWX_RX_NO_DATA_INFO_ERR_POS)\n#define IWX_RX_NO_DATA_INFO_ERR_NONE    0\n#define IWX_RX_NO_DATA_INFO_ERR_BAD_PLCP    1\n#define IWX_RX_NO_DATA_INFO_ERR_UNSUPPORTED_RATE    2\n#define IWX_RX_NO_DATA_INFO_ERR_NO_DELIM        3\n#define IWX_RX_NO_DATA_INFO_ERR_BAD_MAC_HDR    4\n\n#define IWX_RX_NO_DATA_FRAME_TIME_POS    0\n#define IWX_RX_NO_DATA_FRAME_TIME_MSK    (0xfffff << IWX_RX_NO_DATA_FRAME_TIME_POS)\n\n#define IWX_RX_NO_DATA_RX_VEC0_HE_NSTS_MSK    0x03800000\n#define IWX_RX_NO_DATA_RX_VEC0_VHT_NSTS_MSK    0x38000000\n\n/**\n * struct iwx_rx_no_data - RX no data descriptor\n * @info: 7:0 frame type, 15:8 RX error type\n * @rssi: 7:0 energy chain-A,\n *    15:8 chain-B, measured at FINA time (FINA_ENERGY), 16:23 channel\n * @on_air_rise_time: GP2 during on air rise\n * @fr_time: frame time\n * @rate: rate/mcs of frame\n * @phy_info: &enum iwl_rx_phy_data0 and &enum iwl_rx_phy_info_type\n * @rx_vec: DW-12:9 raw RX vectors from DSP according to modulation type.\n *    for VHT: OFDM_RX_VECTOR_SIGA1_OUT, OFDM_RX_VECTOR_SIGA2_OUT\n *    for HE: OFDM_RX_VECTOR_HE_SIGA1_OUT, OFDM_RX_VECTOR_HE_SIGA2_OUT\n */\nstruct iwx_rx_no_data {\n    uint32_t info;\n    uint32_t rssi;\n    uint32_t on_air_rise_time;\n    uint32_t fr_time;\n    uint32_t rate;\n    uint32_t phy_info[2];\n    uint32_t rx_vec[2];\n} __packed; /* RX_NO_DATA_NTFY_API_S_VER_1 */\n\nstruct iwx_frame_release {\n    uint8_t baid;\n    uint8_t reserved;\n    uint16_t nssn;\n};\n\n#define IWX_BAR_FRAME_RELEASE_TID_MASK      0x0000000f\n#define IWX_BAR_FRAME_RELEASE_STA_MASK      0x000001f0\n\n#define IWX_BAR_FRAME_RELEASE_NSSN_MASK     0x00000fff\n#define IWX_BAR_FRAME_RELEASE_SN_MASK       0x00fff000\n#define IWX_BAR_FRAME_RELEASE_BAID_MASK     0x3f000000\n\n/**\n * struct iwx_bar_frame_release - frame release from BAR info\n * @sta_tid: STA & TID information, see &enum iwl_bar_frame_release_sta_tid.\n * @ba_info: BA information, see &enum iwl_bar_frame_release_ba_info.\n */\nstruct iwx_bar_frame_release {\n    uint32_t sta_tid;\n    uint32_t ba_info;\n} __packed; /* RX_BAR_TO_FRAME_RELEASE_API_S_VER_1 */\n\n/**\n * struct iwx_radio_version_notif - information on the radio version\n * ( IWX_RADIO_VERSION_NOTIFICATION = 0x68 )\n * @radio_flavor:\n * @radio_step:\n * @radio_dash:\n */\nstruct iwx_radio_version_notif {\n    uint32_t radio_flavor;\n    uint32_t radio_step;\n    uint32_t radio_dash;\n} __packed; /* IWX_RADIO_VERSION_NOTOFICATION_S_VER_1 */\n\n#define IWX_CARD_ENABLED        0x00\n#define IWX_HW_CARD_DISABLED        0x01\n#define IWX_SW_CARD_DISABLED        0x02\n#define IWX_CT_KILL_CARD_DISABLED    0x04\n#define IWX_HALT_CARD_DISABLED        0x08\n#define IWX_CARD_DISABLED_MSK        0x0f\n#define IWX_CARD_IS_RX_ON        0x10\n\n/**\n * struct iwx_radio_version_notif - information on the radio version\n * (IWX_CARD_STATE_NOTIFICATION = 0xa1 )\n * @flags: %iwx_card_state_flags\n */\nstruct iwx_card_state_notif {\n    uint32_t flags;\n} __packed; /* CARD_STATE_NTFY_API_S_VER_1 */\n\n/**\n * struct iwx_missed_beacons_notif - information on missed beacons\n * ( IWX_MISSED_BEACONS_NOTIFICATION = 0xa2 )\n * @mac_id: interface ID\n * @consec_missed_beacons_since_last_rx: number of consecutive missed\n *    beacons since last RX.\n * @consec_missed_beacons: number of consecutive missed beacons\n * @num_expected_beacons:\n * @num_recvd_beacons:\n */\nstruct iwx_missed_beacons_notif {\n    uint32_t mac_id;\n    uint32_t consec_missed_beacons_since_last_rx;\n    uint32_t consec_missed_beacons;\n    uint32_t num_expected_beacons;\n    uint32_t num_recvd_beacons;\n} __packed; /* IWX_MISSED_BEACON_NTFY_API_S_VER_3 */\n\n/**\n * struct iwx_mfuart_load_notif - mfuart image version & status\n * ( IWX_MFUART_LOAD_NOTIFICATION = 0xb1 )\n * @installed_ver: installed image version\n * @external_ver: external image version\n * @status: MFUART loading status\n * @duration: MFUART loading time\n*/\nstruct iwx_mfuart_load_notif {\n    uint32_t installed_ver;\n    uint32_t external_ver;\n    uint32_t status;\n    uint32_t duration;\n} __packed; /*MFU_LOADER_NTFY_API_S_VER_1*/\n\n/**\n * struct iwx_set_calib_default_cmd - set default value for calibration.\n * ( IWX_SET_CALIB_DEFAULT_CMD = 0x8e )\n * @calib_index: the calibration to set value for\n * @length: of data\n * @data: the value to set for the calibration result\n */\nstruct iwx_set_calib_default_cmd {\n    uint16_t calib_index;\n    uint16_t length;\n    uint8_t data[0];\n} __packed; /* IWX_PHY_CALIB_OVERRIDE_VALUES_S */\n\n#define IWX_MAX_PORT_ID_NUM    2\n#define IWX_MAX_MCAST_FILTERING_ADDRESSES 256\n\n/**\n * struct iwx_mcast_filter_cmd - configure multicast filter.\n * @filter_own: Set 1 to filter out multicast packets sent by station itself\n * @port_id:    Multicast MAC addresses array specifier. This is a strange way\n *        to identify network interface adopted in host-device IF.\n *        It is used by FW as index in array of addresses. This array has\n *        IWX_MAX_PORT_ID_NUM members.\n * @count:    Number of MAC addresses in the array\n * @pass_all:    Set 1 to pass all multicast packets.\n * @bssid:    current association BSSID.\n * @addr_list:    Place holder for array of MAC addresses.\n *        IMPORTANT: add padding if necessary to ensure DWORD alignment.\n */\nstruct iwx_mcast_filter_cmd {\n    uint8_t filter_own;\n    uint8_t port_id;\n    uint8_t count;\n    uint8_t pass_all;\n    uint8_t bssid[6];\n    uint8_t reserved[2];\n    uint8_t addr_list[0];\n} __packed; /* IWX_MCAST_FILTERING_CMD_API_S_VER_1 */\n\nstruct iwx_statistics_dbg {\n    uint32_t burst_check;\n    uint32_t burst_count;\n    uint32_t wait_for_silence_timeout_cnt;\n    uint8_t reserved[12];\n} __packed; /* IWX_STATISTICS_DEBUG_API_S_VER_2 */\n\nstruct iwx_statistics_div {\n    uint32_t tx_on_a;\n    uint32_t tx_on_b;\n    uint32_t exec_time;\n    uint32_t probe_time;\n    uint32_t rssi_ant;\n    uint32_t reserved2;\n} __packed; /* IWX_STATISTICS_SLOW_DIV_API_S_VER_2 */\n\n/**\n * struct mvm_statistics_rx_non_phy\n * @bogus_cts: CTS received when not expecting CTS\n * @bogus_ack: ACK received when not expecting ACK\n * @non_channel_beacons: beacons with our bss id but not on our serving channel\n * @channel_beacons: beacons with our bss id and in our serving channel\n * @num_missed_bcon: number of missed beacons\n * @adc_rx_saturation_time: count in 0.8us units the time the ADC was in\n *    saturation\n * @ina_detection_search_time: total time (in 0.8us) searched for INA\n * @beacon_silence_rssi_a: RSSI silence after beacon frame\n * @beacon_silence_rssi_b: RSSI silence after beacon frame\n * @beacon_silence_rssi_c: RSSI silence after beacon frame\n * @interference_data_flag: flag for interference data availability. 1 when data\n *    is available.\n * @channel_load: counts RX Enable time in uSec\n * @beacon_rssi_a: beacon RSSI on anntena A\n * @beacon_rssi_b: beacon RSSI on antenna B\n * @beacon_rssi_c: beacon RSSI on antenna C\n * @beacon_energy_a: beacon energy on antenna A\n * @beacon_energy_b: beacon energy on antenna B\n * @beacon_energy_c: beacon energy on antenna C\n * @num_bt_kills: number of BT \"kills\" (frame TX aborts)\n * @mac_id: mac ID\n */\nstruct iwx_statistics_rx_non_phy {\n    __le32 bogus_cts;\n    __le32 bogus_ack;\n    __le32 non_channel_beacons;\n    __le32 channel_beacons;\n    __le32 num_missed_bcon;\n    __le32 adc_rx_saturation_time;\n    __le32 ina_detection_search_time;\n    __le32 beacon_silence_rssi_a;\n    __le32 beacon_silence_rssi_b;\n    __le32 beacon_silence_rssi_c;\n    __le32 interference_data_flag;\n    __le32 channel_load;\n    __le32 beacon_rssi_a;\n    __le32 beacon_rssi_b;\n    __le32 beacon_rssi_c;\n    __le32 beacon_energy_a;\n    __le32 beacon_energy_b;\n    __le32 beacon_energy_c;\n    __le32 num_bt_kills;\n    __le32 mac_id;\n} __packed; /* STATISTICS_RX_NON_PHY_API_S_VER_4 */\n\nstruct iwx_statistics_rx_non_phy_v3 {\n    __le32 bogus_cts;    /* CTS received when not expecting CTS */\n    __le32 bogus_ack;    /* ACK received when not expecting ACK */\n    __le32 non_bssid_frames;    /* number of frames with BSSID that\n                     * doesn't belong to the STA BSSID */\n    __le32 filtered_frames;    /* count frames that were dumped in the\n                 * filtering process */\n    __le32 non_channel_beacons;    /* beacons with our bss id but not on\n                     * our serving channel */\n    __le32 channel_beacons;    /* beacons with our bss id and in our\n                 * serving channel */\n    __le32 num_missed_bcon;    /* number of missed beacons */\n    __le32 adc_rx_saturation_time;    /* count in 0.8us units the time the\n                     * ADC was in saturation */\n    __le32 ina_detection_search_time;/* total time (in 0.8us) searched\n                      * for INA */\n    __le32 beacon_silence_rssi_a;    /* RSSI silence after beacon frame */\n    __le32 beacon_silence_rssi_b;    /* RSSI silence after beacon frame */\n    __le32 beacon_silence_rssi_c;    /* RSSI silence after beacon frame */\n    __le32 interference_data_flag;    /* flag for interference data\n                     * availability. 1 when data is\n                     * available. */\n    __le32 channel_load;        /* counts RX Enable time in uSec */\n    __le32 dsp_false_alarms;    /* DSP false alarm (both OFDM\n                     * and CCK) counter */\n    __le32 beacon_rssi_a;\n    __le32 beacon_rssi_b;\n    __le32 beacon_rssi_c;\n    __le32 beacon_energy_a;\n    __le32 beacon_energy_b;\n    __le32 beacon_energy_c;\n    __le32 num_bt_kills;\n    __le32 mac_id;\n    __le32 directed_data_mpdu;\n} __packed; /* STATISTICS_RX_NON_PHY_API_S_VER_3 */\n\nstruct iwx_statistics_rx_phy {\n    __le32 unresponded_rts;\n    __le32 rxe_frame_lmt_overrun;\n    __le32 sent_ba_rsp_cnt;\n    __le32 dsp_self_kill;\n    __le32 reserved;\n} __packed; /* STATISTICS_RX_PHY_API_S_VER_3 */\n\nstruct iwx_statistics_rx_phy_v2 {\n    uint32_t ina_cnt;\n    uint32_t fina_cnt;\n    uint32_t plcp_err;\n    uint32_t crc32_err;\n    uint32_t overrun_err;\n    uint32_t early_overrun_err;\n    uint32_t crc32_good;\n    uint32_t false_alarm_cnt;\n    uint32_t fina_sync_err_cnt;\n    uint32_t sfd_timeout;\n    uint32_t fina_timeout;\n    uint32_t unresponded_rts;\n    uint32_t rxe_frame_limit_overrun;\n    uint32_t sent_ack_cnt;\n    uint32_t sent_cts_cnt;\n    uint32_t sent_ba_rsp_cnt;\n    uint32_t dsp_self_kill;\n    uint32_t mh_format_err;\n    uint32_t re_acq_main_rssi_sum;\n    uint32_t reserved;\n} __packed; /* IWX_STATISTICS_RX_PHY_API_S_VER_2 */\n\nstruct iwx_statistics_rx_ht_phy_v1 {\n    uint32_t plcp_err;\n    uint32_t overrun_err;\n    uint32_t early_overrun_err;\n    uint32_t crc32_good;\n    uint32_t crc32_err;\n    uint32_t mh_format_err;\n    uint32_t agg_crc32_good;\n    uint32_t agg_mpdu_cnt;\n    uint32_t agg_cnt;\n    uint32_t unsupport_mcs;\n} __packed;  /* IWX_STATISTICS_HT_RX_PHY_API_S_VER_1 */\n\nstruct iwx_statistics_rx_ht_phy {\n    __le32 mh_format_err;\n    __le32 agg_mpdu_cnt;\n    __le32 agg_cnt;\n    __le32 unsupport_mcs;\n} __packed;  /* STATISTICS_HT_RX_PHY_API_S_VER_2 */\n\n/*\n * The first MAC indices (starting from 0)\n * are available to the driver, AUX follows\n */\n#define IWX_MAC_INDEX_AUX        4\n#define IWX_MAC_INDEX_MIN_DRIVER    0\n#define IWX_NUM_MAC_INDEX_DRIVER    IWX_MAC_INDEX_AUX\n#define IWX_NUM_MAC_INDEX        (IWX_NUM_MAC_INDEX_DRIVER + 1)\n#define IWX_NUM_MAC_INDEX_CDB    (IWX_NUM_MAC_INDEX_DRIVER + 2)\n\n#define IWX_STATION_COUNT    16\n\nstruct iwx_statistics_tx_non_phy_v3 {\n    __le32 preamble_cnt;\n    __le32 rx_detected_cnt;\n    __le32 bt_prio_defer_cnt;\n    __le32 bt_prio_kill_cnt;\n    __le32 few_bytes_cnt;\n    __le32 cts_timeout;\n    __le32 ack_timeout;\n    __le32 expected_ack_cnt;\n    __le32 actual_ack_cnt;\n    __le32 dump_msdu_cnt;\n    __le32 burst_abort_next_frame_mismatch_cnt;\n    __le32 burst_abort_missing_next_frame_cnt;\n    __le32 cts_timeout_collision;\n    __le32 ack_or_ba_timeout_collision;\n} __packed; /* STATISTICS_TX_NON_PHY_API_S_VER_3 */\n\nstruct iwx_statistics_tx_non_phy {\n    __le32 bt_prio_defer_cnt;\n    __le32 bt_prio_kill_cnt;\n    __le32 few_bytes_cnt;\n    __le32 cts_timeout;\n    __le32 ack_timeout;\n    __le32 dump_msdu_cnt;\n    __le32 burst_abort_next_frame_mismatch_cnt;\n    __le32 burst_abort_missing_next_frame_cnt;\n    __le32 cts_timeout_collision;\n    __le32 ack_or_ba_timeout_collision;\n} __packed; /* STATISTICS_TX_NON_PHY_API_S_VER_4 */\n\n#define IWX_MAX_CHAINS 3\n\nstruct iwx_statistics_tx_non_phy_agg {\n    uint32_t ba_timeout;\n    uint32_t ba_reschedule_frames;\n    uint32_t scd_query_agg_frame_cnt;\n    uint32_t scd_query_no_agg;\n    uint32_t scd_query_agg;\n    uint32_t scd_query_mismatch;\n    uint32_t frame_not_ready;\n    uint32_t underrun;\n    uint32_t bt_prio_kill;\n    uint32_t rx_ba_rsp_cnt;\n    int8_t txpower[IWX_MAX_CHAINS];\n    int8_t reserved;\n    uint32_t reserved2;\n} __packed; /* IWX_STATISTICS_TX_NON_PHY_AGG_API_S_VER_1 */\n\nstruct iwx_statistics_tx_channel_width {\n    uint32_t ext_cca_narrow_ch20[1];\n    uint32_t ext_cca_narrow_ch40[2];\n    uint32_t ext_cca_narrow_ch80[3];\n    uint32_t ext_cca_narrow_ch160[4];\n    uint32_t last_tx_ch_width_indx;\n    uint32_t rx_detected_per_ch_width[4];\n    uint32_t success_per_ch_width[4];\n    uint32_t fail_per_ch_width[4];\n}; /* IWX_STATISTICS_TX_CHANNEL_WIDTH_API_S_VER_1 */\n\nstruct iwx_statistics_tx_v4 {\n    struct iwx_statistics_tx_non_phy_v3 general;\n    struct iwx_statistics_tx_non_phy_agg agg;\n    struct iwx_statistics_tx_channel_width channel_width;\n} __packed; /* STATISTICS_TX_API_S_VER_4 */\n\nstruct iwx_statistics_tx {\n    struct iwx_statistics_tx_non_phy general;\n    struct iwx_statistics_tx_non_phy_agg agg;\n    struct iwx_statistics_tx_channel_width channel_width;\n} __packed; /* STATISTICS_TX_API_S_VER_5 */\n\nstruct iwx_statistics_bt_activity {\n    __le32 hi_priority_tx_req_cnt;\n    __le32 hi_priority_tx_denied_cnt;\n    __le32 lo_priority_tx_req_cnt;\n    __le32 lo_priority_tx_denied_cnt;\n    __le32 hi_priority_rx_req_cnt;\n    __le32 hi_priority_rx_denied_cnt;\n    __le32 lo_priority_rx_req_cnt;\n    __le32 lo_priority_rx_denied_cnt;\n} __packed;  /* STATISTICS_BT_ACTIVITY_API_S_VER_1 */\n\nstruct iwx_statistics_general_common_v19 {\n    __le32 radio_temperature;\n    __le32 radio_voltage;\n    struct iwx_statistics_dbg dbg;\n    __le32 sleep_time;\n    __le32 slots_out;\n    __le32 slots_idle;\n    __le32 ttl_timestamp;\n    struct iwx_statistics_div slow_div;\n    __le32 rx_enable_counter;\n    /*\n     * num_of_sos_states:\n     *  count the number of times we have to re-tune\n     *  in order to get out of bad PHY status\n     */\n    __le32 num_of_sos_states;\n    __le32 beacon_filtered;\n    __le32 missed_beacons;\n    u8 beacon_filter_average_energy;\n    u8 beacon_filter_reason;\n    u8 beacon_filter_current_energy;\n    u8 beacon_filter_reserved;\n    __le32 beacon_filter_delta_time;\n    struct iwx_statistics_bt_activity bt_activity;\n    __le64 rx_time;\n    __le64 on_time_rf;\n    __le64 on_time_scan;\n    __le64 tx_time;\n} __packed;\n\nstruct iwx_statistics_general_common {\n    __le32 radio_temperature;\n    struct iwx_statistics_dbg dbg;\n    __le32 sleep_time;\n    __le32 slots_out;\n    __le32 slots_idle;\n    __le32 ttl_timestamp;\n    struct iwx_statistics_div slow_div;\n    __le32 rx_enable_counter;\n    /*\n     * num_of_sos_states:\n     *  count the number of times we have to re-tune\n     *  in order to get out of bad PHY status\n     */\n    __le32 num_of_sos_states;\n    __le32 beacon_filtered;\n    __le32 missed_beacons;\n    u8 beacon_filter_average_energy;\n    u8 beacon_filter_reason;\n    u8 beacon_filter_current_energy;\n    u8 beacon_filter_reserved;\n    __le32 beacon_filter_delta_time;\n    struct iwx_statistics_bt_activity bt_activity;\n    __le64 rx_time;\n    __le64 on_time_rf;\n    __le64 on_time_scan;\n    __le64 tx_time;\n} __packed; /* STATISTICS_GENERAL_API_S_VER_10 */\n\nstruct iwx_statistics_general_v8 {\n    struct iwx_statistics_general_common_v19 common;\n    __le32 beacon_counter[IWX_NUM_MAC_INDEX];\n    u8 beacon_average_energy[IWX_NUM_MAC_INDEX];\n    u8 reserved[4 - (IWX_NUM_MAC_INDEX % 4)];\n} __packed; /* STATISTICS_GENERAL_API_S_VER_8 */\n\nstruct iwx_statistics_general {\n    struct iwx_statistics_general_common common;\n    uint32_t beacon_counter[IWX_MAC_INDEX_AUX];\n    uint8_t beacon_average_energy[IWX_MAC_INDEX_AUX];\n    uint8_t reserved[8 - IWX_MAC_INDEX_AUX];\n} __packed; /* STATISTICS_GENERAL_API_S_VER_10 */\n\nstruct iwx_statistics_rx {\n    struct iwx_statistics_rx_phy ofdm;\n    struct iwx_statistics_rx_phy cck;\n    struct iwx_statistics_rx_non_phy general;\n    struct iwx_statistics_rx_ht_phy ofdm_ht;\n} __packed; /* IWX_STATISTICS_RX_API_S_VER_4 */\n\nstruct iwx_statistics_rx_v3 {\n    struct iwx_statistics_rx_phy_v2 ofdm;\n    struct iwx_statistics_rx_phy_v2 cck;\n    struct iwx_statistics_rx_non_phy_v3 general;\n    struct iwx_statistics_rx_ht_phy_v1 ofdm_ht;\n} __packed; /* IWX_STATISTICS_RX_API_S_VER_3 */\n\n/*\n * IWX_STATISTICS_NOTIFICATION = 0x9d (notification only, not a command)\n *\n * By default, uCode issues this notification after receiving a beacon\n * while associated.  To disable this behavior, set DISABLE_NOTIF flag in the\n * IWX_REPLY_STATISTICS_CMD 0x9c, above.\n *\n * Statistics counters continue to increment beacon after beacon, but are\n * cleared when changing channels or when driver issues IWX_REPLY_STATISTICS_CMD\n * 0x9c with CLEAR_STATS bit set (see above).\n *\n * uCode also issues this notification during scans.  uCode clears statistics\n * appropriately so that each notification contains statistics for only the\n * one channel that has just been scanned.\n */\n\n/**\n * struct iwx_statistics_load - RX statistics for multi-queue devices\n * @air_time: accumulated air time, per mac\n * @byte_count: accumulated byte count, per mac\n * @pkt_count: accumulated packet count, per mac\n * @avg_energy: average RSSI, per station\n */\nstruct iwx_statistics_load {\n    uint32_t air_time[IWX_MAC_INDEX_AUX];\n    uint32_t byte_count[IWX_MAC_INDEX_AUX];\n    uint32_t pkt_count[IWX_MAC_INDEX_AUX];\n    uint8_t avg_energy[IWX_STATION_COUNT];\n} __packed; /* STATISTICS_RX_MAC_STATION_S_VER_4 */\n\nstruct iwx_statistics_load_v1 {\n    uint32_t air_time[IWX_MAC_INDEX_AUX];\n    uint32_t byte_count[IWX_MAC_INDEX_AUX];\n    uint32_t pkt_count[IWX_MAC_INDEX_AUX];\n    uint8_t avg_energy[IWX_STATION_COUNT];\n} __packed; /* STATISTICS_RX_MAC_STATION_S_VER_1 */\n\nstruct iwx_notif_statistics {\n    uint32_t flag;\n    struct iwx_statistics_rx rx;\n    struct iwx_statistics_tx tx;\n    struct iwx_statistics_general general;\n    struct iwx_statistics_load load_stats;\n} __packed; /* STATISTICS_NTFY_API_S_VER_13 */\n\nstruct iwx_notif_statistics_v11 {\n    __le32 flag;\n    struct iwx_statistics_rx_v3 rx;\n    struct iwx_statistics_tx_v4 tx;\n    struct iwx_statistics_general_v8 general;\n    struct iwx_statistics_load_v1 load_stats;\n} __packed; /* STATISTICS_NTFY_API_S_VER_11 */\n\n/**\n * flags used in statistics notification\n * @IWX_STATISTICS_REPLY_FLG_CLEAR: statistics were cleared after this report\n */\n#define IWX_STATISTICS_REPLY_FLG_CLEAR    0x01\n\n/**\n * flags used in statistics command\n * @IWX_STATISTICS_FLG_CLEAR: request to clear statistics after the report\n *    that's sent after this command\n * @IWX_STATISTICS_FLG_DISABLE_NOTIF: disable unilateral statistics\n *    notifications\n */\n#define IWX_STATISTICS_FLG_CLEAR        0x01\n#define IWX_STATISTICS_FLG_DISABLE_NOTIF    0x02\n\n/**\n * struct iwx_statistics_cmd - statistics config command\n * @flags: IWX_STATISTICS_* flags\n */\nstruct iwx_statistics_cmd {\n    uint32_t flags;\n} __packed; /* STATISTICS_CMD_API_S_VER_1 */\n\n\n/***********************************\n * Smart Fifo API\n ***********************************/\n/* Smart Fifo state */\n#define IWX_SF_LONG_DELAY_ON    0 /* should never be called by driver */\n#define IWX_SF_FULL_ON        1\n#define IWX_SF_UNINIT        2\n#define IWX_SF_INIT_OFF        3\n#define IWX_SF_HW_NUM_STATES    4\n\n/* Smart Fifo possible scenario */\n#define IWX_SF_SCENARIO_SINGLE_UNICAST    0\n#define IWX_SF_SCENARIO_AGG_UNICAST    1\n#define IWX_SF_SCENARIO_MULTICAST    2\n#define IWX_SF_SCENARIO_BA_RESP        3\n#define IWX_SF_SCENARIO_TX_RESP        4\n#define IWX_SF_NUM_SCENARIO        5\n\n#define IWX_SF_TRANSIENT_STATES_NUMBER 2 /* IWX_SF_LONG_DELAY_ON and IWX_SF_FULL_ON */\n#define IWX_SF_NUM_TIMEOUT_TYPES 2    /* Aging timer and Idle timer */\n\n/* smart FIFO default values */\n#define IWX_SF_W_MARK_SISO 4096\n#define IWX_SF_W_MARK_MIMO2 8192\n#define IWX_SF_W_MARK_MIMO3 6144\n#define IWX_SF_W_MARK_LEGACY 4096\n#define IWX_SF_W_MARK_SCAN 4096\n\n/* SF Scenarios timers for default configuration (aligned to 32 uSec) */\n#define IWX_SF_SINGLE_UNICAST_IDLE_TIMER_DEF 160    /* 150 uSec  */\n#define IWX_SF_SINGLE_UNICAST_AGING_TIMER_DEF 400    /* 0.4 mSec */\n#define IWX_SF_AGG_UNICAST_IDLE_TIMER_DEF 160        /* 150 uSec */\n#define IWX_SF_AGG_UNICAST_AGING_TIMER_DEF 400        /* 0.4 mSec */\n#define IWX_SF_MCAST_IDLE_TIMER_DEF 160            /* 150 mSec */\n#define IWX_SF_MCAST_AGING_TIMER_DEF 400        /* 0.4 mSec */\n#define IWX_SF_BA_IDLE_TIMER_DEF 160            /* 150 uSec */\n#define IWX_SF_BA_AGING_TIMER_DEF 400            /* 0.4 mSec */\n#define IWX_SF_TX_RE_IDLE_TIMER_DEF 160            /* 150 uSec */\n#define IWX_SF_TX_RE_AGING_TIMER_DEF 400        /* 0.4 mSec */\n\n/* SF Scenarios timers for FULL_ON state (aligned to 32 uSec) */\n#define IWX_SF_SINGLE_UNICAST_IDLE_TIMER 320    /* 300 uSec  */\n#define IWX_SF_SINGLE_UNICAST_AGING_TIMER 2016    /* 2 mSec */\n#define IWX_SF_AGG_UNICAST_IDLE_TIMER 320    /* 300 uSec */\n#define IWX_SF_AGG_UNICAST_AGING_TIMER 2016    /* 2 mSec */\n#define IWX_SF_MCAST_IDLE_TIMER 2016        /* 2 mSec */\n#define IWX_SF_MCAST_AGING_TIMER 10016        /* 10 mSec */\n#define IWX_SF_BA_IDLE_TIMER 320        /* 300 uSec */\n#define IWX_SF_BA_AGING_TIMER 2016        /* 2 mSec */\n#define IWX_SF_TX_RE_IDLE_TIMER 320        /* 300 uSec */\n#define IWX_SF_TX_RE_AGING_TIMER 2016        /* 2 mSec */\n\n#define IWX_SF_LONG_DELAY_AGING_TIMER 1000000    /* 1 Sec */\n\n#define IWX_SF_CFG_DUMMY_NOTIF_OFF    (1 << 16)\n\n/**\n * Smart Fifo configuration command.\n * @state: smart fifo state, types listed in enum %iwx_sf_state.\n * @watermark: Minimum allowed availabe free space in RXF for transient state.\n * @long_delay_timeouts: aging and idle timer values for each scenario\n * in long delay state.\n * @full_on_timeouts: timer values for each scenario in full on state.\n */\nstruct iwx_sf_cfg_cmd {\n    uint32_t state;\n    uint32_t watermark[IWX_SF_TRANSIENT_STATES_NUMBER];\n    uint32_t long_delay_timeouts[IWX_SF_NUM_SCENARIO][IWX_SF_NUM_TIMEOUT_TYPES];\n    uint32_t full_on_timeouts[IWX_SF_NUM_SCENARIO][IWX_SF_NUM_TIMEOUT_TYPES];\n} __packed; /* IWX_SF_CFG_API_S_VER_2 */\n\n#define IWX_AC_BK    0\n#define IWX_AC_BE    1\n#define IWX_AC_VI    2\n#define IWX_AC_VO    3\n#define IWX_AC_NUM    4\n\n/**\n * MAC context flags\n * @IWX_MAC_PROT_FLG_TGG_PROTECT: 11g protection when transmitting OFDM frames,\n *    this will require CCK RTS/CTS2self.\n *    RTS/CTS will protect full burst time.\n * @IWX_MAC_PROT_FLG_HT_PROT: enable HT protection\n * @IWX_MAC_PROT_FLG_FAT_PROT: protect 40 MHz transmissions\n * @IWX_MAC_PROT_FLG_SELF_CTS_EN: allow CTS2self\n */\n#define IWX_MAC_PROT_FLG_TGG_PROTECT    (1 << 3)\n#define IWX_MAC_PROT_FLG_HT_PROT    (1 << 23)\n#define IWX_MAC_PROT_FLG_FAT_PROT    (1 << 24)\n#define IWX_MAC_PROT_FLG_SELF_CTS_EN    (1 << 30)\n\n#define IWX_MAC_FLG_SHORT_SLOT        (1 << 4)\n#define IWX_MAC_FLG_SHORT_PREAMBLE    (1 << 5)\n\n/**\n * Supported MAC types\n * @IWX_FW_MAC_TYPE_FIRST: lowest supported MAC type\n * @IWX_FW_MAC_TYPE_AUX: Auxiliary MAC (internal)\n * @IWX_FW_MAC_TYPE_LISTENER: monitor MAC type (?)\n * @IWX_FW_MAC_TYPE_PIBSS: Pseudo-IBSS\n * @IWX_FW_MAC_TYPE_IBSS: IBSS\n * @IWX_FW_MAC_TYPE_BSS_STA: BSS (managed) station\n * @IWX_FW_MAC_TYPE_P2P_DEVICE: P2P Device\n * @IWX_FW_MAC_TYPE_P2P_STA: P2P client\n * @IWX_FW_MAC_TYPE_GO: P2P GO\n * @IWX_FW_MAC_TYPE_TEST: ?\n * @IWX_FW_MAC_TYPE_MAX: highest support MAC type\n */\n#define IWX_FW_MAC_TYPE_FIRST        1\n#define IWX_FW_MAC_TYPE_AUX        IWX_FW_MAC_TYPE_FIRST\n#define IWX_FW_MAC_TYPE_LISTENER    2\n#define IWX_FW_MAC_TYPE_PIBSS        3\n#define IWX_FW_MAC_TYPE_IBSS        4\n#define IWX_FW_MAC_TYPE_BSS_STA        5\n#define IWX_FW_MAC_TYPE_P2P_DEVICE    6\n#define IWX_FW_MAC_TYPE_P2P_STA        7\n#define IWX_FW_MAC_TYPE_GO        8\n#define IWX_FW_MAC_TYPE_TEST        9\n#define IWX_FW_MAC_TYPE_MAX        IWX_FW_MAC_TYPE_TEST\n/* IWX_MAC_CONTEXT_TYPE_API_E_VER_1 */\n\n/**\n * TSF hw timer ID\n * @IWX_TSF_ID_A: use TSF A\n * @IWX_TSF_ID_B: use TSF B\n * @IWX_TSF_ID_C: use TSF C\n * @IWX_TSF_ID_D: use TSF D\n * @IWX_NUM_TSF_IDS: number of TSF timers available\n */\n#define IWX_TSF_ID_A    0\n#define IWX_TSF_ID_B    1\n#define IWX_TSF_ID_C    2\n#define IWX_TSF_ID_D    3\n#define IWX_NUM_TSF_IDS    4\n/* IWX_TSF_ID_API_E_VER_1 */\n\n/**\n * struct iwx_mac_data_ap - configuration data for AP MAC context\n * @beacon_time: beacon transmit time in system time\n * @beacon_tsf: beacon transmit time in TSF\n * @bi: beacon interval in TU\n * @bi_reciprocal: 2^32 / bi\n * @dtim_interval: dtim transmit time in TU\n * @dtim_reciprocal: 2^32 / dtim_interval\n * @mcast_qid: queue ID for multicast traffic\n *    NOTE: obsolete from VER2 and on\n * @beacon_template: beacon template ID\n */\nstruct iwx_mac_data_ap {\n    uint32_t beacon_time;\n    uint64_t beacon_tsf;\n    uint32_t bi;\n    uint32_t bi_reciprocal;\n    uint32_t dtim_interval;\n    uint32_t dtim_reciprocal;\n    uint32_t mcast_qid;\n    uint32_t beacon_template;\n} __packed; /* AP_MAC_DATA_API_S_VER_2 */\n\n/**\n * struct iwx_mac_data_ibss - configuration data for IBSS MAC context\n * @beacon_time: beacon transmit time in system time\n * @beacon_tsf: beacon transmit time in TSF\n * @bi: beacon interval in TU\n * @bi_reciprocal: 2^32 / bi\n * @beacon_template: beacon template ID\n */\nstruct iwx_mac_data_ibss {\n    uint32_t beacon_time;\n    uint64_t beacon_tsf;\n    uint32_t bi;\n    uint32_t bi_reciprocal;\n    uint32_t beacon_template;\n} __packed; /* IBSS_MAC_DATA_API_S_VER_1 */\n\n/**\n * struct iwx_mac_data_sta - configuration data for station MAC context\n * @is_assoc: 1 for associated state, 0 otherwise\n * @dtim_time: DTIM arrival time in system time\n * @dtim_tsf: DTIM arrival time in TSF\n * @bi: beacon interval in TU, applicable only when associated\n * @bi_reciprocal: 2^32 / bi , applicable only when associated\n * @dtim_interval: DTIM interval in TU, applicable only when associated\n * @dtim_reciprocal: 2^32 / dtim_interval , applicable only when associated\n * @listen_interval: in beacon intervals, applicable only when associated\n * @assoc_id: unique ID assigned by the AP during association\n */\nstruct iwx_mac_data_sta {\n    uint32_t is_assoc;\n    uint32_t dtim_time;\n    uint64_t dtim_tsf;\n    uint32_t bi;\n    uint32_t bi_reciprocal;\n    uint32_t dtim_interval;\n    uint32_t dtim_reciprocal;\n    uint32_t listen_interval;\n    uint32_t assoc_id;\n    uint32_t assoc_beacon_arrive_time;\n} __packed; /* IWX_STA_MAC_DATA_API_S_VER_1 */\n\n/**\n * struct iwx_mac_data_go - configuration data for P2P GO MAC context\n * @ap: iwx_mac_data_ap struct with most config data\n * @ctwin: client traffic window in TU (period after TBTT when GO is present).\n *    0 indicates that there is no CT window.\n * @opp_ps_enabled: indicate that opportunistic PS allowed\n */\nstruct iwx_mac_data_go {\n    struct iwx_mac_data_ap ap;\n    uint32_t ctwin;\n    uint32_t opp_ps_enabled;\n} __packed; /* GO_MAC_DATA_API_S_VER_1 */\n\n/**\n * struct iwx_mac_data_p2p_sta - configuration data for P2P client MAC context\n * @sta: iwx_mac_data_sta struct with most config data\n * @ctwin: client traffic window in TU (period after TBTT when GO is present).\n *    0 indicates that there is no CT window.\n */\nstruct iwx_mac_data_p2p_sta {\n    struct iwx_mac_data_sta sta;\n    uint32_t ctwin;\n} __packed; /* P2P_STA_MAC_DATA_API_S_VER_1 */\n\n/**\n * struct iwx_mac_data_pibss - Pseudo IBSS config data\n * @stats_interval: interval in TU between statistics notifications to host.\n */\nstruct iwx_mac_data_pibss {\n    uint32_t stats_interval;\n} __packed; /* PIBSS_MAC_DATA_API_S_VER_1 */\n\n/*\n * struct iwx_mac_data_p2p_dev - configuration data for the P2P Device MAC\n * context.\n * @is_disc_extended: if set to true, P2P Device discoverability is enabled on\n *    other channels as well. This should be to true only in case that the\n *    device is discoverable and there is an active GO. Note that setting this\n *    field when not needed, will increase the number of interrupts and have\n *    effect on the platform power, as this setting opens the Rx filters on\n *    all macs.\n */\nstruct iwx_mac_data_p2p_dev {\n    uint32_t is_disc_extended;\n} __packed; /* _P2P_DEV_MAC_DATA_API_S_VER_1 */\n\n/**\n * MAC context filter flags\n * @IWX_MAC_FILTER_IN_PROMISC: accept all data frames\n * @IWX_MAC_FILTER_IN_CONTROL_AND_MGMT: pass all mangement and\n *    control frames to the host\n * @IWX_MAC_FILTER_ACCEPT_GRP: accept multicast frames\n * @IWX_MAC_FILTER_DIS_DECRYPT: don't decrypt unicast frames\n * @IWX_MAC_FILTER_DIS_GRP_DECRYPT: don't decrypt multicast frames\n * @IWX_MAC_FILTER_IN_BEACON: transfer foreign BSS's beacons to host\n *    (in station mode when associated)\n * @IWX_MAC_FILTER_OUT_BCAST: filter out all broadcast frames\n * @IWX_MAC_FILTER_IN_CRC32: extract FCS and append it to frames\n * @IWX_MAC_FILTER_IN_PROBE_REQUEST: pass probe requests to host\n */\n#define IWX_MAC_FILTER_IN_PROMISC        (1 << 0)\n#define IWX_MAC_FILTER_IN_CONTROL_AND_MGMT    (1 << 1)\n#define IWX_MAC_FILTER_ACCEPT_GRP        (1 << 2)\n#define IWX_MAC_FILTER_DIS_DECRYPT        (1 << 3)\n#define IWX_MAC_FILTER_DIS_GRP_DECRYPT        (1 << 4)\n#define IWX_MAC_FILTER_IN_BEACON        (1 << 6)\n#define IWX_MAC_FILTER_OUT_BCAST        (1 << 8)\n#define IWX_MAC_FILTER_IN_CRC32            (1 << 11)\n#define IWX_MAC_FILTER_IN_PROBE_REQUEST        (1 << 12)\n\n#define IWX_MAC_FILTER_IN_11AX          (1 << 14)\n\n/**\n * QoS flags\n * @IWX_MAC_QOS_FLG_UPDATE_EDCA: ?\n * @IWX_MAC_QOS_FLG_TGN: HT is enabled\n * @IWX_MAC_QOS_FLG_TXOP_TYPE: ?\n *\n */\n#define IWX_MAC_QOS_FLG_UPDATE_EDCA    (1 << 0)\n#define IWX_MAC_QOS_FLG_TGN        (1 << 1)\n#define IWX_MAC_QOS_FLG_TXOP_TYPE    (1 << 4)\n\n/**\n * struct iwx_ac_qos - QOS timing params for IWX_MAC_CONTEXT_CMD\n * @cw_min: Contention window, start value in numbers of slots.\n *    Should be a power-of-2, minus 1.  Device's default is 0x0f.\n * @cw_max: Contention window, max value in numbers of slots.\n *    Should be a power-of-2, minus 1.  Device's default is 0x3f.\n * @aifsn:  Number of slots in Arbitration Interframe Space (before\n *    performing random backoff timing prior to Tx).  Device default 1.\n * @fifos_mask: FIFOs used by this MAC for this AC\n * @edca_txop:  Length of Tx opportunity, in uSecs.  Device default is 0.\n *\n * One instance of this config struct for each of 4 EDCA access categories\n * in struct iwx_qosparam_cmd.\n *\n * Device will automatically increase contention window by (2*CW) + 1 for each\n * transmission retry.  Device uses cw_max as a bit mask, ANDed with new CW\n * value, to cap the CW value.\n */\nstruct iwx_ac_qos {\n    uint16_t cw_min;\n    uint16_t cw_max;\n    uint8_t aifsn;\n    uint8_t fifos_mask;\n    uint16_t edca_txop;\n} __packed; /* IWX_AC_QOS_API_S_VER_2 */\n\n/**\n * struct iwx_mac_ctx_cmd - command structure to configure MAC contexts\n * ( IWX_MAC_CONTEXT_CMD = 0x28 )\n * @id_and_color: ID and color of the MAC\n * @action: action to perform, one of IWX_FW_CTXT_ACTION_*\n * @mac_type: one of IWX_FW_MAC_TYPE_*\n * @tsf_id: TSF HW timer, one of IWX_TSF_ID_*\n * @node_addr: MAC address\n * @bssid_addr: BSSID\n * @cck_rates: basic rates available for CCK\n * @ofdm_rates: basic rates available for OFDM\n * @protection_flags: combination of IWX_MAC_PROT_FLG_FLAG_*\n * @cck_short_preamble: 0x20 for enabling short preamble, 0 otherwise\n * @short_slot: 0x10 for enabling short slots, 0 otherwise\n * @filter_flags: combination of IWX_MAC_FILTER_*\n * @qos_flags: from IWX_MAC_QOS_FLG_*\n * @ac: one iwx_mac_qos configuration for each AC\n * @mac_specific: one of struct iwx_mac_data_*, according to mac_type\n */\nstruct iwx_mac_ctx_cmd {\n    /* COMMON_INDEX_HDR_API_S_VER_1 */\n    uint32_t id_and_color;\n    uint32_t action;\n    /* IWX_MAC_CONTEXT_COMMON_DATA_API_S_VER_1 */\n    uint32_t mac_type;\n    uint32_t tsf_id;\n    uint8_t node_addr[6];\n    uint16_t reserved_for_node_addr;\n    uint8_t bssid_addr[6];\n    uint16_t reserved_for_bssid_addr;\n    uint32_t cck_rates;\n    uint32_t ofdm_rates;\n    uint32_t protection_flags;\n    uint32_t cck_short_preamble;\n    uint32_t short_slot;\n    uint32_t filter_flags;\n    /* IWX_MAC_QOS_PARAM_API_S_VER_1 */\n    uint32_t qos_flags;\n    struct iwx_ac_qos ac[IWX_AC_NUM+1];\n    /* IWX_MAC_CONTEXT_COMMON_DATA_API_S */\n    union {\n        struct iwx_mac_data_ap ap;\n        struct iwx_mac_data_go go;\n        struct iwx_mac_data_sta sta;\n        struct iwx_mac_data_p2p_sta p2p_sta;\n        struct iwx_mac_data_p2p_dev p2p_dev;\n        struct iwx_mac_data_pibss pibss;\n        struct iwx_mac_data_ibss ibss;\n    };\n} __packed; /* IWX_MAC_CONTEXT_CMD_API_S_VER_1 */\n\nstatic inline uint32_t iwx_reciprocal(uint32_t v)\n{\n    if (!v)\n        return 0;\n    return 0xFFFFFFFF / v;\n}\n\n/* Power Management Commands, Responses, Notifications */\n\n/**\n * masks for LTR config command flags\n * @IWX_LTR_CFG_FLAG_FEATURE_ENABLE: Feature operational status\n * @IWX_LTR_CFG_FLAG_HW_DIS_ON_SHADOW_REG_ACCESS: allow LTR change on shadow\n *      memory access\n * @IWX_LTR_CFG_FLAG_HW_EN_SHRT_WR_THROUGH: allow LTR msg send on ANY LTR\n *      reg change\n * @IWX_LTR_CFG_FLAG_HW_DIS_ON_D0_2_D3: allow LTR msg send on transition from\n *      D0 to D3\n * @IWX_LTR_CFG_FLAG_SW_SET_SHORT: fixed static short LTR register\n * @IWX_LTR_CFG_FLAG_SW_SET_LONG: fixed static short LONG register\n * @IWX_LTR_CFG_FLAG_DENIE_C10_ON_PD: allow going into C10 on PD\n */\n#define IWX_LTR_CFG_FLAG_FEATURE_ENABLE            0x00000001\n#define IWX_LTR_CFG_FLAG_HW_DIS_ON_SHADOW_REG_ACCESS    0x00000002\n#define IWX_LTR_CFG_FLAG_HW_EN_SHRT_WR_THROUGH        0x00000004\n#define IWX_LTR_CFG_FLAG_HW_DIS_ON_D0_2_D3        0x00000008\n#define IWX_LTR_CFG_FLAG_SW_SET_SHORT            0x00000010\n#define IWX_LTR_CFG_FLAG_SW_SET_LONG            0x00000020\n#define IWX_LTR_CFG_FLAG_DENIE_C10_ON_PD        0x00000040\n\n#define IWX_LTR_VALID_STATES_NUM 4\n\n/**\n * struct iwx_ltr_config_cmd - configures the LTR\n * @flags: See %enum iwx_ltr_config_flags\n * @static_long:\n * @static_short:\n * @ltr_cfg_values:\n * @ltr_short_idle_timeout:\n */\nstruct iwx_ltr_config_cmd {\n    uint32_t flags;\n    uint32_t static_long;\n    uint32_t static_short;\n    uint32_t ltr_cfg_values[IWX_LTR_VALID_STATES_NUM];\n    uint32_t ltr_short_idle_timeout;\n} __packed; /* LTR_CAPABLE_API_S_VER_2 */\n\n/* Radio LP RX Energy Threshold measured in dBm */\n#define IWX_POWER_LPRX_RSSI_THRESHOLD    75\n#define IWX_POWER_LPRX_RSSI_THRESHOLD_MAX    94\n#define IWX_POWER_LPRX_RSSI_THRESHOLD_MIN    30\n\n/**\n * Masks for iwx_mac_power_cmd command flags\n * @IWX_POWER_FLAGS_POWER_SAVE_ENA_MSK: '1' Allow to save power by turning off\n *        receiver and transmitter. '0' - does not allow.\n * @IWX_POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK: '0' Driver disables power management,\n *        '1' Driver enables PM (use rest of parameters)\n * @IWX_POWER_FLAGS_SKIP_OVER_DTIM_MSK: '0' PM have to walk up every DTIM,\n *        '1' PM could sleep over DTIM till listen Interval.\n * @IWX_POWER_FLAGS_SNOOZE_ENA_MSK: Enable snoozing only if uAPSD is enabled and all\n *        access categories are both delivery and trigger enabled.\n * @IWX_POWER_FLAGS_BT_SCO_ENA: Enable BT SCO coex only if uAPSD and\n *        PBW Snoozing enabled\n * @IWX_POWER_FLAGS_ADVANCE_PM_ENA_MSK: Advanced PM (uAPSD) enable mask\n * @IWX_POWER_FLAGS_LPRX_ENA_MSK: Low Power RX enable.\n * @IWX_POWER_FLAGS_AP_UAPSD_MISBEHAVING_ENA_MSK: AP/GO's uAPSD misbehaving\n *        detection enablement\n*/\n#define IWX_POWER_FLAGS_POWER_SAVE_ENA_MSK        (1 << 0)\n#define IWX_POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK    (1 << 1)\n#define IWX_POWER_FLAGS_SKIP_OVER_DTIM_MSK        (1 << 2)\n#define IWX_POWER_FLAGS_SNOOZE_ENA_MSK            (1 << 5)\n#define IWX_POWER_FLAGS_BT_SCO_ENA            (1 << 8)\n#define IWX_POWER_FLAGS_ADVANCE_PM_ENA_MSK        (1 << 9)\n#define IWX_POWER_FLAGS_LPRX_ENA_MSK            (1 << 11)\n#define IWX_POWER_FLAGS_UAPSD_MISBEHAVING_ENA_MSK    (1 << 12)\n\n#define IWX_POWER_VEC_SIZE 5\n\n/**\n * Masks for device power command flags\n * @IWX_DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK:\n *   '1' Allow to save power by turning off receiver and transmitter.\n *   '0' Do not allow. This flag should be always set to '1' unless\n *       one needs to disable actual power down for debug purposes.\n * @IWX_DEVICE_POWER_FLAGS_CAM_MSK:\n *   '1' CAM (Continuous Active Mode) is set, power management is disabled.\n *   '0' Power management is enabled, one of the power schemes is applied.\n */\n#define IWX_DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK    (1 << 0)\n#define IWX_DEVICE_POWER_FLAGS_CAM_MSK            (1 << 13)\n\n/**\n * struct iwx_device_power_cmd - device wide power command.\n * IWX_POWER_TABLE_CMD = 0x77 (command, has simple generic response)\n *\n * @flags:    Power table command flags from IWX_DEVICE_POWER_FLAGS_*\n */\nstruct iwx_device_power_cmd {\n    /* PM_POWER_TABLE_CMD_API_S_VER_6 */\n    uint16_t flags;\n    uint16_t reserved;\n} __packed;\n\n/**\n * struct iwx_mac_power_cmd - New power command containing uAPSD support\n * IWX_MAC_PM_POWER_TABLE = 0xA9 (command, has simple generic response)\n * @id_and_color:    MAC contex identifier\n * @flags:        Power table command flags from POWER_FLAGS_*\n * @keep_alive_seconds:    Keep alive period in seconds. Default - 25 sec.\n *            Minimum allowed:- 3 * DTIM. Keep alive period must be\n *            set regardless of power scheme or current power state.\n *            FW use this value also when PM is disabled.\n * @rx_data_timeout:    Minimum time (usec) from last Rx packet for AM to\n *            PSM transition - legacy PM\n * @tx_data_timeout:    Minimum time (usec) from last Tx packet for AM to\n *            PSM transition - legacy PM\n * @sleep_interval:    not in use\n * @skip_dtim_periods:    Number of DTIM periods to skip if Skip over DTIM flag\n *            is set. For example, if it is required to skip over\n *            one DTIM, this value need to be set to 2 (DTIM periods).\n * @rx_data_timeout_uapsd: Minimum time (usec) from last Rx packet for AM to\n *            PSM transition - uAPSD\n * @tx_data_timeout_uapsd: Minimum time (usec) from last Tx packet for AM to\n *            PSM transition - uAPSD\n * @lprx_rssi_threshold: Signal strength up to which LP RX can be enabled.\n *            Default: 80dbm\n * @num_skip_dtim:    Number of DTIMs to skip if Skip over DTIM flag is set\n * @snooze_interval:    Maximum time between attempts to retrieve buffered data\n *            from the AP [msec]\n * @snooze_window:    A window of time in which PBW snoozing insures that all\n *            packets received. It is also the minimum time from last\n *            received unicast RX packet, before client stops snoozing\n *            for data. [msec]\n * @snooze_step:    TBD\n * @qndp_tid:        TID client shall use for uAPSD QNDP triggers\n * @uapsd_ac_flags:    Set trigger-enabled and delivery-enabled indication for\n *            each corresponding AC.\n *            Use IEEE80211_WMM_IE_STA_QOSINFO_AC* for correct values.\n * @uapsd_max_sp:    Use IEEE80211_WMM_IE_STA_QOSINFO_SP_* for correct\n *            values.\n * @heavy_tx_thld_packets:    TX threshold measured in number of packets\n * @heavy_rx_thld_packets:    RX threshold measured in number of packets\n * @heavy_tx_thld_percentage:    TX threshold measured in load's percentage\n * @heavy_rx_thld_percentage:    RX threshold measured in load's percentage\n * @limited_ps_threshold:\n*/\nstruct iwx_mac_power_cmd {\n    /* CONTEXT_DESC_API_T_VER_1 */\n    uint32_t id_and_color;\n\n    /* CLIENT_PM_POWER_TABLE_S_VER_1 */\n    uint16_t flags;\n    uint16_t keep_alive_seconds;\n    uint32_t rx_data_timeout;\n    uint32_t tx_data_timeout;\n    uint32_t rx_data_timeout_uapsd;\n    uint32_t tx_data_timeout_uapsd;\n    uint8_t lprx_rssi_threshold;\n    uint8_t skip_dtim_periods;\n    uint16_t snooze_interval;\n    uint16_t snooze_window;\n    uint8_t snooze_step;\n    uint8_t qndp_tid;\n    uint8_t uapsd_ac_flags;\n    uint8_t uapsd_max_sp;\n    uint8_t heavy_tx_thld_packets;\n    uint8_t heavy_rx_thld_packets;\n    uint8_t heavy_tx_thld_percentage;\n    uint8_t heavy_rx_thld_percentage;\n    uint8_t limited_ps_threshold;\n    uint8_t reserved;\n} __packed;\n\n#define IWX_DEFAULT_PS_TX_DATA_TIMEOUT      (100 * 1000)\n#define IWX_DEFAULT_PS_RX_DATA_TIMEOUT      (100 * 1000)\n\n/*\n * struct iwx_uapsd_misbehaving_ap_notif - FW sends this notification when\n * associated AP is identified as improperly implementing uAPSD protocol.\n * IWX_PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION = 0x78\n * @sta_id: index of station in uCode's station table - associated AP ID in\n *        this context.\n */\nstruct iwx_uapsd_misbehaving_ap_notif {\n    uint32_t sta_id;\n    uint8_t mac_id;\n    uint8_t reserved[3];\n} __packed;\n\n/**\n * struct iwx_beacon_filter_cmd\n * IWX_REPLY_BEACON_FILTERING_CMD = 0xd2 (command)\n * @id_and_color: MAC contex identifier\n * @bf_energy_delta: Used for RSSI filtering, if in 'normal' state. Send beacon\n *      to driver if delta in Energy values calculated for this and last\n *      passed beacon is greater than this threshold. Zero value means that\n *      the Energy change is ignored for beacon filtering, and beacon will\n *      not be forced to be sent to driver regardless of this delta. Typical\n *      energy delta 5dB.\n * @bf_roaming_energy_delta: Used for RSSI filtering, if in 'roaming' state.\n *      Send beacon to driver if delta in Energy values calculated for this\n *      and last passed beacon is greater than this threshold. Zero value\n *      means that the Energy change is ignored for beacon filtering while in\n *      Roaming state, typical energy delta 1dB.\n * @bf_roaming_state: Used for RSSI filtering. If absolute Energy values\n *      calculated for current beacon is less than the threshold, use\n *      Roaming Energy Delta Threshold, otherwise use normal Energy Delta\n *      Threshold. Typical energy threshold is -72dBm.\n * @bf_temp_threshold: This threshold determines the type of temperature\n *    filtering (Slow or Fast) that is selected (Units are in Celsuis):\n *      If the current temperature is above this threshold - Fast filter\n *    will be used, If the current temperature is below this threshold -\n *    Slow filter will be used.\n * @bf_temp_fast_filter: Send Beacon to driver if delta in temperature values\n *      calculated for this and the last passed beacon is greater than this\n *      threshold. Zero value means that the temperature change is ignored for\n *      beacon filtering; beacons will not be  forced to be sent to driver\n *      regardless of whether its temerature has been changed.\n * @bf_temp_slow_filter: Send Beacon to driver if delta in temperature values\n *      calculated for this and the last passed beacon is greater than this\n *      threshold. Zero value means that the temperature change is ignored for\n *      beacon filtering; beacons will not be forced to be sent to driver\n *      regardless of whether its temerature has been changed.\n * @bf_enable_beacon_filter: 1, beacon filtering is enabled; 0, disabled.\n * @bf_escape_timer: Send beacons to driver if no beacons were passed\n *      for a specific period of time. Units: Beacons.\n * @ba_escape_timer: Fully receive and parse beacon if no beacons were passed\n *      for a longer period of time then this escape-timeout. Units: Beacons.\n * @ba_enable_beacon_abort: 1, beacon abort is enabled; 0, disabled.\n * @bf_threshold_absolute_low: See below.\n * @bf_threshold_absolute_high: Send Beacon to driver if Energy value calculated\n *      for this beacon crossed this absolute threshold. For the 'Increase'\n *      direction the bf_energy_absolute_low[i] is used. For the 'Decrease'\n *      direction the bf_energy_absolute_high[i] is used. Zero value means\n *      that this specific threshold is ignored for beacon filtering, and\n *      beacon will not be forced to be sent to driver due to this setting.\n */\nstruct iwx_beacon_filter_cmd {\n    uint32_t bf_energy_delta;\n    uint32_t bf_roaming_energy_delta;\n    uint32_t bf_roaming_state;\n    uint32_t bf_temp_threshold;\n    uint32_t bf_temp_fast_filter;\n    uint32_t bf_temp_slow_filter;\n    uint32_t bf_enable_beacon_filter;\n    uint32_t bf_debug_flag;\n    uint32_t bf_escape_timer;\n    uint32_t ba_escape_timer;\n    uint32_t ba_enable_beacon_abort;\n    uint32_t bf_threshold_absolute_low[2];\n    uint32_t bf_threshold_absolute_high[2];\n} __packed; /* BEACON_FILTER_CONFIG_API_S_VER_4 */\n\n/* Beacon filtering and beacon abort */\n#define IWX_BF_ENERGY_DELTA_DEFAULT 5\n#define IWX_BF_ENERGY_DELTA_MAX 255\n#define IWX_BF_ENERGY_DELTA_MIN 0\n\n#define IWX_BF_ROAMING_ENERGY_DELTA_DEFAULT 1\n#define IWX_BF_ROAMING_ENERGY_DELTA_MAX 255\n#define IWX_BF_ROAMING_ENERGY_DELTA_MIN 0\n\n#define IWX_BF_ROAMING_STATE_DEFAULT 72\n#define IWX_BF_ROAMING_STATE_MAX 255\n#define IWX_BF_ROAMING_STATE_MIN 0\n\n#define IWX_BF_TEMP_THRESHOLD_DEFAULT 112\n#define IWX_BF_TEMP_THRESHOLD_MAX 255\n#define IWX_BF_TEMP_THRESHOLD_MIN 0\n\n#define IWX_BF_TEMP_FAST_FILTER_DEFAULT 1\n#define IWX_BF_TEMP_FAST_FILTER_MAX 255\n#define IWX_BF_TEMP_FAST_FILTER_MIN 0\n\n#define IWX_BF_TEMP_SLOW_FILTER_DEFAULT 5\n#define IWX_BF_TEMP_SLOW_FILTER_MAX 255\n#define IWX_BF_TEMP_SLOW_FILTER_MIN 0\n\n#define IWX_BF_ENABLE_BEACON_FILTER_DEFAULT 1\n\n#define IWX_BF_DEBUG_FLAG_DEFAULT 0\n\n#define IWX_BF_ESCAPE_TIMER_DEFAULT 50\n#define IWX_BF_ESCAPE_TIMER_MAX 1024\n#define IWX_BF_ESCAPE_TIMER_MIN 0\n\n#define IWX_BA_ESCAPE_TIMER_DEFAULT 6\n#define IWX_BA_ESCAPE_TIMER_D3 9\n#define IWX_BA_ESCAPE_TIMER_MAX 1024\n#define IWX_BA_ESCAPE_TIMER_MIN 0\n\n#define IWX_BA_ENABLE_BEACON_ABORT_DEFAULT 1\n\n#define IWX_BF_CMD_CONFIG_DEFAULTS                         \\\n    .bf_energy_delta = htole32(IWX_BF_ENERGY_DELTA_DEFAULT),         \\\n    .bf_roaming_energy_delta =                         \\\n        htole32(IWX_BF_ROAMING_ENERGY_DELTA_DEFAULT),         \\\n    .bf_roaming_state = htole32(IWX_BF_ROAMING_STATE_DEFAULT),         \\\n    .bf_temp_threshold = htole32(IWX_BF_TEMP_THRESHOLD_DEFAULT),     \\\n    .bf_temp_fast_filter = htole32(IWX_BF_TEMP_FAST_FILTER_DEFAULT), \\\n    .bf_temp_slow_filter = htole32(IWX_BF_TEMP_SLOW_FILTER_DEFAULT), \\\n    .bf_debug_flag = htole32(IWX_BF_DEBUG_FLAG_DEFAULT),         \\\n    .bf_escape_timer = htole32(IWX_BF_ESCAPE_TIMER_DEFAULT),         \\\n    .ba_escape_timer = htole32(IWX_BA_ESCAPE_TIMER_DEFAULT)\n\n/* uCode API values for HT/VHT bit rates */\n#define IWX_RATE_HT_SISO_MCS_0_PLCP    0\n#define IWX_RATE_HT_SISO_MCS_1_PLCP    1\n#define IWX_RATE_HT_SISO_MCS_2_PLCP    2\n#define IWX_RATE_HT_SISO_MCS_3_PLCP    3\n#define IWX_RATE_HT_SISO_MCS_4_PLCP    4\n#define IWX_RATE_HT_SISO_MCS_5_PLCP    5\n#define IWX_RATE_HT_SISO_MCS_6_PLCP    6\n#define IWX_RATE_HT_SISO_MCS_7_PLCP    7\n#define IWX_RATE_HT_MIMO2_MCS_8_PLCP    0x8\n#define IWX_RATE_HT_MIMO2_MCS_9_PLCP    0x9\n#define IWX_RATE_HT_MIMO2_MCS_10_PLCP    0xA\n#define IWX_RATE_HT_MIMO2_MCS_11_PLCP    0xB\n#define IWX_RATE_HT_MIMO2_MCS_12_PLCP    0xC\n#define IWX_RATE_HT_MIMO2_MCS_13_PLCP    0xD\n#define IWX_RATE_HT_MIMO2_MCS_14_PLCP    0xE\n#define IWX_RATE_HT_MIMO2_MCS_15_PLCP    0xF\n#define IWX_RATE_VHT_SISO_MCS_0_PLCP    0\n#define IWX_RATE_VHT_SISO_MCS_1_PLCP    1\n#define IWX_RATE_VHT_SISO_MCS_2_PLCP    2\n#define IWX_RATE_VHT_SISO_MCS_3_PLCP    3\n#define IWX_RATE_VHT_SISO_MCS_4_PLCP    4\n#define IWX_RATE_VHT_SISO_MCS_5_PLCP    5\n#define IWX_RATE_VHT_SISO_MCS_6_PLCP    6\n#define IWX_RATE_VHT_SISO_MCS_7_PLCP    7\n#define IWX_RATE_VHT_SISO_MCS_8_PLCP    8\n#define IWX_RATE_VHT_SISO_MCS_9_PLCP    9\n#define IWX_RATE_VHT_MIMO2_MCS_0_PLCP    0x10\n#define IWX_RATE_VHT_MIMO2_MCS_1_PLCP    0x11\n#define IWX_RATE_VHT_MIMO2_MCS_2_PLCP    0x12\n#define IWX_RATE_VHT_MIMO2_MCS_3_PLCP    0x13\n#define IWX_RATE_VHT_MIMO2_MCS_4_PLCP    0x14\n#define IWX_RATE_VHT_MIMO2_MCS_5_PLCP    0x15\n#define IWX_RATE_VHT_MIMO2_MCS_6_PLCP    0x16\n#define IWX_RATE_VHT_MIMO2_MCS_7_PLCP    0x17\n#define IWX_RATE_VHT_MIMO2_MCS_8_PLCP    0x18\n#define IWX_RATE_VHT_MIMO2_MCS_9_PLCP    0x19\n#define IWX_RATE_HT_SISO_MCS_INV_PLCP    0x1A\n#define IWX_RATE_HT_MIMO2_MCS_INV_PLCP    IWX_RATE_HT_SISO_MCS_INV_PLCP\n#define IWX_RATE_VHT_SISO_MCS_INV_PLCP    IWX_RATE_HT_SISO_MCS_INV_PLCP\n#define IWX_RATE_VHT_MIMO2_MCS_INV_PLCP    IWX_RATE_HT_SISO_MCS_INV_PLCP\n#define IWX_RATE_HT_SISO_MCS_8_PLCP    IWX_RATE_HT_SISO_MCS_INV_PLCP\n#define IWX_RATE_HT_SISO_MCS_9_PLCP    IWX_RATE_HT_SISO_MCS_INV_PLCP\n\n/*\n * These serve as indexes into struct iwx_rate iwx_rates[IWX_RIDX_MAX].\n */\nenum {\n    IWX_RATE_1M_INDEX = 0,\n    IWX_FIRST_CCK_RATE = IWX_RATE_1M_INDEX,\n    IWX_RATE_2M_INDEX,\n    IWX_RATE_5M_INDEX,\n    IWX_RATE_11M_INDEX,\n    IWX_LAST_CCK_RATE = IWX_RATE_11M_INDEX,\n    IWX_RATE_6M_INDEX,\n    IWX_FIRST_OFDM_RATE = IWX_RATE_6M_INDEX,\n    IWX_RATE_MCS_0_INDEX = IWX_RATE_6M_INDEX,\n    IWX_FIRST_HT_RATE = IWX_RATE_MCS_0_INDEX,\n    IWX_FIRST_VHT_RATE = IWX_RATE_MCS_0_INDEX,\n    IWX_RATE_9M_INDEX,\n    IWX_RATE_12M_INDEX,\n    IWX_RATE_MCS_1_INDEX = IWX_RATE_12M_INDEX,\n    IWX_RATE_MCS_8_INDEX,\n    IWX_FIRST_HT_MIMO2_RATE = IWX_RATE_MCS_8_INDEX,\n    IWX_RATE_18M_INDEX,\n    IWX_RATE_MCS_2_INDEX = IWX_RATE_18M_INDEX,\n    IWX_RATE_24M_INDEX,\n    IWX_RATE_MCS_3_INDEX = IWX_RATE_24M_INDEX,\n    IWX_RATE_MCS_9_INDEX,\n    IWX_RATE_36M_INDEX,\n    IWX_RATE_MCS_4_INDEX = IWX_RATE_36M_INDEX,\n    IWX_RATE_MCS_10_INDEX,\n    IWX_RATE_48M_INDEX,\n    IWX_RATE_MCS_5_INDEX = IWX_RATE_48M_INDEX,\n    IWX_RATE_MCS_11_INDEX,\n    IWX_RATE_54M_INDEX,\n    IWX_RATE_MCS_6_INDEX = IWX_RATE_54M_INDEX,\n    IWX_LAST_NON_HT_RATE = IWX_RATE_54M_INDEX,\n    IWX_RATE_MCS_7_INDEX,\n    IWX_LAST_HT_SISO_RATE = IWX_RATE_MCS_7_INDEX,\n    IWX_RATE_MCS_12_INDEX,\n    IWX_RATE_MCS_13_INDEX,\n    IWX_RATE_MCS_14_INDEX,\n    IWX_RATE_MCS_15_INDEX,\n    IWX_LAST_HT_RATE = IWX_RATE_MCS_15_INDEX,\n    IWX_LAST_VHT_RATE = IWX_RATE_MCS_9_INDEX,\n    IWX_RATE_COUNT_LEGACY = IWX_LAST_NON_HT_RATE + 1,\n    IWX_RATE_COUNT = IWX_LAST_HT_RATE + 1,\n};\n\n#define IWX_RATE_BIT_MSK(r) (1 << (IWX_RATE_##r##M_INDEX))\n\n/* fw API values for legacy bit rates, both OFDM and CCK */\n#define IWX_RATE_6M_PLCP     13\n#define IWX_RATE_9M_PLCP     15\n#define IWX_RATE_12M_PLCP    5\n#define IWX_RATE_18M_PLCP    7\n#define IWX_RATE_24M_PLCP    9\n#define IWX_RATE_36M_PLCP    11\n#define IWX_RATE_48M_PLCP    1\n#define IWX_RATE_54M_PLCP    3\n#define IWX_RATE_1M_PLCP     10\n#define IWX_RATE_2M_PLCP     20\n#define IWX_RATE_5M_PLCP     55\n#define IWX_RATE_11M_PLCP    110\n#define IWX_RATE_INVM_PLCP    0xff\n\n/*\n * rate_n_flags bit fields\n *\n * The 32-bit value has different layouts in the low 8 bites depending on the\n * format. There are three formats, HT, VHT and legacy (11abg, with subformats\n * for CCK and OFDM).\n *\n * High-throughput (HT) rate format\n *    bit 8 is 1, bit 26 is 0, bit 9 is 0 (OFDM)\n * Very High-throughput (VHT) rate format\n *    bit 8 is 0, bit 26 is 1, bit 9 is 0 (OFDM)\n * Legacy OFDM rate format for bits 7:0\n *    bit 8 is 0, bit 26 is 0, bit 9 is 0 (OFDM)\n * Legacy CCK rate format for bits 7:0:\n *    bit 8 is 0, bit 26 is 0, bit 9 is 1 (CCK)\n */\n\n/* Bit 8: (1) HT format, (0) legacy or VHT format */\n#define IWX_RATE_MCS_HT_POS 8\n#define IWX_RATE_MCS_HT_MSK_V1 (1 << IWX_RATE_MCS_HT_POS)\n\n/* Bit 9: (1) CCK, (0) OFDM.  HT (bit 8) must be \"0\" for this bit to be valid */\n#define IWX_RATE_MCS_CCK_POS_V1 9\n#define IWX_RATE_MCS_CCK_MSK_V1 (1 << IWX_RATE_MCS_CCK_POS_V1)\n\n/* Bit 26: (1) VHT format, (0) legacy format in bits 8:0 */\n#define IWX_RATE_MCS_VHT_POS_V1 26\n#define IWX_RATE_MCS_VHT_MSK_V1 (1 << IWX_RATE_MCS_VHT_POS_V1)\n\n/* Bit 10 - OFDM HE */\n#define IWX_RATE_MCS_HE_POS_V1        10\n#define IWX_RATE_MCS_HE_MSK_V1        (1 << IWX_RATE_MCS_HE_POS_V1)\n\n/*\n * High-throughput (HT) rate format for bits 7:0\n *\n *  2-0:  MCS rate base\n *        0)   6 Mbps\n *        1)  12 Mbps\n *        2)  18 Mbps\n *        3)  24 Mbps\n *        4)  36 Mbps\n *        5)  48 Mbps\n *        6)  54 Mbps\n *        7)  60 Mbps\n *  4-3:  0)  Single stream (SISO)\n *        1)  Dual stream (MIMO)\n *        2)  Triple stream (MIMO)\n *    5:  Value of 0x20 in bits 7:0 indicates 6 Mbps HT40 duplicate data\n *  (bits 7-6 are zero)\n *\n * Together the low 5 bits work out to the MCS index because we don't\n * support MCSes above 15/23, and 0-7 have one stream, 8-15 have two\n * streams and 16-23 have three streams. We could also support MCS 32\n * which is the duplicate 20 MHz MCS (bit 5 set, all others zero.)\n */\n#define IWX_RATE_HT_MCS_RATE_CODE_MSK_V1    0x7\n#define IWX_RATE_HT_MCS_NSS_POS_V1             3\n#define IWX_RATE_HT_MCS_NSS_MSK_V1             (3 << IWX_RATE_HT_MCS_NSS_POS_V1)\n#define IWX_RATE_HT_MCS_MIMO2_MSK        (1 << IWX_RATE_HT_MCS_NSS_POS_V1)\n\n/* Bit 10: (1) Use Green Field preamble */\n#define IWX_RATE_HT_MCS_GF_POS        10\n#define IWX_RATE_HT_MCS_GF_MSK        (1 << IWX_RATE_HT_MCS_GF_POS)\n\n#define IWX_RATE_HT_MCS_INDEX_MSK_V1        0x3f\n\n/*\n * Very High-throughput (VHT) rate format for bits 7:0\n *\n *  3-0:  VHT MCS (0-9)\n *  5-4:  number of streams - 1:\n *        0)  Single stream (SISO)\n *        1)  Dual stream (MIMO)\n *        2)  Triple stream (MIMO)\n */\n\n/* Bit 4-5: (0) SISO, (1) MIMO2 (2) MIMO3 */\n#define IWX_RATE_VHT_MCS_RATE_CODE_MSK    0xf\n#define IWX_RATE_VHT_MCS_NSS_POS        4\n#define IWX_RATE_VHT_MCS_NSS_MSK        (3 << IWX_RATE_VHT_MCS_NSS_POS)\n#define IWX_RATE_VHT_MCS_MIMO2_MSK        (1 << IWX_RATE_VHT_MCS_NSS_POS)\n\n/*\n * Legacy OFDM rate format for bits 7:0\n *\n *  3-0:  0xD)   6 Mbps\n *        0xF)   9 Mbps\n *        0x5)  12 Mbps\n *        0x7)  18 Mbps\n *        0x9)  24 Mbps\n *        0xB)  36 Mbps\n *        0x1)  48 Mbps\n *        0x3)  54 Mbps\n * (bits 7-4 are 0)\n *\n * Legacy CCK rate format for bits 7:0:\n * bit 8 is 0, bit 26 is 0, bit 9 is 1 (CCK):\n *\n *  6-0:   10)  1 Mbps\n *         20)  2 Mbps\n *         55)  5.5 Mbps\n *        110)  11 Mbps\n * (bit 7 is 0)\n */\n#define IWX_RATE_LEGACY_RATE_MSK_V1 0xff\n\n\n/*\n * Bit 11-12: (0) 20MHz, (1) 40MHz, (2) 80MHz, (3) 160MHz\n * 0 and 1 are valid for HT and VHT, 2 and 3 only for VHT\n */\n#define IWX_RATE_MCS_CHAN_WIDTH_POS        11\n#define IWX_RATE_MCS_CHAN_WIDTH_MSK_V1        (3 << IWX_RATE_MCS_CHAN_WIDTH_POS)\n\n/* Bit 13: (1) Short guard interval (0.4 usec), (0) normal GI (0.8 usec) */\n#define IWX_RATE_MCS_SGI_POS_V1        13\n#define IWX_RATE_MCS_SGI_MSK_V1        BIT(IWX_RATE_MCS_SGI_POS_V1)\n\n/*\n * Bits 13-11: (0) 20MHz, (1) 40MHz, (2) 80MHz, (3) 160MHz, (4) 320MHz\n */\n#define IWX_RATE_MCS_CHAN_WIDTH_MSK            (0x7 << IWX_RATE_MCS_CHAN_WIDTH_POS)\n#define IWX_RATE_MCS_CHAN_WIDTH_20        (0 << IWX_RATE_MCS_CHAN_WIDTH_POS)\n#define IWX_RATE_MCS_CHAN_WIDTH_40        (1 << IWX_RATE_MCS_CHAN_WIDTH_POS)\n#define IWX_RATE_MCS_CHAN_WIDTH_80        (2 << IWX_RATE_MCS_CHAN_WIDTH_POS)\n#define IWX_RATE_MCS_CHAN_WIDTH_160        (3 << IWX_RATE_MCS_CHAN_WIDTH_POS)\n#define IWX_RATE_MCS_CHAN_WIDTH_320        (4 << IWX_RATE_MCS_CHAN_WIDTH_POS)\n\n/* Bit 15-14: Antenna selection:\n * Bit 14: Ant A active\n * Bit 15: Ant B active\n *\n * All relevant definitions are same as in v1\n */\n\n/* Bit 16 (1) LDPC enables, (0) LDPC disabled */\n#define IWX_RATE_MCS_LDPC_POS    16\n#define IWX_RATE_MCS_LDPC_MSK    (1 << IWX_RATE_MCS_LDPC_POS)\n\n/* Bit 17: (0) SS, (1) SS*2 (same as v1) */\n\n/* Bit 18: OFDM-HE dual carrier mode (same as v1) */\n\n/* Bit 19: (0) Beamforming is off, (1) Beamforming is on (same as v1) */\n\n/*\n * Bit 22-20: HE LTF type and guard interval\n * CCK:\n *    0            long preamble\n *    1            short preamble\n * HT/VHT:\n *    0            0.8us\n *    1            0.4us\n * HE (ext) SU:\n *    0            1xLTF+0.8us\n *    1            2xLTF+0.8us\n *    2            2xLTF+1.6us\n *    3            4xLTF+3.2us\n *    4            4xLTF+0.8us\n * HE MU:\n *    0            4xLTF+0.8us\n *    1            2xLTF+0.8us\n *    2            2xLTF+1.6us\n *    3            4xLTF+3.2us\n * HE TRIG:\n *    0            1xLTF+1.6us\n *    1            2xLTF+1.6us\n *    2            4xLTF+3.2us\n * */\n#define IWX_RATE_MCS_HE_GI_LTF_MSK        (0x7 << IWX_RATE_MCS_HE_GI_LTF_POS)\n#define IWX_RATE_MCS_SGI_POS        IWX_RATE_MCS_HE_GI_LTF_POS\n#define IWX_RATE_MCS_SGI_MSK        (1 << IWX_RATE_MCS_SGI_POS)\n#define IWX_RATE_MCS_HE_SU_4_LTF        3\n#define IWX_RATE_MCS_HE_SU_4_LTF_08_GI    4\n\n/* Bit 24-23: HE type. (0) SU, (1) SU_EXT, (2) MU, (3) trigger based */\n#define IWX_RATE_MCS_HE_TYPE_POS        23\n#define IWX_RATE_MCS_HE_TYPE_SU        (0 << IWX_RATE_MCS_HE_TYPE_POS)\n#define IWX_RATE_MCS_HE_TYPE_EXT_SU        (1 << IWX_RATE_MCS_HE_TYPE_POS)\n#define IWX_RATE_MCS_HE_TYPE_MU        (2 << IWX_RATE_MCS_HE_TYPE_POS)\n#define IWX_RATE_MCS_HE_TYPE_TRIG        (3 << IWX_RATE_MCS_HE_TYPE_POS)\n#define IWX_RATE_MCS_HE_TYPE_MSK        (3 << IWX_RATE_MCS_HE_TYPE_POS)\n\n/* Bit 25: duplicate channel enabled\n *\n * if this bit is set, duplicate is according to BW (bits 11-13):\n *\n * CCK:  2x 20MHz\n * OFDM Legacy: N x 20Mhz, (N = BW \\ 2 , either 2, 4, 8, 16)\n * EHT: 2 x BW/2, (80 - 2x40, 160 - 2x80, 320 - 2x160)\n * */\n#define IWX_RATE_MCS_DUP_POS        25\n#define IWX_RATE_MCS_DUP_MSK        (1 << IWX_RATE_MCS_DUP_POS)\n\n/* Bit 26: (1) 106-tone RX (8 MHz RU), (0) normal bandwidth */\n#define IWX_RATE_MCS_HE_106T_POS        26\n#define IWX_RATE_MCS_HE_106T_MSK        (1 << IWX_RATE_MCS_HE_106T_POS)\n\n/* Bit 27: EHT extra LTF:\n * instead of 1 LTF for SISO use 2 LTFs,\n * instead of 2 LTFs for NSTS=2 use 4 LTFs*/\n#define IWX_RATE_MCS_EHT_EXTRA_LTF_POS    27\n#define IWX_RATE_MCS_EHT_EXTRA_LTF_MSK    (1 << IWX_RATE_MCS_EHT_EXTRA_LTF_POS)\n\n/* Bit 14-16: Antenna selection (1) Ant A, (2) Ant B, (4) Ant C */\n#define IWX_RATE_MCS_ANT_POS        14\n#define IWX_RATE_MCS_ANT_A_MSK        (1 << IWX_RATE_MCS_ANT_POS)\n#define IWX_RATE_MCS_ANT_B_MSK        (2 << IWX_RATE_MCS_ANT_POS)\n#define IWX_RATE_MCS_ANT_C_MSK        (4 << IWX_RATE_MCS_ANT_POS)\n#define IWX_RATE_MCS_ANT_AB_MSK        (IWX_RATE_MCS_ANT_A_MSK | \\\n                     IWX_RATE_MCS_ANT_B_MSK)\n#define IWX_RATE_MCS_ANT_ABC_MSK        (IWX_RATE_MCS_ANT_AB_MSK | \\\n                     IWX_RATE_MCS_ANT_C_MSK)\n#define IWX_RATE_MCS_ANT_MSK        IWX_RATE_MCS_ANT_ABC_MSK\n#define IWX_RATE_MCS_ANT_NUM 3\n\n/* Bit 17-18: (0) SS, (1) SS*2 */\n#define IWX_RATE_MCS_STBC_POS        17\n#define IWX_RATE_MCS_STBC_MSK        (1 << IWX_RATE_MCS_STBC_POS)\n\n/* Bit 18: OFDM-HE dual carrier mode */\n#define IWX_RATE_HE_DUAL_CARRIER_MODE    18\n#define IWX_RATE_HE_DUAL_CARRIER_MODE_MSK    (1 << IWX_RATE_HE_DUAL_CARRIER_MODE)\n\n/* Bit 19: (0) Beamforming is off, (1) Beamforming is on */\n#define IWX_RATE_MCS_BF_POS            19\n#define IWX_RATE_MCS_BF_MSK            (1 << IWX_RATE_MCS_BF_POS)\n\n/*\n * Bit 20-21: HE LTF type and guard interval\n * HE (ext) SU:\n *    0            1xLTF+0.8us\n *    1            2xLTF+0.8us\n *    2            2xLTF+1.6us\n *    3 & SGI (bit 13) clear    4xLTF+3.2us\n *    3 & SGI (bit 13) set    4xLTF+0.8us\n * HE MU:\n *    0            4xLTF+0.8us\n *    1            2xLTF+0.8us\n *    2            2xLTF+1.6us\n *    3            4xLTF+3.2us\n * HE TRIG:\n *    0            1xLTF+1.6us\n *    1            2xLTF+1.6us\n *    2            4xLTF+3.2us\n *    3            (does not occur)\n */\n#define IWX_RATE_MCS_HE_GI_LTF_POS        20\n#define IWX_RATE_MCS_HE_GI_LTF_MSK_V1        (3 << IWX_RATE_MCS_HE_GI_LTF_POS)\n\n/* Bit 22-23: HE type. (0) SU, (1) SU_EXT, (2) MU, (3) trigger based */\n#define IWX_RATE_MCS_HE_TYPE_POS_V1        22\n#define IWX_RATE_MCS_HE_TYPE_SU_V1        (0 << IWX_RATE_MCS_HE_TYPE_POS_V1)\n#define IWX_RATE_MCS_HE_TYPE_EXT_SU_V1        BIT(IWX_RATE_MCS_HE_TYPE_POS_V1)\n#define IWX_RATE_MCS_HE_TYPE_MU_V1        (2 << IWX_RATE_MCS_HE_TYPE_POS_V1)\n#define IWX_RATE_MCS_HE_TYPE_TRIG_V1    (3 << IWX_RATE_MCS_HE_TYPE_POS_V1)\n#define IWX_RATE_MCS_HE_TYPE_MSK_V1        (3 << IWX_RATE_MCS_HE_TYPE_POS_V1)\n\n/* Bit 24-25: (0) 20MHz (no dup), (1) 2x20MHz, (2) 4x20MHz, 3 8x20MHz */\n#define IWX_RATE_MCS_DUP_POS_V1        24\n#define IWX_RATE_MCS_DUP_MSK_V1        (3 << IWX_RATE_MCS_DUP_POS_V1)\n\n/* Bit 27: (1) LDPC enabled, (0) LDPC disabled */\n#define IWX_RATE_MCS_LDPC_POS_V1        27\n#define IWX_RATE_MCS_LDPC_MSK_V1        BIT(IWX_RATE_MCS_LDPC_POS_V1)\n\n/* Bit 28: (1) 106-tone RX (8 MHz RU), (0) normal bandwidth */\n#define IWX_RATE_MCS_HE_106T_POS_V1        28\n#define IWX_RATE_MCS_HE_106T_MSK_V1        BIT(IWX_RATE_MCS_HE_106T_POS_V1)\n\n/* Bit 30-31: (1) RTS, (2) CTS */\n#define IWX_RATE_MCS_RTS_REQUIRED_POS  (30)\n#define IWX_RATE_MCS_RTS_REQUIRED_MSK  (0x1 << IWX_RATE_MCS_RTS_REQUIRED_POS)\n\n#define IWX_RATE_MCS_CTS_REQUIRED_POS  (31)\n#define IWX_RATE_MCS_CTS_REQUIRED_MSK  (0x1 << IWX_RATE_MCS_CTS_REQUIRED_POS)\n\n/* Bits 10-8: rate format\n * (0) Legacy CCK (1) Legacy OFDM (2) High-throughput (HT)\n * (3) Very High-throughput (VHT) (4) High-efficiency (HE)\n * (5) Extremely High-throughput (EHT)\n */\n#define IWX_RATE_MCS_MOD_TYPE_POS        8\n#define IWX_RATE_MCS_MOD_TYPE_MSK        (0x7 << IWX_RATE_MCS_MOD_TYPE_POS)\n#define IWX_RATE_MCS_CCK_MSK        (0 << IWX_RATE_MCS_MOD_TYPE_POS)\n#define IWX_RATE_MCS_LEGACY_OFDM_MSK    (1 << IWX_RATE_MCS_MOD_TYPE_POS)\n#define IWX_RATE_MCS_HT_MSK            (2 << IWX_RATE_MCS_MOD_TYPE_POS)\n#define IWX_RATE_MCS_VHT_MSK        (3 << IWX_RATE_MCS_MOD_TYPE_POS)\n#define IWX_RATE_MCS_HE_MSK            (4 << IWX_RATE_MCS_MOD_TYPE_POS)\n#define IWX_RATE_MCS_EHT_MSK        (5 << IWX_RATE_MCS_MOD_TYPE_POS)\n\n/*\n * Legacy CCK rate format for bits 0:3:\n *\n * (0) 0xa - 1 Mbps\n * (1) 0x14 - 2 Mbps\n * (2) 0x37 - 5.5 Mbps\n * (3) 0x6e - 11 nbps\n *\n * Legacy OFDM rate format for bis 3:0:\n *\n * (0) 6 Mbps\n * (1) 9 Mbps\n * (2) 12 Mbps\n * (3) 18 Mbps\n * (4) 24 Mbps\n * (5) 36 Mbps\n * (6) 48 Mbps\n * (7) 54 Mbps\n *\n */\n#define IWX_RATE_LEGACY_RATE_MSK        0x7\n\n/*\n * HT, VHT, HE, EHT rate format for bits 3:0\n * 3-0: MCS\n *\n */\n#define IWX_RATE_HT_MCS_CODE_MSK        0x7\n#define IWX_RATE_MCS_NSS_POS        4\n#define IWX_RATE_MCS_NSS_MSK        (1 << IWX_RATE_MCS_NSS_POS)\n#define IWX_RATE_MCS_CODE_MSK        0xf\n#define IWX_RATE_HT_MCS_INDEX(r)        ((((r) & IWX_RATE_MCS_NSS_MSK) >> 1) | \\\n                     ((r) & IWX_RATE_HT_MCS_CODE_MSK))\n\n/* Link Quality definitions */\n\n/* # entries in rate scale table to support Tx retries */\n#define  IWX_LQ_MAX_RETRY_NUM 16\n\n/* Link quality command flags bit fields */\n\n/* Bit 0: (0) Don't use RTS (1) Use RTS */\n#define IWX_LQ_FLAG_USE_RTS_POS             0\n#define IWX_LQ_FLAG_USE_RTS_MSK            (1 << IWX_LQ_FLAG_USE_RTS_POS)\n\n/* Bit 1-3: LQ command color. Used to match responses to LQ commands */\n#define IWX_LQ_FLAG_COLOR_POS               1\n#define IWX_LQ_FLAG_COLOR_MSK               (7 << IWX_LQ_FLAG_COLOR_POS)\n\n/* Bit 4-5: Tx RTS BW Signalling\n * (0) No RTS BW signalling\n * (1) Static BW signalling\n * (2) Dynamic BW signalling\n */\n#define IWX_LQ_FLAG_RTS_BW_SIG_POS          4\n#define IWX_LQ_FLAG_RTS_BW_SIG_NONE         (0 << IWX_LQ_FLAG_RTS_BW_SIG_POS)\n#define IWX_LQ_FLAG_RTS_BW_SIG_STATIC       (1 << IWX_LQ_FLAG_RTS_BW_SIG_POS)\n#define IWX_LQ_FLAG_RTS_BW_SIG_DYNAMIC      (2 << IWX_LQ_FLAG_RTS_BW_SIG_POS)\n\n/* Bit 6: (0) No dynamic BW selection (1) Allow dynamic BW selection\n * Dyanmic BW selection allows Tx with narrower BW then requested in rates\n */\n#define IWX_LQ_FLAG_DYNAMIC_BW_POS          6\n#define IWX_LQ_FLAG_DYNAMIC_BW_MSK          (1 << IWX_LQ_FLAG_DYNAMIC_BW_POS)\n\n/**\n * Options for TLC config flags\n * @IWX_TLC_MNG_CFG_FLAGS_STBC_MSK: enable STBC. For HE this enables STBC for\n *                    bandwidths <= 80MHz\n * @IWX_TLC_MNG_CFG_FLAGS_LDPC_MSK: enable LDPC\n * @IWX_TLC_MNG_CFG_FLAGS_HE_STBC_160MHZ_MSK: enable STBC in HE at 160MHz\n *                          bandwidth\n * @IWX_TLC_MNG_CFG_FLAGS_HE_DCM_NSS_1_MSK: enable HE Dual Carrier Modulation\n *                        for BPSK (MCS 0) with 1 spatial\n *                        stream\n * @IWX_TLC_MNG_CFG_FLAGS_HE_DCM_NSS_2_MSK: enable HE Dual Carrier Modulation\n *                        for BPSK (MCS 0) with 2 spatial\n *                        streams\n */\n#define IWX_TLC_MNG_CFG_FLAGS_STBC_MSK            (1 << 0)\n#define IWX_TLC_MNG_CFG_FLAGS_LDPC_MSK            (1 << 1)\n#define IWX_TLC_MNG_CFG_FLAGS_HE_STBC_160MHZ_MSK    (1 << 2)\n#define IWX_TLC_MNG_CFG_FLAGS_HE_DCM_NSS_1_MSK        (1 << 3)\n#define IWX_TLC_MNG_CFG_FLAGS_HE_DCM_NSS_2_MSK        (1 << 4)\n\n/**\n * enum iwx_tlc_mng_cfg_cw - channel width options\n * @IWX_TLC_MNG_CH_WIDTH_20MHZ: 20MHZ channel\n * @IWX_TLC_MNG_CH_WIDTH_40MHZ: 40MHZ channel\n * @IWX_TLC_MNG_CH_WIDTH_80MHZ: 80MHZ channel\n * @IWX_TLC_MNG_CH_WIDTH_160MHZ: 160MHZ channel\n * @IWX_TLC_MNG_CH_WIDTH_LAST: maximum value\n */\nenum iwx_tlc_mng_cfg_cw {\n    IWX_TLC_MNG_CH_WIDTH_20MHZ,\n    IWX_TLC_MNG_CH_WIDTH_40MHZ,\n    IWX_TLC_MNG_CH_WIDTH_80MHZ,\n    IWX_TLC_MNG_CH_WIDTH_160MHZ,\n    IWX_TLC_MNG_CH_WIDTH_LAST = IWX_TLC_MNG_CH_WIDTH_160MHZ,\n};\n\n/**\n * @IWX_TLC_MNG_CHAIN_A_MSK: chain A\n * @IWX_TLC_MNG_CHAIN_B_MSK: chain B\n */\n#define IWX_TLC_MNG_CHAIN_A_MSK    (1 << 0)\n#define IWX_TLC_MNG_CHAIN_B_MSK    (1 << 1)\n\n/**\n * enum iwx_tlc_mng_cfg_mode - supported modes\n * @IWX_TLC_MNG_MODE_CCK: enable CCK\n * @IWX_TLC_MNG_MODE_OFDM_NON_HT: enable OFDM (non HT)\n * @IWX_TLC_MNG_MODE_NON_HT: enable non HT\n * @IWX_TLC_MNG_MODE_HT: enable HT\n * @IWX_TLC_MNG_MODE_VHT: enable VHT\n * @IWX_TLC_MNG_MODE_HE: enable HE\n * @IWX_TLC_MNG_MODE_INVALID: invalid value\n * @IWX_TLC_MNG_MODE_NUM: a count of possible modes\n */\nenum iwx_tlc_mng_cfg_mode {\n    IWX_TLC_MNG_MODE_CCK = 0,\n    IWX_TLC_MNG_MODE_OFDM_NON_HT = IWX_TLC_MNG_MODE_CCK,\n    IWX_TLC_MNG_MODE_NON_HT = IWX_TLC_MNG_MODE_CCK,\n    IWX_TLC_MNG_MODE_HT,\n    IWX_TLC_MNG_MODE_VHT,\n    IWX_TLC_MNG_MODE_HE,\n    IWX_TLC_MNG_MODE_INVALID,\n    IWX_TLC_MNG_MODE_NUM = IWX_TLC_MNG_MODE_INVALID,\n};\n\n/**\n * @IWX_TLC_MNG_HT_RATE_MCS0: index of MCS0\n * @IWX_TLC_MNG_HT_RATE_MCS1: index of MCS1\n * @IWX_TLC_MNG_HT_RATE_MCS2: index of MCS2\n * @IWX_TLC_MNG_HT_RATE_MCS3: index of MCS3\n * @IWX_TLC_MNG_HT_RATE_MCS4: index of MCS4\n * @IWX_TLC_MNG_HT_RATE_MCS5: index of MCS5\n * @IWX_TLC_MNG_HT_RATE_MCS6: index of MCS6\n * @IWX_TLC_MNG_HT_RATE_MCS7: index of MCS7\n * @IWX_TLC_MNG_HT_RATE_MCS8: index of MCS8\n * @IWX_TLC_MNG_HT_RATE_MCS9: index of MCS9\n * @IWX_TLC_MNG_HT_RATE_MCS10: index of MCS10\n * @IWX_TLC_MNG_HT_RATE_MCS11: index of MCS11\n * @IWX_TLC_MNG_HT_RATE_MAX: maximal rate for HT/VHT\n */\nenum iwx_tlc_mng_ht_rates {\n    IWX_TLC_MNG_HT_RATE_MCS0 = 0,\n    IWX_TLC_MNG_HT_RATE_MCS1,\n    IWX_TLC_MNG_HT_RATE_MCS2,\n    IWX_TLC_MNG_HT_RATE_MCS3,\n    IWX_TLC_MNG_HT_RATE_MCS4,\n    IWX_TLC_MNG_HT_RATE_MCS5,\n    IWX_TLC_MNG_HT_RATE_MCS6,\n    IWX_TLC_MNG_HT_RATE_MCS7,\n    IWX_TLC_MNG_HT_RATE_MCS8,\n    IWX_TLC_MNG_HT_RATE_MCS9,\n    IWX_TLC_MNG_HT_RATE_MCS10,\n    IWX_TLC_MNG_HT_RATE_MCS11,\n    IWX_TLC_MNG_HT_RATE_MAX = IWX_TLC_MNG_HT_RATE_MCS11,\n};\n\n#define IWX_TLC_NSS_1    0\n#define IWX_TLC_NSS_2    1\n#define IWX_TLC_NSS_MAX    2\n\n#define IWX_TLC_MCS_PER_BW_80   0\n#define IWX_TLC_MCS_PER_BW_160  1\n#define IWX_TLC_MCS_PER_BW_320  2\n#define IWX_TLC_MCS_PER_BW_NUM_V3   (IWX_TLC_MCS_PER_BW_160 + 1)\n#define IWX_TLC_MCS_PER_BW_NUM_V4   (IWX_TLC_MCS_PER_BW_320 + 1)\n\n/**\n * struct iwx_tlc_config_cmd - TLC configuration\n * @sta_id: station id\n * @reserved1: reserved\n * @max_ch_width: max supported channel width from @enum iwx_tlc_mng_cfg_cw\n * @mode: &enum iwx_tlc_mng_cfg_mode\n * @chains: bitmask of IWX_TLC_MNG_CHAIN_*_MSK\n * @amsdu: TX amsdu is supported\n * @flags: bitmask of IWX_TLC_MNG_CFG_*\n * @non_ht_rates: bitmap of supported legacy rates\n * @ht_rates: bitmap of &enum iwl_tlc_mng_ht_rates, per &enum IWL_TLC_MCS_PER_BW\n *  <nss, channel-width> pair (0 - 80mhz width and below, 1 - 160mhz).\n * @max_mpdu_len: max MPDU length, in bytes\n * @sgi_ch_width_supp: bitmap of SGI support per channel width\n *               use (1 << @enum iwx_tlc_mng_cfg_cw)\n * @reserved2: reserved\n * @max_tx_op: max TXOP in uSecs for all AC (BK, BE, VO, VI),\n *           set zero for no limit.\n */\nstruct iwl_tlc_config_cmd_v3 {\n    uint8_t sta_id;\n    uint8_t reserved1[3];\n    uint8_t max_ch_width;\n    uint8_t mode;\n    uint8_t chains;\n    uint8_t amsdu;\n    uint16_t flags;\n    uint16_t non_ht_rates;\n    uint16_t ht_rates[IWX_TLC_NSS_MAX][IWX_TLC_MCS_PER_BW_NUM_V3];\n    uint16_t max_mpdu_len;\n    uint8_t sgi_ch_width_supp;\n    uint8_t reserved2;\n    uint32_t max_tx_op;\n} __packed; /* TLC_MNG_CONFIG_CMD_API_S_VER_3 */\n\n/**\n * struct iwx_tlc_config_cmd_v4 - TLC configuration\n * @sta_id: station id\n * @reserved1: reserved\n * @max_ch_width: max supported channel width from &enum iwl_tlc_mng_cfg_cw\n * @mode: &enum iwl_tlc_mng_cfg_mode\n * @chains: bitmask of &enum iwl_tlc_mng_cfg_chains\n * @sgi_ch_width_supp: bitmap of SGI support per channel width\n *               use BIT(&enum iwl_tlc_mng_cfg_cw)\n * @flags: bitmask of &enum iwl_tlc_mng_cfg_flags\n * @non_ht_rates: bitmap of supported legacy rates\n * @ht_rates: bitmap of &enum iwl_tlc_mng_ht_rates, per <nss, channel-width>\n *          pair (0 - 80mhz width and below, 1 - 160mhz, 2 - 320mhz).\n * @max_mpdu_len: max MPDU length, in bytes\n * @max_tx_op: max TXOP in uSecs for all AC (BK, BE, VO, VI),\n *           set zero for no limit.\n */\nstruct iwx_tlc_config_cmd_v4 {\n    uint8_t sta_id;\n    uint8_t reserved1[3];\n    uint8_t max_ch_width;\n    uint8_t mode;\n    uint8_t chains;\n    uint8_t sgi_ch_width_supp;\n    uint16_t flags;\n    uint16_t non_ht_rates;\n    uint16_t ht_rates[IWX_TLC_NSS_MAX][IWX_TLC_MCS_PER_BW_NUM_V4];\n    uint16_t max_mpdu_len;\n    uint16_t max_tx_op;\n} __packed; /* TLC_MNG_CONFIG_CMD_API_S_VER_4 */\n\n/**\n * @IWX_TLC_NOTIF_FLAG_RATE: last initial rate update\n * @IWX_TLC_NOTIF_FLAG_AMSDU: umsdu parameters update\n */\n#define IWX_TLC_NOTIF_FLAG_RATE        (1 << 0)\n#define IWX_TLC_NOTIF_FLAG_AMSDU    (1 << 1)\n\n/**\n * struct iwx_tlc_update_notif - TLC notification from FW\n * @sta_id: station id\n * @reserved: reserved\n * @flags: bitmap of notifications reported\n * @rate: current initial rate\n * @amsdu_size: Max AMSDU size, in bytes\n * @amsdu_enabled: bitmap for per-TID AMSDU enablement\n */\nstruct iwx_tlc_update_notif {\n    uint8_t sta_id;\n    uint8_t reserved[3];\n    uint32_t flags;\n    uint32_t rate;\n    uint32_t amsdu_size;\n    uint32_t amsdu_enabled;\n} __packed; /* TLC_MNG_UPDATE_NTFY_API_S_VER_2 */\n\n/* Antenna flags. */\n#define IWX_ANT_NONE    0x0\n#define IWX_ANT_INVALID    0xff\n#define IWX_ANT_A    (1 << 0)\n#define IWX_ANT_B    (1 << 1)\n#define IWX_ANT_C    (1 << 2)\n/* Shortcuts. */\n#define IWX_ANT_AB    (IWX_ANT_A | IWX_ANT_B)\n#define IWX_ANT_AC    (IWX_ANT_A | IWX_ANT_C)\n#define IWX_ANT_BC    (IWX_ANT_B | IWX_ANT_C)\n#define IWX_ANT_ABC    (IWX_ANT_A | IWX_ANT_B | IWX_ANT_C)\n#define IWX_MAX_ANT_NUM 3\n\n/**\n * bitmasks for tx_flags in TX command\n * @IWX_TX_CMD_FLG_PROT_REQUIRE: use RTS or CTS-to-self to protect the frame\n * @IWX_TX_CMD_FLG_ACK: expect ACK from receiving station\n * @IWX_TX_CMD_FLG_STA_RATE: use RS table with initial index from the TX command.\n *    Otherwise, use rate_n_flags from the TX command\n * @IWX_TX_CMD_FLG_BA: this frame is a block ack\n * @IWX_TX_CMD_FLG_BAR: this frame is a BA request, immediate BAR is expected\n *    Must set IWX_TX_CMD_FLG_ACK with this flag.\n * @IWX_TX_CMD_FLG_TXOP_PROT: protect frame with full TXOP protection\n * @IWX_TX_CMD_FLG_VHT_NDPA: mark frame is NDPA for VHT beamformer sequence\n * @IWX_TX_CMD_FLG_HT_NDPA: mark frame is NDPA for HT beamformer sequence\n * @IWX_TX_CMD_FLG_CSI_FDBK2HOST: mark to send feedback to host (only if good CRC)\n * @IWX_TX_CMD_FLG_BT_DIS: disable BT priority for this frame\n * @IWX_TX_CMD_FLG_SEQ_CTL: set if FW should override the sequence control.\n *    Should be set for mgmt, non-QOS data, mcast, bcast and in scan command\n * @IWX_TX_CMD_FLG_MORE_FRAG: this frame is non-last MPDU\n * @IWX_TX_CMD_FLG_NEXT_FRAME: this frame includes information of the next frame\n * @IWX_TX_CMD_FLG_TSF: FW should calculate and insert TSF in the frame\n *    Should be set for beacons and probe responses\n * @IWX_TX_CMD_FLG_CALIB: activate PA TX power calibrations\n * @IWX_TX_CMD_FLG_KEEP_SEQ_CTL: if seq_ctl is set, don't increase inner seq count\n * @IWX_TX_CMD_FLG_AGG_START: allow this frame to start aggregation\n * @IWX_TX_CMD_FLG_MH_PAD: driver inserted 2 byte padding after MAC header.\n *    Should be set for 26/30 length MAC headers\n * @IWX_TX_CMD_FLG_RESP_TO_DRV: zero this if the response should go only to FW\n * @IWX_TX_CMD_FLG_CCMP_AGG: this frame uses CCMP for aggregation acceleration\n * @IWX_TX_CMD_FLG_TKIP_MIC_DONE: FW already performed TKIP MIC calculation\n * @IWX_TX_CMD_FLG_DUR: disable duration overwriting used in PS-Poll Assoc-id\n * @IWX_TX_CMD_FLG_FW_DROP: FW should mark frame to be dropped\n * @IWX_TX_CMD_FLG_EXEC_PAPD: execute PAPD\n * @IWX_TX_CMD_FLG_PAPD_TYPE: 0 for reference power, 1 for nominal power\n * @IWX_TX_CMD_FLG_HCCA_CHUNK: mark start of TSPEC chunk\n */\n#define IWX_TX_CMD_FLG_PROT_REQUIRE    (1 << 0)\n#define IWX_TX_CMD_FLG_ACK        (1 << 3)\n#define IWX_TX_CMD_FLG_STA_RATE        (1 << 4)\n#define IWX_TX_CMD_FLG_BA        (1 << 5)\n#define IWX_TX_CMD_FLG_BAR        (1 << 6)\n#define IWX_TX_CMD_FLG_TXOP_PROT    (1 << 7)\n#define IWX_TX_CMD_FLG_VHT_NDPA        (1 << 8)\n#define IWX_TX_CMD_FLG_HT_NDPA        (1 << 9)\n#define IWX_TX_CMD_FLG_CSI_FDBK2HOST    (1 << 10)\n#define IWX_TX_CMD_FLG_BT_DIS        (1 << 12)\n#define IWX_TX_CMD_FLG_SEQ_CTL        (1 << 13)\n#define IWX_TX_CMD_FLG_MORE_FRAG    (1 << 14)\n#define IWX_TX_CMD_FLG_NEXT_FRAME    (1 << 15)\n#define IWX_TX_CMD_FLG_TSF        (1 << 16)\n#define IWX_TX_CMD_FLG_CALIB        (1 << 17)\n#define IWX_TX_CMD_FLG_KEEP_SEQ_CTL    (1 << 18)\n#define IWX_TX_CMD_FLG_AGG_START    (1 << 19)\n#define IWX_TX_CMD_FLG_MH_PAD        (1 << 20)\n#define IWX_TX_CMD_FLG_RESP_TO_DRV    (1 << 21)\n#define IWX_TX_CMD_FLG_CCMP_AGG        (1 << 22)\n#define IWX_TX_CMD_FLG_TKIP_MIC_DONE    (1 << 23)\n#define IWX_TX_CMD_FLG_DUR        (1 << 25)\n#define IWX_TX_CMD_FLG_FW_DROP        (1 << 26)\n#define IWX_TX_CMD_FLG_EXEC_PAPD    (1 << 27)\n#define IWX_TX_CMD_FLG_PAPD_TYPE    (1 << 28)\n#define IWX_TX_CMD_FLG_HCCA_CHUNK    (1U << 31)\n/* IWX_TX_FLAGS_BITS_API_S_VER_1 */\n\n/*\n * TX command security control\n */\n#define IWX_TX_CMD_SEC_WEP        0x01\n#define IWX_TX_CMD_SEC_CCM        0x02\n#define IWX_TX_CMD_SEC_TKIP        0x03\n#define IWX_TX_CMD_SEC_EXT        0x04\n#define IWX_TX_CMD_SEC_MSK        0x07\n#define IWX_TX_CMD_SEC_WEP_KEY_IDX_POS    6\n#define IWX_TX_CMD_SEC_WEP_KEY_IDX_MSK    0xc0\n#define IWX_TX_CMD_SEC_KEY128        0x08\n\n/* TODO: how does these values are OK with only 16 bit variable??? */\n/*\n * TX command next frame info\n *\n * bits 0:2 - security control (IWX_TX_CMD_SEC_*)\n * bit 3 - immediate ACK required\n * bit 4 - rate is taken from STA table\n * bit 5 - frame belongs to BA stream\n * bit 6 - immediate BA response expected\n * bit 7 - unused\n * bits 8:15 - Station ID\n * bits 16:31 - rate\n */\n#define IWX_TX_CMD_NEXT_FRAME_ACK_MSK        (0x8)\n#define IWX_TX_CMD_NEXT_FRAME_STA_RATE_MSK    (0x10)\n#define IWX_TX_CMD_NEXT_FRAME_BA_MSK        (0x20)\n#define IWX_TX_CMD_NEXT_FRAME_IMM_BA_RSP_MSK    (0x40)\n#define IWX_TX_CMD_NEXT_FRAME_FLAGS_MSK        (0xf8)\n#define IWX_TX_CMD_NEXT_FRAME_STA_ID_MSK    (0xff00)\n#define IWX_TX_CMD_NEXT_FRAME_STA_ID_POS    (8)\n#define IWX_TX_CMD_NEXT_FRAME_RATE_MSK        (0xffff0000)\n#define IWX_TX_CMD_NEXT_FRAME_RATE_POS        (16)\n\n/*\n * TX command Frame life time in us - to be written in pm_frame_timeout\n */\n#define IWX_TX_CMD_LIFE_TIME_INFINITE    0xFFFFFFFF\n#define IWX_TX_CMD_LIFE_TIME_DEFAULT    2000000 /* 2000 ms*/\n#define IWX_TX_CMD_LIFE_TIME_PROBE_RESP    40000 /* 40 ms */\n#define IWX_TX_CMD_LIFE_TIME_EXPIRED_FRAME    0\n\n#define IWX_MAX_TID_COUNT    8\n\n/*\n * TID for non QoS frames - to be written in tid_tspec\n */\n#define IWX_TID_NON_QOS    0\n#define IWX_MGMT_TID       15\n\n#define IWX_QID_MGMT       EDCA_AC_BE + IWX_DQA_AUX_QUEUE + 1\n\n/*\n * Limits on the retransmissions - to be written in {data,rts}_retry_limit\n */\n#define IWX_DEFAULT_TX_RETRY            15\n#define IWX_MGMT_DFAULT_RETRY_LIMIT        3\n#define IWX_RTS_DFAULT_RETRY_LIMIT        3\n#define IWX_BAR_DFAULT_RETRY_LIMIT        60\n#define IWX_LOW_RETRY_LIMIT            7\n\n/*\n * The FH will write back to the first TB only, so we need to copy some data\n * into the buffer regardless of whether it should be mapped or not.\n * This indicates how big the first TB must be to include the scratch buffer\n * and the assigned PN.\n * Since PN location is 8 bytes at offset 12, it's 20 now.\n * If we make it bigger then allocations will be bigger and copy slower, so\n * that's probably not useful.\n */\n#define IWX_FIRST_TB_SIZE    20\n#define IWX_FIRST_TB_SIZE_ALIGN ((IWX_FIRST_TB_SIZE + (64 - 1)) & ~(64 - 1))\n\n/**\n * %iwl_tx_cmd offload_assist values\n * @TX_CMD_OFFLD_IP_HDR: offset to start of IP header (in words)\n *    from mac header end. For normal case it is 4 words for SNAP.\n *    note: tx_cmd, mac header and pad are not counted in the offset.\n *    This is used to help the offload in case there is tunneling such as\n *    IPv6 in IPv4, in such case the ip header offset should point to the\n *    inner ip header and IPv4 checksum of the external header should be\n *    calculated by driver.\n * @TX_CMD_OFFLD_L4_EN: enable TCP/UDP checksum\n * @TX_CMD_OFFLD_L3_EN: enable IP header checksum\n * @TX_CMD_OFFLD_MH_SIZE: size of the mac header in words. Includes the IV\n *    field. Doesn't include the pad.\n * @TX_CMD_OFFLD_PAD: mark 2-byte pad was inserted after the mac header for\n *    alignment\n * @TX_CMD_OFFLD_AMSDU: mark TX command is A-MSDU\n */\n#define IWX_TX_CMD_OFFLD_IP_HDR(x)    ((x) << 0)\n#define IWX_TX_CMD_OFFLD_L4_EN        (1 << 6)\n#define IWX_TX_CMD_OFFLD_L3_EN        (1 << 7)\n#define IWX_TX_CMD_OFFLD_MH_SIZE(x)    ((x) << 8)\n#define IWX_TX_CMD_OFFLD_PAD        (1 << 13)\n#define IWX_TX_CMD_OFFLD_AMSDU        (1 << 14)\n#define IWX_TX_CMD_OFFLD_MH_MASK    0x1f\n#define IWX_TX_CMD_OFFLD_IP_HDR_MASK    0x3f\n\nstruct iwx_dram_sec_info {\n    uint32_t pn_low;\n    uint16_t pn_high;\n    uint16_t aux_info;\n} __packed; /* DRAM_SEC_INFO_API_S_VER_1 */\n\n/**\n * bitmasks for tx_flags in TX command for 22000\n * @IWX_TX_FLAGS_CMD_RATE: use rate from the TX command\n * @IWX_TX_FLAGS_ENCRYPT_DIS: frame should not be encrypted, even if it belongs\n *    to a secured STA\n * @IWX_TX_FLAGS_HIGH_PRI: high priority frame (like EAPOL) - can affect rate\n *    selection, retry limits and BT kill\n */\n#define IWX_TX_FLAGS_CMD_RATE        (1 << 0)\n#define IWX_TX_FLAGS_ENCRYPT_DIS    (1 << 1)\n#define IWX_TX_FLAGS_HIGH_PRI        (1 << 2)\n/* TX_FLAGS_BITS_API_S_VER_3 */\n\n/**\n * struct iwx_tx_cmd_gen2 - TX command struct to FW for 22000 devices\n * ( TX_CMD = 0x1c )\n * @len: in bytes of the payload, see below for details\n * @offload_assist: TX offload configuration\n * @flags: combination of TX_CMD_FLG_*\n * @dram_info: FW internal DRAM storage\n * @rate_n_flags: rate for *all* Tx attempts, if TX_CMD_FLG_STA_RATE_MSK is\n *    cleared. Combination of RATE_MCS_*\n * @hdr: 802.11 header\n */\nstruct iwx_tx_cmd_gen2 {\n    uint16_t len;\n    uint16_t offload_assist;\n    uint32_t flags;\n    struct iwx_dram_sec_info dram_info;\n    uint32_t rate_n_flags;\n    struct ieee80211_frame hdr[0];\n} __packed; /* TX_CMD_API_S_VER_7 */\n\n/**\n * struct iwx_tx_cmd_gen3 - TX command struct to FW for AX210+ devices\n * ( TX_CMD = 0x1c )\n * @len: in bytes of the payload, see below for details\n * @flags: combination of &enum iwl_tx_cmd_flags\n * @offload_assist: TX offload configuration\n * @dram_info: FW internal DRAM storage\n * @rate_n_flags: rate for *all* Tx attempts, if TX_CMD_FLG_STA_RATE_MSK is\n *    cleared. Combination of RATE_MCS_*\n * @ttl: time to live - packet lifetime limit. The FW should drop if\n *    passed.\n * @hdr: 802.11 header\n */\nstruct iwx_tx_cmd_gen3 {\n    __le16 len;\n    __le16 flags;\n    __le32 offload_assist;\n    struct iwx_dram_sec_info dram_info;\n    __le32 rate_n_flags;\n    __le64 ttl;\n    struct ieee80211_frame hdr[0];\n} __packed; /* TX_CMD_API_S_VER_8 */\n\n/* For aggregation queues, index must be aligned to frame sequence number. */\n#define IWX_AGG_SSN_TO_TXQ_IDX(x, a)    ((x) & ((a) - 1))\n\n/*\n * TX response related data\n */\n\n/*\n * status that is returned by the fw after attempts to Tx\n * @IWX_TX_STATUS_FAIL_STA_COLOR_MISMATCH: mismatch between color of Tx cmd and\n *    STA table\n * Valid only if frame_count =1\n */\n#define IWX_TX_STATUS_MSK        0x000000ff\n#define IWX_TX_STATUS_SUCCESS        0x01\n#define IWX_TX_STATUS_DIRECT_DONE    0x02\n/* postpone TX */\n#define IWX_TX_STATUS_POSTPONE_DELAY        0x40\n#define IWX_TX_STATUS_POSTPONE_FEW_BYTES    0x41\n#define IWX_TX_STATUS_POSTPONE_BT_PRIO        0x42\n#define IWX_TX_STATUS_POSTPONE_QUIET_PERIOD    0x43\n#define IWX_TX_STATUS_POSTPONE_CALC_TTAK    0x44\n/* abort TX */\n#define IWX_TX_STATUS_FAIL_INTERNAL_CROSSED_RETRY    0x81\n#define IWX_TX_STATUS_FAIL_SHORT_LIMIT            0x82\n#define IWX_TX_STATUS_FAIL_LONG_LIMIT            0x83\n#define IWX_TX_STATUS_FAIL_UNDERRUN            0x84\n#define IWX_TX_STATUS_FAIL_DRAIN_FLOW            0x85\n#define IWX_TX_STATUS_FAIL_RFKILL_FLUSH            0x86\n#define IWX_TX_STATUS_FAIL_LIFE_EXPIRE            0x87\n#define IWX_TX_STATUS_FAIL_DEST_PS            0x88\n#define IWX_TX_STATUS_FAIL_HOST_ABORTED            0x89\n#define IWX_TX_STATUS_FAIL_BT_RETRY            0x8a\n#define IWX_TX_STATUS_FAIL_STA_INVALID            0x8b\n#define IWX_TX_STATUS_FAIL_FRAG_DROPPED            0x8c\n#define IWX_TX_STATUS_FAIL_TID_DISABLE            0x8d\n#define IWX_TX_STATUS_FAIL_FIFO_FLUSHED            0x8e\n#define IWX_TX_STATUS_FAIL_SMALL_CF_POLL        0x8f\n#define IWX_TX_STATUS_FAIL_FW_DROP            0x90\n#define IWX_TX_STATUS_FAIL_STA_COLOR_MISMATCH        0x91\n#define IWX_TX_STATUS_INTERNAL_ABORT            0x92\n#define IWX_TX_MODE_MSK            0x00000f00\n#define IWX_TX_MODE_NO_BURST        0x00000000\n#define IWX_TX_MODE_IN_BURST_SEQ    0x00000100\n#define IWX_TX_MODE_FIRST_IN_BURST    0x00000200\n#define IWX_TX_QUEUE_NUM_MSK        0x0001f000\n#define IWX_TX_NARROW_BW_MSK        0x00060000\n#define IWX_TX_NARROW_BW_1DIV2        0x00020000\n#define IWX_TX_NARROW_BW_1DIV4        0x00040000\n#define IWX_TX_NARROW_BW_1DIV8        0x00060000\n\n/*\n * TX aggregation status\n * @IWX_AGG_TX_STATE_TRY_CNT_MSK: Retry count for 1st frame in aggregation (retries\n *    occur if tx failed for this frame when it was a member of a previous\n *    aggregation block). If rate scaling is used, retry count indicates the\n *    rate table entry used for all frames in the new agg.\n * @IWX_AGG_TX_STATE_SEQ_NUM_MSK: Command ID and sequence number of Tx command for\n *    this frame\n */\n#define IWX_AGG_TX_STATE_STATUS_MSK        0x0fff\n#define IWX_AGG_TX_STATE_TRANSMITTED        0x0000\n#define IWX_AGG_TX_STATE_UNDERRUN        0x0001\n#define IWX_AGG_TX_STATE_BT_PRIO        0x0002\n#define IWX_AGG_TX_STATE_FEW_BYTES        0x0004\n#define IWX_AGG_TX_STATE_ABORT            0x0008\n#define IWX_AGG_TX_STATE_TX_ON_AIR_DROP        0x0010\n#define IWX_AGG_TX_STATE_LAST_SENT_TRY_CNT    0x0020\n#define IWX_AGG_TX_STATE_LAST_SENT_BT_KILL    0x0040\n#define IWX_AGG_TX_STATE_SCD_QUERY        0x0080\n#define IWX_AGG_TX_STATE_TEST_BAD_CRC32        0x0100\n#define IWX_AGG_TX_STATE_RESPONSE        0x01ff\n#define IWX_AGG_TX_STATE_DUMP_TX        0x0200\n#define IWX_AGG_TX_STATE_DELAY_TX        0x0400\n#define IWX_AGG_TX_STATE_TRY_CNT_POS    12\n#define IWX_AGG_TX_STATE_TRY_CNT_MSK    (0xf << IWX_AGG_TX_STATE_TRY_CNT_POS)\n\n#define IWX_AGG_TX_STATE_LAST_SENT_MSK  (IWX_AGG_TX_STATE_LAST_SENT_TTL| \\\n                     IWX_AGG_TX_STATE_LAST_SENT_TRY_CNT| \\\n                     IWX_AGG_TX_STATE_LAST_SENT_BT_KILL)\n\n/*\n * The mask below describes a status where we are absolutely sure that the MPDU\n * wasn't sent. For BA/Underrun we cannot be that sure. All we know that we've\n * written the bytes to the TXE, but we know nothing about what the DSP did.\n */\n#define IWX_AGG_TX_STAT_FRAME_NOT_SENT (IWX_AGG_TX_STATE_FEW_BYTES | \\\n                    IWX_AGG_TX_STATE_ABORT | \\\n                    IWX_AGG_TX_STATE_SCD_QUERY)\n\n/*\n * IWX_REPLY_TX = 0x1c (response)\n *\n * This response may be in one of two slightly different formats, indicated\n * by the frame_count field:\n *\n * 1)    No aggregation (frame_count == 1).  This reports Tx results for a single\n *    frame. Multiple attempts, at various bit rates, may have been made for\n *    this frame.\n *\n * 2)    Aggregation (frame_count > 1).  This reports Tx results for two or more\n *    frames that used block-acknowledge.  All frames were transmitted at\n *    same rate. Rate scaling may have been used if first frame in this new\n *    agg block failed in previous agg block(s).\n *\n *    Note that, for aggregation, ACK (block-ack) status is not delivered\n *    here; block-ack has not been received by the time the device records\n *    this status.\n *    This status relates to reasons the tx might have been blocked or aborted\n *    within the device, rather than whether it was received successfully by\n *    the destination station.\n */\n\n/**\n * struct iwx_agg_tx_status - per packet TX aggregation status\n * @status: enum iwx_tx_agg_status\n * @sequence: Sequence # for this frame's Tx cmd (not SSN!)\n */\nstruct iwx_agg_tx_status {\n    uint16_t status;\n    uint16_t sequence;\n} __packed;\n\n/*\n * definitions for initial rate index field\n * bits [3:0] initial rate index\n * bits [6:4] rate table color, used for the initial rate\n * bit-7 invalid rate indication\n */\n#define IWX_TX_RES_INIT_RATE_INDEX_MSK 0x0f\n#define IWX_TX_RES_RATE_TABLE_COLOR_MSK 0x70\n#define IWX_TX_RES_INV_RATE_INDEX_MSK 0x80\n\n#define IWX_TX_RES_GET_TID(_ra_tid) ((_ra_tid) & 0x0f)\n#define IWX_TX_RES_GET_RA(_ra_tid) ((_ra_tid) >> 4)\n\n/**\n * struct iwx_tx_resp_v3 - notifies that fw is TXing a packet\n * ( IWX_REPLY_TX = 0x1c )\n * @frame_count: 1 no aggregation, >1 aggregation\n * @bt_kill_count: num of times blocked by bluetooth (unused for agg)\n * @failure_rts: num of failures due to unsuccessful RTS\n * @failure_frame: num failures due to no ACK (unused for agg)\n * @initial_rate: for non-agg: rate of the successful Tx. For agg: rate of the\n *    Tx of all the batch. IWX_RATE_MCS_*\n * @wireless_media_time: for non-agg: RTS + CTS + frame tx attempts time + ACK.\n *    for agg: RTS + CTS + aggregation tx time + block-ack time.\n *    in usec.\n * @pa_status: tx power info\n * @pa_integ_res_a: tx power info\n * @pa_integ_res_b: tx power info\n * @pa_integ_res_c: tx power info\n * @measurement_req_id: tx power info\n * @tfd_info: TFD information set by the FH\n * @seq_ctl: sequence control from the Tx cmd\n * @byte_cnt: byte count from the Tx cmd\n * @tlc_info: TLC rate info\n * @ra_tid: bits [3:0] = ra, bits [7:4] = tid\n * @frame_ctrl: frame control\n * @status: for non-agg:  frame status IWX_TX_STATUS_*\n *    for agg: status of 1st frame, IWX_AGG_TX_STATE_*; other frame status fields\n *    follow this one, up to frame_count.\n *\n * After the array of statuses comes the SSN of the SCD. Look at\n * %iwx_get_scd_ssn for more details.\n */\nstruct iwx_tx_resp_v3 {\n    uint8_t frame_count;\n    uint8_t bt_kill_count;\n    uint8_t failure_rts;\n    uint8_t failure_frame;\n    uint32_t initial_rate;\n    uint16_t wireless_media_time;\n\n    uint8_t pa_status;\n    uint8_t pa_integ_res_a[3];\n    uint8_t pa_integ_res_b[3];\n    uint8_t pa_integ_res_c[3];\n    uint16_t measurement_req_id;\n    uint16_t reserved;\n\n    uint32_t tfd_info;\n    uint16_t seq_ctl;\n    uint16_t byte_cnt;\n    uint8_t tlc_info;\n    uint8_t ra_tid;\n    uint16_t frame_ctrl;\n\n    struct iwx_agg_tx_status status;\n} __packed; /* IWX_TX_RSP_API_S_VER_3 */\n\n/**\n * struct iwx_tx_resp - notifies that fw is TXing a packet\n * ( REPLY_TX = 0x1c )\n * @frame_count: 1 no aggregation, >1 aggregation\n * @bt_kill_count: num of times blocked by bluetooth (unused for agg)\n * @failure_rts: num of failures due to unsuccessful RTS\n * @failure_frame: num failures due to no ACK (unused for agg)\n * @initial_rate: for non-agg: rate of the successful Tx. For agg: rate of the\n *    Tx of all the batch. RATE_MCS_*\n * @wireless_media_time: for non-agg: RTS + CTS + frame tx attempts time + ACK.\n *    for agg: RTS + CTS + aggregation tx time + block-ack time.\n *    in usec.\n * @pa_status: tx power info\n * @pa_integ_res_a: tx power info\n * @pa_integ_res_b: tx power info\n * @pa_integ_res_c: tx power info\n * @measurement_req_id: tx power info\n * @reduced_tpc: transmit power reduction used\n * @reserved: reserved\n * @tfd_info: TFD information set by the FH\n * @seq_ctl: sequence control from the Tx cmd\n * @byte_cnt: byte count from the Tx cmd\n * @tlc_info: TLC rate info\n * @ra_tid: bits [3:0] = ra, bits [7:4] = tid\n * @frame_ctrl: frame control\n * @tx_queue: TX queue for this response\n * @reserved2: reserved for padding/alignment\n * @status: for non-agg:  frame status TX_STATUS_*\n *    For version 6 TX response isn't received for aggregation at all.\n *\n * After the array of statuses comes the SSN of the SCD. Look at\n * %iwl_mvm_get_scd_ssn for more details.\n */\nstruct iwx_tx_resp {\n    uint8_t frame_count;\n    uint8_t bt_kill_count;\n    uint8_t failure_rts;\n    uint8_t failure_frame;\n    uint32_t initial_rate;\n    uint16_t wireless_media_time;\n\n    uint8_t pa_status;\n    uint8_t pa_integ_res_a[3];\n    uint8_t pa_integ_res_b[3];\n    uint8_t pa_integ_res_c[3];\n    uint16_t measurement_req_id;\n    uint8_t reduced_tpc;\n    uint8_t reserved;\n\n    uint32_t tfd_info;\n    uint16_t seq_ctl;\n    uint16_t byte_cnt;\n    uint8_t tlc_info;\n    uint8_t ra_tid;\n    uint16_t frame_ctrl;\n    uint16_t tx_queue;\n    uint16_t reserved2;\n    struct iwx_agg_tx_status status;\n} __packed; /* TX_RSP_API_S_VER_6 */\n\n/**\n * struct iwx_compressed_ba_tfd - progress of a TFD queue\n * @q_num: TFD queue number\n * @tfd_index: Index of first un-acked frame in the  TFD queue\n * @scd_queue: For debug only - the physical queue the TFD queue is bound to\n * @tid: TID of the queue (0-7)\n * @reserved: reserved for alignment\n */\nstruct iwx_compressed_ba_tfd {\n    __le16 q_num;\n    __le16 tfd_index;\n    u8 scd_queue;\n    u8 tid;\n    u8 reserved[2];\n} __packed; /* COMPRESSED_BA_TFD_API_S_VER_1 */\n\n/**\n * struct iwx_compressed_ba_ratid - progress of a RA TID queue\n * @q_num: RA TID queue number\n * @tid: TID of the queue\n * @ssn: BA window current SSN\n */\nstruct iwx_compressed_ba_ratid {\n    u8 q_num;\n    u8 tid;\n    __le16 ssn;\n} __packed; /* COMPRESSED_BA_RATID_API_S_VER_1 */\n\n/*\n * enum iwx_ba_resp_flags - TX aggregation status\n * @IWX_BA_RESP_TX_AGG: generated due to BA\n * @IWX_BA_RESP_TX_BAR: generated due to BA after BAR\n * @IWX_BA_RESP_TX_AGG_FAIL: aggregation didn't receive BA\n * @IWX_BA_RESP_TX_UNDERRUN: aggregation got underrun\n * @IWX_BA_RESP_TX_BT_KILL: aggregation got BT-kill\n * @IWX_BA_RESP_TX_DSP_TIMEOUT: aggregation didn't finish within the\n *    expected time\n */\nenum iwx_ba_resp_flags {\n    IWX_BA_RESP_TX_AGG,\n    IWX_BA_RESP_TX_BAR,\n    IWX_BA_RESP_TX_AGG_FAIL,\n    IWX_BA_RESP_TX_UNDERRUN,\n    IWX_BA_RESP_TX_BT_KILL,\n    IWX_BA_RESP_TX_DSP_TIMEOUT\n};\n\n/**\n * struct iwl_mvm_compressed_ba_notif - notifies about reception of BA\n * ( BA_NOTIF = 0xc5 )\n * @flags: status flag, see the &iwl_mvm_ba_resp_flags\n * @sta_id: Index of recipient (BA-sending) station in fw's station table\n * @reduced_txp: power reduced according to TPC. This is the actual value and\n *    not a copy from the LQ command. Thus, if not the first rate was used\n *    for Tx-ing then this value will be set to 0 by FW.\n * @tlc_rate_info: TLC rate info, initial rate index, TLC table color\n * @retry_cnt: retry count\n * @query_byte_cnt: SCD query byte count\n * @query_frame_cnt: SCD query frame count\n * @txed: number of frames sent in the aggregation (all-TIDs)\n * @done: number of frames that were Acked by the BA (all-TIDs)\n * @reserved: reserved (for alignment)\n * @wireless_time: Wireless-media time\n * @tx_rate: the rate the aggregation was sent at\n * @tfd_cnt: number of TFD-Q elements\n * @ra_tid_cnt: number of RATID-Q elements\n * @tfd: array of TFD queue status updates. See &iwl_mvm_compressed_ba_tfd\n *    for details. Length in @tfd_cnt.\n * @ra_tid: array of RA-TID queue status updates. For debug purposes only. See\n *    &iwl_mvm_compressed_ba_ratid for more details. Length in @ra_tid_cnt.\n */\nstruct iwx_compressed_ba_notif {\n    __le32 flags;\n    u8 sta_id;\n    u8 reduced_txp;\n    u8 tlc_rate_info;\n    u8 retry_cnt;\n    __le32 query_byte_cnt;\n    __le16 query_frame_cnt;\n    __le16 txed;\n    __le16 done;\n    __le16 reserved;\n    __le32 wireless_time;\n    __le32 tx_rate;\n    __le16 tfd_cnt;\n    __le16 ra_tid_cnt;\n    struct iwx_compressed_ba_ratid ra_tid[0];\n    struct iwx_compressed_ba_tfd tfd[];\n} __packed; /* COMPRESSED_BA_RES_API_S_VER_4 */\n\nstruct iwx_beacon_notif {\n    struct iwx_tx_resp_v3 beacon_notify_hdr;\n    uint64_t tsf;\n    uint32_t ibss_mgr_status;\n} __packed;\n\n/**\n * dump (flush) control flags\n * @IWX_DUMP_TX_FIFO_FLUSH: Dump MSDUs until the FIFO is empty\n *    and the TFD queues are empty.\n */\n#define IWX_DUMP_TX_FIFO_FLUSH    (1 << 1)\n\n/**\n * struct iwx_tx_path_flush_cmd -- queue/FIFO flush command\n * @queues_ctl: bitmap of queues to flush\n * @flush_ctl: control flags\n * @reserved: reserved\n */\nstruct iwx_tx_path_flush_cmd_v1 {\n    uint32_t queues_ctl;\n    uint16_t flush_ctl;\n    uint16_t reserved;\n} __packed; /* IWX_TX_PATH_FLUSH_CMD_API_S_VER_1 */\n\n/**\n * struct iwl_tx_path_flush_cmd -- queue/FIFO flush command\n * @sta_id: station ID to flush\n * @tid_mask: TID mask to flush\n * @reserved: reserved\n */\nstruct iwx_tx_path_flush_cmd {\n    uint32_t sta_id;\n    uint16_t tid_mask;\n    uint16_t reserved;\n} __packed; /* TX_PATH_FLUSH_CMD_API_S_VER_2 */\n\n#define IWX_TX_FLUSH_QUEUE_RSP 16\n\n/**\n * struct iwx_flush_queue_info - virtual flush queue info\n * @queue_num: virtual queue id\n * @read_before_flush: read pointer before flush\n * @read_after_flush: read pointer after flush\n */\nstruct iwx_flush_queue_info {\n    uint16_t tid;\n    uint16_t queue_num;\n    uint16_t read_before_flush;\n    uint16_t read_after_flush;\n} __packed; /* TFDQ_FLUSH_INFO_API_S_VER_1 */\n\n/**\n * struct iwx_tx_path_flush_cmd_rsp -- queue/FIFO flush command response\n * @num_flushed_queues: number of queues in queues array\n * @queues: all flushed queues\n */\nstruct iwx_tx_path_flush_cmd_rsp {\n    uint16_t sta_id;\n    uint16_t num_flushed_queues;\n    struct iwx_flush_queue_info queues[IWX_TX_FLUSH_QUEUE_RSP];\n} __packed; /* TX_PATH_FLUSH_CMD_RSP_API_S_VER_1 */\n\n/**\n * iwx_get_scd_ssn - returns the SSN of the SCD\n * @tx_resp: the Tx response from the fw (agg or non-agg)\n *\n * When the fw sends an AMPDU, it fetches the MPDUs one after the other. Since\n * it can't know that everything will go well until the end of the AMPDU, it\n * can't know in advance the number of MPDUs that will be sent in the current\n * batch. This is why it writes the agg Tx response while it fetches the MPDUs.\n * Hence, it can't know in advance what the SSN of the SCD will be at the end\n * of the batch. This is why the SSN of the SCD is written at the end of the\n * whole struct at a variable offset. This function knows how to cope with the\n * variable offset and returns the SSN of the SCD.\n */\nstatic inline uint32_t iwx_get_scd_ssn(struct iwx_tx_resp *tx_resp)\n{\n    return le32_to_cpup((uint32_t *)&tx_resp->status +\n                tx_resp->frame_count) & 0xfff;\n}\n\n/**\n * struct iwx_scd_txq_cfg_cmd - New txq hw scheduler config command\n * @token:\n * @sta_id: station id\n * @tid:\n * @scd_queue: scheduler queue to confiug\n * @enable: 1 queue enable, 0 queue disable\n * @aggregate: 1 aggregated queue, 0 otherwise\n * @tx_fifo: %enum iwx_tx_fifo\n * @window: BA window size\n * @ssn: SSN for the BA agreement\n */\nstruct iwx_scd_txq_cfg_cmd {\n    uint8_t token;\n    uint8_t sta_id;\n    uint8_t tid;\n    uint8_t scd_queue;\n    uint8_t enable;\n    uint8_t aggregate;\n    uint8_t tx_fifo;\n    uint8_t window;\n    uint16_t ssn;\n    uint16_t reserved;\n} __packed; /* SCD_QUEUE_CFG_CMD_API_S_VER_1 */\n\n/**\n * struct iwx_scd_txq_cfg_rsp\n * @token: taken from the command\n * @sta_id: station id from the command\n * @tid: tid from the command\n * @scd_queue: scd_queue from the command\n */\nstruct iwx_scd_txq_cfg_rsp {\n    uint8_t token;\n    uint8_t sta_id;\n    uint8_t tid;\n    uint8_t scd_queue;\n} __packed; /* SCD_QUEUE_CFG_RSP_API_S_VER_1 */\n\n\n/* Scan Commands, Responses, Notifications */\n\n/* Max number of IEs for direct SSID scans in a command */\n#define IWX_PROBE_OPTION_MAX        20\n\n#define IWX_SCAN_SHORT_SSID_MAX_SIZE        8\n#define IWX_SCAN_BSSID_MAX_SIZE             16\n\n/**\n * struct iwx_ssid_ie - directed scan network information element\n *\n * Up to 20 of these may appear in IWX_REPLY_SCAN_CMD,\n * selected by \"type\" bit field in struct iwx_scan_channel;\n * each channel may select different ssids from among the 20 entries.\n * SSID IEs get transmitted in reverse order of entry.\n */\nstruct iwx_ssid_ie {\n    uint8_t id;\n    uint8_t len;\n    uint8_t ssid[IEEE80211_NWID_LEN];\n} __packed; /* IWX_SCAN_DIRECT_SSID_IE_API_S_VER_1 */\n\n/* scan offload */\n#define IWX_SCAN_MAX_BLACKLIST_LEN    64\n#define IWX_SCAN_SHORT_BLACKLIST_LEN    16\n#define IWX_SCAN_MAX_PROFILES        11\n#define IWX_SCAN_OFFLOAD_PROBE_REQ_SIZE    512\n\n/* Default watchdog (in MS) for scheduled scan iteration */\n#define IWX_SCHED_SCAN_WATCHDOG cpu_to_le16(15000)\n\n#define IWX_GOOD_CRC_TH_DEFAULT cpu_to_le16(1)\n#define IWX_CAN_ABORT_STATUS 1\n\n#define IWX_FULL_SCAN_MULTIPLIER 5\n#define IWX_FAST_SCHED_SCAN_ITERATIONS 3\n#define IWX_MAX_SCHED_SCAN_PLANS 2\n\n/**\n * iwx_scan_schedule_lmac - schedule of scan offload\n * @delay:        delay between iterations, in seconds.\n * @iterations:        num of scan iterations\n * @full_scan_mul:    number of partial scans before each full scan\n */\nstruct iwx_scan_schedule_lmac {\n    uint16_t delay;\n    uint8_t iterations;\n    uint8_t full_scan_mul;\n} __packed; /* SCAN_SCHEDULE_API_S */\n\n/**\n * iwx_scan_req_tx_cmd - SCAN_REQ_TX_CMD_API_S\n * @tx_flags: combination of TX_CMD_FLG_*\n * @rate_n_flags: rate for *all* Tx attempts, if TX_CMD_FLG_STA_RATE_MSK is\n *    cleared. Combination of RATE_MCS_*\n * @sta_id: index of destination station in FW station table\n * @reserved: for alignment and future use\n */\nstruct iwx_scan_req_tx_cmd {\n    uint32_t tx_flags;\n    uint32_t rate_n_flags;\n    uint8_t sta_id;\n    uint8_t reserved[3];\n} __packed;\n\n#define IWX_UNIFIED_SCAN_CHANNEL_FULL        (1 << 27)\n#define IWX_UNIFIED_SCAN_CHANNEL_PARTIAL    (1 << 28)\n\n/**\n * iwx_scan_channel_cfg_lmac - SCAN_CHANNEL_CFG_S_VER2\n * @flags:        bits 1-20: directed scan to i'th ssid\n *            other bits &enum iwx_scan_channel_flags_lmac\n * @channel_number:    channel number 1-13 etc\n * @iter_count:        scan iteration on this channel\n * @iter_interval:    interval in seconds between iterations on one channel\n */\nstruct iwx_scan_channel_cfg_lmac {\n    uint32_t flags;\n    uint16_t channel_num;\n    uint16_t iter_count;\n    uint32_t iter_interval;\n} __packed;\n\n/*\n * iwx_scan_probe_segment - PROBE_SEGMENT_API_S_VER_1\n * @offset: offset in the data block\n * @len: length of the segment\n */\nstruct iwx_scan_probe_segment {\n    uint16_t offset;\n    uint16_t len;\n} __packed;\n\n/* iwx_scan_probe_req - PROBE_REQUEST_FRAME_API_S_VER_2\n * @mac_header: first (and common) part of the probe\n * @band_data: band specific data\n * @common_data: last (and common) part of the probe\n * @buf: raw data block\n */\nstruct iwx_scan_probe_req_v1 {\n    struct iwx_scan_probe_segment mac_header;\n    struct iwx_scan_probe_segment band_data[2];\n    struct iwx_scan_probe_segment common_data;\n    uint8_t buf[IWX_SCAN_OFFLOAD_PROBE_REQ_SIZE];\n} __packed;\n\n/* iwl_scan_probe_req - PROBE_REQUEST_FRAME_API_S_VER_v2\n * @mac_header: first (and common) part of the probe\n * @band_data: band specific data\n * @common_data: last (and common) part of the probe\n * @buf: raw data block\n */\nstruct iwx_scan_probe_req {\n    struct iwx_scan_probe_segment mac_header;\n    struct iwx_scan_probe_segment band_data[3];\n    struct iwx_scan_probe_segment common_data;\n    uint8_t buf[IWX_SCAN_OFFLOAD_PROBE_REQ_SIZE];\n} __packed;\n\n\n#define IWX_SCAN_CHANNEL_FLAG_EBS        (1 << 0)\n#define IWX_SCAN_CHANNEL_FLAG_EBS_ACCURATE    (1 << 1)\n#define IWX_SCAN_CHANNEL_FLAG_CACHE_ADD        (1 << 2)\n#define IWX_SCAN_CHANNEL_FLAG_EBS_FRAG         (1 << 3)\n#define IWX_SCAN_CHANNEL_FLAG_FORCE_EBS          (1 << 4)\n#define IWX_SCAN_CHANNEL_FLAG_ENABLE_CHAN_ORDER  (1 << 5)\n#define IWX_SCAN_CHANNEL_FLAG_6G_PSC_NO_FILTER   (1 << 6)\n\n/* iwx_scan_channel_opt - CHANNEL_OPTIMIZATION_API_S\n * @flags: enum iwx_scan_channel_flags\n * @non_ebs_ratio: defines the ratio of number of scan iterations where EBS is\n *    involved.\n *    1 - EBS is disabled.\n *    2 - every second scan will be full scan(and so on).\n */\nstruct iwx_scan_channel_opt {\n    uint16_t flags;\n    uint16_t non_ebs_ratio;\n} __packed;\n\n#define IWX_SCAN_PRIORITY_LOW        0\n#define IWX_SCAN_PRIORITY_MEDIUM    1\n#define IWX_SCAN_PRIORITY_HIGH        2\n\n#define IWX_SCAN_PRIORITY_EXT_0_LOWEST  0\n#define IWX_SCAN_PRIORITY_EXT_1     1\n#define IWX_SCAN_PRIORITY_EXT_2     2\n#define IWX_SCAN_PRIORITY_EXT_3     3\n#define IWX_SCAN_PRIORITY_EXT_4     4\n#define IWX_SCAN_PRIORITY_EXT_5     5\n#define IWX_SCAN_PRIORITY_EXT_6     6\n#define IWX_SCAN_PRIORITY_EXT_7_HIGHEST 7\n\n/**\n * iwx_scan_offload_complete - PERIODIC_SCAN_COMPLETE_NTF_API_S_VER_2\n * @last_schedule_line: last schedule line executed (fast or regular)\n * @last_schedule_iteration: last scan iteration executed before scan abort\n * @status: enum iwx_scan_offload_complete_status\n * @ebs_status: EBS success status &enum iwx_scan_ebs_status\n * @time_after_last_iter; time in seconds elapsed after last iteration\n */\nstruct iwx_periodic_scan_complete {\n    uint8_t last_schedule_line;\n    uint8_t last_schedule_iteration;\n    uint8_t status;\n    uint8_t ebs_status;\n    uint32_t time_after_last_iter;\n    uint32_t reserved;\n} __packed;\n\n/**\n * struct iwx_scan_results_notif - scan results for one channel -\n *      SCAN_RESULT_NTF_API_S_VER_3\n * @channel: which channel the results are from\n * @band: 0 for 5.2 GHz, 1 for 2.4 GHz\n * @probe_status: IWX_SCAN_PROBE_STATUS_*, indicates success of probe request\n * @num_probe_not_sent: # of request that weren't sent due to not enough time\n * @duration: duration spent in channel, in usecs\n */\nstruct iwx_scan_results_notif {\n    uint8_t channel;\n    uint8_t band;\n    uint8_t probe_status;\n    uint8_t num_probe_not_sent;\n    uint32_t duration;\n} __packed;\n\n#define IWX_SCAN_CLIENT_SCHED_SCAN        (1 << 0)\n#define IWX_SCAN_CLIENT_NETDETECT        (1 << 1)\n#define IWX_SCAN_CLIENT_ASSET_TRACKING        (1 << 2)\n\n/**\n * iwx_scan_offload_blacklist - IWX_SCAN_OFFLOAD_BLACKLIST_S\n * @ssid:        MAC address to filter out\n * @reported_rssi:    AP rssi reported to the host\n * @client_bitmap: clients ignore this entry  - enum scan_framework_client\n */\nstruct iwx_scan_offload_blacklist {\n    uint8_t ssid[ETHER_ADDR_LEN];\n    uint8_t reported_rssi;\n    uint8_t client_bitmap;\n} __packed;\n\n#define IWX_NETWORK_TYPE_BSS    1\n#define IWX_NETWORK_TYPE_IBSS    2\n#define IWX_NETWORK_TYPE_ANY    3\n\n#define IWX_SCAN_OFFLOAD_SELECT_2_4    0x4\n#define IWX_SCAN_OFFLOAD_SELECT_5_2    0x8\n#define IWX_SCAN_OFFLOAD_SELECT_ANY    0xc\n\n/**\n * iwx_scan_offload_profile - IWX_SCAN_OFFLOAD_PROFILE_S\n * @ssid_index:        index to ssid list in fixed part\n * @unicast_cipher:    encryption olgorithm to match - bitmap\n * @aut_alg:        authentication olgorithm to match - bitmap\n * @network_type:    enum iwx_scan_offload_network_type\n * @band_selection:    enum iwx_scan_offload_band_selection\n * @client_bitmap:    clients waiting for match - enum scan_framework_client\n */\nstruct iwx_scan_offload_profile {\n    uint8_t ssid_index;\n    uint8_t unicast_cipher;\n    uint8_t auth_alg;\n    uint8_t network_type;\n    uint8_t band_selection;\n    uint8_t client_bitmap;\n    uint8_t reserved[2];\n} __packed;\n\n/**\n * iwx_scan_offload_profile_cfg - IWX_SCAN_OFFLOAD_PROFILES_CFG_API_S_VER_1\n * @blaclist:        AP list to filter off from scan results\n * @profiles:        profiles to search for match\n * @blacklist_len:    length of blacklist\n * @num_profiles:    num of profiles in the list\n * @match_notify:    clients waiting for match found notification\n * @pass_match:        clients waiting for the results\n * @active_clients:    active clients bitmap - enum scan_framework_client\n * @any_beacon_notify:    clients waiting for match notification without match\n */\nstruct iwx_scan_offload_profile_cfg {\n    struct iwx_scan_offload_profile profiles[IWX_SCAN_MAX_PROFILES];\n    uint8_t blacklist_len;\n    uint8_t num_profiles;\n    uint8_t match_notify;\n    uint8_t pass_match;\n    uint8_t active_clients;\n    uint8_t any_beacon_notify;\n    uint8_t reserved[2];\n} __packed;\n\n#define IWX_SCAN_OFFLOAD_COMPLETED    1\n#define IWX_SCAN_OFFLOAD_ABORTED    2\n\n/* UMAC Scan API */\n\n#define IWX_SCAN_CONFIG_FLAG_ACTIVATE            (1 << 0)\n#define IWX_SCAN_CONFIG_FLAG_DEACTIVATE            (1 << 1)\n#define IWX_SCAN_CONFIG_FLAG_FORBID_CHUB_REQS        (1 << 2)\n#define IWX_SCAN_CONFIG_FLAG_ALLOW_CHUB_REQS        (1 << 3)\n#define IWX_SCAN_CONFIG_FLAG_SET_TX_CHAINS        (1 << 8)\n#define IWX_SCAN_CONFIG_FLAG_SET_RX_CHAINS        (1 << 9)\n#define IWX_SCAN_CONFIG_FLAG_SET_AUX_STA_ID        (1 << 10)\n#define IWX_SCAN_CONFIG_FLAG_SET_ALL_TIMES        (1 << 11)\n#define IWX_SCAN_CONFIG_FLAG_SET_EFFECTIVE_TIMES    (1 << 12)\n#define IWX_SCAN_CONFIG_FLAG_SET_CHANNEL_FLAGS        (1 << 13)\n#define IWX_SCAN_CONFIG_FLAG_SET_LEGACY_RATES        (1 << 14)\n#define IWX_SCAN_CONFIG_FLAG_SET_MAC_ADDR        (1 << 15)\n#define IWX_SCAN_CONFIG_FLAG_SET_FRAGMENTED        (1 << 16)\n#define IWX_SCAN_CONFIG_FLAG_CLEAR_FRAGMENTED        (1 << 17)\n#define IWX_SCAN_CONFIG_FLAG_SET_CAM_MODE        (1 << 18)\n#define IWX_SCAN_CONFIG_FLAG_CLEAR_CAM_MODE        (1 << 19)\n#define IWX_SCAN_CONFIG_FLAG_SET_PROMISC_MODE        (1 << 20)\n#define IWX_SCAN_CONFIG_FLAG_CLEAR_PROMISC_MODE        (1 << 21)\n\n/* Bits 26-31 are for num of channels in channel_array */\n#define IWX_SCAN_CONFIG_N_CHANNELS(n) ((n) << 26)\n\n/* OFDM basic rates */\n#define IWX_SCAN_CONFIG_RATE_6M        (1 << 0)\n#define IWX_SCAN_CONFIG_RATE_9M        (1 << 1)\n#define IWX_SCAN_CONFIG_RATE_12M    (1 << 2)\n#define IWX_SCAN_CONFIG_RATE_18M    (1 << 3)\n#define IWX_SCAN_CONFIG_RATE_24M    (1 << 4)\n#define IWX_SCAN_CONFIG_RATE_36M    (1 << 5)\n#define IWX_SCAN_CONFIG_RATE_48M    (1 << 6)\n#define IWX_SCAN_CONFIG_RATE_54M    (1 << 7)\n/* CCK basic rates */\n#define IWX_SCAN_CONFIG_RATE_1M        (1 << 8)\n#define IWX_SCAN_CONFIG_RATE_2M        (1 << 9)\n#define IWX_SCAN_CONFIG_RATE_5M        (1 << 10)\n#define IWX_SCAN_CONFIG_RATE_11M    (1 << 11)\n\n/* Bits 16-27 are for supported rates */\n#define IWX_SCAN_CONFIG_SUPPORTED_RATE(rate)    ((rate) << 16)\n\n#define IWX_CHANNEL_FLAG_EBS                (1 << 0)\n#define IWX_CHANNEL_FLAG_ACCURATE_EBS            (1 << 1)\n#define IWX_CHANNEL_FLAG_EBS_ADD            (1 << 2)\n#define IWX_CHANNEL_FLAG_PRE_SCAN_PASSIVE2ACTIVE    (1 << 3)\n\n/**\n * struct iwx_scan_dwell\n * @active:        default dwell time for active scan\n * @passive:        default dwell time for passive scan\n * @fragmented:        default dwell time for fragmented scan\n * @extended:        default dwell time for channels 1, 6 and 11\n */\nstruct iwx_scan_dwell {\n    uint8_t active;\n    uint8_t passive;\n    uint8_t fragmented;\n    uint8_t extended;\n} __packed;\n\n\n#define IWX_SCAN_TWO_LMACS 2\n#define IWX_SCAN_LB_LMAC_IDX 0 /* low-band */\n#define IWX_SCAN_HB_LMAC_IDX 1 /* high-band */\n\n/**\n * struct iwx_scan_config\n * @flags:            enum scan_config_flags\n * @tx_chains:            valid_tx antenna - ANT_* definitions\n * @rx_chains:            valid_rx antenna - ANT_* definitions\n * @legacy_rates:        default legacy rates - enum scan_config_rates\n * @out_of_channel_time:    default max out of serving channel time\n * @suspend_time:        default max suspend time\n * @dwell_active:        default dwell time for active scan\n * @dwell_passive:        default dwell time for passive scan\n * @dwell_fragmented:        default dwell time for fragmented scan\n * @dwell_extended:        default dwell time for channels 1, 6 and 11\n * @mac_addr:            default mac address to be used in probes\n * @bcast_sta_id:        the index of the station in the fw\n * @channel_flags:        default channel flags - enum iwx_channel_flags\n *                scan_config_channel_flag\n * @channel_array:        default supported channels\n */\nstruct iwx_scan_config_v2 {\n    uint32_t flags;\n    uint32_t tx_chains;\n    uint32_t rx_chains;\n    uint32_t legacy_rates;\n    uint32_t out_of_channel_time[IWX_SCAN_TWO_LMACS];\n    uint32_t suspend_time[IWX_SCAN_TWO_LMACS];\n    struct iwx_scan_dwell dwell;\n    uint8_t mac_addr[ETHER_ADDR_LEN];\n    uint8_t bcast_sta_id;\n    uint8_t channel_flags;\n    uint8_t channel_array[];\n} __packed; /* SCAN_CONFIG_DB_CMD_API_S_2 */\n\n/**\n * struct iwx_scan_config\n * @enable_cam_mode: whether to enable CAM mode.\n * @enable_promiscouos_mode: whether to enable promiscouos mode\n * @bcast_sta_id: the index of the station in the fw. Deprecated starting with\n *     API version 5.\n * @reserved: reserved\n * @tx_chains: valid_tx antenna - ANT_* definitions\n * @rx_chains: valid_rx antenna - ANT_* definitions\n */\nstruct iwx_scan_config {\n    uint8_t enable_cam_mode;\n    uint8_t enable_promiscouos_mode;\n    uint8_t bcast_sta_id;\n    uint8_t reserved;\n    uint32_t tx_chains;\n    uint32_t rx_chains;\n} __packed; /* SCAN_CONFIG_DB_CMD_API_S_5 */\n\n/**\n * iwx_umac_scan_flags\n *@IWX_UMAC_SCAN_FLAG_PREEMPTIVE: scan process triggered by this scan request\n *    can be preempted by other scan requests with higher priority.\n *    The low priority scan will be resumed when the higher proirity scan is\n *    completed.\n *@IWX_UMAC_SCAN_FLAG_START_NOTIF: notification will be sent to the driver\n *    when scan starts.\n */\n#define IWX_UMAC_SCAN_FLAG_PREEMPTIVE        (1 << 0)\n#define IWX_UMAC_SCAN_FLAG_START_NOTIF        (1 << 1)\n\n#define IWX_UMAC_SCAN_UID_TYPE_OFFSET        0\n#define IWX_UMAC_SCAN_UID_SEQ_OFFSET        8\n\n#define IWX_UMAC_SCAN_GEN_FLAGS_PERIODIC    (1 << 0)\n#define IWX_UMAC_SCAN_GEN_FLAGS_OVER_BT        (1 << 1)\n#define IWX_UMAC_SCAN_GEN_FLAGS_PASS_ALL    (1 << 2)\n#define IWX_UMAC_SCAN_GEN_FLAGS_PASSIVE        (1 << 3)\n#define IWX_UMAC_SCAN_GEN_FLAGS_PRE_CONNECT    (1 << 4)\n#define IWX_UMAC_SCAN_GEN_FLAGS_ITER_COMPLETE    (1 << 5)\n#define IWX_UMAC_SCAN_GEN_FLAGS_MULTIPLE_SSID    (1 << 6)\n#define IWX_UMAC_SCAN_GEN_FLAGS_FRAGMENTED    (1 << 7)\n#define IWX_UMAC_SCAN_GEN_FLAGS_RRM_ENABLED    (1 << 8)\n#define IWX_UMAC_SCAN_GEN_FLAGS_MATCH        (1 << 9)\n#define IWX_UMAC_SCAN_GEN_FLAGS_EXTENDED_DWELL    (1 << 10)\n/* Extended dwell is obselete when adaptive dwell is used, making this\n * bit reusable. Hence, probe request defer is used only when adaptive\n * dwell is supported. */\n#define IWX_UMAC_SCAN_GEN_FLAGS_PROB_REQ_DEFER_SUPP    (1 << 10)\n#define IWX_UMAC_SCAN_GEN_FLAGS_LMAC2_FRAGMENTED    (1 << 11)\n#define IWX_UMAC_SCAN_GEN_FLAGS_ADAPTIVE_DWELL        (1 << 13)\n#define IWX_UMAC_SCAN_GEN_FLAGS_MAX_CHNL_TIME        (1 << 14)\n#define IWX_UMAC_SCAN_GEN_FLAGS_PROB_REQ_HIGH_TX_RATE    (1 << 15)\n\n/**\n * UMAC scan general flags #2\n * @IWX_UMAC_SCAN_GEN_FLAGS2_NOTIF_PER_CHNL: Whether to send a complete\n *    notification per channel or not.\n * @IWX_UMAC_SCAN_GEN_FLAGS2_ALLOW_CHNL_REORDER: Whether to allow channel\n *    reorder optimization or not.\n */\n#define IWX_UMAC_SCAN_GEN_FLAGS2_NOTIF_PER_CHNL        (1 << 0)\n#define IWX_UMAC_SCAN_GEN_FLAGS2_ALLOW_CHNL_REORDER    (1 << 1)\n\n/**\n * UMAC scan general flags version 2\n *\n * The FW flags were reordered and hence the driver introduce version 2\n *\n * @IWX_UMAC_SCAN_GEN_FLAGS_V2_PERIODIC: periodic or scheduled\n * @IWX_UMAC_SCAN_GEN_FLAGS_V2_PASS_ALL: pass all probe responses and beacons\n *                                       during scan iterations\n * @IWX_UMAC_SCAN_GEN_FLAGS_V2_NTFY_ITER_COMPLETE: send complete notification\n *      on every iteration instead of only once after the last iteration\n * @IWX_UMAC_SCAN_GEN_FLAGS_V2_FRAGMENTED_LMAC1: fragmented scan LMAC1\n * @IWX_UMAC_SCAN_GEN_FLAGS_V2_FRAGMENTED_LMAC2: fragmented scan LMAC2\n * @IWX_UMAC_SCAN_GEN_FLAGS_V2_MATCH: does this scan check for profile matching\n * @IWX_UMAC_SCAN_GEN_FLAGS_V2_USE_ALL_RX_CHAINS: use all valid chains for RX\n * @IWX_UMAC_SCAN_GEN_FLAGS_V2_ADAPTIVE_DWELL: works with adaptive dwell\n *                                             for active channel\n * @IWX_UMAC_SCAN_GEN_FLAGS_V2_PREEMPTIVE: can be preempted by other requests\n * @IWX_UMAC_SCAN_GEN_FLAGS_V2_NTF_START: send notification of scan start\n * @IWX_UMAC_SCAN_GEN_FLAGS_V2_MULTI_SSID: matching on multiple SSIDs\n * @IWX_UMAC_SCAN_GEN_FLAGS_V2_FORCE_PASSIVE: all the channels scanned\n *                                           as passive\n * @IWX_UMAC_SCAN_GEN_FLAGS_V2_TRIGGER_UHB_SCAN: at the end of 2.4GHz and\n *        5.2Ghz bands scan, trigger scan on 6GHz band to discover\n *        the reported collocated APs\n */\n#define IWX_UMAC_SCAN_GEN_FLAGS_V2_PERIODIC             (1 << 0)\n#define IWX_UMAC_SCAN_GEN_FLAGS_V2_PASS_ALL             (1 << 1)\n#define IWX_UMAC_SCAN_GEN_FLAGS_V2_NTFY_ITER_COMPLETE   (1 << 2)\n#define IWX_UMAC_SCAN_GEN_FLAGS_V2_FRAGMENTED_LMAC1     (1 << 3)\n#define IWX_UMAC_SCAN_GEN_FLAGS_V2_FRAGMENTED_LMAC2     (1 << 4)\n#define IWX_UMAC_SCAN_GEN_FLAGS_V2_MATCH                (1 << 5)\n#define IWX_UMAC_SCAN_GEN_FLAGS_V2_USE_ALL_RX_CHAINS    (1 << 6)\n#define IWX_UMAC_SCAN_GEN_FLAGS_V2_ADAPTIVE_DWELL       (1 << 7)\n#define IWX_UMAC_SCAN_GEN_FLAGS_V2_PREEMPTIVE           (1 << 8)\n#define IWX_UMAC_SCAN_GEN_FLAGS_V2_NTF_START            (1 << 9)\n#define IWX_UMAC_SCAN_GEN_FLAGS_V2_MULTI_SSID           (1 << 10)\n#define IWX_UMAC_SCAN_GEN_FLAGS_V2_FORCE_PASSIVE        (1 << 11)\n#define IWX_UMAC_SCAN_GEN_FLAGS_V2_TRIGGER_UHB_SCAN     (1 << 12)\n\n/**\n * struct iwx_scan_channel_cfg_umac\n * @flags:        bitmap - 0-19:    directed scan to i'th ssid.\n * @channel_num:    channel number 1-13 etc.\n * @iter_count:        repetition count for the channel.\n * @iter_interval:    interval between two scan iterations on one channel.\n */\nstruct iwx_scan_channel_cfg_umac {\n    uint32_t flags;\n    union {\n        struct {\n            uint8_t channel_num;\n            uint8_t iter_count;\n            uint16_t iter_interval;\n        } v1; /* SCAN_CHANNEL_CFG_S_VER1 */\n        struct {\n            uint8_t channel_num;\n            uint8_t band;\n            uint8_t iter_count;\n            uint8_t iter_interval;\n        } v2; /* SCAN_CHANNEL_CFG_S_VER{2,3,4} */\n    };\n} __packed;\n\n/**\n * struct iwx_scan_umac_schedule\n * @interval: interval in seconds between scan iterations\n * @iter_count: num of scan iterations for schedule plan, 0xff for infinite loop\n * @reserved: for alignment and future use\n */\nstruct iwx_scan_umac_schedule {\n    uint16_t interval;\n    uint8_t iter_count;\n    uint8_t reserved;\n} __packed; /* SCAN_SCHED_PARAM_API_S_VER_1 */\n\n/**\n * struct iwx_scan_req_umac_tail - the rest of the UMAC scan request command\n *      parameters following channels configuration array.\n * @schedule: two scheduling plans.\n * @delay: delay in TUs before starting the first scan iteration\n * @reserved: for future use and alignment\n * @preq: probe request with IEs blocks\n * @direct_scan: list of SSIDs for directed active scan\n */\nstruct iwx_scan_req_umac_tail_v1 {\n    /* SCAN_PERIODIC_PARAMS_API_S_VER_1 */\n    struct iwx_scan_umac_schedule schedule[IWX_MAX_SCHED_SCAN_PLANS];\n    uint16_t delay;\n    uint16_t reserved;\n    /* SCAN_PROBE_PARAMS_API_S_VER_1 */\n    struct iwx_scan_probe_req_v1 preq;\n    struct iwx_ssid_ie direct_scan[IWX_PROBE_OPTION_MAX];\n} __packed;\n\n/**\n * struct iwx_scan_req_umac_tail - the rest of the UMAC scan request command\n *      parameters following channels configuration array.\n * @schedule: two scheduling plans.\n * @delay: delay in TUs before starting the first scan iteration\n * @reserved: for future use and alignment\n * @preq: probe request with IEs blocks\n * @direct_scan: list of SSIDs for directed active scan\n */\nstruct iwx_scan_req_umac_tail_v2 {\n    /* SCAN_PERIODIC_PARAMS_API_S_VER_1 */\n    struct iwx_scan_umac_schedule schedule[IWX_MAX_SCHED_SCAN_PLANS];\n    uint16_t delay;\n    uint16_t reserved;\n    /* SCAN_PROBE_PARAMS_API_S_VER_2 */\n    struct iwx_scan_probe_req preq;\n    struct iwx_ssid_ie direct_scan[IWX_PROBE_OPTION_MAX];\n} __packed;\n\n/**\n * struct iwx_scan_umac_chan_param\n * @flags: channel flags &enum iwl_scan_channel_flags\n * @count: num of channels in scan request\n * @reserved: for future use and alignment\n */\nstruct iwx_scan_umac_chan_param {\n    uint8_t flags;\n    uint8_t count;\n    uint16_t reserved;\n} __packed; /* SCAN_CHANNEL_PARAMS_API_S_VER_1 */\n\n#define IWX_SCAN_LB_LMAC_IDX 0\n#define IWX_SCAN_HB_LMAC_IDX 1\n\n/**\n * struct iwx_scan_req_umac\n * @flags: &enum iwl_umac_scan_flags\n * @uid: scan id, &enum iwl_umac_scan_uid_offsets\n * @ooc_priority: out of channel priority - &enum iwl_scan_priority\n * @general_flags: &enum iwl_umac_scan_general_flags\n * @scan_start_mac_id: report the scan start TSF time according to this mac TSF\n * @extended_dwell: dwell time for channels 1, 6 and 11\n * @active_dwell: dwell time for active scan per LMAC\n * @passive_dwell: dwell time for passive scan per LMAC\n * @fragmented_dwell: dwell time for fragmented passive scan\n * @adwell_default_n_aps: for adaptive dwell the default number of APs\n *    per channel\n * @adwell_default_n_aps_social: for adaptive dwell the default\n *    number of APs per social (1,6,11) channel\n * @general_flags2: &enum iwl_umac_scan_general_flags2\n * @adwell_max_budget: for adaptive dwell the maximal budget of TU to be added\n *    to total scan time\n * @max_out_time: max out of serving channel time, per LMAC - for CDB there\n *    are 2 LMACs (high band and low band)\n * @suspend_time: max suspend time, per LMAC - for CDB there are 2 LMACs\n * @scan_priority: scan internal prioritization &enum iwl_scan_priority\n * @num_of_fragments: Number of fragments needed for full coverage per band.\n *    Relevant only for fragmented scan.\n * @channel: &struct iwx_scan_umac_chan_param\n * @reserved: for future use and alignment\n * @reserved3: for future use and alignment\n * @data: &struct iwx_scan_channel_cfg_umac and\n *    &struct iwx_scan_req_umac_tail\n */\nstruct iwx_scan_req_umac {\n    uint32_t flags;\n    uint32_t uid;\n    uint32_t ooc_priority;\n    /* SCAN_GENERAL_PARAMS_API_S_VER_1 */\n    uint16_t general_flags;\n    uint8_t reserved;\n    uint8_t scan_start_mac_id;\n    union {\n        struct {\n            uint8_t extended_dwell;\n            uint8_t active_dwell;\n            uint8_t passive_dwell;\n            uint8_t fragmented_dwell;\n            uint32_t max_out_time;\n            uint32_t suspend_time;\n            uint32_t scan_priority;\n            struct iwx_scan_umac_chan_param channel;\n            uint8_t data[];\n        } v1; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_1 */\n        struct {\n            uint8_t extended_dwell;\n            uint8_t active_dwell;\n            uint8_t passive_dwell;\n            uint8_t fragmented_dwell;\n            uint32_t max_out_time[2];\n            uint32_t suspend_time[2];\n            uint32_t scan_priority;\n            struct iwx_scan_umac_chan_param channel;\n            uint8_t data[];\n        } v6; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_6 */\n        struct {\n            uint8_t active_dwell;\n            uint8_t passive_dwell;\n            uint8_t fragmented_dwell;\n            uint8_t adwell_default_n_aps;\n            uint8_t adwell_default_n_aps_social;\n            uint8_t reserved3;\n            uint16_t adwell_max_budget;\n            uint32_t max_out_time[2];\n            uint32_t suspend_time[2];\n            uint32_t scan_priority;\n            struct iwx_scan_umac_chan_param channel;\n            uint8_t data[];\n        } v7; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_7 */\n        struct {\n            uint8_t active_dwell[2];\n            uint8_t reserved2;\n            uint8_t adwell_default_n_aps;\n            uint8_t adwell_default_n_aps_social;\n            uint8_t general_flags2;\n            uint16_t adwell_max_budget;\n            uint32_t max_out_time[2];\n            uint32_t suspend_time[2];\n            uint32_t scan_priority;\n            uint8_t passive_dwell[2];\n            uint8_t num_of_fragments[2];\n            struct iwx_scan_umac_chan_param channel;\n            uint8_t data[];\n        } v8; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_8 */\n        struct {\n            uint8_t active_dwell[2];\n            uint8_t adwell_default_hb_n_aps;\n            uint8_t adwell_default_lb_n_aps;\n            uint8_t adwell_default_n_aps_social;\n            uint8_t general_flags2;\n            uint16_t adwell_max_budget;\n            uint32_t max_out_time[2];\n            uint32_t suspend_time[2];\n            uint32_t scan_priority;\n            uint8_t passive_dwell[2];\n            uint8_t num_of_fragments[2];\n            struct iwx_scan_umac_chan_param channel;\n            uint8_t data[];\n        } v9; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_9 */\n    };\n} __packed;\n\n#define IWX_SCAN_REQ_UMAC_SIZE_V8 sizeof(struct iwx_scan_req_umac)\n#define IWX_SCAN_REQ_UMAC_SIZE_V7 48\n#define IWX_SCAN_REQ_UMAC_SIZE_V6 44\n#define IWX_SCAN_REQ_UMAC_SIZE_V1 36\n\n/**\n * struct iwx_scan_probe_params_v3\n * @preq: scan probe request params\n * @ssid_num: number of valid SSIDs in direct scan array\n * @short_ssid_num: number of valid short SSIDs in short ssid array\n * @bssid_num: number of valid bssid in bssids array\n * @reserved: reserved\n * @direct_scan: list of ssids\n * @short_ssid: array of short ssids\n * @bssid_array: array of bssids\n */\nstruct iwx_scan_probe_params_v3 {\n    struct iwx_scan_probe_req preq;\n    uint8_t ssid_num;\n    uint8_t short_ssid_num;\n    uint8_t bssid_num;\n    uint8_t reserved;\n    struct iwx_ssid_ie direct_scan[IWX_PROBE_OPTION_MAX];\n    uint32_t short_ssid[IWX_SCAN_SHORT_SSID_MAX_SIZE];\n    uint8_t bssid_array[IWX_SCAN_BSSID_MAX_SIZE][ETHER_ADDR_LEN];\n} __packed; /* SCAN_PROBE_PARAMS_API_S_VER_3 */\n\n/**\n * struct iwx_scan_probe_params_v4\n * @preq: scan probe request params\n * @short_ssid_num: number of valid short SSIDs in short ssid array\n * @bssid_num: number of valid bssid in bssids array\n * @reserved: reserved\n * @direct_scan: list of ssids\n * @short_ssid: array of short ssids\n * @bssid_array: array of bssids\n */\nstruct iwx_scan_probe_params_v4 {\n    struct iwx_scan_probe_req preq;\n    uint8_t short_ssid_num;\n    uint8_t bssid_num;\n    uint16_t reserved;\n    struct iwx_ssid_ie direct_scan[IWX_PROBE_OPTION_MAX];\n    uint32_t short_ssid[IWX_SCAN_SHORT_SSID_MAX_SIZE];\n    u8 bssid_array[IWX_SCAN_BSSID_MAX_SIZE][ETHER_ADDR_LEN];\n} __packed; /* SCAN_PROBE_PARAMS_API_S_VER_4 */\n\n#define IWX_SCAN_MAX_NUM_CHANS_V3 67\n\n/**\n * struct iwx_scan_channel_params_v4\n * @flags: channel flags &enum iwl_scan_channel_flags\n * @count: num of channels in scan request\n * @num_of_aps_override: override the number of APs the FW uses to calculate\n *    dwell time when adaptive dwell is used\n * @reserved: for future use and alignment\n * @channel_config: array of explicit channel configurations\n *                  for 2.4Ghz and 5.2Ghz bands\n * @adwell_ch_override_bitmap: when using adaptive dwell, override the number\n *    of APs value with &num_of_aps_override for the channel.\n *    To cast channel to index, use &iwl_mvm_scan_ch_and_band_to_idx\n */\nstruct iwx_scan_channel_params_v4 {\n    uint8_t flags;\n    uint8_t count;\n    uint8_t num_of_aps_override;\n    uint8_t reserved;\n    struct iwx_scan_channel_cfg_umac channel_config[IWX_SCAN_MAX_NUM_CHANS_V3];\n    uint8_t adwell_ch_override_bitmap[16];\n} __packed; /* SCAN_CHANNEL_PARAMS_API_S_VER_4 also\n           SCAN_CHANNEL_PARAMS_API_S_VER_5 */\n\n/**\n * struct iwx_scan_channel_params_v6\n * @flags: channel flags &enum iwl_scan_channel_flags\n * @count: num of channels in scan request\n * @n_aps_override: override the number of APs the FW uses to calculate dwell\n *    time when adaptive dwell is used.\n *    Channel k will use n_aps_override[i] when BIT(20 + i) is set in\n *    channel_config[k].flags\n * @channel_config: array of explicit channel configurations\n *                  for 2.4Ghz and 5.2Ghz bands\n */\nstruct iwx_scan_channel_params_v6 {\n    uint8_t flags;\n    uint8_t count;\n    uint8_t n_aps_override[2];\n    struct iwx_scan_channel_cfg_umac channel_config[IWX_SCAN_MAX_NUM_CHANS_V3];\n} __packed; /* SCAN_CHANNEL_PARAMS_API_S_VER_6 */\n\n/**\n * struct iwl_scan_general_params_v10\n * @flags: &enum iwl_umac_scan_flags\n * @reserved: reserved for future\n * @scan_start_mac_id: report the scan start TSF time according to this mac TSF\n * @active_dwell: dwell time for active scan per LMAC\n * @adwell_default_2g: adaptive dwell default number of APs\n *                        for 2.4GHz channel\n * @adwell_default_5g: adaptive dwell default number of APs\n *                        for 5GHz channels\n * @adwell_default_social_chn: adaptive dwell default number of\n *                             APs per social channel\n * @reserved1: reserved for future\n * @adwell_max_budget: the maximal number of TUs that adaptive dwell\n *                     can add to the total scan time\n * @max_out_of_time: max out of serving channel time, per LMAC\n * @suspend_time: max suspend time, per LMAC\n * @scan_priority: priority of the request\n * @passive_dwell: continues dwell time for passive channel\n *                 (without adaptive dwell)\n * @num_of_fragments: number of fragments needed for full fragmented\n *                    scan coverage.\n */\nstruct iwx_scan_general_params_v10 {\n    uint16_t flags;\n    uint8_t reserved;\n    uint8_t scan_start_mac_id;\n    uint8_t active_dwell[IWX_SCAN_TWO_LMACS];\n    uint8_t adwell_default_2g;\n    uint8_t adwell_default_5g;\n    uint8_t adwell_default_social_chn;\n    uint8_t reserved1;\n    uint16_t adwell_max_budget;\n    uint32_t max_out_of_time[IWX_SCAN_TWO_LMACS];\n    uint32_t suspend_time[IWX_SCAN_TWO_LMACS];\n    uint32_t scan_priority;\n    uint8_t passive_dwell[IWX_SCAN_TWO_LMACS];\n    uint8_t num_of_fragments[IWX_SCAN_TWO_LMACS];\n} __packed; /* SCAN_GENERAL_PARAMS_API_S_VER_10 */\n\n/**\n * struct iwx_scan_periodic_parms_v1\n * @schedule: can scheduling parameter\n * @delay: initial delay of the periodic scan in seconds\n * @reserved: reserved for future\n */\nstruct iwx_scan_periodic_parms_v1 {\n    struct iwx_scan_umac_schedule schedule[IWX_MAX_SCHED_SCAN_PLANS];\n    uint16_t delay;\n    uint16_t reserved;\n} __packed; /* SCAN_PERIODIC_PARAMS_API_S_VER_1 */\n\n/**\n * struct iwx_scan_req_params_v12\n * @general_params: &struct iwl_scan_general_params_v10\n * @channel_params: &struct iwl_scan_channel_params_v4\n * @periodic_params: &struct iwl_scan_periodic_parms_v1\n * @probe_params: &struct iwl_scan_probe_params_v3\n */\nstruct iwx_scan_req_params_v12 {\n    struct iwx_scan_general_params_v10 general_params;\n    struct iwx_scan_channel_params_v4 channel_params;\n    struct iwx_scan_periodic_parms_v1 periodic_params;\n    struct iwx_scan_probe_params_v3 probe_params;\n} __packed; /* SCAN_REQUEST_PARAMS_API_S_VER_12 */\n\n/**\n * struct iwx_scan_req_params_v14\n * @general_params: &struct iwl_scan_general_params_v10\n * @channel_params: &struct iwl_scan_channel_params_v6\n * @periodic_params: &struct iwl_scan_periodic_parms_v1\n * @probe_params: &struct iwl_scan_probe_params_v4\n */\nstruct iwx_scan_req_params_v14 {\n    struct iwx_scan_general_params_v10 general_params;\n    struct iwx_scan_channel_params_v6 channel_params;\n    struct iwx_scan_periodic_parms_v1 periodic_params;\n    struct iwx_scan_probe_params_v4 probe_params;\n} __packed; /* SCAN_REQUEST_PARAMS_API_S_VER_14 */\n\n/**\n * struct iwx_scan_req_umac_v12\n * @uid: scan id, &enum iwl_umac_scan_uid_offsets\n * @ooc_priority: out of channel priority - &enum iwl_scan_priority\n * @scan_params: scan parameters\n */\nstruct iwx_scan_req_umac_v12 {\n    uint32_t uid;\n    uint32_t ooc_priority;\n    struct iwx_scan_req_params_v12 scan_params;\n} __packed; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_12 */\n\n/**\n * struct iwx_scan_req_umac_v14\n * @uid: scan id, &enum iwl_umac_scan_uid_offsets\n * @ooc_priority: out of channel priority - &enum iwl_scan_priority\n * @scan_params: scan parameters\n */\nstruct iwx_scan_req_umac_v14 {\n    uint32_t uid;\n    uint32_t ooc_priority;\n    struct iwx_scan_req_params_v14 scan_params;\n} __packed; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_14 */\n\n/**\n * struct iwx_umac_scan_abort\n * @uid: scan id, &enum iwx_umac_scan_uid_offsets\n * @flags: reserved\n */\nstruct iwx_umac_scan_abort {\n    uint32_t uid;\n    uint32_t flags;\n} __packed; /* SCAN_ABORT_CMD_UMAC_API_S_VER_1 */\n\n/**\n * struct iwx_umac_scan_complete\n * @uid: scan id, &enum iwx_umac_scan_uid_offsets\n * @last_schedule: last scheduling line\n * @last_iter:    last scan iteration number\n * @scan status: &enum iwx_scan_offload_complete_status\n * @ebs_status: &enum iwx_scan_ebs_status\n * @time_from_last_iter: time elapsed from last iteration\n * @reserved: for future use\n */\nstruct iwx_umac_scan_complete {\n    uint32_t uid;\n    uint8_t last_schedule;\n    uint8_t last_iter;\n    uint8_t status;\n    uint8_t ebs_status;\n    uint32_t time_from_last_iter;\n    uint32_t reserved;\n} __packed; /* SCAN_COMPLETE_NTF_UMAC_API_S_VER_1 */\n\n#define IWX_SCAN_OFFLOAD_MATCHING_CHANNELS_LEN 5\n/**\n * struct iwx_scan_offload_profile_match - match information\n * @bssid: matched bssid\n * @channel: channel where the match occurred\n * @energy:\n * @matching_feature:\n * @matching_channels: bitmap of channels that matched, referencing\n *    the channels passed in tue scan offload request\n */\nstruct iwx_scan_offload_profile_match {\n    uint8_t bssid[ETHER_ADDR_LEN];\n    uint16_t reserved;\n    uint8_t channel;\n    uint8_t energy;\n    uint8_t matching_feature;\n    uint8_t matching_channels[IWX_SCAN_OFFLOAD_MATCHING_CHANNELS_LEN];\n} __packed; /* SCAN_OFFLOAD_PROFILE_MATCH_RESULTS_S_VER_1 */\n\n/**\n * struct iwx_scan_offload_profiles_query - match results query response\n * @matched_profiles: bitmap of matched profiles, referencing the\n *    matches passed in the scan offload request\n * @last_scan_age: age of the last offloaded scan\n * @n_scans_done: number of offloaded scans done\n * @gp2_d0u: GP2 when D0U occurred\n * @gp2_invoked: GP2 when scan offload was invoked\n * @resume_while_scanning: not used\n * @self_recovery: obsolete\n * @reserved: reserved\n * @matches: array of match information, one for each match\n */\nstruct iwx_scan_offload_profiles_query {\n    uint32_t matched_profiles;\n    uint32_t last_scan_age;\n    uint32_t n_scans_done;\n    uint32_t gp2_d0u;\n    uint32_t gp2_invoked;\n    uint8_t resume_while_scanning;\n    uint8_t self_recovery;\n    uint16_t reserved;\n    struct iwx_scan_offload_profile_match matches[IWX_SCAN_MAX_PROFILES];\n} __packed; /* SCAN_OFFLOAD_PROFILES_QUERY_RSP_S_VER_2 */\n\n/**\n * struct iwx_umac_scan_iter_complete_notif - notifies end of scanning iteration\n * @uid: scan id, &enum iwx_umac_scan_uid_offsets\n * @scanned_channels: number of channels scanned and number of valid elements in\n *    results array\n * @status: one of SCAN_COMP_STATUS_*\n * @bt_status: BT on/off status\n * @last_channel: last channel that was scanned\n * @tsf_low: TSF timer (lower half) in usecs\n * @tsf_high: TSF timer (higher half) in usecs\n * @results: array of scan results, only \"scanned_channels\" of them are valid\n */\nstruct iwx_umac_scan_iter_complete_notif {\n    uint32_t uid;\n    uint8_t scanned_channels;\n    uint8_t status;\n    uint8_t bt_status;\n    uint8_t last_channel;\n    uint32_t tsf_low;\n    uint32_t tsf_high;\n    struct iwx_scan_results_notif results[];\n} __packed; /* SCAN_ITER_COMPLETE_NTF_UMAC_API_S_VER_1 */\n\n#define IWX_GSCAN_START_CMD            0x0\n#define IWX_GSCAN_STOP_CMD            0x1\n#define IWX_GSCAN_SET_HOTLIST_CMD        0x2\n#define IWX_GSCAN_RESET_HOTLIST_CMD        0x3\n#define IWX_GSCAN_SET_SIGNIFICANT_CHANGE_CMD    0x4\n#define IWX_GSCAN_RESET_SIGNIFICANT_CHANGE_CMD    0x5\n#define IWX_GSCAN_SIGNIFICANT_CHANGE_EVENT    0xFD\n#define IWX_GSCAN_HOTLIST_CHANGE_EVENT        0xFE\n#define IWX_GSCAN_RESULTS_AVAILABLE_EVENT    0xFF\n\n/* STA API */\n\n/**\n * flags for the ADD_STA host command\n * @IWX_STA_FLG_REDUCED_TX_PWR_CTRL:\n * @IWX_STA_FLG_REDUCED_TX_PWR_DATA:\n * @IWX_STA_FLG_DISABLE_TX: set if TX should be disabled\n * @IWX_STA_FLG_PS: set if STA is in Power Save\n * @IWX_STA_FLG_INVALID: set if STA is invalid\n * @IWX_STA_FLG_DLP_EN: Direct Link Protocol is enabled\n * @IWX_STA_FLG_SET_ALL_KEYS: the current key applies to all key IDs\n * @IWX_STA_FLG_DRAIN_FLOW: drain flow\n * @IWX_STA_FLG_PAN: STA is for PAN interface\n * @IWX_STA_FLG_CLASS_AUTH:\n * @IWX_STA_FLG_CLASS_ASSOC:\n * @IWX_STA_FLG_CLASS_MIMO_PROT:\n * @IWX_STA_FLG_MAX_AGG_SIZE_MSK: maximal size for A-MPDU\n * @IWX_STA_FLG_AGG_MPDU_DENS_MSK: maximal MPDU density for Tx aggregation\n * @IWX_STA_FLG_FAT_EN_MSK: support for channel width (for Tx). This flag is\n *    initialised by driver and can be updated by fw upon reception of\n *    action frames that can change the channel width. When cleared the fw\n *    will send all the frames in 20MHz even when FAT channel is requested.\n * @IWX_STA_FLG_MIMO_EN_MSK: support for MIMO. This flag is initialised by the\n *    driver and can be updated by fw upon reception of action frames.\n * @IWX_STA_FLG_MFP_EN: Management Frame Protection\n */\n#define IWX_STA_FLG_REDUCED_TX_PWR_CTRL    (1 << 3)\n#define IWX_STA_FLG_REDUCED_TX_PWR_DATA    (1 << 6)\n\n#define IWX_STA_FLG_DISABLE_TX        (1 << 4)\n\n#define IWX_STA_FLG_PS            (1 << 8)\n#define IWX_STA_FLG_DRAIN_FLOW        (1 << 12)\n#define IWX_STA_FLG_PAN            (1 << 13)\n#define IWX_STA_FLG_CLASS_AUTH        (1 << 14)\n#define IWX_STA_FLG_CLASS_ASSOC        (1 << 15)\n#define IWX_STA_FLG_RTS_MIMO_PROT    (1 << 17)\n\n#define IWX_STA_FLG_MAX_AGG_SIZE_SHIFT    19\n#define IWX_STA_FLG_MAX_AGG_SIZE_8K    (0 << IWX_STA_FLG_MAX_AGG_SIZE_SHIFT)\n#define IWX_STA_FLG_MAX_AGG_SIZE_16K    (1 << IWX_STA_FLG_MAX_AGG_SIZE_SHIFT)\n#define IWX_STA_FLG_MAX_AGG_SIZE_32K    (2 << IWX_STA_FLG_MAX_AGG_SIZE_SHIFT)\n#define IWX_STA_FLG_MAX_AGG_SIZE_64K    (3 << IWX_STA_FLG_MAX_AGG_SIZE_SHIFT)\n#define IWX_STA_FLG_MAX_AGG_SIZE_128K    (4 << IWX_STA_FLG_MAX_AGG_SIZE_SHIFT)\n#define IWX_STA_FLG_MAX_AGG_SIZE_256K    (5 << IWX_STA_FLG_MAX_AGG_SIZE_SHIFT)\n#define IWX_STA_FLG_MAX_AGG_SIZE_512K    (6 << IWX_STA_FLG_MAX_AGG_SIZE_SHIFT)\n#define IWX_STA_FLG_MAX_AGG_SIZE_1024K    (7 << IWX_STA_FLG_MAX_AGG_SIZE_SHIFT)\n#define IWX_STA_FLG_MAX_AGG_SIZE_MSK    (0xf << IWX_STA_FLG_MAX_AGG_SIZE_SHIFT)\n\n#define IWX_STA_FLG_MAX_AGG_SIZE_4M     (9 << IWX_STA_FLG_MAX_AGG_SIZE_SHIFT)\n\n#define IWX_STA_FLG_AGG_MPDU_DENS_SHIFT    23\n#define IWX_STA_FLG_AGG_MPDU_DENS_2US    (4 << IWX_STA_FLG_AGG_MPDU_DENS_SHIFT)\n#define IWX_STA_FLG_AGG_MPDU_DENS_4US    (5 << IWX_STA_FLG_AGG_MPDU_DENS_SHIFT)\n#define IWX_STA_FLG_AGG_MPDU_DENS_8US    (6 << IWX_STA_FLG_AGG_MPDU_DENS_SHIFT)\n#define IWX_STA_FLG_AGG_MPDU_DENS_16US    (7 << IWX_STA_FLG_AGG_MPDU_DENS_SHIFT)\n#define IWX_STA_FLG_AGG_MPDU_DENS_MSK    (7 << IWX_STA_FLG_AGG_MPDU_DENS_SHIFT)\n\n#define IWX_STA_FLG_FAT_EN_20MHZ    (0 << 26)\n#define IWX_STA_FLG_FAT_EN_40MHZ    (1 << 26)\n#define IWX_STA_FLG_FAT_EN_80MHZ    (2 << 26)\n#define IWX_STA_FLG_FAT_EN_160MHZ    (3 << 26)\n#define IWX_STA_FLG_FAT_EN_MSK        (3 << 26)\n\n#define IWX_STA_FLG_MIMO_EN_SISO    (0 << 28)\n#define IWX_STA_FLG_MIMO_EN_MIMO2    (1 << 28)\n#define IWX_STA_FLG_MIMO_EN_MIMO3    (2 << 28)\n#define IWX_STA_FLG_MIMO_EN_MSK        (3 << 28)\n\n/**\n * key flags for the ADD_STA host command\n * @IWX_STA_KEY_FLG_NO_ENC: no encryption\n * @IWX_STA_KEY_FLG_WEP: WEP encryption algorithm\n * @IWX_STA_KEY_FLG_CCM: CCMP encryption algorithm\n * @IWX_STA_KEY_FLG_TKIP: TKIP encryption algorithm\n * @IWX_STA_KEY_FLG_EXT: extended cipher algorithm (depends on the FW support)\n * @IWX_STA_KEY_FLG_CMAC: CMAC encryption algorithm\n * @IWX_STA_KEY_FLG_ENC_UNKNOWN: unknown encryption algorithm\n * @IWX_STA_KEY_FLG_EN_MSK: mask for encryption algorithmi value\n * @IWX_STA_KEY_FLG_WEP_KEY_MAP: wep is either a group key (0 - legacy WEP) or from\n *    station info array (1 - n 1X mode)\n * @IWX_STA_KEY_FLG_KEYID_MSK: the index of the key\n * @IWX_STA_KEY_NOT_VALID: key is invalid\n * @IWX_STA_KEY_FLG_WEP_13BYTES: set for 13 bytes WEP key\n * @IWX_STA_KEY_MULTICAST: set for multicast key\n * @IWX_STA_KEY_MFP: key is used for Management Frame Protection\n */\n#define IWX_STA_KEY_FLG_NO_ENC        (0 << 0)\n#define IWX_STA_KEY_FLG_WEP        (1 << 0)\n#define IWX_STA_KEY_FLG_CCM        (2 << 0)\n#define IWX_STA_KEY_FLG_TKIP        (3 << 0)\n#define IWX_STA_KEY_FLG_EXT        (4 << 0)\n#define IWX_STA_KEY_FLG_CMAC        (6 << 0)\n#define IWX_STA_KEY_FLG_ENC_UNKNOWN    (7 << 0)\n#define IWX_STA_KEY_FLG_EN_MSK        (7 << 0)\n#define IWX_STA_KEY_FLG_WEP_KEY_MAP    (1 << 3)\n#define IWX_STA_KEY_FLG_KEYID_POS    8\n#define IWX_STA_KEY_FLG_KEYID_MSK    (3 << IWX_STA_KEY_FLG_KEYID_POS)\n#define IWX_STA_KEY_NOT_VALID        (1 << 11)\n#define IWX_STA_KEY_FLG_WEP_13BYTES    (1 << 12)\n#define IWX_STA_KEY_MULTICAST        (1 << 14)\n#define IWX_STA_KEY_MFP            (1 << 15)\n\n/**\n * indicate to the fw what flag are being changed\n * @IWX_STA_MODIFY_QUEUE_REMOVAL: this command removes a queue\n * @IWX_STA_MODIFY_TID_DISABLE_TX: this command modifies %tid_disable_tx\n * @IWX_STA_MODIFY_TX_RATE: unused\n * @IWX_STA_MODIFY_ADD_BA_TID: this command modifies %add_immediate_ba_tid\n * @IWX_STA_MODIFY_REMOVE_BA_TID: this command modifies %remove_immediate_ba_tid\n * @IWX_STA_MODIFY_SLEEPING_STA_TX_COUNT: this command modifies %sleep_tx_count\n * @IWX_STA_MODIFY_PROT_TH:\n * @IWX_STA_MODIFY_QUEUES: modify the queues used by this station\n */\n#define IWX_STA_MODIFY_QUEUE_REMOVAL        (1 << 0)\n#define IWX_STA_MODIFY_TID_DISABLE_TX        (1 << 1)\n#define IWX_STA_MODIFY_TX_RATE            (1 << 2)\n#define IWX_STA_MODIFY_ADD_BA_TID        (1 << 3)\n#define IWX_STA_MODIFY_REMOVE_BA_TID        (1 << 4)\n#define IWX_STA_MODIFY_SLEEPING_STA_TX_COUNT    (1 << 5)\n#define IWX_STA_MODIFY_PROT_TH            (1 << 6)\n#define IWX_STA_MODIFY_QUEUES            (1 << 7)\n\n#define IWX_STA_MODE_MODIFY    1\n\n/**\n * type of sleep of the station\n * @IWX_STA_SLEEP_STATE_AWAKE:\n * @IWX_STA_SLEEP_STATE_PS_POLL:\n * @IWX_STA_SLEEP_STATE_UAPSD:\n * @IWX_STA_SLEEP_STATE_MOREDATA: set more-data bit on\n *    (last) released frame\n */\n#define IWX_STA_SLEEP_STATE_AWAKE    0\n#define IWX_STA_SLEEP_STATE_PS_POLL    (1 << 0)\n#define IWX_STA_SLEEP_STATE_UAPSD    (1 << 1)\n#define IWX_STA_SLEEP_STATE_MOREDATA    (1 << 2)\n\n/* STA ID and color bits definitions */\n#define IWX_STA_ID_SEED        (0x0f)\n#define IWX_STA_ID_POS        (0)\n#define IWX_STA_ID_MSK        (IWX_STA_ID_SEED << IWX_STA_ID_POS)\n\n#define IWX_STA_COLOR_SEED    (0x7)\n#define IWX_STA_COLOR_POS    (4)\n#define IWX_STA_COLOR_MSK    (IWX_STA_COLOR_SEED << IWX_STA_COLOR_POS)\n\n#define IWX_STA_ID_N_COLOR_GET_COLOR(id_n_color) \\\n    (((id_n_color) & IWX_STA_COLOR_MSK) >> IWX_STA_COLOR_POS)\n#define IWX_STA_ID_N_COLOR_GET_ID(id_n_color)    \\\n    (((id_n_color) & IWX_STA_ID_MSK) >> IWX_STA_ID_POS)\n\n#define IWX_STA_KEY_MAX_NUM (16)\n#define IWX_STA_KEY_IDX_INVALID (0xff)\n#define IWX_STA_KEY_MAX_DATA_KEY_NUM (4)\n#define IWX_MAX_GLOBAL_KEYS (4)\n#define IWX_STA_KEY_LEN_WEP40 (5)\n#define IWX_STA_KEY_LEN_WEP104 (13)\n\n/**\n * struct iwx_keyinfo - key information\n * @key_flags: type %iwx_sta_key_flag\n * @tkip_rx_tsc_byte2: TSC[2] for key mix ph1 detection\n * @tkip_rx_ttak: 10-byte unicast TKIP TTAK for Rx\n * @key_offset: key offset in the fw's key table\n * @key: 16-byte unicast decryption key\n * @tx_secur_seq_cnt: initial RSC / PN needed for replay check\n * @hw_tkip_mic_rx_key: byte: MIC Rx Key - used for TKIP only\n * @hw_tkip_mic_tx_key: byte: MIC Tx Key - used for TKIP only\n */\nstruct iwx_keyinfo {\n    uint16_t key_flags;\n    uint8_t tkip_rx_tsc_byte2;\n    uint8_t reserved1;\n    uint16_t tkip_rx_ttak[5];\n    uint8_t key_offset;\n    uint8_t reserved2;\n    uint8_t key[16];\n    uint64_t tx_secur_seq_cnt;\n    uint64_t hw_tkip_mic_rx_key;\n    uint64_t hw_tkip_mic_tx_key;\n} __packed;\n\n#define IWX_ADD_STA_STATUS_MASK        0xFF\n#define IWX_ADD_STA_BAID_VALID_MASK    0x8000\n#define IWX_ADD_STA_BAID_MASK        0x7F00\n#define IWX_ADD_STA_BAID_SHIFT        8\n\n/**\n * struct iwx_add_sta_cmd - Add/modify a station in the fw's sta table.\n * ( REPLY_ADD_STA = 0x18 )\n * @add_modify: see &enum iwl_sta_mode\n * @awake_acs: ACs to transmit data on while station is sleeping (for U-APSD)\n * @tid_disable_tx: is tid BIT(tid) enabled for Tx. Clear BIT(x) to enable\n *    AMPDU for tid x. Set %STA_MODIFY_TID_DISABLE_TX to change this field.\n * @mac_id_n_color: the Mac context this station belongs to,\n *    see &enum iwl_ctxt_id_and_color\n * @addr: station's MAC address\n * @reserved2: reserved\n * @sta_id: index of station in uCode's station table\n * @modify_mask: STA_MODIFY_*, selects which parameters to modify vs. leave\n *    alone. 1 - modify, 0 - don't change.\n * @reserved3: reserved\n * @station_flags: look at &enum iwl_sta_flags\n * @station_flags_msk: what of %station_flags have changed,\n *    also &enum iwl_sta_flags\n * @add_immediate_ba_tid: tid for which to add block-ack support (Rx)\n *    Set %STA_MODIFY_ADD_BA_TID to use this field, and also set\n *    add_immediate_ba_ssn.\n * @remove_immediate_ba_tid: tid for which to remove block-ack support (Rx)\n *    Set %STA_MODIFY_REMOVE_BA_TID to use this field\n * @add_immediate_ba_ssn: ssn for the Rx block-ack session. Used together with\n *    add_immediate_ba_tid.\n * @sleep_tx_count: number of packets to transmit to station even though it is\n *    asleep. Used to synchronise PS-poll and u-APSD responses while ucode\n *    keeps track of STA sleep state.\n * @station_type: type of this station. See &enum iwl_sta_type.\n * @sleep_state_flags: Look at &enum iwl_sta_sleep_flag.\n * @assoc_id: assoc_id to be sent in VHT PLCP (9-bit), for grp use 0, for AP\n *    mac-addr.\n * @beamform_flags: beam forming controls\n * @tfd_queue_msk: tfd queues used by this station.\n *    Obselete for new TX API (9 and above).\n * @rx_ba_window: aggregation window size\n * @sp_length: the size of the SP in actual number of frames\n * @uapsd_acs:  4 LS bits are trigger enabled ACs, 4 MS bits are the deliver\n *    enabled ACs.\n *\n * The device contains an internal table of per-station information, with info\n * on security keys, aggregation parameters, and Tx rates for initial Tx\n * attempt and any retries (set by REPLY_TX_LINK_QUALITY_CMD).\n *\n * ADD_STA sets up the table entry for one station, either creating a new\n * entry, or modifying a pre-existing one.\n */\nstruct iwx_add_sta_cmd {\n    uint8_t add_modify;\n    uint8_t awake_acs;\n    uint16_t tid_disable_tx;\n    uint32_t mac_id_n_color;\n    uint8_t addr[ETHER_ADDR_LEN];    /* _STA_ID_MODIFY_INFO_API_S_VER_1 */\n    uint16_t reserved2;\n    uint8_t sta_id;\n    uint8_t modify_mask;\n    uint16_t reserved3;\n    uint32_t station_flags;\n    uint32_t station_flags_msk;\n    uint8_t add_immediate_ba_tid;\n    uint8_t remove_immediate_ba_tid;\n    uint16_t add_immediate_ba_ssn;\n    uint16_t sleep_tx_count;\n    uint8_t sleep_state_flags;\n    uint8_t station_type;\n    uint16_t assoc_id;\n    uint16_t beamform_flags;\n    uint32_t tfd_queue_msk;\n    uint16_t rx_ba_window;\n    uint8_t sp_length;\n    uint8_t uapsd_acs;\n} __packed; /* ADD_STA_CMD_API_S_VER_10 */\n\n/**\n * FW station types\n * ( REPLY_ADD_STA = 0x18 )\n * @IWX_STA_LINK: Link station - normal RX and TX traffic.\n * @IWX_STA_GENERAL_PURPOSE: General purpose. In AP mode used for beacons\n *    and probe responses.\n * @IWX_STA_MULTICAST: multicast traffic,\n * @IWX_STA_TDLS_LINK: TDLS link station\n * @IWX_STA_AUX_ACTIVITY: auxilary station (scan, ROC and so on).\n */\n#define IWX_STA_LINK        0\n#define IWX_STA_GENERAL_PURPOSE    1\n#define IWX_STA_MULTICAST    2\n#define IWX_STA_TDLS_LINK    3\n#define IWX_STA_AUX_ACTIVITY    4\n\n/**\n * struct iwx_add_sta_key_common - add/modify sta key common part\n * ( REPLY_ADD_STA_KEY = 0x17 )\n * @sta_id: index of station in uCode's station table\n * @key_offset: key offset in key storage\n * @key_flags: IWX_STA_KEY_FLG_*\n * @key: key material data\n * @rx_secur_seq_cnt: RX security sequence counter for the key\n */\nstruct iwx_add_sta_key_common {\n    uint8_t sta_id;\n    uint8_t key_offset;\n    uint16_t key_flags;\n    uint8_t key[32];\n    uint8_t rx_secur_seq_cnt[16];\n} __packed;\n\n/**\n * struct iwx_add_sta_key_cmd_v1 - add/modify sta key\n * @common: see &struct iwx_add_sta_key_common\n * @tkip_rx_tsc_byte2: TSC[2] for key mix ph1 detection\n * @reserved: reserved\n * @tkip_rx_ttak: 10-byte unicast TKIP TTAK for Rx\n */\nstruct iwx_add_sta_key_cmd_v1 {\n    struct iwx_add_sta_key_common common;\n    uint8_t tkip_rx_tsc_byte2;\n    uint8_t reserved;\n    uint16_t tkip_rx_ttak[5];\n} __packed; /* ADD_MODIFY_STA_KEY_API_S_VER_1 */\n\n/**\n * struct iwx_add_sta_key_cmd - add/modify sta key\n * @common: see &struct iwx_add_sta_key_common\n * @rx_mic_key: TKIP RX unicast or multicast key\n * @tx_mic_key: TKIP TX key\n * @transmit_seq_cnt: TSC, transmit packet number\n */\nstruct iwx_add_sta_key_cmd {\n   struct iwx_add_sta_key_common common;\n   uint64_t rx_mic_key;\n   uint64_t tx_mic_key;\n   uint64_t transmit_seq_cnt;\n} __packed; /* ADD_MODIFY_STA_KEY_API_S_VER_2 */\n\n/**\n * status in the response to ADD_STA command\n * @IWX_ADD_STA_SUCCESS: operation was executed successfully\n * @IWX_ADD_STA_STATIONS_OVERLOAD: no room left in the fw's station table\n * @IWX_ADD_STA_IMMEDIATE_BA_FAILURE: can't add Rx block ack session\n * @IWX_ADD_STA_MODIFY_NON_EXISTING_STA: driver requested to modify a station\n *    that doesn't exist.\n */\n#define IWX_ADD_STA_SUCCESS            0x1\n#define IWX_ADD_STA_STATIONS_OVERLOAD        0x2\n#define IWX_ADD_STA_IMMEDIATE_BA_FAILURE    0x4\n#define IWX_ADD_STA_MODIFY_NON_EXISTING_STA    0x8\n\n/**\n * struct iwx_rm_sta_cmd - Add / modify a station in the fw's station table\n * ( IWX_REMOVE_STA = 0x19 )\n * @sta_id: the station id of the station to be removed\n */\nstruct iwx_rm_sta_cmd {\n    uint8_t sta_id;\n    uint8_t reserved[3];\n} __packed; /* IWX_REMOVE_STA_CMD_API_S_VER_2 */\n\n/**\n * struct iwx_mgmt_mcast_key_cmd\n * ( IWX_MGMT_MCAST_KEY = 0x1f )\n * @ctrl_flags: %iwx_sta_key_flag\n * @IGTK:\n * @K1: IGTK master key\n * @K2: IGTK sub key\n * @sta_id: station ID that support IGTK\n * @key_id:\n * @receive_seq_cnt: initial RSC/PN needed for replay check\n */\nstruct iwx_mgmt_mcast_key_cmd {\n    uint32_t ctrl_flags;\n    uint8_t IGTK[16];\n    uint8_t K1[16];\n    uint8_t K2[16];\n    uint32_t key_id;\n    uint32_t sta_id;\n    uint64_t receive_seq_cnt;\n} __packed; /* SEC_MGMT_MULTICAST_KEY_CMD_API_S_VER_1 */\n\nstruct iwx_wep_key {\n    uint8_t key_index;\n    uint8_t key_offset;\n    uint16_t reserved1;\n    uint8_t key_size;\n    uint8_t reserved2[3];\n    uint8_t key[16];\n} __packed;\n\nstruct iwx_wep_key_cmd {\n    uint32_t mac_id_n_color;\n    uint8_t num_keys;\n    uint8_t decryption_type;\n    uint8_t flags;\n    uint8_t reserved;\n    struct iwx_wep_key wep_key[0];\n} __packed; /* SEC_CURR_WEP_KEY_CMD_API_S_VER_2 */\n\n/*\n * BT coex\n */\n\n#define IWX_BT_COEX_DISABLE        0x0\n#define IWX_BT_COEX_NW            0x1\n#define IWX_BT_COEX_BT            0x2\n#define IWX_BT_COEX_WIFI        0x3\n/* BT_COEX_MODES_E */\n\n#define IWX_BT_COEX_MPLUT_ENABLED    (1 << 0)\n#define IWX_BT_COEX_MPLUT_BOOST_ENABLED    (1 << 1)\n#define IWX_BT_COEX_SYNC2SCO_ENABLED    (1 << 2)\n#define IWX_BT_COEX_CORUN_ENABLED    (1 << 3)\n#define IWX_BT_COEX_HIGH_BAND_RET    (1 << 4)\n/* BT_COEX_MODULES_ENABLE_E_VER_1 */\n\n/**\n * struct iwx_bt_coex_cmd - bt coex configuration command\n * @mode: enum %iwx_bt_coex_mode\n * @enabled_modules: enum %iwx_bt_coex_enabled_modules\n *\n * The structure is used for the BT_COEX command.\n */\nstruct iwx_bt_coex_cmd {\n    uint32_t mode;\n    uint32_t enabled_modules;\n} __packed; /* BT_COEX_CMD_API_S_VER_6 */\n\n\n/*\n * Location Aware Regulatory (LAR) API - MCC updates\n */\n\n/**\n * struct iwx_mcc_update_cmd - Request the device to update geographic\n * regulatory profile according to the given MCC (Mobile Country Code).\n * The MCC is two letter-code, ascii upper case[A-Z] or '00' for world domain.\n * 'ZZ' MCC will be used to switch to NVM default profile; in this case, the\n * MCC in the cmd response will be the relevant MCC in the NVM.\n * @mcc: given mobile country code\n * @source_id: the source from where we got the MCC, see IWX_MCC_SOURCE_*\n * @reserved: reserved for alignment\n * @key: integrity key for MCC API OEM testing\n * @reserved2: reserved\n */\nstruct iwx_mcc_update_cmd {\n    uint16_t mcc;\n    uint8_t source_id;\n    uint8_t reserved;\n    uint32_t key;\n    uint32_t reserved2[5];\n} __packed; /* LAR_UPDATE_MCC_CMD_API_S_VER_2 */\n\n/**\n * iwx_mcc_update_resp_v3 - response to MCC_UPDATE_CMD.\n * Contains the new channel control profile map, if changed, and the new MCC\n * (mobile country code).\n * The new MCC may be different than what was requested in MCC_UPDATE_CMD.\n * @status: see &enum iwx_mcc_update_status\n * @mcc: the new applied MCC\n * @cap: capabilities for all channels which matches the MCC\n * @source_id: the MCC source, see IWX_MCC_SOURCE_*\n * @time: time elapsed from the MCC test start (in 30 seconds TU)\n * @reserved: reserved.\n * @n_channels: number of channels in @channels_data (may be 14, 39, 50 or 51\n *        channels, depending on platform)\n * @channels: channel control data map, DWORD for each channel. Only the first\n *    16bits are used.\n */\nstruct iwx_mcc_update_resp_v3 {\n    uint32_t status;\n    uint16_t mcc;\n    uint8_t cap;\n    uint8_t source_id;\n    uint16_t time;\n    uint16_t geo_info;\n    uint32_t n_channels;\n    uint32_t channels[0];\n} __packed; /* LAR_UPDATE_MCC_CMD_RESP_S_VER_3 */\n\n/**\n * geographic information.\n * @GEO_NO_INFO: no special info for this geo profile.\n * @GEO_WMM_ETSI_5GHZ_INFO: this geo profile limits the WMM params\n *    for the 5 GHz band.\n */\n#define IWX_GEO_NO_INFO            0\n#define IWX_GEO_WMM_ETSI_5GHZ_INFO (1 << 0)\n\n/**\n * struct iwx_mcc_update_resp - response to MCC_UPDATE_CMD.\n * Contains the new channel control profile map, if changed, and the new MCC\n * (mobile country code).\n * The new MCC may be different than what was requested in MCC_UPDATE_CMD.\n * @status: see &enum iwl_mcc_update_status\n * @mcc: the new applied MCC\n * @cap: capabilities for all channels which matches the MCC\n * @time: time elapsed from the MCC test start (in units of 30 seconds)\n * @geo_info: geographic specific profile information\n *    see IWX_GEO_*\n * @source_id: the MCC source, see IWX_MCC_SOURCE_*\n * @reserved: for four bytes alignment.\n * @n_channels: number of channels in @channels_data.\n * @channels: channel control data map, DWORD for each channel. Only the first\n *    16bits are used.\n */\nstruct iwx_mcc_update_resp {\n    uint32_t status;\n    uint16_t mcc;\n    uint16_t cap;\n    uint16_t time;\n    uint16_t geo_info;\n    uint8_t source_id;\n    uint8_t reserved[3];\n    uint32_t n_channels;\n    uint32_t channels[0];\n} __packed; /* LAR_UPDATE_MCC_CMD_RESP_S_VER_4 */\n\n/**\n * struct iwx_mcc_chub_notif - chub notifies of mcc change\n * (MCC_CHUB_UPDATE_CMD = 0xc9)\n * The Chub (Communication Hub, CommsHUB) is a HW component that connects to\n * the cellular and connectivity cores that gets updates of the mcc, and\n * notifies the ucode directly of any mcc change.\n * The ucode requests the driver to request the device to update geographic\n * regulatory  profile according to the given MCC (Mobile Country Code).\n * The MCC is two letter-code, ascii upper case[A-Z] or '00' for world domain.\n * 'ZZ' MCC will be used to switch to NVM default profile; in this case, the\n * MCC in the cmd response will be the relevant MCC in the NVM.\n * @mcc: given mobile country code\n * @source_id: identity of the change originator, see IWX_MCC_SOURCE_*\n * @reserved1: reserved for alignment\n */\nstruct iwx_mcc_chub_notif {\n    uint16_t mcc;\n    uint8_t source_id;\n    uint8_t reserved1;\n} __packed; /* LAR_MCC_NOTIFY_S */\n\nenum iwx_mcc_update_status {\n    IWX_MCC_RESP_NEW_CHAN_PROFILE,\n    IWX_MCC_RESP_SAME_CHAN_PROFILE,\n    IWX_MCC_RESP_INVALID,\n    IWX_MCC_RESP_NVM_DISABLED,\n    IWX_MCC_RESP_ILLEGAL,\n    IWX_MCC_RESP_LOW_PRIORITY,\n    IWX_MCC_RESP_TEST_MODE_ACTIVE,\n    IWX_MCC_RESP_TEST_MODE_NOT_ACTIVE,\n    IWX_MCC_RESP_TEST_MODE_DENIAL_OF_SERVICE,\n};\n\n#define IWX_MCC_SOURCE_OLD_FW            0\n#define IWX_MCC_SOURCE_ME            1\n#define IWX_MCC_SOURCE_BIOS            2\n#define IWX_MCC_SOURCE_3G_LTE_HOST        3\n#define IWX_MCC_SOURCE_3G_LTE_DEVICE        4\n#define IWX_MCC_SOURCE_WIFI            5\n#define IWX_MCC_SOURCE_RESERVED            6\n#define IWX_MCC_SOURCE_DEFAULT            7\n#define IWX_MCC_SOURCE_UNINITIALIZED        8\n#define IWX_MCC_SOURCE_MCC_API            9\n#define IWX_MCC_SOURCE_GET_CURRENT        0x10\n#define IWX_MCC_SOURCE_GETTING_MCC_TEST_MODE    0x11\n\n/*\n * From Linux commit ab02165ccec4c78162501acedeef1a768acdb811:\n *   As the firmware is slowly running out of command IDs and grouping of\n *   commands is desirable anyway, the firmware is extending the command\n *   header from 4 bytes to 8 bytes to introduce a group (in place of the\n *   former flags field, since that's always 0 on commands and thus can\n *   be easily used to distinguish between the two).\n *\n * These functions retrieve specific information from the id field in\n * the iwx_host_cmd struct which contains the command id, the group id,\n * and the version of the command.\n*/\nstatic inline uint8_t\niwx_cmd_opcode(uint32_t cmdid)\n{\n    return cmdid & 0xff;\n}\n\nstatic inline uint8_t\niwx_cmd_groupid(uint32_t cmdid)\n{\n    return ((cmdid & 0Xff00) >> 8);\n}\n\nstatic inline uint8_t\niwx_cmd_version(uint32_t cmdid)\n{\n    return ((cmdid & 0xff0000) >> 16);\n}\n\nstatic inline uint32_t\niwx_cmd_id(uint8_t opcode, uint8_t groupid, uint8_t version)\n{\n    return opcode + (groupid << 8) + (version << 16);\n}\n\n/* make uint16_t wide id out of uint8_t group and opcode */\n#define IWX_WIDE_ID(grp, opcode) ((grp << 8) | opcode)\n\nstruct iwx_cmd_header {\n    uint8_t cmd;\n    uint8_t group_id;\n    uint8_t idx;\n    uint8_t qid;\n} __packed;\n\nstruct iwx_cmd_header_wide {\n    uint8_t cmd;\n    uint8_t group_id;\n    uint8_t idx;\n    uint8_t qid;\n    uint16_t length;\n    uint8_t reserved;\n    uint8_t version;\n} __packed;\n\n#define IWX_POWER_SCHEME_CAM    1\n#define IWX_POWER_SCHEME_BPS    2\n#define IWX_POWER_SCHEME_LP    3\n\n#define IWX_DEF_CMD_PAYLOAD_SIZE 320\n#define IWX_MAX_CMD_PAYLOAD_SIZE ((4096 - 4) - sizeof(struct iwx_cmd_header))\n#define IWX_CMD_FAILED_MSK 0x40\n\n/**\n * struct iwx_device_cmd\n *\n * For allocation of the command and tx queues, this establishes the overall\n * size of the largest command we send to uCode, except for commands that\n * aren't fully copied and use other TFD space.\n */\nstruct iwx_device_cmd {\n    union {\n        struct {\n            struct iwx_cmd_header hdr;\n            uint8_t data[IWX_DEF_CMD_PAYLOAD_SIZE];\n        };\n        struct {\n            struct iwx_cmd_header_wide hdr_wide;\n            uint8_t data_wide[IWX_DEF_CMD_PAYLOAD_SIZE -\n                    sizeof(struct iwx_cmd_header_wide) +\n                    sizeof(struct iwx_cmd_header)];\n        };\n    };\n} __packed;\n\nstruct iwx_rx_packet {\n    /*\n     * The first 4 bytes of the RX frame header contain both the RX frame\n     * size and some flags.\n     * Bit fields:\n     * 31:    flag flush RB request\n     * 30:    flag ignore TC (terminal counter) request\n     * 29:    flag fast IRQ request\n     * 28-26: Reserved\n     * 25:    Offload enabled\n     * 24:    RPF enabled\n     * 23:    RSS enabled\n     * 22:    Checksum enabled\n     * 21-16: RX queue\n     * 15-14: Reserved\n     * 13-00: RX frame size\n     */\n    uint32_t len_n_flags;\n    struct iwx_cmd_header hdr;\n    uint8_t data[];\n} __packed;\n\n#define    IWX_FH_RSCSR_FRAME_SIZE_MSK    0x00003fff\n#define    IWX_FH_RSCSR_FRAME_INVALID    0x55550000\n#define    IWX_FH_RSCSR_FRAME_ALIGN    0x40\n#define    IWX_FH_RSCSR_RPA_EN        (1 << 25)\n#define    IWX_FH_RSCSR_RADA_EN        (1 << 26)\n#define    IWX_FH_RSCSR_RXQ_POS        16\n#define    IWX_FH_RSCSR_RXQ_MASK        0x3F0000\n\nstatic uint32_t\niwx_rx_packet_len(const struct iwx_rx_packet *pkt)\n{\n\n    return le32toh(pkt->len_n_flags) & IWX_FH_RSCSR_FRAME_SIZE_MSK;\n}\n\nstatic uint32_t\niwx_rx_packet_payload_len(const struct iwx_rx_packet *pkt)\n{\n\n    return iwx_rx_packet_len(pkt) - sizeof(pkt->hdr);\n}\n\n\n#define IWX_MIN_DBM    -100\n#define IWX_MAX_DBM    -33    /* realistic guess */\n\n#define IWX_READ(sc, reg)                        \\\n    bus_space_read_4((sc)->sc_st, (sc)->sc_sh, (reg))\n\n#define IWX_WRITE(sc, reg, val)                        \\\n    bus_space_write_4((sc)->sc_st, (sc)->sc_sh, (reg), (val))\n\n#define IWX_WRITE64(sc, reg, val)                        \\\ndo {   \\\n    IWX_WRITE((sc), (uint32_t)(reg), (val) & 0xffffffff);   \\\n    IWX_WRITE((sc), (uint32_t)(reg) + 4, (val) >> 32);  \\\n} while(0)\n\n#define IWX_WRITE_1(sc, reg, val)                    \\\n    bus_space_write_1((sc)->sc_st, (sc)->sc_sh, (reg), (val))\n\n#define IWX_SETBITS(sc, reg, mask)                    \\\n    IWX_WRITE(sc, reg, IWX_READ(sc, reg) & ~(mask) | (mask))\n\n#define IWX_CLRBITS(sc, reg, mask)                    \\\n    IWX_WRITE(sc, reg, IWX_READ(sc, reg) & ~(mask) | 0)\n\n#define IWX_BARRIER_WRITE(sc)                        \\\n    bus_space_barrier((sc)->sc_st, (sc)->sc_sh, 0, (sc)->sc_sz,    \\\n        BUS_SPACE_BARRIER_WRITE)\n\n#define IWX_BARRIER_READ_WRITE(sc)                    \\\n    bus_space_barrier((sc)->sc_st, (sc)->sc_sh, 0, (sc)->sc_sz,    \\\n        BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE)\n"
  },
  {
    "path": "itlwm/hal_iwx/if_iwxvar.h",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n/*    $OpenBSD: if_iwxvar.h,v 1.13 2020/10/11 07:05:28 mpi Exp $    */\n\n/*\n * Copyright (c) 2014 genua mbh <info@genua.de>\n * Copyright (c) 2014 Fixup Software Ltd.\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\n/*-\n * Based on BSD-licensed source modules in the Linux iwlwifi driver,\n * which were used as the reference documentation for this implementation.\n *\n ******************************************************************************\n *\n * This file is provided under a dual BSD/GPLv2 license.  When using or\n * redistributing this file, you may do so under either license.\n *\n * GPL LICENSE SUMMARY\n *\n * Copyright(c) 2017 Intel Deutschland GmbH\n * Copyright(c) 2018 - 2019 Intel Corporation\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of version 2 of the GNU General Public License as\n * published by the Free Software Foundation.\n *\n * This program is distributed in the hope that it will be useful, but\n * WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * General Public License for more details.\n *\n * BSD LICENSE\n *\n * Copyright(c) 2017 Intel Deutschland GmbH\n * Copyright(c) 2018 - 2019 Intel Corporation\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in\n *    the documentation and/or other materials provided with the\n *    distribution.\n *  * Neither the name Intel Corporation nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n *****************************************************************************\n */\n\n/*-\n * Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n#include <net80211/ieee80211_var.h>\n#include <net80211/ieee80211_amrr.h>\n#include <net80211/ieee80211_mira.h>\n#include <net80211/ieee80211_radiotap.h>\n\n#include <IOKit/network/IOMbufMemoryCursor.h>\n#include <IOKit/IODMACommand.h>\n\n#define IWL_CFG_ANY (~0)\n\n#define IWL_CFG_MAC_TYPE_PU        0x31\n#define IWL_CFG_MAC_TYPE_PNJ        0x32\n#define IWL_CFG_MAC_TYPE_TH        0x32\n#define IWL_CFG_MAC_TYPE_QU        0x33\n#define IWL_CFG_MAC_TYPE_QUZ        0x35\n#define IWL_CFG_MAC_TYPE_QNJ        0x36\n#define IWL_CFG_MAC_TYPE_SO        0x37\n#define IWL_CFG_MAC_TYPE_SNJ        0x42\n#define IWL_CFG_MAC_TYPE_SOF        0x43\n#define IWL_CFG_MAC_TYPE_MA        0x44\n#define IWL_CFG_MAC_TYPE_BZ        0x46\n\n#define IWL_CFG_RF_TYPE_TH        0x105\n#define IWL_CFG_RF_TYPE_TH1        0x108\n#define IWL_CFG_RF_TYPE_JF2        0x105\n#define IWL_CFG_RF_TYPE_JF1        0x108\n#define IWL_CFG_RF_TYPE_HR2        0x10A\n#define IWL_CFG_RF_TYPE_HR1        0x10C\n#define IWL_CFG_RF_TYPE_GF        0x10D\n#define IWL_CFG_RF_TYPE_MR        0x110\n#define IWL_CFG_RF_TYPE_FM        0x112\n\n#define IWL_CFG_RF_ID_TH        0x1\n#define IWL_CFG_RF_ID_TH1        0x1\n#define IWL_CFG_RF_ID_JF        0x3\n#define IWL_CFG_RF_ID_JF1        0x6\n#define IWL_CFG_RF_ID_JF1_DIV        0xA\n#define IWL_CFG_RF_ID_HR        0x7\n#define IWL_CFG_RF_ID_HR1        0x4\n\n#define IWL_CFG_NO_160            0x1\n#define IWL_CFG_160            0x0\n\n#define IWL_CFG_CORES_BT        0x0\n#define IWL_CFG_CORES_BT_GNSS        0x5\n\n#define IWL_CFG_NO_CDB            0x0\n#define IWL_CFG_CDB            0x1\n\n#define IWL_SUBDEVICE_RF_ID(subdevice)    ((u16)((subdevice) & 0x00F0) >> 4)\n#define IWL_SUBDEVICE_NO_160(subdevice)    ((u16)((subdevice) & 0x0200) >> 9)\n#define IWL_SUBDEVICE_CORES(subdevice)    ((u16)((subdevice) & 0x1C00) >> 10)\n\n/* HW REV */\n#define CSR_HW_REV_TYPE(_val)          (((_val) & 0x000FFF0) >> 4)\n\n/* HW RFID */\n#define CSR_HW_RFID_FLAVOR(_val)       (((_val) & 0x000000F) >> 0)\n#define CSR_HW_RFID_DASH(_val)         (((_val) & 0x00000F0) >> 4)\n#define CSR_HW_RFID_STEP(_val)         (((_val) & 0x0000F00) >> 8)\n#define CSR_HW_RFID_TYPE(_val)         (((_val) & 0x0FFF000) >> 12)\n#define CSR_HW_RFID_IS_CDB(_val)       (((_val) & 0x10000000) >> 28)\n#define CSR_HW_RFID_IS_JACKET(_val)    (((_val) & 0x20000000) >> 29)\n\n#define CSR_HW_REV_TYPE_MSK        (0x000FFF0)\n#define CSR_HW_REV_TYPE_NONE        (0x00001F0)\n#define CSR_HW_REV_TYPE_QNJ        (0x0000360)\n#define CSR_HW_REV_TYPE_QNJ_B0        (0x0000364)\n#define CSR_HW_REV_TYPE_QU_B0        (0x0000334)\n#define CSR_HW_REV_TYPE_QU_C0        (0x0000338)\n#define CSR_HW_REV_TYPE_QUZ        (0x0000354)\n#define CSR_HW_REV_TYPE_HR_CDB        (0x0000340)\n#define CSR_HW_REV_TYPE_SO        (0x0000370)\n#define CSR_HW_REV_TYPE_TY        (0x0000420)\n\n/* RF_ID value */\n#define CSR_HW_RF_ID_TYPE_JF        (0x00105100)\n#define CSR_HW_RF_ID_TYPE_HR        (0x0010A000)\n#define CSR_HW_RF_ID_TYPE_HR1        (0x0010c100)\n#define CSR_HW_RF_ID_TYPE_HRCDB        (0x00109F00)\n#define CSR_HW_RF_ID_TYPE_GF        (0x0010D000)\n#define CSR_HW_RF_ID_TYPE_GF4        (0x0010E000)\n\n/* HW_RF CHIP ID  */\n#define CSR_HW_RF_ID_TYPE_CHIP_ID(_val) (((_val) >> 12) & 0xFFF)\n\n/* HW_RF CHIP STEP  */\n#define CSR_HW_RF_STEP(_val) (((_val) >> 8) & 0xF)\n\nstruct iwx_rx_radiotap_header {\n\tstruct ieee80211_radiotap_header wr_ihdr;\n\tuint64_t\twr_tsft;\n\tuint8_t\t\twr_flags;\n\tuint8_t\t\twr_rate;\n\tuint16_t\twr_chan_freq;\n\tuint16_t\twr_chan_flags;\n\tint8_t\t\twr_dbm_antsignal;\n\tint8_t\t\twr_dbm_antnoise;\n} __packed;\n\n#define IWX_RX_RADIOTAP_PRESENT\t\t\t\t\t\t\\\n\t((1 << IEEE80211_RADIOTAP_TSFT) |\t\t\t\t\\\n\t (1 << IEEE80211_RADIOTAP_FLAGS) |\t\t\t\t\\\n\t (1 << IEEE80211_RADIOTAP_RATE) |\t\t\t\t\\\n\t (1 << IEEE80211_RADIOTAP_CHANNEL) |\t\t\t\t\\\n\t (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) |\t\t\t\\\n\t (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE))\n\nstruct iwx_tx_radiotap_header {\n\tstruct ieee80211_radiotap_header wt_ihdr;\n\tuint8_t\t\twt_flags;\n\tuint8_t\t\twt_rate;\n\tuint16_t\twt_chan_freq;\n\tuint16_t\twt_chan_flags;\n} __packed;\n\n#define IWX_TX_RADIOTAP_PRESENT\t\t\t\t\t\t\\\n\t((1 << IEEE80211_RADIOTAP_FLAGS) |\t\t\t\t\\\n\t (1 << IEEE80211_RADIOTAP_RATE) |\t\t\t\t\\\n\t (1 << IEEE80211_RADIOTAP_CHANNEL))\n\n#define IWX_UCODE_SECT_MAX 60\n\n/*\n * fw_status is used to determine if we've already parsed the firmware file\n *\n * In addition to the following, status < 0 ==> -error\n */\n#define IWX_FW_STATUS_NONE\t\t0\n#define IWX_FW_STATUS_INPROGRESS\t1\n#define IWX_FW_STATUS_DONE\t\t2\n\nenum iwx_ucode_type {\n\tIWX_UCODE_TYPE_REGULAR,\n\tIWX_UCODE_TYPE_INIT,\n\tIWX_UCODE_TYPE_WOW,\n\tIWX_UCODE_TYPE_REGULAR_USNIFFER,\n\tIWX_UCODE_TYPE_MAX\n};\n\nstruct iwx_fw_onesect {\n    void *fws_data;\n    uint32_t fws_len;\n    uint32_t fws_devoff;\n};\n\nstruct iwx_fw_sects {\n    struct iwx_fw_onesect fw_sect[IWX_UCODE_SECT_MAX];\n    size_t fw_totlen;\n    int fw_count;\n};\n\nstruct iwx_fw_info {\n\tvoid *fw_rawdata;\n\tsize_t fw_rawsize;\n    void *pnvm_rawdata;\n    size_t pnvm_rawsize;\n\tint fw_status;\n\n\tstruct iwx_fw_sects fw_sects[IWX_UCODE_TYPE_MAX];\n\n\t/* FW debug data parsed for driver usage */\n\tint dbg_dest_tlv_init;\n\tuint8_t *dbg_dest_ver;\n\tuint8_t n_dest_reg;\n\tstruct iwx_fw_dbg_dest_tlv_v1 *dbg_dest_tlv_v1;\n\n\tstruct iwx_fw_dbg_conf_tlv *dbg_conf_tlv[IWX_FW_DBG_CONF_MAX];\n\tsize_t dbg_conf_tlv_len[IWX_FW_DBG_CONF_MAX];\n\tstruct iwx_fw_dbg_trigger_tlv *dbg_trigger_tlv[IWX_FW_DBG_TRIGGER_MAX];\n\tsize_t dbg_trigger_tlv_len[IWX_FW_DBG_TRIGGER_MAX];\n\tstruct iwx_fw_dbg_mem_seg_tlv *dbg_mem_tlv;\n\tsize_t n_mem_tlv;\n};\n\nstruct iwx_nvm_data {\n\tint n_hw_addrs;\n\tuint8_t hw_addr[ETHER_ADDR_LEN];\n\n\tint sku_cap_band_24GHz_enable;\n\tint sku_cap_band_52GHz_enable;\n\tint sku_cap_11n_enable;\n    int sku_cap_11ac_enable;\n    int sku_cap_11ax_enable;\n\tint sku_cap_amt_enable;\n\tint sku_cap_ipan_enable;\n\tint sku_cap_mimo_disable;\n    int lar_enabled;\n    bool vht160_supported;\n\n\tuint8_t valid_tx_ant, valid_rx_ant;\n\n\tuint16_t nvm_version;\n};\n\n/* max bufs per tfd the driver will use */\n#define IWX_MAX_CMD_TBS_PER_TFD 2\n\nstruct iwx_host_cmd {\n\tconst void *data[IWX_MAX_CMD_TBS_PER_TFD];\n\tstruct iwx_rx_packet *resp_pkt;\n\tsize_t resp_pkt_len;\n\tunsigned long _rx_page_addr;\n\tuint32_t _rx_page_order;\n\tint handler_status;\n\n\tuint32_t flags;\n\tuint16_t len[IWX_MAX_CMD_TBS_PER_TFD];\n\tuint8_t dataflags[IWX_MAX_CMD_TBS_PER_TFD];\n\tuint32_t id;\n};\n\n/*\n * DMA glue is from iwn\n */\n\nstruct iwx_dma_info {\n\tIOBufferMemoryDescriptor* buffer;\n    bus_addr_t        paddr;\n    void             *vaddr;\n    bus_size_t        size;\n    IOBufferMemoryDescriptor *bmd;\n    IODMACommand *cmd;\n};\n\nstruct iwx_tx_data {\n\tbus_dmamap_t\tmap;\n\tbus_addr_t\tcmd_paddr;\n\tmbuf_t m;\n\tstruct iwx_node *in;\n    int flags;\n#define IWX_TXDATA_FLAG_CMD_IS_NARROW  0x01\n    uint8_t type;\n};\n\nstruct iwx_tx_ring {\n\tstruct iwx_dma_info\tdesc_dma;\n\tstruct iwx_dma_info\tcmd_dma;\n\tstruct iwx_dma_info\tbc_tbl;\n\tstruct iwx_tfh_tfd\t*desc;\n\tstruct iwx_device_cmd\t*cmd;\n\tstruct iwx_tx_data\tdata[IWX_MIN_256_BA_QUEUE_SIZE_GEN3];\n    unsigned int    ring_count;\n    unsigned int    hi_mark;\n    unsigned int    low_mark;\n\tint\t\t\tqid;\n\tint\t\t\tqueued;\n\tint\t\t\tcur;\n\tint\t\t\ttail;\n};\n\n#define IWX_RX_MQ_RING_COUNT\t512\n/* Linux driver optionally uses 8k buffer */\n#define IWX_RBUF_SIZE\t\t4096\n\nstruct iwx_rx_data {\n\tmbuf_t m;\n\tbus_dmamap_t\tmap;\n};\n\nstruct iwx_rx_ring {\n\tstruct iwx_dma_info\tfree_desc_dma;\n\tstruct iwx_dma_info\tstat_dma;\n\tstruct iwx_dma_info\tused_desc_dma;\n\tvoid\t\t\t*desc;\n\tvoid\t        *stat;\n\tstruct iwx_rx_data\tdata[IWX_RX_MQ_RING_COUNT];\n\tint\t\t\tcur;\n};\n\n#define IWX_FLAG_USE_ICT\t0x01\t/* using Interrupt Cause Table */\n#define IWX_FLAG_RFKILL\t\t0x02\t/* radio kill switch is set */\n#define IWX_FLAG_SCANNING\t0x04\t/* scan in progress */\n#define IWX_FLAG_MAC_ACTIVE\t0x08\t/* MAC context added to firmware */\n#define IWX_FLAG_BINDING_ACTIVE\t0x10\t/* MAC->PHY binding added to firmware */\n#define IWX_FLAG_STA_ACTIVE\t0x20\t/* AP added to firmware station table */\n#define IWX_FLAG_TE_ACTIVE\t0x40\t/* time event is scheduled */\n#define IWX_FLAG_HW_ERR\t\t0x80\t/* hardware error occurred */\n#define IWX_FLAG_SHUTDOWN\t0x100\t/* shutting down; new tasks forbidden */\n#define IWX_FLAG_BGSCAN\t\t0x200\t/* background scan in progress */\n#define IWX_FLAG_TXFLUSH    0x400   /* Tx queue flushing in progress */\n\nstruct iwx_ucode_status {\n\tuint32_t uc_lmac_error_event_table[2];\n\tuint32_t uc_umac_error_event_table;\n\tuint32_t uc_log_event_table;\n\tunsigned int error_event_table_tlv_status;\n\n\tint uc_ok;\n\tint uc_intr;\n};\n\n#define IWX_ERROR_EVENT_TABLE_LMAC1\t(1 << 0)\n#define IWX_ERROR_EVENT_TABLE_LMAC2\t(1 << 1)\n#define IWX_ERROR_EVENT_TABLE_UMAC\t(1 << 2)\n\n#define IWX_CMD_RESP_MAX PAGE_SIZE\n\n/* lower blocks contain EEPROM image and calibration data */\n#define IWX_OTP_LOW_IMAGE_SIZE_FAMILY_7000 \t16384\n#define IWX_OTP_LOW_IMAGE_SIZE_FAMILY_8000\t32768\n\n#define IWX_TE_SESSION_PROTECTION_MAX_TIME_MS 1000\n#define IWX_TE_SESSION_PROTECTION_MIN_TIME_MS 400\n\nenum IWX_CMD_MODE {\n\tIWX_CMD_ASYNC\t\t= (1 << 0),\n\tIWX_CMD_WANT_RESP\t= (1 << 1),\n\tIWX_CMD_SEND_IN_RFKILL\t= (1 << 2),\n};\nenum iwx_hcmd_dataflag {\n\tIWX_HCMD_DFL_NOCOPY     = (1 << 0),\n\tIWX_HCMD_DFL_DUP        = (1 << 1),\n};\n\n#define IWX_NUM_PAPD_CH_GROUPS\t9\n#define IWX_NUM_TXP_CH_GROUPS\t9\n\nstruct iwx_phy_ctxt {\n\tuint16_t id;\n\tuint16_t color;\n\tuint32_t ref;\n\tstruct ieee80211_channel *channel;\n};\n\nstruct iwx_bf_data {\n\tint bf_enabled;\t\t/* filtering\t*/\n\tint ba_enabled;\t\t/* abort\t*/\n\tint ave_beacon_signal;\n\tint last_cqm_event;\n};\n\n/**\n * struct iwx_self_init_dram - dram data used by self init process\n * @fw: lmac and umac dram data\n * @lmac_cnt: number of lmac sections in fw image\n * @umac_cnt: number of umac sections in fw image\n * @paging: paging dram data\n * @paging_cnt: number of paging sections needed by fw image\n */\nstruct iwx_self_init_dram {\n\tstruct iwx_dma_info *fw;\n\tint lmac_cnt;\n    int umac_cnt;\n\tstruct iwx_dma_info *paging;\n\tint paging_cnt;\n};\n\n\n#define IWX_MAX_TID_COUNT 8\n#define IWX_INVALID_QUEUE 0xFFFF\n\nstruct iwx_tid_data {\n    uint16_t seq_number;\n    uint16_t next_reclaimed;\n    uint16_t qid;\n    uint16_t ssn;\n};\n\n#define    INFSLP    UINT64_MAX\n#ifdef DELAY\n#undef DELAY\n#define DELAY IODelay\n#endif\n\nstruct iwl_cfg_trans_params {\n    int integrated;\n    int device_family;\n    int low_latency_xtal;\n    int ltr_delay;\n    int xtal_latency;\n    int bisr_workaround;\n};\n\nstruct iwl_cfg {\n    struct iwl_cfg_trans_params trans;\n    const char *name;\n    const char *fwname;\n    int device_family;\n    int tx_with_siso_diversity;\n    int uhb_supported;\n    uint8_t max_tx_agg_size;\n    uint16_t num_rbds;\n};\n\n/**\n * struct iwx_reorder_buffer - per ra/tid/queue reorder buffer\n * @head_sn: reorder window head sn\n * @num_stored: number of mpdus stored in the buffer\n * @buf_size: the reorder buffer size as set by the last addba request\n * @queue: queue of this reorder buffer\n * @last_amsdu: track last ASMDU SN for duplication detection\n * @last_sub_index: track ASMDU sub frame index for duplication detection\n * @reorder_timer: timer for frames are in the reorder buffer. For AMSDU\n *    it is the time of last received sub-frame\n * @removed: prevent timer re-arming\n * @valid: reordering is valid for this queue\n * @consec_oldsn_drops: consecutive drops due to old SN\n * @consec_oldsn_ampdu_gp2: A-MPDU GP2 timestamp to track\n *    when to apply old SN consecutive drop workaround\n * @consec_oldsn_prev_drop: track whether or not an MPDU\n *    that was single/part of the previous A-MPDU was\n *    dropped due to old SN\n */\nstruct iwx_reorder_buffer {\n    uint16_t head_sn;\n    uint16_t num_stored;\n    uint16_t buf_size;\n    uint16_t last_amsdu;\n    uint8_t last_sub_index;\n    CTimeout *reorder_timer;\n    int removed;\n    int valid;\n    unsigned int consec_oldsn_drops;\n    uint32_t consec_oldsn_ampdu_gp2;\n    unsigned int consec_oldsn_prev_drop;\n#define IWX_AMPDU_CONSEC_DROPS_DELBA    20\n};\n\n/**\n * struct iwx_reorder_buf_entry - reorder buffer entry per frame sequence number\n * @frames: list of mbufs stored (A-MSDU subframes share a sequence number)\n * @reorder_time: time the packet was stored in the reorder buffer\n */\nstruct iwx_reorder_buf_entry {\n    struct mbuf_list frames;\n    struct timeval reorder_time;\n    uint32_t rx_pkt_status;\n    int chanidx;\n    int is_shortpre;\n    uint32_t rate_n_flags;\n    uint32_t device_timestamp;\n    struct ieee80211_rxinfo rxi;\n};\n\n/**\n * struct iwx_rxba_data - BA session data\n * @sta_id: station id\n * @tid: tid of the session\n * @baid: baid of the session\n * @timeout: the timeout set in the addba request\n * @entries_per_queue: # of buffers per queue\n * @last_rx: last rx timestamp, updated only if timeout passed from last update\n * @session_timer: timer to check if BA session expired, runs at 2 * timeout\n * @sc: softc pointer, needed for timer context\n * @reorder_buf: reorder buffer\n * @reorder_buf_data: buffered frames, one entry per sequence number\n */\nstruct iwx_rxba_data {\n    uint8_t sta_id;\n    uint8_t tid;\n    uint8_t baid;\n    uint16_t timeout;\n    uint16_t entries_per_queue;\n    struct timeval last_rx;\n    CTimeout *session_timer;\n    struct iwx_softc *sc;\n    struct iwx_reorder_buffer reorder_buf;\n    struct iwx_reorder_buf_entry entries[IEEE80211_BA_MAX_WINSZ];\n};\n\nstatic inline struct iwx_rxba_data *\niwx_rxba_data_from_reorder_buf(struct iwx_reorder_buffer *buf)\n{\n    return (struct iwx_rxba_data *)((uint8_t *)buf -\n            offsetof(struct iwx_rxba_data, reorder_buf));\n}\n\n/**\n * struct iwx_rxq_dup_data - per station per rx queue data\n * @last_seq: last sequence per tid for duplicate packet detection\n * @last_sub_frame: last subframe packet\n */\nstruct iwx_rxq_dup_data {\n    uint16_t last_seq[IWX_MAX_TID_COUNT + 1];\n    uint8_t last_sub_frame[IWX_MAX_TID_COUNT + 1];\n};\n\nstruct iwx_ba_task_data {\n    uint32_t        start_tidmask;\n    uint32_t        stop_tidmask;\n};\n\nstruct iwx_softc {\n\tstruct device sc_dev;\n\tstruct ieee80211com sc_ic;\n\tint (*sc_newstate)(struct ieee80211com *, enum ieee80211_state, int);\n\tint sc_newstate_pending;\n    pci_intr_handle_t ih;\n\n\tstruct task\t\tinit_task; /* NB: not reference-counted */\n//\tstruct refcnt\t\ttask_refs;\n\tstruct task newstate_task;\n\tenum ieee80211_state\tns_nstate;\n\tint\t\t\tns_arg;\n\n\t/* Task for firmware BlockAck setup/teardown and its arguments. */\n\tstruct task\tba_task;\n    \n    struct iwx_ba_task_data    ba_rx;\n    struct iwx_ba_task_data    ba_tx;\n    \n    struct iwx_tid_data sc_tid_data[IWX_MAX_TID_COUNT + 1];//per tid data + mgmt. Look at %iwx_tid_data.\n\n    /* Task for ERP/HT prot/slot-time/EDCA updates. */\n    struct task        mac_ctxt_task;\n    struct task        chan_ctxt_task;\n\n\tbus_space_tag_t sc_st;\n\tbus_space_handle_t sc_sh;\n\tbus_size_t sc_sz;\n\tbus_dma_tag_t sc_dmat;\n\tpci_chipset_tag_t sc_pct;\n\tpcitag_t sc_pcitag;\n\tIOInterruptEventSource *sc_ih;\n\tint sc_msix;\n\n\t/* TX/RX rings. */\n\tstruct iwx_tx_ring txq[IWX_MAX_TVQM_QUEUES];\n\tstruct iwx_rx_ring rxq;\n\tint qfullmsk;\n    struct iwx_tx_ring sc_tvqm_ring;\n    int first_data_qid;\n\n\tint sc_sf_state;\n\n\t/* ICT table. */\n\tstruct iwx_dma_info\tict_dma;\n\tint\t\t\tict_cur;\n    uint32_t sku_id[3];\n\n\tint sc_hw_rev;\n#define IWX_SILICON_A_STEP\t0\n#define IWX_SILICON_B_STEP\t1\n#define IWX_SILICON_C_STEP\t2\n#define IWX_SILICON_D_STEP\t3\n    int sc_hw_rf_id;\n\tint sc_hw_id;\n    const struct iwl_cfg_trans_params *sc_cfg_params;\n    const struct iwl_cfg *sc_cfg;\n\tint sc_device_family;\n#define IWX_DEVICE_FAMILY_22000\t1\n#define IWX_DEVICE_FAMILY_AX210\t2\n\n\tstruct iwx_dma_info ctxt_info_dma;\n\tstruct iwx_self_init_dram init_dram;\n    /* For gen3 */\n    struct iwx_dma_info prph_scratch_dma;\n    struct iwx_dma_info prph_info_dma;\n    struct iwx_dma_info iml_dma;\n    struct iwx_dma_info pnvm_dram;\n\n\tint sc_fw_chunk_done;\n\tint sc_init_complete;\n#define IWX_INIT_COMPLETE\t0x01\n#define IWX_CALIB_COMPLETE\t0x02\n\n\tstruct iwx_ucode_status sc_uc;\n\tchar sc_fwver[32];\n\n\tint sc_capaflags;\n\tint sc_capa_max_probe_len;\n\tint sc_capa_n_scan_channels;\n    int sc_capa_num_stations;\n\tuint8_t sc_ucode_api[howmany(IWX_NUM_UCODE_TLV_API, NBBY)];\n\tuint8_t sc_enabled_capa[howmany(IWX_NUM_UCODE_TLV_CAPA, NBBY)];\n#define IWX_MAX_FW_CMD_VERSIONS\t800\n\tstruct iwx_fw_cmd_version cmd_versions[IWX_MAX_FW_CMD_VERSIONS];\n\tint n_cmd_versions;\n    char sc_fw_mcc[3];\n    uint16_t sc_fw_mcc_int;\n#define IWX_IML_MAX_LEN 2048*10\n    uint32_t sc_iml_len;\n    uint8_t sc_iml[IWX_IML_MAX_LEN];\n\n\tint sc_intmask;\n\tint sc_flags;\n\n\tuint32_t sc_fh_init_mask;\n\tuint32_t sc_hw_init_mask;\n\tuint32_t sc_fh_mask;\n\tuint32_t sc_hw_mask;\n\n\tint sc_generation;\n\n//\tstruct rwlock ioctl_rwl;\n\n\tint sc_cap_off; /* PCIe caps */\n\n\tconst char *sc_fwname;\n\tstruct iwx_fw_info sc_fw;\n\tstruct iwx_dma_info fw_mon;\n\tint sc_fw_phy_config;\n\tstruct iwx_tlv_calib_ctrl sc_default_calib[IWX_UCODE_TYPE_MAX];\n\n\tstruct iwx_nvm_data sc_nvm;\n\tstruct iwx_bf_data sc_bf;\n\n\tint sc_tx_timer;\n\tint sc_rx_ba_sessions;\n\n\tint sc_scan_last_antenna;\n\n\tint sc_fixed_ridx;\n    \n    uint8_t sc_mgmt_last_antenna_idx; /* for MGMT frames using*/\n\n\tint sc_staid;\n\tint sc_nodecolor;\n\n\tuint8_t *sc_cmd_resp_pkt[IWX_TFD_QUEUE_SIZE_MAX_GEN3];\t\n\tsize_t sc_cmd_resp_len[IWX_TFD_QUEUE_SIZE_MAX_GEN3];\n\tint sc_nic_locks;\n\n\tstruct taskq *sc_nswq;\n\n\tstruct iwx_rx_phy_info sc_last_phy_info;\n    int sc_ampdu_ref;\n#define IWX_MAX_BAID    32\n    struct iwx_rxba_data sc_rxba_data[IWX_MAX_BAID];\n\n\tuint32_t sc_time_event_uid;\n\n\t/* phy contexts.  we only use the first one */\n\tstruct iwx_phy_ctxt sc_phyctxt[IWX_NUM_PHY_CTX];\n\n\tint sc_noise;\n\n    int sc_pm_support;\n\tint sc_ltr_enabled;\n\n\tint sc_integrated;\n\tint sc_tx_with_siso_diversity;\n\tint sc_max_tfd_queue_size;\n    int sc_ltr_delay;\n    int sc_xtal_latency;\n    int sc_low_latency_xtal;\n    \n    int sc_uhb_supported;\n\n#if NBPFILTER > 0\n\tcaddr_t\t\t\tsc_drvbpf;\n\n\tunion {\n\t\tstruct iwx_rx_radiotap_header th;\n\t\tuint8_t\tpad[IEEE80211_RADIOTAP_HDRLEN];\n\t} sc_rxtapu;\n#define sc_rxtap\tsc_rxtapu.th\n\tint\t\t\tsc_rxtap_len;\n\n\tunion {\n\t\tstruct iwx_tx_radiotap_header th;\n\t\tuint8_t\tpad[IEEE80211_RADIOTAP_HDRLEN];\n\t} sc_txtapu;\n#define sc_txtap\tsc_txtapu.th\n\tint\t\t\tsc_txtap_len;\n#endif\n};\n\nstruct iwx_node {\n\tstruct ieee80211_node in_ni;\n\tstruct iwx_phy_ctxt *in_phyctxt;\n    uint8_t in_macaddr[ETHER_ADDR_LEN];\n\n\tuint16_t in_id;\n\tuint16_t in_color;\n    \n    struct iwx_rxq_dup_data dup_data;\n};\n#define IWX_STATION_ID 0\n#define IWX_AUX_STA_ID 1\n#define IWX_MONITOR_STA_ID 2\n\n#define IWX_ICT_SIZE\t\t4096\n#define IWX_ICT_COUNT\t\t(IWX_ICT_SIZE / sizeof (uint32_t))\n#define IWX_ICT_PADDR_SHIFT\t12\n"
  },
  {
    "path": "itlwm/itlwm.cpp",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n#include \"itlwm.hpp\"\n#include <linux/types.h>\n#include <linux/kernel.h>\n\n#include <IOKit/IOInterruptController.h>\n#include <IOKit/IOCommandGate.h>\n#include <IOKit/network/IONetworkMedium.h>\n#include <net/ethernet.h>\n#include <crypto/sha1.h>\n#include <net80211/ieee80211_node.h>\n#include <net80211/ieee80211_ioctl.h>\n\n#define super IOEthernetController\nOSDefineMetaClassAndStructors(itlwm, IOEthernetController)\nOSDefineMetaClassAndStructors(CTimeout, OSObject)\n\nIOWorkLoop *_fWorkloop;\nIOCommandGate *_fCommandGate;\n\nbool itlwm::init(OSDictionary *properties)\n{\n    return super::init(properties);\n}\n\n#define  PCI_MSI_FLAGS        2    /* Message Control */\n#define  PCI_CAP_ID_MSI        0x05    /* Message Signalled Interrupts */\n#define  PCI_MSIX_FLAGS        2    /* Message Control */\n#define  PCI_CAP_ID_MSIX    0x11    /* MSI-X */\n#define  PCI_MSIX_FLAGS_ENABLE    0x8000    /* MSI-X enable */\n#define  PCI_MSI_FLAGS_ENABLE    0x0001    /* MSI feature enabled */\n\nstatic void pciMsiSetEnable(IOPCIDevice *device, UInt8 msiCap, int enable)\n{\n    u16 control;\n    \n    control = device->configRead16(msiCap + PCI_MSI_FLAGS);\n    control &= ~PCI_MSI_FLAGS_ENABLE;\n    if (enable)\n        control |= PCI_MSI_FLAGS_ENABLE;\n    device->configWrite16(msiCap + PCI_MSI_FLAGS, control);\n}\n\nstatic void pciMsiXClearAndSet(IOPCIDevice *device, UInt8 msixCap, UInt16 clear, UInt16 set)\n{\n    u16 ctrl;\n    \n    ctrl = device->configRead16(msixCap + PCI_MSIX_FLAGS);\n    ctrl &= ~clear;\n    ctrl |= set;\n    device->configWrite16(msixCap + PCI_MSIX_FLAGS, ctrl);\n}\n\nIOService* itlwm::probe(IOService *provider, SInt32 *score)\n{\n    bool isMatch = false;\n    super::probe(provider, score);\n    UInt8 msiCap;\n    UInt8 msixCap;\n    IOPCIDevice* device = OSDynamicCast(IOPCIDevice, provider);\n    if (!device) {\n        return NULL;\n    }\n    if (ItlIwx::iwx_match(device)) {\n        isMatch = true;\n        fHalService = new ItlIwx;\n    }\n    if (!isMatch && ItlIwm::iwm_match(device)) {\n        isMatch = true;\n        fHalService = new ItlIwm;\n    }\n    if (!isMatch && ItlIwn::iwn_match(device)) {\n        isMatch = true;\n        fHalService = new ItlIwn;\n    }\n    if (isMatch) {\n        device->findPCICapability(PCI_CAP_ID_MSIX, &msixCap);\n        if (msixCap) {\n            pciMsiXClearAndSet(device, msixCap, PCI_MSIX_FLAGS_ENABLE, 0);\n        }\n        device->findPCICapability(PCI_CAP_ID_MSI, &msiCap);\n        if (msiCap) {\n            pciMsiSetEnable(device, msiCap, 1);\n        }\n        if (!msiCap && !msixCap) {\n            XYLog(\"%s No MSI cap\\n\", __FUNCTION__);\n            fHalService->release();\n            fHalService = NULL;\n            return NULL;\n        }\n        return this;\n    }\n    return NULL;\n}\n\nbool itlwm::configureInterface(IONetworkInterface *netif)\n{\n    IONetworkData *nd;\n    struct _ifnet *ifp = &fHalService->get80211Controller()->ic_ac.ac_if;\n    \n    if (super::configureInterface(netif) == false) {\n        XYLog(\"super failed\\n\");\n        return false;\n    }\n    \n    nd = netif->getParameter(kIONetworkStatsKey);\n    if (!nd || !(fpNetStats = (IONetworkStats *)nd->getBuffer())) {\n        XYLog(\"network statistics buffer unavailable?\\n\");\n        return false;\n    }\n    ifp->netStat = fpNetStats;\n    ether_ifattach(ifp, OSDynamicCast(IOEthernetInterface, netif));\n    fpNetStats->collisions = 0;\n#ifdef __PRIVATE_SPI__\n    netif->configureOutputPullModel(fHalService->getDriverInfo()->getTxQueueSize(), 0, 0, IOEthernetInterface::kOutputPacketSchedulingModelNormal, 0);\n#endif\n    \n    return true;\n}\n\nstruct _ifnet *itlwm::getIfp()\n{\n    return &fHalService->get80211Controller()->ic_ac.ac_if;\n}\n\nIOEthernetInterface *itlwm::getNetworkInterface()\n{\n    return getIfp()->iface;\n}\n\nbool itlwm::createMediumTables(const IONetworkMedium **primary)\n{\n    IONetworkMedium    *medium;\n    \n    OSDictionary *mediumDict = OSDictionary::withCapacity(1);\n    if (mediumDict == NULL) {\n        XYLog(\"Cannot allocate OSDictionary\\n\");\n        return false;\n    }\n    \n    medium = IONetworkMedium::medium(kIOMediumEthernetAuto, 100 * 1000000);\n    IONetworkMedium::addMedium(mediumDict, medium);\n    medium->release();\n    if (primary) {\n        *primary = medium;\n    }\n    \n    bool result = publishMediumDictionary(mediumDict);\n    if (!result) {\n        XYLog(\"Cannot publish medium dictionary!\\n\");\n    }\n\n    mediumDict->release();\n    return result;\n}\n\nvoid itlwm::joinSSID(const char *ssid_name, const char *ssid_pwd)\n{\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    \n    if (strlen(ssid_pwd) == 0) {\n        memset(&nwkey, 0, sizeof(ieee80211_nwkey));\n        nwkey.i_wepon = IEEE80211_NWKEY_OPEN;\n        nwkey.i_defkid = 0;\n        memcpy(join.i_nwid, ssid_name, strlen(ssid_name));\n        join.i_len = strlen(ssid_name);\n        join.i_flags = IEEE80211_JOIN_NWKEY;\n    } else {\n        memset(&wpa, 0, sizeof(ieee80211_wpaparams));\n        wpa.i_enabled = 1;\n        wpa.i_ciphers = 0;\n        wpa.i_groupcipher = 0;\n        wpa.i_protos = IEEE80211_WPA_PROTO_WPA1 | IEEE80211_WPA_PROTO_WPA2;\n        wpa.i_akms = IEEE80211_WPA_AKM_PSK | IEEE80211_WPA_AKM_8021X | IEEE80211_WPA_AKM_SHA256_PSK | IEEE80211_WPA_AKM_SHA256_8021X;\n        memcpy(wpa.i_name, \"zxy\", strlen(\"zxy\"));\n        memset(&psk, 0, sizeof(ieee80211_wpapsk));\n        memcpy(psk.i_name, \"zxy\", strlen(\"zxy\"));\n        psk.i_enabled = 1;\n        pbkdf2_sha1(ssid_pwd, (const uint8_t*)ssid_name, strlen(ssid_name),\n                    4096, psk.i_psk , 32);\n        memset(&nwkey, 0, sizeof(ieee80211_nwkey));\n        nwkey.i_wepon = 0;\n        nwkey.i_defkid = 0;\n        memset(&join, 0, sizeof(ieee80211_join));\n        join.i_wpaparams = wpa;\n        join.i_wpapsk = psk;\n        join.i_flags = IEEE80211_JOIN_WPAPSK | IEEE80211_JOIN_ANY | IEEE80211_JOIN_WPA | IEEE80211_JOIN_8021X;\n        join.i_nwkey = nwkey;\n        join.i_len = strlen(ssid_name);\n        memcpy(join.i_nwid, ssid_name, join.i_len);\n    }\n    if (ieee80211_add_ess(ic, &join) == 0)\n        ic->ic_flags |= IEEE80211_F_AUTO_JOIN;\n}\n\nvoid itlwm::associateSSID(const char *ssid, const char *pwd)\n{\n    struct ieee80211com *ic = fHalService->get80211Controller();\n    if (strlen(pwd) == 0) {\n        memcpy(nwid.i_nwid, ssid, 32);\n        nwid.i_len = strlen((char *)nwid.i_nwid);\n        memset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN);\n        ic->ic_des_esslen = nwid.i_len;\n        memcpy(ic->ic_des_essid, nwid.i_nwid, nwid.i_len);\n        if (ic->ic_des_esslen > 0) {\n            /* 'nwid' disables auto-join magic */\n            ic->ic_flags &= ~IEEE80211_F_AUTO_JOIN;\n        } else if (!TAILQ_EMPTY(&ic->ic_ess)) {\n            /* '-nwid' re-enables auto-join */\n            ic->ic_flags |= IEEE80211_F_AUTO_JOIN;\n        }\n        /* disable WPA/WEP */\n        ieee80211_disable_rsn(ic);\n        ieee80211_disable_wep(ic);\n    } else {\n        memset(&psk, 0, sizeof(psk));\n        memcpy(nwid.i_nwid, ssid, 32);\n        nwid.i_len = strlen((char *)nwid.i_nwid);\n        memset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN);\n        ic->ic_des_esslen = nwid.i_len;\n        memcpy(ic->ic_des_essid, nwid.i_nwid, nwid.i_len);\n        if (ic->ic_des_esslen > 0) {\n            /* 'nwid' disables auto-join magic */\n            ic->ic_flags &= ~IEEE80211_F_AUTO_JOIN;\n        } else if (!TAILQ_EMPTY(&ic->ic_ess)) {\n            /* '-nwid' re-enables auto-join */\n            ic->ic_flags |= IEEE80211_F_AUTO_JOIN;\n        }\n        /* disable WPA/WEP */\n        ieee80211_disable_rsn(ic);\n        ieee80211_disable_wep(ic);\n        size_t passlen = strlen(pwd);\n        /* Parse a WPA passphrase */\n        if (passlen < 8 || passlen > 63)\n            XYLog(\"wpakey: passphrase must be between \"\n                  \"8 and 63 characters\");\n        if (nwid.i_len == 0)\n            XYLog(\"wpakey: nwid not set\");\n        pbkdf2_sha1(pwd, (const uint8_t*)ssid, nwid.i_len, 4096,\n                    psk.i_psk, 32);\n        psk.i_enabled = 1;\n        if (psk.i_enabled) {\n            ic->ic_flags |= IEEE80211_F_PSK;\n            memcpy(ic->ic_psk, psk.i_psk, sizeof(ic->ic_psk));\n            if (ic->ic_flags & IEEE80211_F_WEPON)\n                ieee80211_disable_wep(ic);\n        } else {\n            ic->ic_flags &= ~IEEE80211_F_PSK;\n            memset(ic->ic_psk, 0, sizeof(ic->ic_psk));\n        }\n        memset(&wpa, 0, sizeof(wpa));\n        ieee80211_ioctl_getwpaparms(ic, &wpa);\n        wpa.i_enabled = psk.i_enabled;\n        wpa.i_ciphers = 0;\n        wpa.i_groupcipher = 0;\n        wpa.i_protos = IEEE80211_WPA_PROTO_WPA1 | IEEE80211_WPA_PROTO_WPA2;\n        wpa.i_akms = IEEE80211_WPA_AKM_PSK | IEEE80211_WPA_AKM_8021X | IEEE80211_WPA_AKM_SHA256_PSK | IEEE80211_WPA_AKM_SHA256_8021X;\n        ieee80211_ioctl_setwpaparms(ic, &wpa);\n    }\n    if (ic->ic_state > IEEE80211_S_AUTH && ic->ic_bss != NULL)\n        IEEE80211_SEND_MGMT(ic, ic->ic_bss, IEEE80211_FC0_SUBTYPE_DEAUTH, IEEE80211_REASON_AUTH_LEAVE);\n    ieee80211_del_ess(ic, NULL, 0, 1);\n    struct ieee80211_node *selbs = ieee80211_node_choose_bss(ic, 0, NULL);\n    if (selbs == NULL) {\n        if (ic->ic_state != IEEE80211_S_SCAN) {\n            ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);\n        }\n    } else {\n        if (ic->ic_state > IEEE80211_S_AUTH) {\n            ieee80211_node_join_bss(ic, selbs, 1);\n            fHalService->getDriverController()->clearScanningFlags();\n        } else {\n            if (ic->ic_state != IEEE80211_S_SCAN) {\n                ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);\n            }\n        }\n    }\n}\n\nbool itlwm::start(IOService *provider)\n{\n    int boot_value = 0;\n    if (!super::start(provider)) {\n        return false;\n    }\n    pciNub = OSDynamicCast(IOPCIDevice, provider);\n    if (!pciNub) {\n        return false;\n    }\n    pciNub->setBusMasterEnable(true);\n    pciNub->setIOEnable(true);\n    pciNub->setMemoryEnable(true);\n    pciNub->configWrite8(0x41, 0);\n    if (pciNub->requestPowerDomainState(kIOPMPowerOn,\n                                        (IOPowerConnection *) getParentEntry(gIOPowerPlane), IOPMLowestState) != IOPMNoErr) {\n        return false;\n    }\n    if (initPCIPowerManagment(pciNub) == false) {\n        super::stop(pciNub);\n        return false;\n    }\n    if (_fWorkloop == NULL) {\n        XYLog(\"No _fWorkloop!!\\n\");\n        super::stop(pciNub);\n        releaseAll();\n        return false;\n    }\n    _fCommandGate = IOCommandGate::commandGate(this, (IOCommandGate::Action)itlwm::tsleepHandler);\n    if (_fCommandGate == 0) {\n        XYLog(\"No command gate!!\\n\");\n        super::stop(pciNub);\n        releaseAll();\n        return false;\n    }\n    _fWorkloop->addEventSource(_fCommandGate);\n    const IONetworkMedium *primaryMedium;\n    if (!createMediumTables(&primaryMedium) ||\n        !setCurrentMedium(primaryMedium) || !setSelectedMedium(primaryMedium)) {\n        XYLog(\"setup medium fail\\n\");\n        releaseAll();\n        return false;\n    }\n    fHalService->initWithController(this, _fWorkloop, _fCommandGate);\n    \n    if (PE_parse_boot_argn(\"-novht\", &boot_value, sizeof(boot_value)))\n        fHalService->get80211Controller()->ic_userflags |= IEEE80211_F_NOVHT;\n    if (PE_parse_boot_argn(\"-noht40\", &boot_value, sizeof(boot_value)))\n        fHalService->get80211Controller()->ic_userflags |= IEEE80211_F_NOHT40;\n    \n    if (!fHalService->attach(pciNub)) {\n        XYLog(\"attach fail\\n\");\n        super::stop(pciNub);\n        releaseAll();\n        return false;\n    }\n    if (!attachInterface((IONetworkInterface **)&fNetIf, true)) {\n        XYLog(\"attach to interface fail\\n\");\n        fHalService->detach(pciNub);\n        super::stop(pciNub);\n        releaseAll();\n        return false;\n    }\n    fWatchdogWorkLoop = IOWorkLoop::workLoop();\n    if (fWatchdogWorkLoop == NULL) {\n        XYLog(\"init watchdog workloop fail\\n\");\n        fHalService->detach(pciNub);\n        super::stop(pciNub);\n        releaseAll();\n        return false;\n    }\n    watchdogTimer = IOTimerEventSource::timerEventSource(this, OSMemberFunctionCast(IOTimerEventSource::Action, this, &itlwm::watchdogAction));\n    if (!watchdogTimer) {\n        XYLog(\"init watchdog fail\\n\");\n        fHalService->detach(pciNub);\n        super::stop(pciNub);\n        releaseAll();\n        return false;\n    }\n    fWatchdogWorkLoop->addEventSource(watchdogTimer);\n    setLinkStatus(kIONetworkLinkValid);\n    OSObject *wifiEntryObject = NULL;\n    OSDictionary *wifiEntry = NULL;\n    OSString *entryKey = NULL;\n    OSDictionary *wifiDict = OSDynamicCast(OSDictionary, getProperty(\"WiFiConfig\"));\n    if (wifiDict != NULL) {\n        OSCollectionIterator *iterator = OSCollectionIterator::withCollection(wifiDict);\n        while ((wifiEntryObject = iterator->getNextObject())) {\n            entryKey = OSDynamicCast(OSString, wifiEntryObject);\n            if (entryKey == NULL) {\n                continue;\n            }\n            wifiEntry = OSDynamicCast(OSDictionary, wifiDict->getObject(entryKey));\n            if (wifiEntry == NULL) {\n                continue;\n            }\n            OSString *ssidObj = OSDynamicCast(OSString, wifiEntry->getObject(\"ssid\"));\n            OSString *pwdObj = OSDynamicCast(OSString, wifiEntry->getObject(\"password\"));\n            if (ssidObj == NULL || pwdObj == NULL || ssidObj->isEqualTo(\"\")) {\n                continue;\n            }\n            \n            joinSSID(ssidObj->getCStringNoCopy(), pwdObj->getCStringNoCopy());\n        }\n        iterator->release();\n    }\n    if (TAILQ_EMPTY(&fHalService->get80211Controller()->ic_ess)) {\n        fHalService->get80211Controller()->ic_flags |= IEEE80211_F_AUTO_JOIN;\n    }\n    registerService();\n    fNetIf->registerService();\n    return true;\n}\n\nvoid itlwm::watchdogAction(IOTimerEventSource *timer)\n{\n    struct _ifnet *ifp = getIfp();\n    (*ifp->if_watchdog)(ifp);\n    watchdogTimer->setTimeoutMS(kWatchDogTimerPeriod);\n}\n\nconst OSString * itlwm::newVendorString() const\n{\n    return OSString::withCString(\"Apple\");\n}\n\nconst OSString * itlwm::newModelString() const\n{\n    return OSString::withCString(\"Intel Wireless Card\");\n}\n\nbool itlwm::initPCIPowerManagment(IOPCIDevice *provider)\n{\n    UInt16 reg16;\n\n    reg16 = provider->configRead16(kIOPCIConfigCommand);\n\n    reg16 |= ( kIOPCICommandBusMaster       |\n               kIOPCICommandMemorySpace     |\n               kIOPCICommandMemWrInvalidate );\n\n    reg16 &= ~kIOPCICommandIOSpace;  // disable I/O space\n\n    provider->configWrite16( kIOPCIConfigCommand, reg16 );\n    provider->findPCICapability(kIOPCIPowerManagementCapability,\n                                &pmPCICapPtr);\n    if (pmPCICapPtr) {\n        UInt16 pciPMCReg = provider->configRead32( pmPCICapPtr ) >> 16;\n        if (pciPMCReg & kPCIPMCPMESupportFromD3Cold) {\n            magicPacketSupported = true;\n        }\n        provider->configWrite16((pmPCICapPtr + 4), 0x8000 );\n        IOSleep(10);\n    }\n    return true;\n}\n\nbool itlwm::createWorkLoop()\n{\n    _fWorkloop = IOWorkLoop::workLoop();\n    return _fWorkloop != 0;\n}\n\nIOWorkLoop *itlwm::getWorkLoop() const\n{\n    return _fWorkloop;\n}\n\nIOReturn itlwm::selectMedium(const IONetworkMedium *medium) {\n    setSelectedMedium(medium);\n    return kIOReturnSuccess;\n}\n\nvoid itlwm::stop(IOService *provider)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    struct _ifnet *ifp = &fHalService->get80211Controller()->ic_ac.ac_if;\n    super::stop(provider);\n    setLinkStatus(kIONetworkLinkValid);\n    fHalService->detach(pciNub);\n    ether_ifdetach(ifp);\n    detachInterface(fNetIf, true);\n    OSSafeReleaseNULL(fNetIf);\n    releaseAll();\n}\n\nvoid itlwm::releaseAll()\n{\n    if (fHalService) {\n        fHalService->release();\n        fHalService = NULL;\n    }\n    if (_fWorkloop) {\n        if (_fCommandGate) {\n//            _fCommandGate->disable();\n            _fWorkloop->removeEventSource(_fCommandGate);\n            _fCommandGate->release();\n            _fCommandGate = NULL;\n        }\n        if (fWatchdogWorkLoop && watchdogTimer) {\n            watchdogTimer->cancelTimeout();\n            fWatchdogWorkLoop->removeEventSource(watchdogTimer);\n            watchdogTimer->release();\n            watchdogTimer = NULL;\n            fWatchdogWorkLoop->release();\n            fWatchdogWorkLoop = NULL;\n        }\n        _fWorkloop->release();\n        _fWorkloop = NULL;\n    }\n    unregistPM();\n}\n\nvoid itlwm::free()\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    if (fHalService != NULL) {\n        fHalService->release();\n        fHalService = NULL;\n    }\n    super::free();\n}\n\nIOReturn itlwm::enable(IONetworkInterface *netif)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    super::enable(netif);\n    _fCommandGate->enable();\n    fHalService->enable(netif);\n    watchdogTimer->setTimeoutMS(kWatchDogTimerPeriod);\n    watchdogTimer->enable();\n    return kIOReturnSuccess;\n}\n\nIOReturn itlwm::disable(IONetworkInterface *netif)\n{\n    XYLog(\"%s\\n\", __FUNCTION__);\n    super::disable(netif);\n    watchdogTimer->cancelTimeout();\n    watchdogTimer->disable();\n    fHalService->disable(netif);\n    setLinkStatus(kIONetworkLinkValid);\n    return kIOReturnSuccess;\n}\n\nbool itlwm::\nsetLinkStatus(UInt32 status, const IONetworkMedium * activeMedium, UInt64 speed, OSData * data)\n{\n    _ifnet *ifq = &fHalService->get80211Controller()->ic_ac.ac_if;\n    bool ret = super::setLinkStatus(status, activeMedium, speed, data);\n    if (fNetIf) {\n        if (status & kIONetworkLinkActive) {\n#ifdef __PRIVATE_SPI__\n            fNetIf->startOutputThread();\n#endif\n        } else if (!(status & kIONetworkLinkNoNetworkChange)) {\n#ifdef __PRIVATE_SPI__\n            fNetIf->stopOutputThread();\n            fNetIf->flushOutputQueue();\n#endif\n            ifq_flush(&ifq->if_snd);\n            mq_purge(&fHalService->get80211Controller()->ic_mgtq);\n        }\n    }\n    return ret;\n}\n\nIOReturn itlwm::getHardwareAddress(IOEthernetAddress *addrP)\n{\n    if (IEEE80211_ADDR_EQ(etheranyaddr, fHalService->get80211Controller()->ic_myaddr)) {\n        return kIOReturnError;\n    } else {\n        IEEE80211_ADDR_COPY(addrP, fHalService->get80211Controller()->ic_myaddr);\n        return kIOReturnSuccess;\n    }\n}\n\nIOReturn itlwm::setHardwareAddress(const IOEthernetAddress *addrP)\n{\n    if (!fNetIf || !addrP)\n        return kIOReturnError;\n    if_setlladdr(&fHalService->get80211Controller()->ic_ac.ac_if, addrP->bytes);\n    if (fHalService->get80211Controller()->ic_state > IEEE80211_S_INIT) {\n        fHalService->disable(fNetIf);\n        fHalService->enable(fNetIf);\n    }\n    return kIOReturnSuccess;\n}\n\n#ifdef __PRIVATE_SPI__\nIOReturn itlwm::outputStart(IONetworkInterface *interface, IOOptionBits options)\n{\n    struct _ifnet *ifp = &fHalService->get80211Controller()->ic_ac.ac_if;\n    mbuf_t m = NULL;\n    if (ifq_is_oactive(&ifp->if_snd))\n        return kIOReturnNoResources;\n    while (kIOReturnSuccess == interface->dequeueOutputPackets(1, &m)) {\n        if (outputPacket(m, NULL)!= kIOReturnOutputSuccess ||\n            ifq_is_oactive(&ifp->if_snd))\n            return kIOReturnNoResources;\n    }\n    return kIOReturnSuccess;\n}\n#endif\n\nUInt32 itlwm::outputPacket(mbuf_t m, void *param)\n{\n//    XYLog(\"%s\\n\", __FUNCTION__);\n    IOReturn ret = kIOReturnOutputSuccess;\n    _ifnet *ifp = &fHalService->get80211Controller()->ic_ac.ac_if;\n\n    if (fHalService->get80211Controller()->ic_state != IEEE80211_S_RUN || ifp->if_snd.queue == NULL) {\n        if (m && mbuf_type(m) != MBUF_TYPE_FREE) {\n            freePacket(m);\n        }\n        return kIOReturnOutputDropped;\n    }\n    if (m == NULL) {\n        XYLog(\"%s m==NULL!!\\n\", __FUNCTION__);\n        ifp->netStat->outputErrors++;\n        ret = kIOReturnOutputDropped;\n    }\n    if (!(mbuf_flags(m) & MBUF_PKTHDR) ){\n        XYLog(\"%s pkthdr is NULL!!\\n\", __FUNCTION__);\n        ifp->netStat->outputErrors++;\n        freePacket(m);\n        ret = kIOReturnOutputDropped;\n    }\n    if (mbuf_type(m) == MBUF_TYPE_FREE) {\n        XYLog(\"%s mbuf is FREE!!\\n\", __FUNCTION__);\n        ifp->netStat->outputErrors++;\n        ret = kIOReturnOutputDropped;\n    }\n    if (!ifp->if_snd.queue->lockEnqueue(m)) {\n        freePacket(m);\n        ret = kIOReturnOutputDropped;\n    }\n    (*ifp->if_start)(ifp);\n    return ret;\n}\n\nUInt32 itlwm::getFeatures() const\n{\n    return fHalService->getDriverInfo()->supportedFeatures();\n}\n\nIOReturn itlwm::setPromiscuousMode(IOEnetPromiscuousMode mode)\n{\n    return kIOReturnSuccess;\n}\n\nIOReturn itlwm::setMulticastMode(IOEnetMulticastMode mode)\n{\n    return kIOReturnSuccess;\n}\n\nIOReturn itlwm::setMulticastList(IOEthernetAddress* addr, UInt32 len)\n{\n    return fHalService->getDriverController()->setMulticastList(addr, len);\n}\n\nIOReturn itlwm::getPacketFilters(const OSSymbol *group, UInt32 *filters) const\n{\n    IOReturn    rtn = kIOReturnSuccess;\n    if (group == gIOEthernetWakeOnLANFilterGroup && magicPacketSupported) {\n        *filters = kIOEthernetWakeOnMagicPacket;\n    } else if (group == gIONetworkFilterGroup) {\n        *filters = kIOPacketFilterMulticast | kIOPacketFilterPromiscuous;\n    } else {\n        rtn = IOEthernetController::getPacketFilters(group, filters);\n    }\n    return rtn;\n}\n\nIOReturn itlwm::\ntsleepHandler(OSObject* owner, void* arg0, void* arg1, void* arg2, void* arg3)\n{\n    itlwm* dev = OSDynamicCast(itlwm, owner);\n    if (dev == 0)\n        return kIOReturnError;\n    \n    if (arg1 == 0) {\n        if (_fCommandGate->commandSleep(arg0, THREAD_INTERRUPTIBLE) == THREAD_AWAKENED)\n            return kIOReturnSuccess;\n        else\n            return kIOReturnTimeout;\n    } else {\n        AbsoluteTime deadline;\n        clock_interval_to_deadline((*(int*)arg1), kNanosecondScale, reinterpret_cast<uint64_t*> (&deadline));\n        if (_fCommandGate->commandSleep(arg0, deadline, THREAD_INTERRUPTIBLE) == THREAD_AWAKENED)\n            return kIOReturnSuccess;\n        else\n            return kIOReturnTimeout;\n    }\n}\n"
  },
  {
    "path": "itlwm/itlwm.hpp",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n#include <compat.h>\n#include \"itlhdr.h\"\n#include <linux/kernel.h>\n\n#include <IOKit/network/IOEthernetController.h>\n#include <IOKit/IOWorkLoop.h>\n#include <IOKit/network/IOGatedOutputQueue.h>\n#include <libkern/c++/OSString.h>\n#include <IOKit/IOService.h>\n#include <IOKit/pci/IOPCIDevice.h>\n#include <IOKit/IOLib.h>\n#include <libkern/OSKextLib.h>\n#include <libkern/c++/OSMetaClass.h>\n#include <IOKit/IOFilterInterruptEventSource.h>\n\n#include \"ItlIwm.hpp\"\n#include \"ItlIwx.hpp\"\n#include \"ItlIwn.hpp\"\n\nenum\n{\n    kPowerStateOff = 0,\n    kPowerStateOn,\n    kPowerStateCount\n};\n\n#define kWatchDogTimerPeriod 1000\n\nclass itlwm : public IOEthernetController {\n    OSDeclareDefaultStructors(itlwm)\n    \npublic:\n    \n    //kext\n    virtual bool init(OSDictionary *properties) override;\n    virtual void free() override;\n    virtual IOService* probe(IOService* provider, SInt32* score) override;\n    virtual bool start(IOService *provider) override;\n    virtual void stop(IOService *provider) override;\n    virtual IOReturn getHardwareAddress(IOEthernetAddress* addrP) override;\n    virtual IOReturn setHardwareAddress(const IOEthernetAddress * addrP) override;\n    virtual IOReturn enable(IONetworkInterface *netif) override;\n    virtual IOReturn disable(IONetworkInterface *netif) override;\n    virtual UInt32 outputPacket(mbuf_t, void * param) override;\n    virtual IOReturn setPromiscuousMode(IOEnetPromiscuousMode mode) override;\n    virtual IOReturn setMulticastMode(IOEnetMulticastMode mode) override;\n    virtual IOReturn setMulticastList(IOEthernetAddress* addr, UInt32 len) override;\n    virtual bool configureInterface(IONetworkInterface *netif) override;\n    virtual bool createWorkLoop() override;\n    virtual IOWorkLoop* getWorkLoop() const override;\n    virtual const OSString * newVendorString() const override;\n    virtual const OSString * newModelString() const override;\n    virtual bool setLinkStatus(\n                               UInt32                  status,\n                               const IONetworkMedium * activeMedium = 0,\n                               UInt64                  speed        = 0,\n                               OSData *                data         = 0) override;\n#ifdef __PRIVATE_SPI__\n    virtual IOReturn outputStart(IONetworkInterface *interface, IOOptionBits options) override;\n#endif\n    virtual IOReturn getPacketFilters(const OSSymbol *group, UInt32 *filters) const override;\n    virtual IOReturn selectMedium(const IONetworkMedium *medium) override;\n    virtual UInt32 getFeatures() const override;\n    virtual IOReturn registerWithPolicyMaker( IOService * policyMaker ) override;\n    virtual IOReturn setPowerState( unsigned long powerStateOrdinal,\n                                    IOService *   policyMaker) override;\n    virtual IOReturn setWakeOnMagicPacket( bool active ) override;\n    \n    void releaseAll();\n    void joinSSID(const char *ssid, const char *pwd);\n    void associateSSID(const char *ssid, const char *pwd);\n    void watchdogAction(IOTimerEventSource *timer);\n    \n    bool initPCIPowerManagment(IOPCIDevice *provider);\n    \n    struct _ifnet *getIfp();\n    IOEthernetInterface *getNetworkInterface();\n    \n    static IOReturn tsleepHandler(OSObject* owner, void* arg0 = 0, void* arg1 = 0, void* arg2 = 0, void* arg3 = 0);\n    void setPowerStateOff(void);\n    void setPowerStateOn(void);\n    void unregistPM();\n    \n    bool createMediumTables(const IONetworkMedium **primary);\n    \npublic:\n    IOInterruptEventSource* fInterrupt;\n    IOTimerEventSource *watchdogTimer;\n    IOPCIDevice *pciNub;\n    IONetworkStats *fpNetStats;\n    IOEthernetInterface *fNetIf;\n    IOWorkLoop *fWatchdogWorkLoop;\n    ItlHalService *fHalService;\n    \n    //pm\n    thread_call_t powerOnThreadCall;\n    thread_call_t powerOffThreadCall;\n    UInt32 pmPowerState;\n    IOService *pmPolicyMaker;\n    UInt8 pmPCICapPtr;\n    bool magicPacketEnabled;\n    bool magicPacketSupported;\n    \n    //connect params\n    struct ieee80211_wpaparams wpa;\n    struct ieee80211_wpapsk psk;\n    struct ieee80211_nwkey nwkey;\n    struct ieee80211_join join;\n    struct ieee80211_nwid nwid;\n};\n"
  },
  {
    "path": "itlwm/pm.cpp",
    "content": "/*\n* Copyright (C) 2020  钟先耀\n*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*/\n\n#include \"itlwm.hpp\"\n\nstatic IOPMPowerState powerStateArray[kPowerStateCount] =\n{\n    {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},\n    {1, kIOPMDeviceUsable, kIOPMPowerOn, kIOPMPowerOn, 0, 0, 0, 0, 0, 0, 0, 0}\n};\n\nvoid itlwm::unregistPM()\n{\n    if (powerOffThreadCall) {\n        thread_call_free(powerOffThreadCall);\n        powerOffThreadCall = NULL;\n    }\n    if (powerOnThreadCall) {\n        thread_call_free(powerOnThreadCall);\n        powerOnThreadCall = NULL;\n    }\n}\n\nIOReturn itlwm::setPowerState(unsigned long powerStateOrdinal, IOService *policyMaker)\n{\n    IOReturn result = IOPMAckImplied;\n    \n    if (pmPowerState == powerStateOrdinal) {\n        return result;\n    }\n    switch (powerStateOrdinal) {\n        case kPowerStateOff:\n            if (powerOffThreadCall) {\n                retain();\n                if (thread_call_enter(powerOffThreadCall)) {\n                    release();\n                }\n                result = 5000000;\n            }\n            break;\n        case kPowerStateOn:\n            if (powerOnThreadCall) {\n                retain();\n                if (thread_call_enter(powerOnThreadCall)) {\n                    release();\n                }\n                result = 5000000;\n            }\n            break;\n            \n        default:\n            break;\n    }\n    return result;\n}\n\nIOReturn itlwm::setWakeOnMagicPacket(bool active)\n{\n    magicPacketEnabled = active;\n    return kIOReturnSuccess;\n}\n\nstatic void handleSetPowerStateOff(thread_call_param_t param0,\n                             thread_call_param_t param1)\n{\n    itlwm *self = (itlwm *)param0;\n\n    if (param1 == 0)\n    {\n        self->getCommandGate()->runAction((IOCommandGate::Action)\n                                           handleSetPowerStateOff,\n                                           (void *) 1);\n    }\n    else\n    {\n        self->setPowerStateOff();\n        self->release();\n    }\n}\n\nstatic void handleSetPowerStateOn(thread_call_param_t param0,\n                            thread_call_param_t param1)\n{\n    itlwm *self = (itlwm *) param0;\n\n    if (param1 == 0)\n    {\n        self->getCommandGate()->runAction((IOCommandGate::Action)\n                                           handleSetPowerStateOn,\n                                           (void *) 1);\n    }\n    else\n    {\n        self->setPowerStateOn();\n        self->release();\n    }\n}\n\nIOReturn itlwm::registerWithPolicyMaker(IOService *policyMaker)\n{\n    IOReturn ret;\n    \n    pmPowerState = kPowerStateOn;\n    pmPolicyMaker = policyMaker;\n    \n    powerOffThreadCall = thread_call_allocate(\n                                            (thread_call_func_t)handleSetPowerStateOff,\n                                            (thread_call_param_t)this);\n    powerOnThreadCall  = thread_call_allocate(\n                                            (thread_call_func_t)handleSetPowerStateOn,\n                                              (thread_call_param_t)this);\n    ret = pmPolicyMaker->registerPowerDriver(this,\n                                             powerStateArray,\n                                             kPowerStateCount);\n    return ret;\n}\n\nvoid itlwm::setPowerStateOff()\n{\n    pmPowerState = kPowerStateOff;\n    pmPolicyMaker->acknowledgeSetPowerState();\n}\n\nvoid itlwm::setPowerStateOn()\n{\n    pmPowerState = kPowerStateOn;\n    pmPolicyMaker->acknowledgeSetPowerState();\n}\n"
  },
  {
    "path": "itlwm.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 48;\n\tobjects = {\n\n/* Begin PBXAggregateTarget section */\n\t\t5066D63825287F7900EE6F38 /* fw_gen */ = {\n\t\t\tisa = PBXAggregateTarget;\n\t\t\tbuildConfigurationList = 5066D63B25287F7900EE6F38 /* Build configuration list for PBXAggregateTarget \"fw_gen\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t5066D63C25287F8E00EE6F38 /* Generate Firmware */,\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = fw_gen;\n\t\t\tproductName = fw;\n\t\t};\n/* End PBXAggregateTarget section */\n\n/* Begin PBXBuildFile section */\n\t\t024A07B023FCBC3C009FBA6C /* itlwm.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 024A07AF23FCBC3C009FBA6C /* itlwm.hpp */; };\n\t\t024A07B223FCBC3C009FBA6C /* itlwm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A07B123FCBC3C009FBA6C /* itlwm.cpp */; };\n\t\t024A082E23FCBC6C009FBA6C /* aes.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07C923FCBC6C009FBA6C /* aes.c */; };\n\t\t024A082F23FCBC6C009FBA6C /* hmac.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CA23FCBC6C009FBA6C /* hmac.c */; };\n\t\t024A083023FCBC6C009FBA6C /* sha2.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CB23FCBC6C009FBA6C /* sha2.c */; };\n\t\t024A083123FCBC6C009FBA6C /* rijndael.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CC23FCBC6C009FBA6C /* rijndael.c */; };\n\t\t024A083223FCBC6C009FBA6C /* ecb3_enc.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CD23FCBC6C009FBA6C /* ecb3_enc.c */; };\n\t\t024A083323FCBC6C009FBA6C /* set_key.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CE23FCBC6C009FBA6C /* set_key.c */; };\n\t\t024A083423FCBC6C009FBA6C /* cast.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CF23FCBC6C009FBA6C /* cast.c */; };\n\t\t024A083523FCBC6C009FBA6C /* des_locl.h in Headers */ = {isa = PBXBuildFile; fileRef = 024A07D023FCBC6C009FBA6C /* des_locl.h */; };\n\t\t024A083623FCBC6C009FBA6C /* michael.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07D123FCBC6C009FBA6C /* michael.c */; };\n\t\t024A083723FCBC6C009FBA6C /* key_wrap.h in Headers */ = {isa = PBXBuildFile; fileRef = 024A07D223FCBC6C009FBA6C /* key_wrap.h */; };\n\t\t024A083823FCBC6C009FBA6C /* poly1305.h in Headers */ = {isa = PBXBuildFile; fileRef = 024A07D323FCBC6C009FBA6C /* poly1305.h */; };\n\t\t024A083923FCBC6C009FBA6C /* md5.h in Headers */ = {isa = PBXBuildFile; fileRef = 024A07D423FCBC6C009FBA6C /* md5.h */; };\n\t\t024A083A23FCBC6C009FBA6C /* blf.h in Headers */ = {isa = PBXBuildFile; fileRef = 024A07D523FCBC6C009FBA6C /* blf.h */; };\n\t\t024A083B23FCBC6C009FBA6C /* arc4.h in Headers */ = {isa = PBXBuildFile; fileRef = 024A07D623FCBC6C009FBA6C /* arc4.h */; };\n\t\t024A083C23FCBC6C009FBA6C /* chachapoly.h in Headers */ = {isa = PBXBuildFile; fileRef = 024A07D723FCBC6C009FBA6C /* chachapoly.h */; };\n\t\t024A083D23FCBC6C009FBA6C /* sha1.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07D823FCBC6C009FBA6C /* sha1.c */; };\n\t\t024A083E23FCBC6C009FBA6C /* sk.h in Headers */ = {isa = PBXBuildFile; fileRef = 024A07D923FCBC6C009FBA6C /* sk.h */; };\n\t\t024A083F23FCBC6C009FBA6C /* castsb.h in Headers */ = {isa = PBXBuildFile; fileRef = 024A07DA23FCBC6C009FBA6C /* castsb.h */; };\n\t\t024A084023FCBC6C009FBA6C /* rmd160.h in Headers */ = {isa = PBXBuildFile; fileRef = 024A07DB23FCBC6C009FBA6C /* rmd160.h */; };\n\t\t024A084123FCBC6C009FBA6C /* idgen.h in Headers */ = {isa = PBXBuildFile; fileRef = 024A07DC23FCBC6C009FBA6C /* idgen.h */; };\n\t\t024A084223FCBC6C009FBA6C /* cmac.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07DD23FCBC6C009FBA6C /* cmac.c */; };\n\t\t024A084323FCBC6C009FBA6C /* gmac.h in Headers */ = {isa = PBXBuildFile; fileRef = 024A07DE23FCBC6C009FBA6C /* gmac.h */; };\n\t\t024A084423FCBC6C009FBA6C /* sha2.h in Headers */ = {isa = PBXBuildFile; fileRef = 024A07DF23FCBC6C009FBA6C /* sha2.h */; };\n\t\t024A084523FCBC6C009FBA6C /* hmac.h in Headers */ = {isa = PBXBuildFile; fileRef = 024A07E023FCBC6C009FBA6C /* hmac.h */; };\n\t\t024A084623FCBC6C009FBA6C /* aes.h in Headers */ = {isa = PBXBuildFile; fileRef = 024A07E123FCBC6C009FBA6C /* aes.h */; };\n\t\t024A084723FCBC6C009FBA6C /* cast.h in Headers */ = {isa = PBXBuildFile; fileRef = 024A07E223FCBC6C009FBA6C /* cast.h */; };\n\t\t024A084823FCBC6C009FBA6C /* michael.h in Headers */ = {isa = PBXBuildFile; fileRef = 024A07E323FCBC6C009FBA6C /* michael.h */; };\n\t\t024A084923FCBC6C009FBA6C /* ecb_enc.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07E423FCBC6C009FBA6C /* ecb_enc.c */; };\n\t\t024A084A23FCBC6C009FBA6C /* cryptodev.h in Headers */ = {isa = PBXBuildFile; fileRef = 024A07E523FCBC6C009FBA6C /* cryptodev.h */; };\n\t\t024A084B23FCBC6C009FBA6C /* rijndael.h in Headers */ = {isa = PBXBuildFile; fileRef = 024A07E623FCBC6C009FBA6C /* rijndael.h */; };\n\t\t024A084C23FCBC6C009FBA6C /* chacha_private.h in Headers */ = {isa = PBXBuildFile; fileRef = 024A07E723FCBC6C009FBA6C /* chacha_private.h */; };\n\t\t024A084D23FCBC6C009FBA6C /* sha1.h in Headers */ = {isa = PBXBuildFile; fileRef = 024A07E823FCBC6C009FBA6C /* sha1.h */; };\n\t\t024A084E23FCBC6C009FBA6C /* chachapoly.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07E923FCBC6C009FBA6C /* chachapoly.c */; };\n\t\t024A084F23FCBC6C009FBA6C /* md5.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07EA23FCBC6C009FBA6C /* md5.c */; };\n\t\t024A085023FCBC6C009FBA6C /* arc4.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07EB23FCBC6C009FBA6C /* arc4.c */; };\n\t\t024A085123FCBC6C009FBA6C /* blf.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07EC23FCBC6C009FBA6C /* blf.c */; };\n\t\t024A085223FCBC6C009FBA6C /* poly1305.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07ED23FCBC6C009FBA6C /* poly1305.c */; };\n\t\t024A085323FCBC6C009FBA6C /* spr.h in Headers */ = {isa = PBXBuildFile; fileRef = 024A07EE23FCBC6C009FBA6C /* spr.h */; };\n\t\t024A085423FCBC6C009FBA6C /* podd.h in Headers */ = {isa = PBXBuildFile; fileRef = 024A07EF23FCBC6C009FBA6C /* podd.h */; };\n\t\t024A085523FCBC6C009FBA6C /* key_wrap.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07F023FCBC6C009FBA6C /* key_wrap.c */; };\n\t\t024A085623FCBC6C009FBA6C /* cmac.h in Headers */ = {isa = PBXBuildFile; fileRef = 024A07F123FCBC6C009FBA6C /* cmac.h */; };\n\t\t024A085723FCBC6C009FBA6C /* gmac.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07F223FCBC6C009FBA6C /* gmac.c */; };\n\t\t024A085823FCBC6C009FBA6C /* rmd160.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07F323FCBC6C009FBA6C /* rmd160.c */; };\n\t\t024A085923FCBC6C009FBA6C /* idgen.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07F423FCBC6C009FBA6C /* idgen.c */; };\n\t\t024A088B23FCBE38009FBA6C /* if_iwmreg.h in Headers */ = {isa = PBXBuildFile; fileRef = 024A088923FCBE38009FBA6C /* if_iwmreg.h */; };\n\t\t024A088C23FCBE38009FBA6C /* if_iwmvar.h in Headers */ = {isa = PBXBuildFile; fileRef = 024A088A23FCBE38009FBA6C /* if_iwmvar.h */; };\n\t\t024A08BE23FCD314009FBA6C /* fw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08BD23FCD314009FBA6C /* fw.cpp */; };\n\t\t024A08C023FCD4E2009FBA6C /* utils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08BF23FCD4E2009FBA6C /* utils.cpp */; };\n\t\t024A08C223FCD999009FBA6C /* io.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C123FCD999009FBA6C /* io.cpp */; };\n\t\t024A08C423FCDC14009FBA6C /* rx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C323FCDC14009FBA6C /* rx.cpp */; };\n\t\t024A08C623FCDC3B009FBA6C /* tx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C523FCDC3B009FBA6C /* tx.cpp */; };\n\t\t024A08C823FCE2ED009FBA6C /* hw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C723FCE2ED009FBA6C /* hw.cpp */; };\n\t\t024A08CA23FCE537009FBA6C /* phy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C923FCE537009FBA6C /* phy.cpp */; };\n\t\t024A08CC23FCE5CA009FBA6C /* mac80211.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08CB23FCE5CA009FBA6C /* mac80211.cpp */; };\n\t\t024A08CE23FCE67F009FBA6C /* nvm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08CD23FCE67F009FBA6C /* nvm.cpp */; };\n\t\t024A08D023FCEE88009FBA6C /* ctxt.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08CF23FCEE88009FBA6C /* ctxt.cpp */; };\n\t\t024A08D223FCF395009FBA6C /* led.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08D123FCF395009FBA6C /* led.cpp */; };\n\t\t024A08D423FCF3E6009FBA6C /* power.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08D323FCF3E6009FBA6C /* power.cpp */; };\n\t\t024A08D623FCF4D7009FBA6C /* scan.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08D523FCF4D7009FBA6C /* scan.cpp */; };\n\t\t17FD7F10255E4AC800611406 /* ItlIwn.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 17FD7F0E255E4AC800611406 /* ItlIwn.cpp */; };\n\t\t17FD7F11255E4AC800611406 /* ItlIwn.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 17FD7F0F255E4AC800611406 /* ItlIwn.hpp */; };\n\t\t17FD7F63255E547100611406 /* ItlIwn.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 17FD7F0E255E4AC800611406 /* ItlIwn.cpp */; };\n\t\t17FD7F6A255E547100611406 /* ItlIwn.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 17FD7F0E255E4AC800611406 /* ItlIwn.cpp */; };\n\t\t17FD7F71255E547200611406 /* ItlIwn.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 17FD7F0E255E4AC800611406 /* ItlIwn.cpp */; };\n\t\t17FD7F78255E547200611406 /* ItlIwn.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 17FD7F0E255E4AC800611406 /* ItlIwn.cpp */; };\n\t\t17FD7F7F255E549500611406 /* if_iwnvar.h in Headers */ = {isa = PBXBuildFile; fileRef = 17FD7F0C255E4A0900611406 /* if_iwnvar.h */; };\n\t\t17FD7F86255E549900611406 /* if_iwnreg.h in Headers */ = {isa = PBXBuildFile; fileRef = 17FD7F0D255E4AB000611406 /* if_iwnreg.h */; };\n\t\t35CBE659251CB89700435CBC /* debug.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6C2225027609000F77FF /* debug.h */; };\n\t\t35CBE65A251CB89700435CBC /* IOSkywalkEthernetInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BD025021E66000F77FF /* IOSkywalkEthernetInterface.h */; };\n\t\t35CBE65B251CB89700435CBC /* apple80211_ioctl.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BC525021DEC000F77FF /* apple80211_ioctl.h */; };\n\t\t35CBE661251CB89700435CBC /* apple80211_var.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BC425021DEC000F77FF /* apple80211_var.h */; };\n\t\t35CBE664251CB89700435CBC /* AirportItlwmInterface.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F8CA44A225091AF60036119A /* AirportItlwmInterface.hpp */; };\n\t\t35CBE666251CB89700435CBC /* AirportItlwm.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BBB25021C9C000F77FF /* AirportItlwm.hpp */; };\n\t\t35CBE66F251CB89700435CBC /* apple80211_wps.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BC325021DEC000F77FF /* apple80211_wps.h */; };\n\t\t35CBE671251CB89700435CBC /* _mbuf.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8D257732495A33500872E4F /* _mbuf.cpp */; };\n\t\t35CBE672251CB89700435CBC /* _task.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8F9EDE0240B7415009CB8E7 /* _task.cpp */; };\n\t\t35CBE673251CB89700435CBC /* FwBinary.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5076FA7F24CC71E40011B2BB /* FwBinary.cpp */; };\n\t\t35CBE675251CB89700435CBC /* ieee80211_proto.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC2F24080319007A9422 /* ieee80211_proto.c */; };\n\t\t35CBE676251CB89700435CBC /* AirportItlwmInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8CA44A125091AF60036119A /* AirportItlwmInterface.cpp */; };\n\t\t35CBE677251CB89700435CBC /* _string.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3024080319007A9422 /* _string.c */; };\n\t\t35CBE678251CB89700435CBC /* ieee80211_ioctl.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3224080319007A9422 /* ieee80211_ioctl.c */; };\n\t\t35CBE679251CB89700435CBC /* ieee80211.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3324080319007A9422 /* ieee80211.c */; };\n\t\t35CBE67A251CB89700435CBC /* ieee80211_rssadapt.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3424080319007A9422 /* ieee80211_rssadapt.c */; };\n\t\t35CBE67B251CB89700435CBC /* ieee80211_input.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3524080319007A9422 /* ieee80211_input.c */; };\n\t\t35CBE67C251CB89700435CBC /* timeout.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3724080319007A9422 /* timeout.c */; };\n\t\t35CBE67D251CB89700435CBC /* ieee80211_mira.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3924080319007A9422 /* ieee80211_mira.c */; };\n\t\t35CBE67E251CB89700435CBC /* ieee80211_crypto_bip.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3B24080319007A9422 /* ieee80211_crypto_bip.c */; };\n\t\t35CBE67F251CB89700435CBC /* ieee80211_crypto_tkip.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3C24080319007A9422 /* ieee80211_crypto_tkip.c */; };\n\t\t35CBE680251CB89700435CBC /* ieee80211_crypto_ccmp.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3D24080319007A9422 /* ieee80211_crypto_ccmp.c */; };\n\t\t35CBE681251CB89700435CBC /* ieee80211_crypto_wep.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC462408031A007A9422 /* ieee80211_crypto_wep.c */; };\n\t\t35CBE682251CB89700435CBC /* ieee80211_pae_input.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3E24080319007A9422 /* ieee80211_pae_input.c */; };\n\t\t35CBE683251CB89700435CBC /* ieee80211_amrr.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC4024080319007A9422 /* ieee80211_amrr.c */; };\n\t\t35CBE684251CB89700435CBC /* ieee80211_output.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC472408031A007A9422 /* ieee80211_output.c */; };\n\t\t35CBE685251CB89700435CBC /* ieee80211_crypto.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC482408031A007A9422 /* ieee80211_crypto.c */; };\n\t\t35CBE686251CB89700435CBC /* CTimeout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC492408031A007A9422 /* CTimeout.cpp */; };\n\t\t35CBE687251CB89700435CBC /* ieee80211_regdomain.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC4B2408031A007A9422 /* ieee80211_regdomain.c */; };\n\t\t35CBE688251CB89700435CBC /* ieee80211_node.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC4C2408031A007A9422 /* ieee80211_node.c */; };\n\t\t35CBE689251CB89700435CBC /* ieee80211_pae_output.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC4D2408031A007A9422 /* ieee80211_pae_output.c */; };\n\t\t35CBE68A251CB89700435CBC /* sha1-pbkdf2.c in Sources */ = {isa = PBXBuildFile; fileRef = F88D2B3B2414E64000BBE700 /* sha1-pbkdf2.c */; };\n\t\t35CBE68B251CB89700435CBC /* aes.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07C923FCBC6C009FBA6C /* aes.c */; };\n\t\t35CBE68C251CB89700435CBC /* hmac.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CA23FCBC6C009FBA6C /* hmac.c */; };\n\t\t35CBE68D251CB89700435CBC /* sha2.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CB23FCBC6C009FBA6C /* sha2.c */; };\n\t\t35CBE68E251CB89700435CBC /* rijndael.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CC23FCBC6C009FBA6C /* rijndael.c */; };\n\t\t35CBE68F251CB89700435CBC /* ecb3_enc.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CD23FCBC6C009FBA6C /* ecb3_enc.c */; };\n\t\t35CBE690251CB89700435CBC /* set_key.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CE23FCBC6C009FBA6C /* set_key.c */; };\n\t\t35CBE691251CB89700435CBC /* cast.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CF23FCBC6C009FBA6C /* cast.c */; };\n\t\t35CBE692251CB89700435CBC /* michael.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07D123FCBC6C009FBA6C /* michael.c */; };\n\t\t35CBE693251CB89700435CBC /* sha1.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07D823FCBC6C009FBA6C /* sha1.c */; };\n\t\t35CBE694251CB89700435CBC /* cmac.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07DD23FCBC6C009FBA6C /* cmac.c */; };\n\t\t35CBE695251CB89700435CBC /* ecb_enc.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07E423FCBC6C009FBA6C /* ecb_enc.c */; };\n\t\t35CBE696251CB89700435CBC /* chachapoly.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07E923FCBC6C009FBA6C /* chachapoly.c */; };\n\t\t35CBE697251CB89700435CBC /* md5.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07EA23FCBC6C009FBA6C /* md5.c */; };\n\t\t35CBE698251CB89700435CBC /* arc4.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07EB23FCBC6C009FBA6C /* arc4.c */; };\n\t\t35CBE699251CB89700435CBC /* blf.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07EC23FCBC6C009FBA6C /* blf.c */; };\n\t\t35CBE69A251CB89700435CBC /* poly1305.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07ED23FCBC6C009FBA6C /* poly1305.c */; };\n\t\t35CBE69B251CB89700435CBC /* key_wrap.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07F023FCBC6C009FBA6C /* key_wrap.c */; };\n\t\t35CBE69C251CB89700435CBC /* gmac.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07F223FCBC6C009FBA6C /* gmac.c */; };\n\t\t35CBE69D251CB89700435CBC /* rmd160.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07F323FCBC6C009FBA6C /* rmd160.c */; };\n\t\t35CBE69E251CB89700435CBC /* idgen.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07F423FCBC6C009FBA6C /* idgen.c */; };\n\t\t35CBE69F251CB89700435CBC /* compat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A07BA23FCBC6C009FBA6C /* compat.cpp */; };\n\t\t35CBE6A0251CB89700435CBC /* zutil.c in Sources */ = {isa = PBXBuildFile; fileRef = F8FA0EED2501E8C100B1822E /* zutil.c */; };\n\t\t35CBE6A1251CB89700435CBC /* ItlHalService.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8D364F624F93AFD0029340B /* ItlHalService.cpp */; };\n\t\t35CBE6A2251CB89700435CBC /* ItlIwx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8D6CD642442E8F200D2A454 /* ItlIwx.cpp */; };\n\t\t35CBE6A3251CB89700435CBC /* utils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08BF23FCD4E2009FBA6C /* utils.cpp */; };\n\t\t35CBE6A4251CB89700435CBC /* fw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08BD23FCD314009FBA6C /* fw.cpp */; };\n\t\t35CBE6A5251CB89700435CBC /* io.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C123FCD999009FBA6C /* io.cpp */; };\n\t\t35CBE6A6251CB89700435CBC /* rx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C323FCDC14009FBA6C /* rx.cpp */; };\n\t\t35CBE6A7251CB89700435CBC /* tx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C523FCDC3B009FBA6C /* tx.cpp */; };\n\t\t35CBE6A8251CB89700435CBC /* hw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C723FCE2ED009FBA6C /* hw.cpp */; };\n\t\t35CBE6A9251CB89700435CBC /* phy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C923FCE537009FBA6C /* phy.cpp */; };\n\t\t35CBE6AA251CB89700435CBC /* mac80211.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08CB23FCE5CA009FBA6C /* mac80211.cpp */; };\n\t\t35CBE6AB251CB89700435CBC /* nvm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08CD23FCE67F009FBA6C /* nvm.cpp */; };\n\t\t35CBE6AC251CB89700435CBC /* ctxt.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08CF23FCEE88009FBA6C /* ctxt.cpp */; };\n\t\t35CBE6AD251CB89700435CBC /* led.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08D123FCF395009FBA6C /* led.cpp */; };\n\t\t35CBE6AE251CB89700435CBC /* power.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08D323FCF3E6009FBA6C /* power.cpp */; };\n\t\t35CBE6AF251CB89700435CBC /* scan.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08D523FCF4D7009FBA6C /* scan.cpp */; };\n\t\t35CBE6B0251CB89700435CBC /* ItlIwm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8AF3A2F24F9F35B008911C1 /* ItlIwm.cpp */; };\n\t\t35CBE6B1251CB89700435CBC /* AirportSTAIOCTL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F89B6BDC25022F8C000F77FF /* AirportSTAIOCTL.cpp */; };\n\t\t35CBE6B2251CB89700435CBC /* AirportItlwm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F89B6BBD25021C9C000F77FF /* AirportItlwm.cpp */; };\n\t\t35CBE6B3251CB89700435CBC /* AirportVirtualIOCTL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F89B6BDE25022FB5000F77FF /* AirportVirtualIOCTL.cpp */; };\n\t\t35CBE6B4251CB89700435CBC /* AirportAWDL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F89B6BE025022FC7000F77FF /* AirportAWDL.cpp */; };\n\t\t35CBE6C3251CB8BF00435CBC /* debug.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6C2225027609000F77FF /* debug.h */; };\n\t\t35CBE6C4251CB8BF00435CBC /* IOSkywalkEthernetInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BD025021E66000F77FF /* IOSkywalkEthernetInterface.h */; };\n\t\t35CBE6C5251CB8BF00435CBC /* apple80211_ioctl.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BC525021DEC000F77FF /* apple80211_ioctl.h */; };\n\t\t35CBE6CB251CB8BF00435CBC /* apple80211_var.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BC425021DEC000F77FF /* apple80211_var.h */; };\n\t\t35CBE6CE251CB8BF00435CBC /* AirportItlwmInterface.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F8CA44A225091AF60036119A /* AirportItlwmInterface.hpp */; };\n\t\t35CBE6D0251CB8BF00435CBC /* AirportItlwm.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BBB25021C9C000F77FF /* AirportItlwm.hpp */; };\n\t\t35CBE6D9251CB8BF00435CBC /* apple80211_wps.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BC325021DEC000F77FF /* apple80211_wps.h */; };\n\t\t35CBE6DB251CB8BF00435CBC /* _mbuf.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8D257732495A33500872E4F /* _mbuf.cpp */; };\n\t\t35CBE6DC251CB8BF00435CBC /* _task.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8F9EDE0240B7415009CB8E7 /* _task.cpp */; };\n\t\t35CBE6DD251CB8BF00435CBC /* FwBinary.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5076FA7F24CC71E40011B2BB /* FwBinary.cpp */; };\n\t\t35CBE6DF251CB8BF00435CBC /* ieee80211_proto.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC2F24080319007A9422 /* ieee80211_proto.c */; };\n\t\t35CBE6E0251CB8BF00435CBC /* AirportItlwmInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8CA44A125091AF60036119A /* AirportItlwmInterface.cpp */; };\n\t\t35CBE6E1251CB8BF00435CBC /* _string.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3024080319007A9422 /* _string.c */; };\n\t\t35CBE6E2251CB8BF00435CBC /* ieee80211_ioctl.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3224080319007A9422 /* ieee80211_ioctl.c */; };\n\t\t35CBE6E3251CB8BF00435CBC /* ieee80211.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3324080319007A9422 /* ieee80211.c */; };\n\t\t35CBE6E4251CB8BF00435CBC /* ieee80211_rssadapt.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3424080319007A9422 /* ieee80211_rssadapt.c */; };\n\t\t35CBE6E5251CB8BF00435CBC /* ieee80211_input.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3524080319007A9422 /* ieee80211_input.c */; };\n\t\t35CBE6E6251CB8BF00435CBC /* timeout.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3724080319007A9422 /* timeout.c */; };\n\t\t35CBE6E7251CB8BF00435CBC /* ieee80211_mira.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3924080319007A9422 /* ieee80211_mira.c */; };\n\t\t35CBE6E8251CB8BF00435CBC /* ieee80211_crypto_bip.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3B24080319007A9422 /* ieee80211_crypto_bip.c */; };\n\t\t35CBE6E9251CB8BF00435CBC /* ieee80211_crypto_tkip.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3C24080319007A9422 /* ieee80211_crypto_tkip.c */; };\n\t\t35CBE6EA251CB8BF00435CBC /* ieee80211_crypto_ccmp.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3D24080319007A9422 /* ieee80211_crypto_ccmp.c */; };\n\t\t35CBE6EB251CB8BF00435CBC /* ieee80211_crypto_wep.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC462408031A007A9422 /* ieee80211_crypto_wep.c */; };\n\t\t35CBE6EC251CB8BF00435CBC /* ieee80211_pae_input.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3E24080319007A9422 /* ieee80211_pae_input.c */; };\n\t\t35CBE6ED251CB8BF00435CBC /* ieee80211_amrr.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC4024080319007A9422 /* ieee80211_amrr.c */; };\n\t\t35CBE6EE251CB8BF00435CBC /* ieee80211_output.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC472408031A007A9422 /* ieee80211_output.c */; };\n\t\t35CBE6EF251CB8BF00435CBC /* ieee80211_crypto.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC482408031A007A9422 /* ieee80211_crypto.c */; };\n\t\t35CBE6F0251CB8BF00435CBC /* CTimeout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC492408031A007A9422 /* CTimeout.cpp */; };\n\t\t35CBE6F1251CB8BF00435CBC /* ieee80211_regdomain.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC4B2408031A007A9422 /* ieee80211_regdomain.c */; };\n\t\t35CBE6F2251CB8BF00435CBC /* ieee80211_node.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC4C2408031A007A9422 /* ieee80211_node.c */; };\n\t\t35CBE6F3251CB8BF00435CBC /* ieee80211_pae_output.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC4D2408031A007A9422 /* ieee80211_pae_output.c */; };\n\t\t35CBE6F4251CB8BF00435CBC /* sha1-pbkdf2.c in Sources */ = {isa = PBXBuildFile; fileRef = F88D2B3B2414E64000BBE700 /* sha1-pbkdf2.c */; };\n\t\t35CBE6F5251CB8BF00435CBC /* aes.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07C923FCBC6C009FBA6C /* aes.c */; };\n\t\t35CBE6F6251CB8BF00435CBC /* hmac.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CA23FCBC6C009FBA6C /* hmac.c */; };\n\t\t35CBE6F7251CB8BF00435CBC /* sha2.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CB23FCBC6C009FBA6C /* sha2.c */; };\n\t\t35CBE6F8251CB8BF00435CBC /* rijndael.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CC23FCBC6C009FBA6C /* rijndael.c */; };\n\t\t35CBE6F9251CB8BF00435CBC /* ecb3_enc.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CD23FCBC6C009FBA6C /* ecb3_enc.c */; };\n\t\t35CBE6FA251CB8BF00435CBC /* set_key.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CE23FCBC6C009FBA6C /* set_key.c */; };\n\t\t35CBE6FB251CB8BF00435CBC /* cast.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CF23FCBC6C009FBA6C /* cast.c */; };\n\t\t35CBE6FC251CB8BF00435CBC /* michael.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07D123FCBC6C009FBA6C /* michael.c */; };\n\t\t35CBE6FD251CB8BF00435CBC /* sha1.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07D823FCBC6C009FBA6C /* sha1.c */; };\n\t\t35CBE6FE251CB8BF00435CBC /* cmac.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07DD23FCBC6C009FBA6C /* cmac.c */; };\n\t\t35CBE6FF251CB8BF00435CBC /* ecb_enc.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07E423FCBC6C009FBA6C /* ecb_enc.c */; };\n\t\t35CBE700251CB8BF00435CBC /* chachapoly.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07E923FCBC6C009FBA6C /* chachapoly.c */; };\n\t\t35CBE701251CB8BF00435CBC /* md5.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07EA23FCBC6C009FBA6C /* md5.c */; };\n\t\t35CBE702251CB8BF00435CBC /* arc4.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07EB23FCBC6C009FBA6C /* arc4.c */; };\n\t\t35CBE703251CB8BF00435CBC /* blf.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07EC23FCBC6C009FBA6C /* blf.c */; };\n\t\t35CBE704251CB8BF00435CBC /* poly1305.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07ED23FCBC6C009FBA6C /* poly1305.c */; };\n\t\t35CBE705251CB8BF00435CBC /* key_wrap.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07F023FCBC6C009FBA6C /* key_wrap.c */; };\n\t\t35CBE706251CB8BF00435CBC /* gmac.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07F223FCBC6C009FBA6C /* gmac.c */; };\n\t\t35CBE707251CB8BF00435CBC /* rmd160.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07F323FCBC6C009FBA6C /* rmd160.c */; };\n\t\t35CBE708251CB8BF00435CBC /* idgen.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07F423FCBC6C009FBA6C /* idgen.c */; };\n\t\t35CBE709251CB8BF00435CBC /* compat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A07BA23FCBC6C009FBA6C /* compat.cpp */; };\n\t\t35CBE70A251CB8BF00435CBC /* zutil.c in Sources */ = {isa = PBXBuildFile; fileRef = F8FA0EED2501E8C100B1822E /* zutil.c */; };\n\t\t35CBE70B251CB8BF00435CBC /* ItlHalService.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8D364F624F93AFD0029340B /* ItlHalService.cpp */; };\n\t\t35CBE70C251CB8BF00435CBC /* ItlIwx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8D6CD642442E8F200D2A454 /* ItlIwx.cpp */; };\n\t\t35CBE70D251CB8BF00435CBC /* utils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08BF23FCD4E2009FBA6C /* utils.cpp */; };\n\t\t35CBE70E251CB8BF00435CBC /* fw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08BD23FCD314009FBA6C /* fw.cpp */; };\n\t\t35CBE70F251CB8BF00435CBC /* io.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C123FCD999009FBA6C /* io.cpp */; };\n\t\t35CBE710251CB8BF00435CBC /* rx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C323FCDC14009FBA6C /* rx.cpp */; };\n\t\t35CBE711251CB8BF00435CBC /* tx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C523FCDC3B009FBA6C /* tx.cpp */; };\n\t\t35CBE712251CB8BF00435CBC /* hw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C723FCE2ED009FBA6C /* hw.cpp */; };\n\t\t35CBE713251CB8BF00435CBC /* phy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C923FCE537009FBA6C /* phy.cpp */; };\n\t\t35CBE714251CB8BF00435CBC /* mac80211.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08CB23FCE5CA009FBA6C /* mac80211.cpp */; };\n\t\t35CBE715251CB8BF00435CBC /* nvm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08CD23FCE67F009FBA6C /* nvm.cpp */; };\n\t\t35CBE716251CB8BF00435CBC /* ctxt.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08CF23FCEE88009FBA6C /* ctxt.cpp */; };\n\t\t35CBE717251CB8BF00435CBC /* led.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08D123FCF395009FBA6C /* led.cpp */; };\n\t\t35CBE718251CB8BF00435CBC /* power.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08D323FCF3E6009FBA6C /* power.cpp */; };\n\t\t35CBE719251CB8BF00435CBC /* scan.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08D523FCF4D7009FBA6C /* scan.cpp */; };\n\t\t35CBE71A251CB8BF00435CBC /* ItlIwm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8AF3A2F24F9F35B008911C1 /* ItlIwm.cpp */; };\n\t\t35CBE71B251CB8BF00435CBC /* AirportSTAIOCTL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F89B6BDC25022F8C000F77FF /* AirportSTAIOCTL.cpp */; };\n\t\t35CBE71C251CB8BF00435CBC /* AirportItlwm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F89B6BBD25021C9C000F77FF /* AirportItlwm.cpp */; };\n\t\t35CBE71D251CB8BF00435CBC /* AirportVirtualIOCTL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F89B6BDE25022FB5000F77FF /* AirportVirtualIOCTL.cpp */; };\n\t\t35CBE71E251CB8BF00435CBC /* AirportAWDL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F89B6BE025022FC7000F77FF /* AirportAWDL.cpp */; };\n\t\t35CBE72E251CB8CA00435CBC /* debug.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6C2225027609000F77FF /* debug.h */; };\n\t\t35CBE72F251CB8CA00435CBC /* IOSkywalkEthernetInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BD025021E66000F77FF /* IOSkywalkEthernetInterface.h */; };\n\t\t35CBE730251CB8CA00435CBC /* apple80211_ioctl.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BC525021DEC000F77FF /* apple80211_ioctl.h */; };\n\t\t35CBE736251CB8CA00435CBC /* apple80211_var.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BC425021DEC000F77FF /* apple80211_var.h */; };\n\t\t35CBE739251CB8CA00435CBC /* AirportItlwmInterface.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F8CA44A225091AF60036119A /* AirportItlwmInterface.hpp */; };\n\t\t35CBE73B251CB8CA00435CBC /* AirportItlwm.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BBB25021C9C000F77FF /* AirportItlwm.hpp */; };\n\t\t35CBE744251CB8CA00435CBC /* apple80211_wps.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BC325021DEC000F77FF /* apple80211_wps.h */; };\n\t\t35CBE746251CB8CA00435CBC /* _mbuf.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8D257732495A33500872E4F /* _mbuf.cpp */; };\n\t\t35CBE747251CB8CA00435CBC /* _task.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8F9EDE0240B7415009CB8E7 /* _task.cpp */; };\n\t\t35CBE748251CB8CA00435CBC /* FwBinary.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5076FA7F24CC71E40011B2BB /* FwBinary.cpp */; };\n\t\t35CBE74A251CB8CA00435CBC /* ieee80211_proto.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC2F24080319007A9422 /* ieee80211_proto.c */; };\n\t\t35CBE74B251CB8CA00435CBC /* AirportItlwmInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8CA44A125091AF60036119A /* AirportItlwmInterface.cpp */; };\n\t\t35CBE74C251CB8CA00435CBC /* _string.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3024080319007A9422 /* _string.c */; };\n\t\t35CBE74D251CB8CA00435CBC /* ieee80211_ioctl.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3224080319007A9422 /* ieee80211_ioctl.c */; };\n\t\t35CBE74E251CB8CA00435CBC /* ieee80211.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3324080319007A9422 /* ieee80211.c */; };\n\t\t35CBE74F251CB8CA00435CBC /* ieee80211_rssadapt.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3424080319007A9422 /* ieee80211_rssadapt.c */; };\n\t\t35CBE750251CB8CA00435CBC /* ieee80211_input.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3524080319007A9422 /* ieee80211_input.c */; };\n\t\t35CBE751251CB8CA00435CBC /* timeout.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3724080319007A9422 /* timeout.c */; };\n\t\t35CBE752251CB8CA00435CBC /* ieee80211_mira.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3924080319007A9422 /* ieee80211_mira.c */; };\n\t\t35CBE753251CB8CA00435CBC /* ieee80211_crypto_bip.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3B24080319007A9422 /* ieee80211_crypto_bip.c */; };\n\t\t35CBE754251CB8CA00435CBC /* ieee80211_crypto_tkip.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3C24080319007A9422 /* ieee80211_crypto_tkip.c */; };\n\t\t35CBE755251CB8CA00435CBC /* ieee80211_crypto_ccmp.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3D24080319007A9422 /* ieee80211_crypto_ccmp.c */; };\n\t\t35CBE756251CB8CA00435CBC /* ieee80211_crypto_wep.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC462408031A007A9422 /* ieee80211_crypto_wep.c */; };\n\t\t35CBE757251CB8CA00435CBC /* ieee80211_pae_input.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3E24080319007A9422 /* ieee80211_pae_input.c */; };\n\t\t35CBE758251CB8CA00435CBC /* ieee80211_amrr.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC4024080319007A9422 /* ieee80211_amrr.c */; };\n\t\t35CBE759251CB8CA00435CBC /* ieee80211_output.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC472408031A007A9422 /* ieee80211_output.c */; };\n\t\t35CBE75A251CB8CA00435CBC /* ieee80211_crypto.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC482408031A007A9422 /* ieee80211_crypto.c */; };\n\t\t35CBE75B251CB8CA00435CBC /* CTimeout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC492408031A007A9422 /* CTimeout.cpp */; };\n\t\t35CBE75C251CB8CA00435CBC /* ieee80211_regdomain.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC4B2408031A007A9422 /* ieee80211_regdomain.c */; };\n\t\t35CBE75D251CB8CA00435CBC /* ieee80211_node.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC4C2408031A007A9422 /* ieee80211_node.c */; };\n\t\t35CBE75E251CB8CA00435CBC /* ieee80211_pae_output.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC4D2408031A007A9422 /* ieee80211_pae_output.c */; };\n\t\t35CBE75F251CB8CA00435CBC /* sha1-pbkdf2.c in Sources */ = {isa = PBXBuildFile; fileRef = F88D2B3B2414E64000BBE700 /* sha1-pbkdf2.c */; };\n\t\t35CBE760251CB8CA00435CBC /* aes.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07C923FCBC6C009FBA6C /* aes.c */; };\n\t\t35CBE761251CB8CA00435CBC /* hmac.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CA23FCBC6C009FBA6C /* hmac.c */; };\n\t\t35CBE762251CB8CA00435CBC /* sha2.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CB23FCBC6C009FBA6C /* sha2.c */; };\n\t\t35CBE763251CB8CA00435CBC /* rijndael.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CC23FCBC6C009FBA6C /* rijndael.c */; };\n\t\t35CBE764251CB8CA00435CBC /* ecb3_enc.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CD23FCBC6C009FBA6C /* ecb3_enc.c */; };\n\t\t35CBE765251CB8CA00435CBC /* set_key.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CE23FCBC6C009FBA6C /* set_key.c */; };\n\t\t35CBE766251CB8CA00435CBC /* cast.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CF23FCBC6C009FBA6C /* cast.c */; };\n\t\t35CBE767251CB8CA00435CBC /* michael.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07D123FCBC6C009FBA6C /* michael.c */; };\n\t\t35CBE768251CB8CA00435CBC /* sha1.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07D823FCBC6C009FBA6C /* sha1.c */; };\n\t\t35CBE769251CB8CA00435CBC /* cmac.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07DD23FCBC6C009FBA6C /* cmac.c */; };\n\t\t35CBE76A251CB8CA00435CBC /* ecb_enc.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07E423FCBC6C009FBA6C /* ecb_enc.c */; };\n\t\t35CBE76B251CB8CA00435CBC /* chachapoly.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07E923FCBC6C009FBA6C /* chachapoly.c */; };\n\t\t35CBE76C251CB8CA00435CBC /* md5.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07EA23FCBC6C009FBA6C /* md5.c */; };\n\t\t35CBE76D251CB8CA00435CBC /* arc4.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07EB23FCBC6C009FBA6C /* arc4.c */; };\n\t\t35CBE76E251CB8CA00435CBC /* blf.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07EC23FCBC6C009FBA6C /* blf.c */; };\n\t\t35CBE76F251CB8CA00435CBC /* poly1305.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07ED23FCBC6C009FBA6C /* poly1305.c */; };\n\t\t35CBE770251CB8CA00435CBC /* key_wrap.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07F023FCBC6C009FBA6C /* key_wrap.c */; };\n\t\t35CBE771251CB8CA00435CBC /* gmac.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07F223FCBC6C009FBA6C /* gmac.c */; };\n\t\t35CBE772251CB8CA00435CBC /* rmd160.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07F323FCBC6C009FBA6C /* rmd160.c */; };\n\t\t35CBE773251CB8CA00435CBC /* idgen.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07F423FCBC6C009FBA6C /* idgen.c */; };\n\t\t35CBE774251CB8CA00435CBC /* compat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A07BA23FCBC6C009FBA6C /* compat.cpp */; };\n\t\t35CBE775251CB8CA00435CBC /* zutil.c in Sources */ = {isa = PBXBuildFile; fileRef = F8FA0EED2501E8C100B1822E /* zutil.c */; };\n\t\t35CBE776251CB8CA00435CBC /* ItlHalService.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8D364F624F93AFD0029340B /* ItlHalService.cpp */; };\n\t\t35CBE777251CB8CA00435CBC /* ItlIwx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8D6CD642442E8F200D2A454 /* ItlIwx.cpp */; };\n\t\t35CBE778251CB8CA00435CBC /* utils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08BF23FCD4E2009FBA6C /* utils.cpp */; };\n\t\t35CBE779251CB8CA00435CBC /* fw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08BD23FCD314009FBA6C /* fw.cpp */; };\n\t\t35CBE77A251CB8CA00435CBC /* io.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C123FCD999009FBA6C /* io.cpp */; };\n\t\t35CBE77B251CB8CA00435CBC /* rx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C323FCDC14009FBA6C /* rx.cpp */; };\n\t\t35CBE77C251CB8CA00435CBC /* tx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C523FCDC3B009FBA6C /* tx.cpp */; };\n\t\t35CBE77D251CB8CA00435CBC /* hw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C723FCE2ED009FBA6C /* hw.cpp */; };\n\t\t35CBE77E251CB8CA00435CBC /* phy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C923FCE537009FBA6C /* phy.cpp */; };\n\t\t35CBE77F251CB8CA00435CBC /* mac80211.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08CB23FCE5CA009FBA6C /* mac80211.cpp */; };\n\t\t35CBE780251CB8CA00435CBC /* nvm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08CD23FCE67F009FBA6C /* nvm.cpp */; };\n\t\t35CBE781251CB8CA00435CBC /* ctxt.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08CF23FCEE88009FBA6C /* ctxt.cpp */; };\n\t\t35CBE782251CB8CA00435CBC /* led.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08D123FCF395009FBA6C /* led.cpp */; };\n\t\t35CBE783251CB8CA00435CBC /* power.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08D323FCF3E6009FBA6C /* power.cpp */; };\n\t\t35CBE784251CB8CA00435CBC /* scan.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08D523FCF4D7009FBA6C /* scan.cpp */; };\n\t\t35CBE785251CB8CA00435CBC /* ItlIwm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8AF3A2F24F9F35B008911C1 /* ItlIwm.cpp */; };\n\t\t35CBE786251CB8CA00435CBC /* AirportSTAIOCTL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F89B6BDC25022F8C000F77FF /* AirportSTAIOCTL.cpp */; };\n\t\t35CBE787251CB8CA00435CBC /* AirportItlwm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F89B6BBD25021C9C000F77FF /* AirportItlwm.cpp */; };\n\t\t35CBE788251CB8CA00435CBC /* AirportVirtualIOCTL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F89B6BDE25022FB5000F77FF /* AirportVirtualIOCTL.cpp */; };\n\t\t35CBE789251CB8CA00435CBC /* AirportAWDL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F89B6BE025022FC7000F77FF /* AirportAWDL.cpp */; };\n\t\t5088ECBD252884870068A63D /* libkmod.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5088ECBC252884870068A63D /* libkmod.a */; };\n\t\t5088ECBE252884A30068A63D /* libkmod.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5088ECBC252884870068A63D /* libkmod.a */; };\n\t\t5088ECBF252884AF0068A63D /* libkmod.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5088ECBC252884870068A63D /* libkmod.a */; };\n\t\t5088ECC0252884C10068A63D /* libkmod.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5088ECBC252884870068A63D /* libkmod.a */; };\n\t\t5088ECC1252884D70068A63D /* libkmod.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5088ECBC252884870068A63D /* libkmod.a */; };\n\t\tA5A0C5242A501E6800EF9328 /* arp.c in Sources */ = {isa = PBXBuildFile; fileRef = A5A0C5232A501E6800EF9328 /* arp.c */; };\n\t\tA5A0C5252A501E6800EF9328 /* arp.c in Sources */ = {isa = PBXBuildFile; fileRef = A5A0C5232A501E6800EF9328 /* arp.c */; };\n\t\tA5A0C5262A501E6800EF9328 /* arp.c in Sources */ = {isa = PBXBuildFile; fileRef = A5A0C5232A501E6800EF9328 /* arp.c */; };\n\t\tA5A0C5272A501E6800EF9328 /* arp.c in Sources */ = {isa = PBXBuildFile; fileRef = A5A0C5232A501E6800EF9328 /* arp.c */; };\n\t\tA5A0C5282A501E6800EF9328 /* arp.c in Sources */ = {isa = PBXBuildFile; fileRef = A5A0C5232A501E6800EF9328 /* arp.c */; };\n\t\tA5A0C5292A501E6800EF9328 /* arp.c in Sources */ = {isa = PBXBuildFile; fileRef = A5A0C5232A501E6800EF9328 /* arp.c */; };\n\t\tA5A0C52A2A501E6800EF9328 /* arp.c in Sources */ = {isa = PBXBuildFile; fileRef = A5A0C5232A501E6800EF9328 /* arp.c */; };\n\t\tA5A0C52B2A501E6800EF9328 /* arp.c in Sources */ = {isa = PBXBuildFile; fileRef = A5A0C5232A501E6800EF9328 /* arp.c */; };\n\t\tA5DD111526D93B5F00BA01EF /* rs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5DD111326D93B5F00BA01EF /* rs.cpp */; };\n\t\tA5DD111626D93B5F00BA01EF /* rs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5DD111326D93B5F00BA01EF /* rs.cpp */; };\n\t\tA5DD111726D93B5F00BA01EF /* rs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5DD111326D93B5F00BA01EF /* rs.cpp */; };\n\t\tA5DD111826D93B5F00BA01EF /* rs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5DD111326D93B5F00BA01EF /* rs.cpp */; };\n\t\tA5DD111926D93B5F00BA01EF /* rs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5DD111326D93B5F00BA01EF /* rs.cpp */; };\n\t\tA5DD111A26D93B5F00BA01EF /* rs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5DD111326D93B5F00BA01EF /* rs.cpp */; };\n\t\tA5DD111B26D93B5F00BA01EF /* rs.h in Headers */ = {isa = PBXBuildFile; fileRef = A5DD111426D93B5F00BA01EF /* rs.h */; };\n\t\tA5DD111C26D93B5F00BA01EF /* rs.h in Headers */ = {isa = PBXBuildFile; fileRef = A5DD111426D93B5F00BA01EF /* rs.h */; };\n\t\tA5DD111D26D93B5F00BA01EF /* rs.h in Headers */ = {isa = PBXBuildFile; fileRef = A5DD111426D93B5F00BA01EF /* rs.h */; };\n\t\tA5DD111E26D93B5F00BA01EF /* rs.h in Headers */ = {isa = PBXBuildFile; fileRef = A5DD111426D93B5F00BA01EF /* rs.h */; };\n\t\tA5DD111F26D93B5F00BA01EF /* rs.h in Headers */ = {isa = PBXBuildFile; fileRef = A5DD111426D93B5F00BA01EF /* rs.h */; };\n\t\tA5DD112026D93B5F00BA01EF /* rs.h in Headers */ = {isa = PBXBuildFile; fileRef = A5DD111426D93B5F00BA01EF /* rs.h */; };\n\t\tA5FA2AE428A797B200847103 /* _ifq.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5FA2AE328A797B200847103 /* _ifq.cpp */; };\n\t\tA5FA2AE528A797B200847103 /* _ifq.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5FA2AE328A797B200847103 /* _ifq.cpp */; };\n\t\tA5FA2AE628A797B200847103 /* _ifq.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5FA2AE328A797B200847103 /* _ifq.cpp */; };\n\t\tA5FA2AE728A797B200847103 /* _ifq.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5FA2AE328A797B200847103 /* _ifq.cpp */; };\n\t\tA5FA2AE828A797B200847103 /* _ifq.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5FA2AE328A797B200847103 /* _ifq.cpp */; };\n\t\tA5FA2AE928A797B200847103 /* _ifq.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5FA2AE328A797B200847103 /* _ifq.cpp */; };\n\t\tA5FA2AEA28A797B200847103 /* _ifq.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5FA2AE328A797B200847103 /* _ifq.cpp */; };\n\t\tF800DD9B24FBEBF000789320 /* ItlDriverController.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F800DD9A24FBEBF000789320 /* ItlDriverController.hpp */; };\n\t\tF8294FE424FCBF5100239253 /* FwBinary.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5076FA7F24CC71E40011B2BB /* FwBinary.cpp */; };\n\t\tF837C91D2724577F00B2C499 /* coex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F837C91C2724577F00B2C499 /* coex.cpp */; };\n\t\tF837C91E2724577F00B2C499 /* coex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F837C91C2724577F00B2C499 /* coex.cpp */; };\n\t\tF837C91F2724577F00B2C499 /* coex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F837C91C2724577F00B2C499 /* coex.cpp */; };\n\t\tF837C9202724577F00B2C499 /* coex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F837C91C2724577F00B2C499 /* coex.cpp */; };\n\t\tF837C9212724577F00B2C499 /* coex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F837C91C2724577F00B2C499 /* coex.cpp */; };\n\t\tF837C9222724577F00B2C499 /* coex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F837C91C2724577F00B2C499 /* coex.cpp */; };\n\t\tF84AD8862A497DB200DC8DED /* IO80211WorkQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87A2A497DB200DC8DED /* IO80211WorkQueue.h */; };\n\t\tF84AD8872A497DB200DC8DED /* IO80211WorkQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87A2A497DB200DC8DED /* IO80211WorkQueue.h */; };\n\t\tF84AD8882A497DB200DC8DED /* IO80211WorkQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87A2A497DB200DC8DED /* IO80211WorkQueue.h */; };\n\t\tF84AD8892A497DB200DC8DED /* IO80211WorkQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87A2A497DB200DC8DED /* IO80211WorkQueue.h */; };\n\t\tF84AD88A2A497DB200DC8DED /* IO80211WorkQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87A2A497DB200DC8DED /* IO80211WorkQueue.h */; };\n\t\tF84AD88B2A497DB200DC8DED /* IO80211WorkQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87A2A497DB200DC8DED /* IO80211WorkQueue.h */; };\n\t\tF84AD88C2A497DB200DC8DED /* IO80211WorkQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87A2A497DB200DC8DED /* IO80211WorkQueue.h */; };\n\t\tF84AD88D2A497DB200DC8DED /* IOSkywalkNetworkPacket.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87B2A497DB200DC8DED /* IOSkywalkNetworkPacket.h */; };\n\t\tF84AD88E2A497DB200DC8DED /* IOSkywalkNetworkPacket.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87B2A497DB200DC8DED /* IOSkywalkNetworkPacket.h */; };\n\t\tF84AD88F2A497DB200DC8DED /* IOSkywalkNetworkPacket.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87B2A497DB200DC8DED /* IOSkywalkNetworkPacket.h */; };\n\t\tF84AD8902A497DB200DC8DED /* IOSkywalkNetworkPacket.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87B2A497DB200DC8DED /* IOSkywalkNetworkPacket.h */; };\n\t\tF84AD8912A497DB200DC8DED /* IOSkywalkNetworkPacket.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87B2A497DB200DC8DED /* IOSkywalkNetworkPacket.h */; };\n\t\tF84AD8922A497DB200DC8DED /* IOSkywalkNetworkPacket.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87B2A497DB200DC8DED /* IOSkywalkNetworkPacket.h */; };\n\t\tF84AD8932A497DB200DC8DED /* IOSkywalkNetworkPacket.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87B2A497DB200DC8DED /* IOSkywalkNetworkPacket.h */; };\n\t\tF84AD8942A497DB200DC8DED /* IO80211InfraProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87C2A497DB200DC8DED /* IO80211InfraProtocol.h */; };\n\t\tF84AD8952A497DB200DC8DED /* IO80211InfraProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87C2A497DB200DC8DED /* IO80211InfraProtocol.h */; };\n\t\tF84AD8962A497DB200DC8DED /* IO80211InfraProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87C2A497DB200DC8DED /* IO80211InfraProtocol.h */; };\n\t\tF84AD8972A497DB200DC8DED /* IO80211InfraProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87C2A497DB200DC8DED /* IO80211InfraProtocol.h */; };\n\t\tF84AD8982A497DB200DC8DED /* IO80211InfraProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87C2A497DB200DC8DED /* IO80211InfraProtocol.h */; };\n\t\tF84AD8992A497DB200DC8DED /* IO80211InfraProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87C2A497DB200DC8DED /* IO80211InfraProtocol.h */; };\n\t\tF84AD89A2A497DB200DC8DED /* IO80211InfraProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87C2A497DB200DC8DED /* IO80211InfraProtocol.h */; };\n\t\tF84AD89B2A497DB200DC8DED /* CCPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87D2A497DB200DC8DED /* CCPipe.h */; };\n\t\tF84AD89C2A497DB200DC8DED /* CCPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87D2A497DB200DC8DED /* CCPipe.h */; };\n\t\tF84AD89D2A497DB200DC8DED /* CCPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87D2A497DB200DC8DED /* CCPipe.h */; };\n\t\tF84AD89E2A497DB200DC8DED /* CCPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87D2A497DB200DC8DED /* CCPipe.h */; };\n\t\tF84AD89F2A497DB200DC8DED /* CCPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87D2A497DB200DC8DED /* CCPipe.h */; };\n\t\tF84AD8A02A497DB200DC8DED /* CCPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87D2A497DB200DC8DED /* CCPipe.h */; };\n\t\tF84AD8A12A497DB200DC8DED /* CCPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87D2A497DB200DC8DED /* CCPipe.h */; };\n\t\tF84AD8A22A497DB200DC8DED /* IOSkywalkLogicalLink.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87E2A497DB200DC8DED /* IOSkywalkLogicalLink.h */; };\n\t\tF84AD8A32A497DB200DC8DED /* IOSkywalkLogicalLink.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87E2A497DB200DC8DED /* IOSkywalkLogicalLink.h */; };\n\t\tF84AD8A42A497DB200DC8DED /* IOSkywalkLogicalLink.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87E2A497DB200DC8DED /* IOSkywalkLogicalLink.h */; };\n\t\tF84AD8A52A497DB200DC8DED /* IOSkywalkLogicalLink.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87E2A497DB200DC8DED /* IOSkywalkLogicalLink.h */; };\n\t\tF84AD8A62A497DB200DC8DED /* IOSkywalkLogicalLink.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87E2A497DB200DC8DED /* IOSkywalkLogicalLink.h */; };\n\t\tF84AD8A72A497DB200DC8DED /* IOSkywalkLogicalLink.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87E2A497DB200DC8DED /* IOSkywalkLogicalLink.h */; };\n\t\tF84AD8A82A497DB200DC8DED /* IOSkywalkLogicalLink.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87E2A497DB200DC8DED /* IOSkywalkLogicalLink.h */; };\n\t\tF84AD8A92A497DB200DC8DED /* IO80211InfraInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87F2A497DB200DC8DED /* IO80211InfraInterface.h */; };\n\t\tF84AD8AA2A497DB200DC8DED /* IO80211InfraInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87F2A497DB200DC8DED /* IO80211InfraInterface.h */; };\n\t\tF84AD8AB2A497DB200DC8DED /* IO80211InfraInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87F2A497DB200DC8DED /* IO80211InfraInterface.h */; };\n\t\tF84AD8AC2A497DB200DC8DED /* IO80211InfraInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87F2A497DB200DC8DED /* IO80211InfraInterface.h */; };\n\t\tF84AD8AD2A497DB200DC8DED /* IO80211InfraInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87F2A497DB200DC8DED /* IO80211InfraInterface.h */; };\n\t\tF84AD8AE2A497DB200DC8DED /* IO80211InfraInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87F2A497DB200DC8DED /* IO80211InfraInterface.h */; };\n\t\tF84AD8AF2A497DB200DC8DED /* IO80211InfraInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87F2A497DB200DC8DED /* IO80211InfraInterface.h */; };\n\t\tF84AD8B02A497DB200DC8DED /* CCStream.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8802A497DB200DC8DED /* CCStream.h */; };\n\t\tF84AD8B12A497DB200DC8DED /* CCStream.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8802A497DB200DC8DED /* CCStream.h */; };\n\t\tF84AD8B22A497DB200DC8DED /* CCStream.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8802A497DB200DC8DED /* CCStream.h */; };\n\t\tF84AD8B32A497DB200DC8DED /* CCStream.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8802A497DB200DC8DED /* CCStream.h */; };\n\t\tF84AD8B42A497DB200DC8DED /* CCStream.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8802A497DB200DC8DED /* CCStream.h */; };\n\t\tF84AD8B52A497DB200DC8DED /* CCStream.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8802A497DB200DC8DED /* CCStream.h */; };\n\t\tF84AD8B62A497DB200DC8DED /* CCStream.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8802A497DB200DC8DED /* CCStream.h */; };\n\t\tF84AD8B72A497DB200DC8DED /* CCDataPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8812A497DB200DC8DED /* CCDataPipe.h */; };\n\t\tF84AD8B82A497DB200DC8DED /* CCDataPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8812A497DB200DC8DED /* CCDataPipe.h */; };\n\t\tF84AD8B92A497DB200DC8DED /* CCDataPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8812A497DB200DC8DED /* CCDataPipe.h */; };\n\t\tF84AD8BA2A497DB200DC8DED /* CCDataPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8812A497DB200DC8DED /* CCDataPipe.h */; };\n\t\tF84AD8BB2A497DB200DC8DED /* CCDataPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8812A497DB200DC8DED /* CCDataPipe.h */; };\n\t\tF84AD8BC2A497DB200DC8DED /* CCDataPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8812A497DB200DC8DED /* CCDataPipe.h */; };\n\t\tF84AD8BD2A497DB200DC8DED /* CCDataPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8812A497DB200DC8DED /* CCDataPipe.h */; };\n\t\tF84AD8BE2A497DB200DC8DED /* CCLogStream.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8822A497DB200DC8DED /* CCLogStream.h */; };\n\t\tF84AD8BF2A497DB200DC8DED /* CCLogStream.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8822A497DB200DC8DED /* CCLogStream.h */; };\n\t\tF84AD8C02A497DB200DC8DED /* CCLogStream.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8822A497DB200DC8DED /* CCLogStream.h */; };\n\t\tF84AD8C12A497DB200DC8DED /* CCLogStream.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8822A497DB200DC8DED /* CCLogStream.h */; };\n\t\tF84AD8C22A497DB200DC8DED /* CCLogStream.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8822A497DB200DC8DED /* CCLogStream.h */; };\n\t\tF84AD8C32A497DB200DC8DED /* CCLogStream.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8822A497DB200DC8DED /* CCLogStream.h */; };\n\t\tF84AD8C42A497DB200DC8DED /* CCLogStream.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8822A497DB200DC8DED /* CCLogStream.h */; };\n\t\tF84AD8C52A497DB200DC8DED /* IOSkywalkPacketBufferPool.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8832A497DB200DC8DED /* IOSkywalkPacketBufferPool.h */; };\n\t\tF84AD8C62A497DB200DC8DED /* IOSkywalkPacketBufferPool.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8832A497DB200DC8DED /* IOSkywalkPacketBufferPool.h */; };\n\t\tF84AD8C72A497DB200DC8DED /* IOSkywalkPacketBufferPool.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8832A497DB200DC8DED /* IOSkywalkPacketBufferPool.h */; };\n\t\tF84AD8C82A497DB200DC8DED /* IOSkywalkPacketBufferPool.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8832A497DB200DC8DED /* IOSkywalkPacketBufferPool.h */; };\n\t\tF84AD8C92A497DB200DC8DED /* IOSkywalkPacketBufferPool.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8832A497DB200DC8DED /* IOSkywalkPacketBufferPool.h */; };\n\t\tF84AD8CA2A497DB200DC8DED /* IOSkywalkPacketBufferPool.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8832A497DB200DC8DED /* IOSkywalkPacketBufferPool.h */; };\n\t\tF84AD8CB2A497DB200DC8DED /* IOSkywalkPacketBufferPool.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8832A497DB200DC8DED /* IOSkywalkPacketBufferPool.h */; };\n\t\tF84AD8CC2A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8842A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h */; };\n\t\tF84AD8CD2A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8842A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h */; };\n\t\tF84AD8CE2A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8842A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h */; };\n\t\tF84AD8CF2A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8842A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h */; };\n\t\tF84AD8D02A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8842A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h */; };\n\t\tF84AD8D12A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8842A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h */; };\n\t\tF84AD8D22A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8842A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h */; };\n\t\tF84AD8D32A497DB200DC8DED /* CCLogPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8852A497DB200DC8DED /* CCLogPipe.h */; };\n\t\tF84AD8D42A497DB200DC8DED /* CCLogPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8852A497DB200DC8DED /* CCLogPipe.h */; };\n\t\tF84AD8D52A497DB200DC8DED /* CCLogPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8852A497DB200DC8DED /* CCLogPipe.h */; };\n\t\tF84AD8D62A497DB200DC8DED /* CCLogPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8852A497DB200DC8DED /* CCLogPipe.h */; };\n\t\tF84AD8D72A497DB200DC8DED /* CCLogPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8852A497DB200DC8DED /* CCLogPipe.h */; };\n\t\tF84AD8D82A497DB200DC8DED /* CCLogPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8852A497DB200DC8DED /* CCLogPipe.h */; };\n\t\tF84AD8D92A497DB200DC8DED /* CCLogPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8852A497DB200DC8DED /* CCLogPipe.h */; };\n\t\tF8876A4E28B71F5400A21E42 /* rs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5DD111326D93B5F00BA01EF /* rs.cpp */; };\n\t\tF88CB91424FBE9130060B1A5 /* ItlDriverInfo.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F88CB91324FBE9130060B1A5 /* ItlDriverInfo.hpp */; };\n\t\tF88D2B3D2414E64000BBE700 /* sha1-pbkdf2.c in Sources */ = {isa = PBXBuildFile; fileRef = F88D2B3B2414E64000BBE700 /* sha1-pbkdf2.c */; };\n\t\tF897ECBA266EFF93005EE8F7 /* debug.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6C2225027609000F77FF /* debug.h */; };\n\t\tF897ECBB266EFF93005EE8F7 /* IOSkywalkEthernetInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BD025021E66000F77FF /* IOSkywalkEthernetInterface.h */; };\n\t\tF897ECBC266EFF93005EE8F7 /* apple80211_ioctl.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BC525021DEC000F77FF /* apple80211_ioctl.h */; };\n\t\tF897ECBD266EFF93005EE8F7 /* IO80211P2PInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA36252D834500520FD4 /* IO80211P2PInterface.h */; };\n\t\tF897ECBE266EFF93005EE8F7 /* IO80211WorkLoop.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA39252D834500520FD4 /* IO80211WorkLoop.h */; };\n\t\tF897ECBF266EFF93005EE8F7 /* apple80211_var.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BC425021DEC000F77FF /* apple80211_var.h */; };\n\t\tF897ECC0266EFF93005EE8F7 /* AirportItlwmInterface.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F8CA44A225091AF60036119A /* AirportItlwmInterface.hpp */; };\n\t\tF897ECC1266EFF93005EE8F7 /* IO80211Interface.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA38252D834500520FD4 /* IO80211Interface.h */; };\n\t\tF897ECC2266EFF93005EE8F7 /* (null) in Headers */ = {isa = PBXBuildFile; };\n\t\tF897ECC3266EFF93005EE8F7 /* IO80211SkywalkInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA37252D834500520FD4 /* IO80211SkywalkInterface.h */; };\n\t\tF897ECC4266EFF93005EE8F7 /* AirportItlwm.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BBB25021C9C000F77FF /* AirportItlwm.hpp */; };\n\t\tF897ECC5266EFF93005EE8F7 /* IO80211VirtualInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA34252D834500520FD4 /* IO80211VirtualInterface.h */; };\n\t\tF897ECC6266EFF93005EE8F7 /* IO80211Controller.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA35252D834500520FD4 /* IO80211Controller.h */; };\n\t\tF897ECC7266EFF93005EE8F7 /* (null) in Headers */ = {isa = PBXBuildFile; };\n\t\tF897ECC8266EFF93005EE8F7 /* ieee80211_ra.h in Headers */ = {isa = PBXBuildFile; fileRef = F8C594D225FD935B0007D19C /* ieee80211_ra.h */; };\n\t\tF897ECC9266EFF93005EE8F7 /* apple80211_wps.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BC325021DEC000F77FF /* apple80211_wps.h */; };\n\t\tF897ECCB266EFF93005EE8F7 /* _mbuf.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8D257732495A33500872E4F /* _mbuf.cpp */; };\n\t\tF897ECCC266EFF93005EE8F7 /* ieee80211_ra.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C594D125FD935B0007D19C /* ieee80211_ra.c */; };\n\t\tF897ECCD266EFF93005EE8F7 /* _task.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8F9EDE0240B7415009CB8E7 /* _task.cpp */; };\n\t\tF897ECCE266EFF93005EE8F7 /* FwBinary.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5076FA7F24CC71E40011B2BB /* FwBinary.cpp */; };\n\t\tF897ECD0266EFF93005EE8F7 /* ieee80211_proto.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC2F24080319007A9422 /* ieee80211_proto.c */; };\n\t\tF897ECD1266EFF93005EE8F7 /* AirportItlwmInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8CA44A125091AF60036119A /* AirportItlwmInterface.cpp */; };\n\t\tF897ECD2266EFF93005EE8F7 /* _string.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3024080319007A9422 /* _string.c */; };\n\t\tF897ECD3266EFF93005EE8F7 /* ieee80211_ioctl.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3224080319007A9422 /* ieee80211_ioctl.c */; };\n\t\tF897ECD4266EFF93005EE8F7 /* ieee80211.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3324080319007A9422 /* ieee80211.c */; };\n\t\tF897ECD5266EFF93005EE8F7 /* ieee80211_rssadapt.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3424080319007A9422 /* ieee80211_rssadapt.c */; };\n\t\tF897ECD6266EFF93005EE8F7 /* ieee80211_input.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3524080319007A9422 /* ieee80211_input.c */; };\n\t\tF897ECD7266EFF93005EE8F7 /* timeout.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3724080319007A9422 /* timeout.c */; };\n\t\tF897ECD8266EFF93005EE8F7 /* ieee80211_mira.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3924080319007A9422 /* ieee80211_mira.c */; };\n\t\tF897ECD9266EFF93005EE8F7 /* ieee80211_crypto_bip.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3B24080319007A9422 /* ieee80211_crypto_bip.c */; };\n\t\tF897ECDA266EFF93005EE8F7 /* ieee80211_crypto_tkip.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3C24080319007A9422 /* ieee80211_crypto_tkip.c */; };\n\t\tF897ECDB266EFF93005EE8F7 /* ieee80211_crypto_ccmp.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3D24080319007A9422 /* ieee80211_crypto_ccmp.c */; };\n\t\tF897ECDC266EFF93005EE8F7 /* ieee80211_crypto_wep.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC462408031A007A9422 /* ieee80211_crypto_wep.c */; };\n\t\tF897ECDD266EFF93005EE8F7 /* ieee80211_pae_input.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3E24080319007A9422 /* ieee80211_pae_input.c */; };\n\t\tF897ECDE266EFF93005EE8F7 /* ieee80211_amrr.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC4024080319007A9422 /* ieee80211_amrr.c */; };\n\t\tF897ECDF266EFF93005EE8F7 /* ieee80211_output.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC472408031A007A9422 /* ieee80211_output.c */; };\n\t\tF897ECE0266EFF93005EE8F7 /* ieee80211_crypto.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC482408031A007A9422 /* ieee80211_crypto.c */; };\n\t\tF897ECE1266EFF93005EE8F7 /* CTimeout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC492408031A007A9422 /* CTimeout.cpp */; };\n\t\tF897ECE2266EFF93005EE8F7 /* ieee80211_regdomain.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC4B2408031A007A9422 /* ieee80211_regdomain.c */; };\n\t\tF897ECE3266EFF93005EE8F7 /* ieee80211_node.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC4C2408031A007A9422 /* ieee80211_node.c */; };\n\t\tF897ECE4266EFF93005EE8F7 /* ieee80211_pae_output.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC4D2408031A007A9422 /* ieee80211_pae_output.c */; };\n\t\tF897ECE5266EFF93005EE8F7 /* sha1-pbkdf2.c in Sources */ = {isa = PBXBuildFile; fileRef = F88D2B3B2414E64000BBE700 /* sha1-pbkdf2.c */; };\n\t\tF897ECE6266EFF93005EE8F7 /* aes.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07C923FCBC6C009FBA6C /* aes.c */; };\n\t\tF897ECE7266EFF93005EE8F7 /* hmac.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CA23FCBC6C009FBA6C /* hmac.c */; };\n\t\tF897ECE8266EFF93005EE8F7 /* sha2.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CB23FCBC6C009FBA6C /* sha2.c */; };\n\t\tF897ECE9266EFF93005EE8F7 /* rijndael.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CC23FCBC6C009FBA6C /* rijndael.c */; };\n\t\tF897ECEA266EFF93005EE8F7 /* ecb3_enc.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CD23FCBC6C009FBA6C /* ecb3_enc.c */; };\n\t\tF897ECEB266EFF93005EE8F7 /* set_key.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CE23FCBC6C009FBA6C /* set_key.c */; };\n\t\tF897ECEC266EFF93005EE8F7 /* cast.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CF23FCBC6C009FBA6C /* cast.c */; };\n\t\tF897ECED266EFF93005EE8F7 /* michael.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07D123FCBC6C009FBA6C /* michael.c */; };\n\t\tF897ECEE266EFF93005EE8F7 /* sha1.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07D823FCBC6C009FBA6C /* sha1.c */; };\n\t\tF897ECEF266EFF93005EE8F7 /* cmac.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07DD23FCBC6C009FBA6C /* cmac.c */; };\n\t\tF897ECF0266EFF93005EE8F7 /* ecb_enc.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07E423FCBC6C009FBA6C /* ecb_enc.c */; };\n\t\tF897ECF1266EFF93005EE8F7 /* chachapoly.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07E923FCBC6C009FBA6C /* chachapoly.c */; };\n\t\tF897ECF2266EFF93005EE8F7 /* (null) in Sources */ = {isa = PBXBuildFile; };\n\t\tF897ECF3266EFF93005EE8F7 /* md5.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07EA23FCBC6C009FBA6C /* md5.c */; };\n\t\tF897ECF4266EFF93005EE8F7 /* arc4.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07EB23FCBC6C009FBA6C /* arc4.c */; };\n\t\tF897ECF5266EFF93005EE8F7 /* blf.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07EC23FCBC6C009FBA6C /* blf.c */; };\n\t\tF897ECF6266EFF93005EE8F7 /* poly1305.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07ED23FCBC6C009FBA6C /* poly1305.c */; };\n\t\tF897ECF7266EFF93005EE8F7 /* key_wrap.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07F023FCBC6C009FBA6C /* key_wrap.c */; };\n\t\tF897ECF8266EFF93005EE8F7 /* gmac.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07F223FCBC6C009FBA6C /* gmac.c */; };\n\t\tF897ECF9266EFF93005EE8F7 /* rmd160.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07F323FCBC6C009FBA6C /* rmd160.c */; };\n\t\tF897ECFA266EFF93005EE8F7 /* idgen.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07F423FCBC6C009FBA6C /* idgen.c */; };\n\t\tF897ECFB266EFF93005EE8F7 /* compat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A07BA23FCBC6C009FBA6C /* compat.cpp */; };\n\t\tF897ECFC266EFF93005EE8F7 /* zutil.c in Sources */ = {isa = PBXBuildFile; fileRef = F8FA0EED2501E8C100B1822E /* zutil.c */; };\n\t\tF897ECFD266EFF93005EE8F7 /* ItlHalService.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8D364F624F93AFD0029340B /* ItlHalService.cpp */; };\n\t\tF897ECFE266EFF93005EE8F7 /* ItlIwx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8D6CD642442E8F200D2A454 /* ItlIwx.cpp */; };\n\t\tF897ECFF266EFF93005EE8F7 /* utils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08BF23FCD4E2009FBA6C /* utils.cpp */; };\n\t\tF897ED00266EFF93005EE8F7 /* fw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08BD23FCD314009FBA6C /* fw.cpp */; };\n\t\tF897ED01266EFF93005EE8F7 /* io.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C123FCD999009FBA6C /* io.cpp */; };\n\t\tF897ED02266EFF93005EE8F7 /* rx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C323FCDC14009FBA6C /* rx.cpp */; };\n\t\tF897ED03266EFF93005EE8F7 /* tx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C523FCDC3B009FBA6C /* tx.cpp */; };\n\t\tF897ED04266EFF93005EE8F7 /* hw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C723FCE2ED009FBA6C /* hw.cpp */; };\n\t\tF897ED05266EFF93005EE8F7 /* ItlIwn.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 17FD7F0E255E4AC800611406 /* ItlIwn.cpp */; };\n\t\tF897ED06266EFF93005EE8F7 /* phy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C923FCE537009FBA6C /* phy.cpp */; };\n\t\tF897ED07266EFF93005EE8F7 /* mac80211.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08CB23FCE5CA009FBA6C /* mac80211.cpp */; };\n\t\tF897ED08266EFF93005EE8F7 /* nvm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08CD23FCE67F009FBA6C /* nvm.cpp */; };\n\t\tF897ED09266EFF93005EE8F7 /* ctxt.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08CF23FCEE88009FBA6C /* ctxt.cpp */; };\n\t\tF897ED0A266EFF93005EE8F7 /* led.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08D123FCF395009FBA6C /* led.cpp */; };\n\t\tF897ED0B266EFF93005EE8F7 /* power.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08D323FCF3E6009FBA6C /* power.cpp */; };\n\t\tF897ED0C266EFF93005EE8F7 /* scan.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08D523FCF4D7009FBA6C /* scan.cpp */; };\n\t\tF897ED0D266EFF93005EE8F7 /* ItlIwm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8AF3A2F24F9F35B008911C1 /* ItlIwm.cpp */; };\n\t\tF897ED0E266EFF93005EE8F7 /* AirportSTAIOCTL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F89B6BDC25022F8C000F77FF /* AirportSTAIOCTL.cpp */; };\n\t\tF897ED0F266EFF93005EE8F7 /* AirportItlwm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F89B6BBD25021C9C000F77FF /* AirportItlwm.cpp */; };\n\t\tF897ED10266EFF93005EE8F7 /* AirportVirtualIOCTL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F89B6BDE25022FB5000F77FF /* AirportVirtualIOCTL.cpp */; };\n\t\tF897ED11266EFF93005EE8F7 /* AirportAWDL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F89B6BE025022FC7000F77FF /* AirportAWDL.cpp */; };\n\t\tF897ED13266EFF93005EE8F7 /* libkmod.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5088ECBC252884870068A63D /* libkmod.a */; };\n\t\tF89B6BBC25021C9C000F77FF /* AirportItlwm.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BBB25021C9C000F77FF /* AirportItlwm.hpp */; };\n\t\tF89B6BBE25021C9C000F77FF /* AirportItlwm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F89B6BBD25021C9C000F77FF /* AirportItlwm.cpp */; };\n\t\tF89B6BC725021DED000F77FF /* apple80211_wps.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BC325021DEC000F77FF /* apple80211_wps.h */; };\n\t\tF89B6BC925021DED000F77FF /* apple80211_var.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BC425021DEC000F77FF /* apple80211_var.h */; };\n\t\tF89B6BCB25021DED000F77FF /* apple80211_ioctl.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BC525021DEC000F77FF /* apple80211_ioctl.h */; };\n\t\tF89B6BD725021E66000F77FF /* IOSkywalkEthernetInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BD025021E66000F77FF /* IOSkywalkEthernetInterface.h */; };\n\t\tF89B6BDD25022F8C000F77FF /* AirportSTAIOCTL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F89B6BDC25022F8C000F77FF /* AirportSTAIOCTL.cpp */; };\n\t\tF89B6BDF25022FB5000F77FF /* AirportVirtualIOCTL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F89B6BDE25022FB5000F77FF /* AirportVirtualIOCTL.cpp */; };\n\t\tF89B6BE125022FC7000F77FF /* AirportAWDL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F89B6BE025022FC7000F77FF /* AirportAWDL.cpp */; };\n\t\tF89B6BE22502315B000F77FF /* utils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08BF23FCD4E2009FBA6C /* utils.cpp */; };\n\t\tF89B6BE32502315B000F77FF /* fw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08BD23FCD314009FBA6C /* fw.cpp */; };\n\t\tF89B6BE42502315B000F77FF /* io.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C123FCD999009FBA6C /* io.cpp */; };\n\t\tF89B6BE52502315B000F77FF /* rx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C323FCDC14009FBA6C /* rx.cpp */; };\n\t\tF89B6BE62502315B000F77FF /* tx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C523FCDC3B009FBA6C /* tx.cpp */; };\n\t\tF89B6BE72502315B000F77FF /* hw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C723FCE2ED009FBA6C /* hw.cpp */; };\n\t\tF89B6BE82502315B000F77FF /* phy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C923FCE537009FBA6C /* phy.cpp */; };\n\t\tF89B6BE92502315B000F77FF /* mac80211.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08CB23FCE5CA009FBA6C /* mac80211.cpp */; };\n\t\tF89B6BEA2502315B000F77FF /* nvm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08CD23FCE67F009FBA6C /* nvm.cpp */; };\n\t\tF89B6BEB2502315B000F77FF /* ctxt.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08CF23FCEE88009FBA6C /* ctxt.cpp */; };\n\t\tF89B6BEC2502315B000F77FF /* led.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08D123FCF395009FBA6C /* led.cpp */; };\n\t\tF89B6BED2502315B000F77FF /* power.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08D323FCF3E6009FBA6C /* power.cpp */; };\n\t\tF89B6BEE2502315B000F77FF /* scan.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08D523FCF4D7009FBA6C /* scan.cpp */; };\n\t\tF89B6BEF2502315B000F77FF /* ItlIwm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8AF3A2F24F9F35B008911C1 /* ItlIwm.cpp */; };\n\t\tF89B6BF025023162000F77FF /* ItlIwx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8D6CD642442E8F200D2A454 /* ItlIwx.cpp */; };\n\t\tF89B6BF12502316A000F77FF /* ItlHalService.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8D364F624F93AFD0029340B /* ItlHalService.cpp */; };\n\t\tF89B6BF3250231E3000F77FF /* FwBinary.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5076FA7F24CC71E40011B2BB /* FwBinary.cpp */; };\n\t\tF89B6BF5250231E3000F77FF /* ieee80211_proto.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC2F24080319007A9422 /* ieee80211_proto.c */; };\n\t\tF89B6BF6250231E3000F77FF /* _string.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3024080319007A9422 /* _string.c */; };\n\t\tF89B6BF7250231E3000F77FF /* ieee80211_ioctl.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3224080319007A9422 /* ieee80211_ioctl.c */; };\n\t\tF89B6BF8250231E3000F77FF /* ieee80211.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3324080319007A9422 /* ieee80211.c */; };\n\t\tF89B6BF9250231E3000F77FF /* ieee80211_rssadapt.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3424080319007A9422 /* ieee80211_rssadapt.c */; };\n\t\tF89B6BFA250231E3000F77FF /* ieee80211_input.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3524080319007A9422 /* ieee80211_input.c */; };\n\t\tF89B6BFB250231E3000F77FF /* timeout.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3724080319007A9422 /* timeout.c */; };\n\t\tF89B6BFC250231E3000F77FF /* ieee80211_mira.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3924080319007A9422 /* ieee80211_mira.c */; };\n\t\tF89B6BFD250231E3000F77FF /* ieee80211_crypto_bip.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3B24080319007A9422 /* ieee80211_crypto_bip.c */; };\n\t\tF89B6BFE250231E3000F77FF /* ieee80211_crypto_tkip.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3C24080319007A9422 /* ieee80211_crypto_tkip.c */; };\n\t\tF89B6BFF250231E3000F77FF /* ieee80211_crypto_ccmp.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3D24080319007A9422 /* ieee80211_crypto_ccmp.c */; };\n\t\tF89B6C00250231E3000F77FF /* ieee80211_crypto_wep.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC462408031A007A9422 /* ieee80211_crypto_wep.c */; };\n\t\tF89B6C01250231E3000F77FF /* ieee80211_pae_input.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3E24080319007A9422 /* ieee80211_pae_input.c */; };\n\t\tF89B6C02250231E3000F77FF /* ieee80211_amrr.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC4024080319007A9422 /* ieee80211_amrr.c */; };\n\t\tF89B6C03250231E3000F77FF /* ieee80211_output.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC472408031A007A9422 /* ieee80211_output.c */; };\n\t\tF89B6C04250231E3000F77FF /* ieee80211_crypto.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC482408031A007A9422 /* ieee80211_crypto.c */; };\n\t\tF89B6C05250231E3000F77FF /* CTimeout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC492408031A007A9422 /* CTimeout.cpp */; };\n\t\tF89B6C06250231E3000F77FF /* ieee80211_regdomain.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC4B2408031A007A9422 /* ieee80211_regdomain.c */; };\n\t\tF89B6C07250231E4000F77FF /* ieee80211_node.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC4C2408031A007A9422 /* ieee80211_node.c */; };\n\t\tF89B6C08250231E4000F77FF /* ieee80211_pae_output.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC4D2408031A007A9422 /* ieee80211_pae_output.c */; };\n\t\tF89B6C09250231E4000F77FF /* sha1-pbkdf2.c in Sources */ = {isa = PBXBuildFile; fileRef = F88D2B3B2414E64000BBE700 /* sha1-pbkdf2.c */; };\n\t\tF89B6C0A250231E4000F77FF /* aes.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07C923FCBC6C009FBA6C /* aes.c */; };\n\t\tF89B6C0B250231E4000F77FF /* hmac.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CA23FCBC6C009FBA6C /* hmac.c */; };\n\t\tF89B6C0C250231E4000F77FF /* sha2.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CB23FCBC6C009FBA6C /* sha2.c */; };\n\t\tF89B6C0D250231E4000F77FF /* rijndael.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CC23FCBC6C009FBA6C /* rijndael.c */; };\n\t\tF89B6C0E250231E4000F77FF /* ecb3_enc.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CD23FCBC6C009FBA6C /* ecb3_enc.c */; };\n\t\tF89B6C0F250231E4000F77FF /* set_key.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CE23FCBC6C009FBA6C /* set_key.c */; };\n\t\tF89B6C10250231E4000F77FF /* cast.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CF23FCBC6C009FBA6C /* cast.c */; };\n\t\tF89B6C11250231E4000F77FF /* michael.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07D123FCBC6C009FBA6C /* michael.c */; };\n\t\tF89B6C12250231E4000F77FF /* sha1.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07D823FCBC6C009FBA6C /* sha1.c */; };\n\t\tF89B6C13250231E4000F77FF /* cmac.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07DD23FCBC6C009FBA6C /* cmac.c */; };\n\t\tF89B6C14250231E4000F77FF /* ecb_enc.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07E423FCBC6C009FBA6C /* ecb_enc.c */; };\n\t\tF89B6C15250231E4000F77FF /* chachapoly.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07E923FCBC6C009FBA6C /* chachapoly.c */; };\n\t\tF89B6C16250231E4000F77FF /* md5.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07EA23FCBC6C009FBA6C /* md5.c */; };\n\t\tF89B6C17250231E4000F77FF /* arc4.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07EB23FCBC6C009FBA6C /* arc4.c */; };\n\t\tF89B6C18250231E4000F77FF /* blf.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07EC23FCBC6C009FBA6C /* blf.c */; };\n\t\tF89B6C19250231E4000F77FF /* poly1305.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07ED23FCBC6C009FBA6C /* poly1305.c */; };\n\t\tF89B6C1A250231E4000F77FF /* key_wrap.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07F023FCBC6C009FBA6C /* key_wrap.c */; };\n\t\tF89B6C1B250231E4000F77FF /* gmac.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07F223FCBC6C009FBA6C /* gmac.c */; };\n\t\tF89B6C1C250231E4000F77FF /* rmd160.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07F323FCBC6C009FBA6C /* rmd160.c */; };\n\t\tF89B6C1D250231E4000F77FF /* idgen.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07F423FCBC6C009FBA6C /* idgen.c */; };\n\t\tF89B6C1E250231E4000F77FF /* compat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A07BA23FCBC6C009FBA6C /* compat.cpp */; };\n\t\tF89B6C1F250231E4000F77FF /* zutil.c in Sources */ = {isa = PBXBuildFile; fileRef = F8FA0EED2501E8C100B1822E /* zutil.c */; };\n\t\tF89B6C20250232DC000F77FF /* _mbuf.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8D257732495A33500872E4F /* _mbuf.cpp */; };\n\t\tF89B6C21250232DC000F77FF /* _task.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8F9EDE0240B7415009CB8E7 /* _task.cpp */; };\n\t\tF89B6C2325027609000F77FF /* debug.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6C2225027609000F77FF /* debug.h */; };\n\t\tF89F35F22A49867F00061876 /* IO80211ControllerV2.h in Headers */ = {isa = PBXBuildFile; fileRef = F89F35F12A49867F00061876 /* IO80211ControllerV2.h */; };\n\t\tF89F35F32A49867F00061876 /* IO80211ControllerV2.h in Headers */ = {isa = PBXBuildFile; fileRef = F89F35F12A49867F00061876 /* IO80211ControllerV2.h */; };\n\t\tF89F35F42A49867F00061876 /* IO80211ControllerV2.h in Headers */ = {isa = PBXBuildFile; fileRef = F89F35F12A49867F00061876 /* IO80211ControllerV2.h */; };\n\t\tF89F35F52A49867F00061876 /* IO80211ControllerV2.h in Headers */ = {isa = PBXBuildFile; fileRef = F89F35F12A49867F00061876 /* IO80211ControllerV2.h */; };\n\t\tF89F35F62A49867F00061876 /* IO80211ControllerV2.h in Headers */ = {isa = PBXBuildFile; fileRef = F89F35F12A49867F00061876 /* IO80211ControllerV2.h */; };\n\t\tF89F35F72A49867F00061876 /* IO80211ControllerV2.h in Headers */ = {isa = PBXBuildFile; fileRef = F89F35F12A49867F00061876 /* IO80211ControllerV2.h */; };\n\t\tF89F35F82A49867F00061876 /* IO80211ControllerV2.h in Headers */ = {isa = PBXBuildFile; fileRef = F89F35F12A49867F00061876 /* IO80211ControllerV2.h */; };\n\t\tF8A028222A4A7DDC00C6DE90 /* AirportItlwmV2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8A028202A4A7DDC00C6DE90 /* AirportItlwmV2.cpp */; };\n\t\tF8A028232A4A7DDC00C6DE90 /* AirportItlwmV2.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F8A028212A4A7DDC00C6DE90 /* AirportItlwmV2.hpp */; };\n\t\tF8A0282F2A4A7E0400C6DE90 /* AirportItlwmEthernetInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8A0282D2A4A7E0400C6DE90 /* AirportItlwmEthernetInterface.cpp */; };\n\t\tF8A028302A4A7E0500C6DE90 /* AirportItlwmEthernetInterface.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F8A0282E2A4A7E0400C6DE90 /* AirportItlwmEthernetInterface.hpp */; };\n\t\tF8A028722A4A7FE100C6DE90 /* AirportItlwmSkywalkInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8A028702A4A7FE100C6DE90 /* AirportItlwmSkywalkInterface.cpp */; };\n\t\tF8A028732A4A7FE100C6DE90 /* AirportItlwmSkywalkInterface.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F8A028712A4A7FE100C6DE90 /* AirportItlwmSkywalkInterface.hpp */; };\n\t\tF8A0287F2A4A80EA00C6DE90 /* IOPCIEDeviceWrapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8A0287D2A4A80EA00C6DE90 /* IOPCIEDeviceWrapper.cpp */; };\n\t\tF8A028802A4A80EA00C6DE90 /* IOPCIEDeviceWrapper.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F8A0287E2A4A80EA00C6DE90 /* IOPCIEDeviceWrapper.hpp */; };\n\t\tF8A4307325062CE300EA545E /* zutil.c in Sources */ = {isa = PBXBuildFile; fileRef = F8FA0EED2501E8C100B1822E /* zutil.c */; };\n\t\tF8AE64F9285471560085B4CF /* debug.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6C2225027609000F77FF /* debug.h */; };\n\t\tF8AE64FA285471560085B4CF /* IOSkywalkEthernetInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BD025021E66000F77FF /* IOSkywalkEthernetInterface.h */; };\n\t\tF8AE64FB285471560085B4CF /* apple80211_ioctl.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BC525021DEC000F77FF /* apple80211_ioctl.h */; };\n\t\tF8AE64FC285471560085B4CF /* IO80211P2PInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA36252D834500520FD4 /* IO80211P2PInterface.h */; };\n\t\tF8AE64FD285471560085B4CF /* IO80211WorkLoop.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA39252D834500520FD4 /* IO80211WorkLoop.h */; };\n\t\tF8AE64FE285471560085B4CF /* apple80211_var.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BC425021DEC000F77FF /* apple80211_var.h */; };\n\t\tF8AE64FF285471560085B4CF /* AirportItlwmInterface.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F8CA44A225091AF60036119A /* AirportItlwmInterface.hpp */; };\n\t\tF8AE6500285471560085B4CF /* IO80211Interface.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA38252D834500520FD4 /* IO80211Interface.h */; };\n\t\tF8AE6501285471560085B4CF /* (null) in Headers */ = {isa = PBXBuildFile; };\n\t\tF8AE6502285471560085B4CF /* IO80211SkywalkInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA37252D834500520FD4 /* IO80211SkywalkInterface.h */; };\n\t\tF8AE6503285471560085B4CF /* AirportItlwm.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BBB25021C9C000F77FF /* AirportItlwm.hpp */; };\n\t\tF8AE6504285471560085B4CF /* IO80211VirtualInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA34252D834500520FD4 /* IO80211VirtualInterface.h */; };\n\t\tF8AE6505285471560085B4CF /* IO80211Controller.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA35252D834500520FD4 /* IO80211Controller.h */; };\n\t\tF8AE6506285471560085B4CF /* (null) in Headers */ = {isa = PBXBuildFile; };\n\t\tF8AE6507285471560085B4CF /* ieee80211_ra.h in Headers */ = {isa = PBXBuildFile; fileRef = F8C594D225FD935B0007D19C /* ieee80211_ra.h */; };\n\t\tF8AE6508285471560085B4CF /* apple80211_wps.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BC325021DEC000F77FF /* apple80211_wps.h */; };\n\t\tF8AE650A285471560085B4CF /* _mbuf.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8D257732495A33500872E4F /* _mbuf.cpp */; };\n\t\tF8AE650B285471560085B4CF /* ieee80211_ra.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C594D125FD935B0007D19C /* ieee80211_ra.c */; };\n\t\tF8AE650C285471560085B4CF /* _task.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8F9EDE0240B7415009CB8E7 /* _task.cpp */; };\n\t\tF8AE650D285471560085B4CF /* FwBinary.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5076FA7F24CC71E40011B2BB /* FwBinary.cpp */; };\n\t\tF8AE650F285471560085B4CF /* ieee80211_proto.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC2F24080319007A9422 /* ieee80211_proto.c */; };\n\t\tF8AE6510285471560085B4CF /* AirportItlwmInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8CA44A125091AF60036119A /* AirportItlwmInterface.cpp */; };\n\t\tF8AE6511285471560085B4CF /* _string.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3024080319007A9422 /* _string.c */; };\n\t\tF8AE6512285471560085B4CF /* ieee80211_ioctl.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3224080319007A9422 /* ieee80211_ioctl.c */; };\n\t\tF8AE6513285471560085B4CF /* ieee80211.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3324080319007A9422 /* ieee80211.c */; };\n\t\tF8AE6514285471560085B4CF /* ieee80211_rssadapt.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3424080319007A9422 /* ieee80211_rssadapt.c */; };\n\t\tF8AE6515285471560085B4CF /* ieee80211_input.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3524080319007A9422 /* ieee80211_input.c */; };\n\t\tF8AE6516285471560085B4CF /* timeout.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3724080319007A9422 /* timeout.c */; };\n\t\tF8AE6517285471560085B4CF /* ieee80211_mira.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3924080319007A9422 /* ieee80211_mira.c */; };\n\t\tF8AE6518285471560085B4CF /* ieee80211_crypto_bip.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3B24080319007A9422 /* ieee80211_crypto_bip.c */; };\n\t\tF8AE6519285471560085B4CF /* ieee80211_crypto_tkip.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3C24080319007A9422 /* ieee80211_crypto_tkip.c */; };\n\t\tF8AE651A285471560085B4CF /* ieee80211_crypto_ccmp.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3D24080319007A9422 /* ieee80211_crypto_ccmp.c */; };\n\t\tF8AE651B285471560085B4CF /* ieee80211_crypto_wep.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC462408031A007A9422 /* ieee80211_crypto_wep.c */; };\n\t\tF8AE651C285471560085B4CF /* ieee80211_pae_input.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3E24080319007A9422 /* ieee80211_pae_input.c */; };\n\t\tF8AE651D285471560085B4CF /* ieee80211_amrr.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC4024080319007A9422 /* ieee80211_amrr.c */; };\n\t\tF8AE651E285471560085B4CF /* ieee80211_output.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC472408031A007A9422 /* ieee80211_output.c */; };\n\t\tF8AE651F285471560085B4CF /* ieee80211_crypto.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC482408031A007A9422 /* ieee80211_crypto.c */; };\n\t\tF8AE6520285471560085B4CF /* CTimeout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC492408031A007A9422 /* CTimeout.cpp */; };\n\t\tF8AE6521285471560085B4CF /* ieee80211_regdomain.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC4B2408031A007A9422 /* ieee80211_regdomain.c */; };\n\t\tF8AE6522285471560085B4CF /* ieee80211_node.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC4C2408031A007A9422 /* ieee80211_node.c */; };\n\t\tF8AE6523285471560085B4CF /* ieee80211_pae_output.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC4D2408031A007A9422 /* ieee80211_pae_output.c */; };\n\t\tF8AE6524285471560085B4CF /* sha1-pbkdf2.c in Sources */ = {isa = PBXBuildFile; fileRef = F88D2B3B2414E64000BBE700 /* sha1-pbkdf2.c */; };\n\t\tF8AE6525285471560085B4CF /* aes.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07C923FCBC6C009FBA6C /* aes.c */; };\n\t\tF8AE6526285471560085B4CF /* hmac.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CA23FCBC6C009FBA6C /* hmac.c */; };\n\t\tF8AE6527285471560085B4CF /* sha2.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CB23FCBC6C009FBA6C /* sha2.c */; };\n\t\tF8AE6528285471560085B4CF /* rijndael.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CC23FCBC6C009FBA6C /* rijndael.c */; };\n\t\tF8AE6529285471560085B4CF /* ecb3_enc.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CD23FCBC6C009FBA6C /* ecb3_enc.c */; };\n\t\tF8AE652A285471560085B4CF /* set_key.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CE23FCBC6C009FBA6C /* set_key.c */; };\n\t\tF8AE652B285471560085B4CF /* cast.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CF23FCBC6C009FBA6C /* cast.c */; };\n\t\tF8AE652C285471560085B4CF /* michael.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07D123FCBC6C009FBA6C /* michael.c */; };\n\t\tF8AE652D285471560085B4CF /* sha1.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07D823FCBC6C009FBA6C /* sha1.c */; };\n\t\tF8AE652E285471560085B4CF /* cmac.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07DD23FCBC6C009FBA6C /* cmac.c */; };\n\t\tF8AE652F285471560085B4CF /* ecb_enc.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07E423FCBC6C009FBA6C /* ecb_enc.c */; };\n\t\tF8AE6530285471560085B4CF /* chachapoly.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07E923FCBC6C009FBA6C /* chachapoly.c */; };\n\t\tF8AE6531285471560085B4CF /* (null) in Sources */ = {isa = PBXBuildFile; };\n\t\tF8AE6532285471560085B4CF /* md5.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07EA23FCBC6C009FBA6C /* md5.c */; };\n\t\tF8AE6533285471560085B4CF /* arc4.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07EB23FCBC6C009FBA6C /* arc4.c */; };\n\t\tF8AE6534285471560085B4CF /* blf.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07EC23FCBC6C009FBA6C /* blf.c */; };\n\t\tF8AE6535285471560085B4CF /* poly1305.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07ED23FCBC6C009FBA6C /* poly1305.c */; };\n\t\tF8AE6536285471560085B4CF /* key_wrap.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07F023FCBC6C009FBA6C /* key_wrap.c */; };\n\t\tF8AE6537285471560085B4CF /* gmac.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07F223FCBC6C009FBA6C /* gmac.c */; };\n\t\tF8AE6538285471560085B4CF /* rmd160.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07F323FCBC6C009FBA6C /* rmd160.c */; };\n\t\tF8AE6539285471560085B4CF /* idgen.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07F423FCBC6C009FBA6C /* idgen.c */; };\n\t\tF8AE653A285471560085B4CF /* compat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A07BA23FCBC6C009FBA6C /* compat.cpp */; };\n\t\tF8AE653B285471560085B4CF /* zutil.c in Sources */ = {isa = PBXBuildFile; fileRef = F8FA0EED2501E8C100B1822E /* zutil.c */; };\n\t\tF8AE653C285471560085B4CF /* ItlHalService.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8D364F624F93AFD0029340B /* ItlHalService.cpp */; };\n\t\tF8AE653D285471560085B4CF /* ItlIwx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8D6CD642442E8F200D2A454 /* ItlIwx.cpp */; };\n\t\tF8AE653E285471560085B4CF /* utils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08BF23FCD4E2009FBA6C /* utils.cpp */; };\n\t\tF8AE653F285471560085B4CF /* fw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08BD23FCD314009FBA6C /* fw.cpp */; };\n\t\tF8AE6540285471560085B4CF /* io.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C123FCD999009FBA6C /* io.cpp */; };\n\t\tF8AE6541285471560085B4CF /* rx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C323FCDC14009FBA6C /* rx.cpp */; };\n\t\tF8AE6542285471560085B4CF /* coex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F837C91C2724577F00B2C499 /* coex.cpp */; };\n\t\tF8AE6543285471560085B4CF /* tx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C523FCDC3B009FBA6C /* tx.cpp */; };\n\t\tF8AE6544285471560085B4CF /* hw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C723FCE2ED009FBA6C /* hw.cpp */; };\n\t\tF8AE6545285471560085B4CF /* ItlIwn.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 17FD7F0E255E4AC800611406 /* ItlIwn.cpp */; };\n\t\tF8AE6546285471560085B4CF /* phy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C923FCE537009FBA6C /* phy.cpp */; };\n\t\tF8AE6547285471560085B4CF /* mac80211.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08CB23FCE5CA009FBA6C /* mac80211.cpp */; };\n\t\tF8AE6548285471560085B4CF /* nvm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08CD23FCE67F009FBA6C /* nvm.cpp */; };\n\t\tF8AE6549285471560085B4CF /* ctxt.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08CF23FCEE88009FBA6C /* ctxt.cpp */; };\n\t\tF8AE654A285471560085B4CF /* led.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08D123FCF395009FBA6C /* led.cpp */; };\n\t\tF8AE654B285471560085B4CF /* power.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08D323FCF3E6009FBA6C /* power.cpp */; };\n\t\tF8AE654C285471560085B4CF /* scan.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08D523FCF4D7009FBA6C /* scan.cpp */; };\n\t\tF8AE654D285471560085B4CF /* ItlIwm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8AF3A2F24F9F35B008911C1 /* ItlIwm.cpp */; };\n\t\tF8AE654E285471560085B4CF /* AirportSTAIOCTL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F89B6BDC25022F8C000F77FF /* AirportSTAIOCTL.cpp */; };\n\t\tF8AE654F285471560085B4CF /* AirportItlwm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F89B6BBD25021C9C000F77FF /* AirportItlwm.cpp */; };\n\t\tF8AE6550285471560085B4CF /* AirportVirtualIOCTL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F89B6BDE25022FB5000F77FF /* AirportVirtualIOCTL.cpp */; };\n\t\tF8AE6551285471560085B4CF /* AirportAWDL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F89B6BE025022FC7000F77FF /* AirportAWDL.cpp */; };\n\t\tF8AE6553285471560085B4CF /* libkmod.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5088ECBC252884870068A63D /* libkmod.a */; };\n\t\tF8AF3A3124F9F35B008911C1 /* ItlIwm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8AF3A2F24F9F35B008911C1 /* ItlIwm.cpp */; };\n\t\tF8AF3A3224F9F35B008911C1 /* ItlIwm.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F8AF3A3024F9F35B008911C1 /* ItlIwm.hpp */; };\n\t\tF8B210AB2A2EC2680043ECBD /* debug.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6C2225027609000F77FF /* debug.h */; };\n\t\tF8B210AC2A2EC2680043ECBD /* IOSkywalkEthernetInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BD025021E66000F77FF /* IOSkywalkEthernetInterface.h */; };\n\t\tF8B210AD2A2EC2680043ECBD /* apple80211_ioctl.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BC525021DEC000F77FF /* apple80211_ioctl.h */; };\n\t\tF8B210AE2A2EC2680043ECBD /* IO80211P2PInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA36252D834500520FD4 /* IO80211P2PInterface.h */; };\n\t\tF8B210AF2A2EC2680043ECBD /* IO80211WorkLoop.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA39252D834500520FD4 /* IO80211WorkLoop.h */; };\n\t\tF8B210B02A2EC2680043ECBD /* apple80211_var.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BC425021DEC000F77FF /* apple80211_var.h */; };\n\t\tF8B210B12A2EC2680043ECBD /* AirportItlwmInterface.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F8CA44A225091AF60036119A /* AirportItlwmInterface.hpp */; };\n\t\tF8B210B22A2EC2680043ECBD /* IO80211Interface.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA38252D834500520FD4 /* IO80211Interface.h */; };\n\t\tF8B210B32A2EC2680043ECBD /* (null) in Headers */ = {isa = PBXBuildFile; };\n\t\tF8B210B42A2EC2680043ECBD /* IO80211SkywalkInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA37252D834500520FD4 /* IO80211SkywalkInterface.h */; };\n\t\tF8B210B52A2EC2680043ECBD /* AirportItlwm.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BBB25021C9C000F77FF /* AirportItlwm.hpp */; };\n\t\tF8B210B62A2EC2680043ECBD /* IO80211VirtualInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA34252D834500520FD4 /* IO80211VirtualInterface.h */; };\n\t\tF8B210B72A2EC2680043ECBD /* IO80211Controller.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA35252D834500520FD4 /* IO80211Controller.h */; };\n\t\tF8B210B82A2EC2680043ECBD /* (null) in Headers */ = {isa = PBXBuildFile; };\n\t\tF8B210B92A2EC2680043ECBD /* ieee80211_ra.h in Headers */ = {isa = PBXBuildFile; fileRef = F8C594D225FD935B0007D19C /* ieee80211_ra.h */; };\n\t\tF8B210BA2A2EC2680043ECBD /* apple80211_wps.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BC325021DEC000F77FF /* apple80211_wps.h */; };\n\t\tF8B210BC2A2EC2680043ECBD /* _mbuf.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8D257732495A33500872E4F /* _mbuf.cpp */; };\n\t\tF8B210BD2A2EC2680043ECBD /* ieee80211_ra.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C594D125FD935B0007D19C /* ieee80211_ra.c */; };\n\t\tF8B210BE2A2EC2680043ECBD /* _task.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8F9EDE0240B7415009CB8E7 /* _task.cpp */; };\n\t\tF8B210BF2A2EC2680043ECBD /* FwBinary.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5076FA7F24CC71E40011B2BB /* FwBinary.cpp */; };\n\t\tF8B210C02A2EC2680043ECBD /* ieee80211_proto.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC2F24080319007A9422 /* ieee80211_proto.c */; };\n\t\tF8B210C22A2EC2680043ECBD /* _string.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3024080319007A9422 /* _string.c */; };\n\t\tF8B210C32A2EC2680043ECBD /* ieee80211_ioctl.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3224080319007A9422 /* ieee80211_ioctl.c */; };\n\t\tF8B210C42A2EC2680043ECBD /* ieee80211.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3324080319007A9422 /* ieee80211.c */; };\n\t\tF8B210C52A2EC2680043ECBD /* ieee80211_rssadapt.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3424080319007A9422 /* ieee80211_rssadapt.c */; };\n\t\tF8B210C62A2EC2680043ECBD /* ieee80211_input.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3524080319007A9422 /* ieee80211_input.c */; };\n\t\tF8B210C72A2EC2680043ECBD /* timeout.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3724080319007A9422 /* timeout.c */; };\n\t\tF8B210C82A2EC2680043ECBD /* ieee80211_mira.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3924080319007A9422 /* ieee80211_mira.c */; };\n\t\tF8B210C92A2EC2680043ECBD /* ieee80211_crypto_bip.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3B24080319007A9422 /* ieee80211_crypto_bip.c */; };\n\t\tF8B210CA2A2EC2680043ECBD /* ieee80211_crypto_tkip.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3C24080319007A9422 /* ieee80211_crypto_tkip.c */; };\n\t\tF8B210CB2A2EC2680043ECBD /* ieee80211_crypto_ccmp.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3D24080319007A9422 /* ieee80211_crypto_ccmp.c */; };\n\t\tF8B210CC2A2EC2680043ECBD /* ieee80211_crypto_wep.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC462408031A007A9422 /* ieee80211_crypto_wep.c */; };\n\t\tF8B210CD2A2EC2680043ECBD /* ieee80211_pae_input.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3E24080319007A9422 /* ieee80211_pae_input.c */; };\n\t\tF8B210CE2A2EC2680043ECBD /* ieee80211_amrr.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC4024080319007A9422 /* ieee80211_amrr.c */; };\n\t\tF8B210CF2A2EC2680043ECBD /* ieee80211_output.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC472408031A007A9422 /* ieee80211_output.c */; };\n\t\tF8B210D02A2EC2680043ECBD /* ieee80211_crypto.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC482408031A007A9422 /* ieee80211_crypto.c */; };\n\t\tF8B210D12A2EC2680043ECBD /* CTimeout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC492408031A007A9422 /* CTimeout.cpp */; };\n\t\tF8B210D22A2EC2680043ECBD /* ieee80211_regdomain.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC4B2408031A007A9422 /* ieee80211_regdomain.c */; };\n\t\tF8B210D32A2EC2680043ECBD /* ieee80211_node.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC4C2408031A007A9422 /* ieee80211_node.c */; };\n\t\tF8B210D42A2EC2680043ECBD /* ieee80211_pae_output.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC4D2408031A007A9422 /* ieee80211_pae_output.c */; };\n\t\tF8B210D52A2EC2680043ECBD /* sha1-pbkdf2.c in Sources */ = {isa = PBXBuildFile; fileRef = F88D2B3B2414E64000BBE700 /* sha1-pbkdf2.c */; };\n\t\tF8B210D62A2EC2680043ECBD /* aes.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07C923FCBC6C009FBA6C /* aes.c */; };\n\t\tF8B210D72A2EC2680043ECBD /* hmac.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CA23FCBC6C009FBA6C /* hmac.c */; };\n\t\tF8B210D82A2EC2680043ECBD /* sha2.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CB23FCBC6C009FBA6C /* sha2.c */; };\n\t\tF8B210D92A2EC2680043ECBD /* rijndael.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CC23FCBC6C009FBA6C /* rijndael.c */; };\n\t\tF8B210DA2A2EC2680043ECBD /* ecb3_enc.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CD23FCBC6C009FBA6C /* ecb3_enc.c */; };\n\t\tF8B210DB2A2EC2680043ECBD /* set_key.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CE23FCBC6C009FBA6C /* set_key.c */; };\n\t\tF8B210DC2A2EC2680043ECBD /* cast.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CF23FCBC6C009FBA6C /* cast.c */; };\n\t\tF8B210DD2A2EC2680043ECBD /* michael.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07D123FCBC6C009FBA6C /* michael.c */; };\n\t\tF8B210DE2A2EC2680043ECBD /* sha1.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07D823FCBC6C009FBA6C /* sha1.c */; };\n\t\tF8B210DF2A2EC2680043ECBD /* cmac.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07DD23FCBC6C009FBA6C /* cmac.c */; };\n\t\tF8B210E02A2EC2680043ECBD /* ecb_enc.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07E423FCBC6C009FBA6C /* ecb_enc.c */; };\n\t\tF8B210E12A2EC2680043ECBD /* chachapoly.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07E923FCBC6C009FBA6C /* chachapoly.c */; };\n\t\tF8B210E22A2EC2680043ECBD /* (null) in Sources */ = {isa = PBXBuildFile; };\n\t\tF8B210E32A2EC2680043ECBD /* md5.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07EA23FCBC6C009FBA6C /* md5.c */; };\n\t\tF8B210E42A2EC2680043ECBD /* arc4.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07EB23FCBC6C009FBA6C /* arc4.c */; };\n\t\tF8B210E52A2EC2680043ECBD /* blf.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07EC23FCBC6C009FBA6C /* blf.c */; };\n\t\tF8B210E62A2EC2680043ECBD /* _ifq.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5FA2AE328A797B200847103 /* _ifq.cpp */; };\n\t\tF8B210E72A2EC2680043ECBD /* poly1305.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07ED23FCBC6C009FBA6C /* poly1305.c */; };\n\t\tF8B210E82A2EC2680043ECBD /* key_wrap.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07F023FCBC6C009FBA6C /* key_wrap.c */; };\n\t\tF8B210E92A2EC2680043ECBD /* gmac.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07F223FCBC6C009FBA6C /* gmac.c */; };\n\t\tF8B210EA2A2EC2680043ECBD /* rmd160.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07F323FCBC6C009FBA6C /* rmd160.c */; };\n\t\tF8B210EB2A2EC2680043ECBD /* idgen.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07F423FCBC6C009FBA6C /* idgen.c */; };\n\t\tF8B210EC2A2EC2680043ECBD /* compat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A07BA23FCBC6C009FBA6C /* compat.cpp */; };\n\t\tF8B210ED2A2EC2680043ECBD /* zutil.c in Sources */ = {isa = PBXBuildFile; fileRef = F8FA0EED2501E8C100B1822E /* zutil.c */; };\n\t\tF8B210EE2A2EC2680043ECBD /* ItlHalService.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8D364F624F93AFD0029340B /* ItlHalService.cpp */; };\n\t\tF8B210EF2A2EC2680043ECBD /* ItlIwx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8D6CD642442E8F200D2A454 /* ItlIwx.cpp */; };\n\t\tF8B210F02A2EC2680043ECBD /* utils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08BF23FCD4E2009FBA6C /* utils.cpp */; };\n\t\tF8B210F12A2EC2680043ECBD /* fw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08BD23FCD314009FBA6C /* fw.cpp */; };\n\t\tF8B210F22A2EC2680043ECBD /* io.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C123FCD999009FBA6C /* io.cpp */; };\n\t\tF8B210F32A2EC2680043ECBD /* rx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C323FCDC14009FBA6C /* rx.cpp */; };\n\t\tF8B210F42A2EC2680043ECBD /* coex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F837C91C2724577F00B2C499 /* coex.cpp */; };\n\t\tF8B210F52A2EC2680043ECBD /* tx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C523FCDC3B009FBA6C /* tx.cpp */; };\n\t\tF8B210F62A2EC2680043ECBD /* hw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C723FCE2ED009FBA6C /* hw.cpp */; };\n\t\tF8B210F72A2EC2680043ECBD /* ItlIwn.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 17FD7F0E255E4AC800611406 /* ItlIwn.cpp */; };\n\t\tF8B210F82A2EC2680043ECBD /* phy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C923FCE537009FBA6C /* phy.cpp */; };\n\t\tF8B210F92A2EC2680043ECBD /* mac80211.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08CB23FCE5CA009FBA6C /* mac80211.cpp */; };\n\t\tF8B210FA2A2EC2680043ECBD /* nvm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08CD23FCE67F009FBA6C /* nvm.cpp */; };\n\t\tF8B210FB2A2EC2680043ECBD /* ctxt.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08CF23FCEE88009FBA6C /* ctxt.cpp */; };\n\t\tF8B210FC2A2EC2680043ECBD /* led.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08D123FCF395009FBA6C /* led.cpp */; };\n\t\tF8B210FD2A2EC2680043ECBD /* power.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08D323FCF3E6009FBA6C /* power.cpp */; };\n\t\tF8B210FE2A2EC2680043ECBD /* scan.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08D523FCF4D7009FBA6C /* scan.cpp */; };\n\t\tF8B210FF2A2EC2680043ECBD /* ItlIwm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8AF3A2F24F9F35B008911C1 /* ItlIwm.cpp */; };\n\t\tF8B211052A2EC2680043ECBD /* libkmod.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5088ECBC252884870068A63D /* libkmod.a */; };\n\t\tF8C2EC4F2408031A007A9422 /* ieee80211_proto.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC2F24080319007A9422 /* ieee80211_proto.c */; };\n\t\tF8C2EC502408031A007A9422 /* _string.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3024080319007A9422 /* _string.c */; };\n\t\tF8C2EC512408031A007A9422 /* ieee80211_amrr.h in Headers */ = {isa = PBXBuildFile; fileRef = F8C2EC3124080319007A9422 /* ieee80211_amrr.h */; };\n\t\tF8C2EC522408031A007A9422 /* ieee80211_ioctl.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3224080319007A9422 /* ieee80211_ioctl.c */; };\n\t\tF8C2EC532408031A007A9422 /* ieee80211.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3324080319007A9422 /* ieee80211.c */; };\n\t\tF8C2EC542408031A007A9422 /* ieee80211_rssadapt.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3424080319007A9422 /* ieee80211_rssadapt.c */; };\n\t\tF8C2EC552408031A007A9422 /* ieee80211_input.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3524080319007A9422 /* ieee80211_input.c */; };\n\t\tF8C2EC562408031A007A9422 /* ieee80211_node.h in Headers */ = {isa = PBXBuildFile; fileRef = F8C2EC3624080319007A9422 /* ieee80211_node.h */; };\n\t\tF8C2EC572408031A007A9422 /* timeout.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3724080319007A9422 /* timeout.c */; };\n\t\tF8C2EC582408031A007A9422 /* ieee80211_regdomain.h in Headers */ = {isa = PBXBuildFile; fileRef = F8C2EC3824080319007A9422 /* ieee80211_regdomain.h */; };\n\t\tF8C2EC592408031A007A9422 /* ieee80211_mira.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3924080319007A9422 /* ieee80211_mira.c */; };\n\t\tF8C2EC5A2408031A007A9422 /* ieee80211_crypto.h in Headers */ = {isa = PBXBuildFile; fileRef = F8C2EC3A24080319007A9422 /* ieee80211_crypto.h */; };\n\t\tF8C2EC5B2408031A007A9422 /* ieee80211_crypto_bip.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3B24080319007A9422 /* ieee80211_crypto_bip.c */; };\n\t\tF8C2EC5C2408031A007A9422 /* ieee80211_crypto_tkip.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3C24080319007A9422 /* ieee80211_crypto_tkip.c */; };\n\t\tF8C2EC5D2408031A007A9422 /* ieee80211_crypto_ccmp.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3D24080319007A9422 /* ieee80211_crypto_ccmp.c */; };\n\t\tF8C2EC5E2408031A007A9422 /* ieee80211_pae_input.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3E24080319007A9422 /* ieee80211_pae_input.c */; };\n\t\tF8C2EC5F2408031A007A9422 /* ieee80211_radiotap.h in Headers */ = {isa = PBXBuildFile; fileRef = F8C2EC3F24080319007A9422 /* ieee80211_radiotap.h */; };\n\t\tF8C2EC602408031A007A9422 /* ieee80211_amrr.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC4024080319007A9422 /* ieee80211_amrr.c */; };\n\t\tF8C2EC612408031A007A9422 /* ieee80211_proto.h in Headers */ = {isa = PBXBuildFile; fileRef = F8C2EC4124080319007A9422 /* ieee80211_proto.h */; };\n\t\tF8C2EC622408031A007A9422 /* ieee80211_rssadapt.h in Headers */ = {isa = PBXBuildFile; fileRef = F8C2EC422408031A007A9422 /* ieee80211_rssadapt.h */; };\n\t\tF8C2EC632408031A007A9422 /* ieee80211.h in Headers */ = {isa = PBXBuildFile; fileRef = F8C2EC432408031A007A9422 /* ieee80211.h */; };\n\t\tF8C2EC642408031A007A9422 /* ieee80211_priv.h in Headers */ = {isa = PBXBuildFile; fileRef = F8C2EC442408031A007A9422 /* ieee80211_priv.h */; };\n\t\tF8C2EC652408031A007A9422 /* ieee80211_ioctl.h in Headers */ = {isa = PBXBuildFile; fileRef = F8C2EC452408031A007A9422 /* ieee80211_ioctl.h */; };\n\t\tF8C2EC662408031A007A9422 /* ieee80211_crypto_wep.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC462408031A007A9422 /* ieee80211_crypto_wep.c */; };\n\t\tF8C2EC672408031A007A9422 /* ieee80211_output.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC472408031A007A9422 /* ieee80211_output.c */; };\n\t\tF8C2EC682408031A007A9422 /* ieee80211_crypto.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC482408031A007A9422 /* ieee80211_crypto.c */; };\n\t\tF8C2EC692408031A007A9422 /* CTimeout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC492408031A007A9422 /* CTimeout.cpp */; };\n\t\tF8C2EC6A2408031A007A9422 /* ieee80211_mira.h in Headers */ = {isa = PBXBuildFile; fileRef = F8C2EC4A2408031A007A9422 /* ieee80211_mira.h */; };\n\t\tF8C2EC6B2408031A007A9422 /* ieee80211_regdomain.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC4B2408031A007A9422 /* ieee80211_regdomain.c */; };\n\t\tF8C2EC6C2408031A007A9422 /* ieee80211_node.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC4C2408031A007A9422 /* ieee80211_node.c */; };\n\t\tF8C2EC6D2408031A007A9422 /* ieee80211_pae_output.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC4D2408031A007A9422 /* ieee80211_pae_output.c */; };\n\t\tF8C2EC6E2408031A007A9422 /* ieee80211_var.h in Headers */ = {isa = PBXBuildFile; fileRef = F8C2EC4E2408031A007A9422 /* ieee80211_var.h */; };\n\t\tF8C2EC9124080557007A9422 /* _buf.h in Headers */ = {isa = PBXBuildFile; fileRef = F8C2EC8724080556007A9422 /* _buf.h */; };\n\t\tF8C2EC9224080557007A9422 /* CTimeout.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F8C2EC8824080556007A9422 /* CTimeout.hpp */; };\n\t\tF8C2EC9324080557007A9422 /* _arc4random.h in Headers */ = {isa = PBXBuildFile; fileRef = F8C2EC8924080556007A9422 /* _arc4random.h */; };\n\t\tF8C2EC9424080557007A9422 /* endian.h in Headers */ = {isa = PBXBuildFile; fileRef = F8C2EC8A24080556007A9422 /* endian.h */; };\n\t\tF8C2EC9524080557007A9422 /* _mbuf.h in Headers */ = {isa = PBXBuildFile; fileRef = F8C2EC8B24080556007A9422 /* _mbuf.h */; };\n\t\tF8C2EC9624080557007A9422 /* _if_ether.h in Headers */ = {isa = PBXBuildFile; fileRef = F8C2EC8C24080556007A9422 /* _if_ether.h */; };\n\t\tF8C2EC9724080557007A9422 /* tree.h in Headers */ = {isa = PBXBuildFile; fileRef = F8C2EC8D24080556007A9422 /* tree.h */; };\n\t\tF8C2EC9824080557007A9422 /* _if_media.h in Headers */ = {isa = PBXBuildFile; fileRef = F8C2EC8E24080556007A9422 /* _if_media.h */; };\n\t\tF8C2EC9924080557007A9422 /* _null.h in Headers */ = {isa = PBXBuildFile; fileRef = F8C2EC8F24080556007A9422 /* _null.h */; };\n\t\tF8C2EC9A24080557007A9422 /* timeout.h in Headers */ = {isa = PBXBuildFile; fileRef = F8C2EC9024080556007A9422 /* timeout.h */; };\n\t\tF8C2EC9C2408062D007A9422 /* pcireg.h in Headers */ = {isa = PBXBuildFile; fileRef = F8C2EC9B2408062D007A9422 /* pcireg.h */; };\n\t\tF8C594D325FD935B0007D19C /* ieee80211_ra.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C594D125FD935B0007D19C /* ieee80211_ra.c */; };\n\t\tF8C594D425FD935B0007D19C /* ieee80211_ra.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C594D125FD935B0007D19C /* ieee80211_ra.c */; };\n\t\tF8C594D525FD935B0007D19C /* ieee80211_ra.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C594D125FD935B0007D19C /* ieee80211_ra.c */; };\n\t\tF8C594D625FD935B0007D19C /* ieee80211_ra.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C594D125FD935B0007D19C /* ieee80211_ra.c */; };\n\t\tF8C594D725FD935B0007D19C /* ieee80211_ra.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C594D125FD935B0007D19C /* ieee80211_ra.c */; };\n\t\tF8C594D825FD935B0007D19C /* ieee80211_ra.h in Headers */ = {isa = PBXBuildFile; fileRef = F8C594D225FD935B0007D19C /* ieee80211_ra.h */; };\n\t\tF8C594D925FD935B0007D19C /* ieee80211_ra.h in Headers */ = {isa = PBXBuildFile; fileRef = F8C594D225FD935B0007D19C /* ieee80211_ra.h */; };\n\t\tF8C594DA25FD935B0007D19C /* ieee80211_ra.h in Headers */ = {isa = PBXBuildFile; fileRef = F8C594D225FD935B0007D19C /* ieee80211_ra.h */; };\n\t\tF8C594DB25FD935B0007D19C /* ieee80211_ra.h in Headers */ = {isa = PBXBuildFile; fileRef = F8C594D225FD935B0007D19C /* ieee80211_ra.h */; };\n\t\tF8C594DC25FD935B0007D19C /* ieee80211_ra.h in Headers */ = {isa = PBXBuildFile; fileRef = F8C594D225FD935B0007D19C /* ieee80211_ra.h */; };\n\t\tF8C772922443439A00A1B8A0 /* compat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A07BA23FCBC6C009FBA6C /* compat.cpp */; };\n\t\tF8CA44A325091AF60036119A /* AirportItlwmInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8CA44A125091AF60036119A /* AirportItlwmInterface.cpp */; };\n\t\tF8CA44A425091AF60036119A /* AirportItlwmInterface.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F8CA44A225091AF60036119A /* AirportItlwmInterface.hpp */; };\n\t\tF8D257742495A33500872E4F /* _mbuf.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8D257732495A33500872E4F /* _mbuf.cpp */; };\n\t\tF8D257782495DEFC00872E4F /* Common.h in Headers */ = {isa = PBXBuildFile; fileRef = F8D257762495DEFC00872E4F /* Common.h */; };\n\t\tF8D2577A2495DEFC00872E4F /* IoctlId.h in Headers */ = {isa = PBXBuildFile; fileRef = F8D257772495DEFC00872E4F /* IoctlId.h */; };\n\t\tF8D364F824F93AFD0029340B /* ItlHalService.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8D364F624F93AFD0029340B /* ItlHalService.cpp */; };\n\t\tF8D364FA24F93AFD0029340B /* ItlHalService.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F8D364F724F93AFD0029340B /* ItlHalService.hpp */; };\n\t\tF8D76362244F21BB00DEA040 /* pm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8D76361244F21BB00DEA040 /* pm.cpp */; };\n\t\tF8D94C842B9ABFE20081A3C4 /* CCDataPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8812A497DB200DC8DED /* CCDataPipe.h */; };\n\t\tF8D94C852B9ABFE20081A3C4 /* debug.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6C2225027609000F77FF /* debug.h */; };\n\t\tF8D94C862B9ABFE20081A3C4 /* IOSkywalkEthernetInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BD025021E66000F77FF /* IOSkywalkEthernetInterface.h */; };\n\t\tF8D94C872B9ABFE20081A3C4 /* IO80211InfraProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87C2A497DB200DC8DED /* IO80211InfraProtocol.h */; };\n\t\tF8D94C882B9ABFE20081A3C4 /* IOSkywalkLogicalLink.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87E2A497DB200DC8DED /* IOSkywalkLogicalLink.h */; };\n\t\tF8D94C892B9ABFE20081A3C4 /* AirportItlwmEthernetInterface.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F8A0282E2A4A7E0400C6DE90 /* AirportItlwmEthernetInterface.hpp */; };\n\t\tF8D94C8A2B9ABFE20081A3C4 /* IOSkywalkNetworkPacket.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87B2A497DB200DC8DED /* IOSkywalkNetworkPacket.h */; };\n\t\tF8D94C8B2B9ABFE20081A3C4 /* apple80211_ioctl.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BC525021DEC000F77FF /* apple80211_ioctl.h */; };\n\t\tF8D94C8C2B9ABFE20081A3C4 /* CCLogPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8852A497DB200DC8DED /* CCLogPipe.h */; };\n\t\tF8D94C8D2B9ABFE20081A3C4 /* IO80211P2PInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA36252D834500520FD4 /* IO80211P2PInterface.h */; };\n\t\tF8D94C8E2B9ABFE20081A3C4 /* CCPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87D2A497DB200DC8DED /* CCPipe.h */; };\n\t\tF8D94C8F2B9ABFE20081A3C4 /* IO80211WorkLoop.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA39252D834500520FD4 /* IO80211WorkLoop.h */; };\n\t\tF8D94C902B9ABFE20081A3C4 /* apple80211_var.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BC425021DEC000F77FF /* apple80211_var.h */; };\n\t\tF8D94C912B9ABFE20081A3C4 /* IOSkywalkPacketBufferPool.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8832A497DB200DC8DED /* IOSkywalkPacketBufferPool.h */; };\n\t\tF8D94C922B9ABFE20081A3C4 /* IOSkywalkLegacyEthernetInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8842A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h */; };\n\t\tF8D94C932B9ABFE20081A3C4 /* AirportItlwmInterface.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F8CA44A225091AF60036119A /* AirportItlwmInterface.hpp */; };\n\t\tF8D94C942B9ABFE20081A3C4 /* IO80211Interface.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA38252D834500520FD4 /* IO80211Interface.h */; };\n\t\tF8D94C952B9ABFE20081A3C4 /* IO80211WorkQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87A2A497DB200DC8DED /* IO80211WorkQueue.h */; };\n\t\tF8D94C962B9ABFE20081A3C4 /* (null) in Headers */ = {isa = PBXBuildFile; };\n\t\tF8D94C972B9ABFE20081A3C4 /* IO80211InfraInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87F2A497DB200DC8DED /* IO80211InfraInterface.h */; };\n\t\tF8D94C982B9ABFE20081A3C4 /* IO80211SkywalkInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA37252D834500520FD4 /* IO80211SkywalkInterface.h */; };\n\t\tF8D94C992B9ABFE20081A3C4 /* CCLogStream.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8822A497DB200DC8DED /* CCLogStream.h */; };\n\t\tF8D94C9A2B9ABFE20081A3C4 /* AirportItlwmSkywalkInterface.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F8A028712A4A7FE100C6DE90 /* AirportItlwmSkywalkInterface.hpp */; };\n\t\tF8D94C9B2B9ABFE20081A3C4 /* AirportItlwm.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BBB25021C9C000F77FF /* AirportItlwm.hpp */; };\n\t\tF8D94C9C2B9ABFE20081A3C4 /* IO80211ControllerV2.h in Headers */ = {isa = PBXBuildFile; fileRef = F89F35F12A49867F00061876 /* IO80211ControllerV2.h */; };\n\t\tF8D94C9D2B9ABFE20081A3C4 /* IOPCIEDeviceWrapper.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F8A0287E2A4A80EA00C6DE90 /* IOPCIEDeviceWrapper.hpp */; };\n\t\tF8D94C9E2B9ABFE20081A3C4 /* IO80211VirtualInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA34252D834500520FD4 /* IO80211VirtualInterface.h */; };\n\t\tF8D94C9F2B9ABFE20081A3C4 /* IO80211Controller.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA35252D834500520FD4 /* IO80211Controller.h */; };\n\t\tF8D94CA02B9ABFE20081A3C4 /* (null) in Headers */ = {isa = PBXBuildFile; };\n\t\tF8D94CA12B9ABFE20081A3C4 /* AirportItlwmV2.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F8A028212A4A7DDC00C6DE90 /* AirportItlwmV2.hpp */; };\n\t\tF8D94CA22B9ABFE20081A3C4 /* ieee80211_ra.h in Headers */ = {isa = PBXBuildFile; fileRef = F8C594D225FD935B0007D19C /* ieee80211_ra.h */; };\n\t\tF8D94CA32B9ABFE20081A3C4 /* CCStream.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8802A497DB200DC8DED /* CCStream.h */; };\n\t\tF8D94CA42B9ABFE20081A3C4 /* apple80211_wps.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BC325021DEC000F77FF /* apple80211_wps.h */; };\n\t\tF8D94CA62B9ABFE20081A3C4 /* rs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5DD111326D93B5F00BA01EF /* rs.cpp */; };\n\t\tF8D94CA72B9ABFE20081A3C4 /* _mbuf.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8D257732495A33500872E4F /* _mbuf.cpp */; };\n\t\tF8D94CA82B9ABFE20081A3C4 /* ieee80211_ra.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C594D125FD935B0007D19C /* ieee80211_ra.c */; };\n\t\tF8D94CA92B9ABFE20081A3C4 /* _task.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8F9EDE0240B7415009CB8E7 /* _task.cpp */; };\n\t\tF8D94CAA2B9ABFE20081A3C4 /* FwBinary.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5076FA7F24CC71E40011B2BB /* FwBinary.cpp */; };\n\t\tF8D94CAB2B9ABFE20081A3C4 /* ieee80211_proto.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC2F24080319007A9422 /* ieee80211_proto.c */; };\n\t\tF8D94CAC2B9ABFE20081A3C4 /* _string.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3024080319007A9422 /* _string.c */; };\n\t\tF8D94CAD2B9ABFE20081A3C4 /* ieee80211_ioctl.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3224080319007A9422 /* ieee80211_ioctl.c */; };\n\t\tF8D94CAE2B9ABFE20081A3C4 /* ieee80211.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3324080319007A9422 /* ieee80211.c */; };\n\t\tF8D94CAF2B9ABFE20081A3C4 /* ieee80211_rssadapt.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3424080319007A9422 /* ieee80211_rssadapt.c */; };\n\t\tF8D94CB02B9ABFE20081A3C4 /* ieee80211_input.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3524080319007A9422 /* ieee80211_input.c */; };\n\t\tF8D94CB12B9ABFE20081A3C4 /* timeout.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3724080319007A9422 /* timeout.c */; };\n\t\tF8D94CB22B9ABFE20081A3C4 /* ieee80211_mira.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3924080319007A9422 /* ieee80211_mira.c */; };\n\t\tF8D94CB32B9ABFE20081A3C4 /* ieee80211_crypto_bip.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3B24080319007A9422 /* ieee80211_crypto_bip.c */; };\n\t\tF8D94CB42B9ABFE20081A3C4 /* ieee80211_crypto_tkip.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3C24080319007A9422 /* ieee80211_crypto_tkip.c */; };\n\t\tF8D94CB52B9ABFE20081A3C4 /* ieee80211_crypto_ccmp.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3D24080319007A9422 /* ieee80211_crypto_ccmp.c */; };\n\t\tF8D94CB62B9ABFE20081A3C4 /* ieee80211_crypto_wep.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC462408031A007A9422 /* ieee80211_crypto_wep.c */; };\n\t\tF8D94CB72B9ABFE20081A3C4 /* ieee80211_pae_input.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3E24080319007A9422 /* ieee80211_pae_input.c */; };\n\t\tF8D94CB82B9ABFE20081A3C4 /* ieee80211_amrr.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC4024080319007A9422 /* ieee80211_amrr.c */; };\n\t\tF8D94CB92B9ABFE20081A3C4 /* ieee80211_output.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC472408031A007A9422 /* ieee80211_output.c */; };\n\t\tF8D94CBA2B9ABFE20081A3C4 /* ieee80211_crypto.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC482408031A007A9422 /* ieee80211_crypto.c */; };\n\t\tF8D94CBB2B9ABFE20081A3C4 /* CTimeout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC492408031A007A9422 /* CTimeout.cpp */; };\n\t\tF8D94CBC2B9ABFE20081A3C4 /* ieee80211_regdomain.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC4B2408031A007A9422 /* ieee80211_regdomain.c */; };\n\t\tF8D94CBD2B9ABFE20081A3C4 /* ieee80211_node.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC4C2408031A007A9422 /* ieee80211_node.c */; };\n\t\tF8D94CBE2B9ABFE20081A3C4 /* ieee80211_pae_output.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC4D2408031A007A9422 /* ieee80211_pae_output.c */; };\n\t\tF8D94CBF2B9ABFE20081A3C4 /* sha1-pbkdf2.c in Sources */ = {isa = PBXBuildFile; fileRef = F88D2B3B2414E64000BBE700 /* sha1-pbkdf2.c */; };\n\t\tF8D94CC02B9ABFE20081A3C4 /* aes.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07C923FCBC6C009FBA6C /* aes.c */; };\n\t\tF8D94CC12B9ABFE20081A3C4 /* hmac.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CA23FCBC6C009FBA6C /* hmac.c */; };\n\t\tF8D94CC22B9ABFE20081A3C4 /* sha2.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CB23FCBC6C009FBA6C /* sha2.c */; };\n\t\tF8D94CC32B9ABFE20081A3C4 /* rijndael.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CC23FCBC6C009FBA6C /* rijndael.c */; };\n\t\tF8D94CC42B9ABFE20081A3C4 /* ecb3_enc.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CD23FCBC6C009FBA6C /* ecb3_enc.c */; };\n\t\tF8D94CC52B9ABFE20081A3C4 /* set_key.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CE23FCBC6C009FBA6C /* set_key.c */; };\n\t\tF8D94CC62B9ABFE20081A3C4 /* cast.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CF23FCBC6C009FBA6C /* cast.c */; };\n\t\tF8D94CC72B9ABFE20081A3C4 /* michael.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07D123FCBC6C009FBA6C /* michael.c */; };\n\t\tF8D94CC82B9ABFE20081A3C4 /* arp.c in Sources */ = {isa = PBXBuildFile; fileRef = A5A0C5232A501E6800EF9328 /* arp.c */; };\n\t\tF8D94CC92B9ABFE20081A3C4 /* sha1.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07D823FCBC6C009FBA6C /* sha1.c */; };\n\t\tF8D94CCA2B9ABFE20081A3C4 /* cmac.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07DD23FCBC6C009FBA6C /* cmac.c */; };\n\t\tF8D94CCB2B9ABFE20081A3C4 /* ecb_enc.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07E423FCBC6C009FBA6C /* ecb_enc.c */; };\n\t\tF8D94CCC2B9ABFE20081A3C4 /* chachapoly.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07E923FCBC6C009FBA6C /* chachapoly.c */; };\n\t\tF8D94CCD2B9ABFE20081A3C4 /* AirportItlwmV2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8A028202A4A7DDC00C6DE90 /* AirportItlwmV2.cpp */; };\n\t\tF8D94CCE2B9ABFE20081A3C4 /* (null) in Sources */ = {isa = PBXBuildFile; };\n\t\tF8D94CCF2B9ABFE20081A3C4 /* md5.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07EA23FCBC6C009FBA6C /* md5.c */; };\n\t\tF8D94CD02B9ABFE20081A3C4 /* arc4.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07EB23FCBC6C009FBA6C /* arc4.c */; };\n\t\tF8D94CD12B9ABFE20081A3C4 /* AirportItlwmEthernetInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8A0282D2A4A7E0400C6DE90 /* AirportItlwmEthernetInterface.cpp */; };\n\t\tF8D94CD22B9ABFE20081A3C4 /* AirportItlwmSkywalkInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8A028702A4A7FE100C6DE90 /* AirportItlwmSkywalkInterface.cpp */; };\n\t\tF8D94CD32B9ABFE20081A3C4 /* blf.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07EC23FCBC6C009FBA6C /* blf.c */; };\n\t\tF8D94CD42B9ABFE20081A3C4 /* _ifq.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5FA2AE328A797B200847103 /* _ifq.cpp */; };\n\t\tF8D94CD52B9ABFE20081A3C4 /* poly1305.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07ED23FCBC6C009FBA6C /* poly1305.c */; };\n\t\tF8D94CD62B9ABFE20081A3C4 /* key_wrap.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07F023FCBC6C009FBA6C /* key_wrap.c */; };\n\t\tF8D94CD72B9ABFE20081A3C4 /* gmac.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07F223FCBC6C009FBA6C /* gmac.c */; };\n\t\tF8D94CD82B9ABFE20081A3C4 /* rmd160.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07F323FCBC6C009FBA6C /* rmd160.c */; };\n\t\tF8D94CD92B9ABFE20081A3C4 /* idgen.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07F423FCBC6C009FBA6C /* idgen.c */; };\n\t\tF8D94CDA2B9ABFE20081A3C4 /* compat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A07BA23FCBC6C009FBA6C /* compat.cpp */; };\n\t\tF8D94CDB2B9ABFE20081A3C4 /* zutil.c in Sources */ = {isa = PBXBuildFile; fileRef = F8FA0EED2501E8C100B1822E /* zutil.c */; };\n\t\tF8D94CDC2B9ABFE20081A3C4 /* ItlHalService.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8D364F624F93AFD0029340B /* ItlHalService.cpp */; };\n\t\tF8D94CDD2B9ABFE20081A3C4 /* ItlIwx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8D6CD642442E8F200D2A454 /* ItlIwx.cpp */; };\n\t\tF8D94CDE2B9ABFE20081A3C4 /* utils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08BF23FCD4E2009FBA6C /* utils.cpp */; };\n\t\tF8D94CDF2B9ABFE20081A3C4 /* fw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08BD23FCD314009FBA6C /* fw.cpp */; };\n\t\tF8D94CE02B9ABFE20081A3C4 /* io.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C123FCD999009FBA6C /* io.cpp */; };\n\t\tF8D94CE12B9ABFE20081A3C4 /* rx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C323FCDC14009FBA6C /* rx.cpp */; };\n\t\tF8D94CE22B9ABFE20081A3C4 /* coex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F837C91C2724577F00B2C499 /* coex.cpp */; };\n\t\tF8D94CE32B9ABFE20081A3C4 /* tx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C523FCDC3B009FBA6C /* tx.cpp */; };\n\t\tF8D94CE42B9ABFE20081A3C4 /* hw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C723FCE2ED009FBA6C /* hw.cpp */; };\n\t\tF8D94CE52B9ABFE20081A3C4 /* ItlIwn.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 17FD7F0E255E4AC800611406 /* ItlIwn.cpp */; };\n\t\tF8D94CE62B9ABFE20081A3C4 /* phy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C923FCE537009FBA6C /* phy.cpp */; };\n\t\tF8D94CE72B9ABFE20081A3C4 /* mac80211.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08CB23FCE5CA009FBA6C /* mac80211.cpp */; };\n\t\tF8D94CE82B9ABFE20081A3C4 /* nvm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08CD23FCE67F009FBA6C /* nvm.cpp */; };\n\t\tF8D94CE92B9ABFE20081A3C4 /* ctxt.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08CF23FCEE88009FBA6C /* ctxt.cpp */; };\n\t\tF8D94CEA2B9ABFE20081A3C4 /* led.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08D123FCF395009FBA6C /* led.cpp */; };\n\t\tF8D94CEB2B9ABFE20081A3C4 /* power.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08D323FCF3E6009FBA6C /* power.cpp */; };\n\t\tF8D94CEC2B9ABFE20081A3C4 /* scan.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08D523FCF4D7009FBA6C /* scan.cpp */; };\n\t\tF8D94CED2B9ABFE20081A3C4 /* IOPCIEDeviceWrapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8A0287D2A4A80EA00C6DE90 /* IOPCIEDeviceWrapper.cpp */; };\n\t\tF8D94CEE2B9ABFE20081A3C4 /* ItlIwm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8AF3A2F24F9F35B008911C1 /* ItlIwm.cpp */; };\n\t\tF8D94CF02B9ABFE20081A3C4 /* libkmod.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5088ECBC252884870068A63D /* libkmod.a */; };\n\t\tF8E49A14249B923500BE6868 /* ItlNetworkUserClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8E49A12249B923500BE6868 /* ItlNetworkUserClient.cpp */; };\n\t\tF8E49A15249B923500BE6868 /* ItlNetworkUserClient.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F8E49A13249B923500BE6868 /* ItlNetworkUserClient.hpp */; };\n\t\tF8ED134424FBB5B70068C831 /* ItlIwx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8D6CD642442E8F200D2A454 /* ItlIwx.cpp */; };\n\t\tF8F7EA3A252D834600520FD4 /* IO80211VirtualInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA34252D834500520FD4 /* IO80211VirtualInterface.h */; };\n\t\tF8F7EA3B252D834600520FD4 /* IO80211VirtualInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA34252D834500520FD4 /* IO80211VirtualInterface.h */; };\n\t\tF8F7EA3C252D834600520FD4 /* IO80211VirtualInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA34252D834500520FD4 /* IO80211VirtualInterface.h */; };\n\t\tF8F7EA3D252D834600520FD4 /* IO80211VirtualInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA34252D834500520FD4 /* IO80211VirtualInterface.h */; };\n\t\tF8F7EA3E252D834600520FD4 /* IO80211Controller.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA35252D834500520FD4 /* IO80211Controller.h */; };\n\t\tF8F7EA3F252D834600520FD4 /* IO80211Controller.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA35252D834500520FD4 /* IO80211Controller.h */; };\n\t\tF8F7EA40252D834600520FD4 /* IO80211Controller.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA35252D834500520FD4 /* IO80211Controller.h */; };\n\t\tF8F7EA41252D834600520FD4 /* IO80211Controller.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA35252D834500520FD4 /* IO80211Controller.h */; };\n\t\tF8F7EA42252D834600520FD4 /* IO80211P2PInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA36252D834500520FD4 /* IO80211P2PInterface.h */; };\n\t\tF8F7EA43252D834600520FD4 /* IO80211P2PInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA36252D834500520FD4 /* IO80211P2PInterface.h */; };\n\t\tF8F7EA44252D834600520FD4 /* IO80211P2PInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA36252D834500520FD4 /* IO80211P2PInterface.h */; };\n\t\tF8F7EA45252D834600520FD4 /* IO80211P2PInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA36252D834500520FD4 /* IO80211P2PInterface.h */; };\n\t\tF8F7EA46252D834600520FD4 /* IO80211SkywalkInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA37252D834500520FD4 /* IO80211SkywalkInterface.h */; };\n\t\tF8F7EA47252D834600520FD4 /* IO80211SkywalkInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA37252D834500520FD4 /* IO80211SkywalkInterface.h */; };\n\t\tF8F7EA48252D834600520FD4 /* IO80211SkywalkInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA37252D834500520FD4 /* IO80211SkywalkInterface.h */; };\n\t\tF8F7EA49252D834600520FD4 /* IO80211SkywalkInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA37252D834500520FD4 /* IO80211SkywalkInterface.h */; };\n\t\tF8F7EA4A252D834600520FD4 /* IO80211Interface.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA38252D834500520FD4 /* IO80211Interface.h */; };\n\t\tF8F7EA4B252D834600520FD4 /* IO80211Interface.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA38252D834500520FD4 /* IO80211Interface.h */; };\n\t\tF8F7EA4C252D834600520FD4 /* IO80211Interface.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA38252D834500520FD4 /* IO80211Interface.h */; };\n\t\tF8F7EA4D252D834600520FD4 /* IO80211Interface.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA38252D834500520FD4 /* IO80211Interface.h */; };\n\t\tF8F7EA4E252D834600520FD4 /* IO80211WorkLoop.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA39252D834500520FD4 /* IO80211WorkLoop.h */; };\n\t\tF8F7EA4F252D834600520FD4 /* IO80211WorkLoop.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA39252D834500520FD4 /* IO80211WorkLoop.h */; };\n\t\tF8F7EA50252D834600520FD4 /* IO80211WorkLoop.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA39252D834500520FD4 /* IO80211WorkLoop.h */; };\n\t\tF8F7EA51252D834600520FD4 /* IO80211WorkLoop.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA39252D834500520FD4 /* IO80211WorkLoop.h */; };\n\t\tF8F84F682ADE26F1002808DE /* rs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5DD111326D93B5F00BA01EF /* rs.cpp */; };\n\t\tF8F9257E240974EF0088B8D5 /* bitfield.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F92573240974EE0088B8D5 /* bitfield.h */; };\n\t\tF8F9257F240974EF0088B8D5 /* kernel.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F92574240974EE0088B8D5 /* kernel.h */; };\n\t\tF8F92583240974EF0088B8D5 /* random.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F92578240974EE0088B8D5 /* random.h */; };\n\t\tF8F92586240974EF0088B8D5 /* types.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F9257B240974EF0088B8D5 /* types.h */; };\n\t\tF8F9EDE1240B7415009CB8E7 /* _task.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8F9EDE0240B7415009CB8E7 /* _task.cpp */; };\n\t\tF8FA0EEC2501E7EE00B1822E /* zutil.h in Headers */ = {isa = PBXBuildFile; fileRef = F8FA0EEB2501E7EE00B1822E /* zutil.h */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXContainerItemProxy section */\n\t\t5066D63D252880A700EE6F38 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 024A07A323FCBC3C009FBA6C /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 5066D63825287F7900EE6F38;\n\t\t\tremoteInfo = fw_gen;\n\t\t};\n\t\t5066D63F252880AD00EE6F38 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 024A07A323FCBC3C009FBA6C /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 5066D63825287F7900EE6F38;\n\t\t\tremoteInfo = fw_gen;\n\t\t};\n\t\t5066D6412528814000EE6F38 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 024A07A323FCBC3C009FBA6C /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 5066D63825287F7900EE6F38;\n\t\t\tremoteInfo = fw_gen;\n\t\t};\n\t\t5066D6432528814400EE6F38 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 024A07A323FCBC3C009FBA6C /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 5066D63825287F7900EE6F38;\n\t\t\tremoteInfo = fw_gen;\n\t\t};\n\t\t5066D6452528814900EE6F38 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 024A07A323FCBC3C009FBA6C /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 5066D63825287F7900EE6F38;\n\t\t\tremoteInfo = fw_gen;\n\t\t};\n\t\tF897ECB8266EFF93005EE8F7 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 024A07A323FCBC3C009FBA6C /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 5066D63825287F7900EE6F38;\n\t\t\tremoteInfo = fw_gen;\n\t\t};\n\t\tF8AE64F7285471560085B4CF /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 024A07A323FCBC3C009FBA6C /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 5066D63825287F7900EE6F38;\n\t\t\tremoteInfo = fw_gen;\n\t\t};\n\t\tF8B210A92A2EC2680043ECBD /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 024A07A323FCBC3C009FBA6C /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 5066D63825287F7900EE6F38;\n\t\t\tremoteInfo = fw_gen;\n\t\t};\n\t\tF8D94C822B9ABFE20081A3C4 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 024A07A323FCBC3C009FBA6C /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 5066D63825287F7900EE6F38;\n\t\t\tremoteInfo = fw_gen;\n\t\t};\n/* End PBXContainerItemProxy section */\n\n/* Begin PBXFileReference section */\n\t\t024A07AC23FCBC3C009FBA6C /* itlwm.kext */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = itlwm.kext; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t024A07AF23FCBC3C009FBA6C /* itlwm.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = itlwm.hpp; sourceTree = \"<group>\"; };\n\t\t024A07B123FCBC3C009FBA6C /* itlwm.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = itlwm.cpp; sourceTree = \"<group>\"; };\n\t\t024A07B323FCBC3C009FBA6C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\t024A07BA23FCBC6C009FBA6C /* compat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = compat.cpp; sourceTree = \"<group>\"; };\n\t\t024A07C923FCBC6C009FBA6C /* aes.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aes.c; sourceTree = \"<group>\"; };\n\t\t024A07CA23FCBC6C009FBA6C /* hmac.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hmac.c; sourceTree = \"<group>\"; };\n\t\t024A07CB23FCBC6C009FBA6C /* sha2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sha2.c; sourceTree = \"<group>\"; };\n\t\t024A07CC23FCBC6C009FBA6C /* rijndael.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rijndael.c; sourceTree = \"<group>\"; };\n\t\t024A07CD23FCBC6C009FBA6C /* ecb3_enc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ecb3_enc.c; sourceTree = \"<group>\"; };\n\t\t024A07CE23FCBC6C009FBA6C /* set_key.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = set_key.c; sourceTree = \"<group>\"; };\n\t\t024A07CF23FCBC6C009FBA6C /* cast.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cast.c; sourceTree = \"<group>\"; };\n\t\t024A07D023FCBC6C009FBA6C /* des_locl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = des_locl.h; sourceTree = \"<group>\"; };\n\t\t024A07D123FCBC6C009FBA6C /* michael.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = michael.c; sourceTree = \"<group>\"; };\n\t\t024A07D223FCBC6C009FBA6C /* key_wrap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = key_wrap.h; sourceTree = \"<group>\"; };\n\t\t024A07D323FCBC6C009FBA6C /* poly1305.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = poly1305.h; sourceTree = \"<group>\"; };\n\t\t024A07D423FCBC6C009FBA6C /* md5.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = md5.h; sourceTree = \"<group>\"; };\n\t\t024A07D523FCBC6C009FBA6C /* blf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = blf.h; sourceTree = \"<group>\"; };\n\t\t024A07D623FCBC6C009FBA6C /* arc4.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = arc4.h; sourceTree = \"<group>\"; };\n\t\t024A07D723FCBC6C009FBA6C /* chachapoly.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = chachapoly.h; sourceTree = \"<group>\"; };\n\t\t024A07D823FCBC6C009FBA6C /* sha1.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sha1.c; sourceTree = \"<group>\"; };\n\t\t024A07D923FCBC6C009FBA6C /* sk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sk.h; sourceTree = \"<group>\"; };\n\t\t024A07DA23FCBC6C009FBA6C /* castsb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = castsb.h; sourceTree = \"<group>\"; };\n\t\t024A07DB23FCBC6C009FBA6C /* rmd160.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rmd160.h; sourceTree = \"<group>\"; };\n\t\t024A07DC23FCBC6C009FBA6C /* idgen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = idgen.h; sourceTree = \"<group>\"; };\n\t\t024A07DD23FCBC6C009FBA6C /* cmac.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cmac.c; sourceTree = \"<group>\"; };\n\t\t024A07DE23FCBC6C009FBA6C /* gmac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gmac.h; sourceTree = \"<group>\"; };\n\t\t024A07DF23FCBC6C009FBA6C /* sha2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sha2.h; sourceTree = \"<group>\"; };\n\t\t024A07E023FCBC6C009FBA6C /* hmac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hmac.h; sourceTree = \"<group>\"; };\n\t\t024A07E123FCBC6C009FBA6C /* aes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aes.h; sourceTree = \"<group>\"; };\n\t\t024A07E223FCBC6C009FBA6C /* cast.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cast.h; sourceTree = \"<group>\"; };\n\t\t024A07E323FCBC6C009FBA6C /* michael.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = michael.h; sourceTree = \"<group>\"; };\n\t\t024A07E423FCBC6C009FBA6C /* ecb_enc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ecb_enc.c; sourceTree = \"<group>\"; };\n\t\t024A07E523FCBC6C009FBA6C /* cryptodev.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cryptodev.h; sourceTree = \"<group>\"; };\n\t\t024A07E623FCBC6C009FBA6C /* rijndael.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rijndael.h; sourceTree = \"<group>\"; };\n\t\t024A07E723FCBC6C009FBA6C /* chacha_private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = chacha_private.h; sourceTree = \"<group>\"; };\n\t\t024A07E823FCBC6C009FBA6C /* sha1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sha1.h; sourceTree = \"<group>\"; };\n\t\t024A07E923FCBC6C009FBA6C /* chachapoly.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = chachapoly.c; sourceTree = \"<group>\"; };\n\t\t024A07EA23FCBC6C009FBA6C /* md5.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = md5.c; sourceTree = \"<group>\"; };\n\t\t024A07EB23FCBC6C009FBA6C /* arc4.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = arc4.c; sourceTree = \"<group>\"; };\n\t\t024A07EC23FCBC6C009FBA6C /* blf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blf.c; sourceTree = \"<group>\"; };\n\t\t024A07ED23FCBC6C009FBA6C /* poly1305.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = poly1305.c; sourceTree = \"<group>\"; };\n\t\t024A07EE23FCBC6C009FBA6C /* spr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = spr.h; sourceTree = \"<group>\"; };\n\t\t024A07EF23FCBC6C009FBA6C /* podd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = podd.h; sourceTree = \"<group>\"; };\n\t\t024A07F023FCBC6C009FBA6C /* key_wrap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = key_wrap.c; sourceTree = \"<group>\"; };\n\t\t024A07F123FCBC6C009FBA6C /* cmac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cmac.h; sourceTree = \"<group>\"; };\n\t\t024A07F223FCBC6C009FBA6C /* gmac.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gmac.c; sourceTree = \"<group>\"; };\n\t\t024A07F323FCBC6C009FBA6C /* rmd160.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rmd160.c; sourceTree = \"<group>\"; };\n\t\t024A07F423FCBC6C009FBA6C /* idgen.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = idgen.c; sourceTree = \"<group>\"; };\n\t\t024A082123FCBC6C009FBA6C /* compat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = compat.h; sourceTree = \"<group>\"; };\n\t\t024A088923FCBE38009FBA6C /* if_iwmreg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = if_iwmreg.h; sourceTree = \"<group>\"; };\n\t\t024A088A23FCBE38009FBA6C /* if_iwmvar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = if_iwmvar.h; sourceTree = \"<group>\"; };\n\t\t024A08BC23FCD0A9009FBA6C /* itlhdr.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = itlhdr.h; sourceTree = \"<group>\"; };\n\t\t024A08BD23FCD314009FBA6C /* fw.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = fw.cpp; sourceTree = \"<group>\"; };\n\t\t024A08BF23FCD4E2009FBA6C /* utils.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = utils.cpp; sourceTree = \"<group>\"; };\n\t\t024A08C123FCD999009FBA6C /* io.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = io.cpp; sourceTree = \"<group>\"; };\n\t\t024A08C323FCDC14009FBA6C /* rx.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = rx.cpp; sourceTree = \"<group>\"; };\n\t\t024A08C523FCDC3B009FBA6C /* tx.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = tx.cpp; sourceTree = \"<group>\"; };\n\t\t024A08C723FCE2ED009FBA6C /* hw.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = hw.cpp; sourceTree = \"<group>\"; };\n\t\t024A08C923FCE537009FBA6C /* phy.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = phy.cpp; sourceTree = \"<group>\"; };\n\t\t024A08CB23FCE5CA009FBA6C /* mac80211.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = mac80211.cpp; sourceTree = \"<group>\"; };\n\t\t024A08CD23FCE67F009FBA6C /* nvm.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = nvm.cpp; sourceTree = \"<group>\"; };\n\t\t024A08CF23FCEE88009FBA6C /* ctxt.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ctxt.cpp; sourceTree = \"<group>\"; };\n\t\t024A08D123FCF395009FBA6C /* led.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = led.cpp; sourceTree = \"<group>\"; };\n\t\t024A08D323FCF3E6009FBA6C /* power.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = power.cpp; sourceTree = \"<group>\"; };\n\t\t024A08D523FCF4D7009FBA6C /* scan.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = scan.cpp; sourceTree = \"<group>\"; };\n\t\t17FD7F0C255E4A0900611406 /* if_iwnvar.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = if_iwnvar.h; sourceTree = \"<group>\"; };\n\t\t17FD7F0D255E4AB000611406 /* if_iwnreg.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = if_iwnreg.h; sourceTree = \"<group>\"; };\n\t\t17FD7F0E255E4AC800611406 /* ItlIwn.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ItlIwn.cpp; sourceTree = \"<group>\"; };\n\t\t17FD7F0F255E4AC800611406 /* ItlIwn.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ItlIwn.hpp; sourceTree = \"<group>\"; };\n\t\t17FD7F38255E4EB200611406 /* iwn-6005 */ = {isa = PBXFileReference; lastKnownFileType = text; path = \"iwn-6005\"; sourceTree = \"<group>\"; };\n\t\t17FD7F39255E4EB200611406 /* iwn-135 */ = {isa = PBXFileReference; lastKnownFileType = text; path = \"iwn-135\"; sourceTree = \"<group>\"; };\n\t\t17FD7F3A255E4EB200611406 /* iwn-6030 */ = {isa = PBXFileReference; lastKnownFileType = text; path = \"iwn-6030\"; sourceTree = \"<group>\"; };\n\t\t17FD7F3B255E4EB200611406 /* iwn-1000 */ = {isa = PBXFileReference; lastKnownFileType = text; path = \"iwn-1000\"; sourceTree = \"<group>\"; };\n\t\t17FD7F3C255E4EB200611406 /* iwn-5000 */ = {isa = PBXFileReference; lastKnownFileType = text; path = \"iwn-5000\"; sourceTree = \"<group>\"; };\n\t\t17FD7F3D255E4EB300611406 /* iwn-6000 */ = {isa = PBXFileReference; lastKnownFileType = text; path = \"iwn-6000\"; sourceTree = \"<group>\"; };\n\t\t17FD7F3E255E4EB300611406 /* iwn-105 */ = {isa = PBXFileReference; lastKnownFileType = text; path = \"iwn-105\"; sourceTree = \"<group>\"; };\n\t\t17FD7F3F255E4EB300611406 /* iwn-6050 */ = {isa = PBXFileReference; lastKnownFileType = text; path = \"iwn-6050\"; sourceTree = \"<group>\"; };\n\t\t17FD7F40255E4EB300611406 /* iwn-2030 */ = {isa = PBXFileReference; lastKnownFileType = text; path = \"iwn-2030\"; sourceTree = \"<group>\"; };\n\t\t17FD7F41255E4EB300611406 /* iwn-5150 */ = {isa = PBXFileReference; lastKnownFileType = text; path = \"iwn-5150\"; sourceTree = \"<group>\"; };\n\t\t17FD7F42255E4EB300611406 /* iwn-2000 */ = {isa = PBXFileReference; lastKnownFileType = text; path = \"iwn-2000\"; sourceTree = \"<group>\"; };\n\t\t17FD7F44255E4EB300611406 /* iwn-4965 */ = {isa = PBXFileReference; lastKnownFileType = text; path = \"iwn-4965\"; sourceTree = \"<group>\"; };\n\t\t35CBE6BA251CB89700435CBC /* AirportItlwm.kext */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AirportItlwm.kext; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t35CBE724251CB8BF00435CBC /* AirportItlwm.kext */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AirportItlwm.kext; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t35CBE78F251CB8CA00435CBC /* AirportItlwm.kext */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AirportItlwm.kext; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t5076FA7F24CC71E40011B2BB /* FwBinary.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FwBinary.cpp; sourceTree = \"<group>\"; };\n\t\t5088ECB8252883BF0068A63D /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = \"<group>\"; };\n\t\t5088ECB9252883C60068A63D /* LICENSE */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENSE; sourceTree = \"<group>\"; };\n\t\t5088ECBA252884060068A63D /* iwlwifi-firmware-license */ = {isa = PBXFileReference; lastKnownFileType = text; path = \"iwlwifi-firmware-license\"; sourceTree = \"<group>\"; };\n\t\t5088ECBC252884870068A63D /* libkmod.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libkmod.a; path = MacKernelSDK/Library/x86_64/libkmod.a; sourceTree = \"<group>\"; };\n\t\tA5213EBB27A0C3EC00D7EAB1 /* iwm-9000-46 */ = {isa = PBXFileReference; lastKnownFileType = file; path = \"iwm-9000-46\"; sourceTree = \"<group>\"; };\n\t\tA5213EBC27A0C3ED00D7EAB1 /* iwm-8000C-36 */ = {isa = PBXFileReference; lastKnownFileType = file; path = \"iwm-8000C-36\"; sourceTree = \"<group>\"; };\n\t\tA5213EBD27A0C3ED00D7EAB1 /* iwm-9260-46 */ = {isa = PBXFileReference; lastKnownFileType = file; path = \"iwm-9260-46\"; sourceTree = \"<group>\"; };\n\t\tA5213EBE27A0C3ED00D7EAB1 /* iwm-8265-36 */ = {isa = PBXFileReference; lastKnownFileType = file; path = \"iwm-8265-36\"; sourceTree = \"<group>\"; };\n\t\tA5A0C5222A501E2900EF9328 /* arp.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = arp.h; sourceTree = \"<group>\"; };\n\t\tA5A0C5232A501E6800EF9328 /* arp.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = arp.c; sourceTree = \"<group>\"; };\n\t\tA5DD111326D93B5F00BA01EF /* rs.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = rs.cpp; sourceTree = \"<group>\"; };\n\t\tA5DD111426D93B5F00BA01EF /* rs.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = rs.h; sourceTree = \"<group>\"; };\n\t\tA5FA2AE328A797B200847103 /* _ifq.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = _ifq.cpp; sourceTree = \"<group>\"; };\n\t\tF800DD9A24FBEBF000789320 /* ItlDriverController.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ItlDriverController.hpp; sourceTree = \"<group>\"; };\n\t\tF837C91C2724577F00B2C499 /* coex.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = coex.cpp; sourceTree = \"<group>\"; };\n\t\tF837C9252724732B00B2C499 /* iwlwifi-so-a0-gf-a0.pnvm */ = {isa = PBXFileReference; lastKnownFileType = file; path = \"iwlwifi-so-a0-gf-a0.pnvm\"; sourceTree = \"<group>\"; };\n\t\tF84AD87A2A497DB200DC8DED /* IO80211WorkQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IO80211WorkQueue.h; sourceTree = \"<group>\"; };\n\t\tF84AD87B2A497DB200DC8DED /* IOSkywalkNetworkPacket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IOSkywalkNetworkPacket.h; sourceTree = \"<group>\"; };\n\t\tF84AD87C2A497DB200DC8DED /* IO80211InfraProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IO80211InfraProtocol.h; sourceTree = \"<group>\"; };\n\t\tF84AD87D2A497DB200DC8DED /* CCPipe.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCPipe.h; sourceTree = \"<group>\"; };\n\t\tF84AD87E2A497DB200DC8DED /* IOSkywalkLogicalLink.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IOSkywalkLogicalLink.h; sourceTree = \"<group>\"; };\n\t\tF84AD87F2A497DB200DC8DED /* IO80211InfraInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IO80211InfraInterface.h; sourceTree = \"<group>\"; };\n\t\tF84AD8802A497DB200DC8DED /* CCStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCStream.h; sourceTree = \"<group>\"; };\n\t\tF84AD8812A497DB200DC8DED /* CCDataPipe.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCDataPipe.h; sourceTree = \"<group>\"; };\n\t\tF84AD8822A497DB200DC8DED /* CCLogStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCLogStream.h; sourceTree = \"<group>\"; };\n\t\tF84AD8832A497DB200DC8DED /* IOSkywalkPacketBufferPool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IOSkywalkPacketBufferPool.h; sourceTree = \"<group>\"; };\n\t\tF84AD8842A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IOSkywalkLegacyEthernetInterface.h; sourceTree = \"<group>\"; };\n\t\tF84AD8852A497DB200DC8DED /* CCLogPipe.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCLogPipe.h; sourceTree = \"<group>\"; };\n\t\tF883EC1F266F43F200EA018C /* AirportItlwm-Monterey-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = \"AirportItlwm-Monterey-Info.plist\"; sourceTree = \"<group>\"; };\n\t\tF88CB91324FBE9130060B1A5 /* ItlDriverInfo.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ItlDriverInfo.hpp; sourceTree = \"<group>\"; };\n\t\tF88D2B3B2414E64000BBE700 /* sha1-pbkdf2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sha1-pbkdf2.c\"; sourceTree = \"<group>\"; };\n\t\tF897ED18266EFF93005EE8F7 /* AirportItlwm.kext */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AirportItlwm.kext; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tF89B6B8325021A79000F77FF /* apple_private_spi.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = apple_private_spi.h; sourceTree = \"<group>\"; };\n\t\tF89B6B8525021AF1000F77FF /* Apple80211.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Apple80211.h; sourceTree = \"<group>\"; };\n\t\tF89B6BB925021C9C000F77FF /* AirportItlwm.kext */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AirportItlwm.kext; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tF89B6BBB25021C9C000F77FF /* AirportItlwm.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = AirportItlwm.hpp; sourceTree = \"<group>\"; };\n\t\tF89B6BBD25021C9C000F77FF /* AirportItlwm.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = AirportItlwm.cpp; sourceTree = \"<group>\"; };\n\t\tF89B6BBF25021C9C000F77FF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\tF89B6BC325021DEC000F77FF /* apple80211_wps.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = apple80211_wps.h; sourceTree = \"<group>\"; };\n\t\tF89B6BC425021DEC000F77FF /* apple80211_var.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = apple80211_var.h; sourceTree = \"<group>\"; };\n\t\tF89B6BC525021DEC000F77FF /* apple80211_ioctl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = apple80211_ioctl.h; sourceTree = \"<group>\"; };\n\t\tF89B6BD025021E66000F77FF /* IOSkywalkEthernetInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IOSkywalkEthernetInterface.h; sourceTree = \"<group>\"; };\n\t\tF89B6BDC25022F8C000F77FF /* AirportSTAIOCTL.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = AirportSTAIOCTL.cpp; sourceTree = \"<group>\"; };\n\t\tF89B6BDE25022FB5000F77FF /* AirportVirtualIOCTL.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = AirportVirtualIOCTL.cpp; sourceTree = \"<group>\"; };\n\t\tF89B6BE025022FC7000F77FF /* AirportAWDL.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = AirportAWDL.cpp; sourceTree = \"<group>\"; };\n\t\tF89B6C2225027609000F77FF /* debug.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = debug.h; sourceTree = \"<group>\"; };\n\t\tF89F35F12A49867F00061876 /* IO80211ControllerV2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IO80211ControllerV2.h; sourceTree = \"<group>\"; };\n\t\tF8A028202A4A7DDC00C6DE90 /* AirportItlwmV2.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = AirportItlwmV2.cpp; sourceTree = \"<group>\"; };\n\t\tF8A028212A4A7DDC00C6DE90 /* AirportItlwmV2.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = AirportItlwmV2.hpp; sourceTree = \"<group>\"; };\n\t\tF8A0282D2A4A7E0400C6DE90 /* AirportItlwmEthernetInterface.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = AirportItlwmEthernetInterface.cpp; sourceTree = \"<group>\"; };\n\t\tF8A0282E2A4A7E0400C6DE90 /* AirportItlwmEthernetInterface.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = AirportItlwmEthernetInterface.hpp; sourceTree = \"<group>\"; };\n\t\tF8A028702A4A7FE100C6DE90 /* AirportItlwmSkywalkInterface.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = AirportItlwmSkywalkInterface.cpp; sourceTree = \"<group>\"; };\n\t\tF8A028712A4A7FE100C6DE90 /* AirportItlwmSkywalkInterface.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = AirportItlwmSkywalkInterface.hpp; sourceTree = \"<group>\"; };\n\t\tF8A0287D2A4A80EA00C6DE90 /* IOPCIEDeviceWrapper.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = IOPCIEDeviceWrapper.cpp; sourceTree = \"<group>\"; };\n\t\tF8A0287E2A4A80EA00C6DE90 /* IOPCIEDeviceWrapper.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = IOPCIEDeviceWrapper.hpp; sourceTree = \"<group>\"; };\n\t\tF8A2A68B2A305B9E002ABDDB /* IOSkywalkNetworkInterface.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IOSkywalkNetworkInterface.h; sourceTree = \"<group>\"; };\n\t\tF8A2A68C2A305BAC002ABDDB /* IOSkywalkInterface.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IOSkywalkInterface.h; sourceTree = \"<group>\"; };\n\t\tF8A763892766B95F004606BE /* iwlwifi-so-a0-gf4-a0.pnvm */ = {isa = PBXFileReference; lastKnownFileType = file; path = \"iwlwifi-so-a0-gf4-a0.pnvm\"; sourceTree = \"<group>\"; };\n\t\tF8AE6558285471560085B4CF /* AirportItlwm.kext */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AirportItlwm.kext; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tF8AF3A2F24F9F35B008911C1 /* ItlIwm.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ItlIwm.cpp; sourceTree = \"<group>\"; };\n\t\tF8AF3A3024F9F35B008911C1 /* ItlIwm.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ItlIwm.hpp; sourceTree = \"<group>\"; };\n\t\tF8B2110A2A2EC2680043ECBD /* AirportItlwm.kext */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AirportItlwm.kext; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tF8B783AF240B9F87004C9777 /* _ifq.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = _ifq.h; sourceTree = \"<group>\"; };\n\t\tF8BB56172647FDF500F180EC /* _clock.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = _clock.h; sourceTree = \"<group>\"; };\n\t\tF8BEFA9124CA93E900F6D938 /* _malloc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = _malloc.h; sourceTree = \"<group>\"; };\n\t\tF8C2EC2F24080319007A9422 /* ieee80211_proto.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ieee80211_proto.c; sourceTree = \"<group>\"; };\n\t\tF8C2EC3024080319007A9422 /* _string.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = _string.c; sourceTree = \"<group>\"; };\n\t\tF8C2EC3124080319007A9422 /* ieee80211_amrr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ieee80211_amrr.h; sourceTree = \"<group>\"; };\n\t\tF8C2EC3224080319007A9422 /* ieee80211_ioctl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ieee80211_ioctl.c; sourceTree = \"<group>\"; };\n\t\tF8C2EC3324080319007A9422 /* ieee80211.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ieee80211.c; sourceTree = \"<group>\"; };\n\t\tF8C2EC3424080319007A9422 /* ieee80211_rssadapt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ieee80211_rssadapt.c; sourceTree = \"<group>\"; };\n\t\tF8C2EC3524080319007A9422 /* ieee80211_input.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ieee80211_input.c; sourceTree = \"<group>\"; };\n\t\tF8C2EC3624080319007A9422 /* ieee80211_node.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ieee80211_node.h; sourceTree = \"<group>\"; };\n\t\tF8C2EC3724080319007A9422 /* timeout.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = timeout.c; sourceTree = \"<group>\"; };\n\t\tF8C2EC3824080319007A9422 /* ieee80211_regdomain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ieee80211_regdomain.h; sourceTree = \"<group>\"; };\n\t\tF8C2EC3924080319007A9422 /* ieee80211_mira.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ieee80211_mira.c; sourceTree = \"<group>\"; };\n\t\tF8C2EC3A24080319007A9422 /* ieee80211_crypto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ieee80211_crypto.h; sourceTree = \"<group>\"; };\n\t\tF8C2EC3B24080319007A9422 /* ieee80211_crypto_bip.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ieee80211_crypto_bip.c; sourceTree = \"<group>\"; };\n\t\tF8C2EC3C24080319007A9422 /* ieee80211_crypto_tkip.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ieee80211_crypto_tkip.c; sourceTree = \"<group>\"; };\n\t\tF8C2EC3D24080319007A9422 /* ieee80211_crypto_ccmp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ieee80211_crypto_ccmp.c; sourceTree = \"<group>\"; };\n\t\tF8C2EC3E24080319007A9422 /* ieee80211_pae_input.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ieee80211_pae_input.c; sourceTree = \"<group>\"; };\n\t\tF8C2EC3F24080319007A9422 /* ieee80211_radiotap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ieee80211_radiotap.h; sourceTree = \"<group>\"; };\n\t\tF8C2EC4024080319007A9422 /* ieee80211_amrr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ieee80211_amrr.c; sourceTree = \"<group>\"; };\n\t\tF8C2EC4124080319007A9422 /* ieee80211_proto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ieee80211_proto.h; sourceTree = \"<group>\"; };\n\t\tF8C2EC422408031A007A9422 /* ieee80211_rssadapt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ieee80211_rssadapt.h; sourceTree = \"<group>\"; };\n\t\tF8C2EC432408031A007A9422 /* ieee80211.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ieee80211.h; sourceTree = \"<group>\"; };\n\t\tF8C2EC442408031A007A9422 /* ieee80211_priv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ieee80211_priv.h; sourceTree = \"<group>\"; };\n\t\tF8C2EC452408031A007A9422 /* ieee80211_ioctl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ieee80211_ioctl.h; sourceTree = \"<group>\"; };\n\t\tF8C2EC462408031A007A9422 /* ieee80211_crypto_wep.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ieee80211_crypto_wep.c; sourceTree = \"<group>\"; };\n\t\tF8C2EC472408031A007A9422 /* ieee80211_output.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ieee80211_output.c; sourceTree = \"<group>\"; };\n\t\tF8C2EC482408031A007A9422 /* ieee80211_crypto.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ieee80211_crypto.c; sourceTree = \"<group>\"; };\n\t\tF8C2EC492408031A007A9422 /* CTimeout.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CTimeout.cpp; sourceTree = \"<group>\"; };\n\t\tF8C2EC4A2408031A007A9422 /* ieee80211_mira.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ieee80211_mira.h; sourceTree = \"<group>\"; };\n\t\tF8C2EC4B2408031A007A9422 /* ieee80211_regdomain.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ieee80211_regdomain.c; sourceTree = \"<group>\"; };\n\t\tF8C2EC4C2408031A007A9422 /* ieee80211_node.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ieee80211_node.c; sourceTree = \"<group>\"; };\n\t\tF8C2EC4D2408031A007A9422 /* ieee80211_pae_output.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ieee80211_pae_output.c; sourceTree = \"<group>\"; };\n\t\tF8C2EC4E2408031A007A9422 /* ieee80211_var.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ieee80211_var.h; sourceTree = \"<group>\"; };\n\t\tF8C2EC8724080556007A9422 /* _buf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _buf.h; sourceTree = \"<group>\"; };\n\t\tF8C2EC8824080556007A9422 /* CTimeout.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CTimeout.hpp; sourceTree = \"<group>\"; };\n\t\tF8C2EC8924080556007A9422 /* _arc4random.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _arc4random.h; sourceTree = \"<group>\"; };\n\t\tF8C2EC8A24080556007A9422 /* endian.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = endian.h; sourceTree = \"<group>\"; };\n\t\tF8C2EC8B24080556007A9422 /* _mbuf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _mbuf.h; sourceTree = \"<group>\"; };\n\t\tF8C2EC8C24080556007A9422 /* _if_ether.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _if_ether.h; sourceTree = \"<group>\"; };\n\t\tF8C2EC8D24080556007A9422 /* tree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tree.h; sourceTree = \"<group>\"; };\n\t\tF8C2EC8E24080556007A9422 /* _if_media.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _if_media.h; sourceTree = \"<group>\"; };\n\t\tF8C2EC8F24080556007A9422 /* _null.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _null.h; sourceTree = \"<group>\"; };\n\t\tF8C2EC9024080556007A9422 /* timeout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = timeout.h; sourceTree = \"<group>\"; };\n\t\tF8C2EC9B2408062D007A9422 /* pcireg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pcireg.h; sourceTree = \"<group>\"; };\n\t\tF8C4BF822420FAEB007F410E /* iwm-3160-17 */ = {isa = PBXFileReference; lastKnownFileType = text; path = \"iwm-3160-17\"; sourceTree = \"<group>\"; };\n\t\tF8C4BF8A2420FAEC007F410E /* iwm-3168-29 */ = {isa = PBXFileReference; lastKnownFileType = text; path = \"iwm-3168-29\"; sourceTree = \"<group>\"; };\n\t\tF8C4BF8C2420FAED007F410E /* iwm-7265-17 */ = {isa = PBXFileReference; lastKnownFileType = text; path = \"iwm-7265-17\"; sourceTree = \"<group>\"; };\n\t\tF8C4BF8F2420FAED007F410E /* iwm-7260-17 */ = {isa = PBXFileReference; lastKnownFileType = text; path = \"iwm-7260-17\"; sourceTree = \"<group>\"; };\n\t\tF8C594D125FD935B0007D19C /* ieee80211_ra.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ieee80211_ra.c; sourceTree = \"<group>\"; };\n\t\tF8C594D225FD935B0007D19C /* ieee80211_ra.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ieee80211_ra.h; sourceTree = \"<group>\"; };\n\t\tF8C7EF7B263125DE00BA87B6 /* _netstat.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = _netstat.h; sourceTree = \"<group>\"; };\n\t\tF8CA44A125091AF60036119A /* AirportItlwmInterface.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = AirportItlwmInterface.cpp; sourceTree = \"<group>\"; };\n\t\tF8CA44A225091AF60036119A /* AirportItlwmInterface.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = AirportItlwmInterface.hpp; sourceTree = \"<group>\"; };\n\t\tF8D257732495A33500872E4F /* _mbuf.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = _mbuf.cpp; sourceTree = \"<group>\"; };\n\t\tF8D257762495DEFC00872E4F /* Common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Common.h; sourceTree = \"<group>\"; };\n\t\tF8D257772495DEFC00872E4F /* IoctlId.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IoctlId.h; sourceTree = \"<group>\"; };\n\t\tF8D364F624F93AFD0029340B /* ItlHalService.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ItlHalService.cpp; sourceTree = \"<group>\"; };\n\t\tF8D364F724F93AFD0029340B /* ItlHalService.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ItlHalService.hpp; sourceTree = \"<group>\"; };\n\t\tF8D6CD542442E0D100D2A454 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\tF8D6CD622442E8F200D2A454 /* ItlIwx.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ItlIwx.hpp; sourceTree = \"<group>\"; };\n\t\tF8D6CD642442E8F200D2A454 /* ItlIwx.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ItlIwx.cpp; sourceTree = \"<group>\"; };\n\t\tF8D6CD6C2442F20C00D2A454 /* if_iwxreg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = if_iwxreg.h; sourceTree = \"<group>\"; };\n\t\tF8D6CD6D2442F20C00D2A454 /* if_iwxvar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = if_iwxvar.h; sourceTree = \"<group>\"; };\n\t\tF8D76361244F21BB00DEA040 /* pm.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = pm.cpp; sourceTree = \"<group>\"; };\n\t\tF8D94CF52B9ABFE20081A3C4 /* AirportItlwm.kext */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AirportItlwm.kext; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tF8E3806526D533D400568FEB /* iwlwifi-ty-a0-gf-a0.pnvm */ = {isa = PBXFileReference; lastKnownFileType = file; path = \"iwlwifi-ty-a0-gf-a0.pnvm\"; sourceTree = \"<group>\"; };\n\t\tF8E49A12249B923500BE6868 /* ItlNetworkUserClient.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ItlNetworkUserClient.cpp; sourceTree = \"<group>\"; };\n\t\tF8E49A13249B923500BE6868 /* ItlNetworkUserClient.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ItlNetworkUserClient.hpp; sourceTree = \"<group>\"; };\n\t\tF8EE4D1A241786B0002FA666 /* FwData.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FwData.h; sourceTree = \"<group>\"; };\n\t\tF8F7EA34252D834500520FD4 /* IO80211VirtualInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IO80211VirtualInterface.h; sourceTree = \"<group>\"; };\n\t\tF8F7EA35252D834500520FD4 /* IO80211Controller.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IO80211Controller.h; sourceTree = \"<group>\"; };\n\t\tF8F7EA36252D834500520FD4 /* IO80211P2PInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IO80211P2PInterface.h; sourceTree = \"<group>\"; };\n\t\tF8F7EA37252D834500520FD4 /* IO80211SkywalkInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IO80211SkywalkInterface.h; sourceTree = \"<group>\"; };\n\t\tF8F7EA38252D834500520FD4 /* IO80211Interface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IO80211Interface.h; sourceTree = \"<group>\"; };\n\t\tF8F7EA39252D834500520FD4 /* IO80211WorkLoop.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IO80211WorkLoop.h; sourceTree = \"<group>\"; };\n\t\tF8F884F02791284800545F2C /* iwlwifi-cc-a0-68.ucode */ = {isa = PBXFileReference; lastKnownFileType = file; path = \"iwlwifi-cc-a0-68.ucode\"; sourceTree = \"<group>\"; };\n\t\tF8F884F12791285A00545F2C /* iwlwifi-Qu-b0-hr-b0-68.ucode */ = {isa = PBXFileReference; lastKnownFileType = file; path = \"iwlwifi-Qu-b0-hr-b0-68.ucode\"; sourceTree = \"<group>\"; };\n\t\tF8F884F22791286E00545F2C /* iwlwifi-Qu-b0-jf-b0-68.ucode */ = {isa = PBXFileReference; lastKnownFileType = file; path = \"iwlwifi-Qu-b0-jf-b0-68.ucode\"; sourceTree = \"<group>\"; };\n\t\tF8F884F32791289200545F2C /* iwlwifi-Qu-c0-hr-b0-68.ucode */ = {isa = PBXFileReference; lastKnownFileType = file; path = \"iwlwifi-Qu-c0-hr-b0-68.ucode\"; sourceTree = \"<group>\"; };\n\t\tF8F884F42791289C00545F2C /* iwlwifi-Qu-c0-jf-b0-68.ucode */ = {isa = PBXFileReference; lastKnownFileType = file; path = \"iwlwifi-Qu-c0-jf-b0-68.ucode\"; sourceTree = \"<group>\"; };\n\t\tF8F884F5279128B300545F2C /* iwlwifi-QuZ-a0-hr-b0-68.ucode */ = {isa = PBXFileReference; lastKnownFileType = file; path = \"iwlwifi-QuZ-a0-hr-b0-68.ucode\"; sourceTree = \"<group>\"; };\n\t\tF8F884F6279128C400545F2C /* iwlwifi-QuZ-a0-jf-b0-68.ucode */ = {isa = PBXFileReference; lastKnownFileType = file; path = \"iwlwifi-QuZ-a0-jf-b0-68.ucode\"; sourceTree = \"<group>\"; };\n\t\tF8F884F7279128DD00545F2C /* iwlwifi-so-a0-gf-a0-68.ucode */ = {isa = PBXFileReference; lastKnownFileType = file; path = \"iwlwifi-so-a0-gf-a0-68.ucode\"; sourceTree = \"<group>\"; };\n\t\tF8F884F92791293C00545F2C /* iwlwifi-so-a0-gf4-a0-68.ucode */ = {isa = PBXFileReference; lastKnownFileType = file; path = \"iwlwifi-so-a0-gf4-a0-68.ucode\"; sourceTree = \"<group>\"; };\n\t\tF8F884FA2791294B00545F2C /* iwlwifi-so-a0-hr-b0-68.ucode */ = {isa = PBXFileReference; lastKnownFileType = file; path = \"iwlwifi-so-a0-hr-b0-68.ucode\"; sourceTree = \"<group>\"; };\n\t\tF8F884FB2791295D00545F2C /* iwlwifi-so-a0-jf-b0-68.ucode */ = {isa = PBXFileReference; lastKnownFileType = file; path = \"iwlwifi-so-a0-jf-b0-68.ucode\"; sourceTree = \"<group>\"; };\n\t\tF8F884FC2791296C00545F2C /* iwlwifi-ty-a0-gf-a0-68.ucode */ = {isa = PBXFileReference; lastKnownFileType = file; path = \"iwlwifi-ty-a0-gf-a0-68.ucode\"; sourceTree = \"<group>\"; };\n\t\tF8F92573240974EE0088B8D5 /* bitfield.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bitfield.h; sourceTree = \"<group>\"; };\n\t\tF8F92574240974EE0088B8D5 /* kernel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = kernel.h; sourceTree = \"<group>\"; };\n\t\tF8F92578240974EE0088B8D5 /* random.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = random.h; sourceTree = \"<group>\"; };\n\t\tF8F9257B240974EF0088B8D5 /* types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = types.h; sourceTree = \"<group>\"; };\n\t\tF8F9EDDF240B4741009CB8E7 /* _task.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = _task.h; sourceTree = \"<group>\"; };\n\t\tF8F9EDE0240B7415009CB8E7 /* _task.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = _task.cpp; sourceTree = \"<group>\"; };\n\t\tF8FA0EEB2501E7EE00B1822E /* zutil.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = zutil.h; sourceTree = \"<group>\"; };\n\t\tF8FA0EED2501E8C100B1822E /* zutil.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = zutil.c; sourceTree = \"<group>\"; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\t024A07A923FCBC3C009FBA6C /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t5088ECBD252884870068A63D /* libkmod.a in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t35CBE6B5251CB89700435CBC /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t5088ECC1252884D70068A63D /* libkmod.a in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t35CBE71F251CB8BF00435CBC /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t5088ECBF252884AF0068A63D /* libkmod.a in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t35CBE78A251CB8CA00435CBC /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t5088ECBE252884A30068A63D /* libkmod.a in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tF897ED12266EFF93005EE8F7 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tF897ED13266EFF93005EE8F7 /* libkmod.a in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tF89B6BB625021C9C000F77FF /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t5088ECC0252884C10068A63D /* libkmod.a in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tF8AE6552285471560085B4CF /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tF8AE6553285471560085B4CF /* libkmod.a in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tF8B211042A2EC2680043ECBD /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tF8B211052A2EC2680043ECBD /* libkmod.a in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tF8D94CEF2B9ABFE20081A3C4 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tF8D94CF02B9ABFE20081A3C4 /* libkmod.a in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\t024A07A223FCBC3C009FBA6C = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t5088ECB8252883BF0068A63D /* README.md */,\n\t\t\t\t5088ECB9252883C60068A63D /* LICENSE */,\n\t\t\t\t5088ECBA252884060068A63D /* iwlwifi-firmware-license */,\n\t\t\t\tF8B8F1622493C28B0059FAA8 /* include */,\n\t\t\t\t024A07AE23FCBC3C009FBA6C /* itlwm */,\n\t\t\t\tF8D6CD4F2442E0D100D2A454 /* itl80211 */,\n\t\t\t\tF89B6BBA25021C9C000F77FF /* AirportItlwm */,\n\t\t\t\t024A07AD23FCBC3C009FBA6C /* Products */,\n\t\t\t\t5088ECBB252884870068A63D /* Frameworks */,\n\t\t\t);\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t024A07AD23FCBC3C009FBA6C /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t024A07AC23FCBC3C009FBA6C /* itlwm.kext */,\n\t\t\t\tF89B6BB925021C9C000F77FF /* AirportItlwm.kext */,\n\t\t\t\t35CBE6BA251CB89700435CBC /* AirportItlwm.kext */,\n\t\t\t\t35CBE724251CB8BF00435CBC /* AirportItlwm.kext */,\n\t\t\t\t35CBE78F251CB8CA00435CBC /* AirportItlwm.kext */,\n\t\t\t\tF897ED18266EFF93005EE8F7 /* AirportItlwm.kext */,\n\t\t\t\tF8AE6558285471560085B4CF /* AirportItlwm.kext */,\n\t\t\t\tF8B2110A2A2EC2680043ECBD /* AirportItlwm.kext */,\n\t\t\t\tF8D94CF52B9ABFE20081A3C4 /* AirportItlwm.kext */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t024A07AE23FCBC3C009FBA6C /* itlwm */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t0250B31C23FD768400FF8CEA /* firmware */,\n\t\t\t\t17FD7F0B255E496000611406 /* hal_iwn */,\n\t\t\t\tF8AF3A2E24F9F25E008911C1 /* hal_iwm */,\n\t\t\t\tF8AF3A2D24F9F246008911C1 /* hal_iwx */,\n\t\t\t\t024A07AF23FCBC3C009FBA6C /* itlwm.hpp */,\n\t\t\t\t024A07B123FCBC3C009FBA6C /* itlwm.cpp */,\n\t\t\t\t024A07B323FCBC3C009FBA6C /* Info.plist */,\n\t\t\t\tF8D76361244F21BB00DEA040 /* pm.cpp */,\n\t\t\t\tF8E49A12249B923500BE6868 /* ItlNetworkUserClient.cpp */,\n\t\t\t\tF8E49A13249B923500BE6868 /* ItlNetworkUserClient.hpp */,\n\t\t\t);\n\t\t\tpath = itlwm;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t024A07C723FCBC6C009FBA6C /* openbsd */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tF8C2EC8624080556007A9422 /* sys */,\n\t\t\t\tF8C2EC2E24080319007A9422 /* net80211 */,\n\t\t\t\t024A07C823FCBC6C009FBA6C /* crypto */,\n\t\t\t);\n\t\t\tpath = openbsd;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t024A07C823FCBC6C009FBA6C /* crypto */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tF88D2B3B2414E64000BBE700 /* sha1-pbkdf2.c */,\n\t\t\t\t024A07C923FCBC6C009FBA6C /* aes.c */,\n\t\t\t\t024A07CA23FCBC6C009FBA6C /* hmac.c */,\n\t\t\t\t024A07CB23FCBC6C009FBA6C /* sha2.c */,\n\t\t\t\t024A07CC23FCBC6C009FBA6C /* rijndael.c */,\n\t\t\t\t024A07CD23FCBC6C009FBA6C /* ecb3_enc.c */,\n\t\t\t\t024A07CE23FCBC6C009FBA6C /* set_key.c */,\n\t\t\t\t024A07CF23FCBC6C009FBA6C /* cast.c */,\n\t\t\t\t024A07D023FCBC6C009FBA6C /* des_locl.h */,\n\t\t\t\t024A07D123FCBC6C009FBA6C /* michael.c */,\n\t\t\t\t024A07D223FCBC6C009FBA6C /* key_wrap.h */,\n\t\t\t\t024A07D323FCBC6C009FBA6C /* poly1305.h */,\n\t\t\t\t024A07D423FCBC6C009FBA6C /* md5.h */,\n\t\t\t\t024A07D523FCBC6C009FBA6C /* blf.h */,\n\t\t\t\t024A07D623FCBC6C009FBA6C /* arc4.h */,\n\t\t\t\t024A07D723FCBC6C009FBA6C /* chachapoly.h */,\n\t\t\t\t024A07D823FCBC6C009FBA6C /* sha1.c */,\n\t\t\t\t024A07D923FCBC6C009FBA6C /* sk.h */,\n\t\t\t\t024A07DA23FCBC6C009FBA6C /* castsb.h */,\n\t\t\t\t024A07DB23FCBC6C009FBA6C /* rmd160.h */,\n\t\t\t\t024A07DC23FCBC6C009FBA6C /* idgen.h */,\n\t\t\t\t024A07DD23FCBC6C009FBA6C /* cmac.c */,\n\t\t\t\t024A07DE23FCBC6C009FBA6C /* gmac.h */,\n\t\t\t\t024A07DF23FCBC6C009FBA6C /* sha2.h */,\n\t\t\t\t024A07E023FCBC6C009FBA6C /* hmac.h */,\n\t\t\t\t024A07E123FCBC6C009FBA6C /* aes.h */,\n\t\t\t\t024A07E223FCBC6C009FBA6C /* cast.h */,\n\t\t\t\t024A07E323FCBC6C009FBA6C /* michael.h */,\n\t\t\t\t024A07E423FCBC6C009FBA6C /* ecb_enc.c */,\n\t\t\t\t024A07E523FCBC6C009FBA6C /* cryptodev.h */,\n\t\t\t\t024A07E623FCBC6C009FBA6C /* rijndael.h */,\n\t\t\t\t024A07E723FCBC6C009FBA6C /* chacha_private.h */,\n\t\t\t\t024A07E823FCBC6C009FBA6C /* sha1.h */,\n\t\t\t\t024A07E923FCBC6C009FBA6C /* chachapoly.c */,\n\t\t\t\t024A07EA23FCBC6C009FBA6C /* md5.c */,\n\t\t\t\t024A07EB23FCBC6C009FBA6C /* arc4.c */,\n\t\t\t\t024A07EC23FCBC6C009FBA6C /* blf.c */,\n\t\t\t\t024A07ED23FCBC6C009FBA6C /* poly1305.c */,\n\t\t\t\t024A07EE23FCBC6C009FBA6C /* spr.h */,\n\t\t\t\t024A07EF23FCBC6C009FBA6C /* podd.h */,\n\t\t\t\t024A07F023FCBC6C009FBA6C /* key_wrap.c */,\n\t\t\t\t024A07F123FCBC6C009FBA6C /* cmac.h */,\n\t\t\t\t024A07F223FCBC6C009FBA6C /* gmac.c */,\n\t\t\t\t024A07F323FCBC6C009FBA6C /* rmd160.c */,\n\t\t\t\t024A07F423FCBC6C009FBA6C /* idgen.c */,\n\t\t\t);\n\t\t\tpath = crypto;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t0250B31C23FD768400FF8CEA /* firmware */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tA5213EBC27A0C3ED00D7EAB1 /* iwm-8000C-36 */,\n\t\t\t\tA5213EBE27A0C3ED00D7EAB1 /* iwm-8265-36 */,\n\t\t\t\tA5213EBB27A0C3EC00D7EAB1 /* iwm-9000-46 */,\n\t\t\t\tA5213EBD27A0C3ED00D7EAB1 /* iwm-9260-46 */,\n\t\t\t\tF8C4BF822420FAEB007F410E /* iwm-3160-17 */,\n\t\t\t\tF8C4BF8A2420FAEC007F410E /* iwm-3168-29 */,\n\t\t\t\tF8C4BF8F2420FAED007F410E /* iwm-7260-17 */,\n\t\t\t\tF8C4BF8C2420FAED007F410E /* iwm-7265-17 */,\n\t\t\t\tF8F884F6279128C400545F2C /* iwlwifi-QuZ-a0-jf-b0-68.ucode */,\n\t\t\t\tF8F884F22791286E00545F2C /* iwlwifi-Qu-b0-jf-b0-68.ucode */,\n\t\t\t\tF8F884F32791289200545F2C /* iwlwifi-Qu-c0-hr-b0-68.ucode */,\n\t\t\t\tF8F884F42791289C00545F2C /* iwlwifi-Qu-c0-jf-b0-68.ucode */,\n\t\t\t\tF8F884F02791284800545F2C /* iwlwifi-cc-a0-68.ucode */,\n\t\t\t\tF8F884F12791285A00545F2C /* iwlwifi-Qu-b0-hr-b0-68.ucode */,\n\t\t\t\tF8F884F5279128B300545F2C /* iwlwifi-QuZ-a0-hr-b0-68.ucode */,\n\t\t\t\tF8F884FC2791296C00545F2C /* iwlwifi-ty-a0-gf-a0-68.ucode */,\n\t\t\t\tF8E3806526D533D400568FEB /* iwlwifi-ty-a0-gf-a0.pnvm */,\n\t\t\t\tF8F884F7279128DD00545F2C /* iwlwifi-so-a0-gf-a0-68.ucode */,\n\t\t\t\tF837C9252724732B00B2C499 /* iwlwifi-so-a0-gf-a0.pnvm */,\n\t\t\t\tF8F884FA2791294B00545F2C /* iwlwifi-so-a0-hr-b0-68.ucode */,\n\t\t\t\tF8F884FB2791295D00545F2C /* iwlwifi-so-a0-jf-b0-68.ucode */,\n\t\t\t\tF8F884F92791293C00545F2C /* iwlwifi-so-a0-gf4-a0-68.ucode */,\n\t\t\t\tF8A763892766B95F004606BE /* iwlwifi-so-a0-gf4-a0.pnvm */,\n\t\t\t\t17FD7F3E255E4EB300611406 /* iwn-105 */,\n\t\t\t\t17FD7F39255E4EB200611406 /* iwn-135 */,\n\t\t\t\t17FD7F3B255E4EB200611406 /* iwn-1000 */,\n\t\t\t\t17FD7F42255E4EB300611406 /* iwn-2000 */,\n\t\t\t\t17FD7F40255E4EB300611406 /* iwn-2030 */,\n\t\t\t\t17FD7F44255E4EB300611406 /* iwn-4965 */,\n\t\t\t\t17FD7F3C255E4EB200611406 /* iwn-5000 */,\n\t\t\t\t17FD7F41255E4EB300611406 /* iwn-5150 */,\n\t\t\t\t17FD7F3D255E4EB300611406 /* iwn-6000 */,\n\t\t\t\t17FD7F38255E4EB200611406 /* iwn-6005 */,\n\t\t\t\t17FD7F3A255E4EB200611406 /* iwn-6030 */,\n\t\t\t\t17FD7F3F255E4EB300611406 /* iwn-6050 */,\n\t\t\t);\n\t\t\tpath = firmware;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t17FD7F0B255E496000611406 /* hal_iwn */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t17FD7F0C255E4A0900611406 /* if_iwnvar.h */,\n\t\t\t\t17FD7F0D255E4AB000611406 /* if_iwnreg.h */,\n\t\t\t\t17FD7F0E255E4AC800611406 /* ItlIwn.cpp */,\n\t\t\t\t17FD7F0F255E4AC800611406 /* ItlIwn.hpp */,\n\t\t\t);\n\t\t\tpath = hal_iwn;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t5088ECBB252884870068A63D /* Frameworks */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t5088ECBC252884870068A63D /* libkmod.a */,\n\t\t\t);\n\t\t\tname = Frameworks;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tF8585CC32500EA6F00485C5A /* ClientKit */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tF8D257762495DEFC00872E4F /* Common.h */,\n\t\t\t\tF8D257772495DEFC00872E4F /* IoctlId.h */,\n\t\t\t);\n\t\t\tpath = ClientKit;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tF89B6B7D25021674000F77FF /* Airport */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tF84AD8812A497DB200DC8DED /* CCDataPipe.h */,\n\t\t\t\tF84AD8852A497DB200DC8DED /* CCLogPipe.h */,\n\t\t\t\tF84AD8822A497DB200DC8DED /* CCLogStream.h */,\n\t\t\t\tF84AD87D2A497DB200DC8DED /* CCPipe.h */,\n\t\t\t\tF84AD8802A497DB200DC8DED /* CCStream.h */,\n\t\t\t\tF84AD87F2A497DB200DC8DED /* IO80211InfraInterface.h */,\n\t\t\t\tF84AD87C2A497DB200DC8DED /* IO80211InfraProtocol.h */,\n\t\t\t\tF84AD87A2A497DB200DC8DED /* IO80211WorkQueue.h */,\n\t\t\t\tF84AD8842A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h */,\n\t\t\t\tF84AD87E2A497DB200DC8DED /* IOSkywalkLogicalLink.h */,\n\t\t\t\tF84AD87B2A497DB200DC8DED /* IOSkywalkNetworkPacket.h */,\n\t\t\t\tF84AD8832A497DB200DC8DED /* IOSkywalkPacketBufferPool.h */,\n\t\t\t\tF89B6B8325021A79000F77FF /* apple_private_spi.h */,\n\t\t\t\tF8F7EA35252D834500520FD4 /* IO80211Controller.h */,\n\t\t\t\tF89F35F12A49867F00061876 /* IO80211ControllerV2.h */,\n\t\t\t\tF8F7EA38252D834500520FD4 /* IO80211Interface.h */,\n\t\t\t\tF8F7EA36252D834500520FD4 /* IO80211P2PInterface.h */,\n\t\t\t\tF8F7EA37252D834500520FD4 /* IO80211SkywalkInterface.h */,\n\t\t\t\tF89B6BD025021E66000F77FF /* IOSkywalkEthernetInterface.h */,\n\t\t\t\tF8A2A68B2A305B9E002ABDDB /* IOSkywalkNetworkInterface.h */,\n\t\t\t\tF8A2A68C2A305BAC002ABDDB /* IOSkywalkInterface.h */,\n\t\t\t\tF8F7EA34252D834500520FD4 /* IO80211VirtualInterface.h */,\n\t\t\t\tF8F7EA39252D834500520FD4 /* IO80211WorkLoop.h */,\n\t\t\t\tF89B6BC525021DEC000F77FF /* apple80211_ioctl.h */,\n\t\t\t\tF89B6BC425021DEC000F77FF /* apple80211_var.h */,\n\t\t\t\tF89B6BC325021DEC000F77FF /* apple80211_wps.h */,\n\t\t\t\tF89B6B8525021AF1000F77FF /* Apple80211.h */,\n\t\t\t\tF89B6C2225027609000F77FF /* debug.h */,\n\t\t\t);\n\t\t\tpath = Airport;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tF89B6BBA25021C9C000F77FF /* AirportItlwm */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tF89B6BBB25021C9C000F77FF /* AirportItlwm.hpp */,\n\t\t\t\tF89B6BBD25021C9C000F77FF /* AirportItlwm.cpp */,\n\t\t\t\tF89B6BDC25022F8C000F77FF /* AirportSTAIOCTL.cpp */,\n\t\t\t\tF89B6BDE25022FB5000F77FF /* AirportVirtualIOCTL.cpp */,\n\t\t\t\tF89B6BE025022FC7000F77FF /* AirportAWDL.cpp */,\n\t\t\t\tF8CA44A125091AF60036119A /* AirportItlwmInterface.cpp */,\n\t\t\t\tF8CA44A225091AF60036119A /* AirportItlwmInterface.hpp */,\n\t\t\t\tF89B6BBF25021C9C000F77FF /* Info.plist */,\n\t\t\t\tF883EC1F266F43F200EA018C /* AirportItlwm-Monterey-Info.plist */,\n\t\t\t\tF8A028202A4A7DDC00C6DE90 /* AirportItlwmV2.cpp */,\n\t\t\t\tF8A028212A4A7DDC00C6DE90 /* AirportItlwmV2.hpp */,\n\t\t\t\tF8A0282D2A4A7E0400C6DE90 /* AirportItlwmEthernetInterface.cpp */,\n\t\t\t\tF8A0282E2A4A7E0400C6DE90 /* AirportItlwmEthernetInterface.hpp */,\n\t\t\t\tF8A028702A4A7FE100C6DE90 /* AirportItlwmSkywalkInterface.cpp */,\n\t\t\t\tF8A028712A4A7FE100C6DE90 /* AirportItlwmSkywalkInterface.hpp */,\n\t\t\t\tF8A0287D2A4A80EA00C6DE90 /* IOPCIEDeviceWrapper.cpp */,\n\t\t\t\tF8A0287E2A4A80EA00C6DE90 /* IOPCIEDeviceWrapper.hpp */,\n\t\t\t);\n\t\t\tpath = AirportItlwm;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tF8AF3A2D24F9F246008911C1 /* hal_iwx */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tF8D6CD6C2442F20C00D2A454 /* if_iwxreg.h */,\n\t\t\t\tF8D6CD6D2442F20C00D2A454 /* if_iwxvar.h */,\n\t\t\t\tF8D6CD622442E8F200D2A454 /* ItlIwx.hpp */,\n\t\t\t\tF8D6CD642442E8F200D2A454 /* ItlIwx.cpp */,\n\t\t\t);\n\t\t\tpath = hal_iwx;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tF8AF3A2E24F9F25E008911C1 /* hal_iwm */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t024A088923FCBE38009FBA6C /* if_iwmreg.h */,\n\t\t\t\t024A088A23FCBE38009FBA6C /* if_iwmvar.h */,\n\t\t\t\t024A08BC23FCD0A9009FBA6C /* itlhdr.h */,\n\t\t\t\t024A08BF23FCD4E2009FBA6C /* utils.cpp */,\n\t\t\t\t024A08BD23FCD314009FBA6C /* fw.cpp */,\n\t\t\t\t024A08C123FCD999009FBA6C /* io.cpp */,\n\t\t\t\t024A08C323FCDC14009FBA6C /* rx.cpp */,\n\t\t\t\t024A08C523FCDC3B009FBA6C /* tx.cpp */,\n\t\t\t\t024A08C723FCE2ED009FBA6C /* hw.cpp */,\n\t\t\t\t024A08C923FCE537009FBA6C /* phy.cpp */,\n\t\t\t\t024A08CB23FCE5CA009FBA6C /* mac80211.cpp */,\n\t\t\t\t024A08CD23FCE67F009FBA6C /* nvm.cpp */,\n\t\t\t\t024A08CF23FCEE88009FBA6C /* ctxt.cpp */,\n\t\t\t\t024A08D123FCF395009FBA6C /* led.cpp */,\n\t\t\t\t024A08D323FCF3E6009FBA6C /* power.cpp */,\n\t\t\t\t024A08D523FCF4D7009FBA6C /* scan.cpp */,\n\t\t\t\tF837C91C2724577F00B2C499 /* coex.cpp */,\n\t\t\t\tF8AF3A2F24F9F35B008911C1 /* ItlIwm.cpp */,\n\t\t\t\tF8AF3A3024F9F35B008911C1 /* ItlIwm.hpp */,\n\t\t\t\tA5DD111326D93B5F00BA01EF /* rs.cpp */,\n\t\t\t\tA5DD111426D93B5F00BA01EF /* rs.h */,\n\t\t\t);\n\t\t\tpath = hal_iwm;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tF8B8F1622493C28B0059FAA8 /* include */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tF89B6B7D25021674000F77FF /* Airport */,\n\t\t\t\tF8585CC32500EA6F00485C5A /* ClientKit */,\n\t\t\t\tF8D364FC24F93EE20029340B /* HAL */,\n\t\t\t\tF8EE4D1A241786B0002FA666 /* FwData.h */,\n\t\t\t\t5076FA7F24CC71E40011B2BB /* FwBinary.cpp */,\n\t\t\t);\n\t\t\tpath = include;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tF8C2EC2E24080319007A9422 /* net80211 */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tF8C2EC2F24080319007A9422 /* ieee80211_proto.c */,\n\t\t\t\tF8C2EC3024080319007A9422 /* _string.c */,\n\t\t\t\tF8C2EC3124080319007A9422 /* ieee80211_amrr.h */,\n\t\t\t\tF8C2EC3224080319007A9422 /* ieee80211_ioctl.c */,\n\t\t\t\tF8C2EC3324080319007A9422 /* ieee80211.c */,\n\t\t\t\tF8C2EC3424080319007A9422 /* ieee80211_rssadapt.c */,\n\t\t\t\tF8C2EC3524080319007A9422 /* ieee80211_input.c */,\n\t\t\t\tF8C2EC3624080319007A9422 /* ieee80211_node.h */,\n\t\t\t\tF8C2EC3724080319007A9422 /* timeout.c */,\n\t\t\t\tF8C2EC3824080319007A9422 /* ieee80211_regdomain.h */,\n\t\t\t\tF8C2EC3924080319007A9422 /* ieee80211_mira.c */,\n\t\t\t\tF8C2EC3A24080319007A9422 /* ieee80211_crypto.h */,\n\t\t\t\tF8C2EC3B24080319007A9422 /* ieee80211_crypto_bip.c */,\n\t\t\t\tF8C2EC3C24080319007A9422 /* ieee80211_crypto_tkip.c */,\n\t\t\t\tF8C2EC3D24080319007A9422 /* ieee80211_crypto_ccmp.c */,\n\t\t\t\tF8C2EC462408031A007A9422 /* ieee80211_crypto_wep.c */,\n\t\t\t\tF8C2EC3E24080319007A9422 /* ieee80211_pae_input.c */,\n\t\t\t\tF8C2EC3F24080319007A9422 /* ieee80211_radiotap.h */,\n\t\t\t\tF8C2EC4024080319007A9422 /* ieee80211_amrr.c */,\n\t\t\t\tF8C2EC4124080319007A9422 /* ieee80211_proto.h */,\n\t\t\t\tF8C2EC422408031A007A9422 /* ieee80211_rssadapt.h */,\n\t\t\t\tF8C2EC432408031A007A9422 /* ieee80211.h */,\n\t\t\t\tF8C2EC442408031A007A9422 /* ieee80211_priv.h */,\n\t\t\t\tF8C2EC452408031A007A9422 /* ieee80211_ioctl.h */,\n\t\t\t\tF8C2EC472408031A007A9422 /* ieee80211_output.c */,\n\t\t\t\tF8C2EC482408031A007A9422 /* ieee80211_crypto.c */,\n\t\t\t\tF8C2EC492408031A007A9422 /* CTimeout.cpp */,\n\t\t\t\tF8C2EC4A2408031A007A9422 /* ieee80211_mira.h */,\n\t\t\t\tF8C2EC4B2408031A007A9422 /* ieee80211_regdomain.c */,\n\t\t\t\tF8C2EC4C2408031A007A9422 /* ieee80211_node.c */,\n\t\t\t\tF8C2EC4D2408031A007A9422 /* ieee80211_pae_output.c */,\n\t\t\t\tF8C2EC4E2408031A007A9422 /* ieee80211_var.h */,\n\t\t\t\tF8C594D125FD935B0007D19C /* ieee80211_ra.c */,\n\t\t\t\tF8C594D225FD935B0007D19C /* ieee80211_ra.h */,\n\t\t\t);\n\t\t\tpath = net80211;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tF8C2EC8624080556007A9422 /* sys */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tF8C2EC9B2408062D007A9422 /* pcireg.h */,\n\t\t\t\tF8C2EC8724080556007A9422 /* _buf.h */,\n\t\t\t\tF8C2EC8824080556007A9422 /* CTimeout.hpp */,\n\t\t\t\tF8C2EC8924080556007A9422 /* _arc4random.h */,\n\t\t\t\tF8C2EC8A24080556007A9422 /* endian.h */,\n\t\t\t\tF8C2EC8B24080556007A9422 /* _mbuf.h */,\n\t\t\t\tF8D257732495A33500872E4F /* _mbuf.cpp */,\n\t\t\t\tF8C2EC8C24080556007A9422 /* _if_ether.h */,\n\t\t\t\tF8C2EC8D24080556007A9422 /* tree.h */,\n\t\t\t\tF8C2EC8E24080556007A9422 /* _if_media.h */,\n\t\t\t\tF8C2EC8F24080556007A9422 /* _null.h */,\n\t\t\t\tF8C2EC9024080556007A9422 /* timeout.h */,\n\t\t\t\tF8F9EDDF240B4741009CB8E7 /* _task.h */,\n\t\t\t\tF8F9EDE0240B7415009CB8E7 /* _task.cpp */,\n\t\t\t\tF8B783AF240B9F87004C9777 /* _ifq.h */,\n\t\t\t\tA5FA2AE328A797B200847103 /* _ifq.cpp */,\n\t\t\t\tF8BEFA9124CA93E900F6D938 /* _malloc.h */,\n\t\t\t\tF8C7EF7B263125DE00BA87B6 /* _netstat.h */,\n\t\t\t\tF8BB56172647FDF500F180EC /* _clock.h */,\n\t\t\t\tA5A0C5222A501E2900EF9328 /* arp.h */,\n\t\t\t\tA5A0C5232A501E6800EF9328 /* arp.c */,\n\t\t\t);\n\t\t\tpath = sys;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tF8D364FC24F93EE20029340B /* HAL */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tF8D364F624F93AFD0029340B /* ItlHalService.cpp */,\n\t\t\t\tF8D364F724F93AFD0029340B /* ItlHalService.hpp */,\n\t\t\t\tF88CB91324FBE9130060B1A5 /* ItlDriverInfo.hpp */,\n\t\t\t\tF800DD9A24FBEBF000789320 /* ItlDriverController.hpp */,\n\t\t\t);\n\t\t\tpath = HAL;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tF8D6CD4F2442E0D100D2A454 /* itl80211 */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tF8F9256D240972EE0088B8D5 /* linux */,\n\t\t\t\t024A07C723FCBC6C009FBA6C /* openbsd */,\n\t\t\t\t024A07BA23FCBC6C009FBA6C /* compat.cpp */,\n\t\t\t\t024A082123FCBC6C009FBA6C /* compat.h */,\n\t\t\t\tF8FA0EEB2501E7EE00B1822E /* zutil.h */,\n\t\t\t\tF8FA0EED2501E8C100B1822E /* zutil.c */,\n\t\t\t\tF8D6CD542442E0D100D2A454 /* Info.plist */,\n\t\t\t);\n\t\t\tpath = itl80211;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tF8F9256D240972EE0088B8D5 /* linux */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tF8F92573240974EE0088B8D5 /* bitfield.h */,\n\t\t\t\tF8F92574240974EE0088B8D5 /* kernel.h */,\n\t\t\t\tF8F92578240974EE0088B8D5 /* random.h */,\n\t\t\t\tF8F9257B240974EF0088B8D5 /* types.h */,\n\t\t\t);\n\t\t\tpath = linux;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXHeadersBuildPhase section */\n\t\t024A07A723FCBC3C009FBA6C /* Headers */ = {\n\t\t\tisa = PBXHeadersBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tF8F9257F240974EF0088B8D5 /* kernel.h in Headers */,\n\t\t\t\t024A084D23FCBC6C009FBA6C /* sha1.h in Headers */,\n\t\t\t\t024A084B23FCBC6C009FBA6C /* rijndael.h in Headers */,\n\t\t\t\t024A083923FCBC6C009FBA6C /* md5.h in Headers */,\n\t\t\t\t17FD7F11255E4AC800611406 /* ItlIwn.hpp in Headers */,\n\t\t\t\tF8C2EC5F2408031A007A9422 /* ieee80211_radiotap.h in Headers */,\n\t\t\t\t024A084023FCBC6C009FBA6C /* rmd160.h in Headers */,\n\t\t\t\t024A083823FCBC6C009FBA6C /* poly1305.h in Headers */,\n\t\t\t\tF8C2EC9424080557007A9422 /* endian.h in Headers */,\n\t\t\t\tF8C2EC6A2408031A007A9422 /* ieee80211_mira.h in Headers */,\n\t\t\t\t024A083F23FCBC6C009FBA6C /* castsb.h in Headers */,\n\t\t\t\tF8C2EC9824080557007A9422 /* _if_media.h in Headers */,\n\t\t\t\tF8D257782495DEFC00872E4F /* Common.h in Headers */,\n\t\t\t\tF8C2EC9124080557007A9422 /* _buf.h in Headers */,\n\t\t\t\t024A084123FCBC6C009FBA6C /* idgen.h in Headers */,\n\t\t\t\tF88CB91424FBE9130060B1A5 /* ItlDriverInfo.hpp in Headers */,\n\t\t\t\tF8F92586240974EF0088B8D5 /* types.h in Headers */,\n\t\t\t\t024A083523FCBC6C009FBA6C /* des_locl.h in Headers */,\n\t\t\t\t024A088B23FCBE38009FBA6C /* if_iwmreg.h in Headers */,\n\t\t\t\t17FD7F7F255E549500611406 /* if_iwnvar.h in Headers */,\n\t\t\t\t024A084A23FCBC6C009FBA6C /* cryptodev.h in Headers */,\n\t\t\t\tF8D364FA24F93AFD0029340B /* ItlHalService.hpp in Headers */,\n\t\t\t\t024A083E23FCBC6C009FBA6C /* sk.h in Headers */,\n\t\t\t\tF8AF3A3224F9F35B008911C1 /* ItlIwm.hpp in Headers */,\n\t\t\t\t024A084323FCBC6C009FBA6C /* gmac.h in Headers */,\n\t\t\t\tF8C2EC9C2408062D007A9422 /* pcireg.h in Headers */,\n\t\t\t\tF8C2EC9624080557007A9422 /* _if_ether.h in Headers */,\n\t\t\t\tF8C2EC6E2408031A007A9422 /* ieee80211_var.h in Headers */,\n\t\t\t\tF8C2EC9924080557007A9422 /* _null.h in Headers */,\n\t\t\t\tF8C2EC9A24080557007A9422 /* timeout.h in Headers */,\n\t\t\t\t024A084523FCBC6C009FBA6C /* hmac.h in Headers */,\n\t\t\t\tF8C2EC9724080557007A9422 /* tree.h in Headers */,\n\t\t\t\tF8C2EC512408031A007A9422 /* ieee80211_amrr.h in Headers */,\n\t\t\t\t024A083723FCBC6C009FBA6C /* key_wrap.h in Headers */,\n\t\t\t\tF8C594D825FD935B0007D19C /* ieee80211_ra.h in Headers */,\n\t\t\t\tF8F92583240974EF0088B8D5 /* random.h in Headers */,\n\t\t\t\tF800DD9B24FBEBF000789320 /* ItlDriverController.hpp in Headers */,\n\t\t\t\tF8C2EC9324080557007A9422 /* _arc4random.h in Headers */,\n\t\t\t\t024A084823FCBC6C009FBA6C /* michael.h in Headers */,\n\t\t\t\t024A085423FCBC6C009FBA6C /* podd.h in Headers */,\n\t\t\t\tF8C2EC562408031A007A9422 /* ieee80211_node.h in Headers */,\n\t\t\t\tF8C2EC9524080557007A9422 /* _mbuf.h in Headers */,\n\t\t\t\tA5DD111B26D93B5F00BA01EF /* rs.h in Headers */,\n\t\t\t\t024A084423FCBC6C009FBA6C /* sha2.h in Headers */,\n\t\t\t\t024A088C23FCBE38009FBA6C /* if_iwmvar.h in Headers */,\n\t\t\t\t024A083A23FCBC6C009FBA6C /* blf.h in Headers */,\n\t\t\t\tF8C2EC9224080557007A9422 /* CTimeout.hpp in Headers */,\n\t\t\t\tF8C2EC612408031A007A9422 /* ieee80211_proto.h in Headers */,\n\t\t\t\t024A084723FCBC6C009FBA6C /* cast.h in Headers */,\n\t\t\t\tF8C2EC622408031A007A9422 /* ieee80211_rssadapt.h in Headers */,\n\t\t\t\tF8D2577A2495DEFC00872E4F /* IoctlId.h in Headers */,\n\t\t\t\tF8C2EC652408031A007A9422 /* ieee80211_ioctl.h in Headers */,\n\t\t\t\t024A083C23FCBC6C009FBA6C /* chachapoly.h in Headers */,\n\t\t\t\t024A084C23FCBC6C009FBA6C /* chacha_private.h in Headers */,\n\t\t\t\t024A083B23FCBC6C009FBA6C /* arc4.h in Headers */,\n\t\t\t\t024A084623FCBC6C009FBA6C /* aes.h in Headers */,\n\t\t\t\tF8E49A15249B923500BE6868 /* ItlNetworkUserClient.hpp in Headers */,\n\t\t\t\tF8C2EC632408031A007A9422 /* ieee80211.h in Headers */,\n\t\t\t\t024A085623FCBC6C009FBA6C /* cmac.h in Headers */,\n\t\t\t\tF8F9257E240974EF0088B8D5 /* bitfield.h in Headers */,\n\t\t\t\tF8FA0EEC2501E7EE00B1822E /* zutil.h in Headers */,\n\t\t\t\tF8C2EC642408031A007A9422 /* ieee80211_priv.h in Headers */,\n\t\t\t\t024A07B023FCBC3C009FBA6C /* itlwm.hpp in Headers */,\n\t\t\t\tF8C2EC5A2408031A007A9422 /* ieee80211_crypto.h in Headers */,\n\t\t\t\tF8C2EC582408031A007A9422 /* ieee80211_regdomain.h in Headers */,\n\t\t\t\t024A085323FCBC6C009FBA6C /* spr.h in Headers */,\n\t\t\t\t17FD7F86255E549900611406 /* if_iwnreg.h in Headers */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t35CBE658251CB89700435CBC /* Headers */ = {\n\t\t\tisa = PBXHeadersBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t35CBE659251CB89700435CBC /* debug.h in Headers */,\n\t\t\t\t35CBE65A251CB89700435CBC /* IOSkywalkEthernetInterface.h in Headers */,\n\t\t\t\tF84AD8A52A497DB200DC8DED /* IOSkywalkLogicalLink.h in Headers */,\n\t\t\t\tF84AD8892A497DB200DC8DED /* IO80211WorkQueue.h in Headers */,\n\t\t\t\t35CBE65B251CB89700435CBC /* apple80211_ioctl.h in Headers */,\n\t\t\t\tF84AD8B32A497DB200DC8DED /* CCStream.h in Headers */,\n\t\t\t\tF8F7EA45252D834600520FD4 /* IO80211P2PInterface.h in Headers */,\n\t\t\t\tF8F7EA51252D834600520FD4 /* IO80211WorkLoop.h in Headers */,\n\t\t\t\tF84AD8BA2A497DB200DC8DED /* CCDataPipe.h in Headers */,\n\t\t\t\tF84AD8C12A497DB200DC8DED /* CCLogStream.h in Headers */,\n\t\t\t\tF89F35F52A49867F00061876 /* IO80211ControllerV2.h in Headers */,\n\t\t\t\t35CBE661251CB89700435CBC /* apple80211_var.h in Headers */,\n\t\t\t\t35CBE664251CB89700435CBC /* AirportItlwmInterface.hpp in Headers */,\n\t\t\t\tF84AD8CF2A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h in Headers */,\n\t\t\t\tF8F7EA4D252D834600520FD4 /* IO80211Interface.h in Headers */,\n\t\t\t\tF84AD8AC2A497DB200DC8DED /* IO80211InfraInterface.h in Headers */,\n\t\t\t\tF8F7EA49252D834600520FD4 /* IO80211SkywalkInterface.h in Headers */,\n\t\t\t\t35CBE666251CB89700435CBC /* AirportItlwm.hpp in Headers */,\n\t\t\t\tA5DD111F26D93B5F00BA01EF /* rs.h in Headers */,\n\t\t\t\tF8F7EA3D252D834600520FD4 /* IO80211VirtualInterface.h in Headers */,\n\t\t\t\tF84AD89E2A497DB200DC8DED /* CCPipe.h in Headers */,\n\t\t\t\tF84AD8D62A497DB200DC8DED /* CCLogPipe.h in Headers */,\n\t\t\t\tF8F7EA41252D834600520FD4 /* IO80211Controller.h in Headers */,\n\t\t\t\tF84AD8C82A497DB200DC8DED /* IOSkywalkPacketBufferPool.h in Headers */,\n\t\t\t\tF84AD8972A497DB200DC8DED /* IO80211InfraProtocol.h in Headers */,\n\t\t\t\tF8C594DC25FD935B0007D19C /* ieee80211_ra.h in Headers */,\n\t\t\t\tF84AD8902A497DB200DC8DED /* IOSkywalkNetworkPacket.h in Headers */,\n\t\t\t\t35CBE66F251CB89700435CBC /* apple80211_wps.h in Headers */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t35CBE6C2251CB8BF00435CBC /* Headers */ = {\n\t\t\tisa = PBXHeadersBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t35CBE6C3251CB8BF00435CBC /* debug.h in Headers */,\n\t\t\t\t35CBE6C4251CB8BF00435CBC /* IOSkywalkEthernetInterface.h in Headers */,\n\t\t\t\tF84AD8A32A497DB200DC8DED /* IOSkywalkLogicalLink.h in Headers */,\n\t\t\t\tF84AD8872A497DB200DC8DED /* IO80211WorkQueue.h in Headers */,\n\t\t\t\t35CBE6C5251CB8BF00435CBC /* apple80211_ioctl.h in Headers */,\n\t\t\t\tF84AD8B12A497DB200DC8DED /* CCStream.h in Headers */,\n\t\t\t\tF8F7EA43252D834600520FD4 /* IO80211P2PInterface.h in Headers */,\n\t\t\t\tF8F7EA4F252D834600520FD4 /* IO80211WorkLoop.h in Headers */,\n\t\t\t\tF84AD8B82A497DB200DC8DED /* CCDataPipe.h in Headers */,\n\t\t\t\tF84AD8BF2A497DB200DC8DED /* CCLogStream.h in Headers */,\n\t\t\t\tF89F35F32A49867F00061876 /* IO80211ControllerV2.h in Headers */,\n\t\t\t\t35CBE6CB251CB8BF00435CBC /* apple80211_var.h in Headers */,\n\t\t\t\t35CBE6CE251CB8BF00435CBC /* AirportItlwmInterface.hpp in Headers */,\n\t\t\t\tF84AD8CD2A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h in Headers */,\n\t\t\t\tF8F7EA4B252D834600520FD4 /* IO80211Interface.h in Headers */,\n\t\t\t\tF84AD8AA2A497DB200DC8DED /* IO80211InfraInterface.h in Headers */,\n\t\t\t\tF8F7EA47252D834600520FD4 /* IO80211SkywalkInterface.h in Headers */,\n\t\t\t\t35CBE6D0251CB8BF00435CBC /* AirportItlwm.hpp in Headers */,\n\t\t\t\tA5DD111D26D93B5F00BA01EF /* rs.h in Headers */,\n\t\t\t\tF8F7EA3B252D834600520FD4 /* IO80211VirtualInterface.h in Headers */,\n\t\t\t\tF84AD89C2A497DB200DC8DED /* CCPipe.h in Headers */,\n\t\t\t\tF84AD8D42A497DB200DC8DED /* CCLogPipe.h in Headers */,\n\t\t\t\tF8F7EA3F252D834600520FD4 /* IO80211Controller.h in Headers */,\n\t\t\t\tF84AD8C62A497DB200DC8DED /* IOSkywalkPacketBufferPool.h in Headers */,\n\t\t\t\tF84AD8952A497DB200DC8DED /* IO80211InfraProtocol.h in Headers */,\n\t\t\t\tF8C594DA25FD935B0007D19C /* ieee80211_ra.h in Headers */,\n\t\t\t\tF84AD88E2A497DB200DC8DED /* IOSkywalkNetworkPacket.h in Headers */,\n\t\t\t\t35CBE6D9251CB8BF00435CBC /* apple80211_wps.h in Headers */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t35CBE72D251CB8CA00435CBC /* Headers */ = {\n\t\t\tisa = PBXHeadersBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t35CBE72E251CB8CA00435CBC /* debug.h in Headers */,\n\t\t\t\t35CBE72F251CB8CA00435CBC /* IOSkywalkEthernetInterface.h in Headers */,\n\t\t\t\tF84AD8A22A497DB200DC8DED /* IOSkywalkLogicalLink.h in Headers */,\n\t\t\t\tF84AD8862A497DB200DC8DED /* IO80211WorkQueue.h in Headers */,\n\t\t\t\t35CBE730251CB8CA00435CBC /* apple80211_ioctl.h in Headers */,\n\t\t\t\tF84AD8B02A497DB200DC8DED /* CCStream.h in Headers */,\n\t\t\t\tF8F7EA42252D834600520FD4 /* IO80211P2PInterface.h in Headers */,\n\t\t\t\tF8F7EA4E252D834600520FD4 /* IO80211WorkLoop.h in Headers */,\n\t\t\t\tF84AD8B72A497DB200DC8DED /* CCDataPipe.h in Headers */,\n\t\t\t\tF84AD8BE2A497DB200DC8DED /* CCLogStream.h in Headers */,\n\t\t\t\tF89F35F22A49867F00061876 /* IO80211ControllerV2.h in Headers */,\n\t\t\t\t35CBE736251CB8CA00435CBC /* apple80211_var.h in Headers */,\n\t\t\t\t35CBE739251CB8CA00435CBC /* AirportItlwmInterface.hpp in Headers */,\n\t\t\t\tF84AD8CC2A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h in Headers */,\n\t\t\t\tF8F7EA4A252D834600520FD4 /* IO80211Interface.h in Headers */,\n\t\t\t\tF84AD8A92A497DB200DC8DED /* IO80211InfraInterface.h in Headers */,\n\t\t\t\tF8F7EA46252D834600520FD4 /* IO80211SkywalkInterface.h in Headers */,\n\t\t\t\t35CBE73B251CB8CA00435CBC /* AirportItlwm.hpp in Headers */,\n\t\t\t\tA5DD111C26D93B5F00BA01EF /* rs.h in Headers */,\n\t\t\t\tF8F7EA3A252D834600520FD4 /* IO80211VirtualInterface.h in Headers */,\n\t\t\t\tF84AD89B2A497DB200DC8DED /* CCPipe.h in Headers */,\n\t\t\t\tF84AD8D32A497DB200DC8DED /* CCLogPipe.h in Headers */,\n\t\t\t\tF8F7EA3E252D834600520FD4 /* IO80211Controller.h in Headers */,\n\t\t\t\tF84AD8C52A497DB200DC8DED /* IOSkywalkPacketBufferPool.h in Headers */,\n\t\t\t\tF84AD8942A497DB200DC8DED /* IO80211InfraProtocol.h in Headers */,\n\t\t\t\tF8C594D925FD935B0007D19C /* ieee80211_ra.h in Headers */,\n\t\t\t\tF84AD88D2A497DB200DC8DED /* IOSkywalkNetworkPacket.h in Headers */,\n\t\t\t\t35CBE744251CB8CA00435CBC /* apple80211_wps.h in Headers */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tF897ECB9266EFF93005EE8F7 /* Headers */ = {\n\t\t\tisa = PBXHeadersBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tF84AD8BB2A497DB200DC8DED /* CCDataPipe.h in Headers */,\n\t\t\t\tF897ECBA266EFF93005EE8F7 /* debug.h in Headers */,\n\t\t\t\tF897ECBB266EFF93005EE8F7 /* IOSkywalkEthernetInterface.h in Headers */,\n\t\t\t\tF84AD8982A497DB200DC8DED /* IO80211InfraProtocol.h in Headers */,\n\t\t\t\tF84AD8A62A497DB200DC8DED /* IOSkywalkLogicalLink.h in Headers */,\n\t\t\t\tF84AD8912A497DB200DC8DED /* IOSkywalkNetworkPacket.h in Headers */,\n\t\t\t\tF897ECBC266EFF93005EE8F7 /* apple80211_ioctl.h in Headers */,\n\t\t\t\tF84AD8D72A497DB200DC8DED /* CCLogPipe.h in Headers */,\n\t\t\t\tF897ECBD266EFF93005EE8F7 /* IO80211P2PInterface.h in Headers */,\n\t\t\t\tF84AD89F2A497DB200DC8DED /* CCPipe.h in Headers */,\n\t\t\t\tF897ECBE266EFF93005EE8F7 /* IO80211WorkLoop.h in Headers */,\n\t\t\t\tF897ECBF266EFF93005EE8F7 /* apple80211_var.h in Headers */,\n\t\t\t\tA5DD112026D93B5F00BA01EF /* rs.h in Headers */,\n\t\t\t\tF84AD8C92A497DB200DC8DED /* IOSkywalkPacketBufferPool.h in Headers */,\n\t\t\t\tF84AD8D02A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h in Headers */,\n\t\t\t\tF897ECC0266EFF93005EE8F7 /* AirportItlwmInterface.hpp in Headers */,\n\t\t\t\tF897ECC1266EFF93005EE8F7 /* IO80211Interface.h in Headers */,\n\t\t\t\tF84AD88A2A497DB200DC8DED /* IO80211WorkQueue.h in Headers */,\n\t\t\t\tF897ECC2266EFF93005EE8F7 /* (null) in Headers */,\n\t\t\t\tF84AD8AD2A497DB200DC8DED /* IO80211InfraInterface.h in Headers */,\n\t\t\t\tF897ECC3266EFF93005EE8F7 /* IO80211SkywalkInterface.h in Headers */,\n\t\t\t\tF84AD8C22A497DB200DC8DED /* CCLogStream.h in Headers */,\n\t\t\t\tF897ECC4266EFF93005EE8F7 /* AirportItlwm.hpp in Headers */,\n\t\t\t\tF89F35F62A49867F00061876 /* IO80211ControllerV2.h in Headers */,\n\t\t\t\tF897ECC5266EFF93005EE8F7 /* IO80211VirtualInterface.h in Headers */,\n\t\t\t\tF897ECC6266EFF93005EE8F7 /* IO80211Controller.h in Headers */,\n\t\t\t\tF897ECC7266EFF93005EE8F7 /* (null) in Headers */,\n\t\t\t\tF897ECC8266EFF93005EE8F7 /* ieee80211_ra.h in Headers */,\n\t\t\t\tF84AD8B42A497DB200DC8DED /* CCStream.h in Headers */,\n\t\t\t\tF897ECC9266EFF93005EE8F7 /* apple80211_wps.h in Headers */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tF89B6BB425021C9C000F77FF /* Headers */ = {\n\t\t\tisa = PBXHeadersBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tF89B6C2325027609000F77FF /* debug.h in Headers */,\n\t\t\t\tF89B6BD725021E66000F77FF /* IOSkywalkEthernetInterface.h in Headers */,\n\t\t\t\tF84AD8A42A497DB200DC8DED /* IOSkywalkLogicalLink.h in Headers */,\n\t\t\t\tF84AD8882A497DB200DC8DED /* IO80211WorkQueue.h in Headers */,\n\t\t\t\tF89B6BCB25021DED000F77FF /* apple80211_ioctl.h in Headers */,\n\t\t\t\tF84AD8B22A497DB200DC8DED /* CCStream.h in Headers */,\n\t\t\t\tF8F7EA44252D834600520FD4 /* IO80211P2PInterface.h in Headers */,\n\t\t\t\tF8F7EA50252D834600520FD4 /* IO80211WorkLoop.h in Headers */,\n\t\t\t\tF84AD8B92A497DB200DC8DED /* CCDataPipe.h in Headers */,\n\t\t\t\tF84AD8C02A497DB200DC8DED /* CCLogStream.h in Headers */,\n\t\t\t\tF89F35F42A49867F00061876 /* IO80211ControllerV2.h in Headers */,\n\t\t\t\tF89B6BC925021DED000F77FF /* apple80211_var.h in Headers */,\n\t\t\t\tF8CA44A425091AF60036119A /* AirportItlwmInterface.hpp in Headers */,\n\t\t\t\tF84AD8CE2A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h in Headers */,\n\t\t\t\tF8F7EA4C252D834600520FD4 /* IO80211Interface.h in Headers */,\n\t\t\t\tF84AD8AB2A497DB200DC8DED /* IO80211InfraInterface.h in Headers */,\n\t\t\t\tF8F7EA48252D834600520FD4 /* IO80211SkywalkInterface.h in Headers */,\n\t\t\t\tF89B6BBC25021C9C000F77FF /* AirportItlwm.hpp in Headers */,\n\t\t\t\tA5DD111E26D93B5F00BA01EF /* rs.h in Headers */,\n\t\t\t\tF8F7EA3C252D834600520FD4 /* IO80211VirtualInterface.h in Headers */,\n\t\t\t\tF84AD89D2A497DB200DC8DED /* CCPipe.h in Headers */,\n\t\t\t\tF84AD8D52A497DB200DC8DED /* CCLogPipe.h in Headers */,\n\t\t\t\tF8F7EA40252D834600520FD4 /* IO80211Controller.h in Headers */,\n\t\t\t\tF84AD8C72A497DB200DC8DED /* IOSkywalkPacketBufferPool.h in Headers */,\n\t\t\t\tF84AD8962A497DB200DC8DED /* IO80211InfraProtocol.h in Headers */,\n\t\t\t\tF8C594DB25FD935B0007D19C /* ieee80211_ra.h in Headers */,\n\t\t\t\tF84AD88F2A497DB200DC8DED /* IOSkywalkNetworkPacket.h in Headers */,\n\t\t\t\tF89B6BC725021DED000F77FF /* apple80211_wps.h in Headers */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tF8AE64F8285471560085B4CF /* Headers */ = {\n\t\t\tisa = PBXHeadersBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tF84AD8BC2A497DB200DC8DED /* CCDataPipe.h in Headers */,\n\t\t\t\tF8AE64F9285471560085B4CF /* debug.h in Headers */,\n\t\t\t\tF8AE64FA285471560085B4CF /* IOSkywalkEthernetInterface.h in Headers */,\n\t\t\t\tF84AD8992A497DB200DC8DED /* IO80211InfraProtocol.h in Headers */,\n\t\t\t\tF84AD8A72A497DB200DC8DED /* IOSkywalkLogicalLink.h in Headers */,\n\t\t\t\tF84AD8922A497DB200DC8DED /* IOSkywalkNetworkPacket.h in Headers */,\n\t\t\t\tF8AE64FB285471560085B4CF /* apple80211_ioctl.h in Headers */,\n\t\t\t\tF84AD8D82A497DB200DC8DED /* CCLogPipe.h in Headers */,\n\t\t\t\tF8AE64FC285471560085B4CF /* IO80211P2PInterface.h in Headers */,\n\t\t\t\tF84AD8A02A497DB200DC8DED /* CCPipe.h in Headers */,\n\t\t\t\tF8AE64FD285471560085B4CF /* IO80211WorkLoop.h in Headers */,\n\t\t\t\tF8AE64FE285471560085B4CF /* apple80211_var.h in Headers */,\n\t\t\t\tF84AD8CA2A497DB200DC8DED /* IOSkywalkPacketBufferPool.h in Headers */,\n\t\t\t\tF84AD8D12A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h in Headers */,\n\t\t\t\tF8AE64FF285471560085B4CF /* AirportItlwmInterface.hpp in Headers */,\n\t\t\t\tF8AE6500285471560085B4CF /* IO80211Interface.h in Headers */,\n\t\t\t\tF84AD88B2A497DB200DC8DED /* IO80211WorkQueue.h in Headers */,\n\t\t\t\tF8AE6501285471560085B4CF /* (null) in Headers */,\n\t\t\t\tF84AD8AE2A497DB200DC8DED /* IO80211InfraInterface.h in Headers */,\n\t\t\t\tF8AE6502285471560085B4CF /* IO80211SkywalkInterface.h in Headers */,\n\t\t\t\tF84AD8C32A497DB200DC8DED /* CCLogStream.h in Headers */,\n\t\t\t\tF8AE6503285471560085B4CF /* AirportItlwm.hpp in Headers */,\n\t\t\t\tF89F35F72A49867F00061876 /* IO80211ControllerV2.h in Headers */,\n\t\t\t\tF8AE6504285471560085B4CF /* IO80211VirtualInterface.h in Headers */,\n\t\t\t\tF8AE6505285471560085B4CF /* IO80211Controller.h in Headers */,\n\t\t\t\tF8AE6506285471560085B4CF /* (null) in Headers */,\n\t\t\t\tF8AE6507285471560085B4CF /* ieee80211_ra.h in Headers */,\n\t\t\t\tF84AD8B52A497DB200DC8DED /* CCStream.h in Headers */,\n\t\t\t\tF8AE6508285471560085B4CF /* apple80211_wps.h in Headers */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tF8B210AA2A2EC2680043ECBD /* Headers */ = {\n\t\t\tisa = PBXHeadersBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tF84AD8BD2A497DB200DC8DED /* CCDataPipe.h in Headers */,\n\t\t\t\tF8B210AB2A2EC2680043ECBD /* debug.h in Headers */,\n\t\t\t\tF8B210AC2A2EC2680043ECBD /* IOSkywalkEthernetInterface.h in Headers */,\n\t\t\t\tF84AD89A2A497DB200DC8DED /* IO80211InfraProtocol.h in Headers */,\n\t\t\t\tF84AD8A82A497DB200DC8DED /* IOSkywalkLogicalLink.h in Headers */,\n\t\t\t\tF8A028302A4A7E0500C6DE90 /* AirportItlwmEthernetInterface.hpp in Headers */,\n\t\t\t\tF84AD8932A497DB200DC8DED /* IOSkywalkNetworkPacket.h in Headers */,\n\t\t\t\tF8B210AD2A2EC2680043ECBD /* apple80211_ioctl.h in Headers */,\n\t\t\t\tF84AD8D92A497DB200DC8DED /* CCLogPipe.h in Headers */,\n\t\t\t\tF8B210AE2A2EC2680043ECBD /* IO80211P2PInterface.h in Headers */,\n\t\t\t\tF84AD8A12A497DB200DC8DED /* CCPipe.h in Headers */,\n\t\t\t\tF8B210AF2A2EC2680043ECBD /* IO80211WorkLoop.h in Headers */,\n\t\t\t\tF8B210B02A2EC2680043ECBD /* apple80211_var.h in Headers */,\n\t\t\t\tF84AD8CB2A497DB200DC8DED /* IOSkywalkPacketBufferPool.h in Headers */,\n\t\t\t\tF84AD8D22A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h in Headers */,\n\t\t\t\tF8B210B12A2EC2680043ECBD /* AirportItlwmInterface.hpp in Headers */,\n\t\t\t\tF8B210B22A2EC2680043ECBD /* IO80211Interface.h in Headers */,\n\t\t\t\tF84AD88C2A497DB200DC8DED /* IO80211WorkQueue.h in Headers */,\n\t\t\t\tF8B210B32A2EC2680043ECBD /* (null) in Headers */,\n\t\t\t\tF84AD8AF2A497DB200DC8DED /* IO80211InfraInterface.h in Headers */,\n\t\t\t\tF8B210B42A2EC2680043ECBD /* IO80211SkywalkInterface.h in Headers */,\n\t\t\t\tF84AD8C42A497DB200DC8DED /* CCLogStream.h in Headers */,\n\t\t\t\tF8A028732A4A7FE100C6DE90 /* AirportItlwmSkywalkInterface.hpp in Headers */,\n\t\t\t\tF8B210B52A2EC2680043ECBD /* AirportItlwm.hpp in Headers */,\n\t\t\t\tF89F35F82A49867F00061876 /* IO80211ControllerV2.h in Headers */,\n\t\t\t\tF8A028802A4A80EA00C6DE90 /* IOPCIEDeviceWrapper.hpp in Headers */,\n\t\t\t\tF8B210B62A2EC2680043ECBD /* IO80211VirtualInterface.h in Headers */,\n\t\t\t\tF8B210B72A2EC2680043ECBD /* IO80211Controller.h in Headers */,\n\t\t\t\tF8B210B82A2EC2680043ECBD /* (null) in Headers */,\n\t\t\t\tF8A028232A4A7DDC00C6DE90 /* AirportItlwmV2.hpp in Headers */,\n\t\t\t\tF8B210B92A2EC2680043ECBD /* ieee80211_ra.h in Headers */,\n\t\t\t\tF84AD8B62A497DB200DC8DED /* CCStream.h in Headers */,\n\t\t\t\tF8B210BA2A2EC2680043ECBD /* apple80211_wps.h in Headers */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tF8D94C832B9ABFE20081A3C4 /* Headers */ = {\n\t\t\tisa = PBXHeadersBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tF8D94C842B9ABFE20081A3C4 /* CCDataPipe.h in Headers */,\n\t\t\t\tF8D94C852B9ABFE20081A3C4 /* debug.h in Headers */,\n\t\t\t\tF8D94C862B9ABFE20081A3C4 /* IOSkywalkEthernetInterface.h in Headers */,\n\t\t\t\tF8D94C872B9ABFE20081A3C4 /* IO80211InfraProtocol.h in Headers */,\n\t\t\t\tF8D94C882B9ABFE20081A3C4 /* IOSkywalkLogicalLink.h in Headers */,\n\t\t\t\tF8D94C892B9ABFE20081A3C4 /* AirportItlwmEthernetInterface.hpp in Headers */,\n\t\t\t\tF8D94C8A2B9ABFE20081A3C4 /* IOSkywalkNetworkPacket.h in Headers */,\n\t\t\t\tF8D94C8B2B9ABFE20081A3C4 /* apple80211_ioctl.h in Headers */,\n\t\t\t\tF8D94C8C2B9ABFE20081A3C4 /* CCLogPipe.h in Headers */,\n\t\t\t\tF8D94C8D2B9ABFE20081A3C4 /* IO80211P2PInterface.h in Headers */,\n\t\t\t\tF8D94C8E2B9ABFE20081A3C4 /* CCPipe.h in Headers */,\n\t\t\t\tF8D94C8F2B9ABFE20081A3C4 /* IO80211WorkLoop.h in Headers */,\n\t\t\t\tF8D94C902B9ABFE20081A3C4 /* apple80211_var.h in Headers */,\n\t\t\t\tF8D94C912B9ABFE20081A3C4 /* IOSkywalkPacketBufferPool.h in Headers */,\n\t\t\t\tF8D94C922B9ABFE20081A3C4 /* IOSkywalkLegacyEthernetInterface.h in Headers */,\n\t\t\t\tF8D94C932B9ABFE20081A3C4 /* AirportItlwmInterface.hpp in Headers */,\n\t\t\t\tF8D94C942B9ABFE20081A3C4 /* IO80211Interface.h in Headers */,\n\t\t\t\tF8D94C952B9ABFE20081A3C4 /* IO80211WorkQueue.h in Headers */,\n\t\t\t\tF8D94C962B9ABFE20081A3C4 /* (null) in Headers */,\n\t\t\t\tF8D94C972B9ABFE20081A3C4 /* IO80211InfraInterface.h in Headers */,\n\t\t\t\tF8D94C982B9ABFE20081A3C4 /* IO80211SkywalkInterface.h in Headers */,\n\t\t\t\tF8D94C992B9ABFE20081A3C4 /* CCLogStream.h in Headers */,\n\t\t\t\tF8D94C9A2B9ABFE20081A3C4 /* AirportItlwmSkywalkInterface.hpp in Headers */,\n\t\t\t\tF8D94C9B2B9ABFE20081A3C4 /* AirportItlwm.hpp in Headers */,\n\t\t\t\tF8D94C9C2B9ABFE20081A3C4 /* IO80211ControllerV2.h in Headers */,\n\t\t\t\tF8D94C9D2B9ABFE20081A3C4 /* IOPCIEDeviceWrapper.hpp in Headers */,\n\t\t\t\tF8D94C9E2B9ABFE20081A3C4 /* IO80211VirtualInterface.h in Headers */,\n\t\t\t\tF8D94C9F2B9ABFE20081A3C4 /* IO80211Controller.h in Headers */,\n\t\t\t\tF8D94CA02B9ABFE20081A3C4 /* (null) in Headers */,\n\t\t\t\tF8D94CA12B9ABFE20081A3C4 /* AirportItlwmV2.hpp in Headers */,\n\t\t\t\tF8D94CA22B9ABFE20081A3C4 /* ieee80211_ra.h in Headers */,\n\t\t\t\tF8D94CA32B9ABFE20081A3C4 /* CCStream.h in Headers */,\n\t\t\t\tF8D94CA42B9ABFE20081A3C4 /* apple80211_wps.h in Headers */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXHeadersBuildPhase section */\n\n/* Begin PBXNativeTarget section */\n\t\t024A07AB23FCBC3C009FBA6C /* itlwm */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 024A07B623FCBC3C009FBA6C /* Build configuration list for PBXNativeTarget \"itlwm\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t024A07A723FCBC3C009FBA6C /* Headers */,\n\t\t\t\t024A07A823FCBC3C009FBA6C /* Sources */,\n\t\t\t\t024A07A923FCBC3C009FBA6C /* Frameworks */,\n\t\t\t\t024A07AA23FCBC3C009FBA6C /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\t5066D63E252880A700EE6F38 /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = itlwm;\n\t\t\tproductName = itlwm;\n\t\t\tproductReference = 024A07AC23FCBC3C009FBA6C /* itlwm.kext */;\n\t\t\tproductType = \"com.apple.product-type.kernel-extension\";\n\t\t};\n\t\t35CBE655251CB89700435CBC /* AirportItlwm-Big Sur */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 35CBE6B7251CB89700435CBC /* Build configuration list for PBXNativeTarget \"AirportItlwm-Big Sur\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t35CBE658251CB89700435CBC /* Headers */,\n\t\t\t\t35CBE670251CB89700435CBC /* Sources */,\n\t\t\t\t35CBE6B5251CB89700435CBC /* Frameworks */,\n\t\t\t\t35CBE6B6251CB89700435CBC /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\t5066D6462528814900EE6F38 /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = \"AirportItlwm-Big Sur\";\n\t\t\tproductName = AirportItlwm;\n\t\t\tproductReference = 35CBE6BA251CB89700435CBC /* AirportItlwm.kext */;\n\t\t\tproductType = \"com.apple.product-type.kernel-extension\";\n\t\t};\n\t\t35CBE6BF251CB8BF00435CBC /* AirportItlwm-Mojave */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 35CBE721251CB8BF00435CBC /* Build configuration list for PBXNativeTarget \"AirportItlwm-Mojave\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t35CBE6C2251CB8BF00435CBC /* Headers */,\n\t\t\t\t35CBE6DA251CB8BF00435CBC /* Sources */,\n\t\t\t\t35CBE71F251CB8BF00435CBC /* Frameworks */,\n\t\t\t\t35CBE720251CB8BF00435CBC /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\t5066D6422528814000EE6F38 /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = \"AirportItlwm-Mojave\";\n\t\t\tproductName = AirportItlwm;\n\t\t\tproductReference = 35CBE724251CB8BF00435CBC /* AirportItlwm.kext */;\n\t\t\tproductType = \"com.apple.product-type.kernel-extension\";\n\t\t};\n\t\t35CBE72A251CB8CA00435CBC /* AirportItlwm-High Sierra */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 35CBE78C251CB8CA00435CBC /* Build configuration list for PBXNativeTarget \"AirportItlwm-High Sierra\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t35CBE72D251CB8CA00435CBC /* Headers */,\n\t\t\t\t35CBE745251CB8CA00435CBC /* Sources */,\n\t\t\t\t35CBE78A251CB8CA00435CBC /* Frameworks */,\n\t\t\t\t35CBE78B251CB8CA00435CBC /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\t5066D640252880AD00EE6F38 /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = \"AirportItlwm-High Sierra\";\n\t\t\tproductName = AirportItlwm;\n\t\t\tproductReference = 35CBE78F251CB8CA00435CBC /* AirportItlwm.kext */;\n\t\t\tproductType = \"com.apple.product-type.kernel-extension\";\n\t\t};\n\t\tF897ECB6266EFF93005EE8F7 /* AirportItlwm-Monterey */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = F897ED15266EFF93005EE8F7 /* Build configuration list for PBXNativeTarget \"AirportItlwm-Monterey\" */;\n\t\t\tbuildPhases = (\n\t\t\t\tF897ECB9266EFF93005EE8F7 /* Headers */,\n\t\t\t\tF897ECCA266EFF93005EE8F7 /* Sources */,\n\t\t\t\tF897ED12266EFF93005EE8F7 /* Frameworks */,\n\t\t\t\tF897ED14266EFF93005EE8F7 /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\tF897ECB7266EFF93005EE8F7 /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = \"AirportItlwm-Monterey\";\n\t\t\tproductName = AirportItlwm;\n\t\t\tproductReference = F897ED18266EFF93005EE8F7 /* AirportItlwm.kext */;\n\t\t\tproductType = \"com.apple.product-type.kernel-extension\";\n\t\t};\n\t\tF89B6BB825021C9C000F77FF /* AirportItlwm-Catalina */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = F89B6BC025021C9C000F77FF /* Build configuration list for PBXNativeTarget \"AirportItlwm-Catalina\" */;\n\t\t\tbuildPhases = (\n\t\t\t\tF89B6BB425021C9C000F77FF /* Headers */,\n\t\t\t\tF89B6BB525021C9C000F77FF /* Sources */,\n\t\t\t\tF89B6BB625021C9C000F77FF /* Frameworks */,\n\t\t\t\tF89B6BB725021C9C000F77FF /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\t5066D6442528814400EE6F38 /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = \"AirportItlwm-Catalina\";\n\t\t\tproductName = AirportItlwm;\n\t\t\tproductReference = F89B6BB925021C9C000F77FF /* AirportItlwm.kext */;\n\t\t\tproductType = \"com.apple.product-type.kernel-extension\";\n\t\t};\n\t\tF8AE64F5285471560085B4CF /* AirportItlwm-Ventura */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = F8AE6555285471560085B4CF /* Build configuration list for PBXNativeTarget \"AirportItlwm-Ventura\" */;\n\t\t\tbuildPhases = (\n\t\t\t\tF8AE64F8285471560085B4CF /* Headers */,\n\t\t\t\tF8AE6509285471560085B4CF /* Sources */,\n\t\t\t\tF8AE6552285471560085B4CF /* Frameworks */,\n\t\t\t\tF8AE6554285471560085B4CF /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\tF8AE64F6285471560085B4CF /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = \"AirportItlwm-Ventura\";\n\t\t\tproductName = AirportItlwm;\n\t\t\tproductReference = F8AE6558285471560085B4CF /* AirportItlwm.kext */;\n\t\t\tproductType = \"com.apple.product-type.kernel-extension\";\n\t\t};\n\t\tF8B210A72A2EC2680043ECBD /* AirportItlwm-Sonoma14.0 */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = F8B211072A2EC2680043ECBD /* Build configuration list for PBXNativeTarget \"AirportItlwm-Sonoma14.0\" */;\n\t\t\tbuildPhases = (\n\t\t\t\tF8B210AA2A2EC2680043ECBD /* Headers */,\n\t\t\t\tF8B210BB2A2EC2680043ECBD /* Sources */,\n\t\t\t\tF8B211042A2EC2680043ECBD /* Frameworks */,\n\t\t\t\tF8B211062A2EC2680043ECBD /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\tF8B210A82A2EC2680043ECBD /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = \"AirportItlwm-Sonoma14.0\";\n\t\t\tproductName = AirportItlwm;\n\t\t\tproductReference = F8B2110A2A2EC2680043ECBD /* AirportItlwm.kext */;\n\t\t\tproductType = \"com.apple.product-type.kernel-extension\";\n\t\t};\n\t\tF8D94C802B9ABFE20081A3C4 /* AirportItlwm-Sonoma14.4 */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = F8D94CF22B9ABFE20081A3C4 /* Build configuration list for PBXNativeTarget \"AirportItlwm-Sonoma14.4\" */;\n\t\t\tbuildPhases = (\n\t\t\t\tF8D94C832B9ABFE20081A3C4 /* Headers */,\n\t\t\t\tF8D94CA52B9ABFE20081A3C4 /* Sources */,\n\t\t\t\tF8D94CEF2B9ABFE20081A3C4 /* Frameworks */,\n\t\t\t\tF8D94CF12B9ABFE20081A3C4 /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\tF8D94C812B9ABFE20081A3C4 /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = \"AirportItlwm-Sonoma14.4\";\n\t\t\tproductName = AirportItlwm;\n\t\t\tproductReference = F8D94CF52B9ABFE20081A3C4 /* AirportItlwm.kext */;\n\t\t\tproductType = \"com.apple.product-type.kernel-extension\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\t024A07A323FCBC3C009FBA6C /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tLastUpgradeCheck = 1110;\n\t\t\t\tORGANIZATIONNAME = \"钟先耀\";\n\t\t\t\tTargetAttributes = {\n\t\t\t\t\t024A07AB23FCBC3C009FBA6C = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 11.1;\n\t\t\t\t\t\tProvisioningStyle = Manual;\n\t\t\t\t\t};\n\t\t\t\t\t35CBE655251CB89700435CBC = {\n\t\t\t\t\t\tProvisioningStyle = Manual;\n\t\t\t\t\t};\n\t\t\t\t\t35CBE6BF251CB8BF00435CBC = {\n\t\t\t\t\t\tProvisioningStyle = Manual;\n\t\t\t\t\t};\n\t\t\t\t\t35CBE72A251CB8CA00435CBC = {\n\t\t\t\t\t\tProvisioningStyle = Manual;\n\t\t\t\t\t};\n\t\t\t\t\t5066D63825287F7900EE6F38 = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 12.0;\n\t\t\t\t\t\tProvisioningStyle = Manual;\n\t\t\t\t\t};\n\t\t\t\t\tF897ECB6266EFF93005EE8F7 = {\n\t\t\t\t\t\tProvisioningStyle = Manual;\n\t\t\t\t\t};\n\t\t\t\t\tF89B6BB825021C9C000F77FF = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 11.6;\n\t\t\t\t\t\tProvisioningStyle = Manual;\n\t\t\t\t\t};\n\t\t\t\t\tF8AE64F5285471560085B4CF = {\n\t\t\t\t\t\tProvisioningStyle = Manual;\n\t\t\t\t\t};\n\t\t\t\t\tF8B210A72A2EC2680043ECBD = {\n\t\t\t\t\t\tProvisioningStyle = Manual;\n\t\t\t\t\t};\n\t\t\t\t\tF8D94C802B9ABFE20081A3C4 = {\n\t\t\t\t\t\tProvisioningStyle = Manual;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tbuildConfigurationList = 024A07A623FCBC3C009FBA6C /* Build configuration list for PBXProject \"itlwm\" */;\n\t\t\tcompatibilityVersion = \"Xcode 8.0\";\n\t\t\tdevelopmentRegion = en;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t\tBase,\n\t\t\t);\n\t\t\tmainGroup = 024A07A223FCBC3C009FBA6C;\n\t\t\tproductRefGroup = 024A07AD23FCBC3C009FBA6C /* Products */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\t024A07AB23FCBC3C009FBA6C /* itlwm */,\n\t\t\t\t35CBE72A251CB8CA00435CBC /* AirportItlwm-High Sierra */,\n\t\t\t\t35CBE6BF251CB8BF00435CBC /* AirportItlwm-Mojave */,\n\t\t\t\tF89B6BB825021C9C000F77FF /* AirportItlwm-Catalina */,\n\t\t\t\t35CBE655251CB89700435CBC /* AirportItlwm-Big Sur */,\n\t\t\t\tF897ECB6266EFF93005EE8F7 /* AirportItlwm-Monterey */,\n\t\t\t\tF8AE64F5285471560085B4CF /* AirportItlwm-Ventura */,\n\t\t\t\tF8B210A72A2EC2680043ECBD /* AirportItlwm-Sonoma14.0 */,\n\t\t\t\tF8D94C802B9ABFE20081A3C4 /* AirportItlwm-Sonoma14.4 */,\n\t\t\t\t5066D63825287F7900EE6F38 /* fw_gen */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\t024A07AA23FCBC3C009FBA6C /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t35CBE6B6251CB89700435CBC /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t35CBE720251CB8BF00435CBC /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t35CBE78B251CB8CA00435CBC /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tF897ED14266EFF93005EE8F7 /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tF89B6BB725021C9C000F77FF /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tF8AE6554285471560085B4CF /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tF8B211062A2EC2680043ECBD /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tF8D94CF12B9ABFE20081A3C4 /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXResourcesBuildPhase section */\n\n/* Begin PBXShellScriptBuildPhase section */\n\t\t5066D63C25287F8E00EE6F38 /* Generate Firmware */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputFileListPaths = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\tname = \"Generate Firmware\";\n\t\t\toutputFileListPaths = (\n\t\t\t);\n\t\t\toutputPaths = (\n\t\t\t\t\"$(PROJECT_DIR)/include/FwBinary.cpp\",\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"scripts/fw_gen.sh -P \\\"${PROJECT_DIR}/itlwm/firmware/\\\"\\n\";\n\t\t};\n/* End PBXShellScriptBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\t024A07A823FCBC3C009FBA6C /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tF8A4307325062CE300EA545E /* zutil.c in Sources */,\n\t\t\t\tF8294FE424FCBF5100239253 /* FwBinary.cpp in Sources */,\n\t\t\t\tF8ED134424FBB5B70068C831 /* ItlIwx.cpp in Sources */,\n\t\t\t\tF8C772922443439A00A1B8A0 /* compat.cpp in Sources */,\n\t\t\t\t024A085223FCBC6C009FBA6C /* poly1305.c in Sources */,\n\t\t\t\t024A083023FCBC6C009FBA6C /* sha2.c in Sources */,\n\t\t\t\t024A085023FCBC6C009FBA6C /* arc4.c in Sources */,\n\t\t\t\t024A082F23FCBC6C009FBA6C /* hmac.c in Sources */,\n\t\t\t\tF8C2EC5D2408031A007A9422 /* ieee80211_crypto_ccmp.c in Sources */,\n\t\t\t\tF8C2EC552408031A007A9422 /* ieee80211_input.c in Sources */,\n\t\t\t\tF8C2EC662408031A007A9422 /* ieee80211_crypto_wep.c in Sources */,\n\t\t\t\tF8C2EC692408031A007A9422 /* CTimeout.cpp in Sources */,\n\t\t\t\tF8C2EC682408031A007A9422 /* ieee80211_crypto.c in Sources */,\n\t\t\t\tF8C2EC602408031A007A9422 /* ieee80211_amrr.c in Sources */,\n\t\t\t\tF8C2EC6B2408031A007A9422 /* ieee80211_regdomain.c in Sources */,\n\t\t\t\tF8C2EC5B2408031A007A9422 /* ieee80211_crypto_bip.c in Sources */,\n\t\t\t\tF8C2EC572408031A007A9422 /* timeout.c in Sources */,\n\t\t\t\tF837C91D2724577F00B2C499 /* coex.cpp in Sources */,\n\t\t\t\tF8AF3A3124F9F35B008911C1 /* ItlIwm.cpp in Sources */,\n\t\t\t\tF88D2B3D2414E64000BBE700 /* sha1-pbkdf2.c in Sources */,\n\t\t\t\t024A08D623FCF4D7009FBA6C /* scan.cpp in Sources */,\n\t\t\t\tA5FA2AE428A797B200847103 /* _ifq.cpp in Sources */,\n\t\t\t\tF8D364F824F93AFD0029340B /* ItlHalService.cpp in Sources */,\n\t\t\t\tF8C2EC6C2408031A007A9422 /* ieee80211_node.c in Sources */,\n\t\t\t\t024A08C623FCDC3B009FBA6C /* tx.cpp in Sources */,\n\t\t\t\t024A083423FCBC6C009FBA6C /* cast.c in Sources */,\n\t\t\t\t024A08CA23FCE537009FBA6C /* phy.cpp in Sources */,\n\t\t\t\tF8C2EC502408031A007A9422 /* _string.c in Sources */,\n\t\t\t\t024A082E23FCBC6C009FBA6C /* aes.c in Sources */,\n\t\t\t\tF8C2EC4F2408031A007A9422 /* ieee80211_proto.c in Sources */,\n\t\t\t\t024A07B223FCBC3C009FBA6C /* itlwm.cpp in Sources */,\n\t\t\t\t024A084923FCBC6C009FBA6C /* ecb_enc.c in Sources */,\n\t\t\t\t024A084F23FCBC6C009FBA6C /* md5.c in Sources */,\n\t\t\t\t024A083623FCBC6C009FBA6C /* michael.c in Sources */,\n\t\t\t\tF8C2EC672408031A007A9422 /* ieee80211_output.c in Sources */,\n\t\t\t\t024A08D423FCF3E6009FBA6C /* power.cpp in Sources */,\n\t\t\t\tF8D257742495A33500872E4F /* _mbuf.cpp in Sources */,\n\t\t\t\t024A08C823FCE2ED009FBA6C /* hw.cpp in Sources */,\n\t\t\t\t024A08CE23FCE67F009FBA6C /* nvm.cpp in Sources */,\n\t\t\t\t024A083D23FCBC6C009FBA6C /* sha1.c in Sources */,\n\t\t\t\t17FD7F10255E4AC800611406 /* ItlIwn.cpp in Sources */,\n\t\t\t\tA5DD111526D93B5F00BA01EF /* rs.cpp in Sources */,\n\t\t\t\t024A085923FCBC6C009FBA6C /* idgen.c in Sources */,\n\t\t\t\tF8C2EC522408031A007A9422 /* ieee80211_ioctl.c in Sources */,\n\t\t\t\tF8C594D325FD935B0007D19C /* ieee80211_ra.c in Sources */,\n\t\t\t\t024A085823FCBC6C009FBA6C /* rmd160.c in Sources */,\n\t\t\t\t024A084223FCBC6C009FBA6C /* cmac.c in Sources */,\n\t\t\t\tF8C2EC532408031A007A9422 /* ieee80211.c in Sources */,\n\t\t\t\t024A084E23FCBC6C009FBA6C /* chachapoly.c in Sources */,\n\t\t\t\tF8F9EDE1240B7415009CB8E7 /* _task.cpp in Sources */,\n\t\t\t\t024A085523FCBC6C009FBA6C /* key_wrap.c in Sources */,\n\t\t\t\tF8E49A14249B923500BE6868 /* ItlNetworkUserClient.cpp in Sources */,\n\t\t\t\tF8C2EC6D2408031A007A9422 /* ieee80211_pae_output.c in Sources */,\n\t\t\t\tF8C2EC5E2408031A007A9422 /* ieee80211_pae_input.c in Sources */,\n\t\t\t\t024A08BE23FCD314009FBA6C /* fw.cpp in Sources */,\n\t\t\t\t024A08CC23FCE5CA009FBA6C /* mac80211.cpp in Sources */,\n\t\t\t\t024A083123FCBC6C009FBA6C /* rijndael.c in Sources */,\n\t\t\t\t024A085723FCBC6C009FBA6C /* gmac.c in Sources */,\n\t\t\t\tF8C2EC592408031A007A9422 /* ieee80211_mira.c in Sources */,\n\t\t\t\t024A083223FCBC6C009FBA6C /* ecb3_enc.c in Sources */,\n\t\t\t\tA5A0C5242A501E6800EF9328 /* arp.c in Sources */,\n\t\t\t\t024A08D023FCEE88009FBA6C /* ctxt.cpp in Sources */,\n\t\t\t\tF8D76362244F21BB00DEA040 /* pm.cpp in Sources */,\n\t\t\t\t024A08C023FCD4E2009FBA6C /* utils.cpp in Sources */,\n\t\t\t\t024A08D223FCF395009FBA6C /* led.cpp in Sources */,\n\t\t\t\tF8C2EC542408031A007A9422 /* ieee80211_rssadapt.c in Sources */,\n\t\t\t\t024A08C223FCD999009FBA6C /* io.cpp in Sources */,\n\t\t\t\t024A083323FCBC6C009FBA6C /* set_key.c in Sources */,\n\t\t\t\t024A08C423FCDC14009FBA6C /* rx.cpp in Sources */,\n\t\t\t\tF8C2EC5C2408031A007A9422 /* ieee80211_crypto_tkip.c in Sources */,\n\t\t\t\t024A085123FCBC6C009FBA6C /* blf.c in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t35CBE670251CB89700435CBC /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t35CBE671251CB89700435CBC /* _mbuf.cpp in Sources */,\n\t\t\t\tF8C594D725FD935B0007D19C /* ieee80211_ra.c in Sources */,\n\t\t\t\t35CBE672251CB89700435CBC /* _task.cpp in Sources */,\n\t\t\t\t35CBE673251CB89700435CBC /* FwBinary.cpp in Sources */,\n\t\t\t\tF837C9212724577F00B2C499 /* coex.cpp in Sources */,\n\t\t\t\t35CBE675251CB89700435CBC /* ieee80211_proto.c in Sources */,\n\t\t\t\t35CBE676251CB89700435CBC /* AirportItlwmInterface.cpp in Sources */,\n\t\t\t\t35CBE677251CB89700435CBC /* _string.c in Sources */,\n\t\t\t\t35CBE678251CB89700435CBC /* ieee80211_ioctl.c in Sources */,\n\t\t\t\t35CBE679251CB89700435CBC /* ieee80211.c in Sources */,\n\t\t\t\t35CBE67A251CB89700435CBC /* ieee80211_rssadapt.c in Sources */,\n\t\t\t\t35CBE67B251CB89700435CBC /* ieee80211_input.c in Sources */,\n\t\t\t\t35CBE67C251CB89700435CBC /* timeout.c in Sources */,\n\t\t\t\t35CBE67D251CB89700435CBC /* ieee80211_mira.c in Sources */,\n\t\t\t\t35CBE67E251CB89700435CBC /* ieee80211_crypto_bip.c in Sources */,\n\t\t\t\t35CBE67F251CB89700435CBC /* ieee80211_crypto_tkip.c in Sources */,\n\t\t\t\t35CBE680251CB89700435CBC /* ieee80211_crypto_ccmp.c in Sources */,\n\t\t\t\t35CBE681251CB89700435CBC /* ieee80211_crypto_wep.c in Sources */,\n\t\t\t\t35CBE682251CB89700435CBC /* ieee80211_pae_input.c in Sources */,\n\t\t\t\t35CBE683251CB89700435CBC /* ieee80211_amrr.c in Sources */,\n\t\t\t\t35CBE684251CB89700435CBC /* ieee80211_output.c in Sources */,\n\t\t\t\t35CBE685251CB89700435CBC /* ieee80211_crypto.c in Sources */,\n\t\t\t\t35CBE686251CB89700435CBC /* CTimeout.cpp in Sources */,\n\t\t\t\t35CBE687251CB89700435CBC /* ieee80211_regdomain.c in Sources */,\n\t\t\t\t35CBE688251CB89700435CBC /* ieee80211_node.c in Sources */,\n\t\t\t\t35CBE689251CB89700435CBC /* ieee80211_pae_output.c in Sources */,\n\t\t\t\t35CBE68A251CB89700435CBC /* sha1-pbkdf2.c in Sources */,\n\t\t\t\t35CBE68B251CB89700435CBC /* aes.c in Sources */,\n\t\t\t\t35CBE68C251CB89700435CBC /* hmac.c in Sources */,\n\t\t\t\t35CBE68D251CB89700435CBC /* sha2.c in Sources */,\n\t\t\t\t35CBE68E251CB89700435CBC /* rijndael.c in Sources */,\n\t\t\t\t35CBE68F251CB89700435CBC /* ecb3_enc.c in Sources */,\n\t\t\t\t35CBE690251CB89700435CBC /* set_key.c in Sources */,\n\t\t\t\tA5A0C5282A501E6800EF9328 /* arp.c in Sources */,\n\t\t\t\t35CBE691251CB89700435CBC /* cast.c in Sources */,\n\t\t\t\t35CBE692251CB89700435CBC /* michael.c in Sources */,\n\t\t\t\t35CBE693251CB89700435CBC /* sha1.c in Sources */,\n\t\t\t\t35CBE694251CB89700435CBC /* cmac.c in Sources */,\n\t\t\t\t35CBE695251CB89700435CBC /* ecb_enc.c in Sources */,\n\t\t\t\t35CBE696251CB89700435CBC /* chachapoly.c in Sources */,\n\t\t\t\t35CBE697251CB89700435CBC /* md5.c in Sources */,\n\t\t\t\t35CBE698251CB89700435CBC /* arc4.c in Sources */,\n\t\t\t\t35CBE699251CB89700435CBC /* blf.c in Sources */,\n\t\t\t\tA5DD111926D93B5F00BA01EF /* rs.cpp in Sources */,\n\t\t\t\t35CBE69A251CB89700435CBC /* poly1305.c in Sources */,\n\t\t\t\t35CBE69B251CB89700435CBC /* key_wrap.c in Sources */,\n\t\t\t\t35CBE69C251CB89700435CBC /* gmac.c in Sources */,\n\t\t\t\t35CBE69D251CB89700435CBC /* rmd160.c in Sources */,\n\t\t\t\t35CBE69E251CB89700435CBC /* idgen.c in Sources */,\n\t\t\t\t35CBE69F251CB89700435CBC /* compat.cpp in Sources */,\n\t\t\t\tA5FA2AE828A797B200847103 /* _ifq.cpp in Sources */,\n\t\t\t\t35CBE6A0251CB89700435CBC /* zutil.c in Sources */,\n\t\t\t\t35CBE6A1251CB89700435CBC /* ItlHalService.cpp in Sources */,\n\t\t\t\t35CBE6A2251CB89700435CBC /* ItlIwx.cpp in Sources */,\n\t\t\t\t35CBE6A3251CB89700435CBC /* utils.cpp in Sources */,\n\t\t\t\t35CBE6A4251CB89700435CBC /* fw.cpp in Sources */,\n\t\t\t\t35CBE6A5251CB89700435CBC /* io.cpp in Sources */,\n\t\t\t\t35CBE6A6251CB89700435CBC /* rx.cpp in Sources */,\n\t\t\t\t35CBE6A7251CB89700435CBC /* tx.cpp in Sources */,\n\t\t\t\t35CBE6A8251CB89700435CBC /* hw.cpp in Sources */,\n\t\t\t\t17FD7F78255E547200611406 /* ItlIwn.cpp in Sources */,\n\t\t\t\t35CBE6A9251CB89700435CBC /* phy.cpp in Sources */,\n\t\t\t\t35CBE6AA251CB89700435CBC /* mac80211.cpp in Sources */,\n\t\t\t\t35CBE6AB251CB89700435CBC /* nvm.cpp in Sources */,\n\t\t\t\t35CBE6AC251CB89700435CBC /* ctxt.cpp in Sources */,\n\t\t\t\t35CBE6AD251CB89700435CBC /* led.cpp in Sources */,\n\t\t\t\t35CBE6AE251CB89700435CBC /* power.cpp in Sources */,\n\t\t\t\t35CBE6AF251CB89700435CBC /* scan.cpp in Sources */,\n\t\t\t\t35CBE6B0251CB89700435CBC /* ItlIwm.cpp in Sources */,\n\t\t\t\t35CBE6B1251CB89700435CBC /* AirportSTAIOCTL.cpp in Sources */,\n\t\t\t\t35CBE6B2251CB89700435CBC /* AirportItlwm.cpp in Sources */,\n\t\t\t\t35CBE6B3251CB89700435CBC /* AirportVirtualIOCTL.cpp in Sources */,\n\t\t\t\t35CBE6B4251CB89700435CBC /* AirportAWDL.cpp in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t35CBE6DA251CB8BF00435CBC /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t35CBE6DB251CB8BF00435CBC /* _mbuf.cpp in Sources */,\n\t\t\t\tF8C594D525FD935B0007D19C /* ieee80211_ra.c in Sources */,\n\t\t\t\t35CBE6DC251CB8BF00435CBC /* _task.cpp in Sources */,\n\t\t\t\t35CBE6DD251CB8BF00435CBC /* FwBinary.cpp in Sources */,\n\t\t\t\tF837C91F2724577F00B2C499 /* coex.cpp in Sources */,\n\t\t\t\t35CBE6DF251CB8BF00435CBC /* ieee80211_proto.c in Sources */,\n\t\t\t\t35CBE6E0251CB8BF00435CBC /* AirportItlwmInterface.cpp in Sources */,\n\t\t\t\t35CBE6E1251CB8BF00435CBC /* _string.c in Sources */,\n\t\t\t\t35CBE6E2251CB8BF00435CBC /* ieee80211_ioctl.c in Sources */,\n\t\t\t\t35CBE6E3251CB8BF00435CBC /* ieee80211.c in Sources */,\n\t\t\t\t35CBE6E4251CB8BF00435CBC /* ieee80211_rssadapt.c in Sources */,\n\t\t\t\t35CBE6E5251CB8BF00435CBC /* ieee80211_input.c in Sources */,\n\t\t\t\t35CBE6E6251CB8BF00435CBC /* timeout.c in Sources */,\n\t\t\t\t35CBE6E7251CB8BF00435CBC /* ieee80211_mira.c in Sources */,\n\t\t\t\t35CBE6E8251CB8BF00435CBC /* ieee80211_crypto_bip.c in Sources */,\n\t\t\t\t35CBE6E9251CB8BF00435CBC /* ieee80211_crypto_tkip.c in Sources */,\n\t\t\t\t35CBE6EA251CB8BF00435CBC /* ieee80211_crypto_ccmp.c in Sources */,\n\t\t\t\t35CBE6EB251CB8BF00435CBC /* ieee80211_crypto_wep.c in Sources */,\n\t\t\t\t35CBE6EC251CB8BF00435CBC /* ieee80211_pae_input.c in Sources */,\n\t\t\t\t35CBE6ED251CB8BF00435CBC /* ieee80211_amrr.c in Sources */,\n\t\t\t\t35CBE6EE251CB8BF00435CBC /* ieee80211_output.c in Sources */,\n\t\t\t\t35CBE6EF251CB8BF00435CBC /* ieee80211_crypto.c in Sources */,\n\t\t\t\t35CBE6F0251CB8BF00435CBC /* CTimeout.cpp in Sources */,\n\t\t\t\t35CBE6F1251CB8BF00435CBC /* ieee80211_regdomain.c in Sources */,\n\t\t\t\t35CBE6F2251CB8BF00435CBC /* ieee80211_node.c in Sources */,\n\t\t\t\t35CBE6F3251CB8BF00435CBC /* ieee80211_pae_output.c in Sources */,\n\t\t\t\t35CBE6F4251CB8BF00435CBC /* sha1-pbkdf2.c in Sources */,\n\t\t\t\t35CBE6F5251CB8BF00435CBC /* aes.c in Sources */,\n\t\t\t\t35CBE6F6251CB8BF00435CBC /* hmac.c in Sources */,\n\t\t\t\t35CBE6F7251CB8BF00435CBC /* sha2.c in Sources */,\n\t\t\t\t35CBE6F8251CB8BF00435CBC /* rijndael.c in Sources */,\n\t\t\t\t35CBE6F9251CB8BF00435CBC /* ecb3_enc.c in Sources */,\n\t\t\t\t35CBE6FA251CB8BF00435CBC /* set_key.c in Sources */,\n\t\t\t\tA5A0C5262A501E6800EF9328 /* arp.c in Sources */,\n\t\t\t\t35CBE6FB251CB8BF00435CBC /* cast.c in Sources */,\n\t\t\t\t35CBE6FC251CB8BF00435CBC /* michael.c in Sources */,\n\t\t\t\t35CBE6FD251CB8BF00435CBC /* sha1.c in Sources */,\n\t\t\t\t35CBE6FE251CB8BF00435CBC /* cmac.c in Sources */,\n\t\t\t\t35CBE6FF251CB8BF00435CBC /* ecb_enc.c in Sources */,\n\t\t\t\t35CBE700251CB8BF00435CBC /* chachapoly.c in Sources */,\n\t\t\t\t35CBE701251CB8BF00435CBC /* md5.c in Sources */,\n\t\t\t\t35CBE702251CB8BF00435CBC /* arc4.c in Sources */,\n\t\t\t\t35CBE703251CB8BF00435CBC /* blf.c in Sources */,\n\t\t\t\tA5DD111726D93B5F00BA01EF /* rs.cpp in Sources */,\n\t\t\t\t35CBE704251CB8BF00435CBC /* poly1305.c in Sources */,\n\t\t\t\t35CBE705251CB8BF00435CBC /* key_wrap.c in Sources */,\n\t\t\t\t35CBE706251CB8BF00435CBC /* gmac.c in Sources */,\n\t\t\t\t35CBE707251CB8BF00435CBC /* rmd160.c in Sources */,\n\t\t\t\t35CBE708251CB8BF00435CBC /* idgen.c in Sources */,\n\t\t\t\t35CBE709251CB8BF00435CBC /* compat.cpp in Sources */,\n\t\t\t\tA5FA2AE628A797B200847103 /* _ifq.cpp in Sources */,\n\t\t\t\t35CBE70A251CB8BF00435CBC /* zutil.c in Sources */,\n\t\t\t\t35CBE70B251CB8BF00435CBC /* ItlHalService.cpp in Sources */,\n\t\t\t\t35CBE70C251CB8BF00435CBC /* ItlIwx.cpp in Sources */,\n\t\t\t\t35CBE70D251CB8BF00435CBC /* utils.cpp in Sources */,\n\t\t\t\t35CBE70E251CB8BF00435CBC /* fw.cpp in Sources */,\n\t\t\t\t35CBE70F251CB8BF00435CBC /* io.cpp in Sources */,\n\t\t\t\t35CBE710251CB8BF00435CBC /* rx.cpp in Sources */,\n\t\t\t\t35CBE711251CB8BF00435CBC /* tx.cpp in Sources */,\n\t\t\t\t35CBE712251CB8BF00435CBC /* hw.cpp in Sources */,\n\t\t\t\t17FD7F6A255E547100611406 /* ItlIwn.cpp in Sources */,\n\t\t\t\t35CBE713251CB8BF00435CBC /* phy.cpp in Sources */,\n\t\t\t\t35CBE714251CB8BF00435CBC /* mac80211.cpp in Sources */,\n\t\t\t\t35CBE715251CB8BF00435CBC /* nvm.cpp in Sources */,\n\t\t\t\t35CBE716251CB8BF00435CBC /* ctxt.cpp in Sources */,\n\t\t\t\t35CBE717251CB8BF00435CBC /* led.cpp in Sources */,\n\t\t\t\t35CBE718251CB8BF00435CBC /* power.cpp in Sources */,\n\t\t\t\t35CBE719251CB8BF00435CBC /* scan.cpp in Sources */,\n\t\t\t\t35CBE71A251CB8BF00435CBC /* ItlIwm.cpp in Sources */,\n\t\t\t\t35CBE71B251CB8BF00435CBC /* AirportSTAIOCTL.cpp in Sources */,\n\t\t\t\t35CBE71C251CB8BF00435CBC /* AirportItlwm.cpp in Sources */,\n\t\t\t\t35CBE71D251CB8BF00435CBC /* AirportVirtualIOCTL.cpp in Sources */,\n\t\t\t\t35CBE71E251CB8BF00435CBC /* AirportAWDL.cpp in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t35CBE745251CB8CA00435CBC /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t35CBE746251CB8CA00435CBC /* _mbuf.cpp in Sources */,\n\t\t\t\tF8C594D425FD935B0007D19C /* ieee80211_ra.c in Sources */,\n\t\t\t\t35CBE747251CB8CA00435CBC /* _task.cpp in Sources */,\n\t\t\t\t35CBE748251CB8CA00435CBC /* FwBinary.cpp in Sources */,\n\t\t\t\tF837C91E2724577F00B2C499 /* coex.cpp in Sources */,\n\t\t\t\t35CBE74A251CB8CA00435CBC /* ieee80211_proto.c in Sources */,\n\t\t\t\t35CBE74B251CB8CA00435CBC /* AirportItlwmInterface.cpp in Sources */,\n\t\t\t\t35CBE74C251CB8CA00435CBC /* _string.c in Sources */,\n\t\t\t\t35CBE74D251CB8CA00435CBC /* ieee80211_ioctl.c in Sources */,\n\t\t\t\t35CBE74E251CB8CA00435CBC /* ieee80211.c in Sources */,\n\t\t\t\t35CBE74F251CB8CA00435CBC /* ieee80211_rssadapt.c in Sources */,\n\t\t\t\t35CBE750251CB8CA00435CBC /* ieee80211_input.c in Sources */,\n\t\t\t\t35CBE751251CB8CA00435CBC /* timeout.c in Sources */,\n\t\t\t\t35CBE752251CB8CA00435CBC /* ieee80211_mira.c in Sources */,\n\t\t\t\t35CBE753251CB8CA00435CBC /* ieee80211_crypto_bip.c in Sources */,\n\t\t\t\t35CBE754251CB8CA00435CBC /* ieee80211_crypto_tkip.c in Sources */,\n\t\t\t\t35CBE755251CB8CA00435CBC /* ieee80211_crypto_ccmp.c in Sources */,\n\t\t\t\t35CBE756251CB8CA00435CBC /* ieee80211_crypto_wep.c in Sources */,\n\t\t\t\t35CBE757251CB8CA00435CBC /* ieee80211_pae_input.c in Sources */,\n\t\t\t\t35CBE758251CB8CA00435CBC /* ieee80211_amrr.c in Sources */,\n\t\t\t\t35CBE759251CB8CA00435CBC /* ieee80211_output.c in Sources */,\n\t\t\t\t35CBE75A251CB8CA00435CBC /* ieee80211_crypto.c in Sources */,\n\t\t\t\t35CBE75B251CB8CA00435CBC /* CTimeout.cpp in Sources */,\n\t\t\t\t35CBE75C251CB8CA00435CBC /* ieee80211_regdomain.c in Sources */,\n\t\t\t\t35CBE75D251CB8CA00435CBC /* ieee80211_node.c in Sources */,\n\t\t\t\t35CBE75E251CB8CA00435CBC /* ieee80211_pae_output.c in Sources */,\n\t\t\t\t35CBE75F251CB8CA00435CBC /* sha1-pbkdf2.c in Sources */,\n\t\t\t\t35CBE760251CB8CA00435CBC /* aes.c in Sources */,\n\t\t\t\t35CBE761251CB8CA00435CBC /* hmac.c in Sources */,\n\t\t\t\t35CBE762251CB8CA00435CBC /* sha2.c in Sources */,\n\t\t\t\t35CBE763251CB8CA00435CBC /* rijndael.c in Sources */,\n\t\t\t\t35CBE764251CB8CA00435CBC /* ecb3_enc.c in Sources */,\n\t\t\t\t35CBE765251CB8CA00435CBC /* set_key.c in Sources */,\n\t\t\t\tA5A0C5252A501E6800EF9328 /* arp.c in Sources */,\n\t\t\t\t35CBE766251CB8CA00435CBC /* cast.c in Sources */,\n\t\t\t\t35CBE767251CB8CA00435CBC /* michael.c in Sources */,\n\t\t\t\t35CBE768251CB8CA00435CBC /* sha1.c in Sources */,\n\t\t\t\t35CBE769251CB8CA00435CBC /* cmac.c in Sources */,\n\t\t\t\t35CBE76A251CB8CA00435CBC /* ecb_enc.c in Sources */,\n\t\t\t\t35CBE76B251CB8CA00435CBC /* chachapoly.c in Sources */,\n\t\t\t\t35CBE76C251CB8CA00435CBC /* md5.c in Sources */,\n\t\t\t\t35CBE76D251CB8CA00435CBC /* arc4.c in Sources */,\n\t\t\t\t35CBE76E251CB8CA00435CBC /* blf.c in Sources */,\n\t\t\t\tA5DD111626D93B5F00BA01EF /* rs.cpp in Sources */,\n\t\t\t\t35CBE76F251CB8CA00435CBC /* poly1305.c in Sources */,\n\t\t\t\t35CBE770251CB8CA00435CBC /* key_wrap.c in Sources */,\n\t\t\t\t35CBE771251CB8CA00435CBC /* gmac.c in Sources */,\n\t\t\t\t35CBE772251CB8CA00435CBC /* rmd160.c in Sources */,\n\t\t\t\t35CBE773251CB8CA00435CBC /* idgen.c in Sources */,\n\t\t\t\t35CBE774251CB8CA00435CBC /* compat.cpp in Sources */,\n\t\t\t\tA5FA2AE528A797B200847103 /* _ifq.cpp in Sources */,\n\t\t\t\t35CBE775251CB8CA00435CBC /* zutil.c in Sources */,\n\t\t\t\t35CBE776251CB8CA00435CBC /* ItlHalService.cpp in Sources */,\n\t\t\t\t35CBE777251CB8CA00435CBC /* ItlIwx.cpp in Sources */,\n\t\t\t\t35CBE778251CB8CA00435CBC /* utils.cpp in Sources */,\n\t\t\t\t35CBE779251CB8CA00435CBC /* fw.cpp in Sources */,\n\t\t\t\t35CBE77A251CB8CA00435CBC /* io.cpp in Sources */,\n\t\t\t\t35CBE77B251CB8CA00435CBC /* rx.cpp in Sources */,\n\t\t\t\t35CBE77C251CB8CA00435CBC /* tx.cpp in Sources */,\n\t\t\t\t35CBE77D251CB8CA00435CBC /* hw.cpp in Sources */,\n\t\t\t\t17FD7F63255E547100611406 /* ItlIwn.cpp in Sources */,\n\t\t\t\t35CBE77E251CB8CA00435CBC /* phy.cpp in Sources */,\n\t\t\t\t35CBE77F251CB8CA00435CBC /* mac80211.cpp in Sources */,\n\t\t\t\t35CBE780251CB8CA00435CBC /* nvm.cpp in Sources */,\n\t\t\t\t35CBE781251CB8CA00435CBC /* ctxt.cpp in Sources */,\n\t\t\t\t35CBE782251CB8CA00435CBC /* led.cpp in Sources */,\n\t\t\t\t35CBE783251CB8CA00435CBC /* power.cpp in Sources */,\n\t\t\t\t35CBE784251CB8CA00435CBC /* scan.cpp in Sources */,\n\t\t\t\t35CBE785251CB8CA00435CBC /* ItlIwm.cpp in Sources */,\n\t\t\t\t35CBE786251CB8CA00435CBC /* AirportSTAIOCTL.cpp in Sources */,\n\t\t\t\t35CBE787251CB8CA00435CBC /* AirportItlwm.cpp in Sources */,\n\t\t\t\t35CBE788251CB8CA00435CBC /* AirportVirtualIOCTL.cpp in Sources */,\n\t\t\t\t35CBE789251CB8CA00435CBC /* AirportAWDL.cpp in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tF897ECCA266EFF93005EE8F7 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tF897ECCB266EFF93005EE8F7 /* _mbuf.cpp in Sources */,\n\t\t\t\tF897ECCC266EFF93005EE8F7 /* ieee80211_ra.c in Sources */,\n\t\t\t\tF897ECCD266EFF93005EE8F7 /* _task.cpp in Sources */,\n\t\t\t\tF897ECCE266EFF93005EE8F7 /* FwBinary.cpp in Sources */,\n\t\t\t\tF897ECD0266EFF93005EE8F7 /* ieee80211_proto.c in Sources */,\n\t\t\t\tF897ECD1266EFF93005EE8F7 /* AirportItlwmInterface.cpp in Sources */,\n\t\t\t\tF897ECD2266EFF93005EE8F7 /* _string.c in Sources */,\n\t\t\t\tF897ECD3266EFF93005EE8F7 /* ieee80211_ioctl.c in Sources */,\n\t\t\t\tF897ECD4266EFF93005EE8F7 /* ieee80211.c in Sources */,\n\t\t\t\tF897ECD5266EFF93005EE8F7 /* ieee80211_rssadapt.c in Sources */,\n\t\t\t\tF897ECD6266EFF93005EE8F7 /* ieee80211_input.c in Sources */,\n\t\t\t\tF897ECD7266EFF93005EE8F7 /* timeout.c in Sources */,\n\t\t\t\tF897ECD8266EFF93005EE8F7 /* ieee80211_mira.c in Sources */,\n\t\t\t\tF897ECD9266EFF93005EE8F7 /* ieee80211_crypto_bip.c in Sources */,\n\t\t\t\tF897ECDA266EFF93005EE8F7 /* ieee80211_crypto_tkip.c in Sources */,\n\t\t\t\tF897ECDB266EFF93005EE8F7 /* ieee80211_crypto_ccmp.c in Sources */,\n\t\t\t\tF897ECDC266EFF93005EE8F7 /* ieee80211_crypto_wep.c in Sources */,\n\t\t\t\tF897ECDD266EFF93005EE8F7 /* ieee80211_pae_input.c in Sources */,\n\t\t\t\tF897ECDE266EFF93005EE8F7 /* ieee80211_amrr.c in Sources */,\n\t\t\t\tF897ECDF266EFF93005EE8F7 /* ieee80211_output.c in Sources */,\n\t\t\t\tF897ECE0266EFF93005EE8F7 /* ieee80211_crypto.c in Sources */,\n\t\t\t\tF897ECE1266EFF93005EE8F7 /* CTimeout.cpp in Sources */,\n\t\t\t\tF897ECE2266EFF93005EE8F7 /* ieee80211_regdomain.c in Sources */,\n\t\t\t\tF897ECE3266EFF93005EE8F7 /* ieee80211_node.c in Sources */,\n\t\t\t\tF897ECE4266EFF93005EE8F7 /* ieee80211_pae_output.c in Sources */,\n\t\t\t\tF897ECE5266EFF93005EE8F7 /* sha1-pbkdf2.c in Sources */,\n\t\t\t\tF897ECE6266EFF93005EE8F7 /* aes.c in Sources */,\n\t\t\t\tF897ECE7266EFF93005EE8F7 /* hmac.c in Sources */,\n\t\t\t\tF897ECE8266EFF93005EE8F7 /* sha2.c in Sources */,\n\t\t\t\tF897ECE9266EFF93005EE8F7 /* rijndael.c in Sources */,\n\t\t\t\tF897ECEA266EFF93005EE8F7 /* ecb3_enc.c in Sources */,\n\t\t\t\tF897ECEB266EFF93005EE8F7 /* set_key.c in Sources */,\n\t\t\t\tF897ECEC266EFF93005EE8F7 /* cast.c in Sources */,\n\t\t\t\tF897ECED266EFF93005EE8F7 /* michael.c in Sources */,\n\t\t\t\tF897ECEE266EFF93005EE8F7 /* sha1.c in Sources */,\n\t\t\t\tA5DD111A26D93B5F00BA01EF /* rs.cpp in Sources */,\n\t\t\t\tF897ECEF266EFF93005EE8F7 /* cmac.c in Sources */,\n\t\t\t\tF897ECF0266EFF93005EE8F7 /* ecb_enc.c in Sources */,\n\t\t\t\tF897ECF1266EFF93005EE8F7 /* chachapoly.c in Sources */,\n\t\t\t\tF897ECF2266EFF93005EE8F7 /* (null) in Sources */,\n\t\t\t\tF897ECF3266EFF93005EE8F7 /* md5.c in Sources */,\n\t\t\t\tF897ECF4266EFF93005EE8F7 /* arc4.c in Sources */,\n\t\t\t\tF897ECF5266EFF93005EE8F7 /* blf.c in Sources */,\n\t\t\t\tA5FA2AE928A797B200847103 /* _ifq.cpp in Sources */,\n\t\t\t\tF897ECF6266EFF93005EE8F7 /* poly1305.c in Sources */,\n\t\t\t\tF897ECF7266EFF93005EE8F7 /* key_wrap.c in Sources */,\n\t\t\t\tF897ECF8266EFF93005EE8F7 /* gmac.c in Sources */,\n\t\t\t\tF897ECF9266EFF93005EE8F7 /* rmd160.c in Sources */,\n\t\t\t\tF897ECFA266EFF93005EE8F7 /* idgen.c in Sources */,\n\t\t\t\tF897ECFB266EFF93005EE8F7 /* compat.cpp in Sources */,\n\t\t\t\tF897ECFC266EFF93005EE8F7 /* zutil.c in Sources */,\n\t\t\t\tF897ECFD266EFF93005EE8F7 /* ItlHalService.cpp in Sources */,\n\t\t\t\tF897ECFE266EFF93005EE8F7 /* ItlIwx.cpp in Sources */,\n\t\t\t\tF897ECFF266EFF93005EE8F7 /* utils.cpp in Sources */,\n\t\t\t\tF897ED00266EFF93005EE8F7 /* fw.cpp in Sources */,\n\t\t\t\tF897ED01266EFF93005EE8F7 /* io.cpp in Sources */,\n\t\t\t\tF897ED02266EFF93005EE8F7 /* rx.cpp in Sources */,\n\t\t\t\tF837C9222724577F00B2C499 /* coex.cpp in Sources */,\n\t\t\t\tF897ED03266EFF93005EE8F7 /* tx.cpp in Sources */,\n\t\t\t\tF897ED04266EFF93005EE8F7 /* hw.cpp in Sources */,\n\t\t\t\tF897ED05266EFF93005EE8F7 /* ItlIwn.cpp in Sources */,\n\t\t\t\tF897ED06266EFF93005EE8F7 /* phy.cpp in Sources */,\n\t\t\t\tF897ED07266EFF93005EE8F7 /* mac80211.cpp in Sources */,\n\t\t\t\tF897ED08266EFF93005EE8F7 /* nvm.cpp in Sources */,\n\t\t\t\tF897ED09266EFF93005EE8F7 /* ctxt.cpp in Sources */,\n\t\t\t\tF897ED0A266EFF93005EE8F7 /* led.cpp in Sources */,\n\t\t\t\tF897ED0B266EFF93005EE8F7 /* power.cpp in Sources */,\n\t\t\t\tF897ED0C266EFF93005EE8F7 /* scan.cpp in Sources */,\n\t\t\t\tA5A0C5292A501E6800EF9328 /* arp.c in Sources */,\n\t\t\t\tF897ED0D266EFF93005EE8F7 /* ItlIwm.cpp in Sources */,\n\t\t\t\tF897ED0E266EFF93005EE8F7 /* AirportSTAIOCTL.cpp in Sources */,\n\t\t\t\tF897ED0F266EFF93005EE8F7 /* AirportItlwm.cpp in Sources */,\n\t\t\t\tF897ED10266EFF93005EE8F7 /* AirportVirtualIOCTL.cpp in Sources */,\n\t\t\t\tF897ED11266EFF93005EE8F7 /* AirportAWDL.cpp in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tF89B6BB525021C9C000F77FF /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tF89B6C20250232DC000F77FF /* _mbuf.cpp in Sources */,\n\t\t\t\tF8C594D625FD935B0007D19C /* ieee80211_ra.c in Sources */,\n\t\t\t\tF89B6C21250232DC000F77FF /* _task.cpp in Sources */,\n\t\t\t\tF89B6BF3250231E3000F77FF /* FwBinary.cpp in Sources */,\n\t\t\t\tF837C9202724577F00B2C499 /* coex.cpp in Sources */,\n\t\t\t\tF89B6BF5250231E3000F77FF /* ieee80211_proto.c in Sources */,\n\t\t\t\tF8CA44A325091AF60036119A /* AirportItlwmInterface.cpp in Sources */,\n\t\t\t\tF89B6BF6250231E3000F77FF /* _string.c in Sources */,\n\t\t\t\tF89B6BF7250231E3000F77FF /* ieee80211_ioctl.c in Sources */,\n\t\t\t\tF89B6BF8250231E3000F77FF /* ieee80211.c in Sources */,\n\t\t\t\tF89B6BF9250231E3000F77FF /* ieee80211_rssadapt.c in Sources */,\n\t\t\t\tF89B6BFA250231E3000F77FF /* ieee80211_input.c in Sources */,\n\t\t\t\tF89B6BFB250231E3000F77FF /* timeout.c in Sources */,\n\t\t\t\tF89B6BFC250231E3000F77FF /* ieee80211_mira.c in Sources */,\n\t\t\t\tF89B6BFD250231E3000F77FF /* ieee80211_crypto_bip.c in Sources */,\n\t\t\t\tF89B6BFE250231E3000F77FF /* ieee80211_crypto_tkip.c in Sources */,\n\t\t\t\tF89B6BFF250231E3000F77FF /* ieee80211_crypto_ccmp.c in Sources */,\n\t\t\t\tF89B6C00250231E3000F77FF /* ieee80211_crypto_wep.c in Sources */,\n\t\t\t\tF89B6C01250231E3000F77FF /* ieee80211_pae_input.c in Sources */,\n\t\t\t\tF89B6C02250231E3000F77FF /* ieee80211_amrr.c in Sources */,\n\t\t\t\tF89B6C03250231E3000F77FF /* ieee80211_output.c in Sources */,\n\t\t\t\tF89B6C04250231E3000F77FF /* ieee80211_crypto.c in Sources */,\n\t\t\t\tF89B6C05250231E3000F77FF /* CTimeout.cpp in Sources */,\n\t\t\t\tF89B6C06250231E3000F77FF /* ieee80211_regdomain.c in Sources */,\n\t\t\t\tF89B6C07250231E4000F77FF /* ieee80211_node.c in Sources */,\n\t\t\t\tF89B6C08250231E4000F77FF /* ieee80211_pae_output.c in Sources */,\n\t\t\t\tF89B6C09250231E4000F77FF /* sha1-pbkdf2.c in Sources */,\n\t\t\t\tF89B6C0A250231E4000F77FF /* aes.c in Sources */,\n\t\t\t\tF89B6C0B250231E4000F77FF /* hmac.c in Sources */,\n\t\t\t\tF89B6C0C250231E4000F77FF /* sha2.c in Sources */,\n\t\t\t\tF89B6C0D250231E4000F77FF /* rijndael.c in Sources */,\n\t\t\t\tF89B6C0E250231E4000F77FF /* ecb3_enc.c in Sources */,\n\t\t\t\tF89B6C0F250231E4000F77FF /* set_key.c in Sources */,\n\t\t\t\tA5A0C5272A501E6800EF9328 /* arp.c in Sources */,\n\t\t\t\tF89B6C10250231E4000F77FF /* cast.c in Sources */,\n\t\t\t\tF89B6C11250231E4000F77FF /* michael.c in Sources */,\n\t\t\t\tF89B6C12250231E4000F77FF /* sha1.c in Sources */,\n\t\t\t\tF89B6C13250231E4000F77FF /* cmac.c in Sources */,\n\t\t\t\tF89B6C14250231E4000F77FF /* ecb_enc.c in Sources */,\n\t\t\t\tF89B6C15250231E4000F77FF /* chachapoly.c in Sources */,\n\t\t\t\tF89B6C16250231E4000F77FF /* md5.c in Sources */,\n\t\t\t\tF89B6C17250231E4000F77FF /* arc4.c in Sources */,\n\t\t\t\tF89B6C18250231E4000F77FF /* blf.c in Sources */,\n\t\t\t\tA5DD111826D93B5F00BA01EF /* rs.cpp in Sources */,\n\t\t\t\tF89B6C19250231E4000F77FF /* poly1305.c in Sources */,\n\t\t\t\tF89B6C1A250231E4000F77FF /* key_wrap.c in Sources */,\n\t\t\t\tF89B6C1B250231E4000F77FF /* gmac.c in Sources */,\n\t\t\t\tF89B6C1C250231E4000F77FF /* rmd160.c in Sources */,\n\t\t\t\tF89B6C1D250231E4000F77FF /* idgen.c in Sources */,\n\t\t\t\tF89B6C1E250231E4000F77FF /* compat.cpp in Sources */,\n\t\t\t\tA5FA2AE728A797B200847103 /* _ifq.cpp in Sources */,\n\t\t\t\tF89B6C1F250231E4000F77FF /* zutil.c in Sources */,\n\t\t\t\tF89B6BF12502316A000F77FF /* ItlHalService.cpp in Sources */,\n\t\t\t\tF89B6BF025023162000F77FF /* ItlIwx.cpp in Sources */,\n\t\t\t\tF89B6BE22502315B000F77FF /* utils.cpp in Sources */,\n\t\t\t\tF89B6BE32502315B000F77FF /* fw.cpp in Sources */,\n\t\t\t\tF89B6BE42502315B000F77FF /* io.cpp in Sources */,\n\t\t\t\tF89B6BE52502315B000F77FF /* rx.cpp in Sources */,\n\t\t\t\tF89B6BE62502315B000F77FF /* tx.cpp in Sources */,\n\t\t\t\tF89B6BE72502315B000F77FF /* hw.cpp in Sources */,\n\t\t\t\t17FD7F71255E547200611406 /* ItlIwn.cpp in Sources */,\n\t\t\t\tF89B6BE82502315B000F77FF /* phy.cpp in Sources */,\n\t\t\t\tF89B6BE92502315B000F77FF /* mac80211.cpp in Sources */,\n\t\t\t\tF89B6BEA2502315B000F77FF /* nvm.cpp in Sources */,\n\t\t\t\tF89B6BEB2502315B000F77FF /* ctxt.cpp in Sources */,\n\t\t\t\tF89B6BEC2502315B000F77FF /* led.cpp in Sources */,\n\t\t\t\tF89B6BED2502315B000F77FF /* power.cpp in Sources */,\n\t\t\t\tF89B6BEE2502315B000F77FF /* scan.cpp in Sources */,\n\t\t\t\tF89B6BEF2502315B000F77FF /* ItlIwm.cpp in Sources */,\n\t\t\t\tF89B6BDD25022F8C000F77FF /* AirportSTAIOCTL.cpp in Sources */,\n\t\t\t\tF89B6BBE25021C9C000F77FF /* AirportItlwm.cpp in Sources */,\n\t\t\t\tF89B6BDF25022FB5000F77FF /* AirportVirtualIOCTL.cpp in Sources */,\n\t\t\t\tF89B6BE125022FC7000F77FF /* AirportAWDL.cpp in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tF8AE6509285471560085B4CF /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tF8876A4E28B71F5400A21E42 /* rs.cpp in Sources */,\n\t\t\t\tF8AE650A285471560085B4CF /* _mbuf.cpp in Sources */,\n\t\t\t\tF8AE650B285471560085B4CF /* ieee80211_ra.c in Sources */,\n\t\t\t\tF8AE650C285471560085B4CF /* _task.cpp in Sources */,\n\t\t\t\tF8AE650D285471560085B4CF /* FwBinary.cpp in Sources */,\n\t\t\t\tF8AE650F285471560085B4CF /* ieee80211_proto.c in Sources */,\n\t\t\t\tF8AE6510285471560085B4CF /* AirportItlwmInterface.cpp in Sources */,\n\t\t\t\tF8AE6511285471560085B4CF /* _string.c in Sources */,\n\t\t\t\tF8AE6512285471560085B4CF /* ieee80211_ioctl.c in Sources */,\n\t\t\t\tF8AE6513285471560085B4CF /* ieee80211.c in Sources */,\n\t\t\t\tF8AE6514285471560085B4CF /* ieee80211_rssadapt.c in Sources */,\n\t\t\t\tF8AE6515285471560085B4CF /* ieee80211_input.c in Sources */,\n\t\t\t\tF8AE6516285471560085B4CF /* timeout.c in Sources */,\n\t\t\t\tF8AE6517285471560085B4CF /* ieee80211_mira.c in Sources */,\n\t\t\t\tF8AE6518285471560085B4CF /* ieee80211_crypto_bip.c in Sources */,\n\t\t\t\tF8AE6519285471560085B4CF /* ieee80211_crypto_tkip.c in Sources */,\n\t\t\t\tF8AE651A285471560085B4CF /* ieee80211_crypto_ccmp.c in Sources */,\n\t\t\t\tF8AE651B285471560085B4CF /* ieee80211_crypto_wep.c in Sources */,\n\t\t\t\tF8AE651C285471560085B4CF /* ieee80211_pae_input.c in Sources */,\n\t\t\t\tF8AE651D285471560085B4CF /* ieee80211_amrr.c in Sources */,\n\t\t\t\tF8AE651E285471560085B4CF /* ieee80211_output.c in Sources */,\n\t\t\t\tF8AE651F285471560085B4CF /* ieee80211_crypto.c in Sources */,\n\t\t\t\tF8AE6520285471560085B4CF /* CTimeout.cpp in Sources */,\n\t\t\t\tF8AE6521285471560085B4CF /* ieee80211_regdomain.c in Sources */,\n\t\t\t\tF8AE6522285471560085B4CF /* ieee80211_node.c in Sources */,\n\t\t\t\tF8AE6523285471560085B4CF /* ieee80211_pae_output.c in Sources */,\n\t\t\t\tF8AE6524285471560085B4CF /* sha1-pbkdf2.c in Sources */,\n\t\t\t\tF8AE6525285471560085B4CF /* aes.c in Sources */,\n\t\t\t\tF8AE6526285471560085B4CF /* hmac.c in Sources */,\n\t\t\t\tF8AE6527285471560085B4CF /* sha2.c in Sources */,\n\t\t\t\tF8AE6528285471560085B4CF /* rijndael.c in Sources */,\n\t\t\t\tF8AE6529285471560085B4CF /* ecb3_enc.c in Sources */,\n\t\t\t\tF8AE652A285471560085B4CF /* set_key.c in Sources */,\n\t\t\t\tF8AE652B285471560085B4CF /* cast.c in Sources */,\n\t\t\t\tF8AE652C285471560085B4CF /* michael.c in Sources */,\n\t\t\t\tF8AE652D285471560085B4CF /* sha1.c in Sources */,\n\t\t\t\tF8AE652E285471560085B4CF /* cmac.c in Sources */,\n\t\t\t\tF8AE652F285471560085B4CF /* ecb_enc.c in Sources */,\n\t\t\t\tF8AE6530285471560085B4CF /* chachapoly.c in Sources */,\n\t\t\t\tF8AE6531285471560085B4CF /* (null) in Sources */,\n\t\t\t\tF8AE6532285471560085B4CF /* md5.c in Sources */,\n\t\t\t\tF8AE6533285471560085B4CF /* arc4.c in Sources */,\n\t\t\t\tF8AE6534285471560085B4CF /* blf.c in Sources */,\n\t\t\t\tA5FA2AEA28A797B200847103 /* _ifq.cpp in Sources */,\n\t\t\t\tF8AE6535285471560085B4CF /* poly1305.c in Sources */,\n\t\t\t\tF8AE6536285471560085B4CF /* key_wrap.c in Sources */,\n\t\t\t\tF8AE6537285471560085B4CF /* gmac.c in Sources */,\n\t\t\t\tF8AE6538285471560085B4CF /* rmd160.c in Sources */,\n\t\t\t\tF8AE6539285471560085B4CF /* idgen.c in Sources */,\n\t\t\t\tF8AE653A285471560085B4CF /* compat.cpp in Sources */,\n\t\t\t\tF8AE653B285471560085B4CF /* zutil.c in Sources */,\n\t\t\t\tF8AE653C285471560085B4CF /* ItlHalService.cpp in Sources */,\n\t\t\t\tF8AE653D285471560085B4CF /* ItlIwx.cpp in Sources */,\n\t\t\t\tF8AE653E285471560085B4CF /* utils.cpp in Sources */,\n\t\t\t\tF8AE653F285471560085B4CF /* fw.cpp in Sources */,\n\t\t\t\tF8AE6540285471560085B4CF /* io.cpp in Sources */,\n\t\t\t\tF8AE6541285471560085B4CF /* rx.cpp in Sources */,\n\t\t\t\tF8AE6542285471560085B4CF /* coex.cpp in Sources */,\n\t\t\t\tF8AE6543285471560085B4CF /* tx.cpp in Sources */,\n\t\t\t\tF8AE6544285471560085B4CF /* hw.cpp in Sources */,\n\t\t\t\tF8AE6545285471560085B4CF /* ItlIwn.cpp in Sources */,\n\t\t\t\tF8AE6546285471560085B4CF /* phy.cpp in Sources */,\n\t\t\t\tF8AE6547285471560085B4CF /* mac80211.cpp in Sources */,\n\t\t\t\tF8AE6548285471560085B4CF /* nvm.cpp in Sources */,\n\t\t\t\tF8AE6549285471560085B4CF /* ctxt.cpp in Sources */,\n\t\t\t\tF8AE654A285471560085B4CF /* led.cpp in Sources */,\n\t\t\t\tF8AE654B285471560085B4CF /* power.cpp in Sources */,\n\t\t\t\tF8AE654C285471560085B4CF /* scan.cpp in Sources */,\n\t\t\t\tA5A0C52A2A501E6800EF9328 /* arp.c in Sources */,\n\t\t\t\tF8AE654D285471560085B4CF /* ItlIwm.cpp in Sources */,\n\t\t\t\tF8AE654E285471560085B4CF /* AirportSTAIOCTL.cpp in Sources */,\n\t\t\t\tF8AE654F285471560085B4CF /* AirportItlwm.cpp in Sources */,\n\t\t\t\tF8AE6550285471560085B4CF /* AirportVirtualIOCTL.cpp in Sources */,\n\t\t\t\tF8AE6551285471560085B4CF /* AirportAWDL.cpp in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tF8B210BB2A2EC2680043ECBD /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tF8F84F682ADE26F1002808DE /* rs.cpp in Sources */,\n\t\t\t\tF8B210BC2A2EC2680043ECBD /* _mbuf.cpp in Sources */,\n\t\t\t\tF8B210BD2A2EC2680043ECBD /* ieee80211_ra.c in Sources */,\n\t\t\t\tF8B210BE2A2EC2680043ECBD /* _task.cpp in Sources */,\n\t\t\t\tF8B210BF2A2EC2680043ECBD /* FwBinary.cpp in Sources */,\n\t\t\t\tF8B210C02A2EC2680043ECBD /* ieee80211_proto.c in Sources */,\n\t\t\t\tF8B210C22A2EC2680043ECBD /* _string.c in Sources */,\n\t\t\t\tF8B210C32A2EC2680043ECBD /* ieee80211_ioctl.c in Sources */,\n\t\t\t\tF8B210C42A2EC2680043ECBD /* ieee80211.c in Sources */,\n\t\t\t\tF8B210C52A2EC2680043ECBD /* ieee80211_rssadapt.c in Sources */,\n\t\t\t\tF8B210C62A2EC2680043ECBD /* ieee80211_input.c in Sources */,\n\t\t\t\tF8B210C72A2EC2680043ECBD /* timeout.c in Sources */,\n\t\t\t\tF8B210C82A2EC2680043ECBD /* ieee80211_mira.c in Sources */,\n\t\t\t\tF8B210C92A2EC2680043ECBD /* ieee80211_crypto_bip.c in Sources */,\n\t\t\t\tF8B210CA2A2EC2680043ECBD /* ieee80211_crypto_tkip.c in Sources */,\n\t\t\t\tF8B210CB2A2EC2680043ECBD /* ieee80211_crypto_ccmp.c in Sources */,\n\t\t\t\tF8B210CC2A2EC2680043ECBD /* ieee80211_crypto_wep.c in Sources */,\n\t\t\t\tF8B210CD2A2EC2680043ECBD /* ieee80211_pae_input.c in Sources */,\n\t\t\t\tF8B210CE2A2EC2680043ECBD /* ieee80211_amrr.c in Sources */,\n\t\t\t\tF8B210CF2A2EC2680043ECBD /* ieee80211_output.c in Sources */,\n\t\t\t\tF8B210D02A2EC2680043ECBD /* ieee80211_crypto.c in Sources */,\n\t\t\t\tF8B210D12A2EC2680043ECBD /* CTimeout.cpp in Sources */,\n\t\t\t\tF8B210D22A2EC2680043ECBD /* ieee80211_regdomain.c in Sources */,\n\t\t\t\tF8B210D32A2EC2680043ECBD /* ieee80211_node.c in Sources */,\n\t\t\t\tF8B210D42A2EC2680043ECBD /* ieee80211_pae_output.c in Sources */,\n\t\t\t\tF8B210D52A2EC2680043ECBD /* sha1-pbkdf2.c in Sources */,\n\t\t\t\tF8B210D62A2EC2680043ECBD /* aes.c in Sources */,\n\t\t\t\tF8B210D72A2EC2680043ECBD /* hmac.c in Sources */,\n\t\t\t\tF8B210D82A2EC2680043ECBD /* sha2.c in Sources */,\n\t\t\t\tF8B210D92A2EC2680043ECBD /* rijndael.c in Sources */,\n\t\t\t\tF8B210DA2A2EC2680043ECBD /* ecb3_enc.c in Sources */,\n\t\t\t\tF8B210DB2A2EC2680043ECBD /* set_key.c in Sources */,\n\t\t\t\tF8B210DC2A2EC2680043ECBD /* cast.c in Sources */,\n\t\t\t\tF8B210DD2A2EC2680043ECBD /* michael.c in Sources */,\n\t\t\t\tA5A0C52B2A501E6800EF9328 /* arp.c in Sources */,\n\t\t\t\tF8B210DE2A2EC2680043ECBD /* sha1.c in Sources */,\n\t\t\t\tF8B210DF2A2EC2680043ECBD /* cmac.c in Sources */,\n\t\t\t\tF8B210E02A2EC2680043ECBD /* ecb_enc.c in Sources */,\n\t\t\t\tF8B210E12A2EC2680043ECBD /* chachapoly.c in Sources */,\n\t\t\t\tF8A028222A4A7DDC00C6DE90 /* AirportItlwmV2.cpp in Sources */,\n\t\t\t\tF8B210E22A2EC2680043ECBD /* (null) in Sources */,\n\t\t\t\tF8B210E32A2EC2680043ECBD /* md5.c in Sources */,\n\t\t\t\tF8B210E42A2EC2680043ECBD /* arc4.c in Sources */,\n\t\t\t\tF8A0282F2A4A7E0400C6DE90 /* AirportItlwmEthernetInterface.cpp in Sources */,\n\t\t\t\tF8A028722A4A7FE100C6DE90 /* AirportItlwmSkywalkInterface.cpp in Sources */,\n\t\t\t\tF8B210E52A2EC2680043ECBD /* blf.c in Sources */,\n\t\t\t\tF8B210E62A2EC2680043ECBD /* _ifq.cpp in Sources */,\n\t\t\t\tF8B210E72A2EC2680043ECBD /* poly1305.c in Sources */,\n\t\t\t\tF8B210E82A2EC2680043ECBD /* key_wrap.c in Sources */,\n\t\t\t\tF8B210E92A2EC2680043ECBD /* gmac.c in Sources */,\n\t\t\t\tF8B210EA2A2EC2680043ECBD /* rmd160.c in Sources */,\n\t\t\t\tF8B210EB2A2EC2680043ECBD /* idgen.c in Sources */,\n\t\t\t\tF8B210EC2A2EC2680043ECBD /* compat.cpp in Sources */,\n\t\t\t\tF8B210ED2A2EC2680043ECBD /* zutil.c in Sources */,\n\t\t\t\tF8B210EE2A2EC2680043ECBD /* ItlHalService.cpp in Sources */,\n\t\t\t\tF8B210EF2A2EC2680043ECBD /* ItlIwx.cpp in Sources */,\n\t\t\t\tF8B210F02A2EC2680043ECBD /* utils.cpp in Sources */,\n\t\t\t\tF8B210F12A2EC2680043ECBD /* fw.cpp in Sources */,\n\t\t\t\tF8B210F22A2EC2680043ECBD /* io.cpp in Sources */,\n\t\t\t\tF8B210F32A2EC2680043ECBD /* rx.cpp in Sources */,\n\t\t\t\tF8B210F42A2EC2680043ECBD /* coex.cpp in Sources */,\n\t\t\t\tF8B210F52A2EC2680043ECBD /* tx.cpp in Sources */,\n\t\t\t\tF8B210F62A2EC2680043ECBD /* hw.cpp in Sources */,\n\t\t\t\tF8B210F72A2EC2680043ECBD /* ItlIwn.cpp in Sources */,\n\t\t\t\tF8B210F82A2EC2680043ECBD /* phy.cpp in Sources */,\n\t\t\t\tF8B210F92A2EC2680043ECBD /* mac80211.cpp in Sources */,\n\t\t\t\tF8B210FA2A2EC2680043ECBD /* nvm.cpp in Sources */,\n\t\t\t\tF8B210FB2A2EC2680043ECBD /* ctxt.cpp in Sources */,\n\t\t\t\tF8B210FC2A2EC2680043ECBD /* led.cpp in Sources */,\n\t\t\t\tF8B210FD2A2EC2680043ECBD /* power.cpp in Sources */,\n\t\t\t\tF8B210FE2A2EC2680043ECBD /* scan.cpp in Sources */,\n\t\t\t\tF8A0287F2A4A80EA00C6DE90 /* IOPCIEDeviceWrapper.cpp in Sources */,\n\t\t\t\tF8B210FF2A2EC2680043ECBD /* ItlIwm.cpp in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tF8D94CA52B9ABFE20081A3C4 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tF8D94CA62B9ABFE20081A3C4 /* rs.cpp in Sources */,\n\t\t\t\tF8D94CA72B9ABFE20081A3C4 /* _mbuf.cpp in Sources */,\n\t\t\t\tF8D94CA82B9ABFE20081A3C4 /* ieee80211_ra.c in Sources */,\n\t\t\t\tF8D94CA92B9ABFE20081A3C4 /* _task.cpp in Sources */,\n\t\t\t\tF8D94CAA2B9ABFE20081A3C4 /* FwBinary.cpp in Sources */,\n\t\t\t\tF8D94CAB2B9ABFE20081A3C4 /* ieee80211_proto.c in Sources */,\n\t\t\t\tF8D94CAC2B9ABFE20081A3C4 /* _string.c in Sources */,\n\t\t\t\tF8D94CAD2B9ABFE20081A3C4 /* ieee80211_ioctl.c in Sources */,\n\t\t\t\tF8D94CAE2B9ABFE20081A3C4 /* ieee80211.c in Sources */,\n\t\t\t\tF8D94CAF2B9ABFE20081A3C4 /* ieee80211_rssadapt.c in Sources */,\n\t\t\t\tF8D94CB02B9ABFE20081A3C4 /* ieee80211_input.c in Sources */,\n\t\t\t\tF8D94CB12B9ABFE20081A3C4 /* timeout.c in Sources */,\n\t\t\t\tF8D94CB22B9ABFE20081A3C4 /* ieee80211_mira.c in Sources */,\n\t\t\t\tF8D94CB32B9ABFE20081A3C4 /* ieee80211_crypto_bip.c in Sources */,\n\t\t\t\tF8D94CB42B9ABFE20081A3C4 /* ieee80211_crypto_tkip.c in Sources */,\n\t\t\t\tF8D94CB52B9ABFE20081A3C4 /* ieee80211_crypto_ccmp.c in Sources */,\n\t\t\t\tF8D94CB62B9ABFE20081A3C4 /* ieee80211_crypto_wep.c in Sources */,\n\t\t\t\tF8D94CB72B9ABFE20081A3C4 /* ieee80211_pae_input.c in Sources */,\n\t\t\t\tF8D94CB82B9ABFE20081A3C4 /* ieee80211_amrr.c in Sources */,\n\t\t\t\tF8D94CB92B9ABFE20081A3C4 /* ieee80211_output.c in Sources */,\n\t\t\t\tF8D94CBA2B9ABFE20081A3C4 /* ieee80211_crypto.c in Sources */,\n\t\t\t\tF8D94CBB2B9ABFE20081A3C4 /* CTimeout.cpp in Sources */,\n\t\t\t\tF8D94CBC2B9ABFE20081A3C4 /* ieee80211_regdomain.c in Sources */,\n\t\t\t\tF8D94CBD2B9ABFE20081A3C4 /* ieee80211_node.c in Sources */,\n\t\t\t\tF8D94CBE2B9ABFE20081A3C4 /* ieee80211_pae_output.c in Sources */,\n\t\t\t\tF8D94CBF2B9ABFE20081A3C4 /* sha1-pbkdf2.c in Sources */,\n\t\t\t\tF8D94CC02B9ABFE20081A3C4 /* aes.c in Sources */,\n\t\t\t\tF8D94CC12B9ABFE20081A3C4 /* hmac.c in Sources */,\n\t\t\t\tF8D94CC22B9ABFE20081A3C4 /* sha2.c in Sources */,\n\t\t\t\tF8D94CC32B9ABFE20081A3C4 /* rijndael.c in Sources */,\n\t\t\t\tF8D94CC42B9ABFE20081A3C4 /* ecb3_enc.c in Sources */,\n\t\t\t\tF8D94CC52B9ABFE20081A3C4 /* set_key.c in Sources */,\n\t\t\t\tF8D94CC62B9ABFE20081A3C4 /* cast.c in Sources */,\n\t\t\t\tF8D94CC72B9ABFE20081A3C4 /* michael.c in Sources */,\n\t\t\t\tF8D94CC82B9ABFE20081A3C4 /* arp.c in Sources */,\n\t\t\t\tF8D94CC92B9ABFE20081A3C4 /* sha1.c in Sources */,\n\t\t\t\tF8D94CCA2B9ABFE20081A3C4 /* cmac.c in Sources */,\n\t\t\t\tF8D94CCB2B9ABFE20081A3C4 /* ecb_enc.c in Sources */,\n\t\t\t\tF8D94CCC2B9ABFE20081A3C4 /* chachapoly.c in Sources */,\n\t\t\t\tF8D94CCD2B9ABFE20081A3C4 /* AirportItlwmV2.cpp in Sources */,\n\t\t\t\tF8D94CCE2B9ABFE20081A3C4 /* (null) in Sources */,\n\t\t\t\tF8D94CCF2B9ABFE20081A3C4 /* md5.c in Sources */,\n\t\t\t\tF8D94CD02B9ABFE20081A3C4 /* arc4.c in Sources */,\n\t\t\t\tF8D94CD12B9ABFE20081A3C4 /* AirportItlwmEthernetInterface.cpp in Sources */,\n\t\t\t\tF8D94CD22B9ABFE20081A3C4 /* AirportItlwmSkywalkInterface.cpp in Sources */,\n\t\t\t\tF8D94CD32B9ABFE20081A3C4 /* blf.c in Sources */,\n\t\t\t\tF8D94CD42B9ABFE20081A3C4 /* _ifq.cpp in Sources */,\n\t\t\t\tF8D94CD52B9ABFE20081A3C4 /* poly1305.c in Sources */,\n\t\t\t\tF8D94CD62B9ABFE20081A3C4 /* key_wrap.c in Sources */,\n\t\t\t\tF8D94CD72B9ABFE20081A3C4 /* gmac.c in Sources */,\n\t\t\t\tF8D94CD82B9ABFE20081A3C4 /* rmd160.c in Sources */,\n\t\t\t\tF8D94CD92B9ABFE20081A3C4 /* idgen.c in Sources */,\n\t\t\t\tF8D94CDA2B9ABFE20081A3C4 /* compat.cpp in Sources */,\n\t\t\t\tF8D94CDB2B9ABFE20081A3C4 /* zutil.c in Sources */,\n\t\t\t\tF8D94CDC2B9ABFE20081A3C4 /* ItlHalService.cpp in Sources */,\n\t\t\t\tF8D94CDD2B9ABFE20081A3C4 /* ItlIwx.cpp in Sources */,\n\t\t\t\tF8D94CDE2B9ABFE20081A3C4 /* utils.cpp in Sources */,\n\t\t\t\tF8D94CDF2B9ABFE20081A3C4 /* fw.cpp in Sources */,\n\t\t\t\tF8D94CE02B9ABFE20081A3C4 /* io.cpp in Sources */,\n\t\t\t\tF8D94CE12B9ABFE20081A3C4 /* rx.cpp in Sources */,\n\t\t\t\tF8D94CE22B9ABFE20081A3C4 /* coex.cpp in Sources */,\n\t\t\t\tF8D94CE32B9ABFE20081A3C4 /* tx.cpp in Sources */,\n\t\t\t\tF8D94CE42B9ABFE20081A3C4 /* hw.cpp in Sources */,\n\t\t\t\tF8D94CE52B9ABFE20081A3C4 /* ItlIwn.cpp in Sources */,\n\t\t\t\tF8D94CE62B9ABFE20081A3C4 /* phy.cpp in Sources */,\n\t\t\t\tF8D94CE72B9ABFE20081A3C4 /* mac80211.cpp in Sources */,\n\t\t\t\tF8D94CE82B9ABFE20081A3C4 /* nvm.cpp in Sources */,\n\t\t\t\tF8D94CE92B9ABFE20081A3C4 /* ctxt.cpp in Sources */,\n\t\t\t\tF8D94CEA2B9ABFE20081A3C4 /* led.cpp in Sources */,\n\t\t\t\tF8D94CEB2B9ABFE20081A3C4 /* power.cpp in Sources */,\n\t\t\t\tF8D94CEC2B9ABFE20081A3C4 /* scan.cpp in Sources */,\n\t\t\t\tF8D94CED2B9ABFE20081A3C4 /* IOPCIEDeviceWrapper.cpp in Sources */,\n\t\t\t\tF8D94CEE2B9ABFE20081A3C4 /* ItlIwm.cpp in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin PBXTargetDependency section */\n\t\t5066D63E252880A700EE6F38 /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 5066D63825287F7900EE6F38 /* fw_gen */;\n\t\t\ttargetProxy = 5066D63D252880A700EE6F38 /* PBXContainerItemProxy */;\n\t\t};\n\t\t5066D640252880AD00EE6F38 /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 5066D63825287F7900EE6F38 /* fw_gen */;\n\t\t\ttargetProxy = 5066D63F252880AD00EE6F38 /* PBXContainerItemProxy */;\n\t\t};\n\t\t5066D6422528814000EE6F38 /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 5066D63825287F7900EE6F38 /* fw_gen */;\n\t\t\ttargetProxy = 5066D6412528814000EE6F38 /* PBXContainerItemProxy */;\n\t\t};\n\t\t5066D6442528814400EE6F38 /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 5066D63825287F7900EE6F38 /* fw_gen */;\n\t\t\ttargetProxy = 5066D6432528814400EE6F38 /* PBXContainerItemProxy */;\n\t\t};\n\t\t5066D6462528814900EE6F38 /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 5066D63825287F7900EE6F38 /* fw_gen */;\n\t\t\ttargetProxy = 5066D6452528814900EE6F38 /* PBXContainerItemProxy */;\n\t\t};\n\t\tF897ECB7266EFF93005EE8F7 /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 5066D63825287F7900EE6F38 /* fw_gen */;\n\t\t\ttargetProxy = F897ECB8266EFF93005EE8F7 /* PBXContainerItemProxy */;\n\t\t};\n\t\tF8AE64F6285471560085B4CF /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 5066D63825287F7900EE6F38 /* fw_gen */;\n\t\t\ttargetProxy = F8AE64F7285471560085B4CF /* PBXContainerItemProxy */;\n\t\t};\n\t\tF8B210A82A2EC2680043ECBD /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 5066D63825287F7900EE6F38 /* fw_gen */;\n\t\t\ttargetProxy = F8B210A92A2EC2680043ECBD /* PBXContainerItemProxy */;\n\t\t};\n\t\tF8D94C812B9ABFE20081A3C4 /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 5066D63825287F7900EE6F38 /* fw_gen */;\n\t\t\ttargetProxy = F8D94C822B9ABFE20081A3C4 /* PBXContainerItemProxy */;\n\t\t};\n/* End PBXTargetDependency section */\n\n/* Begin XCBuildConfiguration section */\n\t\t024A07B423FCBC3C009FBA6C /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tARCHS = x86_64;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++14\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_WEAK = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\tCODE_SIGN_IDENTITY = \"\";\n\t\t\t\tCODE_SIGN_STYLE = Manual;\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tCURRENT_PROJECT_VERSION = \"$(MODULE_VERSION)\";\n\t\t\t\tDEBUG_INFORMATION_FORMAT = dwarf;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tENABLE_TESTABILITY = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = c11;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_INPUT_FILETYPE = sourcecode.cpp.cpp;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"ITLWM_VERSION=\\\\\\\"${MODULE_VERSION}\\\\\\\"\",\n\t\t\t\t\t\"GIT_COMMIT=\\\\\\\"${GIT_COMMIT}\\\\\\\"\",\n\t\t\t\t\tIEEE80211_STA_ONLY,\n\t\t\t\t);\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tGIT_COMMIT = \"\";\n\t\t\t\tKERNEL_EXTENSION_HEADER_SEARCH_PATHS = \"$(PROJECT_DIR)/MacKernelSDK/Headers\";\n\t\t\t\tKERNEL_FRAMEWORK_HEADERS = \"$(PROJECT_DIR)/MacKernelSDK/Headers\";\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.12;\n\t\t\t\tMODULE_VERSION = 2.4.0;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;\n\t\t\t\tMTL_FAST_MATH = YES;\n\t\t\t\tOTHER_CPLUSPLUSFLAGS = (\n\t\t\t\t\t\"-Wno-deprecated-register\",\n\t\t\t\t\t\"$(OTHER_CFLAGS)\",\n\t\t\t\t);\n\t\t\t\tSDKROOT = macosx;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t024A07B523FCBC3C009FBA6C /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tARCHS = x86_64;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++14\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_WEAK = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\tCODE_SIGN_IDENTITY = \"\";\n\t\t\t\tCODE_SIGN_STYLE = Manual;\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tCURRENT_PROJECT_VERSION = \"$(MODULE_VERSION)\";\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = c11;\n\t\t\t\tGCC_INPUT_FILETYPE = sourcecode.cpp.cpp;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 1;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"ITLWM_VERSION=\\\\\\\"${MODULE_VERSION}\\\\\\\"\",\n\t\t\t\t\t\"GIT_COMMIT=\\\\\\\"${GIT_COMMIT}\\\\\\\"\",\n\t\t\t\t\tIEEE80211_STA_ONLY,\n\t\t\t\t);\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tGIT_COMMIT = \"\";\n\t\t\t\tKERNEL_EXTENSION_HEADER_SEARCH_PATHS = \"$(PROJECT_DIR)/MacKernelSDK/Headers\";\n\t\t\t\tKERNEL_FRAMEWORK_HEADERS = \"$(PROJECT_DIR)/MacKernelSDK/Headers\";\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.12;\n\t\t\t\tMODULE_VERSION = 2.4.0;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tMTL_FAST_MATH = YES;\n\t\t\t\tOTHER_CPLUSPLUSFLAGS = (\n\t\t\t\t\t\"-Wno-deprecated-register\",\n\t\t\t\t\t\"$(OTHER_CFLAGS)\",\n\t\t\t\t);\n\t\t\t\tSDKROOT = macosx;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t024A07B723FCBC3C009FBA6C /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = \"\";\n\t\t\t\tGCC_PRECOMPILE_PREFIX_HEADER = YES;\n\t\t\t\tGCC_PREFIX_HEADER = itlwm/PrivateSPI.pch;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t__PRIVATE_SPI__,\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = itlwm/Info.plist;\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211\",\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211/openbsd\",\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211/linux\",\n\t\t\t\t\t\"$(PROJECT_DIR)/MacKernelSDK/Library/x86_64\",\n\t\t\t\t);\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.9;\n\t\t\t\tMODULE_NAME = com.zxystd.itlwm;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.zxystd.itlwm;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSYSTEM_HEADER_SEARCH_PATHS = \"itl80211/openbsd itl80211 include\";\n\t\t\t\tWRAPPER_EXTENSION = kext;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t024A07B823FCBC3C009FBA6C /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = \"\";\n\t\t\t\tGCC_PRECOMPILE_PREFIX_HEADER = YES;\n\t\t\t\tGCC_PREFIX_HEADER = itlwm/PrivateSPI.pch;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t__PRIVATE_SPI__,\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = itlwm/Info.plist;\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211\",\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211/openbsd\",\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211/linux\",\n\t\t\t\t\t\"$(PROJECT_DIR)/MacKernelSDK/Library/x86_64\",\n\t\t\t\t);\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.9;\n\t\t\t\tMODULE_NAME = com.zxystd.itlwm;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.zxystd.itlwm;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSYSTEM_HEADER_SEARCH_PATHS = \"itl80211/openbsd itl80211 include\";\n\t\t\t\tWRAPPER_EXTENSION = kext;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t35CBE6B8251CB89700435CBC /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCONFIGURATION_BUILD_DIR = \"$(SYMROOT)/$(CONFIGURATION)/Big Sur\";\n\t\t\t\tCURRENT_PROJECT_VERSION = \"$(MODULE_VERSION)\";\n\t\t\t\tGCC_PRECOMPILE_PREFIX_HEADER = YES;\n\t\t\t\tGCC_PREFIX_HEADER = itlwm/PrivateSPI.pch;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\tUSE_APPLE_SUPPLICANT,\n\t\t\t\t\tAIRPORT,\n\t\t\t\t\t\"__IO80211_TARGET=__MAC_11_0\",\n\t\t\t\t\t__PRIVATE_SPI__,\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = AirportItlwm/Info.plist;\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211/openbsd\",\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211/linux\",\n\t\t\t\t\t\"$(PROJECT_DIR)/MacKernelSDK/Library/x86_64\",\n\t\t\t\t);\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.15;\n\t\t\t\tMODULE_NAME = com.zxystd.AirportItlwm;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.zxystd.AirportItlwm;\n\t\t\t\tPRODUCT_NAME = AirportItlwm;\n\t\t\t\tSYSTEM_HEADER_SEARCH_PATHS = \"itl80211/openbsd itl80211 include\";\n\t\t\t\tWRAPPER_EXTENSION = kext;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t35CBE6B9251CB89700435CBC /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCONFIGURATION_BUILD_DIR = \"$(SYMROOT)/$(CONFIGURATION)/Big Sur\";\n\t\t\t\tCURRENT_PROJECT_VERSION = \"$(MODULE_VERSION)\";\n\t\t\t\tGCC_PRECOMPILE_PREFIX_HEADER = YES;\n\t\t\t\tGCC_PREFIX_HEADER = itlwm/PrivateSPI.pch;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"__IO80211_TARGET=__MAC_11_0\",\n\t\t\t\t\tUSE_APPLE_SUPPLICANT,\n\t\t\t\t\tAIRPORT,\n\t\t\t\t\t__PRIVATE_SPI__,\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = AirportItlwm/Info.plist;\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211/openbsd\",\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211/linux\",\n\t\t\t\t\t\"$(PROJECT_DIR)/MacKernelSDK/Library/x86_64\",\n\t\t\t\t);\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.15;\n\t\t\t\tMODULE_NAME = com.zxystd.AirportItlwm;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.zxystd.AirportItlwm;\n\t\t\t\tPRODUCT_NAME = AirportItlwm;\n\t\t\t\tSYSTEM_HEADER_SEARCH_PATHS = \"itl80211/openbsd itl80211 include\";\n\t\t\t\tWRAPPER_EXTENSION = kext;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t35CBE722251CB8BF00435CBC /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCONFIGURATION_BUILD_DIR = \"$(SYMROOT)/$(CONFIGURATION)/Mojave\";\n\t\t\t\tGCC_PRECOMPILE_PREFIX_HEADER = YES;\n\t\t\t\tGCC_PREFIX_HEADER = itlwm/PrivateSPI.pch;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\tUSE_APPLE_SUPPLICANT,\n\t\t\t\t\tAIRPORT,\n\t\t\t\t\t\"__IO80211_TARGET=__MAC_10_14\",\n\t\t\t\t\t__PRIVATE_SPI__,\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = AirportItlwm/Info.plist;\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211/openbsd\",\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211/linux\",\n\t\t\t\t\t\"$(PROJECT_DIR)/MacKernelSDK/Library/x86_64\",\n\t\t\t\t);\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.14;\n\t\t\t\tMODULE_NAME = com.zxystd.AirportItlwm;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.zxystd.AirportItlwm;\n\t\t\t\tPRODUCT_NAME = AirportItlwm;\n\t\t\t\tSYSTEM_HEADER_SEARCH_PATHS = \"itl80211/openbsd itl80211 include\";\n\t\t\t\tWRAPPER_EXTENSION = kext;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t35CBE723251CB8BF00435CBC /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCONFIGURATION_BUILD_DIR = \"$(SYMROOT)/$(CONFIGURATION)/Mojave\";\n\t\t\t\tGCC_PRECOMPILE_PREFIX_HEADER = YES;\n\t\t\t\tGCC_PREFIX_HEADER = itlwm/PrivateSPI.pch;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\tUSE_APPLE_SUPPLICANT,\n\t\t\t\t\tAIRPORT,\n\t\t\t\t\t\"__IO80211_TARGET=__MAC_10_14\",\n\t\t\t\t\t__PRIVATE_SPI__,\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = AirportItlwm/Info.plist;\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211/openbsd\",\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211/linux\",\n\t\t\t\t\t\"$(PROJECT_DIR)/MacKernelSDK/Library/x86_64\",\n\t\t\t\t);\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.14;\n\t\t\t\tMODULE_NAME = com.zxystd.AirportItlwm;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.zxystd.AirportItlwm;\n\t\t\t\tPRODUCT_NAME = AirportItlwm;\n\t\t\t\tSYSTEM_HEADER_SEARCH_PATHS = \"itl80211/openbsd itl80211 include\";\n\t\t\t\tWRAPPER_EXTENSION = kext;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t35CBE78D251CB8CA00435CBC /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCONFIGURATION_BUILD_DIR = \"$(SYMROOT)/$(CONFIGURATION)/High Sierra\";\n\t\t\t\tGCC_PRECOMPILE_PREFIX_HEADER = YES;\n\t\t\t\tGCC_PREFIX_HEADER = itlwm/PrivateSPI.pch;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\tUSE_APPLE_SUPPLICANT,\n\t\t\t\t\tAIRPORT,\n\t\t\t\t\t\"__IO80211_TARGET=__MAC_10_13\",\n\t\t\t\t\t__PRIVATE_SPI__,\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = AirportItlwm/Info.plist;\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211/openbsd\",\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211/linux\",\n\t\t\t\t\t\"$(PROJECT_DIR)/MacKernelSDK/Library/x86_64\",\n\t\t\t\t);\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.13;\n\t\t\t\tMODULE_NAME = com.zxystd.AirportItlwm;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.zxystd.AirportItlwm;\n\t\t\t\tPRODUCT_NAME = AirportItlwm;\n\t\t\t\tSYSTEM_HEADER_SEARCH_PATHS = \"itl80211/openbsd itl80211 include\";\n\t\t\t\tWRAPPER_EXTENSION = kext;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t35CBE78E251CB8CA00435CBC /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCONFIGURATION_BUILD_DIR = \"$(SYMROOT)/$(CONFIGURATION)/High Sierra\";\n\t\t\t\tGCC_PRECOMPILE_PREFIX_HEADER = YES;\n\t\t\t\tGCC_PREFIX_HEADER = itlwm/PrivateSPI.pch;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"__IO80211_TARGET=__MAC_10_13\",\n\t\t\t\t\tUSE_APPLE_SUPPLICANT,\n\t\t\t\t\tAIRPORT,\n\t\t\t\t\t__PRIVATE_SPI__,\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = AirportItlwm/Info.plist;\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211/openbsd\",\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211/linux\",\n\t\t\t\t\t\"$(PROJECT_DIR)/MacKernelSDK/Library/x86_64\",\n\t\t\t\t);\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.13;\n\t\t\t\tMODULE_NAME = com.zxystd.AirportItlwm;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.zxystd.AirportItlwm;\n\t\t\t\tPRODUCT_NAME = AirportItlwm;\n\t\t\t\tSYSTEM_HEADER_SEARCH_PATHS = \"itl80211/openbsd itl80211 include\";\n\t\t\t\tWRAPPER_EXTENSION = kext;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t5066D63925287F7900EE6F38 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t5066D63A25287F7900EE6F38 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\tF897ED16266EFF93005EE8F7 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCONFIGURATION_BUILD_DIR = \"$(SYMROOT)/$(CONFIGURATION)/Monterey\";\n\t\t\t\tCURRENT_PROJECT_VERSION = \"$(MODULE_VERSION)\";\n\t\t\t\tGCC_PRECOMPILE_PREFIX_HEADER = YES;\n\t\t\t\tGCC_PREFIX_HEADER = itlwm/PrivateSPI.pch;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\tUSE_APPLE_SUPPLICANT,\n\t\t\t\t\tAIRPORT,\n\t\t\t\t\t\"__IO80211_TARGET=__MAC_12_0\",\n\t\t\t\t\t__PRIVATE_SPI__,\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = \"AirportItlwm/AirportItlwm-Monterey-Info.plist\";\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211/openbsd\",\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211/linux\",\n\t\t\t\t\t\"$(PROJECT_DIR)/MacKernelSDK/Library/x86_64\",\n\t\t\t\t);\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.15;\n\t\t\t\tMODULE_NAME = com.zxystd.AirportItlwm;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.zxystd.AirportItlwm;\n\t\t\t\tPRODUCT_NAME = AirportItlwm;\n\t\t\t\tSYSTEM_HEADER_SEARCH_PATHS = \"itl80211/openbsd itl80211 include\";\n\t\t\t\tWRAPPER_EXTENSION = kext;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tF897ED17266EFF93005EE8F7 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCONFIGURATION_BUILD_DIR = \"$(SYMROOT)/$(CONFIGURATION)/Monterey\";\n\t\t\t\tCURRENT_PROJECT_VERSION = \"$(MODULE_VERSION)\";\n\t\t\t\tGCC_PRECOMPILE_PREFIX_HEADER = YES;\n\t\t\t\tGCC_PREFIX_HEADER = itlwm/PrivateSPI.pch;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"__IO80211_TARGET=__MAC_12_0\",\n\t\t\t\t\tUSE_APPLE_SUPPLICANT,\n\t\t\t\t\tAIRPORT,\n\t\t\t\t\t__PRIVATE_SPI__,\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = \"AirportItlwm/AirportItlwm-Monterey-Info.plist\";\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211/openbsd\",\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211/linux\",\n\t\t\t\t\t\"$(PROJECT_DIR)/MacKernelSDK/Library/x86_64\",\n\t\t\t\t);\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.15;\n\t\t\t\tMODULE_NAME = com.zxystd.AirportItlwm;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.zxystd.AirportItlwm;\n\t\t\t\tPRODUCT_NAME = AirportItlwm;\n\t\t\t\tSYSTEM_HEADER_SEARCH_PATHS = \"itl80211/openbsd itl80211 include\";\n\t\t\t\tWRAPPER_EXTENSION = kext;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\tF89B6BC125021C9C000F77FF /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCONFIGURATION_BUILD_DIR = \"$(SYMROOT)/$(CONFIGURATION)/Catalina\";\n\t\t\t\tCURRENT_PROJECT_VERSION = \"$(MODULE_VERSION)\";\n\t\t\t\tGCC_PRECOMPILE_PREFIX_HEADER = YES;\n\t\t\t\tGCC_PREFIX_HEADER = itlwm/PrivateSPI.pch;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\tUSE_APPLE_SUPPLICANT,\n\t\t\t\t\tAIRPORT,\n\t\t\t\t\t\"__IO80211_TARGET=__MAC_10_15\",\n\t\t\t\t\t__PRIVATE_SPI__,\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = AirportItlwm/Info.plist;\n\t\t\t\tKERNEL_EXTENSION_HEADER_SEARCH_PATHS = \"$(PROJECT_DIR)/MacKernelSDK/Headers\";\n\t\t\t\tKERNEL_FRAMEWORK_HEADERS = \"$(PROJECT_DIR)/MacKernelSDK/Headers\";\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211/openbsd\",\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211/linux\",\n\t\t\t\t\t\"$(PROJECT_DIR)/MacKernelSDK/Library/x86_64\",\n\t\t\t\t);\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.15;\n\t\t\t\tMODULE_NAME = com.zxystd.AirportItlwm;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.zxystd.AirportItlwm;\n\t\t\t\tPRODUCT_NAME = AirportItlwm;\n\t\t\t\tSYSTEM_HEADER_SEARCH_PATHS = \"itl80211/openbsd itl80211 include\";\n\t\t\t\tWRAPPER_EXTENSION = kext;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tF89B6BC225021C9C000F77FF /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCONFIGURATION_BUILD_DIR = \"$(SYMROOT)/$(CONFIGURATION)/Catalina\";\n\t\t\t\tCURRENT_PROJECT_VERSION = \"$(MODULE_VERSION)\";\n\t\t\t\tGCC_PRECOMPILE_PREFIX_HEADER = YES;\n\t\t\t\tGCC_PREFIX_HEADER = itlwm/PrivateSPI.pch;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\tUSE_APPLE_SUPPLICANT,\n\t\t\t\t\tAIRPORT,\n\t\t\t\t\t\"__IO80211_TARGET=__MAC_10_15\",\n\t\t\t\t\t__PRIVATE_SPI__,\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = AirportItlwm/Info.plist;\n\t\t\t\tKERNEL_EXTENSION_HEADER_SEARCH_PATHS = \"$(PROJECT_DIR)/MacKernelSDK/Headers\";\n\t\t\t\tKERNEL_FRAMEWORK_HEADERS = \"$(PROJECT_DIR)/MacKernelSDK/Headers\";\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211/openbsd\",\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211/linux\",\n\t\t\t\t\t\"$(PROJECT_DIR)/MacKernelSDK/Library/x86_64\",\n\t\t\t\t);\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.15;\n\t\t\t\tMODULE_NAME = com.zxystd.AirportItlwm;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.zxystd.AirportItlwm;\n\t\t\t\tPRODUCT_NAME = AirportItlwm;\n\t\t\t\tSYSTEM_HEADER_SEARCH_PATHS = \"itl80211/openbsd itl80211 include\";\n\t\t\t\tWRAPPER_EXTENSION = kext;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\tF8AE6556285471560085B4CF /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCONFIGURATION_BUILD_DIR = \"$(SYMROOT)/$(CONFIGURATION)/Ventura\";\n\t\t\t\tCURRENT_PROJECT_VERSION = \"$(MODULE_VERSION)\";\n\t\t\t\tGCC_PRECOMPILE_PREFIX_HEADER = YES;\n\t\t\t\tGCC_PREFIX_HEADER = itlwm/PrivateSPI.pch;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\tUSE_APPLE_SUPPLICANT,\n\t\t\t\t\tAIRPORT,\n\t\t\t\t\t\"__IO80211_TARGET=__MAC_13_0\",\n\t\t\t\t\t__PRIVATE_SPI__,\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = \"AirportItlwm/AirportItlwm-Monterey-Info.plist\";\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211/openbsd\",\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211/linux\",\n\t\t\t\t\t\"$(PROJECT_DIR)/MacKernelSDK/Library/x86_64\",\n\t\t\t\t);\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.15;\n\t\t\t\tMODULE_NAME = com.zxystd.AirportItlwm;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.zxystd.AirportItlwm;\n\t\t\t\tPRODUCT_NAME = AirportItlwm;\n\t\t\t\tSYSTEM_HEADER_SEARCH_PATHS = \"itl80211/openbsd itl80211 include\";\n\t\t\t\tWRAPPER_EXTENSION = kext;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tF8AE6557285471560085B4CF /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCONFIGURATION_BUILD_DIR = \"$(SYMROOT)/$(CONFIGURATION)/Ventura\";\n\t\t\t\tCURRENT_PROJECT_VERSION = \"$(MODULE_VERSION)\";\n\t\t\t\tGCC_PRECOMPILE_PREFIX_HEADER = YES;\n\t\t\t\tGCC_PREFIX_HEADER = itlwm/PrivateSPI.pch;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"__IO80211_TARGET=__MAC_13_0\",\n\t\t\t\t\tUSE_APPLE_SUPPLICANT,\n\t\t\t\t\tAIRPORT,\n\t\t\t\t\t__PRIVATE_SPI__,\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = \"AirportItlwm/AirportItlwm-Monterey-Info.plist\";\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211/openbsd\",\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211/linux\",\n\t\t\t\t\t\"$(PROJECT_DIR)/MacKernelSDK/Library/x86_64\",\n\t\t\t\t);\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.15;\n\t\t\t\tMODULE_NAME = com.zxystd.AirportItlwm;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.zxystd.AirportItlwm;\n\t\t\t\tPRODUCT_NAME = AirportItlwm;\n\t\t\t\tSYSTEM_HEADER_SEARCH_PATHS = \"itl80211/openbsd itl80211 include\";\n\t\t\t\tWRAPPER_EXTENSION = kext;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\tF8B211082A2EC2680043ECBD /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCONFIGURATION_BUILD_DIR = \"$(SYMROOT)/$(CONFIGURATION)/Sonoma14.0\";\n\t\t\t\tCURRENT_PROJECT_VERSION = \"$(MODULE_VERSION)\";\n\t\t\t\tGCC_PRECOMPILE_PREFIX_HEADER = YES;\n\t\t\t\tGCC_PREFIX_HEADER = itlwm/PrivateSPI.pch;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\tAIRPORT,\n\t\t\t\t\t\"__IO80211_TARGET=__MAC_14_0\",\n\t\t\t\t\t__PRIVATE_SPI__,\n\t\t\t\t\tIO80211FAMILY_V2,\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = \"AirportItlwm/AirportItlwm-Sonoma-Info.plist\";\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211/openbsd\",\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211/linux\",\n\t\t\t\t\t\"$(PROJECT_DIR)/MacKernelSDK/Library/x86_64\",\n\t\t\t\t);\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.15;\n\t\t\t\tMODULE_NAME = com.zxystd.AirportItlwm;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.zxystd.AirportItlwm;\n\t\t\t\tPRODUCT_NAME = AirportItlwm;\n\t\t\t\tSYSTEM_HEADER_SEARCH_PATHS = \"itl80211/openbsd itl80211 include\";\n\t\t\t\tWRAPPER_EXTENSION = kext;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tF8B211092A2EC2680043ECBD /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCONFIGURATION_BUILD_DIR = \"$(SYMROOT)/$(CONFIGURATION)/Sonoma14.0\";\n\t\t\t\tCURRENT_PROJECT_VERSION = \"$(MODULE_VERSION)\";\n\t\t\t\tGCC_PRECOMPILE_PREFIX_HEADER = YES;\n\t\t\t\tGCC_PREFIX_HEADER = itlwm/PrivateSPI.pch;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"__IO80211_TARGET=__MAC_14_0\",\n\t\t\t\t\tAIRPORT,\n\t\t\t\t\t__PRIVATE_SPI__,\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\tIO80211FAMILY_V2,\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = \"AirportItlwm/AirportItlwm-Sonoma-Info.plist\";\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211/openbsd\",\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211/linux\",\n\t\t\t\t\t\"$(PROJECT_DIR)/MacKernelSDK/Library/x86_64\",\n\t\t\t\t);\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.15;\n\t\t\t\tMODULE_NAME = com.zxystd.AirportItlwm;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.zxystd.AirportItlwm;\n\t\t\t\tPRODUCT_NAME = AirportItlwm;\n\t\t\t\tSYSTEM_HEADER_SEARCH_PATHS = \"itl80211/openbsd itl80211 include\";\n\t\t\t\tWRAPPER_EXTENSION = kext;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\tF8D94CF32B9ABFE20081A3C4 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCONFIGURATION_BUILD_DIR = \"$(SYMROOT)/$(CONFIGURATION)/Sonoma14.4\";\n\t\t\t\tCURRENT_PROJECT_VERSION = \"$(MODULE_VERSION)\";\n\t\t\t\tGCC_PRECOMPILE_PREFIX_HEADER = YES;\n\t\t\t\tGCC_PREFIX_HEADER = itlwm/PrivateSPI.pch;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\tAIRPORT,\n\t\t\t\t\t\"__IO80211_TARGET=__MAC_14_4\",\n\t\t\t\t\t__PRIVATE_SPI__,\n\t\t\t\t\tIO80211FAMILY_V2,\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = \"AirportItlwm/AirportItlwm-Sonoma-Info.plist\";\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211/openbsd\",\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211/linux\",\n\t\t\t\t\t\"$(PROJECT_DIR)/MacKernelSDK/Library/x86_64\",\n\t\t\t\t);\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.15;\n\t\t\t\tMODULE_NAME = com.zxystd.AirportItlwm;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.zxystd.AirportItlwm;\n\t\t\t\tPRODUCT_MODULE_NAME = AirportItlwm;\n\t\t\t\tPRODUCT_NAME = AirportItlwm;\n\t\t\t\tSYSTEM_HEADER_SEARCH_PATHS = \"itl80211/openbsd itl80211 include\";\n\t\t\t\tWRAPPER_EXTENSION = kext;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tF8D94CF42B9ABFE20081A3C4 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCONFIGURATION_BUILD_DIR = \"$(SYMROOT)/$(CONFIGURATION)/Sonoma14.4\";\n\t\t\t\tCURRENT_PROJECT_VERSION = \"$(MODULE_VERSION)\";\n\t\t\t\tGCC_PRECOMPILE_PREFIX_HEADER = YES;\n\t\t\t\tGCC_PREFIX_HEADER = itlwm/PrivateSPI.pch;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"__IO80211_TARGET=__MAC_14_4\",\n\t\t\t\t\tAIRPORT,\n\t\t\t\t\t__PRIVATE_SPI__,\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\tIO80211FAMILY_V2,\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = \"AirportItlwm/AirportItlwm-Sonoma-Info.plist\";\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211/openbsd\",\n\t\t\t\t\t\"$(PROJECT_DIR)/itl80211/linux\",\n\t\t\t\t\t\"$(PROJECT_DIR)/MacKernelSDK/Library/x86_64\",\n\t\t\t\t);\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.15;\n\t\t\t\tMODULE_NAME = com.zxystd.AirportItlwm;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.zxystd.AirportItlwm;\n\t\t\t\tPRODUCT_MODULE_NAME = AirportItlwm;\n\t\t\t\tPRODUCT_NAME = AirportItlwm;\n\t\t\t\tSYSTEM_HEADER_SEARCH_PATHS = \"itl80211/openbsd itl80211 include\";\n\t\t\t\tWRAPPER_EXTENSION = kext;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\t024A07A623FCBC3C009FBA6C /* Build configuration list for PBXProject \"itlwm\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t024A07B423FCBC3C009FBA6C /* Debug */,\n\t\t\t\t024A07B523FCBC3C009FBA6C /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t024A07B623FCBC3C009FBA6C /* Build configuration list for PBXNativeTarget \"itlwm\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t024A07B723FCBC3C009FBA6C /* Debug */,\n\t\t\t\t024A07B823FCBC3C009FBA6C /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t35CBE6B7251CB89700435CBC /* Build configuration list for PBXNativeTarget \"AirportItlwm-Big Sur\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t35CBE6B8251CB89700435CBC /* Debug */,\n\t\t\t\t35CBE6B9251CB89700435CBC /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t35CBE721251CB8BF00435CBC /* Build configuration list for PBXNativeTarget \"AirportItlwm-Mojave\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t35CBE722251CB8BF00435CBC /* Debug */,\n\t\t\t\t35CBE723251CB8BF00435CBC /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t35CBE78C251CB8CA00435CBC /* Build configuration list for PBXNativeTarget \"AirportItlwm-High Sierra\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t35CBE78D251CB8CA00435CBC /* Debug */,\n\t\t\t\t35CBE78E251CB8CA00435CBC /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t5066D63B25287F7900EE6F38 /* Build configuration list for PBXAggregateTarget \"fw_gen\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t5066D63925287F7900EE6F38 /* Debug */,\n\t\t\t\t5066D63A25287F7900EE6F38 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\tF897ED15266EFF93005EE8F7 /* Build configuration list for PBXNativeTarget \"AirportItlwm-Monterey\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tF897ED16266EFF93005EE8F7 /* Debug */,\n\t\t\t\tF897ED17266EFF93005EE8F7 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\tF89B6BC025021C9C000F77FF /* Build configuration list for PBXNativeTarget \"AirportItlwm-Catalina\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tF89B6BC125021C9C000F77FF /* Debug */,\n\t\t\t\tF89B6BC225021C9C000F77FF /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\tF8AE6555285471560085B4CF /* Build configuration list for PBXNativeTarget \"AirportItlwm-Ventura\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tF8AE6556285471560085B4CF /* Debug */,\n\t\t\t\tF8AE6557285471560085B4CF /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\tF8B211072A2EC2680043ECBD /* Build configuration list for PBXNativeTarget \"AirportItlwm-Sonoma14.0\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tF8B211082A2EC2680043ECBD /* Debug */,\n\t\t\t\tF8B211092A2EC2680043ECBD /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\tF8D94CF22B9ABFE20081A3C4 /* Build configuration list for PBXNativeTarget \"AirportItlwm-Sonoma14.4\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tF8D94CF32B9ABFE20081A3C4 /* Debug */,\n\t\t\t\tF8D94CF42B9ABFE20081A3C4 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = 024A07A323FCBC3C009FBA6C /* Project object */;\n}\n"
  },
  {
    "path": "itlwm.xcodeproj/xcshareddata/xcschemes/AirportItlwm (all).xcscheme",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"1100\"\n   version = \"1.3\">\n   <BuildAction\n      parallelizeBuildables = \"YES\"\n      buildImplicitDependencies = \"YES\">\n      <BuildActionEntries>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"35CBE655251CB89700435CBC\"\n               BuildableName = \"AirportItlwm.kext\"\n               BlueprintName = \"AirportItlwm-Big Sur\"\n               ReferencedContainer = \"container:itlwm.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"F89B6BB825021C9C000F77FF\"\n               BuildableName = \"AirportItlwm.kext\"\n               BlueprintName = \"AirportItlwm-Catalina\"\n               ReferencedContainer = \"container:itlwm.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"35CBE72A251CB8CA00435CBC\"\n               BuildableName = \"AirportItlwm.kext\"\n               BlueprintName = \"AirportItlwm-High Sierra\"\n               ReferencedContainer = \"container:itlwm.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"35CBE6BF251CB8BF00435CBC\"\n               BuildableName = \"AirportItlwm.kext\"\n               BlueprintName = \"AirportItlwm-Mojave\"\n               ReferencedContainer = \"container:itlwm.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"F897ECB6266EFF93005EE8F7\"\n               BuildableName = \"AirportItlwm.kext\"\n               BlueprintName = \"AirportItlwm-Monterey\"\n               ReferencedContainer = \"container:itlwm.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"F8AE64F5285471560085B4CF\"\n               BuildableName = \"AirportItlwm.kext\"\n               BlueprintName = \"AirportItlwm-Ventura\"\n               ReferencedContainer = \"container:itlwm.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"F8B210A72A2EC2680043ECBD\"\n               BuildableName = \"AirportItlwm.kext\"\n               BlueprintName = \"AirportItlwm-Sonoma14.0\"\n               ReferencedContainer = \"container:itlwm.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"F8D94C802B9ABFE20081A3C4\"\n               BuildableName = \"AirportItlwm.kext\"\n               BlueprintName = \"AirportItlwm-Sonoma14.4\"\n               ReferencedContainer = \"container:itlwm.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n      </BuildActionEntries>\n   </BuildAction>\n   <TestAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\">\n      <Testables>\n      </Testables>\n   </TestAction>\n   <LaunchAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      launchStyle = \"0\"\n      useCustomWorkingDirectory = \"NO\"\n      ignoresPersistentStateOnLaunch = \"NO\"\n      debugDocumentVersioning = \"YES\"\n      debugServiceExtension = \"internal\"\n      allowLocationSimulation = \"YES\">\n   </LaunchAction>\n   <ProfileAction\n      buildConfiguration = \"Release\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      savedToolIdentifier = \"\"\n      useCustomWorkingDirectory = \"NO\"\n      debugDocumentVersioning = \"YES\">\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"35CBE655251CB89700435CBC\"\n            BuildableName = \"AirportItlwm.kext\"\n            BlueprintName = \"AirportItlwm-Big Sur\"\n            ReferencedContainer = \"container:itlwm.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n   </ProfileAction>\n   <AnalyzeAction\n      buildConfiguration = \"Debug\">\n   </AnalyzeAction>\n   <ArchiveAction\n      buildConfiguration = \"Release\"\n      revealArchiveInOrganizer = \"YES\">\n   </ArchiveAction>\n</Scheme>\n"
  },
  {
    "path": "itlwm.xcodeproj/xcshareddata/xcschemes/itlwm.xcscheme",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"1160\"\n   version = \"1.3\">\n   <BuildAction\n      parallelizeBuildables = \"YES\"\n      buildImplicitDependencies = \"YES\">\n      <BuildActionEntries>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"024A07AB23FCBC3C009FBA6C\"\n               BuildableName = \"itlwm.kext\"\n               BlueprintName = \"itlwm\"\n               ReferencedContainer = \"container:itlwm.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n      </BuildActionEntries>\n   </BuildAction>\n   <TestAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\">\n      <Testables>\n      </Testables>\n   </TestAction>\n   <LaunchAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      launchStyle = \"0\"\n      useCustomWorkingDirectory = \"NO\"\n      ignoresPersistentStateOnLaunch = \"NO\"\n      debugDocumentVersioning = \"YES\"\n      debugServiceExtension = \"internal\"\n      allowLocationSimulation = \"YES\">\n   </LaunchAction>\n   <ProfileAction\n      buildConfiguration = \"Release\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      savedToolIdentifier = \"\"\n      useCustomWorkingDirectory = \"NO\"\n      debugDocumentVersioning = \"YES\">\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"024A07AB23FCBC3C009FBA6C\"\n            BuildableName = \"itlwm.kext\"\n            BlueprintName = \"itlwm\"\n            ReferencedContainer = \"container:itlwm.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n   </ProfileAction>\n   <AnalyzeAction\n      buildConfiguration = \"Debug\">\n   </AnalyzeAction>\n   <ArchiveAction\n      buildConfiguration = \"Release\"\n      revealArchiveInOrganizer = \"YES\">\n   </ArchiveAction>\n</Scheme>\n"
  },
  {
    "path": "iwlwifi-firmware-license",
    "content": "Copyright (c) 2006-2021, Intel Corporation.\nAll rights reserved.\n\nRedistribution.  Redistribution and use in binary form, without\nmodification, are permitted provided that the following conditions are\nmet:\n\n* Redistributions must reproduce the above copyright notice and the\n  following disclaimer in the documentation and/or other materials\n  provided with the distribution.\n* Neither the name of Intel Corporation nor the names of its suppliers\n  may be used to endorse or promote products derived from this software\n  without specific prior written permission.\n* No reverse engineering, decompilation, or disassembly of this software\n  is permitted.\n\nLimited patent license.  Intel Corporation grants a world-wide,\nroyalty-free, non-exclusive license under patents it now or hereafter\nowns or controls to make, have made, use, import, offer to sell and\nsell (\"Utilize\") this software, but solely to the extent that any\nsuch patent is necessary to Utilize the software alone, or in\ncombination with an operating system licensed under an approved Open\nSource license as listed by the Open Source Initiative at\nhttp://opensource.org/licenses.  The patent license shall not apply to\nany other combinations which include this software.  No hardware per\nse is licensed hereunder.\n\nDISCLAIMER.  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\nCONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,\nBUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\nCOPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,\nBUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS\nOF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR\nTORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE\nUSE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH\nDAMAGE.\n"
  },
  {
    "path": "scripts/fw_gen.sh",
    "content": "#!/bin/sh\n\n#  fw_gen.sh\n#  itlwm\n#\n#  Created by qcwap on 2020/3/10.\n#  Copyright © 2020 钟先耀. All rights reserved.\ntarget_file=\"${PROJECT_DIR}/include/FwBinary.cpp\"\nif [ -f \"$target_file\" ]; then\nexit 0\nfi\nwhile [ $# -gt 0 ];\ndo\n    case $1 in\n    -P) fw_files=$2\n    shift\n    ;;\n    \n    esac\n    shift\ndone\n\nscript_file=\"${PROJECT_DIR}/scripts/zlib_compress_fw.py\"\npython3 \"${script_file}\" \"${target_file}\" \"${fw_files}\"\n"
  },
  {
    "path": "scripts/load.sh",
    "content": "sudo kextunload -b com.zxystd.itlwm\nsudo chown -R root:wheel ./../Build/Products/Debug/itlwm.kext\nsudo kextutil -v 6 ./../Build/Products/Debug/itlwm.kext\n\n"
  },
  {
    "path": "scripts/unload.sh",
    "content": "sudo kextunload ../Build/Products/Debug/itlwm.kext\nsudo kextunload -b com.zxystd.itlwm\n"
  },
  {
    "path": "scripts/zlib_compress_fw.py",
    "content": "#!/usr/bin/python\n# -*- coding: utf-8 -*-\n# zlib_compress_fw.py\n#\n#  Created by qcwap on 2020/9/3.\n#  Copyright © 2020 钟先耀. All rights reserved.\n\nimport zlib\nimport os\nimport struct\nimport sys\n\ncopyright = '''\n//  itlwm\n//\n//  Copyright © 2020 钟先耀. All rights reserved.\n#include \"FwData.h\"\n'''\n\ndef compress(data):\n    return zlib.compress(data)\n    \ndef format_file_name(file_name):\n    return file_name.replace(\".\", \"_\").replace(\"-\", \"_\")\n\ndef write_single_file(target_file, path, file):\n    src_file = open(path, \"rb\")\n    src_data = src_file.read()\n    src_data = compress(src_data)\n    src_len = len(src_data)\n    \n    fw_var_name = format_file_name(file)\n    target_file.write(\"\\nconst unsigned char \")\n    target_file.write(fw_var_name)\n    target_file.write(\"[] = {\")\n    index = 0;\n    block = []\n    while True:\n        if index + 16 >= src_len:\n            block = src_data[index:]\n        else:\n            block = src_data[index:index + 16]\n        index += 16;\n        if len(block) < 16:\n            if len(block):\n                for b in block:\n                    if type(b) is str:\n                        b = ord(b)\n                    target_file.write(\"0x{:02X}, \".format(b))\n                target_file.write(\"\\n\")\n            break\n        target_file.write(\"0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X}, \"\n                \"0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X}, \"\n                \"0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X}, \"\n                \"0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X},\\n\"\n                .format(*struct.unpack(\"BBBBBBBBBBBBBBBB\", block)))\n    target_file.write(\"};\\n\")\n    target_file.write(\"const long int \")\n    target_file.write(fw_var_name)\n    target_file.write(\"_size = sizeof(\")\n    target_file.write(fw_var_name)\n    target_file.write(\");\\n\")\n    src_file.close()\n    \n    \ndef process_files(target_file, dir):\n    if not os.path.exists(target_file):\n        if not os.path.exists(os.path.dirname(target_file)):\n            os.mkdirs(os.path.dirname(target_file))\n    target_file_handle = open(target_file, \"w\")\n    target_file_handle.write(copyright)\n    for root, dirs, files in os.walk(dir):\n        for file in files:\n            path = os.path.join(root, file)\n            write_single_file(target_file_handle, path, file)\n            \n        target_file_handle.write(\"\\n\")\n        target_file_handle.write(\"const struct FwDesc fwList[] = {\")\n        \n        for file in files:\n            target_file_handle.write('{IWL_FW(\"')\n            target_file_handle.write(file)\n            target_file_handle.write('\", ')\n            fw_var_name = format_file_name(file)\n            target_file_handle.write(fw_var_name)\n            target_file_handle.write(\", \")\n            target_file_handle.write(fw_var_name)\n            target_file_handle.write(\"_size)},\\n\")\n            \n        target_file_handle.write(\"};\\n\")\n        target_file_handle.write(\"const int fwNumber = \")\n        target_file_handle.write(str(len(files)))\n        target_file_handle.write(\";\\n\")\n            \n    target_file_handle.close()\n\nif __name__ == '__main__':\n    process_files(sys.argv[1], sys.argv[2])\n"
  }
]