Module Name: src Committed By: christos Date: Sun May 15 13:56:20 UTC 2011
Modified Files: src/sys/dev/pci: if_iwn.c if_iwnreg.h if_iwnvar.h Log Message: update from OpenBSD by msaitoh. Tested on amd64. To generate a diff of this commit: cvs rdiff -u -r1.52 -r1.53 src/sys/dev/pci/if_iwn.c cvs rdiff -u -r1.8 -r1.9 src/sys/dev/pci/if_iwnreg.h cvs rdiff -u -r1.12 -r1.13 src/sys/dev/pci/if_iwnvar.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/pci/if_iwn.c diff -u src/sys/dev/pci/if_iwn.c:1.52 src/sys/dev/pci/if_iwn.c:1.53 --- src/sys/dev/pci/if_iwn.c:1.52 Thu Dec 30 14:27:27 2010 +++ src/sys/dev/pci/if_iwn.c Sun May 15 09:56:20 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: if_iwn.c,v 1.52 2010/12/30 19:27:27 jruoho Exp $ */ +/* $NetBSD: if_iwn.c,v 1.53 2011/05/15 13:56:20 christos Exp $ */ /* $OpenBSD: if_iwn.c,v 1.96 2010/05/13 09:25:03 damien Exp $ */ /*- @@ -22,14 +22,11 @@ * adapters. */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_iwn.c,v 1.52 2010/12/30 19:27:27 jruoho Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_iwn.c,v 1.53 2011/05/15 13:56:20 christos Exp $"); #define IWN_USE_RBUF /* Use local storage for RX */ #undef IWN_HWCRYPTO /* XXX does not even compile yet */ -/* XXX Avoid sensor code (correct option for NetBSD too?) */ -#undef SMALL_KERNEL - #include <sys/param.h> #include <sys/sockio.h> #include <sys/proc.h> @@ -125,10 +122,8 @@ static int iwn_match(device_t , struct cfdata *, void *); static void iwn_attach(device_t , device_t , void *); -const struct iwn_hal *iwn_hal_attach(struct iwn_softc *, pci_product_id_t pid); -#ifndef SMALL_KERNEL -static void iwn_sensor_attach(struct iwn_softc *); -#endif +static int iwn4965_attach(struct iwn_softc *, pci_product_id_t); +static int iwn5000_attach(struct iwn_softc *, pci_product_id_t); static void iwn_radiotap_attach(struct iwn_softc *); static int iwn_detach(device_t , int); #if 0 @@ -160,6 +155,8 @@ static void iwn5000_ict_reset(struct iwn_softc *); static int iwn_read_eeprom(struct iwn_softc *); static void iwn4965_read_eeprom(struct iwn_softc *); + +#define IWN_DEBUG 1 #ifdef IWN_DEBUG static void iwn4965_print_power_group(struct iwn_softc *, int); #endif @@ -276,11 +273,11 @@ static int iwn4965_load_firmware(struct iwn_softc *); static int iwn5000_load_firmware_section(struct iwn_softc *, uint32_t, const uint8_t *, int); +static int iwn5000_load_firmware(struct iwn_softc *); static int iwn_read_firmware_leg(struct iwn_softc *, struct iwn_fw_info *); static int iwn_read_firmware_tlv(struct iwn_softc *, struct iwn_fw_info *, uint16_t); -static int iwn5000_load_firmware(struct iwn_softc *); static int iwn_read_firmware(struct iwn_softc *); static int iwn_clock_wait(struct iwn_softc *); static int iwn_apm_init(struct iwn_softc *); @@ -322,62 +319,6 @@ #define DPRINTFN(n, x) #endif -static const struct iwn_hal iwn4965_hal = { - iwn4965_load_firmware, - iwn4965_read_eeprom, - iwn4965_post_alive, - iwn4965_nic_config, - iwn4965_update_sched, - iwn4965_get_temperature, - iwn4965_get_rssi, - iwn4965_set_txpower, - iwn4965_init_gains, - iwn4965_set_gains, - iwn4965_add_node, - iwn4965_tx_done, -#ifndef IEEE80211_NO_HT - iwn4965_ampdu_tx_start, - iwn4965_ampdu_tx_stop, -#endif - IWN4965_NTXQUEUES, - IWN4965_NDMACHNLS, - IWN4965_ID_BROADCAST, - IWN4965_RXONSZ, - IWN4965_SCHEDSZ, - IWN4965_FW_TEXT_MAXSZ, - IWN4965_FW_DATA_MAXSZ, - IWN4965_FWSZ, - IWN4965_SCHED_TXFACT -}; - -static const struct iwn_hal iwn5000_hal = { - iwn5000_load_firmware, - iwn5000_read_eeprom, - iwn5000_post_alive, - iwn5000_nic_config, - iwn5000_update_sched, - iwn5000_get_temperature, - iwn5000_get_rssi, - iwn5000_set_txpower, - iwn5000_init_gains, - iwn5000_set_gains, - iwn5000_add_node, - iwn5000_tx_done, -#ifndef IEEE80211_NO_HT - iwn5000_ampdu_tx_start, - iwn5000_ampdu_tx_stop, -#endif - IWN5000_NTXQUEUES, - IWN5000_NDMACHNLS, - IWN5000_ID_BROADCAST, - IWN5000_RXONSZ, - IWN5000_SCHEDSZ, - IWN5000_FW_TEXT_MAXSZ, - IWN5000_FW_DATA_MAXSZ, - IWN5000_FWSZ, - IWN5000_SCHED_TXFACT -}; - CFATTACH_DECL_NEW(iwn, sizeof(struct iwn_softc), iwn_match, iwn_attach, iwn_detach, NULL); @@ -404,7 +345,6 @@ struct ieee80211com *ic = &sc->sc_ic; struct ifnet *ifp = &sc->sc_ec.ec_if; struct pci_attach_args *pa = aux; - const struct iwn_hal *hal; const char *intrstr; char devinfo[256]; pci_intr_handle_t ih; @@ -438,8 +378,8 @@ /* Clear device-specific "PCI retry timeout" register (41h). */ reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0x40); - reg &= ~0xff00; - pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, reg); + if (reg & 0xff00) + pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, reg & ~0xff00); /* Enable bus-mastering and hardware bug workaround. */ /* XXX verify the bus-mastering is really needed (not in OpenBSD) */ @@ -475,10 +415,16 @@ } aprint_normal_dev(self, "interrupting at %s\n", intrstr); - /* Attach Hardware Abstraction Layer. */ - hal = iwn_hal_attach(sc, PCI_PRODUCT(pa->pa_id)); - if (hal == NULL) + /* Read hardware revision and attach. */ + sc->hw_type = (IWN_READ(sc, IWN_HW_REV) >> 4) & 0xf; + if (sc->hw_type == IWN_HW_REV_TYPE_4965) + error = iwn4965_attach(sc, PCI_PRODUCT(pa->pa_id)); + else + error = iwn5000_attach(sc, PCI_PRODUCT(pa->pa_id)); + if (error != 0) { + aprint_error(": could not attach device\n"); return; + } if ((error = iwn_hw_prepare(sc)) != 0) { aprint_error(": hardware not ready\n"); @@ -524,8 +470,8 @@ } #endif - /* Allocate TX rings (16 on 4965AGN, 20 on 5000.) */ - for (i = 0; i < hal->ntxqs; i++) { + /* Allocate TX rings (16 on 4965AGN, 20 on >=5000). */ + for (i = 0; i < sc->ntxqs; i++) { if ((error = iwn_alloc_tx_ring(sc, &sc->txq[i], i)) != 0) { aprint_error(": could not allocate TX ring %d\n", i); goto fail4; @@ -572,20 +518,22 @@ IEEE80211_C_WME; /* 802.11e */ #ifndef IEEE80211_NO_HT - /* Set HT capabilities. */ - ic->ic_htcaps = + if (sc->sc_flags & IWN_FLAG_HAS_11N) { + /* Set HT capabilities. */ + ic->ic_htcaps = #if IWN_RBUF_SIZE == 8192 - IEEE80211_HTCAP_AMSDU7935 | + IEEE80211_HTCAP_AMSDU7935 | #endif - IEEE80211_HTCAP_CBW20_40 | - IEEE80211_HTCAP_SGI20 | - IEEE80211_HTCAP_SGI40; - if (sc->hw_type != IWN_HW_REV_TYPE_4965) - ic->ic_htcaps |= IEEE80211_HTCAP_GF; - if (sc->hw_type == IWN_HW_REV_TYPE_6050) - ic->ic_htcaps |= IEEE80211_HTCAP_SMPS_DYN; - else - ic->ic_htcaps |= IEEE80211_HTCAP_SMPS_DIS; + IEEE80211_HTCAP_CBW20_40 | + IEEE80211_HTCAP_SGI20 | + IEEE80211_HTCAP_SGI40; + if (sc->hw_type != IWN_HW_REV_TYPE_4965) + ic->ic_htcaps |= IEEE80211_HTCAP_GF; + if (sc->hw_type == IWN_HW_REV_TYPE_6050) + ic->ic_htcaps |= IEEE80211_HTCAP_SMPS_DYN; + else + ic->ic_htcaps |= IEEE80211_HTCAP_SMPS_DIS; + } #endif /* !IEEE80211_NO_HT */ /* Set supported legacy rates. */ @@ -595,12 +543,14 @@ ic->ic_sup_rates[IEEE80211_MODE_11A] = iwn_rateset_11a; } #ifndef IEEE80211_NO_HT - /* Set supported HT rates. */ - ic->ic_sup_mcs[0] = 0xff; - if (sc->nrxchains > 1) /* MCS 0-7 */ - ic->ic_sup_mcs[1] = 0xff; /* MCS 7-15 */ - if (sc->nrxchains > 2) - ic->ic_sup_mcs[2] = 0xff; /* MCS 16-23 */ + if (sc->sc_flags & IWN_FLAG_HAS_11N) { + /* Set supported HT rates. */ + ic->ic_sup_mcs[0] = 0xff; /* MCS 0-7 */ + if (sc->nrxchains > 1) + ic->ic_sup_mcs[1] = 0xff; /* MCS 7-15 */ + if (sc->nrxchains > 2) + ic->ic_sup_mcs[2] = 0xff; /* MCS 16-23 */ + } #endif /* IBSS channel undefined for now. */ @@ -640,9 +590,6 @@ sc->amrr.amrr_min_success_threshold = 1; sc->amrr.amrr_max_success_threshold = 15; -#ifndef SMALL_KERNEL - iwn_sensor_attach(sc); -#endif iwn_radiotap_attach(sc); /* @@ -673,130 +620,122 @@ fail1: iwn_free_fwmem(sc); } -const struct iwn_hal * -iwn_hal_attach(struct iwn_softc *sc, pci_product_id_t pid) +int +iwn4965_attach(struct iwn_softc *sc, pci_product_id_t pid) { - sc->hw_type = (IWN_READ(sc, IWN_HW_REV) >> 4) & 0xf; + struct iwn_ops *ops = &sc->ops; + + ops->load_firmware = iwn4965_load_firmware; + ops->read_eeprom = iwn4965_read_eeprom; + ops->post_alive = iwn4965_post_alive; + ops->nic_config = iwn4965_nic_config; + ops->update_sched = iwn4965_update_sched; + ops->get_temperature = iwn4965_get_temperature; + ops->get_rssi = iwn4965_get_rssi; + ops->set_txpower = iwn4965_set_txpower; + ops->init_gains = iwn4965_init_gains; + ops->set_gains = iwn4965_set_gains; + ops->add_node = iwn4965_add_node; + ops->tx_done = iwn4965_tx_done; +#ifndef IEEE80211_NO_HT + ops->ampdu_tx_start = iwn4965_ampdu_tx_start; + ops->ampdu_tx_stop = iwn4965_ampdu_tx_stop; +#endif + sc->ntxqs = IWN4965_NTXQUEUES; + sc->ndmachnls = IWN4965_NDMACHNLS; + sc->broadcast_id = IWN4965_ID_BROADCAST; + sc->rxonsz = IWN4965_RXONSZ; + sc->schedsz = IWN4965_SCHEDSZ; + sc->fw_text_maxsz = IWN4965_FW_TEXT_MAXSZ; + sc->fw_data_maxsz = IWN4965_FW_DATA_MAXSZ; + sc->fwsz = IWN4965_FWSZ; + sc->sched_txfact_addr = IWN4965_SCHED_TXFACT; + sc->limits = &iwn4965_sensitivity_limits; + sc->fwname = "iwlwifi-4965-2.ucode"; + /* Override chains masks, ROM is known to be broken. */ + sc->txchainmask = IWN_ANT_AB; + sc->rxchainmask = IWN_ANT_ABC; + + return 0; +} + +int +iwn5000_attach(struct iwn_softc *sc, pci_product_id_t pid) +{ + struct iwn_ops *ops = &sc->ops; + + ops->load_firmware = iwn5000_load_firmware; + ops->read_eeprom = iwn5000_read_eeprom; + ops->post_alive = iwn5000_post_alive; + ops->nic_config = iwn5000_nic_config; + ops->update_sched = iwn5000_update_sched; + ops->get_temperature = iwn5000_get_temperature; + ops->get_rssi = iwn5000_get_rssi; + ops->set_txpower = iwn5000_set_txpower; + ops->init_gains = iwn5000_init_gains; + ops->set_gains = iwn5000_set_gains; + ops->add_node = iwn5000_add_node; + ops->tx_done = iwn5000_tx_done; +#ifndef IEEE80211_NO_HT + ops->ampdu_tx_start = iwn5000_ampdu_tx_start; + ops->ampdu_tx_stop = iwn5000_ampdu_tx_stop; +#endif + sc->ntxqs = IWN5000_NTXQUEUES; + sc->ndmachnls = IWN5000_NDMACHNLS; + sc->broadcast_id = IWN5000_ID_BROADCAST; + sc->rxonsz = IWN5000_RXONSZ; + sc->schedsz = IWN5000_SCHEDSZ; + sc->fw_text_maxsz = IWN5000_FW_TEXT_MAXSZ; + sc->fw_data_maxsz = IWN5000_FW_DATA_MAXSZ; + sc->fwsz = IWN5000_FWSZ; + sc->sched_txfact_addr = IWN5000_SCHED_TXFACT; switch (sc->hw_type) { - case IWN_HW_REV_TYPE_4965: - sc->sc_hal = &iwn4965_hal; - sc->limits = &iwn4965_sensitivity_limits; - sc->fwname = "iwlwifi-4965-2.ucode"; - sc->txchainmask = IWN_ANT_AB; - sc->rxchainmask = IWN_ANT_ABC; - break; case IWN_HW_REV_TYPE_5100: - sc->sc_hal = &iwn5000_hal; sc->limits = &iwn5000_sensitivity_limits; sc->fwname = "iwlwifi-5000-2.ucode"; + /* Override chains masks, ROM is known to be broken. */ sc->txchainmask = IWN_ANT_B; sc->rxchainmask = IWN_ANT_AB; break; case IWN_HW_REV_TYPE_5150: - sc->sc_hal = &iwn5000_hal; sc->limits = &iwn5150_sensitivity_limits; sc->fwname = "iwlwifi-5150-2.ucode"; - sc->txchainmask = IWN_ANT_A; - sc->rxchainmask = IWN_ANT_AB; break; case IWN_HW_REV_TYPE_5300: case IWN_HW_REV_TYPE_5350: - sc->sc_hal = &iwn5000_hal; sc->limits = &iwn5000_sensitivity_limits; sc->fwname = "iwlwifi-5000-2.ucode"; - sc->txchainmask = IWN_ANT_ABC; - sc->rxchainmask = IWN_ANT_ABC; break; case IWN_HW_REV_TYPE_1000: - sc->sc_hal = &iwn5000_hal; sc->limits = &iwn1000_sensitivity_limits; sc->fwname = "iwlwifi-1000-3.ucode"; - sc->txchainmask = IWN_ANT_A; - sc->rxchainmask = IWN_ANT_AB; break; case IWN_HW_REV_TYPE_6000: - sc->sc_hal = &iwn5000_hal; sc->limits = &iwn6000_sensitivity_limits; sc->fwname = "iwlwifi-6000-4.ucode"; - switch (pid) { - case PCI_PRODUCT_INTEL_WIFI_LINK_6000_IPA_1: - case PCI_PRODUCT_INTEL_WIFI_LINK_6000_IPA_2: + if (pid == PCI_PRODUCT_INTEL_WIFI_LINK_6000_IPA_1 || + pid == PCI_PRODUCT_INTEL_WIFI_LINK_6000_IPA_2) { sc->sc_flags |= IWN_FLAG_INTERNAL_PA; + /* Override chains masks, ROM is known to be broken. */ sc->txchainmask = IWN_ANT_BC; sc->rxchainmask = IWN_ANT_BC; - break; - default: - sc->txchainmask = IWN_ANT_ABC; - sc->rxchainmask = IWN_ANT_ABC; - break; } break; case IWN_HW_REV_TYPE_6050: - sc->sc_hal = &iwn5000_hal; sc->limits = &iwn6000_sensitivity_limits; sc->fwname = "iwlwifi-6050-2.ucode"; - sc->txchainmask = IWN_ANT_AB; - sc->rxchainmask = IWN_ANT_AB; break; case IWN_HW_REV_TYPE_6005: - sc->sc_hal = &iwn5000_hal; sc->limits = &iwn6000_sensitivity_limits; sc->fwname = "iwlwifi-6005-2.ucode"; - sc->txchainmask = IWN_ANT_AB; - sc->rxchainmask = IWN_ANT_AB; break; default: aprint_normal(": adapter type %d not supported\n", sc->hw_type); - return NULL; - } - return sc->sc_hal; -} - -#ifndef SMALL_KERNEL -/* - * Attach the adapter on-board thermal sensor to the sensors framework. - */ -static void -iwn_sensor_attach(struct iwn_softc *sc) -{ - int error; - - sc->sc_sensor.units = ENVSYS_STEMP; -#if 0 - /* XXX something like this ought to work */ - sc->sc_sensor.flags = ENVSYS_FMONLIMITS | ENVSYS_FMONNOTSUPP; - sc->sc_sensor.limits.sel_critmax = IWN_CTOK(110); -#endif - (void)strlcpy(sc->sc_sensor.desc, - "temperature", sizeof(sc->sc_sensor.desc)); - - /* Temperature is not valid unless interface is up. */ - sc->sc_sensor.value_cur = 0; - sc->sc_sensor.state = ENVSYS_SINVALID; - - sc->sc_sme = sysmon_envsys_create(); - - /* Initialize sensor */ - if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor)) { - sysmon_envsys_destroy(sc->sc_sme); - return; - } - - /* - * Hook into the System Monitor. - */ - sc->sc_sme->sme_name = device_xname(sc->sc_dev); - sc->sc_sme->sme_flags = SME_DISABLE_REFRESH; - - if ((error = sysmon_envsys_register(sc->sc_sme)) != 0) { - aprint_error_dev(sc->sc_dev, - "unable to register with sysmon (%d)\n", error); - sysmon_envsys_destroy(sc->sc_sme); - return; + return ENOTSUP; } + return 0; } -#endif /* * Attach the interface to 802.11 radiotap. @@ -834,7 +773,7 @@ /* Free DMA resources. */ iwn_free_rx_ring(sc, &sc->rxq); - for (qid = 0; qid < sc->sc_hal->ntxqs; qid++) + for (qid = 0; qid < sc->ntxqs; qid++) iwn_free_tx_ring(sc, &sc->txq[qid]); #ifdef IWN_USE_RBUF iwn_free_rpool(sc); @@ -847,12 +786,6 @@ bus_space_unmap(sc->sc_st, sc->sc_sh, sc->sc_sz); -#ifndef SMALL_KERNEL - /* Detach the thermal sensor. */ - sysmon_envsys_sensor_detach(sc->sc_sme, &sc->sc_sensor); - sysmon_envsys_destroy(sc->sc_sme); -#endif - ieee80211_ifdetach(&sc->sc_ic); if_detach(ifp); @@ -878,8 +811,8 @@ /* Clear device-specific "PCI retry timeout" register (41h). */ reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0x40); - reg &= ~0xff00; - pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, reg); + if (reg & 0xff00) + pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, reg & ~0xff00); s = splnet(); ifp = &sc->sc_ic.ic_if; @@ -1194,7 +1127,7 @@ { /* TX scheduler rings must be aligned on a 1KB boundary. */ return iwn_dma_contig_alloc(sc->sc_dmat, &sc->sched_dma, - (void **)&sc->sched, sc->sc_hal->schedsz, 1024); + (void **)&sc->sched, sc->schedsz, 1024); } static void @@ -1236,7 +1169,7 @@ { /* Must be aligned on a 16-byte boundary. */ return iwn_dma_contig_alloc(sc->sc_dmat, &sc->fw_dma, NULL, - sc->sc_hal->fwsz, 16); + sc->fwsz, 16); } static void @@ -1253,7 +1186,7 @@ ring->cur = 0; - /* Allocate RX descriptors (256-byte aligned.) */ + /* Allocate RX descriptors (256-byte aligned). */ size = IWN_RX_RING_COUNT * sizeof (uint32_t); error = iwn_dma_contig_alloc(sc->sc_dmat, &ring->desc_dma, (void **)&ring->desc, size, 256); @@ -1263,7 +1196,7 @@ goto fail; } - /* Allocate RX status area (16-byte aligned.) */ + /* Allocate RX status area (16-byte aligned). */ error = iwn_dma_contig_alloc(sc->sc_dmat, &ring->stat_dma, (void **)&ring->stat, sizeof (struct iwn_rx_status), 16); if (error != 0) { @@ -1304,7 +1237,7 @@ goto fail; } - /* Set physical address of RX buffer (256-byte aligned.) */ + /* Set physical address of RX buffer (256-byte aligned). */ ring->desc[i] = htole32(data->map->dm_segs[0].ds_addr >> 8); } @@ -1369,7 +1302,7 @@ ring->queued = 0; ring->cur = 0; - /* Allocate TX descriptors (256-byte aligned.) */ + /* Allocate TX descriptors (256-byte aligned). */ size = IWN_TX_RING_COUNT * sizeof (struct iwn_tx_desc); error = iwn_dma_contig_alloc(sc->sc_dmat, &ring->desc_dma, (void **)&ring->desc, size, 256); @@ -1475,7 +1408,7 @@ memset(sc->ict, 0, IWN_ICT_SIZE); sc->ict_cur = 0; - /* Set physical address of ICT table (4KB aligned.) */ + /* Set physical address of ICT table (4KB aligned). */ DPRINTF(("enabling ICT\n")); IWN_WRITE(sc, IWN_DRAM_INT_TBL, IWN_DRAM_INT_TBL_ENABLE | IWN_DRAM_INT_TBL_WRAP_CHECK | sc->ict_dma.paddr >> 12); @@ -1493,7 +1426,7 @@ static int iwn_read_eeprom(struct iwn_softc *sc) { - const struct iwn_hal *hal = sc->sc_hal; + struct iwn_ops *ops = &sc->ops; struct ieee80211com *ic = &sc->sc_ic; uint16_t val; int error; @@ -1530,15 +1463,26 @@ } } + iwn_read_prom_data(sc, IWN_EEPROM_SKU_CAP, &val, 2); + DPRINTF(("SKU capabilities=0x%04x\n", le16toh(val))); + /* Check if HT support is bonded out. */ + if (val & htole16(IWN_EEPROM_SKU_CAP_11N)) + sc->sc_flags |= IWN_FLAG_HAS_11N; + iwn_read_prom_data(sc, IWN_EEPROM_RFCFG, &val, 2); sc->rfcfg = le16toh(val); DPRINTF(("radio config=0x%04x\n", sc->rfcfg)); + /* Read Tx/Rx chains from ROM unless it's known to be broken. */ + if (sc->txchainmask == 0) + sc->txchainmask = IWN_RFCFG_TXANTMSK(sc->rfcfg); + if (sc->rxchainmask == 0) + sc->rxchainmask = IWN_RFCFG_RXANTMSK(sc->rfcfg); /* Read MAC address. */ iwn_read_prom_data(sc, IWN_EEPROM_MAC, ic->ic_myaddr, 6); /* Read adapter-specific information from EEPROM. */ - hal->read_eeprom(sc); + ops->read_eeprom(sc); iwn_apm_stop(sc); /* Power OFF adapter. */ @@ -1553,10 +1497,10 @@ uint16_t val; int i; - /* Read regulatory domain (4 ASCII characters.) */ + /* Read regulatory domain (4 ASCII characters). */ iwn_read_prom_data(sc, IWN4965_EEPROM_DOMAIN, sc->eeprom_domain, 4); - /* Read the list of authorized channels (20MHz ones only.) */ + /* Read the list of authorized channels (20MHz ones only). */ for (i = 0; i < 5; i++) { addr = iwn4965_regulatory_bands[i]; iwn_read_eeprom_channels(sc, i, addr); @@ -1630,18 +1574,18 @@ iwn5000_read_eeprom(struct iwn_softc *sc) { struct iwn5000_eeprom_calib_hdr hdr; - int32_t temp, volt; + int32_t volt; uint32_t base, addr; uint16_t val; int i; - /* Read regulatory domain (4 ASCII characters.) */ + /* Read regulatory domain (4 ASCII characters). */ iwn_read_prom_data(sc, IWN5000_EEPROM_REG, &val, 2); base = le16toh(val); iwn_read_prom_data(sc, base + IWN5000_EEPROM_DOMAIN, sc->eeprom_domain, 4); - /* Read the list of authorized channels (20MHz ones only.) */ + /* Read the list of authorized channels (20MHz ones only). */ for (i = 0; i < 5; i++) { addr = base + iwn5000_regulatory_bands[i]; iwn_read_eeprom_channels(sc, i, addr); @@ -1661,12 +1605,12 @@ if (sc->hw_type == IWN_HW_REV_TYPE_5150) { /* Compute temperature offset. */ iwn_read_prom_data(sc, base + IWN5000_EEPROM_TEMP, &val, 2); - temp = le16toh(val); + sc->eeprom_temp = le16toh(val); iwn_read_prom_data(sc, base + IWN5000_EEPROM_VOLT, &val, 2); volt = le16toh(val); - sc->temp_off = temp - (volt / -5); + sc->temp_off = sc->eeprom_temp - (volt / -5); DPRINTF(("temp=%d volt=%d offset=%dK\n", - temp, volt, sc->temp_off)); + sc->eeprom_temp, volt, sc->temp_off)); } else { /* Read crystal calibration. */ iwn_read_prom_data(sc, base + IWN5000_EEPROM_CRYSTAL, @@ -1961,7 +1905,7 @@ iwn_rx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, struct iwn_rx_data *data) { - const struct iwn_hal *hal = sc->sc_hal; + struct iwn_ops *ops = &sc->ops; struct ieee80211com *ic = &sc->sc_ic; struct ifnet *ifp = ic->ic_ifp; struct iwn_rx_ring *ring = &sc->rxq; @@ -1977,7 +1921,6 @@ /* Check for prior RX_PHY notification. */ if (!sc->last_rx_valid) { DPRINTF(("missing RX_PHY\n")); - ifp->if_ierrors++; return; } sc->last_rx_valid = 0; @@ -1991,7 +1934,6 @@ if (stat->cfg_phy_len > IWN_STAT_MAXLEN) { aprint_error_dev(sc->sc_dev, "invalid RX statistic header\n"); - ifp->if_ierrors++; return; } if (desc->type == IWN_MPDU_RX_DONE) { @@ -2070,7 +2012,7 @@ /* XXX OpenBSD adds decryption here (see also comments in iwn_tx). */ /* NetBSD does decryption in ieee80211_input. */ - rssi = hal->get_rssi(stat); + rssi = ops->get_rssi(stat); /* XXX Added for NetBSD: scans never stop without it */ if (ic->ic_state == IEEE80211_S_SCAN) @@ -2137,7 +2079,7 @@ /* * Process a CALIBRATION_RESULT notification sent by the initialization - * firmware on response to a CMD_CALIB_CONFIG command (5000 only.) + * firmware on response to a CMD_CALIB_CONFIG command (5000 only). */ static void iwn5000_rx_calib_results(struct iwn_softc *sc, struct iwn_rx_desc *desc, @@ -2156,8 +2098,7 @@ switch (calib->code) { case IWN5000_PHY_CALIB_DC: - if (sc->hw_type == IWN_HW_REV_TYPE_5150 || - sc->hw_type == IWN_HW_REV_TYPE_6050) + if (sc->hw_type == IWN_HW_REV_TYPE_5150) idx = 0; break; case IWN5000_PHY_CALIB_LO: @@ -2201,7 +2142,7 @@ iwn_rx_statistics(struct iwn_softc *sc, struct iwn_rx_desc *desc, struct iwn_rx_data *data) { - const struct iwn_hal *hal = sc->sc_hal; + struct iwn_ops *ops = &sc->ops; struct ieee80211com *ic = &sc->sc_ic; struct iwn_calib_state *calib = &sc->calib; struct iwn_stats *stats = (struct iwn_stats *)(desc + 1); @@ -2221,16 +2162,10 @@ if (stats->general.temp != sc->rawtemp) { /* Convert "raw" temperature to degC. */ sc->rawtemp = stats->general.temp; - temp = hal->get_temperature(sc); + temp = ops->get_temperature(sc); DPRINTFN(2, ("temperature=%dC\n", temp)); -#ifndef SMALL_KERNEL - /* Update temperature sensor. */ - sc->sc_sensor.value_cur = IWN_CTOMUK(temp); - sc->sc_sensor.state = ENVSYS_SVALID; -#endif - - /* Update TX power if need be (4965AGN only.) */ + /* Update TX power if need be (4965AGN only). */ if (sc->hw_type == IWN_HW_REV_TYPE_4965) iwn4965_power_calibration(sc, temp); } @@ -2357,6 +2292,7 @@ static void iwn_notif_intr(struct iwn_softc *sc) { + struct iwn_ops *ops = &sc->ops; struct ieee80211com *ic = &sc->sc_ic; struct ifnet *ifp = ic->ic_ifp; uint16_t hw; @@ -2397,7 +2333,7 @@ #endif case IWN_TX_DONE: /* An 802.11 frame has been transmitted. */ - sc->sc_hal->tx_done(sc, desc, data); + ops->tx_done(sc, desc, data); break; case IWN_RX_STATISTICS: @@ -2537,7 +2473,7 @@ /* Wakeup RX and TX rings. */ IWN_WRITE(sc, IWN_FH_RX_WPTR, sc->rxq.cur & ~7); - for (qid = 0; qid < sc->sc_hal->ntxqs; qid++) { + for (qid = 0; qid < sc->ntxqs; qid++) { struct iwn_tx_ring *ring = &sc->txq[qid]; IWN_WRITE(sc, IWN_HBUS_TARG_WRPTR, qid << 8 | ring->cur); } @@ -2551,7 +2487,6 @@ static void iwn_fatal_intr(struct iwn_softc *sc) { - const struct iwn_hal *hal = sc->sc_hal; struct iwn_fw_dump dump; int i; @@ -2561,7 +2496,7 @@ /* Check that the error log address is valid. */ if (sc->errptr < IWN_FW_DATA_BASE || sc->errptr + sizeof (dump) > - IWN_FW_DATA_BASE + hal->fw_data_maxsz) { + IWN_FW_DATA_BASE + sc->fw_data_maxsz) { aprint_error_dev(sc->sc_dev, "bad firmware error log address 0x%08x\n", sc->errptr); return; @@ -2598,7 +2533,7 @@ /* Dump driver status (TX and RX rings) while we're here. */ aprint_error("driver status:\n"); - for (i = 0; i < hal->ntxqs; i++) { + for (i = 0; i < sc->ntxqs; i++) { struct iwn_tx_ring *ring = &sc->txq[i]; aprint_error(" tx ring %2d: qid=%-2d cur=%-3d queued=%-3d\n", i, ring->qid, ring->cur, ring->queued); @@ -2705,7 +2640,7 @@ /* * Update TX scheduler ring when transmitting an 802.11 frame (4965AGN and - * 5000 adapters use a slightly different format.) + * 5000 adapters use a slightly different format). */ static void iwn4965_update_sched(struct iwn_softc *sc, int qid, int idx, uint8_t id, @@ -2769,7 +2704,6 @@ static int iwn_tx(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni, int ac) { - const struct iwn_hal *hal = sc->sc_hal; struct ieee80211com *ic = &sc->sc_ic; struct iwn_node *wn = (void *)ni; struct iwn_tx_ring *ring; @@ -2912,7 +2846,7 @@ if (IEEE80211_IS_MULTICAST(wh->i_addr1) || type != IEEE80211_FC0_TYPE_DATA) - tx->id = hal->broadcast_id; + tx->id = sc->broadcast_id; else tx->id = wn->id; @@ -2937,7 +2871,7 @@ tx->timeout = htole16(0); if (hdrlen & 3) { - /* First segment's length must be a multiple of 4. */ + /* First segment length must be a multiple of 4. */ flags |= IWN_TX_NEED_PADDING; pad = 4 - (hdrlen & 3); } else @@ -2950,7 +2884,7 @@ tx->lifetime = htole32(IWN_LIFETIME_INFINITE); tx->plcp = rinfo->plcp; tx->rflags = rinfo->flags; - if (tx->id == hal->broadcast_id) { + if (tx->id == sc->broadcast_id) { /* Group or management frame. */ tx->linkq = 0; /* XXX Alternate between antenna A and B? */ @@ -3043,7 +2977,7 @@ #ifdef notyet /* Update TX scheduler. */ - hal->update_sched(sc, ring->qid, ring->cur, tx->id, totlen); + ops->update_sched(sc, ring->qid, ring->cur, tx->id, totlen); #endif /* Kick TX ring. */ @@ -3287,7 +3221,7 @@ #ifdef notyet /* Update TX scheduler. */ - sc->sc_hal->update_sched(sc, ring->qid, ring->cur, 0, 0); + ops->update_sched(sc, ring->qid, ring->cur, 0, 0); #endif DPRINTFN(4, ("iwn_cmd %d size=%d %s\n", code, size, async ? " (async)" : "")); @@ -3365,7 +3299,7 @@ static int iwn_add_broadcast_node(struct iwn_softc *sc, int async) { - const struct iwn_hal *hal = sc->sc_hal; + struct iwn_ops *ops = &sc->ops; struct iwn_node_info node; struct iwn_cmd_link_quality linkq; const struct iwn_rate *rinfo; @@ -3374,16 +3308,16 @@ memset(&node, 0, sizeof node); IEEE80211_ADDR_COPY(node.macaddr, etherbroadcastaddr); - node.id = hal->broadcast_id; + node.id = sc->broadcast_id; DPRINTF(("adding broadcast node\n")); - if ((error = hal->add_node(sc, &node, async)) != 0) + if ((error = ops->add_node(sc, &node, async)) != 0) return error; /* Use the first valid TX antenna. */ txant = IWN_LSB(sc->txchainmask); memset(&linkq, 0, sizeof linkq); - linkq.id = hal->broadcast_id; + linkq.id = sc->broadcast_id; linkq.antmsk_1stream = txant; linkq.antmsk_2stream = IWN_ANT_AB; linkq.ampdu_max = 64; @@ -3459,7 +3393,7 @@ mod = le64toh(cmd.tstamp) % val; cmd.binitval = htole32((uint32_t)(val - mod)); - DPRINTF(("timing bintval=%u, tstamp=%zu, init=%u\n", + DPRINTF(("timing bintval=%u, tstamp=%" PRIu64 ", init=%" PRIu32 "\n", ni->ni_intval, le64toh(cmd.tstamp), (uint32_t)(val - mod))); return iwn_cmd(sc, IWN_CMD_TIMING, &cmd, sizeof cmd, 1); @@ -3468,7 +3402,7 @@ static void iwn4965_power_calibration(struct iwn_softc *sc, int temp) { - /* Adjust TX power if need be (delta >= 3 degC.) */ + /* Adjust TX power if need be (delta >= 3 degC). */ DPRINTF(("temperature %d->%d\n", sc->temp, temp)); if (abs(temp - sc->temp) >= 3) { /* Record temperature of last calibration. */ @@ -3716,11 +3650,11 @@ r3 = le32toh(uc->temp[2].chan20MHz); r4 = le32toh(sc->rawtemp); - if (r1 == r3) /* Prevents division by 0 (should not happen.) */ + if (r1 == r3) /* Prevents division by 0 (should not happen). */ return 0; /* Sign-extend 23-bit R4 value to 32-bit. */ - r4 = (r4 << 8) >> 8; + r4 = ((r4 & 0xffffff) ^ 0x800000) - 0x800000; /* Compute temperature in Kelvin. */ temp = (259 * (r4 - r2)) / (r3 - r1); temp = (temp * 97) / 100 + 8; @@ -3753,7 +3687,7 @@ static int iwn_init_sensitivity(struct iwn_softc *sc) { - const struct iwn_hal *hal = sc->sc_hal; + struct iwn_ops *ops = &sc->ops; struct iwn_calib_state *calib = &sc->calib; uint32_t flags; int error; @@ -3776,7 +3710,7 @@ return error; /* Write initial gains. */ - if ((error = hal->init_gains(sc)) != 0) + if ((error = ops->init_gains(sc)) != 0) return error; /* Request statistics at each beacon interval. */ @@ -3794,7 +3728,7 @@ iwn_collect_noise(struct iwn_softc *sc, const struct iwn_rx_general_stats *stats) { - const struct iwn_hal *hal = sc->sc_hal; + struct iwn_ops *ops = &sc->ops; struct iwn_calib_state *calib = &sc->calib; uint32_t val; int i; @@ -3824,13 +3758,13 @@ if ((sc->chainmask & sc->txchainmask) == 0) sc->chainmask |= IWN_LSB(sc->txchainmask); - (void)hal->set_gains(sc); + (void)ops->set_gains(sc); calib->state = IWN_CALIB_STATE_RUN; #ifdef notyet /* XXX Disable RX chains with no antennas connected. */ sc->rxon.rxchain = htole16(IWN_RXCHAIN_SEL(sc->chainmask)); - (void)iwn_cmd(sc, IWN_CMD_RXON, &sc->rxon, hal->rxonsz, 1); + (void)iwn_cmd(sc, IWN_CMD_RXON, &sc->rxon, sc->rxonsz, 1); #endif /* Enable power-saving mode if requested by user. */ @@ -4166,7 +4100,7 @@ static int iwn_config(struct iwn_softc *sc) { - const struct iwn_hal *hal = sc->sc_hal; + struct iwn_ops *ops = &sc->ops; struct ieee80211com *ic = &sc->sc_ic; struct ifnet *ifp = ic->ic_ifp; struct iwn_bluetooth bluetooth; @@ -4234,7 +4168,7 @@ IWN_RXCHAIN_IDLE_COUNT(2); sc->rxon.rxchain = htole16(rxchain); DPRINTF(("setting configuration\n")); - error = iwn_cmd(sc, IWN_CMD_RXON, &sc->rxon, hal->rxonsz, 0); + error = iwn_cmd(sc, IWN_CMD_RXON, &sc->rxon, sc->rxonsz, 0); if (error != 0) { aprint_error_dev(sc->sc_dev, "RXON command failed\n"); @@ -4248,7 +4182,7 @@ } /* Configuration has changed, set TX power accordingly. */ - if ((error = hal->set_txpower(sc, 0)) != 0) { + if ((error = ops->set_txpower(sc, 0)) != 0) { aprint_error_dev(sc->sc_dev, "could not set TX power\n"); return error; @@ -4315,7 +4249,7 @@ tx = (struct iwn_cmd_data *)(hdr + 1); tx->flags = htole32(IWN_TX_AUTO_SEQ); - tx->id = sc->sc_hal->broadcast_id; + tx->id = sc->broadcast_id; tx->lifetime = htole32(IWN_LIFETIME_INFINITE); if (flags & IEEE80211_CHAN_5GHZ) { @@ -4406,7 +4340,7 @@ static int iwn_auth(struct iwn_softc *sc) { - const struct iwn_hal *hal = sc->sc_hal; + struct iwn_ops *ops = &sc->ops; struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_node *ni = ic->ic_bss; int error; @@ -4436,7 +4370,7 @@ } DPRINTF(("rxon chan %d flags %x cck %x ofdm %x\n", sc->rxon.chan, sc->rxon.flags, sc->rxon.cck_mask, sc->rxon.ofdm_mask)); - error = iwn_cmd(sc, IWN_CMD_RXON, &sc->rxon, hal->rxonsz, 1); + error = iwn_cmd(sc, IWN_CMD_RXON, &sc->rxon, sc->rxonsz, 1); if (error != 0) { aprint_error_dev(sc->sc_dev, "RXON command failed\n"); @@ -4444,7 +4378,7 @@ } /* Configuration has changed, set TX power accordingly. */ - if ((error = hal->set_txpower(sc, 1)) != 0) { + if ((error = ops->set_txpower(sc, 1)) != 0) { aprint_error_dev(sc->sc_dev, "could not set TX power\n"); return error; @@ -4464,7 +4398,7 @@ static int iwn_run(struct iwn_softc *sc) { - const struct iwn_hal *hal = sc->sc_hal; + struct iwn_ops *ops = &sc->ops; struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_node *ni = ic->ic_bss; struct iwn_node_info node; @@ -4491,7 +4425,7 @@ sc->rxon.flags |= htole32(IWN_RXON_SHPREAMBLE); sc->rxon.filter |= htole32(IWN_FILTER_BSS); DPRINTF(("rxon chan %d flags %x\n", sc->rxon.chan, sc->rxon.flags)); - error = iwn_cmd(sc, IWN_CMD_RXON, &sc->rxon, hal->rxonsz, 1); + error = iwn_cmd(sc, IWN_CMD_RXON, &sc->rxon, sc->rxonsz, 1); if (error != 0) { aprint_error_dev(sc->sc_dev, "could not update configuration\n"); @@ -4499,7 +4433,7 @@ } /* Configuration has changed, set TX power accordingly. */ - if ((error = hal->set_txpower(sc, 1)) != 0) { + if ((error = ops->set_txpower(sc, 1)) != 0) { aprint_error_dev(sc->sc_dev, "could not set TX power\n"); return error; @@ -4518,7 +4452,7 @@ IWN_AMDPU_DENSITY(5)); /* 2us */ #endif DPRINTF(("adding BSS node\n")); - error = hal->add_node(sc, &node, 1); + error = ops->add_node(sc, &node, 1); if (error != 0) { aprint_error_dev(sc->sc_dev, "could not add BSS node\n"); @@ -4556,7 +4490,7 @@ struct ieee80211_key *k) { struct iwn_softc *sc = ic->ic_softc; - const struct iwn_hal *hal = sc->sc_hal; + struct iwn_ops *ops = &sc->ops; struct iwn_node *wn = (void *)ni; struct iwn_node_info node; uint16_t kflags; @@ -4571,14 +4505,14 @@ memset(&node, 0, sizeof node); node.id = (k->k_flags & IEEE80211_KEY_GROUP) ? - hal->broadcast_id : wn->id; + sc->broadcast_id : wn->id; node.control = IWN_NODE_UPDATE; node.flags = IWN_FLAG_SET_KEY; node.kflags = htole16(kflags); node.kid = k->k_id; memcpy(node.key, k->k_key, k->k_len); DPRINTF(("set key id=%d for node %d\n", k->k_id, node.id)); - return hal->add_node(sc, &node, 1); + return ops->add_node(sc, &node, 1); } static void @@ -4586,7 +4520,7 @@ struct ieee80211_key *k) { struct iwn_softc *sc = ic->ic_softc; - const struct iwn_hal *hal = sc->sc_hal; + struct iwn_ops *ops = &sc->ops; struct iwn_node *wn = (void *)ni; struct iwn_node_info node; @@ -4600,13 +4534,13 @@ return; /* Nothing to do. */ memset(&node, 0, sizeof node); node.id = (k->k_flags & IEEE80211_KEY_GROUP) ? - hal->broadcast_id : wn->id; + sc->broadcast_id : wn->id; node.control = IWN_NODE_UPDATE; node.flags = IWN_FLAG_SET_KEY; node.kflags = htole16(IWN_KFLAG_INVALID); node.kid = 0xff; DPRINTF(("delete keys for node %d\n", node.id)); - (void)hal->add_node(sc, &node, 1); + (void)ops->add_node(sc, &node, 1); } #endif @@ -4654,6 +4588,7 @@ { struct ieee80211_rx_ba *ba = &ni->ni_rx_ba[tid]; struct iwn_softc *sc = ic->ic_softc; + struct iwn_ops *ops = &sc->ops; struct iwn_node *wn = (void *)ni; struct iwn_node_info node; @@ -4665,18 +4600,19 @@ node.addba_ssn = htole16(ba->ba_winstart); DPRINTFN(2, ("ADDBA RA=%d TID=%d SSN=%d\n", wn->id, tid, ba->ba_winstart)); - return sc->sc_hal->add_node(sc, &node, 1); + return ops->add_node(sc, &node, 1); } /* * This function is called by upper layer on teardown of an HT-immediate - * Block Ack agreement (eg. uppon receipt of a DELBA frame.) + * Block Ack agreement (eg. uppon receipt of a DELBA frame). */ static void iwn_ampdu_rx_stop(struct ieee80211com *ic, struct ieee80211_node *ni, uint8_t tid) { struct iwn_softc *sc = ic->ic_softc; + struct iwn_ops *ops = &sc->ops; struct iwn_node *wn = (void *)ni; struct iwn_node_info node; @@ -4686,7 +4622,7 @@ node.flags = IWN_FLAG_SET_DELBA; node.delba_tid = tid; DPRINTFN(2, ("DELBA RA=%d TID=%d\n", wn->id, tid)); - (void)sc->sc_hal->add_node(sc, &node, 1); + (void)ops->add_node(sc, &node, 1); } /* @@ -4699,7 +4635,7 @@ { struct ieee80211_tx_ba *ba = &ni->ni_tx_ba[tid]; struct iwn_softc *sc = ic->ic_softc; - const struct iwn_hal *hal = sc->sc_hal; + struct iwn_ops *ops = &sc->ops; struct iwn_node *wn = (void *)ni; struct iwn_node_info node; int error; @@ -4711,13 +4647,13 @@ node.control = IWN_NODE_UPDATE; node.flags = IWN_FLAG_SET_DISABLE_TID; node.disable_tid = htole16(wn->disable_tid); - error = hal->add_node(sc, &node, 1); + error = ops->add_node(sc, &node, 1); if (error != 0) return error; if ((error = iwn_nic_lock(sc)) != 0) return error; - hal->ampdu_tx_start(sc, ni, tid, ba->ba_winstart); + ops->ampdu_tx_start(sc, ni, tid, ba->ba_winstart); iwn_nic_unlock(sc); return 0; } @@ -4728,10 +4664,11 @@ { struct ieee80211_tx_ba *ba = &ni->ni_tx_ba[tid]; struct iwn_softc *sc = ic->ic_softc; + struct iwn_ops *ops = &sc->ops; if (iwn_nic_lock(sc) != 0) return; - sc->sc_hal->ampdu_tx_stop(sc, tid, ba->ba_winstart); + ops->ampdu_tx_stop(sc, tid, ba->ba_winstart); iwn_nic_unlock(sc); } @@ -4935,7 +4872,7 @@ /* * This function is called after the runtime firmware notifies us of its - * readiness (called in a process context.) + * readiness (called in a process context). */ static int iwn4965_post_alive(struct iwn_softc *sc) @@ -4950,7 +4887,7 @@ iwn_mem_set_region_4(sc, sc->sched_base + IWN4965_SCHED_CTX_OFF, 0, IWN4965_SCHED_CTX_LEN / sizeof (uint32_t)); - /* Set physical address of TX scheduler rings (1KB aligned.) */ + /* Set physical address of TX scheduler rings (1KB aligned). */ iwn_prph_write(sc, IWN4965_SCHED_DRAM_ADDR, sc->sched_dma.paddr >> 10); IWN_SETBITS(sc, IWN_FH_TX_CHICKEN, IWN_FH_TX_CHICKEN_SCHED_RETRY); @@ -4988,7 +4925,7 @@ /* * This function is called after the initialization or runtime firmware - * notifies us of its readiness (called in a process context.) + * notifies us of its readiness (called in a process context). */ static int iwn5000_post_alive(struct iwn_softc *sc) @@ -5006,7 +4943,7 @@ iwn_mem_set_region_4(sc, sc->sched_base + IWN5000_SCHED_CTX_OFF, 0, IWN5000_SCHED_CTX_LEN / sizeof (uint32_t)); - /* Set physical address of TX scheduler rings (1KB aligned.) */ + /* Set physical address of TX scheduler rings (1KB aligned). */ iwn_prph_write(sc, IWN5000_SCHED_DRAM_ADDR, sc->sched_dma.paddr >> 10); IWN_SETBITS(sc, IWN_FH_TX_CHICKEN, IWN_FH_TX_CHICKEN_SCHED_RETRY); @@ -5088,7 +5025,7 @@ /* * The firmware boot code is small and is intended to be copied directly into - * the NIC internal memory (no DMA transfer.) + * the NIC internal memory (no DMA transfer). */ static int iwn4965_load_bootcode(struct iwn_softc *sc, const uint8_t *ucode, int size) @@ -5410,7 +5347,6 @@ static int iwn_read_firmware(struct iwn_softc *sc) { - const struct iwn_hal *hal = sc->sc_hal; struct iwn_fw_info *fw = &sc->fw; firmware_handle_t fwh; int error; @@ -5461,10 +5397,10 @@ } /* Make sure text and data sections fit in hardware memory. */ - if (fw->main.textsz > hal->fw_text_maxsz || - fw->main.datasz > hal->fw_data_maxsz || - fw->init.textsz > hal->fw_text_maxsz || - fw->init.datasz > hal->fw_data_maxsz || + if (fw->main.textsz > sc->fw_text_maxsz || + fw->main.datasz > sc->fw_data_maxsz || + fw->init.textsz > sc->fw_text_maxsz || + fw->init.datasz > sc->fw_data_maxsz || fw->boot.textsz > IWN_FW_BOOT_TEXT_MAXSZ || (fw->boot.textsz & 3) != 0) { aprint_error_dev(sc->sc_dev, @@ -5506,12 +5442,12 @@ pcireg_t reg; int error; - /* Disable L0s exit timer (NMI bug workaround.) */ + /* Disable L0s exit timer (NMI bug workaround). */ IWN_SETBITS(sc, IWN_GIO_CHICKEN, IWN_GIO_CHICKEN_DIS_L0S_TIMER); - /* Don't wait for ICH L0s (ICH bug workaround.) */ + /* Don't wait for ICH L0s (ICH bug workaround). */ IWN_SETBITS(sc, IWN_GIO_CHICKEN, IWN_GIO_CHICKEN_L1A_NO_L0S_RX); - /* Set FH wait threshold to max (HW bug under stress workaround.) */ + /* Set FH wait threshold to max (HW bug under stress workaround). */ IWN_SETBITS(sc, IWN_DBG_HPET_MEM, 0xffff0000); /* Enable HAP INTA to move adapter from L1a to L0s. */ @@ -5537,7 +5473,7 @@ if ((error = iwn_nic_lock(sc)) != 0) return error; if (sc->hw_type == IWN_HW_REV_TYPE_4965) { - /* Enable DMA and BSM (Bootstrap State Machine.) */ + /* Enable DMA and BSM (Bootstrap State Machine). */ iwn_prph_write(sc, IWN_APMG_CLK_EN, IWN_APMG_CLK_CTRL_DMA_CLK_RQT | IWN_APMG_CLK_CTRL_BSM_CLK_RQT); @@ -5637,10 +5573,13 @@ /* Use internal power amplifier only. */ IWN_WRITE(sc, IWN_GP_DRIVER, IWN_GP_DRIVER_RADIO_2X2_IPA); } - if (sc->hw_type == IWN_HW_REV_TYPE_6050 && sc->calib_ver >= 6) { + if ((sc->hw_type == IWN_HW_REV_TYPE_6050 || + sc->hw_type == IWN_HW_REV_TYPE_6005) && sc->calib_ver >= 6) { /* Indicate that ROM calibration version is >=6. */ IWN_SETBITS(sc, IWN_GP_DRIVER, IWN_GP_DRIVER_CALIB_VER6); } + if (sc->hw_type == IWN_HW_REV_TYPE_6005) + IWN_SETBITS(sc, IWN_GP_DRIVER, IWN_GP_DRIVER_6050_1X2); return 0; } @@ -5686,7 +5625,7 @@ static int iwn_hw_init(struct iwn_softc *sc) { - const struct iwn_hal *hal = sc->sc_hal; + struct iwn_ops *ops = &sc->ops; int error, chnl, qid; /* Clear pending interrupts. */ @@ -5705,7 +5644,7 @@ iwn_nic_unlock(sc); /* Perform adapter-specific initialization. */ - if ((error = hal->nic_config(sc)) != 0) + if ((error = ops->nic_config(sc)) != 0) return error; /* Initialize RX ring. */ @@ -5713,9 +5652,9 @@ return error; IWN_WRITE(sc, IWN_FH_RX_CONFIG, 0); IWN_WRITE(sc, IWN_FH_RX_WPTR, 0); - /* Set physical address of RX ring (256-byte aligned.) */ + /* Set physical address of RX ring (256-byte aligned). */ IWN_WRITE(sc, IWN_FH_RX_BASE, sc->rxq.desc_dma.paddr >> 8); - /* Set physical address of RX status (16-byte aligned.) */ + /* Set physical address of RX status (16-byte aligned). */ IWN_WRITE(sc, IWN_FH_STATUS_WPTR, sc->rxq.stat_dma.paddr >> 4); /* Enable RX. */ IWN_WRITE(sc, IWN_FH_RX_CONFIG, @@ -5732,23 +5671,23 @@ return error; /* Initialize TX scheduler. */ - iwn_prph_write(sc, hal->sched_txfact_addr, 0); + iwn_prph_write(sc, sc->sched_txfact_addr, 0); - /* Set physical address of "keep warm" page (16-byte aligned.) */ + /* Set physical address of "keep warm" page (16-byte aligned). */ IWN_WRITE(sc, IWN_FH_KW_ADDR, sc->kw_dma.paddr >> 4); /* Initialize TX rings. */ - for (qid = 0; qid < hal->ntxqs; qid++) { + for (qid = 0; qid < sc->ntxqs; qid++) { struct iwn_tx_ring *txq = &sc->txq[qid]; - /* Set physical address of TX ring (256-byte aligned.) */ + /* Set physical address of TX ring (256-byte aligned). */ IWN_WRITE(sc, IWN_FH_CBBC_QUEUE(qid), txq->desc_dma.paddr >> 8); } iwn_nic_unlock(sc); /* Enable DMA channels. */ - for (chnl = 0; chnl < hal->ndmachnls; chnl++) { + for (chnl = 0; chnl < sc->ndmachnls; chnl++) { IWN_WRITE(sc, IWN_FH_TX_CONFIG(chnl), IWN_FH_TX_CONFIG_DMA_ENA | IWN_FH_TX_CONFIG_DMA_CREDIT_ENA); @@ -5769,7 +5708,11 @@ IWN_WRITE(sc, IWN_UCODE_GP1_CLR, IWN_UCODE_GP1_RFKILL); IWN_WRITE(sc, IWN_UCODE_GP1_CLR, IWN_UCODE_GP1_RFKILL); - if ((error = hal->load_firmware(sc)) != 0) { + /* Enable shadow registers. */ + if (sc->hw_type >= IWN_HW_REV_TYPE_6000) + IWN_SETBITS(sc, IWN_SHADOW_REG_CTRL, 0x800fffff); + + if ((error = ops->load_firmware(sc)) != 0) { aprint_error_dev(sc->sc_dev, "could not load firmware\n"); return error; @@ -5781,15 +5724,13 @@ return error; } /* Do post-firmware initialization. */ - return hal->post_alive(sc); + return ops->post_alive(sc); } static void iwn_hw_stop(struct iwn_softc *sc) { - const struct iwn_hal *hal = sc->sc_hal; int chnl, qid, ntries; - uint32_t tmp; IWN_WRITE(sc, IWN_RESET, IWN_RESET_NEVO); @@ -5803,15 +5744,14 @@ iwn_nic_unlock(sc); /* Stop TX scheduler. */ - iwn_prph_write(sc, hal->sched_txfact_addr, 0); + iwn_prph_write(sc, sc->sched_txfact_addr, 0); /* Stop all DMA channels. */ if (iwn_nic_lock(sc) == 0) { - for (chnl = 0; chnl < hal->ndmachnls; chnl++) { + for (chnl = 0; chnl < sc->ndmachnls; chnl++) { IWN_WRITE(sc, IWN_FH_TX_CONFIG(chnl), 0); for (ntries = 0; ntries < 200; ntries++) { - tmp = IWN_READ(sc, IWN_FH_TX_STATUS); - if ((tmp & IWN_FH_TX_STATUS_IDLE(chnl)) == + if (IWN_READ(sc, IWN_FH_TX_STATUS) & IWN_FH_TX_STATUS_IDLE(chnl)) break; DELAY(10); @@ -5824,7 +5764,7 @@ iwn_reset_rx_ring(sc, &sc->rxq); /* Reset all TX rings. */ - for (qid = 0; qid < hal->ntxqs; qid++) + for (qid = 0; qid < sc->ntxqs; qid++) iwn_reset_tx_ring(sc, &sc->txq[qid]); if (iwn_nic_lock(sc) == 0) { @@ -5926,11 +5866,6 @@ /* Power OFF hardware. */ iwn_hw_stop(sc); -#ifndef SMALL_KERNEL - /* Temperature sensor is no longer valid. */ - sc->sc_sensor.value_cur = 0; - sc->sc_sensor.state = ENVSYS_SINVALID; -#endif if (!disable) mutex_exit(&sc->sc_mtx); } Index: src/sys/dev/pci/if_iwnreg.h diff -u src/sys/dev/pci/if_iwnreg.h:1.8 src/sys/dev/pci/if_iwnreg.h:1.9 --- src/sys/dev/pci/if_iwnreg.h:1.8 Fri Jun 18 17:10:23 2010 +++ src/sys/dev/pci/if_iwnreg.h Sun May 15 09:56:20 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: if_iwnreg.h,v 1.8 2010/06/18 21:10:23 christos Exp $ */ +/* $NetBSD: if_iwnreg.h,v 1.9 2011/05/15 13:56:20 christos Exp $ */ /* $OpenBSD: if_iwnreg.h,v 1.40 2010/05/05 19:41:57 damien Exp $ */ /*- @@ -77,6 +77,7 @@ #define IWN_UCODE_GP1_CLR 0x05c #define IWN_LED 0x094 #define IWN_DRAM_INT_TBL 0x0a0 +#define IWN_SHADOW_REG_CTRL 0x0a8 #define IWN_GIO_CHICKEN 0x100 #define IWN_ANA_PLL 0x20c #define IWN_HW_REV_WA 0x22c @@ -222,6 +223,7 @@ #define IWN_GP_DRIVER_RADIO_2X2_HYB (1 << 0) #define IWN_GP_DRIVER_RADIO_2X2_IPA (2 << 0) #define IWN_GP_DRIVER_CALIB_VER6 (1 << 2) +#define IWN_GP_DRIVER_6050_1X2 (1 << 3) /* Possible flags for register IWN_UCODE_GP1_CLR. */ #define IWN_UCODE_GP1_RFKILL (1 << 1) @@ -290,8 +292,7 @@ #define IWN_FH_TX_CHICKEN_SCHED_RETRY (1 << 1) /* Possible flags for register IWN_FH_TX_STATUS. */ -#define IWN_FH_TX_STATUS_IDLE(chnl) \ - (1 << ((chnl) + 24) | 1 << ((chnl) + 16)) +#define IWN_FH_TX_STATUS_IDLE(chnl) (1 << ((chnl) + 16)) /* Possible flags for register IWN_FH_RX_CONFIG. */ #define IWN_FH_RX_CONFIG_ENA (1 << 31) @@ -861,7 +862,7 @@ #define IWN_CTOMUK(c) (((c) * 1000000) + 273150000) } __packed; -/* Structure for command IWN_CMD_SET_SENSITIVITY. */ +/* Structures for command IWN_CMD_SET_SENSITIVITY. */ struct iwn_sensitivity_cmd { uint16_t which; #define IWN_SENSITIVITY_DEFAULTTBL 0 @@ -880,6 +881,34 @@ uint16_t energy_ofdm_th; } __packed; +struct iwn_enhanced_sensitivity_cmd { + uint16_t which; + uint16_t energy_cck; + uint16_t energy_ofdm; + uint16_t corr_ofdm_x1; + uint16_t corr_ofdm_mrc_x1; + uint16_t corr_cck_mrc_x4; + uint16_t corr_ofdm_x4; + uint16_t corr_ofdm_mrc_x4; + uint16_t corr_barker; + uint16_t corr_barker_mrc; + uint16_t corr_cck_x4; + uint16_t energy_ofdm_th; + /* "Enhanced" part. */ + uint16_t ina_det_ofdm; + uint16_t ina_det_cck; + uint16_t corr_11_9_en; + uint16_t ofdm_det_slope_mrc; + uint16_t ofdm_det_icept_mrc; + uint16_t ofdm_det_slope; + uint16_t ofdm_det_icept; + uint16_t cck_det_slope_mrc; + uint16_t cck_det_icept_mrc; + uint16_t cck_det_slope; + uint16_t cck_det_icept; + uint16_t reserved; +} __packed; + /* Structures for command IWN_CMD_PHY_CALIB. */ struct iwn_phy_calib { uint8_t code; @@ -890,6 +919,8 @@ #define IWN5000_PHY_CALIB_CRYSTAL 15 #define IWN5000_PHY_CALIB_BASE_BAND 16 #define IWN5000_PHY_CALIB_TX_IQ_PERIODIC 17 +#define IWN5000_PHY_CALIB_TEMP_OFFSET 18 + #define IWN5000_PHY_CALIB_RESET_NOISE_GAIN 18 #define IWN5000_PHY_CALIB_NOISE_GAIN 19 @@ -908,6 +939,17 @@ uint8_t reserved[2]; } __packed; +struct iwn5000_phy_calib_temp_offset { + uint8_t code; + uint8_t group; + uint8_t ngroups; + uint8_t isvalid; + int16_t offset; +#define IWN_DEFAULT_TEMP_OFFSET 2700 + + uint16_t reserved; +} __packed; + struct iwn_phy_calib_gain { uint8_t code; uint8_t group; @@ -1293,6 +1335,7 @@ * Offsets into EEPROM. */ #define IWN_EEPROM_MAC 0x015 +#define IWN_EEPROM_SKU_CAP 0x045 #define IWN_EEPROM_RFCFG 0x048 #define IWN4965_EEPROM_DOMAIN 0x060 #define IWN4965_EEPROM_BAND1 0x063 @@ -1321,6 +1364,11 @@ #define IWN5000_EEPROM_TEMP 0x12a #define IWN5000_EEPROM_VOLT 0x12b +/* Possible flags for IWN_EEPROM_SKU_CAP. */ +#define IWN_EEPROM_SKU_CAP_11N (1 << 6) +#define IWN_EEPROM_SKU_CAP_AMT (1 << 7) +#define IWN_EEPROM_SKU_CAP_IPAN (1 << 8) + /* Possible flags for IWN_EEPROM_RFCFG. */ #define IWN_RFCFG_TYPE(x) (((x) >> 0) & 0x3) #define IWN_RFCFG_STEP(x) (((x) >> 2) & 0x3) Index: src/sys/dev/pci/if_iwnvar.h diff -u src/sys/dev/pci/if_iwnvar.h:1.12 src/sys/dev/pci/if_iwnvar.h:1.13 --- src/sys/dev/pci/if_iwnvar.h:1.12 Fri Jul 2 10:47:25 2010 +++ src/sys/dev/pci/if_iwnvar.h Sun May 15 09:56:20 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: if_iwnvar.h,v 1.12 2010/07/02 14:47:25 christos Exp $ */ +/* $NetBSD: if_iwnvar.h,v 1.13 2011/05/15 13:56:20 christos Exp $ */ /* $OpenBSD: if_iwnvar.h,v 1.19 2010/05/05 19:47:43 damien Exp $ */ /*- @@ -174,7 +174,7 @@ struct iwn_fw_part boot; }; -struct iwn_hal { +struct iwn_ops { int (*load_firmware)(struct iwn_softc *); void (*read_eeprom)(struct iwn_softc *); int (*post_alive)(struct iwn_softc *); @@ -196,15 +196,6 @@ void (*ampdu_tx_stop)(struct iwn_softc *, uint8_t, uint16_t); #endif - int ntxqs; - int ndmachnls; - uint8_t broadcast_id; - int rxonsz; - int schedsz; - uint32_t fw_text_maxsz; - uint32_t fw_data_maxsz; - uint32_t fwsz; - bus_size_t sched_txfact_addr; }; struct iwn_softc { @@ -226,15 +217,27 @@ #define IWN_FLAG_CALIB_DONE (1 << 2) #define IWN_FLAG_USE_ICT (1 << 3) #define IWN_FLAG_INTERNAL_PA (1 << 4) +#define IWN_FLAG_HAS_11N (1 << 6) +#define IWN_FLAG_ENH_SENS (1 << 7) /* Added for NetBSD */ #define IWN_FLAG_SCANNING (1 << 8) #define IWN_FLAG_HW_INITED (1 << 9) uint8_t hw_type; - const struct iwn_hal *sc_hal; + + struct iwn_ops ops; const char *fwname; const struct iwn_sensitivity_limits *limits; + int ntxqs; + int ndmachnls; + uint8_t broadcast_id; + int rxonsz; + int schedsz; + uint32_t fw_text_maxsz; + uint32_t fw_data_maxsz; + uint32_t fwsz; + bus_size_t sched_txfact_addr; /* TX scheduler rings. */ struct iwn_dma_info sched_dma; @@ -289,6 +292,7 @@ uint8_t calib_ver; char eeprom_domain[4]; uint32_t eeprom_crystal; + int16_t eeprom_temp; int16_t eeprom_voltage; int8_t maxpwr2GHz; int8_t maxpwr5GHz;