Add arl(4): driver for Aironet Arlan 655 wireless adapters.

MFC after:	2 weeks
This commit is contained in:
Max Khon 2004-03-15 22:24:28 +00:00
parent f6c21c0641
commit 798f0e1603
15 changed files with 3444 additions and 0 deletions

View File

@ -6,6 +6,7 @@ MAN= acpi_toshiba.4 \
amdpm.4 \
apm.4 \
ar.4 \
arl.4 \
CPU_ELAN.4 \
cs.4 \
ct.4 \

View File

@ -0,0 +1,78 @@
.\" Copyright (c) 1997, 1998, 1999
.\" Bill Paul <wpaul@ee.columbia.edu>. 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.
.\" 3. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed by Bill Paul.
.\" 4. Neither the name of the author nor the names of any co-contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul OR THE VOICES IN HIS HEAD
.\" 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.
.\"
.\" $FreeBSD$
.\"
.Dd August 26, 2003
.Dt ARL 4
.Os
.Sh NAME
.Nm arl
.Nd "Aironet Arlan 655 wireless network adapter driver"
.Sh SYNOPSIS
.Cd "device arl"
.Sh DESCRIPTION
The
.Nm
driver provides support for Aironet Arlan 655
wireless network adapter.
The Arlan 655 series adapters operate at 354kbps, 512kbps, 1Mbps and 2Mbps.
.Pp
The Aironet Arlan 655 devices support Aironet TMA, Aironet Non-TMA
and PSP operating modes.
.Pp
By default, the
.Nm
driver configures the Aironet Aironet 655 card for TMA operation.
.Pp
For setup Radio Network parameters use
.Xr arlconfig 8 .
.Sh SEE ALSO
.Xr arp 4 ,
.Xr netintro 4 ,
.Xr arlconfig 8 ,
.Xr ifconfig 8
.Sh HISTORY
The
.Nm
device driver first appeared in
.Fx 5.3 .
.Sh AUTHORS
The
.Nm
driver initally was written by
.An Ivan Sharov Aq ivan.sharov@iname.com .
.Aq ran@styx.aic.net
wrote arlconfig utility and added ioctl support to the driver.
.An Stanislav Svirid Aq count@riss-telecom.ru
ported this driver to new ISA architechture, merged some al driver changes,
fixed some bugs and made it a module.
.An Yuri Kurenkov Aq y.kurenkov@init.ru
wrote this manpage.

View File

@ -122,6 +122,8 @@ dev/aic/aic_isa.c optional aic isa
dev/ar/if_ar.c optional ar
dev/ar/if_ar_pci.c optional ar pci
dev/ar/if_ar_isa.c optional ar isa
dev/arl/if_arl.c optional arl
dev/arl/if_arl_isa.c optional arl isa
dev/cm/if_cm_isa.c optional cm isa
dev/ctau/ctau.c optional ctau
dev/ctau/ctddk.c optional ctau

973
sys/dev/arl/if_arl.c Normal file
View File

