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.23 2005/07/07 15:15:24 joerg 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/sockio.h>
198 #include <sys/mbuf.h>
199 #include <sys/socket.h>
200 #include <sys/syslog.h>
201 #include <sys/proc.h>
202 #include <sys/thread2.h>
204 #include <sys/kernel.h>
205 #include <sys/sysctl.h>
207 #include <machine/bus.h>
208 #include <machine/resource.h>
210 #include <sys/rman.h>
212 #include <net/ethernet.h>
214 #include <net/if_arp.h>
215 #include <net/ifq_var.h>
216 #include <net/if_dl.h>
219 #include <netinet/in.h>
220 #include <netinet/in_systm.h>
221 #include <netinet/ip.h>
222 #include <netinet/if_ether.h>
227 #include <bus/isa/isavar.h>
228 #include <bus/isa/i386/isa_device.h>
229 #include "if_wl_i82586.h" /* Definitions for the Intel chip */
231 /* was 1000 in original, fed to DELAY(x) */
232 #define DELAYCONST 1000
234 #include <machine/if_wl_wavelan.h>
236 static char t_packet[ETHERMTU + sizeof(struct ether_header) + sizeof(long)];
239 struct arpcom wl_ac; /* Ethernet common part */
240 #define wl_if wl_ac.ac_if /* network visible interface */
241 #define wl_addr wl_ac.ac_enaddr /* hardware address */
243 u_char nwid[2]; /* current radio modem nwid */
246 int tbusy; /* flag to determine if xmit is busy */
250 u_short hacr; /* latest host adapter CR command */
252 u_char chan24; /* 2.4 Gz: channel number/EEPROM Area # */
253 u_short freq24; /* 2.4 Gz: resulting frequency */
256 struct resource *res_ioport;
257 struct resource *res_irq;
259 struct callout watchdog_ch;
261 int w_sigitems; /* number of cached entries */
262 /* array of cache entries */
263 struct w_sigcache w_sigcache[ MAXCACHEITEMS ];
264 int w_nextcache; /* next free cache entry */
265 int w_wrapindex; /* next "free" cache entry */
270 * XXX The Wavelan appears to be prone to dropping stuff if you talk to
271 * it too fast. This disgusting hack inserts a delay after each packet
272 * is queued which helps avoid this behaviour on fast systems.
274 static int wl_xmit_delay = 250;
275 SYSCTL_INT(_machdep, OID_AUTO, wl_xmit_delay, CTLFLAG_RW, &wl_xmit_delay, 0, "");
278 * not XXX, but ZZZ (bizarre).
279 * promiscuous mode can be toggled to ignore NWIDs. By default,
280 * it does not. Caution should be exercised about combining
281 * this mode with IFF_ALLMULTI which puts this driver in
284 static int wl_ignore_nwid = 0;
285 SYSCTL_INT(_machdep, OID_AUTO, wl_ignore_nwid, CTLFLAG_RW, &wl_ignore_nwid, 0, "");
288 * Emit diagnostics about transmission problems
290 static int xmt_watch = 0;
291 SYSCTL_INT(_machdep, OID_AUTO, wl_xmit_watch, CTLFLAG_RW, &xmt_watch, 0, "");
294 * Collect SNR statistics
296 static int gathersnr = 0;
297 SYSCTL_INT(_machdep, OID_AUTO, wl_gather_snr, CTLFLAG_RW, &gathersnr, 0, "");
299 static int wlprobe(device_t);
300 static int wlattach(device_t);
301 static int wldetach(device_t);
302 static int wl_alloc_resources(device_t);
303 static void wl_free_resources(device_t);
304 static void wlstart(struct ifnet *);
305 static void wlinit(void *);
306 static int wlioctl(struct ifnet *, u_long, caddr_t, struct ucred *);
307 static timeout_t wlwatchdog;
308 static void wlintr(void *);
309 static void wlxmt(struct wl_softc *, struct mbuf *);
310 static int wldiag(struct wl_softc *);
311 static int wlconfig(struct wl_softc *);
312 static int wlcmd(struct wl_softc *, const char *);
313 static void wlmmcstat(struct wl_softc *);
314 static u_short wlbldru(struct wl_softc *);
315 static u_short wlmmcread(u_int, u_short);
316 static void wlinitmmc(struct wl_softc *);
317 static int wlhwrst(struct wl_softc *);
318 static void wlrustrt(struct wl_softc *);
319 static void wlbldcu(struct wl_softc *);
320 static int wlack(struct wl_softc *);
321 static int wlread(struct wl_softc *, u_short);
322 static void getsnr(struct wl_softc *);
323 static void wlrcv(struct wl_softc *);
324 static int wlrequeue(struct wl_softc *, u_short);
325 static void wlsftwsleaze(u_short *, u_char **, struct mbuf **);
326 static void wlhdwsleaze(u_short *, u_char **, struct mbuf **);
327 static void wltbd(struct wl_softc *);
328 static void wlgetpsa(int, u_char *);
329 static void wlsetpsa(struct wl_softc *);
330 static u_short wlpsacrc(u_char *);
331 static void wldump(struct wl_softc *);
333 static void wl_cache_store(struct wl_softc *, int, struct ether_header *,
335 static void wl_cache_zero(struct wl_softc *);
338 # if defined(__FreeBSD__) && __FreeBSD_version < 300000
339 static int check_allmulti(struct wl_softc *);
343 static device_method_t wl_methods[] = {
344 DEVMETHOD(device_probe, wlprobe),
345 DEVMETHOD(device_attach, wlattach),
346 DEVMETHOD(device_detach, wldetach),
350 static driver_t wl_driver = {
353 sizeof(struct wl_softc)
356 devclass_t wl_devclass;
357 DECLARE_DUMMY_MODULE(if_wl);
358 DRIVER_MODULE(wl, isa, wl_driver, wl_devclass, 0, 0);
359 MODULE_DEPEND(wl, isa, 1, 1, 1);
361 static struct isa_pnp_id wl_ids[] = {
365 /* array for maping irq numbers to values for the irq parameter register */
366 static int irqvals[16] = {
367 0, 0, 0, 0x01, 0x02, 0x04, 0, 0x08, 0, 0, 0x10, 0x20, 0x40, 0, 0, 0x80
373 * This function "probes" or checks for the WaveLAN board on the bus to
374 * see if it is there. As far as I can tell, the best break between this
375 * routine and the attach code is to simply determine whether the board
376 * is configured in properly. Currently my approach to this is to write
377 * and read a word from the SRAM on the board being probed. If the word
378 * comes back properly then we assume the board is there. The config
379 * code expects to see a successful return from the probe routine before
380 * attach will be called.
383 wlprobe(device_t dev)
387 const char *str = "wl%d: board out of range [0..%d]\n";
391 error = ISA_PNP_PROBE(device_get_parent(dev), dev, wl_ids);
392 if (error == ENXIO || error == 0)
395 sc = device_get_softc(dev);
396 error = wl_alloc_resources(dev);
400 base = rman_get_start(sc->res_ioport);
403 * regular CMD() will not work, since no softc yet
405 #define PCMD(base, hacr) outw((base), (hacr))
408 PCMD(base, HACR_RESET); /* reset the board */
409 DELAY(DELAYCONST); /* >> 4 clocks at 6MHz */
410 PCMD(base, HACR_RESET); /* reset the board */
411 DELAY(DELAYCONST); /* >> 4 clocks at 6MHz */
414 /* clear reset command and set PIO#1 in autoincrement mode */
415 PCMD(base, HACR_DEFAULT);
416 PCMD(base, HACR_DEFAULT);
417 outw(PIOR1(base), 0); /* go to beginning of RAM */
418 outsw(PIOP1(base), str, strlen(str)/2+1); /* write string */
420 outw(PIOR1(base), 0); /* rewind */
421 insw(PIOP1(base), inbuf, strlen(str)/2+1); /* read result */
423 if (bcmp(str, inbuf, strlen(str))) {
428 sc->chan24 = 0; /* 2.4 Gz: config channel */
429 sc->freq24 = 0; /* 2.4 Gz: frequency */
431 /* read the PSA from the board into temporary storage */
432 wlgetpsa(base, inbuf);
434 /* We read the IRQ value from the PSA on the board. */
435 for (irq = 15; irq >= 0; irq--)
436 if (irqvals[irq] == inbuf[WLPSA_IRQNO])
438 if ((irq == 0) || (irqvals[irq] == 0)){
439 device_printf(dev, "PSA corrupt (invalid IRQ value)\n");
444 * If the IRQ requested by the PSA is already claimed by another
445 * device, the board won't work, but the user can still access the
446 * driver to change the IRQ.
448 if (bus_get_resource(dev, SYS_RES_IRQ, 0, &sirq, &dummy))
450 if (irq != (int)sirq)
451 device_printf(dev, "board is configured for interrupt %d\n", irq);
456 wl_free_resources(dev);
463 * This function attaches a WaveLAN board to the "system". The rest of
464 * runtime structures are initialized here (this routine is called after
465 * a successful probe of the board). Once the ethernet address is read
466 * and stored, the board's ifnet structure is attached and readied.
469 wlattach(device_t dev)
476 sc = device_get_softc(dev);
479 if_initname(ifp, device_get_name(dev), device_get_unit(dev));
481 error = wl_alloc_resources(dev);
485 base = rman_get_start(sc->res_ioport);
488 device_printf(dev, "%s: base %x, unit %d\n",
489 __func__, base, device_get_unit(dev));
495 sc->hacr = HACR_RESET;
496 callout_init(&sc->watchdog_ch);
497 CMD(sc); /* reset the board */
498 DELAY(DELAYCONST); /* >> 4 clocks at 6MHz */
500 /* clear reset command and set PIO#2 in parameter access mode */
501 sc->hacr = (HACR_DEFAULT & ~HACR_16BITS);
504 /* Read the PSA from the board for our later reference */
505 wlgetpsa(base, sc->psa);
508 sc->nwid[0] = sc->psa[WLPSA_NWID];
509 sc->nwid[1] = sc->psa[WLPSA_NWID+1];
511 /* fetch MAC address - decide which one first */
512 if (sc->psa[WLPSA_MACSEL] & 1) {
517 for(i=0; i < WAVELAN_ADDR_SIZE; ++i) {
518 sc->wl_addr[i] = sc->psa[j + i];
521 /* enter normal 16 bit mode operation */
522 sc->hacr = HACR_DEFAULT;
526 outw(PIOR1(base), OFFSET_SCB + 8); /* address of scb_crcerrs */
527 outw(PIOP1(base), 0); /* clear scb_crcerrs */
528 outw(PIOP1(base), 0); /* clear scb_alnerrs */
529 outw(PIOP1(base), 0); /* clear scb_rscerrs */
530 outw(PIOP1(base), 0); /* clear scb_ovrnerrs */
533 ifp->if_mtu = WAVELAN_MTU;
534 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
536 ifp->if_flags |= IFF_DEBUG;
539 ifp->if_flags |= IFF_MULTICAST;
540 #endif /* MULTICAST */
541 ifp->if_init = wlinit;
542 ifp->if_start = wlstart;
543 ifp->if_ioctl = wlioctl;
544 ifp->if_timer = 0; /* paranoia */
550 ifq_set_maxlen(&ifp->if_snd, IFQ_MAXLEN);
551 ifq_set_ready(&ifp->if_snd);
552 ether_ifattach(ifp, sc->wl_ac.ac_enaddr);
555 printf(", Freq %d MHz",sc->freq24); /* 2.4 Gz */
556 printf("\n"); /* 2.4 Gz */
558 error = bus_setup_intr(dev, sc->res_irq, INTR_TYPE_NET,
559 wlintr, sc, &sc->intr_handle, NULL);
561 device_printf(dev, "setup irq fail!\n");
563 wl_free_resources(dev);
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;
582 /* reset the board */
583 sc->hacr = HACR_RESET;
585 sc->hacr = HACR_DEFAULT;
588 if (sc->intr_handle != NULL) {
589 BUS_TEARDOWN_INTR(parent, dev, sc->res_irq, sc->intr_handle);
590 sc->intr_handle = NULL;
593 bus_generic_detach(dev);
596 wl_free_resources(dev);
601 wl_alloc_resources(device_t dev)
603 struct wl_softc *sc = device_get_softc(dev);
604 int ports = 16; /* Number of ports */
606 sc->res_ioport = bus_alloc_resource(dev, SYS_RES_IOPORT,
607 &sc->rid_ioport, 0ul, ~0ul, ports, RF_ACTIVE);
608 if (sc->res_ioport == NULL)
611 sc->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
612 &sc->rid_irq, RF_SHAREABLE | RF_ACTIVE);
613 if (sc->res_irq == NULL)
618 wl_free_resources(dev);
623 wl_free_resources(device_t dev)
625 struct wl_softc *sc = device_get_softc(dev);
627 if (sc->res_irq != 0) {
628 bus_deactivate_resource(dev, SYS_RES_IRQ, sc->rid_irq, sc->res_irq);
629 bus_release_resource(dev, SYS_RES_IRQ, sc->rid_irq, sc->res_irq);
632 if (sc->res_ioport != 0) {
633 bus_deactivate_resource(dev, SYS_RES_IOPORT,
634 sc->rid_ioport, sc->res_ioport);
635 bus_release_resource(dev, SYS_RES_IOPORT,
636 sc->rid_ioport, sc->res_ioport);
642 * Print out interesting information about the 82596.
645 wldump(struct wl_softc *sc)
650 if_printf(&sc->wl_if, "hasr %04x\n", inw(HASR(base)));
652 if_printf(&sc->wl_if, "scb at %04x:\n ", OFFSET_SCB);
653 outw(PIOR1(base), OFFSET_SCB);
654 for(i = 0; i < 8; i++)
655 printf("%04x ", inw(PIOP1(base)));
658 if_printf(&sc->wl_if, "cu at %04x:\n ", OFFSET_CU);
659 outw(PIOR1(base), OFFSET_CU);
660 for(i = 0; i < 8; i++)
661 printf("%04x ", inw(PIOP1(base)));
664 if_printf(&sc->wl_if, "tbd at %04x:\n ", OFFSET_TBD);
665 outw(PIOR1(base), OFFSET_TBD);
666 for(i = 0; i < 4; i++)
667 printf("%04x ", inw(PIOP1(base)));
671 /* Initialize the Modem Management Controller */
673 wlinitmmc(struct wl_softc *sc)
680 /* enter 8 bit operation */
681 sc->hacr = (HACR_DEFAULT & ~HACR_16BITS);
684 configured = sc->psa[WLPSA_CONFIGURED] & 1;
687 * Set default modem control parameters. Taken from NCR document
690 MMC_WRITE(MMC_JABBER_ENABLE, 0x01);
691 MMC_WRITE(MMC_ANTEN_SEL, 0x02);
692 MMC_WRITE(MMC_IFS, 0x20);
693 MMC_WRITE(MMC_MOD_DELAY, 0x04);
694 MMC_WRITE(MMC_JAM_TIME, 0x38);
695 MMC_WRITE(MMC_DECAY_PRM, 0x00); /* obsolete ? */
696 MMC_WRITE(MMC_DECAY_UPDAT_PRM, 0x00);
698 MMC_WRITE(MMC_LOOPT_SEL, 0x00);
699 if (sc->psa[WLPSA_COMPATNO] & 1) {
700 MMC_WRITE(MMC_THR_PRE_SET, 0x01); /* 0x04 for AT and 0x01 for MCA */
702 MMC_WRITE(MMC_THR_PRE_SET, 0x04); /* 0x04 for AT and 0x01 for MCA */
704 MMC_WRITE(MMC_QUALITY_THR, 0x03);
706 /* use configuration defaults from parameter storage area */
707 if (sc->psa[WLPSA_NWIDENABLE] & 1) {
708 if ((mode & (MOD_PROM | MOD_ENAL)) && wl_ignore_nwid) {
709 MMC_WRITE(MMC_LOOPT_SEL, 0x40);
711 MMC_WRITE(MMC_LOOPT_SEL, 0x00);
714 MMC_WRITE(MMC_LOOPT_SEL, 0x40); /* disable network id check */
716 MMC_WRITE(MMC_THR_PRE_SET, sc->psa[WLPSA_THRESH]);
717 MMC_WRITE(MMC_QUALITY_THR, sc->psa[WLPSA_QUALTHRESH]);
719 MMC_WRITE(MMC_FREEZE, 0x00);
720 MMC_WRITE(MMC_ENCR_ENABLE, 0x00);
722 MMC_WRITE(MMC_NETW_ID_L,sc->nwid[1]); /* set NWID */
723 MMC_WRITE(MMC_NETW_ID_H,sc->nwid[0]);
725 /* enter normal 16 bit mode operation */
726 sc->hacr = HACR_DEFAULT;
728 CMD(sc); /* virtualpc1 needs this! */
730 if (sc->psa[WLPSA_COMPATNO]== /* 2.4 Gz: half-card ver */
731 WLPSA_COMPATNO_WL24B) { /* 2.4 Gz */
732 i=sc->chan24<<4; /* 2.4 Gz: position ch # */
733 MMC_WRITE(MMC_EEADDR,i+0x0f); /* 2.4 Gz: named ch, wc=16 */
734 MMC_WRITE(MMC_EECTRL,MMC_EECTRL_DWLD+ /* 2.4 Gz: Download Synths */
735 MMC_EECTRL_EEOP_READ); /* 2.4 Gz: Read EEPROM */
736 for (i=0; i<1000; ++i) { /* 2.4 Gz: wait for download */
737 DELAY(40); /* 2.4 Gz */
738 if ((wlmmcread(base,MMC_EECTRLstat) /* 2.4 Gz: check DWLD and */
739 &(MMC_EECTRLstat_DWLD /* 2.4 Gz: EEBUSY */
740 +MMC_EECTRLstat_EEBUSY))==0) /* 2.4 Gz: */
741 break; /* 2.4 Gz: download finished */
744 if_printf(&sc->wl_if,
745 "synth load failed\n"); /* 2.4 Gz */
747 MMC_WRITE(MMC_EEADDR,0x61); /* 2.4 Gz: default pwr, wc=2 */
748 MMC_WRITE(MMC_EECTRL,MMC_EECTRL_DWLD+ /* 2.4 Gz: Download Xmit Pwr */
749 MMC_EECTRL_EEOP_READ); /* 2.4 Gz: Read EEPROM */
750 for (i=0; i<1000; ++i) { /* 2.4 Gz: wait for download */
751 DELAY(40); /* 2.4 Gz */
752 if ((wlmmcread(base,MMC_EECTRLstat) /* 2.4 Gz: check DWLD and */
753 &(MMC_EECTRLstat_DWLD /* 2.4 Gz: EEBUSY */
754 +MMC_EECTRLstat_EEBUSY))==0) /* 2.4 Gz: */
755 break; /* 2.4 Gz: download finished */
758 if_printf(&sc->wl_if,
759 "xmit pwr load failed\n");/* 2.4 Gz */
761 MMC_WRITE(MMC_ANALCTRL, /* 2.4 Gz: EXT ant+polarity */
762 MMC_ANALCTRL_ANTPOL + /* 2.4 Gz: */
763 MMC_ANALCTRL_EXTANT); /* 2.4 Gz: */
764 i=sc->chan24<<4; /* 2.4 Gz: position ch # */
765 MMC_WRITE(MMC_EEADDR,i); /* 2.4 Gz: get frequency */
766 MMC_WRITE(MMC_EECTRL, /* 2.4 Gz: EEPROM read */
767 MMC_EECTRL_EEOP_READ); /* 2.4 Gz: */
768 DELAY(40); /* 2.4 Gz */
769 i = wlmmcread(base,MMC_EEDATALrv) /* 2.4 Gz: freq val */
770 + (wlmmcread(base,MMC_EEDATAHrv)<<8); /* 2.4 Gz */
771 sc->freq24 = (i>>6)+2400; /* 2.4 Gz: save real freq */
778 * Another routine that interfaces the "if" layer to this driver.
779 * Simply resets the structures that are used by "upper layers".
780 * As well as calling wlhwrst that does reset the WaveLAN board.
782 * input : softc pointer for this interface
783 * output : structures (if structs) and board are reset
789 struct wl_softc *sc = xsc;
790 struct ifnet *ifp = &sc->wl_if;
794 if (ifp->if_flags & IFF_DEBUG)
795 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");
820 * This routine resets the WaveLAN board that corresponds to the
821 * board number passed in.
823 * input : softc pointer for this interface
824 * output : board is reset
828 wlhwrst(struct wl_softc *sc)
831 if (sc->wl_if.if_flags & IFF_DEBUG)
832 if_printf(&sc->wl_if, "entered wlhwrst()\n");
834 sc->hacr = HACR_RESET;
835 CMD(sc); /* reset the board */
837 /* clear reset command and set PIO#1 in autoincrement mode */
838 sc->hacr = HACR_DEFAULT;
842 if (sc->wl_if.if_flags & IFF_DEBUG)
843 wlmmcstat(sc); /* Display MMC registers */
845 wlbldcu(sc); /* set up command unit structures */
850 if (wlconfig(sc) == 0)
853 * insert code for loopback test here
855 wlrustrt(sc); /* start receive unit */
857 /* enable interrupts */
858 sc->hacr = (HACR_DEFAULT | HACR_INTRON);
867 * This function builds up the command unit structures. It inits
868 * the scp, iscp, scb, cb, tbd, and tbuf.
872 wlbldcu(struct wl_softc *sc)
874 short base = sc->base;
882 bzero(&scp, sizeof(scp));
884 scp.scp_iscp = OFFSET_ISCP;
885 scp.scp_iscp_base = 0;
886 outw(PIOR1(base), OFFSET_SCP);
887 outsw(PIOP1(base), &scp, sizeof(scp_t)/2);
889 bzero(&iscp, sizeof(iscp));
891 iscp.iscp_scb_offset = OFFSET_SCB;
893 iscp.iscp_scb_base = 0;
894 outw(PIOR1(base), OFFSET_ISCP);
895 outsw(PIOP1(base), &iscp, sizeof(iscp_t)/2);
898 scb.scb_command = SCB_RESET;
899 scb.scb_cbl_offset = OFFSET_CU;
900 scb.scb_rfa_offset = OFFSET_RU;
904 scb.scb_ovrnerrs = 0;
905 outw(PIOR1(base), OFFSET_SCB);
906 outsw(PIOP1(base), &scb, sizeof(scb_t)/2);
910 outw(PIOR0(base), OFFSET_ISCP + 0); /* address of iscp_busy */
911 for (i = 1000000; inw(PIOP0(base)) && (i-- > 0); );
912 if (i <= 0) if_printf(&sc->wl_if, "bldcu(): iscp_busy timeout.\n");
913 outw(PIOR0(base), OFFSET_SCB + 0); /* address of scb_status */
914 for (i = STATUS_TRIES; i-- > 0; ) {
915 if (inw(PIOP0(base)) == (SCB_SW_CX|SCB_SW_CNA))
919 if_printf(&sc->wl_if, "bldcu(): not ready after reset.\n");
923 cb.ac_command = AC_CW_EL; /* NOP */
924 cb.ac_link_offset = OFFSET_CU;
925 outw(PIOR1(base), OFFSET_CU);
926 outsw(PIOP1(base), &cb, 6/2);
929 tbd.next_tbd_offset = I82586NULL;
932 outw(PIOR1(base), OFFSET_TBD);
933 outsw(PIOP1(base), &tbd, sizeof(tbd_t)/2);
941 * input : pointer the appropriate "if" struct
942 * output : stuff sent to board if any there
946 wlstart(struct ifnet *ifp)
949 struct wl_softc *sc = ifp->if_softc;
950 short base = sc->base;
951 int scb_status, cu_status, scb_command;
954 if (ifp->if_flags & IFF_DEBUG)
955 if_printf(ifp, "entered wlstart()\n");
958 outw(PIOR1(base), OFFSET_CU);
959 cu_status = inw(PIOP1(base));
960 outw(PIOR0(base),OFFSET_SCB + 0); /* scb_status */
961 scb_status = inw(PIOP0(base));
962 outw(PIOR0(base), OFFSET_SCB + 2);
963 scb_command = inw(PIOP0(base));
966 * don't need OACTIVE check as tbusy here checks to see
967 * if we are already busy
970 if((scb_status & 0x0700) == SCB_CUS_IDLE &&
971 (cu_status & AC_SW_B) == 0){
973 callout_stop(&sc->watchdog_ch);
974 ifp->if_flags &= ~IFF_OACTIVE;
976 * This is probably just a race. The xmt'r is just
977 * became idle but WE have masked interrupts so ...
980 if_printf(ifp, "CU idle, scb %04x %04x cu %04x\n",
981 scb_status, scb_command, cu_status);
983 if (xmt_watch) if_printf(ifp, "!!\n");
985 return; /* genuinely still busy */
987 } else if((scb_status & 0x0700) == SCB_CUS_ACTV ||
988 (cu_status & AC_SW_B)){
990 if_printf(ifp, "CU unexpectedly busy; scb %04x cu %04x\n",
991 scb_status, cu_status);
993 if (xmt_watch) if_printf(ifp, "busy?!");
994 return; /* hey, why are we busy? */
997 /* get ourselves some data */
999 m = ifq_dequeue(&ifp->if_snd);
1003 /* set the watchdog timer so that if the board
1004 * fails to interrupt we will restart
1006 /* try 10 ticks, not very long */
1007 callout_reset(&sc->watchdog_ch, 10, wlwatchdog, sc);
1008 ifp->if_flags |= IFF_OACTIVE;
1012 ifp->if_flags &= ~IFF_OACTIVE;
1019 * This routine does the actual copy of data (including ethernet header
1020 * structure) from the WaveLAN to an mbuf chain that will be passed up
1021 * to the "if" (network interface) layer. NOTE: we currently
1022 * don't handle trailer protocols, so if that is needed, it will
1023 * (at least in part) be added here. For simplicities sake, this
1024 * routine copies the receive buffers from the board into a local (stack)
1025 * buffer until the frame has been copied from the board. Once in
1026 * the local buffer, the contents are copied to an mbuf chain that
1027 * is then enqueued onto the appropriate "if" queue.
1029 * input : softc pointer for this interface and
1030 * an frame descriptor address
1031 * output : the packet is put into an mbuf chain, and passed up
1032 * assumes : if any errors occur, packet is "dropped on the floor"
1036 wlread(struct wl_softc *sc, u_short fd_p)
1038 struct ifnet *ifp = &sc->wl_if;
1039 short base = sc->base;
1041 struct ether_header eh;
1042 struct mbuf *m, *tm;
1045 u_short mlen, len, clen;
1046 u_short bytes_in_msg, bytes_in_mbuf, bytes;
1050 if (ifp->if_flags & IFF_DEBUG)
1051 if_printf(ifp, "entered wlread()\n");
1053 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
1054 if_printf(ifp, "read(): board is not running.\n");
1055 sc->hacr &= ~HACR_INTRON;
1056 CMD(sc); /* turn off interrupts */
1058 /* read ether_header info out of device memory. doesn't
1059 * go into mbuf. goes directly into eh structure
1061 len = sizeof(struct ether_header); /* 14 bytes */
1062 outw(PIOR1(base), fd_p);
1063 insw(PIOP1(base), &fd, (sizeof(fd_t) - len)/2);
1064 insw(PIOP1(base), &eh, (len-2)/2);
1065 eh.ether_type = ntohs(inw(PIOP1(base)));
1067 if (ifp->if_flags & IFF_DEBUG)
1068 if_printf(ifp, "wlread: rcv packet, type is %x\n", eh.ether_type);
1071 * WARNING. above is done now in ether_input, above may be
1072 * useful for debug. jrb
1074 eh.ether_type = htons(eh.ether_type);
1076 if (fd.rbd_offset == I82586NULL) {
1077 if_printf(ifp, "read(): Invalid buffer\n");
1078 if (wlhwrst(sc) != TRUE)
1079 if_printf(ifp, "read(): hwrst trouble.\n");
1083 outw(PIOR1(base), fd.rbd_offset);
1084 insw(PIOP1(base), &rbd, sizeof(rbd_t)/2);
1085 bytes_in_msg = rbd.status & RBD_SW_COUNT;
1086 MGETHDR(m, MB_DONTWAIT, MT_DATA);
1088 if (m == (struct mbuf *)0) {
1090 * not only do we want to return, we need to drop the packet on
1091 * the floor to clear the interrupt.
1094 if (wlhwrst(sc) != TRUE) {
1095 sc->hacr &= ~HACR_INTRON;
1096 CMD(sc); /* turn off interrupts */
1097 if_printf(ifp, "read(): hwrst trouble.\n");
1101 m->m_next = (struct mbuf *) 0;
1102 m->m_pkthdr.rcvif = ifp;
1103 m->m_pkthdr.len = 0; /* don't know this yet */
1106 /* always use a cluster. jrb
1108 MCLGET(m, MB_DONTWAIT);
1109 if (m->m_flags & M_EXT) {
1110 m->m_len = MCLBYTES;
1114 if (wlhwrst(sc) != TRUE) {
1115 sc->hacr &= ~HACR_INTRON;
1116 CMD(sc); /* turn off interrupts */
1117 if_printf(ifp, "read(): hwrst trouble.\n");
1124 bytes_in_mbuf = m->m_len;
1125 mb_p = mtod(tm, u_char *);
1126 bytes = min(bytes_in_mbuf, bytes_in_msg);
1133 outw(PIOR1(base), rbd.buffer_addr);
1134 insw(PIOP1(base), mb_p, len/2);
1138 if (!(bytes_in_mbuf -= bytes)) {
1139 MGET(tm->m_next, MB_DONTWAIT, MT_DATA);
1141 if (tm == (struct mbuf *)0) {
1143 if_printf(ifp, "read(): No mbuf nth\n");
1144 if (wlhwrst(sc) != TRUE) {
1145 sc->hacr &= ~HACR_INTRON;
1146 CMD(sc); /* turn off interrupts */
1147 if_printf(ifp, "read(): hwrst trouble.\n");
1153 bytes_in_mbuf = MLEN;
1154 mb_p = mtod(tm, u_char *);
1159 if (!(bytes_in_msg -= bytes)) {
1160 if (rbd.status & RBD_SW_EOF ||
1161 rbd.next_rbd_offset == I82586NULL) {
1165 outw(PIOR1(base), rbd.next_rbd_offset);
1166 insw(PIOP1(base), &rbd, sizeof(rbd_t)/2);
1167 bytes_in_msg = rbd.status & RBD_SW_COUNT;
1170 rbd.buffer_addr += bytes;
1173 bytes = min(bytes_in_mbuf, bytes_in_msg);
1176 m->m_pkthdr.len = clen;
1179 * If hw is in promiscuous mode (note that I said hardware, not if
1180 * IFF_PROMISC is set in ifnet flags), then if this is a unicast
1181 * packet and the MAC dst is not us, drop it. This check in normally
1182 * inside ether_input(), but IFF_MULTI causes hw promisc without
1183 * a bpf listener, so this is wrong.
1184 * Greg Troxel <gdt@ir.bbn.com>, 1998-08-07
1187 * TBD: also discard packets where NWID does not match.
1188 * However, there does not appear to be a way to read the nwid
1189 * for a received packet. -gdt 1998-08-07
1192 #ifdef WL_USE_IFNET_PROMISC_CHECK /* not defined */
1193 (ifp->if_flags & (IFF_PROMISC|IFF_ALLMULTI))
1195 /* hw is in promisc mode if this is true */
1196 (sc->mode & (MOD_PROM | MOD_ENAL))
1199 (eh.ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */
1200 bcmp(eh.ether_dhost, sc->wl_ac.ac_enaddr,
1201 sizeof(eh.ether_dhost)) != 0 ) {
1207 if (ifp->if_flags & IFF_DEBUG)
1208 if_printf(ifp, "wlrecv %d bytes\n", clen);
1212 wl_cache_store(sc, base, &eh, m);
1216 * received packet is now in a chain of mbuf's. next step is
1217 * to pass the packet upwards.
1220 ether_input(ifp, &eh, m);
1227 * This routine processes an ioctl request from the "if" layer
1230 * input : pointer the appropriate "if" struct, command and data
1231 * output : based on command appropriate action is taken on the
1232 * WaveLAN board(s) or related structures
1233 * return : error is returned containing exit conditions
1237 wlioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cred)
1239 struct ifreq *ifr = (struct ifreq *)data;
1240 struct wl_softc *sc = ifp->if_softc;
1241 short base = sc->base;
1244 int irq, irqval, i, isroot, size;
1247 struct thread *td = curthread; /* XXX */
1251 if (ifp->if_flags & IFF_DEBUG)
1252 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 printf 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);
1490 * Called if the timer set in wlstart expires before an interrupt is received
1491 * from the wavelan. It seems to lose interrupts sometimes.
1492 * The watchdog routine gets called if the transmitter failed to interrupt
1494 * input : which board is timing out
1495 * output : board reset
1499 wlwatchdog(void *vsc)
1501 struct wl_softc *sc = vsc;
1503 log(LOG_ERR, "%s: wavelan device timeout on xmit\n", sc->wl_if.if_xname);
1504 sc->wl_if.if_oerrors++;
1511 * This function is the interrupt handler for the WaveLAN
1512 * board. This routine will be called whenever either a packet
1513 * is received, or a packet has successfully been transfered and
1514 * the unit is ready to transmit another packet.
1516 * input : softc pointer for this interface
1517 * output : either a packet is received, or a packet is transfered
1523 struct wl_softc *sc = arg;
1524 struct ifnet *ifp = &sc->wl_if;
1525 short base = sc->base;
1527 u_short int_type, int_type1;
1530 if (ifp->if_flags & IFF_DEBUG)
1531 if_printf(ifp, "wlintr() called\n");
1534 if((int_type = inw(HASR(base))) & HASR_MMC_INTR) {
1535 /* handle interrupt from the modem management controler */
1536 /* This will clear the interrupt condition */
1537 (void) wlmmcread(base,MMC_DCE_STATUS); /* ignored for now */
1540 if(!(int_type & HASR_INTR)){ /* return if no interrupt from 82586 */
1541 /* commented out. jrb. it happens when reinit occurs
1542 if_printf(ifp, "%s: int_type %x, dump follows\n",
1543 __func__, int_type);
1552 outw(PIOR0(base), OFFSET_SCB + 0); /* get scb status */
1553 int_type = (inw(PIOP0(base)) & SCB_SW_INT);
1554 if (int_type == 0) /* no interrupts left */
1557 int_type1 = wlack(sc); /* acknowledge interrupt(s) */
1558 /* make sure no bits disappeared (others may appear) */
1559 if ((int_type & int_type1) != int_type) {
1560 if_printf(ifp, "wlack() int bits disappeared: "
1561 "%04x != int_type %04x\n", int_type1, int_type);
1563 int_type = int_type1; /* go with the new status */
1567 if (int_type & SCB_SW_FR) {
1572 * receiver not ready
1574 if (int_type & SCB_SW_RNR) {
1577 if (ifp->if_flags & IFF_DEBUG) {
1578 if_printf(ifp, "intr(): receiver overrun! begin_fd = %x\n",
1587 if (int_type & SCB_SW_CNA) {
1589 * At present, we don't care about CNA's. We
1590 * believe they are a side effect of XMT.
1593 if (int_type & SCB_SW_CX) {
1595 * At present, we only request Interrupt for
1598 outw(PIOR1(base), OFFSET_CU); /* get command status */
1599 ac_status = inw(PIOP1(base));
1601 if (xmt_watch) { /* report some anomalies */
1603 if (sc->tbusy == 0) {
1604 if_printf(ifp, "xmt intr but not busy, CU %04x\n",
1607 if (ac_status == 0) {
1608 if_printf(ifp, "xmt intr but ac_status == 0\n");
1610 if (ac_status & AC_SW_A) {
1611 if_printf(ifp, "xmt aborted\n");
1614 if (ac_status & TC_CARRIER) {
1615 if_printf(ifp, "no carrier\n");
1618 if (ac_status & TC_CLS) {
1619 if_printf(ifp, "no CTS\n");
1621 if (ac_status & TC_DMA) {
1622 if_printf(ifp, "DMA underrun\n");
1624 if (ac_status & TC_DEFER) {
1625 if_printf(ifp, "xmt deferred\n");
1627 if (ac_status & TC_SQE) {
1628 if_printf(ifp, "heart beat\n");
1630 if (ac_status & TC_COLLISION) {
1631 if_printf(ifp, "too many collisions\n");
1634 /* if the transmit actually failed, or returned some status */
1635 if ((!(ac_status & AC_SW_OK)) || (ac_status & 0xfff)) {
1636 if (ac_status & (TC_COLLISION | TC_CLS | TC_DMA)) {
1640 /* count collisions */
1641 ifp->if_collisions += (ac_status & 0xf);
1642 /* if TC_COLLISION set and collision count zero, 16 collisions */
1643 if ((ac_status & 0x20) == 0x20) {
1644 ifp->if_collisions += 0x10;
1648 callout_stop(&sc->watchdog_ch);
1649 ifp->if_flags &= ~IFF_OACTIVE;
1658 * This routine is called by the interrupt handler to initiate a
1659 * packet transfer from the board to the "if" layer above this
1660 * driver. This routine checks if a buffer has been successfully
1661 * received by the WaveLAN. If so, the routine wlread is called
1662 * to do the actual transfer of the board data (including the
1663 * ethernet header) into a packet (consisting of an mbuf chain).
1665 * input : softc pointer for this interface
1666 * output : if a packet is available, it is "sent up"
1670 wlrcv(struct wl_softc *sc)
1672 short base = sc->base;
1673 u_short fd_p, status, offset, link_offset;
1676 if (sc->wl_if.if_flags & IFF_DEBUG)
1677 if_printf(&sc->wl_if, "entered wlrcv()\n");
1679 for (fd_p = sc->begin_fd; fd_p != I82586NULL; fd_p = sc->begin_fd) {
1681 outw(PIOR0(base), fd_p + 0); /* address of status */
1682 status = inw(PIOP0(base));
1683 outw(PIOR1(base), fd_p + 4); /* address of link_offset */
1684 link_offset = inw(PIOP1(base));
1685 offset = inw(PIOP1(base)); /* rbd_offset */
1686 if (status == 0xffff || offset == 0xffff /*I82586NULL*/) {
1687 if (wlhwrst(sc) != TRUE)
1688 if_printf(&sc->wl_if, "rcv(): hwrst ffff trouble.\n");
1690 } else if (status & AC_SW_C) {
1691 if (status == (RFD_DONE|RFD_RSC)) {
1694 if (sc->wl_if.if_flags & IFF_DEBUG)
1695 if_printf(&sc->wl_if, "RCV: RSC %x\n", status);
1697 sc->wl_if.if_ierrors++;
1698 } else if (!(status & RFD_OK)) {
1699 if_printf(&sc->wl_if, "RCV: !OK %x\n", status);
1700 sc->wl_if.if_ierrors++;
1701 } else if (status & 0xfff) { /* can't happen */
1702 if_printf(&sc->wl_if, "RCV: ERRs %x\n", status);
1703 sc->wl_if.if_ierrors++;
1704 } else if (!wlread(sc, fd_p))
1707 if (!wlrequeue(sc, fd_p)) {
1708 /* abort on chain error */
1709 if (wlhwrst(sc) != TRUE)
1710 if_printf(&sc->wl_if, "rcv(): hwrst trouble.\n");
1713 sc->begin_fd = link_offset;
1723 * This routine puts rbd's used in the last receive back onto the
1724 * free list for the next receive.
1728 wlrequeue(struct wl_softc *sc, u_short fd_p)
1730 short base = sc->base;
1732 u_short l_rbdp, f_rbdp, rbd_offset;
1734 outw(PIOR0(base), fd_p + 6);
1735 rbd_offset = inw(PIOP0(base));
1736 if ((f_rbdp = rbd_offset) != I82586NULL) {
1739 outw(PIOR0(base), l_rbdp + 0); /* address of status */
1740 if(inw(PIOP0(base)) & RBD_SW_EOF)
1742 outw(PIOP0(base), 0);
1743 outw(PIOR0(base), l_rbdp + 2); /* next_rbd_offset */
1744 if((l_rbdp = inw(PIOP0(base))) == I82586NULL)
1747 outw(PIOP0(base), 0);
1748 outw(PIOR0(base), l_rbdp + 2); /* next_rbd_offset */
1749 outw(PIOP0(base), I82586NULL);
1750 outw(PIOR0(base), l_rbdp + 8); /* address of size */
1751 outw(PIOP0(base), inw(PIOP0(base)) | AC_CW_EL);
1752 outw(PIOR0(base), sc->end_rbd + 2);
1753 outw(PIOP0(base), f_rbdp); /* end_rbd->next_rbd_offset */
1754 outw(PIOR0(base), sc->end_rbd + 8); /* size */
1755 outw(PIOP0(base), inw(PIOP0(base)) & ~AC_CW_EL);
1756 sc->end_rbd = l_rbdp;
1760 fd.command = AC_CW_EL;
1761 fd.link_offset = I82586NULL;
1762 fd.rbd_offset = I82586NULL;
1763 outw(PIOR1(base), fd_p);
1764 outsw(PIOP1(base), &fd, 8/2);
1766 outw(PIOR1(base), sc->end_fd + 2); /* addr of command */
1767 outw(PIOP1(base), 0); /* command = 0 */
1768 outw(PIOP1(base), fd_p); /* end_fd->link_offset = fd_p */
1775 static int xmt_debug = 0;
1776 #endif /* WLDEBUG */
1781 * This routine fills in the appropriate registers and memory
1782 * locations on the WaveLAN board and starts the board off on
1785 * input : softc pointer for this interface, and a pointer to the mbuf
1786 * output : board memory and registers are set for xfer and attention
1790 wlxmt(struct wl_softc *sc, struct mbuf *m)
1792 u_short xmtdata_p = OFFSET_TBUF;
1794 struct mbuf *tm_p = m;
1795 struct ether_header *eh_p = mtod(m, struct ether_header *);
1796 u_char *mb_p = mtod(m, u_char *) + sizeof(struct ether_header);
1797 u_short count = m->m_len - sizeof(struct ether_header);
1799 u_short tbd_p = OFFSET_TBD;
1800 u_short len, clen = 0;
1801 short base = sc->base;
1805 if (sc->wl_if.if_flags & IFF_DEBUG)
1806 if_printf(&sc->wl_if, "entered wlxmt()\n");
1810 cb.ac_command = (AC_CW_EL|AC_TRANSMIT|AC_CW_I);
1811 cb.ac_link_offset = I82586NULL;
1812 outw(PIOR1(base), OFFSET_CU);
1813 outsw(PIOP1(base), &cb, 6/2);
1814 outw(PIOP1(base), OFFSET_TBD); /* cb.cmd.transmit.tbd_offset */
1815 outsw(PIOP1(base), eh_p->ether_dhost, WAVELAN_ADDR_SIZE/2);
1816 outw(PIOP1(base), eh_p->ether_type);
1819 if (sc->wl_if.if_flags & IFF_DEBUG) {
1821 if_printf(&sc->wl_if, "XMT mbuf: L%d @%p ", count, (void *)mb_p);
1822 printf("ether type %x\n", eh_p->ether_type);
1825 #endif /* WLDEBUG */
1826 outw(PIOR0(base), OFFSET_TBD);
1827 outw(PIOP0(base), 0); /* act_count */
1828 outw(PIOR1(base), OFFSET_TBD + 4);
1829 outw(PIOP1(base), xmtdata_p); /* buffer_addr */
1830 outw(PIOP1(base), 0); /* buffer_base */
1833 if (clen + count > WAVELAN_MTU)
1839 outw(PIOR1(base), xmtdata_p);
1840 outsw(PIOP1(base), mb_p, len/2);
1842 outw(PIOR0(base), tbd_p); /* address of act_count */
1843 outw(PIOP0(base), inw(PIOP0(base)) + count);
1845 if ((tm_p = tm_p->m_next) == (struct mbuf *)0)
1848 /* go to the next descriptor */
1849 outw(PIOR0(base), tbd_p + 2);
1850 tbd_p += sizeof (tbd_t);
1851 outw(PIOP0(base), tbd_p); /* next_tbd_offset */
1852 outw(PIOR0(base), tbd_p);
1853 outw(PIOP0(base), 0); /* act_count */
1854 outw(PIOR1(base), tbd_p + 4);
1855 outw(PIOP1(base), xmtdata_p); /* buffer_addr */
1856 outw(PIOP1(base), 0); /* buffer_base */
1857 /* at the end -> coallesce remaining mbufs */
1858 if (tbd_p == OFFSET_TBD + (N_TBD-1) * sizeof (tbd_t)) {
1859 wlsftwsleaze(&count, &mb_p, &tm_p);
1862 /* next mbuf short -> coallesce as needed */
1863 if ( (tm_p->m_next == (struct mbuf *) 0) ||
1864 #define HDW_THRESHOLD 55
1865 tm_p->m_len > HDW_THRESHOLD)
1868 wlhdwsleaze(&count, &mb_p, &tm_p);
1872 } else if ((tm_p = tm_p->m_next) == (struct mbuf *)0)
1874 count = tm_p->m_len;
1875 mb_p = mtod(tm_p, u_char *);
1877 if (sc->wl_if.if_flags & IFF_DEBUG)
1879 if_printf(&sc->wl_if, "mbuf+ L%d @%p ", count, (void *)mb_p);
1880 #endif /* WLDEBUG */
1883 if (sc->wl_if.if_flags & IFF_DEBUG)
1885 if_printf(&sc->wl_if, "CLEN = %d\n", clen);
1886 #endif /* WLDEBUG */
1887 outw(PIOR0(base), tbd_p);
1888 if (clen < ETHERMIN) {
1889 outw(PIOP0(base), inw(PIOP0(base)) + ETHERMIN - clen);
1890 outw(PIOR1(base), xmtdata_p);
1891 for (xmtshort_p = xmtdata_p; clen < ETHERMIN; clen += 2)
1892 outw(PIOP1(base), 0);
1894 outw(PIOP0(base), inw(PIOP0(base)) | TBD_SW_EOF);
1895 outw(PIOR0(base), tbd_p + 2);
1896 outw(PIOP0(base), I82586NULL);
1898 if (sc->wl_if.if_flags & IFF_DEBUG) {
1904 #endif /* WLDEBUG */
1906 outw(PIOR0(base), OFFSET_SCB + 2); /* address of scb_command */
1908 * wait for 586 to clear previous command, complain if it takes
1911 for (spin = 1;;spin = (spin + 1) % 10000) {
1912 if (inw(PIOP0(base)) == 0) { /* it's done, we can go */
1915 if ((spin == 0) && xmt_watch) { /* not waking up, and we care */
1916 if_printf(&sc->wl_if, "slow accepting xmit\n");
1919 outw(PIOP0(base), SCB_CU_STRT); /* new command */
1925 * Pause to avoid transmit overrun problems.
1926 * The required delay tends to vary with platform type, and may be
1927 * related to interrupt loss.
1929 if (wl_xmit_delay) {
1930 DELAY(wl_xmit_delay);
1937 * This function builds the linear linked lists of fd's and
1938 * rbd's. Based on page 4-32 of 1986 Intel microcom handbook.
1942 wlbldru(struct wl_softc *sc)
1944 short base = sc->base;
1947 u_short fd_p = OFFSET_RU;
1948 u_short rbd_p = OFFSET_RBD;
1951 sc->begin_fd = fd_p;
1952 for(i = 0; i < N_FD; i++) {
1955 fd.link_offset = fd_p + sizeof(fd_t);
1956 fd.rbd_offset = I82586NULL;
1957 outw(PIOR1(base), fd_p);
1958 outsw(PIOP1(base), &fd, 8/2);
1959 fd_p = fd.link_offset;
1961 fd_p -= sizeof(fd_t);
1963 outw(PIOR1(base), fd_p + 2);
1964 outw(PIOP1(base), AC_CW_EL); /* command */
1965 outw(PIOP1(base), I82586NULL); /* link_offset */
1968 outw(PIOR0(base), fd_p + 6); /* address of rbd_offset */
1969 outw(PIOP0(base), rbd_p);
1970 outw(PIOR1(base), rbd_p);
1971 for(i = 0; i < N_RBD; i++) {
1973 rbd.buffer_addr = rbd_p + sizeof(rbd_t) + 2;
1974 rbd.buffer_base = 0;
1975 rbd.size = RCVBUFSIZE;
1977 rbd_p += sizeof(ru_t);
1978 rbd.next_rbd_offset = rbd_p;
1980 rbd.next_rbd_offset = I82586NULL;
1981 rbd.size |= AC_CW_EL;
1982 sc->end_rbd = rbd_p;
1984 outsw(PIOP1(base), &rbd, sizeof(rbd_t)/2);
1985 outw(PIOR1(base), rbd_p);
1987 return sc->begin_fd;
1993 * This routine starts the receive unit running. First checks if the
1994 * board is actually ready, then the board is instructed to receive
1999 wlrustrt(struct wl_softc *sc)
2001 short base = sc->base;
2005 if (sc->wl_if.if_flags & IFF_DEBUG)
2006 if_printf(&sc->wl_if, "entered wlrustrt()\n");
2008 outw(PIOR0(base), OFFSET_SCB);
2009 if (inw(PIOP0(base)) & SCB_RUS_READY){
2010 if_printf(&sc->wl_if, "wlrustrt: RUS_READY\n");
2014 outw(PIOR0(base), OFFSET_SCB + 2);
2015 outw(PIOP0(base), SCB_RU_STRT); /* command */
2017 outw(PIOR0(base), OFFSET_SCB + 6); /* address of scb_rfa_offset */
2018 outw(PIOP0(base), rfa);
2026 * This routine does a 586 op-code number 7, and obtains the
2027 * diagnose status for the WaveLAN.
2031 wldiag(struct wl_softc *sc)
2033 short base = sc->base;
2037 if (sc->wl_if.if_flags & IFF_DEBUG)
2038 if_printf(&sc->wl_if, "entered wldiag()\n");
2040 outw(PIOR0(base), OFFSET_SCB);
2041 status = inw(PIOP0(base));
2042 if (status & SCB_SW_INT) {
2043 /* state is 2000 which seems ok
2044 if_printf(&sc->wl_if, "diag(): unexpected initial state %\n",
2049 outw(PIOR1(base), OFFSET_CU);
2050 outw(PIOP1(base), 0); /* ac_status */
2051 outw(PIOP1(base), AC_DIAGNOSE|AC_CW_EL);/* ac_command */
2052 if(wlcmd(sc, "diag()") == 0)
2054 outw(PIOR0(base), OFFSET_CU);
2055 if (inw(PIOP0(base)) & 0x0800) {
2056 if_printf(&sc->wl_if, "i82586 Self Test failed!\n");
2065 * This routine does a standard config of the WaveLAN board.
2069 wlconfig(struct wl_softc *sc)
2071 configure_t configure;
2072 short base = sc->base;
2075 #if defined(__DragonFly__) || (defined(__FreeBSD__) && __FreeBSD_version >= 300000)
2076 struct ifmultiaddr *ifma;
2079 struct ether_multi *enm;
2080 struct ether_multistep step;
2083 #endif /* MULTICAST */
2086 if (sc->wl_if.if_flags & IFF_DEBUG)
2087 if_printf(&sc->wl_if, "entered wlconfig()\n");
2089 outw(PIOR0(base), OFFSET_SCB);
2090 if (inw(PIOP0(base)) & SCB_SW_INT) {
2092 if_printf(&sc->wl_if, "config(): unexpected initial state %x\n",
2098 outw(PIOR1(base), OFFSET_CU);
2099 outw(PIOP1(base), 0); /* ac_status */
2100 outw(PIOP1(base), AC_CONFIGURE|AC_CW_EL); /* ac_command */
2103 configure.fifolim_bytecnt = 0x080c;
2104 configure.addrlen_mode = 0x0600;
2105 configure.linprio_interframe = 0x2060;
2106 configure.slot_time = 0xf200;
2107 configure.hardware = 0x0008; /* tx even w/o CD */
2108 configure.min_frame_len = 0x0040;
2110 /* This is the configuration block suggested by Marc Meertens
2111 * <mmeerten@obelix.utrecht.NCR.COM> in an e-mail message to John
2112 * Ioannidis on 10 Nov 92.
2114 configure.fifolim_bytecnt = 0x040c;
2115 configure.addrlen_mode = 0x0600;
2116 configure.linprio_interframe = 0x2060;
2117 configure.slot_time = 0xf000;
2118 configure.hardware = 0x0008; /* tx even w/o CD */
2119 configure.min_frame_len = 0x0040;
2122 * below is the default board configuration from p2-28 from 586 book
2124 configure.fifolim_bytecnt = 0x080c;
2125 configure.addrlen_mode = 0x2600;
2126 configure.linprio_interframe = 0x7820; /* IFS=120, ACS=2 */
2127 configure.slot_time = 0xf00c; /* slottime=12 */
2128 configure.hardware = 0x0008; /* tx even w/o CD */
2129 configure.min_frame_len = 0x0040;
2131 if(sc->mode & (MOD_PROM | MOD_ENAL)) {
2132 configure.hardware |= 1;
2134 outw(PIOR1(base), OFFSET_CU + 6);
2135 outsw(PIOP1(base), &configure, sizeof(configure_t)/2);
2137 if(wlcmd(sc, "config()-configure") == 0)
2140 outw(PIOR1(base), OFFSET_CU);
2141 outw(PIOP1(base), 0); /* ac_status */
2142 outw(PIOP1(base), AC_MCSETUP|AC_CW_EL); /* ac_command */
2143 outw(PIOR1(base), OFFSET_CU + 8);
2144 #if defined(__DragonFly__) || (defined(__FreeBSD__) && __FreeBSD_version >= 300000)
2145 LIST_FOREACH(ifma, &sc->wl_if.if_multiaddrs, ifma_link) {
2146 if (ifma->ifma_addr->sa_family != AF_LINK)
2149 addrp = LLADDR((struct sockaddr_dl *)ifma->ifma_addr);
2150 outw(PIOP1(base), addrp[0] + (addrp[1] << 8));
2151 outw(PIOP1(base), addrp[2] + (addrp[3] << 8));
2152 outw(PIOP1(base), addrp[4] + (addrp[5] << 8));
2156 ETHER_FIRST_MULTI(step, &sc->wl_ac, enm);
2157 while (enm != NULL) {
2158 unsigned int lo, hi;
2159 /* break if setting a multicast range, else we would crash */
2160 if (bcmp(enm->enm_addrlo, enm->enm_addrhi, 6) != 0) {
2163 lo = (enm->enm_addrlo[3] << 16) + (enm->enm_addrlo[4] << 8)
2164 + enm->enm_addrlo[5];
2165 hi = (enm->enm_addrhi[3] << 16) + (enm->enm_addrhi[4] << 8)
2166 + enm->enm_addrhi[5];
2168 outw(PIOP1(base),enm->enm_addrlo[0] +
2169 (enm->enm_addrlo[1] << 8));
2170 outw(PIOP1(base),enm->enm_addrlo[2] +
2171 ((lo >> 8) & 0xff00));
2172 outw(PIOP1(base), ((lo >> 8) & 0xff) +
2173 ((lo << 8) & 0xff00));
2174 /* #define MCASTDEBUG */
2176 printf("mcast_addr[%d,%d,%d] %x %x %x %x %x %x\n", lo, hi, cnt,
2182 enm->enm_addrlo[5]);
2187 ETHER_NEXT_MULTI(step, enm);
2190 outw(PIOR1(base), OFFSET_CU + 6); /* mc-cnt */
2191 outw(PIOP1(base), cnt * WAVELAN_ADDR_SIZE);
2192 if(wlcmd(sc, "config()-mcaddress") == 0)
2194 #endif /* MULTICAST */
2196 outw(PIOR1(base), OFFSET_CU);
2197 outw(PIOP1(base), 0); /* ac_status */
2198 outw(PIOP1(base), AC_IASETUP|AC_CW_EL); /* ac_command */
2199 outw(PIOR1(base), OFFSET_CU + 6);
2200 outsw(PIOP1(base), sc->wl_addr, WAVELAN_ADDR_SIZE/2);
2202 if(wlcmd(sc, "config()-address") == 0)
2213 * Set channel attention bit and busy wait until command has
2214 * completed. Then acknowledge the command completion.
2217 wlcmd(struct wl_softc *sc, const char *str)
2219 short base = sc->base;
2222 outw(PIOR0(base), OFFSET_SCB + 2); /* address of scb_command */
2223 outw(PIOP0(base), SCB_CU_STRT);
2227 outw(PIOR0(base), OFFSET_CU);
2228 for(i = 0; i < 0xffff; i++)
2229 if (inw(PIOP0(base)) & AC_SW_C)
2231 if (i == 0xffff || !(inw(PIOP0(base)) & AC_SW_OK)) {
2232 if_printf(&sc->wl_if, "%s failed; status = %d, inw = %x, outw = %x\n",
2233 str, inw(PIOP0(base)) & AC_SW_OK, inw(PIOP0(base)),
2235 outw(PIOR0(base), OFFSET_SCB);
2236 printf("scb_status %x\n", inw(PIOP0(base)));
2237 outw(PIOR0(base), OFFSET_SCB+2);
2238 printf("scb_command %x\n", inw(PIOP0(base)));
2239 outw(PIOR0(base), OFFSET_SCB+4);
2240 printf("scb_cbl %x\n", inw(PIOP0(base)));
2241 outw(PIOR0(base), OFFSET_CU+2);
2242 printf("cu_cmd %x\n", inw(PIOP0(base)));
2246 outw(PIOR0(base), OFFSET_SCB);
2247 if ((inw(PIOP0(base)) & SCB_SW_INT) && (inw(PIOP0(base)) != SCB_SW_CNA)) {
2249 if_printf(&sc->wl_if, "%s: unexpected final state %x\n",
2250 str, inw(PIOP0(base)));
2258 * wlack: if the 82596 wants attention because it has finished
2259 * sending or receiving a packet, acknowledge its desire and
2260 * return bits indicating the kind of attention. wlack() returns
2261 * these bits so that the caller can service exactly the
2262 * conditions that wlack() acknowledged.
2265 wlack(struct wl_softc *sc)
2269 short base = sc->base;
2271 outw(PIOR1(base), OFFSET_SCB);
2272 if(!(cmd = (inw(PIOP1(base)) & SCB_SW_INT)))
2275 if (sc->wl_if.if_flags & IFF_DEBUG)
2276 if_printf(&sc->wl_if, "doing a wlack()\n");
2278 outw(PIOP1(base), cmd);
2280 outw(PIOR0(base), OFFSET_SCB + 2); /* address of scb_command */
2281 for (i = 1000000; inw(PIOP0(base)) && (i-- > 0); );
2283 if_printf(&sc->wl_if, "wlack(): board not accepting command.\n");
2288 wltbd(struct wl_softc *sc)
2290 short base = sc->base;
2291 u_short tbd_p = OFFSET_TBD;
2297 outw(PIOR1(base), tbd_p);
2298 insw(PIOP1(base), &tbd, sizeof(tbd_t)/2);
2299 sum += (tbd.act_count & ~TBD_SW_EOF);
2300 printf("%d: addr %x, count %d (%d), next %x, base %x\n",
2301 i++, tbd.buffer_addr,
2302 (tbd.act_count & ~TBD_SW_EOF), sum,
2303 tbd.next_tbd_offset, tbd.buffer_base);
2304 if (tbd.act_count & TBD_SW_EOF)
2306 tbd_p = tbd.next_tbd_offset;
2311 wlhdwsleaze(u_short *countp, u_char **mb_pp, struct mbuf **tm_pp)
2313 struct mbuf *tm_p = *tm_pp;
2314 u_char *mb_p = *mb_pp;
2320 * can we get a run that will be coallesced or
2321 * that terminates before breaking
2324 count += tm_p->m_len;
2325 if (tm_p->m_len & 1)
2327 } while ((tm_p = tm_p->m_next) != (struct mbuf *)0);
2328 if ( (tm_p == (struct mbuf *)0) ||
2329 count > HDW_THRESHOLD) {
2330 *countp = (*tm_pp)->m_len;
2331 *mb_pp = mtod((*tm_pp), u_char *);
2335 /* we need to copy */
2339 cp = (u_char *) t_packet;
2341 bcopy(mtod(tm_p, u_char *), cp, len = tm_p->m_len);
2343 if (count > HDW_THRESHOLD)
2346 if (tm_p->m_next == (struct mbuf *)0)
2348 tm_p = tm_p->m_next;
2351 *mb_pp = (u_char *) t_packet;
2356 wlsftwsleaze(u_short *countp, u_char **mb_pp, struct mbuf **tm_pp)
2358 struct mbuf *tm_p = *tm_pp;
2360 u_char *cp = (u_char *) t_packet;
2363 /* we need to copy */
2365 bcopy(mtod(tm_p, u_char *), cp, len = tm_p->m_len);
2368 if (tm_p->m_next == (struct mbuf *)0)
2370 tm_p = tm_p->m_next;
2374 *mb_pp = (u_char *) t_packet;
2379 wlmmcstat(struct wl_softc *sc)
2381 short base = sc->base;
2384 if_printf(&sc->wl_if, "DCE_STATUS: 0x%x, ",
2385 wlmmcread(base,MMC_DCE_STATUS) & 0x0f);
2386 tmp = wlmmcread(base,MMC_CORRECT_NWID_H) << 8;
2387 tmp |= wlmmcread(base,MMC_CORRECT_NWID_L);
2388 printf("Correct NWID's: %d, ", tmp);
2389 tmp = wlmmcread(base,MMC_WRONG_NWID_H) << 8;
2390 tmp |= wlmmcread(base,MMC_WRONG_NWID_L);
2391 printf("Wrong NWID's: %d\n", tmp);
2392 printf("THR_PRE_SET: 0x%x, ", wlmmcread(base,MMC_THR_PRE_SET));
2393 printf("SIGNAL_LVL: %d, SILENCE_LVL: %d\n",
2394 wlmmcread(base,MMC_SIGNAL_LVL),
2395 wlmmcread(base,MMC_SILENCE_LVL));
2396 printf("SIGN_QUAL: 0x%x, NETW_ID: %x:%x, DES: %d\n",
2397 wlmmcread(base,MMC_SIGN_QUAL),
2398 wlmmcread(base,MMC_NETW_ID_H),
2399 wlmmcread(base,MMC_NETW_ID_L),
2400 wlmmcread(base,MMC_DES_AVAIL));
2404 wlmmcread(u_int base, u_short reg)
2406 while(inw(HASR(base)) & HASR_MMC_BUSY) ;
2407 outw(MMCR(base),reg << 1);
2408 while(inw(HASR(base)) & HASR_MMC_BUSY) ;
2409 return (u_short)inw(MMCR(base)) >> 8;
2413 getsnr(struct wl_softc *sc)
2415 MMC_WRITE(MMC_FREEZE,1);
2417 * SNR retrieval procedure :
2419 * read signal level : wlmmcread(base, MMC_SIGNAL_LVL);
2420 * read silence level : wlmmcread(base, MMC_SILENCE_LVL);
2422 MMC_WRITE(MMC_FREEZE,0);
2424 * SNR is signal:silence ratio.
2431 ** Reads the psa for the wavelan at (base) into (buf)
2434 wlgetpsa(int base, u_char *buf)
2438 PCMD(base, HACR_DEFAULT & ~HACR_16BITS);
2439 PCMD(base, HACR_DEFAULT & ~HACR_16BITS);
2441 for (i = 0; i < 0x40; i++) {
2442 outw(PIOR2(base), i);
2443 buf[i] = inb(PIOP2(base));
2445 PCMD(base, HACR_DEFAULT);
2446 PCMD(base, HACR_DEFAULT);
2452 ** Writes the psa for wavelan (unit) from the softc back to the
2453 ** board. Updates the CRC and sets the CRC OK flag.
2455 ** Do not call this when the board is operating, as it doesn't
2456 ** preserve the hacr.
2459 wlsetpsa(struct wl_softc *sc)
2461 short base = sc->base;
2465 crc = wlpsacrc(sc->psa); /* calculate CRC of PSA */
2466 sc->psa[WLPSA_CRCLOW] = crc & 0xff;
2467 sc->psa[WLPSA_CRCHIGH] = (crc >> 8) & 0xff;
2468 sc->psa[WLPSA_CRCOK] = 0x55; /* default to 'bad' until programming complete */
2470 crit_enter(); /* ick, long pause */
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);
2495 ** CRC routine provided by Christopher Giordano <cgiordan@gdeb.com>,
2496 ** from original code by Tomi Mikkonen (tomitm@remedy.fi)
2499 static u_int crc16_table[16] = {
2500 0x0000, 0xCC01, 0xD801, 0x1400,
2501 0xF001, 0x3C00, 0x2800, 0xE401,
2502 0xA001, 0x6C00, 0x7800, 0xB401,
2503 0x5000, 0x9C01, 0x8801, 0x4400
2507 wlpsacrc(u_char *buf)
2512 for (i = 0; i < 0x3d; i++, buf++) {
2514 r1 = crc16_table[crc & 0xF];
2515 crc = (crc >> 4) & 0x0FFF;
2516 crc = crc ^ r1 ^ crc16_table[*buf & 0xF];
2519 r1 = crc16_table[crc & 0xF];
2520 crc = (crc >> 4) & 0x0FFF;
2521 crc = crc ^ r1 ^ crc16_table[(*buf >> 4) & 0xF];
2530 * take input packet and cache various radio hw characteristics
2531 * indexed by MAC address.
2533 * Some things to think about:
2534 * note that no space is malloced.
2535 * We might hash the mac address if the cache were bigger.
2536 * It is not clear that the cache is big enough.
2537 * It is also not clear how big it should be.
2538 * The cache is IP-specific. We don't care about that as
2539 * we want it to be IP-specific.
2540 * The last N recv. packets are saved. This will tend
2541 * to reward agents and mobile hosts that beacon.
2542 * That is probably fine for mobile ip.
2545 /* globals for wavelan signal strength cache */
2546 /* this should go into softc structure above.
2549 /* set true if you want to limit cache items to broadcast/mcast
2550 * only packets (not unicast)
2552 static int wl_cache_mcastonly = 1;
2553 SYSCTL_INT(_machdep, OID_AUTO, wl_cache_mcastonly, CTLFLAG_RW,
2554 &wl_cache_mcastonly, 0, "");
2556 /* set true if you want to limit cache items to IP packets only
2558 static int wl_cache_iponly = 1;
2559 SYSCTL_INT(_machdep, OID_AUTO, wl_cache_iponly, CTLFLAG_RW,
2560 &wl_cache_iponly, 0, "");
2562 /* zero out the cache
2565 wl_cache_zero(struct wl_softc *sc)
2567 bzero(&sc->w_sigcache[0], sizeof(struct w_sigcache) * MAXCACHEITEMS);
2569 sc->w_nextcache = 0;
2570 sc->w_wrapindex = 0;
2573 /* store hw signal info in cache.
2574 * index is MAC address, but an ip src gets stored too
2575 * There are two filters here controllable via sysctl:
2576 * throw out unicast (on by default, but can be turned off)
2577 * throw out non-ip (on by default, but can be turned off)
2580 void wl_cache_store (struct wl_softc *sc, int base, struct ether_header *eh,
2583 struct ip *ip = NULL; /* Avoid GCC warning */
2585 int signal, silence;
2586 int w_insertcache; /* computed index for cache entry storage */
2587 int ipflag = wl_cache_iponly;
2591 * 2. configurable filter to throw out unicast packets,
2592 * keep multicast only.
2596 /* reject if not IP packet
2598 if ( wl_cache_iponly && (ntohs(eh->ether_type) != 0x800)) {
2602 /* check if broadcast or multicast packet. we toss
2605 if (wl_cache_mcastonly && ((eh->ether_dhost[0] & 1) == 0)) {
2609 /* find the ip header. we want to store the ip_src
2610 * address. use the mtod macro(in mbuf.h)
2611 * to typecast m to struct ip *
2614 ip = mtod(m, struct ip *);
2617 /* do a linear search for a matching MAC address
2618 * in the cache table
2619 * . MAC address is 6 bytes,
2620 * . var w_nextcache holds total number of entries already cached
2622 for(i = 0; i < sc->w_nextcache; i++) {
2623 if (! bcmp(eh->ether_shost, sc->w_sigcache[i].macsrc, 6 )) {
2625 * so we already have this entry,
2626 * update the data, and LRU age
2632 /* did we find a matching mac address?
2633 * if yes, then overwrite a previously existing cache entry
2635 if (i < sc->w_nextcache ) {
2638 /* else, have a new address entry,so
2639 * add this new entry,
2640 * if table full, then we need to replace entry
2644 /* check for space in cache table
2645 * note: w_nextcache also holds number of entries
2646 * added in the cache table
2648 if ( sc->w_nextcache < MAXCACHEITEMS ) {
2649 w_insertcache = sc->w_nextcache;
2651 sc->w_sigitems = sc->w_nextcache;
2653 /* no space found, so simply wrap with wrap index
2654 * and "zap" the next entry
2657 if (sc->w_wrapindex == MAXCACHEITEMS) {
2658 sc->w_wrapindex = 0;
2660 w_insertcache = sc->w_wrapindex++;
2664 /* invariant: w_insertcache now points at some slot
2667 if (w_insertcache < 0 || w_insertcache >= MAXCACHEITEMS) {
2669 "wl_cache_store, bad index: %d of [0..%d], gross cache error\n",
2670 w_insertcache, MAXCACHEITEMS);
2674 /* store items in cache
2677 * .signal (0..63) ,silence (0..63) ,quality (0..15)
2680 sc->w_sigcache[w_insertcache].ipsrc = ip->ip_src.s_addr;
2682 bcopy( eh->ether_shost, sc->w_sigcache[w_insertcache].macsrc, 6);
2683 signal = sc->w_sigcache[w_insertcache].signal = wlmmcread(base, MMC_SIGNAL_LVL) & 0x3f;
2684 silence = sc->w_sigcache[w_insertcache].silence = wlmmcread(base, MMC_SILENCE_LVL) & 0x3f;
2685 sc->w_sigcache[w_insertcache].quality = wlmmcread(base, MMC_SIGN_QUAL) & 0x0f;
2687 sc->w_sigcache[w_insertcache].snr =
2690 sc->w_sigcache[w_insertcache].snr = 0;
2694 #endif /* WLCACHE */
2697 * determine if in all multicast mode or not
2699 * returns: 1 if IFF_ALLMULTI should be set
2704 #if defined(__FreeBSD__) && __FreeBSD_version < 300000 /* not required */
2706 check_allmulti(struct wl_softc *sc)
2708 short base = sc->base;
2709 struct ether_multi *enm;
2710 struct ether_multistep step;
2712 ETHER_FIRST_MULTI(step, &sc->wl_ac, enm);
2713 while (enm != NULL) {
2714 unsigned int lo, hi;
2716 printf("enm_addrlo %x:%x:%x:%x:%x:%x\n", enm->enm_addrlo[0], enm->enm_addrlo[1],
2717 enm->enm_addrlo[2], enm->enm_addrlo[3], enm->enm_addrlo[4],
2718 enm->enm_addrlo[5]);
2719 printf("enm_addrhi %x:%x:%x:%x:%x:%x\n", enm->enm_addrhi[0], enm->enm_addrhi[1],
2720 enm->enm_addrhi[2], enm->enm_addrhi[3], enm->enm_addrhi[4],
2721 enm->enm_addrhi[5]);
2723 if (bcmp(enm->enm_addrlo, enm->enm_addrhi, 6) != 0) {
2726 ETHER_NEXT_MULTI(step, enm);