# $Id: openbsd-airtools_current.diff,v 1.2 2006/03/25 16:22:31 jcs Exp $ # XXX: merged by someone else # # merge bsd airtools into openbsd-current as of 2002-04-02; breaks hostap # # be sure to install bat/common.h from the bsd airtools distribution # # by joshua stein # Index: sbin/wicontrol/wicontrol.c =================================================================== RCS file: /cvs/src/sbin/wicontrol/wicontrol.c,v retrieving revision 1.29 diff -u -r1.29 wicontrol.c --- sbin/wicontrol/wicontrol.c 1 Apr 2002 20:43:08 -0000 1.29 +++ sbin/wicontrol/wicontrol.c 2 Apr 2002 03:40:46 -0000 @@ -57,6 +57,8 @@ #include #endif +#include + #include #include #include @@ -82,6 +84,7 @@ void wi_printwords(struct wi_req *); void wi_printbool(struct wi_req *); void wi_printhex(struct wi_req *); +void wi_printaplist(char *); void wi_dumpinfo(char *); void wi_setkeys(char *, int, char *); void wi_printkeys(struct wi_req *); @@ -92,6 +95,8 @@ void printb(char *, unsigned short, char *); char *portid(char *); +static int listaps; + void wi_getval(iface, wreq) char *iface; @@ -464,6 +469,115 @@ printf(" ]"); } +void +wi_printaplist(iface) + char *iface; +{ + int prism2, len, i = 0, j; + struct wi_req wreq; + struct wi_scan_p2_hdr *wi_p2_h; + struct wi_scan_res *res; + + printf("Available APs:\n"); + + /* first determine if this is a prism2 card or not */ + wreq.wi_len = WI_MAX_DATALEN; + wreq.wi_type = WI_RID_PRISM2; + + wi_getval(iface, &wreq); + prism2 = wreq.wi_val[0]; + + /* send out a scan request */ + wreq.wi_len = prism2 ? 3 : 1; + wreq.wi_type = WI_RID_SCAN_REQ; + + if(prism2) + { + wreq.wi_val[0] = 0x3FFF; + wreq.wi_val[1] = 0x000F; + } + + wi_setval(iface, &wreq); + + /* + * sleep for 100 milliseconds so there's enough time for the card to + * respond... prism2's take a little longer. + */ + usleep(prism2 ? 500000 : 100000); + + /* get the scan results */ + wreq.wi_len = WI_MAX_DATALEN; + wreq.wi_type = WI_RID_SCAN_RES; + + wi_getval(iface, &wreq); + + if(prism2) + { + wi_p2_h = (struct wi_scan_p2_hdr *)wreq.wi_val; + + /* if the reason is 0, this info is invalid */ + if(wi_p2_h->wi_reason == 0) + return; + + i = 4; + } + + len = prism2 ? WI_PRISM2_RES_SIZE : WI_WAVELAN_RES_SIZE; + + for(; i < (wreq.wi_len * 2) - len; i += len) + { + res = (struct wi_scan_res *)((char *)wreq.wi_val + i); + + res->wi_ssid[res->wi_ssid_len] = '\0'; + res->wi_chan = letoh16(res->wi_chan); + res->wi_noise = letoh16(res->wi_noise); + res->wi_signal = letoh16(res->wi_signal); + res->wi_interval = letoh16(res->wi_interval); + res->wi_capinfo = letoh16(res->wi_capinfo); + + printf(" %-8s [ %02x:%02x:%02x:%02x:%02x:%02x ] [ %-2d ] " + "[ %d %d %d ] %-3d ", res->wi_ssid, + res->wi_bssid[0], res->wi_bssid[1], res->wi_bssid[2], + res->wi_bssid[3], res->wi_bssid[4], res->wi_bssid[5], + res->wi_chan, res->wi_signal - res->wi_noise, + res->wi_signal, res->wi_noise, res->wi_interval); + + if(res->wi_capinfo) + { + printf("[ "); + if(res->wi_capinfo & WI_CAPINFO_ESS) + printf("ess "); + if(res->wi_capinfo & WI_CAPINFO_IBSS) + printf("ibss "); + if(res->wi_capinfo & WI_CAPINFO_PRIV) + printf("priv "); + printf("] "); + } + + if(prism2) + { + printf("\n [ "); + for(j = 0; res->wi_srates[j] != 0; j++) + { + res->wi_srates[j] = res->wi_srates[j] & + WI_VAR_SRATES_MASK; + printf("%d.%d ", res->wi_srates[j] / 2, + (res->wi_srates[j] % 2) * 5); + } + printf("] "); + + printf("* %2.1f *", res->wi_rate == 0xa ? 1 : + (res->wi_rate == 0x14 ? 2 : + (res->wi_rate == 0x37 ? 5.5 : + (res->wi_rate == 0x6e ? 11 : 0)))); + } + + putchar('\n'); + } + + return; +} + #define WI_STRING 0x01 #define WI_BOOL 0x02 #define WI_WORDS 0x03 @@ -489,6 +603,8 @@ { WI_RID_CURRENT_CHAN, WI_WORDS, "Current channel:\t\t\t" }, { WI_RID_COMMS_QUALITY, WI_WORDS, "Comms quality/signal/noise:\t\t" }, { WI_RID_PROMISC, WI_BOOL, "Promiscuous mode:\t\t\t" }, + { WI_RID_PROCFRAME, WI_BOOL, "Process 802.11b Frame:\t\t\t" }, + { WI_RID_PRISM2, WI_WORDS, "Intersil-Prism2 based card:\t\t" }, { WI_RID_PORTTYPE, WI_WORDS, "Port type (1=BSS, 3=ad-hoc, 6=Host AP):\t"}, { WI_RID_MAC_NODE, WI_HEXBYTES, "MAC address:\t\t\t\t"}, { WI_RID_TX_RATE, WI_WORDS, "TX rate (selection):\t\t\t"}, @@ -603,6 +719,9 @@ printf("\n"); } } + + if (listaps) + wi_printaplist(iface); } void @@ -714,7 +833,7 @@ fprintf(stderr, "usage: %s interface [-ol]" " [-t tx rate] [-n network name] [-s station name]\n" - " [-e 0|1] [-k key [-v 1|2|3|4]] [-T 1|2|3|4]\n" + " [-e 0|1] [-k key [-v 1|2|3|4]] [-T 1|2|3|4] [-F 0|1] [-L]\n" " [-c 0|1] [-q SSID] [-p port type] [-a access point density]\n" " [-m MAC address] [-d max data length] [-r RTS threshold]\n" " [-f frequency] [-M 0|1] [-P 0|1] [-S max sleep duration]\n" @@ -749,6 +868,7 @@ { 'R', wi_setword, WI_RID_ROAMING_MODE, NULL }, { 'S', wi_setword, WI_RID_MAX_SLEEP, NULL }, { 'T', wi_setword, WI_RID_TX_CRYPT_KEY, NULL }, + { 'F', wi_setword, WI_RID_PROCFRAME, NULL }, /* These options will never be command line options which is why they are not 'quoted' */ @@ -776,7 +896,7 @@ } while((ch = getopt(argc, argv, - "a:c:d:e:f:hi:k:lm:n:op:q:r:s:t:v:A:M:S:P:R:T:")) != -1) { + "a:c:d:e:f:hi:k:lm:n:op:q:r:s:t:v:A:F:LM:S:P:R:T:")) != -1) { for (p = 0; ch && wi_opt[p].key; p++) if (ch == wi_opt[p].key) { if (ch == 'p' && !isdigit(*optarg)) @@ -796,6 +916,9 @@ break; case 'o': dumpstats++; + break; + case 'L': + listaps++; break; case 'l': dumpstations++; Index: sys/dev/ic/if_wi.c =================================================================== RCS file: /cvs/src/sys/dev/ic/if_wi.c,v retrieving revision 1.39 diff -u -r1.39 if_wi.c --- sys/dev/ic/if_wi.c 2 Apr 2002 00:31:59 -0000 1.39 +++ sys/dev/ic/if_wi.c 2 Apr 2002 03:40:48 -0000 @@ -101,6 +101,8 @@ #include #include +#include "/usr/include/bat/common.h" + #define BPF_MTAP(if,mbuf) bpf_mtap((if)->if_bpf, (mbuf)) #define BPFATTACH(if_bpf,if,dlt,sz) #define STATIC @@ -141,7 +143,7 @@ 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, @@ -164,6 +166,9 @@ 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 *, int); void wi_init(void *); @@ -400,7 +405,6 @@ { struct ifnet *ifp; struct ether_header *eh; - struct wi_frame rx_frame; struct mbuf *m; int id; @@ -408,138 +412,255 @@ 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 (rx_frame.wi_status & htole16(WI_STAT_ERRSTAT)) { - 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; + + /* 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; + } - 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.rcvif = ifp; - eh = mtod(m, struct ether_header *); - 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; + } - if (rx_frame.wi_status == WI_STAT_MGMT && - sc->wi_ptype == WI_PORTTYPE_AP) { + rx_frame = mtod(m, struct wi_frame *); - if ((WI_802_11_OFFSET_RAW + rx_frame.wi_dat_len + 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, - rx_frame.wi_dat_len, rx_frame.wi_status); + switch ((rx_frame->wi_status & htole16(WI_STAT_MAC_PORT)) + >> 8) { + case 7: + switch (rx_frame->wi_frame_ctl & + htole16(WI_FCTL_FTYPE)) { + case WI_FTYPE_DATA: + hdrlen = WI_DATA_HDRLEN; + datlen = letoh16(rx_frame->wi_dat_len) + + WI_FCS_LEN; + break; + case WI_FTYPE_MGMT: + hdrlen = WI_MGMT_HDRLEN; + datlen = letoh16(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: + printf(WI_PRT_FMT ": received packet of " + "unknown type on port 7\n", + WI_PRT_ARG(sc)); + m_freem(m); + ifp->if_ierrors++; + return; + } + case 0: + hdrlen = WI_DATA_HDRLEN; + datlen = letoh16(rx_frame->wi_dat_len) + WI_FCS_LEN; + break; + default: + printf(WI_PRT_FMT ": received packet on invalid port " + "(wi_status=0x%x)\n", WI_PRT_ARG(sc)); 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, - rx_frame.wi_dat_len + 2)) { + if ((hdrlen + datlen + 2) > MCLBYTES) { + printf(WI_PRT_FMT ": oversize packet recieved " + "(wi_dat_len=%d, wi_status=0x%d)\n", + WI_PRT_ARG(sc), datlen, + 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 + rx_frame.wi_dat_len; - - /* 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 (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 = - 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); + m->m_pkthdr.len = m->m_len = hdrlen + datlen; + } else { + struct wi_frame rx_frame; - if (wi_read_data(sc, id, WI_802_11_OFFSET, mtod(m, caddr_t) + - sizeof(struct ether_header), m->m_len + 2)) { + /* First read in the frame header */ + if (wi_read_data(sc, id, 0, (caddr_t)&rx_frame, + sizeof(rx_frame))) { 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); + if (rx_frame.wi_status & htole16(WI_STAT_ERRSTAT)) { 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)) { + 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_MGMT && + sc->wi_ptype == WI_PORTTYPE_AP) { + + if ((WI_802_11_OFFSET_RAW + rx_frame.wi_dat_len + 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, + rx_frame.wi_dat_len, 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, + rx_frame.wi_dat_len + 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 + rx_frame.wi_dat_len; + + /* 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)); + 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) { + /* + * If we're in procframe or monitor mode, + * don't pass this on to the kernel. + */ + if (sc->wi_procframe || sc->wi_debug.wi_monitor) { + m_freem(m); + } else { + /* XXX: this needs to be moved + 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; - } + // 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 - /* Handle BPF listeners. */ - if (ifp->if_bpf) - BPF_MTAP(ifp, m); + /* Handle BPF listeners. */ + if (ifp->if_bpf) + BPF_MTAP(ifp, m); #endif - /* Receive packet. */ - ether_input_mbuf(ifp, m); + /* Receive packet. */ + ether_input_mbuf(ifp, m); + } return; } @@ -582,7 +703,7 @@ 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), @@ -608,12 +729,24 @@ 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 to 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 == 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; @@ -634,10 +767,12 @@ } 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; @@ -648,9 +783,9 @@ 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)) { @@ -685,7 +820,7 @@ { DPRINTF(WID_RESET, ("wi_reset: sc %p\n", sc)); - 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)); CSR_WRITE_2(sc, WI_INT_EN, 0); CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF); @@ -725,7 +860,7 @@ } /* 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. */ @@ -889,7 +1024,7 @@ 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); @@ -1007,7 +1142,7 @@ { 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); @@ -1294,6 +1429,16 @@ else bcopy((char *)&sc->wi_keys, (char *)&wreq, sizeof(struct wi_ltv_keys)); + } else if (wreq.wi_type == WI_RID_PROCFRAME) { + wreq.wi_len = 2; + wreq.wi_val[0] = htole16(sc->wi_procframe); + } else if (wreq.wi_type == WI_RID_PRISM2) { + wreq.wi_len = 2; + wreq.wi_val[0] = htole16(sc->sc_prism2); + } else if (wreq.wi_type == WI_RID_SCAN_RES && !sc->sc_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; @@ -1312,6 +1457,17 @@ } 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_inqure 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 the prism2 card's rid interface. + */ + } else if (wreq.wi_type == WI_RID_SCAN_REQ && !sc->sc_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) @@ -1320,6 +1476,26 @@ wi_init(ifp); } break; + case SIOCGPRISM2DEBUG: + error = copyin(ifr->ifr_data, &wreq, sizeof(wreq)); + if (error) + break; + if (!(ifp->if_flags & IFF_RUNNING) || !sc->sc_prism2) { + error = EIO; + break; + } + error = wi_get_debug(sc, &wreq); + error = copyout(&wreq, ifr->ifr_data, sizeof(wreq)); + break; + case SIOCSPRISM2DEBUG: + error = suser(p->p_ucred, &p->p_acflag); + if (error) + break; + 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 */ @@ -1495,7 +1671,7 @@ 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", @@ -1794,7 +1970,7 @@ 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 ": xmit failed\n", WI_PRT_ARG(sc)); ifp->if_flags |= IFF_OACTIVE; @@ -1838,7 +2014,7 @@ 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 ": xmit failed\n", WI_PRT_ARG(sc)); return(EIO); } @@ -1862,7 +2038,7 @@ 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); timeout_del(&sc->sc_timo); @@ -2256,4 +2432,147 @@ ws->i_len = 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); } Index: sys/dev/ic/if_wivar.h =================================================================== RCS file: /cvs/src/sys/dev/ic/if_wivar.h,v retrieving revision 1.6 diff -u -r1.6 if_wivar.h --- sys/dev/ic/if_wivar.h 28 Mar 2002 18:21:06 -0000 1.6 +++ sys/dev/ic/if_wivar.h 2 Apr 2002 03:40:48 -0000 @@ -48,6 +48,7 @@ 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; @@ -68,6 +69,8 @@ struct ieee80211_nwid wi_ibss_name; u_int8_t wi_txbuf[1596]; + u_int8_t wi_scanbuf[1596]; + int wi_scanbuf_len; int wi_has_wep; int wi_use_wep; int wi_authmode; @@ -83,8 +86,25 @@ struct wihap_info wi_hostap_info; u_int32_t wi_icv; int wi_icv_flag; -}; + 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_PRT_FMT "%s" #define WI_PRT_ARG(sc) (sc)->sc_dev.dv_xname