@ -0,0 +1,973 @@
/*
* $RISS: if_arl/dev/arl/if_arl.c,v 1.5 2004/01/22 12:49:05 frol Exp $
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/proc.h>
#include <sys/conf.h>
#include <sys/module.h>
#include <sys/bus.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/rman.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <net/if_media.h>
#include <net/ethernet.h>
#include <net/bpf.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <machine/clock.h>
#include <dev/arl/if_arlreg.h>
/*#define DEBUG */
#ifdef DEBUG
#define D(x) {printf("arl%d: ", sc->arl_unit); printf x; }
#else
#define D(x)
#endif
/*
* channel attention
*/
#define ARL_CHANNEL(sc) \
{ \
D(("channel ctrl %x reg %x\n", sc->arl_control, ar->controlRegister)); \
ar->controlRegister = (sc->arl_control ^= ARL_CHANNEL_ATTENTION); \
}
/*
* Check registration
*/
#define ARL_CHECKREG(sc) (ar->registrationMode && ar->registrationStatus == 0)
#ifndef BPF_MTAP
#define BPF_MTAP(_ifp,_m) \
do { \
if ((_ifp)->if_bpf) \
bpf_mtap((_ifp), (_m)); \
} while (0)
#endif
#if __FreeBSD_version < 500100
#define BROADCASTADDR (etherbroadcastaddr)
#define _ARL_CURPROC (curproc)
#else
#define BROADCASTADDR (sc->arpcom.ac_if.if_broadcastaddr)
#define _ARL_CURPROC (curthread)
#endif
static void arl_hwreset (struct arl_softc *);
static void arl_reset (struct arl_softc *);
static int arl_ioctl (struct ifnet *, u_long, caddr_t);
static void arl_init (void *);
static void arl_start (struct ifnet *);
static void arl_watchdog (struct ifnet *);
static void arl_waitreg (struct ifnet *);
static void arl_enable (struct arl_softc *);
static void arl_config (struct arl_softc *);
static int arl_command (struct arl_softc *);
static void arl_put (struct arl_softc *);
static void arl_read (struct arl_softc *, caddr_t, int);
static void arl_recv (struct arl_softc *);
static struct mbuf* arl_get (caddr_t, int, int, struct ifnet *);
devclass_t arl_devclass;
/*
* Attach device
*/
int
arl_attach(dev)
device_t dev;
{
struct arl_softc* sc = device_get_softc(dev);
struct ifnet *ifp = &sc->arpcom.ac_if;
int attached;
D(("attach\n"));
if (ar->configuredStatusFlag == 0 && bootverbose)
printf("arl%d: card is NOT configured\n", sc->arl_unit);
arl_reset (sc);
attached = (ifp->if_softc != 0);
/* Initialize ifnet structure. */
ifp->if_softc = sc;
#if __FreeBSD_version < 502000
ifp->if_unit = sc->arl_unit;
ifp->if_name = "arl";
#else
if_initname(ifp, device_get_name(dev), device_get_unit(dev));
#endif
ifp->if_mtu = ETHERMTU;
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_output = ether_output;
ifp->if_start = arl_start;
ifp->if_ioctl = arl_ioctl;
ifp->if_watchdog = arl_watchdog;
ifp->if_init = arl_init;
ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
ifp->if_baudrate = 2000000;
ifp->if_timer = 0;
/*
* Attach the interface
*/
if (!attached) {
#if __FreeBSD_version < 500100
ether_ifattach(ifp, ETHER_BPF_SUPPORTED);
#else
ether_ifattach(ifp, sc->arpcom.ac_enaddr);
#endif
}
return (0);
}
/*
* Hardware reset
* reset all setting to default ( setted ARLANDGS )
*/
static void
arl_hwreset(sc)
struct arl_softc *sc;
{
D(("hw reset\n"));
ar->controlRegister = 1;
DELAY(ARDELAY1);
if (arl_wait_reset(sc, 0x24, ARDELAY1))
arl_stop(sc);
ar->controlRegister = (sc->arl_control = 1);
DELAY(ARDELAY1);
}
/*
* wait arlan command
*/
static int
arl_command(sc)
struct arl_softc *sc;
{
int i; /* long stuppid delay ??? */
D(("commandByte %x\n", ar->commandByte));
for (i = 100000; ar->commandByte && i; i--)
;
if (i == 0)
ar->commandByte = 0;
return (i == 0);
}
/*
* Enable for recieveng
*/
static void
arl_enable(sc)
struct arl_softc *sc;
{
D(("enable\n"));
sc->arl_control = (ARL_INTERRUPT_ENABLE | ARL_CLEAR_INTERRUPT);
ar->controlRegister = sc->arl_control;
arl_command(sc);
ar->rxStatusVector = 0;
ar->commandByte = 0x83;
ar->commandParameter[0] = 1;
ARL_CHANNEL(sc);
arl_command(sc);
}
/*
* reset and set user parameters
*/
static void
arl_reset(sc)
struct arl_softc *sc;
{
D(("reset\n"));
arl_hwreset(sc);
ar->resetFlag1 = 1;
bzero((ar), 0x1FF0); /* fill memory board with 0 */
ar->resetFlag1 = 0;
sc->arl_control = 0;
/* if (arl_wait_reset(sc, 0x168, ARDELAY1))
return;
*/
#if 1
{
int cnt = 0x168;
int delay = ARDELAY1;
ar->resetFlag = 0xFF; /* wish reset */
ar->controlRegister = 0; /* unreeze - do it */
while (ar->resetFlag && cnt--)
DELAY(delay);
if (cnt == 0) {
printf("arl%d: reset timeout\n", sc->arl_unit);
return;
}
D(("reset wait %d\n", 0x168 - cnt));
}
#endif
if (ar->diagnosticInfo != 0xff) {
printf("arl%d: reset error\n", sc->arl_unit);
return;
}
arl_config(sc);
}
/*
* configure radio parameters
*/
static void
arl_config(sc)
struct arl_softc *sc;
{
int i;
D(("config\n"));
SET_ARL_PARAM(spreadingCode);
SET_ARL_PARAM(channelNumber);
SET_ARL_PARAM(channelSet);
SET_ARL_PARAM(registrationMode);
SET_ARL_PARAM(priority);
SET_ARL_PARAM(receiveMode);
bcopy(arcfg.sid, ar->systemId, 4 * sizeof(ar->systemId[0]));
bcopy(arcfg.specifiedRouter, ar->specifiedRouter, ETHER_ADDR_LEN);
bcopy(arcfg.lanCardNodeId, ar->lanCardNodeId, ETHER_ADDR_LEN);
bzero(ar->name, ARLAN_NAME_SIZE); /* clear name */
strncpy(ar->name, arcfg.name, ARLAN_NAME_SIZE);
ar->diagnosticInfo = 0;
ar->commandByte = 1;
ARL_CHANNEL(sc);
DELAY(ARDELAY1);
/*
if (arl_command(sc) != 0) {
int i;
for (i = 0x168; ar->diagnosticInfo == 0 && i; i--) {
DELAY(ARDELAY1);
}
if (i != 0 && ar->diagnosticInfo != 0xff)
printf("arl%d: config error\n", sc->arl_unit);
else if (i == 0)
printf("arl%d: config timeout\n", sc->arl_unit);
} else
printf("arl%d: config failed\n", sc->arl_unit);
*/
if (arl_command(sc)) {
D(("config failed\n"));
return;
}
for (i = 0x168; ar->diagnosticInfo == 0 && i; i--)
DELAY(ARDELAY1);
if (i == 0) {
D(("config timeout\n"));
return;
}
if (ar->diagnosticInfo != 0xff) {
D(("config error\n"));
return;
}
D(("config lanCardNodeId %6D\n", ar->lanCardNodeId, ":"));
D(("config channel set %d, frequency %d, spread %d, mode %d\n",
ar->channelSet,
ar->channelNumber,
ar->spreadingCode,
ar->registrationMode));
/* clear quality stat */
bzero(&(aqual), ARLAN_MAX_QUALITY * sizeof(aqual[0]));
}
/*
* Socket Ioctl's.
*/
static int
arl_ioctl(ifp, cmd, data)
register struct ifnet *ifp;
u_long cmd;
caddr_t data;
{
struct arl_softc *sc = ifp->if_softc;
struct ifreq *ifr = (struct ifreq *)data;
d_thread_t *td = _ARL_CURPROC;
struct arl_req arlan_io;
int count, s, error = 0;
caddr_t user;
D(("ioctl %lx\n", cmd));
s = splimp();
switch (cmd) {
case SIOCSIFADDR:
case SIOCGIFADDR:
case SIOCSIFMTU:
error = ether_ioctl(ifp, cmd, data);
break;
case SIOCSIFFLAGS:
if (ifp->if_flags & IFF_UP) {
if (!(ifp->if_flags & IFF_RUNNING))
arl_init(sc);
} else {
if (ifp->if_flags & IFF_RUNNING)
arl_stop(sc);
}
break;
#define GET_PARAM(name) (arlan_io.cfg.name = ar->name)
#define GET_COPY_PARAM(name) \
{ \
bzero(arlan_io.cfg.name, sizeof(arlan_io.cfg.name)); \
bcopy(ar->name, arlan_io.cfg.name, sizeof(arlan_io.cfg.name)); \
}
case SIOCGARLALL:
bzero(&arlan_io, sizeof(arlan_io));
if (!suser(td)) {
bcopy(ar->systemId, arlan_io.cfg.sid, 4);
}
GET_COPY_PARAM(name);
GET_COPY_PARAM(lanCardNodeId);
GET_COPY_PARAM(specifiedRouter);
GET_PARAM(channelNumber);
GET_PARAM(channelSet);
GET_PARAM(spreadingCode);
GET_PARAM(registrationMode);
GET_PARAM(hardwareType);
GET_PARAM(majorHardwareVersion);
GET_PARAM(minorHardwareVersion);
GET_PARAM(radioModule);
GET_PARAM(priority);
GET_PARAM(receiveMode);
arlan_io.cfg.txRetry = arcfg.txRetry;
user = (void *)ifr->ifr_data;
for (count = 0; count < sizeof(arlan_io); count++)
if (subyte(user + count, ((char *)&arlan_io)[count]))
return (EFAULT);
break;
#define SET_PARAM(name) \
do { \
if (arlan_io.what_set & ARLAN_SET_##name) \
arcfg.name = arlan_io.cfg.name; \
} while (0)
#define SET_COPY_PARAM(name) \
do { \
if (arlan_io.what_set & ARLAN_SET_##name) { \
bzero(arcfg.name, sizeof(arcfg.name)); \
bcopy(arlan_io.cfg.name, arcfg.name, sizeof(arcfg.name)); \
} \
} while (0)
case SIOCSARLALL:
if (suser(td))
break;
user = (void *)ifr->ifr_data;
for (count = 0; count < sizeof(arlan_io); count++) {
if (fubyte(user + count) < 0)
return (EFAULT);
}
bcopy(user, (char *)&arlan_io, sizeof(arlan_io));
D(("need set 0x%04x\n", arlan_io.what_set));
if (arlan_io.what_set) {
SET_COPY_PARAM(name);
SET_COPY_PARAM(sid);
SET_COPY_PARAM(specifiedRouter);
SET_COPY_PARAM(lanCardNodeId);
SET_PARAM(channelSet);
SET_PARAM(channelNumber);
SET_PARAM(spreadingCode);
SET_PARAM(registrationMode);
SET_PARAM(priority);
SET_PARAM(receiveMode);
if (arlan_io.what_set & ARLAN_SET_txRetry)
arcfg.txRetry = arlan_io.cfg.txRetry;
arl_config(sc);
}
#undef SET_COPY_PARAM
#undef SET_PARAM
#undef GET_COPY_PARAM
#undef GET_PARAM
break;
case SIOCGARLQLT:
user = (void *)ifr->ifr_data;
for (count = 0; count < sizeof(struct arl_quality); count++) {
if (fubyte(user + count) < 0)
return (EFAULT);
}
while (ar->interruptInProgress) ; /* wait */
bcopy(&(aqual), (void *)ifr->ifr_data, sizeof(aqual));
break;
case SIOCGARLSTB:
user = (void *)ifr->ifr_data;
for (count = 0; count < sizeof(struct arl_stats); count++) {
if (fubyte(user + count) < 0)
return (EFAULT);
}
while (ar->lancpuLock) ;
ar->hostcpuLock = 1;
bcopy(&(ar->stat), (void *)ifr->ifr_data, sizeof(struct arl_stats));
ar->hostcpuLock = 0;
break;
default:
error = EINVAL;
}
splx(s);
return (error);
}
/*
* Wait registration
*/
static void
arl_waitreg(ifp)
struct ifnet *ifp;
{
struct arl_softc *sc = ifp->if_softc;
D(("wait reg\n"));
if (ifp->if_flags & IFF_RUNNING) {
if (ARL_CHECKREG(sc)) {
/* wait registration */
D(("wait registration\n"));
ifp->if_watchdog = arl_waitreg;
ifp->if_timer = 2;
} else {
/* registration restored */
D(("registration restored\n"));
ifp->if_timer = 0;
arl_init(sc);
}
}
}
/*
* Handle transmit timeouts.
*/
static void
arl_watchdog(ifp)
struct ifnet *ifp;
{
struct arl_softc *sc = ifp->if_softc;
if (!(ifp->if_flags & IFF_RUNNING))
return;
D(("device timeout\n"));
if (ARL_CHECKREG(sc)) {
/* Lost registratoin */
D(("timeout lost registration\n"));
ifp->if_watchdog = arl_waitreg;
ifp->if_timer = 2;
}
}
/*
* Initialize
*/
static void
arl_init(xsc)
void *xsc;
{
struct arl_softc *sc = xsc;
struct ifnet *ifp = &sc->arpcom.ac_if;
int s;
D(("init\n"));
if (TAILQ_EMPTY(&ifp->if_addrhead))
return;
s = splimp();
if (ARL_CHECKREG(sc))
arl_reset(sc);
arl_enable(sc);
/* set flags */
ifp->if_flags |= IFF_RUNNING;
ifp->if_flags &= ~IFF_OACTIVE;
arl_start(ifp);
splx(s);
D(("init done\n"));
}
/*
* Put buffer into arlan buffer and start transmit
*/
static void
arl_put(sc)
struct arl_softc *sc;
{
struct arl_tx_param txp;
int i;
if (ARL_CHECKREG(sc))
sc->arpcom.ac_if.if_oerrors++;
/* copy dst adr */
for(i = 0; i < 6; i++)
txp.dest[i] = sc->arl_tx[i];
txp.clear = 0;
txp.retries = arcfg.txRetry; /* use default value */
txp.routing = 1;
txp.scrambled = 0;
txp.offset = (intptr_t)ar->txBuffer - (intptr_t)(ar);
txp.length = sc->tx_len - ARLAN_HEADER_SIZE;
#ifdef SEND_ARLAN_HEADER
if (ar->registrationMode != 1)
txp.length = sc->tx_len;
#endif
/* copy from internal buffer to adapter memory */
#ifdef SEND_ARLAN_HEADER
if (ar->registrationMode)
#endif
bcopy(sc->arl_tx + ARLAN_HEADER_SIZE,
ar->txBuffer,
sc->tx_len - ARLAN_HEADER_SIZE);
#ifdef SEND_ARLAN_MODE
else
bcopy(sc->arl_tx, ar->txBuffer, sc->tx_len);
#endif
/* copy command parametr */
bcopy(&txp, ar->commandParameter, 14);
ar->commandByte = 0x85; /* send command */
ARL_CHANNEL(sc);
if (arl_command(sc))
sc->arpcom.ac_if.if_oerrors++;
}
/*
* start output
*/
static void
arl_start(ifp)
struct ifnet *ifp;
{
struct arl_softc *sc;
struct mbuf *m;
struct mbuf *m0 = NULL;
sc = ifp->if_softc;
D(("start\n"));
/* Don't do anything if output is active */
if (ifp->if_flags & IFF_OACTIVE)
return;
/* Dequeue the next datagram */
IF_DEQUEUE(&ifp->if_snd, m0);
/* If there's nothing to send, return. */
if (m0 != NULL) {
ifp->if_flags |= IFF_OACTIVE;
/* Copy the datagram to the buffer. */
sc->tx_len = 0;
for(m = m0; m != NULL; m = m->m_next) {
if (m->m_len == 0)
continue;
bcopy(mtod(m, caddr_t),
sc->arl_tx + sc->tx_len, m->m_len);
sc->tx_len += m->m_len;
}
/* if packet size is less than minimum ethernet frame size,
* pad it with zeroes to that size */
if (sc->tx_len < ETHER_MIN_LEN) {
bzero(sc->arl_tx + sc->tx_len, ETHER_MIN_LEN - sc->tx_len);
sc->tx_len = ETHER_MIN_LEN;
}
/* Give the packet to the bpf, if any */
BPF_MTAP(ifp, m0);
m_freem(m0);
/* Now transmit the datagram */
ifp->if_timer = 1; /* wait 1 sec */
ifp->if_watchdog = arl_watchdog;
arl_put(sc);
}
}
/*
* stop interface
*/
void
arl_stop(sc)
struct arl_softc *sc;
{
struct ifnet *ifp;
int s;
s = splimp();
ifp = &sc->arpcom.ac_if;
ifp->if_timer = 0; /* disable timer */
ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
/* arl_hwreset( unit ); */
sc->rx_len = 0;
sc->tx_len = 0;
/* disable interrupt */
ar->controlRegister = 0;
splx(s);
}
/*
* Pull read data off a interface.
* Len is length of data, with local net header stripped.
*/
static struct mbuf*
arl_get(buf, totlen, off0, ifp)
caddr_t buf;
int totlen;
int off0;
struct ifnet * ifp;
{
struct mbuf *top, **mp, *m;
int off = off0, len;
caddr_t cp = buf;
char *epkt;
cp = buf;
epkt = cp + totlen;
if (off) {
cp += off + 2 * sizeof(u_short);
totlen -= 2 * sizeof(u_short);
}
MGETHDR(m, M_DONTWAIT, MT_DATA);
if (m == 0)
return (0);
m->m_pkthdr.rcvif = ifp;
m->m_pkthdr.len = totlen;
m->m_len = MHLEN;
top = 0;
mp = &top;
while (totlen > 0) {
if (top) {
MGET(m, M_DONTWAIT, MT_DATA);
if (m == 0) {
m_freem(top);
return (0);
}
m->m_len = MLEN;
}
len = min(totlen, epkt - cp);
if (len >= MINCLSIZE) {
MCLGET(m, M_DONTWAIT);
if (m->m_flags & M_EXT)
m->m_len = len = min(len, MCLBYTES);
else
len = m->m_len;
} else {
/*
* * Place initial small packet/header at end of mbuf.
* */
if (len < m->m_len) {
if (top == 0 && len + max_linkhdr <= m->m_len)
m->m_data += max_linkhdr;
m->m_len = len;
} else
len = m->m_len;
}
bcopy(cp, mtod(m, caddr_t), (unsigned)len);
cp += len;
*mp = m;
mp = &m->m_next;
totlen -= len;
if (cp == epkt)
cp = buf;
}
return (top);
}
/* ------------------------------------------------------------------
* * Pass a packet up to the higher levels.
* */
static void
arl_read(sc, buf, len)
struct arl_softc *sc;
caddr_t buf;
int len;
{
register struct ether_header *eh;
struct ifnet *ifp = &sc->arpcom.ac_if;
struct mbuf *m;
eh = (struct ether_header *)buf;
/*
* Check if there's a bpf filter listening on this interface.
* If so, hand off the raw packet to bpf.
*/
if (ifp->if_bpf) {
/*
* Note that the interface cannot be in promiscuous mode if
* there are no bpf listeners. And if el are in promiscuous
* mode, el have to check if this packet is really ours.
*
* This test does not support multicasts.
*/
if ((ifp->if_flags & IFF_PROMISC)
&& bcmp(eh->ether_dhost, sc->arpcom.ac_enaddr,
sizeof(eh->ether_dhost)) != 0
&& bcmp(eh->ether_dhost, BROADCASTADDR,
sizeof(eh->ether_dhost)) != 0)
return;
}
/*
* Pull packet off interface.
*/
#if __FreeBSD_version < 500100
buf += sizeof(struct ether_header);
len -= sizeof(struct ether_header);
#endif
m = arl_get(buf, len, 0, ifp);
if (m == 0)
return;
#if __FreeBSD_version < 500100
ether_input(ifp, eh, m);
#else
(*ifp->if_input)(ifp, m);
#endif
}
/*
* get packet from adapter
*/
static void
arl_recv(sc)
struct arl_softc *sc;
{
sc->rx_len = ar->rxLength;
if (sc->rx_len) {
#ifdef SEND_ARLAN_HEADER
if (ar->registrationMode == 1) {
#endif
bcopy(ar->ultimateDestAddress, sc->arl_rx, 6);
bcopy(ar->rxSrc, (char*)sc->arl_rx + 6, 6);
bcopy((char *)(ar) + ar->rxOffset,
(char *)sc->arl_rx + 12,
sc->rx_len);
sc->rx_len += ARLAN_HEADER_SIZE;
#ifdef SEND_ARLAN_HEADER
} else {
bcopy((char *)(ar) + ar->rxOffset,
(char *)sc->arl_rx, sc->rx_len);
}
#endif
}
}
/*
* Ethernet interface interrupt processor
*/
void
arl_intr(arg)
void *arg;
{
register struct arl_softc *sc = (struct arl_softc *) arg;
struct ifnet *ifp = &sc->arpcom.ac_if;
/* enable interrupt */
ar->controlRegister = (sc->arl_control & ~ARL_CLEAR_INTERRUPT);
ar->controlRegister = (sc->arl_control | ARL_CLEAR_INTERRUPT);
if (ar->txStatusVector) {
if (ar->txStatusVector != 1)
sc->arpcom.ac_if.if_collisions++;
ifp->if_timer = 0; /* disable timer */
ifp->if_flags &= ~IFF_OACTIVE;
arl_start(ifp);
ar->txStatusVector = 0;
/* (sc->quality.txLevel)[ar->txAckQuality & 0x0f]++;
(sc->quality.txQuality)[(ar->txAckQuality & 0xf0) >> 4]++;*/
}
if (ar->rxStatusVector) {
/* (sc->quality.rxLevel)[ar->rxQuality & 0x0f]++;
(sc->quality.rxQuality)[(ar->rxQuality & 0xf0) >> 4]++; */
if (ar->rxStatusVector == 1) { /* it is data frame */
arl_recv(sc);
arl_read(sc, sc->arl_rx, sc->rx_len);
ifp->if_opackets++;
}
ar->rxStatusVector = 0;
ar->commandByte = 0x83;
ar->commandParameter[0] = 1;
ARL_CHANNEL(sc);
if (arl_command(sc))
ifp->if_ierrors++;
}
return;
}
/*
* waiting for resetFlag dropped
*/
int
arl_wait_reset(sc, cnt, delay)
struct arl_softc *sc;
int cnt;
int delay;
{
D(("wait_reset cnt=%d delay=%d\n", cnt, delay));
ar->resetFlag = 1; /* wish reset */
ar->controlRegister = 0; /* unreeze - do it */
while (ar->resetFlag && cnt--)
DELAY(delay);
D(("reset done. %d cycles left\n", cnt));
if (cnt == 0)
printf("arl%d: reset failed\n", sc->arl_unit);
return (cnt == 0);
}
/*
* Allocate an irq resource with the given resource id
*/
int
arl_alloc_irq(dev, rid, flags)
device_t dev;
int rid;
int flags;
{
struct arl_softc *sc = device_get_softc(dev);
struct resource *res;
res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
0ul, ~0ul, 1, (RF_ACTIVE | flags));
if (res) {
sc->irq_rid = rid;
sc->irq_res = res;
return (0);
} else
return (ENOENT);
}
/*
* Allocate an memory resource with the given resource id
*/
int
arl_alloc_memory(dev, rid, size)
device_t dev;
int rid;
int size;
{
struct arl_softc *sc = device_get_softc(dev);
struct resource *res;
res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
0ul, ~0ul, size, RF_ACTIVE);
if (res) {
sc->mem_rid = rid;
sc->mem_res = res;
return (0);
} else
return (ENOENT);
}
/*
* Release all resources
*/
void
arl_release_resources(dev)
device_t dev;
{
struct arl_softc *sc = device_get_softc(dev);
if (sc->mem_res) {
bus_release_resource(dev, SYS_RES_MEMORY,
sc->mem_rid, sc->mem_res);
sc->mem_res = 0;
}
if (sc->irq_res) {
bus_release_resource(dev, SYS_RES_IRQ,
sc->irq_rid, sc->irq_res);
sc->irq_res = 0;
}
}

