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;

Reply via email to