Index: sys/dev/bwi/if_bwireg.h =================================================================== --- sys/dev/bwi/if_bwireg.h (revision 257371) +++ sys/dev/bwi/if_bwireg.h (working copy) @@ -395,8 +395,8 @@ #define BWI_SPROM_IDLE_TSSI_MASK_11A __BITS(15, 8) /* XXX */ #define BWI_SPROM_CARD_FLAGS 0x72 #define BWI_SPROM_ANT_GAIN 0x74 -#define BWI_SPROM_ANT_GAIN_MASK_11A __BITS(7, 0) -#define BWI_SPROM_ANT_GAIN_MASK_11BG __BITS(15, 8) +#define BWI_SPROM_ANT_GAIN_MASK_11BG __BITS(7, 0) +#define BWI_SPROM_ANT_GAIN_MASK_11A __BITS(15, 8) /* * SPROM card flags Index: sys/dev/iwn/if_iwn.c =================================================================== --- sys/dev/iwn/if_iwn.c (revision 257415) +++ sys/dev/iwn/if_iwn.c (working copy) @@ -78,6 +78,8 @@ #include #include #include +#include + #include struct iwn_ident { @@ -182,7 +184,6 @@ static void iwn_read_eeprom_enhinfo(struct iwn_softc *); static struct ieee80211_node *iwn_node_alloc(struct ieee80211vap *, const uint8_t mac[IEEE80211_ADDR_LEN]); -static void iwn_newassoc(struct ieee80211_node *, int); static int iwn_media_change(struct ifnet *); static int iwn_newstate(struct ieee80211vap *, enum ieee80211_state, int); static void iwn_calib_timeout(void *); @@ -227,7 +228,6 @@ static void iwn_start_locked(struct ifnet *); static void iwn_watchdog(void *); static int iwn_ioctl(struct ifnet *, u_long, caddr_t); -static int iwn_cmd(struct iwn_softc *, int, const void *, int, int); static int iwn4965_add_node(struct iwn_softc *, struct iwn_node_info *, int); static int iwn5000_add_node(struct iwn_softc *, struct iwn_node_info *, @@ -294,6 +294,7 @@ static int iwn5000_send_wimax_coex(struct iwn_softc *); static int iwn5000_crystal_calib(struct iwn_softc *); static int iwn5000_temp_offset_calib(struct iwn_softc *); +static int iwn5000_temp_offset_calibv2(struct iwn_softc *); static int iwn4965_post_alive(struct iwn_softc *); static int iwn5000_post_alive(struct iwn_softc *); static int iwn4965_load_bootcode(struct iwn_softc *, const uint8_t *, @@ -328,6 +329,7 @@ static void iwn_scan_curchan(struct ieee80211_scan_state *, unsigned long); static void iwn_scan_mindwell(struct ieee80211_scan_state *); static void iwn_hw_reset(void *, int); +static int iwn_config_specific(struct iwn_softc *, uint16_t); #ifdef IWN_DEBUG static char *iwn_get_csr_string(int); static void iwn_debug_register(struct iwn_softc *); @@ -708,6 +710,7 @@ sc->rxchainmask = IWN_ANT_ABC; /* Enable normal btcoex */ sc->sc_flags |= IWN_FLAG_BTCOEX; + sc->base_params = &iwn_default_base_params; /* !! TODO : Define something may be more specific */ DPRINTF(sc, IWN_DEBUG_TRACE, "%s: end\n",__func__); @@ -748,91 +751,7 @@ sc->reset_noise_gain = IWN5000_PHY_CALIB_RESET_NOISE_GAIN; sc->noise_gain = IWN5000_PHY_CALIB_NOISE_GAIN; - switch (sc->hw_type) { - case IWN_HW_REV_TYPE_5100: - sc->limits = &iwn5000_sensitivity_limits; - sc->fwname = "iwn5000fw"; - /* Override chains masks, ROM is known to be broken. */ - sc->txchainmask = IWN_ANT_B; - sc->rxchainmask = IWN_ANT_AB; - /* Enable normal btcoex */ - sc->sc_flags |= IWN_FLAG_BTCOEX; - break; - case IWN_HW_REV_TYPE_5150: - sc->limits = &iwn5150_sensitivity_limits; - sc->fwname = "iwn5150fw"; - /* Enable normal btcoex */ - sc->sc_flags |= IWN_FLAG_BTCOEX; - break; - case IWN_HW_REV_TYPE_5300: - case IWN_HW_REV_TYPE_5350: - sc->limits = &iwn5000_sensitivity_limits; - sc->fwname = "iwn5000fw"; - /* Enable normal btcoex */ - sc->sc_flags |= IWN_FLAG_BTCOEX; - break; - case IWN_HW_REV_TYPE_1000: - sc->limits = &iwn1000_sensitivity_limits; - sc->fwname = "iwn1000fw"; - /* Enable normal btcoex */ - sc->sc_flags |= IWN_FLAG_BTCOEX; - break; - case IWN_HW_REV_TYPE_6000: - sc->limits = &iwn6000_sensitivity_limits; - sc->fwname = "iwn6000fw"; - /* - * Disable btcoex for 6200. - * XXX TODO: disable for 6205; no btcoex as well - * (6230/6235 - enable bluetooth) - */ - if (pid != 0x422c) { - /* Enable normal btcoex */ - sc->sc_flags |= IWN_FLAG_BTCOEX; - } - if (pid == 0x422c || pid == 0x4239) { - 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; - case IWN_HW_REV_TYPE_6050: - sc->limits = &iwn6000_sensitivity_limits; - sc->fwname = "iwn6050fw"; - /* Override chains masks, ROM is known to be broken. */ - sc->txchainmask = IWN_ANT_AB; - sc->rxchainmask = IWN_ANT_AB; - /* Enable normal btcoex */ - sc->sc_flags |= IWN_FLAG_BTCOEX; - break; - case IWN_HW_REV_TYPE_6005: - sc->limits = &iwn6000_sensitivity_limits; - if (pid != 0x0082 && pid != 0x0085) { - sc->fwname = "iwn6000g2bfw"; - sc->sc_flags |= IWN_FLAG_ADV_BTCOEX; - } else { - sc->fwname = "iwn6000g2afw"; - /* - * 6250 - disable bluetooth coexistence. - */ - } - break; - default: - device_printf(sc->sc_dev, "adapter type %d not supported\n", - sc->hw_type); - DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end in error\n",__func__); - return ENOTSUP; - } - if (sc->sc_flags & IWN_FLAG_BTCOEX) - device_printf(sc->sc_dev, - "enable basic bluetooth coexistence\n"); - else if (sc->sc_flags & IWN_FLAG_ADV_BTCOEX) - device_printf(sc->sc_dev, - "enable advanced bluetooth coexistence\n"); - else - device_printf(sc->sc_dev, - "disable bluetooth coexistence\n"); - return 0; + return iwn_config_specific(sc,pid); } /* @@ -881,6 +800,13 @@ IEEE80211_ADDR_COPY(mac1, mac); + if(unit == 1) { + if(!(sc->sc_flags & IWN_FLAG_PAN_SUPPORT)) + return NULL; + mac1[5] += 1; + sc->ctx = IWN_RXON_PAN_CTX; + } + ivp = (struct iwn_vap *) malloc(sizeof(struct iwn_vap), M_80211_VAP, M_NOWAIT | M_ZERO); if (ivp == NULL) @@ -887,13 +813,27 @@ return NULL; vap = &ivp->iv_vap; ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac1); - ivp->ctx = IWN_RXON_BSS_CTX; - IEEE80211_ADDR_COPY(ivp->macaddr, mac1); + + if(unit == 1) { + ivp->ctx = IWN_RXON_PAN_CTX; + ivp->iv_newstate = vap->iv_newstate; + vap->iv_newstate = iwn_newstate_pan; + IEEE80211_ADDR_COPY(ivp->macaddr, mac1); + memset(&sc->rx_on[IWN_RXON_PAN_CTX], 0, sizeof (struct iwn_rxon)); + memcpy(&sc->rx_on[IWN_RXON_PAN_CTX], &sc->rx_on[IWN_RXON_BSS_CTX], sc->rxonsz); + IEEE80211_ADDR_COPY(sc->rx_on[IWN_RXON_PAN_CTX].myaddr, mac1); + sc->rx_on[IWN_RXON_PAN_CTX].mode = IWN_MODE_2STA; + sc->ivap[IWN_RXON_PAN_CTX] = vap; + } + else { + ivp->ctx = IWN_RXON_BSS_CTX; + IEEE80211_ADDR_COPY(ivp->macaddr, mac1); + ivp->iv_newstate = vap->iv_newstate; + vap->iv_newstate = iwn_newstate; + sc->ivap[IWN_RXON_BSS_CTX] = vap; + } + vap->iv_bmissthreshold = 10; /* override default */ - /* Override with driver methods. */ - ivp->iv_newstate = vap->iv_newstate; - vap->iv_newstate = iwn_newstate; - sc->ivap[IWN_RXON_BSS_CTX] = vap; ieee80211_ratectl_init(vap); /* Complete setup. */ @@ -906,7 +846,11 @@ iwn_vap_delete(struct ieee80211vap *vap) { struct iwn_vap *ivp = IWN_VAP(vap); + struct iwn_softc *sc = vap->iv_ic->ic_ifp->if_softc; + if(ivp->ctx == IWN_RXON_PAN_CTX) + sc->ctx = 0; + ieee80211_ratectl_deinit(vap); ieee80211_vap_detach(vap); free(ivp, M_80211_VAP); @@ -1154,7 +1098,7 @@ iwn_nic_unlock(sc); /* Set auto clock gate disable bit for HW with OTP shadow RAM. */ - if (sc->hw_type != IWN_HW_REV_TYPE_1000) { + if (sc->base_params->shadow_ram_support) { IWN_SETBITS(sc, IWN_DBG_LINK_PWR_MGMT, IWN_RESET_LINK_PWR_MGMT_DIS); } @@ -1167,11 +1111,11 @@ * Find the block before last block (contains the EEPROM image) * for HW without OTP shadow RAM. */ - if (sc->hw_type == IWN_HW_REV_TYPE_1000) { + if (!(sc->base_params->shadow_ram_support)) { /* Switch to absolute addressing mode. */ IWN_CLRBITS(sc, IWN_OTP_GP, IWN_OTP_GP_RELATIVE_ACCESS); base = prev = 0; - for (count = 0; count < IWN1000_OTP_NBLOCKS; count++) { + for (count = 0; count < sc->base_params->max_ll_items; count++) { error = iwn_read_prom_data(sc, base, &next, 2); if (error != 0) return error; @@ -1180,7 +1124,7 @@ prev = base; base = le16toh(next); } - if (count == 0 || count == IWN1000_OTP_NBLOCKS) + if (count == 0 || count == sc->base_params->max_ll_items) return EIO; /* Skip "next" word. */ sc->prom_base = prev + 1; @@ -1816,7 +1760,7 @@ { struct iwn5000_eeprom_calib_hdr hdr; int32_t volt; - uint32_t base, addr; + uint32_t base; uint16_t val; int i; @@ -1829,16 +1773,12 @@ sc->eeprom_domain, 4); /* Read the list of authorized channels (20MHz ones only). */ - for (i = 0; i < 7; i++) { - if (sc->hw_type >= IWN_HW_REV_TYPE_6000) - addr = base + iwn6000_regulatory_bands[i]; - else - addr = base + iwn5000_regulatory_bands[i]; - iwn_read_eeprom_channels(sc, i, addr); + for (i = 0; i < (IWN_NBANDS - 1); i++) { + iwn_read_eeprom_channels(sc, i, base+sc->base_params->regulatory_bands[i]); } /* Read enhanced TX power information for 6000 Series. */ - if (sc->hw_type >= IWN_HW_REV_TYPE_6000) + if (sc->base_params->enhanced_TX_power) iwn_read_eeprom_enhinfo(sc); iwn_read_prom_data(sc, IWN5000_EEPROM_CAL, &val, 2); @@ -1849,6 +1789,14 @@ hdr.version, hdr.pa_type, le16toh(hdr.volt)); sc->calib_ver = hdr.version; + if (sc->base_params->calib_need & IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSETv2) { + sc->eeprom_voltage = le16toh(hdr.volt); + iwn_read_prom_data(sc, base + IWN5000_EEPROM_TEMP, &val, 2); + sc->eeprom_temp_high=le16toh(val); + iwn_read_prom_data(sc, base + IWN5000_EEPROM_VOLT, &val, 2); + sc->eeprom_temp = le16toh(val); + } + if (sc->hw_type == IWN_HW_REV_TYPE_5150) { /* Compute temperature offset. */ iwn_read_prom_data(sc, base + IWN5000_EEPROM_TEMP, &val, 2); @@ -2279,7 +2227,7 @@ #undef RV } -static void +void iwn_newassoc(struct ieee80211_node *ni, int isnew) { /* Doesn't do anything at the moment */ @@ -2698,29 +2646,30 @@ switch (calib->code) { case IWN5000_PHY_CALIB_DC: - if ((sc->sc_flags & IWN_FLAG_INTERNAL_PA) == 0 && - (sc->hw_type == IWN_HW_REV_TYPE_5150 || - sc->hw_type >= IWN_HW_REV_TYPE_6000) && - sc->hw_type != IWN_HW_REV_TYPE_6050) + if (sc->base_params->calib_need & IWN_FLG_NEED_PHY_CALIB_DC) idx = 0; break; case IWN5000_PHY_CALIB_LO: - idx = 1; + if (sc->base_params->calib_need & IWN_FLG_NEED_PHY_CALIB_LO) + idx = 1; break; case IWN5000_PHY_CALIB_TX_IQ: - idx = 2; + if (sc->base_params->calib_need & IWN_FLG_NEED_PHY_CALIB_TX_IQ) + idx = 2; break; case IWN5000_PHY_CALIB_TX_IQ_PERIODIC: - if (sc->hw_type < IWN_HW_REV_TYPE_6000 && - sc->hw_type != IWN_HW_REV_TYPE_5150) + if (sc->base_params->calib_need & IWN_FLG_NEED_PHY_CALIB_TX_IQ_PERIODIC) idx = 3; break; case IWN5000_PHY_CALIB_BASE_BAND: - idx = 4; + if (sc->base_params->calib_need & IWN_FLG_NEED_PHY_CALIB_BASE_BAND) + idx = 4; break; } - if (idx == -1) /* Ignore other results. */ + if (idx == -1) { /* Ignore other results. */ + DPRINTF(sc,IWN_DEBUG_CALIBRATE,"Ignoring calib result %d",calib->code); return; + } /* Save calibration result. */ if (sc->calibcmd[idx].buf != NULL) @@ -2752,6 +2701,7 @@ struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); struct iwn_calib_state *calib = &sc->calib; struct iwn_stats *stats = (struct iwn_stats *)(desc + 1); + struct ieee80211vap *vap1; int temp; DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__); @@ -2763,6 +2713,13 @@ __func__); return; } + if(sc->ctx == IWN_RXON_PAN_CTX) { + vap1 = sc->ivap[IWN_RXON_PAN_CTX]; + /* Ignore statistics received during a scan. */ + if (vap1->iv_state != IEEE80211_S_RUN || + (ic->ic_flags & IEEE80211_F_SCAN)) + return; + } bus_dmamap_sync(sc->rxq.data_dmat, data->map, BUS_DMASYNC_POSTREAD); @@ -2947,12 +2904,19 @@ static void iwn_cmd_done(struct iwn_softc *sc, struct iwn_rx_desc *desc) { - struct iwn_tx_ring *ring = &sc->txq[4]; + struct iwn_tx_ring *ring; struct iwn_tx_data *data; + int cmd_queue_num; - if ((desc->qid & 0xf) != 4) + if(sc->sc_flags & IWN_FLAG_PAN_SUPPORT) + cmd_queue_num = IWN_PAN_CMD_QUEUE; + else + cmd_queue_num = IWN_CMD_QUEUE_NUM; + + if ((desc->qid & IWN_RX_DESC_QID_MSK) != cmd_queue_num) return; /* Not a command ack. */ + ring = &sc->txq[cmd_queue_num]; data = &ring->data[desc->idx]; /* If the command was mapped in an mbuf, free it. */ @@ -3104,7 +3068,7 @@ desc->type, iwn_intr_str(desc->type), le16toh(desc->len)); - if (!(desc->qid & 0x80)) /* Reply to a command. */ + if (!(desc->qid & IWN_UNSOLICITED_RX_NOTIF)) /* Reply to a command. */ iwn_cmd_done(sc, desc); switch (desc->type) { @@ -3137,7 +3101,10 @@ { struct iwn_beacon_missed *miss = (struct iwn_beacon_missed *)(desc + 1); - int misses; + struct ieee80211vap *vap0 = sc->ivap[IWN_RXON_BSS_CTX]; + struct ieee80211vap *vap1 = sc->ivap[IWN_RXON_PAN_CTX]; + int misses,iv_bmissthreshold; + int DoReinit =0 ; bus_dmamap_sync(sc->rxq.data_dmat, data->map, BUS_DMASYNC_POSTREAD); @@ -3144,17 +3111,31 @@ misses = le32toh(miss->consecutive); DPRINTF(sc, IWN_DEBUG_STATE, - "%s: beacons missed %d/%d\n", __func__, - misses, le32toh(miss->total)); + "%s: beacons missed %d/%d rcv %d expect %d\n", __func__, + misses, le32toh(miss->total), le32toh(miss->received), + le32toh(miss->expected)); + + iv_bmissthreshold = vap0->iv_bmissthreshold; + + if(sc->ctx == IWN_RXON_PAN_CTX) { + iv_bmissthreshold = vap1->iv_bmissthreshold; + if (vap0->iv_state == IEEE80211_S_RUN && + vap1->iv_state == IEEE80211_S_RUN && + (ic->ic_flags & IEEE80211_F_SCAN) == 0) + DoReinit = 1; + } + else if (vap0->iv_state == IEEE80211_S_RUN && + (ic->ic_flags & IEEE80211_F_SCAN) == 0) + DoReinit = 1; + /* * If more than 5 consecutive beacons are missed, * reinitialize the sensitivity state machine. */ - if (vap->iv_state == IEEE80211_S_RUN && - (ic->ic_flags & IEEE80211_F_SCAN) == 0) { + if (DoReinit==1) { if (misses > 5) (void)iwn_init_sensitivity(sc); - if (misses >= vap->iv_bmissthreshold) { + if (misses >= iv_bmissthreshold) { IWN_UNLOCK(sc); ieee80211_beacon_miss(ic); IWN_LOCK(sc); @@ -3565,6 +3546,7 @@ const struct ieee80211_txparam *tp; struct ieee80211vap *vap = ni->ni_vap; struct ieee80211com *ic = ni->ni_ic; + struct iwn_vap *ivp = IWN_VAP(vap); struct iwn_node *wn = (void *)ni; struct iwn_tx_ring *ring; struct iwn_tx_desc *desc; @@ -3597,21 +3579,23 @@ qos = 0; tid = 0; } - ac = M_WME_GETAC(m); - if (m->m_flags & M_AMPDU_MPDU) { + + if(ivp->ctx == IWN_RXON_PAN_CTX) + ac = iwn_pan_ac_to_queue[M_WME_GETAC(m)]; + else + ac = iwn_bss_ac_to_queue[M_WME_GETAC(m)]; + + if (IEEE80211_QOS_HAS_SEQ(wh) && + IEEE80211_AMPDU_RUNNING(&ni->ni_tx_ampdu[ac])) { struct ieee80211_tx_ampdu *tap = &ni->ni_tx_ampdu[ac]; - if (!IEEE80211_AMPDU_RUNNING(tap)) { - m_freem(m); - return EINVAL; - } - - ac = *(int *)tap->txa_private; + ring = &sc->txq[*(int *)tap->txa_private]; *(uint16_t *)wh->i_seq = htole16(ni->ni_txseqs[tid] << IEEE80211_SEQ_SEQ_SHIFT); ni->ni_txseqs[tid]++; - } - ring = &sc->txq[ac]; + } else + ring = &sc->txq[ac]; + desc = &ring->desc[ring->cur]; data = &ring->data[ring->cur]; @@ -3704,9 +3688,12 @@ } if (IEEE80211_IS_MULTICAST(wh->i_addr1) || - type != IEEE80211_FC0_TYPE_DATA) - tx->id = sc->broadcast_id; - else + type != IEEE80211_FC0_TYPE_DATA) { + if(ivp->ctx == IWN_RXON_PAN_CTX) + tx->id = IWN_PAN_ID_BCAST; + else + tx->id = sc->broadcast_id; + } else tx->id = wn->id; if (type == IEEE80211_FC0_TYPE_MGT) { @@ -3866,6 +3853,7 @@ u_int hdrlen; int ac, totlen, error, pad, nsegs = 0, i, rate; uint8_t type; + struct iwn_vap *ivp = IWN_VAP(vap); DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__); @@ -3948,7 +3936,10 @@ tx->len = htole16(totlen); tx->tid = 0; - tx->id = sc->broadcast_id; + if(ivp->ctx == IWN_RXON_PAN_CTX) + tx->id = IWN_PAN_ID_BCAST; + else + tx->id = sc->broadcast_id; tx->rts_ntries = params->ibp_try1; tx->data_ntries = params->ibp_try0; tx->lifetime = htole32(IWN_LIFETIME_INFINITE); @@ -4199,16 +4190,16 @@ /* * Send a command to the firmware. */ -static int +int iwn_cmd(struct iwn_softc *sc, int code, const void *buf, int size, int async) { - struct iwn_tx_ring *ring = &sc->txq[4]; + struct iwn_tx_ring *ring ; struct iwn_tx_desc *desc; struct iwn_tx_data *data; struct iwn_tx_cmd *cmd; struct mbuf *m; bus_addr_t paddr; - int totlen, error; + int totlen, error,cmd_queue_num; DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__); @@ -4215,6 +4206,12 @@ if (async == 0) IWN_LOCK_ASSERT(sc); + if(sc->sc_flags & IWN_FLAG_PAN_SUPPORT) + cmd_queue_num = IWN_PAN_CMD_QUEUE; + else + cmd_queue_num = IWN_CMD_QUEUE_NUM; + + ring = &sc->txq[cmd_queue_num]; desc = &ring->desc[ring->cur]; data = &ring->data[ring->cur]; totlen = 4 + size; @@ -5340,25 +5337,61 @@ 0xc0004000, 0x00004000, 0xf0005000, 0xf0005000, }; struct iwn6000_btcoex_config btconfig; + struct iwn2000_btcoex_config btconfig2k; struct iwn_btcoex_priotable btprio; struct iwn_btcoex_prot btprot; int error, i; + uint8_t flags; memset(&btconfig, 0, sizeof btconfig); - btconfig.flags = 145; - btconfig.max_kill = 5; - btconfig.bt3_t7_timer = 1; - btconfig.kill_ack = htole32(0xffff0000); - btconfig.kill_cts = htole32(0xffff0000); - btconfig.sample_time = 2; - btconfig.bt3_t2_timer = 0xc; - for (i = 0; i < 12; i++) - btconfig.lookup_table[i] = htole32(btcoex_3wire[i]); - btconfig.valid = htole16(0xff); - btconfig.prio_boost = 0xf0; - DPRINTF(sc, IWN_DEBUG_RESET, - "%s: configuring advanced bluetooth coexistence\n", __func__); - error = iwn_cmd(sc, IWN_CMD_BT_COEX, &btconfig, sizeof(btconfig), 1); + memset(&btconfig2k, 0, sizeof btconfig2k); + + flags = IWN_BT_FLAG_COEX6000_MODE_3W << IWN_BT_FLAG_COEX6000_MODE_SHIFT; // Done as is in linux kernel 3.2 + + if (sc->base_params->bt_sco_disable) + flags &= ~IWN_BT_FLAG_SYNC_2_BT_DISABLE; + else + flags |= IWN_BT_FLAG_SYNC_2_BT_DISABLE; + + flags |= IWN_BT_FLAG_COEX6000_CHAN_INHIBITION; + + + /* Default flags result is 145 as old value */ + + /* Flags value has to be review. Values must change if we which to disable it */ + if (sc->base_params->bt_session_2) { + btconfig2k.flags = flags; + btconfig2k.max_kill = 5; + btconfig2k.bt3_t7_timer = 1; + btconfig2k.kill_ack = htole32(0xffff0000); + btconfig2k.kill_cts = htole32(0xffff0000); + btconfig2k.sample_time = 2; + btconfig2k.bt3_t2_timer = 0xc; + + for (i = 0; i < 12; i++) + btconfig2k.lookup_table[i] = htole32(btcoex_3wire[i]); + btconfig2k.valid = htole16(0xff); + btconfig2k.prio_boost = htole32(0xf0); + DPRINTF(sc, IWN_DEBUG_RESET, + "%s: configuring advanced bluetooth coexistence session 2, flags : 0X%x\n", __func__,flags); + error = iwn_cmd(sc, IWN_CMD_BT_COEX, &btconfig2k, sizeof(btconfig2k), 1); + } else { + btconfig.flags = flags; + btconfig.max_kill = 5; + btconfig.bt3_t7_timer = 1; + btconfig.kill_ack = htole32(0xffff0000); + btconfig.kill_cts = htole32(0xffff0000); + btconfig.sample_time = 2; + btconfig.bt3_t2_timer = 0xc; + + for (i = 0; i < 12; i++) + btconfig.lookup_table[i] = htole32(btcoex_3wire[i]); + btconfig.valid = htole16(0xff); + btconfig.prio_boost = 0xf0; + DPRINTF(sc, IWN_DEBUG_RESET, + "%s: configuring advanced bluetooth coexistence, flags : 0X%x\n", __func__,flags); + error = iwn_cmd(sc, IWN_CMD_BT_COEX, &btconfig, sizeof(btconfig), 1); + } if (error != 0) return error; @@ -5413,8 +5446,18 @@ DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__); - if (sc->hw_type == IWN_HW_REV_TYPE_6005) { - /* Set radio temperature sensor offset. */ + if ((sc->base_params->calib_need & IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSET) + && (sc->base_params->calib_need & IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSETv2)) { + device_printf(sc->sc_dev,"%s: temp_offset and temp_offsetv2 are" + " exclusive each together. Review NIC config file. Conf" + " : 0x%08x Flags : 0x%08x \n", __func__, + sc->base_params->calib_need, + (IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSET | + IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSETv2)); + return EINVAL; + } + /* Compute temperature calib if needed. Will be send by send calib */ + if (sc->base_params->calib_need & IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSET) { error = iwn5000_temp_offset_calib(sc); if (error != 0) { device_printf(sc->sc_dev, @@ -5421,6 +5464,13 @@ "%s: could not set temperature offset\n", __func__); return error; } + } else if (sc->base_params->calib_need & IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSETv2) { + error = iwn5000_temp_offset_calibv2(sc); + if (error != 0) { + device_printf(sc->sc_dev, + "%s: could not compute temperature offset v2\n", __func__); + return error; + } } if (sc->hw_type == IWN_HW_REV_TYPE_6050) { @@ -5449,17 +5499,18 @@ } } - /* Configure bluetooth coexistence. */ - error = 0; - if (sc->sc_flags & IWN_FLAG_ADV_BTCOEX) - error = iwn_send_advanced_btcoex(sc); - else if (sc->sc_flags & IWN_FLAG_BTCOEX) - error = iwn_send_btcoex(sc); - if (error != 0) { - device_printf(sc->sc_dev, - "%s: could not configure bluetooth coexistence, error %d\n", - __func__, error); - return error; + /* Configure bluetooth coexistence if needed. */ + if (sc->base_params->bt_mode != NONE) { + if (sc->base_params->bt_mode == ADVANCED) + error = iwn_send_advanced_btcoex(sc); + else + error = iwn_send_btcoex(sc); + if (error != 0) { + device_printf(sc->sc_dev, + "%s: could not configure bluetooth coexistence, error %d\n", + __func__, error); + return error; + } } /* Set mode, channel, RX filter and enable RX. */ @@ -5553,6 +5604,8 @@ struct ieee80211com *ic = ifp->if_l2com; struct ieee80211_scan_state *ss = ic->ic_scan; /*XXX*/ struct ieee80211_node *ni = ss->ss_vap->iv_bss; + struct ieee80211vap *vap = ni->ni_vap; + struct iwn_vap *ivp = IWN_VAP(vap); struct iwn_scan_hdr *hdr; struct iwn_cmd_data *tx; struct iwn_scan_essid *essid; @@ -5567,7 +5620,11 @@ DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__); - sc->rxon = &sc->rx_on[IWN_RXON_BSS_CTX]; + if(ivp->ctx == IWN_RXON_BSS_CTX) + sc->rxon = &sc->rx_on[IWN_RXON_BSS_CTX]; + else if(ivp->ctx == IWN_RXON_PAN_CTX) + sc->rxon = &sc->rx_on[IWN_RXON_PAN_CTX]; + buf = malloc(IWN_SCAN_MAXSZ, M_DEVBUF, M_NOWAIT | M_ZERO); if (buf == NULL) { device_printf(sc->sc_dev, @@ -5599,7 +5656,11 @@ tx = (struct iwn_cmd_data *)(hdr + 1); tx->flags = htole32(IWN_TX_AUTO_SEQ); - tx->id = sc->broadcast_id; + if(ivp->ctx == IWN_RXON_PAN_CTX) + tx->id = IWN_PAN_ID_BCAST; + else + tx->id = sc->broadcast_id; + tx->lifetime = htole32(IWN_LIFETIME_INFINITE); if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) { @@ -5636,7 +5697,7 @@ IEEE80211_FC0_SUBTYPE_PROBE_REQ; wh->i_fc[1] = IEEE80211_FC1_DIR_NODS; IEEE80211_ADDR_COPY(wh->i_addr1, ifp->if_broadcastaddr); - IEEE80211_ADDR_COPY(wh->i_addr2, IF_LLADDR(ifp)); + IEEE80211_ADDR_COPY(wh->i_addr2, ivp->macaddr); IEEE80211_ADDR_COPY(wh->i_addr3, ifp->if_broadcastaddr); *(uint16_t *)&wh->i_dur[0] = 0; /* filled by HW */ *(uint16_t *)&wh->i_seq[0] = 0; /* filled by HW */ @@ -5788,6 +5849,15 @@ DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__); sc->rxon = &sc->rx_on[IWN_RXON_BSS_CTX]; + + if(sc->ctx == IWN_RXON_PAN_CTX) { + if ((error = iwn_set_pan_params(sc)) != 0) { + device_printf(sc->sc_dev, + "%s: iwn_set_pan_params error %d\n", __func__, error); + return error; + } + } + if (ic->ic_opmode == IEEE80211_M_MONITOR) { /* Link LED blinks while monitoring. */ iwn_set_led(sc, IWN_LED_LINK, 5, 5); @@ -6263,9 +6333,15 @@ { int idx, error; - for (idx = 0; idx < 5; idx++) { - if (sc->calibcmd[idx].buf == NULL) - continue; /* No results available. */ + for (idx = 0; idx < IWN5000_PHY_CALIB_MAX_RESULT ; idx++) { + if (!(sc->base_params->calib_need & (1<calibcmd[idx].buf == NULL) { + DPRINTF(sc, IWN_DEBUG_CALIBRATE, "Need calib idx : %d but no available data\n",idx); + continue; + } DPRINTF(sc, IWN_DEBUG_CALIBRATE, "send calibration result idx=%d len=%d\n", idx, sc->calibcmd[idx].len); @@ -6342,6 +6418,32 @@ return iwn_cmd(sc, IWN_CMD_PHY_CALIB, &cmd, sizeof cmd, 0); } +static int +iwn5000_temp_offset_calibv2(struct iwn_softc *sc) +{ + struct iwn5000_phy_calib_temp_offsetv2 cmd; + + memset(&cmd, 0, sizeof cmd); + cmd.code = IWN5000_PHY_CALIB_TEMP_OFFSET; + cmd.ngroups = 1; + cmd.isvalid = 1; + if (sc->eeprom_temp != 0) { + cmd.offset_low = htole16(sc->eeprom_temp); + cmd.offset_high = htole16(sc->eeprom_temp_high); + } 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(sc, IWN_DEBUG_CALIBRATE, "setting radio sensor low offset to %d, high offset to %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 * readiness (called in a process context). @@ -6427,7 +6529,11 @@ IWN_SETBITS(sc, IWN_FH_TX_CHICKEN, IWN_FH_TX_CHICKEN_SCHED_RETRY); /* Enable chain mode for all queues, except command queue. */ - iwn_prph_write(sc, IWN5000_SCHED_QCHAIN_SEL, 0xfffef); + if(sc->sc_flags & IWN_FLAG_PAN_SUPPORT) + iwn_prph_write(sc, IWN5000_SCHED_QCHAIN_SEL, 0xffdff); + else + iwn_prph_write(sc, IWN5000_SCHED_QCHAIN_SEL, 0xfffef); + iwn_prph_write(sc, IWN5000_SCHED_AGGR_SEL, 0); for (qid = 0; qid < IWN5000_NTXQUEUES; qid++) { @@ -6447,11 +6553,20 @@ /* Identify TX FIFO rings (0-7). */ iwn_prph_write(sc, IWN5000_SCHED_TXFACT, 0xff); - /* Mark TX rings (4 EDCA + cmd + 2 HCCA) as active. */ - for (qid = 0; qid < 7; qid++) { - static uint8_t qid2fifo[] = { 3, 2, 1, 0, 7, 5, 6 }; - iwn_prph_write(sc, IWN5000_SCHED_QUEUE_STATUS(qid), - IWN5000_TXQ_STATUS_ACTIVE | qid2fifo[qid]); + if(sc->sc_flags & IWN_FLAG_PAN_SUPPORT) { + /* Mark TX rings as active. */ + for (qid = 0; qid < 11; qid++) { + static uint8_t qid2fifo[] = { 3, 2, 1, 0, 0, 4, 2, 5, 4, 7, 5 }; + iwn_prph_write(sc, IWN5000_SCHED_QUEUE_STATUS(qid), + IWN5000_TXQ_STATUS_ACTIVE | qid2fifo[qid]); + } + } else { + /* Mark TX rings (4 EDCA + cmd + 2 HCCA) as active. */ + for (qid = 0; qid < 7; qid++) { + static uint8_t qid2fifo[] = { 3, 2, 1, 0, 7, 5, 6 }; + iwn_prph_write(sc, IWN5000_SCHED_QUEUE_STATUS(qid), + IWN5000_TXQ_STATUS_ACTIVE | qid2fifo[qid]); + } } iwn_nic_unlock(sc); @@ -6463,7 +6578,7 @@ __func__, error); return error; } - if (sc->hw_type != IWN_HW_REV_TYPE_5150) { + if (!(sc->base_params->no_crystal_calibration)) { /* Perform crystal calibration. */ error = iwn5000_crystal_calib(sc); if (error != 0) { @@ -6964,9 +7079,8 @@ else IWN_CLRBITS(sc, IWN_GIO, IWN_GIO_L0S_ENA); - if (sc->hw_type != IWN_HW_REV_TYPE_4965 && - sc->hw_type <= IWN_HW_REV_TYPE_1000) - IWN_SETBITS(sc, IWN_ANA_PLL, IWN_ANA_PLL_INIT); + if (sc->base_params->pll_cfg_val) + IWN_SETBITS(sc, IWN_ANA_PLL, sc->base_params->pll_cfg_val); /* Wait for clock stabilization before accessing prph. */ if ((error = iwn_clock_wait(sc)) != 0) @@ -7078,13 +7192,12 @@ /* 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->hw_type == IWN_HW_REV_TYPE_6005) && sc->calib_ver >= 6) { + if (sc->base_params->additional_nic_config && 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); + if (sc->base_params->additional_gp_drv_bit) + IWN_SETBITS(sc, IWN_GP_DRIVER, sc->base_params->additional_gp_drv_bit); return 0; } @@ -7219,7 +7332,7 @@ IWN_WRITE(sc, IWN_UCODE_GP1_CLR, IWN_UCODE_GP1_RFKILL); /* Enable shadow registers. */ - if (sc->hw_type >= IWN_HW_REV_TYPE_6000) + if (sc->base_params->shadow_reg_enable) IWN_SETBITS(sc, IWN_SHADOW_REG_CTRL, 0x800fffff); if ((error = ops->load_firmware(sc)) != 0) { @@ -7546,6 +7659,427 @@ iwn_init(sc); ieee80211_notify_radio(ic, 1); } + +/* + * Define specific configuration based on device id and subdevice id + * pid : PCI device id + */ +static int +iwn_config_specific(struct iwn_softc *sc, uint16_t pid) +{ + switch(pid) { +/* 1000 Series */ + case IWN_DID_1000_1: + case IWN_DID_1000_2: + switch(sc->subdevice_id) { + case IWN_SDID_1000_1: + case IWN_SDID_1000_2: + case IWN_SDID_1000_3: + case IWN_SDID_1000_4: + case IWN_SDID_1000_5: + case IWN_SDID_1000_6: + case IWN_SDID_1000_7: + case IWN_SDID_1000_8: + case IWN_SDID_1000_9: + case IWN_SDID_1000_10: + case IWN_SDID_1000_11: + case IWN_SDID_1000_12: + sc->limits = &iwn1000_sensitivity_limits; + sc->base_params = &iwn_1000_base_params; + sc->fwname = "iwn1000fw"; + break; + default: + device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :" + "0x%04x rev %d not supported (subdevice)\n", pid, + sc->subdevice_id,sc->hw_type); + return ENOTSUP; + } + break; +/* 6x00 Series */ + case IWN_DID_6x00_2: + case IWN_DID_6x00_4: + case IWN_DID_6x00_1: + case IWN_DID_6x00_3: + sc->fwname = "iwn6000fw"; + sc->limits = &iwn6000_sensitivity_limits; + switch(sc->subdevice_id) { + case IWN_SDID_6x00_1: + case IWN_SDID_6x00_2: + case IWN_SDID_6x00_8: + //iwl6000_3agn_cfg + sc->base_params = &iwn_6000_base_params; + break; + case IWN_SDID_6x00_3: + case IWN_SDID_6x00_6: + case IWN_SDID_6x00_9: + ////iwl6000i_2agn + case IWN_SDID_6x00_4: + case IWN_SDID_6x00_7: + case IWN_SDID_6x00_10: + //iwl6000i_2abg_cfg + case IWN_SDID_6x00_5: + //iwl6000i_2bg_cfg + sc->base_params = &iwn_6000i_base_params; + sc->sc_flags |= IWN_FLAG_INTERNAL_PA; + sc->txchainmask = IWN_ANT_BC; + sc->rxchainmask = IWN_ANT_BC; + break; + default: + device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :" + "0x%04x rev %d not supported (subdevice)\n", pid, + sc->subdevice_id,sc->hw_type); + return ENOTSUP; + } + break; +/* 6x05 Series */ + case IWN_DID_6x05_1: + case IWN_DID_6x05_2: + switch(sc->subdevice_id) { + case IWN_SDID_6x05_1: + case IWN_SDID_6x05_4: + case IWN_SDID_6x05_6: + //iwl6005_2agn_cfg + case IWN_SDID_6x05_2: + case IWN_SDID_6x05_5: + case IWN_SDID_6x05_7: + //iwl6005_2abg_cfg + case IWN_SDID_6x05_3: + //iwl6005_2bg_cfg + case IWN_SDID_6x05_8: + case IWN_SDID_6x05_9: + //iwl6005_2agn_sff_cfg + case IWN_SDID_6x05_10: + //iwl6005_2agn_d_cfg + case IWN_SDID_6x05_11: + //iwl6005_2agn_mow1_cfg + case IWN_SDID_6x05_12: + //iwl6005_2agn_mow2_cfg + sc->fwname = "iwn6000g2afw"; + sc->limits = &iwn6000_sensitivity_limits; + sc->base_params = &iwn_6000g2_base_params; + break; + default: + device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :" + "0x%04x rev %d not supported (subdevice)\n", pid, + sc->subdevice_id,sc->hw_type); + return ENOTSUP; + } + break; +/* 6x35 Series */ + case IWN_DID_6035_1: + case IWN_DID_6035_2: + switch(sc->subdevice_id) { + case IWN_SDID_6035_1: + case IWN_SDID_6035_2: + case IWN_SDID_6035_3: + case IWN_SDID_6035_4: + sc->fwname = "iwn6000g2bfw"; + sc->limits = &iwn6000_sensitivity_limits; + sc->base_params = &iwn_6000g2b_base_params; + break; + default: + device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :" + "0x%04x rev %d not supported (subdevice)\n", pid, + sc->subdevice_id,sc->hw_type); + return ENOTSUP; + } + break; +/* 6x50 WiFi/WiMax Series */ + case IWN_DID_6050_1: + case IWN_DID_6050_2: + switch(sc->subdevice_id) { + case IWN_SDID_6050_1: + case IWN_SDID_6050_3: + case IWN_SDID_6050_5: + //iwl6050_2agn_cfg + case IWN_SDID_6050_2: + case IWN_SDID_6050_4: + case IWN_SDID_6050_6: + //iwl6050_2abg_cfg + sc->fwname = "iwn6050fw"; + sc->txchainmask = IWN_ANT_AB; + sc->rxchainmask = IWN_ANT_AB; + sc->limits = &iwn6000_sensitivity_limits; + sc->base_params = &iwn_6050_base_params; + break; + default: + device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :" + "0x%04x rev %d not supported (subdevice)\n", pid, + sc->subdevice_id,sc->hw_type); + return ENOTSUP; + } + break; +/* 6150 WiFi/WiMax Series */ + case IWN_DID_6150_1: + case IWN_DID_6150_2: + switch(sc->subdevice_id) { + case IWN_SDID_6150_1: + case IWN_SDID_6150_3: + case IWN_SDID_6150_5: + // iwl6150_bgn_cfg + case IWN_SDID_6150_2: + case IWN_SDID_6150_4: + case IWN_SDID_6150_6: + //iwl6150_bg_cfg + sc->fwname = "iwn6050fw"; + sc->limits = &iwn6000_sensitivity_limits; + sc->base_params = &iwn_6150_base_params; + break; + default: + device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :" + "0x%04x rev %d not supported (subdevice)\n", pid, + sc->subdevice_id,sc->hw_type); + return ENOTSUP; + } + break; +/* 6030 Series and 1030 Series */ + case IWN_DID_x030_1: + case IWN_DID_x030_2: + case IWN_DID_x030_3: + case IWN_DID_x030_4: + switch(sc->subdevice_id) { + case IWN_SDID_x030_1: + case IWN_SDID_x030_3: + case IWN_SDID_x030_5: + // iwl1030_bgn_cfg + case IWN_SDID_x030_2: + case IWN_SDID_x030_4: + case IWN_SDID_x030_6: + //iwl1030_bg_cfg + case IWN_SDID_x030_7: + case IWN_SDID_x030_10: + case IWN_SDID_x030_14: + //iwl6030_2agn_cfg + case IWN_SDID_x030_8: + case IWN_SDID_x030_11: + case IWN_SDID_x030_15: + // iwl6030_2bgn_cfg + case IWN_SDID_x030_9: + case IWN_SDID_x030_12: + case IWN_SDID_x030_16: + // iwl6030_2abg_cfg + case IWN_SDID_x030_13: + //iwl6030_2bg_cfg + sc->fwname = "iwn6000g2bfw"; + sc->limits = &iwn6000_sensitivity_limits; + sc->base_params = &iwn_6000g2b_base_params; + break; + default: + device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :" + "0x%04x rev %d not supported (subdevice)\n", pid, + sc->subdevice_id,sc->hw_type); + return ENOTSUP; + } + break; +/* 130 Series WiFi */ +/* XXX: This series will need adjustment for rate. + * see rx_with_siso_diversity in linux kernel + */ + case IWN_DID_130_1: + case IWN_DID_130_2: + switch(sc->subdevice_id) { + case IWN_SDID_130_1: + case IWN_SDID_130_3: + case IWN_SDID_130_5: + //iwl130_bgn_cfg + case IWN_SDID_130_2: + case IWN_SDID_130_4: + case IWN_SDID_130_6: + //iwl130_bg_cfg + sc->fwname = "iwn6000g2bfw"; + sc->limits = &iwn6000_sensitivity_limits; + sc->base_params = &iwn_6000g2b_base_params; + break; + default: + device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :" + "0x%04x rev %d not supported (subdevice)\n", pid, + sc->subdevice_id,sc->hw_type); + return ENOTSUP; + } + break; +/* 100 Series WiFi */ + case IWN_DID_100_1: + case IWN_DID_100_2: + switch(sc->subdevice_id) { + case IWN_SDID_100_1: + case IWN_SDID_100_2: + case IWN_SDID_100_3: + case IWN_SDID_100_4: + case IWN_SDID_100_5: + case IWN_SDID_100_6: + sc->limits = &iwn1000_sensitivity_limits; + sc->base_params = &iwn_1000_base_params; + sc->fwname = "iwn100fw"; + break; + default: + device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :" + "0x%04x rev %d not supported (subdevice)\n", pid, + sc->subdevice_id,sc->hw_type); + return ENOTSUP; + } + break; + +/* 2x00 Series */ + case IWN_DID_2x00_1: + case IWN_DID_2x00_2: + switch(sc->subdevice_id) { + case IWN_SDID_2x00_1: + case IWN_SDID_2x00_2: + case IWN_SDID_2x00_3: + //iwl2000_2bgn_cfg + case IWN_SDID_2x00_4: + //iwl2000_2bgn_d_cfg + sc->limits = &iwn2030_sensitivity_limits; + sc->base_params = &iwn2000_base_params; + sc->fwname = "iwn2000fw"; + break; + default: + device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :" + "0x%04x rev %d not supported (subdevice) \n", + pid, sc->subdevice_id, sc->hw_type); + return ENOTSUP; + } + break; +/* 2x30 Series */ + case IWN_DID_2x30_1: + case IWN_DID_2x30_2: + switch(sc->subdevice_id) { + case IWN_SDID_2x30_1: + case IWN_SDID_2x30_3: + case IWN_SDID_2x30_5: + //iwl100_bgn_cfg + case IWN_SDID_2x30_2: + case IWN_SDID_2x30_4: + case IWN_SDID_2x30_6: + //iwl100_bg_cfg + sc->limits = &iwn2030_sensitivity_limits; + sc->base_params = &iwn2030_base_params; + sc->fwname = "iwn2030fw"; + break; + default: + device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :" + "0x%04x rev %d not supported (subdevice)\n", pid, + sc->subdevice_id,sc->hw_type); + return ENOTSUP; + } + break; +/* 5x00 Series */ + case IWN_DID_5x00_1: + case IWN_DID_5x00_2: + case IWN_DID_5x00_3: + case IWN_DID_5x00_4: + sc->limits = &iwn5000_sensitivity_limits; + sc->base_params = &iwn_default_base_params; + sc->fwname = "iwn5000fw"; + switch(sc->subdevice_id) { + case IWN_SDID_5x00_1: + case IWN_SDID_5x00_2: + case IWN_SDID_5x00_3: + case IWN_SDID_5x00_4: + case IWN_SDID_5x00_9: + case IWN_SDID_5x00_10: + case IWN_SDID_5x00_11: + case IWN_SDID_5x00_12: + case IWN_SDID_5x00_17: + case IWN_SDID_5x00_18: + case IWN_SDID_5x00_19: + case IWN_SDID_5x00_20: + //iwl5100_agn_cfg + sc->txchainmask = IWN_ANT_B; + sc->rxchainmask = IWN_ANT_AB; + break; + case IWN_SDID_5x00_5: + case IWN_SDID_5x00_6: + case IWN_SDID_5x00_13: + case IWN_SDID_5x00_14: + case IWN_SDID_5x00_21: + case IWN_SDID_5x00_22: + //iwl5100_bgn_cfg + sc->txchainmask = IWN_ANT_B; + sc->rxchainmask = IWN_ANT_AB; + break; + case IWN_SDID_5x00_7: + case IWN_SDID_5x00_8: + case IWN_SDID_5x00_15: + case IWN_SDID_5x00_16: + case IWN_SDID_5x00_23: + case IWN_SDID_5x00_24: + //iwl5100_abg_cfg + sc->txchainmask = IWN_ANT_B; + sc->rxchainmask = IWN_ANT_AB; + break; + case IWN_SDID_5x00_25: + case IWN_SDID_5x00_26: + case IWN_SDID_5x00_27: + case IWN_SDID_5x00_28: + case IWN_SDID_5x00_29: + case IWN_SDID_5x00_30: + case IWN_SDID_5x00_31: + case IWN_SDID_5x00_32: + case IWN_SDID_5x00_33: + case IWN_SDID_5x00_34: + case IWN_SDID_5x00_35: + case IWN_SDID_5x00_36: + //iwl5300_agn_cfg + sc->txchainmask = IWN_ANT_ABC; + sc->rxchainmask = IWN_ANT_ABC; + break; + default: + device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :" + "0x%04x rev %d not supported (subdevice)\n", pid, + sc->subdevice_id,sc->hw_type); + return ENOTSUP; + } + break; +/* 5x50 Series */ + case IWN_DID_5x50_1: + case IWN_DID_5x50_2: + case IWN_DID_5x50_3: + case IWN_DID_5x50_4: + sc->limits = &iwn5000_sensitivity_limits; + sc->base_params = &iwn_default_base_params; + sc->fwname = "iwn5000fw"; + switch(sc->subdevice_id) { + case IWN_SDID_5x50_1: + case IWN_SDID_5x50_2: + case IWN_SDID_5x50_3: + //iwl5350_agn_cfg + sc->limits = &iwn5000_sensitivity_limits; + sc->base_params = &iwn_default_base_params; + sc->fwname = "iwn5000fw"; + break; + case IWN_SDID_5x50_4: + case IWN_SDID_5x50_5: + case IWN_SDID_5x50_8: + case IWN_SDID_5x50_9: + case IWN_SDID_5x50_10: + case IWN_SDID_5x50_11: + //iwl5150_agn_cfg + case IWN_SDID_5x50_6: + case IWN_SDID_5x50_7: + case IWN_SDID_5x50_12: + case IWN_SDID_5x50_13: + //iwl5150_abg_cfg + sc->limits = &iwn5000_sensitivity_limits; + sc->fwname = "iwn5150fw"; + sc->base_params = &iwn_5x50_base_params; + break; + default: + device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :" + "0x%04x rev %d not supported (subdevice)\n", pid, + sc->subdevice_id,sc->hw_type); + return ENOTSUP; + } + break; + default: + device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id : 0x%04x" + "rev 0x%08x not supported (device)\n", pid, sc->subdevice_id, + sc->hw_type); + return ENOTSUP; + } + return 0; +} + #ifdef IWN_DEBUG #define IWN_DESC(x) case x: return #x #define COUNTOF(array) (sizeof(array) / sizeof(array[0])) Index: sys/dev/iwn/if_iwn_debug.h =================================================================== --- sys/dev/iwn/if_iwn_debug.h (revision 257613) +++ sys/dev/iwn/if_iwn_debug.h (working copy) @@ -53,7 +53,7 @@ printf(fmt, __VA_ARGS__); \ } while (0) -static const char * +static inline const char * iwn_intr_str(uint8_t cmd) { switch (cmd) { Index: sys/dev/iwn/if_iwn_devid.h =================================================================== --- sys/dev/iwn/if_iwn_devid.h (revision 257607) +++ sys/dev/iwn/if_iwn_devid.h (working copy) @@ -57,6 +57,18 @@ /* * -------------------------------------------------------------------------- + * Device ID for 2x00 series + * -------------------------------------------------------------------------- + */ +#define IWN_DID_2x00_1 0x0890 +#define IWN_DID_2x00_2 0x0891 +/* SubDevice ID */ +#define IWN_SDID_2x00_1 0x4022 +#define IWN_SDID_2x00_2 0x4222 +#define IWN_SDID_2x00_3 0x4422 +#define IWN_SDID_2x00_4 0x4822 +/* + * -------------------------------------------------------------------------- * Device ID for 2x30 series * -------------------------------------------------------------------------- */ Index: sys/dev/iwn/if_iwnreg.h =================================================================== --- sys/dev/iwn/if_iwnreg.h (revision 257605) +++ sys/dev/iwn/if_iwnreg.h (working copy) @@ -2,6 +2,8 @@ /* $OpenBSD: if_iwnreg.h,v 1.40 2010/05/05 19:41:57 damien Exp $ */ /*- + * Copyright (c) 2013 Cedric GROSS + * Copyright (c) 2011 Intel Corporation * Copyright (c) 2007, 2008 * Damien Bergamini * @@ -224,6 +226,7 @@ #define IWN_GP_DRIVER_CALIB_VER6 (1 << 2) #define IWN_GP_DRIVER_6050_1X2 (1 << 3) #define IWN_GP_DRIVER_REG_BIT_RADIO_IQ_INVERT (1 << 7) +#define IWN_GP_DRIVER_NONE 0 /* Possible flags for register IWN_UCODE_GP1_CLR. */ #define IWN_UCODE_GP1_RFKILL (1 << 1) @@ -1104,6 +1107,10 @@ uint16_t reserved; } __packed; +/* Define maximal number of calib result send to runtime firmware + * PS: TEMP_OFFSET count for 2 (std and v2) + */ +#define IWN5000_PHY_CALIB_MAX_RESULT 8 /* Structures for command IWN_CMD_PHY_CALIB. */ struct iwn_phy_calib { uint8_t code; @@ -1124,6 +1131,15 @@ uint8_t isvalid; } __packed; +#define IWN_BUF_IX_PHY_CALIB_DC 0 +#define IWN_BUF_IX_PHY_CALIB_LO 1 +#define IWN_BUF_IX_PHY_CALIB_TX_IQ 2 +#define IWN_BUF_IX_PHY_CALIB_CRYSTAL 3 +#define IWN_BUF_IX_PHY_CALIB_BASE_BAND 4 +#define IWN_BUF_IX_PHY_CALIB_TX_IQ_PERIODIC 5 +#define IWN_BUF_IX_PHY_CALIB_TEMP_OFFSET 6 +#define IWN_BUF_IX_PHY_CALIB_TEMP_OFFSETv2 7 + struct iwn5000_phy_calib_crystal { uint8_t code; uint8_t group; @@ -1734,6 +1750,16 @@ IWN5000_EEPROM_NO_HT40, }; +static const uint32_t iwn2030_regulatory_bands[IWN_NBANDS] = { + IWN5000_EEPROM_BAND1, + IWN5000_EEPROM_BAND2, + IWN5000_EEPROM_BAND3, + IWN5000_EEPROM_BAND4, + IWN5000_EEPROM_BAND5, + IWN6000_EEPROM_BAND6, + IWN5000_EEPROM_BAND7 +}; + #define IWN_CHAN_BANDS_COUNT 7 #define IWN_MAX_CHAN_PER_BAND 14 static const struct iwn_chan_band { @@ -2056,4 +2082,289 @@ bus_space_barrier((sc)->sc_st, (sc)->sc_sh, 0, (sc)->sc_sz, \ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE) +/* ========================================================================== + * NIC PARAMETERS + * + * ========================================================================== + */ + +/* Flags for managing calibration result. See calib_need + * in iwn_base_params struct + */ +#define IWN_FLG_NEED_PHY_CALIB_DC (1<<0) +#define IWN_FLG_NEED_PHY_CALIB_LO (1<<1) +#define IWN_FLG_NEED_PHY_CALIB_TX_IQ (1<<2) +#define IWN_FLG_NEED_PHY_CALIB_CRYSTAL (1<<3) +#define IWN_FLG_NEED_PHY_CALIB_BASE_BAND (1<<4) +#define IWN_FLG_NEED_PHY_CALIB_TX_IQ_PERIODIC (1<<5) +#define IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSET (1<<6) +#define IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSETv2 (1<<7) + +/* Define some parameters for managing different NIC. + * Refer to linux specific file like iwl-xxxx.c to determine correct value + * for NIC. + * + * @max_ll_items: max number of OTP blocks + * @shadow_ram_support: shadow support for OTP memory + * @shadow_reg_enable: HW shadhow register bit + * @no_idle_support: do not support idle mode + * @advanced_bt_coexist : Advanced BT management + * @bt_session_2 : NIC need a new struct for configure BT coexistence. Needed + * only if advanced_bt_coexist is true + * @bt_sco_disable : + * @additional_nic_config: For 6005 series + * @iq_invert : ? But need it for N 2000 series + * @regulatory_bands : XXX + * @enhanced_TX_power : EEPROM Has advanced TX power options. Set 'True' + * if update_enhanced_txpower = iwl_eeprom_enhanced_txpower. + * See iwl-agn-devices.c file to determine that(enhanced_txpower) + * @need_temp_offset_calib : Need to compute some temp offset for calibration. + * @calib_need : Use IWN_FLG_NEED_PHY_CALIB_* flags to specify which + * calibration data ucode need. See calib_init_cfg in iwl-xxxx.c + * linux kernel file + * @no_crystal_calibration : See no_xtal_calib in linux + * @support_hostap: Define IEEE80211_C_HOSTAP for ic_caps + * @no_multi_vaps: See iwn_vap_create + * @additional_gp_drv_bit : Specific bit to defined during nic_config + * @bt_mode: BT configuration mode + */ +enum bt_mode_enum { + NONE, + SIMPLE, + ADVANCED +}; + +struct iwn_base_params { + uint32_t pll_cfg_val; + const uint16_t max_ll_items; +#define IWN_OTP_MAX_LL_ITEMS_1000 (3) /* OTP blocks for 1000 */ +#define IWN_OTP_MAX_LL_ITEMS_6x00 (4) /* OTP blocks for 6x00 */ +#define IWN_OTP_MAX_LL_ITEMS_6x50 (7) /* OTP blocks for 6x50 */ +#define IWN_OTP_MAX_LL_ITEMS_2x00 (4) /* OTP blocks for 2x00 */ + const bool shadow_ram_support; + const bool shadow_reg_enable; + const bool bt_session_2; + const bool bt_sco_disable; + const bool additional_nic_config; + const uint32_t *regulatory_bands; + const bool enhanced_TX_power; + const uint16_t calib_need; + const bool no_crystal_calibration; + const bool support_hostap; + const bool no_multi_vaps; + uint8_t additional_gp_drv_bit; + enum bt_mode_enum bt_mode; +}; + +static const struct iwn_base_params iwn_default_base_params = { + IWN_ANA_PLL_INIT, /* pll_cfg_val; */ + IWN_OTP_MAX_LL_ITEMS_6x00, /* max_ll_items */ + true, /* shadow_ram_support */ + false, /* shadow_reg_enable */ + false, /* bt_session_2 */ + true, /* bt_sco_disable */ + false, /* additional_nic_config */ + iwn5000_regulatory_bands, /* regulatory_bands */ + false, /* enhanced_TX_power */ + (IWN_FLG_NEED_PHY_CALIB_DC | IWN_FLG_NEED_PHY_CALIB_LO + | IWN_FLG_NEED_PHY_CALIB_TX_IQ | IWN_FLG_NEED_PHY_CALIB_BASE_BAND ), + false, /* no_crystal_calibration */ + false, /* support_hostap */ + true, /* no_multi_vaps */ + IWN_GP_DRIVER_NONE, /* additional_gp_drv_bit */ + NONE, /* bt_mode */ +}; + +static const struct iwn_base_params iwn2000_base_params = { + 0, + IWN_OTP_MAX_LL_ITEMS_2x00, + true, + false, + false, + true, + false, + iwn2030_regulatory_bands, + true, + (IWN_FLG_NEED_PHY_CALIB_DC | IWN_FLG_NEED_PHY_CALIB_LO | + IWN_FLG_NEED_PHY_CALIB_TX_IQ | IWN_FLG_NEED_PHY_CALIB_BASE_BAND | + IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSETv2 ), + false, + true, + false, + IWN_GP_DRIVER_REG_BIT_RADIO_IQ_INVERT, + NONE, +}; + +static const struct iwn_base_params iwn2030_base_params = { + 0, + IWN_OTP_MAX_LL_ITEMS_2x00, + true, + false, + true, + true, + false, + iwn2030_regulatory_bands, + true, + (IWN_FLG_NEED_PHY_CALIB_DC | IWN_FLG_NEED_PHY_CALIB_LO | + IWN_FLG_NEED_PHY_CALIB_TX_IQ | IWN_FLG_NEED_PHY_CALIB_BASE_BAND | + IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSETv2 ), + false, + true, + false, + IWN_GP_DRIVER_REG_BIT_RADIO_IQ_INVERT, + ADVANCED, +}; + +static const struct iwn_base_params iwn_1000_base_params = { + IWN_ANA_PLL_INIT, + IWN_OTP_MAX_LL_ITEMS_1000, + false, + false, + false, + false, + false, + iwn5000_regulatory_bands, + false, + ( IWN_FLG_NEED_PHY_CALIB_DC | IWN_FLG_NEED_PHY_CALIB_LO | + IWN_FLG_NEED_PHY_CALIB_TX_IQ | IWN_FLG_NEED_PHY_CALIB_BASE_BAND ), + false, + false, + true, + IWN_GP_DRIVER_NONE, + NONE, +}; +static const struct iwn_base_params iwn_6000_base_params = { + 0, + IWN_OTP_MAX_LL_ITEMS_6x00, + true, + false, + false, + false, + false, + iwn6000_regulatory_bands, + true, + (IWN_FLG_NEED_PHY_CALIB_DC | IWN_FLG_NEED_PHY_CALIB_LO | + IWN_FLG_NEED_PHY_CALIB_TX_IQ | IWN_FLG_NEED_PHY_CALIB_BASE_BAND ), + false, + false, + true, + IWN_GP_DRIVER_NONE, + SIMPLE, +}; +static const struct iwn_base_params iwn_6000i_base_params = { + 0, + IWN_OTP_MAX_LL_ITEMS_6x00, + true, + false, + false, + true, + false, + iwn6000_regulatory_bands, + true, + (IWN_FLG_NEED_PHY_CALIB_DC | IWN_FLG_NEED_PHY_CALIB_LO | + IWN_FLG_NEED_PHY_CALIB_TX_IQ | IWN_FLG_NEED_PHY_CALIB_BASE_BAND ), + false, + false, + true, + IWN_GP_DRIVER_NONE, + SIMPLE, +}; +static const struct iwn_base_params iwn_6000g2_base_params = { + 0, + IWN_OTP_MAX_LL_ITEMS_6x00, + true, + false, + false, + true, + false, + iwn6000_regulatory_bands, + true, + (IWN_FLG_NEED_PHY_CALIB_DC | IWN_FLG_NEED_PHY_CALIB_LO | + IWN_FLG_NEED_PHY_CALIB_TX_IQ | IWN_FLG_NEED_PHY_CALIB_BASE_BAND | + IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSET ), + false, + false, + true, + 0, + SIMPLE, +}; +static const struct iwn_base_params iwn_6050_base_params = { + 0, + IWN_OTP_MAX_LL_ITEMS_6x50, + true, + false, + false, + true, + true, + iwn6000_regulatory_bands, + true, + (IWN_FLG_NEED_PHY_CALIB_DC | IWN_FLG_NEED_PHY_CALIB_LO | + IWN_FLG_NEED_PHY_CALIB_TX_IQ | IWN_FLG_NEED_PHY_CALIB_BASE_BAND | + IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSET ), + false, + false, + true, + IWN_GP_DRIVER_NONE, + SIMPLE, +}; +static const struct iwn_base_params iwn_6150_base_params = { + 0, + IWN_OTP_MAX_LL_ITEMS_6x50, + true, + false, + false, + true, + true, + iwn6000_regulatory_bands, + true, + (IWN_FLG_NEED_PHY_CALIB_DC | IWN_FLG_NEED_PHY_CALIB_LO | + IWN_FLG_NEED_PHY_CALIB_TX_IQ | IWN_FLG_NEED_PHY_CALIB_BASE_BAND | + IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSET ), + false, + false, + true, + IWN_GP_DRIVER_6050_1X2, + SIMPLE, +}; + +/* IWL_DEVICE_6035 & IWL_DEVICE_6030 */ +static const struct iwn_base_params iwn_6000g2b_base_params = { + 0, + IWN_OTP_MAX_LL_ITEMS_6x00, + true, + false, + false, + true, + false, + iwn6000_regulatory_bands, + true, + (IWN_FLG_NEED_PHY_CALIB_DC | IWN_FLG_NEED_PHY_CALIB_LO | + IWN_FLG_NEED_PHY_CALIB_TX_IQ | IWN_FLG_NEED_PHY_CALIB_BASE_BAND | + IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSET ), + false, + false, + true, + IWN_GP_DRIVER_NONE, + ADVANCED, +}; +static const struct iwn_base_params iwn_5x50_base_params = { + IWN_ANA_PLL_INIT, + IWN_OTP_MAX_LL_ITEMS_6x00, + true, + false, + false, + true, + false, + iwn5000_regulatory_bands, + false, + (IWN_FLG_NEED_PHY_CALIB_DC | IWN_FLG_NEED_PHY_CALIB_LO | + IWN_FLG_NEED_PHY_CALIB_TX_IQ | IWN_FLG_NEED_PHY_CALIB_BASE_BAND ), + true, + false, + true, + IWN_GP_DRIVER_NONE, + SIMPLE, +}; + + #endif /* __IF_IWNREG_H__ */ Index: sys/dev/iwn/if_iwnvar.h =================================================================== --- sys/dev/iwn/if_iwnvar.h (revision 257371) +++ sys/dev/iwn/if_iwnvar.h (working copy) @@ -388,10 +388,13 @@ */ int current_pwrsave_level; - /* For specifique params */ - struct iwn_base_params *base_params; + /* For specific params */ + const struct iwn_base_params *base_params; }; +extern int iwn_cmd(struct iwn_softc *, int, const void *, int, int); +extern void iwn_newassoc(struct ieee80211_node *, int); + #define IWN_LOCK_INIT(_sc) \ mtx_init(&(_sc)->sc_mtx, device_get_nameunit((_sc)->sc_dev), \ MTX_NETWORK_LOCK, MTX_DEF) Index: sys/modules/bwi/Makefile =================================================================== --- sys/modules/bwi/Makefile (revision 257474) +++ sys/modules/bwi/Makefile (working copy) @@ -7,8 +7,4 @@ SRCS = if_bwi.c if_bwi_pci.c bwimac.c bwiphy.c bwirf.c SRCS += device_if.h bus_if.h pci_if.h opt_inet.h opt_bwi.h opt_wlan.h -opt_bwi.h: - echo '#define BWI_DEBUG 1' > opt_bwi.h -# echo '#define BWI_DEBUG_VERBOSE 1' >> opt_bwi.h - .include Index: sys/modules/iwn/Makefile =================================================================== --- sys/modules/iwn/Makefile (revision 257371) +++ sys/modules/iwn/Makefile (working copy) @@ -3,6 +3,14 @@ .PATH: ${.CURDIR}/../../dev/iwn KMOD = if_iwn -SRCS = if_iwn.c device_if.h bus_if.h pci_if.h opt_iwn.h opt_wlan.h +SRCS = if_iwn.c if_iwn_pan.c device_if.h bus_if.h pci_if.h opt_wlan.h ++SRCS = opt_iwn.h +.if !defined(KERNBUILDDIR) +opt_wlan.h: + echo "#define IEEE80211_DEBUG 1" > ${.TARGET} +.endif +.if IWN_DEBUG +CFLAGS+=-DIWN_DEBUG +.endif .include