354
sys/dev/arl/if_arl_isa.c Normal file
View File

@ -0,0 +1,354 @@
/*
* $RISS: if_arl/dev/arl/if_arl_isa.c,v 1.4 2004/01/22 12:08:48 count Exp $
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/socket.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/bus.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/rman.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <net/if_mib.h>
#include <isa/isavar.h>
#include <isa/pnpvar.h>
#include <isa/isa_common.h>
#include <machine/clock.h>
#include <machine/md_var.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <vm/vm_param.h>
#include <dev/arl/if_arlreg.h>
static void arl_isa_identify(driver_t *, device_t);
static int arl_isa_probe (device_t);
static int arl_isa_attach (device_t);
static int arl_isa_detach (device_t);
static char* arl_make_desc (u_int8_t, u_int8_t);
#define ARL_MAX_ATYPE_LEN 10
static struct arl_type {
u_int8_t type;
char* desc;
}
arl_type_list[] = {
{ 0, "450" },
{ 1, "650" },
{ 0xb, "670" },
{ 0xc, "670E" },
{ 0xd, "650E" },
{ 0xe, "440LT" },
{ 0x2e, "655" },
{ 0x6b, "IC2200" },
{ 0, 0 }
};
#define ARL_MAX_RTYPE_LEN 10
struct radio_type {
u_int8_t type;
char* desc;
} radio_type_list [] = {
{ 1, "092/094" },
{ 2, "020" },
{ 3, "092A" },
{ 4, "020B" },
{ 5, "095" },
{ 6, "024" },
{ 7, "025B" },
{ 8, "024B" },
{ 9, "024C" },
{10, "025C" },
{11, "024-1A" },
{12, "025-1A" },
};
static char*
arl_make_desc(hw_type, radio_mod)
u_int8_t hw_type;
u_int8_t radio_mod;
{
static char desc[80];
char atype[ARL_MAX_ATYPE_LEN], rtype[ARL_MAX_RTYPE_LEN];
int i;
*atype = *rtype = 0;
/* arl type */
for(i = 0; arl_type_list[i].desc; i++) {
if (arl_type_list[i].type == hw_type)
break;
}
if (arl_type_list[i].desc)
strncpy(atype, arl_type_list[i].desc, ARL_MAX_ATYPE_LEN);
else
snprintf(atype, ARL_MAX_ATYPE_LEN, "(0x%x)", hw_type);
/* radio type */
for(i = 0; radio_type_list[i].desc; i++)
if (radio_type_list[i].type == radio_mod)
break;
if (radio_type_list[i].desc)
strncpy(rtype, radio_type_list[i].desc, ARL_MAX_RTYPE_LEN);
else
snprintf(rtype, ARL_MAX_RTYPE_LEN, "(0x%x)", radio_mod);
snprintf(desc, 80, "ArLan type %s, radio module %s", atype, rtype);
return desc;
}
#define ARL_ADDR2VEC(addr) (1 << ((addr - ARL_BASE_START) / ARL_BASE_STEP))
static void
arl_isa_identify (driver_t *driver, device_t parent)
{
device_t child;
struct arl_softc *sc;
int chunk, found, i;
u_int16_t free_mem = 0xFFFF;
if (bootverbose)
printf("in identify\n");
/* Try avoid already added devices */
for (i = 0; (child = device_find_child(parent, "arl", i)) != NULL; i++) {
chunk = bus_get_resource_start(child, SYS_RES_MEMORY, 0);
if (bootverbose)
device_printf(child, "found at iomem = 0x%0x\n", chunk);
if (chunk >= ARL_BASE_START && chunk <= ARL_BASE_END)
free_mem ^= ARL_ADDR2VEC(chunk);
}
if (bootverbose)
printf("arl: free mem vector = 0x%x\n", free_mem);
for (chunk = ARL_BASE_START; chunk <= ARL_BASE_END; chunk += ARL_BASE_STEP) {
/* If device 'arl' with this chunk was found early - skip it */
if ( !(free_mem & ARL_ADDR2VEC(chunk)) )
continue;
found = 0;
child = BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, "arl", -1);
device_set_driver(child, driver);
sc = device_get_softc(child);
bzero(sc, sizeof(*sc));
bus_set_resource(child, SYS_RES_MEMORY, sc->mem_rid, chunk,
ARL_BASE_STEP);
if (arl_alloc_memory(child, sc->mem_rid, ARL_BASE_STEP) == 0) {
ar = (struct arl_private *) rman_get_virtual(sc->mem_res);
if (!bcmp(ar->textRegion, ARLAN_SIGN, sizeof(ARLAN_SIGN) - 1))
found++;
}
if (bootverbose)
device_printf(child, "%sfound at 0x%x\n",
!found ? "not " : "", chunk);
arl_release_resources(child);
if (!found) {
bus_delete_resource(child, SYS_RES_MEMORY, sc->mem_rid);
device_delete_child(parent, child);
}
}
}
static int
arl_isa_probe (device_t dev)
{
struct arl_softc *sc = device_get_softc(dev);
int error;
u_char *ptr;
u_int8_t irq;
if (isa_get_vendorid(dev))
return (ENXIO);
if (bootverbose)
device_printf(dev, "in probe\n");
bzero(sc, sizeof(struct arl_softc));
sc->arl_unit = device_get_unit(dev);
error = arl_alloc_memory(dev, 0, ARL_BASE_STEP);
if (error) {
if (bootverbose)
device_printf(dev, "Error allocating memory (%d)\n", error);
return (error);
}
ar = (struct arl_private *) rman_get_virtual(sc->mem_res);
if (bcmp(ar->textRegion, ARLAN_SIGN, sizeof(ARLAN_SIGN) - 1)) {
if (bootverbose)
device_printf(dev, "not found\n");
error = ENOENT;
goto bad;
}
irq = ar->irqLevel;
if (irq == 2)
irq = 9;
error = bus_set_resource(dev, SYS_RES_IRQ, 0, irq, 1);
if (error)
goto bad;
error = arl_alloc_irq(dev, 0, 0);
if (error) {
if (bootverbose)
device_printf(dev, "Can't allocate IRQ %d\n", irq);
goto bad;
}
ar->controlRegister = 1; /* freeze board */
/* Memory test */
for (ptr = (u_char *) ar;
ptr < ((u_char *) ar + ARL_BASE_STEP - 1); ptr++) {
u_char c;
c = *ptr; *ptr = ~(*ptr);
if (*ptr != (u_char)~c) {
device_printf(dev, "board memory failed at [%lx]\n",
rman_get_start(sc->mem_res) + (ptr - (u_char *)ar));
break; /* skip memory test */
}
}
bzero((void *) ar, ARL_BASE_STEP - 1); /* clear board ram */
if (arl_wait_reset(sc, 100, ARDELAY)) {
error = ENXIO;
goto bad;
}
if (ar->diagnosticInfo == 0xFF) {
/* Copy arp to arpcom struct */
bcopy(ar->lanCardNodeId, sc->arpcom.ac_enaddr,
ETHER_ADDR_LEN);
/* copy values to local cache */
bzero(&arcfg, sizeof(arcfg));
bcopy(ar->lanCardNodeId, arcfg.lanCardNodeId,
sizeof(ar->lanCardNodeId));
bcopy(ar->specifiedRouter, arcfg.specifiedRouter,
sizeof(ar->specifiedRouter));
GET_ARL_PARAM(hardwareType);
GET_ARL_PARAM(majorHardwareVersion);
GET_ARL_PARAM(minorHardwareVersion);
GET_ARL_PARAM(radioModule);
GET_ARL_PARAM(channelSet);
if (!arcfg.channelSet)
arcfg.channelSet = ar->defaultChannelSet;
GET_ARL_PARAM(channelNumber);
GET_ARL_PARAM(registrationMode);
GET_ARL_PARAM(spreadingCode);
GET_ARL_PARAM(priority);
GET_ARL_PARAM(receiveMode);
arcfg.txRetry = 0; /* use default */
strncpy(arcfg.name, ar->name, ARLAN_NAME_SIZE);
bcopy(ar->systemId, arcfg.sid, 4 * sizeof(ar->systemId[0]));
device_set_desc_copy(dev, arl_make_desc(ar->hardwareType, ar->radioModule));
error = 0;
} else {
if (bootverbose)
device_printf(dev, "board self-test failed (0x%x)!\n",
ar->diagnosticInfo);
error = ENXIO;
}
bad:
arl_release_resources(dev);
return (error);
}
static int
arl_isa_attach (device_t dev)
{
struct arl_softc *sc = device_get_softc(dev);
int error;
if (bootverbose)
device_printf(dev, "in attach\n");
arl_alloc_memory(dev, sc->mem_rid, ARL_BASE_STEP);
arl_alloc_irq(dev, sc->irq_rid, 0);
error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET,
arl_intr, sc, &sc->irq_handle);
if (error) {
arl_release_resources(dev);
return (error);
}
#if __FreeBSD_version < 502108
device_printf(dev, "Ethernet address %6D\n", sc->arpcom.ac_enaddr, ":");
#endif
return arl_attach(dev);
}
static int
arl_isa_detach(device_t dev)
{
struct arl_softc *sc = device_get_softc(dev);
arl_stop(sc);
/* ifmedia_removeall(&sc->an_ifmedia); */
#if __FreeBSD_version < 500100
ether_ifdetach(&sc->arpcom.ac_if, ETHER_BPF_SUPPORTED);
#else
ether_ifdetach(&sc->arpcom.ac_if);
#endif
bus_teardown_intr(dev, sc->irq_res, sc->irq_handle);
arl_release_resources(dev);
return (0);
}
static device_method_t arl_isa_methods[] = {
/* Device interface */
DEVMETHOD(device_identify, arl_isa_identify),
DEVMETHOD(device_probe, arl_isa_probe),
DEVMETHOD(device_attach, arl_isa_attach),
DEVMETHOD(device_detach, arl_isa_detach),
{ 0, 0 }
};
static driver_t arl_isa_driver = {
"arl",
arl_isa_methods,
sizeof(struct arl_softc)
};
extern devclass_t arl_devclass;
DRIVER_MODULE(arl, isa, arl_isa_driver, arl_devclass, 0, 0);
MODULE_DEPEND(arl, isa, 1, 1, 1);
MODULE_DEPEND(arl, ether, 1, 1, 1);

310
sys/dev/arl/if_arlreg.h Normal file
View File

@ -0,0 +1,310 @@
/*
* $RISS: if_arl/dev/arl/if_arlreg.h,v 1.2 2004/01/22 09:18:13 count Exp $
* $FreeBSD$
*/
#ifndef _IF_ARLREG_H
#define _IF_ARLREG_H
#define ARL_BASE_START 0xC0000
#define ARL_BASE_END 0xDE000
#define ARL_BASE_STEP 0x2000
#define ARLAN_NAME_SIZE 16
#define ARLAN_NAME "ArLan655-SCT"
/*
* Statistics
*/
struct arl_stats {
u_int32_t numDatagramsTransmitted;
u_int32_t numReTransmissions;
u_int32_t numFramesDiscarded;
u_int32_t numDatagramsReceived;
u_int32_t numDuplicateReceivedFrames;
u_int32_t numDatagramsDiscarded;
u_int16_t maxNumReTransmitDatagram;
u_int16_t maxNumReTransmitFrames;
u_int16_t maxNumConsecutiveDuplicateFrames;
u_int32_t numBytesTransmitted;
u_int32_t numBytesReceived;
u_int32_t numCRCErrors;
u_int32_t numLengthErrors;
u_int32_t numAbortErrors;
u_int32_t numTXUnderruns;
u_int32_t numRXOverruns;
u_int32_t numHoldOffs;
u_int32_t numFramesTransmitted;
u_int32_t numFramesReceived;
u_int32_t numReceiveFramesLost;
u_int32_t numRXBufferOverflows;
u_int32_t numFramesDiscardedAddrMismatch;
u_int32_t numFramesDiscardedSIDMismatch;
u_int32_t numPollsTransmistted;
u_int32_t numPollAcknowledges;
u_int32_t numStatusVectorTimeouts;
u_int32_t numNACKReceived;
} __attribute__((packed));
/*
* Arlan private structure in memomory
*/
struct arl_private {
/* Header Signature */
char textRegion[48];
u_int8_t resetFlag;
u_int8_t diagnosticInfo;
u_int16_t diagnosticOffset;
u_int8_t _1[12];
u_int8_t lanCardNodeId[6];
u_int8_t broadcastAddress[6];
u_int8_t hardwareType;
u_int8_t majorHardwareVersion;
u_int8_t minorHardwareVersion;
u_int8_t radioModule;
u_int8_t defaultChannelSet;
u_int8_t _2[47];
/* Control/Status Block - 0x0080 */
u_int8_t interruptInProgress;
u_int8_t cntrlRegImage;
u_int8_t _3[14];
u_int8_t commandByte;
u_int8_t commandParameter[15];
/* Receive Status - 0x00a0 */
u_int8_t rxStatusVector;
u_int8_t rxFrmType;
u_int16_t rxOffset;
u_int16_t rxLength;
u_int8_t rxSrc[6];
u_int8_t rxBroadcastFlag;
u_int8_t rxQuality;
u_int8_t scrambled;
u_int8_t _4[1];
/* Transmit Status - 0x00b0 */
u_int8_t txStatusVector;
u_int8_t txAckQuality;
u_int8_t numRetries;
u_int8_t _5[14];
u_int8_t registeredRouter[6];
u_int8_t backboneRouter[6];
u_int8_t registrationStatus;
u_int8_t configuredStatusFlag;
u_int8_t _6[1];
u_int8_t ultimateDestAddress[6];
u_int8_t immedDestAddress[6];
u_int8_t immedSrcAddress[6];
u_int16_t rxSequenceNumber;
u_int8_t assignedLocaltalkAddress;
u_int8_t _7[27];
/* System Parameter Block */
/* - Driver Parameters (Novell Specific) */
u_int16_t txTimeout;
u_int16_t transportTime;
u_int8_t _8[4];
/* - Configuration Parameters */
u_int8_t irqLevel;
u_int8_t spreadingCode;
u_int8_t channelSet;
u_int8_t channelNumber;
u_int16_t radioNodeId;
u_int8_t _9[2];
u_int8_t scramblingDisable;
u_int8_t radioType;
u_int16_t routerId;
u_int8_t _10[9];
u_int8_t txAttenuation;
u_int8_t systemId[4]; /* on an odd address for a long !!! */
u_int16_t globalChecksum;
u_int8_t _11[4];
u_int16_t maxDatagramSize;
u_int16_t maxFrameSize;
u_int8_t maxRetries;
u_int8_t receiveMode;
u_int8_t priority;
u_int8_t rootOrRepeater;
u_int8_t specifiedRouter[6];
u_int16_t fastPollPeriod;
u_int8_t pollDecay;
u_int8_t fastPollDelay[2];
u_int8_t arlThreshold;
u_int8_t arlDecay;
u_int8_t _12[1];
u_int16_t specRouterTimeout;
u_int8_t _13[5];
/* Scrambled Area */
u_int8_t SID[4];
u_int8_t encryptionKey[12];
u_int8_t _14[2];
u_int8_t waitTime[2];
u_int8_t lParameter[2];
u_int8_t _15[3];
u_int16_t headerSize;
u_int16_t sectionChecksum;
u_int8_t registrationMode;
u_int8_t registrationFill;
u_int16_t pollPeriod;
u_int16_t refreshPeriod;
u_int8_t name[ARLAN_NAME_SIZE];
u_int8_t NID[6];
u_int8_t localTalkAddress;
u_int8_t codeFormat;
u_int8_t SSCode[64];
u_int8_t _16[0x140];
/* Statistics Block - 0x0300 */
u_int8_t hostcpuLock;
u_int8_t lancpuLock;
u_int8_t resetTime[18];
struct arl_stats stat;
u_int8_t _17[0x86];
u_int8_t txBuffer[0x800];
u_int8_t rxBuffer[0x800];
u_int8_t _18[0x0bfd];
u_int8_t resetFlag1;
u_int8_t _19;
u_int8_t controlRegister;
};
/*
* Transmit parametrs
*/
struct arl_tx_param {
u_int16_t offset;
u_int16_t length;
u_int8_t dest[6];
u_int8_t clear;
u_int8_t retries;
u_int8_t routing;
u_int8_t scrambled;
};
#define ARL_HARDWARE_RESET 0x01
#define ARL_CHANNEL_ATTENTION 0x02
#define ARL_INTERRUPT_ENABLE 0x04
#define ARL_CLEAR_INTERRUPT 0x08
/* additions for sys/sockio.h ( socket ioctl parameters for arlan card ) */
#define SIOCGARLQLT _IOWR('i', 70, struct ifreq) /* get QUALITY */
#define SIOCGARLALL _IOWR('i', 71, struct ifreq) /* get ALL */
#define SIOCSARLALL _IOWR('i', 72, struct ifreq) /* set paramter (who_set) */
#define SIOCGARLSTB _IOWR('i', 73, struct ifreq) /* get statistic block */
/*
* Arlan request struct via ioctl
*/
struct arl_cfg_param {
u_char name[ARLAN_NAME_SIZE];
u_int8_t sid[4];
u_int8_t channelSet;
u_int8_t channelNumber;
u_int8_t spreadingCode;
u_int8_t registrationMode;
u_int8_t lanCardNodeId[6];
u_int8_t specifiedRouter[6];
u_int8_t hardwareType;
u_int8_t majorHardwareVersion;
u_int8_t minorHardwareVersion;
u_int8_t radioModule;
u_int8_t priority;
u_int8_t receiveMode;
u_int8_t txRetry;
};
struct arl_req {
u_int32_t what_set;
struct arl_cfg_param cfg;
};
#define ARLAN_MAX_QUALITY 16
struct arl_quality {
u_int8_t macsrc[6];
int rx_quality;
int tx_quality;
};
#define ARLAN_SET_name 0x0001
#define ARLAN_SET_sid 0x0002
#define ARLAN_SET_channelSet 0x0004
#define ARLAN_SET_channelNumber 0x0008
#define ARLAN_SET_spreadingCode 0x0010
#define ARLAN_SET_registrationMode 0x0020
#define ARLAN_SET_lanCardNodeId 0x0040
#define ARLAN_SET_specifiedRouter 0x0080
#define ARLAN_SET_priority 0x0100
#define ARLAN_SET_receiveMode 0x0200
#define ARLAN_SET_txRetry 0x0400
#ifdef _KERNEL
struct arl_softc {
struct arpcom arpcom; /* Ethernet common */
int arl_unit;
struct arl_private * arl_mem; /* arlan data */
struct arl_cfg_param arl_cfg; /* arlan vars in our mem */
u_char arl_control;
int mem_rid; /* resource id for mem */
struct resource* mem_res; /* resource for mem */
int irq_rid; /* resource id for irq */
struct resource* irq_res; /* resource for irq */
void* irq_handle; /* handle for irq handler */
u_char arl_tx[2048];
int tx_len;
u_char arl_rx[2048];
int rx_len;
struct arl_quality quality[ARLAN_MAX_QUALITY];
};
#endif
#define ARLAN_SIGN "TELESYSTEM"
#define ARLAN_HEADER_SIZE 0x0C
#define ar sc->arl_mem
#define arcfg sc->arl_cfg
#define aqual sc->quality
#define ARDELAY 10000
#define ARDELAY1 50000
#define WAIT_RESET(cnt, delay) \
do { \
int i; \
for (i = cnt; i && ar->resetFlag; i--) { \
DELAY(delay); \
} \
} while (0);
#define GET_ARL_PARAM(name) (arcfg.name = ar->name)
#define SET_ARL_PARAM(name) (ar->name = arcfg.name)
#ifdef _KERNEL
void arl_release_resources (device_t);
int arl_alloc_memory (device_t, int, int);
int arl_alloc_irq (device_t, int, int);
int arl_attach (device_t);
int arl_wait_reset (struct arl_softc *, int, int);
void arl_stop (struct arl_softc *);
driver_intr_t arl_intr;
#endif
#endif /* _IF_ARLREG_H */

View File

@ -493,6 +493,7 @@ hint.mse.0.irq="5"
# ar: Arnet SYNC/570i hdlc sync 2/4 port V.35/X.21 serial driver
# (requires sppp)
# arl: Aironet Arlan 655 wireless adapters.
# ath: Atheros a/b/g WiFi adapters (requires ath_hal and wlan)
# ctau: Cronyx/Tau sync dual port V.35/RS-232/RS-530/RS-449/X.21/G.703/E1
# serial adaptor (requires sppp (default), or NETGRAPH if
@ -521,6 +522,10 @@ hint.ar.0.at="isa"
hint.ar.0.port="0x300"
hint.ar.0.irq="10"
hint.ar.0.maddr="0xd0000"
device arl
hint.arl.0.at="isa"
hint.arl.0.irq="9"
hint.arl.0.maddr="0xd0000"
device ctau
hint.ctau.0.at="isa"
hint.ctau.0.port="0x240"

View File

@ -20,6 +20,7 @@ SUBDIR= ${_3dfx} \
${_aout} \
${_apm} \
${_ar} \
${_arl} \
${_arcnet} \
${_asr} \
ath \
@ -284,6 +285,7 @@ _amd= amd
_aout= aout
_apm= apm
_ar= ar
_arl= arl
_arcnet= arcnet
_ath_hal= ath_hal
_awi= awi

10
sys/modules/arl/Makefile Normal file
View File

@ -0,0 +1,10 @@
# $RISS: if_arl/modules/if_arl/Makefile,v 1.3 2003/01/13 08:05:29 frol Exp $
# $FreeBSD$
.PATH: ${.CURDIR}/../../dev/arl
KMOD= if_arl
SRCS= if_arl.c if_arl_isa.c device_if.h bus_if.h isa_if.h
CFLAGS= -I${.CURDIR}/../..
.include <bsd.kmod.mk>

View File

@ -10,6 +10,7 @@ SUBDIR= ac \
ancontrol \
${_apm} \
${_apmd} \
${_arlconfig} \
arp \
${_asf} \
${_atm} \
@ -241,6 +242,7 @@ _acpi= acpi
.endif
_apm= apm
_apmd= apmd
_arlconfig= arlconfig
_asf= asf
.if !defined(NO_BLUETOOTH)
_bluetooth= bluetooth

View File

@ -0,0 +1,11 @@
#
# $RISS: if_arl/arlconfig/Makefile,v 1.5 2003/01/13 08:05:29 frol Exp $
# $FreeBSD$
#
PROG= arlconfig
SRCS= arlconfig.c
CFLAGS= -I${.CURDIR}/../../sys
MAN= arlconfig.8
.include <bsd.prog.mk>

View File

@ -0,0 +1,236 @@
.\" Copyright (c) 1997, 1998, 1999
.\" Bill Paul <wpaul@ee.columbia.edu> 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.
.\" 3. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed by Bill Paul.
.\" 4. Neither the name of the author nor the names of any co-contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul OR THE VOICES IN HIS HEAD
.\" 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.
.\"
.\" $FreeBSD$
.\"
.Dd August 25,2003
.Dt ARLCONTROL 8
.Os
.Sh NAME
.Nm arlconfig
.Nd configure Aironet Arlan 655 device
.Sh SYNOPSIS
.Nm
.Ar iface Cm name Ar name
.Nm
.Ar iface Cm sid Ar SID
.Nm
.Ar iface Cm country Ar country ( Cm 9-15 )
.Nm
.Ar iface Cm channel Ar channel
(depend on
.Ar country )
.Nm
.Ar iface Cm freq Ar freq ( Cm 2412, 2427, 2442, 2457, 2465 )
.Nm
.Ar iface Cm spread Ar spread Cm ( 354, 500, 1000, 2000 )
.Nm
.Ar iface Cm bitrate Ar bitrate ( Cm 0-4)
.Nm
.Ar iface Cm mode Ar mode ( Cm 640 | 655 )
.Nm
.Ar iface Cm priority Ar priority ( Cm normal, high, highest )
.Nm
.Ar iface Cm stat
.Nm
.Ar iface Cm quality Ar seconds [ Cm count Ar <count> ]
.Sh DESCRIPTION
The
.Nm
utility controls the operation of Aironet Arlan 655 wireless networking
devices via the
.Xr arl 4
driver.
Most of the parameters that can be changed are related to the
Aironet protocol which the Aironet Arlan 655 card implements.
The parameters include
the station name, the station operation mode
.Ar (point to point or infrastructure) ,
and the network name of a service
set to join.
The
.Nm
utility can also be used to view the current NIC status, configuration
and to dump out the values of the card's statistics counters.
.Pp
The
.Ar iface
argument given to
.Nm
should be the logical interface name associated with the Aironet Arlan 655
device
.Li ( arl0 , arl1 ,
etc.) and must be specified.
.Sh OPTIONS
The options are as follows:
.Bl -tag -width indent
.It Cm name Ar name
Set
.Ar Device Name .
This
parameter is used to establish a 15-byte ASCII name
for the Arlan 655 Client Card. The
.Ar Device Name
is optional and may be left blank.
.Pp
If you choose to assign a name, while operating in
.Ar TMA
mode, the name will appear in the Arlan Access Point's Registration Table.
Duplicate names are allowed.
.It Cm sid Ar SID
Set
.Ar System Identifier.
The System Identifier
.Ar (SID)
is a 4-byte, hexadecimal digit value that
is attached to each packet sent out over the radio. Establishing a
.Ar SID
allows you to group nodes into a microcelluar network and exclude
those nodes that are whiting radio range on other networks.
.Pp
The
.Ar SID
value must be an even number, cannot exceed ts and must start with
00 or 02. Examples of valid SID values are: 00000102, 0200AA14, 00013A18,
007F6380. The
.Ar default
SID is
.Cm 00000002 .
.Pp
Since nodes will only receive packets from other nodes with a matching SID,
you must make sure that the Arlan 655 Client Card is set the same SID as
other nodes on your network.
.It Cm mode Ar mode ( Cm 640 | 655 )
Use
.Ar operating mode
parameter to specify whether you are operating in
.Ar TMA , Non-TMA
or
.Ar PSP
mode. The
.Ar default
setting is
.Cm TMA
mode.
.Bl -column ".Em Mode" ".Em Regmode" -offset indent indent
.Em "Mode Registration mode"
.It 640 Ta TMA
.It 655 Ta Non-TMA
.It PSP Ta Power save mode
.El
.!!!
.It Cm country Ar country ( Cm 9-15 )
.It Cm channel Ar channel
.It Cm freq Ar freq ( Cm 2412, 2427, 2442, 2457, 2465 )
Chose
.Ar country , channel , freq
parameters that depend on the
.Ar contry
according to the following table:
.Bl -column ".Em Country" ".Em Channel" ".Em MHz" -offset indent indent
.Em "Country Ch_Set MHz"
.It "North America" Ta 9 Ta "2412, 2427, 2442, 2457, 2465"
.It "U.S.A " Ta 9 Ta "2412, 2427, 2442, 2457, 2465"
.It "Canada " Ta 9 Ta "2412, 2427, 2442, 2457, 2465"
.It "Mexico " Ta 9 Ta "2412, 2427, 2442, 2457, 2465"
.IT "New Zealand " Ta 9 Ta "2412, 2427, 2442, 2457, 2465"
.It "E.T.S.I " Ta 10 Ta "2412, 2427, 2442, 2457, 2472"
.It "Japan " Ta 11 Ta "2484"
.It "France " Ta 12 Ta "2457, 2465, 2475"
.It "Australia " Ta 13 Ta "2411, 2425, 2439"
.It "Germany " Ta 14 Ta "2427, 2442, 2457"
.It "U.K.(MPT1349)" Ta 15 Ta "2460"
.It "U.K. " Ta 15 Ta "2460"
.It "Spain " Ta 15 Ta "2460"
.El
.It Cm bitrate Ar bitrate ( Cm 0-4)
.It Cm spread Ar spread Cm ( 354, 500, 1000, 2000 )
Set device operating bitrate or spread.
.Bl -column ".Em Rate" ".Em Spread" ".Em kb/s" -offset indent indent
.Em "Rate Spread kb/s"
.It 0 Ta - Ta Auto
.It 1 Ta 354 Ta 354
.It 2 Ta 512 Ta 512
.It 3 Ta 1000 Ta 1000
.It 4 Ta 2000 Ta 2000
.El
.It Cm priority Ar priority ( Cm normal, high, highest )
Use the
.Ar priority
parameter to set the priority of the Atlan 655 Radio Media Access Control
the values are
.Cm normal , high
or
.Cm higest .
The higher the priority set, the more likely this unit wil be first
to successfully transmit a packet when multiple units are trying
to transmit at the same time.
.Pp
The percentage of units on your network that you set to other than
.Dq normal
should be kept small - 10 percent or less.
.It Cm stat
Print internal Arlan 655 statistics block.
.It Cm quality Ar seconds [ Cm count Ar <count> ]
Perform link quality test during
.Ar seconds
transmitting
.Ar count
packets.
Currently is broken.
.El
.Sh EXAMPLES
.Bd -literal -offset indent
alrlconfig arl0 name NODE1 sid 4 freq 2442
arlconfig arl0 quality 10 seconds
arlconfig arl0 status
.Pp
You can configure Arlan 655 card from /etc/start_if.arl0. For example:
.Pp
#!/bin/sh
/sbin/arlconfig arl0 sid 0x000002 freq 2412 spread 2000 mode 640
.Sh SEE ALSO
.Xr arl 4 ,
.Xr "Arlan 655 ISA Wireless LAN Client Card User Guide" .
.Sh HISTORY
The
.Nm
utility first appeared in
.Fx 5.3 .
.Sh BUGS
Aironet Arlan 640 bridges and Arlan 630 access points don't understand
country codes other than 9.
.Sh AUTHORS
The
.Nm
utility was written by
.Aq ran@styx.aic.net .
Manpage was written by
.An Yuri Kurenkov Aq y.kurenkov@init.ru .

View File

