This is a program for configuring the Parameter Storage Area on ISA

Wavelan cards via the 'wl' driver.  It can be used to set the IRQ, and
discover all manner of odd things about the device.
This commit is contained in:
Mike Smith 1997-05-22 08:58:18 +00:00
parent e847647398
commit 1b6394c6c7
3 changed files with 435 additions and 0 deletions

View File

@ -0,0 +1,7 @@
# $Id$
PROG= wlconfig
SRCS= wlconfig.c
CFLAGS+= Wall
MAN8= wlconfig.8
.include <bsd.prog.mk>

View File

@ -0,0 +1,103 @@
.Dd December 26 1996
.Os
.Dt WLCONFIG 8
.Sh NAME
.Nm wlconfig
.Nd read/write wavelan config parameters
.Sh SYNOPSIS
.Nm wlconfig
.Ar ifname
.Op Ar param value ...
.Sh DESCRIPTION
The
.Nm wlconfig
command can be used to read and set parameters for the NCR/AT&T Wavelan
radio LAN card. Various parameters stored in the nonvolatile Parameter
Storage Area (PSA) on the card can be modified with this program, which
obviates the need for the DOS-based
.Nm instconf.exe
program.
.Pp
The
.Ar ifname
parameter specifies the wavelan interface name (eg.
.Pa wl0
). If no other arguments are supplied, the current contents of the PSA
are interpreted and displayed.
.Pp
The
.Ar param
and
.Ar value
arguments can be used to change the value of several of the parameters.
Any number of
.Ar param value
pairs may be supplied.
.Bl -tag -width 15n -compat -offset indent
.It Va param
.Va value
.It irq
IRQ value (used at next reset), may be one of 3,4,5,6,10,11,12,15
.It mac
Local MAC value (ethernet address)
.It macsel
.Sq soft
(as set by the
.Sq mac
parameter) or
.Sq default
(as set at the factory).
.It nwid
The NWID is a 2-byte parameter passed to the card's radio modem.
NWIDs allow multiple logically discrete networks to operate
independantly whilse occupying the same airspace.
Packets with a different NWID are simply ignored by the modem.
In the hardware, NWIDs are stored long-term in non-volative memory
(called the PSA or programmable storage area), and are loaded by
software into the radio modem when the driver is
initialized. This sets the default NWID loaded at startup.
.It curnwid
This sets the current operating NWID (but does not save it to the
PSA).
.El
.Pp
Note that if the IRQ on the Wavelan card is incorrect, the interface
will be configured, but will not function. The
.Nm wlconfig
program should then be used to reconfigure the card to a sensible
value.
.Sh EXAMPLES
Set the NWID to 0x1234 :
.Bd -literal -offset
# wlconfig wl0 nwid 0x1234
.Ed
.Pp
Show the current settings :
.Bd -literal -offset
# wlconfig wl0
Board type : ISA
Base address options : 0x300, 0x390, 0x3c0, 0x3e0
Waitstates : 0
Bus mode : ISA
IRQ : 10
Default MAC address : 08:00:0e:20:3d:4b
Soft MAC address : 00:00:00:00:00:00
Current MAC address : Default
Adapter compatability : PC-AT 2.4GHz
Threshold preset : 1
Call code required : NO
Subband : 2425MHz
Quality threshold : 3
Hardware version : 0 (Rel1/Rel2)
Network ID enable : YES
NWID : 0xdead
Datalink security : NO
Databus width : 16 (variable)
Configuration state : unconfigured
CRC-16 : 0x3c26
CRC status : OK
.Ed
.Sh HISTORY
This implementation of the
.Nm wlconfig
command is completely new, written for Hilink Internet by Michael Smith.

View File

