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
This commit is contained in:
Warner Losh 2002-03-29 00:26:23 +00:00
parent fd503e698c
commit 8cf3aa5fce
3 changed files with 773 additions and 85 deletions

View File

@ -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 <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_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

View File

@ -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);
}

View File

@ -32,6 +32,10 @@
* $FreeBSD$
*/
#include <netinet/if_ether.h>
#include <dev/wi/if_wavelan_ieee.h>
#include <sys/bus.h>
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)