[BACK]Return to if_iwn.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / pci

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/sys/dev/pci/if_iwn.c between version 1.62.6.3 and 1.63

version 1.62.6.3, 2017/12/03 11:37:08 version 1.63, 2013/03/30 03:21:05
Line 1 
Line 1 
 /*      $NetBSD$        */  /*      $NetBSD$        */
 /*      $OpenBSD: if_iwn.c,v 1.135 2014/09/10 07:22:09 dcoppa Exp $     */  /*      $OpenBSD: if_iwn.c,v 1.96 2010/05/13 09:25:03 damien Exp $      */
   
 /*-  /*-
  * Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>   * Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
Line 35  __KERNEL_RCSID(0, "$NetBSD$");
Line 35  __KERNEL_RCSID(0, "$NetBSD$");
 #include <sys/socket.h>  #include <sys/socket.h>
 #include <sys/systm.h>  #include <sys/systm.h>
 #include <sys/malloc.h>  #include <sys/malloc.h>
 #ifdef notyetMODULE  
 #include <sys/module.h>  
 #endif  
 #include <sys/mutex.h>  #include <sys/mutex.h>
 #include <sys/conf.h>  #include <sys/conf.h>
 #include <sys/kauth.h>  #include <sys/kauth.h>
Line 47  __KERNEL_RCSID(0, "$NetBSD$");
Line 44  __KERNEL_RCSID(0, "$NetBSD$");
   
 #include <sys/bus.h>  #include <sys/bus.h>
 #include <machine/endian.h>  #include <machine/endian.h>
 #include <sys/intr.h>  #include <machine/intr.h>
   
 #include <dev/pci/pcireg.h>  #include <dev/pci/pcireg.h>
 #include <dev/pci/pcivar.h>  #include <dev/pci/pcivar.h>
Line 102  static const pci_product_id_t iwn_device
Line 99  static const pci_product_id_t iwn_device
         PCI_PRODUCT_INTEL_WIFI_LINK_6005_2X2_2,          PCI_PRODUCT_INTEL_WIFI_LINK_6005_2X2_2,
         PCI_PRODUCT_INTEL_WIFI_LINK_6230_1,          PCI_PRODUCT_INTEL_WIFI_LINK_6230_1,
         PCI_PRODUCT_INTEL_WIFI_LINK_6230_2,          PCI_PRODUCT_INTEL_WIFI_LINK_6230_2,
         PCI_PRODUCT_INTEL_WIFI_LINK_6235,  
         PCI_PRODUCT_INTEL_WIFI_LINK_6235_2,  
         PCI_PRODUCT_INTEL_WIFI_LINK_100_1,  
         PCI_PRODUCT_INTEL_WIFI_LINK_100_2,  
         PCI_PRODUCT_INTEL_WIFI_LINK_130_1,  
         PCI_PRODUCT_INTEL_WIFI_LINK_130_2,  
         PCI_PRODUCT_INTEL_WIFI_LINK_2230_1,  
         PCI_PRODUCT_INTEL_WIFI_LINK_2230_2,  
         PCI_PRODUCT_INTEL_WIFI_LINK_2200_1,  
         PCI_PRODUCT_INTEL_WIFI_LINK_2200_2,  
         PCI_PRODUCT_INTEL_WIFI_LINK_135_1,  
         PCI_PRODUCT_INTEL_WIFI_LINK_135_2,  
         PCI_PRODUCT_INTEL_WIFI_LINK_105_1,  
         PCI_PRODUCT_INTEL_WIFI_LINK_105_2,  
 };  };
   
 /*  /*
Line 201  static void iwn_notif_intr(struct iwn_so
Line 184  static void iwn_notif_intr(struct iwn_so
 static void     iwn_wakeup_intr(struct iwn_softc *);  static void     iwn_wakeup_intr(struct iwn_softc *);
 static void     iwn_fatal_intr(struct iwn_softc *);  static void     iwn_fatal_intr(struct iwn_softc *);
 static int      iwn_intr(void *);  static int      iwn_intr(void *);
 static void     iwn_softintr(void *);  
 static void     iwn4965_update_sched(struct iwn_softc *, int, int, uint8_t,  static void     iwn4965_update_sched(struct iwn_softc *, int, int, uint8_t,
                     uint16_t);                      uint16_t);
 static void     iwn5000_update_sched(struct iwn_softc *, int, int, uint8_t,  static void     iwn5000_update_sched(struct iwn_softc *, int, int, uint8_t,
Line 245  static void iwn_tune_sensitivity(struct 
Line 227  static void iwn_tune_sensitivity(struct 
 static int      iwn_send_sensitivity(struct iwn_softc *);  static int      iwn_send_sensitivity(struct iwn_softc *);
 static int      iwn_set_pslevel(struct iwn_softc *, int, int, int);  static int      iwn_set_pslevel(struct iwn_softc *, int, int, int);
 static int      iwn5000_runtime_calib(struct iwn_softc *);  static int      iwn5000_runtime_calib(struct iwn_softc *);
   
 static int      iwn_config_bt_coex_bluetooth(struct iwn_softc *);  
 static int      iwn_config_bt_coex_prio_table(struct iwn_softc *);  
 static int      iwn_config_bt_coex_adv1(struct iwn_softc *);  
 static int      iwn_config_bt_coex_adv2(struct iwn_softc *);  
   
 static int      iwn_config(struct iwn_softc *);  static int      iwn_config(struct iwn_softc *);
 static uint16_t iwn_get_active_dwell_time(struct iwn_softc *, uint16_t,  
                     uint8_t);  
 static uint16_t iwn_limit_dwell(struct iwn_softc *, uint16_t);  
 static uint16_t iwn_get_passive_dwell_time(struct iwn_softc *, uint16_t);  
 static int      iwn_scan(struct iwn_softc *, uint16_t);  static int      iwn_scan(struct iwn_softc *, uint16_t);
 static int      iwn_auth(struct iwn_softc *);  static int      iwn_auth(struct iwn_softc *);
 static int      iwn_run(struct iwn_softc *);  static int      iwn_run(struct iwn_softc *);
Line 287  static void iwn5000_ampdu_tx_stop(struct
Line 259  static void iwn5000_ampdu_tx_stop(struct
 static int      iwn5000_query_calibration(struct iwn_softc *);  static int      iwn5000_query_calibration(struct iwn_softc *);
 static int      iwn5000_send_calibration(struct iwn_softc *);  static int      iwn5000_send_calibration(struct iwn_softc *);
 static int      iwn5000_send_wimax_coex(struct iwn_softc *);  static int      iwn5000_send_wimax_coex(struct iwn_softc *);
 static int      iwn6000_temp_offset_calib(struct iwn_softc *);  
 static int      iwn2000_temp_offset_calib(struct iwn_softc *);  
 static int      iwn4965_post_alive(struct iwn_softc *);  static int      iwn4965_post_alive(struct iwn_softc *);
 static int      iwn5000_post_alive(struct iwn_softc *);  static int      iwn5000_post_alive(struct iwn_softc *);
 static int      iwn4965_load_bootcode(struct iwn_softc *, const uint8_t *,  static int      iwn4965_load_bootcode(struct iwn_softc *, const uint8_t *,
Line 324  static int iwn_alloc_rpool(struct iwn_so
Line 294  static int iwn_alloc_rpool(struct iwn_so
 static void     iwn_free_rpool(struct iwn_softc *);  static void     iwn_free_rpool(struct iwn_softc *);
 #endif  #endif
   
 static void     iwn_fix_channel(struct ieee80211com *, struct mbuf *,  /* XXX needed by iwn_scan */
                     struct iwn_rx_stat *);  static u_int8_t *ieee80211_add_ssid(u_int8_t *, const u_int8_t *, u_int);
   static u_int8_t *ieee80211_add_rates(u_int8_t *,
       const struct ieee80211_rateset *);
   static u_int8_t *ieee80211_add_xrates(u_int8_t *,
       const struct ieee80211_rateset *);
   
   static void     iwn_fix_channel(struct ieee80211com *, struct mbuf *);
   
 #ifdef IWN_DEBUG  #ifdef IWN_DEBUG
 #define DPRINTF(x)      do { if (iwn_debug > 0) printf x; } while (0)  #define DPRINTF(x)      do { if (iwn_debug > 0) printf x; } while (0)
Line 363  iwn_attach(device_t parent __unused, dev
Line 339  iwn_attach(device_t parent __unused, dev
         struct ifnet *ifp = &sc->sc_ec.ec_if;          struct ifnet *ifp = &sc->sc_ec.ec_if;
         struct pci_attach_args *pa = aux;          struct pci_attach_args *pa = aux;
         const char *intrstr;          const char *intrstr;
           pci_intr_handle_t ih;
         pcireg_t memtype, reg;          pcireg_t memtype, reg;
         int i, error;          int i, error;
         char intrbuf[PCI_INTRSTR_LEN];  
   
         sc->sc_dev = self;          sc->sc_dev = self;
         sc->sc_pct = pa->pa_pc;          sc->sc_pct = pa->pa_pc;
Line 385  iwn_attach(device_t parent __unused, dev
Line 361  iwn_attach(device_t parent __unused, dev
         error = pci_get_capability(sc->sc_pct, sc->sc_pcitag,          error = pci_get_capability(sc->sc_pct, sc->sc_pcitag,
             PCI_CAP_PCIEXPRESS, &sc->sc_cap_off, NULL);              PCI_CAP_PCIEXPRESS, &sc->sc_cap_off, NULL);
         if (error == 0) {          if (error == 0) {
                 aprint_error_dev(self,                  aprint_error(": PCIe capability structure not found!\n");
                     "PCIe capability structure not found!\n");  
                 return;                  return;
         }          }
   
Line 395  iwn_attach(device_t parent __unused, dev
Line 370  iwn_attach(device_t parent __unused, dev
         if (reg & 0xff00)          if (reg & 0xff00)
                 pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, reg & ~0xff00);                  pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, reg & ~0xff00);
   
         /* Enable bus-mastering. */          /* Enable bus-mastering and hardware bug workaround. */
         /* XXX verify the bus-mastering is really needed (not in OpenBSD) */          /* XXX verify the bus-mastering is really needed (not in OpenBSD) */
         reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, PCI_COMMAND_STATUS_REG);          reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, PCI_COMMAND_STATUS_REG);
         reg |= PCI_COMMAND_MASTER_ENABLE;          reg |= PCI_COMMAND_MASTER_ENABLE;
           if (reg & PCI_COMMAND_INTERRUPT_DISABLE) {
                   DPRINTF(("PCIe INTx Disable set\n"));
                   reg &= ~PCI_COMMAND_INTERRUPT_DISABLE;
           }
         pci_conf_write(sc->sc_pct, sc->sc_pcitag, PCI_COMMAND_STATUS_REG, reg);          pci_conf_write(sc->sc_pct, sc->sc_pcitag, PCI_COMMAND_STATUS_REG, reg);
   
         memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, IWN_PCI_BAR0);          memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, IWN_PCI_BAR0);
         error = pci_mapreg_map(pa, IWN_PCI_BAR0, memtype, 0, &sc->sc_st,          error = pci_mapreg_map(pa, IWN_PCI_BAR0, memtype, 0, &sc->sc_st,
             &sc->sc_sh, NULL, &sc->sc_sz);              &sc->sc_sh, NULL, &sc->sc_sz);
         if (error != 0) {          if (error != 0) {
                 aprint_error_dev(self, "can't map mem space\n");                  aprint_error(": can't map mem space\n");
                 return;                  return;
         }          }
   
         sc->sc_soft_ih = softint_establish(SOFTINT_NET, iwn_softintr, sc);  
         if (sc->sc_soft_ih == NULL) {  
                 aprint_error_dev(self, "can't establish soft interrupt\n");  
                 goto unmap;  
         }  
   
         /* Install interrupt handler. */          /* Install interrupt handler. */
         error = pci_intr_alloc(pa, &sc->sc_pihp, NULL, 0);          if (pci_intr_map(pa, &ih) != 0) {
         if (error) {                  aprint_error(": can't map interrupt\n");
                 aprint_error_dev(self, "can't allocate interrupt\n");                  return;
                 goto failsi;  
         }          }
         reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, PCI_COMMAND_STATUS_REG);          intrstr = pci_intr_string(sc->sc_pct, ih);
         if (pci_intr_type(sc->sc_pct, sc->sc_pihp[0]) == PCI_INTR_TYPE_INTX)          sc->sc_ih = pci_intr_establish(sc->sc_pct, ih, IPL_NET, iwn_intr, sc);
                 CLR(reg, PCI_COMMAND_INTERRUPT_DISABLE);  
         else  
                 SET(reg, PCI_COMMAND_INTERRUPT_DISABLE);  
         pci_conf_write(sc->sc_pct, sc->sc_pcitag, PCI_COMMAND_STATUS_REG, reg);  
         intrstr = pci_intr_string(sc->sc_pct, sc->sc_pihp[0], intrbuf,  
             sizeof(intrbuf));  
         sc->sc_ih = pci_intr_establish_xname(sc->sc_pct, sc->sc_pihp[0],  
             IPL_NET, iwn_intr, sc, device_xname(self));  
         if (sc->sc_ih == NULL) {          if (sc->sc_ih == NULL) {
                 aprint_error_dev(self, "can't establish interrupt");                  aprint_error(": can't establish interrupt");
                 if (intrstr != NULL)                  if (intrstr != NULL)
                         aprint_error(" at %s", intrstr);                          aprint_error(" at %s", intrstr);
                 aprint_error("\n");                  aprint_error("\n");
                 goto failia;                  return;
         }          }
         aprint_normal_dev(self, "interrupting at %s\n", intrstr);          aprint_normal_dev(self, "interrupting at %s\n", intrstr);
   
         /* Read hardware revision and attach. */          /* Read hardware revision and attach. */
         sc->hw_type =          sc->hw_type = (IWN_READ(sc, IWN_HW_REV) >> 4) & 0xf;
             (IWN_READ(sc, IWN_HW_REV) & IWN_HW_REV_TYPE_MASK)  
               >> IWN_HW_REV_TYPE_SHIFT;  
         if (sc->hw_type == IWN_HW_REV_TYPE_4965)          if (sc->hw_type == IWN_HW_REV_TYPE_4965)
                 error = iwn4965_attach(sc, PCI_PRODUCT(pa->pa_id));                  error = iwn4965_attach(sc, PCI_PRODUCT(pa->pa_id));
         else          else
                 error = iwn5000_attach(sc, PCI_PRODUCT(pa->pa_id));                  error = iwn5000_attach(sc, PCI_PRODUCT(pa->pa_id));
         if (error != 0) {          if (error != 0) {
                 aprint_error_dev(self, "could not attach device\n");                  aprint_error(": could not attach device\n");
                 goto failih;                  return;
         }          }
   
         if ((error = iwn_hw_prepare(sc)) != 0) {          if ((error = iwn_hw_prepare(sc)) != 0) {
                 aprint_error_dev(self, "hardware not ready\n");                  aprint_error(": hardware not ready\n");
                 goto failih;                  return;
         }          }
   
         /* Read MAC address, channels, etc from EEPROM. */          /* Read MAC address, channels, etc from EEPROM. */
         if ((error = iwn_read_eeprom(sc)) != 0) {          if ((error = iwn_read_eeprom(sc)) != 0) {
                 aprint_error_dev(self, "could not read EEPROM\n");                  aprint_error(": could not read EEPROM\n");
                 goto failih;                  return;
         }          }
   
         /* Allocate DMA memory for firmware transfers. */          /* Allocate DMA memory for firmware transfers. */
         if ((error = iwn_alloc_fwmem(sc)) != 0) {          if ((error = iwn_alloc_fwmem(sc)) != 0) {
                 aprint_error_dev(self,                  aprint_error(": could not allocate memory for firmware\n");
                     "could not allocate memory for firmware\n");                  return;
                 goto failih;  
         }          }
   
         /* Allocate "Keep Warm" page. */          /* Allocate "Keep Warm" page. */
         if ((error = iwn_alloc_kw(sc)) != 0) {          if ((error = iwn_alloc_kw(sc)) != 0) {
                 aprint_error_dev(self, "could not allocate keep warm page\n");                  aprint_error(": could not allocate keep warm page\n");
                 goto fail1;                  goto fail1;
         }          }
   
         /* Allocate ICT table for 5000 Series. */          /* Allocate ICT table for 5000 Series. */
         if (sc->hw_type != IWN_HW_REV_TYPE_4965 &&          if (sc->hw_type != IWN_HW_REV_TYPE_4965 &&
             (error = iwn_alloc_ict(sc)) != 0) {              (error = iwn_alloc_ict(sc)) != 0) {
                 aprint_error_dev(self, "could not allocate ICT table\n");                  aprint_error(": could not allocate ICT table\n");
                 goto fail2;                  goto fail2;
         }          }
   
         /* Allocate TX scheduler "rings". */          /* Allocate TX scheduler "rings". */
         if ((error = iwn_alloc_sched(sc)) != 0) {          if ((error = iwn_alloc_sched(sc)) != 0) {
                 aprint_error_dev(self,                  aprint_error(": could not allocate TX scheduler rings\n");
                     "could not allocate TX scheduler rings\n");  
                 goto fail3;                  goto fail3;
         }          }
   