@ -0,0 +1,325 @@
/*
* Copyright (C) 1996
* Michael Smith. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY Michael Smith AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL Michael Smith OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id$
*
*/
/*
* wlconfig.c
*
* utility to read out and change various WAVELAN parameters.
* Currently supports NWID and IRQ values.
*
* The NWID is used by 2 or more wavelan controllers to determine
* if packets should be received or not. It is a filter that
* is roughly analogous to the "channel" setting with a garage
* door controller. Two companies side by side with wavelan devices
* that could actually hear each other can use different NWIDs
* and ignore packets. In truth however, the air space is shared,
* and the NWID is a virtual filter.
*
* In the current set of wavelan drivers, ioctls changed only
* the runtime radio modem registers which act in a manner analogous
* to an ethernet transceiver. The ioctls do not change the
* stored nvram PSA (or parameter storage area). At boot, the PSA
* values are stored in the radio modem. Thus when the
* system reboots it will restore the wavelan NWID to the value
* stored in the PSA. The NCR/ATT dos utilities must be used to
* change the initial NWID values in the PSA. The wlconfig utility
* may be used to set a different NWID at runtime; this is only
* permitted while the interface is up and running.
*
* By contrast, the IRQ value can only be changed while the
* Wavelan card is down and unconfigured, and it will remain
* disabled after an IRQ change until reboot.
*
*/
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <machine/if_wl_wavelan.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
extern struct ether_addr *ether_aton(char *a);
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
/* translate IRQ bit to number */
/* array for maping irq numbers to values for the irq parameter register */
static int irqvals[16] = {
0, 0, 0, 0x01, 0x02, 0x04, 0, 0x08, 0, 0, 0x10, 0x20, 0x40, 0, 0, 0x80
};
int
wlirq(int irqval)
{
int irq;
for(irq = 0; irq < 16; irq++)
if(irqvals[irq] == irqval)
return(irq);
return 0;
}
char *compat_type[] = {
"PC-AT 915MHz",
"PC-MC 915MHz",
"PC-AT 2.4GHz",
"PC-MC 2.4GHz",
"PCCARD or 1/2 size AT, 915MHz or 2.4GHz"
};
char *subband[] = {
"915MHz/see WaveModem",
"2425MHz",
"2460MHz",
"2484MHz",
"2430.5MHz"
};
/*
** print_psa
**
** Given a pointer to a PSA structure, print it out
*/
void
print_psa(u_char *psa, int currnwid)
{
int nwid;
/*
** Work out what sort of board we have
*/
if (psa[0] == 0x14) {
printf("Board type : Microchannel\n");
} else {
if (psa[1] == 0) {
printf("Board type : PCCARD\n");
} else {
printf("Board type : ISA");
if ((psa[4] == 0) &&
(psa[5] == 0) &&
(psa[6] == 0))
printf(" (DEC OEM)");
printf("\n");
printf("Base address options : 0x300, 0x%02x0, 0x%02x0, 0x%02x0\n",
(int)psa[1], (int)psa[2], (int)psa[3]);
printf("Waitstates : %d\n",psa[7] & 0xf);
printf("Bus mode : %s\n",(psa[7] & 0x10) ? "EISA" : "ISA");
printf("IRQ : %d\n",wlirq(psa[8]));
}
}
printf("Default MAC address : %02x:%02x:%02x:%02x:%02x:%02x\n",
psa[0x10],psa[0x11],psa[0x12],psa[0x13],psa[0x14],psa[0x15]);
printf("Soft MAC address : %02x:%02x:%02x:%02x:%02x:%02x\n",
psa[0x16],psa[0x17],psa[0x18],psa[0x19],psa[0x1a],psa[0x1b]);
printf("Current MAC address : %s\n",(psa[0x1c] & 0x1) ? "Soft" : "Default");
printf("Adapter compatability : ");
if (psa[0x1d] < 5) {
printf("%s\n",compat_type[psa[0x1d]]);
} else {
printf("unknown\n");
}
printf("Threshold preset : %d\n",psa[0x1e]);
printf("Call code required : %s\n",(psa[0x1f] & 0x1) ? "YES" : "NO");
if (psa[0x1f] & 0x1)
printf("Call code : 0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
psa[0x30],psa[0x31],psa[0x32],psa[0x33],psa[0x34],psa[0x35],psa[0x36],psa[0x37]);
printf("Subband : %s\n",subband[psa[0x20] & 0xf]);
printf("Quality threshold : %d\n",psa[0x21]);
printf("Hardware version : %d (%s)\n",psa[0x22],psa[0x22] ? "Rel3" : "Rel1/Rel2");
printf("Network ID enable : %s\n",(psa[0x25] & 0x1) ? "YES" : "NO");
if (psa[0x25] & 0x1) {
nwid = (psa[0x23] << 8) + psa[0x24];
printf("NWID : 0x%04x\n",nwid);
if (nwid != currnwid) {
printf("Current NWID : 0x%04x\n",currnwid);
}
}
printf("Datalink security : %s\n",(psa[0x26] & 0x1) ? "YES" : "NO");
if (psa[0x26] & 0x1) {
printf("Encryption key : ");
if (psa[0x27] == 0) {
printf("DENIED\n");
} else {
printf("0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
psa[0x27],psa[0x28],psa[0x29],psa[0x2a],psa[0x2b],psa[0x2c],psa[0x2d],psa[0x2e]);
}
}
printf("Databus width : %d (%s)\n",
(psa[0x2f] & 0x1) ? 16 : 8, (psa[0x2f] & 0x80) ? "fixed" : "variable");
printf("Configuration state : %sconfigured\n",(psa[0x38] & 0x1) ? "" : "un");
printf("CRC-16 : 0x%02x%02x\n",psa[0x3e],psa[0x3d]);
printf("CRC status : ");
switch(psa[0x3f]) {
case 0xaa:
printf("OK\n");
break;
case 0x55:
printf("BAD\n");
break;
default:
printf("Error\n");
break;
}
}
void
syntax(char *pname)
{
fprintf(stderr,"Usage: %s <ifname> [<param> <value> ...]\n",pname);
fprintf(stderr," <ifname> Wavelan interface name.\n");
fprintf(stderr," <param> Parameter name (see below)\n");
fprintf(stderr," <value> New value for parameter.\n");
fprintf(stderr," Parameter name: Value:\n");
fprintf(stderr," irq 3,4,5,6,10,11,12,15\n");
fprintf(stderr," mac soft ethernet address\n");
fprintf(stderr," macsel soft or default\n");
fprintf(stderr," nwid default NWID (0x0-0xffff)\n");
fprintf(stderr," currnwid current NWID (0x0-0xffff) or 'get'\n");
exit(1);
}
void
main(int argc, char *argv[])
{
int sd;
struct ifreq ifr;
u_char psabuf[0x40];
int val, argind, i;
char *cp, *param, *value;
struct ether_addr *ea;
int work = 0;
int currnwid;
if ((argc < 2) || (argc % 2))
syntax(argv[0]);
/* get a socket */
sd = socket(AF_INET, SOCK_DGRAM, 0);
if (sd < 0)
err(1,"socket");
strncpy(ifr.ifr_name, argv[1], sizeof(ifr.ifr_name));
ifr.ifr_addr.sa_family = AF_INET;
/* get the PSA */
ifr.ifr_data = (caddr_t)psabuf;
if (ioctl(sd, SIOCGWLPSA, (caddr_t)&ifr))
err(1,"Get PSA");
/* get the current NWID */
if (ioctl(sd, SIOCGWLCNWID, (caddr_t)&ifr))
err(1,"Get NWID");
currnwid = (int)ifr.ifr_data;
/* just dump and exit? */
if (argc == 2) {
print_psa(psabuf, currnwid);
exit(0);
}
/* loop reading arg pairs */
for (argind = 2; argind < argc; argind += 2) {
param = argv[argind];
value = argv[argind+1];
/* What to do? */
if (!strcasecmp(param,"currnwid")) { /* set current NWID */
val = strtol(value,&cp,0);
if ((val < 0) || (val > 0xffff) || (cp == value))
errx(1,"Bad NWID '%s'",value);
ifr.ifr_data = (caddr_t)val;
if (ioctl(sd, SIOCSWLCNWID, (caddr_t)&ifr))
err(1,"Set NWID (interface not up?)");
continue ;
}
if (!strcasecmp(param,"irq")) {
val = strtol(value,&cp,0);
val = irqvals[val];
if ((val == 0) || (cp == value))
errx(1,"Bad IRQ '%s'",value);
psabuf[WLPSA_IRQNO] = (u_char)val;
work = 1;
continue;
}
if (!strcasecmp(param,"mac")) {
if ((ea = ether_aton(value)) == NULL)
errx(1,"Bad ethernet address '%s'",value);
for (i = 0; i < 6; i++)
psabuf[WLPSA_LOCALMAC + i] = ea->octet[i];
work = 1;
continue;
}
if (!strcasecmp(param,"macsel")) {
if (!strcasecmp(value,"local")) {
psabuf[WLPSA_MACSEL] |= 0x1;
work = 1;
continue;
}
if (!strcasecmp(value,"universal")) {
psabuf[WLPSA_MACSEL] &= ~0x1;
work = 1;
continue;
}
errx(1,"Bad macsel value '%s'",value);
}
if (!strcasecmp(param,"nwid")) {
val = strtol(value,&cp,0);
if ((val < 0) || (val > 0xffff) || (cp == value))
errx(1,"Bad NWID '%s'",value);
psabuf[WLPSA_NWID] = (val >> 8) & 0xff;
psabuf[WLPSA_NWID+1] = val & 0xff;
work = 1;
continue;
}
errx(1,"Unknown parameter '%s'",param);
}
if (work) {
ifr.ifr_data = (caddr_t)psabuf;
if (ioctl(sd, SIOCSWLPSA, (caddr_t)&ifr))
err(1,"Set PSA");
}
}