diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 2002-06-02 16:11:42 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 2002-06-02 16:11:42 +0000 |
commit | e1911cbef977ccb3bb76dbba1bdc76b56be0d952 (patch) | |
tree | 23527b98b664e677bfca515cbeea5f7269ca15aa /sys/dev/ic | |
parent | 426c9769ea744018e36523028904cc3804ceab2f (diff) |
BSD air-tools 0.2 patches from dachb0den labs; h1kari@dachb0den.com
The common.h include file has been incorporated into if_wi_ieee.h
similar to what is in FreeBSD.
Diffstat (limited to 'sys/dev/ic')
-rw-r--r-- | sys/dev/ic/if_wi.c | 553 | ||||
-rw-r--r-- | sys/dev/ic/if_wi_ieee.h | 374 | ||||
-rw-r--r-- | sys/dev/ic/if_wivar.h | 22 |
3 files changed, 822 insertions, 127 deletions
diff --git a/sys/dev/ic/if_wi.c b/sys/dev/ic/if_wi.c index e64e95c7c47..e9a3c233973 100644 --- a/sys/dev/ic/if_wi.c +++ b/sys/dev/ic/if_wi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_wi.c,v 1.61 2002/05/31 19:27:40 millert Exp $ */ +/* $OpenBSD: if_wi.c,v 1.62 2002/06/02 16:11:41 millert Exp $ */ /* * Copyright (c) 1997, 1998, 1999 @@ -124,7 +124,7 @@ u_int32_t widebug = WIDEBUG; #if !defined(lint) && !defined(__OpenBSD__) static const char rcsid[] = - "$OpenBSD: if_wi.c,v 1.61 2002/05/31 19:27:40 millert Exp $"; + "$OpenBSD: if_wi.c,v 1.62 2002/06/02 16:11:41 millert Exp $"; #endif /* lint */ #ifdef foo @@ -142,7 +142,7 @@ STATIC void wi_txeof(struct wi_softc *, int); STATIC void wi_update_stats(struct wi_softc *); STATIC void wi_setmulti(struct wi_softc *); -STATIC int wi_cmd(struct wi_softc *, int, int); +STATIC int wi_cmd(struct wi_softc *, int, int, int, int); STATIC int wi_read_record(struct wi_softc *, struct wi_ltv_gen *); STATIC int wi_write_record(struct wi_softc *, struct wi_ltv_gen *); STATIC int wi_read_data(struct wi_softc *, int, @@ -165,6 +165,9 @@ STATIC int wi_sync_media(struct wi_softc *, int, int); STATIC int wi_set_pm(struct wi_softc *, struct ieee80211_power *); STATIC int wi_get_pm(struct wi_softc *, struct ieee80211_power *); +STATIC int wi_get_debug(struct wi_softc *, struct wi_req *); +STATIC int wi_set_debug(struct wi_softc *, struct wi_req *); + int wi_intr(void *); int wi_attach(struct wi_softc *); void wi_init(struct wi_softc *); @@ -463,7 +466,6 @@ wi_rxeof(sc) { struct ifnet *ifp; struct ether_header *eh; - struct wi_frame rx_frame; struct mbuf *m; int id; @@ -471,134 +473,233 @@ wi_rxeof(sc) id = CSR_READ_2(sc, WI_RX_FID); - /* First read in the frame header */ - if (wi_read_data(sc, id, 0, (caddr_t)&rx_frame, sizeof(rx_frame))) { - ifp->if_ierrors++; - return; - } + if (sc->wi_procframe || sc->wi_debug.wi_monitor) { + struct wi_frame *rx_frame; + int datlen, hdrlen; - /* - * Drop undecryptable or packets with receive errors here - */ - if (rx_frame.wi_status & htole16(WI_STAT_ERRSTAT)) { - ifp->if_ierrors++; - return; - } - - MGETHDR(m, M_DONTWAIT, MT_DATA); - if (m == NULL) { - ifp->if_ierrors++; - return; - } - MCLGET(m, M_DONTWAIT); - if (!(m->m_flags & M_EXT)) { - m_freem(m); - ifp->if_ierrors++; - return; - } - - /* Align the data after the ethernet header */ - m->m_data = (caddr_t) ALIGN(m->m_data + sizeof(struct ether_header)) - - sizeof(struct ether_header); + MGETHDR(m, M_DONTWAIT, MT_DATA); + if (m == NULL) { + ifp->if_ierrors++; + return; + } + MCLGET(m, M_DONTWAIT); + if (!(m->m_flags & M_EXT)) { + m_freem(m); + ifp->if_ierrors++; + return; + } - eh = mtod(m, struct ether_header *); - m->m_pkthdr.rcvif = ifp; + m->m_pkthdr.rcvif = ifp; - if (rx_frame.wi_status == htole16(WI_STAT_MGMT) && - sc->wi_ptype == WI_PORTTYPE_AP) { + if (wi_read_data(sc, id, 0, mtod(m, caddr_t), + sizeof(struct wi_frame))) { + m_freem(m); + ifp->if_ierrors++; + return; + } - u_int16_t rxlen = letoh16(rx_frame.wi_dat_len); + rx_frame = mtod(m, struct wi_frame *); - if ((WI_802_11_OFFSET_RAW + rxlen + 2) > MCLBYTES) { - printf("%s: oversized mgmt packet received in " - "hostap mode (wi_dat_len=%d, wi_status=0x%x)\n", - sc->sc_dev.dv_xname, - rxlen, letoh16(rx_frame.wi_status)); + if (rx_frame->wi_status & htole16(WI_STAT_BADCRC)) { m_freem(m); - ifp->if_ierrors++; + ifp->if_ierrors++; return; } - /* Put the whole header in there. */ - bcopy(&rx_frame, mtod(m, void *), sizeof(struct wi_frame)); - if (wi_read_data(sc, id, WI_802_11_OFFSET_RAW, - mtod(m, caddr_t) + WI_802_11_OFFSET_RAW, rxlen + 2)) { + switch ((letoh16(rx_frame->wi_status) & WI_STAT_MAC_PORT) + >> 8) { + case 7: + switch (letoh16(rx_frame->wi_frame_ctl) & + WI_FCTL_FTYPE) { + case WI_FTYPE_DATA: + hdrlen = WI_DATA_HDRLEN; + datlen = letoh16(rx_frame->wi_dat_len); + break; + case WI_FTYPE_MGMT: + hdrlen = WI_MGMT_HDRLEN; + datlen = letoh16(rx_frame->wi_dat_len); + break; + case WI_FTYPE_CTL: + hdrlen = WI_CTL_HDRLEN; + datlen = 0; + break; + default: + printf(WI_PRT_FMT ": received packet of " + "unknown type on port 7\n", WI_PRT_ARG(sc)); + m_freem(m); + ifp->if_ierrors++; + return; + } + break; + case 0: + hdrlen = WI_DATA_HDRLEN; + datlen = letoh16(rx_frame->wi_dat_len); + break; + default: + printf(WI_PRT_FMT ": received packet on invalid port " + "(wi_status=0x%x)\n", WI_PRT_ARG(sc), + letoh16(rx_frame->wi_status)); m_freem(m); - if (sc->arpcom.ac_if.if_flags & IFF_DEBUG) - printf("wihap: failed to copy header\n"); ifp->if_ierrors++; return; } - m->m_pkthdr.len = m->m_len = WI_802_11_OFFSET_RAW + rxlen; - - /* XXX: consider giving packet to bhp? */ - - wihap_mgmt_input(sc, &rx_frame, m); - - return; - } - - if (rx_frame.wi_status == htole16(WI_STAT_1042) || - rx_frame.wi_status == htole16(WI_STAT_TUNNEL) || - rx_frame.wi_status == htole16(WI_STAT_WMP_MSG)) { - if ((letoh16(rx_frame.wi_dat_len) + WI_SNAPHDR_LEN) > MCLBYTES) { - printf(WI_PRT_FMT ": oversized packet received " - "(wi_dat_len=%d, wi_status=0x%x)\n", - WI_PRT_ARG(sc), letoh16(rx_frame.wi_dat_len), - letoh16(rx_frame.wi_status)); + if ((hdrlen + datlen + 2) > MCLBYTES) { m_freem(m); ifp->if_ierrors++; return; } - m->m_pkthdr.len = m->m_len = - letoh16(rx_frame.wi_dat_len) + WI_SNAPHDR_LEN; - - bcopy((char *)&rx_frame.wi_dst_addr, - (char *)&eh->ether_dhost, ETHER_ADDR_LEN); - bcopy((char *)&rx_frame.wi_src_addr, - (char *)&eh->ether_shost, ETHER_ADDR_LEN); - bcopy((char *)&rx_frame.wi_type, - (char *)&eh->ether_type, ETHER_TYPE_LEN); - - if (wi_read_data(sc, id, WI_802_11_OFFSET, mtod(m, caddr_t) + - sizeof(struct ether_header), m->m_len + 2)) { - ifp->if_ierrors++; + + if (wi_read_data(sc, id, hdrlen, mtod(m, caddr_t) + hdrlen, + datlen + 2)) { m_freem(m); + ifp->if_ierrors++; return; } + + m->m_pkthdr.len = m->m_len = hdrlen + datlen; } else { - if ((letoh16(rx_frame.wi_dat_len) + - sizeof(struct ether_header)) > MCLBYTES) { - printf(WI_PRT_FMT ": oversized packet received " - "(wi_dat_len=%d, wi_status=0x%x)\n", - WI_PRT_ARG(sc), letoh16(rx_frame.wi_dat_len), - letoh16(rx_frame.wi_status)); - m_freem(m); + struct wi_frame rx_frame; + + /* First read in the frame header */ + if (wi_read_data(sc, id, 0, (caddr_t)&rx_frame, + sizeof(rx_frame))) { ifp->if_ierrors++; return; } - m->m_pkthdr.len = m->m_len = - letoh16(rx_frame.wi_dat_len) + sizeof(struct ether_header); - if (wi_read_data(sc, id, WI_802_3_OFFSET, - mtod(m, caddr_t), m->m_len + 2)) { + /* + * Drop undecryptable or packets with receive errors here + */ + if (rx_frame.wi_status & htole16(WI_STAT_ERRSTAT)) { + ifp->if_ierrors++; + return; + } + + MGETHDR(m, M_DONTWAIT, MT_DATA); + if (m == NULL) { + ifp->if_ierrors++; + return; + } + MCLGET(m, M_DONTWAIT); + if (!(m->m_flags & M_EXT)) { m_freem(m); ifp->if_ierrors++; return; } - } - ifp->if_ipackets++; + /* Align the data after the ethernet header */ + m->m_data = (caddr_t)ALIGN(m->m_data + + sizeof(struct ether_header)) - sizeof(struct ether_header); + + eh = mtod(m, struct ether_header *); + m->m_pkthdr.rcvif = ifp; + + if (rx_frame.wi_status == htole16(WI_STAT_MGMT) && + sc->wi_ptype == WI_PORTTYPE_AP) { + + u_int16_t rxlen = letoh16(rx_frame.wi_dat_len); + + if ((WI_802_11_OFFSET_RAW + rxlen + 2) > MCLBYTES) { + printf("%s: oversized mgmt packet received in " + "hostap mode (wi_dat_len=%d, " + "wi_status=0x%x)\n", sc->sc_dev.dv_xname, + rxlen, letoh16(rx_frame.wi_status)); + m_freem(m); + ifp->if_ierrors++; + return; + } + + /* Put the whole header in there. */ + bcopy(&rx_frame, mtod(m, void *), + sizeof(struct wi_frame)); + if (wi_read_data(sc, id, WI_802_11_OFFSET_RAW, + mtod(m, caddr_t) + WI_802_11_OFFSET_RAW, + rxlen + 2)) { + m_freem(m); + if (sc->arpcom.ac_if.if_flags & IFF_DEBUG) + printf("wihap: failed to copy header\n"); + ifp->if_ierrors++; + return; + } + + m->m_pkthdr.len = m->m_len = + WI_802_11_OFFSET_RAW + rxlen; + + /* XXX: consider giving packet to bhp? */ + + wihap_mgmt_input(sc, &rx_frame, m); - if (sc->wi_ptype == WI_PORTTYPE_AP) { - /* - * Give host AP code first crack at data packets. - * If it decides to handle it (or drop it), it will return - * a non-zero. Otherwise, it is destined for this host. - */ - if (wihap_data_input(sc, &rx_frame, m)) return; + } + + if (rx_frame.wi_status == htole16(WI_STAT_1042) || + rx_frame.wi_status == htole16(WI_STAT_TUNNEL) || + rx_frame.wi_status == htole16(WI_STAT_WMP_MSG)) { + if ((letoh16(rx_frame.wi_dat_len) + WI_SNAPHDR_LEN) > + MCLBYTES) { + printf(WI_PRT_FMT ": oversized packet received " + "(wi_dat_len=%d, wi_status=0x%x)\n", + WI_PRT_ARG(sc), + letoh16(rx_frame.wi_dat_len), + letoh16(rx_frame.wi_status)); + m_freem(m); + ifp->if_ierrors++; + return; + } + m->m_pkthdr.len = m->m_len = + letoh16(rx_frame.wi_dat_len) + WI_SNAPHDR_LEN; + + bcopy((char *)&rx_frame.wi_dst_addr, + (char *)&eh->ether_dhost, ETHER_ADDR_LEN); + bcopy((char *)&rx_frame.wi_src_addr, + (char *)&eh->ether_shost, ETHER_ADDR_LEN); + bcopy((char *)&rx_frame.wi_type, + (char *)&eh->ether_type, ETHER_TYPE_LEN); + + if (wi_read_data(sc, id, WI_802_11_OFFSET, + mtod(m, caddr_t) + sizeof(struct ether_header), + m->m_len + 2)) { + ifp->if_ierrors++; + m_freem(m); + return; + } + } else { + if ((letoh16(rx_frame.wi_dat_len) + + sizeof(struct ether_header)) > MCLBYTES) { + printf(WI_PRT_FMT ": oversized packet received " + "(wi_dat_len=%d, wi_status=0x%x)\n", + WI_PRT_ARG(sc), + letoh16(rx_frame.wi_dat_len), + letoh16(rx_frame.wi_status)); + m_freem(m); + ifp->if_ierrors++; + return; + } + m->m_pkthdr.len = m->m_len = + letoh16(rx_frame.wi_dat_len) + + sizeof(struct ether_header); + + if (wi_read_data(sc, id, WI_802_3_OFFSET, + mtod(m, caddr_t), m->m_len + 2)) { + m_freem(m); + ifp->if_ierrors++; + return; + } + } + + ifp->if_ipackets++; + + if (sc->wi_ptype == WI_PORTTYPE_AP) { + /* + * Give host AP code first crack at data packets. + * If it decides to handle it (or drop it), it will + * return a non-zero. Otherwise, it is destined for + * this host. + */ + if (wihap_data_input(sc, &rx_frame, m)) + return; + } } #if NBPFILTER > 0 @@ -607,8 +708,11 @@ wi_rxeof(sc) BPF_MTAP(ifp, m); #endif - /* Receive packet. */ - ether_input_mbuf(ifp, m); + /* Receive packet unless in procframe or monitor mode. */ + if (sc->wi_procframe || sc->wi_debug.wi_monitor) + m_freem(m); + else + ether_input_mbuf(ifp, m); return; } @@ -651,7 +755,7 @@ wi_inquire(xsc) return; s = splnet(); - rv = wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_COUNTERS); + rv = wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_COUNTERS, 0, 0); splx(s); if (rv) printf(WI_PRT_FMT ": wi_cmd failed with %d\n", WI_PRT_ARG(sc), @@ -677,12 +781,17 @@ wi_update_stats(sc) wi_read_data(sc, id, 0, (char *)&gen, 4); - if (gen.wi_type != WI_INFO_COUNTERS) + if (gen.wi_type == htole16(WI_INFO_SCAN_RESULTS)) { + sc->wi_scanbuf_len = letoh16(gen.wi_len); + wi_read_data(sc, id, 4, (char *)sc->wi_scanbuf, + sc->wi_scanbuf_len * 2); + return; + } else if (gen.wi_type != htole16(WI_INFO_COUNTERS)) return; /* Some card versions have a larger stats structure */ - len = (gen.wi_len - 1 < sizeof(sc->wi_stats) / 4) ? - gen.wi_len - 1 : sizeof(sc->wi_stats) / 4; + len = (letoh16(gen.wi_len) - 1 < sizeof(sc->wi_stats) / 4) ? + letoh16(gen.wi_len) - 1 : sizeof(sc->wi_stats) / 4; ptr = (u_int32_t *)&sc->wi_stats; @@ -703,10 +812,12 @@ wi_update_stats(sc) } STATIC int -wi_cmd(sc, cmd, val) +wi_cmd(sc, cmd, val0, val1, val2) struct wi_softc *sc; int cmd; - int val; + int val0; + int val1; + int val2; { int i, s = 0; @@ -717,9 +828,9 @@ wi_cmd(sc, cmd, val) DELAY(10); } - CSR_WRITE_2(sc, WI_PARAM0, val); - CSR_WRITE_2(sc, WI_PARAM1, 0); - CSR_WRITE_2(sc, WI_PARAM2, 0); + CSR_WRITE_2(sc, WI_PARAM0, val0); + CSR_WRITE_2(sc, WI_PARAM1, val1); + CSR_WRITE_2(sc, WI_PARAM2, val2); CSR_WRITE_2(sc, WI_COMMAND, cmd); for (i = WI_TIMEOUT; i--; DELAY(10)) { @@ -759,7 +870,7 @@ wi_reset(sc) (sc->wi_flags & WI_FLAGS_INITIALIZED)) return; - if (wi_cmd(sc, WI_CMD_INI, 0)) + if (wi_cmd(sc, WI_CMD_INI, 0, 0, 0)) printf(WI_PRT_FMT ": init failed\n", WI_PRT_ARG(sc)); else sc->wi_flags |= WI_FLAGS_INITIALIZED; @@ -830,7 +941,7 @@ wi_read_record(sc, ltv) } /* Tell the NIC to enter record read mode. */ - if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_READ, ltv->wi_type)) + if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_READ, ltv->wi_type, 0, 0)) return(EIO); /* Seek to the record. */ @@ -1004,7 +1115,7 @@ wi_write_record(sc, ltv) if (ltv->wi_len > 1) CSR_WRITE_RAW_2(sc, WI_DATA1, ptr, (ltv->wi_len-1) *2); - if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_WRITE, ltv->wi_type)) + if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_WRITE, ltv->wi_type, 0, 0)) return(EIO); return(0); @@ -1122,7 +1233,7 @@ wi_alloc_nicmem(sc, len, id) { int i; - if (wi_cmd(sc, WI_CMD_ALLOC_MEM, len)) { + if (wi_cmd(sc, WI_CMD_ALLOC_MEM, len, 0, 0)) { printf(WI_PRT_FMT ": failed to allocate %d bytes on NIC\n", WI_PRT_ARG(sc), len); return(ENOMEM); @@ -1320,6 +1431,7 @@ wi_ioctl(ifp, command, data) switch(command) { case SIOCSWAVELAN: + case SIOCSPRISM2DEBUG: case SIOCS80211NWID: case SIOCS80211NWKEY: case SIOCS80211POWER: @@ -1404,12 +1516,14 @@ wi_ioctl(ifp, command, data) error = EINVAL; break; } - if (wreq.wi_type == WI_RID_IFACE_STATS) { + switch (wreq.wi_type) { + case WI_RID_IFACE_STATS: /* XXX native byte order */ 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) { + break; + case WI_RID_DEFLT_CRYPT_KEYS: /* For non-root user, return all-zeroes keys */ if (suser(p->p_ucred, &p->p_acflag)) bzero((char *)&wreq, @@ -1417,11 +1531,29 @@ wi_ioctl(ifp, command, data) else bcopy((char *)&sc->wi_keys, (char *)&wreq, sizeof(struct wi_ltv_keys)); - } else { + break; + case WI_RID_PROCFRAME: + wreq.wi_len = 2; + wreq.wi_val[0] = htole16(sc->wi_procframe); + break; + case WI_RID_PRISM2: + wreq.wi_len = 2; + wreq.wi_val[0] = htole16(sc->sc_firmware_type == + WI_LUCENT ? 0 : 1); + break; + case WI_RID_SCAN_RES: + if (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; + break; + } + default: if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq)) { error = EINVAL; - break; } + break; } error = copyout(&wreq, ifr->ifr_data, sizeof(wreq)); break; @@ -1439,12 +1571,26 @@ wi_ioctl(ifp, command, data) error = wi_mgmt_xmit(sc, (caddr_t)&wreq.wi_val, wreq.wi_len); break; + case WI_RID_PROCFRAME: + sc->wi_procframe = letoh16(wreq.wi_val[0]); + error = 0; + break; + case WI_RID_SCAN_REQ: + error = 0; + if (sc->sc_firmware_type == WI_LUCENT) + wi_cmd(sc, WI_CMD_INQUIRE, + WI_INFO_SCAN_RESULTS, 0, 0); + else + error = wi_write_record(sc, + (struct wi_ltv_gen *)&wreq); + break; case WI_RID_SYMBOL_DIVERSITY: case WI_RID_ROAMING_MODE: case WI_RID_CREATE_IBSS: case WI_RID_MICROWAVE_OVEN: /* - * Check for features that may not be supported. + * Check for features that may not be supported + * (must be just before default case). */ if ((wreq.wi_type == WI_RID_SYMBOL_DIVERSITY && !(sc->wi_flags & WI_FLAGS_HAS_DIVERSITY)) || @@ -1464,6 +1610,24 @@ wi_ioctl(ifp, command, data) wi_init(sc); } break; + case SIOCGPRISM2DEBUG: + error = copyin(ifr->ifr_data, &wreq, sizeof(wreq)); + if (error) + break; + if (!(ifp->if_flags & IFF_RUNNING) || + sc->sc_firmware_type == WI_LUCENT) { + error = EIO; + break; + } + error = wi_get_debug(sc, &wreq); + error = copyout(&wreq, ifr->ifr_data, sizeof(wreq)); + break; + case SIOCSPRISM2DEBUG: + error = copyin(ifr->ifr_data, &wreq, sizeof(wreq)); + if (error) + break; + error = wi_set_debug(sc, &wreq); + break; case SIOCG80211NWID: if (ifp->if_flags & IFF_UP) { /* Return the desired ID */ @@ -1648,7 +1812,7 @@ wi_init(sc) wi_setmulti(sc); /* Enable desired port */ - wi_cmd(sc, WI_CMD_ENABLE | sc->wi_portnum, 0); + wi_cmd(sc, WI_CMD_ENABLE | sc->wi_portnum, 0, 0, 0); if (wi_alloc_nicmem(sc, ETHER_MAX_LEN + sizeof(struct wi_frame) + 8, &id)) printf(WI_PRT_FMT ": tx buffer allocation failed\n", @@ -1951,7 +2115,7 @@ nextpkt: m_freem(m0); - if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id)) + if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id, 0, 0)) printf(WI_PRT_FMT ": wi_start: xmit failed\n", WI_PRT_ARG(sc)); ifp->if_flags |= IFF_OACTIVE; @@ -1996,7 +2160,7 @@ wi_mgmt_xmit(sc, data, len) wi_write_data(sc, id, WI_802_11_OFFSET_RAW, dptr, (len - sizeof(struct wi_80211_hdr)) + 2); - if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id)) { + if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id, 0, 0)) { printf(WI_PRT_FMT ": wi_mgmt_xmit: xmit failed\n", WI_PRT_ARG(sc)); return(EIO); @@ -2023,7 +2187,7 @@ wi_stop(sc) ifp = &sc->arpcom.ac_if; CSR_WRITE_2(sc, WI_INT_EN, 0); - wi_cmd(sc, WI_CMD_DISABLE|sc->wi_portnum, 0); + wi_cmd(sc, WI_CMD_DISABLE|sc->wi_portnum, 0, 0, 0); ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE); ifp->if_timer = 0; @@ -2460,3 +2624,146 @@ wi_set_ssid(ws, id, len) memcpy(ws->i_nwid, id, len); return (0); } + +STATIC int +wi_get_debug(sc, wreq) + struct wi_softc *sc; + struct wi_req *wreq; +{ + int error = 0; + + wreq->wi_len = 1; + + switch (wreq->wi_type) { + case WI_DEBUG_SLEEP: + wreq->wi_len++; + wreq->wi_val[0] = htole16(sc->wi_debug.wi_sleep); + break; + case WI_DEBUG_DELAYSUPP: + wreq->wi_len++; + wreq->wi_val[0] = htole16(sc->wi_debug.wi_delaysupp); + break; + case WI_DEBUG_TXSUPP: + wreq->wi_len++; + wreq->wi_val[0] = htole16(sc->wi_debug.wi_txsupp); + break; + case WI_DEBUG_MONITOR: + wreq->wi_len++; + wreq->wi_val[0] = htole16(sc->wi_debug.wi_monitor); + break; + case WI_DEBUG_LEDTEST: + wreq->wi_len += 3; + wreq->wi_val[0] = htole16(sc->wi_debug.wi_ledtest); + wreq->wi_val[1] = htole16(sc->wi_debug.wi_ledtest_param0); + wreq->wi_val[2] = htole16(sc->wi_debug.wi_ledtest_param1); + break; + case WI_DEBUG_CONTTX: + wreq->wi_len += 2; + wreq->wi_val[0] = htole16(sc->wi_debug.wi_conttx); + wreq->wi_val[1] = htole16(sc->wi_debug.wi_conttx_param0); + break; + case WI_DEBUG_CONTRX: + wreq->wi_len++; + wreq->wi_val[0] = htole16(sc->wi_debug.wi_contrx); + break; + case WI_DEBUG_SIGSTATE: + wreq->wi_len += 2; + wreq->wi_val[0] = htole16(sc->wi_debug.wi_sigstate); + wreq->wi_val[1] = htole16(sc->wi_debug.wi_sigstate_param0); + break; + case WI_DEBUG_CONFBITS: + wreq->wi_len += 2; + wreq->wi_val[0] = htole16(sc->wi_debug.wi_confbits); + wreq->wi_val[1] = htole16(sc->wi_debug.wi_confbits_param0); + break; + default: + error = EIO; + break; + } + + return (error); +} + +STATIC int +wi_set_debug(sc, wreq) + struct wi_softc *sc; + struct wi_req *wreq; +{ + int error = 0; + u_int16_t cmd, param0 = 0, param1 = 0; + + switch (wreq->wi_type) { + case WI_DEBUG_RESET: + case WI_DEBUG_INIT: + case WI_DEBUG_CALENABLE: + break; + case WI_DEBUG_SLEEP: + sc->wi_debug.wi_sleep = 1; + break; + case WI_DEBUG_WAKE: + sc->wi_debug.wi_sleep = 0; + break; + case WI_DEBUG_CHAN: + param0 = letoh16(wreq->wi_val[0]); + break; + case WI_DEBUG_DELAYSUPP: + sc->wi_debug.wi_delaysupp = 1; + break; + case WI_DEBUG_TXSUPP: + sc->wi_debug.wi_txsupp = 1; + break; + case WI_DEBUG_MONITOR: + sc->wi_debug.wi_monitor = 1; + break; + case WI_DEBUG_LEDTEST: + param0 = letoh16(wreq->wi_val[0]); + param1 = letoh16(wreq->wi_val[1]); + sc->wi_debug.wi_ledtest = 1; + sc->wi_debug.wi_ledtest_param0 = param0; + sc->wi_debug.wi_ledtest_param1 = param1; + break; + case WI_DEBUG_CONTTX: + param0 = letoh16(wreq->wi_val[0]); + sc->wi_debug.wi_conttx = 1; + sc->wi_debug.wi_conttx_param0 = param0; + break; + case WI_DEBUG_STOPTEST: + sc->wi_debug.wi_delaysupp = 0; + sc->wi_debug.wi_txsupp = 0; + sc->wi_debug.wi_monitor = 0; + sc->wi_debug.wi_ledtest = 0; + sc->wi_debug.wi_ledtest_param0 = 0; + sc->wi_debug.wi_ledtest_param1 = 0; + sc->wi_debug.wi_conttx = 0; + sc->wi_debug.wi_conttx_param0 = 0; + sc->wi_debug.wi_contrx = 0; + sc->wi_debug.wi_sigstate = 0; + sc->wi_debug.wi_sigstate_param0 = 0; + break; + case WI_DEBUG_CONTRX: + sc->wi_debug.wi_contrx = 1; + break; + case WI_DEBUG_SIGSTATE: + param0 = letoh16(wreq->wi_val[0]); + sc->wi_debug.wi_sigstate = 1; + sc->wi_debug.wi_sigstate_param0 = param0; + break; + case WI_DEBUG_CONFBITS: + param0 = letoh16(wreq->wi_val[0]); + param1 = letoh16(wreq->wi_val[1]); + sc->wi_debug.wi_confbits = param0; + sc->wi_debug.wi_confbits_param0 = param1; + break; + default: + error = EIO; + break; + } + + if (error) + return (error); + + cmd = WI_CMD_DEBUG | (wreq->wi_type << 8); + error = wi_cmd(sc, cmd, param0, param1, 0); + + return (error); +} diff --git a/sys/dev/ic/if_wi_ieee.h b/sys/dev/ic/if_wi_ieee.h index 7bd29b3c3e3..7ce194f472b 100644 --- a/sys/dev/ic/if_wi_ieee.h +++ b/sys/dev/ic/if_wi_ieee.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_wi_ieee.h,v 1.7 2002/04/20 03:56:37 millert Exp $ */ +/* $OpenBSD: if_wi_ieee.h,v 1.8 2002/06/02 16:11:41 millert Exp $ */ /* * Copyright (c) 1997, 1998, 1999 @@ -268,8 +268,6 @@ struct wi_counters { #define WI_RID_DEFLT_CRYPT_KEYS 0xFCB0 #define WI_RID_TX_CRYPT_KEY 0xFCB1 #define WI_RID_TICK_TIME 0xFCE0 /* Auxiliary Timer tick interval */ -#define WI_RID_SCAN_REQ 0xFCE1 -#define WI_RID_JOIN_REQ 0xFCE2 struct wi_key { u_int16_t wi_keylen; @@ -331,6 +329,376 @@ struct wi_ltv_keys { #define WI_RID_PCI_INFO 0xFD87 /* point coordination func cap */ /* + * Scan Information + */ +#define WI_RID_BCAST_SCAN_REQ 0xFCAB /* Broadcast Scan request (Symbol) */ +#define BSCAN_5SEC 0x01 +#define BSCAN_ONETIME 0x02 +#define BSCAN_PASSIVE 0x40 +#define BSCAN_BCAST 0x80 +#define WI_RID_SCAN_REQ 0xFCE1 /* Scan request (STA only) */ +#define WI_RID_JOIN_REQ 0xFCE2 /* Join request (STA only) */ +#define WI_RID_AUTH_STATION 0xFCE3 /* Authenticates Station (AP) */ +#define WI_RID_CHANNEL_REQ 0xFCE4 /* Channel Information Request (AP) */ +#define WI_RID_SCAN_RES 0xFD88 /* Scan Results Table */ + +/* + * bsd-airtools v0.2 - source-mods v0.2 [common.h] + * by h1kari - (c) Dachb0den Labs 2001 + */ + +/* + * Copyright (c) 2001 Dachb0den Labs. + * David Hulton <h1kari@dachb0den.com>. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by David Hulton. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY David Hulton AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL David Hulton OR THE VOICES IN HIS HEAD + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * standard hermes recieve frame used by wavelan/prism2 cards + */ +struct wi_rx_frame { + /* + * hermes prefix header. supplies information on the current status of + * the network and various other statistics gathered from the + * management/control frames as used internally. + */ + u_int16_t wi_status; + u_int16_t wi_ts0; + u_int16_t wi_ts1; + u_int8_t wi_silence; + u_int8_t wi_signal; + u_int8_t wi_rate; + u_int8_t wi_rx_flow; + u_int16_t wi_rsvd0; + u_int16_t wi_rsvd1; + /* + * standard 80211 frame header. all packets have to use this header as + * per the AN9900 from intersil, even management/control. for + * management packets, they just threw the header into the data field, + * but for control packets the headers are lost in translation and + * therefore not all control packet info can be displayed. + */ + u_int16_t wi_frame_ctl; + u_int16_t wi_id; + u_int8_t wi_addr1[6]; + u_int8_t wi_addr2[6]; + u_int8_t wi_addr3[6]; + u_int16_t wi_seq_ctl; + u_int8_t wi_addr4[6]; + u_int16_t wi_dat_len; + /* + * another wierdity with the drivers. they append a 802.3 header which + * is somewhat redundant, since all the same data is provided in the + * 802.11 header. + */ + u_int8_t wi_dst_addr[6]; + u_int8_t wi_src_addr[6]; + u_int16_t wi_len; +}; +#define WI_DATA_HDRLEN WI_802_11_OFFSET +#define WI_MGMT_HDRLEN WI_802_11_OFFSET_RAW +#define WI_CTL_HDRLEN WI_802_11_OFFSET_RAW + + +/* + * all data packets have a snap (sub-network access protocol) header that + * isn't entirely definied, but added for ethernet compatibility. + */ +struct wi_snap_frame { + u_int16_t wi_dat[3]; + u_int16_t wi_type; +}; + + +/* + * management frame headers + * note: all management frames consist of a static header and variable length + * fields. + */ + +/* + * variable length field structure + */ +struct wi_mgmt_var_hdr { + u_int8_t wi_code; + u_int8_t wi_len; + u_int8_t wi_data[256]; +}; + +/* + * management beacon frame prefix + */ +struct wi_mgmt_beacon_hdr { + u_int32_t wi_ts0; + u_int32_t wi_ts1; + u_int16_t wi_interval; + u_int16_t wi_capinfo; +}; + +/* + * ibss announcement traffic indication message (atim) frame + * note: no parameters + */ + +/* + * management disassociation frame + */ +struct wi_mgmt_disas_hdr { + u_int16_t wi_reason; +}; + +/* + * management association request frame prefix + */ +struct wi_mgmt_asreq_hdr { + u_int16_t wi_capinfo; + u_int16_t wi_interval; +}; + +/* + * management association response frame prefix + */ +struct wi_mgmt_asresp_hdr { + u_int16_t wi_capinfo; + u_int16_t wi_status; + u_int16_t wi_aid; +}; + +/* + * management reassociation request frame prefix + */ +struct wi_mgmt_reasreq_hdr { + u_int16_t wi_capinfo; + u_int16_t wi_interval; + u_int8_t wi_currap[6]; +}; + +/* + * management reassociation response frame prefix + */ +struct wi_mgmt_reasresp_hdr { + u_int16_t wi_capinfo; + u_int16_t wi_status; + u_int16_t wi_aid; +}; + +/* + * management probe request frame prefix + * note: no static parameters, only variable length + */ + +/* + * management probe response frame prefix + */ +struct wi_mgmt_proberesp_hdr { + u_int32_t wi_ts0; + u_int32_t wi_ts1; + u_int16_t wi_interval; + u_int16_t wi_capinfo; +}; + +/* + * management authentication frame prefix + */ +struct wi_mgmt_auth_hdr { + u_int16_t wi_algo; + u_int16_t wi_seq; + u_int16_t wi_status; +}; + +/* + * management deauthentication frame + */ +struct wi_mgmt_deauth_hdr { + u_int16_t wi_reason; +}; + + +/* + * rid configuration register definitions + */ +#define WI_RID_PROCFRAME 0x3137 /* Return full frame information */ +#define WI_RID_PRISM2 0x3138 /* tell if we're a prism2 card or not */ + + +/* + * 802.11 definitions + */ +#define WI_STAT_BADCRC 0x0001 +#define WI_STAT_UNDECRYPTABLE 0x0002 +#define WI_STAT_ERRSTAT 0x0003 +#define WI_STAT_MAC_PORT 0x0700 +#define WI_STAT_1042 0x2000 +#define WI_STAT_TUNNEL 0x4000 +#define WI_STAT_WMP_MSG 0x6000 +#define WI_RXSTAT_MSG_TYPE 0xE000 + +#define WI_FCTL_OPT_MASK 0xFF00 +#define WI_AID_SET 0xC000 +#define WI_AID_MASK 0x3FFF +#define WI_SCTL_FRAGNUM_MASK 0x000F +#define WI_SCTL_SEQNUM_MASK 0xFFF0 + +#define WI_STAT_UNSPEC_FAIL 1 +#define WI_STAT_CAPINFO_FAIL 10 +#define WI_STAT_REAS_DENY 11 +#define WI_STAT_ASSOC_DENY 12 +#define WI_STAT_ALGO_FAIL 13 +#define WI_STAT_SEQ_FAIL 14 +#define WI_STAT_CHAL_FAIL 15 +#define WI_STAT_TOUT_FAIL 16 +#define WI_STAT_OVERL_DENY 17 +#define WI_STAT_RATE_DENY 18 + +#define WI_FTYPE_MGMT 0x0000 +#define WI_FTYPE_CTL 0x0004 +#define WI_FTYPE_DATA 0x0008 + +#define WI_FCTL_VERS 0x0002 +#define WI_FCTL_FTYPE 0x000C +#define WI_FCTL_STYPE 0x00F0 +#define WI_FCTL_TODS 0x0100 +#define WI_FCTL_FROMDS 0x0200 +#define WI_FCTL_MOREFRAGS 0x0400 +#define WI_FCTL_RETRY 0x0800 +#define WI_FCTL_PM 0x1000 +#define WI_FCTL_MOREDATA 0x2000 +#define WI_FCTL_WEP 0x4000 +#define WI_FCTL_ORDER 0x8000 + +#define WI_FCS_LEN 0x4 /* checksum length */ + + +/* + * management definitions + */ +#define WI_STYPE_MGMT_ASREQ 0x0000 +#define WI_STYPE_MGMT_ASRESP 0x0010 +#define WI_STYPE_MGMT_REASREQ 0x0020 +#define WI_STYPE_MGMT_REASRESP 0x0030 +#define WI_STYPE_MGMT_PROBEREQ 0x0040 +#define WI_STYPE_MGMT_PROBERESP 0x0050 +#define WI_STYPE_MGMT_BEACON 0x0080 +#define WI_STYPE_MGMT_ATIM 0x0090 +#define WI_STYPE_MGMT_DISAS 0x00A0 +#define WI_STYPE_MGMT_AUTH 0x00B0 +#define WI_STYPE_MGMT_DEAUTH 0x00C0 + +#define WI_CAPINFO_ESS 0x01 +#define WI_CAPINFO_IBSS 0x02 +#define WI_CAPINFO_CFPOLL 0x04 +#define WI_CAPINFO_CFPOLLREQ 0x08 +#define WI_CAPINFO_PRIV 0x10 + +#define WI_REASON_UNSPEC 1 +#define WI_REASON_AUTH_INVALID 2 +#define WI_REASON_DEAUTH_LEAVE 3 +#define WI_REASON_DISAS_INACT 4 +#define WI_REASON_DISAS_OVERL 5 +#define WI_REASON_CLASS2 6 +#define WI_REASON_CLASS3 7 +#define WI_REASON_DISAS_LEAVE 8 +#define WI_REASON_NOAUTH 9 + +#define WI_VAR_SSID 0 +#define WI_VAR_SRATES 1 +#define WI_VAR_FH 2 +#define WI_VAR_DS 3 +#define WI_VAR_CF 4 +#define WI_VAR_TIM 5 +#define WI_VAR_IBSS 6 +#define WI_VAR_CHAL 16 + +#define WI_VAR_SRATES_MASK 0x7F + + +/* + * control definitions + */ +#define WI_STYPE_CTL_PSPOLL 0x00A0 +#define WI_STYPE_CTL_RTS 0x00B0 +#define WI_STYPE_CTL_CTS 0x00C0 +#define WI_STYPE_CTL_ACK 0x00D0 +#define WI_STYPE_CTL_CFEND 0x00E0 +#define WI_STYPE_CTL_CFENDCFACK 0x00F0 + + +/* + * ap scanning structures + */ +struct wi_scan_res { + u_int16_t wi_chan; + u_int16_t wi_noise; + u_int16_t wi_signal; + u_int8_t wi_bssid[6]; + u_int16_t wi_interval; + u_int16_t wi_capinfo; + u_int16_t wi_ssid_len; + u_int8_t wi_ssid[32]; + u_int8_t wi_srates[10]; + u_int8_t wi_rate; + u_int8_t wi_rsvd; +}; +#define WI_WAVELAN_RES_SIZE 50 + +struct wi_scan_p2_hdr { + u_int16_t wi_rsvd; + u_int16_t wi_reason; +}; +#define WI_PRISM2_RES_SIZE 62 + + +/* + * prism2 debug mode definitions + */ +#define SIOCSPRISM2DEBUG _IOW('i', 137, struct ifreq) +#define SIOCGPRISM2DEBUG _IOWR('i', 138, struct ifreq) + +#define WI_CMD_DEBUG 0x0038 /* prism2 debug */ + +#define WI_DEBUG_RESET 0x00 +#define WI_DEBUG_INIT 0x01 +#define WI_DEBUG_SLEEP 0x02 +#define WI_DEBUG_WAKE 0x03 +#define WI_DEBUG_CHAN 0x08 +#define WI_DEBUG_DELAYSUPP 0x09 +#define WI_DEBUG_TXSUPP 0x0A +#define WI_DEBUG_MONITOR 0x0B +#define WI_DEBUG_LEDTEST 0x0C +#define WI_DEBUG_CONTTX 0x0E +#define WI_DEBUG_STOPTEST 0x0F +#define WI_DEBUG_CONTRX 0x10 +#define WI_DEBUG_SIGSTATE 0x11 +#define WI_DEBUG_CALENABLE 0x13 +#define WI_DEBUG_CONFBITS 0x15 + +/* * Modem information */ #define WI_RID_PHY_TYPE 0xFDC0 /* phys layer type indication */ diff --git a/sys/dev/ic/if_wivar.h b/sys/dev/ic/if_wivar.h index 382f55319ab..7103b7ecfd2 100644 --- a/sys/dev/ic/if_wivar.h +++ b/sys/dev/ic/if_wivar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_wivar.h,v 1.11 2002/04/26 19:20:27 millert Exp $ */ +/* $OpenBSD: if_wivar.h,v 1.12 2002/06/02 16:11:41 millert Exp $ */ /* * Copyright (c) 1997, 1998, 1999 @@ -51,6 +51,7 @@ struct wi_softc { int wi_tx_mgmt_id; int wi_flags; int wi_if_flags; + u_int16_t wi_procframe; u_int16_t wi_ptype; u_int16_t wi_portnum; u_int16_t wi_max_data_len; @@ -72,6 +73,8 @@ struct wi_softc { struct ieee80211_nwid wi_ibss_name; u_int8_t wi_txbuf[1596]; + u_int8_t wi_scanbuf[1596]; + u_int8_t wi_scanbuf_len; int wi_use_wep; int wi_tx_key; struct wi_ltv_keys wi_keys; @@ -85,6 +88,23 @@ struct wi_softc { u_int32_t wi_icv; int wi_icv_flag; int wi_ibss_port; + + struct { + u_int16_t wi_sleep; + u_int16_t wi_delaysupp; + u_int16_t wi_txsupp; + u_int16_t wi_monitor; + u_int16_t wi_ledtest; + u_int16_t wi_ledtest_param0; + u_int16_t wi_ledtest_param1; + u_int16_t wi_conttx; + u_int16_t wi_conttx_param0; + u_int16_t wi_contrx; + u_int16_t wi_sigstate; + u_int16_t wi_sigstate_param0; + u_int16_t wi_confbits; + u_int16_t wi_confbits_param0; + } wi_debug; }; /* Values for wi_flags. */ |