Add support for MPI-350 the mini-pci Cisco Aironet card. This needs more

work.  The interface was gleaned from the Linux driver.  Currently only
one RX & one TX buffer are used.  Firmware support is not tested so for the
MPI-350 so it is disabled.  Signal cache and monitor mode are not supported
yet.  Signal cache is not supported since in encapsulation mode ethernet
frames are returned by the chip.  LAN monitor mode support will be added
shortly.  Thanks to Warner for the MPI-350 card he sent me.

Add support for RSSI map from PR kern/32880 which was incomplete.  Enhanced
with the ability to select the cache mode of raw, dbm or per-cent.

Clean up Signal/Noise/Quality structures and units with help from
Marco Molteni.

Change flash to use a malloc'ed buffer when needed.

PR:		kern/32880
Submitted by:	Douglas S. J. De Couto decouto@pdos.lcs.mit.edu,
		Marco Molteni
MFC:		3 weeks
This commit is contained in:
Doug Ambrisko 2002-12-29 19:22:07 +00:00
parent 6a1b2a22ef
commit 6cafe2646a
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=108401
7 changed files with 1430 additions and 352 deletions

View File

@ -132,6 +132,25 @@ struct an_sigcache {
};
#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,6 +354,7 @@ struct an_ltv_genconfig {
#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,6 +523,16 @@ struct an_ltv_radioinfo {
/* ??? */
};
/*
* 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,7 +550,7 @@ struct an_ltv_status {
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_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,12 +571,15 @@ struct an_ltv_status {
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_normalized_strength; /* 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_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,6 +676,7 @@ struct an_ltv_leap_password {
#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

File diff suppressed because it is too large Load Diff

View File

@ -193,4 +193,3 @@ an_pccard_attach(device_t dev)
error = an_attach(sc, device_get_unit(dev), flags);
return (error);
}

View File

@ -101,6 +101,7 @@ struct an_type {
#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,6 +133,12 @@ an_probe_pci(device_t dev)
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,21 +155,26 @@ an_attach_pci(dev)
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 (pci_get_vendor(dev) == AIRONET_VENDORID &&
pci_get_device(dev) == AIRONET_DEVICEID_MPI350) {
sc->mpi350 = 1;
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;
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;
}
sc->port_rid = AN_PCI_LOIO;
error = an_alloc_port(dev, sc->port_rid, 1);
if (error) {
@ -173,17 +185,55 @@ an_attach_pci(dev)
sc->an_btag = rman_get_bustag(sc->port_res);
sc->an_bhandle = rman_get_bushandle(sc->port_res);
/* Allocate memory for MPI350 */
if (sc->mpi350) {
/* Allocate memory */
sc->mem_rid = PCIR_MAPS + 4;
error = an_alloc_memory(dev, sc->mem_rid, 1);
if (error) {
printf("an%d: couldn't map memory\n", unit);
goto fail;
}
sc->an_mem_btag = rman_get_bustag(sc->mem_res);
sc->an_mem_bhandle = rman_get_bushandle(sc->mem_res);
/* Allocate aux. memory */
sc->mem_aux_rid = PCIR_MAPS + 8;
error = an_alloc_aux_memory(dev, sc->mem_aux_rid,
AN_AUXMEMSIZE);
if (error) {
printf("an%d: couldn't map aux memory\n", unit);
goto fail;
}
sc->an_mem_aux_btag = rman_get_bustag(sc->mem_aux_res);
sc->an_mem_aux_bhandle = rman_get_bushandle(sc->mem_aux_res);
/* Allocate DMA region */
error = bus_dma_tag_create(NULL, /* parent */
1, 0, /* alignment, bounds */
BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
NULL, NULL, /* filter, filterarg */
0x3ffff, /* maxsize XXX */
1, /* nsegments */
0xffff, /* maxsegsize XXX */
BUS_DMA_ALLOCNOW, /* flags */
&sc->an_dtag);
if (error) {
printf("an%d: couldn't get DMA region\n", unit);
goto fail;
}
}
/* Allocate interrupt */
error = an_alloc_irq(dev, 0, RF_SHAREABLE);
if (error) {
an_release_resources(dev);
goto fail;
}
error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET,
an_intr, sc, &sc->irq_handle);
if (error) {
an_release_resources(dev);
goto fail;
}
@ -191,6 +241,8 @@ an_attach_pci(dev)
error = an_attach(sc, device_get_unit(dev), flags);
fail:
if (error)
an_release_resources(dev);
return(error);
}

View File

