📄 if_wi.c
字号:
sc->every_second_handle = timeout(wi_every_second, sc, hz); WI_UNLOCK(sc, s);}/*! \fn void wi_removeCacheEntry(struct wi_softc *sc, int entry) \brief This function removes the specified entry from the sigcache and extended cache. \param sc Pointer to the wi_softc structure of the specific interface \param entry Zero based index to the cache If the specified entry is not the last one, then the last entry in both caches is copied to the specified entry, thereby overwriting it. After this the last entry is zeroed and wi_sigitems is decremented.*/void wi_removeCacheEntry(struct wi_softc *sc, int entry) { if (sc->arpcom.ac_if.if_flags & IFF_DEBUG) device_printf(sc->dev, "remove timed out station %6D in slot %d\n", (u_char *) sc->wi_sigextcache[entry].macsrc, ":", entry); if (entry < sc->wi_sigitems - 1) { /* we're not the last, so copy... */ memcpy(&sc->wi_sigextcache[entry], &sc->wi_sigextcache[sc->wi_sigitems - 1], sizeof(struct wi_sigextcache)); memcpy(&sc->wi_sigcache[entry], &sc->wi_sigcache[sc->wi_sigitems - 1], sizeof(struct wi_sigcache)); bzero(&sc->wi_sigextcache[sc->wi_sigitems-1], sizeof(struct wi_sigextcache)); bzero(&sc->wi_sigcache[sc->wi_sigitems-1], sizeof(struct wi_sigcache)); } else if (entry == sc->wi_sigitems -1) { /* we're the last item, don't copy but do zero-ing only */ bzero(&sc->wi_sigextcache[entry], sizeof(struct wi_sigextcache)); bzero(&sc->wi_sigcache[entry], sizeof(struct wi_sigcache)); } else return; /* the entry is not a valid one (must range from 0..sc->wi_sigitems-1) */ /* decrease total number of cached items */ sc->wi_nextitem--; sc->wi_sigitems--; wi_dumpCache(sc);}void wi_dumpCache(struct wi_softc *sc) { int i; if (sc->arpcom.ac_if.if_flags & IFF_DEBUG) device_printf(sc->dev, "Dumping cache, %d items\n", sc->wi_sigitems); for (i = 0; i < sc->wi_sigitems; i++) if (sc->arpcom.ac_if.if_flags & IFF_DEBUG) device_printf(sc->dev, "Entry %d:\t%6D\n", i, (u_char *) sc->wi_sigextcache[i].macsrc, ":");}#endif /* WICACHE */intwi_generic_detach(dev) device_t dev;{ struct wi_softc *sc; struct ifnet *ifp; int s; sc = device_get_softc(dev); WI_LOCK(sc, s); ifp = &sc->arpcom.ac_if; if (sc->wi_gone) { device_printf(dev, "already unloaded\n"); WI_UNLOCK(sc, s); return(ENODEV); } wi_stop(sc); /* Delete all remaining media. */ ifmedia_removeall(&sc->ifmedia); ether_ifdetach(ifp); bus_teardown_intr(dev, sc->irq, sc->wi_intrhand); wi_free(dev); sc->wi_gone = 1; WI_UNLOCK(sc, s);#if __FreeBSD_version >= 500000 mtx_destroy(&sc->wi_mtx);#endif return(0);}intwi_generic_attach(device_t dev){ struct wi_softc *sc; struct wi_ltv_macaddr mac; struct wi_ltv_gen gen; struct ifnet *ifp; int error; int s; /* XXX maybe we need the splimp stuff here XXX */ sc = device_get_softc(dev); ifp = &sc->arpcom.ac_if; error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET, wi_intr, sc, &sc->wi_intrhand); if (error) { device_printf(dev, "bus_setup_intr() failed! (%d)\n", error); wi_free(dev); return (error); }#if __FreeBSD_version >= 500000 mtx_init(&sc->wi_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, MTX_DEF | MTX_RECURSE);#endif WI_LOCK(sc, s); /* Reset the NIC. */ wi_reset(sc); /* * Read the station address. * And do it twice. I've seen PRISM-based cards that return * an error when trying to read it the first time, which causes * the probe to fail. */ mac.wi_type = WI_RID_MAC_NODE; mac.wi_len = 4; wi_read_record(sc, (struct wi_ltv_gen *)&mac); if ((error = wi_read_record(sc, (struct wi_ltv_gen *)&mac)) != 0) { device_printf(dev, "mac read failed %d\n", error); wi_free(dev); return (error); } bcopy((char *)&mac.wi_mac_addr, (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN); device_printf(dev, "802.11 address: %6D\n", sc->arpcom.ac_enaddr, ":"); wi_get_id(sc); ifp->if_softc = sc; ifp->if_unit = sc->wi_unit; ifp->if_name = "wi"; ifp->if_mtu = ETHERMTU; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = wi_ioctl; ifp->if_output = ether_output; ifp->if_start = wi_start; ifp->if_watchdog = wi_watchdog; ifp->if_init = wi_init; ifp->if_baudrate = 10000000; ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; bzero(sc->wi_node_name, sizeof(sc->wi_node_name)); bcopy(WI_DEFAULT_NODENAME, sc->wi_node_name, sizeof(WI_DEFAULT_NODENAME) - 1); bzero(sc->wi_net_name, sizeof(sc->wi_net_name)); bcopy(WI_DEFAULT_NETNAME, sc->wi_net_name, sizeof(WI_DEFAULT_NETNAME) - 1); bzero(sc->wi_ibss_name, sizeof(sc->wi_ibss_name)); bcopy(WI_DEFAULT_IBSS, sc->wi_ibss_name, sizeof(WI_DEFAULT_IBSS) - 1); sc->wi_portnum = WI_DEFAULT_PORT; sc->wi_ptype = WI_PORTTYPE_BSS; sc->wi_ap_density = WI_DEFAULT_AP_DENSITY; sc->wi_rts_thresh = WI_DEFAULT_RTS_THRESH; sc->wi_tx_rate = WI_DEFAULT_TX_RATE; sc->wi_max_data_len = WI_DEFAULT_DATALEN; sc->wi_create_ibss = WI_DEFAULT_CREATE_IBSS; sc->wi_pm_enabled = WI_DEFAULT_PM_ENABLED; sc->wi_max_sleep = WI_DEFAULT_MAX_SLEEP; sc->wi_roaming = WI_DEFAULT_ROAMING; sc->wi_authtype = WI_DEFAULT_AUTHTYPE; sc->wi_authmode = IEEE80211_AUTH_OPEN; /* * Read the default channel from the NIC. This may vary * depending on the country where the NIC was purchased, so * we can't hard-code a default and expect it to work for * everyone. */ gen.wi_type = WI_RID_OWN_CHNL; gen.wi_len = 2; wi_read_record(sc, &gen); sc->wi_channel = gen.wi_val; /* * Set flags based on firmware version. */ switch (sc->sc_firmware_type) { case WI_LUCENT: sc->wi_flags |= WI_FLAGS_HAS_ROAMING; if (sc->sc_sta_firmware_ver >= 60000) sc->wi_flags |= WI_FLAGS_HAS_MOR; if (sc->sc_sta_firmware_ver >= 60006) { sc->wi_flags |= WI_FLAGS_HAS_IBSS; sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS; } sc->wi_ibss_port = htole16(1); break; case WI_INTERSIL: sc->wi_flags |= WI_FLAGS_HAS_ROAMING; if (sc->sc_sta_firmware_ver >= 800) { sc->wi_flags |= WI_FLAGS_HAS_IBSS; sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS; } /* * version 0.8.3 and newer are the only ones that are known * to currently work. Earlier versions can be made to work, * at least according to the Linux driver. */ if (sc->sc_sta_firmware_ver >= 803) sc->wi_flags |= WI_FLAGS_HAS_HOSTAP; sc->wi_ibss_port = htole16(0); break; case WI_SYMBOL: sc->wi_flags |= WI_FLAGS_HAS_DIVERSITY; if (sc->sc_sta_firmware_ver >= 20000) sc->wi_flags |= WI_FLAGS_HAS_IBSS; /* Older Symbol firmware does not support IBSS creation. */ if (sc->sc_sta_firmware_ver >= 25000) sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS; sc->wi_ibss_port = htole16(4); break; } /* * Find out if we support WEP on this card. */ gen.wi_type = WI_RID_WEP_AVAIL; gen.wi_len = 2; wi_read_record(sc, &gen); sc->wi_has_wep = gen.wi_val; if (bootverbose) device_printf(sc->dev, "wi_has_wep = %d\n", sc->wi_has_wep); /* * Find supported rates. */ gen.wi_type = WI_RID_DATA_RATES; gen.wi_len = 2; if (wi_read_record(sc, &gen)) sc->wi_supprates = WI_SUPPRATES_1M | WI_SUPPRATES_2M | WI_SUPPRATES_5M | WI_SUPPRATES_11M; else sc->wi_supprates = gen.wi_val; bzero((char *)&sc->wi_stats, sizeof(sc->wi_stats)); wi_init(sc); wi_stop(sc); ifmedia_init(&sc->ifmedia, 0, wi_media_change, wi_media_status);#define ADD(m, c) ifmedia_add(&sc->ifmedia, (m), (c), NULL) if (sc->wi_supprates & WI_SUPPRATES_1M) { ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, 0, 0), 0); ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, IFM_IEEE80211_ADHOC, 0), 0); if (sc->wi_flags & WI_FLAGS_HAS_IBSS) ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, IFM_IEEE80211_IBSS, 0), 0); if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS) ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, IFM_IEEE80211_IBSSMASTER, 0), 0); if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP) ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, IFM_IEEE80211_HOSTAP, 0), 0); } if (sc->wi_supprates & WI_SUPPRATES_2M) { ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, 0, 0), 0); ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, IFM_IEEE80211_ADHOC, 0), 0); if (sc->wi_flags & WI_FLAGS_HAS_IBSS) ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, IFM_IEEE80211_IBSS, 0), 0); if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS) ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, IFM_IEEE80211_IBSSMASTER, 0), 0); if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP) ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, IFM_IEEE80211_HOSTAP, 0), 0); } if (sc->wi_supprates & WI_SUPPRATES_5M) { ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, 0, 0), 0); ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, IFM_IEEE80211_ADHOC, 0), 0); if (sc->wi_flags & WI_FLAGS_HAS_IBSS) ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, IFM_IEEE80211_IBSS, 0), 0); if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS) ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, IFM_IEEE80211_IBSSMASTER, 0), 0); if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP) ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, IFM_IEEE80211_HOSTAP, 0), 0); } if (sc->wi_supprates & WI_SUPPRATES_11M) { ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, 0, 0), 0); ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, IFM_IEEE80211_ADHOC, 0), 0); if (sc->wi_flags & WI_FLAGS_HAS_IBSS) ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, IFM_IEEE80211_IBSS, 0), 0); if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS) ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, IFM_IEEE80211_IBSSMASTER, 0), 0); if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP) ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, IFM_IEEE80211_HOSTAP, 0), 0); ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_MANUAL, 0, 0), 0); } ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, IFM_IEEE80211_ADHOC, 0), 0); if (sc->wi_flags & WI_FLAGS_HAS_IBSS) ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, IFM_IEEE80211_IBSS, 0), 0); if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS) ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, IFM_IEEE80211_IBSSMASTER, 0), 0); if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP) ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, IFM_IEEE80211_HOSTAP, 0), 0); ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0), 0);#undef ADD ifmedia_set(&sc->ifmedia, IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0)); /* * Call MI attach routine. */ ether_ifattach(ifp, sc->arpcom.ac_enaddr); callout_handle_init(&sc->wi_stat_ch); WI_UNLOCK(sc, s); return(0);}static voidwi_get_id(sc) struct wi_softc *sc;{ struct wi_ltv_ver ver; struct wi_card_ident *id; /* getting chip identity */ memset(&ver, 0, sizeof(ver)); ver.wi_type = WI_RID_CARD_ID; ver.wi_len = 5; wi_read_record(sc, (struct wi_ltv_gen *)&ver); device_printf(sc->dev, "using "); sc->sc_firmware_type = WI_NOTYPE; for (id = wi_card_ident; id->card_name != NULL; id++) { if (le16toh(ver.wi_ver[0]) == id->card_id) { printf("%s", id->card_name); sc->sc_firmware_type = id->firm_type; break; } } if (sc->sc_firmware_type == WI_NOTYPE) { if (le16toh(ver.wi_ver[0]) & 0x8000) { printf("Unknown PRISM2 chip"); sc->sc_firmware_type = WI_INTERSIL; } else { printf("Unknown Lucent chip"); sc->sc_firmware_type = WI_LUCENT; } } if (sc->sc_firmware_type != WI_LUCENT) { /* get primary firmware version */ memset(&ver, 0, sizeof(ver)); ver.wi_type = WI_RID_PRI_IDENTITY; ver.wi_len = 5; wi_read_record(sc, (struct wi_ltv_gen *)&ver); ver.wi_ver[1] = le16toh(ver.wi_ver[1]); ver.wi_ver[2] = le16toh(ver.wi_ver[2]); ver.wi_ver[3] = le16toh(ver.wi_ver[3]); sc->sc_pri_firmware_ver = ver.wi_ver[2] * 10000 + ver.wi_ver[3] * 100 + ver.wi_ver[1]; } /* get station firmware version */ memset(&ver, 0, sizeof(ver)); ver.wi_type = WI_RID_STA_IDENTITY; ver.wi_len = 5; wi_read_record(sc, (struct wi_ltv_gen *)&ver); ver.wi_ver[1] = le16toh(ver.wi_ver[1]); ver.wi_ver[2] = le16toh(ver.wi_ver[2]); ver.wi_ver[3] = le16toh(ver.wi_ver[3]); sc->sc_sta_firmware_ver = ver.wi_ver[2] * 10000 + ver.wi_ver[3] * 100 + ver.wi_ver[1]; if (sc->sc_firmware_type == WI_INTERSIL && (sc->sc_sta_firmware_ver == 10102 || sc->sc_sta_firmware_ver == 20102)) { struct wi_ltv_str sver; char *p; memset(&sver, 0, sizeof(sver)); sver.wi_type = WI_RID_SYMBOL_IDENTITY; sver.wi_len = 7; /* value should be the format like "V2.00-11" */ if (wi_read_record(sc, (struct wi_ltv_gen *)&sver) == 0 && *(p = (char *)sver.wi_str) >= 'A' && p[2] == '.' && p[5] == '-' && p[8] == '\0') { sc->sc_firmware_type = WI_SYMBOL; sc->sc_sta_firmware_ver = (p[1] - '0') * 10000 + (p[3] - '0') * 1000 + (p[4] - '0') * 100 + (p[6] - '0') * 10 + (p[7] - '0'); } } printf("\n"); device_printf(sc->dev, "%s Firmware: ", sc->sc_firmware_type == WI_LUCENT ? "Lucent" : (sc->sc_firmware_type == WI_SYMBOL ? "Symbol" : "Intersil")); /* * The primary firmware is only valid on Prism based chipsets * (INTERSIL or SYMBOL). */ if (sc->sc_firmware_type != WI_LUCENT) printf("Primary %u.%02u.%02u, ", sc->sc_pri_firmware_ver / 10000, (sc->sc_pri_firmware_ver % 10000) / 100, sc->sc_pri_firmware_ver % 100); printf("Station %u.%02u.%02u\n", sc->sc_sta_firmware_ver / 10000, (sc->sc_sta_firmware_ver % 10000) / 100, sc->sc_sta_firmware_ver % 100); return;}static voidwi_rxeof(sc) struct wi_softc *sc;{ struct ifnet *ifp; struct ether_header *eh; struct mbuf *m; int id; ifp = &sc->arpcom.ac_if;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -