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

Reply via email to