1 /* $FreeBSD: src/sys/i386/isa/if_wl.c,v 1.27.2.2 2000/07/17 21:24:32 archie Exp $ */
2 /* $DragonFly: src/sys/dev/netif/wl/if_wl.c,v 1.31 2008/05/14 11:59:22 sephe Exp $ */
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain all copyright
8 * notices, this list of conditions and the following disclaimer.
9 * 2. The names of the authors may not be used to endorse or promote products
10 * derived from this software withough specific prior written permission
12 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
13 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
14 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
15 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
16 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
17 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
18 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
19 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
20 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
21 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 * if_wl.c - original MACH, then BSDI ISA wavelan driver
26 * ported to mach by Anders Klemets
27 * to BSDI by Robert Morris
28 * to FreeBSD by Jim Binkley
29 * to FreeBSD 2.2+ by Michael Smith
32 * Changed interface to match 2.1-2.2 differences.
33 * Implement IRQ selection logic in wlprobe()
34 * Implement PSA updating.
35 * Pruned heading comments for relevance.
36 * Ripped out all the 'interface counters' cruft.
37 * Cut the missing-interrupt timer back to 100ms.
39 * now supports all multicast mode (mrouted will work),
40 * but unfortunately must do that by going into promiscuous mode
41 * NWID sysctl added so that normally promiscuous mode is NWID-specific
42 * but can be made NWID-inspecific
46 * Ported to FreeBSD, got promiscuous mode working with bpfs,
47 * and rewired timer routine. The i82586 will hang occasionally on output
48 * and the watchdog timer will kick it if so and log an entry.
49 * 2 second timeout there. Apparently the chip loses an interrupt.
50 * Code borrowed from if_ie.c for watchdog timer.
52 * The wavelan card is a 2mbit radio modem that emulates ethernet;
53 * i.e., it uses MAC addresses. This should not be a surprise since
54 * it uses an ethernet controller as a major hw item.
55 * It can broadcast, unicast or apparently multicast in a base cell
56 * using a omni-directional antennae that is
57 * about 800 feet around the base cell barring walls and metal.
58 * With directional antennae, it can be used point to point over a mile
59 * or so apparently (haven't tried that).
61 * There are ISA and pcmcia versions (not supported by this code).
62 * The ISA card has an Intel 82586 lan controller on it. It consists
63 * of 2 pieces of hw, the lan controller (intel) and a radio-modem.
64 * The latter has an extra set of controller registers that has nothing
65 * to do with the i82586 and allows setting and monitoring of radio
66 * signal strength, etc. There is a nvram area called the PSA that
67 * contains a number of setup variables including the IRQ and so-called
68 * NWID or Network ID. The NWID must be set the same for all radio
69 * cards to communicate (unless you are using the ATT/NCR roaming feature
70 * with their access points. There is no support for that here. Roaming
71 * involves a link-layer beacon sent out from the access points. End
72 * stations monitor the signal strength and only use the strongest
73 * access point). This driver assumes that the base ISA port, IRQ,
74 * and NWID are first set in nvram via the dos-side "instconf.exe" utility
75 * supplied with the card. This driver takes the ISA port from
76 * the kernel configuration setup, and then determines the IRQ either
77 * from the kernel config (if an explicit IRQ is set) or from the
78 * PSA on the card if not.
79 * The hw also magically just uses the IRQ set in the nvram.
80 * The NWID is used magically as well by the radio-modem
81 * to determine which packets to keep or throw out.
85 * device wl0 at isa? port 0x300 net irq ?
88 * 1. WLDEBUG. (off) - if turned on enables IFF_DEBUG set via ifconfig debug
89 * 2. MULTICAST (on) - turned on and works up to and including mrouted
90 * 3. WLCACHE (off) - define to turn on a signal strength
91 * (and other metric) cache that is indexed by sender MAC address.
92 * Apps can read this out to learn the remote signal strength of a
93 * sender. Note that it has a switch so that it only stores
94 * broadcast/multicast senders but it could be set to store unicast
95 * too only. Size is hardwired in if_wl_wavelan.h
97 * one further note: promiscuous mode is a curious thing. In this driver,
98 * promiscuous mode apparently CAN catch ALL packets and ignore the NWID
99 * setting. This is probably more useful in a sense (for snoopers) if
100 * you are interested in all traffic as opposed to if you are interested
101 * in just your own. There is a driver specific sysctl to turn promiscuous
102 * from just promiscuous to wildly promiscuous...
104 * This driver also knows how to load the synthesizers in the 2.4 Gz
105 * ISA Half-card, Product number 847647476 (USA/FCC IEEE Channel set).
106 * This product consists of a "mothercard" that contains the 82586,
107 * NVRAM that holds the PSA, and the ISA-buss interface custom ASIC.
108 * The radio transceiver is a "daughtercard" called the WaveMODEM which
109 * connects to the mothercard through two single-inline connectors: a
110 * 20-pin connector provides DC-power and modem signals, and a 3-pin
111 * connector which exports the antenna connection. The code herein
112 * loads the receive and transmit synthesizers and the corresponding
113 * transmitter output power value from an EEPROM controlled through
114 * additional registers via the MMC. The EEPROM address selected
115 * are those whose values are preset by the DOS utility programs
116 * provided with the product, and this provides compatible operation
117 * with the DOS Packet Driver software. A future modification will
118 * add the necessary functionality to this driver and to the wlconfig
119 * utility to completely replace the DOS Configuration Utilities.
120 * The 2.4 Gz WaveMODEM is described in document number 407-024692/E,
121 * and is available through Lucent Technologies OEM supply channels.
128 * Olivetti PC586 Mach Ethernet driver v1.0
129 * Copyright Ing. C. Olivetti & C. S.p.A. 1988, 1989
130 * All rights reserved.
135 Copyright 1988, 1989 by Olivetti Advanced Technology Center, Inc.,
136 Cupertino, California.
140 Permission to use, copy, modify, and distribute this software and
141 its documentation for any purpose and without fee is hereby
142 granted, provided that the above copyright notice appears in all
143 copies and that both the copyright notice and this permission notice
144 appear in supporting documentation, and that the name of Olivetti
145 not be used in advertising or publicity pertaining to distribution
146 of the software without specific, written prior permission.
148 OLIVETTI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
149 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
150 IN NO EVENT SHALL OLIVETTI BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
151 CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
152 LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
153 NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUR OF OR IN CONNECTION
154 WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
158 Copyright 1988, 1989 by Intel Corporation, Santa Clara, California.
162 Permission to use, copy, modify, and distribute this software and
163 its documentation for any purpose and without fee is hereby
164 granted, provided that the above copyright notice appears in all
165 copies and that both the copyright notice and this permission notice
166 appear in supporting documentation, and that the name of Intel
167 not be used in advertising or publicity pertaining to distribution
168 of the software without specific, written prior permission.
170 INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
171 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
172 IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
173 CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
174 LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
175 NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
176 WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
182 * 1. The best book on the 82586 is:
183 * LAN Components User's Manual by Intel
184 * The copy I found was dated 1984. This really tells you
185 * what the state machines are doing
186 * 2. In the current design, we only do one write at a time,
187 * though the hardware is capable of chaining and possibly
188 * even batching. The problem is that we only make one
189 * transmit buffer available in sram space.
192 #include "opt_wavelan.h"
193 #include "opt_inet.h"
195 #include <sys/param.h>
196 #include <sys/systm.h>
197 #include <sys/kernel.h>
198 #include <sys/sockio.h>
199 #include <sys/mbuf.h>
200 #include <sys/socket.h>
201 #include <sys/syslog.h>
202 #include <sys/proc.h>
203 #include <sys/serialize.h>
204 #include <sys/sysctl.h>
206 #include <sys/rman.h>
207 #include <sys/thread2.h>
208 #include <sys/interrupt.h>
210 #include <net/ethernet.h>
212 #include <net/if_arp.h>
213 #include <net/ifq_var.h>
214 #include <net/if_dl.h>
217 #include <netinet/in.h>
218 #include <netinet/in_systm.h>
219 #include <netinet/ip.h>
220 #include <netinet/if_ether.h>
225 #include <bus/isa/isavar.h>
226 #include <bus/isa/i386/isa_device.h>
227 #include "if_wl_i82586.h" /* Definitions for the Intel chip */
229 /* was 1000 in original, fed to DELAY(x) */
230 #define DELAYCONST 1000
232 #include <machine/if_wl_wavelan.h>
234 static char t_packet[ETHERMTU + sizeof(struct ether_header) + sizeof(long)];
237 struct arpcom wl_ac; /* Ethernet common part */
238 #define wl_if wl_ac.ac_if /* network visible interface */
239 #define wl_addr wl_ac.ac_enaddr /* hardware address */
241 u_char nwid[2]; /* current radio modem nwid */
244 int tbusy; /* flag to determine if xmit is busy */
248 u_short hacr; /* latest host adapter CR command */
250 u_char chan24; /* 2.4 Gz: channel number/EEPROM Area # */
251 u_short freq24; /* 2.4 Gz: resulting frequency */
254 struct resource *res_ioport;
255 struct resource *res_irq;
257 struct callout watchdog_ch;
259 int w_sigitems; /* number of cached entries */
260 /* array of cache entries */
261 struct w_sigcache w_sigcache[ MAXCACHEITEMS ];
262 int w_nextcache; /* next free cache entry */
263 int w_wrapindex; /* next "free" cache entry */
268 * XXX The Wavelan appears to be prone to dropping stuff if you talk to
269 * it too fast. This disgusting hack inserts a delay after each packet
270 * is queued which helps avoid this behaviour on fast systems.
272 static int wl_xmit_delay = 250;
273 SYSCTL_INT(_machdep, OID_AUTO, wl_xmit_delay, CTLFLAG_RW, &wl_xmit_delay, 0, "");
276 * not XXX, but ZZZ (bizarre).
277 * promiscuous mode can be toggled to ignore NWIDs. By default,
278 * it does not. Caution should be exercised about combining
279 * this mode with IFF_ALLMULTI which puts this driver in
282 static int wl_ignore_nwid = 0;
283 SYSCTL_INT(_machdep, OID_AUTO, wl_ignore_nwid, CTLFLAG_RW, &wl_ignore_nwid, 0, "");
286 * Emit diagnostics about transmission problems
288 static int xmt_watch = 0;
289 SYSCTL_INT(_machdep, OID_AUTO, wl_xmit_watch, CTLFLAG_RW, &xmt_watch, 0, "");
292 * Collect SNR statistics
294 static int gathersnr = 0;
295 SYSCTL_INT(_machdep, OID_AUTO, wl_gather_snr, CTLFLAG_RW, &gathersnr, 0, "");
297 static int wlprobe(device_t);
298 static int wlattach(device_t);
299 static int wldetach(device_t);
300 static int wl_alloc_resources(device_t);
301 static void wl_free_resources(device_t);
302 static void wlstart(struct ifnet *);
303 static void wlinit(void *);
304 static int wlioctl(struct ifnet *, u_long, caddr_t, struct ucred *);
305 static timeout_t wlwatchdog;
306 static void wlintr(void *);
307 static void wlxmt(struct wl_softc *, struct mbuf *);
308 static int wldiag(struct wl_softc *);
309 static int wlconfig(struct wl_softc *);
310 static int wlcmd(struct wl_softc *, const char *);
311 static void wlmmcstat(struct wl_softc *);
312 static u_short wlbldru(struct wl_softc *);
313 static u_short wlmmcread(u_int, u_short);
314 static void wlinitmmc(struct wl_softc *);
315 static int wlhwrst(struct wl_softc *);
316 static void wlrustrt(struct wl_softc *);
317 static void wlbldcu(struct wl_softc *);
318 static int wlack(struct wl_softc *);
319 static int wlread(struct wl_softc *, u_short);
320 static void getsnr(struct wl_softc *);
321 static void wlrcv(struct wl_softc *);
322 static int wlrequeue(struct wl_softc *, u_short);
323 static void wlsftwsleaze(u_short *, u_char **, struct mbuf **);
324 static void wlhdwsleaze(u_short *, u_char **, struct mbuf **);
325 static void wltbd(struct wl_softc *);
326 static void wlgetpsa(int, u_char *);
327 static void wlsetpsa(struct wl_softc *);
328 static u_short wlpsacrc(u_char *);
329 static void wldump(struct wl_softc *);
331 static void wl_cache_store(struct wl_softc *, int, struct ether_header *,
333 static void wl_cache_zero(struct wl_softc *);
336 # if defined(__FreeBSD__) && __FreeBSD_version < 300000
337 static int check_allmulti(struct wl_softc *);
341 static device_method_t wl_methods[] = {
342 DEVMETHOD(device_probe, wlprobe),
343 DEVMETHOD(device_attach, wlattach),
344 DEVMETHOD(device_detach, wldetach),
348 static driver_t wl_driver = {
351 sizeof(struct wl_softc)
354 devclass_t wl_devclass;
355 DECLARE_DUMMY_MODULE(if_wl);
356 DRIVER_MODULE(wl, isa, wl_driver, wl_devclass, 0, 0);
357 MODULE_DEPEND(wl, isa, 1, 1, 1);
359 static struct isa_pnp_id wl_ids[] = {
363 /* array for maping irq numbers to values for the irq parameter register */
364 static int irqvals[16] = {
365 0, 0, 0, 0x01, 0x02, 0x04, 0, 0x08, 0, 0, 0x10, 0x20, 0x40, 0, 0, 0x80
371 * This function "probes" or checks for the WaveLAN board on the bus to
372 * see if it is there. As far as I can tell, the best break between this
373 * routine and the attach code is to simply determine whether the board
374 * is configured in properly. Currently my approach to this is to write
375 * and read a word from the SRAM on the board being probed. If the word
376 * comes back properly then we assume the board is there. The config
377 * code expects to see a successful return from the probe routine before
378 * attach will be called.
381 wlprobe(device_t dev)
385 const char *str = "wl%d: board out of range [0..%d]\n";
389 error = ISA_PNP_PROBE(device_get_parent(dev), dev, wl_ids);
390 if (error == ENXIO || error == 0)
393 sc = device_get_softc(dev);
394 error = wl_alloc_resources(dev);
398 base = rman_get_start(sc->res_ioport);
401 * regular CMD() will not work, since no softc yet
403 #define PCMD(base, hacr) outw((base), (hacr))
405 PCMD(base, HACR_RESET); /* reset the board */
406 DELAY(DELAYCONST); /* >> 4 clocks at 6MHz */
407 PCMD(base, HACR_RESET); /* reset the board */
408 DELAY(DELAYCONST); /* >> 4 clocks at 6MHz */
410 /* clear reset command and set PIO#1 in autoincrement mode */
411 PCMD(base, HACR_DEFAULT);
412 PCMD(base, HACR_DEFAULT);
413 outw(PIOR1(base), 0); /* go to beginning of RAM */
414 outsw(PIOP1(base), str, strlen(str)/2+1); /* write string */
416 outw(PIOR1(base), 0); /* rewind */
417 insw(PIOP1(base), inbuf, strlen(str)/2+1); /* read result */
419 if (bcmp(str, inbuf, strlen(str))) {
424 sc->chan24 = 0; /* 2.4 Gz: config channel */
425 sc->freq24 = 0; /* 2.4 Gz: frequency */
427 /* read the PSA from the board into temporary storage */
428 wlgetpsa(base, inbuf);
430 /* We read the IRQ value from the PSA on the board. */
431 for (irq = 15; irq >= 0; irq--)
432 if (irqvals[irq] == inbuf[WLPSA_IRQNO])
434 if ((irq == 0) || (irqvals[irq] == 0)){
435 device_printf(dev, "PSA corrupt (invalid IRQ value)\n");
440 * If the IRQ requested by the PSA is already claimed by another
441 * device, the board won't work, but the user can still access the
442 * driver to change the IRQ.
444 if (bus_get_resource(dev, SYS_RES_IRQ, 0, &sirq, &dummy))
446 if (irq != (int)sirq)
447 device_printf(dev, "board is configured for interrupt %d\n", irq);
452 wl_free_resources(dev);
459 * This function attaches a WaveLAN board to the "system". The rest of
460 * runtime structures are initialized here (this routine is called after
461 * a successful probe of the board). Once the ethernet address is read
462 * and stored, the board's ifnet structure is attached and readied.
465 wlattach(device_t dev)
472 sc = device_get_softc(dev);
475 if_initname(ifp, device_get_name(dev), device_get_unit(dev));
477 error = wl_alloc_resources(dev);
481 base = rman_get_start(sc->res_ioport);
484 device_printf(dev, "%s: base %x, unit %d\n",
485 __func__, base, device_get_unit(dev));
491 sc->hacr = HACR_RESET;
492 callout_init(&sc->watchdog_ch);
493 CMD(sc); /* reset the board */
494 DELAY(DELAYCONST); /* >> 4 clocks at 6MHz */
496 /* clear reset command and set PIO#2 in parameter access mode */
497 sc->hacr = (HACR_DEFAULT & ~HACR_16BITS);
500 /* Read the PSA from the board for our later reference */
501 wlgetpsa(base, sc->psa);
504 sc->nwid[0] = sc->psa[WLPSA_NWID];
505 sc->nwid[1] = sc->psa[WLPSA_NWID+1];
507 /* fetch MAC address - decide which one first */
508 if (sc->psa[WLPSA_MACSEL] & 1) {
513 for(i=0; i < WAVELAN_ADDR_SIZE; ++i) {
514 sc->wl_addr[i] = sc->psa[j + i];
517 /* enter normal 16 bit mode operation */
518 sc->hacr = HACR_DEFAULT;
522 outw(PIOR1(base), OFFSET_SCB + 8); /* address of scb_crcerrs */
523 outw(PIOP1(base), 0); /* clear scb_crcerrs */
524 outw(PIOP1(base), 0); /* clear scb_alnerrs */
525 outw(PIOP1(base), 0); /* clear scb_rscerrs */
526 outw(PIOP1(base), 0); /* clear scb_ovrnerrs */
529 ifp->if_mtu = WAVELAN_MTU;
530 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
532 ifp->if_flags |= IFF_DEBUG;
535 ifp->if_flags |= IFF_MULTICAST;
536 #endif /* MULTICAST */
537 ifp->if_init = wlinit;
538 ifp->if_start = wlstart;
539 ifp->if_ioctl = wlioctl;
540 ifp->if_timer = 0; /* paranoia */
546 ifq_set_maxlen(&ifp->if_snd, IFQ_MAXLEN);
547 ifq_set_ready(&ifp->if_snd);
548 ether_ifattach(ifp, sc->wl_ac.ac_enaddr, NULL);
551 kprintf(", Freq %d MHz",sc->freq24); /* 2.4 Gz */
552 kprintf("\n"); /* 2.4 Gz */
554 error = bus_setup_intr(dev, sc->res_irq, INTR_NETSAFE,
555 wlintr, sc, &sc->intr_handle,
558 device_printf(dev, "setup irq fail!\n");
560 wl_free_resources(dev);
564 ifp->if_cpuid = ithread_cpuid(rman_get_start(sc->res_irq));
565 KKASSERT(ifp->if_cpuid >= 0 && ifp->if_cpuid < ncpus);
573 wldetach(device_t dev)
575 struct wl_softc *sc = device_get_softc(dev);
576 device_t parent = device_get_parent(dev);
577 struct ifnet *ifp = &sc->wl_if;
579 lwkt_serialize_enter(ifp->if_serializer);
581 /* reset the board */
582 sc->hacr = HACR_RESET;
584 sc->hacr = HACR_DEFAULT;
587 if (sc->intr_handle != NULL) {
588 BUS_TEARDOWN_INTR(parent, dev, sc->res_irq, sc->intr_handle);
589 sc->intr_handle = NULL;
592 lwkt_serialize_exit(ifp->if_serializer);
595 bus_generic_detach(dev);
596 wl_free_resources(dev);
602 wl_alloc_resources(device_t dev)
604 struct wl_softc *sc = device_get_softc(dev);
605 int ports = 16; /* Number of ports */
607 sc->res_ioport = bus_alloc_resource(dev, SYS_RES_IOPORT,
608 &sc->rid_ioport, 0ul, ~0ul, ports, RF_ACTIVE);
609 if (sc->res_ioport == NULL)
612 sc->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
613 &sc->rid_irq, RF_SHAREABLE | RF_ACTIVE);
614 if (sc->res_irq == NULL)
619 wl_free_resources(dev);
624 wl_free_resources(device_t dev)
626 struct wl_softc *sc = device_get_softc(dev);
628 if (sc->res_irq != 0) {
629 bus_deactivate_resource(dev, SYS_RES_IRQ, sc->rid_irq, sc->res_irq);
630 bus_release_resource(dev, SYS_RES_IRQ, sc->rid_irq, sc->res_irq);
633 if (sc->res_ioport != 0) {
634 bus_deactivate_resource(dev, SYS_RES_IOPORT,
635 sc->rid_ioport, sc->res_ioport);
636 bus_release_resource(dev, SYS_RES_IOPORT,
637 sc->rid_ioport, sc->res_ioport);
643 * Print out interesting information about the 82596.
646 wldump(struct wl_softc *sc)
651 if_printf(&sc->wl_if, "hasr %04x\n", inw(HASR(base)));
653 if_printf(&sc->wl_if, "scb at %04x:\n ", OFFSET_SCB);
654 outw(PIOR1(base), OFFSET_SCB);
655 for(i = 0; i < 8; i++)
656 kprintf("%04x ", inw(PIOP1(base)));
659 if_printf(&sc->wl_if, "cu at %04x:\n ", OFFSET_CU);
660 outw(PIOR1(base), OFFSET_CU);
661 for(i = 0; i < 8; i++)
662 kprintf("%04x ", inw(PIOP1(base)));
665 if_printf(&sc->wl_if, "tbd at %04x:\n ", OFFSET_TBD);
666 outw(PIOR1(base), OFFSET_TBD);
667 for(i = 0; i < 4; i++)
668 kprintf("%04x ", inw(PIOP1(base)));
672 /* Initialize the Modem Management Controller */
674 wlinitmmc(struct wl_softc *sc)
681 /* enter 8 bit operation */
682 sc->hacr = (HACR_DEFAULT & ~HACR_16BITS);
685 configured = sc->psa[WLPSA_CONFIGURED] & 1;
688 * Set default modem control parameters. Taken from NCR document
691 MMC_WRITE(MMC_JABBER_ENABLE, 0x01);
692 MMC_WRITE(MMC_ANTEN_SEL, 0x02);
693 MMC_WRITE(MMC_IFS, 0x20);
694 MMC_WRITE(MMC_MOD_DELAY, 0x04);
695 MMC_WRITE(MMC_JAM_TIME, 0x38);
696 MMC_WRITE(MMC_DECAY_PRM, 0x00); /* obsolete ? */
697 MMC_WRITE(MMC_DECAY_UPDAT_PRM, 0x00);
699 MMC_WRITE(MMC_LOOPT_SEL, 0x00);
700 if (sc->psa[WLPSA_COMPATNO] & 1) {
701 MMC_WRITE(MMC_THR_PRE_SET, 0x01); /* 0x04 for AT and 0x01 for MCA */
703 MMC_WRITE(MMC_THR_PRE_SET, 0x04); /* 0x04 for AT and 0x01 for MCA */
705 MMC_WRITE(MMC_QUALITY_THR, 0x03);
707 /* use configuration defaults from parameter storage area */
708 if (sc->psa[WLPSA_NWIDENABLE] & 1) {
709 if ((mode & (MOD_PROM | MOD_ENAL)) && wl_ignore_nwid) {
710 MMC_WRITE(MMC_LOOPT_SEL, 0x40);
712 MMC_WRITE(MMC_LOOPT_SEL, 0x00);
715 MMC_WRITE(MMC_LOOPT_SEL, 0x40); /* disable network id check */
717 MMC_WRITE(MMC_THR_PRE_SET, sc->psa[WLPSA_THRESH]);
718 MMC_WRITE(MMC_QUALITY_THR, sc->psa[WLPSA_QUALTHRESH]);
720 MMC_WRITE(MMC_FREEZE, 0x00);
721 MMC_WRITE(MMC_ENCR_ENABLE, 0x00);
723 MMC_WRITE(MMC_NETW_ID_L,sc->nwid[1]); /* set NWID */
724 MMC_WRITE(MMC_NETW_ID_H,sc->nwid[0]);
726 /* enter normal 16 bit mode operation */
727 sc->hacr = HACR_DEFAULT;
729 CMD(sc); /* virtualpc1 needs this! */
731 if (sc->psa[WLPSA_COMPATNO]== /* 2.4 Gz: half-card ver */
732 WLPSA_COMPATNO_WL24B) { /* 2.4 Gz */
733 i=sc->chan24<<4; /* 2.4 Gz: position ch # */
734 MMC_WRITE(MMC_EEADDR,i+0x0f); /* 2.4 Gz: named ch, wc=16 */
735 MMC_WRITE(MMC_EECTRL,MMC_EECTRL_DWLD+ /* 2.4 Gz: Download Synths */
736 MMC_EECTRL_EEOP_READ); /* 2.4 Gz: Read EEPROM */
737 for (i=0; i<1000; ++i) { /* 2.4 Gz: wait for download */
738 DELAY(40); /* 2.4 Gz */
739 if ((wlmmcread(base,MMC_EECTRLstat) /* 2.4 Gz: check DWLD and */
740 &(MMC_EECTRLstat_DWLD /* 2.4 Gz: EEBUSY */
741 +MMC_EECTRLstat_EEBUSY))==0) /* 2.4 Gz: */
742 break; /* 2.4 Gz: download finished */
745 if_printf(&sc->wl_if,
746 "synth load failed\n"); /* 2.4 Gz */
748 MMC_WRITE(MMC_EEADDR,0x61); /* 2.4 Gz: default pwr, wc=2 */
749 MMC_WRITE(MMC_EECTRL,MMC_EECTRL_DWLD+ /* 2.4 Gz: Download Xmit Pwr */
750 MMC_EECTRL_EEOP_READ); /* 2.4 Gz: Read EEPROM */
751 for (i=0; i<1000; ++i) { /* 2.4 Gz: wait for download */
752 DELAY(40); /* 2.4 Gz */
753 if ((wlmmcread(base,MMC_EECTRLstat) /* 2.4 Gz: check DWLD and */
754 &(MMC_EECTRLstat_DWLD /* 2.4 Gz: EEBUSY */
755 +MMC_EECTRLstat_EEBUSY))==0) /* 2.4 Gz: */
756 break; /* 2.4 Gz: download finished */
759 if_printf(&sc->wl_if,
760 "xmit pwr load failed\n");/* 2.4 Gz */
762 MMC_WRITE(MMC_ANALCTRL, /* 2.4 Gz: EXT ant+polarity */
763 MMC_ANALCTRL_ANTPOL + /* 2.4 Gz: */
764 MMC_ANALCTRL_EXTANT); /* 2.4 Gz: */
765 i=sc->chan24<<4; /* 2.4 Gz: position ch # */
766 MMC_WRITE(MMC_EEADDR,i); /* 2.4 Gz: get frequency */
767 MMC_WRITE(MMC_EECTRL, /* 2.4 Gz: EEPROM read */
768 MMC_EECTRL_EEOP_READ); /* 2.4 Gz: */
769 DELAY(40); /* 2.4 Gz */
770 i = wlmmcread(base,MMC_EEDATALrv) /* 2.4 Gz: freq val */
771 + (wlmmcread(base,MMC_EEDATAHrv)<<8); /* 2.4 Gz */
772 sc->freq24 = (i>>6)+2400; /* 2.4 Gz: save real freq */
779 * Another routine that interfaces the "if" layer to this driver.
780 * Simply resets the structures that are used by "upper layers".
781 * As well as calling wlhwrst that does reset the WaveLAN board.
783 * input : softc pointer for this interface
784 * output : structures (if structs) and board are reset
790 struct wl_softc *sc = xsc;
791 struct ifnet *ifp = &sc->wl_if;
795 if (ifp->if_flags & IFF_DEBUG)
796 if_printf(ifp, "entered wlinit()\n");
798 if ((stat = wlhwrst(sc)) == TRUE) {
799 ifp->if_flags |= IFF_RUNNING; /* same as DSF_RUNNING */
801 * OACTIVE is used by upper-level routines
804 ifp->if_flags &= ~IFF_OACTIVE; /* same as tbusy below */
806 sc->flags |= DSF_RUNNING;
808 callout_stop(&sc->watchdog_ch);
812 if_printf(ifp, "init(): trouble resetting board.\n");
819 * This routine resets the WaveLAN board that corresponds to the
820 * board number passed in.
822 * input : softc pointer for this interface
823 * output : board is reset
827 wlhwrst(struct wl_softc *sc)
830 if (sc->wl_if.if_flags & IFF_DEBUG)
831 if_printf(&sc->wl_if, "entered wlhwrst()\n");
833 sc->hacr = HACR_RESET;
834 CMD(sc); /* reset the board */
836 /* clear reset command and set PIO#1 in autoincrement mode */
837 sc->hacr = HACR_DEFAULT;
841 if (sc->wl_if.if_flags & IFF_DEBUG)
842 wlmmcstat(sc); /* Display MMC registers */
844 wlbldcu(sc); /* set up command unit structures */
849 if (wlconfig(sc) == 0)
852 * insert code for loopback test here
854 wlrustrt(sc); /* start receive unit */
856 /* enable interrupts */
857 sc->hacr = (HACR_DEFAULT | HACR_INTRON);
866 * This function builds up the command unit structures. It inits
867 * the scp, iscp, scb, cb, tbd, and tbuf.
871 wlbldcu(struct wl_softc *sc)
873 short base = sc->base;
881 bzero(&scp, sizeof(scp));
883 scp.scp_iscp = OFFSET_ISCP;
884 scp.scp_iscp_base = 0;
885 outw(PIOR1(base), OFFSET_SCP);
886 outsw(PIOP1(base), &scp, sizeof(scp_t)/2);
888 bzero(&iscp, sizeof(iscp));
890 iscp.iscp_scb_offset = OFFSET_SCB;
892 iscp.iscp_scb_base = 0;
893 outw(PIOR1(base), OFFSET_ISCP);
894 outsw(PIOP1(base), &iscp, sizeof(iscp_t)/2);
897 scb.scb_command = SCB_RESET;
898 scb.scb_cbl_offset = OFFSET_CU;
899 scb.scb_rfa_offset = OFFSET_RU;
903 scb.scb_ovrnerrs = 0;
904 outw(PIOR1(base), OFFSET_SCB);
905 outsw(PIOP1(base), &scb, sizeof(scb_t)/2);
909 outw(PIOR0(base), OFFSET_ISCP + 0); /* address of iscp_busy */
910 for (i = 1000000; inw(PIOP0(base)) && (i-- > 0); );
911 if (i <= 0) if_printf(&sc->wl_if, "bldcu(): iscp_busy timeout.\n");
912 outw(PIOR0(base), OFFSET_SCB + 0); /* address of scb_status */
913 for (i = STATUS_TRIES; i-- > 0; ) {
914 if (inw(PIOP0(base)) == (SCB_SW_CX|SCB_SW_CNA))
918 if_printf(&sc->wl_if, "bldcu(): not ready after reset.\n");
922 cb.ac_command = AC_CW_EL; /* NOP */
923 cb.ac_link_offset = OFFSET_CU;
924 outw(PIOR1(base), OFFSET_CU);
925 outsw(PIOP1(base), &cb, 6/2);
928 tbd.next_tbd_offset = I82586NULL;
931 outw(PIOR1(base), OFFSET_TBD);
932 outsw(PIOP1(base), &tbd, sizeof(tbd_t)/2);
940 * input : pointer the appropriate "if" struct
941 * output : stuff sent to board if any there
945 wlstart(struct ifnet *ifp)
948 struct wl_softc *sc = ifp->if_softc;
949 short base = sc->base;
950 int scb_status, cu_status, scb_command;
953 if (ifp->if_flags & IFF_DEBUG)
954 if_printf(ifp, "entered wlstart()\n");
957 outw(PIOR1(base), OFFSET_CU);
958 cu_status = inw(PIOP1(base));
959 outw(PIOR0(base),OFFSET_SCB + 0); /* scb_status */
960 scb_status = inw(PIOP0(base));
961 outw(PIOR0(base), OFFSET_SCB + 2);
962 scb_command = inw(PIOP0(base));
965 * don't need OACTIVE check as tbusy here checks to see
966 * if we are already busy
969 if((scb_status & 0x0700) == SCB_CUS_IDLE &&
970 (cu_status & AC_SW_B) == 0){
972 callout_stop(&sc->watchdog_ch);
973 ifp->if_flags &= ~IFF_OACTIVE;
975 * This is probably just a race. The xmt'r is just
976 * became idle but WE have masked interrupts so ...
979 if_printf(ifp, "CU idle, scb %04x %04x cu %04x\n",
980 scb_status, scb_command, cu_status);
982 if (xmt_watch) if_printf(ifp, "!!\n");
984 return; /* genuinely still busy */
986 } else if((scb_status & 0x0700) == SCB_CUS_ACTV ||
987 (cu_status & AC_SW_B)){
989 if_printf(ifp, "CU unexpectedly busy; scb %04x cu %04x\n",
990 scb_status, cu_status);
992 if (xmt_watch) if_printf(ifp, "busy?!");
993 return; /* hey, why are we busy? */
996 /* get ourselves some data */
998 m = ifq_dequeue(&ifp->if_snd, NULL);
1002 /* set the watchdog timer so that if the board
1003 * fails to interrupt we will restart
1005 /* try 10 ticks, not very long */
1006 callout_reset(&sc->watchdog_ch, 10, wlwatchdog, sc);
1007 ifp->if_flags |= IFF_OACTIVE;
1011 ifp->if_flags &= ~IFF_OACTIVE;
1018 * This routine does the actual copy of data (including ethernet header
1019 * structure) from the WaveLAN to an mbuf chain that will be passed up
1020 * to the "if" (network interface) layer. NOTE: we currently
1021 * don't handle trailer protocols, so if that is needed, it will
1022 * (at least in part) be added here. For simplicities sake, this
1023 * routine copies the receive buffers from the board into a local (stack)
1024 * buffer until the frame has been copied from the board. Once in
1025 * the local buffer, the contents are copied to an mbuf chain that
1026 * is then enqueued onto the appropriate "if" queue.
1028 * input : softc pointer for this interface and
1029 * an frame descriptor address
1030 * output : the packet is put into an mbuf chain, and passed up
1031 * assumes : if any errors occur, packet is "dropped on the floor"
1035 wlread(struct wl_softc *sc, u_short fd_p)
1037 struct ifnet *ifp = &sc->wl_if;
1038 short base = sc->base;
1040 struct ether_header eh;
1041 struct mbuf *m, *tm;
1044 u_short mlen, len, clen;
1045 u_short bytes_in_msg, bytes_in_mbuf, bytes;
1049 if (ifp->if_flags & IFF_DEBUG)
1050 if_printf(ifp, "entered wlread()\n");
1052 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
1053 if_printf(ifp, "read(): board is not running.\n");
1054 sc->hacr &= ~HACR_INTRON;
1055 CMD(sc); /* turn off interrupts */
1057 /* read ether_header info out of device memory. doesn't
1058 * go into mbuf. goes directly into eh structure
1060 len = sizeof(struct ether_header); /* 14 bytes */
1061 outw(PIOR1(base), fd_p);
1062 insw(PIOP1(base), &fd, (sizeof(fd_t) - len)/2);
1063 insw(PIOP1(base), &eh, (len-2)/2);
1064 eh.ether_type = ntohs(inw(PIOP1(base)));
1066 if (ifp->if_flags & IFF_DEBUG)
1067 if_printf(ifp, "wlread: rcv packet, type is %x\n", eh.ether_type);
1070 * WARNING. above is done now in ether_input, above may be
1071 * useful for debug. jrb
1073 eh.ether_type = htons(eh.ether_type);
1075 if (fd.rbd_offset == I82586NULL) {
1076 if_printf(ifp, "read(): Invalid buffer\n");
1077 if (wlhwrst(sc) != TRUE)
1078 if_printf(ifp, "read(): hwrst trouble.\n");
1082 outw(PIOR1(base), fd.rbd_offset);
1083 insw(PIOP1(base), &rbd, sizeof(rbd_t)/2);
1084 bytes_in_msg = rbd.status & RBD_SW_COUNT;
1085 MGETHDR(m, MB_DONTWAIT, MT_DATA);
1089 * not only do we want to return, we need to drop the packet on
1090 * the floor to clear the interrupt.
1093 if (wlhwrst(sc) != TRUE) {
1094 sc->hacr &= ~HACR_INTRON;
1095 CMD(sc); /* turn off interrupts */
1096 if_printf(ifp, "read(): hwrst trouble.\n");
1100 m->m_next = (struct mbuf *) 0;
1101 m->m_pkthdr.rcvif = ifp;
1102 m->m_pkthdr.len = 0; /* don't know this yet */
1105 /* always use a cluster. jrb
1107 MCLGET(m, MB_DONTWAIT);
1108 if (m->m_flags & M_EXT) {
1109 m->m_len = MCLBYTES;
1113 if (wlhwrst(sc) != TRUE) {
1114 sc->hacr &= ~HACR_INTRON;
1115 CMD(sc); /* turn off interrupts */
1116 if_printf(ifp, "read(): hwrst trouble.\n");
1123 bytes_in_mbuf = m->m_len - sizeof(eh);
1124 mb_p = mtod(tm, u_char *);
1125 bytes = min(bytes_in_mbuf, bytes_in_msg);
1126 bcopy(&eh, mb_p, sizeof(eh));
1134 outw(PIOR1(base), rbd.buffer_addr);
1135 insw(PIOP1(base), mb_p, len/2);
1139 if (!(bytes_in_mbuf -= bytes)) {
1140 MGET(tm->m_next, MB_DONTWAIT, MT_DATA);
1142 if (tm == (struct mbuf *)0) {
1144 if_printf(ifp, "read(): No mbuf nth\n");
1145 if (wlhwrst(sc) != TRUE) {
1146 sc->hacr &= ~HACR_INTRON;
1147 CMD(sc); /* turn off interrupts */
1148 if_printf(ifp, "read(): hwrst trouble.\n");
1154 bytes_in_mbuf = MLEN;
1155 mb_p = mtod(tm, u_char *);
1160 if (!(bytes_in_msg -= bytes)) {
1161 if (rbd.status & RBD_SW_EOF ||
1162 rbd.next_rbd_offset == I82586NULL) {
1166 outw(PIOR1(base), rbd.next_rbd_offset);
1167 insw(PIOP1(base), &rbd, sizeof(rbd_t)/2);
1168 bytes_in_msg = rbd.status & RBD_SW_COUNT;
1171 rbd.buffer_addr += bytes;
1174 bytes = min(bytes_in_mbuf, bytes_in_msg);
1177 m->m_pkthdr.len = clen;
1180 * If hw is in promiscuous mode (note that I said hardware, not if
1181 * IFF_PROMISC is set in ifnet flags), then if this is a unicast
1182 * packet and the MAC dst is not us, drop it. This check in normally
1183 * inside ether_input(), but IFF_MULTI causes hw promisc without
1184 * a bpf listener, so this is wrong.
1185 * Greg Troxel <gdt@ir.bbn.com>, 1998-08-07
1188 * TBD: also discard packets where NWID does not match.
1189 * However, there does not appear to be a way to read the nwid
1190 * for a received packet. -gdt 1998-08-07
1193 #ifdef WL_USE_IFNET_PROMISC_CHECK /* not defined */
1194 (ifp->if_flags & (IFF_PROMISC|IFF_ALLMULTI))
1196 /* hw is in promisc mode if this is true */
1197 (sc->mode & (MOD_PROM | MOD_ENAL))
1200 (eh.ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */
1201 bcmp(eh.ether_dhost, sc->wl_ac.ac_enaddr,
1202 sizeof(eh.ether_dhost)) != 0 ) {
1208 if (ifp->if_flags & IFF_DEBUG)
1209 if_printf(ifp, "wlrecv %d bytes\n", clen);
1213 wl_cache_store(sc, base, &eh, m);
1217 * received packet is now in a chain of mbuf's. next step is
1218 * to pass the packet upwards.
1221 ifp->if_input(ifp, m);
1228 * This routine processes an ioctl request from the "if" layer
1231 * input : pointer the appropriate "if" struct, command and data
1232 * output : based on command appropriate action is taken on the
1233 * WaveLAN board(s) or related structures
1234 * return : error is returned containing exit conditions
1238 wlioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cred)
1240 struct ifreq *ifr = (struct ifreq *)data;
1241 struct wl_softc *sc = ifp->if_softc;
1242 short base = sc->base;
1245 int irq, irqval, i, isroot, size;
1248 struct thread *td = curthread; /* XXX */
1252 if (ifp->if_flags & IFF_DEBUG)
1253 if_printf(ifp, "entered wlioctl()\n");
1257 if (ifp->if_flags & IFF_ALLMULTI) {
1260 if (ifp->if_flags & IFF_PROMISC) {
1263 if(ifp->if_flags & IFF_LINK0) {
1267 * force a complete reset if the recieve multicast/
1268 * promiscuous mode changes so that these take
1269 * effect immediately.
1272 if (sc->mode != mode) {
1274 if (sc->flags & DSF_RUNNING) {
1275 sc->flags &= ~DSF_RUNNING;
1279 /* if interface is marked DOWN and still running then
1282 if ((ifp->if_flags & IFF_UP) == 0 && sc->flags & DSF_RUNNING) {
1283 if_printf(ifp, "ioctl(): board is not running\n");
1284 sc->flags &= ~DSF_RUNNING;
1285 sc->hacr &= ~HACR_INTRON;
1286 CMD(sc); /* turn off interrupts */
1288 /* else if interface is UP and RUNNING, start it
1290 else if (ifp->if_flags & IFF_UP && (sc->flags & DSF_RUNNING) == 0) {
1294 /* if WLDEBUG set on interface, then kprintf rf-modem regs
1296 if(ifp->if_flags & IFF_DEBUG)
1303 #if defined(__FreeBSD__) && __FreeBSD_version < 300000
1304 if (cmd == SIOCADDMULTI) {
1305 error = ether_addmulti(ifr, &sc->wl_ac);
1308 error = ether_delmulti(ifr, &sc->wl_ac);
1311 /* see if we should be in all multicast mode
1312 * note that 82586 cannot do that, must simulate with
1315 if (check_allmulti(sc)) {
1316 ifp->if_flags |= IFF_ALLMULTI;
1317 sc->mode |= MOD_ENAL;
1318 sc->flags &= ~DSF_RUNNING;
1324 if (error == ENETRESET) {
1325 if(sc->flags & DSF_RUNNING) {
1326 sc->flags &= ~DSF_RUNNING;
1335 #endif /* MULTICAST */
1337 /* DEVICE SPECIFIC */
1340 /* copy the PSA out to the caller */
1342 /* pointer to buffer in user space */
1343 up = (void *)ifr->ifr_data;
1344 /* work out if they're root */
1345 isroot = (suser(td) == 0);
1347 for (i = 0; i < 0x40; i++) {
1348 /* don't hand the DES key out to non-root users */
1349 if ((i > WLPSA_DESKEY) && (i < (WLPSA_DESKEY + 8)) && !isroot)
1351 if (subyte((up + i), sc->psa[i]))
1357 /* copy the PSA in from the caller; we only copy _some_ values */
1360 if ((error = suser(td)))
1362 error = EINVAL; /* assume the worst */
1363 /* pointer to buffer in user space containing data */
1364 up = (void *)ifr->ifr_data;
1366 /* check validity of input range */
1367 for (i = 0; i < 0x40; i++)
1368 if (fubyte(up + i) < 0)
1371 /* check IRQ value */
1372 irqval = fubyte(up+WLPSA_IRQNO);
1373 for (irq = 15; irq >= 0; irq--)
1374 if(irqvals[irq] == irqval)
1376 if (irq == 0) /* oops */
1379 sc->psa[WLPSA_IRQNO] = irqval;
1382 for (i = 0; i < 6; i++)
1383 sc->psa[WLPSA_LOCALMAC+i] = fubyte(up+WLPSA_LOCALMAC+i);
1386 sc->psa[WLPSA_MACSEL] = fubyte(up+WLPSA_MACSEL);
1389 sc->psa[WLPSA_NWID] = fubyte(up+WLPSA_NWID);
1390 sc->psa[WLPSA_NWID+1] = fubyte(up+WLPSA_NWID+1);
1393 wlsetpsa(sc); /* update the PSA */
1397 /* get the current NWID out of the sc since we stored it there */
1399 ifr->ifr_data = (caddr_t) (sc->nwid[0] << 8 | sc->nwid[1]);
1404 * change the nwid dynamically. This
1405 * ONLY changes the radio modem and does not
1409 * 1. save in softc "soft registers"
1410 * 2. save in radio modem (MMC)
1414 if ((error = suser(td)))
1416 if (!(ifp->if_flags & IFF_UP)) {
1417 error = EIO; /* only allowed while up */
1420 * soft c nwid shadows radio modem setting
1422 sc->nwid[0] = (int)ifr->ifr_data >> 8;
1423 sc->nwid[1] = (int)ifr->ifr_data & 0xff;
1424 MMC_WRITE(MMC_NETW_ID_L,sc->nwid[1]);
1425 MMC_WRITE(MMC_NETW_ID_H,sc->nwid[0]);
1429 /* copy the EEPROM in 2.4 Gz WaveMODEM out to the caller */
1432 if ((error = suser(td)))
1434 /* pointer to buffer in user space */
1435 up = (void *)ifr->ifr_data;
1437 for (i=0x00; i<0x80; ++i) { /* 2.4 Gz: size of EEPROM */
1438 MMC_WRITE(MMC_EEADDR,i); /* 2.4 Gz: get frequency */
1439 MMC_WRITE(MMC_EECTRL, /* 2.4 Gz: EEPROM read */
1440 MMC_EECTRL_EEOP_READ); /* 2.4 Gz: */
1441 DELAY(40); /* 2.4 Gz */
1442 if (subyte(up + 2*i , /* 2.4 Gz: pass low byte of */
1443 wlmmcread(base,MMC_EEDATALrv)) /* 2.4 Gz: EEPROM word */
1444 ) return(EFAULT); /* 2.4 Gz: */
1445 if (subyte(up + 2*i+1, /* 2.4 Gz: pass hi byte of */
1446 wlmmcread(base,MMC_EEDATALrv)) /* 2.4 Gz: EEPROM word */
1447 ) return(EFAULT); /* 2.4 Gz: */
1452 /* zero (Delete) the wl cache */
1455 if ((error = suser(td)))
1460 /* read out the number of used cache elements */
1462 ifr->ifr_data = (caddr_t) sc->w_sigitems;
1465 /* read out the wl cache */
1467 /* pointer to buffer in user space */
1468 up = (void *)ifr->ifr_data;
1469 cpt = (char *) &sc->w_sigcache[0];
1470 size = sc->w_sigitems * sizeof(struct w_sigcache);
1472 for (i = 0; i < size; i++) {
1473 if (subyte((up + i), *cpt++))
1480 error = ether_ioctl(ifp, cmd, data);
1489 * Called if the timer set in wlstart expires before an interrupt is received
1490 * from the wavelan. It seems to lose interrupts sometimes.
1491 * The watchdog routine gets called if the transmitter failed to interrupt
1493 * input : which board is timing out
1494 * output : board reset
1498 wlwatchdog(void *vsc)
1500 struct wl_softc *sc = vsc;
1501 struct ifnet *ifp = &sc->wl_if;
1503 lwkt_serialize_enter(ifp->if_serializer);
1504 log(LOG_ERR, "%s: wavelan device timeout on xmit\n", sc->wl_if.if_xname);
1505 sc->wl_if.if_oerrors++;
1507 lwkt_serialize_exit(ifp->if_serializer);
1513 * This function is the interrupt handler for the WaveLAN
1514 * board. This routine will be called whenever either a packet
1515 * is received, or a packet has successfully been transfered and
1516 * the unit is ready to transmit another packet.
1518 * input : softc pointer for this interface
1519 * output : either a packet is received, or a packet is transfered
1525 struct wl_softc *sc = arg;
1526 struct ifnet *ifp = &sc->wl_if;
1527 short base = sc->base;
1529 u_short int_type, int_type1;
1532 if (ifp->if_flags & IFF_DEBUG)
1533 if_printf(ifp, "wlintr() called\n");
1536 if((int_type = inw(HASR(base))) & HASR_MMC_INTR) {
1537 /* handle interrupt from the modem management controler */
1538 /* This will clear the interrupt condition */
1539 wlmmcread(base,MMC_DCE_STATUS); /* ignored for now */
1542 if(!(int_type & HASR_INTR)){ /* return if no interrupt from 82586 */
1543 /* commented out. jrb. it happens when reinit occurs
1544 if_printf(ifp, "%s: int_type %x, dump follows\n",
1545 __func__, int_type);
1554 outw(PIOR0(base), OFFSET_SCB + 0); /* get scb status */
1555 int_type = (inw(PIOP0(base)) & SCB_SW_INT);
1556 if (int_type == 0) /* no interrupts left */
1559 int_type1 = wlack(sc); /* acknowledge interrupt(s) */
1560 /* make sure no bits disappeared (others may appear) */
1561 if ((int_type & int_type1) != int_type) {
1562 if_printf(ifp, "wlack() int bits disappeared: "
1563 "%04x != int_type %04x\n", int_type1, int_type);
1565 int_type = int_type1; /* go with the new status */
1569 if (int_type & SCB_SW_FR) {
1574 * receiver not ready
1576 if (int_type & SCB_SW_RNR) {
1579 if (ifp->if_flags & IFF_DEBUG) {
1580 if_printf(ifp, "intr(): receiver overrun! begin_fd = %x\n",
1589 if (int_type & SCB_SW_CNA) {
1591 * At present, we don't care about CNA's. We
1592 * believe they are a side effect of XMT.
1595 if (int_type & SCB_SW_CX) {
1597 * At present, we only request Interrupt for
1600 outw(PIOR1(base), OFFSET_CU); /* get command status */
1601 ac_status = inw(PIOP1(base));
1603 if (xmt_watch) { /* report some anomalies */
1605 if (sc->tbusy == 0) {
1606 if_printf(ifp, "xmt intr but not busy, CU %04x\n",
1609 if (ac_status == 0) {
1610 if_printf(ifp, "xmt intr but ac_status == 0\n");
1612 if (ac_status & AC_SW_A) {
1613 if_printf(ifp, "xmt aborted\n");
1616 if (ac_status & TC_CARRIER) {
1617 if_printf(ifp, "no carrier\n");
1620 if (ac_status & TC_CLS) {
1621 if_printf(ifp, "no CTS\n");
1623 if (ac_status & TC_DMA) {
1624 if_printf(ifp, "DMA underrun\n");
1626 if (ac_status & TC_DEFER) {
1627 if_printf(ifp, "xmt deferred\n");
1629 if (ac_status & TC_SQE) {
1630 if_printf(ifp, "heart beat\n");
1632 if (ac_status & TC_COLLISION) {
1633 if_printf(ifp, "too many collisions\n");
1636 /* if the transmit actually failed, or returned some status */
1637 if ((!(ac_status & AC_SW_OK)) || (ac_status & 0xfff)) {
1638 if (ac_status & (TC_COLLISION | TC_CLS | TC_DMA)) {
1642 /* count collisions */
1643 ifp->if_collisions += (ac_status & 0xf);
1644 /* if TC_COLLISION set and collision count zero, 16 collisions */
1645 if ((ac_status & 0x20) == 0x20) {
1646 ifp->if_collisions += 0x10;
1650 callout_stop(&sc->watchdog_ch);
1651 ifp->if_flags &= ~IFF_OACTIVE;
1660 * This routine is called by the interrupt handler to initiate a
1661 * packet transfer from the board to the "if" layer above this
1662 * driver. This routine checks if a buffer has been successfully
1663 * received by the WaveLAN. If so, the routine wlread is called
1664 * to do the actual transfer of the board data (including the
1665 * ethernet header) into a packet (consisting of an mbuf chain).
1667 * input : softc pointer for this interface
1668 * output : if a packet is available, it is "sent up"
1672 wlrcv(struct wl_softc *sc)
1674 short base = sc->base;
1675 u_short fd_p, status, offset, link_offset;
1678 if (sc->wl_if.if_flags & IFF_DEBUG)
1679 if_printf(&sc->wl_if, "entered wlrcv()\n");
1681 for (fd_p = sc->begin_fd; fd_p != I82586NULL; fd_p = sc->begin_fd) {
1683 outw(PIOR0(base), fd_p + 0); /* address of status */
1684 status = inw(PIOP0(base));
1685 outw(PIOR1(base), fd_p + 4); /* address of link_offset */
1686 link_offset = inw(PIOP1(base));
1687 offset = inw(PIOP1(base)); /* rbd_offset */
1688 if (status == 0xffff || offset == 0xffff /*I82586NULL*/) {
1689 if (wlhwrst(sc) != TRUE)
1690 if_printf(&sc->wl_if, "rcv(): hwrst ffff trouble.\n");
1692 } else if (status & AC_SW_C) {
1693 if (status == (RFD_DONE|RFD_RSC)) {
1696 if (sc->wl_if.if_flags & IFF_DEBUG)
1697 if_printf(&sc->wl_if, "RCV: RSC %x\n", status);
1699 sc->wl_if.if_ierrors++;
1700 } else if (!(status & RFD_OK)) {
1701 if_printf(&sc->wl_if, "RCV: !OK %x\n", status);
1702 sc->wl_if.if_ierrors++;
1703 } else if (status & 0xfff) { /* can't happen */
1704 if_printf(&sc->wl_if, "RCV: ERRs %x\n", status);
1705 sc->wl_if.if_ierrors++;
1706 } else if (!wlread(sc, fd_p))
1709 if (!wlrequeue(sc, fd_p)) {
1710 /* abort on chain error */
1711 if (wlhwrst(sc) != TRUE)
1712 if_printf(&sc->wl_if, "rcv(): hwrst trouble.\n");
1715 sc->begin_fd = link_offset;
1725 * This routine puts rbd's used in the last receive back onto the
1726 * free list for the next receive.
1730 wlrequeue(struct wl_softc *sc, u_short fd_p)
1732 short base = sc->base;
1734 u_short l_rbdp, f_rbdp, rbd_offset;
1736 outw(PIOR0(base), fd_p + 6);
1737 rbd_offset = inw(PIOP0(base));
1738 if ((f_rbdp = rbd_offset) != I82586NULL) {
1741 outw(PIOR0(base), l_rbdp + 0); /* address of status */
1742 if(inw(PIOP0(base)) & RBD_SW_EOF)
1744 outw(PIOP0(base), 0);
1745 outw(PIOR0(base), l_rbdp + 2); /* next_rbd_offset */
1746 if((l_rbdp = inw(PIOP0(base))) == I82586NULL)
1749 outw(PIOP0(base), 0);
1750 outw(PIOR0(base), l_rbdp + 2); /* next_rbd_offset */
1751 outw(PIOP0(base), I82586NULL);
1752 outw(PIOR0(base), l_rbdp + 8); /* address of size */
1753 outw(PIOP0(base), inw(PIOP0(base)) | AC_CW_EL);
1754 outw(PIOR0(base), sc->end_rbd + 2);
1755 outw(PIOP0(base), f_rbdp); /* end_rbd->next_rbd_offset */
1756 outw(PIOR0(base), sc->end_rbd + 8); /* size */
1757 outw(PIOP0(base), inw(PIOP0(base)) & ~AC_CW_EL);
1758 sc->end_rbd = l_rbdp;
1762 fd.command = AC_CW_EL;
1763 fd.link_offset = I82586NULL;
1764 fd.rbd_offset = I82586NULL;
1765 outw(PIOR1(base), fd_p);
1766 outsw(PIOP1(base), &fd, 8/2);
1768 outw(PIOR1(base), sc->end_fd + 2); /* addr of command */
1769 outw(PIOP1(base), 0); /* command = 0 */
1770 outw(PIOP1(base), fd_p); /* end_fd->link_offset = fd_p */
1777 static int xmt_debug = 0;
1778 #endif /* WLDEBUG */
1783 * This routine fills in the appropriate registers and memory
1784 * locations on the WaveLAN board and starts the board off on
1787 * input : softc pointer for this interface, and a pointer to the mbuf
1788 * output : board memory and registers are set for xfer and attention
1792 wlxmt(struct wl_softc *sc, struct mbuf *m)
1794 u_short xmtdata_p = OFFSET_TBUF;
1796 struct mbuf *tm_p = m;
1797 struct ether_header *eh_p = mtod(m, struct ether_header *);
1798 u_char *mb_p = mtod(m, u_char *) + sizeof(struct ether_header);
1799 u_short count = m->m_len - sizeof(struct ether_header);
1801 u_short tbd_p = OFFSET_TBD;
1802 u_short len, clen = 0;
1803 short base = sc->base;
1807 if (sc->wl_if.if_flags & IFF_DEBUG)
1808 if_printf(&sc->wl_if, "entered wlxmt()\n");
1812 cb.ac_command = (AC_CW_EL|AC_TRANSMIT|AC_CW_I);
1813 cb.ac_link_offset = I82586NULL;
1814 outw(PIOR1(base), OFFSET_CU);
1815 outsw(PIOP1(base), &cb, 6/2);
1816 outw(PIOP1(base), OFFSET_TBD); /* cb.cmd.transmit.tbd_offset */
1817 outsw(PIOP1(base), eh_p->ether_dhost, WAVELAN_ADDR_SIZE/2);
1818 outw(PIOP1(base), eh_p->ether_type);
1821 if (sc->wl_if.if_flags & IFF_DEBUG) {
1823 if_printf(&sc->wl_if, "XMT mbuf: L%d @%p ", count, (void *)mb_p);
1824 kprintf("ether type %x\n", eh_p->ether_type);
1827 #endif /* WLDEBUG */
1828 outw(PIOR0(base), OFFSET_TBD);
1829 outw(PIOP0(base), 0); /* act_count */
1830 outw(PIOR1(base), OFFSET_TBD + 4);
1831 outw(PIOP1(base), xmtdata_p); /* buffer_addr */
1832 outw(PIOP1(base), 0); /* buffer_base */
1835 if (clen + count > WAVELAN_MTU)
1841 outw(PIOR1(base), xmtdata_p);
1842 outsw(PIOP1(base), mb_p, len/2);
1844 outw(PIOR0(base), tbd_p); /* address of act_count */
1845 outw(PIOP0(base), inw(PIOP0(base)) + count);
1847 if ((tm_p = tm_p->m_next) == (struct mbuf *)0)
1850 /* go to the next descriptor */
1851 outw(PIOR0(base), tbd_p + 2);
1852 tbd_p += sizeof (tbd_t);
1853 outw(PIOP0(base), tbd_p); /* next_tbd_offset */
1854 outw(PIOR0(base), tbd_p);
1855 outw(PIOP0(base), 0); /* act_count */
1856 outw(PIOR1(base), tbd_p + 4);
1857 outw(PIOP1(base), xmtdata_p); /* buffer_addr */
1858 outw(PIOP1(base), 0); /* buffer_base */
1859 /* at the end -> coallesce remaining mbufs */
1860 if (tbd_p == OFFSET_TBD + (N_TBD-1) * sizeof (tbd_t)) {
1861 wlsftwsleaze(&count, &mb_p, &tm_p);
1864 /* next mbuf short -> coallesce as needed */
1865 if ( (tm_p->m_next == (struct mbuf *) 0) ||
1866 #define HDW_THRESHOLD 55
1867 tm_p->m_len > HDW_THRESHOLD)
1870 wlhdwsleaze(&count, &mb_p, &tm_p);
1874 } else if ((tm_p = tm_p->m_next) == (struct mbuf *)0)
1876 count = tm_p->m_len;
1877 mb_p = mtod(tm_p, u_char *);
1879 if (sc->wl_if.if_flags & IFF_DEBUG)
1881 if_printf(&sc->wl_if, "mbuf+ L%d @%p ", count, (void *)mb_p);
1882 #endif /* WLDEBUG */
1885 if (sc->wl_if.if_flags & IFF_DEBUG)
1887 if_printf(&sc->wl_if, "CLEN = %d\n", clen);
1888 #endif /* WLDEBUG */
1889 outw(PIOR0(base), tbd_p);
1890 if (clen < ETHERMIN) {
1891 outw(PIOP0(base), inw(PIOP0(base)) + ETHERMIN - clen);
1892 outw(PIOR1(base), xmtdata_p);
1893 for (xmtshort_p = xmtdata_p; clen < ETHERMIN; clen += 2)
1894 outw(PIOP1(base), 0);
1896 outw(PIOP0(base), inw(PIOP0(base)) | TBD_SW_EOF);
1897 outw(PIOR0(base), tbd_p + 2);
1898 outw(PIOP0(base), I82586NULL);
1900 if (sc->wl_if.if_flags & IFF_DEBUG) {
1906 #endif /* WLDEBUG */
1908 outw(PIOR0(base), OFFSET_SCB + 2); /* address of scb_command */
1910 * wait for 586 to clear previous command, complain if it takes
1913 for (spin = 1;;spin = (spin + 1) % 10000) {
1914 if (inw(PIOP0(base)) == 0) { /* it's done, we can go */
1917 if ((spin == 0) && xmt_watch) { /* not waking up, and we care */
1918 if_printf(&sc->wl_if, "slow accepting xmit\n");
1921 outw(PIOP0(base), SCB_CU_STRT); /* new command */
1927 * Pause to avoid transmit overrun problems.
1928 * The required delay tends to vary with platform type, and may be
1929 * related to interrupt loss.
1931 if (wl_xmit_delay) {
1932 DELAY(wl_xmit_delay);
1939 * This function builds the linear linked lists of fd's and
1940 * rbd's. Based on page 4-32 of 1986 Intel microcom handbook.
1944 wlbldru(struct wl_softc *sc)
1946 short base = sc->base;
1949 u_short fd_p = OFFSET_RU;
1950 u_short rbd_p = OFFSET_RBD;
1953 sc->begin_fd = fd_p;
1954 for(i = 0; i < N_FD; i++) {
1957 fd.link_offset = fd_p + sizeof(fd_t);
1958 fd.rbd_offset = I82586NULL;
1959 outw(PIOR1(base), fd_p);
1960 outsw(PIOP1(base), &fd, 8/2);
1961 fd_p = fd.link_offset;
1963 fd_p -= sizeof(fd_t);
1965 outw(PIOR1(base), fd_p + 2);
1966 outw(PIOP1(base), AC_CW_EL); /* command */
1967 outw(PIOP1(base), I82586NULL); /* link_offset */
1970 outw(PIOR0(base), fd_p + 6); /* address of rbd_offset */
1971 outw(PIOP0(base), rbd_p);
1972 outw(PIOR1(base), rbd_p);
1973 for(i = 0; i < N_RBD; i++) {
1975 rbd.buffer_addr = rbd_p + sizeof(rbd_t) + 2;
1976 rbd.buffer_base = 0;
1977 rbd.size = RCVBUFSIZE;
1979 rbd_p += sizeof(ru_t);
1980 rbd.next_rbd_offset = rbd_p;
1982 rbd.next_rbd_offset = I82586NULL;
1983 rbd.size |= AC_CW_EL;
1984 sc->end_rbd = rbd_p;
1986 outsw(PIOP1(base), &rbd, sizeof(rbd_t)/2);
1987 outw(PIOR1(base), rbd_p);
1989 return sc->begin_fd;
1995 * This routine starts the receive unit running. First checks if the
1996 * board is actually ready, then the board is instructed to receive
2001 wlrustrt(struct wl_softc *sc)
2003 short base = sc->base;
2007 if (sc->wl_if.if_flags & IFF_DEBUG)
2008 if_printf(&sc->wl_if, "entered wlrustrt()\n");
2010 outw(PIOR0(base), OFFSET_SCB);
2011 if (inw(PIOP0(base)) & SCB_RUS_READY){
2012 if_printf(&sc->wl_if, "wlrustrt: RUS_READY\n");
2016 outw(PIOR0(base), OFFSET_SCB + 2);
2017 outw(PIOP0(base), SCB_RU_STRT); /* command */
2019 outw(PIOR0(base), OFFSET_SCB + 6); /* address of scb_rfa_offset */
2020 outw(PIOP0(base), rfa);
2028 * This routine does a 586 op-code number 7, and obtains the
2029 * diagnose status for the WaveLAN.
2033 wldiag(struct wl_softc *sc)
2035 short base = sc->base;
2039 if (sc->wl_if.if_flags & IFF_DEBUG)
2040 if_printf(&sc->wl_if, "entered wldiag()\n");
2042 outw(PIOR0(base), OFFSET_SCB);
2043 status = inw(PIOP0(base));
2044 if (status & SCB_SW_INT) {
2045 /* state is 2000 which seems ok
2046 if_printf(&sc->wl_if, "diag(): unexpected initial state %\n",
2051 outw(PIOR1(base), OFFSET_CU);
2052 outw(PIOP1(base), 0); /* ac_status */
2053 outw(PIOP1(base), AC_DIAGNOSE|AC_CW_EL);/* ac_command */
2054 if(wlcmd(sc, "diag()") == 0)
2056 outw(PIOR0(base), OFFSET_CU);
2057 if (inw(PIOP0(base)) & 0x0800) {
2058 if_printf(&sc->wl_if, "i82586 Self Test failed!\n");
2067 * This routine does a standard config of the WaveLAN board.
2071 wlconfig(struct wl_softc *sc)
2073 configure_t configure;
2074 short base = sc->base;
2077 #if defined(__DragonFly__) || (defined(__FreeBSD__) && __FreeBSD_version >= 300000)
2078 struct ifmultiaddr *ifma;
2081 struct ether_multi *enm;
2082 struct ether_multistep step;
2085 #endif /* MULTICAST */
2088 if (sc->wl_if.if_flags & IFF_DEBUG)
2089 if_printf(&sc->wl_if, "entered wlconfig()\n");
2091 outw(PIOR0(base), OFFSET_SCB);
2092 if (inw(PIOP0(base)) & SCB_SW_INT) {
2094 if_printf(&sc->wl_if, "config(): unexpected initial state %x\n",
2100 outw(PIOR1(base), OFFSET_CU);
2101 outw(PIOP1(base), 0); /* ac_status */
2102 outw(PIOP1(base), AC_CONFIGURE|AC_CW_EL); /* ac_command */
2105 configure.fifolim_bytecnt = 0x080c;
2106 configure.addrlen_mode = 0x0600;
2107 configure.linprio_interframe = 0x2060;
2108 configure.slot_time = 0xf200;
2109 configure.hardware = 0x0008; /* tx even w/o CD */
2110 configure.min_frame_len = 0x0040;
2112 /* This is the configuration block suggested by Marc Meertens
2113 * <mmeerten@obelix.utrecht.NCR.COM> in an e-mail message to John
2114 * Ioannidis on 10 Nov 92.
2116 configure.fifolim_bytecnt = 0x040c;
2117 configure.addrlen_mode = 0x0600;
2118 configure.linprio_interframe = 0x2060;
2119 configure.slot_time = 0xf000;
2120 configure.hardware = 0x0008; /* tx even w/o CD */
2121 configure.min_frame_len = 0x0040;
2124 * below is the default board configuration from p2-28 from 586 book
2126 configure.fifolim_bytecnt = 0x080c;
2127 configure.addrlen_mode = 0x2600;
2128 configure.linprio_interframe = 0x7820; /* IFS=120, ACS=2 */
2129 configure.slot_time = 0xf00c; /* slottime=12 */
2130 configure.hardware = 0x0008; /* tx even w/o CD */
2131 configure.min_frame_len = 0x0040;
2133 if(sc->mode & (MOD_PROM | MOD_ENAL)) {
2134 configure.hardware |= 1;
2136 outw(PIOR1(base), OFFSET_CU + 6);
2137 outsw(PIOP1(base), &configure, sizeof(configure_t)/2);
2139 if(wlcmd(sc, "config()-configure") == 0)
2142 outw(PIOR1(base), OFFSET_CU);
2143 outw(PIOP1(base), 0); /* ac_status */
2144 outw(PIOP1(base), AC_MCSETUP|AC_CW_EL); /* ac_command */
2145 outw(PIOR1(base), OFFSET_CU + 8);
2146 #if defined(__DragonFly__) || (defined(__FreeBSD__) && __FreeBSD_version >= 300000)
2147 LIST_FOREACH(ifma, &sc->wl_if.if_multiaddrs, ifma_link) {
2148 if (ifma->ifma_addr->sa_family != AF_LINK)
2151 addrp = LLADDR((struct sockaddr_dl *)ifma->ifma_addr);
2152 outw(PIOP1(base), addrp[0] + (addrp[1] << 8));
2153 outw(PIOP1(base), addrp[2] + (addrp[3] << 8));
2154 outw(PIOP1(base), addrp[4] + (addrp[5] << 8));
2158 ETHER_FIRST_MULTI(step, &sc->wl_ac, enm);
2159 while (enm != NULL) {
2160 unsigned int lo, hi;
2161 /* break if setting a multicast range, else we would crash */
2162 if (bcmp(enm->enm_addrlo, enm->enm_addrhi, 6) != 0) {
2165 lo = (enm->enm_addrlo[3] << 16) + (enm->enm_addrlo[4] << 8)
2166 + enm->enm_addrlo[5];
2167 hi = (enm->enm_addrhi[3] << 16) + (enm->enm_addrhi[4] << 8)
2168 + enm->enm_addrhi[5];
2170 outw(PIOP1(base),enm->enm_addrlo[0] +
2171 (enm->enm_addrlo[1] << 8));
2172 outw(PIOP1(base),enm->enm_addrlo[2] +
2173 ((lo >> 8) & 0xff00));
2174 outw(PIOP1(base), ((lo >> 8) & 0xff) +
2175 ((lo << 8) & 0xff00));
2176 /* #define MCASTDEBUG */
2178 kprintf("mcast_addr[%d,%d,%d] %x %x %x %x %x %x\n", lo, hi, cnt,
2184 enm->enm_addrlo[5]);
2189 ETHER_NEXT_MULTI(step, enm);
2192 outw(PIOR1(base), OFFSET_CU + 6); /* mc-cnt */
2193 outw(PIOP1(base), cnt * WAVELAN_ADDR_SIZE);
2194 if(wlcmd(sc, "config()-mcaddress") == 0)
2196 #endif /* MULTICAST */
2198 outw(PIOR1(base), OFFSET_CU);
2199 outw(PIOP1(base), 0); /* ac_status */
2200 outw(PIOP1(base), AC_IASETUP|AC_CW_EL); /* ac_command */
2201 outw(PIOR1(base), OFFSET_CU + 6);
2202 outsw(PIOP1(base), sc->wl_addr, WAVELAN_ADDR_SIZE/2);
2204 if(wlcmd(sc, "config()-address") == 0)
2215 * Set channel attention bit and busy wait until command has
2216 * completed. Then acknowledge the command completion.
2219 wlcmd(struct wl_softc *sc, const char *str)
2221 short base = sc->base;
2224 outw(PIOR0(base), OFFSET_SCB + 2); /* address of scb_command */
2225 outw(PIOP0(base), SCB_CU_STRT);
2229 outw(PIOR0(base), OFFSET_CU);
2230 for(i = 0; i < 0xffff; i++)
2231 if (inw(PIOP0(base)) & AC_SW_C)
2233 if (i == 0xffff || !(inw(PIOP0(base)) & AC_SW_OK)) {
2234 if_printf(&sc->wl_if, "%s failed; status = %d, inw = %x, outw = %x\n",
2235 str, inw(PIOP0(base)) & AC_SW_OK, inw(PIOP0(base)),
2237 outw(PIOR0(base), OFFSET_SCB);
2238 kprintf("scb_status %x\n", inw(PIOP0(base)));
2239 outw(PIOR0(base), OFFSET_SCB+2);
2240 kprintf("scb_command %x\n", inw(PIOP0(base)));
2241 outw(PIOR0(base), OFFSET_SCB+4);
2242 kprintf("scb_cbl %x\n", inw(PIOP0(base)));
2243 outw(PIOR0(base), OFFSET_CU+2);
2244 kprintf("cu_cmd %x\n", inw(PIOP0(base)));
2248 outw(PIOR0(base), OFFSET_SCB);
2249 if ((inw(PIOP0(base)) & SCB_SW_INT) && (inw(PIOP0(base)) != SCB_SW_CNA)) {
2251 if_printf(&sc->wl_if, "%s: unexpected final state %x\n",
2252 str, inw(PIOP0(base)));
2260 * wlack: if the 82596 wants attention because it has finished
2261 * sending or receiving a packet, acknowledge its desire and
2262 * return bits indicating the kind of attention. wlack() returns
2263 * these bits so that the caller can service exactly the
2264 * conditions that wlack() acknowledged.
2267 wlack(struct wl_softc *sc)
2271 short base = sc->base;
2273 outw(PIOR1(base), OFFSET_SCB);
2274 if(!(cmd = (inw(PIOP1(base)) & SCB_SW_INT)))
2277 if (sc->wl_if.if_flags & IFF_DEBUG)
2278 if_printf(&sc->wl_if, "doing a wlack()\n");
2280 outw(PIOP1(base), cmd);
2282 outw(PIOR0(base), OFFSET_SCB + 2); /* address of scb_command */
2283 for (i = 1000000; inw(PIOP0(base)) && (i-- > 0); );
2285 if_printf(&sc->wl_if, "wlack(): board not accepting command.\n");
2290 wltbd(struct wl_softc *sc)
2292 short base = sc->base;
2293 u_short tbd_p = OFFSET_TBD;
2299 outw(PIOR1(base), tbd_p);
2300 insw(PIOP1(base), &tbd, sizeof(tbd_t)/2);
2301 sum += (tbd.act_count & ~TBD_SW_EOF);
2302 kprintf("%d: addr %x, count %d (%d), next %x, base %x\n",
2303 i++, tbd.buffer_addr,
2304 (tbd.act_count & ~TBD_SW_EOF), sum,
2305 tbd.next_tbd_offset, tbd.buffer_base);
2306 if (tbd.act_count & TBD_SW_EOF)
2308 tbd_p = tbd.next_tbd_offset;
2313 wlhdwsleaze(u_short *countp, u_char **mb_pp, struct mbuf **tm_pp)
2315 struct mbuf *tm_p = *tm_pp;
2316 u_char *mb_p = *mb_pp;
2322 * can we get a run that will be coallesced or
2323 * that terminates before breaking
2326 count += tm_p->m_len;
2327 if (tm_p->m_len & 1)
2329 } while ((tm_p = tm_p->m_next) != (struct mbuf *)0);
2330 if ( (tm_p == (struct mbuf *)0) ||
2331 count > HDW_THRESHOLD) {
2332 *countp = (*tm_pp)->m_len;
2333 *mb_pp = mtod((*tm_pp), u_char *);
2337 /* we need to copy */
2341 cp = (u_char *) t_packet;
2343 bcopy(mtod(tm_p, u_char *), cp, len = tm_p->m_len);
2345 if (count > HDW_THRESHOLD)
2348 if (tm_p->m_next == (struct mbuf *)0)
2350 tm_p = tm_p->m_next;
2353 *mb_pp = (u_char *) t_packet;
2358 wlsftwsleaze(u_short *countp, u_char **mb_pp, struct mbuf **tm_pp)
2360 struct mbuf *tm_p = *tm_pp;
2362 u_char *cp = (u_char *) t_packet;
2365 /* we need to copy */
2367 bcopy(mtod(tm_p, u_char *), cp, len = tm_p->m_len);
2370 if (tm_p->m_next == (struct mbuf *)0)
2372 tm_p = tm_p->m_next;
2376 *mb_pp = (u_char *) t_packet;
2381 wlmmcstat(struct wl_softc *sc)
2383 short base = sc->base;
2386 if_printf(&sc->wl_if, "DCE_STATUS: 0x%x, ",
2387 wlmmcread(base,MMC_DCE_STATUS) & 0x0f);
2388 tmp = wlmmcread(base,MMC_CORRECT_NWID_H) << 8;
2389 tmp |= wlmmcread(base,MMC_CORRECT_NWID_L);
2390 kprintf("Correct NWID's: %d, ", tmp);
2391 tmp = wlmmcread(base,MMC_WRONG_NWID_H) << 8;
2392 tmp |= wlmmcread(base,MMC_WRONG_NWID_L);
2393 kprintf("Wrong NWID's: %d\n", tmp);
2394 kprintf("THR_PRE_SET: 0x%x, ", wlmmcread(base,MMC_THR_PRE_SET));
2395 kprintf("SIGNAL_LVL: %d, SILENCE_LVL: %d\n",
2396 wlmmcread(base,MMC_SIGNAL_LVL),
2397 wlmmcread(base,MMC_SILENCE_LVL));
2398 kprintf("SIGN_QUAL: 0x%x, NETW_ID: %x:%x, DES: %d\n",
2399 wlmmcread(base,MMC_SIGN_QUAL),
2400 wlmmcread(base,MMC_NETW_ID_H),
2401 wlmmcread(base,MMC_NETW_ID_L),
2402 wlmmcread(base,MMC_DES_AVAIL));
2406 wlmmcread(u_int base, u_short reg)
2408 while(inw(HASR(base)) & HASR_MMC_BUSY) ;
2409 outw(MMCR(base),reg << 1);
2410 while(inw(HASR(base)) & HASR_MMC_BUSY) ;
2411 return (u_short)inw(MMCR(base)) >> 8;
2415 getsnr(struct wl_softc *sc)
2417 MMC_WRITE(MMC_FREEZE,1);
2419 * SNR retrieval procedure :
2421 * read signal level : wlmmcread(base, MMC_SIGNAL_LVL);
2422 * read silence level : wlmmcread(base, MMC_SILENCE_LVL);
2424 MMC_WRITE(MMC_FREEZE,0);
2426 * SNR is signal:silence ratio.
2433 ** Reads the psa for the wavelan at (base) into (buf)
2436 wlgetpsa(int base, u_char *buf)
2440 PCMD(base, HACR_DEFAULT & ~HACR_16BITS);
2441 PCMD(base, HACR_DEFAULT & ~HACR_16BITS);
2443 for (i = 0; i < 0x40; i++) {
2444 outw(PIOR2(base), i);
2445 buf[i] = inb(PIOP2(base));
2447 PCMD(base, HACR_DEFAULT);
2448 PCMD(base, HACR_DEFAULT);
2454 ** Writes the psa for wavelan (unit) from the softc back to the
2455 ** board. Updates the CRC and sets the CRC OK flag.
2457 ** Do not call this when the board is operating, as it doesn't
2458 ** preserve the hacr.
2461 wlsetpsa(struct wl_softc *sc)
2463 short base = sc->base;
2467 crc = wlpsacrc(sc->psa); /* calculate CRC of PSA */
2468 sc->psa[WLPSA_CRCLOW] = crc & 0xff;
2469 sc->psa[WLPSA_CRCHIGH] = (crc >> 8) & 0xff;
2470 sc->psa[WLPSA_CRCOK] = 0x55; /* default to 'bad' until programming complete */
2472 PCMD(base, HACR_DEFAULT & ~HACR_16BITS);
2473 PCMD(base, HACR_DEFAULT & ~HACR_16BITS);
2475 for (i = 0; i < 0x40; i++) {
2477 outw(PIOR2(base),i); /* write param memory */
2479 outb(PIOP2(base), sc->psa[i]);
2482 outw(PIOR2(base),WLPSA_CRCOK); /* update CRC flag*/
2484 sc->psa[WLPSA_CRCOK] = 0xaa; /* OK now */
2485 outb(PIOP2(base), 0xaa); /* all OK */
2488 PCMD(base, HACR_DEFAULT);
2489 PCMD(base, HACR_DEFAULT);
2493 ** CRC routine provided by Christopher Giordano <cgiordan@gdeb.com>,
2494 ** from original code by Tomi Mikkonen (tomitm@remedy.fi)
2497 static u_int crc16_table[16] = {
2498 0x0000, 0xCC01, 0xD801, 0x1400,
2499 0xF001, 0x3C00, 0x2800, 0xE401,
2500 0xA001, 0x6C00, 0x7800, 0xB401,
2501 0x5000, 0x9C01, 0x8801, 0x4400
2505 wlpsacrc(u_char *buf)
2510 for (i = 0; i < 0x3d; i++, buf++) {
2512 r1 = crc16_table[crc & 0xF];
2513 crc = (crc >> 4) & 0x0FFF;
2514 crc = crc ^ r1 ^ crc16_table[*buf & 0xF];
2517 r1 = crc16_table[crc & 0xF];
2518 crc = (crc >> 4) & 0x0FFF;
2519 crc = crc ^ r1 ^ crc16_table[(*buf >> 4) & 0xF];
2528 * take input packet and cache various radio hw characteristics
2529 * indexed by MAC address.
2531 * Some things to think about:
2532 * note that no space is malloced.
2533 * We might hash the mac address if the cache were bigger.
2534 * It is not clear that the cache is big enough.
2535 * It is also not clear how big it should be.
2536 * The cache is IP-specific. We don't care about that as
2537 * we want it to be IP-specific.
2538 * The last N recv. packets are saved. This will tend
2539 * to reward agents and mobile hosts that beacon.
2540 * That is probably fine for mobile ip.
2543 /* globals for wavelan signal strength cache */
2544 /* this should go into softc structure above.
2547 /* set true if you want to limit cache items to broadcast/mcast
2548 * only packets (not unicast)
2550 static int wl_cache_mcastonly = 1;
2551 SYSCTL_INT(_machdep, OID_AUTO, wl_cache_mcastonly, CTLFLAG_RW,
2552 &wl_cache_mcastonly, 0, "");
2554 /* set true if you want to limit cache items to IP packets only
2556 static int wl_cache_iponly = 1;
2557 SYSCTL_INT(_machdep, OID_AUTO, wl_cache_iponly, CTLFLAG_RW,
2558 &wl_cache_iponly, 0, "");
2560 /* zero out the cache
2563 wl_cache_zero(struct wl_softc *sc)
2565 bzero(&sc->w_sigcache[0], sizeof(struct w_sigcache) * MAXCACHEITEMS);
2567 sc->w_nextcache = 0;
2568 sc->w_wrapindex = 0;
2571 /* store hw signal info in cache.
2572 * index is MAC address, but an ip src gets stored too
2573 * There are two filters here controllable via sysctl:
2574 * throw out unicast (on by default, but can be turned off)
2575 * throw out non-ip (on by default, but can be turned off)
2578 wl_cache_store(struct wl_softc *sc, int base, struct ether_header *eh,
2581 struct ip *ip = NULL; /* Avoid GCC warning */
2583 int signal, silence;
2584 int w_insertcache; /* computed index for cache entry storage */
2585 int ipflag = wl_cache_iponly;
2589 * 2. configurable filter to throw out unicast packets,
2590 * keep multicast only.
2594 /* reject if not IP packet
2596 if ( wl_cache_iponly && (ntohs(eh->ether_type) != 0x800)) {
2600 /* check if broadcast or multicast packet. we toss
2603 if (wl_cache_mcastonly && ((eh->ether_dhost[0] & 1) == 0)) {
2607 /* find the ip header. we want to store the ip_src
2608 * address. use the mtod macro(in mbuf.h)
2609 * to typecast m to struct ip *
2612 ip = mtod(m, struct ip *);
2615 /* do a linear search for a matching MAC address
2616 * in the cache table
2617 * . MAC address is 6 bytes,
2618 * . var w_nextcache holds total number of entries already cached
2620 for(i = 0; i < sc->w_nextcache; i++) {
2621 if (! bcmp(eh->ether_shost, sc->w_sigcache[i].macsrc, 6 )) {
2623 * so we already have this entry,
2624 * update the data, and LRU age
2630 /* did we find a matching mac address?
2631 * if yes, then overwrite a previously existing cache entry
2633 if (i < sc->w_nextcache ) {
2636 /* else, have a new address entry,so
2637 * add this new entry,
2638 * if table full, then we need to replace entry
2642 /* check for space in cache table
2643 * note: w_nextcache also holds number of entries
2644 * added in the cache table
2646 if ( sc->w_nextcache < MAXCACHEITEMS ) {
2647 w_insertcache = sc->w_nextcache;
2649 sc->w_sigitems = sc->w_nextcache;
2651 /* no space found, so simply wrap with wrap index
2652 * and "zap" the next entry
2655 if (sc->w_wrapindex == MAXCACHEITEMS) {
2656 sc->w_wrapindex = 0;
2658 w_insertcache = sc->w_wrapindex++;
2662 /* invariant: w_insertcache now points at some slot
2665 if (w_insertcache < 0 || w_insertcache >= MAXCACHEITEMS) {
2667 "wl_cache_store, bad index: %d of [0..%d], gross cache error\n",
2668 w_insertcache, MAXCACHEITEMS);
2672 /* store items in cache
2675 * .signal (0..63) ,silence (0..63) ,quality (0..15)
2678 sc->w_sigcache[w_insertcache].ipsrc = ip->ip_src.s_addr;
2680 bcopy( eh->ether_shost, sc->w_sigcache[w_insertcache].macsrc, 6);
2681 signal = sc->w_sigcache[w_insertcache].signal = wlmmcread(base, MMC_SIGNAL_LVL) & 0x3f;
2682 silence = sc->w_sigcache[w_insertcache].silence = wlmmcread(base, MMC_SILENCE_LVL) & 0x3f;
2683 sc->w_sigcache[w_insertcache].quality = wlmmcread(base, MMC_SIGN_QUAL) & 0x0f;
2685 sc->w_sigcache[w_insertcache].snr =
2688 sc->w_sigcache[w_insertcache].snr = 0;
2692 #endif /* WLCACHE */
2695 * determine if in all multicast mode or not
2697 * returns: 1 if IFF_ALLMULTI should be set
2702 #if defined(__FreeBSD__) && __FreeBSD_version < 300000 /* not required */
2704 check_allmulti(struct wl_softc *sc)
2706 short base = sc->base;
2707 struct ether_multi *enm;
2708 struct ether_multistep step;
2710 ETHER_FIRST_MULTI(step, &sc->wl_ac, enm);
2711 while (enm != NULL) {
2712 unsigned int lo, hi;
2714 kprintf("enm_addrlo %x:%x:%x:%x:%x:%x\n", enm->enm_addrlo[0], enm->enm_addrlo[1],
2715 enm->enm_addrlo[2], enm->enm_addrlo[3], enm->enm_addrlo[4],
2716 enm->enm_addrlo[5]);
2717 kprintf("enm_addrhi %x:%x:%x:%x:%x:%x\n", enm->enm_addrhi[0], enm->enm_addrhi[1],
2718 enm->enm_addrhi[2], enm->enm_addrhi[3], enm->enm_addrhi[4],
2719 enm->enm_addrhi[5]);
2721 if (bcmp(enm->enm_addrlo, enm->enm_addrhi, 6) != 0) {
2724 ETHER_NEXT_MULTI(step, enm);