From 09b9789b28dd8453a54cb424115f31a6d3672527 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Fri, 19 Aug 2016 22:27:14 +0000 Subject: [PATCH] Remove the wl(4) driver and wlconfig(8) utility. The wl(4) driver supports pre-802.11 PCCard wireless adapters that are slower than 802.11b. They do not work with any of the 802.11 framework and the driver hasn't been reported to actually work in a long time. Relnotes: yes --- ObsoleteFiles.inc | 4 + .../doc/en_US.ISO8859-1/hardware/article.xml | 3 - share/man/man4/man4.i386/Makefile | 3 +- share/man/man4/man4.i386/wl.4 | 193 -- sys/conf/files | 1 - sys/conf/options | 2 - sys/dev/wl/if_wl.c | 2620 ----------------- sys/dev/wl/if_wl.h | 133 - sys/dev/wl/if_wl_i82586.h | 266 -- sys/i386/conf/NOTES | 5 - sys/modules/Makefile | 2 - sys/modules/wl/Makefile | 10 - targets/pseudo/userland/Makefile.depend | 3 +- tools/build/mk/OptionalObsoleteFiles.inc | 6 - tools/kerneldoc/subsys/Doxyfile-dev_wl | 21 - usr.sbin/Makefile.i386 | 3 - usr.sbin/wlconfig/Makefile | 9 - usr.sbin/wlconfig/Makefile.depend | 16 - usr.sbin/wlconfig/wlconfig.8 | 143 - usr.sbin/wlconfig/wlconfig.c | 417 --- 20 files changed, 6 insertions(+), 3854 deletions(-) delete mode 100644 share/man/man4/man4.i386/wl.4 delete mode 100644 sys/dev/wl/if_wl.c delete mode 100644 sys/dev/wl/if_wl.h delete mode 100644 sys/dev/wl/if_wl_i82586.h delete mode 100644 sys/modules/wl/Makefile delete mode 100644 tools/kerneldoc/subsys/Doxyfile-dev_wl delete mode 100644 usr.sbin/wlconfig/Makefile delete mode 100644 usr.sbin/wlconfig/Makefile.depend delete mode 100644 usr.sbin/wlconfig/wlconfig.8 delete mode 100644 usr.sbin/wlconfig/wlconfig.c diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc index 1b0710ac5203..e13a87c30fea 100644 --- a/ObsoleteFiles.inc +++ b/ObsoleteFiles.inc @@ -38,6 +38,10 @@ # xargs -n1 | sort | uniq -d; # done +# 20160819: Remove wl(4) and wlconfig(8) +OLD_FILES+=usr/share/man/man4/i386/wl.4.gz +OLD_FILES+=usr/sbin/wlconfig +OLD_FILES+=usr/share/man/man8/i386/wlconfig.8.gz # 20160819: Remove si(4) and sicontrol(8) OLD_FILES+=usr/share/man/man4/si.4.gz OLD_FILES+=usr/sbin/sicontrol diff --git a/release/doc/en_US.ISO8859-1/hardware/article.xml b/release/doc/en_US.ISO8859-1/hardware/article.xml index bffb5820e8cc..795709e0547c 100644 --- a/release/doc/en_US.ISO8859-1/hardware/article.xml +++ b/release/doc/en_US.ISO8859-1/hardware/article.xml @@ -1023,9 +1023,6 @@ Intersil PRISM-2.5, Intersil Prism-3, and Symbol Spectrum24 chipsets (&man.wi.4; driver) - [&arch.i386;] NCR / AT&T / Lucent Technologies WaveLan - T1-speed ISA/radio LAN cards (&man.wl.4; driver) - [&arch.i386;, &arch.amd64;] Intel PRO/Wireless 3945ABG MiniPCI network adapters (&man.wpi.4; driver) diff --git a/share/man/man4/man4.i386/Makefile b/share/man/man4/man4.i386/Makefile index 7b25eca28c62..21cff03c68db 100644 --- a/share/man/man4/man4.i386/Makefile +++ b/share/man/man4/man4.i386/Makefile @@ -31,8 +31,7 @@ MAN= aic.4 \ streams.4 \ svr4.4 \ vpd.4 \ - vx.4 \ - wl.4 + vx.4 MLINKS= CPU_ELAN.4 CPU_SOEKRIS.4 MLINKS+=pae.4 PAE.4 diff --git a/share/man/man4/man4.i386/wl.4 b/share/man/man4/man4.i386/wl.4 deleted file mode 100644 index e697d2318a26..000000000000 --- a/share/man/man4/man4.i386/wl.4 +++ /dev/null @@ -1,193 +0,0 @@ -.\" -.\" Copyright (c) 1997, Jim Binkley -.\" 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 Jim Binkley -.\" 4. The name of the author may not be used to endorse or promote products -.\" derived from this software without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 THE AUTHOR 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. -.\" -.\" $FreeBSD$ -.Dd September 29, 2006 -.Dt WL 4 i386 -.Os -.Sh NAME -.Nm wl -.Nd T1 speed ISA/radio lan card -.Sh SYNOPSIS -.Cd "device wl0 at isa? port 0x300 irq 5" -.Sh DESCRIPTION -The -.Nm -driver controls a radio lan card system made originally by -NCR, then ATT, now Lucent. -The system is spread-spectrum radio -at around 915 MHz (or 2.4 GHz). -With the supplied omni-directional antennae, -about 400 feet (indoors, more outdoors) can be covered in circumference. -This card can talk to the companion (wlp0) pccard. -Speeds vary -from 1 megabit to theoretically 2 megabits (roughly T1 in speed). -.Pp -The card has three fundamental hardware -units, a so-called PSA or programmable storage area, a radio modem, -and a Ethernet lan controller. -The latter component is the -ancient (and not very honorable) Intel 82586 Ethernet chip. -Fundamentally it appears to the operating system as an Ethernet system, -and speaks IEEE MAC addresses. -The radio modem simply translates -Ethernet packets to/from radio packets, that are either at 2.4 GHz -or 915 MHz depending on the radio modem. -It supports a collision -avoidance scheme. -The lan controller -supports promiscuous mode, broadcast, and multicasting -(although there is a glitch -in the latter). -"It thinks it is Ethernet". -.Pp -How it is used -depends on the kind of antennae deployed with it. -Point to point -applications are possible as are Ethernet-like lan use. -The vendor -ships an omni-directional antennae that works in the -vicinity of 400 feet (indoors). -Point to point antennae can be purchased that will go miles. -.Sh SETUP -The card can either be initialized with the vendor supplied DOS setup software. -Typically minimally an IRQ, port, and Network ID must be supplied. -Michael Smith's -.Xr wlconfig 8 -utility can now be used to do this work from -the UNIX side. -The card is "not" plug and play. -The network id controls whether one set of cards can hear another. -If different, cards will read physical packets, but they will be discarded -by the radio modem. -.Sh CONTROL -In addition to the config utility, there are several sysctl -switches that can be used to modify runtime parameters. -The -.Xr sysctl 8 -variables are as follows: -.Bl -diag -.It "machdep.wl_xmit_delay " -This variable will cause the driver to insert a delay on transmit. -250 is the default. -The delay should probably be a bit longer -on faster cpus and less on slower cpus. -It exists because the 82586 -was not designed to work with Pentium-speed cpu systems and if overdriven -will have copious xmit side errors. -.It machdep.wl_ignore_nwid <0 | 1> -This switch defaults to 0; i.e., the nwid is not ignored. -It can -be set to 1 to cause the nwid to not be used. -This may be useful -when the device is in promiscuous mode as one can watch for all -packets and ignore nwid differences. -.It machdep.wl_xmit_watch -This switch is not currently useful. -.It machdep.wl_gather_snr -This switch is not currently useful. -.Pp -There is also a signal strength cache in the driver. -It may be interrogated -with -.Xr wlconfig 8 . -Incoming packets -are checked for certain hardware radio-modem values including signal -strength, silence, and quality, which range fro 0..63, 0..63, and 0..15 -respectively. -Thus one can read out signal strenth values to see -how close/far peer nodes are. -The signal strength cache is indexed by -sender MAC address. -There are two sysctls that change how it filters packets. -Both are on -by default. -.It machdep.wl_wlcache_mcastonly <0 | 1> -By default this switch is on. -It forces the cache to filter out -unicast packets. -Only broadcast or multicast packets are accepted. -.It machdep.wl_wlcache_iponly <0 | 1> -By default this switch is on. -It forces the driver to discard non-IP -packets and also stores the IP src address. -ARP packets are ignored, -as are any other network protocol barring IPv4 packets. -.El -.Sh SEE ALSO -.Xr sysctl 8 , -.Xr wlconfig 8 -.Pp -.Pa http://www.wavelan.com -.Sh HISTORY -The -.Nm -driver was written by -.An Anders Klemets -(thousands of years ago?) and -appears to be based on an even older Intel 82586 driver. -The 82586 -controller was one of the first (if not the first?) integrated lan -controller on the block. -That does not mean it was the best either. -Anders ported and or created a driver for the ISA wavelan and PCCARD -wavelan system too (wlp). -.An Robert T. Morris, Jr. -ported the Mach drivers to BSDI. -.An Jim Binkley -ported them to -.Fx 2.1 . -.An Michael Smith -ported the -.Nm -driver only to 2.2.2. -Jim and Michael have been -maintaining them. -The current state of the driver is NOT ANYONE'S -FAULT. -Thanks to -.An Bernie Doehner -and -.An Robert Buaas -for contributions. -.Sh AUTHORS -Too numerous to mention. -See above. -.Sh CAVEATS -The 82586 has numerous defects. -It may experience transmit-side -errors when modern faster cpus send packets at it faster than it can handle. -The driver (and probably the chip) does not support an all multicast mode. -As a result, it can be used with applications like -.Xr mrouted 8 Pq Pa ports/net/mrouted , -but it must go into promiscuous mode for that to work. -The driver -is slow to change modes from "normal" to promiscuous mode, presumably -due to delays in the configuration code. diff --git a/sys/conf/files b/sys/conf/files index 8b2c5032fe4b..1ce19df4ed3d 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -2933,7 +2933,6 @@ dev/wb/if_wb.c optional wb pci dev/wi/if_wi.c optional wi dev/wi/if_wi_pccard.c optional wi pccard dev/wi/if_wi_pci.c optional wi pci -dev/wl/if_wl.c optional wl isa dev/wpi/if_wpi.c optional wpi pci wpifw.c optional wpifw \ compile-with "${AWK} -f $S/tools/fw_stub.awk wpi.fw:wpifw:153229 -mwpi -c${.TARGET}" \ diff --git a/sys/conf/options b/sys/conf/options index f115e7e14212..aa6318bc5943 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -218,8 +218,6 @@ SW_WATCHDOG opt_watchdog.h TURNSTILE_PROFILING UMTX_PROFILING VERBOSE_SYSINIT -WLCACHE opt_wavelan.h -WLDEBUG opt_wavelan.h # POSIX kernel options P1003_1B_MQUEUE opt_posix.h diff --git a/sys/dev/wl/if_wl.c b/sys/dev/wl/if_wl.c deleted file mode 100644 index 08d0fc87c771..000000000000 --- a/sys/dev/wl/if_wl.c +++ /dev/null @@ -1,2620 +0,0 @@ -/*- - * 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 all copyright - * notices, this list of conditions and the following disclaimer. - * 2. The names of the authors may not be used to endorse or promote products - * derived from this software without specific prior written permission - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 THE AUTHORS 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. - * - */ -/* - * if_wl.c - original MACH, then BSDI ISA wavelan driver - * ported to mach by Anders Klemets - * to BSDI by Robert Morris - * to FreeBSD by Jim Binkley - * to FreeBSD 2.2+ by Michael Smith - * - * 2.2 update: - * Changed interface to match 2.1-2.2 differences. - * Implement IRQ selection logic in wlprobe() - * Implement PSA updating. - * Pruned heading comments for relevance. - * Ripped out all the 'interface counters' cruft. - * Cut the missing-interrupt timer back to 100ms. - * 2.2.1 update: - * now supports all multicast mode (mrouted will work), - * but unfortunately must do that by going into promiscuous mode - * NWID sysctl added so that normally promiscuous mode is NWID-specific - * but can be made NWID-inspecific - * 7/14/97 jrb - * - * Work done: - * Ported to FreeBSD, got promiscuous mode working with bpfs, - * and rewired timer routine. The i82586 will hang occasionally on output - * and the watchdog timer will kick it if so and log an entry. - * 2 second timeout there. Apparently the chip loses an interrupt. - * Code borrowed from if_ie.c for watchdog timer. - * - * The wavelan card is a 2mbit radio modem that emulates ethernet; - * i.e., it uses MAC addresses. This should not be a surprise since - * it uses an ethernet controller as a major hw item. - * It can broadcast, unicast or apparently multicast in a base cell - * using an omni-directional antennae that is - * about 800 feet around the base cell barring walls and metal. - * With directional antennae, it can be used point to point over a mile - * or so apparently (haven't tried that). - * - * There are ISA and pcmcia versions (not supported by this code). - * The ISA card has an Intel 82586 lan controller on it. It consists - * of 2 pieces of hw, the lan controller (intel) and a radio-modem. - * The latter has an extra set of controller registers that has nothing - * to do with the i82586 and allows setting and monitoring of radio - * signal strength, etc. There is a nvram area called the PSA that - * contains a number of setup variables including the IRQ and so-called - * NWID or Network ID. The NWID must be set the same for all radio - * cards to communicate (unless you are using the ATT/NCR roaming feature - * with their access points. There is no support for that here. Roaming - * involves a link-layer beacon sent out from the access points. End - * stations monitor the signal strength and only use the strongest - * access point). This driver assumes that the base ISA port, IRQ, - * and NWID are first set in nvram via the dos-side "instconf.exe" utility - * supplied with the card. This driver takes the ISA port from - * the kernel configuration setup, and then determines the IRQ either - * from the kernel config (if an explicit IRQ is set) or from the - * PSA on the card if not. - * The hw also magically just uses the IRQ set in the nvram. - * The NWID is used magically as well by the radio-modem - * to determine which packets to keep or throw out. - * - * sample config: - * - * device wl0 at isa? port 0x300 net irq ? - * - * Ifdefs: - * 1. WLDEBUG. (off) - if turned on enables IFF_DEBUG set via ifconfig debug - * 2. MULTICAST (on) - turned on and works up to and including mrouted - * 3. WLCACHE (off) - define to turn on a signal strength - * (and other metric) cache that is indexed by sender MAC address. - * Apps can read this out to learn the remote signal strength of a - * sender. Note that it has a switch so that it only stores - * broadcast/multicast senders but it could be set to store unicast - * too only. Size is hardwired in if_wl_wavelan.h - * - * one further note: promiscuous mode is a curious thing. In this driver, - * promiscuous mode apparently CAN catch ALL packets and ignore the NWID - * setting. This is probably more useful in a sense (for snoopers) if - * you are interested in all traffic as opposed to if you are interested - * in just your own. There is a driver specific sysctl to turn promiscuous - * from just promiscuous to wildly promiscuous... - * - * This driver also knows how to load the synthesizers in the 2.4 Gz - * ISA Half-card, Product number 847647476 (USA/FCC IEEE Channel set). - * This product consists of a "mothercard" that contains the 82586, - * NVRAM that holds the PSA, and the ISA-buss interface custom ASIC. - * The radio transceiver is a "daughtercard" called the WaveMODEM which - * connects to the mothercard through two single-inline connectors: a - * 20-pin connector provides DC-power and modem signals, and a 3-pin - * connector which exports the antenna connection. The code herein - * loads the receive and transmit synthesizers and the corresponding - * transmitter output power value from an EEPROM controlled through - * additional registers via the MMC. The EEPROM address selected - * are those whose values are preset by the DOS utility programs - * provided with the product, and this provides compatible operation - * with the DOS Packet Driver software. A future modification will - * add the necessary functionality to this driver and to the wlconfig - * utility to completely replace the DOS Configuration Utilities. - * The 2.4 Gz WaveMODEM is described in document number 407-024692/E, - * and is available through Lucent Technologies OEM supply channels. - * --RAB 1997/06/08. - */ - -#define MULTICAST 1 - -/* - * Olivetti PC586 Mach Ethernet driver v1.0 - * Copyright Ing. C. Olivetti & C. S.p.A. 1988, 1989 - * All rights reserved. - * - */ -/* - Copyright 1988, 1989 by Olivetti Advanced Technology Center, Inc., -Cupertino, California. - - All Rights Reserved - - Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appears in all -copies and that both the copyright notice and this permission notice -appear in supporting documentation, and that the name of Olivetti -not be used in advertising or publicity pertaining to distribution -of the software without specific, written prior permission. - - OLIVETTI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, -IN NO EVENT SHALL OLIVETTI BE LIABLE FOR ANY SPECIAL, INDIRECT, OR -CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, -NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUR OF OR IN CONNECTION -WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ -/* - Copyright 1988, 1989 by Intel Corporation, Santa Clara, California. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appears in all -copies and that both the copyright notice and this permission notice -appear in supporting documentation, and that the name of Intel -not be used in advertising or publicity pertaining to distribution -of the software without specific, written prior permission. - -INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, -IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR -CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, -NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION -WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#include -__FBSDID("$FreeBSD$"); - -/* - * NOTE: - * by rvb: - * 1. The best book on the 82586 is: - * LAN Components User's Manual by Intel - * The copy I found was dated 1984. This really tells you - * what the state machines are doing - * 2. In the current design, we only do one write at a time, - * though the hardware is capable of chaining and possibly - * even batching. The problem is that we only make one - * transmit buffer available in sram space. - */ - -#include "opt_wavelan.h" -#include "opt_inet.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include - -#ifdef INET -#include -#include -#include -#include -#endif - -#include -#include - -/* was 1000 in original, fed to DELAY(x) */ -#define DELAYCONST 1000 -#include /* Definitions for the Intel chip */ -#include -#include - -static char t_packet[ETHERMTU + sizeof(struct ether_header) + sizeof(long)]; - -struct wl_softc { - device_t dev; - struct ifnet *ifp; - u_char psa[0x40]; - u_char nwid[2]; /* current radio modem nwid */ - int flags; - int tbusy; /* flag to determine if xmit is busy */ - u_short begin_fd; - u_short end_fd; - u_short end_rbd; - u_short hacr; /* latest host adapter CR command */ - short mode; - u_char chan24; /* 2.4 Gz: channel number/EEPROM Area # */ - u_short freq24; /* 2.4 Gz: resulting frequency */ - int rid_ioport; - int rid_irq; - struct resource *res_ioport; - struct resource *res_irq; - void *intr_cookie; - struct mtx wl_mtx; - struct callout watchdog_timer; -#ifdef WLCACHE - int w_sigitems; /* number of cached entries */ - /* array of cache entries */ - struct w_sigcache w_sigcache[ MAXCACHEITEMS ]; - int w_nextcache; /* next free cache entry */ - int w_wrapindex; /* next "free" cache entry */ -#endif -}; - -#define WL_LOCK(_sc) mtx_lock(&(_sc)->wl_mtx) -#define WL_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->wl_mtx, MA_OWNED) -#define WL_UNLOCK(_sc) mtx_unlock(&(_sc)->wl_mtx) - -static int wlprobe(device_t); -static int wlattach(device_t); -static int wldetach(device_t); - -static device_method_t wl_methods[] = { - DEVMETHOD(device_probe, wlprobe), - DEVMETHOD(device_attach, wlattach), - DEVMETHOD(device_detach, wldetach), - { 0, 0} -}; - -static driver_t wl_driver = { - "wl", - wl_methods, - sizeof (struct wl_softc) -}; - -devclass_t wl_devclass; -DRIVER_MODULE(wl, isa, wl_driver, wl_devclass, 0, 0); -MODULE_DEPEND(wl, isa, 1, 1, 1); -MODULE_DEPEND(wl, ether, 1, 1, 1); - -static struct isa_pnp_id wl_ids[] = { - {0, NULL} -}; - -/* - * XXX The Wavelan appears to be prone to dropping stuff if you talk to - * it too fast. This disgusting hack inserts a delay after each packet - * is queued which helps avoid this behaviour on fast systems. - */ -static int wl_xmit_delay = 250; -SYSCTL_INT(_machdep, OID_AUTO, wl_xmit_delay, CTLFLAG_RW, &wl_xmit_delay, 0, ""); - -/* - * not XXX, but ZZZ (bizarre). - * promiscuous mode can be toggled to ignore NWIDs. By default, - * it does not. Caution should be exercised about combining - * this mode with IFF_ALLMULTI which puts this driver in - * promiscuous mode. - */ -static int wl_ignore_nwid = 0; -SYSCTL_INT(_machdep, OID_AUTO, wl_ignore_nwid, CTLFLAG_RW, &wl_ignore_nwid, 0, ""); - -/* - * Emit diagnostics about transmission problems - */ -static int xmt_watch = 0; -SYSCTL_INT(_machdep, OID_AUTO, wl_xmit_watch, CTLFLAG_RW, &xmt_watch, 0, ""); - -/* - * Collect SNR statistics - */ -static int gathersnr = 0; -SYSCTL_INT(_machdep, OID_AUTO, wl_gather_snr, CTLFLAG_RW, &gathersnr, 0, ""); - -static int wl_allocate_resources(device_t device); -static int wl_deallocate_resources(device_t device); -static void wlstart(struct ifnet *ifp); -static void wlstart_locked(struct ifnet *ifp); -static void wlinit(void *xsc); -static void wlinit_locked(struct wl_softc *sc); -static int wlioctl(struct ifnet *ifp, u_long cmd, caddr_t data); -static void wlwatchdog(void *arg); -static void wlintr(void *arg); -static void wlxmt(struct wl_softc *sc, struct mbuf *m); -static int wldiag(struct wl_softc *sc); -static int wlconfig(struct wl_softc *sc); -static int wlcmd(struct wl_softc *sc, char *str); -static void wlmmcstat(struct wl_softc *sc); -static u_short wlbldru(struct wl_softc *sc); -static u_short wlmmcread(struct wl_softc *sc, u_short reg); -static void wlinitmmc(struct wl_softc *sc); -static int wlhwrst(struct wl_softc *sc); -static void wlrustrt(struct wl_softc *sc); -static void wlbldcu(struct wl_softc *sc); -static int wlack(struct wl_softc *sc); -static int wlread(struct wl_softc *sc, u_short fd_p); -static void getsnr(struct wl_softc *sc); -static void wlrcv(struct wl_softc *sc); -static int wlrequeue(struct wl_softc *sc, u_short fd_p); -static void wlsftwsleaze(u_short *countp, u_char **mb_pp, struct mbuf **tm_pp, struct wl_softc *sc); -static void wlhdwsleaze(u_short *countp, u_char **mb_pp, struct mbuf **tm_pp, struct wl_softc *sc); -#ifdef WLDEBUG -static void wltbd(struct wl_softc *sc); -#endif -static void wlgetpsa(struct wl_softc *sc, u_char *buf); -static void wlsetpsa(struct wl_softc *sc); -static u_short wlpsacrc(u_char *buf); -static void wldump(struct wl_softc *sc); -#ifdef WLCACHE -static void wl_cache_store(struct wl_softc *, struct ether_header *, struct mbuf *); -static void wl_cache_zero(struct wl_softc *sc); -#endif - -/* 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 -}; - -/* - * wlprobe: - * - * This function "probes" or checks for the WaveLAN board on the bus to - * see if it is there. As far as I can tell, the best break between this - * routine and the attach code is to simply determine whether the board - * is configured in properly. Currently my approach to this is to write - * and read a word from the SRAM on the board being probed. If the word - * comes back properly then we assume the board is there. The config - * code expects to see a successful return from the probe routine before - * attach will be called. - * - * input : address device is mapped to, and unit # being checked - * output : a '1' is returned if the board exists, and a 0 otherwise - * - */ -static int -wlprobe(device_t device) -{ - struct wl_softc *sc; - char *str = "wl%d: board out of range [0..%d]\n"; - u_char inbuf[100]; - rman_res_t junk, sirq; - int error, irq; - - error = ISA_PNP_PROBE(device_get_parent(device), device, wl_ids); - if (error == ENXIO || error == 0) - return (error); - - sc = device_get_softc(device); - error = wl_allocate_resources(device); - if (error) - goto errexit; - - /* TBD. not true. - * regular CMD() will not work, since no softc yet - */ -#define PCMD(sc, hacr) WL_WRITE_2((sc), HACR, (hacr)) - - PCMD(sc, HACR_RESET); /* reset the board */ - DELAY(DELAYCONST); /* >> 4 clocks at 6MHz */ - PCMD(sc, HACR_RESET); /* reset the board */ - DELAY(DELAYCONST); /* >> 4 clocks at 6MHz */ - - /* clear reset command and set PIO#1 in autoincrement mode */ - PCMD(sc, HACR_DEFAULT); - PCMD(sc, HACR_DEFAULT); - WL_WRITE_2(sc, PIOR1, 0); /* go to beginning of RAM */ - WL_WRITE_MULTI_2(sc, PIOP1, str, strlen(str)/2+1); /* write string */ - - WL_WRITE_2(sc, PIOR1, 0); /* rewind */ - WL_READ_MULTI_2(sc, PIOP1, inbuf, strlen(str)/2+1); /* read result */ - - if (bcmp(str, inbuf, strlen(str))) { - error = ENXIO; - goto errexit; - } - - sc->chan24 = 0; /* 2.4 Gz: config channel */ - sc->freq24 = 0; /* 2.4 Gz: frequency */ - - /* read the PSA from the board into temporary storage */ - wlgetpsa(sc, inbuf); - - /* We read the IRQ value from the PSA on the board. */ - for (irq = 15; irq >= 0; irq--) - if (irqvals[irq] == inbuf[WLPSA_IRQNO]) - break; - if ((irq == 0) || (irqvals[irq] == 0)){ - device_printf(device, "PSA corrupt (invalid IRQ value)\n"); - } else { - /* - * If the IRQ requested by the PSA is already claimed by another - * device, the board won't work, but the user can still access the - * driver to change the IRQ. - */ - if (bus_get_resource(device, SYS_RES_IRQ, 0, &sirq, &junk)) - goto errexit; - if (irq != (int)sirq) - device_printf(device, "board is configured for interrupt %d\n", - irq); - } - wl_deallocate_resources(device); - return (0); - -errexit: - wl_deallocate_resources(device); - return (error); -} - -/* - * wlattach: - * - * This function attaches a WaveLAN board to the "system". The rest of - * runtime structures are initialized here (this routine is called after - * a successful probe of the board). Once the ethernet address is read - * and stored, the board's ifnet structure is attached and readied. - * - * input : isa_dev structure setup in autoconfig - * output : board structs and ifnet is setup - * - */ -static int -wlattach(device_t device) -{ - struct wl_softc *sc; - int error, i, j; - struct ifnet *ifp; - u_char eaddr[6]; - - sc = device_get_softc(device); - sc->dev = device; - ifp = sc->ifp = if_alloc(IFT_ETHER); - if (ifp == NULL) { - device_printf(device, "can not if_alloc()\n"); - return (ENOSPC); - } - - mtx_init(&sc->wl_mtx, device_get_nameunit(device), MTX_NETWORK_LOCK, - MTX_DEF); - callout_init_mtx(&sc->watchdog_timer, &sc->wl_mtx, 0); - - error = wl_allocate_resources(device); - if (error) { - wl_deallocate_resources(device); - return (ENXIO); - } - -#ifdef WLDEBUG - printf("wlattach: base %jx, unit %d\n", rman_get_start(sc->res_ioport), - device_get_unit(device)); -#endif - - sc->flags = 0; - sc->mode = 0; - sc->hacr = HACR_RESET; - CMD(sc); /* reset the board */ - DELAY(DELAYCONST); /* >> 4 clocks at 6MHz */ - - /* clear reset command and set PIO#2 in parameter access mode */ - sc->hacr = (HACR_DEFAULT & ~HACR_16BITS); - CMD(sc); - - /* Read the PSA from the board for our later reference */ - wlgetpsa(sc, sc->psa); - - /* fetch NWID */ - sc->nwid[0] = sc->psa[WLPSA_NWID]; - sc->nwid[1] = sc->psa[WLPSA_NWID+1]; - - /* fetch MAC address - decide which one first */ - if (sc->psa[WLPSA_MACSEL] & 1) - j = WLPSA_LOCALMAC; - else - j = WLPSA_UNIMAC; - for (i=0; i < WAVELAN_ADDR_SIZE; ++i) - eaddr[i] = sc->psa[j + i]; - - /* enter normal 16 bit mode operation */ - sc->hacr = HACR_DEFAULT; - CMD(sc); - - wlinitmmc(sc); - WL_WRITE_2(sc, PIOR1, OFFSET_SCB + 8); /* address of scb_crcerrs */ - WL_WRITE_2(sc, PIOP1, 0); /* clear scb_crcerrs */ - WL_WRITE_2(sc, PIOP1, 0); /* clear scb_alnerrs */ - WL_WRITE_2(sc, PIOP1, 0); /* clear scb_rscerrs */ - WL_WRITE_2(sc, PIOP1, 0); /* clear scb_ovrnerrs */ - - ifp->if_softc = sc; - ifp->if_mtu = WAVELAN_MTU; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; -#ifdef WLDEBUG - ifp->if_flags |= IFF_DEBUG; -#endif -#if MULTICAST - ifp->if_flags |= IFF_MULTICAST; -#endif /* MULTICAST */ - if_initname(ifp, device_get_name(device), device_get_unit(device)); - ifp->if_init = wlinit; - ifp->if_start = wlstart; - ifp->if_ioctl = wlioctl; - ifp->if_snd.ifq_maxlen = ifqmaxlen; - /* no entries - ifp->if_done - ifp->if_reset - */ - ether_ifattach(ifp, eaddr); - - if_printf(ifp, "NWID 0x%02x%02x", sc->nwid[0], sc->nwid[1]); - if (sc->freq24) - printf(", Freq %d MHz",sc->freq24); /* 2.4 Gz */ - printf("\n"); /* 2.4 Gz */ - - bus_setup_intr(device, sc->res_irq, INTR_TYPE_NET, NULL, wlintr, sc, &sc->intr_cookie); - - if (bootverbose) - wldump(sc); - return (0); -} - -static int -wldetach(device_t device) -{ - struct wl_softc *sc = device_get_softc(device); - struct ifnet *ifp; - - ifp = sc->ifp; - ether_ifdetach(ifp); - - WL_LOCK(sc); - - /* reset the board */ - sc->hacr = HACR_RESET; - CMD(sc); - sc->hacr = HACR_DEFAULT; - CMD(sc); - callout_stop(&sc->watchdog_timer); - WL_UNLOCK(sc); - callout_drain(&sc->watchdog_timer); - - if (sc->intr_cookie != NULL) { - bus_teardown_intr(device, sc->res_irq, sc->intr_cookie); - sc->intr_cookie = NULL; - } - - wl_deallocate_resources(device); - if_free(ifp); - mtx_destroy(&sc->wl_mtx); - return (0); -} - -static int -wl_allocate_resources(device_t device) -{ - struct wl_softc *sc = device_get_softc(device); - int ports = 16; /* Number of ports */ - - sc->res_ioport = bus_alloc_resource_anywhere(device, SYS_RES_IOPORT, - &sc->rid_ioport, ports, RF_ACTIVE); - if (sc->res_ioport == NULL) - goto errexit; - - sc->res_irq = bus_alloc_resource_any(device, SYS_RES_IRQ, - &sc->rid_irq, RF_SHAREABLE|RF_ACTIVE); - if (sc->res_irq == NULL) - goto errexit; - return (0); - -errexit: - wl_deallocate_resources(device); - return (ENXIO); -} - -static int -wl_deallocate_resources(device_t device) -{ - struct wl_softc *sc = device_get_softc(device); - - if (sc->res_irq != 0) { - bus_release_resource(device, SYS_RES_IRQ, - sc->rid_irq, sc->res_irq); - sc->res_irq = 0; - } - if (sc->res_ioport != 0) { - bus_release_resource(device, SYS_RES_IOPORT, - sc->rid_ioport, sc->res_ioport); - sc->res_ioport = 0; - } - return (0); -} - -/* - * Print out interesting information about the 82596. - */ -static void -wldump(struct wl_softc *sc) -{ - int i; - - printf("hasr %04x\n", WL_READ_2(sc, HASR)); - - printf("scb at %04x:\n ", OFFSET_SCB); - WL_WRITE_2(sc, PIOR1, OFFSET_SCB); - for (i = 0; i < 8; i++) - printf("%04x ", WL_READ_2(sc, PIOP1)); - printf("\n"); - - printf("cu at %04x:\n ", OFFSET_CU); - WL_WRITE_2(sc, PIOR1, OFFSET_CU); - for (i = 0; i < 8; i++) - printf("%04x ", WL_READ_2(sc, PIOP1)); - printf("\n"); - - printf("tbd at %04x:\n ", OFFSET_TBD); - WL_WRITE_2(sc, PIOR1, OFFSET_TBD); - for (i = 0; i < 4; i++) - printf("%04x ", WL_READ_2(sc, PIOP1)); - printf("\n"); -} - -/* Initialize the Modem Management Controller */ -static void -wlinitmmc(struct wl_softc *sc) -{ - int configured; - int mode = sc->mode; - int i; /* 2.4 Gz */ - - /* enter 8 bit operation */ - sc->hacr = (HACR_DEFAULT & ~HACR_16BITS); - CMD(sc); - - configured = sc->psa[WLPSA_CONFIGURED] & 1; - - /* - * Set default modem control parameters. Taken from NCR document - * 407-0024326 Rev. A - */ - MMC_WRITE(MMC_JABBER_ENABLE, 0x01); - MMC_WRITE(MMC_ANTEN_SEL, 0x02); - MMC_WRITE(MMC_IFS, 0x20); - MMC_WRITE(MMC_MOD_DELAY, 0x04); - MMC_WRITE(MMC_JAM_TIME, 0x38); - MMC_WRITE(MMC_DECAY_PRM, 0x00); /* obsolete ? */ - MMC_WRITE(MMC_DECAY_UPDAT_PRM, 0x00); - if (!configured) { - MMC_WRITE(MMC_LOOPT_SEL, 0x00); - if (sc->psa[WLPSA_COMPATNO] & 1) { - MMC_WRITE(MMC_THR_PRE_SET, 0x01); /* 0x04 for AT and 0x01 for MCA */ - } else { - MMC_WRITE(MMC_THR_PRE_SET, 0x04); /* 0x04 for AT and 0x01 for MCA */ - } - MMC_WRITE(MMC_QUALITY_THR, 0x03); - } else { - /* use configuration defaults from parameter storage area */ - if (sc->psa[WLPSA_NWIDENABLE] & 1) { - if ((mode & (MOD_PROM | MOD_ENAL)) && wl_ignore_nwid) { - MMC_WRITE(MMC_LOOPT_SEL, 0x40); - } else { - MMC_WRITE(MMC_LOOPT_SEL, 0x00); - } - } else { - MMC_WRITE(MMC_LOOPT_SEL, 0x40); /* disable network id check */ - } - MMC_WRITE(MMC_THR_PRE_SET, sc->psa[WLPSA_THRESH]); - MMC_WRITE(MMC_QUALITY_THR, sc->psa[WLPSA_QUALTHRESH]); - } - MMC_WRITE(MMC_FREEZE, 0x00); - MMC_WRITE(MMC_ENCR_ENABLE, 0x00); - - MMC_WRITE(MMC_NETW_ID_L,sc->nwid[1]); /* set NWID */ - MMC_WRITE(MMC_NETW_ID_H,sc->nwid[0]); - - /* enter normal 16 bit mode operation */ - sc->hacr = HACR_DEFAULT; - CMD(sc); - CMD(sc); /* virtualpc1 needs this! */ - - if (sc->psa[WLPSA_COMPATNO]== /* 2.4 Gz: half-card ver */ - WLPSA_COMPATNO_WL24B) { /* 2.4 Gz */ - i=sc->chan24<<4; /* 2.4 Gz: position ch # */ - MMC_WRITE(MMC_EEADDR,i+0x0f); /* 2.4 Gz: named ch, wc=16 */ - MMC_WRITE(MMC_EECTRL,MMC_EECTRL_DWLD+ /* 2.4 Gz: Download Synths */ - MMC_EECTRL_EEOP_READ); /* 2.4 Gz: Read EEPROM */ - for (i=0; i<1000; ++i) { /* 2.4 Gz: wait for download */ - DELAY(40); /* 2.4 Gz */ - if ((wlmmcread(sc, MMC_EECTRLstat) /* 2.4 Gz: check DWLD and */ - &(MMC_EECTRLstat_DWLD /* 2.4 Gz: EEBUSY */ - +MMC_EECTRLstat_EEBUSY))==0) /* 2.4 Gz: */ - break; /* 2.4 Gz: download finished */ - } /* 2.4 Gz */ - if (i==1000) printf("wl: synth load failed\n"); /* 2.4 Gz */ - MMC_WRITE(MMC_EEADDR,0x61); /* 2.4 Gz: default pwr, wc=2 */ - MMC_WRITE(MMC_EECTRL,MMC_EECTRL_DWLD+ /* 2.4 Gz: Download Xmit Pwr */ - MMC_EECTRL_EEOP_READ); /* 2.4 Gz: Read EEPROM */ - for (i=0; i<1000; ++i) { /* 2.4 Gz: wait for download */ - DELAY(40); /* 2.4 Gz */ - if ((wlmmcread(sc, MMC_EECTRLstat) /* 2.4 Gz: check DWLD and */ - &(MMC_EECTRLstat_DWLD /* 2.4 Gz: EEBUSY */ - +MMC_EECTRLstat_EEBUSY))==0) /* 2.4 Gz: */ - break; /* 2.4 Gz: download finished */ - } /* 2.4 Gz */ - if (i==1000) printf("wl: xmit pwr load failed\n"); /* 2.4 Gz */ - MMC_WRITE(MMC_ANALCTRL, /* 2.4 Gz: EXT ant+polarity */ - MMC_ANALCTRL_ANTPOL + /* 2.4 Gz: */ - MMC_ANALCTRL_EXTANT); /* 2.4 Gz: */ - i=sc->chan24<<4; /* 2.4 Gz: position ch # */ - MMC_WRITE(MMC_EEADDR,i); /* 2.4 Gz: get frequency */ - MMC_WRITE(MMC_EECTRL, /* 2.4 Gz: EEPROM read */ - MMC_EECTRL_EEOP_READ); /* 2.4 Gz: */ - DELAY(40); /* 2.4 Gz */ - i = wlmmcread(sc, MMC_EEDATALrv) /* 2.4 Gz: freq val */ - + (wlmmcread(sc, MMC_EEDATAHrv)<<8); /* 2.4 Gz */ - sc->freq24 = (i>>6)+2400; /* 2.4 Gz: save real freq */ - } -} - -/* - * wlinit: - * - * Another routine that interfaces the "if" layer to this driver. - * Simply resets the structures that are used by "upper layers". - * As well as calling wlhwrst that does reset the WaveLAN board. - * - * input : softc pointer for this interface - * output : structures (if structs) and board are reset - * - */ -static void -wlinit(void *xsc) -{ - struct wl_softc *sc = xsc; - - WL_LOCK(sc); - wlinit_locked(sc); - WL_UNLOCK(sc); -} - -static void -wlinit_locked(struct wl_softc *sc) -{ - struct ifnet *ifp = sc->ifp; - int stat; - -#ifdef WLDEBUG - if (sc->ifp->if_flags & IFF_DEBUG) - if_printf(ifp, "entered wlinit()\n"); -#endif - WL_LOCK_ASSERT(sc); - if ((stat = wlhwrst(sc)) == TRUE) { - sc->ifp->if_drv_flags |= IFF_DRV_RUNNING; /* same as DSF_RUNNING */ - /* - * OACTIVE is used by upper-level routines - * and must be set - */ - sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; /* same as tbusy below */ - - sc->flags |= DSF_RUNNING; - sc->tbusy = 0; - callout_stop(&sc->watchdog_timer); - - wlstart_locked(ifp); - } else { - if_printf(ifp, "init(): trouble resetting board.\n"); - } -} - -/* - * wlhwrst: - * - * This routine resets the WaveLAN board that corresponds to the - * board number passed in. - * - * input : board number to do a hardware reset - * output : board is reset - * - */ -static int -wlhwrst(struct wl_softc *sc) -{ - -#ifdef WLDEBUG - if (sc->ifp->if_flags & IFF_DEBUG) - if_printf(sc->ifp, "entered wlhwrst()\n"); -#endif - sc->hacr = HACR_RESET; - CMD(sc); /* reset the board */ - - /* clear reset command and set PIO#1 in autoincrement mode */ - sc->hacr = HACR_DEFAULT; - CMD(sc); - -#ifdef WLDEBUG - if (sc->ifp->if_flags & IFF_DEBUG) - wlmmcstat(sc); /* Display MMC registers */ -#endif /* WLDEBUG */ - wlbldcu(sc); /* set up command unit structures */ - - if (wldiag(sc) == 0) - return(0); - - if (wlconfig(sc) == 0) - return(0); - /* - * insert code for loopback test here - */ - wlrustrt(sc); /* start receive unit */ - - /* enable interrupts */ - sc->hacr = (HACR_DEFAULT | HACR_INTRON); - CMD(sc); - - return(1); -} - -/* - * wlbldcu: - * - * This function builds up the command unit structures. It inits - * the scp, iscp, scb, cb, tbd, and tbuf. - * - */ -static void -wlbldcu(struct wl_softc *sc) -{ - scp_t scp; - iscp_t iscp; - scb_t scb; - ac_t cb; - tbd_t tbd; - int i; - - bzero(&scp, sizeof(scp)); - scp.scp_sysbus = 0; - scp.scp_iscp = OFFSET_ISCP; - scp.scp_iscp_base = 0; - WL_WRITE_2(sc, PIOR1, OFFSET_SCP); - WL_WRITE_MULTI_2(sc, PIOP1, &scp, sizeof(scp_t)/2); - - bzero(&iscp, sizeof(iscp)); - iscp.iscp_busy = 1; - iscp.iscp_scb_offset = OFFSET_SCB; - iscp.iscp_scb = 0; - iscp.iscp_scb_base = 0; - WL_WRITE_2(sc, PIOR1, OFFSET_ISCP); - WL_WRITE_MULTI_2(sc, PIOP1, &iscp, sizeof(iscp_t)/2); - - scb.scb_status = 0; - scb.scb_command = SCB_RESET; - scb.scb_cbl_offset = OFFSET_CU; - scb.scb_rfa_offset = OFFSET_RU; - scb.scb_crcerrs = 0; - scb.scb_alnerrs = 0; - scb.scb_rscerrs = 0; - scb.scb_ovrnerrs = 0; - WL_WRITE_2(sc, PIOR1, OFFSET_SCB); - WL_WRITE_MULTI_2(sc, PIOP1, &scb, sizeof(scb_t)/2); - - SET_CHAN_ATTN(sc); - - WL_WRITE_2(sc, PIOR0, OFFSET_ISCP + 0); /* address of iscp_busy */ - for (i = 1000000; WL_READ_2(sc, PIOP0) && (i-- > 0); ) - continue; - if (i <= 0) - device_printf(sc->dev, "bldcu(): iscp_busy timeout.\n"); - WL_WRITE_2(sc, PIOR0, OFFSET_SCB + 0); /* address of scb_status */ - for (i = STATUS_TRIES; i-- > 0; ) { - if (WL_READ_2(sc, PIOP0) == (SCB_SW_CX|SCB_SW_CNA)) - break; - } - if (i <= 0) - device_printf(sc->dev, "bldcu(): not ready after reset.\n"); - wlack(sc); - - cb.ac_status = 0; - cb.ac_command = AC_CW_EL; /* NOP */ - cb.ac_link_offset = OFFSET_CU; - WL_WRITE_2(sc, PIOR1, OFFSET_CU); - WL_WRITE_MULTI_2(sc, PIOP1, &cb, 6/2); - - tbd.act_count = 0; - tbd.next_tbd_offset = I82586NULL; - tbd.buffer_addr = 0; - tbd.buffer_base = 0; - WL_WRITE_2(sc, PIOR1, OFFSET_TBD); - WL_WRITE_MULTI_2(sc, PIOP1, &tbd, sizeof(tbd_t)/2); -} - -/* - * wlstart: - * - * send a packet - * - * input : board number - * output : stuff sent to board if any there - * - */ -static void -wlstart(struct ifnet *ifp) -{ - struct wl_softc *sc = ifp->if_softc; - - WL_LOCK(sc); - wlstart_locked(ifp); - WL_UNLOCK(sc); -} - -static void -wlstart_locked(struct ifnet *ifp) -{ - struct mbuf *m; - struct wl_softc *sc = ifp->if_softc; - int scb_status, cu_status, scb_command; - - WL_LOCK_ASSERT(sc); -#ifdef WLDEBUG - if (sc->ifp->if_flags & IFF_DEBUG) - if_printf(ifp, "entered wlstart()\n"); -#endif - - WL_WRITE_2(sc, PIOR1, OFFSET_CU); - cu_status = WL_READ_2(sc, PIOP1); - WL_WRITE_2(sc, PIOR0,OFFSET_SCB + 0); /* scb_status */ - scb_status = WL_READ_2(sc, PIOP0); - WL_WRITE_2(sc, PIOR0, OFFSET_SCB + 2); - scb_command = WL_READ_2(sc, PIOP0); - - /* - * don't need OACTIVE check as tbusy here checks to see - * if we are already busy - */ - if (sc->tbusy) { - if ((scb_status & 0x0700) == SCB_CUS_IDLE && - (cu_status & AC_SW_B) == 0){ - sc->tbusy = 0; - callout_stop(&sc->watchdog_timer); - sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - /* - * This is probably just a race. The xmt'r is just - * became idle but WE have masked interrupts so ... - */ -#ifdef WLDEBUG - if_printf(ifp, "CU idle, scb %04x %04x cu %04x\n", - scb_status, scb_command, cu_status); -#endif - if (xmt_watch) printf("!!"); - } else { - return; /* genuinely still busy */ - } - } else if ((scb_status & 0x0700) == SCB_CUS_ACTV || - (cu_status & AC_SW_B)){ -#ifdef WLDEBUG - if_printf(ifp, "CU unexpectedly busy; scb %04x cu %04x\n", - scb_status, cu_status); -#endif - if (xmt_watch) - if_printf(ifp, "busy?!\n"); - return; /* hey, why are we busy? */ - } - - /* get ourselves some data */ - IF_DEQUEUE(&ifp->if_snd, m); - if (m != NULL) { - /* let BPF see it before we commit it */ - BPF_MTAP(ifp, m); - sc->tbusy++; - /* set the watchdog timer so that if the board - * fails to interrupt we will restart - */ - /* try 10 ms, not very long */ - callout_reset(&sc->watchdog_timer, hz / 100, wlwatchdog, sc); - sc->ifp->if_drv_flags |= IFF_DRV_OACTIVE; - if_inc_counter(sc->ifp, IFCOUNTER_OPACKETS, 1); - wlxmt(sc, m); - } else { - sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - } - return; -} - -/* - * wlread: - * - * This routine does the actual copy of data (including ethernet header - * structure) from the WaveLAN to an mbuf chain that will be passed up - * to the "if" (network interface) layer. NOTE: we currently - * don't handle trailer protocols, so if that is needed, it will - * (at least in part) be added here. For simplicities sake, this - * routine copies the receive buffers from the board into a local (stack) - * buffer until the frame has been copied from the board. Once in - * the local buffer, the contents are copied to an mbuf chain that - * is then enqueued onto the appropriate "if" queue. - * - * input : board number, and a frame descriptor address - * output : the packet is put into an mbuf chain, and passed up - * assumes : if any errors occur, packet is "dropped on the floor" - * - */ -static int -wlread(struct wl_softc *sc, u_short fd_p) -{ - struct ifnet *ifp = sc->ifp; - fd_t fd; - struct ether_header *eh; - struct mbuf *m; - rbd_t rbd; - u_char *mb_p; - u_short mlen, len; - u_short bytes_in_msg, bytes_in_mbuf, bytes; - - WL_LOCK_ASSERT(sc); - -#ifdef WLDEBUG - if (sc->ifp->if_flags & IFF_DEBUG) - if_printf(ifp, "entered wlread()\n"); -#endif - if (!((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING))) { - if_printf(ifp, "read(): board is not running.\n"); - sc->hacr &= ~HACR_INTRON; - CMD(sc); /* turn off interrupts */ - } - - /* - * Collect message size. - */ - WL_WRITE_2(sc, PIOR1, fd_p); - WL_READ_MULTI_2(sc, PIOP1, &fd, sizeof(fd_t)/2); - if (fd.rbd_offset == I82586NULL) { - if (wlhwrst(sc) != TRUE) { - sc->hacr &= ~HACR_INTRON; - CMD(sc); /* turn off interrupts */ - if_printf(ifp, "read(): hwrst trouble.\n"); - } - return 0; - } - - WL_WRITE_2(sc, PIOR1, fd.rbd_offset); - WL_READ_MULTI_2(sc, PIOP1, &rbd, sizeof(rbd_t)/2); - bytes_in_msg = rbd.status & RBD_SW_COUNT; - - /* - * Allocate a cluster'd mbuf to receive the packet. - */ - m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); - if (m == NULL) { - if (wlhwrst(sc) != TRUE) { - sc->hacr &= ~HACR_INTRON; - CMD(sc); /* turn off interrupts */ - if_printf(ifp, "read(): hwrst trouble.\n"); - } - return 0; - } - m->m_pkthdr.len = m->m_len = MCLBYTES; - m_adj(m, ETHER_ALIGN); /* align IP header */ - - /* - * Collect the message data. - */ - mlen = 0; - mb_p = mtod(m, u_char *); - bytes_in_mbuf = m->m_len; - - /* Put the ethernet header inside the mbuf. */ - bcopy(&fd.destination[0], mb_p, 14); - mb_p += 14; - mlen += 14; - bytes_in_mbuf -= 14; - - bytes = min(bytes_in_mbuf, bytes_in_msg); - for (;;) { - if (bytes & 1) { - len = bytes + 1; - } else { - len = bytes; - } - WL_WRITE_2(sc, PIOR1, rbd.buffer_addr); - WL_READ_MULTI_2(sc, PIOP1, mb_p, len/2); - mlen += bytes; - - if (bytes > bytes_in_mbuf) { - /* XXX something wrong, a packet should fit in 1 cluster */ - m_freem(m); - if_printf(ifp, "read(): packet too large (%u > %u)\n", - bytes, bytes_in_mbuf); - if (wlhwrst(sc) != TRUE) { - sc->hacr &= ~HACR_INTRON; - CMD(sc); /* turn off interrupts */ - if_printf(ifp, "read(): hwrst trouble.\n"); - } - return 0; - } - mb_p += bytes; - bytes_in_mbuf -= bytes; - bytes_in_msg -= bytes; - if (bytes_in_msg == 0) { - if (rbd.status & RBD_SW_EOF || rbd.next_rbd_offset == I82586NULL) { - break; - } - WL_WRITE_2(sc, PIOR1, rbd.next_rbd_offset); - WL_READ_MULTI_2(sc, PIOP1, &rbd, sizeof(rbd_t)/2); - bytes_in_msg = rbd.status & RBD_SW_COUNT; - } else { - rbd.buffer_addr += bytes; - } - - bytes = min(bytes_in_mbuf, bytes_in_msg); - } - - m->m_pkthdr.len = m->m_len = mlen; - m->m_pkthdr.rcvif = ifp; - - /* - * If hw is in promiscuous mode (note that I said hardware, not if - * IFF_PROMISC is set in ifnet flags), then if this is a unicast - * packet and the MAC dst is not us, drop it. This check in normally - * inside ether_input(), but IFF_MULTI causes hw promisc without - * a bpf listener, so this is wrong. - * Greg Troxel , 1998-08-07 - */ - /* - * TBD: also discard packets where NWID does not match. - * However, there does not appear to be a way to read the nwid - * for a received packet. -gdt 1998-08-07 - */ - /* XXX verify mbuf length */ - eh = mtod(m, struct ether_header *); - if ( -#ifdef WL_USE_IFNET_PROMISC_CHECK /* not defined */ - (sc->ifp->if_flags & (IFF_PROMISC|IFF_ALLMULTI)) -#else - /* hw is in promisc mode if this is true */ - (sc->mode & (MOD_PROM | MOD_ENAL)) -#endif - && - (eh->ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */ - bcmp(eh->ether_dhost, IF_LLADDR(sc->ifp), - sizeof(eh->ether_dhost)) != 0 ) { - m_freem(m); - return 1; - } - -#ifdef WLDEBUG - if (sc->ifp->if_flags & IFF_DEBUG) - if_printf(ifp, "wlrecv %u bytes\n", mlen); -#endif - -#ifdef WLCACHE - wl_cache_store(sc, eh, m); -#endif - - /* - * received packet is now in a chain of mbuf's. next step is - * to pass the packet upwards. - */ - WL_UNLOCK(sc); - (*ifp->if_input)(ifp, m); - WL_LOCK(sc); - return 1; -} - -/* - * wlioctl: - * - * This routine processes an ioctl request from the "if" layer - * above. - * - * input : pointer the appropriate "if" struct, command, and data - * output : based on command appropriate action is taken on the - * WaveLAN board(s) or related structures - * return : error is returned containing exit conditions - * - */ -static int -wlioctl(struct ifnet *ifp, u_long cmd, caddr_t data) -{ - struct ifreq *ifr = (struct ifreq *)data; - struct wl_softc *sc = ifp->if_softc; - short mode = 0; - int error = 0; - struct thread *td = curthread; /* XXX */ - int irq, irqval, i, isroot; - char psa_buf[0x40]; - char eeprom_buf[0x80]; -#ifdef WLCACHE - size_t size; - char * cpt; -#endif - -#ifdef WLDEBUG - if (sc->ifp->if_flags & IFF_DEBUG) - if_printf(ifp, "entered wlioctl()\n"); -#endif - switch (cmd) { - case SIOCSIFFLAGS: - WL_LOCK(sc); - if (ifp->if_flags & IFF_ALLMULTI) { - mode |= MOD_ENAL; - } - if (ifp->if_flags & IFF_PROMISC) { - mode |= MOD_PROM; - } - if (ifp->if_flags & IFF_LINK0) { - mode |= MOD_PROM; - } - /* - * force a complete reset if the receive multicast/ - * promiscuous mode changes so that these take - * effect immediately. - * - */ - if (sc->mode != mode) { - sc->mode = mode; - if (sc->flags & DSF_RUNNING) { - sc->flags &= ~DSF_RUNNING; - wlinit_locked(sc); - } - } - /* if interface is marked DOWN and still running then - * stop it. - */ - if ((ifp->if_flags & IFF_UP) == 0 && sc->flags & DSF_RUNNING) { - if_printf(ifp, "ioctl(): board is not running\n"); - sc->flags &= ~DSF_RUNNING; - sc->hacr &= ~HACR_INTRON; - CMD(sc); /* turn off interrupts */ - } - /* else if interface is UP and RUNNING, start it - */ - else if (ifp->if_flags & IFF_UP && (sc->flags & DSF_RUNNING) == 0) { - wlinit_locked(sc); - } - - /* if WLDEBUG set on interface, then printf rf-modem regs - */ - if (ifp->if_flags & IFF_DEBUG) - wlmmcstat(sc); - WL_UNLOCK(sc); - break; -#if MULTICAST - case SIOCADDMULTI: - case SIOCDELMULTI: - - wlinit(sc); - break; -#endif /* MULTICAST */ - - /* DEVICE SPECIFIC */ - - - /* copy the PSA out to the caller */ - case SIOCGWLPSA: - /* work out if they're root */ - isroot = (priv_check(td, PRIV_NET80211_GETKEY) == 0); - - bzero(psa_buf, sizeof(psa_buf)); - WL_LOCK(sc); - for (i = 0; i < 0x40; i++) { - /* don't hand the DES key out to non-root users */ - if ((i > WLPSA_DESKEY) && (i < (WLPSA_DESKEY + 8)) && !isroot) - continue; - psa_buf[i] = sc->psa[i]; - } - WL_UNLOCK(sc); - - error = copyout(psa_buf, ifr->ifr_data, sizeof(psa_buf)); - break; - - - /* copy the PSA in from the caller; we only copy _some_ values */ - case SIOCSWLPSA: - /* root only */ - if ((error = priv_check(td, PRIV_DRIVER))) - break; - - error = copyin(ifr->ifr_data, psa_buf, sizeof(psa_buf)); - if (error) - break; - - /* check IRQ value */ - irqval = psa_buf[WLPSA_IRQNO]; - for (irq = 15; irq >= 0; irq--) - if (irqvals[irq] == irqval) - break; - if (irq == 0) /* oops */ - break; - WL_LOCK(sc); - /* new IRQ */ - sc->psa[WLPSA_IRQNO] = irqval; - - /* local MAC */ - for (i = 0; i < 6; i++) - sc->psa[WLPSA_LOCALMAC + i] = psa_buf[WLPSA_LOCALMAC + i]; - - /* MAC select */ - sc->psa[WLPSA_MACSEL] = psa_buf[WLPSA_MACSEL]; - - /* default nwid */ - sc->psa[WLPSA_NWID] = psa_buf[WLPSA_NWID]; - sc->psa[WLPSA_NWID + 1] = psa_buf[WLPSA_NWID + 1]; - - wlsetpsa(sc); /* update the PSA */ - WL_UNLOCK(sc); - break; - - - /* get the current NWID out of the sc since we stored it there */ - case SIOCGWLCNWID: - WL_LOCK(sc); - ifr->ifr_data = (caddr_t) (sc->nwid[0] << 8 | sc->nwid[1]); - WL_UNLOCK(sc); - break; - - - /* - * change the nwid dynamically. This - * ONLY changes the radio modem and does not - * change the PSA. - * - * 2 steps: - * 1. save in softc "soft registers" - * 2. save in radio modem (MMC) - */ - case SIOCSWLCNWID: - /* root only */ - if ((error = priv_check(td, PRIV_DRIVER))) - break; - WL_LOCK(sc); - if (!(ifp->if_flags & IFF_UP)) { - error = EIO; /* only allowed while up */ - } else { - /* - * soft c nwid shadows radio modem setting - */ - sc->nwid[0] = (int)ifr->ifr_data >> 8; - sc->nwid[1] = (int)ifr->ifr_data & 0xff; - MMC_WRITE(MMC_NETW_ID_L,sc->nwid[1]); - MMC_WRITE(MMC_NETW_ID_H,sc->nwid[0]); - } - WL_UNLOCK(sc); - break; - - /* copy the EEPROM in 2.4 Gz WaveMODEM out to the caller */ - case SIOCGWLEEPROM: - /* root only */ - if ((error = priv_check(td, PRIV_DRIVER))) - break; - - bzero(eeprom_buf, sizeof(eeprom_buf)); - WL_LOCK(sc); - for (i=0x00; i<0x80; ++i) { /* 2.4 Gz: size of EEPROM */ - MMC_WRITE(MMC_EEADDR,i); /* 2.4 Gz: get frequency */ - MMC_WRITE(MMC_EECTRL, /* 2.4 Gz: EEPROM read */ - MMC_EECTRL_EEOP_READ); /* 2.4 Gz: */ - DELAY(40); /* 2.4 Gz */ - eeprom_buf[2 * i] = /* 2.4 Gz: pass low byte of */ - wlmmcread(sc, MMC_EEDATALrv); /* 2.4 Gz: EEPROM word */ - eeprom_buf[2 * i + 1] = /* 2.4 Gz: pass hi byte of */ - wlmmcread(sc, MMC_EEDATALrv); /* 2.4 Gz: EEPROM word */ - } - WL_UNLOCK(sc); - error = copyout(ifr->ifr_data, eeprom_buf, sizeof(eeprom_buf)); - break; - -#ifdef WLCACHE - /* zero (Delete) the wl cache */ - case SIOCDWLCACHE: - /* root only */ - if ((error = priv_check(td, PRIV_DRIVER))) - break; - WL_LOCK(sc); - wl_cache_zero(sc); - WL_UNLOCK(sc); - break; - - /* read out the number of used cache elements */ - case SIOCGWLCITEM: - WL_LOCK(sc); - ifr->ifr_data = (caddr_t) sc->w_sigitems; - WL_UNLOCK(sc); - break; - - /* read out the wl cache */ - case SIOCGWLCACHE: - WL_LOCK(sc); - size = sc->w_sigitems * sizeof(struct w_sigcache); - cpt = malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO); - if (cpt == NULL) { - WL_UNLOCK(sc); - return (ENOMEM); - } - - bcopy(sc->w_sigcache, cpt, size); - WL_UNLOCK(sc); - - error = copyout(cpt, ifr->ifr_data, size); - free(cpt, M_DEVBUF); - break; -#endif - - default: - error = ether_ioctl(ifp, cmd, data); - break; - } - return (error); -} - -/* - * wlwatchdog(): - * - * Called if the timer set in wlstart expires before an interrupt is received - * from the wavelan. It seems to lose interrupts sometimes. - * The watchdog routine gets called if the transmitter failed to interrupt - * - * input : which board is timing out - * output : board reset - * - */ -static void -wlwatchdog(void *vsc) -{ - struct wl_softc *sc = vsc; - - log(LOG_ERR, "%s: wavelan device timeout on xmit\n", sc->ifp->if_xname); - if_inc_counter(sc->ifp, IFCOUNTER_OERRORS, 1); - wlinit_locked(sc); -} - -/* - * wlintr: - * - * This function is the interrupt handler for the WaveLAN - * board. This routine will be called whenever either a packet - * is received, or a packet has successfully been transferred and - * the unit is ready to transmit another packet. - * - * input : board number that interrupted - * output : either a packet is received, or a packet is transferred - * - */ -static void -wlintr(void *arg) -{ - struct wl_softc *sc = (struct wl_softc *)arg; - int ac_status; - u_short int_type, int_type1; - - WL_LOCK(sc); -#ifdef WLDEBUG - if (sc->ifp->if_flags & IFF_DEBUG) - if_printf(sc->ifp, "wlintr() called\n"); -#endif - - if ((int_type = WL_READ_2(sc, HASR)) & HASR_MMC_INTR) { - /* handle interrupt from the modem management controller */ - /* This will clear the interrupt condition */ - (void) wlmmcread(sc, MMC_DCE_STATUS); /* ignored for now */ - } - - if (!(int_type & HASR_INTR)){ /* return if no interrupt from 82586 */ - /* commented out. jrb. it happens when reinit occurs - printf("wlintr: int_type %x, dump follows\n", int_type); - wldump(sc); - */ - WL_UNLOCK(sc); - return; - } - - if (gathersnr) - getsnr(sc); - for (;;) { - WL_WRITE_2(sc, PIOR0, OFFSET_SCB + 0); /* get scb status */ - int_type = (WL_READ_2(sc, PIOP0) & SCB_SW_INT); - if (int_type == 0) /* no interrupts left */ - break; - - int_type1 = wlack(sc); /* acknowledge interrupt(s) */ - /* make sure no bits disappeared (others may appear) */ - if ((int_type & int_type1) != int_type) - printf("wlack() int bits disappeared : %04x != int_type %04x\n", - int_type1, int_type); - int_type = int_type1; /* go with the new status */ - /* - * incoming packet - */ - if (int_type & SCB_SW_FR) { - if_inc_counter(sc->ifp, IFCOUNTER_IPACKETS, 1); - wlrcv(sc); - } - /* - * receiver not ready - */ - if (int_type & SCB_SW_RNR) { - if_inc_counter(sc->ifp, IFCOUNTER_IERRORS, 1); -#ifdef WLDEBUG - if (sc->ifp->if_flags & IFF_DEBUG) - if_printf(sc->ifp, "intr(): receiver overrun! begin_fd = %x\n", - sc->begin_fd); -#endif - wlrustrt(sc); - } - /* - * CU not ready - */ - if (int_type & SCB_SW_CNA) { - /* - * At present, we don't care about CNA's. We - * believe they are a side effect of XMT. - */ - } - if (int_type & SCB_SW_CX) { - /* - * At present, we only request Interrupt for - * XMT. - */ - WL_WRITE_2(sc, PIOR1, OFFSET_CU); /* get command status */ - ac_status = WL_READ_2(sc, PIOP1); - - if (xmt_watch) { /* report some anomalies */ - - if (sc->tbusy == 0) { - if_printf(sc->ifp, "xmt intr but not busy, CU %04x\n", - ac_status); - } - if (ac_status == 0) { - if_printf(sc->ifp, "xmt intr but ac_status == 0\n"); - } - if (ac_status & AC_SW_A) { - if_printf(sc->ifp, "xmt aborted\n"); - } -#ifdef notdef - if (ac_status & TC_CARRIER) { - if_printf(sc->ifp, "no carrier\n"); - } -#endif /* notdef */ - if (ac_status & TC_CLS) { - if_printf(sc->ifp, "no CTS\n"); - } - if (ac_status & TC_DMA) { - if_printf(sc->ifp, "DMA underrun\n"); - } - if (ac_status & TC_DEFER) { - if_printf(sc->ifp, "xmt deferred\n"); - } - if (ac_status & TC_SQE) { - if_printf(sc->ifp, "heart beat\n"); - } - if (ac_status & TC_COLLISION) { - if_printf(sc->ifp, "too many collisions\n"); - } - } - /* if the transmit actually failed, or returned some status */ - if ((!(ac_status & AC_SW_OK)) || (ac_status & 0xfff)) { - if (ac_status & (TC_COLLISION | TC_CLS | TC_DMA)) { - if_inc_counter(sc->ifp, IFCOUNTER_OERRORS, 1); - } - /* count collisions */ - if_inc_counter(sc->ifp, IFCOUNTER_COLLISIONS, (ac_status & 0xf)); - /* if TC_COLLISION set and collision count zero, 16 collisions */ - if ((ac_status & 0x20) == 0x20) { - if_inc_counter(sc->ifp, IFCOUNTER_COLLISIONS, 0x10); - } - } - sc->tbusy = 0; - callout_stop(&sc->watchdog_timer); - sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - wlstart_locked(sc->ifp); - } - } - WL_UNLOCK(sc); - return; -} - -/* - * wlrcv: - * - * This routine is called by the interrupt handler to initiate a - * packet transfer from the board to the "if" layer above this - * driver. This routine checks if a buffer has been successfully - * received by the WaveLAN. If so, the routine wlread is called - * to do the actual transfer of the board data (including the - * ethernet header) into a packet (consisting of an mbuf chain). - * - * input : number of the board to check - * output : if a packet is available, it is "sent up" - * - */ -static void -wlrcv(struct wl_softc *sc) -{ - u_short fd_p, status, offset, link_offset; - -#ifdef WLDEBUG - if (sc->ifp->if_flags & IFF_DEBUG) - if_printf(sc->ifp, "entered wlrcv()\n"); -#endif - for (fd_p = sc->begin_fd; fd_p != I82586NULL; fd_p = sc->begin_fd) { - - WL_WRITE_2(sc, PIOR0, fd_p + 0); /* address of status */ - status = WL_READ_2(sc, PIOP0); - WL_WRITE_2(sc, PIOR1, fd_p + 4); /* address of link_offset */ - link_offset = WL_READ_2(sc, PIOP1); - offset = WL_READ_2(sc, PIOP1); /* rbd_offset */ - if (status == 0xffff || offset == 0xffff /*I82586NULL*/) { - if (wlhwrst(sc) != TRUE) - if_printf(sc->ifp, "rcv(): hwrst ffff trouble.\n"); - return; - } else if (status & AC_SW_C) { - if (status == (RFD_DONE|RFD_RSC)) { - /* lost one */ -#ifdef WLDEBUG - if (sc->ifp->if_flags & IFF_DEBUG) - if_printf(sc->ifp, "RCV: RSC %x\n", status); -#endif - if_inc_counter(sc->ifp, IFCOUNTER_IERRORS, 1); - } else if (!(status & RFD_OK)) { - if_printf(sc->ifp, "RCV: !OK %x\n", status); - if_inc_counter(sc->ifp, IFCOUNTER_IERRORS, 1); - } else if (status & 0xfff) { /* can't happen */ - if_printf(sc->ifp, "RCV: ERRs %x\n", status); - if_inc_counter(sc->ifp, IFCOUNTER_IERRORS, 1); - } else if (!wlread(sc, fd_p)) - return; - - if (!wlrequeue(sc, fd_p)) { - /* abort on chain error */ - if (wlhwrst(sc) != TRUE) - if_printf(sc->ifp, "rcv(): hwrst trouble.\n"); - return; - } - sc->begin_fd = link_offset; - } else { - break; - } - } - return; -} - -/* - * wlrequeue: - * - * This routine puts rbd's used in the last receive back onto the - * free list for the next receive. - * - */ -static int -wlrequeue(struct wl_softc *sc, u_short fd_p) -{ - fd_t fd; - u_short l_rbdp, f_rbdp, rbd_offset; - - WL_WRITE_2(sc, PIOR0, fd_p + 6); - rbd_offset = WL_READ_2(sc, PIOP0); - if ((f_rbdp = rbd_offset) != I82586NULL) { - l_rbdp = f_rbdp; - for (;;) { - WL_WRITE_2(sc, PIOR0, l_rbdp + 0); /* address of status */ - if (WL_READ_2(sc, PIOP0) & RBD_SW_EOF) - break; - WL_WRITE_2(sc, PIOP0, 0); - WL_WRITE_2(sc, PIOR0, l_rbdp + 2); /* next_rbd_offset */ - if ((l_rbdp = WL_READ_2(sc, PIOP0)) == I82586NULL) - break; - } - WL_WRITE_2(sc, PIOP0, 0); - WL_WRITE_2(sc, PIOR0, l_rbdp + 2); /* next_rbd_offset */ - WL_WRITE_2(sc, PIOP0, I82586NULL); - WL_WRITE_2(sc, PIOR0, l_rbdp + 8); /* address of size */ - WL_WRITE_2(sc, PIOP0, WL_READ_2(sc, PIOP0) | AC_CW_EL); - WL_WRITE_2(sc, PIOR0, sc->end_rbd + 2); - WL_WRITE_2(sc, PIOP0, f_rbdp); /* end_rbd->next_rbd_offset */ - WL_WRITE_2(sc, PIOR0, sc->end_rbd + 8); /* size */ - WL_WRITE_2(sc, PIOP0, WL_READ_2(sc, PIOP0) & ~AC_CW_EL); - sc->end_rbd = l_rbdp; - } - - fd.status = 0; - fd.command = AC_CW_EL; - fd.link_offset = I82586NULL; - fd.rbd_offset = I82586NULL; - WL_WRITE_2(sc, PIOR1, fd_p); - WL_WRITE_MULTI_2(sc, PIOP1, &fd, 8/2); - - WL_WRITE_2(sc, PIOR1, sc->end_fd + 2); /* addr of command */ - WL_WRITE_2(sc, PIOP1, 0); /* command = 0 */ - WL_WRITE_2(sc, PIOP1, fd_p); /* end_fd->link_offset = fd_p */ - sc->end_fd = fd_p; - - return 1; -} - -#ifdef WLDEBUG -static int xmt_debug = 0; -#endif /* WLDEBUG */ - -/* - * wlxmt: - * - * This routine fills in the appropriate registers and memory - * locations on the WaveLAN board and starts the board off on - * the transmit. - * - * input : pointers to board of interest's softc and the mbuf - * output : board memory and registers are set for xfer and attention - * - */ -static void -wlxmt(struct wl_softc *sc, struct mbuf *m) -{ - u_short xmtdata_p = OFFSET_TBUF; - u_short xmtshort_p; - struct mbuf *tm_p = m; - struct ether_header *eh_p = mtod(m, struct ether_header *); - u_char *mb_p = mtod(m, u_char *) + sizeof(struct ether_header); - u_short count = m->m_len - sizeof(struct ether_header); - ac_t cb; - u_short tbd_p = OFFSET_TBD; - u_short len, clen = 0; - int spin; - -#ifdef WLDEBUG - if (sc->ifp->if_flags & IFF_DEBUG) - if_printf(sc->ifp, "entered wlxmt()\n"); -#endif - - cb.ac_status = 0; - cb.ac_command = (AC_CW_EL|AC_TRANSMIT|AC_CW_I); - cb.ac_link_offset = I82586NULL; - WL_WRITE_2(sc, PIOR1, OFFSET_CU); - WL_WRITE_MULTI_2(sc, PIOP1, &cb, 6/2); - WL_WRITE_2(sc, PIOP1, OFFSET_TBD); /* cb.cmd.transmit.tbd_offset */ - WL_WRITE_MULTI_2(sc, PIOP1, eh_p->ether_dhost, WAVELAN_ADDR_SIZE/2); - WL_WRITE_2(sc, PIOP1, eh_p->ether_type); - -#ifdef WLDEBUG - if (sc->ifp->if_flags & IFF_DEBUG) { - if (xmt_debug) { - printf("XMT mbuf: L%d @%p ", count, (void *)mb_p); - printf("ether type %x\n", eh_p->ether_type); - } - } -#endif /* WLDEBUG */ - WL_WRITE_2(sc, PIOR0, OFFSET_TBD); - WL_WRITE_2(sc, PIOP0, 0); /* act_count */ - WL_WRITE_2(sc, PIOR1, OFFSET_TBD + 4); - WL_WRITE_2(sc, PIOP1, xmtdata_p); /* buffer_addr */ - WL_WRITE_2(sc, PIOP1, 0); /* buffer_base */ - for (;;) { - if (count) { - if (clen + count > WAVELAN_MTU) - break; - if (count & 1) - len = count + 1; - else - len = count; - WL_WRITE_2(sc, PIOR1, xmtdata_p); - WL_WRITE_MULTI_2(sc, PIOP1, mb_p, len/2); - clen += count; - WL_WRITE_2(sc, PIOR0, tbd_p); /* address of act_count */ - WL_WRITE_2(sc, PIOP0, WL_READ_2(sc, PIOP0) + count); - xmtdata_p += len; - if ((tm_p = tm_p->m_next) == (struct mbuf *)0) - break; - if (count & 1) { - /* go to the next descriptor */ - WL_WRITE_2(sc, PIOR0, tbd_p + 2); - tbd_p += sizeof (tbd_t); - WL_WRITE_2(sc, PIOP0, tbd_p); /* next_tbd_offset */ - WL_WRITE_2(sc, PIOR0, tbd_p); - WL_WRITE_2(sc, PIOP0, 0); /* act_count */ - WL_WRITE_2(sc, PIOR1, tbd_p + 4); - WL_WRITE_2(sc, PIOP1, xmtdata_p); /* buffer_addr */ - WL_WRITE_2(sc, PIOP1, 0); /* buffer_base */ - /* at the end -> coallesce remaining mbufs */ - if (tbd_p == OFFSET_TBD + (N_TBD-1) * sizeof (tbd_t)) { - wlsftwsleaze(&count, &mb_p, &tm_p, sc); - continue; - } - /* next mbuf short -> coallesce as needed */ - if ( (tm_p->m_next == (struct mbuf *) 0) || -#define HDW_THRESHOLD 55 - tm_p->m_len > HDW_THRESHOLD) - /* ok */; - else { - wlhdwsleaze(&count, &mb_p, &tm_p, sc); - continue; - } - } - } else if ((tm_p = tm_p->m_next) == (struct mbuf *)0) - break; - count = tm_p->m_len; - mb_p = mtod(tm_p, u_char *); -#ifdef WLDEBUG - if (sc->ifp->if_flags & IFF_DEBUG) - if (xmt_debug) - printf("mbuf+ L%d @%p ", count, (void *)mb_p); -#endif /* WLDEBUG */ - } -#ifdef WLDEBUG - if (sc->ifp->if_flags & IFF_DEBUG) - if (xmt_debug) - printf("CLEN = %d\n", clen); -#endif /* WLDEBUG */ - WL_WRITE_2(sc, PIOR0, tbd_p); - if (clen < ETHERMIN) { - WL_WRITE_2(sc, PIOP0, WL_READ_2(sc, PIOP0) + ETHERMIN - clen); - WL_WRITE_2(sc, PIOR1, xmtdata_p); - for (xmtshort_p = xmtdata_p; clen < ETHERMIN; clen += 2) - WL_WRITE_2(sc, PIOP1, 0); - } - WL_WRITE_2(sc, PIOP0, WL_READ_2(sc, PIOP0) | TBD_SW_EOF); - WL_WRITE_2(sc, PIOR0, tbd_p + 2); - WL_WRITE_2(sc, PIOP0, I82586NULL); -#ifdef WLDEBUG - if (sc->ifp->if_flags & IFF_DEBUG) { - if (xmt_debug) { - wltbd(sc); - printf("\n"); - } - } -#endif /* WLDEBUG */ - - WL_WRITE_2(sc, PIOR0, OFFSET_SCB + 2); /* address of scb_command */ - /* - * wait for 586 to clear previous command, complain if it takes - * too long - */ - for (spin = 1;;spin = (spin + 1) % 10000) { - if (WL_READ_2(sc, PIOP0) == 0) { /* it's done, we can go */ - break; - } - if ((spin == 0) && xmt_watch) { /* not waking up, and we care */ - if_printf(sc->ifp, "slow accepting xmit\n"); - } - } - WL_WRITE_2(sc, PIOP0, SCB_CU_STRT); /* new command */ - SET_CHAN_ATTN(sc); - - m_freem(m); - - /* XXX - * Pause to avoid transmit overrun problems. - * The required delay tends to vary with platform type, and may be - * related to interrupt loss. - */ - if (wl_xmit_delay) { - DELAY(wl_xmit_delay); - } - return; -} - -/* - * wlbldru: - * - * This function builds the linear linked lists of fd's and - * rbd's. Based on page 4-32 of 1986 Intel microcom handbook. - * - */ -static u_short -wlbldru(struct wl_softc *sc) -{ - fd_t fd; - rbd_t rbd; - u_short fd_p = OFFSET_RU; - u_short rbd_p = OFFSET_RBD; - int i; - - sc->begin_fd = fd_p; - for (i = 0; i < N_FD; i++) { - fd.status = 0; - fd.command = 0; - fd.link_offset = fd_p + sizeof(fd_t); - fd.rbd_offset = I82586NULL; - WL_WRITE_2(sc, PIOR1, fd_p); - WL_WRITE_MULTI_2(sc, PIOP1, &fd, 8/2); - fd_p = fd.link_offset; - } - fd_p -= sizeof(fd_t); - sc->end_fd = fd_p; - WL_WRITE_2(sc, PIOR1, fd_p + 2); - WL_WRITE_2(sc, PIOP1, AC_CW_EL); /* command */ - WL_WRITE_2(sc, PIOP1, I82586NULL); /* link_offset */ - fd_p = OFFSET_RU; - - WL_WRITE_2(sc, PIOR0, fd_p + 6); /* address of rbd_offset */ - WL_WRITE_2(sc, PIOP0, rbd_p); - WL_WRITE_2(sc, PIOR1, rbd_p); - for (i = 0; i < N_RBD; i++) { - rbd.status = 0; - rbd.buffer_addr = rbd_p + sizeof(rbd_t) + 2; - rbd.buffer_base = 0; - rbd.size = RCVBUFSIZE; - if (i != N_RBD-1) { - rbd_p += sizeof(ru_t); - rbd.next_rbd_offset = rbd_p; - } else { - rbd.next_rbd_offset = I82586NULL; - rbd.size |= AC_CW_EL; - sc->end_rbd = rbd_p; - } - WL_WRITE_MULTI_2(sc, PIOP1, &rbd, sizeof(rbd_t)/2); - WL_WRITE_2(sc, PIOR1, rbd_p); - } - return sc->begin_fd; -} - -/* - * wlrustrt: - * - * This routine starts the receive unit running. First checks if the - * board is actually ready, then the board is instructed to receive - * packets again. - * - */ -static void -wlrustrt(struct wl_softc *sc) -{ - u_short rfa; - -#ifdef WLDEBUG - if (sc->ifp->if_flags & IFF_DEBUG) - if_printf(sc->ifp, "entered wlrustrt()\n"); -#endif - WL_WRITE_2(sc, PIOR0, OFFSET_SCB); - if (WL_READ_2(sc, PIOP0) & SCB_RUS_READY){ - printf("wlrustrt: RUS_READY\n"); - return; - } - - WL_WRITE_2(sc, PIOR0, OFFSET_SCB + 2); - WL_WRITE_2(sc, PIOP0, SCB_RU_STRT); /* command */ - rfa = wlbldru(sc); - WL_WRITE_2(sc, PIOR0, OFFSET_SCB + 6); /* address of scb_rfa_offset */ - WL_WRITE_2(sc, PIOP0, rfa); - - SET_CHAN_ATTN(sc); - return; -} - -/* - * wldiag: - * - * This routine does a 586 op-code number 7, and obtains the - * diagnose status for the WaveLAN. - * - */ -static int -wldiag(struct wl_softc *sc) -{ - short status; - -#ifdef WLDEBUG - if (sc->ifp->if_flags & IFF_DEBUG) - if_printf(sc->ifp, "entered wldiag()\n"); -#endif - WL_WRITE_2(sc, PIOR0, OFFSET_SCB); - status = WL_READ_2(sc, PIOP0); - if (status & SCB_SW_INT) { - /* state is 2000 which seems ok - if_printf(sc->ifp, "diag(): unexpected initial state %\n", - WL_READ_2(sc, PIOP0)); - */ - wlack(sc); - } - WL_WRITE_2(sc, PIOR1, OFFSET_CU); - WL_WRITE_2(sc, PIOP1, 0); /* ac_status */ - WL_WRITE_2(sc, PIOP1, AC_DIAGNOSE|AC_CW_EL);/* ac_command */ - if (wlcmd(sc, "diag()") == 0) - return 0; - WL_WRITE_2(sc, PIOR0, OFFSET_CU); - if (WL_READ_2(sc, PIOP0) & 0x0800) { - if_printf(sc->ifp, "i82586 Self Test failed!\n"); - return 0; - } - return TRUE; -} - -/* - * wlconfig: - * - * This routine does a standard config of the WaveLAN board. - * - */ -static int -wlconfig(struct wl_softc *sc) -{ - configure_t configure; - -#if MULTICAST - struct ifmultiaddr *ifma; - u_char *addrp; - int cnt = 0; -#endif /* MULTICAST */ - -#ifdef WLDEBUG - if (sc->ifp->if_flags & IFF_DEBUG) - if_printf(sc->ifp, "entered wlconfig()\n"); -#endif - WL_WRITE_2(sc, PIOR0, OFFSET_SCB); - if (WL_READ_2(sc, PIOP0) & SCB_SW_INT) { - /* - if_printf(sc->ifp, "config(): unexpected initial state %x\n", - WL_READ_2(sc, PIOP0)); - */ - } - wlack(sc); - - WL_WRITE_2(sc, PIOR1, OFFSET_CU); - WL_WRITE_2(sc, PIOP1, 0); /* ac_status */ - WL_WRITE_2(sc, PIOP1, AC_CONFIGURE|AC_CW_EL); /* ac_command */ - -/* jrb hack */ - configure.fifolim_bytecnt = 0x080c; - configure.addrlen_mode = 0x0600; - configure.linprio_interframe = 0x2060; - configure.slot_time = 0xf200; - configure.hardware = 0x0008; /* tx even w/o CD */ - configure.min_frame_len = 0x0040; -#if 0 - /* This is the configuration block suggested by Marc Meertens - * in an e-mail message to John - * Ioannidis on 10 Nov 92. - */ - configure.fifolim_bytecnt = 0x040c; - configure.addrlen_mode = 0x0600; - configure.linprio_interframe = 0x2060; - configure.slot_time = 0xf000; - configure.hardware = 0x0008; /* tx even w/o CD */ - configure.min_frame_len = 0x0040; -#else - /* - * below is the default board configuration from p2-28 from 586 book - */ - configure.fifolim_bytecnt = 0x080c; - configure.addrlen_mode = 0x2600; - configure.linprio_interframe = 0x7820; /* IFS=120, ACS=2 */ - configure.slot_time = 0xf00c; /* slottime=12 */ - configure.hardware = 0x0008; /* tx even w/o CD */ - configure.min_frame_len = 0x0040; -#endif - if (sc->mode & (MOD_PROM | MOD_ENAL)) - configure.hardware |= 1; - WL_WRITE_2(sc, PIOR1, OFFSET_CU + 6); - WL_WRITE_MULTI_2(sc, PIOP1, &configure, sizeof(configure_t)/2); - - if (wlcmd(sc, "config()-configure") == 0) - return 0; -#if MULTICAST - WL_WRITE_2(sc, PIOR1, OFFSET_CU); - WL_WRITE_2(sc, PIOP1, 0); /* ac_status */ - WL_WRITE_2(sc, PIOP1, AC_MCSETUP|AC_CW_EL); /* ac_command */ - WL_WRITE_2(sc, PIOR1, OFFSET_CU + 8); - if_maddr_rlock(sc->ifp); - TAILQ_FOREACH(ifma, &sc->ifp->if_multiaddrs, ifma_link) { - if (ifma->ifma_addr->sa_family != AF_LINK) - continue; - - addrp = LLADDR((struct sockaddr_dl *)ifma->ifma_addr); - WL_WRITE_2(sc, PIOP1, addrp[0] + (addrp[1] << 8)); - WL_WRITE_2(sc, PIOP1, addrp[2] + (addrp[3] << 8)); - WL_WRITE_2(sc, PIOP1, addrp[4] + (addrp[5] << 8)); - ++cnt; - } - if_maddr_runlock(sc->ifp); - WL_WRITE_2(sc, PIOR1, OFFSET_CU + 6); /* mc-cnt */ - WL_WRITE_2(sc, PIOP1, cnt * WAVELAN_ADDR_SIZE); - if (wlcmd(sc, "config()-mcaddress") == 0) - return 0; -#endif /* MULTICAST */ - - WL_WRITE_2(sc, PIOR1, OFFSET_CU); - WL_WRITE_2(sc, PIOP1, 0); /* ac_status */ - WL_WRITE_2(sc, PIOP1, AC_IASETUP|AC_CW_EL); /* ac_command */ - WL_WRITE_2(sc, PIOR1, OFFSET_CU + 6); - WL_WRITE_MULTI_2(sc, PIOP1, IF_LLADDR(sc->ifp), WAVELAN_ADDR_SIZE/2); - - if (wlcmd(sc, "config()-address") == 0) - return(0); - - wlinitmmc(sc); - - return(1); -} - -/* - * wlcmd: - * - * Set channel attention bit and busy wait until command has - * completed. Then acknowledge the command completion. - */ -static int -wlcmd(struct wl_softc *sc, char *str) -{ - int i; - - WL_WRITE_2(sc, PIOR0, OFFSET_SCB + 2); /* address of scb_command */ - WL_WRITE_2(sc, PIOP0, SCB_CU_STRT); - - SET_CHAN_ATTN(sc); - - WL_WRITE_2(sc, PIOR0, OFFSET_CU); - for (i = 0; i < 0xffff; i++) - if (WL_READ_2(sc, PIOP0) & AC_SW_C) - break; - if (i == 0xffff || !(WL_READ_2(sc, PIOP0) & AC_SW_OK)) { - if_printf(sc->ifp, "%s failed; status = %d, inw = %x, outw = %x\n", - str, WL_READ_2(sc, PIOP0) & AC_SW_OK, WL_READ_2(sc, PIOP0), - WL_READ_2(sc, PIOR0)); - WL_WRITE_2(sc, PIOR0, OFFSET_SCB); - printf("scb_status %x\n", WL_READ_2(sc, PIOP0)); - WL_WRITE_2(sc, PIOR0, OFFSET_SCB+2); - printf("scb_command %x\n", WL_READ_2(sc, PIOP0)); - WL_WRITE_2(sc, PIOR0, OFFSET_SCB+4); - printf("scb_cbl %x\n", WL_READ_2(sc, PIOP0)); - WL_WRITE_2(sc, PIOR0, OFFSET_CU+2); - printf("cu_cmd %x\n", WL_READ_2(sc, PIOP0)); - return(0); - } - - WL_WRITE_2(sc, PIOR0, OFFSET_SCB); - if ((WL_READ_2(sc, PIOP0) & SCB_SW_INT) && - (WL_READ_2(sc, PIOP0) != SCB_SW_CNA)) { - /* - if_printf(sc->ifp, "%s: unexpected final state %x\n", - str, WL_READ_2(sc, PIOP0)); - */ - } - wlack(sc); - return(TRUE); -} - -/* - * wlack: if the 82596 wants attention because it has finished - * sending or receiving a packet, acknowledge its desire and - * return bits indicating the kind of attention. wlack() returns - * these bits so that the caller can service exactly the - * conditions that wlack() acknowledged. - */ -static int -wlack(struct wl_softc *sc) -{ - int i; - u_short cmd; - - WL_WRITE_2(sc, PIOR1, OFFSET_SCB); - if (!(cmd = (WL_READ_2(sc, PIOP1) & SCB_SW_INT))) - return(0); -#ifdef WLDEBUG - if (sc->ifp->if_flags & IFF_DEBUG) - if_printf(sc->ifp, "doing a wlack()\n"); -#endif - WL_WRITE_2(sc, PIOP1, cmd); - SET_CHAN_ATTN(sc); - WL_WRITE_2(sc, PIOR0, OFFSET_SCB + 2); /* address of scb_command */ - for (i = 1000000; WL_READ_2(sc, PIOP0) && (i-- > 0); ) - continue; - if (i < 1) - if_printf(sc->ifp, "wlack(): board not accepting command.\n"); - return(cmd); -} - -#ifdef WLDEBUG -static void -wltbd(struct wl_softc *sc) -{ - u_short tbd_p = OFFSET_TBD; - tbd_t tbd; - int i = 0; - int sum = 0; - - for (;;) { - WL_WRITE_2(sc, PIOR1, tbd_p); - WL_READ_MULTI_2(sc, PIOP1, &tbd, sizeof(tbd_t)/2); - sum += (tbd.act_count & ~TBD_SW_EOF); - printf("%d: addr %x, count %d (%d), next %x, base %x\n", - i++, tbd.buffer_addr, - (tbd.act_count & ~TBD_SW_EOF), sum, - tbd.next_tbd_offset, tbd.buffer_base); - if (tbd.act_count & TBD_SW_EOF) - break; - tbd_p = tbd.next_tbd_offset; - } -} -#endif - -static void -wlhdwsleaze(u_short *countp, u_char **mb_pp, struct mbuf **tm_pp, struct wl_softc *sc) -{ - struct mbuf *tm_p = *tm_pp; - u_char *mb_p = *mb_pp; - u_short count = 0; - u_char *cp; - int len; - - /* - * can we get a run that will be coallesced or - * that terminates before breaking - */ - do { - count += tm_p->m_len; - if (tm_p->m_len & 1) - break; - } while ((tm_p = tm_p->m_next) != (struct mbuf *)0); - if ( (tm_p == (struct mbuf *)0) || - count > HDW_THRESHOLD) { - *countp = (*tm_pp)->m_len; - *mb_pp = mtod((*tm_pp), u_char *); - return; - } - - /* we need to copy */ - tm_p = *tm_pp; - mb_p = *mb_pp; - count = 0; - cp = (u_char *) t_packet; - for (;;) { - bcopy(mtod(tm_p, u_char *), cp, len = tm_p->m_len); - count += len; - if (count > HDW_THRESHOLD) - break; - cp += len; - if (tm_p->m_next == (struct mbuf *)0) - break; - tm_p = tm_p->m_next; - } - *countp = count; - *mb_pp = (u_char *) t_packet; - *tm_pp = tm_p; - return; -} - - -static void -wlsftwsleaze(u_short *countp, u_char **mb_pp, struct mbuf **tm_pp, struct wl_softc *sc) -{ - struct mbuf *tm_p = *tm_pp; - u_short count = 0; - u_char *cp = (u_char *) t_packet; - int len; - - /* we need to copy */ - for (;;) { - bcopy(mtod(tm_p, u_char *), cp, len = tm_p->m_len); - count += len; - cp += len; - if (tm_p->m_next == (struct mbuf *)0) - break; - tm_p = tm_p->m_next; - } - - *countp = count; - *mb_pp = (u_char *) t_packet; - *tm_pp = tm_p; - return; -} - -static void -wlmmcstat(struct wl_softc *sc) -{ - u_short tmp; - - device_printf(sc->dev, "DCE_STATUS: 0x%x, ", - wlmmcread(sc, MMC_DCE_STATUS) & 0x0f); - tmp = wlmmcread(sc, MMC_CORRECT_NWID_H) << 8; - tmp |= wlmmcread(sc, MMC_CORRECT_NWID_L); - printf("Correct NWID's: %d, ", tmp); - tmp = wlmmcread(sc, MMC_WRONG_NWID_H) << 8; - tmp |= wlmmcread(sc, MMC_WRONG_NWID_L); - printf("Wrong NWID's: %d\n", tmp); - printf("THR_PRE_SET: 0x%x, ", wlmmcread(sc, MMC_THR_PRE_SET)); - printf("SIGNAL_LVL: %d, SILENCE_LVL: %d\n", - wlmmcread(sc, MMC_SIGNAL_LVL), - wlmmcread(sc, MMC_SILENCE_LVL)); - printf("SIGN_QUAL: 0x%x, NETW_ID: %x:%x, DES: %d\n", - wlmmcread(sc, MMC_SIGN_QUAL), - wlmmcread(sc, MMC_NETW_ID_H), - wlmmcread(sc, MMC_NETW_ID_L), - wlmmcread(sc, MMC_DES_AVAIL)); -} - -static u_short -wlmmcread(struct wl_softc *sc, u_short reg) -{ - while (WL_READ_2(sc, HASR) & HASR_MMC_BUSY) - continue; - WL_WRITE_2(sc, MMCR,reg << 1); - while (WL_READ_2(sc, HASR) & HASR_MMC_BUSY) - continue; - return (u_short)WL_READ_2(sc, MMCR) >> 8; -} - -static void -getsnr(struct wl_softc *sc) -{ - MMC_WRITE(MMC_FREEZE,1); - /* - * SNR retrieval procedure : - * - * read signal level : wlmmcread(sc, MMC_SIGNAL_LVL); - * read silence level : wlmmcread(sc, MMC_SILENCE_LVL); - */ - MMC_WRITE(MMC_FREEZE,0); - /* - * SNR is signal:silence ratio. - */ -} - -/* -** wlgetpsa -** -** Reads the psa for the wavelan at (sc) into (buf) -*/ -static void -wlgetpsa(struct wl_softc *sc, u_char *buf) -{ - int i; - - PCMD(sc, HACR_DEFAULT & ~HACR_16BITS); - PCMD(sc, HACR_DEFAULT & ~HACR_16BITS); - - for (i = 0; i < 0x40; i++) { - WL_WRITE_2(sc, PIOR2, i); - buf[i] = WL_READ_1(sc, PIOP2); - } - PCMD(sc, HACR_DEFAULT); - PCMD(sc, HACR_DEFAULT); -} - -/* -** wlsetpsa -** -** Writes the psa for wavelan (unit) from the softc back to the -** board. Updates the CRC and sets the CRC OK flag. -** -** Do not call this when the board is operating, as it doesn't -** preserve the hacr. -*/ -static void -wlsetpsa(struct wl_softc *sc) -{ - int i; - u_short crc; - - crc = wlpsacrc(sc->psa); /* calculate CRC of PSA */ - sc->psa[WLPSA_CRCLOW] = crc & 0xff; - sc->psa[WLPSA_CRCHIGH] = (crc >> 8) & 0xff; - sc->psa[WLPSA_CRCOK] = 0x55; /* default to 'bad' until programming complete */ - - PCMD(sc, HACR_DEFAULT & ~HACR_16BITS); - PCMD(sc, HACR_DEFAULT & ~HACR_16BITS); - - for (i = 0; i < 0x40; i++) { - DELAY(DELAYCONST); - WL_WRITE_2(sc, PIOR2, i); /* write param memory */ - DELAY(DELAYCONST); - WL_WRITE_1(sc, PIOP2, sc->psa[i]); - } - DELAY(DELAYCONST); - WL_WRITE_2(sc, PIOR2, WLPSA_CRCOK); /* update CRC flag*/ - DELAY(DELAYCONST); - sc->psa[WLPSA_CRCOK] = 0xaa; /* OK now */ - WL_WRITE_1(sc, PIOP2, 0xaa); /* all OK */ - DELAY(DELAYCONST); - - PCMD(sc, HACR_DEFAULT); - PCMD(sc, HACR_DEFAULT); -} - -/* -** CRC routine provided by Christopher Giordano , -** from original code by Tomi Mikkonen (tomitm@remedy.fi) -*/ - -static u_int crc16_table[16] = { - 0x0000, 0xCC01, 0xD801, 0x1400, - 0xF001, 0x3C00, 0x2800, 0xE401, - 0xA001, 0x6C00, 0x7800, 0xB401, - 0x5000, 0x9C01, 0x8801, 0x4400 -}; - -static u_short -wlpsacrc(u_char *buf) -{ - u_short crc = 0; - int i, r1; - - for (i = 0; i < 0x3d; i++, buf++) { - /* lower 4 bits */ - r1 = crc16_table[crc & 0xF]; - crc = (crc >> 4) & 0x0FFF; - crc = crc ^ r1 ^ crc16_table[*buf & 0xF]; - - /* upper 4 bits */ - r1 = crc16_table[crc & 0xF]; - crc = (crc >> 4) & 0x0FFF; - crc = crc ^ r1 ^ crc16_table[(*buf >> 4) & 0xF]; - } - return(crc); -} -#ifdef WLCACHE - -/* - * wl_cache_store - * - * take input packet and cache various radio hw characteristics - * indexed by MAC address. - * - * Some things to think about: - * note that no space is malloced. - * We might hash the mac address if the cache were bigger. - * It is not clear that the cache is big enough. - * It is also not clear how big it should be. - * The cache is IP-specific. We don't care about that as - * we want it to be IP-specific. - * The last N recv. packets are saved. This will tend - * to reward agents and mobile hosts that beacon. - * That is probably fine for mobile ip. - */ - -/* globals for wavelan signal strength cache */ -/* this should go into softc structure above. -*/ - -/* set true if you want to limit cache items to broadcast/mcast - * only packets (not unicast) - */ -static int wl_cache_mcastonly = 1; -SYSCTL_INT(_machdep, OID_AUTO, wl_cache_mcastonly, CTLFLAG_RW, - &wl_cache_mcastonly, 0, ""); - -/* set true if you want to limit cache items to IP packets only -*/ -static int wl_cache_iponly = 1; -SYSCTL_INT(_machdep, OID_AUTO, wl_cache_iponly, CTLFLAG_RW, - &wl_cache_iponly, 0, ""); - -/* zero out the cache -*/ -static void -wl_cache_zero(struct wl_softc *sc) -{ - - bzero(&sc->w_sigcache[0], sizeof(struct w_sigcache) * MAXCACHEITEMS); - sc->w_sigitems = 0; - sc->w_nextcache = 0; - sc->w_wrapindex = 0; -} - -/* store hw signal info in cache. - * index is MAC address, but an ip src gets stored too - * There are two filters here controllable via sysctl: - * throw out unicast (on by default, but can be turned off) - * throw out non-ip (on by default, but can be turned off) - */ -static -void wl_cache_store (struct wl_softc *sc, struct ether_header *eh, - struct mbuf *m) -{ -#ifdef INET - struct ip *ip = NULL; /* Avoid GCC warning */ - int i; - int signal, silence; - int w_insertcache; /* computed index for cache entry storage */ - int ipflag = wl_cache_iponly; -#endif - - /* filters: - * 1. ip only - * 2. configurable filter to throw out unicast packets, - * keep multicast only. - */ - -#ifdef INET - /* reject if not IP packet - */ - if ( wl_cache_iponly && (ntohs(eh->ether_type) != 0x800)) { - return; - } - - /* check if broadcast or multicast packet. we toss - * unicast packets - */ - if (wl_cache_mcastonly && ((eh->ether_dhost[0] & 1) == 0)) { - return; - } - - /* find the ip header. we want to store the ip_src - * address. use the mtod macro(in mbuf.h) - * to typecast m to struct ip * - */ - if (ipflag) { - ip = mtod(m, struct ip *); - } - - /* do a linear search for a matching MAC address - * in the cache table - * . MAC address is 6 bytes, - * . var w_nextcache holds total number of entries already cached - */ - for (i = 0; i < sc->w_nextcache; i++) { - if (! bcmp(eh->ether_shost, sc->w_sigcache[i].macsrc, 6 )) { - /* Match!, - * so we already have this entry, - * update the data, and LRU age - */ - break; - } - } - - /* did we find a matching mac address? - * if yes, then overwrite a previously existing cache entry - */ - if (i < sc->w_nextcache ) { - w_insertcache = i; - } - /* else, have a new address entry,so - * add this new entry, - * if table full, then we need to replace entry - */ - else { - - /* check for space in cache table - * note: w_nextcache also holds number of entries - * added in the cache table - */ - if ( sc->w_nextcache < MAXCACHEITEMS ) { - w_insertcache = sc->w_nextcache; - sc->w_nextcache++; - sc->w_sigitems = sc->w_nextcache; - } - /* no space found, so simply wrap with wrap index - * and "zap" the next entry - */ - else { - if (sc->w_wrapindex == MAXCACHEITEMS) { - sc->w_wrapindex = 0; - } - w_insertcache = sc->w_wrapindex++; - } - } - - /* invariant: w_insertcache now points at some slot - * in cache. - */ - if (w_insertcache < 0 || w_insertcache >= MAXCACHEITEMS) { - log(LOG_ERR, - "wl_cache_store, bad index: %d of [0..%d], gross cache error\n", - w_insertcache, MAXCACHEITEMS); - return; - } - - /* store items in cache - * .ipsrc - * .macsrc - * .signal (0..63) ,silence (0..63) ,quality (0..15) - */ - if (ipflag) { - sc->w_sigcache[w_insertcache].ipsrc = ip->ip_src.s_addr; - } - bcopy( eh->ether_shost, sc->w_sigcache[w_insertcache].macsrc, 6); - signal = sc->w_sigcache[w_insertcache].signal = wlmmcread(sc, MMC_SIGNAL_LVL) & 0x3f; - silence = sc->w_sigcache[w_insertcache].silence = wlmmcread(sc, MMC_SILENCE_LVL) & 0x3f; - sc->w_sigcache[w_insertcache].quality = wlmmcread(sc, MMC_SIGN_QUAL) & 0x0f; - if (signal > 0) - sc->w_sigcache[w_insertcache].snr = - signal - silence; - else - sc->w_sigcache[w_insertcache].snr = 0; -#endif /* INET */ - -} -#endif /* WLCACHE */ diff --git a/sys/dev/wl/if_wl.h b/sys/dev/wl/if_wl.h deleted file mode 100644 index 77a24cc12bdf..000000000000 --- a/sys/dev/wl/if_wl.h +++ /dev/null @@ -1,133 +0,0 @@ -/*- - * 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 all copyright - * notices, this list of conditions and the following disclaimer. - * 2. The names of the authors may not be used to endorse or promote products - * derived from this software without specific prior written permission - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 THE AUTHORS 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$ - */ -/* Definitions for WaveLAN driver */ - -#ifndef _IF_WL_H -#define _IF_WL_H - -#define STATUS_TRIES 15000 - -#define N_FD 100 -#define N_RBD 100 -#define N_TBD 72 -#define RCVBUFSIZE 540 -#define I82586NULL 0xffff - -#define DSF_RUNNING 1 - -#define MOD_ENAL 1 -#define MOD_PROM 2 - -typedef struct { - rbd_t r; - char rbd_pad[2]; - char rbuffer[RCVBUFSIZE]; -} ru_t; - -/* Board 64k RAM layout. Offsets from 0x0000 */ - -#define OFFSET_RU 0x0000 /* 0x64 * fd_t = 0x898 */ -#define OFFSET_RBD 0x0900 /* 0x64 * ru_t = 0xd7a0 */ -#define OFFSET_CU 0xe0a0 /* 0x100 */ -#define OFFSET_TBD 0xe1a0 /* 0x48 * tbd_t = 0x240 */ -#define OFFSET_TBUF 0xe3e0 /* 0x1bfe */ -#define OFFSET_SCB 0xffde /* 0x1 * scb_t = 0x10 */ -#define OFFSET_ISCP 0xffee /* 0x1 * iscp_t = 0x8 */ -#define OFFSET_SCP 0xfff6 /* 0x1 * scp_t = 0xa */ - -/* WaveLAN host interface definitions */ - -#define HACR 0x0 /* Host Adapter Command Register */ -#define HASR 0x0 /* Host Adapter Status Register */ -#define MMCR 0x2 /* Modem Management Ctrl Register */ -#define PIOR0 0x4 /* Program I/O Address Register 0 */ -#define PIOP0 0x6 /* Program I/O Port 0 */ -#define PIOR1 0x8 /* Program I/O Address Register 1 */ -#define PIOP1 0xa /* Program I/O Port 1 */ -#define PIOR2 0xc /* Program I/O Address Register 2 */ -#define PIOP2 0xe /* Program I/O Port 2 */ - -/* Program I/O Mode Register values */ - -#define STATIC_PIO 0 /* Mode 1: static mode */ -#define AUTOINCR_PIO 1 /* Mode 2: auto increment mode */ -#define AUTODECR_PIO 2 /* Mode 3: auto decrement mode */ -#define PARAM_ACCESS_PIO 3 /* Mode 4: LAN parameter access mode */ -#define PIO_MASK 3 /* register mask */ -#define PIOM(cmd,piono) ((u_short)cmd << 10 << (piono * 2)) - -/* Host Adapter status register definitions */ - -#define HASR_INTR 0x0001 /* Interrupt request from 82586 */ -#define HASR_MMC_INTR 0x0002 /* Interrupt request from MMC */ -#define HASR_MMC_BUSY 0x0004 /* MMC busy indication */ -#define HASR_PARA_BUSY 0x0008 /* LAN parameter storage area busy */ - -/* Host Adapter command register definitions */ - -#define HACR_RESET 0x0001 /* Reset board */ -#define HACR_CA 0x0002 /* Set Channel Attention for 82586 */ -#define HACR_16BITS 0x0004 /* 1==16 bits operation, 0==8 bits */ -#define HACR_OUT1 0x0008 /* General purpose output pin */ -#define HACR_OUT2 0x0010 /* General purpose output pin */ -#define HACR_MASK_82586 0x0020 /* Mask 82586 interrupts, 1==unmask */ -#define HACR_MASK_MMC 0x0040 /* Mask MMC interrupts, 1==unmask */ -#define HACR_INTR_CLEN 0x0080 /* interrupt status clear enable */ - -#define HACR_DEFAULT (HACR_OUT1 | HACR_OUT2 | HACR_16BITS | PIOM(STATIC_PIO, 0) | PIOM(AUTOINCR_PIO, 1) | PIOM(PARAM_ACCESS_PIO, 2)) -#define HACR_INTRON (HACR_MASK_82586 | HACR_MASK_MMC | HACR_INTR_CLEN) - -#define WL_READ_1(sc, reg) bus_read_1((sc)->res_ioport, (reg)) -#define WL_READ_2(sc, reg) bus_read_2((sc)->res_ioport, (reg)) -#define WL_READ_MULTI_2(sc, reg, buf, len) \ - bus_read_multi_2((sc)->res_ioport, (reg), (uint16_t *)(buf), (len)) -#define WL_WRITE_1(sc, reg, val) \ - bus_write_1((sc)->res_ioport, (reg), (val)) -#define WL_WRITE_2(sc, reg, val) \ - bus_write_2((sc)->res_ioport, (reg), (val)) -#define WL_WRITE_MULTI_2(sc, reg, buf, len) \ - bus_write_multi_2((sc)->res_ioport, (reg), (uint16_t *)(buf), (len)) - -#define CMD(sc) \ - { \ - WL_WRITE_2(sc, HACR, sc->hacr); \ - /* delay for 50 us, might only be needed sometimes */ \ - DELAY(DELAYCONST); \ - } - -/* macro for setting the channel attention bit. No delays here since - * it is used in critical sections - */ -#define SET_CHAN_ATTN(sc) \ - { \ - WL_WRITE_2(sc, HACR, sc->hacr | HACR_CA); \ - } - - -#define MMC_WRITE(cmd,val) \ - while (WL_READ_2(sc, HASR) & HASR_MMC_BUSY) ; \ - WL_WRITE_2(sc, MMCR, \ - (u_short)(((u_short)(val) << 8) | ((cmd) << 1) | 1)) - -#endif /* _IF_WL_H */ - diff --git a/sys/dev/wl/if_wl_i82586.h b/sys/dev/wl/if_wl_i82586.h deleted file mode 100644 index fc08adcc5226..000000000000 --- a/sys/dev/wl/if_wl_i82586.h +++ /dev/null @@ -1,266 +0,0 @@ -/*- - * Mach Operating System - * Copyright (c) 1991,1990,1989 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - * - * $FreeBSD$ - */ -/* - Copyright 1988, 1989 by Olivetti Advanced Technology Center, Inc., -Cupertino, California. - - All Rights Reserved - - Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appears in all -copies and that both the copyright notice and this permission notice -appear in supporting documentation, and that the name of Olivetti -not be used in advertising or publicity pertaining to distribution -of the software without specific, written prior permission. - - OLIVETTI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, -IN NO EVENT SHALL OLIVETTI BE LIABLE FOR ANY SPECIAL, INDIRECT, OR -CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, -NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUR OF OR IN CONNECTION -WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -/* - * Defines for managing the status word of the 82586 cpu. For details see - * the Intel LAN Component User's Manual starting at p. 2-14. - * - */ - -#define SCB_SW_INT 0xf000 -#define SCB_SW_CX 0x8000 /* CU finished w/ int. bit set */ -#define SCB_SW_FR 0x4000 /* RU finished receiving a frame */ -#define SCB_SW_CNA 0x2000 /* CU left active state */ -#define SCB_SW_RNR 0x1000 /* RU left ready state */ - -/* - * Defines for managing the Command Unit Status portion of the 82586 - * System Control Block. - * - */ - -#define SCB_CUS_IDLE 0x0000 -#define SCB_CUS_SUSPND 0x0100 -#define SCB_CUS_ACTV 0x0200 - -/* - * Defines for managing the Receive Unit Status portion of the System - * Control Block. - * - */ - -#define SCB_RUS_IDLE 0x0000 -#define SCB_RUS_SUSPND 0x0010 -#define SCB_RUS_NORESRC 0x0020 -#define SCB_RUS_READY 0x0040 - -/* - * Defines that manage portions of the Command Word in the System Control - * Block of the 82586. Below are the Interrupt Acknowledge Bits and their - * appropriate masks. - * - */ - -#define SCB_ACK_CX 0x8000 -#define SCB_ACK_FR 0x4000 -#define SCB_ACK_CNA 0x2000 -#define SCB_ACK_RNR 0x1000 - -/* - * Defines for managing the Command Unit Control word, and the Receive - * Unit Control word. The software RESET bit is also defined. - * - */ - -#define SCB_CU_STRT 0x0100 -#define SCB_CU_RSUM 0x0200 -#define SCB_CU_SUSPND 0x0300 -#define SCB_CU_ABRT 0x0400 - -#define SCB_RESET 0x0080 - -#define SCB_RU_STRT 0x0010 -#define SCB_RU_RSUM 0x0020 -#define SCB_RU_SUSPND 0x0030 -#define SCB_RU_ABRT 0x0040 - - -/* - * The following define Action Commands for the 82586 chip. - * - */ - -#define AC_NOP 0x00 -#define AC_IASETUP 0x01 -#define AC_CONFIGURE 0x02 -#define AC_MCSETUP 0x03 -#define AC_TRANSMIT 0x04 -#define AC_TDR 0x05 -#define AC_DUMP 0x06 -#define AC_DIAGNOSE 0x07 - - -/* - * Defines for General Format for Action Commands, both Status Words, and - * Command Words. - * - */ - -#define AC_SW_C 0x8000 -#define AC_SW_B 0x4000 -#define AC_SW_OK 0x2000 -#define AC_SW_A 0x1000 -#define TC_CARRIER 0x0400 -#define TC_CLS 0x0200 -#define TC_DMA 0x0100 -#define TC_DEFER 0x0080 -#define TC_SQE 0x0040 -#define TC_COLLISION 0x0020 -#define AC_CW_EL 0x8000 -#define AC_CW_S 0x4000 -#define AC_CW_I 0x2000 - -/* - * Specific defines for the transmit action command. - * - */ - -#define TBD_SW_EOF 0x8000 -#define TBD_SW_COUNT 0x3fff - -/* - * Specific defines for the receive frame actions. - * - */ - -#define RBD_SW_EOF 0x8000 -#define RBD_SW_COUNT 0x3fff - -#define RFD_DONE 0x8000 -#define RFD_BUSY 0x4000 -#define RFD_OK 0x2000 -#define RFD_CRC 0x0800 -#define RFD_ALN 0x0400 -#define RFD_RSC 0x0200 -#define RFD_DMA 0x0100 -#define RFD_SHORT 0x0080 -#define RFD_EOF 0x0040 -#define RFD_EL 0x8000 -#define RFD_SUSP 0x4000 -/* - * 82586 chip specific structure definitions. For details, see the Intel - * LAN Components manual. - * - */ - - -typedef struct { - u_short scp_sysbus; - u_short scp_unused[2]; - u_short scp_iscp; - u_short scp_iscp_base; -} scp_t; - - -typedef struct { - u_short iscp_busy; - u_short iscp_scb_offset; - u_short iscp_scb; - u_short iscp_scb_base; -} iscp_t; - - -typedef struct { - u_short scb_status; - u_short scb_command; - u_short scb_cbl_offset; - u_short scb_rfa_offset; - u_short scb_crcerrs; - u_short scb_alnerrs; - u_short scb_rscerrs; - u_short scb_ovrnerrs; -} scb_t; - - -typedef struct { - u_short tbd_offset; - u_char dest_addr[6]; - u_short length; -} transmit_t; - - -typedef struct { - u_short fifolim_bytecnt; - u_short addrlen_mode; - u_short linprio_interframe; - u_short slot_time; - u_short hardware; - u_short min_frame_len; -} configure_t; - - -typedef struct { - u_short ac_status; - u_short ac_command; - u_short ac_link_offset; - union { - transmit_t transmit; - configure_t configure; - u_char iasetup[6]; - } cmd; -} ac_t; - - -typedef struct { - u_short act_count; - u_short next_tbd_offset; - u_short buffer_addr; - u_short buffer_base; -} tbd_t; - - -typedef struct { - u_short status; - u_short command; - u_short link_offset; - u_short rbd_offset; - u_char destination[6]; - u_char source[6]; - u_short length; -} fd_t; - - -typedef struct { - u_short status; - u_short next_rbd_offset; - u_short buffer_addr; - u_short buffer_base; - u_short size; -} rbd_t; diff --git a/sys/i386/conf/NOTES b/sys/i386/conf/NOTES index 1c972820922f..632db68576df 100644 --- a/sys/i386/conf/NOTES +++ b/sys/i386/conf/NOTES @@ -648,11 +648,6 @@ hint.sbni.0.port="0x210" hint.sbni.0.irq="0xefdead" hint.sbni.0.flags="0" device vmx # VMware VMXNET3 Ethernet -device wl -hint.wl.0.at="isa" -hint.wl.0.port="0x300" -options WLCACHE # enables the signal-strength cache -options WLDEBUG # enables verbose debugging output device wpi # Intel 3945ABG wireless NICs. # IEEE 802.11 adapter firmware modules diff --git a/sys/modules/Makefile b/sys/modules/Makefile index c089aa974d0a..7395e7a584b3 100644 --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -391,7 +391,6 @@ SUBDIR= \ wb \ ${_wbwd} \ ${_wi} \ - ${_wl} \ wlan \ wlan_acl \ wlan_amrr \ @@ -728,7 +727,6 @@ _ctau= ctau .endif _dpt= dpt _ex= ex -_wl= wl .elif ${MACHINE} == "pc98" _canbepm= canbepm _canbus= canbus diff --git a/sys/modules/wl/Makefile b/sys/modules/wl/Makefile deleted file mode 100644 index c46891cc0707..000000000000 --- a/sys/modules/wl/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# $FreeBSD$ - -.PATH: ${.CURDIR}/../../dev/wl - -KMOD= if_wl -SRCS= if_wl.c -SRCS+= bus_if.h device_if.h isa_if.h -SRCS+= opt_inet.h opt_wavelan.h - -.include diff --git a/targets/pseudo/userland/Makefile.depend b/targets/pseudo/userland/Makefile.depend index e0a404ba38f9..80d05d3cdd19 100644 --- a/targets/pseudo/userland/Makefile.depend +++ b/targets/pseudo/userland/Makefile.depend @@ -865,8 +865,7 @@ DIRDEPS.i386= \ usr.sbin/spkrtest \ usr.sbin/zzz \ usr.sbin/acpi \ - usr.sbin/boot0cfg \ - usr.sbin/wlconfig + usr.sbin/boot0cfg DIRDEPS.arm64= \ usr.sbin/acpi \ diff --git a/tools/build/mk/OptionalObsoleteFiles.inc b/tools/build/mk/OptionalObsoleteFiles.inc index bf452d5a40fb..4edd5f7c2c87 100644 --- a/tools/build/mk/OptionalObsoleteFiles.inc +++ b/tools/build/mk/OptionalObsoleteFiles.inc @@ -8744,9 +8744,6 @@ OLD_FILES+=usr/sbin/hostapd OLD_FILES+=usr/sbin/hostapd_cli OLD_FILES+=usr/sbin/ndis_events OLD_FILES+=usr/sbin/wlandebug -.if ${TARGET_ARCH} == "i386" -OLD_FILES+=usr/sbin/wlconfig -.endif OLD_FILES+=usr/sbin/wpa_cli OLD_FILES+=usr/sbin/wpa_passphrase OLD_FILES+=usr/sbin/wpa_supplicant @@ -8761,9 +8758,6 @@ OLD_FILES+=usr/share/man/man5/wpa_supplicant.conf.5.gz OLD_FILES+=usr/share/man/man8/ancontrol.8.gz OLD_FILES+=usr/share/man/man8/hostapd.8.gz OLD_FILES+=usr/share/man/man8/hostapd_cli.8.gz -.if ${TARGET_ARCH} == "i386" -OLD_FILES+=usr/share/man/man8/i386/wlconfig.8.gz -.endif OLD_FILES+=usr/share/man/man8/ndis_events.8.gz OLD_FILES+=usr/share/man/man8/wlandebug.8.gz OLD_FILES+=usr/share/man/man8/wpa_cli.8.gz diff --git a/tools/kerneldoc/subsys/Doxyfile-dev_wl b/tools/kerneldoc/subsys/Doxyfile-dev_wl deleted file mode 100644 index 2203b594652c..000000000000 --- a/tools/kerneldoc/subsys/Doxyfile-dev_wl +++ /dev/null @@ -1,21 +0,0 @@ -# Doxyfile 1.5.2 - -# $FreeBSD$ - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- -PROJECT_NAME = "FreeBSD kernel WL device code" -OUTPUT_DIRECTORY = $(DOXYGEN_DEST_PATH)/dev_wl/ -EXTRACT_ALL = YES # for undocumented src, no warnings enabled -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- -INPUT = $(DOXYGEN_SRC_PATH)/dev/wl/ \ - $(NOTREVIEWED) - -GENERATE_TAGFILE = dev_wl/dev_wl.tag - -@INCLUDE_PATH = $(DOXYGEN_INCLUDE_PATH) -@INCLUDE = common-Doxyfile - diff --git a/usr.sbin/Makefile.i386 b/usr.sbin/Makefile.i386 index c754dc690381..e8a44c4d8d74 100644 --- a/usr.sbin/Makefile.i386 +++ b/usr.sbin/Makefile.i386 @@ -29,9 +29,6 @@ SUBDIR+= boot0cfg .if ${MK_HYPERV} != "no" SUBDIR+= hyperv .endif -.if ${MK_WIRELESS} != "no" -SUBDIR+= wlconfig -.endif .elif ${MACHINE} == "pc98" SUBDIR+= boot98cfg .endif diff --git a/usr.sbin/wlconfig/Makefile b/usr.sbin/wlconfig/Makefile deleted file mode 100644 index 8bc62629a0d8..000000000000 --- a/usr.sbin/wlconfig/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# $FreeBSD$ - -PROG= wlconfig -MAN= wlconfig.8 -MANSUBDIR= /i386 - -WARNS?= 2 - -.include diff --git a/usr.sbin/wlconfig/Makefile.depend b/usr.sbin/wlconfig/Makefile.depend deleted file mode 100644 index 79eb58b4a779..000000000000 --- a/usr.sbin/wlconfig/Makefile.depend +++ /dev/null @@ -1,16 +0,0 @@ -# $FreeBSD$ -# Autogenerated - do NOT edit! - -DIRDEPS = \ - gnu/lib/libgcc \ - include \ - include/xlocale \ - lib/${CSU_DIR} \ - lib/libc \ - - -.include - -.if ${DEP_RELDIR} == ${_DEP_RELDIR} -# local dependencies - needed for -jN in clean tree -.endif diff --git a/usr.sbin/wlconfig/wlconfig.8 b/usr.sbin/wlconfig/wlconfig.8 deleted file mode 100644 index b4483394d3f0..000000000000 --- a/usr.sbin/wlconfig/wlconfig.8 +++ /dev/null @@ -1,143 +0,0 @@ -.\" $FreeBSD$ -.\" -.Dd December 26, 1996 -.Dt WLCONFIG 8 i386 -.Os -.Sh NAME -.Nm wlconfig -.Nd read/write wavelan config parameters -.Sh SYNOPSIS -.Nm -.Ar ifname -.Op Ar param value ... -.Sh DESCRIPTION -The -.Nm -utility can be used to read and set parameters for the NCR/AT&T Wavelan -radio LAN card. -Various parameters stored in the non-volatile Parameter -Storage Area (PSA) on the card can be modified with this program, replacing -the DOS-based -.Nm instconf.exe -program. -It can also be used to interrogate the optional signal -strength cache which may have been compiled into the driver. -.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 parameters. -Any number of -.Ar param value -pairs may be supplied. -.Bl -tag -width 15n -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 -independently whilst 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-volatile 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 currnwid -This sets the current operating NWID (but does not save it to the -PSA). -.It cache -The driver may maintain a per interface fixed size cache of signal strength, -silence, and quality levels, which are indexed by sender MAC addresses. -Input packets are stored in the cache, and when received, the values -stored in the radio modem are interrogated and stored. -There are also two sysctl values (iponly and multicast only) which -can be used for filtering out some input packets. -By default, the -cache mechanism stores only non-unicast IP packets, but this can -be changed with -.Xr sysctl 8 . -Each non-filtered -input packet causes a cache update, hence one can monitor -the antennae signal strength to a remote system. -There are three commands that can be given as values: -.Sq raw , -which prints out the raw signal strength data as found in the radio -modem hardware value, -.Sq scale , -which scales the raw hardware values to 0..100%, and -.Sq zero -which clears out the cache in case you want to store new samples. -.El -.Pp -Note that if the IRQ on the Wavelan card is incorrect, the interface -will be configured, but will not function. -The -.Nm -utility should then be used to reconfigure the card to a sensible -value. -.Sh EXAMPLES -Set the NWID to 0x1234: -.Bd -literal -offset indent -# wlconfig wl0 nwid 0x1234 -.Ed -.Pp -Show the current settings: -.Bd -literal -offset indent -# 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 compatibility : 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 -.Pp -Print a scaled version of the signal strength cache: -.Bd -literal -offset indent -# wlconfig wl0 cache scale -.Ed -.Sh SEE ALSO -.Xr wl 4 , -.Xr sysctl 8 -.Sh HISTORY -This implementation of the -.Nm -utility is completely new, written for Hilink Internet by -.An Michael Smith , -and updated by -.An Jim Binkley &c . diff --git a/usr.sbin/wlconfig/wlconfig.c b/usr.sbin/wlconfig/wlconfig.c deleted file mode 100644 index f361b2cb99fb..000000000000 --- a/usr.sbin/wlconfig/wlconfig.c +++ /dev/null @@ -1,417 +0,0 @@ -/* - * 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. - */ - -#ifndef lint -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - -/* - * 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 -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -/* 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 -}; - -/* cache */ -static int w_sigitems; /* count of valid items */ -static struct w_sigcache wsc[MAXCACHEITEMS]; - -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 compatibility : "); - 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; - } -} - - -static void -usage() -{ - fprintf(stderr,"usage: wlconfig ifname [param value ...]\n"); - exit(1); -} - - -void -get_cache(int sd, struct ifreq *ifr) -{ - /* get the cache count */ - if (ioctl(sd, SIOCGWLCITEM, (caddr_t)ifr)) - err(1, "SIOCGWLCITEM - get cache count"); - w_sigitems = (int) ifr->ifr_data; - - ifr->ifr_data = (caddr_t) &wsc; - /* get the cache */ - if (ioctl(sd, SIOCGWLCACHE, (caddr_t)ifr)) - err(1, "SIOCGWLCACHE - get cache count"); -} - -static int -scale_value(int value, int max) -{ - double dmax = (double) max; - if (value > max) - return(100); - return((value/dmax) * 100); -} - -static void -dump_cache(int rawFlag) -{ - int i; - int signal, silence, quality; - - if (rawFlag) - printf("signal range 0..63: silence 0..63: quality 0..15\n"); - else - printf("signal range 0..100: silence 0..100: quality 0..100\n"); - - /* after you read it, loop through structure,i.e. wsc - * print each item: - */ - for(i = 0; i < w_sigitems; i++) { - printf("[%d:%d]>\n", i+1, w_sigitems); - printf("\tip: %d.%d.%d.%d,",((wsc[i].ipsrc >> 0) & 0xff), - ((wsc[i].ipsrc >> 8) & 0xff), - ((wsc[i].ipsrc >> 16) & 0xff), - ((wsc[i].ipsrc >> 24) & 0xff)); - printf(" mac: %02x:%02x:%02x:%02x:%02x:%02x\n", - wsc[i].macsrc[0]&0xff, - wsc[i].macsrc[1]&0xff, - wsc[i].macsrc[2]&0xff, - wsc[i].macsrc[3]&0xff, - wsc[i].macsrc[4]&0xff, - wsc[i].macsrc[5]&0xff); - if (rawFlag) { - signal = wsc[i].signal; - silence = wsc[i].silence; - quality = wsc[i].quality; - } - else { - signal = scale_value(wsc[i].signal, 63); - silence = scale_value(wsc[i].silence, 63); - quality = scale_value(wsc[i].quality, 15); - } - printf("\tsignal: %d, silence: %d, quality: %d, ", - signal, - silence, - quality); - printf("snr: %d\n", signal - silence); - } -} - -#define raw_cache() dump_cache(1) -#define scale_cache() dump_cache(0) - -int -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)) - usage(); - - /* 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; - } - if (!strcasecmp(param,"cache")) { - - /* raw cache dump - */ - if (!strcasecmp(value,"raw")) { - get_cache(sd, &ifr); - raw_cache(); - continue; - } - /* scaled cache dump - */ - else if (!strcasecmp(value,"scale")) { - get_cache(sd, &ifr); - scale_cache(); - continue; - } - /* zero out cache - */ - else if (!strcasecmp(value,"zero")) { - if (ioctl(sd, SIOCDWLCACHE, (caddr_t)&ifr)) - err(1,"zero cache"); - continue; - } - errx(1,"unknown value '%s'", value); - } - 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"); - } - return(0); -}