Line 502  iwn_attach(device_t parent __unused, dev
Line 462  iwn_attach(device_t parent __unused, dev
         /* Allocate TX rings (16 on 4965AGN, 20 on >=5000). */          /* Allocate TX rings (16 on 4965AGN, 20 on >=5000). */
         for (i = 0; i < sc->ntxqs; i++) {          for (i = 0; i < sc->ntxqs; i++) {
                 if ((error = iwn_alloc_tx_ring(sc, &sc->txq[i], i)) != 0) {                  if ((error = iwn_alloc_tx_ring(sc, &sc->txq[i], i)) != 0) {
                         aprint_error_dev(self,                          aprint_error(": could not allocate TX ring %d\n", i);
                             "could not allocate TX ring %d\n", i);  
                         goto fail4;                          goto fail4;
                 }                  }
         }          }
   
         /* Allocate RX ring. */          /* Allocate RX ring. */
         if ((error = iwn_alloc_rx_ring(sc, &sc->rxq)) != 0) {          if ((error = iwn_alloc_rx_ring(sc, &sc->rxq)) != 0) {
                 aprint_error_dev(self, "could not allocate RX ring\n");                  aprint_error(": could not allocate RX ring\n");
                 goto fail4;                  goto fail4;
         }          }
   
Line 596  iwn_attach(device_t parent __unused, dev
Line 555  iwn_attach(device_t parent __unused, dev
         IFQ_SET_READY(&ifp->if_snd);          IFQ_SET_READY(&ifp->if_snd);
         memcpy(ifp->if_xname, device_xname(self), IFNAMSIZ);          memcpy(ifp->if_xname, device_xname(self), IFNAMSIZ);
   
         error = if_initialize(ifp);          if_attach(ifp);
         if (error != 0) {  
                 aprint_error_dev(sc->sc_dev, "if_initialize failed(%d)\n",  
                     error);  
                 goto fail5;  
         }  
         ieee80211_ifattach(ic);          ieee80211_ifattach(ic);
         /* Use common softint-based if_input */  
         ifp->if_percpuq = if_percpuq_create(ifp);  
         if_register(ifp);  
   
         ic->ic_node_alloc = iwn_node_alloc;          ic->ic_node_alloc = iwn_node_alloc;
         ic->ic_newassoc = iwn_newassoc;          ic->ic_newassoc = iwn_newassoc;
 #ifdef IWN_HWCRYPTO  #ifdef IWN_HWCRYPTO
Line 644  iwn_attach(device_t parent __unused, dev
Line 594  iwn_attach(device_t parent __unused, dev
         /* XXX NetBSD add call to ieee80211_announce for dmesg. */          /* XXX NetBSD add call to ieee80211_announce for dmesg. */
         ieee80211_announce(ic);          ieee80211_announce(ic);
   
         sc->sc_flags |= IWN_FLAG_ATTACHED;  
         return;          return;
   
         /* Free allocated memory if something failed during attachment. */          /* Free allocated memory if something failed during attachment. */
 fail5:  iwn_free_rx_ring(sc, &sc->rxq);  
 fail4:  while (--i >= 0)  fail4:  while (--i >= 0)
                 iwn_free_tx_ring(sc, &sc->txq[i]);                  iwn_free_tx_ring(sc, &sc->txq[i]);
 #ifdef IWN_USE_RBUF  #ifdef IWN_USE_RBUF
Line 659  fail3: if (sc->ict != NULL)
Line 607  fail3: if (sc->ict != NULL)
                 iwn_free_ict(sc);                  iwn_free_ict(sc);
 fail2:  iwn_free_kw(sc);  fail2:  iwn_free_kw(sc);
 fail1:  iwn_free_fwmem(sc);  fail1:  iwn_free_fwmem(sc);
 failih: pci_intr_disestablish(sc->sc_pct, sc->sc_ih);  
         sc->sc_ih = NULL;  
 failia: pci_intr_release(sc->sc_pct, sc->sc_pihp, 1);  
         sc->sc_pihp = NULL;  
 failsi: softint_disestablish(sc->sc_soft_ih);  
         sc->sc_soft_ih = NULL;  
 unmap:  bus_space_unmap(sc->sc_st, sc->sc_sh, sc->sc_sz);  
 }  }
   
 int  int
Line 677  iwn4965_attach(struct iwn_softc *sc, pci
Line 618  iwn4965_attach(struct iwn_softc *sc, pci
         ops->read_eeprom = iwn4965_read_eeprom;          ops->read_eeprom = iwn4965_read_eeprom;
         ops->post_alive = iwn4965_post_alive;          ops->post_alive = iwn4965_post_alive;
         ops->nic_config = iwn4965_nic_config;          ops->nic_config = iwn4965_nic_config;
         ops->config_bt_coex = iwn_config_bt_coex_bluetooth;  
         ops->update_sched = iwn4965_update_sched;          ops->update_sched = iwn4965_update_sched;
         ops->get_temperature = iwn4965_get_temperature;          ops->get_temperature = iwn4965_get_temperature;
         ops->get_rssi = iwn4965_get_rssi;          ops->get_rssi = iwn4965_get_rssi;
Line 717  iwn5000_attach(struct iwn_softc *sc, pci
Line 657  iwn5000_attach(struct iwn_softc *sc, pci
         ops->read_eeprom = iwn5000_read_eeprom;          ops->read_eeprom = iwn5000_read_eeprom;
         ops->post_alive = iwn5000_post_alive;          ops->post_alive = iwn5000_post_alive;
         ops->nic_config = iwn5000_nic_config;          ops->nic_config = iwn5000_nic_config;
         ops->config_bt_coex = iwn_config_bt_coex_bluetooth;  
         ops->update_sched = iwn5000_update_sched;          ops->update_sched = iwn5000_update_sched;
         ops->get_temperature = iwn5000_get_temperature;          ops->get_temperature = iwn5000_get_temperature;
         ops->get_rssi = iwn5000_get_rssi;          ops->get_rssi = iwn5000_get_rssi;
Line 759  iwn5000_attach(struct iwn_softc *sc, pci
Line 698  iwn5000_attach(struct iwn_softc *sc, pci
                 break;                  break;
         case IWN_HW_REV_TYPE_1000:          case IWN_HW_REV_TYPE_1000:
                 sc->limits = &iwn1000_sensitivity_limits;                  sc->limits = &iwn1000_sensitivity_limits;
                 if (pid == PCI_PRODUCT_INTEL_WIFI_LINK_100_1 ||                  sc->fwname = "iwlwifi-1000-3.ucode";
                     pid == PCI_PRODUCT_INTEL_WIFI_LINK_100_2)  
                         sc->fwname = "iwlwifi-100-5.ucode";  
                 else  
                         sc->fwname = "iwlwifi-1000-3.ucode";  
                 break;                  break;
         case IWN_HW_REV_TYPE_6000:          case IWN_HW_REV_TYPE_6000:
                 sc->limits = &iwn6000_sensitivity_limits;                  sc->limits = &iwn6000_sensitivity_limits;
Line 782  iwn5000_attach(struct iwn_softc *sc, pci
Line 717  iwn5000_attach(struct iwn_softc *sc, pci
                 break;                  break;
         case IWN_HW_REV_TYPE_6005:          case IWN_HW_REV_TYPE_6005:
                 sc->limits = &iwn6000_sensitivity_limits;                  sc->limits = &iwn6000_sensitivity_limits;
                 /* Type 6030 cards return IWN_HW_REV_TYPE_6005 */                  sc->fwname = "iwlwifi-6000g2a-5.ucode";
                 if (pid == PCI_PRODUCT_INTEL_WIFI_LINK_1030_1 ||  
                     pid == PCI_PRODUCT_INTEL_WIFI_LINK_1030_2 ||  
                     pid == PCI_PRODUCT_INTEL_WIFI_LINK_6230_1 ||  
                     pid == PCI_PRODUCT_INTEL_WIFI_LINK_6230_2 ||  
                     pid == PCI_PRODUCT_INTEL_WIFI_LINK_6235   ||  
                     pid == PCI_PRODUCT_INTEL_WIFI_LINK_6235_2) {  
                         sc->fwname = "iwlwifi-6000g2b-6.ucode";  
                         ops->config_bt_coex = iwn_config_bt_coex_adv1;  
                 }  
                 else  
                         sc->fwname = "iwlwifi-6000g2a-5.ucode";  
                 break;  
         case IWN_HW_REV_TYPE_2030:  
                 sc->limits = &iwn2030_sensitivity_limits;  
                 sc->fwname = "iwlwifi-2030-6.ucode";  
                 ops->config_bt_coex = iwn_config_bt_coex_adv2;  
                 break;  
         case IWN_HW_REV_TYPE_2000:  
                 sc->limits = &iwn2000_sensitivity_limits;  
                 sc->fwname = "iwlwifi-2000-6.ucode";  
                 break;  
         case IWN_HW_REV_TYPE_135:  
                 sc->limits = &iwn2000_sensitivity_limits;  
                 sc->fwname = "iwlwifi-135-6.ucode";  
                 ops->config_bt_coex = iwn_config_bt_coex_adv2;  
                 break;  
         case IWN_HW_REV_TYPE_105:  
                 sc->limits = &iwn2000_sensitivity_limits;  
                 sc->fwname = "iwlwifi-105-6.ucode";  
                 break;                  break;
         default:          default:
                 aprint_normal(": adapter type %d not supported\n", sc->hw_type);                  aprint_normal(": adapter type %d not supported\n", sc->hw_type);
Line 848  iwn_detach(device_t self, int flags __un
Line 754  iwn_detach(device_t self, int flags __un
         struct ifnet *ifp = sc->sc_ic.ic_ifp;          struct ifnet *ifp = sc->sc_ic.ic_ifp;
         int qid;          int qid;
   
         if (!(sc->sc_flags & IWN_FLAG_ATTACHED))  
                 return 0;  
   
         callout_stop(&sc->calib_to);          callout_stop(&sc->calib_to);
   
         /* Uninstall interrupt handler. */          /* Uninstall interrupt handler. */
         if (sc->sc_ih != NULL)          if (sc->sc_ih != NULL)
                 pci_intr_disestablish(sc->sc_pct, sc->sc_ih);                  pci_intr_disestablish(sc->sc_pct, sc->sc_ih);
         if (sc->sc_pihp != NULL)  
                 pci_intr_release(sc->sc_pct, sc->sc_pihp, 1);  
         if (sc->sc_soft_ih != NULL)  
                 softint_disestablish(sc->sc_soft_ih);  
   
         /* Free DMA resources. */          /* Free DMA resources. */
         iwn_free_rx_ring(sc, &sc->rxq);          iwn_free_rx_ring(sc, &sc->rxq);
Line 998  iwn_mem_write(struct iwn_softc *sc, uint
Line 897  iwn_mem_write(struct iwn_softc *sc, uint
         IWN_WRITE(sc, IWN_MEM_WDATA, data);          IWN_WRITE(sc, IWN_MEM_WDATA, data);
 }  }
   
 #ifndef IEEE80211_NO_HT  
 static __inline void  static __inline void
 iwn_mem_write_2(struct iwn_softc *sc, uint32_t addr, uint16_t data)  iwn_mem_write_2(struct iwn_softc *sc, uint32_t addr, uint16_t data)
 {  {
Line 1011  iwn_mem_write_2(struct iwn_softc *sc, ui
Line 909  iwn_mem_write_2(struct iwn_softc *sc, ui
                 tmp = (tmp & 0xffff0000) | data;                  tmp = (tmp & 0xffff0000) | data;
         iwn_mem_write(sc, addr & ~3, tmp);          iwn_mem_write(sc, addr & ~3, tmp);
 }  }
 #endif  
   
 static __inline void  static __inline void
 iwn_mem_read_region_4(struct iwn_softc *sc, uint32_t addr, uint32_t *data,  iwn_mem_read_region_4(struct iwn_softc *sc, uint32_t addr, uint32_t *data,
Line 1498  iwn5000_ict_reset(struct iwn_softc *sc)
Line 1395  iwn5000_ict_reset(struct iwn_softc *sc)
   
         /* Reset ICT table. */          /* Reset ICT table. */
         memset(sc->ict, 0, IWN_ICT_SIZE);          memset(sc->ict, 0, IWN_ICT_SIZE);
         bus_dmamap_sync(sc->sc_dmat, sc->ict_dma.map, 0, IWN_ICT_SIZE,  
             BUS_DMASYNC_PREWRITE);  
         sc->ict_cur = 0;          sc->ict_cur = 0;
   
         /* Set physical address of ICT table (4KB aligned). */          /* Set physical address of ICT table (4KB aligned). */
Line 1696  iwn5000_read_eeprom(struct iwn_softc *sc
Line 1591  iwn5000_read_eeprom(struct iwn_softc *sc
             hdr.version, hdr.pa_type, le16toh(hdr.volt)));              hdr.version, hdr.pa_type, le16toh(hdr.volt)));
         sc->calib_ver = hdr.version;          sc->calib_ver = hdr.version;
   
         if (sc->hw_type == IWN_HW_REV_TYPE_2030 ||  
             sc->hw_type == IWN_HW_REV_TYPE_2000 ||  
             sc->hw_type == IWN_HW_REV_TYPE_135  ||  
             sc->hw_type == IWN_HW_REV_TYPE_105) {  
                 sc->eeprom_voltage = le16toh(hdr.volt);  
                 iwn_read_prom_data(sc, base + IWN5000_EEPROM_TEMP, &val, 2);  
                 sc->eeprom_temp = le16toh(val);  
                 iwn_read_prom_data(sc, base + IWN2000_EEPROM_RAWTEMP, &val, 2);  
                 sc->eeprom_rawtemp = le16toh(val);  
         }  
   
         if (sc->hw_type == IWN_HW_REV_TYPE_5150) {          if (sc->hw_type == IWN_HW_REV_TYPE_5150) {
                 /* Compute temperature offset. */                  /* Compute temperature offset. */
                 iwn_read_prom_data(sc, base + IWN5000_EEPROM_TEMP, &val, 2);                  iwn_read_prom_data(sc, base + IWN5000_EEPROM_TEMP, &val, 2);
Line 1787  iwn_read_eeprom_enhinfo(struct iwn_softc
Line 1671  iwn_read_eeprom_enhinfo(struct iwn_softc
         struct iwn_eeprom_enhinfo enhinfo[35];          struct iwn_eeprom_enhinfo enhinfo[35];
         uint16_t val, base;          uint16_t val, base;
         int8_t maxpwr;          int8_t maxpwr;
         uint8_t flags;  
         int i;          int i;
   
         iwn_read_prom_data(sc, IWN5000_EEPROM_REG, &val, 2);          iwn_read_prom_data(sc, IWN5000_EEPROM_REG, &val, 2);
Line 1797  iwn_read_eeprom_enhinfo(struct iwn_softc
Line 1680  iwn_read_eeprom_enhinfo(struct iwn_softc
   
         memset(sc->enh_maxpwr, 0, sizeof sc->enh_maxpwr);          memset(sc->enh_maxpwr, 0, sizeof sc->enh_maxpwr);
         for (i = 0; i < __arraycount(enhinfo); i++) {          for (i = 0; i < __arraycount(enhinfo); i++) {
                 flags = enhinfo[i].flags;                  if (enhinfo[i].chan == 0 || enhinfo[i].reserved != 0)
                 if (!(flags & IWN_ENHINFO_VALID))  
                         continue;       /* Skip invalid entries. */                          continue;       /* Skip invalid entries. */
   
                 maxpwr = 0;                  maxpwr = 0;
Line 1891  iwn_newstate(struct ieee80211com *ic, en
Line 1773  iwn_newstate(struct ieee80211com *ic, en
                 /* XXX Do not abort a running scan. */                  /* XXX Do not abort a running scan. */
                 if (sc->sc_flags & IWN_FLAG_SCANNING) {                  if (sc->sc_flags & IWN_FLAG_SCANNING) {
                         if (ic->ic_state != nstate)                          if (ic->ic_state != nstate)
                                 aprint_debug_dev(sc->sc_dev, "scan request(%d) "                                  aprint_error_dev(sc->sc_dev, "scan request(%d) "
                                     "while scanning(%d) ignored\n", nstate,                                      "while scanning(%d) ignored\n", nstate,
                                     ic->ic_state);                                      ic->ic_state);
                         break;                          break;
Line 1900  iwn_newstate(struct ieee80211com *ic, en
Line 1782  iwn_newstate(struct ieee80211com *ic, en
                 /* XXX Not sure if call and flags are needed. */                  /* XXX Not sure if call and flags are needed. */
                 ieee80211_node_table_reset(&ic->ic_scan);                  ieee80211_node_table_reset(&ic->ic_scan);
                 ic->ic_flags |= IEEE80211_F_SCAN | IEEE80211_F_ASCAN;                  ic->ic_flags |= IEEE80211_F_SCAN | IEEE80211_F_ASCAN;
                 sc->sc_flags |= IWN_FLAG_SCANNING_2GHZ;                  sc->sc_flags |= IWN_FLAG_SCANNING;
   
                 /* Make the link LED blink while we're scanning. */                  /* Make the link LED blink while we're scanning. */
                 iwn_set_led(sc, IWN_LED_LINK, 10, 10);                  iwn_set_led(sc, IWN_LED_LINK, 10, 10);
Line 1923  iwn_newstate(struct ieee80211com *ic, en
Line 1805  iwn_newstate(struct ieee80211com *ic, en
                 sc->rxon.filter &= ~htole32(IWN_FILTER_BSS);                  sc->rxon.filter &= ~htole32(IWN_FILTER_BSS);
                 sc->calib.state = IWN_CALIB_STATE_INIT;                  sc->calib.state = IWN_CALIB_STATE_INIT;
   
                 /* Wait until we hear a beacon before we transmit */  
                 if (IEEE80211_IS_CHAN_PASSIVE(ic->ic_curchan))  
                         sc->sc_beacon_wait = 1;  
   
                 if ((error = iwn_auth(sc)) != 0) {                  if ((error = iwn_auth(sc)) != 0) {
                         aprint_error_dev(sc->sc_dev,                          aprint_error_dev(sc->sc_dev,
                             "could not move to auth state\n");                              "could not move to auth state\n");
Line 1935  iwn_newstate(struct ieee80211com *ic, en
Line 1813  iwn_newstate(struct ieee80211com *ic, en
                 break;                  break;
   
         case IEEE80211_S_RUN:          case IEEE80211_S_RUN:
                 /*  
                  * RUN -> RUN transition; Just restart timers.  
                  */  
                 if (ic->ic_state == IEEE80211_S_RUN) {  
                         sc->calib_cnt = 0;  
                         break;  
                 }  
   
                 /* Wait until we hear a beacon before we transmit */  
                 if (IEEE80211_IS_CHAN_PASSIVE(ic->ic_curchan))  
                         sc->sc_beacon_wait = 1;  
   
                 if ((error = iwn_run(sc)) != 0) {                  if ((error = iwn_run(sc)) != 0) {
                         aprint_error_dev(sc->sc_dev,                          aprint_error_dev(sc->sc_dev,
                             "could not move to run state\n");                              "could not move to run state\n");
Line 1957  iwn_newstate(struct ieee80211com *ic, en
Line 1823  iwn_newstate(struct ieee80211com *ic, en
         case IEEE80211_S_INIT:          case IEEE80211_S_INIT:
                 sc->sc_flags &= ~IWN_FLAG_SCANNING;                  sc->sc_flags &= ~IWN_FLAG_SCANNING;
                 sc->calib.state = IWN_CALIB_STATE_INIT;                  sc->calib.state = IWN_CALIB_STATE_INIT;
                 /*  
                  * Purge the xmit queue so we don't have old frames  
                  * during a new association attempt.  
                  */  
                 sc->sc_beacon_wait = 0;  
                 ifp->if_flags &= ~IFF_OACTIVE;  
                 iwn_start(ifp);  
                 break;                  break;
         }          }
   
Line 2005  iwn_calib_timeout(void *arg)
Line 1864  iwn_calib_timeout(void *arg)
         splx(s);          splx(s);
   
         /* Automatic rate control triggered every 500ms. */          /* Automatic rate control triggered every 500ms. */
         callout_schedule(&sc->calib_to, mstohz(500));          callout_schedule(&sc->calib_to, hz/2);
 }  }
   
 /*  /*
Line 2045  iwn_rx_done(struct iwn_softc *sc, struct
Line 1904  iwn_rx_done(struct iwn_softc *sc, struct
         struct iwn_rx_stat *stat;          struct iwn_rx_stat *stat;
         char    *head;          char    *head;
         uint32_t flags;          uint32_t flags;
         int error, len, rssi, s;          int error, len, rssi;
   
         if (desc->type == IWN_MPDU_RX_DONE) {          if (desc->type == IWN_MPDU_RX_DONE) {
                 /* Check for prior RX_PHY notification. */                  /* Check for prior RX_PHY notification. */
Line 2131  iwn_rx_done(struct iwn_softc *sc, struct
Line 1990  iwn_rx_done(struct iwn_softc *sc, struct
             BUS_DMASYNC_PREWRITE);              BUS_DMASYNC_PREWRITE);
   
         /* Finalize mbuf. */          /* Finalize mbuf. */
         m_set_rcvif(m, ifp);          m->m_pkthdr.rcvif = ifp;
         m->m_data = head;          m->m_data = head;
         m->m_pkthdr.len = m->m_len = len;          m->m_pkthdr.len = m->m_len = len;
   
         s = splnet();  
   
         /* Grab a reference to the source node. */          /* Grab a reference to the source node. */
         wh = mtod(m, struct ieee80211_frame *);          wh = mtod(m, struct ieee80211_frame *);
         ni = ieee80211_find_rxnode(ic, (struct ieee80211_frame_min *)wh);          ni = ieee80211_find_rxnode(ic, (struct ieee80211_frame_min *)wh);
Line 2148  iwn_rx_done(struct iwn_softc *sc, struct
Line 2005  iwn_rx_done(struct iwn_softc *sc, struct
   
         /* XXX Added for NetBSD: scans never stop without it */          /* XXX Added for NetBSD: scans never stop without it */
         if (ic->ic_state == IEEE80211_S_SCAN)          if (ic->ic_state == IEEE80211_S_SCAN)
                 iwn_fix_channel(ic, m, stat);                  iwn_fix_channel(ic, m);
   
         if (sc->sc_drvbpf != NULL) {          if (sc->sc_drvbpf != NULL) {
                 struct iwn_rx_radiotap_header *tap = &sc->sc_rxtap;                  struct iwn_rx_radiotap_header *tap = &sc->sc_rxtap;
Line 2185  iwn_rx_done(struct iwn_softc *sc, struct
Line 2042  iwn_rx_done(struct iwn_softc *sc, struct
                 bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_rxtap_len, m);                  bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_rxtap_len, m);
         }          }
   
         /*  
          * If it's a beacon and we're waiting, then do the wakeup.  
          */  
         if (sc->sc_beacon_wait) {  
                 uint8_t type, subtype;  
                 type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;  
                 subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;  
                 /*  
                  * This assumes at this point we've received our own  
                  * beacon.  
                  */  
                 if (type == IEEE80211_FC0_TYPE_MGT &&  
                     subtype == IEEE80211_FC0_SUBTYPE_BEACON) {  
                         sc->sc_beacon_wait = 0;  
                         ifp->if_flags &= ~IFF_OACTIVE;  
                         iwn_start(ifp);  
                 }  
         }  
   
         /* Send the frame to the 802.11 layer. */          /* Send the frame to the 802.11 layer. */
         ieee80211_input(ic, m, ni, rssi, 0);          ieee80211_input(ic, m, ni, rssi, 0);
   
         /* Node is no longer needed. */          /* Node is no longer needed. */
         ieee80211_free_node(ni);          ieee80211_free_node(ni);
   
         splx(s);  
 }  }
   
 #ifndef IEEE80211_NO_HT  #ifndef IEEE80211_NO_HT
Line 2251  iwn5000_rx_calib_results(struct iwn_soft
Line 2087  iwn5000_rx_calib_results(struct iwn_soft
   
         switch (calib->code) {          switch (calib->code) {
         case IWN5000_PHY_CALIB_DC:          case IWN5000_PHY_CALIB_DC:
                 if (sc->hw_type == IWN_HW_REV_TYPE_5150 ||                  if (sc->hw_type == IWN_HW_REV_TYPE_5150)
                     sc->hw_type == IWN_HW_REV_TYPE_2030 ||  
                     sc->hw_type == IWN_HW_REV_TYPE_2000 ||  
                     sc->hw_type == IWN_HW_REV_TYPE_135  ||  
                     sc->hw_type == IWN_HW_REV_TYPE_105)  
                         idx = 0;                          idx = 0;
                 break;                  break;
         case IWN5000_PHY_CALIB_LO:          case IWN5000_PHY_CALIB_LO:
Line 2395  iwn_tx_done(struct iwn_softc *sc, struct
Line 2227  iwn_tx_done(struct iwn_softc *sc, struct
         struct iwn_tx_ring *ring = &sc->txq[desc->qid & 0xf];          struct iwn_tx_ring *ring = &sc->txq[desc->qid & 0xf];
         struct iwn_tx_data *data = &ring->data[desc->idx];          struct iwn_tx_data *data = &ring->data[desc->idx];
         struct iwn_node *wn = (struct iwn_node *)data->ni;          struct iwn_node *wn = (struct iwn_node *)data->ni;
         int s;  
   
         s = splnet();  
   
         /* Update rate control statistics. */          /* Update rate control statistics. */
         wn->amn.amn_txcnt++;          wn->amn.amn_txcnt++;
Line 2423  iwn_tx_done(struct iwn_softc *sc, struct
Line 2252  iwn_tx_done(struct iwn_softc *sc, struct
                 sc->qfullmsk &= ~(1 << ring->qid);                  sc->qfullmsk &= ~(1 << ring->qid);
                 if (sc->qfullmsk == 0 && (ifp->if_flags & IFF_OACTIVE)) {                  if (sc->qfullmsk == 0 && (ifp->if_flags & IFF_OACTIVE)) {
                         ifp->if_flags &= ~IFF_OACTIVE;                          ifp->if_flags &= ~IFF_OACTIVE;
                         iwn_start(ifp);                          (*ifp->if_start)(ifp);
                 }                  }
         }          }
   
         splx(s);  
 }  }
   
 /*  /*
Line 2466  iwn_notif_intr(struct iwn_softc *sc)
Line 2293  iwn_notif_intr(struct iwn_softc *sc)
         struct ieee80211com *ic = &sc->sc_ic;          struct ieee80211com *ic = &sc->sc_ic;
         struct ifnet *ifp = ic->ic_ifp;          struct ifnet *ifp = ic->ic_ifp;
         uint16_t hw;          uint16_t hw;
         int s;  
   
         bus_dmamap_sync(sc->sc_dmat, sc->rxq.stat_dma.map,          bus_dmamap_sync(sc->sc_dmat, sc->rxq.stat_dma.map,
             0, sc->rxq.stat_dma.size, BUS_DMASYNC_POSTREAD);              0, sc->rxq.stat_dma.size, BUS_DMASYNC_POSTREAD);
Line 2570  iwn_notif_intr(struct iwn_softc *sc)
Line 2396  iwn_notif_intr(struct iwn_softc *sc)
                                 aprint_error_dev(sc->sc_dev,                                  aprint_error_dev(sc->sc_dev,
                                     "Radio transmitter is off\n");                                      "Radio transmitter is off\n");
                                 /* Turn the interface down. */                                  /* Turn the interface down. */
                                 s = splnet();  
                                 ifp->if_flags &= ~IFF_UP;                                  ifp->if_flags &= ~IFF_UP;
                                 iwn_stop(ifp, 1);                                  iwn_stop(ifp, 1);
                                 splx(s);  
                                 return; /* No further processing. */                                  return; /* No further processing. */
                         }                          }
                         break;                          break;
Line 2608  iwn_notif_intr(struct iwn_softc *sc)
Line 2432  iwn_notif_intr(struct iwn_softc *sc)
                                  * We just finished scanning 2GHz channels,                                   * We just finished scanning 2GHz channels,
                                  * start scanning 5GHz ones.                                   * start scanning 5GHz ones.
                                  */                                   */
                                 sc->sc_flags &= ~IWN_FLAG_SCANNING_2GHZ;  
                                 sc->sc_flags |= IWN_FLAG_SCANNING_5GHZ;  
                                 if (iwn_scan(sc, IEEE80211_CHAN_5GHZ) == 0)                                  if (iwn_scan(sc, IEEE80211_CHAN_5GHZ) == 0)
                                         break;                                          break;
                         }                          }
Line 2721  static int
Line 2543  static int
 iwn_intr(void *arg)  iwn_intr(void *arg)
 {  {
         struct iwn_softc *sc = arg;          struct iwn_softc *sc = arg;
           struct ifnet *ifp = sc->sc_ic.ic_ifp;
           uint32_t r1, r2, tmp;
   
         /* Disable interrupts. */          /* Disable interrupts. */
         IWN_WRITE(sc, IWN_INT_MASK, 0);          IWN_WRITE(sc, IWN_INT_MASK, 0);
   
         softint_schedule(sc->sc_soft_ih);  
         return 1;  
 }  
   
 static void  
 iwn_softintr(void *arg)  
 {  
         struct iwn_softc *sc = arg;  
         struct ifnet *ifp = sc->sc_ic.ic_ifp;  
         uint32_t r1, r2, tmp;  
         int s;  
   
         /* Read interrupts from ICT (fast) or from registers (slow). */          /* Read interrupts from ICT (fast) or from registers (slow). */
         if (sc->sc_flags & IWN_FLAG_USE_ICT) {          if (sc->sc_flags & IWN_FLAG_USE_ICT) {
                 bus_dmamap_sync(sc->sc_dmat, sc->ict_dma.map, 0,  
                     IWN_ICT_SIZE, BUS_DMASYNC_POSTREAD);  
                 tmp = 0;                  tmp = 0;
                 while (sc->ict[sc->ict_cur] != 0) {                  while (sc->ict[sc->ict_cur] != 0) {
                         tmp |= sc->ict[sc->ict_cur];                          tmp |= sc->ict[sc->ict_cur];
                         sc->ict[sc->ict_cur] = 0;       /* Acknowledge. */                          sc->ict[sc->ict_cur] = 0;       /* Acknowledge. */
                         sc->ict_cur = (sc->ict_cur + 1) % IWN_ICT_COUNT;                          sc->ict_cur = (sc->ict_cur + 1) % IWN_ICT_COUNT;
                 }                  }
                 bus_dmamap_sync(sc->sc_dmat, sc->ict_dma.map, 0,  
                     IWN_ICT_SIZE, BUS_DMASYNC_PREWRITE);  
                 tmp = le32toh(tmp);                  tmp = le32toh(tmp);
                 if (tmp == 0xffffffff)  /* Shouldn't happen. */                  if (tmp == 0xffffffff)  /* Shouldn't happen. */
                         tmp = 0;                          tmp = 0;
Line 2759  iwn_softintr(void *arg)
Line 2567  iwn_softintr(void *arg)
         } else {          } else {
                 r1 = IWN_READ(sc, IWN_INT);                  r1 = IWN_READ(sc, IWN_INT);
                 if (r1 == 0xffffffff || (r1 & 0xfffffff0) == 0xa5a5a5a0)                  if (r1 == 0xffffffff || (r1 & 0xfffffff0) == 0xa5a5a5a0)
                         return; /* Hardware gone! */                          return 0;       /* Hardware gone! */
                 r2 = IWN_READ(sc, IWN_FH_INT);                  r2 = IWN_READ(sc, IWN_FH_INT);
         }          }
         if (r1 == 0 && r2 == 0) {          if (r1 == 0 && r2 == 0) {
                 goto out;       /* Interrupt not for us. */                  if (ifp->if_flags & IFF_UP)
                           IWN_WRITE(sc, IWN_INT_MASK, sc->int_mask);
                   return 0;       /* Interrupt not for us. */
         }          }
   
         /* Acknowledge interrupts. */          /* Acknowledge interrupts. */
Line 2786  iwn_softintr(void *arg)
Line 2596  iwn_softintr(void *arg)
                     "fatal firmware error\n");                      "fatal firmware error\n");
                 /* Dump firmware error log and stop. */                  /* Dump firmware error log and stop. */
                 iwn_fatal_intr(sc);                  iwn_fatal_intr(sc);
                 s = splnet();  
                 ifp->if_flags &= ~IFF_UP;                  ifp->if_flags &= ~IFF_UP;
                 iwn_stop(ifp, 1);                  iwn_stop(ifp, 1);
                 splx(s);                  return 1;
                 return;  
         }          }
         if ((r1 & (IWN_INT_FH_RX | IWN_INT_SW_RX | IWN_INT_RX_PERIODIC)) ||          if ((r1 & (IWN_INT_FH_RX | IWN_INT_SW_RX | IWN_INT_RX_PERIODIC)) ||
             (r2 & IWN_FH_INT_RX)) {              (r2 & IWN_FH_INT_RX)) {
                 if (sc->sc_flags & IWN_FLAG_USE_ICT) {                  if (sc->sc_flags & IWN_FLAG_USE_ICT) {
                         if (r1 & (IWN_INT_FH_RX | IWN_INT_SW_RX))                          if (r1 & (IWN_INT_FH_RX | IWN_INT_SW_RX))
                                 IWN_WRITE(sc, IWN_FH_INT, IWN_FH_INT_RX);                                  IWN_WRITE(sc, IWN_FH_INT, IWN_FH_INT_RX);
                         IWN_WRITE_1(sc, IWN_INT_PERIODIC, IWN_INT_PERIODIC_DIS);                          IWN_WRITE_1(sc, IWN_INT_PERIODIC,
                               IWN_INT_PERIODIC_DIS);
                         iwn_notif_intr(sc);                          iwn_notif_intr(sc);
                         if (r1 & (IWN_INT_FH_RX | IWN_INT_SW_RX)) {                          if (r1 & (IWN_INT_FH_RX | IWN_INT_SW_RX)) {
                                 IWN_WRITE_1(sc, IWN_INT_PERIODIC,                                  IWN_WRITE_1(sc, IWN_INT_PERIODIC,
Line 2819  iwn_softintr(void *arg)
Line 2628  iwn_softintr(void *arg)
         if (r1 & IWN_INT_WAKEUP)          if (r1 & IWN_INT_WAKEUP)
                 iwn_wakeup_intr(sc);                  iwn_wakeup_intr(sc);
   
 out:  
         /* Re-enable interrupts. */          /* Re-enable interrupts. */
         if (ifp->if_flags & IFF_UP)          if (ifp->if_flags & IFF_UP)
                 IWN_WRITE(sc, IWN_INT_MASK, sc->int_mask);                  IWN_WRITE(sc, IWN_INT_MASK, sc->int_mask);
   
           return 1;
 }  }
   
 /*  /*
Line 2916  iwn_tx(struct iwn_softc *sc, struct mbuf
Line 2726  iwn_tx(struct iwn_softc *sc, struct mbuf
         hdrlen = ieee80211_anyhdrsize(wh);          hdrlen = ieee80211_anyhdrsize(wh);
         type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;          type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
   
         hdrlen2 = (ieee80211_has_qos(wh)) ?          hdrlen2 = (IEEE80211_QOS_HAS_SEQ(wh)) ?
             sizeof (struct ieee80211_qosframe) :              sizeof (struct ieee80211_qosframe) :
             sizeof (struct ieee80211_frame);              sizeof (struct ieee80211_frame);
   
Line 2926  iwn_tx(struct iwn_softc *sc, struct mbuf
Line 2736  iwn_tx(struct iwn_softc *sc, struct mbuf
   
         /* XXX OpenBSD sets a different tid when using QOS */          /* XXX OpenBSD sets a different tid when using QOS */
         tid = 0;          tid = 0;
         if (ieee80211_has_qos(wh)) {          if (IEEE80211_QOS_HAS_SEQ(wh)) {
                 cap = &ic->ic_wme.wme_chanParams;                  cap = &ic->ic_wme.wme_chanParams;
                 noack = cap->cap_wmeParams[ac].wmep_noackPolicy;                  noack = cap->cap_wmeParams[ac].wmep_noackPolicy;
         }          }
Line 3192  iwn_start(struct ifnet *ifp)
Line 3002  iwn_start(struct ifnet *ifp)
                 return;                  return;
   
         for (;;) {          for (;;) {
                 if (sc->sc_beacon_wait == 1) {  
                         ifp->if_flags |= IFF_OACTIVE;  
                         break;  
                 }  
   
                 if (sc->qfullmsk != 0) {                  if (sc->qfullmsk != 0) {
                         ifp->if_flags |= IFF_OACTIVE;                          ifp->if_flags |= IFF_OACTIVE;
                         break;                          break;
Line 3204  iwn_start(struct ifnet *ifp)
Line 3009  iwn_start(struct ifnet *ifp)
                 /* Send pending management frames first. */                  /* Send pending management frames first. */
                 IF_DEQUEUE(&ic->ic_mgtq, m);                  IF_DEQUEUE(&ic->ic_mgtq, m);
                 if (m != NULL) {                  if (m != NULL) {
                         ni = M_GETCTX(m, struct ieee80211_node *);                          ni = (void *)m->m_pkthdr.rcvif;
                         ac = 0;                          ac = 0;
                         goto sendit;                          goto sendit;
                 }                  }
Line 3239  iwn_start(struct ifnet *ifp)
Line 3044  iwn_start(struct ifnet *ifp)
                 ac = (eh->ether_type != htons(ETHERTYPE_PAE)) ?                  ac = (eh->ether_type != htons(ETHERTYPE_PAE)) ?
                     M_WME_GETAC(m) : WME_AC_BE;                      M_WME_GETAC(m) : WME_AC_BE;
   
                 if (sc->sc_beacon_wait == 0)                  bpf_mtap(ifp, m);
                         bpf_mtap(ifp, m);  
   
                 if ((m = ieee80211_encap(ic, m, ni)) == NULL) {                  if ((m = ieee80211_encap(ic, m, ni)) == NULL) {
                         ieee80211_free_node(ni);                          ieee80211_free_node(ni);
Line 3248  iwn_start(struct ifnet *ifp)
Line 3052  iwn_start(struct ifnet *ifp)
                         continue;                          continue;
                 }                  }
 sendit:  sendit:
                 if (sc->sc_beacon_wait)  
                         continue;  
   
                 bpf_mtap3(ic->ic_rawbpf, m);                  bpf_mtap3(ic->ic_rawbpf, m);
   
                 if (iwn_tx(sc, m, ni, ac) != 0) {                  if (iwn_tx(sc, m, ni, ac) != 0) {
Line 3262  sendit:
Line 3063  sendit:
                 sc->sc_tx_timer = 5;                  sc->sc_tx_timer = 5;
                 ifp->if_timer = 1;                  ifp->if_timer = 1;
         }          }
   
         if (sc->sc_beacon_wait > 1)  
                 sc->sc_beacon_wait = 0;  
 }  }
   
 static void  static void
Line 3294  iwn_ioctl(struct ifnet *ifp, u_long cmd,
Line 3092  iwn_ioctl(struct ifnet *ifp, u_long cmd,
 {  {
         struct iwn_softc *sc = ifp->if_softc;          struct iwn_softc *sc = ifp->if_softc;
         struct ieee80211com *ic = &sc->sc_ic;          struct ieee80211com *ic = &sc->sc_ic;
           struct ifaddr *ifa;
         const struct sockaddr *sa;          const struct sockaddr *sa;
         int s, error = 0;          int s, error = 0;
   
Line 3301  iwn_ioctl(struct ifnet *ifp, u_long cmd,
Line 3100  iwn_ioctl(struct ifnet *ifp, u_long cmd,
   
         switch (cmd) {          switch (cmd) {
         case SIOCSIFADDR:          case SIOCSIFADDR:
                   ifa = (struct ifaddr *)data;
                 ifp->if_flags |= IFF_UP;                  ifp->if_flags |= IFF_UP;
   #ifdef INET
                   if (ifa->ifa_addr->sa_family == AF_INET)
                           arp_ifinit(&ic->ic_ac, ifa);
   #endif
                 /* FALLTHROUGH */                  /* FALLTHROUGH */
         case SIOCSIFFLAGS:          case SIOCSIFFLAGS:
                 /* XXX Added as it is in every NetBSD driver */                  /* XXX Added as it is in every NetBSD driver */
Line 3757  static int
Line 3561  static int
 iwn5000_set_txpower(struct iwn_softc *sc, int async)  iwn5000_set_txpower(struct iwn_softc *sc, int async)
 {  {
         struct iwn5000_cmd_txpower cmd;          struct iwn5000_cmd_txpower cmd;
         int cmdid;  
   
         /*          /*
          * TX power calibration is handled automatically by the firmware           * TX power calibration is handled automatically by the firmware
Line 3768  iwn5000_set_txpower(struct iwn_softc *sc
Line 3571  iwn5000_set_txpower(struct iwn_softc *sc
         cmd.flags = IWN5000_TXPOWER_NO_CLOSED;          cmd.flags = IWN5000_TXPOWER_NO_CLOSED;
         cmd.srv_limit = IWN5000_TXPOWER_AUTO;          cmd.srv_limit = IWN5000_TXPOWER_AUTO;
         DPRINTF(("setting TX power\n"));          DPRINTF(("setting TX power\n"));
         if (IWN_UCODE_API(sc->ucode_rev) == 1)          return iwn_cmd(sc, IWN_CMD_TXPOWER_DBM, &cmd, sizeof cmd, async);
                 cmdid = IWN_CMD_TXPOWER_DBM_V1;  
         else  
                 cmdid = IWN_CMD_TXPOWER_DBM;  
         return iwn_cmd(sc, cmdid, &cmd, sizeof cmd, async);  
 }  }
   
 /*  /*
Line 3988  iwn5000_init_gains(struct iwn_softc *sc)
Line 3787  iwn5000_init_gains(struct iwn_softc *sc)
         struct iwn_phy_calib cmd;          struct iwn_phy_calib cmd;
   
         memset(&cmd, 0, sizeof cmd);          memset(&cmd, 0, sizeof cmd);
         cmd.code = sc->reset_noise_gain;          cmd.code = IWN5000_PHY_CALIB_RESET_NOISE_GAIN;
         cmd.ngroups = 1;          cmd.ngroups = 1;
         cmd.isvalid = 1;          cmd.isvalid = 1;
         DPRINTF(("setting initial differential gains\n"));          DPRINTF(("setting initial differential gains\n"));
Line 4038  iwn5000_set_gains(struct iwn_softc *sc)
Line 3837  iwn5000_set_gains(struct iwn_softc *sc)
         div = (sc->hw_type == IWN_HW_REV_TYPE_6050) ? 20 : 30;          div = (sc->hw_type == IWN_HW_REV_TYPE_6050) ? 20 : 30;
   
         memset(&cmd, 0, sizeof cmd);          memset(&cmd, 0, sizeof cmd);
         cmd.code = sc->noise_gain;          cmd.code = IWN5000_PHY_CALIB_NOISE_GAIN;
         cmd.ngroups = 1;          cmd.ngroups = 1;
         cmd.isvalid = 1;          cmd.isvalid = 1;
         /* Get first available RX antenna as referential. */          /* Get first available RX antenna as referential. */
Line 4214  static int
Line 4013  static int
 iwn_send_sensitivity(struct iwn_softc *sc)  iwn_send_sensitivity(struct iwn_softc *sc)
 {  {
         struct iwn_calib_state *calib = &sc->calib;          struct iwn_calib_state *calib = &sc->calib;
         struct iwn_enhanced_sensitivity_cmd cmd;          struct iwn_sensitivity_cmd cmd;
         int len;  
   
         memset(&cmd, 0, sizeof cmd);          memset(&cmd, 0, sizeof cmd);
         len = sizeof (struct iwn_sensitivity_cmd);  
         cmd.which = IWN_SENSITIVITY_WORKTBL;          cmd.which = IWN_SENSITIVITY_WORKTBL;
         /* OFDM modulation. */          /* OFDM modulation. */
         cmd.corr_ofdm_x1     = htole16(calib->ofdm_x1);          cmd.corr_ofdm_x1     = htole16(calib->ofdm_x1);
Line 4233  iwn_send_sensitivity(struct iwn_softc *s
Line 4030  iwn_send_sensitivity(struct iwn_softc *s
         cmd.energy_cck       = htole16(calib->energy_cck);          cmd.energy_cck       = htole16(calib->energy_cck);
         /* Barker modulation: use default values. */          /* Barker modulation: use default values. */
         cmd.corr_barker      = htole16(190);          cmd.corr_barker      = htole16(190);
         cmd.corr_barker_mrc  = htole16(sc->limits->barker_mrc);          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:  
         DPRINTFN(2, ("setting sensitivity %d/%d/%d/%d/%d/%d/%d\n",          DPRINTFN(2, ("setting sensitivity %d/%d/%d/%d/%d/%d/%d\n",
             calib->ofdm_x1, calib->ofdm_mrc_x1, calib->ofdm_x4,              calib->ofdm_x1, calib->ofdm_mrc_x1, calib->ofdm_x4,
             calib->ofdm_mrc_x4, calib->cck_x4, calib->cck_mrc_x4,              calib->ofdm_mrc_x4, calib->cck_x4, calib->cck_mrc_x4,
             calib->energy_cck));              calib->energy_cck));
         return iwn_cmd(sc, IWN_CMD_SET_SENSITIVITY, &cmd, len, 1);          return iwn_cmd(sc, IWN_CMD_SET_SENSITIVITY, &cmd, sizeof cmd, 1);
 }  }
   
 /*  /*
Line 4282  iwn_set_pslevel(struct iwn_softc *sc, in
Line 4067  iwn_set_pslevel(struct iwn_softc *sc, in
                 cmd.flags |= htole16(IWN_PS_FAST_PD);                  cmd.flags |= htole16(IWN_PS_FAST_PD);
         /* Retrieve PCIe Active State Power Management (ASPM). */          /* Retrieve PCIe Active State Power Management (ASPM). */
         reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag,          reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag,
             sc->sc_cap_off + PCIE_LCSR);              sc->sc_cap_off + PCI_PCIE_LCSR);
         if (!(reg & PCIE_LCSR_ASPM_L0S))        /* L0s Entry disabled. */          if (!(reg & PCI_PCIE_LCSR_ASPM_L0S))    /* L0s Entry disabled. */
                 cmd.flags |= htole16(IWN_PS_PCI_PMGT);                  cmd.flags |= htole16(IWN_PS_PCI_PMGT);
         cmd.rxtimeout = htole32(pmgt->rxtimeout * 1024);          cmd.rxtimeout = htole32(pmgt->rxtimeout * 1024);
         cmd.txtimeout = htole32(pmgt->txtimeout * 1024);          cmd.txtimeout = htole32(pmgt->txtimeout * 1024);
Line 4322  iwn5000_runtime_calib(struct iwn_softc *
Line 4107  iwn5000_runtime_calib(struct iwn_softc *
 }  }
   
 static int  static int
 iwn_config_bt_coex_bluetooth(struct iwn_softc *sc)  
 {  
         struct iwn_bluetooth bluetooth;  
   
         memset(&bluetooth, 0, sizeof bluetooth);  
         bluetooth.flags = IWN_BT_COEX_ENABLE;  
         bluetooth.lead_time = IWN_BT_LEAD_TIME_DEF;  
         bluetooth.max_kill = IWN_BT_MAX_KILL_DEF;  
   
         DPRINTF(("configuring bluetooth coexistence\n"));  
         return iwn_cmd(sc, IWN_CMD_BT_COEX, &bluetooth, sizeof bluetooth, 0);  
 }  
   
 static int  
 iwn_config_bt_coex_prio_table(struct iwn_softc *sc)  
 {  
         uint8_t prio_table[16];  
   
         memset(&prio_table, 0, sizeof prio_table);  
         prio_table[ 0] =  6;    /* init calibration 1           */  
         prio_table[ 1] =  7;    /* init calibration 2           */  
         prio_table[ 2] =  2;    /* periodic calib low 1         */  
         prio_table[ 3] =  3;    /* periodic calib low 2         */  
         prio_table[ 4] =  4;    /* periodic calib high 1        */  
         prio_table[ 5] =  5;    /* periodic calib high 2        */  
         prio_table[ 6] =  6;    /* dtim                         */  
         prio_table[ 7] =  8;    /* scan52                       */  
         prio_table[ 8] = 10;    /* scan24                       */  
   
         DPRINTF(("sending priority lookup table\n"));  
         return iwn_cmd(sc, IWN_CMD_BT_COEX_PRIO_TABLE,  
                        &prio_table, sizeof prio_table, 0);  
 }  
   
 static int  
 iwn_config_bt_coex_adv_config(struct iwn_softc *sc, struct iwn_bt_basic *basic,  
     size_t len)  
 {  
         struct iwn_btcoex_prot btprot;  
         int error;  
   
         basic->bt.flags = IWN_BT_COEX_ENABLE;  
         basic->bt.lead_time = IWN_BT_LEAD_TIME_DEF;  
         basic->bt.max_kill = IWN_BT_MAX_KILL_DEF;  
         basic->bt.bt3_timer_t7_value = IWN_BT_BT3_T7_DEF;  
         basic->bt.kill_ack_mask = IWN_BT_KILL_ACK_MASK_DEF;  
         basic->bt.kill_cts_mask = IWN_BT_KILL_CTS_MASK_DEF;  
         basic->bt3_prio_sample_time = IWN_BT_BT3_PRIO_SAMPLE_DEF;  
         basic->bt3_timer_t2_value = IWN_BT_BT3_T2_DEF;  
         basic->bt3_lookup_table[ 0] = htole32(0xaaaaaaaa); /* Normal */  
         basic->bt3_lookup_table[ 1] = htole32(0xaaaaaaaa);  
         basic->bt3_lookup_table[ 2] = htole32(0xaeaaaaaa);  
         basic->bt3_lookup_table[ 3] = htole32(0xaaaaaaaa);  
         basic->bt3_lookup_table[ 4] = htole32(0xcc00ff28);  
         basic->bt3_lookup_table[ 5] = htole32(0x0000aaaa);  
         basic->bt3_lookup_table[ 6] = htole32(0xcc00aaaa);  
         basic->bt3_lookup_table[ 7] = htole32(0x0000aaaa);  
         basic->bt3_lookup_table[ 8] = htole32(0xc0004000);  
         basic->bt3_lookup_table[ 9] = htole32(0x00004000);  
         basic->bt3_lookup_table[10] = htole32(0xf0005000);  
         basic->bt3_lookup_table[11] = htole32(0xf0005000);  
         basic->reduce_txpower = 0; /* as not implemented */  
         basic->valid = IWN_BT_ALL_VALID_MASK;  
   
         DPRINTF(("configuring advanced bluetooth coexistence v1\n"));  
         error = iwn_cmd(sc, IWN_CMD_BT_COEX, basic, len, 0);  
         if (error != 0) {  
                 aprint_error_dev(sc->sc_dev,  
                         "could not configure advanced bluetooth coexistence\n");  
                 return error;  
         }  
   
         error = iwn_config_bt_coex_prio_table(sc);  
         if (error != 0) {  
                 aprint_error_dev(sc->sc_dev,  
                         "could not configure send BT priority table\n");  
                 return error;  
         }  
   
         /* Force BT state machine change */  
         memset(&btprot, 0, sizeof btprot);  
         btprot.open = 1;  
         btprot.type = 1;  
         error = iwn_cmd(sc, IWN_CMD_BT_COEX_PROT, &btprot, sizeof btprot, 1);  
         if (error != 0) {  
                 aprint_error_dev(sc->sc_dev, "could not open BT protcol\n");  
                 return error;  
         }  
   
         btprot.open = 0;  
         error = iwn_cmd(sc, IWN_CMD_BT_COEX_PROT, &btprot, sizeof btprot, 1);  
         if (error != 0) {  
                 aprint_error_dev(sc->sc_dev, "could not close BT protcol\n");  
                 return error;  
         }  
         return 0;  
 }  
   
 static int  
 iwn_config_bt_coex_adv1(struct iwn_softc *sc)  
 {  
         struct iwn_bt_adv1 d;  
   
         memset(&d, 0, sizeof d);  
         d.prio_boost = IWN_BT_PRIO_BOOST_DEF;  
         d.tx_prio_boost = 0;  
         d.rx_prio_boost = 0;  
         return iwn_config_bt_coex_adv_config(sc, &d.basic, sizeof d);  
 }  
   
 static int  
 iwn_config_bt_coex_adv2(struct iwn_softc *sc)  
 {  
         struct iwn_bt_adv2 d;  
   
         memset(&d, 0, sizeof d);  
         d.prio_boost = IWN_BT_PRIO_BOOST_DEF;  
         d.tx_prio_boost = 0;  
         d.rx_prio_boost = 0;  
         return iwn_config_bt_coex_adv_config(sc, &d.basic, sizeof d);  
 }  
   
 static int  
 iwn_config(struct iwn_softc *sc)  iwn_config(struct iwn_softc *sc)
 {  {
         struct iwn_ops *ops = &sc->ops;          struct iwn_ops *ops = &sc->ops;
         struct ieee80211com *ic = &sc->sc_ic;          struct ieee80211com *ic = &sc->sc_ic;
         struct ifnet *ifp = ic->ic_ifp;          struct ifnet *ifp = ic->ic_ifp;
           struct iwn_bluetooth bluetooth;
         uint32_t txmask;          uint32_t txmask;
         uint16_t rxchain;          uint16_t rxchain;
         int error;          int error;
   
         error = ops->config_bt_coex(sc);  
         if (error != 0) {  
                 aprint_error_dev(sc->sc_dev,  
                         "could not configure bluetooth coexistence\n");  
                 return error;  
         }  
   
         /* Set radio temperature sensor offset. */  
         if (sc->hw_type == IWN_HW_REV_TYPE_6005) {  
                 error = iwn6000_temp_offset_calib(sc);  
                 if (error != 0) {  
                         aprint_error_dev(sc->sc_dev,  
                             "could not set temperature offset\n");  
                         return error;  
                 }  
         }  
   
         if (sc->hw_type == IWN_HW_REV_TYPE_2030 ||  
             sc->hw_type == IWN_HW_REV_TYPE_2000 ||  
             sc->hw_type == IWN_HW_REV_TYPE_135  ||  
             sc->hw_type == IWN_HW_REV_TYPE_105) {  
                 error = iwn2000_temp_offset_calib(sc);  
                 if (error != 0) {  
                         aprint_error_dev(sc->sc_dev,  
                             "could not set temperature offset\n");  
                         return error;  
                 }  
         }  
   
         if (sc->hw_type == IWN_HW_REV_TYPE_6050 ||          if (sc->hw_type == IWN_HW_REV_TYPE_6050 ||
             sc->hw_type == IWN_HW_REV_TYPE_6005) {              sc->hw_type == IWN_HW_REV_TYPE_6005) {
                 /* Configure runtime DC calibration. */                  /* Configure runtime DC calibration. */
Line 4507  iwn_config(struct iwn_softc *sc)
Line 4141  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);
           if (error != 0) {
                   aprint_error_dev(sc->sc_dev,
                       "could not configure bluetooth coexistence\n");
                   return error;
           }
   
         /* Set mode, channel, RX filter and enable RX. */          /* Set mode, channel, RX filter and enable RX. */
         memset(&sc->rxon, 0, sizeof (struct iwn_rxon));          memset(&sc->rxon, 0, sizeof (struct iwn_rxon));
         IEEE80211_ADDR_COPY(ic->ic_myaddr, CLLADDR(ifp->if_sadl));          IEEE80211_ADDR_COPY(ic->ic_myaddr, CLLADDR(ifp->if_sadl));
Line 4576  iwn_config(struct iwn_softc *sc)
Line 4223  iwn_config(struct iwn_softc *sc)
         return 0;          return 0;
 }  }
   
 static uint16_t  
 iwn_get_active_dwell_time(struct iwn_softc *sc, uint16_t flags,  
     uint8_t n_probes)  
 {  
         /* No channel? Default to 2GHz settings */  
         if (flags & IEEE80211_CHAN_2GHZ)  
                 return IWN_ACTIVE_DWELL_TIME_2GHZ +  
                     IWN_ACTIVE_DWELL_FACTOR_2GHZ * (n_probes + 1);  
   
         /* 5GHz dwell time */  
         return IWN_ACTIVE_DWELL_TIME_5GHZ +  
             IWN_ACTIVE_DWELL_FACTOR_5GHZ * (n_probes + 1);  
 }  
   
 /*  
  * Limit the total dwell time to 85% of the beacon interval.  
  *  
  * Returns the dwell time in milliseconds.  
  */  
 static uint16_t  
 iwn_limit_dwell(struct iwn_softc *sc, uint16_t dwell_time)  
 {  
         struct ieee80211com *ic = &sc->sc_ic;  
         struct ieee80211_node *ni = ic->ic_bss;  
         int bintval = 0;  
   
         /* bintval is in TU (1.024mS) */  
         if (ni != NULL)  
                 bintval = ni->ni_intval;  
   
         /*  
          * If it's non-zero, we should calculate the minimum of  
          * it and the DWELL_BASE.  
          *  
          * XXX Yes, the math should take into account that bintval  
          * is 1.024mS, not 1mS..  
          */  
         if (bintval > 0)  
                 return MIN(IWN_PASSIVE_DWELL_BASE, ((bintval * 85) / 100));  
   
         /* No association context? Default */  
         return IWN_PASSIVE_DWELL_BASE;  
 }  
   
 static uint16_t  
 iwn_get_passive_dwell_time(struct iwn_softc *sc, uint16_t flags)  
 {  
         uint16_t passive;  
         if (flags & IEEE80211_CHAN_2GHZ)  
                 passive = IWN_PASSIVE_DWELL_BASE + IWN_PASSIVE_DWELL_TIME_2GHZ;  
         else  
                 passive = IWN_PASSIVE_DWELL_BASE + IWN_PASSIVE_DWELL_TIME_5GHZ;  
   
         /* Clamp to the beacon interval if we're associated */  
         return iwn_limit_dwell(sc, passive);  
 }  
   
 static int  static int
 iwn_scan(struct iwn_softc *sc, uint16_t flags)  iwn_scan(struct iwn_softc *sc, uint16_t flags)
 {  {
Line 4645  iwn_scan(struct iwn_softc *sc, uint16_t 
Line 4235  iwn_scan(struct iwn_softc *sc, uint16_t 
         struct ieee80211_rateset *rs;          struct ieee80211_rateset *rs;
         struct ieee80211_channel *c;          struct ieee80211_channel *c;
         uint8_t *buf, *frm;          uint8_t *buf, *frm;
         uint16_t rxchain, dwell_active, dwell_passive;          uint16_t rxchain;
         uint8_t txant;          uint8_t txant;
         int buflen, error, is_active;          int buflen, error;
   
         buf = malloc(IWN_SCAN_MAXSZ, M_DEVBUF, M_NOWAIT | M_ZERO);          buf = malloc(IWN_SCAN_MAXSZ, M_DEVBUF, M_NOWAIT | M_ZERO);
         if (buf == NULL) {          if (buf == NULL) {
Line 4698  iwn_scan(struct iwn_softc *sc, uint16_t 
Line 4288  iwn_scan(struct iwn_softc *sc, uint16_t 
         txant = IWN_LSB(sc->txchainmask);          txant = IWN_LSB(sc->txchainmask);
         tx->rflags |= IWN_RFLAG_ANT(txant);          tx->rflags |= IWN_RFLAG_ANT(txant);
   
         /*  
          * Only do active scanning if we're announcing a probe request  
          * for a given SSID (or more, if we ever add it to the driver.)  
          */  
         is_active = 0;  
   
         essid = (struct iwn_scan_essid *)(tx + 1);          essid = (struct iwn_scan_essid *)(tx + 1);
         if (ic->ic_des_esslen != 0) {          if (ic->ic_des_esslen != 0) {
                 essid[0].id = IEEE80211_ELEMID_SSID;                  essid[0].id = IEEE80211_ELEMID_SSID;
                 essid[0].len = ic->ic_des_esslen;                  essid[0].len = ic->ic_des_esslen;
                 memcpy(essid[0].data, ic->ic_des_essid, ic->ic_des_esslen);                  memcpy(essid[0].data, ic->ic_des_essid, ic->ic_des_esslen);
   
                 is_active = 1;  
         }          }
         /*          /*
          * Build a probe request frame.  Most of the following code is a           * Build a probe request frame.  Most of the following code is a
Line 4739  iwn_scan(struct iwn_softc *sc, uint16_t 
Line 4321  iwn_scan(struct iwn_softc *sc, uint16_t 
         /* Set length of probe request. */          /* Set length of probe request. */
         tx->len = htole16(frm - (uint8_t *)wh);          tx->len = htole16(frm - (uint8_t *)wh);
   
   
         /*  
          * If active scanning is requested but a certain channel is  
          * marked passive, we can do active scanning if we detect  
          * transmissions.  
          *  
          * There is an issue with some firmware versions that triggers  
          * a sysassert on a "good CRC threshold" of zero (== disabled),  
          * on a radar channel even though this means that we should NOT  
          * send probes.  
          *  
          * The "good CRC threshold" is the number of frames that we  
          * need to receive during our dwell time on a channel before  
          * sending out probes -- setting this to a huge value will  
          * mean we never reach it, but at the same time work around  
          * the aforementioned issue. Thus use IWN_GOOD_CRC_TH_NEVER  
          * here instead of IWN_GOOD_CRC_TH_DISABLED.  
          *  
          * This was fixed in later versions along with some other  
          * scan changes, and the threshold behaves as a flag in those  
          * versions.  
          */  
   
         /*  
          * If we're doing active scanning, set the crc_threshold  
          * to a suitable value.  This is different to active veruss  
          * passive scanning depending upon the channel flags; the  
          * firmware will obey that particular check for us.  
          */  
         if (sc->tlv_feature_flags & IWN_UCODE_TLV_FLAGS_NEWSCAN)  
                 hdr->crc_threshold = is_active ?  
                     IWN_GOOD_CRC_TH_DEFAULT : IWN_GOOD_CRC_TH_DISABLED;  
         else  
                 hdr->crc_threshold = is_active ?  
                     IWN_GOOD_CRC_TH_DEFAULT : IWN_GOOD_CRC_TH_NEVER;  
   
         chan = (struct iwn_scan_chan *)frm;          chan = (struct iwn_scan_chan *)frm;
         for (c  = &ic->ic_channels[1];          for (c  = &ic->ic_channels[1];
              c <= &ic->ic_channels[IEEE80211_CHAN_MAX]; c++) {               c <= &ic->ic_channels[IEEE80211_CHAN_MAX]; c++) {
Line 4788  iwn_scan(struct iwn_softc *sc, uint16_t 
Line 4334  iwn_scan(struct iwn_softc *sc, uint16_t 
                         chan->flags |= htole32(IWN_CHAN_ACTIVE);                          chan->flags |= htole32(IWN_CHAN_ACTIVE);
                 if (ic->ic_des_esslen != 0)                  if (ic->ic_des_esslen != 0)
                         chan->flags |= htole32(IWN_CHAN_NPBREQS(1));                          chan->flags |= htole32(IWN_CHAN_NPBREQS(1));
   
                 /*  
                  * Calculate the active/passive dwell times.  
                  */  
   
                 dwell_active = iwn_get_active_dwell_time(sc, flags, is_active);  
                 dwell_passive = iwn_get_passive_dwell_time(sc, flags);  
   
                 /* Make sure they're valid */  
                 if (dwell_passive <= dwell_active)  
                         dwell_passive = dwell_active + 1;  
   
                 chan->active = htole16(dwell_active);  
                 chan->passive = htole16(dwell_passive);  
   
                 chan->dsp_gain = 0x6e;                  chan->dsp_gain = 0x6e;
                 if (IEEE80211_IS_CHAN_5GHZ(c)) {                  if (IEEE80211_IS_CHAN_5GHZ(c)) {
                         chan->rf_gain = 0x3b;                          chan->rf_gain = 0x3b;
                           chan->active  = htole16(24);
                           chan->passive = htole16(110);
                 } else {                  } else {
                         chan->rf_gain = 0x28;                          chan->rf_gain = 0x28;
                           chan->active  = htole16(36);
                           chan->passive = htole16(120);
                 }                  }
                 hdr->nchan++;                  hdr->nchan++;
                 chan++;                  chan++;
Line 5355  iwn5000_send_wimax_coex(struct iwn_softc
Line 4890  iwn5000_send_wimax_coex(struct iwn_softc
         return iwn_cmd(sc, IWN5000_CMD_WIMAX_COEX, &wimax, sizeof wimax, 0);          return iwn_cmd(sc, IWN5000_CMD_WIMAX_COEX, &wimax, sizeof wimax, 0);
 }  }
   
 static int  
 iwn6000_temp_offset_calib(struct iwn_softc *sc)  
 {  
         struct iwn6000_phy_calib_temp_offset cmd;  
   
         memset(&cmd, 0, sizeof cmd);  
         cmd.code = IWN6000_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", le16toh(cmd.offset)));  
         return iwn_cmd(sc, IWN_CMD_PHY_CALIB, &cmd, sizeof cmd, 0);  
 }  
   
 static int  
 iwn2000_temp_offset_calib(struct iwn_softc *sc)  
 {  
         struct iwn2000_phy_calib_temp_offset cmd;  
   
         memset(&cmd, 0, sizeof cmd);  
         cmd.code = IWN2000_PHY_CALIB_TEMP_OFFSET;  
         cmd.ngroups = 1;  
         cmd.isvalid = 1;  
         if (sc->eeprom_rawtemp != 0) {  
                 cmd.offset_low = htole16(sc->eeprom_rawtemp);  
                 cmd.offset_high = htole16(sc->eeprom_temp);  
         } else {  
                 cmd.offset_low = htole16(IWN_DEFAULT_TEMP_OFFSET);  
                 cmd.offset_high = htole16(IWN_DEFAULT_TEMP_OFFSET);  
         }  
         cmd.burnt_voltage_ref = htole16(sc->eeprom_voltage);  
         DPRINTF(("setting radio sensor offset to %d:%d, voltage to %d\n",  
             le16toh(cmd.offset_low), le16toh(cmd.offset_high),  
             le16toh(cmd.burnt_voltage_ref)));  
         return iwn_cmd(sc, IWN_CMD_PHY_CALIB, &cmd, sizeof cmd, 0);  
 }  
   
 /*  /*
  * This function is called after the runtime firmware notifies us of its   * This function is called after the runtime firmware notifies us of its
  * readiness (called in a process context).   * readiness (called in a process context).
Line 5744  iwn_read_firmware_leg(struct iwn_softc *
Line 5239  iwn_read_firmware_leg(struct iwn_softc *
         ptr = (const uint32_t *)fw->data;          ptr = (const uint32_t *)fw->data;
         rev = le32toh(*ptr++);          rev = le32toh(*ptr++);
   
         sc->ucode_rev = rev;  
   
         /* Check firmware API version. */          /* Check firmware API version. */
         if (IWN_FW_API(rev) <= 1) {          if (IWN_FW_API(rev) <= 1) {
                 aprint_error_dev(sc->sc_dev,                  aprint_error_dev(sc->sc_dev,
Line 5811  iwn_read_firmware_tlv(struct iwn_softc *
Line 5304  iwn_read_firmware_tlv(struct iwn_softc *
         }          }
         DPRINTF(("FW: \"%.64s\", build 0x%x\n", hdr->descr,          DPRINTF(("FW: \"%.64s\", build 0x%x\n", hdr->descr,
             le32toh(hdr->build)));              le32toh(hdr->build)));
         sc->ucode_rev = le32toh(hdr->rev);  
   
         /*          /*
          * Select the closest supported alternative that is less than           * Select the closest supported alternative that is less than
Line 5861  iwn_read_firmware_tlv(struct iwn_softc *
Line 5353  iwn_read_firmware_tlv(struct iwn_softc *
                         fw->boot.text = ptr;                          fw->boot.text = ptr;
                         fw->boot.textsz = len;                          fw->boot.textsz = len;
                         break;                          break;
                 case IWN_FW_TLV_ENH_SENS:  
                         if (len != 0) {  
                                 aprint_error_dev(sc->sc_dev,  
                                     "TLV type %d has invalid size %u\n",  
                                     le16toh(tlv->type), len);  
                                 goto next;  
                         }  
                         sc->sc_flags |= IWN_FLAG_ENH_SENS;  
                         break;  
                 case IWN_FW_TLV_PHY_CALIB:  
                         if (len != sizeof(uint32_t)) {  
                                 aprint_error_dev(sc->sc_dev,  
                                     "TLV type %d has invalid size %u\n",  
                                     le16toh(tlv->type), len);  
                                 goto next;  
                         }  
                         if (le32toh(*ptr) <= IWN5000_PHY_CALIB_MAX) {  
                                 sc->reset_noise_gain = le32toh(*ptr);  
                                 sc->noise_gain = le32toh(*ptr) + 1;  
                         }  
                         break;  
                 case IWN_FW_TLV_FLAGS:  
                         if (len < sizeof(uint32_t))  
                                 break;  
                         if (len % sizeof(uint32_t))  
                                 break;  
                         sc->tlv_feature_flags = le32toh(*ptr);  
                         DPRINTF(("feature: 0x%08x\n", sc->tlv_feature_flags));  
                         break;  
                 default:                  default:
                         DPRINTF(("TLV type %d not handled\n",                          DPRINTF(("TLV type %d not handled\n",
                             le16toh(tlv->type)));                              le16toh(tlv->type)));
Line 5908  iwn_read_firmware(struct iwn_softc *sc)
Line 5371  iwn_read_firmware(struct iwn_softc *sc)
         firmware_handle_t fwh;          firmware_handle_t fwh;
         int error;          int error;
   
         /*  
          * Some PHY calibration commands are firmware-dependent; these  
          * are the default values that will be overridden if  
          * necessary.  
          */  
         sc->reset_noise_gain = IWN5000_PHY_CALIB_RESET_NOISE_GAIN;  
         sc->noise_gain = IWN5000_PHY_CALIB_NOISE_GAIN;  
   
         /* Initialize for error returns */          /* Initialize for error returns */
         fw->data = NULL;          fw->data = NULL;
         fw->size = 0;          fw->size = 0;
Line 6020  iwn_apm_init(struct iwn_softc *sc)
Line 5475  iwn_apm_init(struct iwn_softc *sc)
   
         /* Retrieve PCIe Active State Power Management (ASPM). */          /* Retrieve PCIe Active State Power Management (ASPM). */
         reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag,          reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag,
             sc->sc_cap_off + PCIE_LCSR);              sc->sc_cap_off + PCI_PCIE_LCSR);
         /* Workaround for HW instability in PCIe L0->L0s->L1 transition. */          /* Workaround for HW instability in PCIe L0->L0s->L1 transition. */
         if (reg & PCIE_LCSR_ASPM_L1)    /* L1 Entry enabled. */          if (reg & PCI_PCIE_LCSR_ASPM_L1)        /* L1 Entry enabled. */
                 IWN_SETBITS(sc, IWN_GIO, IWN_GIO_L0S_ENA);                  IWN_SETBITS(sc, IWN_GIO, IWN_GIO_L0S_ENA);
         else          else
                 IWN_CLRBITS(sc, IWN_GIO, IWN_GIO_L0S_ENA);                  IWN_CLRBITS(sc, IWN_GIO, IWN_GIO_L0S_ENA);
Line 6067  iwn_apm_stop_master(struct iwn_softc *sc
Line 5522  iwn_apm_stop_master(struct iwn_softc *sc
                         return;                          return;
                 DELAY(10);                  DELAY(10);
         }          }
         aprint_error_dev(sc->sc_dev, "timeout waiting for master\n");          aprint_error_dev(sc->sc_dev,
               "timeout waiting for master\n");
 }  }
   
 static void  static void
Line 6138  iwn5000_nic_config(struct iwn_softc *sc)
Line 5594  iwn5000_nic_config(struct iwn_softc *sc)
                 IWN_WRITE(sc, IWN_GP_DRIVER, IWN_GP_DRIVER_RADIO_2X2_IPA);                  IWN_WRITE(sc, IWN_GP_DRIVER, IWN_GP_DRIVER_RADIO_2X2_IPA);
         }          }
         if ((sc->hw_type == IWN_HW_REV_TYPE_6050 ||          if ((sc->hw_type == IWN_HW_REV_TYPE_6050 ||
              sc->hw_type == IWN_HW_REV_TYPE_6005) && sc->calib_ver >= 6) {                  sc->hw_type == IWN_HW_REV_TYPE_6005) && sc->calib_ver >= 6) {
                 /* Indicate that ROM calibration version is >=6. */                  /* Indicate that ROM calibration version is >=6. */
                 IWN_SETBITS(sc, IWN_GP_DRIVER, IWN_GP_DRIVER_CALIB_VER6);                  IWN_SETBITS(sc, IWN_GP_DRIVER, IWN_GP_DRIVER_CALIB_VER6);
         }          }
         if (sc->hw_type == IWN_HW_REV_TYPE_6005)          if (sc->hw_type == IWN_HW_REV_TYPE_6005)
                 IWN_SETBITS(sc, IWN_GP_DRIVER, IWN_GP_DRIVER_6050_1X2);                  IWN_SETBITS(sc, IWN_GP_DRIVER, IWN_GP_DRIVER_6050_1X2);
         if (sc->hw_type == IWN_HW_REV_TYPE_2030 ||  
             sc->hw_type == IWN_HW_REV_TYPE_2000 ||  
             sc->hw_type == IWN_HW_REV_TYPE_135  ||  
             sc->hw_type == IWN_HW_REV_TYPE_105)  
                 IWN_SETBITS(sc, IWN_GP_DRIVER, IWN_GP_DRIVER_RADIO_IQ_INVERT);  
         return 0;          return 0;
 }  }
   
Line 6400  iwn_init(struct ifnet *ifp)
Line 5851  iwn_init(struct ifnet *ifp)
                 goto fail;                  goto fail;
         }          }
   
         sc->sc_beacon_wait = 0;  
   
         ifp->if_flags &= ~IFF_OACTIVE;          ifp->if_flags &= ~IFF_OACTIVE;
         ifp->if_flags |= IFF_RUNNING;          ifp->if_flags |= IFF_RUNNING;
   
Line 6572  iwn_free_rpool(struct iwn_softc *sc)
Line 6021  iwn_free_rpool(struct iwn_softc *sc)
 #endif  #endif
   
 /*  /*
    * XXX code from OpenBSD src/sys/net80211/ieee80211_output.c
    * Copyright (c) 2001 Atsushi Onoe
    * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting
    * Copyright (c) 2007-2009 Damien Bergamini
    * All rights reserved.
    */
   
   /*
    * Add an SSID element to a frame (see 7.3.2.1).
    */
   static u_int8_t *
   ieee80211_add_ssid(u_int8_t *frm, const u_int8_t *ssid, u_int len)
   {
           *frm++ = IEEE80211_ELEMID_SSID;
           *frm++ = len;
           memcpy(frm, ssid, len);
           return frm + len;
   }
   
   /*
    * Add a supported rates element to a frame (see 7.3.2.2).
    */
   static u_int8_t *
   ieee80211_add_rates(u_int8_t *frm, const struct ieee80211_rateset *rs)
   {
           int nrates;
   
           *frm++ = IEEE80211_ELEMID_RATES;
           nrates = min(rs->rs_nrates, IEEE80211_RATE_SIZE);
           *frm++ = nrates;
           memcpy(frm, rs->rs_rates, nrates);
           return frm + nrates;
   }
   
   /*
    * Add an extended supported rates element to a frame (see 7.3.2.14).
    */
   static u_int8_t *
   ieee80211_add_xrates(u_int8_t *frm, const struct ieee80211_rateset *rs)
   {
           int nrates;
   
           KASSERT(rs->rs_nrates > IEEE80211_RATE_SIZE);
   
           *frm++ = IEEE80211_ELEMID_XRATES;
           nrates = rs->rs_nrates - IEEE80211_RATE_SIZE;
           *frm++ = nrates;
           memcpy(frm, rs->rs_rates + IEEE80211_RATE_SIZE, nrates);
           return frm + nrates;
   }
   
   /*
  * XXX: Hack to set the current channel to the value advertised in beacons or   * XXX: Hack to set the current channel to the value advertised in beacons or
  * probe responses. Only used during AP detection.   * probe responses. Only used during AP detection.
  * XXX: Duplicated from if_iwi.c   * XXX: Duplicated from if_iwi.c
  */   */
 static void  static void
 iwn_fix_channel(struct ieee80211com *ic, struct mbuf *m,  iwn_fix_channel(struct ieee80211com *ic, struct mbuf *m)
     struct iwn_rx_stat *stat)  
 {  {
         struct iwn_softc *sc = ic->ic_ifp->if_softc;  
         struct ieee80211_frame *wh;          struct ieee80211_frame *wh;
         uint8_t subtype;          uint8_t subtype;
         uint8_t *frm, *efrm;          uint8_t *frm, *efrm;
Line 6596  iwn_fix_channel(struct ieee80211com *ic,
Line 6095  iwn_fix_channel(struct ieee80211com *ic,
             subtype != IEEE80211_FC0_SUBTYPE_PROBE_RESP)              subtype != IEEE80211_FC0_SUBTYPE_PROBE_RESP)
                 return;                  return;
   
         if (sc->sc_flags & IWN_FLAG_SCANNING_5GHZ) {  
                 int chan = le16toh(stat->chan);  
                 if (chan < __arraycount(ic->ic_channels))  
                         ic->ic_curchan = &ic->ic_channels[chan];  
                 return;  
         }  
   
         frm = (uint8_t *)(wh + 1);          frm = (uint8_t *)(wh + 1);
         efrm = mtod(m, uint8_t *) + m->m_len;          efrm = mtod(m, uint8_t *) + m->m_len;
   
Line 6618  iwn_fix_channel(struct ieee80211com *ic,
Line 6110  iwn_fix_channel(struct ieee80211com *ic,
         }          }
 }  }
   
 #ifdef notyetMODULE  
   
 MODULE(MODULE_CLASS_DRIVER, if_iwn, "pci");  
   
 #ifdef _MODULE  
 #include "ioconf.c"  
 #endif  
   
 static int  
 if_iwn_modcmd(modcmd_t cmd, void *data)  
 {  
         int error = 0;  
   
         switch (cmd) {  
         case MODULE_CMD_INIT:  
 #ifdef _MODULE  
                 error = config_init_component(cfdriver_ioconf_if_iwn,  
                         cfattach_ioconf_if_iwn, cfdata_ioconf_if_iwn);  
 #endif  
                 return error;  
         case MODULE_CMD_FINI:  
 #ifdef _MODULE  
                 error = config_fini_component(cfdriver_ioconf_if_iwn,  
                         cfattach_ioconf_if_iwn, cfdata_ioconf_if_iwn);  
 #endif  
                 return error;  
         case MODULE_CMD_AUTOUNLOAD:  
 #ifdef _MODULE  
                 /* XXX This is not optional! */  
 #endif  
                 return error;  
         default:  
                 return ENOTTY;  
         }  
 }  
 #endif  

Legend:
Removed from v.1.62.6.3  
changed lines
  Added in v.1.63

CVSweb <webmaster@jp.NetBSD.org>