From 8cf3aa5fce361fd50412addd025f3bb2658be8b4 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Fri, 29 Mar 2002 00:26:23 +0000 Subject: [PATCH] Integrate the air-tools 0.2 from dachb0den labs. o This moves the common.h file into if_wavelan_ieee.h Submitted by: h1kari@dachb0den.com --- sys/dev/wi/if_wavelan_ieee.h | 358 ++++++++++++++++++++++++++ sys/dev/wi/if_wi.c | 476 ++++++++++++++++++++++++++++------- sys/dev/wi/if_wireg.h | 24 ++ 3 files changed, 773 insertions(+), 85 deletions(-) diff --git a/sys/dev/wi/if_wavelan_ieee.h b/sys/dev/wi/if_wavelan_ieee.h index 334d724df6de..9695bfd26642 100644 --- a/sys/dev/wi/if_wavelan_ieee.h +++ b/sys/dev/wi/if_wavelan_ieee.h @@ -319,5 +319,363 @@ struct wi_ltv_keys { #define WI_RID_MAC_PROC_DELAY 0xFDC5 /* MAC processing delay time */ #define WI_RID_DATA_RATES 0xFDC6 /* supported data rates */ +/* + * bsd-airtools v0.2 - source-mods v0.2 [common.h] + * by h1kari - (c) Dachb0den Labs 2001 + */ + +/* + * Copyright (c) 2001 Dachb0den Labs. + * David Hulton . 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_SCAN_REQ 0xFCE1 /* scan request information */ +#define WI_RID_SCAN_RES 0xFD88 /* scan result information */ + +#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 #endif diff --git a/sys/dev/wi/if_wi.c b/sys/dev/wi/if_wi.c index 21ab969684e7..b18cd2633f4f 100644 --- a/sys/dev/wi/if_wi.c +++ b/sys/dev/wi/if_wi.c @@ -172,6 +172,9 @@ static void wi_get_id(struct wi_softc *, device_t); static int wi_media_change(struct ifnet *); static void wi_media_status(struct ifnet *, struct ifmediareq *); +static int wi_get_debug(struct wi_softc *, struct wi_req *); +static int wi_set_debug(struct wi_softc *, struct wi_req *); + static device_method_t wi_pccard_methods[] = { /* Device interface */ DEVMETHOD(device_probe, pccard_compat_probe), @@ -248,6 +251,7 @@ static const struct pccard_product wi_pccard_products[] = { PCMCIA_CARD(EMTAC, WLAN, 0), PCMCIA_CARD(ERICSSON, WIRELESSLAN, 0), PCMCIA_CARD(GEMTEK, WLAN, 0), + PCMCIA_CARD(HWN, AIRWAY80211, 0), PCMCIA_CARD(INTEL, PRO_WLAN_2011, 0), PCMCIA_CARD(INTERSIL, PRISM2, 0), PCMCIA_CARD(IODATA2, WNB11PCM, 0), @@ -712,7 +716,6 @@ wi_rxeof(sc) { struct ifnet *ifp; struct ether_header *eh; - struct wi_frame rx_frame; struct mbuf *m; int id; @@ -720,102 +723,207 @@ 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 we have the procframe flag set, disregard all this and just + * read the data from the device. + */ + if (sc->wi_procframe || sc->wi_debug.wi_monitor) { + struct wi_frame *rx_frame; + int datlen, hdrlen; - if (rx_frame.wi_status & 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; - } - - eh = mtod(m, struct ether_header *); - m->m_pkthdr.rcvif = ifp; - - if (rx_frame.wi_status == WI_STAT_1042 || - rx_frame.wi_status == WI_STAT_TUNNEL || - rx_frame.wi_status == WI_STAT_WMP_MSG) { - if((rx_frame.wi_dat_len + WI_SNAPHDR_LEN) > MCLBYTES) { - device_printf(sc->dev, "oversized packet received " - "(wi_dat_len=%d, wi_status=0x%x)\n", - rx_frame.wi_dat_len, rx_frame.wi_status); + /* first allocate mbuf for packet storage */ + 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; } - m->m_pkthdr.len = m->m_len = - rx_frame.wi_dat_len + WI_SNAPHDR_LEN; + + m->m_pkthdr.rcvif = ifp; + + /* now read wi_frame first so we know how much data to read */ + if (wi_read_data(sc, id, 0, mtod(m, caddr_t), + sizeof(struct wi_frame))) { + m_freem(m); + ifp->if_ierrors++; + return; + } + + rx_frame = mtod(m, struct wi_frame *); + + switch ((rx_frame->wi_status & WI_STAT_MAC_PORT) >> 8) { + case 7: + switch (rx_frame->wi_frame_ctl & WI_FCTL_FTYPE) { + case WI_FTYPE_DATA: + hdrlen = WI_DATA_HDRLEN; + datlen = rx_frame->wi_dat_len + WI_FCS_LEN; + break; + case WI_FTYPE_MGMT: + hdrlen = WI_MGMT_HDRLEN; + datlen = rx_frame->wi_dat_len + WI_FCS_LEN; + break; + case WI_FTYPE_CTL: + /* + * prism2 cards don't pass control packets + * down properly or consistently, so we'll only + * pass down the header. + */ + hdrlen = WI_CTL_HDRLEN; + datlen = 0; + break; + default: + device_printf(sc->dev, "received packet of " + "unknown type on port 7\n"); + m_freem(m); + ifp->if_ierrors++; + return; + } + break; + case 0: + hdrlen = WI_DATA_HDRLEN; + datlen = rx_frame->wi_dat_len + WI_FCS_LEN; + break; + default: + device_printf(sc->dev, "received packet on invalid " + "port (wi_status=0x%x)\n", rx_frame->wi_status); + m_freem(m); + ifp->if_ierrors++; + return; + } + + if ((hdrlen + datlen + 2) > MCLBYTES) { + device_printf(sc->dev, "oversized packet received " + "(wi_dat_len=%d, wi_status=0x%x)\n", + datlen, rx_frame->wi_status); + m_freem(m); + ifp->if_ierrors++; + return; + } + + 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; + + ifp->if_ipackets++; + + /* Handle BPF listeners. */ + if (ifp->if_bpf) + bpf_mtap(ifp, m); + + m_freem(m); + } else { + 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; + } + + if (rx_frame.wi_status & 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; + } + + eh = mtod(m, struct ether_header *); + m->m_pkthdr.rcvif = ifp; + + if (rx_frame.wi_status == WI_STAT_1042 || + rx_frame.wi_status == WI_STAT_TUNNEL || + rx_frame.wi_status == WI_STAT_WMP_MSG) { + if((rx_frame.wi_dat_len + WI_SNAPHDR_LEN) > MCLBYTES) { + device_printf(sc->dev, + "oversized packet received " + "(wi_dat_len=%d, wi_status=0x%x)\n", + rx_frame.wi_dat_len, rx_frame.wi_status); + m_freem(m); + ifp->if_ierrors++; + return; + } + m->m_pkthdr.len = m->m_len = + rx_frame.wi_dat_len + WI_SNAPHDR_LEN; #if 0 - bcopy((char *)&rx_frame.wi_addr1, - (char *)&eh->ether_dhost, ETHER_ADDR_LEN); - if (sc->wi_ptype == WI_PORTTYPE_ADHOC) { - bcopy((char *)&rx_frame.wi_addr2, - (char *)&eh->ether_shost, ETHER_ADDR_LEN); - } else { - bcopy((char *)&rx_frame.wi_addr3, - (char *)&eh->ether_shost, ETHER_ADDR_LEN); - } + bcopy((char *)&rx_frame.wi_addr1, + (char *)&eh->ether_dhost, ETHER_ADDR_LEN); + if (sc->wi_ptype == WI_PORTTYPE_ADHOC) { + bcopy((char *)&rx_frame.wi_addr2, + (char *)&eh->ether_shost, ETHER_ADDR_LEN); + } else { + bcopy((char *)&rx_frame.wi_addr3, + (char *)&eh->ether_shost, ETHER_ADDR_LEN); + } #else - 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_dst_addr, + (char *)&eh->ether_dhost, ETHER_ADDR_LEN); + bcopy((char *)&rx_frame.wi_src_addr, + (char *)&eh->ether_shost, ETHER_ADDR_LEN); #endif - bcopy((char *)&rx_frame.wi_type, - (char *)&eh->ether_type, ETHER_TYPE_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)) { - m_freem(m); - ifp->if_ierrors++; - return; + if (wi_read_data(sc, id, WI_802_11_OFFSET, + mtod(m, caddr_t) + sizeof(struct ether_header), + m->m_len + 2)) { + m_freem(m); + ifp->if_ierrors++; + return; + } + } else { + if((rx_frame.wi_dat_len + + sizeof(struct ether_header)) > MCLBYTES) { + device_printf(sc->dev, + "oversized packet received " + "(wi_dat_len=%d, wi_status=0x%x)\n", + rx_frame.wi_dat_len, rx_frame.wi_status); + m_freem(m); + ifp->if_ierrors++; + return; + } + m->m_pkthdr.len = m->m_len = + 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; + } } - } else { - if((rx_frame.wi_dat_len + - sizeof(struct ether_header)) > MCLBYTES) { - device_printf(sc->dev, "oversized packet received " - "(wi_dat_len=%d, wi_status=0x%x)\n", - rx_frame.wi_dat_len, rx_frame.wi_status); - m_freem(m); - ifp->if_ierrors++; - return; - } - m->m_pkthdr.len = m->m_len = - 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++; - ifp->if_ipackets++; - - /* Receive packet. */ - m_adj(m, sizeof(struct ether_header)); + /* Receive packet. */ + m_adj(m, sizeof(struct ether_header)); #ifdef WICACHE - wi_cache_store(sc, eh, m, rx_frame.wi_q_info); + wi_cache_store(sc, eh, m, rx_frame.wi_q_info); #endif - ether_input(ifp, eh, m); + ether_input(ifp, eh, m); + } } static void @@ -876,7 +984,20 @@ wi_update_stats(sc) wi_read_data(sc, id, 0, (char *)&gen, 4); - if (gen.wi_type != WI_INFO_COUNTERS) + /* + * if we just got our scan results, copy it over into the scan buffer + * so we can return it to anyone that asks for it. (add a little + * compatibility with the prism2 scanning mechanism) + */ + if (gen.wi_type == WI_INFO_SCAN_RESULTS) + { + sc->wi_scanbuf_len = gen.wi_len; + wi_read_data(sc, id, 4, (char *)sc->wi_scanbuf, + sc->wi_scanbuf_len * 2); + + return; + } + else if (gen.wi_type != WI_INFO_COUNTERS) return; len = (gen.wi_len - 1 < sizeof(sc->wi_stats) / 4) ? @@ -1617,7 +1738,17 @@ wi_ioctl(ifp, command, data) sc->wi_sigitems) / 2) + 1; } #endif - else { + 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->wi_prism2; + } else if (wreq.wi_type == WI_RID_SCAN_RES && !sc->wi_prism2) { + memcpy((char *)wreq.wi_val, (char *)sc->wi_scanbuf, + sc->wi_scanbuf_len * 2); + wreq.wi_len = sc->wi_scanbuf_len; + } else { if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq)) { error = EINVAL; break; @@ -1637,12 +1768,43 @@ wi_ioctl(ifp, command, data) } 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 handled by a prism2 card's rid interface. + */ + } else if (wreq.wi_type == WI_RID_SCAN_REQ && !sc->wi_prism2) { + wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_SCAN_RESULTS, 0, 0); } else { error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq); if (!error) wi_setdef(sc, &wreq); } break; + case SIOCGPRISM2DEBUG: + error = copyin(ifr->ifr_data, &wreq, sizeof(wreq)); + if (error) + break; + if (!(ifp->if_flags & IFF_RUNNING) || !sc->wi_prism2) { + error = EIO; + break; + } + error = wi_get_debug(sc, &wreq); + if (error == 0) + error = copyout(&wreq, ifr->ifr_data, sizeof(wreq)); + break; + case SIOCSPRISM2DEBUG: + if ((error = suser(p))) + goto out; + error = copyin(ifr->ifr_data, &wreq, sizeof(wreq)); + if (error) + break; + error = wi_set_debug(sc, &wreq); + break; case SIOCG80211: switch(ireq->i_type) { case IEEE80211_IOC_SSID: @@ -2051,9 +2213,10 @@ wi_start(ifp) /* * If there's a BPF listner, bounce a copy of - * this frame to him. + * this frame to him. Also, don't send this to the bpf sniffer + * if we're in procframe or monitor sniffing mode. */ - if (ifp->if_bpf) + if (!(sc->wi_procframe || sc->wi_debug.wi_monitor) && ifp->if_bpf) bpf_mtap(ifp, m0); m_freem(m0); @@ -2594,3 +2757,146 @@ wi_media_status(ifp, imr) imr->ifm_status |= IFM_ACTIVE; } } + +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] = sc->wi_debug.wi_sleep; + break; + case WI_DEBUG_DELAYSUPP: + wreq->wi_len++; + wreq->wi_val[0] = sc->wi_debug.wi_delaysupp; + break; + case WI_DEBUG_TXSUPP: + wreq->wi_len++; + wreq->wi_val[0] = sc->wi_debug.wi_txsupp; + break; + case WI_DEBUG_MONITOR: + wreq->wi_len++; + wreq->wi_val[0] = sc->wi_debug.wi_monitor; + break; + case WI_DEBUG_LEDTEST: + wreq->wi_len += 3; + wreq->wi_val[0] = sc->wi_debug.wi_ledtest; + wreq->wi_val[1] = sc->wi_debug.wi_ledtest_param0; + wreq->wi_val[2] = sc->wi_debug.wi_ledtest_param1; + break; + case WI_DEBUG_CONTTX: + wreq->wi_len += 2; + wreq->wi_val[0] = sc->wi_debug.wi_conttx; + wreq->wi_val[1] = sc->wi_debug.wi_conttx_param0; + break; + case WI_DEBUG_CONTRX: + wreq->wi_len++; + wreq->wi_val[0] = sc->wi_debug.wi_contrx; + break; + case WI_DEBUG_SIGSTATE: + wreq->wi_len += 2; + wreq->wi_val[0] = sc->wi_debug.wi_sigstate; + wreq->wi_val[1] = sc->wi_debug.wi_sigstate_param0; + break; + case WI_DEBUG_CONFBITS: + wreq->wi_len += 2; + wreq->wi_val[0] = sc->wi_debug.wi_confbits; + wreq->wi_val[1] = 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 = 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 = wreq->wi_val[0]; + param1 = 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 = 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 = wreq->wi_val[0]; + sc->wi_debug.wi_sigstate = 1; + sc->wi_debug.wi_sigstate_param0 = param0; + break; + case WI_DEBUG_CONFBITS: + param0 = wreq->wi_val[0]; + param1 = 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/wi/if_wireg.h b/sys/dev/wi/if_wireg.h index c7c575024e9e..6f808f5f2be2 100644 --- a/sys/dev/wi/if_wireg.h +++ b/sys/dev/wi/if_wireg.h @@ -32,6 +32,10 @@ * $FreeBSD$ */ +#include +#include +#include + struct wi_counters { u_int32_t wi_tx_unicast_frames; u_int32_t wi_tx_multicast_frames; @@ -111,6 +115,7 @@ struct wi_softc { int wi_tx_mgmt_id; int wi_gone; 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; @@ -129,6 +134,8 @@ struct wi_softc { char wi_net_name[32]; char wi_ibss_name[32]; u_int8_t wi_txbuf[1596]; + u_int8_t wi_scanbuf[1596]; + int wi_scanbuf_len; struct wi_counters wi_stats; int wi_has_wep; int wi_use_wep; @@ -145,6 +152,23 @@ struct wi_softc { int wi_firmware_ver; int wi_nic_type; int wi_bus_type; /* Bus attachment type */ + 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; + }; #define WI_LOCK(_sc)