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.30 2006/12/22 23:26:22 swildner 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>
209 #include <net/ethernet.h>
211 #include <net/if_arp.h>
212 #include <net/ifq_var.h>
213 #include <net/if_dl.h>
216 #include <netinet/in.h>
217 #include <netinet/in_systm.h>
218 #include <netinet/ip.h>
219 #include <netinet/if_ether.h>
224 #include <bus/isa/isavar.h>
225 #include <bus/isa/i386/isa_device.h>
226 #include "if_wl_i82586.h" /* Definitions for the Intel chip */
228 /* was 1000 in original, fed to DELAY(x) */
229 #define DELAYCONST 1000
231 #include <machine/if_wl_wavelan.h>
233 static char t_packet[ETHERMTU + sizeof(struct ether_header) + sizeof(long)];
236 struct arpcom wl_ac; /* Ethernet common part */
237 #define wl_if wl_ac.ac_if /* network visible interface */
238 #define wl_addr wl_ac.ac_enaddr /* hardware address */
240 u_char nwid[2]; /* current radio modem nwid */
243 int tbusy; /* flag to determine if xmit is busy */
247 u_short hacr; /* latest host adapter CR command */
249 u_char chan24; /* 2.4 Gz: channel number/EEPROM Area # */
250 u_short freq24; /* 2.4 Gz: resulting frequency */
253 struct resource *res_ioport;
254 struct resource *res_irq;
256 struct callout watchdog_ch;
258 int w_sigitems; /* number of cached entries */
259 /* array of cache entries */
260 struct w_sigcache w_sigcache[ MAXCACHEITEMS ];
261 int w_nextcache; /* next free cache entry */
262 int w_wrapindex; /* next "free" cache entry */
267 * XXX The Wavelan appears to be prone to dropping stuff if you talk to
268 * it too fast. This disgusting hack inserts a delay after each packet
269 * is queued which helps avoid this behaviour on fast systems.
271 static int wl_xmit_delay = 250;
272 SYSCTL_INT(_machdep, OID_AUTO, wl_xmit_delay, CTLFLAG_RW, &wl_xmit_delay, 0, "");
275 * not XXX, but ZZZ (bizarre).
276 * promiscuous mode can be toggled to ignore NWIDs. By default,
277 * it does not. Caution should be exercised about combining
278 * this mode with IFF_ALLMULTI which puts this driver in
281 static int wl_ignore_nwid = 0;
282 SYSCTL_INT(_machdep, OID_AUTO, wl_ignore_nwid, CTLFLAG_RW, &wl_ignore_nwid, 0, "");
285 * Emit diagnostics about transmission problems
287 static int xmt_watch = 0;
288 SYSCTL_INT(_machdep, OID_AUTO, wl_xmit_watch, CTLFLAG_RW, &xmt_watch, 0, "");
291 * Collect SNR statistics
293 static int gathersnr = 0;
294 SYSCTL_INT(_machdep, OID_AUTO, wl_gather_snr, CTLFLAG_RW, &gathersnr, 0, "");
296 static int wlprobe(device_t);
297 static int wlattach(device_t);
298 static int wldetach(device_t);
299 static int wl_alloc_resources(device_t);
300 static void wl_free_resources(device_t);
301 static void wlstart(struct ifnet *);
302 static void wlinit(void *);
303 static int wlioctl(struct ifnet *, u_long, caddr_t, struct ucred *);
304 static timeout_t wlwatchdog;
305 static void wlintr(void *);
306 static void wlxmt(struct wl_softc *, struct mbuf *);
307 static int wldiag(struct wl_softc *);
308 static int wlconfig(struct wl_softc *);
309 static int wlcmd(struct wl_softc *, const char *);
310 static void wlmmcstat(struct wl_softc *);
311 static u_short wlbldru(struct wl_softc *);
312 static u_short wlmmcread(u_int, u_short);
313 static void wlinitmmc(struct wl_softc *);
314 static int wlhwrst(struct wl_softc *);
315 static void wlrustrt(struct wl_softc *);
316 static void wlbldcu(struct wl_softc *);
317 static int wlack(struct wl_softc *);
318 static int wlread(struct wl_softc *, u_short);
319 static void getsnr(struct wl_softc *);
320 static void wlrcv(struct wl_softc *);
321 static int wlrequeue(struct wl_softc *, u_short);
322 static void wlsftwsleaze(u_short *, u_char **, struct mbuf **);
323 static void wlhdwsleaze(u_short *, u_char **, struct mbuf **);
324 static void wltbd(struct wl_softc *);
325 static void wlgetpsa(int, u_char *);
326 static void wlsetpsa(struct wl_softc *);
327 static u_short wlpsacrc(u_char *);
328 static void wldump(struct wl_softc *);
330 static void wl_cache_store(struct wl_softc *, int, struct ether_header *,
332 static void wl_cache_zero(struct wl_softc *);
335 # if defined(__FreeBSD__) && __FreeBSD_version < 300000
336 static int check_allmulti(struct wl_softc *);
340 static device_method_t wl_methods[] = {
341 DEVMETHOD(device_probe, wlprobe),
342 DEVMETHOD(device_attach, wlattach),
343 DEVMETHOD(device_detach, wldetach),
347 static driver_t wl_driver = {
350 sizeof(struct wl_softc)
353 devclass_t wl_devclass;
354 DECLARE_DUMMY_MODULE(if_wl);
355 DRIVER_MODULE(wl, isa, wl_driver, wl_devclass, 0, 0);
356 MODULE_DEPEND(wl, isa, 1, 1, 1);
358 static struct isa_pnp_id wl_ids[] = {
362 /* array for maping irq numbers to values for the irq parameter register */
363 static int irqvals[16] = {
364 0, 0, 0, 0x01, 0x02, 0x04, 0, 0x08, 0, 0, 0x10, 0x20, 0x40, 0, 0, 0x80
370 * This function "probes" or checks for the WaveLAN board on the bus to
371 * see if it is there. As far as I can tell, the best break between this
372 * routine and the attach code is to simply determine whether the board
373 * is configured in properly. Currently my approach to this is to write
374 * and read a word from the SRAM on the board being probed. If the word
375 * comes back properly then we assume the board is there. The config
376 * code expects to see a successful return from the probe routine before
377 * attach will be called.
380 wlprobe(device_t dev)
384 const char *str = "wl%d: board out of range [0..%d]\n";
388 error = ISA_PNP_PROBE(device_get_parent(dev), dev, wl_ids);
389 if (error == ENXIO || error == 0)
392 sc = device_get_softc(dev);
393 error = wl_alloc_resources(dev);
397 base = rman_get_start(sc->res_ioport);
400 * regular CMD() will not work, since no softc yet
402 #define PCMD(base, hacr) outw((base), (hacr))
404 PCMD(base, HACR_RESET); /* reset the board */
405 DELAY(DELAYCONST); /* >> 4 clocks at 6MHz */
406 PCMD(base, HACR_RESET); /* reset the board */
407 DELAY(DELAYCONST); /* >> 4 clocks at 6MHz */
409 /* clear reset command and set PIO#1 in autoincrement mode */
410 PCMD(base, HACR_DEFAULT);
411 PCMD(base, HACR_DEFAULT);
412 outw(PIOR1(base), 0); /* go to beginning of RAM */
413 outsw(PIOP1(base), str, strlen(str)/2+1); /* write string */
415 outw(PIOR1(base), 0); /* rewind */
416 insw(PIOP1(base), inbuf, strlen(str)/2+1); /* read result */
418 if (bcmp(str, inbuf, strlen(str))) {
423 sc->chan24 = 0; /* 2.4 Gz: config channel */
424 sc->freq24 = 0; /* 2.4 Gz: frequency */
426 /* read the PSA from the board into temporary storage */
427 wlgetpsa(base, inbuf);
429 /* We read the IRQ value from the PSA on the board. */
430 for (irq = 15; irq >= 0; irq--)
431 if (irqvals[irq] == inbuf[WLPSA_IRQNO])
433 if ((irq == 0) || (irqvals[irq] == 0)){
434 device_printf(dev, "PSA corrupt (invalid IRQ value)\n");
439 * If the IRQ requested by the PSA is already claimed by another
440 * device, the board won't work, but the user can still access the
441 * driver to change the IRQ.
443 if (bus_get_resource(dev, SYS_RES_IRQ, 0, &sirq, &dummy))
445 if (irq != (int)sirq)
446 device_printf(dev, "board is configured for interrupt %d\n", irq);
451 wl_free_resources(dev);
458 * This function attaches a WaveLAN board to the "system". The rest of
459 * runtime structures are initialized here (this routine is called after
460 * a successful probe of the board). Once the ethernet address is read
461 * and stored, the board's ifnet structure is attached and readied.
464 wlattach(device_t dev)
471 sc = device_get_softc(dev);
474 if_initname(ifp, device_get_name(dev), device_get_unit(dev));
476 error = wl_alloc_resources(dev);
480 base = rman_get_start(sc->res_ioport);
483 device_printf(dev, "%s: base %x, unit %d\n",
484 __func__, base, device_get_unit(dev));
490 sc->hacr = HACR_RESET;
491 callout_init(&sc->watchdog_ch);
492 CMD(sc); /* reset the board */
493 DELAY(DELAYCONST); /* >> 4 clocks at 6MHz */
495 /* clear reset command and set PIO#2 in parameter access mode */
496 sc->hacr = (HACR_DEFAULT & ~HACR_16BITS);
499 /* Read the PSA from the board for our later reference */
500 wlgetpsa(base, sc->psa);
503 sc->nwid[0] = sc->psa[WLPSA_NWID];
504 sc->nwid[1] = sc->psa[WLPSA_NWID+1];
506 /* fetch MAC address - decide which one first */
507 if (sc->psa[WLPSA_MACSEL] & 1) {
512 for(i=0; i < WAVELAN_ADDR_SIZE; ++i) {
513 sc->wl_addr[i] = sc->psa[j + i];
516 /* enter normal 16 bit mode operation */
517 sc->hacr = HACR_DEFAULT;
521 outw(PIOR1(base), OFFSET_SCB + 8); /* address of scb_crcerrs */
522 outw(PIOP1(base), 0); /* clear scb_crcerrs */
523 outw(PIOP1(base), 0); /* clear scb_alnerrs */
524 outw(PIOP1(base), 0); /* clear scb_rscerrs */
525 outw(PIOP1(base), 0); /* clear scb_ovrnerrs */
528 ifp->if_mtu = WAVELAN_MTU;
529 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
531 ifp->if_flags |= IFF_DEBUG;
534 ifp->if_flags |= IFF_MULTICAST;
535 #endif /* MULTICAST */
536 ifp->if_init = wlinit;
537 ifp->if_start = wlstart;
538 ifp->if_ioctl = wlioctl;
539 ifp->if_timer = 0; /* paranoia */
545 ifq_set_maxlen(&ifp->if_snd, IFQ_MAXLEN);
546 ifq_set_ready(&ifp->if_snd);
547 ether_ifattach(ifp, sc->wl_ac.ac_enaddr, NULL);
550 kprintf(", Freq %d MHz",sc->freq24); /* 2.4 Gz */
551 kprintf("\n"); /* 2.4 Gz */
553 error = bus_setup_intr(dev, sc->res_irq, INTR_NETSAFE,
554 wlintr, sc, &sc->intr_handle,
557 device_printf(dev, "setup irq fail!\n");
559 wl_free_resources(dev);
569 wldetach(device_t dev)
571 struct wl_softc *sc = device_get_softc(dev);
572 device_t parent = device_get_parent(dev);
573 struct ifnet *ifp = &sc->wl_if;
575 lwkt_serialize_enter(ifp->if_serializer);
577 /* reset the board */
578 sc->hacr = HACR_RESET;
580 sc->hacr = HACR_DEFAULT;
583 if (sc->intr_handle != NULL) {
584 BUS_TEARDOWN_INTR(parent, dev, sc->res_irq, sc->intr_handle);
585 sc->intr_handle = NULL;
588 lwkt_serialize_exit(ifp->if_serializer);
591 bus_generic_detach(dev);
592 wl_free_resources(dev);
598 wl_alloc_resources(device_t dev)
600 struct wl_softc *sc = device_get_softc(dev);
601 int ports = 16; /* Number of ports */
603 sc->res_ioport = bus_alloc_resource(dev, SYS_RES_IOPORT,
604 &sc->rid_ioport, 0ul, ~0ul, ports, RF_ACTIVE);
605 if (sc->res_ioport == NULL)
608 sc->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
609 &sc->rid_irq, RF_SHAREABLE | RF_ACTIVE);
610 if (sc->res_irq == NULL)
615 wl_free_resources(dev);
620 wl_free_resources(device_t dev)
622 struct wl_softc *sc = device_get_softc(dev);
624 if (sc->res_irq != 0) {
625 bus_deactivate_resource(dev, SYS_RES_IRQ, sc->rid_irq, sc->res_irq);
626 bus_release_resource(dev, SYS_RES_IRQ, sc->rid_irq, sc->res_irq);
629 if (sc->res_ioport != 0) {
630 bus_deactivate_resource(dev, SYS_RES_IOPORT,
631 sc->rid_ioport, sc->res_ioport);
632 bus_release_resource(dev, SYS_RES_IOPORT,
633 sc->rid_ioport, sc->res_ioport);
639 * Print out interesting information about the 82596.
642 wldump(struct wl_softc *sc)
647 if_printf(&sc->wl_if, "hasr %04x\n", inw(HASR(base)));
649 if_printf(&sc->wl_if, "scb at %04x:\n ", OFFSET_SCB);
650 outw(PIOR1(base), OFFSET_SCB);
651 for(i = 0; i < 8; i++)
652 kprintf("%04x ", inw(PIOP1(base)));
655 if_printf(&sc->wl_if, "cu at %04x:\n ", OFFSET_CU);
656 outw(PIOR1(base), OFFSET_CU);
657 for(i = 0; i < 8; i++)
658 kprintf("%04x ", inw(PIOP1(base)));
661 if_printf(&sc->wl_if, "tbd at %04x:\n ", OFFSET_TBD);
662 outw(PIOR1(base), OFFSET_TBD);
663 for(i = 0; i < 4; i++)
664 kprintf("%04x ", inw(PIOP1(base)));
668 /* Initialize the Modem Management Controller */
670 wlinitmmc(struct wl_softc *sc)
677 /* enter 8 bit operation */
678 sc->hacr = (HACR_DEFAULT & ~HACR_16BITS);
681 configured = sc->psa[WLPSA_CONFIGURED] & 1;
684 * Set default modem control parameters. Taken from NCR document
687 MMC_WRITE(MMC_JABBER_ENABLE, 0x01);
688 MMC_WRITE(MMC_ANTEN_SEL, 0x02);
689 MMC_WRITE(MMC_IFS, 0x20);
690 MMC_WRITE(MMC_MOD_DELAY, 0x04);
691 MMC_WRITE(MMC_JAM_TIME, 0x38);
692 MMC_WRITE(MMC_DECAY_PRM, 0x00); /* obsolete ? */
693 MMC_WRITE(MMC_DECAY_UPDAT_PRM, 0x00);
695 MMC_WRITE(MMC_LOOPT_SEL, 0x00);
696 if (sc->psa[WLPSA_COMPATNO] & 1) {
697 MMC_WRITE(MMC_THR_PRE_SET, 0x01); /* 0x04 for AT and 0x01 for MCA */
699 MMC_WRITE(MMC_THR_PRE_SET, 0x04); /* 0x04 for AT and 0x01 for MCA */
701 MMC_WRITE(MMC_QUALITY_THR, 0x03);
703 /* use configuration defaults from parameter storage area */
704 if (sc->psa[WLPSA_NWIDENABLE] & 1) {
705 if ((mode & (MOD_PROM | MOD_ENAL)) && wl_ignore_nwid) {
706 MMC_WRITE(MMC_LOOPT_SEL, 0x40);
708 MMC_WRITE(MMC_LOOPT_SEL, 0x00);
711 MMC_WRITE(MMC_LOOPT_SEL, 0x40); /* disable network id check */
713 MMC_WRITE(MMC_THR_PRE_SET, sc->psa[WLPSA_THRESH]);
714 MMC_WRITE(MMC_QUALITY_THR, sc->psa[WLPSA_QUALTHRESH]);
716 MMC_WRITE(MMC_FREEZE, 0x00);
717 MMC_WRITE(MMC_ENCR_ENABLE, 0x00);
719 MMC_WRITE(MMC_NETW_ID_L,sc->nwid[1]); /* set NWID */
720 MMC_WRITE(MMC_NETW_ID_H,sc->nwid[0]);
722 /* enter normal 16 bit mode operation */
723 sc->hacr = HACR_DEFAULT;
725 CMD(sc); /* virtualpc1 needs this! */
727 if (sc->psa[WLPSA_COMPATNO]== /* 2.4 Gz: half-card ver */
728 WLPSA_COMPATNO_WL24B) { /* 2.4 Gz */
729 i=sc->chan24<<4; /* 2.4 Gz: position ch # */
730 MMC_WRITE(MMC_EEADDR,i+0x0f); /* 2.4 Gz: named ch, wc=16 */
731 MMC_WRITE(MMC_EECTRL,MMC_EECTRL_DWLD+ /* 2.4 Gz: Download Synths */
732 MMC_EECTRL_EEOP_READ); /* 2.4 Gz: Read EEPROM */
733 for (i=0; i<1000; ++i) { /* 2.4 Gz: wait for download */
734 DELAY(40); /* 2.4 Gz */
735 if ((wlmmcread(base,MMC_EECTRLstat) /* 2.4 Gz: check DWLD and */
736 &(MMC_EECTRLstat_DWLD /* 2.4 Gz: EEBUSY */
737 +MMC_EECTRLstat_EEBUSY))==0) /* 2.4 Gz: */
738 break; /* 2.4 Gz: download finished */
741 if_printf(&sc->wl_if,
742 "synth load failed\n"); /* 2.4 Gz */
744 MMC_WRITE(MMC_EEADDR,0x61); /* 2.4 Gz: default pwr, wc=2 */
745 MMC_WRITE(MMC_EECTRL,MMC_EECTRL_DWLD+ /* 2.4 Gz: Download Xmit Pwr */
746 MMC_EECTRL_EEOP_READ); /* 2.4 Gz: Read EEPROM */
747 for (i=0; i<1000; ++i) { /* 2.4 Gz: wait for download */
748 DELAY(40); /* 2.4 Gz */
749 if ((wlmmcread(base,MMC_EECTRLstat) /* 2.4 Gz: check DWLD and */
750 &(MMC_EECTRLstat_DWLD /* 2.4 Gz: EEBUSY */
751 +MMC_EECTRLstat_EEBUSY))==0) /* 2.4 Gz: */
752 break; /* 2.4 Gz: download finished */
755 if_printf(&sc->wl_if,
756 "xmit pwr load failed\n");/* 2.4 Gz */
758 MMC_WRITE(MMC_ANALCTRL, /* 2.4 Gz: EXT ant+polarity */
759 MMC_ANALCTRL_ANTPOL + /* 2.4 Gz: */
760 MMC_ANALCTRL_EXTANT); /* 2.4 Gz: */
761 i=sc->chan24<<4; /* 2.4 Gz: position ch # */
762 MMC_WRITE(MMC_EEADDR,i); /* 2.4 Gz: get frequency */
763 MMC_WRITE(MMC_EECTRL, /* 2.4 Gz: EEPROM read */
764 MMC_EECTRL_EEOP_READ); /* 2.4 Gz: */
765 DELAY(40); /* 2.4 Gz */
766 i = wlmmcread(base,MMC_EEDATALrv) /* 2.4 Gz: freq val */
767 + (wlmmcread(base,MMC_EEDATAHrv)<<8); /* 2.4 Gz */
768 sc->freq24 = (i>>6)+2400; /* 2.4 Gz: save real freq */
775 * Another routine that interfaces the "if" layer to this driver.
776 * Simply resets the structures that are used by "upper layers".
777 * As well as calling wlhwrst that does reset the WaveLAN board.
779 * input : softc pointer for this interface
780 * output : structures (if structs) and board are reset
786 struct wl_softc *sc = xsc;
787 struct ifnet *ifp = &sc->wl_if;
791 if (ifp->if_flags & IFF_DEBUG)
792 if_printf(ifp, "entered wlinit()\n");
794 if ((stat = wlhwrst(sc)) == TRUE) {
795 ifp->if_flags |= IFF_RUNNING; /* same as DSF_RUNNING */
797 * OACTIVE is used by upper-level routines
800 ifp->if_flags &= ~IFF_OACTIVE; /* same as tbusy below */
802 sc->flags |= DSF_RUNNING;
804 callout_stop(&sc->watchdog_ch);
808 if_printf(ifp, "init(): trouble resetting board.\n");
815 * This routine resets the WaveLAN board that corresponds to the
816 * board number passed in.
818 * input : softc pointer for this interface
819 * output : board is reset
823 wlhwrst(struct wl_softc *sc)
826 if (sc->wl_if.if_flags & IFF_DEBUG)
827 if_printf(&sc->wl_if, "entered wlhwrst()\n");
829 sc->hacr = HACR_RESET;
830 CMD(sc); /* reset the board */
832 /* clear reset command and set PIO#1 in autoincrement mode */
833 sc->hacr = HACR_DEFAULT;
837 if (sc->wl_if.if_flags & IFF_DEBUG)
838 wlmmcstat(sc); /* Display MMC registers */
840 wlbldcu(sc); /* set up command unit structures */
845 if (wlconfig(sc) == 0)
848 * insert code for loopback test here
850 wlrustrt(sc); /* start receive unit */
852 /* enable interrupts */
853 sc->hacr = (HACR_DEFAULT | HACR_INTRON);
862 * This function builds up the command unit structures. It inits
863 * the scp, iscp, scb, cb, tbd, and tbuf.
867 wlbldcu(struct wl_softc *sc)
869 short base = sc->base;
877 bzero(&scp, sizeof(scp));
879 scp.scp_iscp = OFFSET_ISCP;
880 scp.scp_iscp_base = 0;
881 outw(PIOR1(base), OFFSET_SCP);
882 outsw(PIOP1(base), &scp, sizeof(scp_t)/2);
884 bzero(&iscp, sizeof(iscp));
886 iscp.iscp_scb_offset = OFFSET_SCB;
888 iscp.iscp_scb_base = 0;
889 outw(PIOR1(base), OFFSET_ISCP);
890 outsw(PIOP1(base), &iscp, sizeof(iscp_t)/2);
893 scb.scb_command = SCB_RESET;
894 scb.scb_cbl_offset = OFFSET_CU;
895 scb.scb_rfa_offset = OFFSET_RU;
899 scb.scb_ovrnerrs = 0;
900 outw(PIOR1(base), OFFSET_SCB);
901 outsw(PIOP1(base), &scb, sizeof(scb_t)/2);
905 outw(PIOR0(base), OFFSET_ISCP + 0); /* address of iscp_busy */
906 for (i = 1000000; inw(PIOP0(base)) && (i-- > 0); );
907 if (i <= 0) if_printf(&sc->wl_if, "bldcu(): iscp_busy timeout.\n");
908 outw(PIOR0(base), OFFSET_SCB + 0); /* address of scb_status */
909 for (i = STATUS_TRIES; i-- > 0; ) {
910 if (inw(PIOP0(base)) == (SCB_SW_CX|SCB_SW_CNA))
914 if_printf(&sc->wl_if, "bldcu(): not ready after reset.\n");
918 cb.ac_command = AC_CW_EL; /* NOP */
919 cb.ac_link_offset = OFFSET_CU;
920 outw(PIOR1(base), OFFSET_CU);
921 outsw(PIOP1(base), &cb, 6/2);
924 tbd.next_tbd_offset = I82586NULL;
927 outw(PIOR1(base), OFFSET_TBD);
928 outsw(PIOP1(base), &tbd, sizeof(tbd_t)/2);
936 * input : pointer the appropriate "if" struct
937 * output : stuff sent to board if any there
941 wlstart(struct ifnet *ifp)
944 struct wl_softc *sc = ifp->if_softc;
945 short base = sc->base;
946 int scb_status, cu_status, scb_command;
949 if (ifp->if_flags & IFF_DEBUG)
950 if_printf(ifp, "entered wlstart()\n");
953 outw(PIOR1(base), OFFSET_CU);
954 cu_status = inw(PIOP1(base));
955 outw(PIOR0(base),OFFSET_SCB + 0); /* scb_status */
956 scb_status = inw(PIOP0(base));
957 outw(PIOR0(base), OFFSET_SCB + 2);
958 scb_command = inw(PIOP0(base));
961 * don't need OACTIVE check as tbusy here checks to see
962 * if we are already busy
965 if((scb_status & 0x0700) == SCB_CUS_IDLE &&
966 (cu_status & AC_SW_B) == 0){
968 callout_stop(&sc->watchdog_ch);
969 ifp->if_flags &= ~IFF_OACTIVE;
971 * This is probably just a race. The xmt'r is just
972 * became idle but WE have masked interrupts so ...
975 if_printf(ifp, "CU idle, scb %04x %04x cu %04x\n",
976 scb_status, scb_command, cu_status);
978 if (xmt_watch) if_printf(ifp, "!!\n");
980 return; /* genuinely still busy */
982 } else if((scb_status & 0x0700) == SCB_CUS_ACTV ||
983 (cu_status & AC_SW_B)){
985 if_printf(ifp, "CU unexpectedly busy; scb %04x cu %04x\n",
986 scb_status, cu_status);
988 if (xmt_watch) if_printf(ifp, "busy?!");
989 return; /* hey, why are we busy? */
992 /* get ourselves some data */
994 m = ifq_dequeue(&ifp->if_snd, NULL);
998 /* set the watchdog timer so that if the board
999 * fails to interrupt we will restart
1001 /* try 10 ticks, not very long */
1002 callout_reset(&sc->watchdog_ch, 10, wlwatchdog, sc);
1003 ifp->if_flags |= IFF_OACTIVE;
1007 ifp->if_flags &= ~IFF_OACTIVE;
1014 * This routine does the actual copy of data (including ethernet header
1015 * structure) from the WaveLAN to an mbuf chain that will be passed up
1016 * to the "if" (network interface) layer. NOTE: we currently
1017 * don't handle trailer protocols, so if that is needed, it will
1018 * (at least in part) be added here. For simplicities sake, this
1019 * routine copies the receive buffers from the board into a local (stack)
1020 * buffer until the frame has been copied from the board. Once in
1021 * the local buffer, the contents are copied to an mbuf chain that
1022 * is then enqueued onto the appropriate "if" queue.
1024 * input : softc pointer for this interface and
1025 * an frame descriptor address
1026 * output : the packet is put into an mbuf chain, and passed up
1027 * assumes : if any errors occur, packet is "dropped on the floor"
1031 wlread(struct wl_softc *sc, u_short fd_p)
1033 struct ifnet *ifp = &sc->wl_if;
1034 short base = sc->base;
1036 struct ether_header eh;
1037 struct mbuf *m, *tm;
1040 u_short mlen, len, clen;
1041 u_short bytes_in_msg, bytes_in_mbuf, bytes;
1045 if (ifp->if_flags & IFF_DEBUG)
1046 if_printf(ifp, "entered wlread()\n");
1048 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
1049 if_printf(ifp, "read(): board is not running.\n");
1050 sc->hacr &= ~HACR_INTRON;
1051 CMD(sc); /* turn off interrupts */
1053 /* read ether_header info out of device memory. doesn't
1054 * go into mbuf. goes directly into eh structure
1056 len = sizeof(struct ether_header); /* 14 bytes */
1057 outw(PIOR1(base), fd_p);
1058 insw(PIOP1(base), &fd, (sizeof(fd_t) - len)/2);
1059 insw(PIOP1(base), &eh, (len-2)/2);
1060 eh.ether_type = ntohs(inw(PIOP1(base)));
1062 if (ifp->if_flags & IFF_DEBUG)
1063 if_printf(ifp, "wlread: rcv packet, type is %x\n", eh.ether_type);
1066 * WARNING. above is done now in ether_input, above may be
1067 * useful for debug. jrb
1069 eh.ether_type = htons(eh.ether_type);
1071 if (fd.rbd_offset == I82586NULL) {
1072 if_printf(ifp, "read(): Invalid buffer\n");
1073 if (wlhwrst(sc) != TRUE)
1074 if_printf(ifp, "read(): hwrst trouble.\n");
1078 outw(PIOR1(base), fd.rbd_offset);
1079 insw(PIOP1(base), &rbd, sizeof(rbd_t)/2);
1080 bytes_in_msg = rbd.status & RBD_SW_COUNT;
1081 MGETHDR(m, MB_DONTWAIT, MT_DATA);
1085 * not only do we want to return, we need to drop the packet on
1086 * the floor to clear the interrupt.
1089 if (wlhwrst(sc) != TRUE) {
1090 sc->hacr &= ~HACR_INTRON;
1091 CMD(sc); /* turn off interrupts */
1092 if_printf(ifp, "read(): hwrst trouble.\n");
1096 m->m_next = (struct mbuf *) 0;
1097 m->m_pkthdr.rcvif = ifp;
1098 m->m_pkthdr.len = 0; /* don't know this yet */
1101 /* always use a cluster. jrb
1103 MCLGET(m, MB_DONTWAIT);
1104 if (m->m_flags & M_EXT) {
1105 m->m_len = MCLBYTES;
1109 if (wlhwrst(sc) != TRUE) {
1110 sc->hacr &= ~HACR_INTRON;
1111 CMD(sc); /* turn off interrupts */
1112 if_printf(ifp, "read(): hwrst trouble.\n");
1119 bytes_in_mbuf = m->m_len - sizeof(eh);
1120 mb_p = mtod(tm, u_char *);
1121 bytes = min(bytes_in_mbuf, bytes_in_msg);
1122 bcopy(&eh, mb_p, sizeof(eh));
1130 outw(PIOR1(base), rbd.buffer_addr);
1131 insw(PIOP1(base), mb_p, len/2);
1135 if (!(bytes_in_mbuf -= bytes)) {
1136 MGET(tm->m_next, MB_DONTWAIT, MT_DATA);
1138 if (tm == (struct mbuf *)0) {
1140 if_printf(ifp, "read(): No mbuf nth\n");
1141 if (wlhwrst(sc) != TRUE) {
1142 sc->hacr &= ~HACR_INTRON;
1143 CMD(sc); /* turn off interrupts */
1144 if_printf(ifp, "read(): hwrst trouble.\n");
1150 bytes_in_mbuf = MLEN;
1151 mb_p = mtod(tm, u_char *);
1156 if (!(bytes_in_msg -= bytes)) {
1157 if (rbd.status & RBD_SW_EOF ||
1158 rbd.next_rbd_offset == I82586NULL) {
1162 outw(PIOR1(base), rbd.next_rbd_offset);
1163 insw(PIOP1(base), &rbd, sizeof(rbd_t)/2);
1164 bytes_in_msg = rbd.status & RBD_SW_COUNT;
1167 rbd.buffer_addr += bytes;
1170 bytes = min(bytes_in_mbuf, bytes_in_msg);
1173 m->m_pkthdr.len = clen;
1176 * If hw is in promiscuous mode (note that I said hardware, not if
1177 * IFF_PROMISC is set in ifnet flags), then if this is a unicast
1178 * packet and the MAC dst is not us, drop it. This check in normally
1179 * inside ether_input(), but IFF_MULTI causes hw promisc without
1180 * a bpf listener, so this is wrong.
1181 * Greg Troxel <gdt@ir.bbn.com>, 1998-08-07
1184 * TBD: also discard packets where NWID does not match.
1185 * However, there does not appear to be a way to read the nwid
1186 * for a received packet. -gdt 1998-08-07
1189 #ifdef WL_USE_IFNET_PROMISC_CHECK /* not defined */
1190 (ifp->if_flags & (IFF_PROMISC|IFF_ALLMULTI))
1192 /* hw is in promisc mode if this is true */
1193 (sc->mode & (MOD_PROM | MOD_ENAL))
1196 (eh.ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */
1197 bcmp(eh.ether_dhost, sc->wl_ac.ac_enaddr,
1198 sizeof(eh.ether_dhost)) != 0 ) {
1204 if (ifp->if_flags & IFF_DEBUG)
1205 if_printf(ifp, "wlrecv %d bytes\n", clen);
1209 wl_cache_store(sc, base, &eh, m);
1213 * received packet is now in a chain of mbuf's. next step is
1214 * to pass the packet upwards.
1217 ifp->if_input(ifp, m);
1224 * This routine processes an ioctl request from the "if" layer
1227 * input : pointer the appropriate "if" struct, command and data
1228 * output : based on command appropriate action is taken on the
1229 * WaveLAN board(s) or related structures
1230 * return : error is returned containing exit conditions
1234 wlioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cred)
1236 struct ifreq *ifr = (struct ifreq *)data;
1237 struct wl_softc *sc = ifp->if_softc;
1238 short base = sc->base;
1241 int irq, irqval, i, isroot, size;
1244 struct thread *td = curthread; /* XXX */
1248 if (ifp->if_flags & IFF_DEBUG)
1249 if_printf(ifp, "entered wlioctl()\n");
1253 if (ifp->if_flags & IFF_ALLMULTI) {
1256 if (ifp->if_flags & IFF_PROMISC) {
1259 if(ifp->if_flags & IFF_LINK0) {
1263 * force a complete reset if the recieve multicast/
1264 * promiscuous mode changes so that these take
1265 * effect immediately.
1268 if (sc->mode != mode) {
1270 if (sc->flags & DSF_RUNNING) {
1271 sc->flags &= ~DSF_RUNNING;
1275 /* if interface is marked DOWN and still running then
1278 if ((ifp->if_flags & IFF_UP) == 0 && sc->flags & DSF_RUNNING) {
1279 if_printf(ifp, "ioctl(): board is not running\n");
1280 sc->flags &= ~DSF_RUNNING;
1281 sc->hacr &= ~HACR_INTRON;
1282 CMD(sc); /* turn off interrupts */
1284 /* else if interface is UP and RUNNING, start it
1286 else if (ifp->if_flags & IFF_UP && (sc->flags & DSF_RUNNING) == 0) {
1290 /* if WLDEBUG set on interface, then kprintf rf-modem regs
1292 if(ifp->if_flags & IFF_DEBUG)
1299 #if defined(__FreeBSD__) && __FreeBSD_version < 300000
1300 if (cmd == SIOCADDMULTI) {
1301 error = ether_addmulti(ifr, &sc->wl_ac);
1304 error = ether_delmulti(ifr, &sc->wl_ac);
1307 /* see if we should be in all multicast mode
1308 * note that 82586 cannot do that, must simulate with
1311 if (check_allmulti(sc)) {
1312 ifp->if_flags |= IFF_ALLMULTI;
1313 sc->mode |= MOD_ENAL;
1314 sc->flags &= ~DSF_RUNNING;
1320 if (error == ENETRESET) {
1321 if(sc->flags & DSF_RUNNING) {
1322 sc->flags &= ~DSF_RUNNING;
1331 #endif /* MULTICAST */
1333 /* DEVICE SPECIFIC */
1336 /* copy the PSA out to the caller */
1338 /* pointer to buffer in user space */
1339 up = (void *)ifr->ifr_data;
1340 /* work out if they're root */
1341 isroot = (suser(td) == 0);
1343 for (i = 0; i < 0x40; i++) {
1344 /* don't hand the DES key out to non-root users */
1345 if ((i > WLPSA_DESKEY) && (i < (WLPSA_DESKEY + 8)) && !isroot)
1347 if (subyte((up + i), sc->psa[i]))
1353 /* copy the PSA in from the caller; we only copy _some_ values */
1356 if ((error = suser(td)))
1358 error = EINVAL; /* assume the worst */
1359 /* pointer to buffer in user space containing data */
1360 up = (void *)ifr->ifr_data;
1362 /* check validity of input range */
1363 for (i = 0; i < 0x40; i++)
1364 if (fubyte(up + i) < 0)
1367 /* check IRQ value */
1368 irqval = fubyte(up+WLPSA_IRQNO);
1369 for (irq = 15; irq >= 0; irq--)
1370 if(irqvals[irq] == irqval)
1372 if (irq == 0) /* oops */
1375 sc->psa[WLPSA_IRQNO] = irqval;
1378 for (i = 0; i < 6; i++)
1379 sc->psa[WLPSA_LOCALMAC+i] = fubyte(up+WLPSA_LOCALMAC+i);
1382 sc->psa[WLPSA_MACSEL] = fubyte(up+WLPSA_MACSEL);
1385 sc->psa[WLPSA_NWID] = fubyte(up+WLPSA_NWID);
1386 sc->psa[WLPSA_NWID+1] = fubyte(up+WLPSA_NWID+1);
1389 wlsetpsa(sc); /* update the PSA */
1393 /* get the current NWID out of the sc since we stored it there */
1395 ifr->ifr_data = (caddr_t) (sc->nwid[0] << 8 | sc->nwid[1]);
1400 * change the nwid dynamically. This
1401 * ONLY changes the radio modem and does not
1405 * 1. save in softc "soft registers"
1406 * 2. save in radio modem (MMC)
1410 if ((error = suser(td)))
1412 if (!(ifp->if_flags & IFF_UP)) {
1413 error = EIO; /* only allowed while up */
1416 * soft c nwid shadows radio modem setting
1418 sc->nwid[0] = (int)ifr->ifr_data >> 8;
1419 sc->nwid[1] = (int)ifr->ifr_data & 0xff;
1420 MMC_WRITE(MMC_NETW_ID_L,sc->nwid[1]);
1421 MMC_WRITE(MMC_NETW_ID_H,sc->nwid[0]);
1425 /* copy the EEPROM in 2.4 Gz WaveMODEM out to the caller */
1428 if ((error = suser(td)))
1430 /* pointer to buffer in user space */
1431 up = (void *)ifr->ifr_data;
1433 for (i=0x00; i<0x80; ++i) { /* 2.4 Gz: size of EEPROM */
1434 MMC_WRITE(MMC_EEADDR,i); /* 2.4 Gz: get frequency */
1435 MMC_WRITE(MMC_EECTRL, /* 2.4 Gz: EEPROM read */
1436 MMC_EECTRL_EEOP_READ); /* 2.4 Gz: */
1437 DELAY(40); /* 2.4 Gz */
1438 if (subyte(up + 2*i , /* 2.4 Gz: pass low byte of */
1439 wlmmcread(base,MMC_EEDATALrv)) /* 2.4 Gz: EEPROM word */
1440 ) return(EFAULT); /* 2.4 Gz: */
1441 if (subyte(up + 2*i+1, /* 2.4 Gz: pass hi byte of */
1442 wlmmcread(base,MMC_EEDATALrv)) /* 2.4 Gz: EEPROM word */
1443 ) return(EFAULT); /* 2.4 Gz: */
1448 /* zero (Delete) the wl cache */
1451 if ((error = suser(td)))
1456 /* read out the number of used cache elements */
1458 ifr->ifr_data = (caddr_t) sc->w_sigitems;
1461 /* read out the wl cache */
1463 /* pointer to buffer in user space */
1464 up = (void *)ifr->ifr_data;
1465 cpt = (char *) &sc->w_sigcache[0];
1466 size = sc->w_sigitems * sizeof(struct w_sigcache);
1468 for (i = 0; i < size; i++) {
1469 if (subyte((up + i), *cpt++))
1476 error = ether_ioctl(ifp, cmd, data);
1485 * Called if the timer set in wlstart expires before an interrupt is received
1486 * from the wavelan. It seems to lose interrupts sometimes.
1487 * The watchdog routine gets called if the transmitter failed to interrupt
1489 * input : which board is timing out
1490 * output : board reset
1494 wlwatchdog(void *vsc)
1496 struct wl_softc *sc = vsc;
1497 struct ifnet *ifp = &sc->wl_if;
1499 lwkt_serialize_enter(ifp->if_serializer);
1500 log(LOG_ERR, "%s: wavelan device timeout on xmit\n", sc->wl_if.if_xname);
1501 sc->wl_if.if_oerrors++;
1503 lwkt_serialize_exit(ifp->if_serializer);
1509 * This function is the interrupt handler for the WaveLAN
1510 * board. This routine will be called whenever either a packet
1511 * is received, or a packet has successfully been transfered and
1512 * the unit is ready to transmit another packet.
1514 * input : softc pointer for this interface
1515 * output : either a packet is received, or a packet is transfered
1521 struct wl_softc *sc = arg;
1522 struct ifnet *ifp = &sc->wl_if;
1523 short base = sc->base;
1525 u_short int_type, int_type1;
1528 if (ifp->if_flags & IFF_DEBUG)
1529 if_printf(ifp, "wlintr() called\n");
1532 if((int_type = inw(HASR(base))) & HASR_MMC_INTR) {
1533 /* handle interrupt from the modem management controler */
1534 /* This will clear the interrupt condition */
1535 wlmmcread(base,MMC_DCE_STATUS); /* ignored for now */
1538 if(!(int_type & HASR_INTR)){ /* return if no interrupt from 82586 */
1539 /* commented out. jrb. it happens when reinit occurs
1540 if_printf(ifp, "%s: int_type %x, dump follows\n",
1541 __func__, int_type);
1550 outw(PIOR0(base), OFFSET_SCB + 0); /* get scb status */
1551 int_type = (inw(PIOP0(base)) & SCB_SW_INT);
1552 if (int_type == 0) /* no interrupts left */
1555 int_type1 = wlack(sc); /* acknowledge interrupt(s) */
1556 /* make sure no bits disappeared (others may appear) */
1557 if ((int_type & int_type1) != int_type) {
1558 if_printf(ifp, "wlack() int bits disappeared: "
1559 "%04x != int_type %04x\n", int_type1, int_type);
1561 int_type = int_type1; /* go with the new status */
1565 if (int_type & SCB_SW_FR) {
1570 * receiver not ready
1572 if (int_type & SCB_SW_RNR) {
1575 if (ifp->if_flags & IFF_DEBUG) {
1576 if_printf(ifp, "intr(): receiver overrun! begin_fd = %x\n",
1585 if (int_type & SCB_SW_CNA) {
1587 * At present, we don't care about CNA's. We
1588 * believe they are a side effect of XMT.
1591 if (int_type & SCB_SW_CX) {
1593 * At present, we only request Interrupt for
1596 outw(PIOR1(base), OFFSET_CU); /* get command status */
1597 ac_status = inw(PIOP1(base));
1599 if (xmt_watch) { /* report some anomalies */
1601 if (sc->tbusy == 0) {
1602 if_printf(ifp, "xmt intr but not busy, CU %04x\n",
1605 if (ac_status == 0) {
1606 if_printf(ifp, "xmt intr but ac_status == 0\n");
1608 if (ac_status & AC_SW_A) {
1609 if_printf(ifp, "xmt aborted\n");
1612 if (ac_status & TC_CARRIER) {
1613 if_printf(ifp, "no carrier\n");
1616 if (ac_status & TC_CLS) {
1617 if_printf(ifp, "no CTS\n");
1619 if (ac_status & TC_DMA) {
1620 if_printf(ifp, "DMA underrun\n");
1622 if (ac_status & TC_DEFER) {
1623 if_printf(ifp, "xmt deferred\n");
1625 if (ac_status & TC_SQE) {
1626 if_printf(ifp, "heart beat\n");
1628 if (ac_status & TC_COLLISION) {
1629 if_printf(ifp, "too many collisions\n");
1632 /* if the transmit actually failed, or returned some status */
1633 if ((!(ac_status & AC_SW_OK)) || (ac_status & 0xfff)) {
1634 if (ac_status & (TC_COLLISION | TC_CLS | TC_DMA)) {
1638 /* count collisions */
1639 ifp->if_collisions += (ac_status & 0xf);
1640 /* if TC_COLLISION set and collision count zero, 16 collisions */
1641 if ((ac_status & 0x20) == 0x20) {
1642 ifp->if_collisions += 0x10;
1646 callout_stop(&sc->watchdog_ch);
1647 ifp->if_flags &= ~IFF_OACTIVE;
1656 * This routine is called by the interrupt handler to initiate a
1657 * packet transfer from the board to the "if" layer above this
1658 * driver. This routine checks if a buffer has been successfully
1659 * received by the WaveLAN. If so, the routine wlread is called
1660 * to do the actual transfer of the board data (including the
1661 * ethernet header) into a packet (consisting of an mbuf chain).
1663 * input : softc pointer for this interface
1664 * output : if a packet is available, it is "sent up"
1668 wlrcv(struct wl_softc *sc)
1670 short base = sc->base;
1671 u_short fd_p, status, offset, link_offset;
1674 if (sc->wl_if.if_flags & IFF_DEBUG)
1675 if_printf(&sc->wl_if, "entered wlrcv()\n");
1677 for (fd_p = sc->begin_fd; fd_p != I82586NULL; fd_p = sc->begin_fd) {
1679 outw(PIOR0(base), fd_p + 0); /* address of status */
1680 status = inw(PIOP0(base));
1681 outw(PIOR1(base), fd_p + 4); /* address of link_offset */
1682 link_offset = inw(PIOP1(base));
1683 offset = inw(PIOP1(base)); /* rbd_offset */
1684 if (status == 0xffff || offset == 0xffff /*I82586NULL*/) {
1685 if (wlhwrst(sc) != TRUE)
1686 if_printf(&sc->wl_if, "rcv(): hwrst ffff trouble.\n");
1688 } else if (status & AC_SW_C) {
1689 if (status == (RFD_DONE|RFD_RSC)) {
1692 if (sc->wl_if.if_flags & IFF_DEBUG)
1693 if_printf(&sc->wl_if, "RCV: RSC %x\n", status);
1695 sc->wl_if.if_ierrors++;
1696 } else if (!(status & RFD_OK)) {
1697 if_printf(&sc->wl_if, "RCV: !OK %x\n", status);
1698 sc->wl_if.if_ierrors++;
1699 } else if (status & 0xfff) { /* can't happen */
1700 if_printf(&sc->wl_if, "RCV: ERRs %x\n", status);
1701 sc->wl_if.if_ierrors++;
1702 } else if (!wlread(sc, fd_p))
1705 if (!wlrequeue(sc, fd_p)) {
1706 /* abort on chain error */
1707 if (wlhwrst(sc) != TRUE)
1708 if_printf(&sc->wl_if, "rcv(): hwrst trouble.\n");
1711 sc->begin_fd = link_offset;
1721 * This routine puts rbd's used in the last receive back onto the
1722 * free list for the next receive.
1726 wlrequeue(struct wl_softc *sc, u_short fd_p)
1728 short base = sc->base;
1730 u_short l_rbdp, f_rbdp, rbd_offset;
1732 outw(PIOR0(base), fd_p + 6);
1733 rbd_offset = inw(PIOP0(base));
1734 if ((f_rbdp = rbd_offset) != I82586NULL) {
1737 outw(PIOR0(base), l_rbdp + 0); /* address of status */
1738 if(inw(PIOP0(base)) & RBD_SW_EOF)
1740 outw(PIOP0(base), 0);
1741 outw(PIOR0(base), l_rbdp + 2); /* next_rbd_offset */
1742 if((l_rbdp = inw(PIOP0(base))) == I82586NULL)
1745 outw(PIOP0(base), 0);
1746 outw(PIOR0(base), l_rbdp + 2); /* next_rbd_offset */
1747 outw(PIOP0(base), I82586NULL);
1748 outw(PIOR0(base), l_rbdp + 8); /* address of size */
1749 outw(PIOP0(base), inw(PIOP0(base)) | AC_CW_EL);
1750 outw(PIOR0(base), sc->end_rbd + 2);
1751 outw(PIOP0(base), f_rbdp); /* end_rbd->next_rbd_offset */
1752 outw(PIOR0(base), sc->end_rbd + 8); /* size */
1753 outw(PIOP0(base), inw(PIOP0(base)) & ~AC_CW_EL);
1754 sc->end_rbd = l_rbdp;
1758 fd.command = AC_CW_EL;
1759 fd.link_offset = I82586NULL;
1760 fd.rbd_offset = I82586NULL;
1761 outw(PIOR1(base), fd_p);
1762 outsw(PIOP1(base), &fd, 8/2);
1764 outw(PIOR1(base), sc->end_fd + 2); /* addr of command */
1765 outw(PIOP1(base), 0); /* command = 0 */
1766 outw(PIOP1(base), fd_p); /* end_fd->link_offset = fd_p */
1773 static int xmt_debug = 0;
1774 #endif /* WLDEBUG */
1779 * This routine fills in the appropriate registers and memory
1780 * locations on the WaveLAN board and starts the board off on
1783 * input : softc pointer for this interface, and a pointer to the mbuf
1784 * output : board memory and registers are set for xfer and attention
1788 wlxmt(struct wl_softc *sc, struct mbuf *m)
1790 u_short xmtdata_p = OFFSET_TBUF;
1792 struct mbuf *tm_p = m;
1793 struct ether_header *eh_p = mtod(m, struct ether_header *);
1794 u_char *mb_p = mtod(m, u_char *) + sizeof(struct ether_header);
1795 u_short count = m->m_len - sizeof(struct ether_header);
1797 u_short tbd_p = OFFSET_TBD;
1798 u_short len, clen = 0;
1799 short base = sc->base;
1803 if (sc->wl_if.if_flags & IFF_DEBUG)
1804 if_printf(&sc->wl_if, "entered wlxmt()\n");
1808 cb.ac_command = (AC_CW_EL|AC_TRANSMIT|AC_CW_I);
1809 cb.ac_link_offset = I82586NULL;
1810 outw(PIOR1(base), OFFSET_CU);
1811 outsw(PIOP1(base), &cb, 6/2);
1812 outw(PIOP1(base), OFFSET_TBD); /* cb.cmd.transmit.tbd_offset */
1813 outsw(PIOP1(base), eh_p->ether_dhost, WAVELAN_ADDR_SIZE/2);
1814 outw(PIOP1(base), eh_p->ether_type);
1817 if (sc->wl_if.if_flags & IFF_DEBUG) {
1819 if_printf(&sc->wl_if, "XMT mbuf: L%d @%p ", count, (void *)mb_p);
1820 kprintf("ether type %x\n", eh_p->ether_type);
1823 #endif /* WLDEBUG */
1824 outw(PIOR0(base), OFFSET_TBD);
1825 outw(PIOP0(base), 0); /* act_count */
1826 outw(PIOR1(base), OFFSET_TBD + 4);
1827 outw(PIOP1(base), xmtdata_p); /* buffer_addr */
1828 outw(PIOP1(base), 0); /* buffer_base */
1831 if (clen + count > WAVELAN_MTU)
1837 outw(PIOR1(base), xmtdata_p);
1838 outsw(PIOP1(base), mb_p, len/2);
1840 outw(PIOR0(base), tbd_p); /* address of act_count */
1841 outw(PIOP0(base), inw(PIOP0(base)) + count);
1843 if ((tm_p = tm_p->m_next) == (struct mbuf *)0)
1846 /* go to the next descriptor */
1847 outw(PIOR0(base), tbd_p + 2);
1848 tbd_p += sizeof (tbd_t);
1849 outw(PIOP0(base), tbd_p); /* next_tbd_offset */
1850 outw(PIOR0(base), tbd_p);
1851 outw(PIOP0(base), 0); /* act_count */
1852 outw(PIOR1(base), tbd_p + 4);
1853 outw(PIOP1(base), xmtdata_p); /* buffer_addr */
1854 outw(PIOP1(base), 0); /* buffer_base */
1855 /* at the end -> coallesce remaining mbufs */
1856 if (tbd_p == OFFSET_TBD + (N_TBD-1) * sizeof (tbd_t)) {
1857 wlsftwsleaze(&count, &mb_p, &tm_p);
1860 /* next mbuf short -> coallesce as needed */
1861 if ( (tm_p->m_next == (struct mbuf *) 0) ||
1862 #define HDW_THRESHOLD 55
1863 tm_p->m_len > HDW_THRESHOLD)
1866 wlhdwsleaze(&count, &mb_p, &tm_p);
1870 } else if ((tm_p = tm_p->m_next) == (struct mbuf *)0)
1872 count = tm_p->m_len;
1873 mb_p = mtod(tm_p, u_char *);
1875 if (sc->wl_if.if_flags & IFF_DEBUG)
1877 if_printf(&sc->wl_if, "mbuf+ L%d @%p ", count, (void *)mb_p);
1878 #endif /* WLDEBUG */
1881 if (sc->wl_if.if_flags & IFF_DEBUG)
1883 if_printf(&sc->wl_if, "CLEN = %d\n", clen);
1884 #endif /* WLDEBUG */
1885 outw(PIOR0(base), tbd_p);
1886 if (clen < ETHERMIN) {
1887 outw(PIOP0(base), inw(PIOP0(base)) + ETHERMIN - clen);
1888 outw(PIOR1(base), xmtdata_p);
1889 for (xmtshort_p = xmtdata_p; clen < ETHERMIN; clen += 2)
1890 outw(PIOP1(base), 0);
1892 outw(PIOP0(base), inw(PIOP0(base)) | TBD_SW_EOF);
1893 outw(PIOR0(base), tbd_p + 2);
1894 outw(PIOP0(base), I82586NULL);
1896 if (sc->wl_if.if_flags & IFF_DEBUG) {
1902 #endif /* WLDEBUG */
1904 outw(PIOR0(base), OFFSET_SCB + 2); /* address of scb_command */
1906 * wait for 586 to clear previous command, complain if it takes
1909 for (spin = 1;;spin = (spin + 1) % 10000) {
1910 if (inw(PIOP0(base)) == 0) { /* it's done, we can go */
1913 if ((spin == 0) && xmt_watch) { /* not waking up, and we care */
1914 if_printf(&sc->wl_if, "slow accepting xmit\n");
1917 outw(PIOP0(base), SCB_CU_STRT); /* new command */
1923 * Pause to avoid transmit overrun problems.
1924 * The required delay tends to vary with platform type, and may be
1925 * related to interrupt loss.
1927 if (wl_xmit_delay) {
1928 DELAY(wl_xmit_delay);
1935 * This function builds the linear linked lists of fd's and
1936 * rbd's. Based on page 4-32 of 1986 Intel microcom handbook.
1940 wlbldru(struct wl_softc *sc)
1942 short base = sc->base;
1945 u_short fd_p = OFFSET_RU;
1946 u_short rbd_p = OFFSET_RBD;
1949 sc->begin_fd = fd_p;
1950 for(i = 0; i < N_FD; i++) {
1953 fd.link_offset = fd_p + sizeof(fd_t);
1954 fd.rbd_offset = I82586NULL;
1955 outw(PIOR1(base), fd_p);
1956 outsw(PIOP1(base), &fd, 8/2);
1957 fd_p = fd.link_offset;
1959 fd_p -= sizeof(fd_t);
1961 outw(PIOR1(base), fd_p + 2);
1962 outw(PIOP1(base), AC_CW_EL); /* command */
1963 outw(PIOP1(base), I82586NULL); /* link_offset */
1966 outw(PIOR0(base), fd_p + 6); /* address of rbd_offset */
1967 outw(PIOP0(base), rbd_p);
1968 outw(PIOR1(base), rbd_p);
1969 for(i = 0; i < N_RBD; i++) {
1971 rbd.buffer_addr = rbd_p + sizeof(rbd_t) + 2;
1972 rbd.buffer_base = 0;
1973 rbd.size = RCVBUFSIZE;
1975 rbd_p += sizeof(ru_t);
1976 rbd.next_rbd_offset = rbd_p;
1978 rbd.next_rbd_offset = I82586NULL;
1979 rbd.size |= AC_CW_EL;
1980 sc->end_rbd = rbd_p;
1982 outsw(PIOP1(base), &rbd, sizeof(rbd_t)/2);
1983 outw(PIOR1(base), rbd_p);
1985 return sc->begin_fd;
1991 * This routine starts the receive unit running. First checks if the
1992 * board is actually ready, then the board is instructed to receive
1997 wlrustrt(struct wl_softc *sc)
1999 short base = sc->base;
2003 if (sc->wl_if.if_flags & IFF_DEBUG)
2004 if_printf(&sc->wl_if, "entered wlrustrt()\n");
2006 outw(PIOR0(base), OFFSET_SCB);
2007 if (inw(PIOP0(base)) & SCB_RUS_READY){
2008 if_printf(&sc->wl_if, "wlrustrt: RUS_READY\n");
2012 outw(PIOR0(base), OFFSET_SCB + 2);
2013 outw(PIOP0(base), SCB_RU_STRT); /* command */
2015 outw(PIOR0(base), OFFSET_SCB + 6); /* address of scb_rfa_offset */
2016 outw(PIOP0(base), rfa);
2024 * This routine does a 586 op-code number 7, and obtains the
2025 * diagnose status for the WaveLAN.
2029 wldiag(struct wl_softc *sc)
2031 short base = sc->base;
2035 if (sc->wl_if.if_flags & IFF_DEBUG)
2036 if_printf(&sc->wl_if, "entered wldiag()\n");
2038 outw(PIOR0(base), OFFSET_SCB);
2039 status = inw(PIOP0(base));
2040 if (status & SCB_SW_INT) {
2041 /* state is 2000 which seems ok
2042 if_printf(&sc->wl_if, "diag(): unexpected initial state %\n",
2047 outw(PIOR1(base), OFFSET_CU);
2048 outw(PIOP1(base), 0); /* ac_status */
2049 outw(PIOP1(base), AC_DIAGNOSE|AC_CW_EL);/* ac_command */
2050 if(wlcmd(sc, "diag()") == 0)
2052 outw(PIOR0(base), OFFSET_CU);
2053 if (inw(PIOP0(base)) & 0x0800) {
2054 if_printf(&sc->wl_if, "i82586 Self Test failed!\n");
2063 * This routine does a standard config of the WaveLAN board.
2067 wlconfig(struct wl_softc *sc)
2069 configure_t configure;
2070 short base = sc->base;
2073 #if defined(__DragonFly__) || (defined(__FreeBSD__) && __FreeBSD_version >= 300000)
2074 struct ifmultiaddr *ifma;
2077 struct ether_multi *enm;
2078 struct ether_multistep step;
2081 #endif /* MULTICAST */
2084 if (sc->wl_if.if_flags & IFF_DEBUG)
2085 if_printf(&sc->wl_if, "entered wlconfig()\n");
2087 outw(PIOR0(base), OFFSET_SCB);
2088 if (inw(PIOP0(base)) & SCB_SW_INT) {
2090 if_printf(&sc->wl_if, "config(): unexpected initial state %x\n",
2096 outw(PIOR1(base), OFFSET_CU);
2097 outw(PIOP1(base), 0); /* ac_status */
2098 outw(PIOP1(base), AC_CONFIGURE|AC_CW_EL); /* ac_command */
2101 configure.fifolim_bytecnt = 0x080c;
2102 configure.addrlen_mode = 0x0600;
2103 configure.linprio_interframe = 0x2060;
2104 configure.slot_time = 0xf200;
2105 configure.hardware = 0x0008; /* tx even w/o CD */
2106 configure.min_frame_len = 0x0040;
2108 /* This is the configuration block suggested by Marc Meertens
2109 * <mmeerten@obelix.utrecht.NCR.COM> in an e-mail message to John
2110 * Ioannidis on 10 Nov 92.
2112 configure.fifolim_bytecnt = 0x040c;
2113 configure.addrlen_mode = 0x0600;
2114 configure.linprio_interframe = 0x2060;
2115 configure.slot_time = 0xf000;
2116 configure.hardware = 0x0008; /* tx even w/o CD */
2117 configure.min_frame_len = 0x0040;
2120 * below is the default board configuration from p2-28 from 586 book
2122 configure.fifolim_bytecnt = 0x080c;
2123 configure.addrlen_mode = 0x2600;
2124 configure.linprio_interframe = 0x7820; /* IFS=120, ACS=2 */
2125 configure.slot_time = 0xf00c; /* slottime=12 */
2126 configure.hardware = 0x0008; /* tx even w/o CD */
2127 configure.min_frame_len = 0x0040;
2129 if(sc->mode & (MOD_PROM | MOD_ENAL)) {
2130 configure.hardware |= 1;
2132 outw(PIOR1(base), OFFSET_CU + 6);
2133 outsw(PIOP1(base), &configure, sizeof(configure_t)/2);
2135 if(wlcmd(sc, "config()-configure") == 0)
2138 outw(PIOR1(base), OFFSET_CU);
2139 outw(PIOP1(base), 0); /* ac_status */
2140 outw(PIOP1(base), AC_MCSETUP|AC_CW_EL); /* ac_command */
2141 outw(PIOR1(base), OFFSET_CU + 8);
2142 #if defined(__DragonFly__) || (defined(__FreeBSD__) && __FreeBSD_version >= 300000)
2143 LIST_FOREACH(ifma, &sc->wl_if.if_multiaddrs, ifma_link) {
2144 if (ifma->ifma_addr->sa_family != AF_LINK)
2147 addrp = LLADDR((struct sockaddr_dl *)ifma->ifma_addr);
2148 outw(PIOP1(base), addrp[0] + (addrp[1] << 8));
2149 outw(PIOP1(base), addrp[2] + (addrp[3] << 8));
2150 outw(PIOP1(base), addrp[4] + (addrp[5] << 8));
2154 ETHER_FIRST_MULTI(step, &sc->wl_ac, enm);
2155 while (enm != NULL) {
2156 unsigned int lo, hi;
2157 /* break if setting a multicast range, else we would crash */
2158 if (bcmp(enm->enm_addrlo, enm->enm_addrhi, 6) != 0) {
2161 lo = (enm->enm_addrlo[3] << 16) + (enm->enm_addrlo[4] << 8)
2162 + enm->enm_addrlo[5];
2163 hi = (enm->enm_addrhi[3] << 16) + (enm->enm_addrhi[4] << 8)
2164 + enm->enm_addrhi[5];
2166 outw(PIOP1(base),enm->enm_addrlo[0] +
2167 (enm->enm_addrlo[1] << 8));
2168 outw(PIOP1(base),enm->enm_addrlo[2] +
2169 ((lo >> 8) & 0xff00));
2170 outw(PIOP1(base), ((lo >> 8) & 0xff) +
2171 ((lo << 8) & 0xff00));
2172 /* #define MCASTDEBUG */
2174 kprintf("mcast_addr[%d,%d,%d] %x %x %x %x %x %x\n", lo, hi, cnt,
2180 enm->enm_addrlo[5]);
2185 ETHER_NEXT_MULTI(step, enm);
2188 outw(PIOR1(base), OFFSET_CU + 6); /* mc-cnt */
2189 outw(PIOP1(base), cnt * WAVELAN_ADDR_SIZE);
2190 if(wlcmd(sc, "config()-mcaddress") == 0)
2192 #endif /* MULTICAST */
2194 outw(PIOR1(base), OFFSET_CU);
2195 outw(PIOP1(base), 0); /* ac_status */
2196 outw(PIOP1(base), AC_IASETUP|AC_CW_EL); /* ac_command */
2197 outw(PIOR1(base), OFFSET_CU + 6);
2198 outsw(PIOP1(base), sc->wl_addr, WAVELAN_ADDR_SIZE/2);
2200 if(wlcmd(sc, "config()-address") == 0)
2211 * Set channel attention bit and busy wait until command has
2212 * completed. Then acknowledge the command completion.
2215 wlcmd(struct wl_softc *sc, const char *str)
2217 short base = sc->base;
2220 outw(PIOR0(base), OFFSET_SCB + 2); /* address of scb_command */
2221 outw(PIOP0(base), SCB_CU_STRT);
2225 outw(PIOR0(base), OFFSET_CU);
2226 for(i = 0; i < 0xffff; i++)
2227 if (inw(PIOP0(base)) & AC_SW_C)
2229 if (i == 0xffff || !(inw(PIOP0(base)) & AC_SW_OK)) {
2230 if_printf(&sc->wl_if, "%s failed; status = %d, inw = %x, outw = %x\n",
2231 str, inw(PIOP0(base)) & AC_SW_OK, inw(PIOP0(base)),
2233 outw(PIOR0(base), OFFSET_SCB);
2234 kprintf("scb_status %x\n", inw(PIOP0(base)));
2235 outw(PIOR0(base), OFFSET_SCB+2);
2236 kprintf("scb_command %x\n", inw(PIOP0(base)));
2237 outw(PIOR0(base), OFFSET_SCB+4);
2238 kprintf("scb_cbl %x\n", inw(PIOP0(base)));
2239 outw(PIOR0(base), OFFSET_CU+2);
2240 kprintf("cu_cmd %x\n", inw(PIOP0(base)));
2244 outw(PIOR0(base), OFFSET_SCB);
2245 if ((inw(PIOP0(base)) & SCB_SW_INT) && (inw(PIOP0(base)) != SCB_SW_CNA)) {
2247 if_printf(&sc->wl_if, "%s: unexpected final state %x\n",
2248 str, inw(PIOP0(base)));
2256 * wlack: if the 82596 wants attention because it has finished
2257 * sending or receiving a packet, acknowledge its desire and
2258 * return bits indicating the kind of attention. wlack() returns
2259 * these bits so that the caller can service exactly the
2260 * conditions that wlack() acknowledged.
2263 wlack(struct wl_softc *sc)
2267 short base = sc->base;
2269 outw(PIOR1(base), OFFSET_SCB);
2270 if(!(cmd = (inw(PIOP1(base)) & SCB_SW_INT)))
2273 if (sc->wl_if.if_flags & IFF_DEBUG)
2274 if_printf(&sc->wl_if, "doing a wlack()\n");
2276 outw(PIOP1(base), cmd);
2278 outw(PIOR0(base), OFFSET_SCB + 2); /* address of scb_command */
2279 for (i = 1000000; inw(PIOP0(base)) && (i-- > 0); );
2281 if_printf(&sc->wl_if, "wlack(): board not accepting command.\n");
2286 wltbd(struct wl_softc *sc)
2288 short base = sc->base;
2289 u_short tbd_p = OFFSET_TBD;
2295 outw(PIOR1(base), tbd_p);
2296 insw(PIOP1(base), &tbd, sizeof(tbd_t)/2);
2297 sum += (tbd.act_count & ~TBD_SW_EOF);
2298 kprintf("%d: addr %x, count %d (%d), next %x, base %x\n",
2299 i++, tbd.buffer_addr,
2300 (tbd.act_count & ~TBD_SW_EOF), sum,
2301 tbd.next_tbd_offset, tbd.buffer_base);
2302 if (tbd.act_count & TBD_SW_EOF)
2304 tbd_p = tbd.next_tbd_offset;
2309 wlhdwsleaze(u_short *countp, u_char **mb_pp, struct mbuf **tm_pp)
2311 struct mbuf *tm_p = *tm_pp;
2312 u_char *mb_p = *mb_pp;
2318 * can we get a run that will be coallesced or
2319 * that terminates before breaking
2322 count += tm_p->m_len;
2323 if (tm_p->m_len & 1)
2325 } while ((tm_p = tm_p->m_next) != (struct mbuf *)0);
2326 if ( (tm_p == (struct mbuf *)0) ||
2327 count > HDW_THRESHOLD) {
2328 *countp = (*tm_pp)->m_len;
2329 *mb_pp = mtod((*tm_pp), u_char *);
2333 /* we need to copy */
2337 cp = (u_char *) t_packet;
2339 bcopy(mtod(tm_p, u_char *), cp, len = tm_p->m_len);
2341 if (count > HDW_THRESHOLD)
2344 if (tm_p->m_next == (struct mbuf *)0)
2346 tm_p = tm_p->m_next;
2349 *mb_pp = (u_char *) t_packet;
2354 wlsftwsleaze(u_short *countp, u_char **mb_pp, struct mbuf **tm_pp)
2356 struct mbuf *tm_p = *tm_pp;
2358 u_char *cp = (u_char *) t_packet;
2361 /* we need to copy */
2363 bcopy(mtod(tm_p, u_char *), cp, len = tm_p->m_len);
2366 if (tm_p->m_next == (struct mbuf *)0)
2368 tm_p = tm_p->m_next;
2372 *mb_pp = (u_char *) t_packet;
2377 wlmmcstat(struct wl_softc *sc)
2379 short base = sc->base;
2382 if_printf(&sc->wl_if, "DCE_STATUS: 0x%x, ",
2383 wlmmcread(base,MMC_DCE_STATUS) & 0x0f);
2384 tmp = wlmmcread(base,MMC_CORRECT_NWID_H) << 8;
2385 tmp |= wlmmcread(base,MMC_CORRECT_NWID_L);
2386 kprintf("Correct NWID's: %d, ", tmp);
2387 tmp = wlmmcread(base,MMC_WRONG_NWID_H) << 8;
2388 tmp |= wlmmcread(base,MMC_WRONG_NWID_L);
2389 kprintf("Wrong NWID's: %d\n", tmp);
2390 kprintf("THR_PRE_SET: 0x%x, ", wlmmcread(base,MMC_THR_PRE_SET));
2391 kprintf("SIGNAL_LVL: %d, SILENCE_LVL: %d\n",
2392 wlmmcread(base,MMC_SIGNAL_LVL),
2393 wlmmcread(base,MMC_SILENCE_LVL));
2394 kprintf("SIGN_QUAL: 0x%x, NETW_ID: %x:%x, DES: %d\n",
2395 wlmmcread(base,MMC_SIGN_QUAL),
2396 wlmmcread(base,MMC_NETW_ID_H),
2397 wlmmcread(base,MMC_NETW_ID_L),
2398 wlmmcread(base,MMC_DES_AVAIL));
2402 wlmmcread(u_int base, u_short reg)
2404 while(inw(HASR(base)) & HASR_MMC_BUSY) ;
2405 outw(MMCR(base),reg << 1);
2406 while(inw(HASR(base)) & HASR_MMC_BUSY) ;
2407 return (u_short)inw(MMCR(base)) >> 8;
2411 getsnr(struct wl_softc *sc)
2413 MMC_WRITE(MMC_FREEZE,1);
2415 * SNR retrieval procedure :
2417 * read signal level : wlmmcread(base, MMC_SIGNAL_LVL);
2418 * read silence level : wlmmcread(base, MMC_SILENCE_LVL);
2420 MMC_WRITE(MMC_FREEZE,0);
2422 * SNR is signal:silence ratio.
2429 ** Reads the psa for the wavelan at (base) into (buf)
2432 wlgetpsa(int base, u_char *buf)
2436 PCMD(base, HACR_DEFAULT & ~HACR_16BITS);
2437 PCMD(base, HACR_DEFAULT & ~HACR_16BITS);
2439 for (i = 0; i < 0x40; i++) {
2440 outw(PIOR2(base), i);
2441 buf[i] = inb(PIOP2(base));
2443 PCMD(base, HACR_DEFAULT);
2444 PCMD(base, HACR_DEFAULT);
2450 ** Writes the psa for wavelan (unit) from the softc back to the
2451 ** board. Updates the CRC and sets the CRC OK flag.
2453 ** Do not call this when the board is operating, as it doesn't
2454 ** preserve the hacr.
2457 wlsetpsa(struct wl_softc *sc)
2459 short base = sc->base;
2463 crc = wlpsacrc(sc->psa); /* calculate CRC of PSA */
2464 sc->psa[WLPSA_CRCLOW] = crc & 0xff;
2465 sc->psa[WLPSA_CRCHIGH] = (crc >> 8) & 0xff;
2466 sc->psa[WLPSA_CRCOK] = 0x55; /* default to 'bad' until programming complete */
2468 PCMD(base, HACR_DEFAULT & ~HACR_16BITS);
2469 PCMD(base, HACR_DEFAULT & ~HACR_16BITS);
2471 for (i = 0; i < 0x40; i++) {
2473 outw(PIOR2(base),i); /* write param memory */
2475 outb(PIOP2(base), sc->psa[i]);
2478 outw(PIOR2(base),WLPSA_CRCOK); /* update CRC flag*/
2480 sc->psa[WLPSA_CRCOK] = 0xaa; /* OK now */
2481 outb(PIOP2(base), 0xaa); /* all OK */
2484 PCMD(base, HACR_DEFAULT);
2485 PCMD(base, HACR_DEFAULT);
2489 ** CRC routine provided by Christopher Giordano <cgiordan@gdeb.com>,
2490 ** from original code by Tomi Mikkonen (tomitm@remedy.fi)
2493 static u_int crc16_table[16] = {
2494 0x0000, 0xCC01, 0xD801, 0x1400,
2495 0xF001, 0x3C00, 0x2800, 0xE401,
2496 0xA001, 0x6C00, 0x7800, 0xB401,
2497 0x5000, 0x9C01, 0x8801, 0x4400
2501 wlpsacrc(u_char *buf)
2506 for (i = 0; i < 0x3d; i++, buf++) {
2508 r1 = crc16_table[crc & 0xF];
2509 crc = (crc >> 4) & 0x0FFF;
2510 crc = crc ^ r1 ^ crc16_table[*buf & 0xF];
2513 r1 = crc16_table[crc & 0xF];
2514 crc = (crc >> 4) & 0x0FFF;
2515 crc = crc ^ r1 ^ crc16_table[(*buf >> 4) & 0xF];
2524 * take input packet and cache various radio hw characteristics
2525 * indexed by MAC address.
2527 * Some things to think about:
2528 * note that no space is malloced.
2529 * We might hash the mac address if the cache were bigger.
2530 * It is not clear that the cache is big enough.
2531 * It is also not clear how big it should be.
2532 * The cache is IP-specific. We don't care about that as
2533 * we want it to be IP-specific.
2534 * The last N recv. packets are saved. This will tend
2535 * to reward agents and mobile hosts that beacon.
2536 * That is probably fine for mobile ip.
2539 /* globals for wavelan signal strength cache */
2540 /* this should go into softc structure above.
2543 /* set true if you want to limit cache items to broadcast/mcast
2544 * only packets (not unicast)
2546 static int wl_cache_mcastonly = 1;
2547 SYSCTL_INT(_machdep, OID_AUTO, wl_cache_mcastonly, CTLFLAG_RW,
2548 &wl_cache_mcastonly, 0, "");
2550 /* set true if you want to limit cache items to IP packets only
2552 static int wl_cache_iponly = 1;
2553 SYSCTL_INT(_machdep, OID_AUTO, wl_cache_iponly, CTLFLAG_RW,
2554 &wl_cache_iponly, 0, "");
2556 /* zero out the cache
2559 wl_cache_zero(struct wl_softc *sc)
2561 bzero(&sc->w_sigcache[0], sizeof(struct w_sigcache) * MAXCACHEITEMS);
2563 sc->w_nextcache = 0;
2564 sc->w_wrapindex = 0;
2567 /* store hw signal info in cache.
2568 * index is MAC address, but an ip src gets stored too
2569 * There are two filters here controllable via sysctl:
2570 * throw out unicast (on by default, but can be turned off)
2571 * throw out non-ip (on by default, but can be turned off)
2574 wl_cache_store(struct wl_softc *sc, int base, struct ether_header *eh,
2577 struct ip *ip = NULL; /* Avoid GCC warning */
2579 int signal, silence;
2580 int w_insertcache; /* computed index for cache entry storage */
2581 int ipflag = wl_cache_iponly;
2585 * 2. configurable filter to throw out unicast packets,
2586 * keep multicast only.
2590 /* reject if not IP packet
2592 if ( wl_cache_iponly && (ntohs(eh->ether_type) != 0x800)) {
2596 /* check if broadcast or multicast packet. we toss
2599 if (wl_cache_mcastonly && ((eh->ether_dhost[0] & 1) == 0)) {
2603 /* find the ip header. we want to store the ip_src
2604 * address. use the mtod macro(in mbuf.h)
2605 * to typecast m to struct ip *
2608 ip = mtod(m, struct ip *);
2611 /* do a linear search for a matching MAC address
2612 * in the cache table
2613 * . MAC address is 6 bytes,
2614 * . var w_nextcache holds total number of entries already cached
2616 for(i = 0; i < sc->w_nextcache; i++) {
2617 if (! bcmp(eh->ether_shost, sc->w_sigcache[i].macsrc, 6 )) {
2619 * so we already have this entry,
2620 * update the data, and LRU age
2626 /* did we find a matching mac address?
2627 * if yes, then overwrite a previously existing cache entry
2629 if (i < sc->w_nextcache ) {
2632 /* else, have a new address entry,so
2633 * add this new entry,
2634 * if table full, then we need to replace entry
2638 /* check for space in cache table
2639 * note: w_nextcache also holds number of entries
2640 * added in the cache table
2642 if ( sc->w_nextcache < MAXCACHEITEMS ) {
2643 w_insertcache = sc->w_nextcache;
2645 sc->w_sigitems = sc->w_nextcache;
2647 /* no space found, so simply wrap with wrap index
2648 * and "zap" the next entry
2651 if (sc->w_wrapindex == MAXCACHEITEMS) {
2652 sc->w_wrapindex = 0;
2654 w_insertcache = sc->w_wrapindex++;
2658 /* invariant: w_insertcache now points at some slot
2661 if (w_insertcache < 0 || w_insertcache >= MAXCACHEITEMS) {
2663 "wl_cache_store, bad index: %d of [0..%d], gross cache error\n",
2664 w_insertcache, MAXCACHEITEMS);
2668 /* store items in cache
2671 * .signal (0..63) ,silence (0..63) ,quality (0..15)
2674 sc->w_sigcache[w_insertcache].ipsrc = ip->ip_src.s_addr;
2676 bcopy( eh->ether_shost, sc->w_sigcache[w_insertcache].macsrc, 6);
2677 signal = sc->w_sigcache[w_insertcache].signal = wlmmcread(base, MMC_SIGNAL_LVL) & 0x3f;
2678 silence = sc->w_sigcache[w_insertcache].silence = wlmmcread(base, MMC_SILENCE_LVL) & 0x3f;
2679 sc->w_sigcache[w_insertcache].quality = wlmmcread(base, MMC_SIGN_QUAL) & 0x0f;
2681 sc->w_sigcache[w_insertcache].snr =
2684 sc->w_sigcache[w_insertcache].snr = 0;
2688 #endif /* WLCACHE */
2691 * determine if in all multicast mode or not
2693 * returns: 1 if IFF_ALLMULTI should be set
2698 #if defined(__FreeBSD__) && __FreeBSD_version < 300000 /* not required */
2700 check_allmulti(struct wl_softc *sc)
2702 short base = sc->base;
2703 struct ether_multi *enm;
2704 struct ether_multistep step;
2706 ETHER_FIRST_MULTI(step, &sc->wl_ac, enm);
2707 while (enm != NULL) {
2708 unsigned int lo, hi;
2710 kprintf("enm_addrlo %x:%x:%x:%x:%x:%x\n", enm->enm_addrlo[0], enm->enm_addrlo[1],
2711 enm->enm_addrlo[2], enm->enm_addrlo[3], enm->enm_addrlo[4],
2712 enm->enm_addrlo[5]);
2713 kprintf("enm_addrhi %x:%x:%x:%x:%x:%x\n", enm->enm_addrhi[0], enm->enm_addrhi[1],
2714 enm->enm_addrhi[2], enm->enm_addrhi[3], enm->enm_addrhi[4],
2715 enm->enm_addrhi[5]);
2717 if (bcmp(enm->enm_addrlo, enm->enm_addrhi, 6) != 0) {
2720 ETHER_NEXT_MULTI(step, enm);