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.17 2005/02/20 03:58:04 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.
193 #include "opt_wavelan.h"
194 #include "opt_inet.h"
196 #include <sys/param.h>
197 #include <sys/systm.h>
198 #include <sys/sockio.h>
199 #include <sys/mbuf.h>
200 #include <sys/socket.h>
201 #include <sys/syslog.h>
202 #include <sys/proc.h>
204 #include <sys/kernel.h>
205 #include <sys/sysctl.h>
207 #include <net/ethernet.h>
209 #include <net/ifq_var.h>
210 #include <net/if_dl.h>
213 #include <netinet/in.h>
214 #include <netinet/in_systm.h>
215 #include <netinet/ip.h>
216 #include <netinet/if_ether.h>
221 #include <machine/clock.h>
223 #include <bus/isa/i386/isa_device.h>
224 #include "if_wl_i82586.h" /* Definitions for the Intel chip */
226 /* was 1000 in original, fed to DELAY(x) */
227 #define DELAYCONST 1000
229 #include <machine/if_wl_wavelan.h>
231 static char t_packet[ETHERMTU + sizeof(struct ether_header) + sizeof(long)];
234 struct arpcom wl_ac; /* Ethernet common part */
235 #define wl_if wl_ac.ac_if /* network visible interface */
236 #define wl_addr wl_ac.ac_enaddr /* hardware address */
238 u_char nwid[2]; /* current radio modem nwid */
242 int tbusy; /* flag to determine if xmit is busy */
246 u_short hacr; /* latest host adapter CR command */
248 u_char chan24; /* 2.4 Gz: channel number/EEPROM Area # */
249 u_short freq24; /* 2.4 Gz: resulting frequency */
250 struct callout watchdog_ch;
252 int w_sigitems; /* number of cached entries */
253 /* array of cache entries */
254 struct w_sigcache w_sigcache[ MAXCACHEITEMS ];
255 int w_nextcache; /* next free cache entry */
256 int w_wrapindex; /* next "free" cache entry */
259 static struct wl_softc wl_softc[NWL];
261 #define WLSOFTC(unit) ((struct wl_softc *)(&wl_softc[unit]))
263 static int wlprobe(struct isa_device *);
264 static int wlattach(struct isa_device *);
266 DECLARE_DUMMY_MODULE(if_wl);
268 struct isa_driver wldriver = {
269 wlprobe, wlattach, "wl", 0
273 * XXX The Wavelan appears to be prone to dropping stuff if you talk to
274 * it too fast. This disgusting hack inserts a delay after each packet
275 * is queued which helps avoid this behaviour on fast systems.
277 static int wl_xmit_delay = 250;
278 SYSCTL_INT(_machdep, OID_AUTO, wl_xmit_delay, CTLFLAG_RW, &wl_xmit_delay, 0, "");
281 * not XXX, but ZZZ (bizarre).
282 * promiscuous mode can be toggled to ignore NWIDs. By default,
283 * it does not. Caution should be exercised about combining
284 * this mode with IFF_ALLMULTI which puts this driver in
287 static int wl_ignore_nwid = 0;
288 SYSCTL_INT(_machdep, OID_AUTO, wl_ignore_nwid, CTLFLAG_RW, &wl_ignore_nwid, 0, "");
291 * Emit diagnostics about transmission problems
293 static int xmt_watch = 0;
294 SYSCTL_INT(_machdep, OID_AUTO, wl_xmit_watch, CTLFLAG_RW, &xmt_watch, 0, "");
297 * Collect SNR statistics
299 static int gathersnr = 0;
300 SYSCTL_INT(_machdep, OID_AUTO, wl_gather_snr, CTLFLAG_RW, &gathersnr, 0, "");
302 static void wlstart(struct ifnet *ifp);
303 static void wlinit(void *xsc);
304 static int wlioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *);
305 static timeout_t wlwatchdog;
306 static ointhand2_t wlintr;
307 static void wlxmt(int unt, struct mbuf *m);
308 static int wldiag(int unt);
309 static int wlconfig(int unit);
310 static int wlcmd(int unit, char *str);
311 static void wlmmcstat(int unit);
312 static u_short wlbldru(int unit);
313 static u_short wlmmcread(u_int base, u_short reg);
314 static void wlinitmmc(int unit);
315 static int wlhwrst(int unit);
316 static void wlrustrt(int unit);
317 static void wlbldcu(int unit);
318 static int wlack(int unit);
319 static int wlread(int unit, u_short fd_p);
320 static void getsnr(int unit);
321 static void wlrcv(int unit);
322 static int wlrequeue(int unit, u_short fd_p);
323 static void wlsftwsleaze(u_short *countp, u_char **mb_pp, struct mbuf **tm_pp, int unit);
324 static void wlhdwsleaze(u_short *countp, u_char **mb_pp, struct mbuf **tm_pp, int unit);
325 static void wltbd(int unit);
326 static void wlgetpsa(int base, u_char *buf);
327 static void wlsetpsa(int unit);
328 static u_short wlpsacrc(u_char *buf);
329 static void wldump(int unit);
331 static void wl_cache_store(int, int, struct ether_header *, struct mbuf *);
332 static void wl_cache_zero(int unit);
335 # if defined(__FreeBSD__) && __FreeBSD_version < 300000
336 static int check_allmulti(int unit);
340 /* array for maping irq numbers to values for the irq parameter register */
341 static int irqvals[16] = {
342 0, 0, 0, 0x01, 0x02, 0x04, 0, 0x08, 0, 0, 0x10, 0x20, 0x40, 0, 0, 0x80
344 /* mask of valid IRQs */
345 #define WL_IRQS (IRQ3|IRQ4|IRQ5|IRQ7|IRQ10|IRQ11|IRQ12|IRQ15)
350 * This function "probes" or checks for the WaveLAN board on the bus to
351 * see if it is there. As far as I can tell, the best break between this
352 * routine and the attach code is to simply determine whether the board
353 * is configured in properly. Currently my approach to this is to write
354 * and read a word from the SRAM on the board being probed. If the word
355 * comes back properly then we assume the board is there. The config
356 * code expects to see a successful return from the probe routine before
357 * attach will be called.
359 * input : address device is mapped to, and unit # being checked
360 * output : a '1' is returned if the board exists, and a 0 otherwise
364 wlprobe(struct isa_device *id)
366 struct wl_softc *sc = &wl_softc[id->id_unit];
367 short base = id->id_iobase;
368 char *str = "wl%d: board out of range [0..%d]\n";
370 unsigned long oldpri;
374 * regular CMD() will not work, since no softc yet
376 #define PCMD(base, hacr) outw((base), (hacr))
379 PCMD(base, HACR_RESET); /* reset the board */
380 DELAY(DELAYCONST); /* >> 4 clocks at 6MHz */
381 PCMD(base, HACR_RESET); /* reset the board */
382 DELAY(DELAYCONST); /* >> 4 clocks at 6MHz */
385 /* clear reset command and set PIO#1 in autoincrement mode */
386 PCMD(base, HACR_DEFAULT);
387 PCMD(base, HACR_DEFAULT);
388 outw(PIOR1(base), 0); /* go to beginning of RAM */
389 outsw(PIOP1(base), str, strlen(str)/2+1); /* write string */
391 outw(PIOR1(base), 0); /* rewind */
392 insw(PIOP1(base), inbuf, strlen(str)/2+1); /* read result */
394 if (bcmp(str, inbuf, strlen(str)))
397 sc->chan24 = 0; /* 2.4 Gz: config channel */
398 sc->freq24 = 0; /* 2.4 Gz: frequency */
400 /* read the PSA from the board into temporary storage */
401 wlgetpsa(base, inbuf);
403 /* We read the IRQ value from the PSA on the board. */
404 for (irq = 15; irq >= 0; irq--)
405 if (irqvals[irq] == inbuf[WLPSA_IRQNO])
407 if ((irq == 0) || (irqvals[irq] == 0)){
408 printf("wl%d: PSA corrupt (invalid IRQ value)\n", id->id_unit);
409 id->id_irq = 0; /* no interrupt */
412 * If the IRQ requested by the PSA is already claimed by another
413 * device, the board won't work, but the user can still access the
414 * driver to change the IRQ.
416 id->id_irq = (1<<irq); /* use IRQ from PSA */
425 * This function attaches a WaveLAN board to the "system". The rest of
426 * runtime structures are initialized here (this routine is called after
427 * a successful probe of the board). Once the ethernet address is read
428 * and stored, the board's ifnet structure is attached and readied.
430 * input : isa_dev structure setup in autoconfig
431 * output : board structs and ifnet is setup
435 wlattach(struct isa_device *id)
437 struct wl_softc *sc = (struct wl_softc *) &wl_softc[id->id_unit];
438 short base = id->id_iobase;
440 u_char unit = id->id_unit;
441 struct ifnet *ifp = &sc->wl_if;
444 printf("wlattach: base %x, unit %d\n", base, unit);
446 id->id_ointr = wlintr;
451 sc->hacr = HACR_RESET;
452 callout_init(&sc->watchdog_ch);
453 CMD(unit); /* reset the board */
454 DELAY(DELAYCONST); /* >> 4 clocks at 6MHz */
456 /* clear reset command and set PIO#2 in parameter access mode */
457 sc->hacr = (HACR_DEFAULT & ~HACR_16BITS);
460 /* Read the PSA from the board for our later reference */
461 wlgetpsa(base, sc->psa);
464 sc->nwid[0] = sc->psa[WLPSA_NWID];
465 sc->nwid[1] = sc->psa[WLPSA_NWID+1];
467 /* fetch MAC address - decide which one first */
468 if (sc->psa[WLPSA_MACSEL] & 1) {
473 for(i=0; i < WAVELAN_ADDR_SIZE; ++i) {
474 sc->wl_addr[i] = sc->psa[j + i];
477 /* enter normal 16 bit mode operation */
478 sc->hacr = HACR_DEFAULT;
482 outw(PIOR1(base), OFFSET_SCB + 8); /* address of scb_crcerrs */
483 outw(PIOP1(base), 0); /* clear scb_crcerrs */
484 outw(PIOP1(base), 0); /* clear scb_alnerrs */
485 outw(PIOP1(base), 0); /* clear scb_rscerrs */
486 outw(PIOP1(base), 0); /* clear scb_ovrnerrs */
488 bzero(ifp, sizeof(ifp));
490 if_initname(ifp, "wl", id->id_unit);
491 ifp->if_mtu = WAVELAN_MTU;
492 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
494 ifp->if_flags |= IFF_DEBUG;
497 ifp->if_flags |= IFF_MULTICAST;
498 #endif /* MULTICAST */
499 ifp->if_init = wlinit;
500 ifp->if_start = wlstart;
501 ifp->if_ioctl = wlioctl;
502 ifp->if_timer = 0; /* paranoia */
508 ifq_set_maxlen(&ifp->if_snd, IFQ_MAXLEN);
509 ifq_set_ready(&ifp->if_snd);
510 ether_ifattach(ifp, sc->wl_ac.ac_enaddr);
512 bcopy(&sc->wl_addr[0], sc->wl_ac.ac_enaddr, WAVELAN_ADDR_SIZE);
513 if_printf(ifp, "NWID 0x%02x%02x", sc->nwid[0], sc->nwid[1]);
515 printf(", Freq %d MHz",sc->freq24); /* 2.4 Gz */
516 printf("\n"); /* 2.4 Gz */
525 * Print out interesting information about the 82596.
530 struct wl_softc *sp = WLSOFTC(unit);
534 printf("hasr %04x\n", inw(HASR(base)));
536 printf("scb at %04x:\n ", OFFSET_SCB);
537 outw(PIOR1(base), OFFSET_SCB);
538 for(i = 0; i < 8; i++)
539 printf("%04x ", inw(PIOP1(base)));
542 printf("cu at %04x:\n ", OFFSET_CU);
543 outw(PIOR1(base), OFFSET_CU);
544 for(i = 0; i < 8; i++)
545 printf("%04x ", inw(PIOP1(base)));
548 printf("tbd at %04x:\n ", OFFSET_TBD);
549 outw(PIOR1(base), OFFSET_TBD);
550 for(i = 0; i < 4; i++)
551 printf("%04x ", inw(PIOP1(base)));
555 /* Initialize the Modem Management Controller */
559 struct wl_softc *sp = WLSOFTC(unit);
565 /* enter 8 bit operation */
566 sp->hacr = (HACR_DEFAULT & ~HACR_16BITS);
569 configured = sp->psa[WLPSA_CONFIGURED] & 1;
572 * Set default modem control parameters. Taken from NCR document
575 MMC_WRITE(MMC_JABBER_ENABLE, 0x01);
576 MMC_WRITE(MMC_ANTEN_SEL, 0x02);
577 MMC_WRITE(MMC_IFS, 0x20);
578 MMC_WRITE(MMC_MOD_DELAY, 0x04);
579 MMC_WRITE(MMC_JAM_TIME, 0x38);
580 MMC_WRITE(MMC_DECAY_PRM, 0x00); /* obsolete ? */
581 MMC_WRITE(MMC_DECAY_UPDAT_PRM, 0x00);
583 MMC_WRITE(MMC_LOOPT_SEL, 0x00);
584 if (sp->psa[WLPSA_COMPATNO] & 1) {
585 MMC_WRITE(MMC_THR_PRE_SET, 0x01); /* 0x04 for AT and 0x01 for MCA */
587 MMC_WRITE(MMC_THR_PRE_SET, 0x04); /* 0x04 for AT and 0x01 for MCA */
589 MMC_WRITE(MMC_QUALITY_THR, 0x03);
591 /* use configuration defaults from parameter storage area */
592 if (sp->psa[WLPSA_NWIDENABLE] & 1) {
593 if ((mode & (MOD_PROM | MOD_ENAL)) && wl_ignore_nwid) {
594 MMC_WRITE(MMC_LOOPT_SEL, 0x40);
596 MMC_WRITE(MMC_LOOPT_SEL, 0x00);
599 MMC_WRITE(MMC_LOOPT_SEL, 0x40); /* disable network id check */
601 MMC_WRITE(MMC_THR_PRE_SET, sp->psa[WLPSA_THRESH]);
602 MMC_WRITE(MMC_QUALITY_THR, sp->psa[WLPSA_QUALTHRESH]);
604 MMC_WRITE(MMC_FREEZE, 0x00);
605 MMC_WRITE(MMC_ENCR_ENABLE, 0x00);
607 MMC_WRITE(MMC_NETW_ID_L,sp->nwid[1]); /* set NWID */
608 MMC_WRITE(MMC_NETW_ID_H,sp->nwid[0]);
610 /* enter normal 16 bit mode operation */
611 sp->hacr = HACR_DEFAULT;
613 CMD(unit); /* virtualpc1 needs this! */
615 if (sp->psa[WLPSA_COMPATNO]== /* 2.4 Gz: half-card ver */
616 WLPSA_COMPATNO_WL24B) { /* 2.4 Gz */
617 i=sp->chan24<<4; /* 2.4 Gz: position ch # */
618 MMC_WRITE(MMC_EEADDR,i+0x0f); /* 2.4 Gz: named ch, wc=16 */
619 MMC_WRITE(MMC_EECTRL,MMC_EECTRL_DWLD+ /* 2.4 Gz: Download Synths */
620 MMC_EECTRL_EEOP_READ); /* 2.4 Gz: Read EEPROM */
621 for (i=0; i<1000; ++i) { /* 2.4 Gz: wait for download */
622 DELAY(40); /* 2.4 Gz */
623 if ((wlmmcread(base,MMC_EECTRLstat) /* 2.4 Gz: check DWLD and */
624 &(MMC_EECTRLstat_DWLD /* 2.4 Gz: EEBUSY */
625 +MMC_EECTRLstat_EEBUSY))==0) /* 2.4 Gz: */
626 break; /* 2.4 Gz: download finished */
628 if (i==1000) printf("wl: synth load failed\n"); /* 2.4 Gz */
629 MMC_WRITE(MMC_EEADDR,0x61); /* 2.4 Gz: default pwr, wc=2 */
630 MMC_WRITE(MMC_EECTRL,MMC_EECTRL_DWLD+ /* 2.4 Gz: Download Xmit Pwr */
631 MMC_EECTRL_EEOP_READ); /* 2.4 Gz: Read EEPROM */
632 for (i=0; i<1000; ++i) { /* 2.4 Gz: wait for download */
633 DELAY(40); /* 2.4 Gz */
634 if ((wlmmcread(base,MMC_EECTRLstat) /* 2.4 Gz: check DWLD and */
635 &(MMC_EECTRLstat_DWLD /* 2.4 Gz: EEBUSY */
636 +MMC_EECTRLstat_EEBUSY))==0) /* 2.4 Gz: */
637 break; /* 2.4 Gz: download finished */
639 if (i==1000) printf("wl: xmit pwr load failed\n"); /* 2.4 Gz */
640 MMC_WRITE(MMC_ANALCTRL, /* 2.4 Gz: EXT ant+polarity */
641 MMC_ANALCTRL_ANTPOL + /* 2.4 Gz: */
642 MMC_ANALCTRL_EXTANT); /* 2.4 Gz: */
643 i=sp->chan24<<4; /* 2.4 Gz: position ch # */
644 MMC_WRITE(MMC_EEADDR,i); /* 2.4 Gz: get frequency */
645 MMC_WRITE(MMC_EECTRL, /* 2.4 Gz: EEPROM read */
646 MMC_EECTRL_EEOP_READ); /* 2.4 Gz: */
647 DELAY(40); /* 2.4 Gz */
648 i = wlmmcread(base,MMC_EEDATALrv) /* 2.4 Gz: freq val */
649 + (wlmmcread(base,MMC_EEDATAHrv)<<8); /* 2.4 Gz */
650 sp->freq24 = (i>>6)+2400; /* 2.4 Gz: save real freq */
657 * Another routine that interfaces the "if" layer to this driver.
658 * Simply resets the structures that are used by "upper layers".
659 * As well as calling wlhwrst that does reset the WaveLAN board.
661 * input : softc pointer for this interface
662 * output : structures (if structs) and board are reset
668 struct wl_softc *sc = xsc;
669 struct ifnet *ifp = &sc->wl_if;
674 if (sc->wl_if.if_flags & IFF_DEBUG)
675 printf("wl%d: entered wlinit()\n",sc->unit);
677 #if defined(__DragonFly__) || (defined(__FreeBSD__) && __FreeBSD_version >= 300000)
678 if (TAILQ_EMPTY(&ifp->if_addrhead)) {
680 if (ifp->if_addrlist == (struct ifaddr *)0) {
685 if ((stat = wlhwrst(sc->unit)) == TRUE) {
686 sc->wl_if.if_flags |= IFF_RUNNING; /* same as DSF_RUNNING */
688 * OACTIVE is used by upper-level routines
691 sc->wl_if.if_flags &= ~IFF_OACTIVE; /* same as tbusy below */
693 sc->flags |= DSF_RUNNING;
695 callout_stop(&sc->watchdog_ch);
699 printf("wl%d init(): trouble resetting board.\n", sc->unit);
707 * This routine resets the WaveLAN board that corresponds to the
708 * board number passed in.
710 * input : board number to do a hardware reset
711 * output : board is reset
717 struct wl_softc *sc = WLSOFTC(unit);
720 if (sc->wl_if.if_flags & IFF_DEBUG)
721 printf("wl%d: entered wlhwrst()\n",unit);
723 sc->hacr = HACR_RESET;
724 CMD(unit); /* reset the board */
726 /* clear reset command and set PIO#1 in autoincrement mode */
727 sc->hacr = HACR_DEFAULT;
731 if (sc->wl_if.if_flags & IFF_DEBUG)
732 wlmmcstat(unit); /* Display MMC registers */
734 wlbldcu(unit); /* set up command unit structures */
736 if (wldiag(unit) == 0)
739 if (wlconfig(unit) == 0)
742 * insert code for loopback test here
744 wlrustrt(unit); /* start receive unit */
746 /* enable interrupts */
747 sc->hacr = (HACR_DEFAULT | HACR_INTRON);
756 * This function builds up the command unit structures. It inits
757 * the scp, iscp, scb, cb, tbd, and tbuf.
763 struct wl_softc *sc = WLSOFTC(unit);
764 short base = sc->base;
772 bzero(&scp, sizeof(scp));
774 scp.scp_iscp = OFFSET_ISCP;
775 scp.scp_iscp_base = 0;
776 outw(PIOR1(base), OFFSET_SCP);
777 outsw(PIOP1(base), &scp, sizeof(scp_t)/2);
779 bzero(&iscp, sizeof(iscp));
781 iscp.iscp_scb_offset = OFFSET_SCB;
783 iscp.iscp_scb_base = 0;
784 outw(PIOR1(base), OFFSET_ISCP);
785 outsw(PIOP1(base), &iscp, sizeof(iscp_t)/2);
788 scb.scb_command = SCB_RESET;
789 scb.scb_cbl_offset = OFFSET_CU;
790 scb.scb_rfa_offset = OFFSET_RU;
794 scb.scb_ovrnerrs = 0;
795 outw(PIOR1(base), OFFSET_SCB);
796 outsw(PIOP1(base), &scb, sizeof(scb_t)/2);
800 outw(PIOR0(base), OFFSET_ISCP + 0); /* address of iscp_busy */
801 for (i = 1000000; inw(PIOP0(base)) && (i-- > 0); );
802 if (i <= 0) printf("wl%d bldcu(): iscp_busy timeout.\n", unit);
803 outw(PIOR0(base), OFFSET_SCB + 0); /* address of scb_status */
804 for (i = STATUS_TRIES; i-- > 0; ) {
805 if (inw(PIOP0(base)) == (SCB_SW_CX|SCB_SW_CNA))
809 printf("wl%d bldcu(): not ready after reset.\n", unit);
813 cb.ac_command = AC_CW_EL; /* NOP */
814 cb.ac_link_offset = OFFSET_CU;
815 outw(PIOR1(base), OFFSET_CU);
816 outsw(PIOP1(base), &cb, 6/2);
819 tbd.next_tbd_offset = I82586NULL;
822 outw(PIOR1(base), OFFSET_TBD);
823 outsw(PIOP1(base), &tbd, sizeof(tbd_t)/2);
831 * input : board number
832 * output : stuff sent to board if any there
836 wlstart(struct ifnet *ifp)
838 int unit = ifp->if_dunit;
840 struct wl_softc *sc = WLSOFTC(unit);
841 short base = sc->base;
842 int scb_status, cu_status, scb_command;
845 if (sc->wl_if.if_flags & IFF_DEBUG)
846 printf("wl%d: entered wlstart()\n",unit);
849 outw(PIOR1(base), OFFSET_CU);
850 cu_status = inw(PIOP1(base));
851 outw(PIOR0(base),OFFSET_SCB + 0); /* scb_status */
852 scb_status = inw(PIOP0(base));
853 outw(PIOR0(base), OFFSET_SCB + 2);
854 scb_command = inw(PIOP0(base));
857 * don't need OACTIVE check as tbusy here checks to see
858 * if we are already busy
861 if((scb_status & 0x0700) == SCB_CUS_IDLE &&
862 (cu_status & AC_SW_B) == 0){
864 callout_stop(&sc->watchdog_ch);
865 sc->wl_ac.ac_if.if_flags &= ~IFF_OACTIVE;
867 * This is probably just a race. The xmt'r is just
868 * became idle but WE have masked interrupts so ...
871 printf("wl%d: CU idle, scb %04x %04x cu %04x\n",
872 unit, scb_status, scb_command, cu_status);
874 if (xmt_watch) printf("!!");
876 return; /* genuinely still busy */
878 } else if((scb_status & 0x0700) == SCB_CUS_ACTV ||
879 (cu_status & AC_SW_B)){
881 printf("wl%d: CU unexpectedly busy; scb %04x cu %04x\n",
882 unit, scb_status, cu_status);
884 if (xmt_watch) printf("wl%d: busy?!",unit);
885 return; /* hey, why are we busy? */
888 /* get ourselves some data */
890 m = ifq_dequeue(&ifp->if_snd);
894 /* set the watchdog timer so that if the board
895 * fails to interrupt we will restart
897 /* try 10 ticks, not very long */
898 callout_reset(&sc->watchdog_ch, 10, wlwatchdog, sc);
899 sc->wl_ac.ac_if.if_flags |= IFF_OACTIVE;
900 sc->wl_if.if_opackets++;
903 sc->wl_ac.ac_if.if_flags &= ~IFF_OACTIVE;
911 * This routine does the actual copy of data (including ethernet header
912 * structure) from the WaveLAN to an mbuf chain that will be passed up
913 * to the "if" (network interface) layer. NOTE: we currently
914 * don't handle trailer protocols, so if that is needed, it will
915 * (at least in part) be added here. For simplicities sake, this
916 * routine copies the receive buffers from the board into a local (stack)
917 * buffer until the frame has been copied from the board. Once in
918 * the local buffer, the contents are copied to an mbuf chain that
919 * is then enqueued onto the appropriate "if" queue.
921 * input : board number, and an frame descriptor address
922 * output : the packet is put into an mbuf chain, and passed up
923 * assumes : if any errors occur, packet is "dropped on the floor"
927 wlread(int unit, u_short fd_p)
929 struct wl_softc *sc = WLSOFTC(unit);
930 struct ifnet *ifp = &sc->wl_if;
931 short base = sc->base;
933 struct ether_header eh;
937 u_short mlen, len, clen;
938 u_short bytes_in_msg, bytes_in_mbuf, bytes;
942 if (sc->wl_if.if_flags & IFF_DEBUG)
943 printf("wl%d: entered wlread()\n",unit);
945 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
946 printf("%s read(): board is not running.\n", ifp->if_xname);
947 sc->hacr &= ~HACR_INTRON;
948 CMD(unit); /* turn off interrupts */
950 /* read ether_header info out of device memory. doesn't
951 * go into mbuf. goes directly into eh structure
953 len = sizeof(struct ether_header); /* 14 bytes */
954 outw(PIOR1(base), fd_p);
955 insw(PIOP1(base), &fd, (sizeof(fd_t) - len)/2);
956 insw(PIOP1(base), &eh, (len-2)/2);
957 eh.ether_type = ntohs(inw(PIOP1(base)));
959 if (sc->wl_if.if_flags & IFF_DEBUG) {
960 printf("wlread: rcv packet, type is %x\n", eh.ether_type);
964 * WARNING. above is done now in ether_input, above may be
965 * useful for debug. jrb
967 eh.ether_type = htons(eh.ether_type);
969 if (fd.rbd_offset == I82586NULL) {
970 printf("wl%d read(): Invalid buffer\n", unit);
971 if (wlhwrst(unit) != TRUE) {
972 printf("wl%d read(): hwrst trouble.\n", unit);
977 outw(PIOR1(base), fd.rbd_offset);
978 insw(PIOP1(base), &rbd, sizeof(rbd_t)/2);
979 bytes_in_msg = rbd.status & RBD_SW_COUNT;
980 MGETHDR(m, MB_DONTWAIT, MT_DATA);
982 if (m == (struct mbuf *)0) {
984 * not only do we want to return, we need to drop the packet on
985 * the floor to clear the interrupt.
988 if (wlhwrst(unit) != TRUE) {
989 sc->hacr &= ~HACR_INTRON;
990 CMD(unit); /* turn off interrupts */
991 printf("wl%d read(): hwrst trouble.\n", unit);
995 m->m_next = (struct mbuf *) 0;
996 m->m_pkthdr.rcvif = ifp;
997 m->m_pkthdr.len = 0; /* don't know this yet */
1000 /* always use a cluster. jrb
1002 MCLGET(m, MB_DONTWAIT);
1003 if (m->m_flags & M_EXT) {
1004 m->m_len = MCLBYTES;
1008 if (wlhwrst(unit) != TRUE) {
1009 sc->hacr &= ~HACR_INTRON;
1010 CMD(unit); /* turn off interrupts */
1011 printf("wl%d read(): hwrst trouble.\n", unit);
1018 bytes_in_mbuf = m->m_len;
1019 mb_p = mtod(tm, u_char *);
1020 bytes = min(bytes_in_mbuf, bytes_in_msg);
1027 outw(PIOR1(base), rbd.buffer_addr);
1028 insw(PIOP1(base), mb_p, len/2);
1032 if (!(bytes_in_mbuf -= bytes)) {
1033 MGET(tm->m_next, MB_DONTWAIT, MT_DATA);
1035 if (tm == (struct mbuf *)0) {
1037 printf("wl%d read(): No mbuf nth\n", unit);
1038 if (wlhwrst(unit) != TRUE) {
1039 sc->hacr &= ~HACR_INTRON;
1040 CMD(unit); /* turn off interrupts */
1041 printf("wl%d read(): hwrst trouble.\n", unit);
1047 bytes_in_mbuf = MLEN;
1048 mb_p = mtod(tm, u_char *);
1053 if (!(bytes_in_msg -= bytes)) {
1054 if (rbd.status & RBD_SW_EOF ||
1055 rbd.next_rbd_offset == I82586NULL) {
1059 outw(PIOR1(base), rbd.next_rbd_offset);
1060 insw(PIOP1(base), &rbd, sizeof(rbd_t)/2);
1061 bytes_in_msg = rbd.status & RBD_SW_COUNT;
1064 rbd.buffer_addr += bytes;
1067 bytes = min(bytes_in_mbuf, bytes_in_msg);
1070 m->m_pkthdr.len = clen;
1073 * If hw is in promiscuous mode (note that I said hardware, not if
1074 * IFF_PROMISC is set in ifnet flags), then if this is a unicast
1075 * packet and the MAC dst is not us, drop it. This check in normally
1076 * inside ether_input(), but IFF_MULTI causes hw promisc without
1077 * a bpf listener, so this is wrong.
1078 * Greg Troxel <gdt@ir.bbn.com>, 1998-08-07
1081 * TBD: also discard packets where NWID does not match.
1082 * However, there does not appear to be a way to read the nwid
1083 * for a received packet. -gdt 1998-08-07
1086 #ifdef WL_USE_IFNET_PROMISC_CHECK /* not defined */
1087 (sc->wl_ac.ac_if.if_flags & (IFF_PROMISC|IFF_ALLMULTI))
1089 /* hw is in promisc mode if this is true */
1090 (sc->mode & (MOD_PROM | MOD_ENAL))
1093 (eh.ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */
1094 bcmp(eh.ether_dhost, sc->wl_ac.ac_enaddr,
1095 sizeof(eh.ether_dhost)) != 0 ) {
1101 if (sc->wl_if.if_flags & IFF_DEBUG)
1102 printf("wl%d: wlrecv %d bytes\n", unit, clen);
1106 wl_cache_store(unit, base, &eh, m);
1110 * received packet is now in a chain of mbuf's. next step is
1111 * to pass the packet upwards.
1114 ether_input(&sc->wl_if, &eh, m);
1121 * This routine processes an ioctl request from the "if" layer
1124 * input : pointer the appropriate "if" struct, command, and data
1125 * output : based on command appropriate action is taken on the
1126 * WaveLAN board(s) or related structures
1127 * return : error is returned containing exit conditions
1131 wlioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cred)
1133 struct ifreq *ifr = (struct ifreq *)data;
1134 int unit = ifp->if_dunit;
1135 struct wl_softc *sc = WLSOFTC(unit);
1136 short base = sc->base;
1138 int opri, error = 0;
1139 int irq, irqval, i, isroot, size;
1142 struct thread *td = curthread; /* XXX */
1146 if (sc->wl_if.if_flags & IFF_DEBUG)
1147 printf("wl%d: entered wlioctl()\n",unit);
1154 error = ether_ioctl(ifp, cmd, data);
1158 if (ifp->if_flags & IFF_ALLMULTI) {
1161 if (ifp->if_flags & IFF_PROMISC) {
1164 if(ifp->if_flags & IFF_LINK0) {
1168 * force a complete reset if the recieve multicast/
1169 * promiscuous mode changes so that these take
1170 * effect immediately.
1173 if (sc->mode != mode) {
1175 if (sc->flags & DSF_RUNNING) {
1176 sc->flags &= ~DSF_RUNNING;
1180 /* if interface is marked DOWN and still running then
1183 if ((ifp->if_flags & IFF_UP) == 0 && sc->flags & DSF_RUNNING) {
1184 printf("wl%d ioctl(): board is not running\n", unit);
1185 sc->flags &= ~DSF_RUNNING;
1186 sc->hacr &= ~HACR_INTRON;
1187 CMD(unit); /* turn off interrupts */
1189 /* else if interface is UP and RUNNING, start it
1191 else if (ifp->if_flags & IFF_UP && (sc->flags & DSF_RUNNING) == 0) {
1195 /* if WLDEBUG set on interface, then printf rf-modem regs
1197 if(ifp->if_flags & IFF_DEBUG)
1204 #if defined(__FreeBSD__) && __FreeBSD_version < 300000
1205 if (cmd == SIOCADDMULTI) {
1206 error = ether_addmulti(ifr, &sc->wl_ac);
1209 error = ether_delmulti(ifr, &sc->wl_ac);
1212 /* see if we should be in all multicast mode
1213 * note that 82586 cannot do that, must simulate with
1216 if ( check_allmulti(unit)) {
1217 ifp->if_flags |= IFF_ALLMULTI;
1218 sc->mode |= MOD_ENAL;
1219 sc->flags &= ~DSF_RUNNING;
1225 if (error == ENETRESET) {
1226 if(sc->flags & DSF_RUNNING) {
1227 sc->flags &= ~DSF_RUNNING;
1236 #endif /* MULTICAST */
1238 /* DEVICE SPECIFIC */
1241 /* copy the PSA out to the caller */
1243 /* pointer to buffer in user space */
1244 up = (void *)ifr->ifr_data;
1245 /* work out if they're root */
1246 isroot = (suser(td) == 0);
1248 for (i = 0; i < 0x40; i++) {
1249 /* don't hand the DES key out to non-root users */
1250 if ((i > WLPSA_DESKEY) && (i < (WLPSA_DESKEY + 8)) && !isroot)
1252 if (subyte((up + i), sc->psa[i]))
1258 /* copy the PSA in from the caller; we only copy _some_ values */
1261 if ((error = suser(td)))
1263 error = EINVAL; /* assume the worst */
1264 /* pointer to buffer in user space containing data */
1265 up = (void *)ifr->ifr_data;
1267 /* check validity of input range */
1268 for (i = 0; i < 0x40; i++)
1269 if (fubyte(up + i) < 0)
1272 /* check IRQ value */
1273 irqval = fubyte(up+WLPSA_IRQNO);
1274 for (irq = 15; irq >= 0; irq--)
1275 if(irqvals[irq] == irqval)
1277 if (irq == 0) /* oops */
1280 sc->psa[WLPSA_IRQNO] = irqval;
1283 for (i = 0; i < 6; i++)
1284 sc->psa[WLPSA_LOCALMAC+i] = fubyte(up+WLPSA_LOCALMAC+i);
1287 sc->psa[WLPSA_MACSEL] = fubyte(up+WLPSA_MACSEL);
1290 sc->psa[WLPSA_NWID] = fubyte(up+WLPSA_NWID);
1291 sc->psa[WLPSA_NWID+1] = fubyte(up+WLPSA_NWID+1);
1294 wlsetpsa(unit); /* update the PSA */
1298 /* get the current NWID out of the sc since we stored it there */
1300 ifr->ifr_data = (caddr_t) (sc->nwid[0] << 8 | sc->nwid[1]);
1305 * change the nwid dynamically. This
1306 * ONLY changes the radio modem and does not
1310 * 1. save in softc "soft registers"
1311 * 2. save in radio modem (MMC)
1315 if ((error = suser(td)))
1317 if (!(ifp->if_flags & IFF_UP)) {
1318 error = EIO; /* only allowed while up */
1321 * soft c nwid shadows radio modem setting
1323 sc->nwid[0] = (int)ifr->ifr_data >> 8;
1324 sc->nwid[1] = (int)ifr->ifr_data & 0xff;
1325 MMC_WRITE(MMC_NETW_ID_L,sc->nwid[1]);
1326 MMC_WRITE(MMC_NETW_ID_H,sc->nwid[0]);
1330 /* copy the EEPROM in 2.4 Gz WaveMODEM out to the caller */
1333 if ((error = suser(td)))
1335 /* pointer to buffer in user space */
1336 up = (void *)ifr->ifr_data;
1338 for (i=0x00; i<0x80; ++i) { /* 2.4 Gz: size of EEPROM */
1339 MMC_WRITE(MMC_EEADDR,i); /* 2.4 Gz: get frequency */
1340 MMC_WRITE(MMC_EECTRL, /* 2.4 Gz: EEPROM read */
1341 MMC_EECTRL_EEOP_READ); /* 2.4 Gz: */
1342 DELAY(40); /* 2.4 Gz */
1343 if (subyte(up + 2*i , /* 2.4 Gz: pass low byte of */
1344 wlmmcread(base,MMC_EEDATALrv)) /* 2.4 Gz: EEPROM word */
1345 ) return(EFAULT); /* 2.4 Gz: */
1346 if (subyte(up + 2*i+1, /* 2.4 Gz: pass hi byte of */
1347 wlmmcread(base,MMC_EEDATALrv)) /* 2.4 Gz: EEPROM word */
1348 ) return(EFAULT); /* 2.4 Gz: */
1353 /* zero (Delete) the wl cache */
1356 if ((error = suser(td)))
1358 wl_cache_zero(unit);
1361 /* read out the number of used cache elements */
1363 ifr->ifr_data = (caddr_t) sc->w_sigitems;
1366 /* read out the wl cache */
1368 /* pointer to buffer in user space */
1369 up = (void *)ifr->ifr_data;
1370 cpt = (char *) &sc->w_sigcache[0];
1371 size = sc->w_sigitems * sizeof(struct w_sigcache);
1373 for (i = 0; i < size; i++) {
1374 if (subyte((up + i), *cpt++))
1390 * Called if the timer set in wlstart expires before an interrupt is received
1391 * from the wavelan. It seems to lose interrupts sometimes.
1392 * The watchdog routine gets called if the transmitter failed to interrupt
1394 * input : which board is timing out
1395 * output : board reset
1399 wlwatchdog(void *vsc)
1401 struct wl_softc *sc = vsc;
1402 int unit = sc->unit;
1404 log(LOG_ERR, "wl%d: wavelan device timeout on xmit\n", unit);
1405 sc->wl_ac.ac_if.if_oerrors++;
1412 * This function is the interrupt handler for the WaveLAN
1413 * board. This routine will be called whenever either a packet
1414 * is received, or a packet has successfully been transfered and
1415 * the unit is ready to transmit another packet.
1417 * input : board number that interrupted
1418 * output : either a packet is received, or a packet is transfered
1425 struct wl_softc *sc = &wl_softc[unit];
1426 short base = sc->base;
1428 u_short int_type, int_type1;
1431 if (sc->wl_if.if_flags & IFF_DEBUG)
1432 printf("wl%d: wlintr() called\n",unit);
1435 if((int_type = inw(HASR(base))) & HASR_MMC_INTR) {
1436 /* handle interrupt from the modem management controler */
1437 /* This will clear the interrupt condition */
1438 (void) wlmmcread(base,MMC_DCE_STATUS); /* ignored for now */
1441 if(!(int_type & HASR_INTR)){ /* return if no interrupt from 82586 */
1442 /* commented out. jrb. it happens when reinit occurs
1443 printf("wlintr: int_type %x, dump follows\n", int_type);
1452 outw(PIOR0(base), OFFSET_SCB + 0); /* get scb status */
1453 int_type = (inw(PIOP0(base)) & SCB_SW_INT);
1454 if (int_type == 0) /* no interrupts left */
1457 int_type1 = wlack(unit); /* acknowledge interrupt(s) */
1458 /* make sure no bits disappeared (others may appear) */
1459 if ((int_type & int_type1) != int_type)
1460 printf("wlack() int bits disappeared : %04x != int_type %04x\n",
1461 int_type1, int_type);
1462 int_type = int_type1; /* go with the new status */
1466 if (int_type & SCB_SW_FR) {
1467 sc->wl_if.if_ipackets++;
1471 * receiver not ready
1473 if (int_type & SCB_SW_RNR) {
1474 sc->wl_if.if_ierrors++;
1476 if (sc->wl_if.if_flags & IFF_DEBUG)
1477 printf("wl%d intr(): receiver overrun! begin_fd = %x\n",
1478 unit, sc->begin_fd);
1485 if (int_type & SCB_SW_CNA) {
1487 * At present, we don't care about CNA's. We
1488 * believe they are a side effect of XMT.
1491 if (int_type & SCB_SW_CX) {
1493 * At present, we only request Interrupt for
1496 outw(PIOR1(base), OFFSET_CU); /* get command status */
1497 ac_status = inw(PIOP1(base));
1499 if (xmt_watch) { /* report some anomalies */
1501 if (sc->tbusy == 0) {
1502 printf("wl%d: xmt intr but not busy, CU %04x\n",
1505 if (ac_status == 0) {
1506 printf("wl%d: xmt intr but ac_status == 0\n", unit);
1508 if (ac_status & AC_SW_A) {
1509 printf("wl%d: xmt aborted\n",unit);
1512 if (ac_status & TC_CARRIER) {
1513 printf("wl%d: no carrier\n", unit);
1516 if (ac_status & TC_CLS) {
1517 printf("wl%d: no CTS\n", unit);
1519 if (ac_status & TC_DMA) {
1520 printf("wl%d: DMA underrun\n", unit);
1522 if (ac_status & TC_DEFER) {
1523 printf("wl%d: xmt deferred\n",unit);
1525 if (ac_status & TC_SQE) {
1526 printf("wl%d: heart beat\n", unit);
1528 if (ac_status & TC_COLLISION) {
1529 printf("wl%d: too many collisions\n", unit);
1532 /* if the transmit actually failed, or returned some status */
1533 if ((!(ac_status & AC_SW_OK)) || (ac_status & 0xfff)) {
1534 if (ac_status & (TC_COLLISION | TC_CLS | TC_DMA)) {
1535 sc->wl_if.if_oerrors++;
1537 /* count collisions */
1538 sc->wl_if.if_collisions += (ac_status & 0xf);
1539 /* if TC_COLLISION set and collision count zero, 16 collisions */
1540 if ((ac_status & 0x20) == 0x20) {
1541 sc->wl_if.if_collisions += 0x10;
1545 callout_stop(&sc->watchdog_ch);
1546 sc->wl_ac.ac_if.if_flags &= ~IFF_OACTIVE;
1547 wlstart(&(sc->wl_if));
1556 * This routine is called by the interrupt handler to initiate a
1557 * packet transfer from the board to the "if" layer above this
1558 * driver. This routine checks if a buffer has been successfully
1559 * received by the WaveLAN. If so, the routine wlread is called
1560 * to do the actual transfer of the board data (including the
1561 * ethernet header) into a packet (consisting of an mbuf chain).
1563 * input : number of the board to check
1564 * output : if a packet is available, it is "sent up"
1570 struct wl_softc *sc = WLSOFTC(unit);
1571 short base = sc->base;
1572 u_short fd_p, status, offset, link_offset;
1575 if (sc->wl_if.if_flags & IFF_DEBUG)
1576 printf("wl%d: entered wlrcv()\n",unit);
1578 for (fd_p = sc->begin_fd; fd_p != I82586NULL; fd_p = sc->begin_fd) {
1580 outw(PIOR0(base), fd_p + 0); /* address of status */
1581 status = inw(PIOP0(base));
1582 outw(PIOR1(base), fd_p + 4); /* address of link_offset */
1583 link_offset = inw(PIOP1(base));
1584 offset = inw(PIOP1(base)); /* rbd_offset */
1585 if (status == 0xffff || offset == 0xffff /*I82586NULL*/) {
1586 if (wlhwrst(unit) != TRUE)
1587 printf("wl%d rcv(): hwrst ffff trouble.\n", unit);
1589 } else if (status & AC_SW_C) {
1590 if (status == (RFD_DONE|RFD_RSC)) {
1593 if (sc->wl_if.if_flags & IFF_DEBUG)
1594 printf("wl%d RCV: RSC %x\n", unit, status);
1596 sc->wl_if.if_ierrors++;
1597 } else if (!(status & RFD_OK)) {
1598 printf("wl%d RCV: !OK %x\n", unit, status);
1599 sc->wl_if.if_ierrors++;
1600 } else if (status & 0xfff) { /* can't happen */
1601 printf("wl%d RCV: ERRs %x\n", unit, status);
1602 sc->wl_if.if_ierrors++;
1603 } else if (!wlread(unit, fd_p))
1606 if (!wlrequeue(unit, fd_p)) {
1607 /* abort on chain error */
1608 if (wlhwrst(unit) != TRUE)
1609 printf("wl%d rcv(): hwrst trouble.\n", unit);
1612 sc->begin_fd = link_offset;
1623 * This routine puts rbd's used in the last receive back onto the
1624 * free list for the next receive.
1628 wlrequeue(int unit, u_short fd_p)
1630 struct wl_softc *sc = WLSOFTC(unit);
1631 short base = sc->base;
1633 u_short l_rbdp, f_rbdp, rbd_offset;
1635 outw(PIOR0(base), fd_p + 6);
1636 rbd_offset = inw(PIOP0(base));
1637 if ((f_rbdp = rbd_offset) != I82586NULL) {
1640 outw(PIOR0(base), l_rbdp + 0); /* address of status */
1641 if(inw(PIOP0(base)) & RBD_SW_EOF)
1643 outw(PIOP0(base), 0);
1644 outw(PIOR0(base), l_rbdp + 2); /* next_rbd_offset */
1645 if((l_rbdp = inw(PIOP0(base))) == I82586NULL)
1648 outw(PIOP0(base), 0);
1649 outw(PIOR0(base), l_rbdp + 2); /* next_rbd_offset */
1650 outw(PIOP0(base), I82586NULL);
1651 outw(PIOR0(base), l_rbdp + 8); /* address of size */
1652 outw(PIOP0(base), inw(PIOP0(base)) | AC_CW_EL);
1653 outw(PIOR0(base), sc->end_rbd + 2);
1654 outw(PIOP0(base), f_rbdp); /* end_rbd->next_rbd_offset */
1655 outw(PIOR0(base), sc->end_rbd + 8); /* size */
1656 outw(PIOP0(base), inw(PIOP0(base)) & ~AC_CW_EL);
1657 sc->end_rbd = l_rbdp;
1661 fd.command = AC_CW_EL;
1662 fd.link_offset = I82586NULL;
1663 fd.rbd_offset = I82586NULL;
1664 outw(PIOR1(base), fd_p);
1665 outsw(PIOP1(base), &fd, 8/2);
1667 outw(PIOR1(base), sc->end_fd + 2); /* addr of command */
1668 outw(PIOP1(base), 0); /* command = 0 */
1669 outw(PIOP1(base), fd_p); /* end_fd->link_offset = fd_p */
1676 static int xmt_debug = 0;
1677 #endif /* WLDEBUG */
1682 * This routine fills in the appropriate registers and memory
1683 * locations on the WaveLAN board and starts the board off on
1686 * input : board number of interest, and a pointer to the mbuf
1687 * output : board memory and registers are set for xfer and attention
1691 wlxmt(int unit, struct mbuf *m)
1693 struct wl_softc *sc = WLSOFTC(unit);
1694 u_short xmtdata_p = OFFSET_TBUF;
1696 struct mbuf *tm_p = m;
1697 struct ether_header *eh_p = mtod(m, struct ether_header *);
1698 u_char *mb_p = mtod(m, u_char *) + sizeof(struct ether_header);
1699 u_short count = m->m_len - sizeof(struct ether_header);
1701 u_short tbd_p = OFFSET_TBD;
1702 u_short len, clen = 0;
1703 short base = sc->base;
1707 if (sc->wl_if.if_flags & IFF_DEBUG)
1708 printf("wl%d: entered wlxmt()\n",unit);
1712 cb.ac_command = (AC_CW_EL|AC_TRANSMIT|AC_CW_I);
1713 cb.ac_link_offset = I82586NULL;
1714 outw(PIOR1(base), OFFSET_CU);
1715 outsw(PIOP1(base), &cb, 6/2);
1716 outw(PIOP1(base), OFFSET_TBD); /* cb.cmd.transmit.tbd_offset */
1717 outsw(PIOP1(base), eh_p->ether_dhost, WAVELAN_ADDR_SIZE/2);
1718 outw(PIOP1(base), eh_p->ether_type);
1721 if (sc->wl_if.if_flags & IFF_DEBUG) {
1723 printf("XMT mbuf: L%d @%p ", count, (void *)mb_p);
1724 printf("ether type %x\n", eh_p->ether_type);
1727 #endif /* WLDEBUG */
1728 outw(PIOR0(base), OFFSET_TBD);
1729 outw(PIOP0(base), 0); /* act_count */
1730 outw(PIOR1(base), OFFSET_TBD + 4);
1731 outw(PIOP1(base), xmtdata_p); /* buffer_addr */
1732 outw(PIOP1(base), 0); /* buffer_base */
1735 if (clen + count > WAVELAN_MTU)
1741 outw(PIOR1(base), xmtdata_p);
1742 outsw(PIOP1(base), mb_p, len/2);
1744 outw(PIOR0(base), tbd_p); /* address of act_count */
1745 outw(PIOP0(base), inw(PIOP0(base)) + count);
1747 if ((tm_p = tm_p->m_next) == (struct mbuf *)0)
1750 /* go to the next descriptor */
1751 outw(PIOR0(base), tbd_p + 2);
1752 tbd_p += sizeof (tbd_t);
1753 outw(PIOP0(base), tbd_p); /* next_tbd_offset */
1754 outw(PIOR0(base), tbd_p);
1755 outw(PIOP0(base), 0); /* act_count */
1756 outw(PIOR1(base), tbd_p + 4);
1757 outw(PIOP1(base), xmtdata_p); /* buffer_addr */
1758 outw(PIOP1(base), 0); /* buffer_base */
1759 /* at the end -> coallesce remaining mbufs */
1760 if (tbd_p == OFFSET_TBD + (N_TBD-1) * sizeof (tbd_t)) {
1761 wlsftwsleaze(&count, &mb_p, &tm_p, unit);
1764 /* next mbuf short -> coallesce as needed */
1765 if ( (tm_p->m_next == (struct mbuf *) 0) ||
1766 #define HDW_THRESHOLD 55
1767 tm_p->m_len > HDW_THRESHOLD)
1770 wlhdwsleaze(&count, &mb_p, &tm_p, unit);
1774 } else if ((tm_p = tm_p->m_next) == (struct mbuf *)0)
1776 count = tm_p->m_len;
1777 mb_p = mtod(tm_p, u_char *);
1779 if (sc->wl_if.if_flags & IFF_DEBUG)
1781 printf("mbuf+ L%d @%p ", count, (void *)mb_p);
1782 #endif /* WLDEBUG */
1785 if (sc->wl_if.if_flags & IFF_DEBUG)
1787 printf("CLEN = %d\n", clen);
1788 #endif /* WLDEBUG */
1789 outw(PIOR0(base), tbd_p);
1790 if (clen < ETHERMIN) {
1791 outw(PIOP0(base), inw(PIOP0(base)) + ETHERMIN - clen);
1792 outw(PIOR1(base), xmtdata_p);
1793 for (xmtshort_p = xmtdata_p; clen < ETHERMIN; clen += 2)
1794 outw(PIOP1(base), 0);
1796 outw(PIOP0(base), inw(PIOP0(base)) | TBD_SW_EOF);
1797 outw(PIOR0(base), tbd_p + 2);
1798 outw(PIOP0(base), I82586NULL);
1800 if (sc->wl_if.if_flags & IFF_DEBUG) {
1806 #endif /* WLDEBUG */
1808 outw(PIOR0(base), OFFSET_SCB + 2); /* address of scb_command */
1810 * wait for 586 to clear previous command, complain if it takes
1813 for (spin = 1;;spin = (spin + 1) % 10000) {
1814 if (inw(PIOP0(base)) == 0) { /* it's done, we can go */
1817 if ((spin == 0) && xmt_watch) { /* not waking up, and we care */
1818 printf("wl%d: slow accepting xmit\n",unit);
1821 outw(PIOP0(base), SCB_CU_STRT); /* new command */
1822 SET_CHAN_ATTN(unit);
1827 * Pause to avoid transmit overrun problems.
1828 * The required delay tends to vary with platform type, and may be
1829 * related to interrupt loss.
1831 if (wl_xmit_delay) {
1832 DELAY(wl_xmit_delay);
1840 * This function builds the linear linked lists of fd's and
1841 * rbd's. Based on page 4-32 of 1986 Intel microcom handbook.
1847 struct wl_softc *sc = WLSOFTC(unit);
1848 short base = sc->base;
1851 u_short fd_p = OFFSET_RU;
1852 u_short rbd_p = OFFSET_RBD;
1855 sc->begin_fd = fd_p;
1856 for(i = 0; i < N_FD; i++) {
1859 fd.link_offset = fd_p + sizeof(fd_t);
1860 fd.rbd_offset = I82586NULL;
1861 outw(PIOR1(base), fd_p);
1862 outsw(PIOP1(base), &fd, 8/2);
1863 fd_p = fd.link_offset;
1865 fd_p -= sizeof(fd_t);
1867 outw(PIOR1(base), fd_p + 2);
1868 outw(PIOP1(base), AC_CW_EL); /* command */
1869 outw(PIOP1(base), I82586NULL); /* link_offset */
1872 outw(PIOR0(base), fd_p + 6); /* address of rbd_offset */
1873 outw(PIOP0(base), rbd_p);
1874 outw(PIOR1(base), rbd_p);
1875 for(i = 0; i < N_RBD; i++) {
1877 rbd.buffer_addr = rbd_p + sizeof(rbd_t) + 2;
1878 rbd.buffer_base = 0;
1879 rbd.size = RCVBUFSIZE;
1881 rbd_p += sizeof(ru_t);
1882 rbd.next_rbd_offset = rbd_p;
1884 rbd.next_rbd_offset = I82586NULL;
1885 rbd.size |= AC_CW_EL;
1886 sc->end_rbd = rbd_p;
1888 outsw(PIOP1(base), &rbd, sizeof(rbd_t)/2);
1889 outw(PIOR1(base), rbd_p);
1891 return sc->begin_fd;
1897 * This routine starts the receive unit running. First checks if the
1898 * board is actually ready, then the board is instructed to receive
1905 struct wl_softc *sc = WLSOFTC(unit);
1906 short base = sc->base;
1910 if (sc->wl_if.if_flags & IFF_DEBUG)
1911 printf("wl%d: entered wlrustrt()\n",unit);
1913 outw(PIOR0(base), OFFSET_SCB);
1914 if (inw(PIOP0(base)) & SCB_RUS_READY){
1915 printf("wlrustrt: RUS_READY\n");
1919 outw(PIOR0(base), OFFSET_SCB + 2);
1920 outw(PIOP0(base), SCB_RU_STRT); /* command */
1921 rfa = wlbldru(unit);
1922 outw(PIOR0(base), OFFSET_SCB + 6); /* address of scb_rfa_offset */
1923 outw(PIOP0(base), rfa);
1925 SET_CHAN_ATTN(unit);
1932 * This routine does a 586 op-code number 7, and obtains the
1933 * diagnose status for the WaveLAN.
1939 struct wl_softc *sc = WLSOFTC(unit);
1940 short base = sc->base;
1944 if (sc->wl_if.if_flags & IFF_DEBUG)
1945 printf("wl%d: entered wldiag()\n",unit);
1947 outw(PIOR0(base), OFFSET_SCB);
1948 status = inw(PIOP0(base));
1949 if (status & SCB_SW_INT) {
1950 /* state is 2000 which seems ok
1951 printf("wl%d diag(): unexpected initial state %\n",
1952 unit, inw(PIOP0(base)));
1956 outw(PIOR1(base), OFFSET_CU);
1957 outw(PIOP1(base), 0); /* ac_status */
1958 outw(PIOP1(base), AC_DIAGNOSE|AC_CW_EL);/* ac_command */
1959 if(wlcmd(unit, "diag()") == 0)
1961 outw(PIOR0(base), OFFSET_CU);
1962 if (inw(PIOP0(base)) & 0x0800) {
1963 printf("wl%d: i82586 Self Test failed!\n", unit);
1972 * This routine does a standard config of the WaveLAN board.
1978 configure_t configure;
1979 struct wl_softc *sc = WLSOFTC(unit);
1980 short base = sc->base;
1983 #if defined(__DragonFly__) || (defined(__FreeBSD__) && __FreeBSD_version >= 300000)
1984 struct ifmultiaddr *ifma;
1987 struct ether_multi *enm;
1988 struct ether_multistep step;
1991 #endif /* MULTICAST */
1994 if (sc->wl_if.if_flags & IFF_DEBUG)
1995 printf("wl%d: entered wlconfig()\n",unit);
1997 outw(PIOR0(base), OFFSET_SCB);
1998 if (inw(PIOP0(base)) & SCB_SW_INT) {
2000 printf("wl%d config(): unexpected initial state %x\n",
2001 unit, inw(PIOP0(base)));
2006 outw(PIOR1(base), OFFSET_CU);
2007 outw(PIOP1(base), 0); /* ac_status */
2008 outw(PIOP1(base), AC_CONFIGURE|AC_CW_EL); /* ac_command */
2011 configure.fifolim_bytecnt = 0x080c;
2012 configure.addrlen_mode = 0x0600;
2013 configure.linprio_interframe = 0x2060;
2014 configure.slot_time = 0xf200;
2015 configure.hardware = 0x0008; /* tx even w/o CD */
2016 configure.min_frame_len = 0x0040;
2018 /* This is the configuration block suggested by Marc Meertens
2019 * <mmeerten@obelix.utrecht.NCR.COM> in an e-mail message to John
2020 * Ioannidis on 10 Nov 92.
2022 configure.fifolim_bytecnt = 0x040c;
2023 configure.addrlen_mode = 0x0600;
2024 configure.linprio_interframe = 0x2060;
2025 configure.slot_time = 0xf000;
2026 configure.hardware = 0x0008; /* tx even w/o CD */
2027 configure.min_frame_len = 0x0040;
2030 * below is the default board configuration from p2-28 from 586 book
2032 configure.fifolim_bytecnt = 0x080c;
2033 configure.addrlen_mode = 0x2600;
2034 configure.linprio_interframe = 0x7820; /* IFS=120, ACS=2 */
2035 configure.slot_time = 0xf00c; /* slottime=12 */
2036 configure.hardware = 0x0008; /* tx even w/o CD */
2037 configure.min_frame_len = 0x0040;
2039 if(sc->mode & (MOD_PROM | MOD_ENAL)) {
2040 configure.hardware |= 1;
2042 outw(PIOR1(base), OFFSET_CU + 6);
2043 outsw(PIOP1(base), &configure, sizeof(configure_t)/2);
2045 if(wlcmd(unit, "config()-configure") == 0)
2048 outw(PIOR1(base), OFFSET_CU);
2049 outw(PIOP1(base), 0); /* ac_status */
2050 outw(PIOP1(base), AC_MCSETUP|AC_CW_EL); /* ac_command */
2051 outw(PIOR1(base), OFFSET_CU + 8);
2052 #if defined(__DragonFly__) || (defined(__FreeBSD__) && __FreeBSD_version >= 300000)
2053 for (ifma = sc->wl_if.if_multiaddrs.lh_first; ifma;
2054 ifma = ifma->ifma_link.le_next) {
2055 if (ifma->ifma_addr->sa_family != AF_LINK)
2058 addrp = LLADDR((struct sockaddr_dl *)ifma->ifma_addr);
2059 outw(PIOP1(base), addrp[0] + (addrp[1] << 8));
2060 outw(PIOP1(base), addrp[2] + (addrp[3] << 8));
2061 outw(PIOP1(base), addrp[4] + (addrp[5] << 8));
2065 ETHER_FIRST_MULTI(step, &sc->wl_ac, enm);
2066 while (enm != NULL) {
2067 unsigned int lo, hi;
2068 /* break if setting a multicast range, else we would crash */
2069 if (bcmp(enm->enm_addrlo, enm->enm_addrhi, 6) != 0) {
2072 lo = (enm->enm_addrlo[3] << 16) + (enm->enm_addrlo[4] << 8)
2073 + enm->enm_addrlo[5];
2074 hi = (enm->enm_addrhi[3] << 16) + (enm->enm_addrhi[4] << 8)
2075 + enm->enm_addrhi[5];
2077 outw(PIOP1(base),enm->enm_addrlo[0] +
2078 (enm->enm_addrlo[1] << 8));
2079 outw(PIOP1(base),enm->enm_addrlo[2] +
2080 ((lo >> 8) & 0xff00));
2081 outw(PIOP1(base), ((lo >> 8) & 0xff) +
2082 ((lo << 8) & 0xff00));
2083 /* #define MCASTDEBUG */
2085 printf("mcast_addr[%d,%d,%d] %x %x %x %x %x %x\n", lo, hi, cnt,
2091 enm->enm_addrlo[5]);
2096 ETHER_NEXT_MULTI(step, enm);
2099 outw(PIOR1(base), OFFSET_CU + 6); /* mc-cnt */
2100 outw(PIOP1(base), cnt * WAVELAN_ADDR_SIZE);
2101 if(wlcmd(unit, "config()-mcaddress") == 0)
2103 #endif /* MULTICAST */
2105 outw(PIOR1(base), OFFSET_CU);
2106 outw(PIOP1(base), 0); /* ac_status */
2107 outw(PIOP1(base), AC_IASETUP|AC_CW_EL); /* ac_command */
2108 outw(PIOR1(base), OFFSET_CU + 6);
2109 outsw(PIOP1(base), sc->wl_addr, WAVELAN_ADDR_SIZE/2);
2111 if(wlcmd(unit, "config()-address") == 0)
2122 * Set channel attention bit and busy wait until command has
2123 * completed. Then acknowledge the command completion.
2126 wlcmd(int unit, char *str)
2128 struct wl_softc *sc = WLSOFTC(unit);
2129 short base = sc->base;
2132 outw(PIOR0(base), OFFSET_SCB + 2); /* address of scb_command */
2133 outw(PIOP0(base), SCB_CU_STRT);
2135 SET_CHAN_ATTN(unit);
2137 outw(PIOR0(base), OFFSET_CU);
2138 for(i = 0; i < 0xffff; i++)
2139 if (inw(PIOP0(base)) & AC_SW_C)
2141 if (i == 0xffff || !(inw(PIOP0(base)) & AC_SW_OK)) {
2142 printf("wl%d: %s failed; status = %d, inw = %x, outw = %x\n",
2143 unit, str, inw(PIOP0(base)) & AC_SW_OK, inw(PIOP0(base)), inw(PIOR0(base)));
2144 outw(PIOR0(base), OFFSET_SCB);
2145 printf("scb_status %x\n", inw(PIOP0(base)));
2146 outw(PIOR0(base), OFFSET_SCB+2);
2147 printf("scb_command %x\n", inw(PIOP0(base)));
2148 outw(PIOR0(base), OFFSET_SCB+4);
2149 printf("scb_cbl %x\n", inw(PIOP0(base)));
2150 outw(PIOR0(base), OFFSET_CU+2);
2151 printf("cu_cmd %x\n", inw(PIOP0(base)));
2155 outw(PIOR0(base), OFFSET_SCB);
2156 if ((inw(PIOP0(base)) & SCB_SW_INT) && (inw(PIOP0(base)) != SCB_SW_CNA)) {
2158 printf("wl%d %s: unexpected final state %x\n",
2159 unit, str, inw(PIOP0(base)));
2167 * wlack: if the 82596 wants attention because it has finished
2168 * sending or receiving a packet, acknowledge its desire and
2169 * return bits indicating the kind of attention. wlack() returns
2170 * these bits so that the caller can service exactly the
2171 * conditions that wlack() acknowledged.
2178 struct wl_softc *sc = WLSOFTC(unit);
2179 short base = sc->base;
2181 outw(PIOR1(base), OFFSET_SCB);
2182 if(!(cmd = (inw(PIOP1(base)) & SCB_SW_INT)))
2185 if (sc->wl_if.if_flags & IFF_DEBUG)
2186 printf("wl%d: doing a wlack()\n",unit);
2188 outw(PIOP1(base), cmd);
2189 SET_CHAN_ATTN(unit);
2190 outw(PIOR0(base), OFFSET_SCB + 2); /* address of scb_command */
2191 for (i = 1000000; inw(PIOP0(base)) && (i-- > 0); );
2193 printf("wl%d wlack(): board not accepting command.\n", unit);
2200 struct wl_softc *sc = WLSOFTC(unit);
2201 short base = sc->base;
2202 u_short tbd_p = OFFSET_TBD;
2208 outw(PIOR1(base), tbd_p);
2209 insw(PIOP1(base), &tbd, sizeof(tbd_t)/2);
2210 sum += (tbd.act_count & ~TBD_SW_EOF);
2211 printf("%d: addr %x, count %d (%d), next %x, base %x\n",
2212 i++, tbd.buffer_addr,
2213 (tbd.act_count & ~TBD_SW_EOF), sum,
2214 tbd.next_tbd_offset, tbd.buffer_base);
2215 if (tbd.act_count & TBD_SW_EOF)
2217 tbd_p = tbd.next_tbd_offset;
2222 wlhdwsleaze(u_short *countp, u_char **mb_pp, struct mbuf **tm_pp, int unit)
2224 struct mbuf *tm_p = *tm_pp;
2225 u_char *mb_p = *mb_pp;
2231 * can we get a run that will be coallesced or
2232 * that terminates before breaking
2235 count += tm_p->m_len;
2236 if (tm_p->m_len & 1)
2238 } while ((tm_p = tm_p->m_next) != (struct mbuf *)0);
2239 if ( (tm_p == (struct mbuf *)0) ||
2240 count > HDW_THRESHOLD) {
2241 *countp = (*tm_pp)->m_len;
2242 *mb_pp = mtod((*tm_pp), u_char *);
2246 /* we need to copy */
2250 cp = (u_char *) t_packet;
2252 bcopy(mtod(tm_p, u_char *), cp, len = tm_p->m_len);
2254 if (count > HDW_THRESHOLD)
2257 if (tm_p->m_next == (struct mbuf *)0)
2259 tm_p = tm_p->m_next;
2262 *mb_pp = (u_char *) t_packet;
2269 wlsftwsleaze(u_short *countp, u_char **mb_pp, struct mbuf **tm_pp, int unit)
2271 struct mbuf *tm_p = *tm_pp;
2273 u_char *cp = (u_char *) t_packet;
2276 /* we need to copy */
2278 bcopy(mtod(tm_p, u_char *), cp, len = tm_p->m_len);
2281 if (tm_p->m_next == (struct mbuf *)0)
2283 tm_p = tm_p->m_next;
2287 *mb_pp = (u_char *) t_packet;
2295 struct wl_softc *sc = WLSOFTC(unit);
2296 short base = sc->base;
2299 printf("wl%d: DCE_STATUS: 0x%x, ", unit,
2300 wlmmcread(base,MMC_DCE_STATUS) & 0x0f);
2301 tmp = wlmmcread(base,MMC_CORRECT_NWID_H) << 8;
2302 tmp |= wlmmcread(base,MMC_CORRECT_NWID_L);
2303 printf("Correct NWID's: %d, ", tmp);
2304 tmp = wlmmcread(base,MMC_WRONG_NWID_H) << 8;
2305 tmp |= wlmmcread(base,MMC_WRONG_NWID_L);
2306 printf("Wrong NWID's: %d\n", tmp);
2307 printf("THR_PRE_SET: 0x%x, ", wlmmcread(base,MMC_THR_PRE_SET));
2308 printf("SIGNAL_LVL: %d, SILENCE_LVL: %d\n",
2309 wlmmcread(base,MMC_SIGNAL_LVL),
2310 wlmmcread(base,MMC_SILENCE_LVL));
2311 printf("SIGN_QUAL: 0x%x, NETW_ID: %x:%x, DES: %d\n",
2312 wlmmcread(base,MMC_SIGN_QUAL),
2313 wlmmcread(base,MMC_NETW_ID_H),
2314 wlmmcread(base,MMC_NETW_ID_L),
2315 wlmmcread(base,MMC_DES_AVAIL));
2319 wlmmcread(u_int base, u_short reg)
2321 while(inw(HASR(base)) & HASR_MMC_BUSY) ;
2322 outw(MMCR(base),reg << 1);
2323 while(inw(HASR(base)) & HASR_MMC_BUSY) ;
2324 return (u_short)inw(MMCR(base)) >> 8;
2330 MMC_WRITE(MMC_FREEZE,1);
2332 * SNR retrieval procedure :
2334 * read signal level : wlmmcread(base, MMC_SIGNAL_LVL);
2335 * read silence level : wlmmcread(base, MMC_SILENCE_LVL);
2337 MMC_WRITE(MMC_FREEZE,0);
2339 * SNR is signal:silence ratio.
2346 ** Reads the psa for the wavelan at (base) into (buf)
2349 wlgetpsa(int base, u_char *buf)
2353 PCMD(base, HACR_DEFAULT & ~HACR_16BITS);
2354 PCMD(base, HACR_DEFAULT & ~HACR_16BITS);
2356 for (i = 0; i < 0x40; i++) {
2357 outw(PIOR2(base), i);
2358 buf[i] = inb(PIOP2(base));
2360 PCMD(base, HACR_DEFAULT);
2361 PCMD(base, HACR_DEFAULT);
2367 ** Writes the psa for wavelan (unit) from the softc back to the
2368 ** board. Updates the CRC and sets the CRC OK flag.
2370 ** Do not call this when the board is operating, as it doesn't
2371 ** preserve the hacr.
2376 struct wl_softc *sc = WLSOFTC(unit);
2377 short base = sc->base;
2381 crc = wlpsacrc(sc->psa); /* calculate CRC of PSA */
2382 sc->psa[WLPSA_CRCLOW] = crc & 0xff;
2383 sc->psa[WLPSA_CRCHIGH] = (crc >> 8) & 0xff;
2384 sc->psa[WLPSA_CRCOK] = 0x55; /* default to 'bad' until programming complete */
2386 oldpri = splimp(); /* ick, long pause */
2388 PCMD(base, HACR_DEFAULT & ~HACR_16BITS);
2389 PCMD(base, HACR_DEFAULT & ~HACR_16BITS);
2391 for (i = 0; i < 0x40; i++) {
2393 outw(PIOR2(base),i); /* write param memory */
2395 outb(PIOP2(base), sc->psa[i]);
2398 outw(PIOR2(base),WLPSA_CRCOK); /* update CRC flag*/
2400 sc->psa[WLPSA_CRCOK] = 0xaa; /* OK now */
2401 outb(PIOP2(base), 0xaa); /* all OK */
2404 PCMD(base, HACR_DEFAULT);
2405 PCMD(base, HACR_DEFAULT);
2411 ** CRC routine provided by Christopher Giordano <cgiordan@gdeb.com>,
2412 ** from original code by Tomi Mikkonen (tomitm@remedy.fi)
2415 static u_int crc16_table[16] = {
2416 0x0000, 0xCC01, 0xD801, 0x1400,
2417 0xF001, 0x3C00, 0x2800, 0xE401,
2418 0xA001, 0x6C00, 0x7800, 0xB401,
2419 0x5000, 0x9C01, 0x8801, 0x4400
2423 wlpsacrc(u_char *buf)
2428 for (i = 0; i < 0x3d; i++, buf++) {
2430 r1 = crc16_table[crc & 0xF];
2431 crc = (crc >> 4) & 0x0FFF;
2432 crc = crc ^ r1 ^ crc16_table[*buf & 0xF];
2435 r1 = crc16_table[crc & 0xF];
2436 crc = (crc >> 4) & 0x0FFF;
2437 crc = crc ^ r1 ^ crc16_table[(*buf >> 4) & 0xF];
2446 * take input packet and cache various radio hw characteristics
2447 * indexed by MAC address.
2449 * Some things to think about:
2450 * note that no space is malloced.
2451 * We might hash the mac address if the cache were bigger.
2452 * It is not clear that the cache is big enough.
2453 * It is also not clear how big it should be.
2454 * The cache is IP-specific. We don't care about that as
2455 * we want it to be IP-specific.
2456 * The last N recv. packets are saved. This will tend
2457 * to reward agents and mobile hosts that beacon.
2458 * That is probably fine for mobile ip.
2461 /* globals for wavelan signal strength cache */
2462 /* this should go into softc structure above.
2465 /* set true if you want to limit cache items to broadcast/mcast
2466 * only packets (not unicast)
2468 static int wl_cache_mcastonly = 1;
2469 SYSCTL_INT(_machdep, OID_AUTO, wl_cache_mcastonly, CTLFLAG_RW,
2470 &wl_cache_mcastonly, 0, "");
2472 /* set true if you want to limit cache items to IP packets only
2474 static int wl_cache_iponly = 1;
2475 SYSCTL_INT(_machdep, OID_AUTO, wl_cache_iponly, CTLFLAG_RW,
2476 &wl_cache_iponly, 0, "");
2478 /* zero out the cache
2481 wl_cache_zero(int unit)
2483 struct wl_softc *sc = WLSOFTC(unit);
2485 bzero(&sc->w_sigcache[0], sizeof(struct w_sigcache) * MAXCACHEITEMS);
2487 sc->w_nextcache = 0;
2488 sc->w_wrapindex = 0;
2491 /* store hw signal info in cache.
2492 * index is MAC address, but an ip src gets stored too
2493 * There are two filters here controllable via sysctl:
2494 * throw out unicast (on by default, but can be turned off)
2495 * throw out non-ip (on by default, but can be turned off)
2498 void wl_cache_store (int unit, int base, struct ether_header *eh,
2501 struct ip *ip = NULL; /* Avoid GCC warning */
2503 int signal, silence;
2504 int w_insertcache; /* computed index for cache entry storage */
2505 struct wl_softc *sc = WLSOFTC(unit);
2506 int ipflag = wl_cache_iponly;
2510 * 2. configurable filter to throw out unicast packets,
2511 * keep multicast only.
2515 /* reject if not IP packet
2517 if ( wl_cache_iponly && (ntohs(eh->ether_type) != 0x800)) {
2521 /* check if broadcast or multicast packet. we toss
2524 if (wl_cache_mcastonly && ((eh->ether_dhost[0] & 1) == 0)) {
2528 /* find the ip header. we want to store the ip_src
2529 * address. use the mtod macro(in mbuf.h)
2530 * to typecast m to struct ip *
2533 ip = mtod(m, struct ip *);
2536 /* do a linear search for a matching MAC address
2537 * in the cache table
2538 * . MAC address is 6 bytes,
2539 * . var w_nextcache holds total number of entries already cached
2541 for(i = 0; i < sc->w_nextcache; i++) {
2542 if (! bcmp(eh->ether_shost, sc->w_sigcache[i].macsrc, 6 )) {
2544 * so we already have this entry,
2545 * update the data, and LRU age
2551 /* did we find a matching mac address?
2552 * if yes, then overwrite a previously existing cache entry
2554 if (i < sc->w_nextcache ) {
2557 /* else, have a new address entry,so
2558 * add this new entry,
2559 * if table full, then we need to replace entry
2563 /* check for space in cache table
2564 * note: w_nextcache also holds number of entries
2565 * added in the cache table
2567 if ( sc->w_nextcache < MAXCACHEITEMS ) {
2568 w_insertcache = sc->w_nextcache;
2570 sc->w_sigitems = sc->w_nextcache;
2572 /* no space found, so simply wrap with wrap index
2573 * and "zap" the next entry
2576 if (sc->w_wrapindex == MAXCACHEITEMS) {
2577 sc->w_wrapindex = 0;
2579 w_insertcache = sc->w_wrapindex++;
2583 /* invariant: w_insertcache now points at some slot
2586 if (w_insertcache < 0 || w_insertcache >= MAXCACHEITEMS) {
2588 "wl_cache_store, bad index: %d of [0..%d], gross cache error\n",
2589 w_insertcache, MAXCACHEITEMS);
2593 /* store items in cache
2596 * .signal (0..63) ,silence (0..63) ,quality (0..15)
2599 sc->w_sigcache[w_insertcache].ipsrc = ip->ip_src.s_addr;
2601 bcopy( eh->ether_shost, sc->w_sigcache[w_insertcache].macsrc, 6);
2602 signal = sc->w_sigcache[w_insertcache].signal = wlmmcread(base, MMC_SIGNAL_LVL) & 0x3f;
2603 silence = sc->w_sigcache[w_insertcache].silence = wlmmcread(base, MMC_SILENCE_LVL) & 0x3f;
2604 sc->w_sigcache[w_insertcache].quality = wlmmcread(base, MMC_SIGN_QUAL) & 0x0f;
2606 sc->w_sigcache[w_insertcache].snr =
2609 sc->w_sigcache[w_insertcache].snr = 0;
2613 #endif /* WLCACHE */
2616 * determine if in all multicast mode or not
2618 * returns: 1 if IFF_ALLMULTI should be set
2623 #if defined(__FreeBSD__) && __FreeBSD_version < 300000 /* not required */
2625 check_allmulti(int unit)
2627 struct wl_softc *sc = WLSOFTC(unit);
2628 short base = sc->base;
2629 struct ether_multi *enm;
2630 struct ether_multistep step;
2632 ETHER_FIRST_MULTI(step, &sc->wl_ac, enm);
2633 while (enm != NULL) {
2634 unsigned int lo, hi;
2636 printf("enm_addrlo %x:%x:%x:%x:%x:%x\n", enm->enm_addrlo[0], enm->enm_addrlo[1],
2637 enm->enm_addrlo[2], enm->enm_addrlo[3], enm->enm_addrlo[4],
2638 enm->enm_addrlo[5]);
2639 printf("enm_addrhi %x:%x:%x:%x:%x:%x\n", enm->enm_addrhi[0], enm->enm_addrhi[1],
2640 enm->enm_addrhi[2], enm->enm_addrhi[3], enm->enm_addrhi[4],
2641 enm->enm_addrhi[5]);
2643 if (bcmp(enm->enm_addrlo, enm->enm_addrhi, 6) != 0) {
2646 ETHER_NEXT_MULTI(step, enm);