@ -0,0 +1,612 @@
/*
* $RISS: if_arl/arlconfig/arlconfig.c,v 1.3 2003/01/13 07:23:25 count Exp $
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <limits.h>
#include <dev/arl/if_arlreg.h>
struct freq_list {
short fr_no;
char* name;
};
struct freq_list freq_list_1[] = {
{ 0, "908.50" },
{ 1, "910.06" },
{ 2, "915.52" },
{ 3, "915.00" },
{ 4, "917.83" },
{ 5, "919.22" },
{ 6, "922.26" },
{ 7, "911.45" },
{ 8, "915.00" },
{ 9, "918.55" },
{ 10,"915.00" },
{ 11,"915.00" }
};
struct freq_list freq_list_6[] = {
{ 0, "920.31" },
{ 1, "920.33" },
{ 2, "921.55" },
{ 3, "922.17" },
{ 4, "922.79" },
{ 5, "921.46" },
{ 6, "921.55" }
};
struct freq_list freq_list_9[] = {
{ 0, "Bad" },
{ 1, "2412" },
{ 2, "2427" },
{ 3, "2442" },
{ 4, "2457" },
{ 5, "2465" }
};
struct freq_list freq_list_10[] = {
{ 0, "Bad" },
{ 1, "2412" },
{ 2, "2427" },
{ 3, "2442" },
{ 4, "2457" },
{ 5, "2472" }
};
struct freq_list freq_list_11[] = {
{ 0, "Bad" },
{ 1, "2484" }
};
struct freq_list freq_list_12[] = {
{ 0, "Bad" },
{ 1, "2457" },
{ 2, "2465" },
{ 3, "2472" },
};
struct freq_list freq_list_13[] = {
{ 0, "Bad" },
{ 1, "2411" },
{ 2, "2425" },
{ 3, "2439" }
};
struct freq_list freq_list_14[] = {
{ 0, "Bad" },
{ 1, "2427" },
{ 2, "2442" },
{ 3, "2457" }
};
struct freq_list freq_list_15[] = {
{ 0, "Bad" },
{ 1, "2460" }
};
#define MAXFREQ(a) sizeof(a)/sizeof(struct freq_list)
struct rate_list {
short rate_no;
char* name;
};
struct rate_list rate_list_2400[] = {
{ 0, "Bad" },
{ 1, "354" },
{ 2, "512" },
{ 3, "1000" },
{ 4, "2000" }
};
struct radio_type {
int id;
char* name;
} radio_type_list [] = {
{ 0, "No EPROM" },
{ 1, "092/094" },
{ 2, "020" },
{ 3, "092A" },
{ 4, "020B" },
{ 5, "095" },
{ 6, "024" },
{ 7, "025B" },
{ 8, "024B" },
{ 9, "024C" },
{10, "025C" },
{11, "024-1A" },
{12, "025-1A" },
{13, "Other" }
};
static struct ch_list {
short chan;
char* fr;
char* country;
struct rate_list* rate;
struct freq_list* freq;
int max_freq;
} CHSET[] = {
{ 0, 0, 0, 0, 0, 0 },
{ 1, "900 Mhz", "Canada, U.S.A., Mexico", 0, freq_list_1, MAXFREQ(freq_list_1) },
{ 2, 0, 0, 0, 0, 0 },
{ 3, 0, 0, 0, 0, 0 },
{ 4, 0, 0, 0, 0, 0 },
{ 5, 0, 0, 0, 0, 0 },
{ 6, "900 Mhz", "Australia", 0, freq_list_6, MAXFREQ(freq_list_6) },
{ 7, 0, 0, 0, 0, 0 },
{ 8, 0, 0, 0, 0, 0 },
{ 9, "2400 Mhz", "North America", rate_list_2400, freq_list_9, MAXFREQ(freq_list_9) },
{ 10, "2400 Mhz", "E.T.S.I", rate_list_2400, freq_list_10, MAXFREQ(freq_list_10) },
{ 11, "2400 Mhz", "Japan", rate_list_2400, freq_list_11, MAXFREQ(freq_list_11) },
{ 12, "2400 Mhz", "France", rate_list_2400, freq_list_12, MAXFREQ(freq_list_12) },
{ 13, "2400 Mhz", "Australia", rate_list_2400, freq_list_13, MAXFREQ(freq_list_13) },
{ 14, "2400 Mhz", "Germany", rate_list_2400, freq_list_14, MAXFREQ(freq_list_14) },
{ 15, "2400 Mhz", "U.K.(MPT1349),Spain", rate_list_2400, freq_list_15, MAXFREQ(freq_list_15) }
};
char* registrationMode[] = {
"NON-TMA",
"TMA",
"PSP"
};
char* priorityList[] = {
"normal",
"high",
"highest"
};
void
usage()
{
const char *progname = getprogname();
#if 0
fprintf(stderr, "\nArlan configuration utility.\n\n");
#endif
fprintf(stderr, "Usage: %s <ifname> [<param> <value> ...]\n", progname);
fprintf(stderr, "\t<ifname>\tArlan interface name.\n");
fprintf(stderr, "\t<param>\t\tParameter name (see below).\n");
fprintf(stderr, "\t<value>\t\tNew value for parameter.\n");
fprintf(stderr, "Parameter name:\t\tValue:\n");
fprintf(stderr, "\tname\t\tset Name.\n");
fprintf(stderr, "\tsid\t\tset System ID.\n");
fprintf(stderr, "\tfreq\t\tset Frequency Channel (2412, 2427, 2442, 2457, 2465)\n");
fprintf(stderr, "\tspread\t\tset Bitrate (354, 500, 1000, 2000)\n");
fprintf(stderr, "\tmode\t\tset Mode (640, 655, PSP).\n");
fprintf(stderr, "\tcountry\t\tset Country (9-15)\n");
fprintf(stderr, "\tchannel\t\tset Channel (depended on country)\n");
fprintf(stderr, "\tbitrate\t\tset Bitrate (0-4)\n");
fprintf(stderr, "\tpriority\tset Priority (normal, high, highest)\n");
#if 0
fprintf(stderr, "\tparent\t\tset Arlan parent's MAC.\n");
fprintf(stderr, "\taddr\t\tset Arlan MAC.\n");
#endif
fprintf(stderr, "or: %s <ifname> stat\n", progname);
fprintf(stderr, "\tprint internal arlan statistics block\n");
fprintf(stderr, "or: %s <ifname> quality <seconds> [count <count>]\n",
progname);
fprintf(stderr, "\tprint receive packet level and quality with interval\n");
exit(0);
}
void
print_al(struct arl_cfg_param *arl_io)
{
printf("Arlan-655(IC2000) type 0x%x v%d.%d, radio module type %s\n",
arl_io->hardwareType,
arl_io->majorHardwareVersion,
arl_io->minorHardwareVersion,
(arl_io->radioModule < 13) ?
radio_type_list[arl_io->radioModule].name : "Unknown" );
printf("\tname %s, sid 0x%06x, mode %s, num tx retry %d\n",
arl_io->name,
*(int *)arl_io->sid,
(arl_io->registrationMode < 3) ?
registrationMode[arl_io->registrationMode]:"Unknown",
arl_io->txRetry );
printf("\tchannel set %d, %s, %s\n",
arl_io->channelSet,
CHSET[arl_io->channelSet].fr,
CHSET[arl_io->channelSet].country);
printf("\tfrequency %s Mhz, bitrate %s kb/s, priority %s, receive mode %d\n",
(CHSET[arl_io->channelSet].freq &&
CHSET[arl_io->channelSet].max_freq > arl_io->channelNumber) ?
CHSET[arl_io->channelSet].freq[arl_io->channelNumber].name :
"unknown",
(CHSET[arl_io->channelSet].rate) ?
CHSET[arl_io->channelSet].rate[arl_io->spreadingCode].name :
"unknown",
arl_io->priority <= 2 ?
priorityList[arl_io->priority] : "unknown",
arl_io->receiveMode);
printf("\tether %s",
(char *)ether_ntoa((struct ether_addr *)arl_io->lanCardNodeId));
printf(" registered to %s\n",
(char *)ether_ntoa((struct ether_addr *)arl_io->specifiedRouter));
}
void
print_stb( struct arl_stats stb )
{
printf("Arlan internal statistics block\n\n");
printf("%8u\tdatagrams transmitted\n",
stb.numDatagramsTransmitted);
printf("%8u\tre-transmitted\n",
stb.numReTransmissions);
printf("%8u\tframes discarded internally in a router\n",
stb.numFramesDiscarded);
printf("%8u\tdatagrams received\n",
stb.numDatagramsReceived);
printf("%8u\tduplicate received frame\n",
stb.numDuplicateReceivedFrames);
printf("%8u\tdatagrams discarded due to unavailable mail box buffer\n",
stb.numDatagramsDiscarded);
printf("%8d\tmaximum of re-transmissions datagram\n",
stb.maxNumReTransmitDatagram);
printf("%8d\tmaximum of re-transmissions frame\n",
stb.maxNumReTransmitFrames);
printf("%8d\tmaximum of consecutive duplicate received frames\n",
stb.maxNumConsecutiveDuplicateFrames);
printf("%8u\tbytes transmitted\n",
stb.numBytesTransmitted);
printf("%8u\tbytes received\n",
stb.numBytesReceived);
printf("%8u\tCRC errors\n",
stb.numCRCErrors);
printf("%8u\tlength errors\n",
stb.numLengthErrors);
printf("%8u\tabort errors\n",
stb.numAbortErrors);
printf("%8u\tTX underuns\n",
stb.numTXUnderruns);
printf("%8u\tRX overruns\n",
stb.numRXOverruns);
printf("%8u\tHold Offs (channel tested busy, tx delayed)\n",
stb.numHoldOffs);
printf("%8u\tframes transmitted\n",
stb.numFramesTransmitted);
printf("%8u\tframes received\n",
stb.numFramesReceived);
printf("%8u\treceive frames lost due unavailable buffer\n",
stb.numReceiveFramesLost);
printf("%8u\tRX buffer overflows \n",
stb.numRXBufferOverflows);
printf("%8u\tframes discarded due to Address mismatch\n",
stb.numFramesDiscardedAddrMismatch);
printf("%8u\tframes discarded due to SID mismatch\n",
stb.numFramesDiscardedSIDMismatch);
printf("%8u\tpolls transmitted\n",
stb.numPollsTransmistted);
printf("%8u\tpoll acknowledges received\n",
stb.numPollAcknowledges);
printf("%8u\tstatus vector timeout\n",
stb.numStatusVectorTimeouts);
printf("%8u\tNACK packets received\n",
stb.numNACKReceived);
}
#ifdef ARL_QUALITY
void
print_qlt(struct arl_quality qlt, int count)
{
int i, s;
int v, v1;
time_t t;
int minLevel, maxLevel, avgLevel;
int minQuality, maxQuality, avgQuality;
t = time(NULL);
localtime(&t);
printf("#%d Current date-time: %s", count, ctime(&t));
printf(" %-39s %s\n","Receive Level","Receive Quality");
printf(
" pkts 0.......10 11............100 > pkts 0.......10 11............100 >\n"\
" -----+----------+-----------------+--- -----+----------+-----------------+---\n");
minLevel = 16;
maxLevel = 0;
avgLevel = 0;
minQuality = 16;
maxQuality = 0;
avgQuality = 0;
for (i = 0, s = 0; i < ARLAN_MAX_QUALITY; i++) {
v = qlt.rxLevel[i];
if (v) {
if (i < minLevel)
minLevel = i;
if (i > maxLevel)
maxLevel = i;
avgLevel += v*i;
printf(" %-4d %x", v, i);
} else
printf(" o %x", i);
s += v;
if (v < 10)
;
else if (v < 100)
v = 10 + ((v-10) * 20) / 90;
else if (v < 1000)
v = 31;
else
v = 32;
v1 = v;
while (v) {
printf("*");
v--;
}
v = 33 - v1;
while (v) {
printf(" ");
v--;
}
v = qlt.rxQuality[i];
if (v) {
if (i < minQuality)
minQuality = i;
if (i > maxQuality)
maxQuality = i;
avgQuality += v*i;
printf("%-4d %x", v, i);
} else
printf("o %x", i);
if (v < 10)
;
else if (v < 100)
v = 10 + ((v-10) * 20) / 90;
else if (v < 1000)
v = 31;
else
v = 32;
}
v1 = v;
while (v) {
printf("*");
v--;
}
printf("\n");
}
printf(" -----+----------+-----------------+--- -----+----------+-----------------+---\n");
if (minLevel > 15)
minLevel = 0;
if (minQuality > 15)
minQuality = 0;
printf("\tPackets count %-6d\n", s);
if (!s)
s++;
printf("\tLevel min %d/avg %d/max %d\n",
minLevel, avgLevel/s, maxLevel);
printf("\tQuality min %d/avg %d/max %d\n",
minQuality, avgQuality/s, maxQuality);
}
#endif /* ARL_QUALITY */
int
main(int argc, char *argv[])
{
struct ifreq ifr;
struct arl_req arl_io;
struct ether_addr *ea;
struct arl_stats stb;
/*static arl_quality qlt;*/
int sd, argind, val = -1;
long val2;
char *param, *value, *value2;
/*int end_count, i;*/
if (argc < 2)
usage();
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;
bzero(&arl_io, sizeof(arl_io));
ifr.ifr_data = (caddr_t)&arl_io;
if (argc == 2) {
if (ioctl(sd, SIOCGARLALL, (caddr_t)&ifr))
err(1,"Get ALL");
print_al(&arl_io.cfg);
exit(0);
}
if (argc == 3) {
if (!strcasecmp(argv[2], "stat")) {
strncpy(ifr.ifr_name, argv[1], sizeof(ifr.ifr_name));
ifr.ifr_addr.sa_family = AF_INET;
ifr.ifr_data = (caddr_t)&stb;
if (ioctl(sd, SIOCGARLSTB, (caddr_t)&ifr))
err(1,"Get STB");
print_stb(stb);
exit(0);
}
#ifdef ARL_QUALITY
if (!strcasecmp(argv[2],"quality") && argc > 3) {
val = atoi(argv[3]);
if (val < 0 || val >= 3601)
err(1,"Bad time range");
end_count = 0;
if (argc > 5 && !strcasecmp(argv[4], "count"))
end_count = atoi(argv[5]);
printf("\n");
i = 0;
while (i < end_count || !end_count) { /* loop */
if (i++)
sleep(val);
strncpy(ifr.ifr_name,
argv[1], sizeof(ifr.ifr_name));
ifr.ifr_addr.sa_family = AF_INET;
ifr.ifr_data = (caddr_t)&qlt;
if (ioctl(sd, SIOCGARLQLT, (caddr_t)&ifr))
err(1,"Get QLT");
print_qlt(qlt, i);
}
exit(0);
}
#endif /* ARL_QUALITY */
}
arl_io.what_set = 0;
for (argind = 2; argind < argc; argind += 2) {
param = argv[argind];
value = argv[argind+1];
val = -1;
if (!strcasecmp(param, "name")) {
bzero(arl_io.cfg.name, 16);
strncpy(arl_io.cfg.name, value, 16);
arl_io.what_set |= ARLAN_SET_name;
}
if (!strcasecmp(param, "sid")) {
val2 = strtol(value, &value2, 0);
if (val2 < 0 || val2 > 0xffffff || val2 % 2 ||
value == value2)
err(1, "Bad SID - %s", value);
bcopy(&val2, arl_io.cfg.sid, 4);
arl_io.what_set |= ARLAN_SET_sid;
}
if (!strcasecmp (param, "freq")) {
if (!strcmp(value, "2412"))
val = 1;
else if (!strcmp(value, "2427"))
val = 2;
else if (!strcmp(value, "2442"))
val = 3;
else if (!strcmp(value, "2457"))
val = 4;
else if (!strcmp(value, "2465"))
val = 5;
if (val == -1)
err(1, "Bad Frequency - %s", value);
arl_io.cfg.channelNumber = val;
arl_io.what_set |= ARLAN_SET_channelNumber;
}
if (!strcasecmp(param, "spread")) {
if (!strcmp(value, "354"))
val = 1;
else if (!strcmp(value, "500"))
val = 2;
else if (!strcmp(value, "1000"))
val = 3;
else if (!strcmp(value, "2000"))
val = 4;
if (val == -1)
err (1, "Bad Bitrate - %s", value);
arl_io.cfg.spreadingCode = val;
arl_io.what_set |= ARLAN_SET_spreadingCode;
}
if (!strcasecmp(param, "priority")) {
if (!strcasecmp(value, "normal"))
val = 0;
else if (!strcasecmp(value, "high"))
val = 1;
else if (!strcasecmp(value, "highest"))
val = 2;
if (val == -1)
err( 1, "Bad priority - %s", value);
arl_io.cfg.priority = val;
arl_io.what_set |= ARLAN_SET_priority;
}
if (!strcasecmp(param, "mode")) {
if (!strcmp(value, "655"))
val = 0;
else if (!strcmp(value, "640"))
val = 1;
else if (!strcasecmp (value, "PSP"))
val = 2;
if (val == -1)
err (1, "Bad Mode - %s", value);
arl_io.cfg.registrationMode = val;
arl_io.what_set |= ARLAN_SET_registrationMode;
}
if (!strcasecmp(param, "parent")) {
if ((ea = (struct ether_addr*) ether_aton(value)) == NULL)
err (1, "Bad parent's MAC - %s", value);
for (val = 0; val < 6; val++) {
arl_io.cfg.specifiedRouter[val] =
(int) ea->octet[val];
}
arl_io.what_set |= ARLAN_SET_specifiedRouter;
}
if (!strcasecmp(param, "addr")) {
if ((ea = (struct ether_addr*) ether_aton(value)) == NULL)
err (1, "Bad MAC - %s", value);
for (val = 0; val < 6; val++) {
arl_io.cfg.lanCardNodeId[val] =
(int) ea->octet[val];
}
arl_io.what_set |= ARLAN_SET_lanCardNodeId;
}
if (!strcasecmp(param, "country")) {
arl_io.cfg.channelSet = atoi(value);
arl_io.what_set |= ARLAN_SET_channelSet;
}
if (!strcasecmp(param, "channel")) {
arl_io.cfg.channelNumber = atoi(value);
arl_io.what_set |= ARLAN_SET_channelNumber;
}
if (!strcasecmp(param, "bitrate")) {
arl_io.cfg.spreadingCode = atoi(value);
arl_io.what_set |= ARLAN_SET_spreadingCode;
}
if (!strcasecmp(param, "receive")) {
arl_io.cfg.receiveMode = atoi(value);
arl_io.what_set |= ARLAN_SET_receiveMode;
}
if (!strcasecmp(param, "txretry")) {
arl_io.cfg.txRetry = atoi(value);
arl_io.what_set |= ARLAN_SET_txRetry;
}
}
if (arl_io.what_set) {
if (ioctl(sd, SIOCSARLALL, (caddr_t)&ifr))
err (1, "Set ALL" );
if (ioctl(sd, SIOCGARLALL, (caddr_t)&ifr))
err (1, "Get ALL");
print_al(&arl_io.cfg);
}
return 0;
}

View File