@ -32,7 +32,7 @@
* $FreeBSD$
*/
#define AN_TIMEOUT 65536
#define AN_TIMEOUT 600000
/* Default network name: <empty string> */
#define AN_DEFAULT_NETNAME ""
@ -57,25 +57,60 @@
#define CSR_READ_1(sc, reg) \
bus_space_read_1(sc->an_btag, sc->an_bhandle, reg)
/*
* memory space access macros
*/
#define CSR_MEM_WRITE_2(sc, reg, val) \
bus_space_write_2(sc->an_mem_btag, sc->an_mem_bhandle, reg, val)
#define CSR_MEM_READ_2(sc, reg) \
bus_space_read_2(sc->an_mem_btag, sc->an_mem_bhandle, reg)
#define CSR_MEM_WRITE_1(sc, reg, val) \
bus_space_write_1(sc->an_mem_btag, sc->an_mem_bhandle, reg, val)
#define CSR_MEM_READ_1(sc, reg) \
bus_space_read_1(sc->an_mem_btag, sc->an_mem_bhandle, reg)
/*
* aux. memory space access macros
*/
#define CSR_MEM_AUX_WRITE_4(sc, reg, val) \
bus_space_write_4(sc->an_mem_aux_btag, sc->an_mem_aux_bhandle, reg, val)
#define CSR_MEM_AUX_READ_4(sc, reg) \
bus_space_read_4(sc->an_mem_aux_btag, sc->an_mem_aux_bhandle, reg)
#define CSR_MEM_AUX_WRITE_1(sc, reg, val) \
bus_space_write_1(sc->an_mem_aux_btag, sc->an_mem_aux_bhandle, reg, val)
#define CSR_MEM_AUX_READ_1(sc, reg) \
bus_space_read_1(sc->an_mem_aux_btag, sc->an_mem_aux_bhandle, reg)
/*
* Size of Aironet I/O space.
*/
#define AN_IOSIZ 0x40
/*
* Size of aux. memory space ... probably not needed DJA
*/
#define AN_AUXMEMSIZE (256 * 1024)
/*
* Hermes register definitions and what little I know about them.
*/
/* Hermes command/status registers. */
#define AN_COMMAND 0x00
#define AN_PARAM0 0x02
#define AN_PARAM1 0x04
#define AN_PARAM2 0x06
#define AN_STATUS 0x08
#define AN_RESP0 0x0A
#define AN_RESP1 0x0C
#define AN_RESP2 0x0E
#define AN_LINKSTAT 0x10
#define AN_COMMAND(x) (x ? 0x00 : 0x00)
#define AN_PARAM0(x) (x ? 0x04 : 0x02)
#define AN_PARAM1(x) (x ? 0x08 : 0x04)
#define AN_PARAM2(x) (x ? 0x0c : 0x06)
#define AN_STATUS(x) (x ? 0x10 : 0x08)
#define AN_RESP0(x) (x ? 0x14 : 0x0A)
#define AN_RESP1(x) (x ? 0x18 : 0x0C)
#define AN_RESP2(x) (x ? 0x1c : 0x0E)
#define AN_LINKSTAT(x) (x ? 0x20 : 0x10)
/* Command register */
#define AN_CMD_BUSY 0x8000 /* busy bit */
@ -97,6 +132,7 @@
#define AN_CMD_TX 0x000B /* transmit */
#define AN_CMD_DEALLOC_MEM 0x000C
#define AN_CMD_NOOP2 0x0010
#define AN_CMD_ALLOC_DESC 0x0020
#define AN_CMD_ACCESS 0x0021
#define AN_CMD_ALLOC_BUF 0x0028
#define AN_CMD_PSP_NODES 0x0030
@ -105,6 +141,69 @@
#define AN_CMD_SLEEP 0x0085
#define AN_CMD_SAVECFG 0x0108
/*
* MPI 350 DMA descriptor information
*/
#define AN_DESCRIPTOR_TX 0x01
#define AN_DESCRIPTOR_RX 0x02
#define AN_DESCRIPTOR_TXCMP 0x04
#define AN_DESCRIPTOR_HOSTWRITE 0x08
#define AN_DESCRIPTOR_HOSTREAD 0x10
#define AN_DESCRIPTOR_HOSTRW 0x20
#define AN_MAX_RX_DESC 1
#define AN_MAX_TX_DESC 1
#define AN_HOSTBUFSIZ 1840
struct an_card_rid_desc
{
unsigned an_rid:16;
unsigned an_len:15;
unsigned an_valid:1;
u_int64_t an_phys;
};
struct an_card_rx_desc
{
unsigned an_ctrl:15;
unsigned an_done:1;
unsigned an_len:15;
unsigned an_valid:1;
u_int64_t an_phys;
};
struct an_card_tx_desc
{
unsigned an_offset:15;
unsigned an_eoc:1;
unsigned an_len:15;
unsigned an_valid:1;
u_int64_t an_phys;
};
#define AN_RID_BUFFER_SIZE 2048
#define AN_RX_BUFFER_SIZE 1840
#define AN_TX_BUFFER_SIZE 1840
#define AN_HOST_DESC_OFFSET 0x8
#define AN_RX_DESC_OFFSET (AN_HOST_DESC_OFFSET + \
sizeof(struct an_card_rid_desc))
#define AN_TX_DESC_OFFSET (AN_RX_DESC_OFFSET + \
(AN_MAX_RX_DESC * sizeof(struct an_card_rx_desc)))
struct an_command {
u_int16_t an_cmd;
u_int16_t an_parm0;
u_int16_t an_parm1;
u_int16_t an_parm2;
};
struct an_reply {
u_int16_t an_status;
u_int16_t an_resp0;
u_int16_t an_resp1;
u_int16_t an_resp2;
};
/*
* Reclaim qualifier bit, applicable to the
* TX command.
@ -169,9 +268,10 @@
#define AN_OFF_DATAOFF 0x0FFF
/* Event registers */
#define AN_EVENT_STAT 0x30 /* Event status */
#define AN_INT_EN 0x32 /* Interrupt enable/disable */
#define AN_EVENT_ACK 0x34 /* Ack event */
#define AN_EVENT_STAT(x) (x ? 0x60 : 0x30) /* Event status */
#define AN_INT_EN(x) (x ? 0x64 : 0x32) /* Interrupt enable/
disable */
#define AN_EVENT_ACK(x) (x ? 0x68 : 0x34) /* Ack event */
/* Events */
#define AN_EV_CLR_STUCK_BUSY 0x4000 /* clear stuck busy bit */
@ -188,10 +288,10 @@
(AN_EV_RX|AN_EV_TX|AN_EV_TX_EXC|AN_EV_ALLOC|AN_EV_LINKSTAT)
/* Host software registers */
#define AN_SW0 0x28
#define AN_SW1 0x2A
#define AN_SW2 0x2C
#define AN_SW3 0x2E
#define AN_SW0(x) (x ? 0x50 : 0x28)
#define AN_SW1(x) (x ? 0x54 : 0x2A)
#define AN_SW2(x) (x ? 0x58 : 0x2C)
#define AN_SW3(x) (x ? 0x5c : 0x2E)
#define AN_CNTL 0x14
@ -311,6 +411,15 @@ struct an_snap_hdr {
u_int16_t an_snap_type;
};
struct an_dma_alloc {
u_int32_t an_dma_paddr;
caddr_t an_dma_vaddr;
bus_dmamap_t an_dma_map;
bus_dma_segment_t an_dma_seg;
bus_size_t an_dma_size;
int an_dma_nseg;
};
#define AN_TX_RING_CNT 4
#define AN_INC(x, y) (x) = (x + 1) % y
@ -319,6 +428,7 @@ struct an_tx_ring_data {
u_int16_t an_tx_ring[AN_TX_RING_CNT];
int an_tx_prod;
int an_tx_cons;
int an_tx_empty;
};
struct an_softc {
@ -328,13 +438,24 @@ struct an_softc {
int port_rid; /* resource id for port range */
struct resource* port_res; /* resource for port range */
int mem_rid; /* resource id for memory range */
int mem_used; /* nonzero if memory used */
struct resource* mem_res; /* resource for memory range */
int mem_aux_rid; /* resource id for memory range */
int mem_aux_used; /* nonzero if memory used */
struct resource* mem_aux_res; /* resource for memory range */
int irq_rid; /* resource id for irq */
struct resource* irq_res; /* resource for irq */
void* irq_handle; /* handle for irq handler */
struct resource* irq_res; /* resource for irq */
bus_space_handle_t an_bhandle_p;
bus_space_handle_t an_bhandle;
bus_space_tag_t an_btag;
bus_space_handle_t an_mem_bhandle;
bus_space_tag_t an_mem_btag;
bus_space_handle_t an_mem_aux_bhandle;
bus_space_tag_t an_mem_aux_btag;
bus_dma_tag_t an_dtag;
struct an_ltv_genconfig an_config;
struct an_ltv_caps an_caps;
struct an_ltv_ssidlist an_ssidlist;
@ -354,6 +475,8 @@ struct an_softc {
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,6 +486,11 @@ struct an_softc {
int an_was_monitor;
u_char buf_802_11[MCLBYTES];
struct an_req areq;
unsigned short* an_flash_buffer;
int mpi350;
struct an_dma_alloc an_rid_buffer;
struct an_dma_alloc an_rx_buffer[AN_MAX_RX_DESC];
struct an_dma_alloc an_tx_buffer[AN_MAX_TX_DESC];
};
#define AN_LOCK(_sc) mtx_lock(&(_sc)->an_mtx)
@ -371,6 +499,7 @@ struct an_softc {
void an_release_resources (device_t);
int an_alloc_port (device_t, int, int);
int an_alloc_memory (device_t, int, int);
int an_alloc_aux_memory (device_t, int, int);
int an_alloc_irq (device_t, int, int);
int an_probe (device_t);
void an_shutdown (device_t);

View File

@ -50,6 +50,12 @@
.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,6 +196,27 @@ Display current NIC configuration.
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
.Va machdep.an_cache_mode
.Xr sysctl 8
variable can be set to
.Cm raw , dbm
or
.Cm per .
.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:

View File

@ -58,8 +58,9 @@ static const char rcsid[] =
#include <errno.h>
#include <err.h>
#include <md4.h>
#include <ctype.h>
static void an_getval(const char *, struct an_req *);
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,6 +87,7 @@ static void an_str2key(char *, struct an_ltv_key *);
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,12 +133,14 @@ int main(int, char **);
#define ACT_SET_MONITOR_MODE 37
#define ACT_SET_LEAP_MODE 38
static void an_getval(iface, areq)
#define ACT_DUMPRSSIMAP 39
static int an_getval(iface, areq)
const char *iface;
struct an_req *areq;
{
struct ifreq ifr;
int s;
int s, okay = 1;
bzero((char *)&ifr, sizeof(ifr));
@ -148,12 +152,14 @@ static void an_getval(iface, areq)
if (s == -1)
err(1, "socket");
if (ioctl(s, SIOCGAIRONET, &ifr) == -1)
if (ioctl(s, SIOCGAIRONET, &ifr) == -1) {
okay = 0;
err(1, "SIOCGAIRONET");
}
close(s);
return;
return okay;
}
static void an_setval(iface, areq)
@ -260,6 +266,21 @@ static void an_dumpstatus(iface)
{
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,10 +309,22 @@ static void an_dumpstatus(iface)
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);
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,7 +411,9 @@ static void an_dumpcaps(iface)
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)
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,11 +421,13 @@ static void an_dumpcaps(iface)
printf("antenna 1 and 2");
printf(" ]");
printf("\nTX Diversity:\t\t[ ");
if (caps->an_rx_diversity == AN_DIVERSITY_ANTENNA_1_ONLY)
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_rx_diversity == AN_DIVERSITY_ANTENNA_2_ONLY)
else if (caps->an_tx_diversity == AN_DIVERSITY_ANTENNA_2_ONLY)
printf("antenna 2 only");
else if (caps->an_rx_diversity == AN_DIVERSITY_ANTENNA_1_AND_2)
else if (caps->an_tx_diversity == AN_DIVERSITY_ANTENNA_1_AND_2)
printf("antenna 1 and 2");
printf(" ]");
printf("\nSupported power levels:\t");
@ -786,7 +823,9 @@ static void an_dumpconfig(iface)
printf(" ]");
printf("\nRX Diversity:\t\t\t\t[ ");
diversity = cfg->an_diversity & 0xFF;
if (diversity == AN_DIVERSITY_ANTENNA_1_ONLY)
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,7 +834,9 @@ static void an_dumpconfig(iface)
printf(" ]");
printf("\nTX Diversity:\t\t\t\t[ ");
diversity = (cfg->an_diversity >> 8) & 0xFF;
if (diversity == AN_DIVERSITY_ANTENNA_1_ONLY)
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,6 +869,34 @@ static void an_dumpconfig(iface)
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,6 +907,7 @@ static void usage(p)
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,12 +994,12 @@ static void an_setconfig(iface, act, arg)
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 {
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,7 +1589,7 @@ int main(argc, argv)
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) {
"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,6 +1623,9 @@ int main(argc, argv)
case 'C':
act = ACT_DUMPCONFIG;
break;
case 'R':
act = ACT_DUMPRSSIMAP;
break;
case 't':
act = ACT_SET_TXRATE;
arg = optarg;
@ -1605,9 +1678,13 @@ int main(argc, argv)
act = ACT_SET_DIVERSITY_TX;
break;
default:
errx(1, "must specift RX or TX diversity");
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':
@ -1718,6 +1795,9 @@ int main(argc, argv)
case ACT_DUMPAP:
an_dumpap(iface);
break;
case ACT_DUMPRSSIMAP:
an_dumprssimap(iface);
break;
case ACT_SET_SSID1:
case ACT_SET_SSID2:
case ACT_SET_SSID3: