2 * Redistribution and use in source and binary forms, with or without
3 * modification, are permitted provided that the following conditions
5 * 1. Redistributions of source code must retain all copyright
6 * notices, this list of conditions and the following disclaimer.
7 * 2. The names of the authors may not be used to endorse or promote products
8 * derived from this software without specific prior written permission
10 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
11 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
12 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
13 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
14 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
15 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
16 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
17 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
18 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
19 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 * if_wl.c - original MACH, then BSDI ISA wavelan driver
24 * ported to mach by Anders Klemets
25 * to BSDI by Robert Morris
26 * to FreeBSD by Jim Binkley
27 * to FreeBSD 2.2+ by Michael Smith
30 * Changed interface to match 2.1-2.2 differences.
31 * Implement IRQ selection logic in wlprobe()
32 * Implement PSA updating.
33 * Pruned heading comments for relevance.
34 * Ripped out all the 'interface counters' cruft.
35 * Cut the missing-interrupt timer back to 100ms.
37 * now supports all multicast mode (mrouted will work),
38 * but unfortunately must do that by going into promiscuous mode
39 * NWID sysctl added so that normally promiscuous mode is NWID-specific
40 * but can be made NWID-inspecific
44 * Ported to FreeBSD, got promiscuous mode working with bpfs,
45 * and rewired timer routine. The i82586 will hang occasionally on output
46 * and the watchdog timer will kick it if so and log an entry.
47 * 2 second timeout there. Apparently the chip loses an interrupt.
48 * Code borrowed from if_ie.c for watchdog timer.
50 * The wavelan card is a 2mbit radio modem that emulates ethernet;
51 * i.e., it uses MAC addresses. This should not be a surprise since
52 * it uses an ethernet controller as a major hw item.
53 * It can broadcast, unicast or apparently multicast in a base cell
54 * using an omni-directional antennae that is
55 * about 800 feet around the base cell barring walls and metal.
56 * With directional antennae, it can be used point to point over a mile
57 * or so apparently (haven't tried that).
59 * There are ISA and pcmcia versions (not supported by this code).
60 * The ISA card has an Intel 82586 lan controller on it. It consists
61 * of 2 pieces of hw, the lan controller (intel) and a radio-modem.
62 * The latter has an extra set of controller registers that has nothing
63 * to do with the i82586 and allows setting and monitoring of radio
64 * signal strength, etc. There is a nvram area called the PSA that
65 * contains a number of setup variables including the IRQ and so-called
66 * NWID or Network ID. The NWID must be set the same for all radio
67 * cards to communicate (unless you are using the ATT/NCR roaming feature
68 * with their access points. There is no support for that here. Roaming
69 * involves a link-layer beacon sent out from the access points. End
70 * stations monitor the signal strength and only use the strongest
71 * access point). This driver assumes that the base ISA port, IRQ,
72 * and NWID are first set in nvram via the dos-side "instconf.exe" utility
73 * supplied with the card. This driver takes the ISA port from
74 * the kernel configuration setup, and then determines the IRQ either
75 * from the kernel config (if an explicit IRQ is set) or from the
76 * PSA on the card if not.
77 * The hw also magically just uses the IRQ set in the nvram.
78 * The NWID is used magically as well by the radio-modem
79 * to determine which packets to keep or throw out.
83 * device wl0 at isa? port 0x300 net irq ?
86 * 1. WLDEBUG. (off) - if turned on enables IFF_DEBUG set via ifconfig debug
87 * 2. MULTICAST (on) - turned on and works up to and including mrouted
88 * 3. WLCACHE (off) - define to turn on a signal strength
89 * (and other metric) cache that is indexed by sender MAC address.
90 * Apps can read this out to learn the remote signal strength of a
91 * sender. Note that it has a switch so that it only stores
92 * broadcast/multicast senders but it could be set to store unicast
93 * too only. Size is hardwired in if_wl_wavelan.h
95 * one further note: promiscuous mode is a curious thing. In this driver,
96 * promiscuous mode apparently CAN catch ALL packets and ignore the NWID
97 * setting. This is probably more useful in a sense (for snoopers) if
98 * you are interested in all traffic as opposed to if you are interested
99 * in just your own. There is a driver specific sysctl to turn promiscuous
100 * from just promiscuous to wildly promiscuous...
102 * This driver also knows how to load the synthesizers in the 2.4 Gz
103 * ISA Half-card, Product number 847647476 (USA/FCC IEEE Channel set).
104 * This product consists of a "mothercard" that contains the 82586,
105 * NVRAM that holds the PSA, and the ISA-buss interface custom ASIC.
106 * The radio transceiver is a "daughtercard" called the WaveMODEM which
107 * connects to the mothercard through two single-inline connectors: a
108 * 20-pin connector provides DC-power and modem signals, and a 3-pin
109 * connector which exports the antenna connection. The code herein
110 * loads the receive and transmit synthesizers and the corresponding
111 * transmitter output power value from an EEPROM controlled through
112 * additional registers via the MMC. The EEPROM address selected
113 * are those whose values are preset by the DOS utility programs
114 * provided with the product, and this provides compatible operation
115 * with the DOS Packet Driver software. A future modification will
116 * add the necessary functionality to this driver and to the wlconfig
117 * utility to completely replace the DOS Configuration Utilities.
118 * The 2.4 Gz WaveMODEM is described in document number 407-024692/E,
119 * and is available through Lucent Technologies OEM supply channels.
126 * Olivetti PC586 Mach Ethernet driver v1.0
127 * Copyright Ing. C. Olivetti & C. S.p.A. 1988, 1989
128 * All rights reserved.
132 Copyright 1988, 1989 by Olivetti Advanced Technology Center, Inc.,
133 Cupertino, California.
137 Permission to use, copy, modify, and distribute this software and
138 its documentation for any purpose and without fee is hereby
139 granted, provided that the above copyright notice appears in all
140 copies and that both the copyright notice and this permission notice
141 appear in supporting documentation, and that the name of Olivetti
142 not be used in advertising or publicity pertaining to distribution
143 of the software without specific, written prior permission.
145 OLIVETTI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
146 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
147 IN NO EVENT SHALL OLIVETTI BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
148 CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
149 LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
150 NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUR OF OR IN CONNECTION
151 WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
154 Copyright 1988, 1989 by Intel Corporation, Santa Clara, California.
158 Permission to use, copy, modify, and distribute this software and
159 its documentation for any purpose and without fee is hereby
160 granted, provided that the above copyright notice appears in all
161 copies and that both the copyright notice and this permission notice
162 appear in supporting documentation, and that the name of Intel
163 not be used in advertising or publicity pertaining to distribution
164 of the software without specific, written prior permission.
166 INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
167 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
168 IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
169 CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
170 LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
171 NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
172 WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
175 #include <sys/cdefs.h>
176 __FBSDID("$FreeBSD$");
181 * 1. The best book on the 82586 is:
182 * LAN Components User's Manual by Intel
183 * The copy I found was dated 1984. This really tells you
184 * what the state machines are doing
185 * 2. In the current design, we only do one write at a time,
186 * though the hardware is capable of chaining and possibly
187 * even batching. The problem is that we only make one
188 * transmit buffer available in sram space.
191 #include "opt_wavelan.h"
192 #include "opt_inet.h"
194 #include <sys/param.h>
195 #include <sys/systm.h>
196 #include <sys/kernel.h>
197 #include <sys/module.h>
198 #include <sys/sockio.h>
199 #include <sys/mbuf.h>
200 #include <sys/priv.h>
201 #include <sys/socket.h>
202 #include <sys/syslog.h>
203 #include <machine/bus.h>
204 #include <machine/resource.h>
206 #include <sys/rman.h>
208 #include <sys/sysctl.h>
210 #include <net/ethernet.h>
212 #include <net/if_var.h>
213 #include <net/if_arp.h>
214 #include <net/if_dl.h>
215 #include <net/if_types.h>
218 #include <netinet/in.h>
219 #include <netinet/in_systm.h>
220 #include <netinet/ip.h>
221 #include <netinet/if_ether.h>
225 #include <isa/isavar.h>
227 /* was 1000 in original, fed to DELAY(x) */
228 #define DELAYCONST 1000
229 #include <dev/wl/if_wl_i82586.h> /* Definitions for the Intel chip */
230 #include <dev/wl/if_wl.h>
231 #include <machine/if_wl_wavelan.h>
233 static char t_packet[ETHERMTU + sizeof(struct ether_header) + sizeof(long)];
239 u_char nwid[2]; /* current radio modem nwid */
241 int tbusy; /* flag to determine if xmit is busy */
245 u_short hacr; /* latest host adapter CR command */
247 u_char chan24; /* 2.4 Gz: channel number/EEPROM Area # */
248 u_short freq24; /* 2.4 Gz: resulting frequency */
251 struct resource *res_ioport;
252 struct resource *res_irq;
255 struct callout watchdog_timer;
257 int w_sigitems; /* number of cached entries */
258 /* array of cache entries */
259 struct w_sigcache w_sigcache[ MAXCACHEITEMS ];
260 int w_nextcache; /* next free cache entry */
261 int w_wrapindex; /* next "free" cache entry */
265 #define WL_LOCK(_sc) mtx_lock(&(_sc)->wl_mtx)
266 #define WL_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->wl_mtx, MA_OWNED)
267 #define WL_UNLOCK(_sc) mtx_unlock(&(_sc)->wl_mtx)
269 static int wlprobe(device_t);
270 static int wlattach(device_t);
271 static int wldetach(device_t);
273 static device_method_t wl_methods[] = {
274 DEVMETHOD(device_probe, wlprobe),
275 DEVMETHOD(device_attach, wlattach),
276 DEVMETHOD(device_detach, wldetach),
280 static driver_t wl_driver = {
283 sizeof (struct wl_softc)
286 devclass_t wl_devclass;
287 DRIVER_MODULE(wl, isa, wl_driver, wl_devclass, 0, 0);
288 MODULE_DEPEND(wl, isa, 1, 1, 1);
289 MODULE_DEPEND(wl, ether, 1, 1, 1);
291 static struct isa_pnp_id wl_ids[] = {
296 * XXX The Wavelan appears to be prone to dropping stuff if you talk to
297 * it too fast. This disgusting hack inserts a delay after each packet
298 * is queued which helps avoid this behaviour on fast systems.
300 static int wl_xmit_delay = 250;
301 SYSCTL_INT(_machdep, OID_AUTO, wl_xmit_delay, CTLFLAG_RW, &wl_xmit_delay, 0, "");
304 * not XXX, but ZZZ (bizarre).
305 * promiscuous mode can be toggled to ignore NWIDs. By default,
306 * it does not. Caution should be exercised about combining
307 * this mode with IFF_ALLMULTI which puts this driver in
310 static int wl_ignore_nwid = 0;
311 SYSCTL_INT(_machdep, OID_AUTO, wl_ignore_nwid, CTLFLAG_RW, &wl_ignore_nwid, 0, "");
314 * Emit diagnostics about transmission problems
316 static int xmt_watch = 0;
317 SYSCTL_INT(_machdep, OID_AUTO, wl_xmit_watch, CTLFLAG_RW, &xmt_watch, 0, "");
320 * Collect SNR statistics
322 static int gathersnr = 0;
323 SYSCTL_INT(_machdep, OID_AUTO, wl_gather_snr, CTLFLAG_RW, &gathersnr, 0, "");
325 static int wl_allocate_resources(device_t device);
326 static int wl_deallocate_resources(device_t device);
327 static void wlstart(struct ifnet *ifp);
328 static void wlstart_locked(struct ifnet *ifp);
329 static void wlinit(void *xsc);
330 static void wlinit_locked(struct wl_softc *sc);
331 static int wlioctl(struct ifnet *ifp, u_long cmd, caddr_t data);
332 static void wlwatchdog(void *arg);
333 static void wlintr(void *arg);
334 static void wlxmt(struct wl_softc *sc, struct mbuf *m);
335 static int wldiag(struct wl_softc *sc);
336 static int wlconfig(struct wl_softc *sc);
337 static int wlcmd(struct wl_softc *sc, char *str);
338 static void wlmmcstat(struct wl_softc *sc);
339 static u_short wlbldru(struct wl_softc *sc);
340 static u_short wlmmcread(struct wl_softc *sc, u_short reg);
341 static void wlinitmmc(struct wl_softc *sc);
342 static int wlhwrst(struct wl_softc *sc);
343 static void wlrustrt(struct wl_softc *sc);
344 static void wlbldcu(struct wl_softc *sc);
345 static int wlack(struct wl_softc *sc);
346 static int wlread(struct wl_softc *sc, u_short fd_p);
347 static void getsnr(struct wl_softc *sc);
348 static void wlrcv(struct wl_softc *sc);
349 static int wlrequeue(struct wl_softc *sc, u_short fd_p);
350 static void wlsftwsleaze(u_short *countp, u_char **mb_pp, struct mbuf **tm_pp, struct wl_softc *sc);
351 static void wlhdwsleaze(u_short *countp, u_char **mb_pp, struct mbuf **tm_pp, struct wl_softc *sc);
353 static void wltbd(struct wl_softc *sc);
355 static void wlgetpsa(struct wl_softc *sc, u_char *buf);
356 static void wlsetpsa(struct wl_softc *sc);
357 static u_short wlpsacrc(u_char *buf);
358 static void wldump(struct wl_softc *sc);
360 static void wl_cache_store(struct wl_softc *, struct ether_header *, struct mbuf *);
361 static void wl_cache_zero(struct wl_softc *sc);
364 /* array for maping irq numbers to values for the irq parameter register */
365 static int irqvals[16] = {
366 0, 0, 0, 0x01, 0x02, 0x04, 0, 0x08, 0, 0, 0x10, 0x20, 0x40, 0, 0, 0x80
372 * This function "probes" or checks for the WaveLAN board on the bus to
373 * see if it is there. As far as I can tell, the best break between this
374 * routine and the attach code is to simply determine whether the board
375 * is configured in properly. Currently my approach to this is to write
376 * and read a word from the SRAM on the board being probed. If the word
377 * comes back properly then we assume the board is there. The config
378 * code expects to see a successful return from the probe routine before
379 * attach will be called.
381 * input : address device is mapped to, and unit # being checked
382 * output : a '1' is returned if the board exists, and a 0 otherwise
386 wlprobe(device_t device)
389 char *str = "wl%d: board out of range [0..%d]\n";
391 rman_res_t junk, sirq;
394 error = ISA_PNP_PROBE(device_get_parent(device), device, wl_ids);
395 if (error == ENXIO || error == 0)
398 sc = device_get_softc(device);
399 error = wl_allocate_resources(device);
404 * regular CMD() will not work, since no softc yet
406 #define PCMD(sc, hacr) WL_WRITE_2((sc), HACR, (hacr))
408 PCMD(sc, HACR_RESET); /* reset the board */
409 DELAY(DELAYCONST); /* >> 4 clocks at 6MHz */
410 PCMD(sc, HACR_RESET); /* reset the board */
411 DELAY(DELAYCONST); /* >> 4 clocks at 6MHz */
413 /* clear reset command and set PIO#1 in autoincrement mode */
414 PCMD(sc, HACR_DEFAULT);
415 PCMD(sc, HACR_DEFAULT);
416 WL_WRITE_2(sc, PIOR1, 0); /* go to beginning of RAM */
417 WL_WRITE_MULTI_2(sc, PIOP1, str, strlen(str)/2+1); /* write string */
419 WL_WRITE_2(sc, PIOR1, 0); /* rewind */
420 WL_READ_MULTI_2(sc, PIOP1, inbuf, strlen(str)/2+1); /* read result */
422 if (bcmp(str, inbuf, strlen(str))) {
427 sc->chan24 = 0; /* 2.4 Gz: config channel */
428 sc->freq24 = 0; /* 2.4 Gz: frequency */
430 /* read the PSA from the board into temporary storage */
433 /* We read the IRQ value from the PSA on the board. */
434 for (irq = 15; irq >= 0; irq--)
435 if (irqvals[irq] == inbuf[WLPSA_IRQNO])
437 if ((irq == 0) || (irqvals[irq] == 0)){
438 device_printf(device, "PSA corrupt (invalid IRQ value)\n");
441 * If the IRQ requested by the PSA is already claimed by another
442 * device, the board won't work, but the user can still access the
443 * driver to change the IRQ.
445 if (bus_get_resource(device, SYS_RES_IRQ, 0, &sirq, &junk))
447 if (irq != (int)sirq)
448 device_printf(device, "board is configured for interrupt %d\n",
451 wl_deallocate_resources(device);
455 wl_deallocate_resources(device);
462 * This function attaches a WaveLAN board to the "system". The rest of
463 * runtime structures are initialized here (this routine is called after
464 * a successful probe of the board). Once the ethernet address is read
465 * and stored, the board's ifnet structure is attached and readied.
467 * input : isa_dev structure setup in autoconfig
468 * output : board structs and ifnet is setup
472 wlattach(device_t device)
479 sc = device_get_softc(device);
481 ifp = sc->ifp = if_alloc(IFT_ETHER);
483 device_printf(device, "can not if_alloc()\n");
487 mtx_init(&sc->wl_mtx, device_get_nameunit(device), MTX_NETWORK_LOCK,
489 callout_init_mtx(&sc->watchdog_timer, &sc->wl_mtx, 0);
491 error = wl_allocate_resources(device);
493 wl_deallocate_resources(device);
498 printf("wlattach: base %jx, unit %d\n", rman_get_start(sc->res_ioport),
499 device_get_unit(device));
504 sc->hacr = HACR_RESET;
505 CMD(sc); /* reset the board */
506 DELAY(DELAYCONST); /* >> 4 clocks at 6MHz */
508 /* clear reset command and set PIO#2 in parameter access mode */
509 sc->hacr = (HACR_DEFAULT & ~HACR_16BITS);
512 /* Read the PSA from the board for our later reference */
513 wlgetpsa(sc, sc->psa);
516 sc->nwid[0] = sc->psa[WLPSA_NWID];
517 sc->nwid[1] = sc->psa[WLPSA_NWID+1];
519 /* fetch MAC address - decide which one first */
520 if (sc->psa[WLPSA_MACSEL] & 1)
524 for (i=0; i < WAVELAN_ADDR_SIZE; ++i)
525 eaddr[i] = sc->psa[j + i];
527 /* enter normal 16 bit mode operation */
528 sc->hacr = HACR_DEFAULT;
532 WL_WRITE_2(sc, PIOR1, OFFSET_SCB + 8); /* address of scb_crcerrs */
533 WL_WRITE_2(sc, PIOP1, 0); /* clear scb_crcerrs */
534 WL_WRITE_2(sc, PIOP1, 0); /* clear scb_alnerrs */
535 WL_WRITE_2(sc, PIOP1, 0); /* clear scb_rscerrs */
536 WL_WRITE_2(sc, PIOP1, 0); /* clear scb_ovrnerrs */
539 ifp->if_mtu = WAVELAN_MTU;
540 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
542 ifp->if_flags |= IFF_DEBUG;
545 ifp->if_flags |= IFF_MULTICAST;
546 #endif /* MULTICAST */
547 if_initname(ifp, device_get_name(device), device_get_unit(device));
548 ifp->if_init = wlinit;
549 ifp->if_start = wlstart;
550 ifp->if_ioctl = wlioctl;
551 ifp->if_snd.ifq_maxlen = ifqmaxlen;
556 ether_ifattach(ifp, eaddr);
558 if_printf(ifp, "NWID 0x%02x%02x", sc->nwid[0], sc->nwid[1]);
560 printf(", Freq %d MHz",sc->freq24); /* 2.4 Gz */
561 printf("\n"); /* 2.4 Gz */
563 bus_setup_intr(device, sc->res_irq, INTR_TYPE_NET, NULL, wlintr, sc, &sc->intr_cookie);
571 wldetach(device_t device)
573 struct wl_softc *sc = device_get_softc(device);
581 /* reset the board */
582 sc->hacr = HACR_RESET;
584 sc->hacr = HACR_DEFAULT;
586 callout_stop(&sc->watchdog_timer);
588 callout_drain(&sc->watchdog_timer);
590 if (sc->intr_cookie != NULL) {
591 bus_teardown_intr(device, sc->res_irq, sc->intr_cookie);
592 sc->intr_cookie = NULL;
595 wl_deallocate_resources(device);
597 mtx_destroy(&sc->wl_mtx);
602 wl_allocate_resources(device_t device)
604 struct wl_softc *sc = device_get_softc(device);
605 int ports = 16; /* Number of ports */
607 sc->res_ioport = bus_alloc_resource_anywhere(device, SYS_RES_IOPORT,
608 &sc->rid_ioport, ports, RF_ACTIVE);
609 if (sc->res_ioport == NULL)
612 sc->res_irq = bus_alloc_resource_any(device, SYS_RES_IRQ,
613 &sc->rid_irq, RF_SHAREABLE|RF_ACTIVE);
614 if (sc->res_irq == NULL)
619 wl_deallocate_resources(device);
624 wl_deallocate_resources(device_t device)
626 struct wl_softc *sc = device_get_softc(device);
628 if (sc->res_irq != 0) {
629 bus_release_resource(device, SYS_RES_IRQ,
630 sc->rid_irq, sc->res_irq);
633 if (sc->res_ioport != 0) {
634 bus_release_resource(device, SYS_RES_IOPORT,
635 sc->rid_ioport, sc->res_ioport);
642 * Print out interesting information about the 82596.
645 wldump(struct wl_softc *sc)
649 printf("hasr %04x\n", WL_READ_2(sc, HASR));
651 printf("scb at %04x:\n ", OFFSET_SCB);
652 WL_WRITE_2(sc, PIOR1, OFFSET_SCB);
653 for (i = 0; i < 8; i++)
654 printf("%04x ", WL_READ_2(sc, PIOP1));
657 printf("cu at %04x:\n ", OFFSET_CU);
658 WL_WRITE_2(sc, PIOR1, OFFSET_CU);
659 for (i = 0; i < 8; i++)
660 printf("%04x ", WL_READ_2(sc, PIOP1));
663 printf("tbd at %04x:\n ", OFFSET_TBD);
664 WL_WRITE_2(sc, PIOR1, OFFSET_TBD);
665 for (i = 0; i < 4; i++)
666 printf("%04x ", WL_READ_2(sc, PIOP1));
670 /* Initialize the Modem Management Controller */
672 wlinitmmc(struct wl_softc *sc)
678 /* enter 8 bit operation */
679 sc->hacr = (HACR_DEFAULT & ~HACR_16BITS);
682 configured = sc->psa[WLPSA_CONFIGURED] & 1;
685 * Set default modem control parameters. Taken from NCR document
688 MMC_WRITE(MMC_JABBER_ENABLE, 0x01);
689 MMC_WRITE(MMC_ANTEN_SEL, 0x02);
690 MMC_WRITE(MMC_IFS, 0x20);
691 MMC_WRITE(MMC_MOD_DELAY, 0x04);
692 MMC_WRITE(MMC_JAM_TIME, 0x38);
693 MMC_WRITE(MMC_DECAY_PRM, 0x00); /* obsolete ? */
694 MMC_WRITE(MMC_DECAY_UPDAT_PRM, 0x00);
696 MMC_WRITE(MMC_LOOPT_SEL, 0x00);
697 if (sc->psa[WLPSA_COMPATNO] & 1) {
698 MMC_WRITE(MMC_THR_PRE_SET, 0x01); /* 0x04 for AT and 0x01 for MCA */
700 MMC_WRITE(MMC_THR_PRE_SET, 0x04); /* 0x04 for AT and 0x01 for MCA */
702 MMC_WRITE(MMC_QUALITY_THR, 0x03);
704 /* use configuration defaults from parameter storage area */
705 if (sc->psa[WLPSA_NWIDENABLE] & 1) {
706 if ((mode & (MOD_PROM | MOD_ENAL)) && wl_ignore_nwid) {
707 MMC_WRITE(MMC_LOOPT_SEL, 0x40);
709 MMC_WRITE(MMC_LOOPT_SEL, 0x00);
712 MMC_WRITE(MMC_LOOPT_SEL, 0x40); /* disable network id check */
714 MMC_WRITE(MMC_THR_PRE_SET, sc->psa[WLPSA_THRESH]);
715 MMC_WRITE(MMC_QUALITY_THR, sc->psa[WLPSA_QUALTHRESH]);
717 MMC_WRITE(MMC_FREEZE, 0x00);
718 MMC_WRITE(MMC_ENCR_ENABLE, 0x00);
720 MMC_WRITE(MMC_NETW_ID_L,sc->nwid[1]); /* set NWID */
721 MMC_WRITE(MMC_NETW_ID_H,sc->nwid[0]);
723 /* enter normal 16 bit mode operation */
724 sc->hacr = HACR_DEFAULT;
726 CMD(sc); /* virtualpc1 needs this! */
728 if (sc->psa[WLPSA_COMPATNO]== /* 2.4 Gz: half-card ver */
729 WLPSA_COMPATNO_WL24B) { /* 2.4 Gz */
730 i=sc->chan24<<4; /* 2.4 Gz: position ch # */
731 MMC_WRITE(MMC_EEADDR,i+0x0f); /* 2.4 Gz: named ch, wc=16 */
732 MMC_WRITE(MMC_EECTRL,MMC_EECTRL_DWLD+ /* 2.4 Gz: Download Synths */
733 MMC_EECTRL_EEOP_READ); /* 2.4 Gz: Read EEPROM */
734 for (i=0; i<1000; ++i) { /* 2.4 Gz: wait for download */
735 DELAY(40); /* 2.4 Gz */
736 if ((wlmmcread(sc, MMC_EECTRLstat) /* 2.4 Gz: check DWLD and */
737 &(MMC_EECTRLstat_DWLD /* 2.4 Gz: EEBUSY */
738 +MMC_EECTRLstat_EEBUSY))==0) /* 2.4 Gz: */
739 break; /* 2.4 Gz: download finished */
741 if (i==1000) printf("wl: synth load failed\n"); /* 2.4 Gz */
742 MMC_WRITE(MMC_EEADDR,0x61); /* 2.4 Gz: default pwr, wc=2 */
743 MMC_WRITE(MMC_EECTRL,MMC_EECTRL_DWLD+ /* 2.4 Gz: Download Xmit Pwr */
744 MMC_EECTRL_EEOP_READ); /* 2.4 Gz: Read EEPROM */
745 for (i=0; i<1000; ++i) { /* 2.4 Gz: wait for download */
746 DELAY(40); /* 2.4 Gz */
747 if ((wlmmcread(sc, MMC_EECTRLstat) /* 2.4 Gz: check DWLD and */
748 &(MMC_EECTRLstat_DWLD /* 2.4 Gz: EEBUSY */
749 +MMC_EECTRLstat_EEBUSY))==0) /* 2.4 Gz: */
750 break; /* 2.4 Gz: download finished */
752 if (i==1000) printf("wl: xmit pwr load failed\n"); /* 2.4 Gz */
753 MMC_WRITE(MMC_ANALCTRL, /* 2.4 Gz: EXT ant+polarity */
754 MMC_ANALCTRL_ANTPOL + /* 2.4 Gz: */
755 MMC_ANALCTRL_EXTANT); /* 2.4 Gz: */
756 i=sc->chan24<<4; /* 2.4 Gz: position ch # */
757 MMC_WRITE(MMC_EEADDR,i); /* 2.4 Gz: get frequency */
758 MMC_WRITE(MMC_EECTRL, /* 2.4 Gz: EEPROM read */
759 MMC_EECTRL_EEOP_READ); /* 2.4 Gz: */
760 DELAY(40); /* 2.4 Gz */
761 i = wlmmcread(sc, MMC_EEDATALrv) /* 2.4 Gz: freq val */
762 + (wlmmcread(sc, MMC_EEDATAHrv)<<8); /* 2.4 Gz */
763 sc->freq24 = (i>>6)+2400; /* 2.4 Gz: save real freq */
770 * Another routine that interfaces the "if" layer to this driver.
771 * Simply resets the structures that are used by "upper layers".
772 * As well as calling wlhwrst that does reset the WaveLAN board.
774 * input : softc pointer for this interface
775 * output : structures (if structs) and board are reset
781 struct wl_softc *sc = xsc;
789 wlinit_locked(struct wl_softc *sc)
791 struct ifnet *ifp = sc->ifp;
795 if (sc->ifp->if_flags & IFF_DEBUG)
796 if_printf(ifp, "entered wlinit()\n");
799 if ((stat = wlhwrst(sc)) == TRUE) {
800 sc->ifp->if_drv_flags |= IFF_DRV_RUNNING; /* same as DSF_RUNNING */
802 * OACTIVE is used by upper-level routines
805 sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; /* same as tbusy below */
807 sc->flags |= DSF_RUNNING;
809 callout_stop(&sc->watchdog_timer);
813 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 : board number to do a hardware reset
824 * output : board is reset
828 wlhwrst(struct wl_softc *sc)
832 if (sc->ifp->if_flags & IFF_DEBUG)
833 if_printf(sc->ifp, "entered wlhwrst()\n");
835 sc->hacr = HACR_RESET;
836 CMD(sc); /* reset the board */
838 /* clear reset command and set PIO#1 in autoincrement mode */
839 sc->hacr = HACR_DEFAULT;
843 if (sc->ifp->if_flags & IFF_DEBUG)
844 wlmmcstat(sc); /* Display MMC registers */
846 wlbldcu(sc); /* set up command unit structures */
851 if (wlconfig(sc) == 0)
854 * insert code for loopback test here
856 wlrustrt(sc); /* start receive unit */
858 /* enable interrupts */
859 sc->hacr = (HACR_DEFAULT | HACR_INTRON);
868 * This function builds up the command unit structures. It inits
869 * the scp, iscp, scb, cb, tbd, and tbuf.
873 wlbldcu(struct wl_softc *sc)
882 bzero(&scp, sizeof(scp));
884 scp.scp_iscp = OFFSET_ISCP;
885 scp.scp_iscp_base = 0;
886 WL_WRITE_2(sc, PIOR1, OFFSET_SCP);
887 WL_WRITE_MULTI_2(sc, PIOP1, &scp, sizeof(scp_t)/2);
889 bzero(&iscp, sizeof(iscp));
891 iscp.iscp_scb_offset = OFFSET_SCB;
893 iscp.iscp_scb_base = 0;
894 WL_WRITE_2(sc, PIOR1, OFFSET_ISCP);
895 WL_WRITE_MULTI_2(sc, PIOP1, &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 WL_WRITE_2(sc, PIOR1, OFFSET_SCB);
906 WL_WRITE_MULTI_2(sc, PIOP1, &scb, sizeof(scb_t)/2);
910 WL_WRITE_2(sc, PIOR0, OFFSET_ISCP + 0); /* address of iscp_busy */
911 for (i = 1000000; WL_READ_2(sc, PIOP0) && (i-- > 0); )
914 device_printf(sc->dev, "bldcu(): iscp_busy timeout.\n");
915 WL_WRITE_2(sc, PIOR0, OFFSET_SCB + 0); /* address of scb_status */
916 for (i = STATUS_TRIES; i-- > 0; ) {
917 if (WL_READ_2(sc, PIOP0) == (SCB_SW_CX|SCB_SW_CNA))
921 device_printf(sc->dev, "bldcu(): not ready after reset.\n");
925 cb.ac_command = AC_CW_EL; /* NOP */
926 cb.ac_link_offset = OFFSET_CU;
927 WL_WRITE_2(sc, PIOR1, OFFSET_CU);
928 WL_WRITE_MULTI_2(sc, PIOP1, &cb, 6/2);
931 tbd.next_tbd_offset = I82586NULL;
934 WL_WRITE_2(sc, PIOR1, OFFSET_TBD);
935 WL_WRITE_MULTI_2(sc, PIOP1, &tbd, sizeof(tbd_t)/2);
943 * input : board number
944 * output : stuff sent to board if any there
948 wlstart(struct ifnet *ifp)
950 struct wl_softc *sc = ifp->if_softc;
958 wlstart_locked(struct ifnet *ifp)
961 struct wl_softc *sc = ifp->if_softc;
962 int scb_status, cu_status, scb_command;
966 if (sc->ifp->if_flags & IFF_DEBUG)
967 if_printf(ifp, "entered wlstart()\n");
970 WL_WRITE_2(sc, PIOR1, OFFSET_CU);
971 cu_status = WL_READ_2(sc, PIOP1);
972 WL_WRITE_2(sc, PIOR0,OFFSET_SCB + 0); /* scb_status */
973 scb_status = WL_READ_2(sc, PIOP0);
974 WL_WRITE_2(sc, PIOR0, OFFSET_SCB + 2);
975 scb_command = WL_READ_2(sc, PIOP0);
978 * don't need OACTIVE check as tbusy here checks to see
979 * if we are already busy
982 if ((scb_status & 0x0700) == SCB_CUS_IDLE &&
983 (cu_status & AC_SW_B) == 0){
985 callout_stop(&sc->watchdog_timer);
986 sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
988 * This is probably just a race. The xmt'r is just
989 * became idle but WE have masked interrupts so ...
992 if_printf(ifp, "CU idle, scb %04x %04x cu %04x\n",
993 scb_status, scb_command, cu_status);
995 if (xmt_watch) printf("!!");
997 return; /* genuinely still busy */
999 } else if ((scb_status & 0x0700) == SCB_CUS_ACTV ||
1000 (cu_status & AC_SW_B)){
1002 if_printf(ifp, "CU unexpectedly busy; scb %04x cu %04x\n",
1003 scb_status, cu_status);
1006 if_printf(ifp, "busy?!\n");
1007 return; /* hey, why are we busy? */
1010 /* get ourselves some data */
1011 IF_DEQUEUE(&ifp->if_snd, m);
1013 /* let BPF see it before we commit it */
1016 /* set the watchdog timer so that if the board
1017 * fails to interrupt we will restart
1019 /* try 10 ms, not very long */
1020 callout_reset(&sc->watchdog_timer, hz / 100, wlwatchdog, sc);
1021 sc->ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1022 if_inc_counter(sc->ifp, IFCOUNTER_OPACKETS, 1);
1025 sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1033 * This routine does the actual copy of data (including ethernet header
1034 * structure) from the WaveLAN to an mbuf chain that will be passed up
1035 * to the "if" (network interface) layer. NOTE: we currently
1036 * don't handle trailer protocols, so if that is needed, it will
1037 * (at least in part) be added here. For simplicities sake, this
1038 * routine copies the receive buffers from the board into a local (stack)
1039 * buffer until the frame has been copied from the board. Once in
1040 * the local buffer, the contents are copied to an mbuf chain that
1041 * is then enqueued onto the appropriate "if" queue.
1043 * input : board number, and a frame descriptor address
1044 * output : the packet is put into an mbuf chain, and passed up
1045 * assumes : if any errors occur, packet is "dropped on the floor"
1049 wlread(struct wl_softc *sc, u_short fd_p)
1051 struct ifnet *ifp = sc->ifp;
1053 struct ether_header *eh;
1058 u_short bytes_in_msg, bytes_in_mbuf, bytes;
1063 if (sc->ifp->if_flags & IFF_DEBUG)
1064 if_printf(ifp, "entered wlread()\n");
1066 if (!((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING))) {
1067 if_printf(ifp, "read(): board is not running.\n");
1068 sc->hacr &= ~HACR_INTRON;
1069 CMD(sc); /* turn off interrupts */
1073 * Collect message size.
1075 WL_WRITE_2(sc, PIOR1, fd_p);
1076 WL_READ_MULTI_2(sc, PIOP1, &fd, sizeof(fd_t)/2);
1077 if (fd.rbd_offset == I82586NULL) {
1078 if (wlhwrst(sc) != TRUE) {
1079 sc->hacr &= ~HACR_INTRON;
1080 CMD(sc); /* turn off interrupts */
1081 if_printf(ifp, "read(): hwrst trouble.\n");
1086 WL_WRITE_2(sc, PIOR1, fd.rbd_offset);
1087 WL_READ_MULTI_2(sc, PIOP1, &rbd, sizeof(rbd_t)/2);
1088 bytes_in_msg = rbd.status & RBD_SW_COUNT;
1091 * Allocate a cluster'd mbuf to receive the packet.
1093 m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
1095 if (wlhwrst(sc) != TRUE) {
1096 sc->hacr &= ~HACR_INTRON;
1097 CMD(sc); /* turn off interrupts */
1098 if_printf(ifp, "read(): hwrst trouble.\n");
1102 m->m_pkthdr.len = m->m_len = MCLBYTES;
1103 m_adj(m, ETHER_ALIGN); /* align IP header */
1106 * Collect the message data.
1109 mb_p = mtod(m, u_char *);
1110 bytes_in_mbuf = m->m_len;
1112 /* Put the ethernet header inside the mbuf. */
1113 bcopy(&fd.destination[0], mb_p, 14);
1116 bytes_in_mbuf -= 14;
1118 bytes = min(bytes_in_mbuf, bytes_in_msg);
1125 WL_WRITE_2(sc, PIOR1, rbd.buffer_addr);
1126 WL_READ_MULTI_2(sc, PIOP1, mb_p, len/2);
1129 if (bytes > bytes_in_mbuf) {
1130 /* XXX something wrong, a packet should fit in 1 cluster */
1132 if_printf(ifp, "read(): packet too large (%u > %u)\n",
1133 bytes, bytes_in_mbuf);
1134 if (wlhwrst(sc) != TRUE) {
1135 sc->hacr &= ~HACR_INTRON;
1136 CMD(sc); /* turn off interrupts */
1137 if_printf(ifp, "read(): hwrst trouble.\n");
1142 bytes_in_mbuf -= bytes;
1143 bytes_in_msg -= bytes;
1144 if (bytes_in_msg == 0) {
1145 if (rbd.status & RBD_SW_EOF || rbd.next_rbd_offset == I82586NULL) {
1148 WL_WRITE_2(sc, PIOR1, rbd.next_rbd_offset);
1149 WL_READ_MULTI_2(sc, PIOP1, &rbd, sizeof(rbd_t)/2);
1150 bytes_in_msg = rbd.status & RBD_SW_COUNT;
1152 rbd.buffer_addr += bytes;
1155 bytes = min(bytes_in_mbuf, bytes_in_msg);
1158 m->m_pkthdr.len = m->m_len = mlen;
1159 m->m_pkthdr.rcvif = ifp;
1162 * If hw is in promiscuous mode (note that I said hardware, not if
1163 * IFF_PROMISC is set in ifnet flags), then if this is a unicast
1164 * packet and the MAC dst is not us, drop it. This check in normally
1165 * inside ether_input(), but IFF_MULTI causes hw promisc without
1166 * a bpf listener, so this is wrong.
1167 * Greg Troxel <gdt@ir.bbn.com>, 1998-08-07
1170 * TBD: also discard packets where NWID does not match.
1171 * However, there does not appear to be a way to read the nwid
1172 * for a received packet. -gdt 1998-08-07
1174 /* XXX verify mbuf length */
1175 eh = mtod(m, struct ether_header *);
1177 #ifdef WL_USE_IFNET_PROMISC_CHECK /* not defined */
1178 (sc->ifp->if_flags & (IFF_PROMISC|IFF_ALLMULTI))
1180 /* hw is in promisc mode if this is true */
1181 (sc->mode & (MOD_PROM | MOD_ENAL))
1184 (eh->ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */
1185 bcmp(eh->ether_dhost, IF_LLADDR(sc->ifp),
1186 sizeof(eh->ether_dhost)) != 0 ) {
1192 if (sc->ifp->if_flags & IFF_DEBUG)
1193 if_printf(ifp, "wlrecv %u bytes\n", mlen);
1197 wl_cache_store(sc, eh, m);
1201 * received packet is now in a chain of mbuf's. next step is
1202 * to pass the packet upwards.
1205 (*ifp->if_input)(ifp, m);
1213 * This routine processes an ioctl request from the "if" layer
1216 * input : pointer the appropriate "if" struct, command, and data
1217 * output : based on command appropriate action is taken on the
1218 * WaveLAN board(s) or related structures
1219 * return : error is returned containing exit conditions
1223 wlioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1225 struct ifreq *ifr = (struct ifreq *)data;
1226 struct wl_softc *sc = ifp->if_softc;
1229 struct thread *td = curthread; /* XXX */
1230 int irq, irqval, i, isroot;
1232 char eeprom_buf[0x80];
1239 if (sc->ifp->if_flags & IFF_DEBUG)
1240 if_printf(ifp, "entered wlioctl()\n");
1245 if (ifp->if_flags & IFF_ALLMULTI) {
1248 if (ifp->if_flags & IFF_PROMISC) {
1251 if (ifp->if_flags & IFF_LINK0) {
1255 * force a complete reset if the receive multicast/
1256 * promiscuous mode changes so that these take
1257 * effect immediately.
1260 if (sc->mode != mode) {
1262 if (sc->flags & DSF_RUNNING) {
1263 sc->flags &= ~DSF_RUNNING;
1267 /* if interface is marked DOWN and still running then
1270 if ((ifp->if_flags & IFF_UP) == 0 && sc->flags & DSF_RUNNING) {
1271 if_printf(ifp, "ioctl(): board is not running\n");
1272 sc->flags &= ~DSF_RUNNING;
1273 sc->hacr &= ~HACR_INTRON;
1274 CMD(sc); /* turn off interrupts */
1276 /* else if interface is UP and RUNNING, start it
1278 else if (ifp->if_flags & IFF_UP && (sc->flags & DSF_RUNNING) == 0) {
1282 /* if WLDEBUG set on interface, then printf rf-modem regs
1284 if (ifp->if_flags & IFF_DEBUG)
1294 #endif /* MULTICAST */
1296 /* DEVICE SPECIFIC */
1299 /* copy the PSA out to the caller */
1301 /* work out if they're root */
1302 isroot = (priv_check(td, PRIV_NET80211_GETKEY) == 0);
1304 bzero(psa_buf, sizeof(psa_buf));
1306 for (i = 0; i < 0x40; i++) {
1307 /* don't hand the DES key out to non-root users */
1308 if ((i > WLPSA_DESKEY) && (i < (WLPSA_DESKEY + 8)) && !isroot)
1310 psa_buf[i] = sc->psa[i];
1314 error = copyout(psa_buf, ifr->ifr_data, sizeof(psa_buf));
1318 /* copy the PSA in from the caller; we only copy _some_ values */
1321 if ((error = priv_check(td, PRIV_DRIVER)))
1324 error = copyin(ifr->ifr_data, psa_buf, sizeof(psa_buf));
1328 /* check IRQ value */
1329 irqval = psa_buf[WLPSA_IRQNO];
1330 for (irq = 15; irq >= 0; irq--)
1331 if (irqvals[irq] == irqval)
1333 if (irq == 0) /* oops */
1337 sc->psa[WLPSA_IRQNO] = irqval;
1340 for (i = 0; i < 6; i++)
1341 sc->psa[WLPSA_LOCALMAC + i] = psa_buf[WLPSA_LOCALMAC + i];
1344 sc->psa[WLPSA_MACSEL] = psa_buf[WLPSA_MACSEL];
1347 sc->psa[WLPSA_NWID] = psa_buf[WLPSA_NWID];
1348 sc->psa[WLPSA_NWID + 1] = psa_buf[WLPSA_NWID + 1];
1350 wlsetpsa(sc); /* update the PSA */
1355 /* get the current NWID out of the sc since we stored it there */
1358 ifr->ifr_data = (caddr_t) (sc->nwid[0] << 8 | sc->nwid[1]);
1364 * change the nwid dynamically. This
1365 * ONLY changes the radio modem and does not
1369 * 1. save in softc "soft registers"
1370 * 2. save in radio modem (MMC)
1374 if ((error = priv_check(td, PRIV_DRIVER)))
1377 if (!(ifp->if_flags & IFF_UP)) {
1378 error = EIO; /* only allowed while up */
1381 * soft c nwid shadows radio modem setting
1383 sc->nwid[0] = (int)ifr->ifr_data >> 8;
1384 sc->nwid[1] = (int)ifr->ifr_data & 0xff;
1385 MMC_WRITE(MMC_NETW_ID_L,sc->nwid[1]);
1386 MMC_WRITE(MMC_NETW_ID_H,sc->nwid[0]);
1391 /* copy the EEPROM in 2.4 Gz WaveMODEM out to the caller */
1394 if ((error = priv_check(td, PRIV_DRIVER)))
1397 bzero(eeprom_buf, sizeof(eeprom_buf));
1399 for (i=0x00; i<0x80; ++i) { /* 2.4 Gz: size of EEPROM */
1400 MMC_WRITE(MMC_EEADDR,i); /* 2.4 Gz: get frequency */
1401 MMC_WRITE(MMC_EECTRL, /* 2.4 Gz: EEPROM read */
1402 MMC_EECTRL_EEOP_READ); /* 2.4 Gz: */
1403 DELAY(40); /* 2.4 Gz */
1404 eeprom_buf[2 * i] = /* 2.4 Gz: pass low byte of */
1405 wlmmcread(sc, MMC_EEDATALrv); /* 2.4 Gz: EEPROM word */
1406 eeprom_buf[2 * i + 1] = /* 2.4 Gz: pass hi byte of */
1407 wlmmcread(sc, MMC_EEDATALrv); /* 2.4 Gz: EEPROM word */
1410 error = copyout(ifr->ifr_data, eeprom_buf, sizeof(eeprom_buf));
1414 /* zero (Delete) the wl cache */
1417 if ((error = priv_check(td, PRIV_DRIVER)))
1424 /* read out the number of used cache elements */
1427 ifr->ifr_data = (caddr_t) sc->w_sigitems;
1431 /* read out the wl cache */
1434 size = sc->w_sigitems * sizeof(struct w_sigcache);
1435 cpt = malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO);
1441 bcopy(sc->w_sigcache, cpt, size);
1444 error = copyout(cpt, ifr->ifr_data, size);
1445 free(cpt, M_DEVBUF);
1450 error = ether_ioctl(ifp, cmd, data);
1459 * Called if the timer set in wlstart expires before an interrupt is received
1460 * from the wavelan. It seems to lose interrupts sometimes.
1461 * The watchdog routine gets called if the transmitter failed to interrupt
1463 * input : which board is timing out
1464 * output : board reset
1468 wlwatchdog(void *vsc)
1470 struct wl_softc *sc = vsc;
1472 log(LOG_ERR, "%s: wavelan device timeout on xmit\n", sc->ifp->if_xname);
1473 if_inc_counter(sc->ifp, IFCOUNTER_OERRORS, 1);
1480 * This function is the interrupt handler for the WaveLAN
1481 * board. This routine will be called whenever either a packet
1482 * is received, or a packet has successfully been transferred and
1483 * the unit is ready to transmit another packet.
1485 * input : board number that interrupted
1486 * output : either a packet is received, or a packet is transferred
1492 struct wl_softc *sc = (struct wl_softc *)arg;
1494 u_short int_type, int_type1;
1498 if (sc->ifp->if_flags & IFF_DEBUG)
1499 if_printf(sc->ifp, "wlintr() called\n");
1502 if ((int_type = WL_READ_2(sc, HASR)) & HASR_MMC_INTR) {
1503 /* handle interrupt from the modem management controller */
1504 /* This will clear the interrupt condition */
1505 (void) wlmmcread(sc, MMC_DCE_STATUS); /* ignored for now */
1508 if (!(int_type & HASR_INTR)){ /* return if no interrupt from 82586 */
1509 /* commented out. jrb. it happens when reinit occurs
1510 printf("wlintr: int_type %x, dump follows\n", int_type);
1520 WL_WRITE_2(sc, PIOR0, OFFSET_SCB + 0); /* get scb status */
1521 int_type = (WL_READ_2(sc, PIOP0) & SCB_SW_INT);
1522 if (int_type == 0) /* no interrupts left */
1525 int_type1 = wlack(sc); /* acknowledge interrupt(s) */
1526 /* make sure no bits disappeared (others may appear) */
1527 if ((int_type & int_type1) != int_type)
1528 printf("wlack() int bits disappeared : %04x != int_type %04x\n",
1529 int_type1, int_type);
1530 int_type = int_type1; /* go with the new status */
1534 if (int_type & SCB_SW_FR) {
1535 if_inc_counter(sc->ifp, IFCOUNTER_IPACKETS, 1);
1539 * receiver not ready
1541 if (int_type & SCB_SW_RNR) {
1542 if_inc_counter(sc->ifp, IFCOUNTER_IERRORS, 1);
1544 if (sc->ifp->if_flags & IFF_DEBUG)
1545 if_printf(sc->ifp, "intr(): receiver overrun! begin_fd = %x\n",
1553 if (int_type & SCB_SW_CNA) {
1555 * At present, we don't care about CNA's. We
1556 * believe they are a side effect of XMT.
1559 if (int_type & SCB_SW_CX) {
1561 * At present, we only request Interrupt for
1564 WL_WRITE_2(sc, PIOR1, OFFSET_CU); /* get command status */
1565 ac_status = WL_READ_2(sc, PIOP1);
1567 if (xmt_watch) { /* report some anomalies */
1569 if (sc->tbusy == 0) {
1570 if_printf(sc->ifp, "xmt intr but not busy, CU %04x\n",
1573 if (ac_status == 0) {
1574 if_printf(sc->ifp, "xmt intr but ac_status == 0\n");
1576 if (ac_status & AC_SW_A) {
1577 if_printf(sc->ifp, "xmt aborted\n");
1580 if (ac_status & TC_CARRIER) {
1581 if_printf(sc->ifp, "no carrier\n");
1584 if (ac_status & TC_CLS) {
1585 if_printf(sc->ifp, "no CTS\n");
1587 if (ac_status & TC_DMA) {
1588 if_printf(sc->ifp, "DMA underrun\n");
1590 if (ac_status & TC_DEFER) {
1591 if_printf(sc->ifp, "xmt deferred\n");
1593 if (ac_status & TC_SQE) {
1594 if_printf(sc->ifp, "heart beat\n");
1596 if (ac_status & TC_COLLISION) {
1597 if_printf(sc->ifp, "too many collisions\n");
1600 /* if the transmit actually failed, or returned some status */
1601 if ((!(ac_status & AC_SW_OK)) || (ac_status & 0xfff)) {
1602 if (ac_status & (TC_COLLISION | TC_CLS | TC_DMA)) {
1603 if_inc_counter(sc->ifp, IFCOUNTER_OERRORS, 1);
1605 /* count collisions */
1606 if_inc_counter(sc->ifp, IFCOUNTER_COLLISIONS, (ac_status & 0xf));
1607 /* if TC_COLLISION set and collision count zero, 16 collisions */
1608 if ((ac_status & 0x20) == 0x20) {
1609 if_inc_counter(sc->ifp, IFCOUNTER_COLLISIONS, 0x10);
1613 callout_stop(&sc->watchdog_timer);
1614 sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1615 wlstart_locked(sc->ifp);
1625 * This routine is called by the interrupt handler to initiate a
1626 * packet transfer from the board to the "if" layer above this
1627 * driver. This routine checks if a buffer has been successfully
1628 * received by the WaveLAN. If so, the routine wlread is called
1629 * to do the actual transfer of the board data (including the
1630 * ethernet header) into a packet (consisting of an mbuf chain).
1632 * input : number of the board to check
1633 * output : if a packet is available, it is "sent up"
1637 wlrcv(struct wl_softc *sc)
1639 u_short fd_p, status, offset, link_offset;
1642 if (sc->ifp->if_flags & IFF_DEBUG)
1643 if_printf(sc->ifp, "entered wlrcv()\n");
1645 for (fd_p = sc->begin_fd; fd_p != I82586NULL; fd_p = sc->begin_fd) {
1647 WL_WRITE_2(sc, PIOR0, fd_p + 0); /* address of status */
1648 status = WL_READ_2(sc, PIOP0);
1649 WL_WRITE_2(sc, PIOR1, fd_p + 4); /* address of link_offset */
1650 link_offset = WL_READ_2(sc, PIOP1);
1651 offset = WL_READ_2(sc, PIOP1); /* rbd_offset */
1652 if (status == 0xffff || offset == 0xffff /*I82586NULL*/) {
1653 if (wlhwrst(sc) != TRUE)
1654 if_printf(sc->ifp, "rcv(): hwrst ffff trouble.\n");
1656 } else if (status & AC_SW_C) {
1657 if (status == (RFD_DONE|RFD_RSC)) {
1660 if (sc->ifp->if_flags & IFF_DEBUG)
1661 if_printf(sc->ifp, "RCV: RSC %x\n", status);
1663 if_inc_counter(sc->ifp, IFCOUNTER_IERRORS, 1);
1664 } else if (!(status & RFD_OK)) {
1665 if_printf(sc->ifp, "RCV: !OK %x\n", status);
1666 if_inc_counter(sc->ifp, IFCOUNTER_IERRORS, 1);
1667 } else if (status & 0xfff) { /* can't happen */
1668 if_printf(sc->ifp, "RCV: ERRs %x\n", status);
1669 if_inc_counter(sc->ifp, IFCOUNTER_IERRORS, 1);
1670 } else if (!wlread(sc, fd_p))
1673 if (!wlrequeue(sc, fd_p)) {
1674 /* abort on chain error */
1675 if (wlhwrst(sc) != TRUE)
1676 if_printf(sc->ifp, "rcv(): hwrst trouble.\n");
1679 sc->begin_fd = link_offset;
1690 * This routine puts rbd's used in the last receive back onto the
1691 * free list for the next receive.
1695 wlrequeue(struct wl_softc *sc, u_short fd_p)
1698 u_short l_rbdp, f_rbdp, rbd_offset;
1700 WL_WRITE_2(sc, PIOR0, fd_p + 6);
1701 rbd_offset = WL_READ_2(sc, PIOP0);
1702 if ((f_rbdp = rbd_offset) != I82586NULL) {
1705 WL_WRITE_2(sc, PIOR0, l_rbdp + 0); /* address of status */
1706 if (WL_READ_2(sc, PIOP0) & RBD_SW_EOF)
1708 WL_WRITE_2(sc, PIOP0, 0);
1709 WL_WRITE_2(sc, PIOR0, l_rbdp + 2); /* next_rbd_offset */
1710 if ((l_rbdp = WL_READ_2(sc, PIOP0)) == I82586NULL)
1713 WL_WRITE_2(sc, PIOP0, 0);
1714 WL_WRITE_2(sc, PIOR0, l_rbdp + 2); /* next_rbd_offset */
1715 WL_WRITE_2(sc, PIOP0, I82586NULL);
1716 WL_WRITE_2(sc, PIOR0, l_rbdp + 8); /* address of size */
1717 WL_WRITE_2(sc, PIOP0, WL_READ_2(sc, PIOP0) | AC_CW_EL);
1718 WL_WRITE_2(sc, PIOR0, sc->end_rbd + 2);
1719 WL_WRITE_2(sc, PIOP0, f_rbdp); /* end_rbd->next_rbd_offset */
1720 WL_WRITE_2(sc, PIOR0, sc->end_rbd + 8); /* size */
1721 WL_WRITE_2(sc, PIOP0, WL_READ_2(sc, PIOP0) & ~AC_CW_EL);
1722 sc->end_rbd = l_rbdp;
1726 fd.command = AC_CW_EL;
1727 fd.link_offset = I82586NULL;
1728 fd.rbd_offset = I82586NULL;
1729 WL_WRITE_2(sc, PIOR1, fd_p);
1730 WL_WRITE_MULTI_2(sc, PIOP1, &fd, 8/2);
1732 WL_WRITE_2(sc, PIOR1, sc->end_fd + 2); /* addr of command */
1733 WL_WRITE_2(sc, PIOP1, 0); /* command = 0 */
1734 WL_WRITE_2(sc, PIOP1, fd_p); /* end_fd->link_offset = fd_p */
1741 static int xmt_debug = 0;
1742 #endif /* WLDEBUG */
1747 * This routine fills in the appropriate registers and memory
1748 * locations on the WaveLAN board and starts the board off on
1751 * input : pointers to board of interest's softc and the mbuf
1752 * output : board memory and registers are set for xfer and attention
1756 wlxmt(struct wl_softc *sc, struct mbuf *m)
1758 u_short xmtdata_p = OFFSET_TBUF;
1760 struct mbuf *tm_p = m;
1761 struct ether_header *eh_p = mtod(m, struct ether_header *);
1762 u_char *mb_p = mtod(m, u_char *) + sizeof(struct ether_header);
1763 u_short count = m->m_len - sizeof(struct ether_header);
1765 u_short tbd_p = OFFSET_TBD;
1766 u_short len, clen = 0;
1770 if (sc->ifp->if_flags & IFF_DEBUG)
1771 if_printf(sc->ifp, "entered wlxmt()\n");
1775 cb.ac_command = (AC_CW_EL|AC_TRANSMIT|AC_CW_I);
1776 cb.ac_link_offset = I82586NULL;
1777 WL_WRITE_2(sc, PIOR1, OFFSET_CU);
1778 WL_WRITE_MULTI_2(sc, PIOP1, &cb, 6/2);
1779 WL_WRITE_2(sc, PIOP1, OFFSET_TBD); /* cb.cmd.transmit.tbd_offset */
1780 WL_WRITE_MULTI_2(sc, PIOP1, eh_p->ether_dhost, WAVELAN_ADDR_SIZE/2);
1781 WL_WRITE_2(sc, PIOP1, eh_p->ether_type);
1784 if (sc->ifp->if_flags & IFF_DEBUG) {
1786 printf("XMT mbuf: L%d @%p ", count, (void *)mb_p);
1787 printf("ether type %x\n", eh_p->ether_type);
1790 #endif /* WLDEBUG */
1791 WL_WRITE_2(sc, PIOR0, OFFSET_TBD);
1792 WL_WRITE_2(sc, PIOP0, 0); /* act_count */
1793 WL_WRITE_2(sc, PIOR1, OFFSET_TBD + 4);
1794 WL_WRITE_2(sc, PIOP1, xmtdata_p); /* buffer_addr */
1795 WL_WRITE_2(sc, PIOP1, 0); /* buffer_base */
1798 if (clen + count > WAVELAN_MTU)
1804 WL_WRITE_2(sc, PIOR1, xmtdata_p);
1805 WL_WRITE_MULTI_2(sc, PIOP1, mb_p, len/2);
1807 WL_WRITE_2(sc, PIOR0, tbd_p); /* address of act_count */
1808 WL_WRITE_2(sc, PIOP0, WL_READ_2(sc, PIOP0) + count);
1810 if ((tm_p = tm_p->m_next) == (struct mbuf *)0)
1813 /* go to the next descriptor */
1814 WL_WRITE_2(sc, PIOR0, tbd_p + 2);
1815 tbd_p += sizeof (tbd_t);
1816 WL_WRITE_2(sc, PIOP0, tbd_p); /* next_tbd_offset */
1817 WL_WRITE_2(sc, PIOR0, tbd_p);
1818 WL_WRITE_2(sc, PIOP0, 0); /* act_count */
1819 WL_WRITE_2(sc, PIOR1, tbd_p + 4);
1820 WL_WRITE_2(sc, PIOP1, xmtdata_p); /* buffer_addr */
1821 WL_WRITE_2(sc, PIOP1, 0); /* buffer_base */
1822 /* at the end -> coallesce remaining mbufs */
1823 if (tbd_p == OFFSET_TBD + (N_TBD-1) * sizeof (tbd_t)) {
1824 wlsftwsleaze(&count, &mb_p, &tm_p, sc);
1827 /* next mbuf short -> coallesce as needed */
1828 if ( (tm_p->m_next == (struct mbuf *) 0) ||
1829 #define HDW_THRESHOLD 55
1830 tm_p->m_len > HDW_THRESHOLD)
1833 wlhdwsleaze(&count, &mb_p, &tm_p, sc);
1837 } else if ((tm_p = tm_p->m_next) == (struct mbuf *)0)
1839 count = tm_p->m_len;
1840 mb_p = mtod(tm_p, u_char *);
1842 if (sc->ifp->if_flags & IFF_DEBUG)
1844 printf("mbuf+ L%d @%p ", count, (void *)mb_p);
1845 #endif /* WLDEBUG */
1848 if (sc->ifp->if_flags & IFF_DEBUG)
1850 printf("CLEN = %d\n", clen);
1851 #endif /* WLDEBUG */
1852 WL_WRITE_2(sc, PIOR0, tbd_p);
1853 if (clen < ETHERMIN) {
1854 WL_WRITE_2(sc, PIOP0, WL_READ_2(sc, PIOP0) + ETHERMIN - clen);
1855 WL_WRITE_2(sc, PIOR1, xmtdata_p);
1856 for (xmtshort_p = xmtdata_p; clen < ETHERMIN; clen += 2)
1857 WL_WRITE_2(sc, PIOP1, 0);
1859 WL_WRITE_2(sc, PIOP0, WL_READ_2(sc, PIOP0) | TBD_SW_EOF);
1860 WL_WRITE_2(sc, PIOR0, tbd_p + 2);
1861 WL_WRITE_2(sc, PIOP0, I82586NULL);
1863 if (sc->ifp->if_flags & IFF_DEBUG) {
1869 #endif /* WLDEBUG */
1871 WL_WRITE_2(sc, PIOR0, OFFSET_SCB + 2); /* address of scb_command */
1873 * wait for 586 to clear previous command, complain if it takes
1876 for (spin = 1;;spin = (spin + 1) % 10000) {
1877 if (WL_READ_2(sc, PIOP0) == 0) { /* it's done, we can go */
1880 if ((spin == 0) && xmt_watch) { /* not waking up, and we care */
1881 if_printf(sc->ifp, "slow accepting xmit\n");
1884 WL_WRITE_2(sc, PIOP0, SCB_CU_STRT); /* new command */
1890 * Pause to avoid transmit overrun problems.
1891 * The required delay tends to vary with platform type, and may be
1892 * related to interrupt loss.
1894 if (wl_xmit_delay) {
1895 DELAY(wl_xmit_delay);
1903 * This function builds the linear linked lists of fd's and
1904 * rbd's. Based on page 4-32 of 1986 Intel microcom handbook.
1908 wlbldru(struct wl_softc *sc)
1912 u_short fd_p = OFFSET_RU;
1913 u_short rbd_p = OFFSET_RBD;
1916 sc->begin_fd = fd_p;
1917 for (i = 0; i < N_FD; i++) {
1920 fd.link_offset = fd_p + sizeof(fd_t);
1921 fd.rbd_offset = I82586NULL;
1922 WL_WRITE_2(sc, PIOR1, fd_p);
1923 WL_WRITE_MULTI_2(sc, PIOP1, &fd, 8/2);
1924 fd_p = fd.link_offset;
1926 fd_p -= sizeof(fd_t);
1928 WL_WRITE_2(sc, PIOR1, fd_p + 2);
1929 WL_WRITE_2(sc, PIOP1, AC_CW_EL); /* command */
1930 WL_WRITE_2(sc, PIOP1, I82586NULL); /* link_offset */
1933 WL_WRITE_2(sc, PIOR0, fd_p + 6); /* address of rbd_offset */
1934 WL_WRITE_2(sc, PIOP0, rbd_p);
1935 WL_WRITE_2(sc, PIOR1, rbd_p);
1936 for (i = 0; i < N_RBD; i++) {
1938 rbd.buffer_addr = rbd_p + sizeof(rbd_t) + 2;
1939 rbd.buffer_base = 0;
1940 rbd.size = RCVBUFSIZE;
1942 rbd_p += sizeof(ru_t);
1943 rbd.next_rbd_offset = rbd_p;
1945 rbd.next_rbd_offset = I82586NULL;
1946 rbd.size |= AC_CW_EL;
1947 sc->end_rbd = rbd_p;
1949 WL_WRITE_MULTI_2(sc, PIOP1, &rbd, sizeof(rbd_t)/2);
1950 WL_WRITE_2(sc, PIOR1, rbd_p);
1952 return sc->begin_fd;
1958 * This routine starts the receive unit running. First checks if the
1959 * board is actually ready, then the board is instructed to receive
1964 wlrustrt(struct wl_softc *sc)
1969 if (sc->ifp->if_flags & IFF_DEBUG)
1970 if_printf(sc->ifp, "entered wlrustrt()\n");
1972 WL_WRITE_2(sc, PIOR0, OFFSET_SCB);
1973 if (WL_READ_2(sc, PIOP0) & SCB_RUS_READY){
1974 printf("wlrustrt: RUS_READY\n");
1978 WL_WRITE_2(sc, PIOR0, OFFSET_SCB + 2);
1979 WL_WRITE_2(sc, PIOP0, SCB_RU_STRT); /* command */
1981 WL_WRITE_2(sc, PIOR0, OFFSET_SCB + 6); /* address of scb_rfa_offset */
1982 WL_WRITE_2(sc, PIOP0, rfa);
1991 * This routine does a 586 op-code number 7, and obtains the
1992 * diagnose status for the WaveLAN.
1996 wldiag(struct wl_softc *sc)
2001 if (sc->ifp->if_flags & IFF_DEBUG)
2002 if_printf(sc->ifp, "entered wldiag()\n");
2004 WL_WRITE_2(sc, PIOR0, OFFSET_SCB);
2005 status = WL_READ_2(sc, PIOP0);
2006 if (status & SCB_SW_INT) {
2007 /* state is 2000 which seems ok
2008 if_printf(sc->ifp, "diag(): unexpected initial state %\n",
2009 WL_READ_2(sc, PIOP0));
2013 WL_WRITE_2(sc, PIOR1, OFFSET_CU);
2014 WL_WRITE_2(sc, PIOP1, 0); /* ac_status */
2015 WL_WRITE_2(sc, PIOP1, AC_DIAGNOSE|AC_CW_EL);/* ac_command */
2016 if (wlcmd(sc, "diag()") == 0)
2018 WL_WRITE_2(sc, PIOR0, OFFSET_CU);
2019 if (WL_READ_2(sc, PIOP0) & 0x0800) {
2020 if_printf(sc->ifp, "i82586 Self Test failed!\n");
2029 * This routine does a standard config of the WaveLAN board.
2033 wlconfig(struct wl_softc *sc)
2035 configure_t configure;
2038 struct ifmultiaddr *ifma;
2041 #endif /* MULTICAST */
2044 if (sc->ifp->if_flags & IFF_DEBUG)
2045 if_printf(sc->ifp, "entered wlconfig()\n");
2047 WL_WRITE_2(sc, PIOR0, OFFSET_SCB);
2048 if (WL_READ_2(sc, PIOP0) & SCB_SW_INT) {
2050 if_printf(sc->ifp, "config(): unexpected initial state %x\n",
2051 WL_READ_2(sc, PIOP0));
2056 WL_WRITE_2(sc, PIOR1, OFFSET_CU);
2057 WL_WRITE_2(sc, PIOP1, 0); /* ac_status */
2058 WL_WRITE_2(sc, PIOP1, AC_CONFIGURE|AC_CW_EL); /* ac_command */
2061 configure.fifolim_bytecnt = 0x080c;
2062 configure.addrlen_mode = 0x0600;
2063 configure.linprio_interframe = 0x2060;
2064 configure.slot_time = 0xf200;
2065 configure.hardware = 0x0008; /* tx even w/o CD */
2066 configure.min_frame_len = 0x0040;
2068 /* This is the configuration block suggested by Marc Meertens
2069 * <mmeerten@obelix.utrecht.NCR.COM> in an e-mail message to John
2070 * Ioannidis on 10 Nov 92.
2072 configure.fifolim_bytecnt = 0x040c;
2073 configure.addrlen_mode = 0x0600;
2074 configure.linprio_interframe = 0x2060;
2075 configure.slot_time = 0xf000;
2076 configure.hardware = 0x0008; /* tx even w/o CD */
2077 configure.min_frame_len = 0x0040;
2080 * below is the default board configuration from p2-28 from 586 book
2082 configure.fifolim_bytecnt = 0x080c;
2083 configure.addrlen_mode = 0x2600;
2084 configure.linprio_interframe = 0x7820; /* IFS=120, ACS=2 */
2085 configure.slot_time = 0xf00c; /* slottime=12 */
2086 configure.hardware = 0x0008; /* tx even w/o CD */
2087 configure.min_frame_len = 0x0040;
2089 if (sc->mode & (MOD_PROM | MOD_ENAL))
2090 configure.hardware |= 1;
2091 WL_WRITE_2(sc, PIOR1, OFFSET_CU + 6);
2092 WL_WRITE_MULTI_2(sc, PIOP1, &configure, sizeof(configure_t)/2);
2094 if (wlcmd(sc, "config()-configure") == 0)
2097 WL_WRITE_2(sc, PIOR1, OFFSET_CU);
2098 WL_WRITE_2(sc, PIOP1, 0); /* ac_status */
2099 WL_WRITE_2(sc, PIOP1, AC_MCSETUP|AC_CW_EL); /* ac_command */
2100 WL_WRITE_2(sc, PIOR1, OFFSET_CU + 8);
2101 if_maddr_rlock(sc->ifp);
2102 TAILQ_FOREACH(ifma, &sc->ifp->if_multiaddrs, ifma_link) {
2103 if (ifma->ifma_addr->sa_family != AF_LINK)
2106 addrp = LLADDR((struct sockaddr_dl *)ifma->ifma_addr);
2107 WL_WRITE_2(sc, PIOP1, addrp[0] + (addrp[1] << 8));
2108 WL_WRITE_2(sc, PIOP1, addrp[2] + (addrp[3] << 8));
2109 WL_WRITE_2(sc, PIOP1, addrp[4] + (addrp[5] << 8));
2112 if_maddr_runlock(sc->ifp);
2113 WL_WRITE_2(sc, PIOR1, OFFSET_CU + 6); /* mc-cnt */
2114 WL_WRITE_2(sc, PIOP1, cnt * WAVELAN_ADDR_SIZE);
2115 if (wlcmd(sc, "config()-mcaddress") == 0)
2117 #endif /* MULTICAST */
2119 WL_WRITE_2(sc, PIOR1, OFFSET_CU);
2120 WL_WRITE_2(sc, PIOP1, 0); /* ac_status */
2121 WL_WRITE_2(sc, PIOP1, AC_IASETUP|AC_CW_EL); /* ac_command */
2122 WL_WRITE_2(sc, PIOR1, OFFSET_CU + 6);
2123 WL_WRITE_MULTI_2(sc, PIOP1, IF_LLADDR(sc->ifp), WAVELAN_ADDR_SIZE/2);
2125 if (wlcmd(sc, "config()-address") == 0)
2136 * Set channel attention bit and busy wait until command has
2137 * completed. Then acknowledge the command completion.
2140 wlcmd(struct wl_softc *sc, char *str)
2144 WL_WRITE_2(sc, PIOR0, OFFSET_SCB + 2); /* address of scb_command */
2145 WL_WRITE_2(sc, PIOP0, SCB_CU_STRT);
2149 WL_WRITE_2(sc, PIOR0, OFFSET_CU);
2150 for (i = 0; i < 0xffff; i++)
2151 if (WL_READ_2(sc, PIOP0) & AC_SW_C)
2153 if (i == 0xffff || !(WL_READ_2(sc, PIOP0) & AC_SW_OK)) {
2154 if_printf(sc->ifp, "%s failed; status = %d, inw = %x, outw = %x\n",
2155 str, WL_READ_2(sc, PIOP0) & AC_SW_OK, WL_READ_2(sc, PIOP0),
2156 WL_READ_2(sc, PIOR0));
2157 WL_WRITE_2(sc, PIOR0, OFFSET_SCB);
2158 printf("scb_status %x\n", WL_READ_2(sc, PIOP0));
2159 WL_WRITE_2(sc, PIOR0, OFFSET_SCB+2);
2160 printf("scb_command %x\n", WL_READ_2(sc, PIOP0));
2161 WL_WRITE_2(sc, PIOR0, OFFSET_SCB+4);
2162 printf("scb_cbl %x\n", WL_READ_2(sc, PIOP0));
2163 WL_WRITE_2(sc, PIOR0, OFFSET_CU+2);
2164 printf("cu_cmd %x\n", WL_READ_2(sc, PIOP0));
2168 WL_WRITE_2(sc, PIOR0, OFFSET_SCB);
2169 if ((WL_READ_2(sc, PIOP0) & SCB_SW_INT) &&
2170 (WL_READ_2(sc, PIOP0) != SCB_SW_CNA)) {
2172 if_printf(sc->ifp, "%s: unexpected final state %x\n",
2173 str, WL_READ_2(sc, PIOP0));
2181 * wlack: if the 82596 wants attention because it has finished
2182 * sending or receiving a packet, acknowledge its desire and
2183 * return bits indicating the kind of attention. wlack() returns
2184 * these bits so that the caller can service exactly the
2185 * conditions that wlack() acknowledged.
2188 wlack(struct wl_softc *sc)
2193 WL_WRITE_2(sc, PIOR1, OFFSET_SCB);
2194 if (!(cmd = (WL_READ_2(sc, PIOP1) & SCB_SW_INT)))
2197 if (sc->ifp->if_flags & IFF_DEBUG)
2198 if_printf(sc->ifp, "doing a wlack()\n");
2200 WL_WRITE_2(sc, PIOP1, cmd);
2202 WL_WRITE_2(sc, PIOR0, OFFSET_SCB + 2); /* address of scb_command */
2203 for (i = 1000000; WL_READ_2(sc, PIOP0) && (i-- > 0); )
2206 if_printf(sc->ifp, "wlack(): board not accepting command.\n");
2212 wltbd(struct wl_softc *sc)
2214 u_short tbd_p = OFFSET_TBD;
2220 WL_WRITE_2(sc, PIOR1, tbd_p);
2221 WL_READ_MULTI_2(sc, PIOP1, &tbd, sizeof(tbd_t)/2);
2222 sum += (tbd.act_count & ~TBD_SW_EOF);
2223 printf("%d: addr %x, count %d (%d), next %x, base %x\n",
2224 i++, tbd.buffer_addr,
2225 (tbd.act_count & ~TBD_SW_EOF), sum,
2226 tbd.next_tbd_offset, tbd.buffer_base);
2227 if (tbd.act_count & TBD_SW_EOF)
2229 tbd_p = tbd.next_tbd_offset;
2235 wlhdwsleaze(u_short *countp, u_char **mb_pp, struct mbuf **tm_pp, struct wl_softc *sc)
2237 struct mbuf *tm_p = *tm_pp;
2238 u_char *mb_p = *mb_pp;
2244 * can we get a run that will be coallesced or
2245 * that terminates before breaking
2248 count += tm_p->m_len;
2249 if (tm_p->m_len & 1)
2251 } while ((tm_p = tm_p->m_next) != (struct mbuf *)0);
2252 if ( (tm_p == (struct mbuf *)0) ||
2253 count > HDW_THRESHOLD) {
2254 *countp = (*tm_pp)->m_len;
2255 *mb_pp = mtod((*tm_pp), u_char *);
2259 /* we need to copy */
2263 cp = (u_char *) t_packet;
2265 bcopy(mtod(tm_p, u_char *), cp, len = tm_p->m_len);
2267 if (count > HDW_THRESHOLD)
2270 if (tm_p->m_next == (struct mbuf *)0)
2272 tm_p = tm_p->m_next;
2275 *mb_pp = (u_char *) t_packet;
2282 wlsftwsleaze(u_short *countp, u_char **mb_pp, struct mbuf **tm_pp, struct wl_softc *sc)
2284 struct mbuf *tm_p = *tm_pp;
2286 u_char *cp = (u_char *) t_packet;
2289 /* we need to copy */
2291 bcopy(mtod(tm_p, u_char *), cp, len = tm_p->m_len);
2294 if (tm_p->m_next == (struct mbuf *)0)
2296 tm_p = tm_p->m_next;
2300 *mb_pp = (u_char *) t_packet;
2306 wlmmcstat(struct wl_softc *sc)
2310 device_printf(sc->dev, "DCE_STATUS: 0x%x, ",
2311 wlmmcread(sc, MMC_DCE_STATUS) & 0x0f);
2312 tmp = wlmmcread(sc, MMC_CORRECT_NWID_H) << 8;
2313 tmp |= wlmmcread(sc, MMC_CORRECT_NWID_L);
2314 printf("Correct NWID's: %d, ", tmp);
2315 tmp = wlmmcread(sc, MMC_WRONG_NWID_H) << 8;
2316 tmp |= wlmmcread(sc, MMC_WRONG_NWID_L);
2317 printf("Wrong NWID's: %d\n", tmp);
2318 printf("THR_PRE_SET: 0x%x, ", wlmmcread(sc, MMC_THR_PRE_SET));
2319 printf("SIGNAL_LVL: %d, SILENCE_LVL: %d\n",
2320 wlmmcread(sc, MMC_SIGNAL_LVL),
2321 wlmmcread(sc, MMC_SILENCE_LVL));
2322 printf("SIGN_QUAL: 0x%x, NETW_ID: %x:%x, DES: %d\n",
2323 wlmmcread(sc, MMC_SIGN_QUAL),
2324 wlmmcread(sc, MMC_NETW_ID_H),
2325 wlmmcread(sc, MMC_NETW_ID_L),
2326 wlmmcread(sc, MMC_DES_AVAIL));
2330 wlmmcread(struct wl_softc *sc, u_short reg)
2332 while (WL_READ_2(sc, HASR) & HASR_MMC_BUSY)
2334 WL_WRITE_2(sc, MMCR,reg << 1);
2335 while (WL_READ_2(sc, HASR) & HASR_MMC_BUSY)
2337 return (u_short)WL_READ_2(sc, MMCR) >> 8;
2341 getsnr(struct wl_softc *sc)
2343 MMC_WRITE(MMC_FREEZE,1);
2345 * SNR retrieval procedure :
2347 * read signal level : wlmmcread(sc, MMC_SIGNAL_LVL);
2348 * read silence level : wlmmcread(sc, MMC_SILENCE_LVL);
2350 MMC_WRITE(MMC_FREEZE,0);
2352 * SNR is signal:silence ratio.
2359 ** Reads the psa for the wavelan at (sc) into (buf)
2362 wlgetpsa(struct wl_softc *sc, u_char *buf)
2366 PCMD(sc, HACR_DEFAULT & ~HACR_16BITS);
2367 PCMD(sc, HACR_DEFAULT & ~HACR_16BITS);
2369 for (i = 0; i < 0x40; i++) {
2370 WL_WRITE_2(sc, PIOR2, i);
2371 buf[i] = WL_READ_1(sc, PIOP2);
2373 PCMD(sc, HACR_DEFAULT);
2374 PCMD(sc, HACR_DEFAULT);
2380 ** Writes the psa for wavelan (unit) from the softc back to the
2381 ** board. Updates the CRC and sets the CRC OK flag.
2383 ** Do not call this when the board is operating, as it doesn't
2384 ** preserve the hacr.
2387 wlsetpsa(struct wl_softc *sc)
2392 crc = wlpsacrc(sc->psa); /* calculate CRC of PSA */
2393 sc->psa[WLPSA_CRCLOW] = crc & 0xff;
2394 sc->psa[WLPSA_CRCHIGH] = (crc >> 8) & 0xff;
2395 sc->psa[WLPSA_CRCOK] = 0x55; /* default to 'bad' until programming complete */
2397 PCMD(sc, HACR_DEFAULT & ~HACR_16BITS);
2398 PCMD(sc, HACR_DEFAULT & ~HACR_16BITS);
2400 for (i = 0; i < 0x40; i++) {
2402 WL_WRITE_2(sc, PIOR2, i); /* write param memory */
2404 WL_WRITE_1(sc, PIOP2, sc->psa[i]);
2407 WL_WRITE_2(sc, PIOR2, WLPSA_CRCOK); /* update CRC flag*/
2409 sc->psa[WLPSA_CRCOK] = 0xaa; /* OK now */
2410 WL_WRITE_1(sc, PIOP2, 0xaa); /* all OK */
2413 PCMD(sc, HACR_DEFAULT);
2414 PCMD(sc, HACR_DEFAULT);
2418 ** CRC routine provided by Christopher Giordano <cgiordan@gdeb.com>,
2419 ** from original code by Tomi Mikkonen (tomitm@remedy.fi)
2422 static u_int crc16_table[16] = {
2423 0x0000, 0xCC01, 0xD801, 0x1400,
2424 0xF001, 0x3C00, 0x2800, 0xE401,
2425 0xA001, 0x6C00, 0x7800, 0xB401,
2426 0x5000, 0x9C01, 0x8801, 0x4400
2430 wlpsacrc(u_char *buf)
2435 for (i = 0; i < 0x3d; i++, buf++) {
2437 r1 = crc16_table[crc & 0xF];
2438 crc = (crc >> 4) & 0x0FFF;
2439 crc = crc ^ r1 ^ crc16_table[*buf & 0xF];
2442 r1 = crc16_table[crc & 0xF];
2443 crc = (crc >> 4) & 0x0FFF;
2444 crc = crc ^ r1 ^ crc16_table[(*buf >> 4) & 0xF];
2453 * take input packet and cache various radio hw characteristics
2454 * indexed by MAC address.
2456 * Some things to think about:
2457 * note that no space is malloced.
2458 * We might hash the mac address if the cache were bigger.
2459 * It is not clear that the cache is big enough.
2460 * It is also not clear how big it should be.
2461 * The cache is IP-specific. We don't care about that as
2462 * we want it to be IP-specific.
2463 * The last N recv. packets are saved. This will tend
2464 * to reward agents and mobile hosts that beacon.
2465 * That is probably fine for mobile ip.
2468 /* globals for wavelan signal strength cache */
2469 /* this should go into softc structure above.
2472 /* set true if you want to limit cache items to broadcast/mcast
2473 * only packets (not unicast)
2475 static int wl_cache_mcastonly = 1;
2476 SYSCTL_INT(_machdep, OID_AUTO, wl_cache_mcastonly, CTLFLAG_RW,
2477 &wl_cache_mcastonly, 0, "");
2479 /* set true if you want to limit cache items to IP packets only
2481 static int wl_cache_iponly = 1;
2482 SYSCTL_INT(_machdep, OID_AUTO, wl_cache_iponly, CTLFLAG_RW,
2483 &wl_cache_iponly, 0, "");
2485 /* zero out the cache
2488 wl_cache_zero(struct wl_softc *sc)
2491 bzero(&sc->w_sigcache[0], sizeof(struct w_sigcache) * MAXCACHEITEMS);
2493 sc->w_nextcache = 0;
2494 sc->w_wrapindex = 0;
2497 /* store hw signal info in cache.
2498 * index is MAC address, but an ip src gets stored too
2499 * There are two filters here controllable via sysctl:
2500 * throw out unicast (on by default, but can be turned off)
2501 * throw out non-ip (on by default, but can be turned off)
2504 void wl_cache_store (struct wl_softc *sc, struct ether_header *eh,
2508 struct ip *ip = NULL; /* Avoid GCC warning */
2510 int signal, silence;
2511 int w_insertcache; /* computed index for cache entry storage */
2512 int ipflag = wl_cache_iponly;
2517 * 2. configurable filter to throw out unicast packets,
2518 * keep multicast only.
2522 /* reject if not IP packet
2524 if ( wl_cache_iponly && (ntohs(eh->ether_type) != 0x800)) {
2528 /* check if broadcast or multicast packet. we toss
2531 if (wl_cache_mcastonly && ((eh->ether_dhost[0] & 1) == 0)) {
2535 /* find the ip header. we want to store the ip_src
2536 * address. use the mtod macro(in mbuf.h)
2537 * to typecast m to struct ip *
2540 ip = mtod(m, struct ip *);
2543 /* do a linear search for a matching MAC address
2544 * in the cache table
2545 * . MAC address is 6 bytes,
2546 * . var w_nextcache holds total number of entries already cached
2548 for (i = 0; i < sc->w_nextcache; i++) {
2549 if (! bcmp(eh->ether_shost, sc->w_sigcache[i].macsrc, 6 )) {
2551 * so we already have this entry,
2552 * update the data, and LRU age
2558 /* did we find a matching mac address?
2559 * if yes, then overwrite a previously existing cache entry
2561 if (i < sc->w_nextcache ) {
2564 /* else, have a new address entry,so
2565 * add this new entry,
2566 * if table full, then we need to replace entry
2570 /* check for space in cache table
2571 * note: w_nextcache also holds number of entries
2572 * added in the cache table
2574 if ( sc->w_nextcache < MAXCACHEITEMS ) {
2575 w_insertcache = sc->w_nextcache;
2577 sc->w_sigitems = sc->w_nextcache;
2579 /* no space found, so simply wrap with wrap index
2580 * and "zap" the next entry
2583 if (sc->w_wrapindex == MAXCACHEITEMS) {
2584 sc->w_wrapindex = 0;
2586 w_insertcache = sc->w_wrapindex++;
2590 /* invariant: w_insertcache now points at some slot
2593 if (w_insertcache < 0 || w_insertcache >= MAXCACHEITEMS) {
2595 "wl_cache_store, bad index: %d of [0..%d], gross cache error\n",
2596 w_insertcache, MAXCACHEITEMS);
2600 /* store items in cache
2603 * .signal (0..63) ,silence (0..63) ,quality (0..15)
2606 sc->w_sigcache[w_insertcache].ipsrc = ip->ip_src.s_addr;
2608 bcopy( eh->ether_shost, sc->w_sigcache[w_insertcache].macsrc, 6);
2609 signal = sc->w_sigcache[w_insertcache].signal = wlmmcread(sc, MMC_SIGNAL_LVL) & 0x3f;
2610 silence = sc->w_sigcache[w_insertcache].silence = wlmmcread(sc, MMC_SILENCE_LVL) & 0x3f;
2611 sc->w_sigcache[w_insertcache].quality = wlmmcread(sc, MMC_SIGN_QUAL) & 0x0f;
2613 sc->w_sigcache[w_insertcache].snr =
2616 sc->w_sigcache[w_insertcache].snr = 0;
2620 #endif /* WLCACHE */