@ -0,0 +1,236 @@
.\" Copyright (c) 1997, 1998, 1999
.\" Bill Paul <wpaul@ee.columbia.edu> 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.
.\" 3. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed by Bill Paul.
.\" 4. Neither the name of the author nor the names of any co-contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul OR THE VOICES IN HIS HEAD
.\" 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.
.\"
.\" $FreeBSD$
.\"
.Dd August 25,2003
.Dt ARLCONTROL 8
.Os
.Sh NAME
.Nm arlconfig
.Nd configure Aironet Arlan 655 device
.Sh SYNOPSIS
.Nm
.Ar iface Cm name Ar name
.Nm
.Ar iface Cm sid Ar SID
.Nm
.Ar iface Cm country Ar country ( Cm 9-15 )
.Nm
.Ar iface Cm channel Ar channel
(depend on
.Ar country )
.Nm
.Ar iface Cm freq Ar freq ( Cm 2412, 2427, 2442, 2457, 2465 )
.Nm
.Ar iface Cm spread Ar spread Cm ( 354, 500, 1000, 2000 )
.Nm
.Ar iface Cm bitrate Ar bitrate ( Cm 0-4)
.Nm
.Ar iface Cm mode Ar mode ( Cm 640 | 655 )
.Nm
.Ar iface Cm priority Ar priority ( Cm normal, high, highest )
.Nm
.Ar iface Cm stat
.Nm
.Ar iface Cm quality Ar seconds [ Cm count Ar <count> ]
.Sh DESCRIPTION
The
.Nm
utility controls the operation of Aironet Arlan 655 wireless networking
devices via the
.Xr arl 4
driver.
Most of the parameters that can be changed are related to the
Aironet protocol which the Aironet Arlan 655 card implements.
The parameters include
the station name, the station operation mode
.Ar (point to point or infrastructure) ,
and the network name of a service
set to join.
The
.Nm
utility can also be used to view the current NIC status, configuration
and to dump out the values of the card's statistics counters.
.Pp
The
.Ar iface
argument given to
.Nm
should be the logical interface name associated with the Aironet Arlan 655
device
.Li ( arl0 , arl1 ,
etc.) and must be specified.
.Sh OPTIONS
The options are as follows:
.Bl -tag -width indent
.It Cm name Ar name
Set
.Ar Device Name .
This
parameter is used to establish a 15-byte ASCII name
for the Arlan 655 Client Card. The
.Ar Device Name
is optional and may be left blank.
.Pp
If you choose to assign a name, while operating in
.Ar TMA
mode, the name will appear in the Arlan Access Point's Registration Table.
Duplicate names are allowed.
.It Cm sid Ar SID
Set
.Ar System Identifier.
The System Identifier
.Ar (SID)
is a 4-byte, hexadecimal digit value that
is attached to each packet sent out over the radio. Establishing a
.Ar SID
allows you to group nodes into a microcelluar network and exclude
those nodes that are whiting radio range on other networks.
.Pp
The
.Ar SID
value must be an even number, cannot exceed ts and must start with
00 or 02. Examples of valid SID values are: 00000102, 0200AA14, 00013A18,
007F6380. The
.Ar default
SID is
.Cm 00000002 .
.Pp
Since nodes will only receive packets from other nodes with a matching SID,
you must make sure that the Arlan 655 Client Card is set the same SID as
other nodes on your network.
.It Cm mode Ar mode ( Cm 640 | 655 )
Use
.Ar operating mode
parameter to specify whether you are operating in
.Ar TMA , Non-TMA
or
.Ar PSP
mode. The
.Ar default
setting is
.Cm TMA
mode.
.Bl -column ".Em Mode" ".Em Regmode" -offset indent indent
.Em "Mode Registration mode"
.It 640 Ta TMA
.It 655 Ta Non-TMA
.It PSP Ta Power save mode
.El
.!!!
.It Cm country Ar country ( Cm 9-15 )
.It Cm channel Ar channel
.It Cm freq Ar freq ( Cm 2412, 2427, 2442, 2457, 2465 )
Chose
.Ar country , channel , freq
parameters that depend on the
.Ar contry
according to the following table:
.Bl -column ".Em Country" ".Em Channel" ".Em MHz" -offset indent indent
.Em "Country Ch_Set MHz"
.It "North America" Ta 9 Ta "2412, 2427, 2442, 2457, 2465"
.It "U.S.A " Ta 9 Ta "2412, 2427, 2442, 2457, 2465"
.It "Canada " Ta 9 Ta "2412, 2427, 2442, 2457, 2465"
.It "Mexico " Ta 9 Ta "2412, 2427, 2442, 2457, 2465"
.IT "New Zealand " Ta 9 Ta "2412, 2427, 2442, 2457, 2465"
.It "E.T.S.I " Ta 10 Ta "2412, 2427, 2442, 2457, 2472"
.It "Japan " Ta 11 Ta "2484"
.It "France " Ta 12 Ta "2457, 2465, 2475"
.It "Australia " Ta 13 Ta "2411, 2425, 2439"
.It "Germany " Ta 14 Ta "2427, 2442, 2457"
.It "U.K.(MPT1349)" Ta 15 Ta "2460"
.It "U.K. " Ta 15 Ta "2460"
.It "Spain " Ta 15 Ta "2460"
.El
.It Cm bitrate Ar bitrate ( Cm 0-4)
.It Cm spread Ar spread Cm ( 354, 500, 1000, 2000 )
Set device operating bitrate or spread.
.Bl -column ".Em Rate" ".Em Spread" ".Em kb/s" -offset indent indent
.Em "Rate Spread kb/s"
.It 0 Ta - Ta Auto
.It 1 Ta 354 Ta 354
.It 2 Ta 512 Ta 512
.It 3 Ta 1000 Ta 1000
.It 4 Ta 2000 Ta 2000
.El
.It Cm priority Ar priority ( Cm normal, high, highest )
Use the
.Ar priority
parameter to set the priority of the Atlan 655 Radio Media Access Control
the values are
.Cm normal , high
or
.Cm higest .
The higher the priority set, the more likely this unit wil be first
to successfully transmit a packet when multiple units are trying
to transmit at the same time.
.Pp
The percentage of units on your network that you set to other than
.Dq normal
should be kept small - 10 percent or less.
.It Cm stat
Print internal Arlan 655 statistics block.
.It Cm quality Ar seconds [ Cm count Ar <count> ]
Perform link quality test during
.Ar seconds
transmitting
.Ar count
packets.
Currently is broken.
.El
.Sh EXAMPLES
.Bd -literal -offset indent
alrlconfig arl0 name NODE1 sid 4 freq 2442
arlconfig arl0 quality 10 seconds
arlconfig arl0 status
.Pp
You can configure Arlan 655 card from /etc/start_if.arl0. For example:
.Pp
#!/bin/sh
/sbin/arlconfig arl0 sid 0x000002 freq 2412 spread 2000 mode 640
.Sh SEE ALSO
.Xr arl 4 ,
.Xr "Arlan 655 ISA Wireless LAN Client Card User Guide" .
.Sh HISTORY
The
.Nm
utility first appeared in
.Fx 5.3 .
.Sh BUGS
Aironet Arlan 640 bridges and Arlan 630 access points don't understand
country codes other than 9.
.Sh AUTHORS
The
.Nm
utility was written by
.Aq ran@styx.aic.net .
Manpage was written by
.An Yuri Kurenkov Aq y.kurenkov@init.ru .

View File

