Date: Thu, 24 Oct 2002 20:42:54 -0700 (PDT) From: Doug Ambrisko <ambrisko@ambrisko.com> To: David Wolfskill <david@catwhisker.org> Cc: current@FreeBSD.org Subject: Re: "Expensive timeout(9) function" @an_stats_update() [/usr/src/sys/dev/an/if_an.c:724] Message-ID: <200210250342.g9P3gsu86966@ambrisko.com> In-Reply-To: <200210221422.g9MEMxwU006241@bunrab.catwhisker.org>
next in thread | previous in thread | raw e-mail | index | archive | help
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 majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200210250342.g9P3gsu86966>
