diff --git a/src/add-ons/kernel/drivers/network/wlan/Jamfile b/src/add-ons/kernel/drivers/network/wlan/Jamfile index ef4e08c303..e19ceeed18 100644 --- a/src/add-ons/kernel/drivers/network/wlan/Jamfile +++ b/src/add-ons/kernel/drivers/network/wlan/Jamfile @@ -10,13 +10,13 @@ SubInclude HAIKU_TOP src add-ons kernel drivers network wlan marvell88w8335 ; # FreeBSD 9.3 drivers SubInclude HAIKU_TOP src add-ons kernel drivers network wlan atheroswifi ; SubInclude HAIKU_TOP src add-ons kernel drivers network wlan broadcom43xx ; -SubInclude HAIKU_TOP src add-ons kernel drivers network wlan iprowifi2200 ; SubInclude HAIKU_TOP src add-ons kernel drivers network wlan marvell88w8363 ; SubInclude HAIKU_TOP src add-ons kernel drivers network wlan ralinkwifi ; SubInclude HAIKU_TOP src add-ons kernel drivers network wlan wavelanwifi ; # FreeBSD 11.1 drivers SubInclude HAIKU_TOP src add-ons kernel drivers network wlan aironetwifi ; +SubInclude HAIKU_TOP src add-ons kernel drivers network wlan iprowifi2200 ; SubInclude HAIKU_TOP src add-ons kernel drivers network wlan iprowifi3945 ; SubInclude HAIKU_TOP src add-ons kernel drivers network wlan iprowifi4965 ; diff --git a/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/Jamfile b/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/Jamfile index 0f81e1c581..e9b723b410 100644 --- a/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/Jamfile +++ b/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/Jamfile @@ -1,8 +1,8 @@ SubDir HAIKU_TOP src add-ons kernel drivers network wlan iprowifi2200 ; -UseHeaders [ FDirName $(HAIKU_TOP) src libs compat freebsd_network compat ] +UseHeaders [ FDirName $(HAIKU_TOP) src libs compat freebsd11_network compat ] : true ; -UseHeaders [ FDirName $(HAIKU_TOP) src libs compat freebsd_wlan ] : true ; +UseHeaders [ FDirName $(HAIKU_TOP) src libs compat freebsd11_wlan ] : true ; UsePrivateHeaders net system ; UsePrivateKernelHeaders ; @@ -10,10 +10,10 @@ UsePrivateKernelHeaders ; Includes [ FGristFiles kernel_c++_structs.h ] : kernel_c++_struct_sizes.h ; -SubDirCcFlags [ FDefines _KERNEL=1 FBSD_DRIVER=1 ] - -Wno-format - -Wno-unused - -Wno-uninitialized +SubDirCcFlags [ FDefines _KERNEL=1 FBSD_DRIVER=1 ] + -Wno-format + -Wno-unused + -Wno-uninitialized -Werror ; UseHeaders [ FDirName $(SUBDIR) ] : true ; @@ -24,8 +24,8 @@ KernelAddon iprowifi2200 : if_iwi.c glue.c : - libfreebsd_wlan.a - libfreebsd_network.a + libfreebsd11_wlan.a + libfreebsd11_network.a ; # Note: Due to licensing restrictions, we can only distribute the archive. diff --git a/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/dev/iwi/if_iwi.c b/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/dev/iwi/if_iwi.c index 6d17b95611..c5a4b481f7 100644 --- a/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/dev/iwi/if_iwi.c +++ b/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/dev/iwi/if_iwi.c @@ -28,7 +28,7 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: releng/11.2/sys/dev/iwi/if_iwi.c 332288 2018-04-08 16:54:07Z brooks $"); /*- * Intel(R) PRO/Wireless 2200BG/2225BG/2915ABG driver @@ -64,6 +64,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -83,6 +84,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #define IWI_DEBUG #ifdef IWI_DEBUG @@ -128,10 +130,19 @@ static const struct iwi_ident iwi_ident_table[] = { { 0, 0, NULL } }; +static const uint8_t def_chan_2ghz[] = + { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 }; +static const uint8_t def_chan_5ghz_band1[] = + { 36, 40, 44, 48, 52, 56, 60, 64 }; +static const uint8_t def_chan_5ghz_band2[] = + { 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 }; +static const uint8_t def_chan_5ghz_band3[] = + { 149, 153, 157, 161, 165 }; + static struct ieee80211vap *iwi_vap_create(struct ieee80211com *, - const char name[IFNAMSIZ], int unit, enum ieee80211_opmode opmode, int flags, - const uint8_t bssid[IEEE80211_ADDR_LEN], - const uint8_t mac[IEEE80211_ADDR_LEN]); + const char [IFNAMSIZ], int, enum ieee80211_opmode, int, + const uint8_t [IEEE80211_ADDR_LEN], + const uint8_t [IEEE80211_ADDR_LEN]); static void iwi_vap_delete(struct ieee80211vap *); static void iwi_dma_map_addr(void *, bus_dma_segment_t *, int, int); static int iwi_alloc_cmd_ring(struct iwi_softc *, struct iwi_cmd_ring *, @@ -152,8 +163,7 @@ static void iwi_node_free(struct ieee80211_node *); static void iwi_media_status(struct ifnet *, struct ifmediareq *); static int iwi_newstate(struct ieee80211vap *, enum ieee80211_state, int); static void iwi_wme_init(struct iwi_softc *); -static int iwi_wme_setparams(struct iwi_softc *, struct ieee80211com *); -static void iwi_update_wme(void *, int); +static int iwi_wme_setparams(struct iwi_softc *); static int iwi_wme_update(struct ieee80211com *); static uint16_t iwi_read_prom_word(struct iwi_softc *, uint8_t); static void iwi_frame_intr(struct iwi_softc *, struct iwi_rx_data *, int, @@ -164,14 +174,15 @@ static void iwi_tx_intr(struct iwi_softc *, struct iwi_tx_ring *); static void iwi_intr(void *); static int iwi_cmd(struct iwi_softc *, uint8_t, void *, uint8_t); static void iwi_write_ibssnode(struct iwi_softc *, const u_int8_t [], int); -static int iwi_tx_start(struct ifnet *, struct mbuf *, +static int iwi_tx_start(struct iwi_softc *, struct mbuf *, struct ieee80211_node *, int); static int iwi_raw_xmit(struct ieee80211_node *, struct mbuf *, const struct ieee80211_bpf_params *); -static void iwi_start_locked(struct ifnet *); -static void iwi_start(struct ifnet *); +static void iwi_start(struct iwi_softc *); +static int iwi_transmit(struct ieee80211com *, struct mbuf *); static void iwi_watchdog(void *); -static int iwi_ioctl(struct ifnet *, u_long, caddr_t); +static int iwi_ioctl(struct ieee80211com *, u_long, void *); +static void iwi_parent(struct ieee80211com *); static void iwi_stop_master(struct iwi_softc *); static int iwi_reset(struct iwi_softc *); static int iwi_load_ucode(struct iwi_softc *, const struct iwi_fw *); @@ -202,6 +213,9 @@ static void iwi_radio_off(void *, int); static void iwi_sysctlattach(struct iwi_softc *); static void iwi_led_event(struct iwi_softc *, int); static void iwi_ledattach(struct iwi_softc *); +static void iwi_collect_bands(struct ieee80211com *, uint8_t [], size_t); +static void iwi_getradiocaps(struct ieee80211com *, int, int *, + struct ieee80211_channel []); static int iwi_probe(device_t); static int iwi_attach(device_t); @@ -267,23 +281,15 @@ static int iwi_attach(device_t dev) { struct iwi_softc *sc = device_get_softc(dev); - struct ifnet *ifp; - struct ieee80211com *ic; + struct ieee80211com *ic = &sc->sc_ic; uint16_t val; int i, error; - uint8_t bands; - uint8_t macaddr[IEEE80211_ADDR_LEN]; sc->sc_dev = dev; - - ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211); - if (ifp == NULL) { - device_printf(dev, "can not if_alloc()\n"); - return ENXIO; - } - ic = ifp->if_l2com; + sc->sc_ledevent = ticks; IWI_LOCK_INIT(sc); + mbufq_init(&sc->sc_snd, ifqmaxlen); sc->sc_unr = new_unrhdr(1, IWI_MAX_IBSSNODE-1, &sc->sc_mtx); @@ -291,7 +297,6 @@ iwi_attach(device_t dev) TASK_INIT(&sc->sc_radiofftask, 0, iwi_radio_off, sc); TASK_INIT(&sc->sc_restarttask, 0, iwi_restart, sc); TASK_INIT(&sc->sc_disassoctask, 0, iwi_disassoc, sc); - TASK_INIT(&sc->sc_wmetask, 0, iwi_update_wme, sc); TASK_INIT(&sc->sc_monitortask, 0, iwi_monitor_scan, sc); callout_init_mtx(&sc->sc_wdtimer, &sc->sc_mtx, 0); @@ -351,17 +356,8 @@ iwi_attach(device_t dev) iwi_wme_init(sc); - ifp->if_softc = sc; - if_initname(ifp, device_get_name(dev), device_get_unit(dev)); - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; - ifp->if_init = iwi_init; - ifp->if_ioctl = iwi_ioctl; - ifp->if_start = iwi_start; - IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); - ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; - IFQ_SET_READY(&ifp->if_snd); - - ic->ic_ifp = ifp; + ic->ic_softc = sc; + ic->ic_name = device_get_nameunit(dev); ic->ic_opmode = IEEE80211_M_STA; ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ @@ -381,23 +377,19 @@ iwi_attach(device_t dev) /* read MAC address from EEPROM */ val = iwi_read_prom_word(sc, IWI_EEPROM_MAC + 0); - macaddr[0] = val & 0xff; - macaddr[1] = val >> 8; + ic->ic_macaddr[0] = val & 0xff; + ic->ic_macaddr[1] = val >> 8; val = iwi_read_prom_word(sc, IWI_EEPROM_MAC + 1); - macaddr[2] = val & 0xff; - macaddr[3] = val >> 8; + ic->ic_macaddr[2] = val & 0xff; + ic->ic_macaddr[3] = val >> 8; val = iwi_read_prom_word(sc, IWI_EEPROM_MAC + 2); - macaddr[4] = val & 0xff; - macaddr[5] = val >> 8; - - bands = 0; - setbit(&bands, IEEE80211_MODE_11B); - setbit(&bands, IEEE80211_MODE_11G); - if (pci_get_device(dev) >= 0x4223) - setbit(&bands, IEEE80211_MODE_11A); - ieee80211_init_channels(ic, NULL, &bands); + ic->ic_macaddr[4] = val & 0xff; + ic->ic_macaddr[5] = val >> 8; - ieee80211_ifattach(ic, macaddr); + iwi_getradiocaps(ic, IEEE80211_CHAN_MAX, &ic->ic_nchans, + ic->ic_channels); + + ieee80211_ifattach(ic); /* override default methods */ ic->ic_node_alloc = iwi_node_alloc; sc->sc_node_free = ic->ic_node_free; @@ -412,6 +404,10 @@ iwi_attach(device_t dev) ic->ic_vap_create = iwi_vap_create; ic->ic_vap_delete = iwi_vap_delete; + ic->ic_ioctl = iwi_ioctl; + ic->ic_transmit = iwi_transmit; + ic->ic_parent = iwi_parent; + ic->ic_getradiocaps = iwi_getradiocaps; ieee80211_radiotap_attach(ic, &sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap), @@ -446,8 +442,7 @@ static int iwi_detach(device_t dev) { struct iwi_softc *sc = device_get_softc(dev); - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; bus_teardown_intr(dev, sc->irq, sc->sc_ih); @@ -478,22 +473,20 @@ iwi_detach(device_t dev) sc->mem); delete_unrhdr(sc->sc_unr); + mbufq_drain(&sc->sc_snd); IWI_LOCK_DESTROY(sc); - if_free(ifp); - return 0; } static struct ieee80211vap * -iwi_vap_create(struct ieee80211com *ic, - const char name[IFNAMSIZ], int unit, enum ieee80211_opmode opmode, int flags, - const uint8_t bssid[IEEE80211_ADDR_LEN], - const uint8_t mac[IEEE80211_ADDR_LEN]) +iwi_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit, + enum ieee80211_opmode opmode, int flags, + const uint8_t bssid[IEEE80211_ADDR_LEN], + const uint8_t mac[IEEE80211_ADDR_LEN]) { - struct ifnet *ifp = ic->ic_ifp; - struct iwi_softc *sc = ifp->if_softc; + struct iwi_softc *sc = ic->ic_softc; struct iwi_vap *ivp; struct ieee80211vap *vap; int i; @@ -515,12 +508,9 @@ iwi_vap_create(struct ieee80211com *ic, if (iwi_init_fw_dma(sc, i)) return NULL; - ivp = (struct iwi_vap *) malloc(sizeof(struct iwi_vap), - M_80211_VAP, M_NOWAIT | M_ZERO); - if (ivp == NULL) - return NULL; + ivp = malloc(sizeof(struct iwi_vap), M_80211_VAP, M_WAITOK | M_ZERO); vap = &ivp->iwi_vap; - ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac); + ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid); /* override the default, the setting comes from the linux driver */ vap->iv_bmissthreshold = 24; /* override with driver methods */ @@ -528,7 +518,8 @@ iwi_vap_create(struct ieee80211com *ic, vap->iv_newstate = iwi_newstate; /* complete setup */ - ieee80211_vap_attach(vap, ieee80211_media_change, iwi_media_status); + ieee80211_vap_attach(vap, ieee80211_media_change, iwi_media_status, + mac); ic->ic_opmode = opmode; return vap; } @@ -564,7 +555,7 @@ iwi_alloc_cmd_ring(struct iwi_softc *sc, struct iwi_cmd_ring *ring, int count) error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 4, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, - count * IWI_CMD_DESC_SIZE, 1, count * IWI_CMD_DESC_SIZE, 0, + count * IWI_CMD_DESC_SIZE, 1, count * IWI_CMD_DESC_SIZE, 0, NULL, NULL, &ring->desc_dmat); if (error != 0) { device_printf(sc->sc_dev, "could not create desc DMA tag\n"); @@ -609,7 +600,7 @@ iwi_free_cmd_ring(struct iwi_softc *sc, struct iwi_cmd_ring *ring) } if (ring->desc_dmat != NULL) - bus_dma_tag_destroy(ring->desc_dmat); + bus_dma_tag_destroy(ring->desc_dmat); } static int @@ -626,7 +617,7 @@ iwi_alloc_tx_ring(struct iwi_softc *sc, struct iwi_tx_ring *ring, int count, error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 4, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, - count * IWI_TX_DESC_SIZE, 1, count * IWI_TX_DESC_SIZE, 0, NULL, + count * IWI_TX_DESC_SIZE, 1, count * IWI_TX_DESC_SIZE, 0, NULL, NULL, &ring->desc_dmat); if (error != 0) { device_printf(sc->sc_dev, "could not create desc DMA tag\n"); @@ -780,7 +771,7 @@ iwi_alloc_rx_ring(struct iwi_softc *sc, struct iwi_rx_ring *ring, int count) goto fail; } - data->m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); + data->m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); if (data->m == NULL) { device_printf(sc->sc_dev, "could not allocate rx mbuf\n"); @@ -855,9 +846,9 @@ static int iwi_suspend(device_t dev) { struct iwi_softc *sc = device_get_softc(dev); + struct ieee80211com *ic = &sc->sc_ic; - iwi_stop(sc); - + ieee80211_suspend_all(ic); return 0; } @@ -865,13 +856,11 @@ static int iwi_resume(device_t dev) { struct iwi_softc *sc = device_get_softc(dev); - struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = &sc->sc_ic; pci_write_config(dev, 0x41, 0, 1); - if (ifp->if_flags & IFF_UP) - iwi_init(sc); - + ieee80211_resume_all(ic); return 0; } @@ -893,7 +882,7 @@ static void iwi_node_free(struct ieee80211_node *ni) { struct ieee80211com *ic = ni->ni_ic; - struct iwi_softc *sc = ic->ic_ifp->if_softc; + struct iwi_softc *sc = ic->ic_softc; struct iwi_node *in = (struct iwi_node *)ni; if (in->in_station != -1) { @@ -905,7 +894,7 @@ iwi_node_free(struct ieee80211_node *ni) sc->sc_node_free(ni); } -/* +/* * Convert h/w rate code to IEEE rate code. */ static int @@ -937,11 +926,14 @@ iwi_media_status(struct ifnet *ifp, struct ifmediareq *imr) { struct ieee80211vap *vap = ifp->if_softc; struct ieee80211com *ic = vap->iv_ic; - struct iwi_softc *sc = ic->ic_ifp->if_softc; + struct iwi_softc *sc = ic->ic_softc; + struct ieee80211_node *ni; /* read current transmission rate from adapter */ - vap->iv_bss->ni_txrate = + ni = ieee80211_ref_node(vap->iv_bss); + ni->ni_txrate = iwi_cvtrate(CSR_READ_4(sc, IWI_CSR_CURRENT_TX_RATE)); + ieee80211_free_node(ni); ieee80211_media_status(ifp, imr); } @@ -950,8 +942,7 @@ iwi_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) { struct iwi_vap *ivp = IWI_VAP(vap); struct ieee80211com *ic = vap->iv_ic; - struct ifnet *ifp = ic->ic_ifp; - struct iwi_softc *sc = ifp->if_softc; + struct iwi_softc *sc = ic->ic_softc; IWI_LOCK_DECL; DPRINTF(("%s: %s -> %s flags 0x%x\n", __func__, @@ -1054,8 +1045,9 @@ iwi_wme_init(struct iwi_softc *sc) } static int -iwi_wme_setparams(struct iwi_softc *sc, struct ieee80211com *ic) +iwi_wme_setparams(struct iwi_softc *sc) { + struct ieee80211com *ic = &sc->sc_ic; const struct wmeParams *wmep; int ac; @@ -1075,23 +1067,12 @@ iwi_wme_setparams(struct iwi_softc *sc, struct ieee80211com *ic) #undef IWI_USEC #undef IWI_EXP2 -static void -iwi_update_wme(void *arg, int npending) -{ - struct ieee80211com *ic = arg; - struct iwi_softc *sc = ic->ic_ifp->if_softc; - IWI_LOCK_DECL; - - IWI_LOCK(sc); - (void) iwi_wme_setparams(sc, ic); - IWI_UNLOCK(sc); -} - static int iwi_wme_update(struct ieee80211com *ic) { - struct iwi_softc *sc = ic->ic_ifp->if_softc; + struct iwi_softc *sc = ic->ic_softc; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); + IWI_LOCK_DECL; /* * We may be called to update the WME parameters in @@ -1101,8 +1082,11 @@ iwi_wme_update(struct ieee80211com *ic) * to the adapter as part of the work iwi_auth_and_assoc * does. */ - if (vap->iv_state == IEEE80211_S_RUN) - ieee80211_runtask(ic, &sc->sc_wmetask); + if (vap->iv_state == IEEE80211_S_RUN) { + IWI_LOCK(sc); + iwi_wme_setparams(sc); + IWI_UNLOCK(sc); + } return (0); } @@ -1184,8 +1168,7 @@ iwi_read_prom_word(struct iwi_softc *sc, uint8_t addr) static void iwi_setcurchan(struct iwi_softc *sc, int chan) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; sc->curchan = chan; ieee80211_radiotap_chan_change(ic); @@ -1195,8 +1178,7 @@ static void iwi_frame_intr(struct iwi_softc *sc, struct iwi_rx_data *data, int i, struct iwi_frame *frame) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct mbuf *mnew, *m; struct ieee80211_node *ni; int type, error, framelen; @@ -1230,9 +1212,9 @@ iwi_frame_intr(struct iwi_softc *sc, struct iwi_rx_data *data, int i, * drop the received packet and reuse the old mbuf. In the unlikely * case that the old mbuf can't be reloaded either, explicitly panic. */ - mnew = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); + mnew = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); if (mnew == NULL) { - ifp->if_ierrors++; + counter_u64_add(ic->ic_ierrors, 1); return; } @@ -1253,7 +1235,7 @@ iwi_frame_intr(struct iwi_softc *sc, struct iwi_rx_data *data, int i, panic("%s: could not load old rx mbuf", device_get_name(sc->sc_dev)); } - ifp->if_ierrors++; + counter_u64_add(ic->ic_ierrors, 1); return; } @@ -1266,7 +1248,6 @@ iwi_frame_intr(struct iwi_softc *sc, struct iwi_rx_data *data, int i, CSR_WRITE_4(sc, data->reg, data->physaddr); /* finalize mbuf */ - m->m_pkthdr.rcvif = ifp; m->m_pkthdr.len = m->m_len = sizeof (struct iwi_hdr) + sizeof (struct iwi_frame) + framelen; @@ -1349,8 +1330,8 @@ iwi_checkforqos(struct ieee80211vap *vap, frm += 2; wme = NULL; - while (frm < efrm) { - IEEE80211_VERIFY_LENGTH(efrm - frm, frm[1], return); + while (efrm - frm > 1) { + IEEE80211_VERIFY_LENGTH(efrm - frm, frm[1] + 2, return); switch (*frm) { case IEEE80211_ELEMID_VENDOR: if (iswmeoui(frm)) @@ -1360,16 +1341,44 @@ iwi_checkforqos(struct ieee80211vap *vap, frm += frm[1] + 2; } - ni = vap->iv_bss; + ni = ieee80211_ref_node(vap->iv_bss); ni->ni_capinfo = capinfo; ni->ni_associd = associd & 0x3fff; if (wme != NULL) ni->ni_flags |= IEEE80211_NODE_QOS; else ni->ni_flags &= ~IEEE80211_NODE_QOS; + ieee80211_free_node(ni); #undef SUBTYPE } +static void +iwi_notif_link_quality(struct iwi_softc *sc, struct iwi_notif *notif) +{ + struct iwi_notif_link_quality *lq; + int len; + + len = le16toh(notif->len); + + DPRINTFN(5, ("Notification (%u) - len=%d, sizeof=%zu\n", + notif->type, + len, + sizeof(struct iwi_notif_link_quality) + )); + + /* enforce length */ + if (len != sizeof(struct iwi_notif_link_quality)) { + DPRINTFN(5, ("Notification: (%u) too short (%d)\n", + notif->type, + len)); + return; + } + + lq = (struct iwi_notif_link_quality *)(notif + 1); + memcpy(&sc->sc_linkqual, lq, sizeof(sc->sc_linkqual)); + sc->sc_linkqual_valid = 1; +} + /* * Task queue callbacks for iwi_notification_intr used to avoid LOR's. */ @@ -1377,8 +1386,7 @@ iwi_checkforqos(struct ieee80211vap *vap, static void iwi_notification_intr(struct iwi_softc *sc, struct iwi_notif *notif) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); struct iwi_notif_scan_channel *chan; struct iwi_notif_scan_complete *scan; @@ -1539,9 +1547,12 @@ iwi_notification_intr(struct iwi_softc *sc, struct iwi_notif *notif) case IWI_NOTIF_TYPE_CALIBRATION: case IWI_NOTIF_TYPE_NOISE: - case IWI_NOTIF_TYPE_LINK_QUALITY: + /* XXX handle? */ DPRINTFN(5, ("Notification (%u)\n", notif->type)); break; + case IWI_NOTIF_TYPE_LINK_QUALITY: + iwi_notif_link_quality(sc, notif); + break; default: DPRINTF(("unknown notification type %u flags 0x%x len %u\n", @@ -1596,47 +1607,33 @@ iwi_rx_intr(struct iwi_softc *sc) static void iwi_tx_intr(struct iwi_softc *sc, struct iwi_tx_ring *txq) { - struct ifnet *ifp = sc->sc_ifp; struct iwi_tx_data *data; uint32_t hw; hw = CSR_READ_4(sc, txq->csr_ridx); - for (; txq->next != hw;) { + while (txq->next != hw) { data = &txq->data[txq->next]; - + DPRINTFN(15, ("tx done idx=%u\n", txq->next)); bus_dmamap_sync(txq->data_dmat, data->map, BUS_DMASYNC_POSTWRITE); bus_dmamap_unload(txq->data_dmat, data->map); - if (data->m->m_flags & M_TXCB) - ieee80211_process_callback(data->ni, data->m, 0/*XXX*/); - m_freem(data->m); - data->m = NULL; - ieee80211_free_node(data->ni); + ieee80211_tx_complete(data->ni, data->m, 0); data->ni = NULL; - - DPRINTFN(15, ("tx done idx=%u\n", txq->next)); - - ifp->if_opackets++; - + data->m = NULL; txq->queued--; txq->next = (txq->next + 1) % IWI_TX_RING_COUNT; } - sc->sc_tx_timer = 0; - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - if (sc->sc_softled) iwi_led_event(sc, IWI_LED_TX); - - iwi_start_locked(ifp); + iwi_start(sc); } static void iwi_fatal_error_intr(struct iwi_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); device_printf(sc->sc_dev, "firmware error\n"); @@ -1652,10 +1649,8 @@ iwi_fatal_error_intr(struct iwi_softc *sc) static void iwi_radio_off_intr(struct iwi_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - ieee80211_runtask(ic, &sc->sc_radiofftask); + ieee80211_runtask(&sc->sc_ic, &sc->sc_radiofftask); } static void @@ -1774,10 +1769,9 @@ iwi_write_ibssnode(struct iwi_softc *sc, } static int -iwi_tx_start(struct ifnet *ifp, struct mbuf *m0, struct ieee80211_node *ni, +iwi_tx_start(struct iwi_softc *sc, struct mbuf *m0, struct ieee80211_node *ni, int ac) { - struct iwi_softc *sc = ifp->if_softc; struct ieee80211vap *vap = ni->ni_vap; struct ieee80211com *ic = ni->ni_ic; struct iwi_node *in = (struct iwi_node *)ni; @@ -1820,9 +1814,10 @@ iwi_tx_start(struct ifnet *ifp, struct mbuf *m0, struct ieee80211_node *ni, in->in_station = alloc_unr(sc->sc_unr); if (in->in_station == -1) { /* h/w table is full */ + if_inc_counter(ni->ni_vap->iv_ifp, + IFCOUNTER_OERRORS, 1); m_freem(m0); ieee80211_free_node(ni); - ifp->if_oerrors++; return 0; } iwi_write_ibssnode(sc, @@ -1847,7 +1842,7 @@ iwi_tx_start(struct ifnet *ifp, struct mbuf *m0, struct ieee80211_node *ni, } else staid = 0; - if (wh->i_fc[1] & IEEE80211_FC1_WEP) { + if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { k = ieee80211_crypto_encap(ni, m0); if (k == NULL) { m_freem(m0); @@ -1882,7 +1877,7 @@ iwi_tx_start(struct ifnet *ifp, struct mbuf *m0, struct ieee80211_node *ni, return error; } if (error != 0) { - mnew = m_defrag(m0, M_DONTWAIT); + mnew = m_defrag(m0, M_NOWAIT); if (mnew == NULL) { device_printf(sc->sc_dev, "could not defragment mbuf\n"); @@ -1948,127 +1943,141 @@ iwi_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, return 0; } -static void -iwi_start_locked(struct ifnet *ifp) +static int +iwi_transmit(struct ieee80211com *ic, struct mbuf *m) +{ + struct iwi_softc *sc = ic->ic_softc; + int error; + IWI_LOCK_DECL; + + IWI_LOCK(sc); + if (!sc->sc_running) { + IWI_UNLOCK(sc); + return (ENXIO); + } + error = mbufq_enqueue(&sc->sc_snd, m); + if (error) { + IWI_UNLOCK(sc); + return (error); + } + iwi_start(sc); + IWI_UNLOCK(sc); + return (0); +} + +static void +iwi_start(struct iwi_softc *sc) { - struct iwi_softc *sc = ifp->if_softc; struct mbuf *m; struct ieee80211_node *ni; int ac; IWI_LOCK_ASSERT(sc); - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) - return; - - for (;;) { - IFQ_DRV_DEQUEUE(&ifp->if_snd, m); - if (m == NULL) - break; + while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) { ac = M_WME_GETAC(m); if (sc->txq[ac].queued > IWI_TX_RING_COUNT - 8) { /* there is no place left in this ring; tail drop */ /* XXX tail drop */ - IFQ_DRV_PREPEND(&ifp->if_snd, m); - ifp->if_drv_flags |= IFF_DRV_OACTIVE; + mbufq_prepend(&sc->sc_snd, m); break; } - ni = (struct ieee80211_node *) m->m_pkthdr.rcvif; - if (iwi_tx_start(ifp, m, ni, ac) != 0) { + if (iwi_tx_start(sc, m, ni, ac) != 0) { + if_inc_counter(ni->ni_vap->iv_ifp, + IFCOUNTER_OERRORS, 1); ieee80211_free_node(ni); - ifp->if_oerrors++; break; } - sc->sc_tx_timer = 5; } } -static void -iwi_start(struct ifnet *ifp) -{ - struct iwi_softc *sc = ifp->if_softc; - IWI_LOCK_DECL; - - IWI_LOCK(sc); - iwi_start_locked(ifp); - IWI_UNLOCK(sc); -} - static void iwi_watchdog(void *arg) { struct iwi_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; IWI_LOCK_ASSERT(sc); if (sc->sc_tx_timer > 0) { if (--sc->sc_tx_timer == 0) { - if_printf(ifp, "device timeout\n"); - ifp->if_oerrors++; + device_printf(sc->sc_dev, "device timeout\n"); + counter_u64_add(ic->ic_oerrors, 1); ieee80211_runtask(ic, &sc->sc_restarttask); } } if (sc->sc_state_timer > 0) { if (--sc->sc_state_timer == 0) { - if_printf(ifp, "firmware stuck in state %d, resetting\n", + device_printf(sc->sc_dev, + "firmware stuck in state %d, resetting\n", sc->fw_state); - if (sc->fw_state == IWI_FW_SCANNING) { - struct ieee80211com *ic = ifp->if_l2com; + if (sc->fw_state == IWI_FW_SCANNING) ieee80211_cancel_scan(TAILQ_FIRST(&ic->ic_vaps)); - } ieee80211_runtask(ic, &sc->sc_restarttask); sc->sc_state_timer = 3; } } if (sc->sc_busy_timer > 0) { if (--sc->sc_busy_timer == 0) { - if_printf(ifp, "firmware command timeout, resetting\n"); + device_printf(sc->sc_dev, + "firmware command timeout, resetting\n"); ieee80211_runtask(ic, &sc->sc_restarttask); } } callout_reset(&sc->sc_wdtimer, hz, iwi_watchdog, sc); } -static int -iwi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) +static void +iwi_parent(struct ieee80211com *ic) { - struct iwi_softc *sc = ifp->if_softc; - struct ieee80211com *ic = ifp->if_l2com; - struct ifreq *ifr = (struct ifreq *) data; - int error = 0, startall = 0; + struct iwi_softc *sc = ic->ic_softc; + int startall = 0; IWI_LOCK_DECL; - switch (cmd) { - case SIOCSIFFLAGS: - IWI_LOCK(sc); - if (ifp->if_flags & IFF_UP) { - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { - iwi_init_locked(sc); - startall = 1; - } - } else { - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - iwi_stop_locked(sc); + IWI_LOCK(sc); + if (ic->ic_nrunning > 0) { + if (!sc->sc_running) { + iwi_init_locked(sc); + startall = 1; } - IWI_UNLOCK(sc); - if (startall) - ieee80211_start_all(ic); + } else if (sc->sc_running) + iwi_stop_locked(sc); + IWI_UNLOCK(sc); + if (startall) + ieee80211_start_all(ic); +} + +static int +iwi_ioctl(struct ieee80211com *ic, u_long cmd, void *data) +{ + struct ifreq *ifr = data; + struct iwi_softc *sc = ic->ic_softc; + int error; + IWI_LOCK_DECL; + + IWI_LOCK(sc); + switch (cmd) { +#ifndef __HAIKU__ + case SIOCGIWISTATS: + /* XXX validate permissions/memory/etc? */ + error = copyout(&sc->sc_linkqual, ifr_data_get_ptr(ifr), + sizeof(struct iwi_notif_link_quality)); break; - case SIOCGIFMEDIA: - error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd); - break; - case SIOCGIFADDR: - error = ether_ioctl(ifp, cmd, data); +#endif + case SIOCZIWISTATS: + memset(&sc->sc_linkqual, 0, + sizeof(struct iwi_notif_link_quality)); + error = 0; break; default: - error = EINVAL; + error = ENOTTY; break; } - return error; + IWI_UNLOCK(sc); + + return (error); } static void @@ -2547,8 +2556,7 @@ iwi_setwepkeys(struct iwi_softc *sc, struct ieee80211vap *vap) static int iwi_config(struct iwi_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct iwi_configuration config; struct iwi_rateset rs; struct iwi_txpower power; @@ -2557,8 +2565,8 @@ iwi_config(struct iwi_softc *sc) IWI_LOCK_ASSERT(sc); - DPRINTF(("Setting MAC address to %6D\n", IF_LLADDR(ifp), ":")); - error = iwi_cmd(sc, IWI_CMD_SET_MAC_ADDRESS, IF_LLADDR(ifp), + DPRINTF(("Setting MAC address to %6D\n", ic->ic_macaddr, ":")); + error = iwi_cmd(sc, IWI_CMD_SET_MAC_ADDRESS, ic->ic_macaddr, IEEE80211_ADDR_LEN); if (error != 0) return error; @@ -2678,7 +2686,7 @@ iwi_monitor_scan(void *arg, int npending) static int iwi_scanchan(struct iwi_softc *sc, unsigned long maxdwell, int allchan) { - struct ieee80211com *ic; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_channel *chan; struct ieee80211_scan_state *ss; struct iwi_scan_ext scan; @@ -2695,7 +2703,6 @@ iwi_scanchan(struct iwi_softc *sc, unsigned long maxdwell, int allchan) } IWI_STATE_BEGIN(sc, IWI_FW_SCANNING); - ic = sc->sc_ifp->if_l2com; ss = ic->ic_scan; memset(&scan, 0, sizeof scan); @@ -2809,7 +2816,7 @@ iwi_auth_and_assoc(struct iwi_softc *sc, struct ieee80211vap *vap) { struct ieee80211com *ic = vap->iv_ic; struct ifnet *ifp = vap->iv_ifp; - struct ieee80211_node *ni = vap->iv_bss; + struct ieee80211_node *ni; struct iwi_configuration config; struct iwi_associate *assoc = &sc->assoc; struct iwi_rateset rs; @@ -2819,6 +2826,8 @@ iwi_auth_and_assoc(struct iwi_softc *sc, struct ieee80211vap *vap) IWI_LOCK_ASSERT(sc); + ni = ieee80211_ref_node(vap->iv_bss); + if (sc->flags & IWI_FLAG_ASSOCIATED) { DPRINTF(("Already associated\n")); return (-1); @@ -2899,7 +2908,7 @@ iwi_auth_and_assoc(struct iwi_softc *sc, struct ieee80211vap *vap) if ((vap->iv_flags & IEEE80211_F_WME) && ni->ni_ies.wme_ie != NULL) { /* NB: don't treat WME setup as failure */ - if (iwi_wme_setparams(sc, ic) == 0 && iwi_wme_setie(sc) == 0) + if (iwi_wme_setparams(sc) == 0 && iwi_wme_setie(sc) == 0) assoc->policy |= htole16(IWI_POLICY_WME); /* XXX complain on failure? */ } @@ -2931,7 +2940,7 @@ iwi_auth_and_assoc(struct iwi_softc *sc, struct ieee80211vap *vap) * key setup. This typically is due to a user app bug * but if we blindly grab the key the firmware will * barf so avoid it for now. - */ + */ if (vap->iv_def_txkey != IEEE80211_KEYIX_NONE) assoc->auth |= vap->iv_def_txkey << 4; @@ -2977,6 +2986,7 @@ iwi_auth_and_assoc(struct iwi_softc *sc, struct ieee80211vap *vap) le16toh(assoc->intval))); error = iwi_cmd(sc, IWI_CMD_ASSOCIATE, assoc, sizeof *assoc); done: + ieee80211_free_node(ni); if (error) IWI_STATE_END(sc, IWI_FW_ASSOCIATING); @@ -3079,7 +3089,6 @@ error: static void iwi_init_locked(struct iwi_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; struct iwi_rx_data *data; int i; @@ -3153,8 +3162,7 @@ iwi_init_locked(struct iwi_softc *sc) } callout_reset(&sc->sc_wdtimer, hz, iwi_watchdog, sc); - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - ifp->if_drv_flags |= IFF_DRV_RUNNING; + sc->sc_running = 1; return; fail: IWI_STATE_END(sc, IWI_FW_LOADING); @@ -3166,15 +3174,14 @@ static void iwi_init(void *priv) { struct iwi_softc *sc = priv; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; IWI_LOCK_DECL; IWI_LOCK(sc); iwi_init_locked(sc); IWI_UNLOCK(sc); - if (ifp->if_drv_flags & IFF_DRV_RUNNING) + if (sc->sc_running) ieee80211_start_all(ic); } @@ -3182,11 +3189,10 @@ static void iwi_stop_locked(void *priv) { struct iwi_softc *sc = priv; - struct ifnet *ifp = sc->sc_ifp; IWI_LOCK_ASSERT(sc); - ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); + sc->sc_running = 0; if (sc->sc_softled) { callout_stop(&sc->sc_ledtimer); @@ -3247,7 +3253,7 @@ static void iwi_radio_on(void *arg, int pending) { struct iwi_softc *sc = arg; - struct ieee80211com *ic = sc->sc_ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; device_printf(sc->sc_dev, "radio turned on\n"); @@ -3268,10 +3274,7 @@ iwi_rfkill_poll(void *arg) * it is enabled so we must poll for the latter. */ if (!iwi_getrfkill(sc)) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - - ieee80211_runtask(ic, &sc->sc_radiontask); + ieee80211_runtask(&sc->sc_ic, &sc->sc_radiontask); return; } callout_reset(&sc->sc_rftimer, 2*hz, iwi_rfkill_poll, sc); @@ -3281,7 +3284,7 @@ static void iwi_radio_off(void *arg, int pending) { struct iwi_softc *sc = arg; - struct ieee80211com *ic = sc->sc_ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; IWI_LOCK_DECL; device_printf(sc->sc_dev, "radio turned off\n"); @@ -3418,7 +3421,6 @@ iwi_led_blink(struct iwi_softc *sc, int on, int off) static void iwi_led_event(struct iwi_softc *sc, int event) { -#define N(a) (sizeof(a)/sizeof(a[0])) /* NB: on/off times from the Atheros NDIS driver, w/ permission */ static const struct { u_int rate; /* tx/rx iwi rate */ @@ -3448,13 +3450,13 @@ iwi_led_event(struct iwi_softc *sc, int event) return; switch (event) { case IWI_LED_POLL: - j = N(blinkrates)-1; + j = nitems(blinkrates)-1; break; case IWI_LED_TX: /* read current transmission rate from adapter */ txrate = CSR_READ_4(sc, IWI_CSR_CURRENT_TX_RATE); if (blinkrates[sc->sc_txrix].rate != txrate) { - for (j = 0; j < N(blinkrates)-1; j++) + for (j = 0; j < nitems(blinkrates)-1; j++) if (blinkrates[j].rate == txrate) break; sc->sc_txrix = j; @@ -3463,7 +3465,7 @@ iwi_led_event(struct iwi_softc *sc, int event) break; case IWI_LED_RX: if (blinkrates[sc->sc_rxrix].rate != sc->sc_rxrate) { - for (j = 0; j < N(blinkrates)-1; j++) + for (j = 0; j < nitems(blinkrates)-1; j++) if (blinkrates[j].rate == sc->sc_rxrate) break; sc->sc_rxrix = j; @@ -3474,7 +3476,6 @@ iwi_led_event(struct iwi_softc *sc, int event) /* XXX beware of overflow */ iwi_led_blink(sc, (blinkrates[j].timeOn * hz) / 1000, (blinkrates[j].timeOff * hz) / 1000); -#undef N } static int @@ -3545,8 +3546,8 @@ iwi_scan_start(struct ieee80211com *ic) static void iwi_set_channel(struct ieee80211com *ic) { - struct ifnet *ifp = ic->ic_ifp; - struct iwi_softc *sc = ifp->if_softc; + struct iwi_softc *sc = ic->ic_softc; + if (sc->fw_state == IWI_FW_IDLE) iwi_setcurchan(sc, ic->ic_curchan->ic_ieee); } @@ -3555,8 +3556,7 @@ static void iwi_scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell) { struct ieee80211vap *vap = ss->ss_vap; - struct ifnet *ifp = vap->iv_ic->ic_ifp; - struct iwi_softc *sc = ifp->if_softc; + struct iwi_softc *sc = vap->iv_ic->ic_softc; IWI_LOCK_DECL; IWI_LOCK(sc); @@ -3574,8 +3574,7 @@ iwi_scan_mindwell(struct ieee80211_scan_state *ss) static void iwi_scan_end(struct ieee80211com *ic) { - struct ifnet *ifp = ic->ic_ifp; - struct iwi_softc *sc = ifp->if_softc; + struct iwi_softc *sc = ic->ic_softc; IWI_LOCK_DECL; IWI_LOCK(sc); @@ -3585,3 +3584,40 @@ iwi_scan_end(struct ieee80211com *ic) iwi_cmd(sc, IWI_CMD_ABORT_SCAN, NULL, 0); IWI_UNLOCK(sc); } + +static void +iwi_collect_bands(struct ieee80211com *ic, uint8_t bands[], size_t bands_sz) +{ + struct iwi_softc *sc = ic->ic_softc; + device_t dev = sc->sc_dev; + + memset(bands, 0, bands_sz); + setbit(bands, IEEE80211_MODE_11B); + setbit(bands, IEEE80211_MODE_11G); + if (pci_get_device(dev) >= 0x4223) + setbit(bands, IEEE80211_MODE_11A); +} + +static void +iwi_getradiocaps(struct ieee80211com *ic, + int maxchans, int *nchans, struct ieee80211_channel chans[]) +{ + uint8_t bands[IEEE80211_MODE_BYTES]; + + iwi_collect_bands(ic, bands, sizeof(bands)); + *nchans = 0; + if (isset(bands, IEEE80211_MODE_11B) || isset(bands, IEEE80211_MODE_11G)) + ieee80211_add_channel_list_2ghz(chans, maxchans, nchans, + def_chan_2ghz, nitems(def_chan_2ghz), bands, 0); + if (isset(bands, IEEE80211_MODE_11A)) { + ieee80211_add_channel_list_5ghz(chans, maxchans, nchans, + def_chan_5ghz_band1, nitems(def_chan_5ghz_band1), + bands, 0); + ieee80211_add_channel_list_5ghz(chans, maxchans, nchans, + def_chan_5ghz_band2, nitems(def_chan_5ghz_band2), + bands, 0); + ieee80211_add_channel_list_5ghz(chans, maxchans, nchans, + def_chan_5ghz_band3, nitems(def_chan_5ghz_band3), + bands, 0); + } +} diff --git a/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/dev/iwi/if_iwi_ioctl.h b/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/dev/iwi/if_iwi_ioctl.h new file mode 100644 index 0000000000..565e135626 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/dev/iwi/if_iwi_ioctl.h @@ -0,0 +1,25 @@ +/*- + * Copyright (c) 2014 Adrian Chadd + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD: releng/11.2/sys/dev/iwi/if_iwi_ioctl.h 263920 2014-03-29 19:53:04Z adrian $ + */ +#ifndef __IF_IWI_IOCTL_H__ +#define __IF_IWI_IOCTL_H__ + +/* XXX how should I pick appropriate ioctl numbers? */ +#define SIOCGIWISTATS _IOWR('i', 147, struct ifreq) +#define SIOCZIWISTATS _IOWR('i', 148, struct ifreq) + +#endif /* __IF_IWI_IOCTL_H__ */ diff --git a/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/dev/iwi/if_iwireg.h b/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/dev/iwi/if_iwireg.h index fb56fa59bb..06c4eadf65 100644 --- a/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/dev/iwi/if_iwireg.h +++ b/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/dev/iwi/if_iwireg.h @@ -1,4 +1,4 @@ -/* $FreeBSD$ */ +/* $FreeBSD: releng/11.2/sys/dev/iwi/if_iwireg.h 331722 2018-03-29 02:50:57Z eadler $ */ /*- * Copyright (c) 2004, 2005 @@ -221,6 +221,7 @@ struct iwi_notif_association { /* structure for notification IWI_NOTIF_TYPE_SCAN_CHANNEL */ struct iwi_notif_scan_channel { uint8_t nchan; + /* XXX this is iwi_cmd_stats, and a u8 reserved field */ uint8_t reserved[47]; } __packed; @@ -239,6 +240,68 @@ struct iwi_notif_beacon_state { uint32_t number; } __packed; +/* structure(s) for notification IWI_NOTIF_TYPE_LINK_QUALITY */ + +#define RX_FREE_BUFFERS 32 +#define RX_LOW_WATERMARK 8 + +#define SUP_RATE_11A_MAX_NUM_CHANNELS 8 +#define SUP_RATE_11B_MAX_NUM_CHANNELS 4 +#define SUP_RATE_11G_MAX_NUM_CHANNELS 12 + +// Used for passing to driver number of successes and failures per rate +struct iwi_rate_histogram { + union { + uint32_t a[SUP_RATE_11A_MAX_NUM_CHANNELS]; + uint32_t b[SUP_RATE_11B_MAX_NUM_CHANNELS]; + uint32_t g[SUP_RATE_11G_MAX_NUM_CHANNELS]; + } success; + union { + uint32_t a[SUP_RATE_11A_MAX_NUM_CHANNELS]; + uint32_t b[SUP_RATE_11B_MAX_NUM_CHANNELS]; + uint32_t g[SUP_RATE_11G_MAX_NUM_CHANNELS]; + } failed; +} __packed; + +/* statistics command response */ +struct iwi_cmd_stats { + uint8_t cmd_id; + uint8_t seq_num; + uint16_t good_sfd; + uint16_t bad_plcp; + uint16_t wrong_bssid; + uint16_t valid_mpdu; + uint16_t bad_mac_header; + uint16_t reserved_frame_types; + uint16_t rx_ina; + uint16_t bad_crc32; + uint16_t invalid_cts; + uint16_t invalid_acks; + uint16_t long_distance_ina_fina; + uint16_t dsp_silence_unreachable; + uint16_t accumulated_rssi; + uint16_t rx_ovfl_frame_tossed; + uint16_t rssi_silence_threshold; + uint16_t rx_ovfl_frame_supplied; + uint16_t last_rx_frame_signal; + uint16_t last_rx_frame_noise; + uint16_t rx_autodetec_no_ofdm; + uint16_t rx_autodetec_no_barker; + uint16_t reserved; +} __packed; + +#define SILENCE_OVER_THRESH (1) +#define SILENCE_UNDER_THRESH (2) + +struct iwi_notif_link_quality { + struct iwi_cmd_stats stats; + uint8_t rate; + uint8_t modulation; + struct iwi_rate_histogram histogram; + uint8_t silence_notification_type; /* SILENCE_OVER/UNDER_THRESH */ + uint16_t silence_count; +} __packed; + /* received frame header */ struct iwi_frame { uint32_t reserved1[2]; @@ -418,7 +481,7 @@ struct iwi_scan { #define IWI_SCAN_TYPES 5 /* scan result codes */ -#define IWI_SCAN_COMPLETED 1 /* scan compeleted sucessfully */ +#define IWI_SCAN_COMPLETED 1 /* scan compeleted successfully */ #define IWI_SCAN_ABORTED 2 /* scan was aborted by the driver */ /* structure for command IWI_CMD_SCAN_EXT */ diff --git a/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/dev/iwi/if_iwivar.h b/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/dev/iwi/if_iwivar.h index c733c0f9d8..98c88d027b 100644 --- a/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/dev/iwi/if_iwivar.h +++ b/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/dev/iwi/if_iwivar.h @@ -1,4 +1,4 @@ -/* $FreeBSD$ */ +/* $FreeBSD: releng/11.2/sys/dev/iwi/if_iwivar.h 331722 2018-03-29 02:50:57Z eadler $ */ /*- * Copyright (c) 2004, 2005 @@ -125,11 +125,13 @@ struct iwi_vap { #define IWI_VAP(vap) ((struct iwi_vap *)(vap)) struct iwi_softc { - struct ifnet *sc_ifp; - void (*sc_node_free)(struct ieee80211_node *); + struct mtx sc_mtx; + struct ieee80211com sc_ic; + struct mbufq sc_snd; device_t sc_dev; - struct mtx sc_mtx; + void (*sc_node_free)(struct ieee80211_node *); + uint8_t sc_mcast[IEEE80211_ADDR_LEN]; struct unrhdr *sc_unr; @@ -190,10 +192,10 @@ struct iwi_softc { struct task sc_radiofftask; /* radio off processing */ struct task sc_restarttask; /* restart adapter processing */ struct task sc_disassoctask; - struct task sc_wmetask; /* set wme parameters */ struct task sc_monitortask; - unsigned int sc_softled : 1, /* enable LED gpio status */ + unsigned int sc_running : 1, /* initialized */ + sc_softled : 1, /* enable LED gpio status */ sc_ledstate: 1, /* LED on/off state */ sc_blinking: 1; /* LED blink operation active */ u_int sc_nictype; /* NIC type from EEPROM */ @@ -216,6 +218,9 @@ struct iwi_softc { struct iwi_rx_radiotap_header sc_rxtap; struct iwi_tx_radiotap_header sc_txtap; + struct iwi_notif_link_quality sc_linkqual; + int sc_linkqual_valid; + #if defined(__HAIKU__) uint32_t sc_intr_status; #endif