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;