David Wolfskill writes: | Noticed a bunch of: | > Expensive timeout(9) function: 0xc0170e40(0xc274c000) 0.001114387 | | from running (yesterday's) -CURRENT, so I thought I'd check against | (yesterday's kernel.debug (before I replaced it with today's). | | I do have some patches to the "an" driver installed (from Doug Ambrisko) | that don't seem to have been committed (yet?). | | If he (or anyone else) would like me to test things, I'm willing and | able.
I haven't seen that but -current isn't being very stable on my laptop so I have to keep going back to -stable for my job. I'm getting some patches ready to commit. Need some work on the man page. It closes a PR that was partially incomplete. You might want to get rid of that old stuff and try this. The only timeout calls an_stats_update. I don't really see why it would take a long time. Note this patch doesn't touch that function so it shouldn't fix that problem. Doug A. Index: sys/dev/an/if_aironet_ieee.h =================================================================== RCS file: /cvs/src/sys/dev/an/if_aironet_ieee.h,v retrieving revision 1.10 diff -c -r1.10 if_aironet_ieee.h *** sys/dev/an/if_aironet_ieee.h 23 Sep 2002 18:54:29 -0000 1.10 --- sys/dev/an/if_aironet_ieee.h 25 Oct 2002 03:33:33 -0000 *************** *** 132,137 **** --- 132,156 ---- }; #endif + /* + * The card provides an 8-bit signal strength value (RSSI), which can + * be converted to a dBm power value (or a percent) using a table in + * the card's firmware (when available). The tables are slightly + * different in individual cards, even of the same model. If the + * table is not available, the mapping can be approximated by dBm = + * RSSI - 100. This approximation can be seen by plotting a few + * tables, and also matches some info on the Intersil web site (I + * think they make the RF front end for the cards. However, the linux + * driver uses the approximation dBm = RSSI/2 - 95. I think that is + * just wrong. + */ + + struct an_rssi_entry { + u_int8_t an_rss_pct; + u_int8_t an_rss_dbm; + }; + + struct an_ltv_key { u_int16_t an_len; u_int16_t an_type; *************** *** 335,340 **** --- 354,360 ---- #define AN_RXMODE_80211_MONITOR_ANYBSS 0x0004 #define AN_RXMODE_LAN_MONITOR_CURBSS 0x0005 #define AN_RXMODE_NO_8023_HEADER 0x0100 + #define AN_RXMODE_NORMALIZED_RSSI 0x0200 #define AN_RATE_1MBPS 0x0002 #define AN_RATE_2MBPS 0x0004 *************** *** 503,508 **** --- 523,538 ---- /* ??? */ }; + /* + * RSSI map. If available in the card's firmware, this can be used to + * convert the 8-bit RSSI values from the card into dBm. + */ + struct an_ltv_rssi_map { + u_int16_t an_len; + u_int16_t an_type; + struct an_rssi_entry an_entries[256]; + }; + /* * Status (read only). Note: the manual claims this RID is 108 bytes * long (0x6A is the last datum, which is 2 bytes long) however when *************** *** 520,526 **** u_int8_t an_macaddr[6]; /* 0x02 */ u_int16_t an_opmode; /* 0x08 */ u_int16_t an_errcode; /* 0x0A */ ! u_int16_t an_cur_signal_strength; /* 0x0C */ u_int16_t an_ssidlen; /* 0x0E */ u_int8_t an_ssid[32]; /* 0x10 */ u_int8_t an_ap_name[16]; /* 0x30 */ --- 550,556 ---- u_int8_t an_macaddr[6]; /* 0x02 */ u_int16_t an_opmode; /* 0x08 */ u_int16_t an_errcode; /* 0x0A */ ! u_int16_t an_signal_quality; /* 0x0C */ u_int16_t an_ssidlen; /* 0x0E */ u_int8_t an_ssid[32]; /* 0x10 */ u_int8_t an_ap_name[16]; /* 0x30 */ *************** *** 541,552 **** u_int16_t an_cur_signal_quality; /* 0x6C */ u_int16_t an_current_tx_rate; /* 0x6E */ u_int16_t an_ap_device; /* 0x70 */ ! u_int16_t an_normalized_rssi; /* 0x72 */ u_int16_t an_short_pre_in_use; /* 0x74 */ u_int8_t an_ap_ip_addr[4]; /* 0x76 */ ! u_int16_t an_max_noise_prev_sec; /* 0x7A */ ! u_int16_t an_avg_noise_prev_min; /* 0x7C */ ! u_int16_t an_max_noise_prev_min; /* 0x7E */ u_int16_t an_spare[5]; }; --- 571,585 ---- u_int16_t an_cur_signal_quality; /* 0x6C */ u_int16_t an_current_tx_rate; /* 0x6E */ u_int16_t an_ap_device; /* 0x70 */ ! u_int16_t an_normalized_strength; /* 0x72 */ u_int16_t an_short_pre_in_use; /* 0x74 */ u_int8_t an_ap_ip_addr[4]; /* 0x76 */ ! u_int8_t an_noise_prev_sec_pc; /* 0x7A */ ! u_int8_t an_noise_prev_sec_db; /* 0x7B */ ! u_int8_t an_avg_noise_prev_min_pc; /* 0x7C */ ! u_int8_t an_avg_noise_prev_min_db; /* 0x7D */ ! u_int8_t an_max_noise_prev_min_pc; /* 0x7E */ ! u_int8_t an_max_noise_prev_min_db; /* 0x7F */ u_int16_t an_spare[5]; }; *************** *** 643,648 **** --- 676,682 ---- #define AN_RID_CAPABILITIES 0xFF00 /* PC 4500/4800 capabilities */ #define AN_RID_AP_INFO 0xFF01 /* Access point info */ #define AN_RID_RADIO_INFO 0xFF02 /* Radio info */ + #define AN_RID_RSSI_MAP 0xFF04 /* RSSI <-> dBm table */ #define AN_RID_STATUS 0xFF50 /* Current status info */ #define AN_RID_BEACONS_HST 0xFF51 #define AN_RID_BUSY_HST 0xFF52 Index: sys/dev/an/if_an.c =================================================================== RCS file: /cvs/src/sys/dev/an/if_an.c,v retrieving revision 1.37 diff -c -r1.37 if_an.c *** sys/dev/an/if_an.c 28 Sep 2002 17:14:23 -0000 1.37 --- sys/dev/an/if_an.c 25 Oct 2002 03:33:33 -0000 *************** *** 107,112 **** --- 107,113 ---- #include <sys/lock.h> #include <sys/mutex.h> #include <machine/resource.h> + #include <sys/malloc.h> #include <net/if.h> #include <net/if_arp.h> *************** *** 157,163 **** static void an_setdef (struct an_softc *, struct an_req *); #ifdef ANCACHE static void an_cache_store (struct an_softc *, struct ether_header *, ! struct mbuf *, unsigned short); #endif /* function definitions for use with the Cisco's Linux configuration --- 158,164 ---- static void an_setdef (struct an_softc *, struct an_req *); #ifdef ANCACHE static void an_cache_store (struct an_softc *, struct ether_header *, ! struct mbuf *, u_int8_t, u_int8_t); #endif /* function definitions for use with the Cisco's Linux configuration *************** *** 184,193 **** --- 185,201 ---- static void an_media_status (struct ifnet *, struct ifmediareq *); static int an_dump = 0; + static int an_cache_mode = 0; + + #define DBM 0 + #define PERCENT 1 + #define RAW 2 static char an_conf[256]; + static char an_conf_cache[256]; /* sysctl vars */ + SYSCTL_NODE(_machdep, OID_AUTO, an, CTLFLAG_RD, 0, "dump RID"); static int *************** *** 197,213 **** char *s = an_conf; last = an_dump; - bzero(an_conf, sizeof(an_conf)); switch (an_dump) { case 0: ! strcat(an_conf, "off"); break; case 1: ! strcat(an_conf, "type"); break; case 2: ! strcat(an_conf, "dump"); break; default: snprintf(an_conf, 5, "%x", an_dump); --- 205,220 ---- char *s = an_conf; last = an_dump; switch (an_dump) { case 0: ! strcpy(an_conf, "off"); break; case 1: ! strcpy(an_conf, "type"); break; case 2: ! strcpy(an_conf, "dump"); break; default: snprintf(an_conf, 5, "%x", an_dump); *************** *** 216,222 **** error = sysctl_handle_string(oidp, an_conf, sizeof(an_conf), req); ! if (strncmp(an_conf,"off", 4) == 0) { an_dump = 0; } if (strncmp(an_conf,"dump", 4) == 0) { --- 223,229 ---- error = sysctl_handle_string(oidp, an_conf, sizeof(an_conf), req); ! if (strncmp(an_conf,"off", 3) == 0) { an_dump = 0; } if (strncmp(an_conf,"dump", 4) == 0) { *************** *** 247,252 **** --- 254,297 ---- SYSCTL_PROC(_machdep, OID_AUTO, an_dump, CTLTYPE_STRING | CTLFLAG_RW, 0, sizeof(an_conf), sysctl_an_dump, "A", ""); + static int + sysctl_an_cache_mode(SYSCTL_HANDLER_ARGS) + { + int error, last; + + last = an_cache_mode; + + switch (an_cache_mode) { + case 1: + strcpy(an_conf_cache, "per"); + break; + case 2: + strcpy(an_conf_cache, "raw"); + break; + default: + strcpy(an_conf_cache, "dbm"); + break; + } + + error = sysctl_handle_string(oidp, an_conf_cache, + sizeof(an_conf_cache), req); + + if (strncmp(an_conf_cache,"dbm", 3) == 0) { + an_cache_mode = 0; + } + if (strncmp(an_conf_cache,"per", 3) == 0) { + an_cache_mode = 1; + } + if (strncmp(an_conf_cache,"raw", 3) == 0) { + an_cache_mode = 2; + } + + return error; + } + + SYSCTL_PROC(_machdep, OID_AUTO, an_cache_mode, CTLTYPE_STRING | CTLFLAG_RW, + 0, sizeof(an_conf_cache), sysctl_an_cache_mode, "A", ""); + /* * We probe for an Aironet 4500/4800 card by attempting to * read the default SSID list. On reset, the first entry in *************** *** 385,390 **** --- 430,436 ---- sc->an_associated = 0; sc->an_monitor = 0; sc->an_was_monitor = 0; + sc->an_flash_buffer = NULL; /* Reset the NIC. */ an_reset(sc); *************** *** 437,442 **** --- 483,505 ---- return(EIO); } + #ifdef ANCACHE + /* Read the RSSI <-> dBm map */ + sc->an_have_rssimap = 0; + if (sc->an_caps.an_softcaps & 8) { + sc->an_rssimap.an_type = AN_RID_RSSI_MAP; + sc->an_rssimap.an_len = sizeof(struct an_ltv_rssi_map); + if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_rssimap)) { + printf("an%d: unable to get RSSI <-> dBM map\n", sc->an_unit); + } else { + printf("an%d: got RSSI <-> dBM map\n", sc->an_unit); + sc->an_have_rssimap = 1; + } + } else { + printf("an%d: no RSSI <-> dBM map\n", sc->an_unit); + } + #endif + bcopy((char *)&sc->an_caps.an_oemaddr, (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN); *************** *** 656,662 **** /* Receive packet. */ m_adj(m, sizeof(struct ether_header)); #ifdef ANCACHE ! an_cache_store(sc, eh, m, rx_frame.an_rx_signal_strength); #endif ether_input(ifp, eh, m); } --- 719,726 ---- /* Receive packet. */ m_adj(m, sizeof(struct ether_header)); #ifdef ANCACHE ! an_cache_store(sc, eh, m, rx_frame.an_rx_signal_strength, ! rx_frame.an_rsvd0); #endif ether_input(ifp, eh, m); } *************** *** 1898,1903 **** --- 1962,1970 ---- } } + if (sc->an_have_rssimap) + sc->an_config.an_rxmode |= AN_RXMODE_NORMALIZED_RSSI; + /* Set the ssid list */ sc->an_ssidlist.an_type = AN_RID_SSIDLIST; sc->an_ssidlist.an_len = sizeof(struct an_ltv_ssidlist); *************** *** 2074,2079 **** --- 2141,2151 ---- ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE); + if (sc->an_flash_buffer) { + free(sc->an_flash_buffer, M_DEVBUF); + sc->an_flash_buffer = NULL; + } + AN_UNLOCK(sc); return; *************** *** 2177,2187 **** * strength in MAC (src) indexed cache. */ static void ! an_cache_store (sc, eh, m, rx_quality) struct an_softc *sc; struct ether_header *eh; struct mbuf *m; ! unsigned short rx_quality; { struct ip *ip = 0; int i; --- 2249,2260 ---- * strength in MAC (src) indexed cache. */ static void ! an_cache_store (sc, eh, m, rx_rssi, rx_quality) struct an_softc *sc; struct ether_header *eh; struct mbuf *m; ! u_int8_t rx_rssi; ! u_int8_t rx_quality; { struct ip *ip = 0; int i; *************** *** 2213,2219 **** #ifdef SIGDEBUG printf("an: q value %x (MSB=0x%x, LSB=0x%x) \n", ! rx_quality & 0xffff, rx_quality >> 8, rx_quality & 0xff); #endif /* find the ip header. we want to store the ip_src --- 2286,2292 ---- #ifdef SIGDEBUG printf("an: q value %x (MSB=0x%x, LSB=0x%x) \n", ! rx_rssi & 0xffff, rx_rssi >> 8, rx_rssi & 0xff); #endif /* find the ip header. we want to store the ip_src *************** *** 2290,2296 **** } bcopy( eh->ether_shost, sc->an_sigcache[cache_slot].macsrc, 6); ! sc->an_sigcache[cache_slot].signal = rx_quality; return; } --- 2363,2403 ---- } bcopy( eh->ether_shost, sc->an_sigcache[cache_slot].macsrc, 6); ! ! switch (an_cache_mode) { ! case DBM: ! if (sc->an_have_rssimap) { ! sc->an_sigcache[cache_slot].signal = ! - sc->an_rssimap.an_entries[rx_rssi].an_rss_dbm; ! sc->an_sigcache[cache_slot].quality = ! - sc->an_rssimap.an_entries[rx_quality].an_rss_dbm; ! } else { ! sc->an_sigcache[cache_slot].signal = rx_rssi - 100; ! sc->an_sigcache[cache_slot].quality = rx_quality - 100; ! } ! break; ! case PERCENT: ! if (sc->an_have_rssimap) { ! sc->an_sigcache[cache_slot].signal = ! sc->an_rssimap.an_entries[rx_rssi].an_rss_pct; ! sc->an_sigcache[cache_slot].quality = ! sc->an_rssimap.an_entries[rx_quality].an_rss_pct; ! } else { ! if (rx_rssi > 100) ! rx_rssi = 100; ! if (rx_quality > 100) ! rx_quality = 100; ! sc->an_sigcache[cache_slot].signal = rx_rssi; ! sc->an_sigcache[cache_slot].quality = rx_quality; ! } ! break; ! case RAW: ! sc->an_sigcache[cache_slot].signal = rx_rssi; ! sc->an_sigcache[cache_slot].quality = rx_quality; ! break; ! } ! ! sc->an_sigcache[cache_slot].noise = 0; return; } *************** *** 2554,2560 **** * Linux driver */ ! #define FLASH_DELAY(x) tsleep(ifp, PZERO, "flash", ((x) / hz) + 1); static int unstickbusy(ifp) --- 2661,2669 ---- * Linux driver */ ! #define FLASH_DELAY(x) tsleep(ifp, PZERO, "flash", ((x) / hz) + 1); ! #define FLASH_COMMAND 0x7e7e ! #define FLASH_SIZE 32 * 1024 static int unstickbusy(ifp) *************** *** 2632,2638 **** /* * STEP 2) Put the card in legendary flash mode */ - #define FLASH_COMMAND 0x7e7e static int setflashmode(ifp) --- 2741,2746 ---- *************** *** 2762,2770 **** * the card */ - static char flashbuffer[1024 * 38]; /* RAW Buffer for flash will be - * dynamic next */ - static int flashputbuf(ifp) struct ifnet *ifp; --- 2870,2875 ---- *************** *** 2775,2786 **** /* Write stuff */ ! bufp = (unsigned short *)flashbuffer; CSR_WRITE_2(sc, AN_AUX_PAGE, 0x100); CSR_WRITE_2(sc, AN_AUX_OFFSET, 0); ! for (nwords = 0; nwords != 16384; nwords++) { CSR_WRITE_2(sc, AN_AUX_DATA, bufp[nwords] & 0xffff); } --- 2880,2891 ---- /* Write stuff */ ! bufp = sc->an_flash_buffer; CSR_WRITE_2(sc, AN_AUX_PAGE, 0x100); CSR_WRITE_2(sc, AN_AUX_OFFSET, 0); ! for (nwords = 0; nwords != FLASH_SIZE / 2; nwords++) { CSR_WRITE_2(sc, AN_AUX_DATA, bufp[nwords] & 0xffff); } *************** *** 2828,2834 **** return cmdreset(ifp); break; case AIROFLSHSTFL: ! return setflashmode(ifp); break; case AIROFLSHGCHR: /* Get char from aux */ copyin(l_ioctl->data, &sc->areq, l_ioctl->len); --- 2933,2947 ---- return cmdreset(ifp); break; case AIROFLSHSTFL: ! if (sc->an_flash_buffer) { ! free(sc->an_flash_buffer, M_DEVBUF); ! sc->an_flash_buffer = NULL; ! } ! sc->an_flash_buffer = malloc(FLASH_SIZE, M_DEVBUF, M_WAITOK); ! if (sc->an_flash_buffer) ! return setflashmode(ifp); ! else ! return ENOBUFS; break; case AIROFLSHGCHR: /* Get char from aux */ copyin(l_ioctl->data, &sc->areq, l_ioctl->len); *************** *** 2847,2858 **** return 0; break; case AIROFLPUTBUF: /* Send 32k to card */ ! if (l_ioctl->len > sizeof(flashbuffer)) { printf("an%d: Buffer to big, %x %x\n", sc->an_unit, ! l_ioctl->len, sizeof(flashbuffer)); return -EINVAL; } ! copyin(l_ioctl->data, &flashbuffer, l_ioctl->len); if ((status = flashputbuf(ifp)) != 0) return -EIO; --- 2960,2971 ---- return 0; break; case AIROFLPUTBUF: /* Send 32k to card */ ! if (l_ioctl->len > FLASH_SIZE) { printf("an%d: Buffer to big, %x %x\n", sc->an_unit, ! l_ioctl->len, FLASH_SIZE); return -EINVAL; } ! copyin(l_ioctl->data, sc->an_flash_buffer, l_ioctl->len); if ((status = flashputbuf(ifp)) != 0) return -EIO; Index: sys/dev/an/if_an_pci.c =================================================================== RCS file: /cvs/src/sys/dev/an/if_an_pci.c,v retrieving revision 1.13 diff -c -r1.13 if_an_pci.c *** sys/dev/an/if_an_pci.c 20 Mar 2002 02:02:34 -0000 1.13 --- sys/dev/an/if_an_pci.c 25 Oct 2002 03:33:33 -0000 *************** *** 101,106 **** --- 101,107 ---- #define AIRONET_DEVICEID_4500 0x4500 #define AIRONET_DEVICEID_4800 0x4800 #define AIRONET_DEVICEID_4xxx 0x0001 + #define AIRONET_DEVICEID_MPI350 0xA504 #define AN_PCI_PLX_LOIO 0x14 /* PLX chip iobase */ #define AN_PCI_LOIO 0x18 /* Aironet iobase */ *************** *** 132,137 **** --- 133,144 ---- t++; } + if (pci_get_vendor(dev) == AIRONET_VENDORID && + pci_get_device(dev) == AIRONET_DEVICEID_MPI350) { + device_set_desc(dev, "Cisco Aironet MPI350"); + return(0); + } + return(ENXIO); } *************** *** 148,168 **** flags = device_get_flags(dev); bzero(sc, sizeof(struct an_softc)); ! /* ! * Map control/status registers. ! */ ! command = pci_read_config(dev, PCIR_COMMAND, 4); ! command |= PCIM_CMD_PORTEN; ! pci_write_config(dev, PCIR_COMMAND, command, 4); ! command = pci_read_config(dev, PCIR_COMMAND, 4); ! ! if (!(command & PCIM_CMD_PORTEN)) { ! printf("an%d: failed to enable I/O ports!\n", unit); ! error = ENXIO; ! goto fail; } - - sc->port_rid = AN_PCI_LOIO; error = an_alloc_port(dev, sc->port_rid, 1); if (error) { --- 155,178 ---- flags = device_get_flags(dev); bzero(sc, sizeof(struct an_softc)); ! if (pci_get_device(dev) == AIRONET_DEVICEID_MPI350) { ! sc->port_rid = PCIR_MAPS; ! } else { ! /* ! * Map control/status registers. ! */ ! command = pci_read_config(dev, PCIR_COMMAND, 4); ! command |= PCIM_CMD_PORTEN; ! pci_write_config(dev, PCIR_COMMAND, command, 4); ! command = pci_read_config(dev, PCIR_COMMAND, 4); ! ! if (!(command & PCIM_CMD_PORTEN)) { ! printf("an%d: failed to enable I/O ports!\n", unit); ! error = ENXIO; ! goto fail; ! } ! sc->port_rid = AN_PCI_LOIO; } error = an_alloc_port(dev, sc->port_rid, 1); if (error) { Index: sys/dev/an/if_anreg.h =================================================================== RCS file: /cvs/src/sys/dev/an/if_anreg.h,v retrieving revision 1.13 diff -c -r1.13 if_anreg.h *** sys/dev/an/if_anreg.h 23 Sep 2002 18:54:29 -0000 1.13 --- sys/dev/an/if_anreg.h 25 Oct 2002 03:33:33 -0000 *************** *** 354,359 **** --- 354,361 ---- int an_sigitems; struct an_sigcache an_sigcache[MAXANCACHE]; int an_nextitem; + int an_have_rssimap; + struct an_ltv_rssi_map an_rssimap; #endif struct callout_handle an_stat_ch; struct mtx an_mtx; *************** *** 363,368 **** --- 365,371 ---- int an_was_monitor; u_char buf_802_11[MCLBYTES]; struct an_req areq; + unsigned short* an_flash_buffer; }; #define AN_LOCK(_sc) mtx_lock(&(_sc)->an_mtx) Index: usr.sbin/ancontrol/ancontrol.8 =================================================================== RCS file: /cvs/src/usr.sbin/ancontrol/ancontrol.8,v retrieving revision 1.23 diff -c -r1.23 ancontrol.8 *** usr.sbin/ancontrol/ancontrol.8 14 Jul 2002 14:42:17 -0000 1.23 --- usr.sbin/ancontrol/ancontrol.8 25 Oct 2002 03:33:33 -0000 *************** *** 50,55 **** --- 50,61 ---- .Nm .Fl i Ar iface Fl C .Nm + .Fl i Ar iface Fl Q + .Nm + .Fl i Ar iface Fl Z + .Nm + .Fl i Ar iface Fl R + .Nm .Fl i Ar iface Fl t Cm 0 Ns - Ns Cm 4 .Nm .Fl i Ar iface Fl s Cm 0 Ns - Ns Cm 3 *************** *** 190,195 **** --- 196,216 ---- This shows the current operation mode, receive mode, MAC address, power save settings, various timing settings, channel selection, diversity, transmit power and transmit speed. + .It Fl i Ar iface Fl Q + Display the cached signal strength information maintained by the + .Xr an 4 + driver. + The driver retains information about signal strength and + noise level for packets received from different hosts. + The signal strength and noise level values are displayed in units of dBms by + default. The sysctl machdep.an_cache_mode can be set to raw, dbm or per. + XXX needs work. + .It Fl i Ar iface Fl Z + Clear the signal strength cache maintained internally by the + .Xr an 4 + driver. + .It Fl i Ar iface Fl R + Display RSSI map that converts from the RSSI index to percent and dBm. .It Fl i Ar iface Fl t Cm 0 Ns - Ns Cm 4 Select transmit speed. The available settings are as follows: Index: usr.sbin/ancontrol/ancontrol.c =================================================================== RCS file: /cvs/src/usr.sbin/ancontrol/ancontrol.c,v retrieving revision 1.18 diff -c -r1.18 ancontrol.c *** usr.sbin/ancontrol/ancontrol.c 11 Jul 2002 18:20:49 -0000 1.18 --- usr.sbin/ancontrol/ancontrol.c 25 Oct 2002 03:33:33 -0000 *************** *** 58,65 **** #include <errno.h> #include <err.h> #include <md4.h> ! static void an_getval(const char *, struct an_req *); static void an_setval(const char *, struct an_req *); static void an_printwords(u_int16_t *, int); static void an_printspeeds(u_int8_t*, int); --- 58,66 ---- #include <errno.h> #include <err.h> #include <md4.h> + #include <ctype.h> ! static int an_getval(const char *, struct an_req *); static void an_setval(const char *, struct an_req *); static void an_printwords(u_int16_t *, int); static void an_printspeeds(u_int8_t*, int); *************** *** 86,91 **** --- 87,93 ---- static void an_setkeys(const char *, char *, int); static void an_enable_tx_key(const char *, char *); static void an_enable_leap_mode(const char *, char *); + static void an_dumprssimap(const char *); static void usage(char *); int main(int, char **); *************** *** 131,142 **** #define ACT_SET_MONITOR_MODE 37 #define ACT_SET_LEAP_MODE 38 ! static void an_getval(iface, areq) const char *iface; struct an_req *areq; { struct ifreq ifr; ! int s; bzero((char *)&ifr, sizeof(ifr)); --- 133,146 ---- #define ACT_SET_MONITOR_MODE 37 #define ACT_SET_LEAP_MODE 38 ! #define ACT_DUMPRSSIMAP 39 ! ! static int an_getval(iface, areq) const char *iface; struct an_req *areq; { struct ifreq ifr; ! int s, okay = 1; bzero((char *)&ifr, sizeof(ifr)); *************** *** 148,159 **** if (s == -1) err(1, "socket"); ! if (ioctl(s, SIOCGAIRONET, &ifr) == -1) err(1, "SIOCGAIRONET"); close(s); ! return; } static void an_setval(iface, areq) --- 152,165 ---- if (s == -1) err(1, "socket"); ! if (ioctl(s, SIOCGAIRONET, &ifr) == -1) { ! okay = 0; err(1, "SIOCGAIRONET"); + } close(s); ! return okay; } static void an_setval(iface, areq) *************** *** 260,265 **** --- 266,286 ---- { struct an_ltv_status *sts; struct an_req areq; + struct an_ltv_rssi_map an_rssimap; + int rssimap_valid = 0; + + /* + * Try to get RSSI to percent and dBM table + */ + + an_rssimap.an_len = sizeof(an_rssimap); + an_rssimap.an_type = AN_RID_RSSI_MAP; + rssimap_valid = an_getval(iface, (struct an_req*)&an_rssimap); + + if (rssimap_valid) + printf("RSSI table:\t\t[ present ]\n"); + else + printf("RSSI table:\t\t[ not available ]\n"); areq.an_len = sizeof(areq); areq.an_type = AN_RID_STATUS; *************** *** 288,297 **** printf("]\n"); printf("Error code:\t\t"); an_printhex((char *)&sts->an_errcode, 1); ! printf("\nSignal quality:\t\t"); ! an_printhex((char *)&sts->an_cur_signal_quality, 1); ! printf("\nSignal strength:\t[ %d%% ]",sts->an_normalized_rssi); ! printf("\nMax Noise:\t\t[ %d%% ]",sts->an_avg_noise_prev_min); /* * XXX: This uses the old definition of the rate field (units of * 500kbps). Technically the new definition is that this field --- 309,330 ---- printf("]\n"); printf("Error code:\t\t"); an_printhex((char *)&sts->an_errcode, 1); ! if (rssimap_valid) ! printf("\nSignal strength:\t[ %d%% ]", ! an_rssimap.an_entries[ ! sts->an_normalized_strength].an_rss_pct); ! else ! printf("\nSignal strength:\t[ %d%% ]", ! sts->an_normalized_strength); ! printf("\nAverage Noise:\t\t[ %d%% ]",sts->an_avg_noise_prev_min_pc); ! if (rssimap_valid) ! printf("\nSignal quality:\t\t[ %d%% ]", ! an_rssimap.an_entries[ ! sts->an_cur_signal_quality].an_rss_pct); ! else ! printf("\nSignal quality:\t\t[ %d ]", ! sts->an_cur_signal_quality); ! printf("\nMax Noise:\t\t[ %d%% ]",sts->an_max_noise_prev_min_pc); /* * XXX: This uses the old definition of the rate field (units of * 500kbps). Technically the new definition is that this field *************** *** 378,384 **** printf("\nSupported speeds:\t"); an_printspeeds(caps->an_rates, 8); printf("\nRX Diversity:\t\t[ "); ! if (caps->an_rx_diversity == AN_DIVERSITY_ANTENNA_1_ONLY) printf("antenna 1 only"); else if (caps->an_rx_diversity == AN_DIVERSITY_ANTENNA_2_ONLY) printf("antenna 2 only"); --- 411,419 ---- printf("\nSupported speeds:\t"); an_printspeeds(caps->an_rates, 8); printf("\nRX Diversity:\t\t[ "); ! if (caps->an_rx_diversity == AN_DIVERSITY_FACTORY_DEFAULT) ! printf("factory default"); ! else if (caps->an_rx_diversity == AN_DIVERSITY_ANTENNA_1_ONLY) printf("antenna 1 only"); else if (caps->an_rx_diversity == AN_DIVERSITY_ANTENNA_2_ONLY) printf("antenna 2 only"); *************** *** 386,396 **** printf("antenna 1 and 2"); printf(" ]"); printf("\nTX Diversity:\t\t[ "); ! if (caps->an_rx_diversity == AN_DIVERSITY_ANTENNA_1_ONLY) printf("antenna 1 only"); ! else if (caps->an_rx_diversity == AN_DIVERSITY_ANTENNA_2_ONLY) printf("antenna 2 only"); ! else if (caps->an_rx_diversity == AN_DIVERSITY_ANTENNA_1_AND_2) printf("antenna 1 and 2"); printf(" ]"); printf("\nSupported power levels:\t"); --- 421,433 ---- printf("antenna 1 and 2"); printf(" ]"); printf("\nTX Diversity:\t\t[ "); ! if (caps->an_tx_diversity == AN_DIVERSITY_FACTORY_DEFAULT) ! printf("factory default"); ! else if (caps->an_tx_diversity == AN_DIVERSITY_ANTENNA_1_ONLY) printf("antenna 1 only"); ! else if (caps->an_tx_diversity == AN_DIVERSITY_ANTENNA_2_ONLY) printf("antenna 2 only"); ! else if (caps->an_tx_diversity == AN_DIVERSITY_ANTENNA_1_AND_2) printf("antenna 1 and 2"); printf(" ]"); printf("\nSupported power levels:\t"); *************** *** 786,792 **** printf(" ]"); printf("\nRX Diversity:\t\t\t\t[ "); diversity = cfg->an_diversity & 0xFF; ! if (diversity == AN_DIVERSITY_ANTENNA_1_ONLY) printf("antenna 1 only"); else if (diversity == AN_DIVERSITY_ANTENNA_2_ONLY) printf("antenna 2 only"); --- 823,831 ---- printf(" ]"); printf("\nRX Diversity:\t\t\t\t[ "); diversity = cfg->an_diversity & 0xFF; ! if (diversity == AN_DIVERSITY_FACTORY_DEFAULT) ! printf("factory default"); ! else if (diversity == AN_DIVERSITY_ANTENNA_1_ONLY) printf("antenna 1 only"); else if (diversity == AN_DIVERSITY_ANTENNA_2_ONLY) printf("antenna 2 only"); *************** *** 795,801 **** printf(" ]"); printf("\nTX Diversity:\t\t\t\t[ "); diversity = (cfg->an_diversity >> 8) & 0xFF; ! if (diversity == AN_DIVERSITY_ANTENNA_1_ONLY) printf("antenna 1 only"); else if (diversity == AN_DIVERSITY_ANTENNA_2_ONLY) printf("antenna 2 only"); --- 834,842 ---- printf(" ]"); printf("\nTX Diversity:\t\t\t\t[ "); diversity = (cfg->an_diversity >> 8) & 0xFF; ! if (diversity == AN_DIVERSITY_FACTORY_DEFAULT) ! printf("factory default"); ! else if (diversity == AN_DIVERSITY_ANTENNA_1_ONLY) printf("antenna 1 only"); else if (diversity == AN_DIVERSITY_ANTENNA_2_ONLY) printf("antenna 2 only"); *************** *** 828,833 **** --- 869,902 ---- return; } + static void an_dumprssimap(iface) + const char *iface; + { + struct an_ltv_rssi_map *rssi; + struct an_req areq; + int i; + + areq.an_len = sizeof(areq); + areq.an_type = AN_RID_RSSI_MAP; + + an_getval(iface, &areq); + + rssi = (struct an_ltv_rssi_map *)&areq; + + printf("idx\tpct\t dBm\n"); + + for (i = 0; i < 0xFF; i++) { + /* + * negate the dBm value: it's the only way the power + * level makes sense + */ + printf("%3d\t%3d\t%4d\n", i, + rssi->an_entries[i].an_rss_pct, + - rssi->an_entries[i].an_rss_dbm); + } + + return; + } static void usage(p) char *p; *************** *** 838,843 **** --- 907,913 ---- fprintf(stderr, "\t%s -i iface -I (show NIC capabilities)\n", p); fprintf(stderr, "\t%s -i iface -T (show stats counters)\n", p); fprintf(stderr, "\t%s -i iface -C (show current config)\n", p); + fprintf(stderr, "\t%s -i iface -R (show RSSI map)\n", p); fprintf(stderr, "\t%s -i iface -t 0-4 (set TX speed)\n", p); fprintf(stderr, "\t%s -i iface -s 0-3 (set power save mode)\n", p); fprintf(stderr, "\t%s -i iface [-v 1-4] -a AP (specify AP)\n", p); *************** *** 924,935 **** errx(1, "bad diversity setting: %d", diversity); break; } ! if (atoi(arg) == ACT_SET_DIVERSITY_RX) { ! cfg->an_diversity &= 0x00FF; ! cfg->an_diversity |= (diversity << 8); ! } else { cfg->an_diversity &= 0xFF00; cfg->an_diversity |= diversity; } break; case ACT_SET_TXPWR: --- 994,1005 ---- errx(1, "bad diversity setting: %d", diversity); break; } ! if (act == ACT_SET_DIVERSITY_RX) { cfg->an_diversity &= 0xFF00; cfg->an_diversity |= diversity; + } else { + cfg->an_diversity &= 0x00FF; + cfg->an_diversity |= (diversity << 8); } break; case ACT_SET_TXPWR: *************** *** 1519,1525 **** opterr = 1; while ((ch = getopt(argc, argv, ! "ANISCTht:a:e:o:s:n:v:d:j:b:c:r:p:w:m:l:k:K:W:QZM:L:")) != -1) { switch(ch) { case 'Z': #ifdef ANCACHE --- 1589,1595 ---- opterr = 1; while ((ch = getopt(argc, argv, ! "ANISCTRht:a:e:o:s:n:v:d:j:b:c:r:p:w:m:l:k:K:W:QZM:L:")) != -1) { switch(ch) { case 'Z': #ifdef ANCACHE *************** *** 1553,1558 **** --- 1623,1631 ---- case 'C': act = ACT_DUMPCONFIG; break; + case 'R': + act = ACT_DUMPRSSIMAP; + break; case 't': act = ACT_SET_TXRATE; arg = optarg; *************** *** 1605,1613 **** act = ACT_SET_DIVERSITY_TX; break; default: ! errx(1, "must specift RX or TX diversity"); break; } arg = optarg; break; case 'j': --- 1678,1690 ---- act = ACT_SET_DIVERSITY_TX; break; default: ! errx(1, "must specify RX or TX diversity"); break; } + if (!isdigit(*optarg)) { + errx(1, "%s is not numeric", optarg); + exit(1); + } arg = optarg; break; case 'j': *************** *** 1717,1722 **** --- 1794,1802 ---- break; case ACT_DUMPAP: an_dumpap(iface); + break; + case ACT_DUMPRSSIMAP: + an_dumprssimap(iface); break; case ACT_SET_SSID1: case ACT_SET_SSID2: To Unsubscribe: send mail to [EMAIL PROTECTED] with "unsubscribe freebsd-current" in the body of the message