📄 if_wi.c
字号:
/* char wrongaddr2[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};*/ if (!bcmp(tx_frame->wi_dst_addr, wrongaddr1, 6))/* || !bcmp(tx_frame->wi_dst_addr, wrongaddr2, 6))*/ /* wrong dest address, forget this frame */ ; else { msglen = tx_frame->wi_dat_len; msglen += WI_SNAPHDR_LEN; /* if we're using WEP, 64 bits is added to packet */ if (sc->wi_use_wep) msglen += 8; if (sc->arpcom.ac_if.if_flags & IFF_DEBUG) { device_printf(sc->dev, "wi_dat_len=%d\n", tx_frame->wi_dat_len); device_printf(sc->dev, "status=%d, ", tx_frame->wi_status); device_printf(sc->dev, "thus len=%ld\n", msglen); } int cache_slot; cache_slot = wi_findCacheEntry(sc, tx_frame->wi_dst_addr); if (cache_slot > -1) { struct wi_sigextcache *p; p = &sc->wi_sigextcache[cache_slot]; /* printf("cach_slot %d\n", cache_slot); */ p->sndpkts++; p->sndbytes += msglen; p->tempsndbytes += msglen; if (sc->wi_ptype == WI_PORTTYPE_BSS) p->remove_ctr = sc->wi_timeout_time;/* device_printf(sc->dev, "bw_timer: storing cache in slot %d\n", cache_slot);*/ } } }#endif if (wi_seek(sc, id, off, WI_BAP0)) return(EIO); ptr = (u_int16_t *)buf; for (i = 0; i < (len / 2); i++) CSR_WRITE_2(sc, WI_DATA0, ptr[i]);#ifdef WI_HERMES_AUTOINC_WAR CSR_WRITE_2(sc, WI_DATA0, 0x1234); CSR_WRITE_2(sc, WI_DATA0, 0x5678); if (wi_seek(sc, id, off + len, WI_BAP0)) return(EIO); if (CSR_READ_2(sc, WI_DATA0) != 0x1234 || CSR_READ_2(sc, WI_DATA0) != 0x5678) { if (--retries >= 0) goto again; device_printf(sc->dev, "wi_write_data device timeout\n"); return (EIO); }#endif return(0);}/* * Allocate a region of memory inside the NIC and zero * it out. */static intwi_alloc_nicmem(sc, len, id) struct wi_softc *sc; int len; int *id;{ int i; if (wi_cmd(sc, WI_CMD_ALLOC_MEM, len, 0, 0)) { device_printf(sc->dev, "failed to allocate %d bytes on NIC\n", len); return(ENOMEM); } for (i = 0; i < WI_TIMEOUT; i++) { if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_ALLOC) break; DELAY(WI_DELAY); } if (i == WI_TIMEOUT) { device_printf(sc->dev, "time out allocating memory on card\n"); return(ETIMEDOUT); } CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC); *id = CSR_READ_2(sc, WI_ALLOC_FID); if (wi_seek(sc, *id, 0, WI_BAP0)) { device_printf(sc->dev, "seek failed while allocating memory on card\n"); return(EIO); } for (i = 0; i < len / 2; i++) CSR_WRITE_2(sc, WI_DATA0, 0); return(0);}static voidwi_setmulti(sc) struct wi_softc *sc;{ struct ifnet *ifp; int i = 0; struct ifmultiaddr *ifma; struct wi_ltv_mcast mcast; ifp = &sc->arpcom.ac_if; bzero((char *)&mcast, sizeof(mcast)); mcast.wi_type = WI_RID_MCAST_LIST; mcast.wi_len = (3 * 16) + 1; if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) { wi_write_record(sc, (struct wi_ltv_gen *)&mcast); return; }#if __FreeBSD_version < 500000 LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {#else TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {#endif if (ifma->ifma_addr->sa_family != AF_LINK) continue; if (i < 16) { bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr), (char *)&mcast.wi_mcast[i], ETHER_ADDR_LEN); i++; } else { bzero((char *)&mcast, sizeof(mcast)); break; } } mcast.wi_len = (i * 3) + 1; wi_write_record(sc, (struct wi_ltv_gen *)&mcast); return;}static voidwi_setdef(sc, wreq) struct wi_softc *sc; struct wi_req *wreq;{ struct sockaddr_dl *sdl; struct ifaddr *ifa; struct ifnet *ifp; ifp = &sc->arpcom.ac_if; switch(wreq->wi_type) { case WI_RID_MAC_NODE: ifa = ifaddr_byindex(ifp->if_index); sdl = (struct sockaddr_dl *)ifa->ifa_addr; bcopy((char *)&wreq->wi_val, (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN); bcopy((char *)&wreq->wi_val, LLADDR(sdl), ETHER_ADDR_LEN); break; case WI_RID_PORTTYPE: sc->wi_ptype = le16toh(wreq->wi_val[0]); break; case WI_RID_TX_RATE: sc->wi_tx_rate = le16toh(wreq->wi_val[0]); break; case WI_RID_MAX_DATALEN: sc->wi_max_data_len = le16toh(wreq->wi_val[0]); break; case WI_RID_RTS_THRESH: sc->wi_rts_thresh = le16toh(wreq->wi_val[0]); break; case WI_RID_SYSTEM_SCALE: sc->wi_ap_density = le16toh(wreq->wi_val[0]); break; case WI_RID_CREATE_IBSS: sc->wi_create_ibss = le16toh(wreq->wi_val[0]); break; case WI_RID_OWN_CHNL: sc->wi_channel = le16toh(wreq->wi_val[0]); break; case WI_RID_NODENAME: bzero(sc->wi_node_name, sizeof(sc->wi_node_name)); bcopy((char *)&wreq->wi_val[1], sc->wi_node_name, 30); break; case WI_RID_DESIRED_SSID: bzero(sc->wi_net_name, sizeof(sc->wi_net_name)); bcopy((char *)&wreq->wi_val[1], sc->wi_net_name, 30); break; case WI_RID_OWN_SSID: bzero(sc->wi_ibss_name, sizeof(sc->wi_ibss_name)); bcopy((char *)&wreq->wi_val[1], sc->wi_ibss_name, 30); break; case WI_RID_PM_ENABLED: sc->wi_pm_enabled = le16toh(wreq->wi_val[0]); break; case WI_RID_MICROWAVE_OVEN: sc->wi_mor_enabled = le16toh(wreq->wi_val[0]); break; case WI_RID_MAX_SLEEP: sc->wi_max_sleep = le16toh(wreq->wi_val[0]); break; case WI_RID_CNFAUTHMODE: sc->wi_authtype = le16toh(wreq->wi_val[0]); break; case WI_RID_ROAMING_MODE: sc->wi_roaming = le16toh(wreq->wi_val[0]); break; case WI_RID_ENCRYPTION: sc->wi_use_wep = le16toh(wreq->wi_val[0]); break; case WI_RID_TX_CRYPT_KEY: sc->wi_tx_key = le16toh(wreq->wi_val[0]); break; case WI_RID_DEFLT_CRYPT_KEYS: bcopy((char *)wreq, (char *)&sc->wi_keys, sizeof(struct wi_ltv_keys)); break; default: break; } /* Reinitialize WaveLAN. */ wi_init(sc); return;}static intwi_ioctl(ifp, command, data) struct ifnet *ifp; u_long command; caddr_t data;{ int error = 0; int len; int s; uint16_t mif; uint16_t val; u_int8_t tmpkey[14]; char tmpssid[IEEE80211_NWID_LEN]; struct wi_softc *sc; struct wi_req wreq; struct ifreq *ifr; struct ieee80211req *ireq;#if __FreeBSD_version >= 500000 struct thread *td = curthread;#else struct proc *td = curproc; /* Little white lie */#endif sc = ifp->if_softc; WI_LOCK(sc, s); ifr = (struct ifreq *)data; ireq = (struct ieee80211req *)data; if (sc->wi_gone) { error = ENODEV; goto out; } switch(command) { case SIOCSIFFLAGS: /* * Can't do promisc and hostap at the same time. If all that's * changing is the promisc flag, try to short-circuit a call to * wi_init() by just setting PROMISC in the hardware. */ if (ifp->if_flags & IFF_UP) { if (sc->wi_ptype != WI_PORTTYPE_HOSTAP && ifp->if_flags & IFF_RUNNING) { if (ifp->if_flags & IFF_PROMISC && !(sc->wi_if_flags & IFF_PROMISC)) { WI_SETVAL(WI_RID_PROMISC, 1); } else if (!(ifp->if_flags & IFF_PROMISC) && sc->wi_if_flags & IFF_PROMISC) { WI_SETVAL(WI_RID_PROMISC, 0); } else { wi_init(sc); } } else { wi_init(sc); } } else { if (ifp->if_flags & IFF_RUNNING) { wi_stop(sc); } } sc->wi_if_flags = ifp->if_flags; error = 0; break; case SIOCSIFMEDIA: case SIOCGIFMEDIA: error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command); break; case SIOCADDMULTI: case SIOCDELMULTI: wi_setmulti(sc); error = 0; break; case SIOCGWAVELAN: error = copyin(ifr->ifr_data, &wreq, sizeof(wreq)); if (error) break; if (wreq.wi_len > WI_MAX_DATALEN) { error = EINVAL; break; } /* Don't show WEP keys to non-root users. */ if (wreq.wi_type == WI_RID_DEFLT_CRYPT_KEYS && suser(td)) break; if (wreq.wi_type == WI_RID_IFACE_STATS) { bcopy((char *)&sc->wi_stats, (char *)&wreq.wi_val, sizeof(sc->wi_stats)); wreq.wi_len = (sizeof(sc->wi_stats) / 2) + 1; } else if (wreq.wi_type == WI_RID_DEFLT_CRYPT_KEYS) { bcopy((char *)&sc->wi_keys, (char *)&wreq, sizeof(struct wi_ltv_keys)); }#ifdef WICACHE else if (wreq.wi_type == WI_RID_ZERO_CACHE) { device_printf(sc->dev, "ioctl ZERO-ing CACHE!!!\n"); sc->wi_sigitems = sc->wi_nextitem = 0; } else if (wreq.wi_type == WI_RID_READ_CACHE) { char *pt = (char *)&wreq.wi_val; /* we make sure we don't exceed the WI_MAX_DATALEN limit if we have more than can be transfered, simply skip those also, we return this number of items, not the real, bigger one so older programs can still work with this driver */ int tocopy, maxtransfer; tocopy = sc->wi_sigitems; maxtransfer = (WI_MAX_DATALEN << 1) * sizeof(struct wi_sigcache); if (tocopy > maxtransfer) tocopy = maxtransfer; bcopy((char *)&tocopy, (char *)pt, sizeof(int)); pt += (sizeof (int)); wreq.wi_len = sizeof(int) / 2; bcopy((char *)&sc->wi_sigcache, (char *)pt, sizeof(struct wi_sigcache) * tocopy); wreq.wi_len += ((sizeof(struct wi_sigcache) * tocopy) / 2) + 1; } else if (wreq.wi_type == WI_RID_ZERO_EXTCACHE) { sc->wi_sigitems = sc->wi_nextitem = 0; /* set whole cache buffer to zero */ bzero(sc->wi_sigextcache, MAXWICACHE * sizeof(struct wi_sigextcache)); } else if (wreq.wi_type == WI_RID_READ_EXTCACHE) { char *pt = (char *)&wreq.wi_val; int offset, tocopy; bcopy(pt, (char *) &offset, sizeof(int)); /* offset now contains the first entry the user wants to have we give all entries from [offset, offset+MAXCACHE_TRANSFER-1] or less, if the end is reached. */ /* but the first integer we return is always total number of items! */ bcopy((char *)&sc->wi_sigitems, (char *)pt, sizeof(int)); pt += (sizeof (int)); wreq.wi_len = sizeof(int) / 2; tocopy = MAXCACHE_TRANSFER; if (sc->wi_sigitems - offset < tocopy) tocopy = sc->wi_sigitems - offset; if (sc->arpcom.ac_if.if_flags & IFF_DEBUG) device_printf(sc->dev, "READ_EXTCACHE returning %d items: %d till %d\n", tocopy, offset, offset+tocopy-1); if (tocopy > 0) { bcopy((char *)&sc->wi_sigextcache[offset], (char *)pt, sizeof(struct wi_sigextcache) * tocopy); wreq.wi_len += ((sizeof(struct wi_sigextcache) * tocopy) / 2) + 1; } } else if (wreq.wi_type == WI_RID_READ_EWMACONSTBW) { int ewmaconst = (int) (1000 * sc->wi_ewmaconst_bw); bcopy((char *)&ewmaconst, (char *)&wreq.wi_val, sizeof(int)); wreq.wi_len = sizeof(int) / 2; /* in words... */ } else if (wreq.wi_type == WI_RID_READ_EWMACONSTSNQ) { int ewmaconst = (int) (1000 * sc->wi_ewmaconst_snq); bcopy((char *)&ewmaconst, (char *)&wreq.wi_val, sizeof(int)); wreq.wi_len = sizeof(int) / 2; /* in words... */ } else if (wreq.wi_type == WI_RID_READ_TIMEOUT_TIME) { wreq.wi_val[0] = sc->wi_timeout_time; wreq.wi_len = 2; /* why should this be 2 (check other word-returns)? we're only returning 1 word! */ }#endif else if (wreq.wi_type == WI_RID_PROCFRAME) { wreq.wi_len = 2; wreq.wi_val[0] = sc->wi_procframe; } else if (wreq.wi_type == WI_RID_PRISM2) { wreq.wi_len = 2; wreq.wi_val[0] = sc->sc_firmware_type != WI_LUCENT; } else if (wreq.wi_type == WI_RID_SCAN_RES && sc->sc_firmware_type == WI_LUCENT) { memcpy((char *)wreq.wi_val, (char *)sc->wi_scanbuf, sc->wi_scanbuf_len * 2); wreq.wi_len = sc->wi_scanbuf_len; } else if (wreq.wi_type == WI_RID_MIF) { mif = wreq.wi_val[0]; error = wi_cmd(sc, WI_CMD_READMIF, mif, 0, 0); val = CSR_READ_2(sc, WI_RESP0); wreq.wi_len = 2; wreq.wi_val[0] = val; } else { if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq)) { error = EINVAL; break; } } error = copyout(&wreq, ifr->ifr_data, sizeof(wreq)); break; case SIOCSWAVELAN: if ((error = suser(td))) goto out; error = copyin(ifr->ifr_data, &wreq, sizeof(wreq)); if (error) break; if (wreq.wi_len > WI_MAX_DATALEN) { error = EINVAL; break; } if (wreq.wi_type == WI_RID_IFACE_STATS) { error = EINVAL; break; } else if (wreq.wi_type == WI_RID_MGMT_XMIT) { error = wi_mgmt_xmit(sc, (caddr_t)&wreq.wi_val, wreq.wi_len); } else if (wreq.wi_type == WI_RID_PROCFRAME) { sc->wi_procframe = wreq.wi_val[0]; /* * if we're getting a scan request from a wavelan card * (non-prism2), send out a cmd_inquire to the card to scan * results for the scan will be received through the info * interrupt handler. otherwise the scan request can be * directly han
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -