summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordamien <damien@openbsd.org>2011-01-09 15:45:37 +0000
committerdamien <damien@openbsd.org>2011-01-09 15:45:37 +0000
commit0bfcb362c36eee6da75166f2dec9ab148ead4115 (patch)
treec5e45edbd564cb81b4a10811ebba7b4d8d4fadaa
parentAdd and install tbl(7); (diff)
downloadwireguard-openbsd-0bfcb362c36eee6da75166f2dec9ab148ead4115.tar.xz
wireguard-openbsd-0bfcb362c36eee6da75166f2dec9ab148ead4115.zip
cleanup; change the way opns are attached.
include a fix for Intel Centrino Advanced-N 6250 devices by Antonio R Nicolosi.
-rw-r--r--sys/dev/pci/if_iwn.c612
-rw-r--r--sys/dev/pci/if_iwnreg.h53
-rw-r--r--sys/dev/pci/if_iwnvar.h30
3 files changed, 391 insertions, 304 deletions
diff --git a/sys/dev/pci/if_iwn.c b/sys/dev/pci/if_iwn.c
index 22f6d651cfa..a0bf3f5be56 100644
--- a/sys/dev/pci/if_iwn.c
+++ b/sys/dev/pci/if_iwn.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_iwn.c,v 1.106 2010/12/31 19:48:56 damien Exp $ */
+/* $OpenBSD: if_iwn.c,v 1.107 2011/01/09 15:45:37 damien Exp $ */
/*-
* Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
@@ -32,7 +32,6 @@
#include <sys/malloc.h>
#include <sys/conf.h>
#include <sys/device.h>
-#include <sys/sensors.h>
#include <sys/workq.h>
#include <machine/bus.h>
@@ -96,10 +95,8 @@ static const struct pci_matchid iwn_devices[] = {
int iwn_match(struct device *, void *, void *);
void iwn_attach(struct device *, struct device *, void *);
-const struct iwn_hal *iwn_hal_attach(struct iwn_softc *, pci_product_id_t);
-#ifndef SMALL_KERNEL
-void iwn_sensor_attach(struct iwn_softc *);
-#endif
+int iwn4965_attach(struct iwn_softc *, pci_product_id_t);
+int iwn5000_attach(struct iwn_softc *, pci_product_id_t);
#if NBPFILTER > 0
void iwn_radiotap_attach(struct iwn_softc *);
#endif
@@ -208,6 +205,8 @@ void iwn_tune_sensitivity(struct iwn_softc *,
const struct iwn_rx_stats *);
int iwn_send_sensitivity(struct iwn_softc *);
int iwn_set_pslevel(struct iwn_softc *, int, int, int);
+int iwn_send_temperature_offset(struct iwn_softc *);
+int iwn_send_btcoex(struct iwn_softc *);
int iwn_config(struct iwn_softc *);
int iwn_scan(struct iwn_softc *, uint16_t);
int iwn_auth(struct iwn_softc *);
@@ -237,6 +236,8 @@ void iwn5000_ampdu_tx_stop(struct iwn_softc *,
int iwn5000_query_calibration(struct iwn_softc *);
int iwn5000_send_calibration(struct iwn_softc *);
int iwn5000_send_wimax_coex(struct iwn_softc *);
+int iwn5000_crystal_calib(struct iwn_softc *);
+int iwn5000_temp_offset_calib(struct iwn_softc *);
int iwn4965_post_alive(struct iwn_softc *);
int iwn5000_post_alive(struct iwn_softc *);
int iwn4965_load_bootcode(struct iwn_softc *, const uint8_t *,
@@ -271,62 +272,6 @@ int iwn_debug = 0;
#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
-};
-
struct cfdriver iwn_cd = {
NULL, "iwn", DV_IFNET
};
@@ -350,7 +295,6 @@ iwn_attach(struct device *parent, struct device *self, void *aux)
struct ieee80211com *ic = &sc->sc_ic;
struct ifnet *ifp = &ic->ic_if;
struct pci_attach_args *pa = aux;
- const struct iwn_hal *hal;
const char *intrstr;
pci_intr_handle_t ih;
pcireg_t memtype, reg;
@@ -373,8 +317,8 @@ iwn_attach(struct device *parent, struct device *self, void *aux)
/* 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);
/* Hardware bug workaround. */
reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, PCI_COMMAND_STATUS_REG);
@@ -410,10 +354,16 @@ iwn_attach(struct device *parent, struct device *self, void *aux)
}
printf(": %s", 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) {
+ printf(": could not attach device\n");
return;
+ }
if ((error = iwn_hw_prepare(sc)) != 0) {
printf(": hardware not ready\n");
@@ -451,8 +401,8 @@ iwn_attach(struct device *parent, struct device *self, void *aux)
goto fail3;
}
- /* 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) {
printf(": could not allocate TX ring %d\n", i);
goto fail4;
@@ -494,20 +444,22 @@ iwn_attach(struct device *parent, struct device *self, void *aux)
IEEE80211_C_PMGT; /* power saving supported */
#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. */
@@ -518,12 +470,14 @@ iwn_attach(struct device *parent, struct device *self, void *aux)
ieee80211_std_rateset_11a;
}
#ifndef IEEE80211_NO_HT
- /* 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 */
+ 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. */
@@ -559,9 +513,6 @@ iwn_attach(struct device *parent, struct device *self, void *aux)
sc->amrr.amrr_min_success_threshold = 1;
sc->amrr.amrr_max_success_threshold = 15;
-#ifndef SMALL_KERNEL
- iwn_sensor_attach(sc);
-#endif
#if NBPFILTER > 0
iwn_radiotap_attach(sc);
#endif
@@ -578,28 +529,83 @@ fail2: iwn_free_kw(sc);
fail1: iwn_free_fwmem(sc);
}
-const struct iwn_hal *
-iwn_hal_attach(struct iwn_softc *sc, pci_product_id_t pid)
-{
- sc->hw_type = (IWN_READ(sc, IWN_HW_REV) >> 4) & 0xf;
+int
+iwn4965_attach(struct iwn_softc *sc, pci_product_id_t pid)
+{
+ 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 = "iwn-4965";
+ 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 = "iwn-4965";
- 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 = "iwn-5000";
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 = "iwn-5150";
sc->txchainmask = IWN_ANT_A;
@@ -607,21 +613,18 @@ iwn_hal_attach(struct iwn_softc *sc, pci_product_id_t pid)
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 = "iwn-5000";
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 = "iwn-1000";
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 = "iwn-6000";
switch (pid) {
@@ -638,14 +641,12 @@ iwn_hal_attach(struct iwn_softc *sc, pci_product_id_t pid)
}
break;
case IWN_HW_REV_TYPE_6050:
- sc->sc_hal = &iwn5000_hal;
sc->limits = &iwn6000_sensitivity_limits;
sc->fwname = "iwn-6050";
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 = "iwn-6005";
sc->txchainmask = IWN_ANT_AB;
@@ -653,27 +654,10 @@ iwn_hal_attach(struct iwn_softc *sc, pci_product_id_t pid)
break;
default:
printf(": adapter type %d not supported\n", sc->hw_type);
- return NULL;
+ return ENOTSUP;
}
- return sc->sc_hal;
-}
-
-#ifndef SMALL_KERNEL
-/*
- * Attach the adapter on-board thermal sensor to the sensors framework.
- */
-void
-iwn_sensor_attach(struct iwn_softc *sc)
-{
- strlcpy(sc->sensordev.xname, sc->sc_dev.dv_xname,
- sizeof sc->sensordev.xname);
- sc->sensor.type = SENSOR_TEMP;
- /* Temperature is not valid unless interface is up. */
- sc->sensor.flags = SENSOR_FINVALID;
- sensor_attach(&sc->sensordev, &sc->sensor);
- sensordev_install(&sc->sensordev);
+ return 0;
}
-#endif
#if NBPFILTER > 0
/*
@@ -710,7 +694,7 @@ iwn_detach(struct device *self, int flags)
/* 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]);
iwn_free_sched(sc);
iwn_free_kw(sc);
@@ -720,12 +704,6 @@ iwn_detach(struct device *self, int flags)
bus_space_unmap(sc->sc_st, sc->sc_sh, sc->sc_sz);
-#ifndef SMALL_KERNEL
- /* Detach the thermal sensor. */
- sensor_detach(&sc->sensordev, &sc->sensor);
- sensordev_deinstall(&sc->sensordev);
-#endif
-
ieee80211_ifdetach(ifp);
if_detach(ifp);
@@ -762,8 +740,8 @@ iwn_resume(void *arg1, void *arg2)
/* 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();
while (sc->sc_flags & IWN_FLAG_BUSY)
@@ -1072,7 +1050,7 @@ iwn_alloc_sched(struct iwn_softc *sc)
{
/* 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);
}
void
@@ -1114,7 +1092,7 @@ iwn_alloc_fwmem(struct iwn_softc *sc)
{
/* 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);
}
void
@@ -1131,7 +1109,7 @@ iwn_alloc_rx_ring(struct iwn_softc *sc, struct iwn_rx_ring *ring)
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);
@@ -1141,7 +1119,7 @@ iwn_alloc_rx_ring(struct iwn_softc *sc, struct iwn_rx_ring *ring)
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) {
@@ -1182,7 +1160,7 @@ iwn_alloc_rx_ring(struct iwn_softc *sc, struct iwn_rx_ring *ring)
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);
}
@@ -1247,7 +1225,7 @@ iwn_alloc_tx_ring(struct iwn_softc *sc, struct iwn_tx_ring *ring, int qid)
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);
@@ -1353,7 +1331,7 @@ iwn5000_ict_reset(struct iwn_softc *sc)
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);
@@ -1371,7 +1349,7 @@ iwn5000_ict_reset(struct iwn_softc *sc)
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;
@@ -1407,15 +1385,26 @@ iwn_read_eeprom(struct iwn_softc *sc)
}
}
+ iwn_read_prom_data(sc, IWN_EEPROM_SKU_CAP, &val, 2);
+ DPRINTF(("SKU capabilities=0x%04x\n", letoh16(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 = letoh16(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. */
@@ -1430,10 +1419,10 @@ iwn4965_read_eeprom(struct iwn_softc *sc)
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);
@@ -1507,18 +1496,18 @@ void
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 = letoh16(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);
@@ -1538,12 +1527,12 @@ iwn5000_read_eeprom(struct iwn_softc *sc)
if (sc->hw_type == IWN_HW_REV_TYPE_5150) {
/* Compute temperature offset. */
iwn_read_prom_data(sc, base + IWN5000_EEPROM_TEMP, &val, 2);
- temp = letoh16(val);
+ sc->eeprom_temp = letoh16(val);
iwn_read_prom_data(sc, base + IWN5000_EEPROM_VOLT, &val, 2);
volt = letoh16(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,
@@ -1872,7 +1861,7 @@ void
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_if;
struct iwn_rx_ring *ring = &sc->rxq;
@@ -2010,7 +1999,7 @@ iwn_rx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc,
rxi.rxi_flags |= IEEE80211_RXI_HWDEC;
}
- rssi = hal->get_rssi(stat);
+ rssi = ops->get_rssi(stat);
#if NBPFILTER > 0
if (sc->sc_drvbpf != NULL) {
@@ -2084,7 +2073,7 @@ iwn_rx_compressed_ba(struct iwn_softc *sc, struct iwn_rx_desc *desc,
/*
* 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).
*/
void
iwn5000_rx_calib_results(struct iwn_softc *sc, struct iwn_rx_desc *desc,
@@ -2103,8 +2092,7 @@ iwn5000_rx_calib_results(struct iwn_softc *sc, struct iwn_rx_desc *desc,
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:
@@ -2148,7 +2136,7 @@ void
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);
@@ -2168,14 +2156,10 @@ iwn_rx_statistics(struct iwn_softc *sc, struct iwn_rx_desc *desc,
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));
- /* Update temperature sensor. */
- sc->sensor.value = IWN_CTOMUK(temp);
- sc->sensor.flags &= ~SENSOR_FINVALID;
-
- /* 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);
}
@@ -2302,6 +2286,7 @@ iwn_cmd_done(struct iwn_softc *sc, struct iwn_rx_desc *desc)
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_if;
uint16_t hw;
@@ -2342,7 +2327,7 @@ iwn_notif_intr(struct iwn_softc *sc)
#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:
@@ -2480,7 +2465,7 @@ iwn_wakeup_intr(struct iwn_softc *sc)
/* 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);
}
@@ -2494,7 +2479,6 @@ iwn_wakeup_intr(struct iwn_softc *sc)
void
iwn_fatal_intr(struct iwn_softc *sc)
{
- const struct iwn_hal *hal = sc->sc_hal;
struct iwn_fw_dump dump;
int i;
@@ -2504,7 +2488,7 @@ iwn_fatal_intr(struct iwn_softc *sc)
/* 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) {
printf("%s: bad firmware error log address 0x%08x\n",
sc->sc_dev.dv_xname, sc->errptr);
return;
@@ -2541,7 +2525,7 @@ iwn_fatal_intr(struct iwn_softc *sc)
/* Dump driver status (TX and RX rings) while we're here. */
printf("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];
printf(" tx ring %2d: qid=%-2d cur=%-3d queued=%-3d\n",
i, ring->qid, ring->cur, ring->queued);
@@ -2646,7 +2630,7 @@ iwn_intr(void *arg)
/*
* 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).
*/
void
iwn4965_update_sched(struct iwn_softc *sc, int qid, int idx, uint8_t id,
@@ -2704,7 +2688,6 @@ iwn5000_reset_sched(struct iwn_softc *sc, int qid, int idx)
int
iwn_tx(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
{
- 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;
@@ -2845,7 +2828,7 @@ iwn_tx(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
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;
@@ -2879,7 +2862,7 @@ iwn_tx(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
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? */
@@ -2994,7 +2977,7 @@ iwn_tx(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
#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. */
@@ -3237,7 +3220,7 @@ iwn_cmd(struct iwn_softc *sc, int code, const void *buf, int size, int async)
#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
/* Kick command ring. */
@@ -3314,7 +3297,7 @@ iwn_set_link_quality(struct iwn_softc *sc, struct ieee80211_node *ni)
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;
@@ -3323,16 +3306,16 @@ iwn_add_broadcast_node(struct iwn_softc *sc, int async)
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;
@@ -3427,7 +3410,7 @@ iwn_set_timing(struct iwn_softc *sc, struct ieee80211_node *ni)
cmd.lintval = htole16(10);
/* Compute remaining time until next beacon. */
- val = (uint64_t)ni->ni_intval * 1024; /* msecs -> usecs */
+ val = (uint64_t)ni->ni_intval * IEEE80211_DUR_TU;
mod = letoh64(cmd.tstamp) % val;
cmd.binitval = htole32((uint32_t)(val - mod));
@@ -3440,7 +3423,7 @@ iwn_set_timing(struct iwn_softc *sc, struct ieee80211_node *ni)
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. */
@@ -3688,7 +3671,7 @@ iwn4965_get_temperature(struct iwn_softc *sc)
r3 = letoh32(uc->temp[2].chan20MHz);
r4 = letoh32(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. */
@@ -3708,8 +3691,7 @@ iwn5000_get_temperature(struct iwn_softc *sc)
/*
* Temperature is not used by the driver for 5000 Series because
- * TX power calibration is handled by firmware. We export it to
- * users through the sensor framework though.
+ * TX power calibration is handled by firmware.
*/
temp = letoh32(sc->rawtemp);
if (sc->hw_type == IWN_HW_REV_TYPE_5150) {
@@ -3725,7 +3707,7 @@ iwn5000_get_temperature(struct iwn_softc *sc)
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;
@@ -3748,7 +3730,7 @@ iwn_init_sensitivity(struct iwn_softc *sc)
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. */
@@ -3766,7 +3748,7 @@ void
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;
@@ -3796,13 +3778,13 @@ iwn_collect_noise(struct iwn_softc *sc,
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. */
@@ -3938,7 +3920,7 @@ iwn_tune_sensitivity(struct iwn_softc *sc, const struct iwn_rx_stats *stats)
/* Compute number of false alarms since last call for OFDM. */
fa = letoh32(stats->ofdm.bad_plcp) - calib->bad_plcp_ofdm;
fa += letoh32(stats->ofdm.fa) - calib->fa_ofdm;
- fa *= 200 * 1024; /* 200TU */
+ fa *= 200 * IEEE80211_DUR_TU; /* 200TU */
/* Save counters values for next call. */
calib->bad_plcp_ofdm = letoh32(stats->ofdm.bad_plcp);
@@ -3993,7 +3975,7 @@ iwn_tune_sensitivity(struct iwn_softc *sc, const struct iwn_rx_stats *stats)
/* Compute number of false alarms since last call for CCK. */
fa = letoh32(stats->cck.bad_plcp) - calib->bad_plcp_cck;
fa += letoh32(stats->cck.fa) - calib->fa_cck;
- fa *= 200 * 1024; /* 200TU */
+ fa *= 200 * IEEE80211_DUR_TU; /* 200TU */
/* Save counters values for next call. */
calib->bad_plcp_cck = letoh32(stats->cck.bad_plcp);
@@ -4054,30 +4036,40 @@ int
iwn_send_sensitivity(struct iwn_softc *sc)
{
struct iwn_calib_state *calib = &sc->calib;
- struct iwn_sensitivity_cmd cmd;
+ struct iwn_enhanced_sensitivity_cmd cmd;
+ int len;
memset(&cmd, 0, sizeof cmd);
+ len = sizeof (struct iwn_sensitivity_cmd);
cmd.which = IWN_SENSITIVITY_WORKTBL;
/* OFDM modulation. */
- cmd.corr_ofdm_x1 = htole16(calib->ofdm_x1);
- cmd.corr_ofdm_mrc_x1 = htole16(calib->ofdm_mrc_x1);
- cmd.corr_ofdm_x4 = htole16(calib->ofdm_x4);
- cmd.corr_ofdm_mrc_x4 = htole16(calib->ofdm_mrc_x4);
- cmd.energy_ofdm = htole16(sc->limits->energy_ofdm);
- cmd.energy_ofdm_th = htole16(62);
+ cmd.corr_ofdm_x1 = htole16(calib->ofdm_x1);
+ cmd.corr_ofdm_mrc_x1 = htole16(calib->ofdm_mrc_x1);
+ cmd.corr_ofdm_x4 = htole16(calib->ofdm_x4);
+ cmd.corr_ofdm_mrc_x4 = htole16(calib->ofdm_mrc_x4);
+ cmd.energy_ofdm = htole16(sc->limits->energy_ofdm);
+ cmd.energy_ofdm_th = htole16(62);
/* CCK modulation. */
- cmd.corr_cck_x4 = htole16(calib->cck_x4);
- cmd.corr_cck_mrc_x4 = htole16(calib->cck_mrc_x4);
- cmd.energy_cck = htole16(calib->energy_cck);
+ cmd.corr_cck_x4 = htole16(calib->cck_x4);
+ cmd.corr_cck_mrc_x4 = htole16(calib->cck_mrc_x4);
+ cmd.energy_cck = htole16(calib->energy_cck);
/* Barker modulation: use default values. */
- cmd.corr_barker = htole16(190);
- cmd.corr_barker_mrc = htole16(390);
-
- DPRINTFN(2, ("setting sensitivity %d/%d/%d/%d/%d/%d/%d\n",
- calib->ofdm_x1, calib->ofdm_mrc_x1, calib->ofdm_x4,
- calib->ofdm_mrc_x4, calib->cck_x4, calib->cck_mrc_x4,
- calib->energy_cck));
- return iwn_cmd(sc, IWN_CMD_SET_SENSITIVITY, &cmd, sizeof cmd, 1);
+ cmd.corr_barker = htole16(190);
+ cmd.corr_barker_mrc = htole16(390);
+ if (!(sc->sc_flags & IWN_FLAG_ENH_SENS))
+ goto send;
+ /* Enhanced sensitivity settings. */
+ len = sizeof (struct iwn_enhanced_sensitivity_cmd);
+ cmd.ofdm_det_slope_mrc = htole16(668);
+ cmd.ofdm_det_icept_mrc = htole16(4);
+ cmd.ofdm_det_slope = htole16(486);
+ cmd.ofdm_det_icept = htole16(37);
+ cmd.cck_det_slope_mrc = htole16(853);
+ cmd.cck_det_icept_mrc = htole16(4);
+ cmd.cck_det_slope = htole16(476);
+ cmd.cck_det_icept = htole16(99);
+send:
+ return iwn_cmd(sc, IWN_CMD_SET_SENSITIVITY, &cmd, len, 1);
}
/*
@@ -4136,17 +4128,39 @@ iwn_set_pslevel(struct iwn_softc *sc, int dtim, int level, int async)
}
int
+iwn_send_btcoex(struct iwn_softc *sc)
+{
+ struct iwn_bluetooth cmd;
+
+ memset(&cmd, 0, sizeof cmd);
+ cmd.flags = IWN_BT_COEX_CHAN_ANN | IWN_BT_COEX_BT_PRIO;
+ cmd.lead_time = IWN_BT_LEAD_TIME_DEF;
+ cmd.max_kill = IWN_BT_MAX_KILL_DEF;
+ DPRINTF(("configuring bluetooth coexistence\n"));
+ return iwn_cmd(sc, IWN_CMD_BT_COEX, &cmd, sizeof(cmd), 0);
+}
+
+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_if;
- struct iwn_bluetooth bluetooth;
uint32_t txmask;
uint16_t rxchain;
int error;
- /* Configure valid TX chains for 5000 Series. */
+ if (sc->hw_type == IWN_HW_REV_TYPE_6005) {
+ /* Set radio temperature sensor offset. */
+ error = iwn5000_temp_offset_calib(sc);
+ if (error != 0) {
+ printf("%s: could not set temperature offset\n",
+ sc->sc_dev.dv_xname);
+ return error;
+ }
+ }
+
+ /* Configure valid TX chains for >=5000 Series. */
if (sc->hw_type != IWN_HW_REV_TYPE_4965) {
txmask = htole32(sc->txchainmask);
DPRINTF(("configuring valid TX chains 0x%x\n", txmask));
@@ -4160,12 +4174,7 @@ iwn_config(struct iwn_softc *sc)
}
/* Configure bluetooth coexistence. */
- memset(&bluetooth, 0, sizeof bluetooth);
- bluetooth.flags = IWN_BT_COEX_CHAN_ANN | IWN_BT_COEX_BT_PRIO;
- bluetooth.lead_time = IWN_BT_LEAD_TIME_DEF;
- bluetooth.max_kill = IWN_BT_MAX_KILL_DEF;
- DPRINTF(("configuring bluetooth coexistence\n"));
- error = iwn_cmd(sc, IWN_CMD_BT_COEX, &bluetooth, sizeof bluetooth, 0);
+ error = iwn_send_btcoex(sc);
if (error != 0) {
printf("%s: could not configure bluetooth coexistence\n",
sc->sc_dev.dv_xname);
@@ -4206,7 +4215,7 @@ iwn_config(struct iwn_softc *sc)
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) {
printf("%s: RXON command failed\n", sc->sc_dev.dv_xname);
return error;
@@ -4219,7 +4228,7 @@ iwn_config(struct iwn_softc *sc)
}
/* Configuration has changed, set TX power accordingly. */
- if ((error = hal->set_txpower(sc, 0)) != 0) {
+ if ((error = ops->set_txpower(sc, 0)) != 0) {
printf("%s: could not set TX power\n", sc->sc_dev.dv_xname);
return error;
}
@@ -4285,7 +4294,7 @@ iwn_scan(struct iwn_softc *sc, uint16_t flags)
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) {
@@ -4376,7 +4385,7 @@ iwn_scan(struct iwn_softc *sc, uint16_t flags)
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;
@@ -4406,14 +4415,14 @@ iwn_auth(struct iwn_softc *sc)
}
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) {
printf("%s: RXON command failed\n", sc->sc_dev.dv_xname);
return error;
}
/* Configuration has changed, set TX power accordingly. */
- if ((error = hal->set_txpower(sc, 1)) != 0) {
+ if ((error = ops->set_txpower(sc, 1)) != 0) {
printf("%s: could not set TX power\n", sc->sc_dev.dv_xname);
return error;
}
@@ -4432,7 +4441,7 @@ iwn_auth(struct iwn_softc *sc)
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;
@@ -4458,7 +4467,7 @@ iwn_run(struct iwn_softc *sc)
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) {
printf("%s: could not update configuration\n",
sc->sc_dev.dv_xname);
@@ -4466,7 +4475,7 @@ iwn_run(struct iwn_softc *sc)
}
/* Configuration has changed, set TX power accordingly. */
- if ((error = hal->set_txpower(sc, 1)) != 0) {
+ if ((error = ops->set_txpower(sc, 1)) != 0) {
printf("%s: could not set TX power\n", sc->sc_dev.dv_xname);
return error;
}
@@ -4484,7 +4493,7 @@ iwn_run(struct iwn_softc *sc)
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) {
printf("%s: could not add BSS node\n", sc->sc_dev.dv_xname);
return error;
@@ -4520,7 +4529,7 @@ iwn_set_key(struct ieee80211com *ic, struct ieee80211_node *ni,
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;
@@ -4535,14 +4544,14 @@ iwn_set_key(struct ieee80211com *ic, struct ieee80211_node *ni,
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);
}
void
@@ -4550,7 +4559,7 @@ iwn_delete_key(struct ieee80211com *ic, struct ieee80211_node *ni,
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;
@@ -4564,13 +4573,13 @@ iwn_delete_key(struct ieee80211com *ic, struct ieee80211_node *ni,
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);
}
#ifndef IEEE80211_NO_HT
@@ -4584,6 +4593,7 @@ iwn_ampdu_rx_start(struct ieee80211com *ic, struct ieee80211_node *ni,
{
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;
@@ -4595,18 +4605,19 @@ iwn_ampdu_rx_start(struct ieee80211com *ic, struct ieee80211_node *ni,
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).
*/
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;
@@ -4616,7 +4627,7 @@ iwn_ampdu_rx_stop(struct ieee80211com *ic, struct ieee80211_node *ni,
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);
}
/*
@@ -4629,7 +4640,7 @@ iwn_ampdu_tx_start(struct ieee80211com *ic, struct ieee80211_node *ni,
{
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;
@@ -4641,13 +4652,13 @@ iwn_ampdu_tx_start(struct ieee80211com *ic, struct ieee80211_node *ni,
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;
}
@@ -4658,10 +4669,11 @@ iwn_ampdu_tx_stop(struct ieee80211com *ic, struct ieee80211_node *ni,
{
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);
}
@@ -4863,9 +4875,42 @@ iwn5000_send_wimax_coex(struct iwn_softc *sc)
return iwn_cmd(sc, IWN5000_CMD_WIMAX_COEX, &wimax, sizeof wimax, 0);
}
+int
+iwn5000_crystal_calib(struct iwn_softc *sc)
+{
+ struct iwn5000_phy_calib_crystal cmd;
+
+ memset(&cmd, 0, sizeof cmd);
+ cmd.code = IWN5000_PHY_CALIB_CRYSTAL;
+ cmd.ngroups = 1;
+ cmd.isvalid = 1;
+ cmd.cap_pin[0] = letoh32(sc->eeprom_crystal) & 0xff;
+ cmd.cap_pin[1] = (letoh32(sc->eeprom_crystal) >> 16) & 0xff;
+ DPRINTF(("sending crystal calibration %d, %d\n",
+ cmd.cap_pin[0], cmd.cap_pin[1]));
+ return iwn_cmd(sc, IWN_CMD_PHY_CALIB, &cmd, sizeof cmd, 0);
+}
+
+int
+iwn5000_temp_offset_calib(struct iwn_softc *sc)
+{
+ struct iwn5000_phy_calib_temp_offset cmd;
+
+ memset(&cmd, 0, sizeof cmd);
+ cmd.code = IWN5000_PHY_CALIB_TEMP_OFFSET;
+ cmd.ngroups = 1;
+ cmd.isvalid = 1;
+ if (sc->eeprom_temp != 0)
+ cmd.offset = htole16(sc->eeprom_temp);
+ else
+ cmd.offset = htole16(IWN_DEFAULT_TEMP_OFFSET);
+ DPRINTF(("setting radio sensor offset to %d\n", letoh16(cmd.offset)));
+ return iwn_cmd(sc, IWN_CMD_PHY_CALIB, &cmd, sizeof cmd, 0);
+}
+
/*
* This function is called after the runtime firmware notifies us of its
- * readiness (called in a process context.)
+ * readiness (called in a process context).
*/
int
iwn4965_post_alive(struct iwn_softc *sc)
@@ -4880,7 +4925,7 @@ iwn4965_post_alive(struct iwn_softc *sc)
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);
@@ -4918,7 +4963,7 @@ iwn4965_post_alive(struct iwn_softc *sc)
/*
* 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).
*/
int
iwn5000_post_alive(struct iwn_softc *sc)
@@ -4936,7 +4981,7 @@ iwn5000_post_alive(struct iwn_softc *sc)
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);
@@ -4978,18 +5023,8 @@ iwn5000_post_alive(struct iwn_softc *sc)
return error;
}
if (sc->hw_type != IWN_HW_REV_TYPE_5150) {
- struct iwn5000_phy_calib_crystal cmd;
-
/* Perform crystal calibration. */
- memset(&cmd, 0, sizeof cmd);
- cmd.code = IWN5000_PHY_CALIB_CRYSTAL;
- cmd.ngroups = 1;
- cmd.isvalid = 1;
- cmd.cap_pin[0] = letoh32(sc->eeprom_crystal) & 0xff;
- cmd.cap_pin[1] = (letoh32(sc->eeprom_crystal) >> 16) & 0xff;
- DPRINTF(("sending crystal calibration %d, %d\n",
- cmd.cap_pin[0], cmd.cap_pin[1]));
- error = iwn_cmd(sc, IWN_CMD_PHY_CALIB, &cmd, sizeof cmd, 0);
+ error = iwn5000_crystal_calib(sc);
if (error != 0) {
printf("%s: crystal calibration failed\n",
sc->sc_dev.dv_xname);
@@ -5018,7 +5053,7 @@ iwn5000_post_alive(struct iwn_softc *sc)
/*
* 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).
*/
int
iwn4965_load_bootcode(struct iwn_softc *sc, const uint8_t *ucode, int size)
@@ -5340,7 +5375,6 @@ iwn_read_firmware_tlv(struct iwn_softc *sc, struct iwn_fw_info *fw,
int
iwn_read_firmware(struct iwn_softc *sc)
{
- const struct iwn_hal *hal = sc->sc_hal;
struct iwn_fw_info *fw = &sc->fw;
int error;
@@ -5372,10 +5406,10 @@ iwn_read_firmware(struct iwn_softc *sc)
}
/* 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) {
printf("%s: firmware sections too large\n",
@@ -5413,12 +5447,12 @@ iwn_apm_init(struct iwn_softc *sc)
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. */
@@ -5444,7 +5478,7 @@ iwn_apm_init(struct iwn_softc *sc)
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);
@@ -5543,10 +5577,13 @@ iwn5000_nic_config(struct iwn_softc *sc)
/* 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;
}
@@ -5592,7 +5629,7 @@ iwn_hw_prepare(struct iwn_softc *sc)
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. */
@@ -5611,7 +5648,7 @@ iwn_hw_init(struct iwn_softc *sc)
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. */
@@ -5619,9 +5656,9 @@ iwn_hw_init(struct iwn_softc *sc)
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,
@@ -5638,23 +5675,23 @@ iwn_hw_init(struct iwn_softc *sc)
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);
@@ -5675,7 +5712,11 @@ iwn_hw_init(struct iwn_softc *sc)
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) {
printf("%s: could not load firmware\n", sc->sc_dev.dv_xname);
return error;
}
@@ -5686,13 +5727,12 @@ iwn_hw_init(struct iwn_softc *sc)
return error;
}
/* Do post-firmware initialization. */
- return hal->post_alive(sc);
+ return ops->post_alive(sc);
}
void
iwn_hw_stop(struct iwn_softc *sc)
{
- const struct iwn_hal *hal = sc->sc_hal;
int chnl, qid, ntries;
IWN_WRITE(sc, IWN_RESET, IWN_RESET_NEVO);
@@ -5707,11 +5747,11 @@ iwn_hw_stop(struct iwn_softc *sc)
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++) {
if (IWN_READ(sc, IWN_FH_TX_STATUS) &
@@ -5727,7 +5767,7 @@ iwn_hw_stop(struct iwn_softc *sc)
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) {
@@ -5816,8 +5856,4 @@ iwn_stop(struct ifnet *ifp, int disable)
/* Power OFF hardware. */
iwn_hw_stop(sc);
-
- /* Temperature sensor is no longer valid. */
- sc->sensor.value = 0;
- sc->sensor.flags |= SENSOR_FINVALID;
}
diff --git a/sys/dev/pci/if_iwnreg.h b/sys/dev/pci/if_iwnreg.h
index d941e62c286..cd88cd010f3 100644
--- a/sys/dev/pci/if_iwnreg.h
+++ b/sys/dev/pci/if_iwnreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_iwnreg.h,v 1.41 2010/07/20 19:24:31 damien Exp $ */
+/* $OpenBSD: if_iwnreg.h,v 1.42 2011/01/09 15:45:37 damien Exp $ */
/*-
* Copyright (c) 2007, 2008
@@ -72,6 +72,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
@@ -217,6 +218,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)
@@ -855,7 +857,7 @@ struct iwn_critical_temp {
#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
@@ -874,6 +876,34 @@ struct iwn_sensitivity_cmd {
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;
@@ -884,6 +914,8 @@ struct iwn_phy_calib {
#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
@@ -902,6 +934,17 @@ struct iwn5000_phy_calib_crystal {
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;
@@ -1287,6 +1330,7 @@ struct iwn_fw_tlv {
* 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
@@ -1315,6 +1359,11 @@ struct iwn_fw_tlv {
#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)
diff --git a/sys/dev/pci/if_iwnvar.h b/sys/dev/pci/if_iwnvar.h
index f806348f377..cdf37f44c21 100644
--- a/sys/dev/pci/if_iwnvar.h
+++ b/sys/dev/pci/if_iwnvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_iwnvar.h,v 1.21 2010/09/07 16:21:45 deraadt Exp $ */
+/* $OpenBSD: if_iwnvar.h,v 1.22 2011/01/09 15:45:37 damien Exp $ */
/*-
* Copyright (c) 2007, 2008
@@ -156,7 +156,7 @@ struct iwn_fw_info {
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 *);
@@ -178,15 +178,6 @@ struct iwn_hal {
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 {
@@ -208,12 +199,24 @@ struct iwn_softc {
#define IWN_FLAG_USE_ICT (1 << 3)
#define IWN_FLAG_INTERNAL_PA (1 << 4)
#define IWN_FLAG_BUSY (1 << 5)
+#define IWN_FLAG_HAS_11N (1 << 6)
+#define IWN_FLAG_ENH_SENS (1 << 7)
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;
@@ -243,8 +246,6 @@ struct iwn_softc {
bus_size_t sc_sz;
int sc_cap_off; /* PCIe Capabilities. */
- struct ksensordev sensordev;
- struct ksensor sensor;
struct timeout calib_to;
int calib_cnt;
struct iwn_calib_state calib;
@@ -269,6 +270,7 @@ struct iwn_softc {
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;