@ -0,0 +1,612 @@
/*
* $RISS: if_arl/arlconfig/arlconfig.c,v 1.3 2003/01/13 07:23:25 count Exp $
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <limits.h>
#include <dev/arl/if_arlreg.h>
struct freq_list {
short fr_no;
char* name;
};
struct freq_list freq_list_1[] = {
{ 0, "908.50" },
{ 1, "910.06" },
{ 2, "915.52" },
{ 3, "915.00" },
{ 4, "917.83" },
{ 5, "919.22" },
{ 6, "922.26" },
{ 7, "911.45" },
{ 8, "915.00" },
{ 9, "918.55" },
{ 10,"915.00" },
{ 11,"915.00" }
};
struct freq_list freq_list_6[] = {
{ 0, "920.31" },
{ 1, "920.33" },
{ 2, "921.55" },
{ 3, "922.17" },
{ 4, "922.79" },
{ 5, "921.46" },
{ 6, "921.55" }
};
struct freq_list freq_list_9[] = {
{ 0, "Bad" },
{ 1, "2412" },
{ 2, "2427" },
{ 3, "2442" },
{ 4, "2457" },
{ 5, "2465" }
};
struct freq_list freq_list_10[] = {
{ 0, "Bad" },
{ 1, "2412" },
{ 2, "2427" },
{ 3, "2442" },
{ 4, "2457" },
{ 5, "2472" }
};
struct freq_list freq_list_11[] = {
{ 0, "Bad" },
{ 1, "2484" }
};
struct freq_list freq_list_12[] = {
{ 0, "Bad" },
{ 1, "2457" },
{ 2, "2465" },
{ 3, "2472" },
};
struct freq_list freq_list_13[] = {
{ 0, "Bad" },
{ 1, "2411" },
{ 2, "2425" },
{ 3, "2439" }
};
struct freq_list freq_list_14[] = {
{ 0, "Bad" },
{ 1, "2427" },
{ 2, "2442" },
{ 3, "2457" }
};
struct freq_list freq_list_15[] = {
{ 0, "Bad" },
{ 1, "2460" }
};
#define MAXFREQ(a) sizeof(a)/sizeof(struct freq_list)
struct rate_list {
short rate_no;
char* name;
};
struct rate_list rate_list_2400[] = {
{ 0, "Bad" },
{ 1, "354" },
{ 2, "512" },
{ 3, "1000" },
{ 4, "2000" }
};
struct radio_type {
int id;
char* name;
} radio_type_list [] = {
{ 0, "No EPROM" },
{ 1, "092/094" },
{ 2, "020" },
{ 3, "092A" },
{ 4, "020B" },
{ 5, "095" },
{ 6, "024" },
{ 7, "025B" },
{ 8, "024B" },
{ 9, "024C" },
{10, "025C" },
{11, "024-1A" },
{12, "025-1A" },
{13, "Other" }
};
static struct ch_list {
short chan;
char* fr;
char* country;
struct rate_list* rate;
struct freq_list* freq;
int max_freq;
} CHSET[] = {
{ 0, 0, 0, 0, 0, 0 },
{ 1, "900 Mhz", "Canada, U.S.A., Mexico", 0, freq_list_1, MAXFREQ(freq_list_1) },
{ 2, 0, 0, 0, 0, 0 },
{ 3, 0, 0, 0, 0, 0 },
{ 4, 0, 0, 0, 0, 0 },
{ 5, 0, 0, 0, 0, 0 },
{ 6, "900 Mhz", "Australia", 0, freq_list_6, MAXFREQ(freq_list_6) },
{ 7, 0, 0, 0, 0, 0 },
{ 8, 0, 0, 0, 0, 0 },
{ 9, "2400 Mhz", "North America", rate_list_2400, freq_list_9, MAXFREQ(freq_list_9) },
{ 10, "2400 Mhz", "E.T.S.I", rate_list_2400, freq_list_10, MAXFREQ(freq_list_10) },
{ 11, "2400 Mhz", "Japan", rate_list_2400, freq_list_11, MAXFREQ(freq_list_11) },
{ 12, "2400 Mhz", "France", rate_list_2400, freq_list_12, MAXFREQ(freq_list_12) },
{ 13, "2400 Mhz", "Australia", rate_list_2400, freq_list_13, MAXFREQ(freq_list_13) },
{ 14, "2400 Mhz", "Germany", rate_list_2400, freq_list_14, MAXFREQ(freq_list_14) },
{ 15, "2400 Mhz", "U.K.(MPT1349),Spain", rate_list_2400, freq_list_15, MAXFREQ(freq_list_15) }
};
char* registrationMode[] = {
"NON-TMA",
"TMA",
"PSP"
};
char* priorityList[] = {
"normal",
"high",
"highest"
};
void
usage()
{
const char *progname = getprogname();
#if 0
fprintf(stderr, "\nArlan configuration utility.\n\n");
#endif
fprintf(stderr, "Usage: %s <ifname> [<param> <value> ...]\n", progname);
fprintf(stderr, "\t<ifname>\tArlan interface name.\n");
fprintf(stderr, "\t<param>\t\tParameter name (see below).\n");
fprintf(stderr, "\t<value>\t\tNew value for parameter.\n");
fprintf(stderr, "Parameter name:\t\tValue:\n");
fprintf(stderr, "\tname\t\tset Name.\n");
fprintf(stderr, "\tsid\t\tset System ID.\n");
fprintf(stderr, "\tfreq\t\tset Frequency Channel (2412, 2427, 2442, 2457, 2465)\n");
fprintf(stderr, "\tspread\t\tset Bitrate (354, 500, 1000, 2000)\n");
fprintf(stderr, "\tmode\t\tset Mode (640, 655, PSP).\n");
fprintf(stderr, "\tcountry\t\tset Country (9-15)\n");
fprintf(stderr, "\tchannel\t\tset Channel (depended on country)\n");
fprintf(stderr, "\tbitrate\t\tset Bitrate (0-4)\n");
fprintf(stderr, "\tpriority\tset Priority (normal, high, highest)\n");
#if 0
fprintf(stderr, "\tparent\t\tset Arlan parent's MAC.\n");
fprintf(stderr, "\taddr\t\tset Arlan MAC.\n");
#endif
fprintf(stderr, "or: %s <ifname> stat\n", progname);
fprintf(stderr, "\tprint internal arlan statistics block\n");
fprintf(stderr, "or: %s <ifname> quality <seconds> [count <count>]\n",
progname);
fprintf(stderr, "\tprint receive packet level and quality with interval\n");
exit(0);
}
void
print_al(struct arl_cfg_param *arl_io)
{
printf("Arlan-655(IC2000) type 0x%x v%d.%d, radio module type %s\n",
arl_io->hardwareType,
arl_io->majorHardwareVersion,
arl_io->minorHardwareVersion,
(arl_io->radioModule < 13) ?
radio_type_list[arl_io->radioModule].name : "Unknown" );
printf("\tname %s, sid 0x%06x, mode %s, num tx retry %d\n",
arl_io->name,
*(int *)arl_io->sid,
(arl_io->registrationMode < 3) ?
registrationMode[arl_io->registrationMode]:"Unknown",
arl_io->txRetry );
printf("\tchannel set %d, %s, %s\n",
arl_io->channelSet,
CHSET[arl_io->channelSet].fr,
CHSET[arl_io->channelSet].country);
printf("\tfrequency %s Mhz, bitrate %s kb/s, priority %s, receive mode %d\n",
(CHSET[arl_io->channelSet].freq &&
CHSET[arl_io->channelSet].max_freq > arl_io->channelNumber) ?
CHSET[arl_io->channelSet].freq[arl_io->channelNumber].name :
"unknown",
(CHSET[arl_io->channelSet].rate) ?
CHSET[arl_io->channelSet].rate[arl_io->spreadingCode].name :
"unknown",
arl_io->priority <= 2 ?
priorityList[arl_io->priority] : "unknown",
arl_io->receiveMode);
printf("\tether %s",
(char *)ether_ntoa((struct ether_addr *)arl_io->lanCardNodeId));
printf(" registered to %s\n",
(char *)ether_ntoa((struct ether_addr *)arl_io->specifiedRouter));
}
void
print_stb( struct arl_stats stb )
{
printf("Arlan internal statistics block\n\n");
printf("%8u\tdatagrams transmitted\n",
stb.numDatagramsTransmitted);
printf("%8u\tre-transmitted\n",
stb.numReTransmissions);
printf("%8u\tframes discarded internally in a router\n",
stb.numFramesDiscarded);
printf("%8u\tdatagrams received\n",
stb.numDatagramsReceived);
printf("%8u\tduplicate received frame\n",
stb.numDuplicateReceivedFrames);
printf("%8u\tdatagrams discarded due to unavailable mail box buffer\n",
stb.numDatagramsDiscarded);
printf("%8d\tmaximum of re-transmissions datagram\n",
stb.maxNumReTransmitDatagram);
printf("%8d\tmaximum of re-transmissions frame\n",
stb.maxNumReTransmitFrames);
printf("%8d\tmaximum of consecutive duplicate received frames\n",
stb.maxNumConsecutiveDuplicateFrames);
printf("%8u\tbytes transmitted\n",
stb.numBytesTransmitted);
printf("%8u\tbytes received\n",
stb.numBytesReceived);
printf("%8u\tCRC errors\n",
stb.numCRCErrors);
printf("%8u\tlength errors\n",
stb.numLengthErrors);
printf("%8u\tabort errors\n",
stb.numAbortErrors);
printf("%8u\tTX underuns\n",
stb.numTXUnderruns);
printf("%8u\tRX overruns\n",
stb.numRXOverruns);
printf("%8u\tHold Offs (channel tested busy, tx delayed)\n",
stb.numHoldOffs);
printf("%8u\tframes transmitted\n",
stb.numFramesTransmitted);
printf("%8u\tframes received\n",
stb.numFramesReceived);
printf("%8u\treceive frames lost due unavailable buffer\n",
stb.numReceiveFramesLost);
printf("%8u\tRX buffer overflows \n",
stb.numRXBufferOverflows);
printf("%8u\tframes discarded due to Address mismatch\n",
stb.numFramesDiscardedAddrMismatch);
printf("%8u\tframes discarded due to SID mismatch\n",
stb.numFramesDiscardedSIDMismatch);
printf("%8u\tpolls transmitted\n",
stb.numPollsTransmistted);
printf("%8u\tpoll acknowledges received\n",
stb.numPollAcknowledges);
printf("%8u\tstatus vector timeout\n",
stb.numStatusVectorTimeouts);
printf("%8u\tNACK packets received\n",
stb.numNACKReceived);
}
#ifdef ARL_QUALITY
void
print_qlt(struct arl_quality qlt, int count)
{
int i, s;
int v, v1;
time_t t;
int minLevel, maxLevel, avgLevel;
int minQuality, maxQuality, avgQuality;
t = time(NULL);
localtime(&t);
printf("#%d Current date-time: %s", count, ctime(&t));
printf(" %-39s %s\n","Receive Level","Receive Quality");
printf(
" pkts 0.......10 11............100 > pkts 0.......10 11............100 >\n"\
" -----+----------+-----------------+--- -----+----------+-----------------+---\n");
minLevel = 16;
maxLevel = 0;
avgLevel = 0;
minQuality = 16;
maxQuality = 0;
avgQuality = 0;
for (i = 0, s = 0; i < ARLAN_MAX_QUALITY; i++) {
v = qlt.rxLevel[i];
if (v) {
if (i < minLevel)
minLevel = i;
if (i > maxLevel)
maxLevel = i;
avgLevel += v*i;
printf(" %-4d %x", v, i);
} else
printf(" o %x", i);
s += v;
if (v < 10)
;
else if (v < 100)
v = 10 + ((v-10) * 20) / 90;
else if (v < 1000)
v = 31;
else
v = 32;
v1 = v;
while (v) {
printf("*");
v--;
}
v = 33 - v1;
while (v) {
printf(" ");
v--;
}
v = qlt.rxQuality[i];
if (v) {
if (i < minQuality)
minQuality = i;
if (i > maxQuality)
maxQuality = i;
avgQuality += v*i;
printf("%-4d %x", v, i);
} else
printf("o %x", i);
if (v < 10)
;
else if (v < 100)
v = 10 + ((v-10) * 20) / 90;
else if (v < 1000)
v = 31;
else
v = 32;
}
v1 = v;
while (v) {
printf("*");
v--;
}
printf("\n");
}
printf(" -----+----------+-----------------+--- -----+----------+-----------------+---\n");
if (minLevel > 15)
minLevel = 0;
if (minQuality > 15)
minQuality = 0;
printf("\tPackets count %-6d\n", s);
if (!s)
s++;
printf("\tLevel min %d/avg %d/max %d\n",
minLevel, avgLevel/s, maxLevel);
printf("\tQuality min %d/avg %d/max %d\n",
minQuality, avgQuality/s, maxQuality);
}
#endif /* ARL_QUALITY */
int
main(int argc, char *argv[])
{
struct ifreq ifr;
struct arl_req arl_io;
struct ether_addr *ea;
struct arl_stats stb;
/*static arl_quality qlt;*/
int sd, argind, val = -1;
long val2;
char *param, *value, *value2;
/*int end_count, i;*/
if (argc < 2)
usage();
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;
bzero(&arl_io, sizeof(arl_io));
ifr.ifr_data = (caddr_t)&arl_io;
if (argc == 2) {
if (ioctl(sd, SIOCGARLALL, (caddr_t)&ifr))
err(1,"Get ALL");
print_al(&arl_io.cfg);
exit(0);
}
if (argc == 3) {
if (!strcasecmp(argv[2], "stat")) {
strncpy(ifr.ifr_name, argv[1], sizeof(ifr.ifr_name));
ifr.ifr_addr.sa_family = AF_INET;
ifr.ifr_data = (caddr_t)&stb;
if (ioctl(sd, SIOCGARLSTB, (caddr_t)&ifr))
err(1,"Get STB");
print_stb(stb);
exit(0);
}
#ifdef ARL_QUALITY
if (!strcasecmp(argv[2],"quality") && argc > 3) {
val = atoi(argv[3]);
if (val < 0 || val >= 3601)
err(1,"Bad time range");
end_count = 0;
if (argc > 5 && !strcasecmp(argv[4], "count"))
end_count = atoi(argv[5]);
printf("\n");
i = 0;
while (i < end_count || !end_count) { /* loop */
if (i++)
sleep(val);
strncpy(ifr.ifr_name,
argv[1], sizeof(ifr.ifr_name));
ifr.ifr_addr.sa_family = AF_INET;
ifr.ifr_data = (caddr_t)&qlt;
if (ioctl(sd, SIOCGARLQLT, (caddr_t)&ifr))
err(1,"Get QLT");
print_qlt(qlt, i);
}
exit(0);
}
#endif /* ARL_QUALITY */
}
arl_io.what_set = 0;
for (argind = 2; argind < argc; argind += 2) {
param = argv[argind];
value = argv[argind+1];
val = -1;
if (!strcasecmp(param, "name")) {
bzero(arl_io.cfg.name, 16);
strncpy(arl_io.cfg.name, value, 16);
arl_io.what_set |= ARLAN_SET_name;
}
if (!strcasecmp(param, "sid")) {
val2 = strtol(value, &value2, 0);
if (val2 < 0 || val2 > 0xffffff || val2 % 2 ||
value == value2)
err(1, "Bad SID - %s", value);
bcopy(&val2, arl_io.cfg.sid, 4);
arl_io.what_set |= ARLAN_SET_sid;
}
if (!strcasecmp (param, "freq")) {
if (!strcmp(value, "2412"))
val = 1;
else if (!strcmp(value, "2427"))
val = 2;
else if (!strcmp(value, "2442"))
val = 3;
else if (!strcmp(value, "2457"))
val = 4;
else if (!strcmp(value, "2465"))
val = 5;
if (val == -1)
err(1, "Bad Frequency - %s", value);
arl_io.cfg.channelNumber = val;
arl_io.what_set |= ARLAN_SET_channelNumber;
}
if (!strcasecmp(param, "spread")) {
if (!strcmp(value, "354"))
val = 1;
else if (!strcmp(value, "500"))
val = 2;
else if (!strcmp(value, "1000"))
val = 3;
else if (!strcmp(value, "2000"))
val = 4;
if (val == -1)
err (1, "Bad Bitrate - %s", value);
arl_io.cfg.spreadingCode = val;
arl_io.what_set |= ARLAN_SET_spreadingCode;
}
if (!strcasecmp(param, "priority")) {
if (!strcasecmp(value, "normal"))
val = 0;
else if (!strcasecmp(value, "high"))
val = 1;
else if (!strcasecmp(value, "highest"))
val = 2;
if (val == -1)
err( 1, "Bad priority - %s", value);
arl_io.cfg.priority = val;
arl_io.what_set |= ARLAN_SET_priority;
}
if (!strcasecmp(param, "mode")) {
if (!strcmp(value, "655"))
val = 0;
else if (!strcmp(value, "640"))
val = 1;
else if (!strcasecmp (value, "PSP"))
val = 2;
if (val == -1)
err (1, "Bad Mode - %s", value);
arl_io.cfg.registrationMode = val;
arl_io.what_set |= ARLAN_SET_registrationMode;
}
if (!strcasecmp(param, "parent")) {
if ((ea = (struct ether_addr*) ether_aton(value)) == NULL)
err (1, "Bad parent's MAC - %s", value);
for (val = 0; val < 6; val++) {
arl_io.cfg.specifiedRouter[val] =
(int) ea->octet[val];
}
arl_io.what_set |= ARLAN_SET_specifiedRouter;
}
if (!strcasecmp(param, "addr")) {
if ((ea = (struct ether_addr*) ether_aton(value)) == NULL)
err (1, "Bad MAC - %s", value);
for (val = 0; val < 6; val++) {
arl_io.cfg.lanCardNodeId[val] =
(int) ea->octet[val];
}
arl_io.what_set |= ARLAN_SET_lanCardNodeId;
}
if (!strcasecmp(param, "country")) {
arl_io.cfg.channelSet = atoi(value);
arl_io.what_set |= ARLAN_SET_channelSet;
}
if (!strcasecmp(param, "channel")) {
arl_io.cfg.channelNumber = atoi(value);
arl_io.what_set |= ARLAN_SET_channelNumber;
}
if (!strcasecmp(param, "bitrate")) {
arl_io.cfg.spreadingCode = atoi(value);
arl_io.what_set |= ARLAN_SET_spreadingCode;
}
if (!strcasecmp(param, "receive")) {
arl_io.cfg.receiveMode = atoi(value);
arl_io.what_set |= ARLAN_SET_receiveMode;
}
if (!strcasecmp(param, "txretry")) {
arl_io.cfg.txRetry = atoi(value);
arl_io.what_set |= ARLAN_SET_txRetry;
}
}
if (arl_io.what_set) {
if (ioctl(sd, SIOCSARLALL, (caddr_t)&ifr))
err (1, "Set ALL" );
if (ioctl(sd, SIOCGARLALL, (caddr_t)&ifr))
err (1, "Get ALL");
print_al(&arl_io.cfg);
}
return 0;
}