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.18 2005/05/27 15:36:10 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);
1152 if (ifp->if_flags & IFF_ALLMULTI) {
1155 if (ifp->if_flags & IFF_PROMISC) {
1158 if(ifp->if_flags & IFF_LINK0) {
1162 * force a complete reset if the recieve multicast/
1163 * promiscuous mode changes so that these take
1164 * effect immediately.
1167 if (sc->mode != mode) {
1169 if (sc->flags & DSF_RUNNING) {
1170 sc->flags &= ~DSF_RUNNING;
1174 /* if interface is marked DOWN and still running then
1177 if ((ifp->if_flags & IFF_UP) == 0 && sc->flags & DSF_RUNNING) {
1178 printf("wl%d ioctl(): board is not running\n", unit);
1179 sc->flags &= ~DSF_RUNNING;
1180 sc->hacr &= ~HACR_INTRON;
1181 CMD(unit); /* turn off interrupts */
1183 /* else if interface is UP and RUNNING, start it
1185 else if (ifp->if_flags & IFF_UP && (sc->flags & DSF_RUNNING) == 0) {
1189 /* if WLDEBUG set on interface, then printf rf-modem regs
1191 if(ifp->if_flags & IFF_DEBUG)
1198 #if defined(__FreeBSD__) && __FreeBSD_version < 300000
1199 if (cmd == SIOCADDMULTI) {
1200 error = ether_addmulti(ifr, &sc->wl_ac);
1203 error = ether_delmulti(ifr, &sc->wl_ac);
1206 /* see if we should be in all multicast mode
1207 * note that 82586 cannot do that, must simulate with
1210 if ( check_allmulti(unit)) {
1211 ifp->if_flags |= IFF_ALLMULTI;
1212 sc->mode |= MOD_ENAL;
1213 sc->flags &= ~DSF_RUNNING;
1219 if (error == ENETRESET) {
1220 if(sc->flags & DSF_RUNNING) {
1221 sc->flags &= ~DSF_RUNNING;
1230 #endif /* MULTICAST */
1232 /* DEVICE SPECIFIC */
1235 /* copy the PSA out to the caller */
1237 /* pointer to buffer in user space */
1238 up = (void *)ifr->ifr_data;
1239 /* work out if they're root */
1240 isroot = (suser(td) == 0);
1242 for (i = 0; i < 0x40; i++) {
1243 /* don't hand the DES key out to non-root users */
1244 if ((i > WLPSA_DESKEY) && (i < (WLPSA_DESKEY + 8)) && !isroot)
1246 if (subyte((up + i), sc->psa[i]))
1252 /* copy the PSA in from the caller; we only copy _some_ values */
1255 if ((error = suser(td)))
1257 error = EINVAL; /* assume the worst */
1258 /* pointer to buffer in user space containing data */
1259 up = (void *)ifr->ifr_data;
1261 /* check validity of input range */
1262 for (i = 0; i < 0x40; i++)
1263 if (fubyte(up + i) < 0)
1266 /* check IRQ value */
1267 irqval = fubyte(up+WLPSA_IRQNO);
1268 for (irq = 15; irq >= 0; irq--)
1269 if(irqvals[irq] == irqval)
1271 if (irq == 0) /* oops */
1274 sc->psa[WLPSA_IRQNO] = irqval;
1277 for (i = 0; i < 6; i++)
1278 sc->psa[WLPSA_LOCALMAC+i] = fubyte(up+WLPSA_LOCALMAC+i);
1281 sc->psa[WLPSA_MACSEL] = fubyte(up+WLPSA_MACSEL);
1284 sc->psa[WLPSA_NWID] = fubyte(up+WLPSA_NWID);
1285 sc->psa[WLPSA_NWID+1] = fubyte(up+WLPSA_NWID+1);
1288 wlsetpsa(unit); /* update the PSA */
1292 /* get the current NWID out of the sc since we stored it there */
1294 ifr->ifr_data = (caddr_t) (sc->nwid[0] << 8 | sc->nwid[1]);
1299 * change the nwid dynamically. This
1300 * ONLY changes the radio modem and does not
1304 * 1. save in softc "soft registers"
1305 * 2. save in radio modem (MMC)
1309 if ((error = suser(td)))
1311 if (!(ifp->if_flags & IFF_UP)) {
1312 error = EIO; /* only allowed while up */
1315 * soft c nwid shadows radio modem setting
1317 sc->nwid[0] = (int)ifr->ifr_data >> 8;
1318 sc->nwid[1] = (int)ifr->ifr_data & 0xff;
1319 MMC_WRITE(MMC_NETW_ID_L,sc->nwid[1]);
1320 MMC_WRITE(MMC_NETW_ID_H,sc->nwid[0]);
1324 /* copy the EEPROM in 2.4 Gz WaveMODEM out to the caller */
1327 if ((error = suser(td)))
1329 /* pointer to buffer in user space */
1330 up = (void *)ifr->ifr_data;
1332 for (i=0x00; i<0x80; ++i) { /* 2.4 Gz: size of EEPROM */
1333 MMC_WRITE(MMC_EEADDR,i); /* 2.4 Gz: get frequency */
1334 MMC_WRITE(MMC_EECTRL, /* 2.4 Gz: EEPROM read */
1335 MMC_EECTRL_EEOP_READ); /* 2.4 Gz: */
1336 DELAY(40); /* 2.4 Gz */
1337 if (subyte(up + 2*i , /* 2.4 Gz: pass low byte of */
1338 wlmmcread(base,MMC_EEDATALrv)) /* 2.4 Gz: EEPROM word */
1339 ) return(EFAULT); /* 2.4 Gz: */
1340 if (subyte(up + 2*i+1, /* 2.4 Gz: pass hi byte of */
1341 wlmmcread(base,MMC_EEDATALrv)) /* 2.4 Gz: EEPROM word */
1342 ) return(EFAULT); /* 2.4 Gz: */
1347 /* zero (Delete) the wl cache */
1350 if ((error = suser(td)))
1352 wl_cache_zero(unit);
1355 /* read out the number of used cache elements */
1357 ifr->ifr_data = (caddr_t) sc->w_sigitems;
1360 /* read out the wl cache */
1362 /* pointer to buffer in user space */
1363 up = (void *)ifr->ifr_data;
1364 cpt = (char *) &sc->w_sigcache[0];
1365 size = sc->w_sigitems * sizeof(struct w_sigcache);
1367 for (i = 0; i < size; i++) {
1368 if (subyte((up + i), *cpt++))
1375 error = ether_ioctl(ifp, cmd, data);
1385 * Called if the timer set in wlstart expires before an interrupt is received
1386 * from the wavelan. It seems to lose interrupts sometimes.
1387 * The watchdog routine gets called if the transmitter failed to interrupt
1389 * input : which board is timing out
1390 * output : board reset
1394 wlwatchdog(void *vsc)
1396 struct wl_softc *sc = vsc;
1397 int unit = sc->unit;
1399 log(LOG_ERR, "wl%d: wavelan device timeout on xmit\n", unit);
1400 sc->wl_ac.ac_if.if_oerrors++;
1407 * This function is the interrupt handler for the WaveLAN
1408 * board. This routine will be called whenever either a packet
1409 * is received, or a packet has successfully been transfered and
1410 * the unit is ready to transmit another packet.
1412 * input : board number that interrupted
1413 * output : either a packet is received, or a packet is transfered
1420 struct wl_softc *sc = &wl_softc[unit];
1421 short base = sc->base;
1423 u_short int_type, int_type1;
1426 if (sc->wl_if.if_flags & IFF_DEBUG)
1427 printf("wl%d: wlintr() called\n",unit);
1430 if((int_type = inw(HASR(base))) & HASR_MMC_INTR) {
1431 /* handle interrupt from the modem management controler */
1432 /* This will clear the interrupt condition */
1433 (void) wlmmcread(base,MMC_DCE_STATUS); /* ignored for now */
1436 if(!(int_type & HASR_INTR)){ /* return if no interrupt from 82586 */
1437 /* commented out. jrb. it happens when reinit occurs
1438 printf("wlintr: int_type %x, dump follows\n", int_type);
1447 outw(PIOR0(base), OFFSET_SCB + 0); /* get scb status */
1448 int_type = (inw(PIOP0(base)) & SCB_SW_INT);
1449 if (int_type == 0) /* no interrupts left */
1452 int_type1 = wlack(unit); /* acknowledge interrupt(s) */
1453 /* make sure no bits disappeared (others may appear) */
1454 if ((int_type & int_type1) != int_type)
1455 printf("wlack() int bits disappeared : %04x != int_type %04x\n",
1456 int_type1, int_type);
1457 int_type = int_type1; /* go with the new status */
1461 if (int_type & SCB_SW_FR) {
1462 sc->wl_if.if_ipackets++;
1466 * receiver not ready
1468 if (int_type & SCB_SW_RNR) {
1469 sc->wl_if.if_ierrors++;
1471 if (sc->wl_if.if_flags & IFF_DEBUG)
1472 printf("wl%d intr(): receiver overrun! begin_fd = %x\n",
1473 unit, sc->begin_fd);
1480 if (int_type & SCB_SW_CNA) {
1482 * At present, we don't care about CNA's. We
1483 * believe they are a side effect of XMT.
1486 if (int_type & SCB_SW_CX) {
1488 * At present, we only request Interrupt for
1491 outw(PIOR1(base), OFFSET_CU); /* get command status */
1492 ac_status = inw(PIOP1(base));
1494 if (xmt_watch) { /* report some anomalies */
1496 if (sc->tbusy == 0) {
1497 printf("wl%d: xmt intr but not busy, CU %04x\n",
1500 if (ac_status == 0) {
1501 printf("wl%d: xmt intr but ac_status == 0\n", unit);
1503 if (ac_status & AC_SW_A) {
1504 printf("wl%d: xmt aborted\n",unit);
1507 if (ac_status & TC_CARRIER) {
1508 printf("wl%d: no carrier\n", unit);
1511 if (ac_status & TC_CLS) {
1512 printf("wl%d: no CTS\n", unit);
1514 if (ac_status & TC_DMA) {
1515 printf("wl%d: DMA underrun\n", unit);
1517 if (ac_status & TC_DEFER) {
1518 printf("wl%d: xmt deferred\n",unit);
1520 if (ac_status & TC_SQE) {
1521 printf("wl%d: heart beat\n", unit);
1523 if (ac_status & TC_COLLISION) {
1524 printf("wl%d: too many collisions\n", unit);
1527 /* if the transmit actually failed, or returned some status */
1528 if ((!(ac_status & AC_SW_OK)) || (ac_status & 0xfff)) {
1529 if (ac_status & (TC_COLLISION | TC_CLS | TC_DMA)) {
1530 sc->wl_if.if_oerrors++;
1532 /* count collisions */
1533 sc->wl_if.if_collisions += (ac_status & 0xf);
1534 /* if TC_COLLISION set and collision count zero, 16 collisions */
1535 if ((ac_status & 0x20) == 0x20) {
1536 sc->wl_if.if_collisions += 0x10;
1540 callout_stop(&sc->watchdog_ch);
1541 sc->wl_ac.ac_if.if_flags &= ~IFF_OACTIVE;
1542 wlstart(&(sc->wl_if));
1551 * This routine is called by the interrupt handler to initiate a
1552 * packet transfer from the board to the "if" layer above this
1553 * driver. This routine checks if a buffer has been successfully
1554 * received by the WaveLAN. If so, the routine wlread is called
1555 * to do the actual transfer of the board data (including the
1556 * ethernet header) into a packet (consisting of an mbuf chain).
1558 * input : number of the board to check
1559 * output : if a packet is available, it is "sent up"
1565 struct wl_softc *sc = WLSOFTC(unit);
1566 short base = sc->base;
1567 u_short fd_p, status, offset, link_offset;
1570 if (sc->wl_if.if_flags & IFF_DEBUG)
1571 printf("wl%d: entered wlrcv()\n",unit);
1573 for (fd_p = sc->begin_fd; fd_p != I82586NULL; fd_p = sc->begin_fd) {
1575 outw(PIOR0(base), fd_p + 0); /* address of status */
1576 status = inw(PIOP0(base));
1577 outw(PIOR1(base), fd_p + 4); /* address of link_offset */
1578 link_offset = inw(PIOP1(base));
1579 offset = inw(PIOP1(base)); /* rbd_offset */
1580 if (status == 0xffff || offset == 0xffff /*I82586NULL*/) {
1581 if (wlhwrst(unit) != TRUE)
1582 printf("wl%d rcv(): hwrst ffff trouble.\n", unit);
1584 } else if (status & AC_SW_C) {
1585 if (status == (RFD_DONE|RFD_RSC)) {
1588 if (sc->wl_if.if_flags & IFF_DEBUG)
1589 printf("wl%d RCV: RSC %x\n", unit, status);
1591 sc->wl_if.if_ierrors++;
1592 } else if (!(status & RFD_OK)) {
1593 printf("wl%d RCV: !OK %x\n", unit, status);
1594 sc->wl_if.if_ierrors++;
1595 } else if (status & 0xfff) { /* can't happen */
1596 printf("wl%d RCV: ERRs %x\n", unit, status);
1597 sc->wl_if.if_ierrors++;
1598 } else if (!wlread(unit, fd_p))
1601 if (!wlrequeue(unit, fd_p)) {
1602 /* abort on chain error */
1603 if (wlhwrst(unit) != TRUE)
1604 printf("wl%d rcv(): hwrst trouble.\n", unit);
1607 sc->begin_fd = link_offset;
1618 * This routine puts rbd's used in the last receive back onto the
1619 * free list for the next receive.
1623 wlrequeue(int unit, u_short fd_p)
1625 struct wl_softc *sc = WLSOFTC(unit);
1626 short base = sc->base;
1628 u_short l_rbdp, f_rbdp, rbd_offset;
1630 outw(PIOR0(base), fd_p + 6);
1631 rbd_offset = inw(PIOP0(base));
1632 if ((f_rbdp = rbd_offset) != I82586NULL) {
1635 outw(PIOR0(base), l_rbdp + 0); /* address of status */
1636 if(inw(PIOP0(base)) & RBD_SW_EOF)
1638 outw(PIOP0(base), 0);
1639 outw(PIOR0(base), l_rbdp + 2); /* next_rbd_offset */
1640 if((l_rbdp = inw(PIOP0(base))) == I82586NULL)
1643 outw(PIOP0(base), 0);
1644 outw(PIOR0(base), l_rbdp + 2); /* next_rbd_offset */
1645 outw(PIOP0(base), I82586NULL);
1646 outw(PIOR0(base), l_rbdp + 8); /* address of size */
1647 outw(PIOP0(base), inw(PIOP0(base)) | AC_CW_EL);
1648 outw(PIOR0(base), sc->end_rbd + 2);
1649 outw(PIOP0(base), f_rbdp); /* end_rbd->next_rbd_offset */
1650 outw(PIOR0(base), sc->end_rbd + 8); /* size */
1651 outw(PIOP0(base), inw(PIOP0(base)) & ~AC_CW_EL);
1652 sc->end_rbd = l_rbdp;
1656 fd.command = AC_CW_EL;
1657 fd.link_offset = I82586NULL;
1658 fd.rbd_offset = I82586NULL;
1659 outw(PIOR1(base), fd_p);
1660 outsw(PIOP1(base), &fd, 8/2);
1662 outw(PIOR1(base), sc->end_fd + 2); /* addr of command */
1663 outw(PIOP1(base), 0); /* command = 0 */
1664 outw(PIOP1(base), fd_p); /* end_fd->link_offset = fd_p */
1671 static int xmt_debug = 0;
1672 #endif /* WLDEBUG */
1677 * This routine fills in the appropriate registers and memory
1678 * locations on the WaveLAN board and starts the board off on
1681 * input : board number of interest, and a pointer to the mbuf
1682 * output : board memory and registers are set for xfer and attention
1686 wlxmt(int unit, struct mbuf *m)
1688 struct wl_softc *sc = WLSOFTC(unit);
1689 u_short xmtdata_p = OFFSET_TBUF;
1691 struct mbuf *tm_p = m;
1692 struct ether_header *eh_p = mtod(m, struct ether_header *);
1693 u_char *mb_p = mtod(m, u_char *) + sizeof(struct ether_header);
1694 u_short count = m->m_len - sizeof(struct ether_header);
1696 u_short tbd_p = OFFSET_TBD;
1697 u_short len, clen = 0;
1698 short base = sc->base;
1702 if (sc->wl_if.if_flags & IFF_DEBUG)
1703 printf("wl%d: entered wlxmt()\n",unit);
1707 cb.ac_command = (AC_CW_EL|AC_TRANSMIT|AC_CW_I);
1708 cb.ac_link_offset = I82586NULL;
1709 outw(PIOR1(base), OFFSET_CU);
1710 outsw(PIOP1(base), &cb, 6/2);
1711 outw(PIOP1(base), OFFSET_TBD); /* cb.cmd.transmit.tbd_offset */
1712 outsw(PIOP1(base), eh_p->ether_dhost, WAVELAN_ADDR_SIZE/2);
1713 outw(PIOP1(base), eh_p->ether_type);
1716 if (sc->wl_if.if_flags & IFF_DEBUG) {
1718 printf("XMT mbuf: L%d @%p ", count, (void *)mb_p);
1719 printf("ether type %x\n", eh_p->ether_type);
1722 #endif /* WLDEBUG */
1723 outw(PIOR0(base), OFFSET_TBD);
1724 outw(PIOP0(base), 0); /* act_count */
1725 outw(PIOR1(base), OFFSET_TBD + 4);
1726 outw(PIOP1(base), xmtdata_p); /* buffer_addr */
1727 outw(PIOP1(base), 0); /* buffer_base */
1730 if (clen + count > WAVELAN_MTU)
1736 outw(PIOR1(base), xmtdata_p);
1737 outsw(PIOP1(base), mb_p, len/2);
1739 outw(PIOR0(base), tbd_p); /* address of act_count */
1740 outw(PIOP0(base), inw(PIOP0(base)) + count);
1742 if ((tm_p = tm_p->m_next) == (struct mbuf *)0)
1745 /* go to the next descriptor */
1746 outw(PIOR0(base), tbd_p + 2);
1747 tbd_p += sizeof (tbd_t);
1748 outw(PIOP0(base), tbd_p); /* next_tbd_offset */
1749 outw(PIOR0(base), tbd_p);
1750 outw(PIOP0(base), 0); /* act_count */
1751 outw(PIOR1(base), tbd_p + 4);
1752 outw(PIOP1(base), xmtdata_p); /* buffer_addr */
1753 outw(PIOP1(base), 0); /* buffer_base */
1754 /* at the end -> coallesce remaining mbufs */
1755 if (tbd_p == OFFSET_TBD + (N_TBD-1) * sizeof (tbd_t)) {
1756 wlsftwsleaze(&count, &mb_p, &tm_p, unit);
1759 /* next mbuf short -> coallesce as needed */
1760 if ( (tm_p->m_next == (struct mbuf *) 0) ||
1761 #define HDW_THRESHOLD 55
1762 tm_p->m_len > HDW_THRESHOLD)
1765 wlhdwsleaze(&count, &mb_p, &tm_p, unit);
1769 } else if ((tm_p = tm_p->m_next) == (struct mbuf *)0)
1771 count = tm_p->m_len;
1772 mb_p = mtod(tm_p, u_char *);
1774 if (sc->wl_if.if_flags & IFF_DEBUG)
1776 printf("mbuf+ L%d @%p ", count, (void *)mb_p);
1777 #endif /* WLDEBUG */
1780 if (sc->wl_if.if_flags & IFF_DEBUG)
1782 printf("CLEN = %d\n", clen);
1783 #endif /* WLDEBUG */
1784 outw(PIOR0(base), tbd_p);
1785 if (clen < ETHERMIN) {
1786 outw(PIOP0(base), inw(PIOP0(base)) + ETHERMIN - clen);
1787 outw(PIOR1(base), xmtdata_p);
1788 for (xmtshort_p = xmtdata_p; clen < ETHERMIN; clen += 2)
1789 outw(PIOP1(base), 0);
1791 outw(PIOP0(base), inw(PIOP0(base)) | TBD_SW_EOF);
1792 outw(PIOR0(base), tbd_p + 2);
1793 outw(PIOP0(base), I82586NULL);
1795 if (sc->wl_if.if_flags & IFF_DEBUG) {
1801 #endif /* WLDEBUG */
1803 outw(PIOR0(base), OFFSET_SCB + 2); /* address of scb_command */
1805 * wait for 586 to clear previous command, complain if it takes
1808 for (spin = 1;;spin = (spin + 1) % 10000) {
1809 if (inw(PIOP0(base)) == 0) { /* it's done, we can go */
1812 if ((spin == 0) && xmt_watch) { /* not waking up, and we care */
1813 printf("wl%d: slow accepting xmit\n",unit);
1816 outw(PIOP0(base), SCB_CU_STRT); /* new command */
1817 SET_CHAN_ATTN(unit);
1822 * Pause to avoid transmit overrun problems.
1823 * The required delay tends to vary with platform type, and may be
1824 * related to interrupt loss.
1826 if (wl_xmit_delay) {
1827 DELAY(wl_xmit_delay);
1835 * This function builds the linear linked lists of fd's and
1836 * rbd's. Based on page 4-32 of 1986 Intel microcom handbook.
1842 struct wl_softc *sc = WLSOFTC(unit);
1843 short base = sc->base;
1846 u_short fd_p = OFFSET_RU;
1847 u_short rbd_p = OFFSET_RBD;
1850 sc->begin_fd = fd_p;
1851 for(i = 0; i < N_FD; i++) {
1854 fd.link_offset = fd_p + sizeof(fd_t);
1855 fd.rbd_offset = I82586NULL;
1856 outw(PIOR1(base), fd_p);
1857 outsw(PIOP1(base), &fd, 8/2);
1858 fd_p = fd.link_offset;
1860 fd_p -= sizeof(fd_t);
1862 outw(PIOR1(base), fd_p + 2);
1863 outw(PIOP1(base), AC_CW_EL); /* command */
1864 outw(PIOP1(base), I82586NULL); /* link_offset */
1867 outw(PIOR0(base), fd_p + 6); /* address of rbd_offset */
1868 outw(PIOP0(base), rbd_p);
1869 outw(PIOR1(base), rbd_p);
1870 for(i = 0; i < N_RBD; i++) {
1872 rbd.buffer_addr = rbd_p + sizeof(rbd_t) + 2;
1873 rbd.buffer_base = 0;
1874 rbd.size = RCVBUFSIZE;
1876 rbd_p += sizeof(ru_t);
1877 rbd.next_rbd_offset = rbd_p;
1879 rbd.next_rbd_offset = I82586NULL;
1880 rbd.size |= AC_CW_EL;
1881 sc->end_rbd = rbd_p;
1883 outsw(PIOP1(base), &rbd, sizeof(rbd_t)/2);
1884 outw(PIOR1(base), rbd_p);
1886 return sc->begin_fd;
1892 * This routine starts the receive unit running. First checks if the
1893 * board is actually ready, then the board is instructed to receive
1900 struct wl_softc *sc = WLSOFTC(unit);
1901 short base = sc->base;
1905 if (sc->wl_if.if_flags & IFF_DEBUG)
1906 printf("wl%d: entered wlrustrt()\n",unit);
1908 outw(PIOR0(base), OFFSET_SCB);
1909 if (inw(PIOP0(base)) & SCB_RUS_READY){
1910 printf("wlrustrt: RUS_READY\n");
1914 outw(PIOR0(base), OFFSET_SCB + 2);
1915 outw(PIOP0(base), SCB_RU_STRT); /* command */
1916 rfa = wlbldru(unit);
1917 outw(PIOR0(base), OFFSET_SCB + 6); /* address of scb_rfa_offset */
1918 outw(PIOP0(base), rfa);
1920 SET_CHAN_ATTN(unit);
1927 * This routine does a 586 op-code number 7, and obtains the
1928 * diagnose status for the WaveLAN.
1934 struct wl_softc *sc = WLSOFTC(unit);
1935 short base = sc->base;
1939 if (sc->wl_if.if_flags & IFF_DEBUG)
1940 printf("wl%d: entered wldiag()\n",unit);
1942 outw(PIOR0(base), OFFSET_SCB);
1943 status = inw(PIOP0(base));
1944 if (status & SCB_SW_INT) {
1945 /* state is 2000 which seems ok
1946 printf("wl%d diag(): unexpected initial state %\n",
1947 unit, inw(PIOP0(base)));
1951 outw(PIOR1(base), OFFSET_CU);
1952 outw(PIOP1(base), 0); /* ac_status */
1953 outw(PIOP1(base), AC_DIAGNOSE|AC_CW_EL);/* ac_command */
1954 if(wlcmd(unit, "diag()") == 0)
1956 outw(PIOR0(base), OFFSET_CU);
1957 if (inw(PIOP0(base)) & 0x0800) {
1958 printf("wl%d: i82586 Self Test failed!\n", unit);
1967 * This routine does a standard config of the WaveLAN board.
1973 configure_t configure;
1974 struct wl_softc *sc = WLSOFTC(unit);
1975 short base = sc->base;
1978 #if defined(__DragonFly__) || (defined(__FreeBSD__) && __FreeBSD_version >= 300000)
1979 struct ifmultiaddr *ifma;
1982 struct ether_multi *enm;
1983 struct ether_multistep step;
1986 #endif /* MULTICAST */
1989 if (sc->wl_if.if_flags & IFF_DEBUG)
1990 printf("wl%d: entered wlconfig()\n",unit);
1992 outw(PIOR0(base), OFFSET_SCB);
1993 if (inw(PIOP0(base)) & SCB_SW_INT) {
1995 printf("wl%d config(): unexpected initial state %x\n",
1996 unit, inw(PIOP0(base)));
2001 outw(PIOR1(base), OFFSET_CU);
2002 outw(PIOP1(base), 0); /* ac_status */
2003 outw(PIOP1(base), AC_CONFIGURE|AC_CW_EL); /* ac_command */
2006 configure.fifolim_bytecnt = 0x080c;
2007 configure.addrlen_mode = 0x0600;
2008 configure.linprio_interframe = 0x2060;
2009 configure.slot_time = 0xf200;
2010 configure.hardware = 0x0008; /* tx even w/o CD */
2011 configure.min_frame_len = 0x0040;
2013 /* This is the configuration block suggested by Marc Meertens
2014 * <mmeerten@obelix.utrecht.NCR.COM> in an e-mail message to John
2015 * Ioannidis on 10 Nov 92.
2017 configure.fifolim_bytecnt = 0x040c;
2018 configure.addrlen_mode = 0x0600;
2019 configure.linprio_interframe = 0x2060;
2020 configure.slot_time = 0xf000;
2021 configure.hardware = 0x0008; /* tx even w/o CD */
2022 configure.min_frame_len = 0x0040;
2025 * below is the default board configuration from p2-28 from 586 book
2027 configure.fifolim_bytecnt = 0x080c;
2028 configure.addrlen_mode = 0x2600;
2029 configure.linprio_interframe = 0x7820; /* IFS=120, ACS=2 */
2030 configure.slot_time = 0xf00c; /* slottime=12 */
2031 configure.hardware = 0x0008; /* tx even w/o CD */
2032 configure.min_frame_len = 0x0040;
2034 if(sc->mode & (MOD_PROM | MOD_ENAL)) {
2035 configure.hardware |= 1;
2037 outw(PIOR1(base), OFFSET_CU + 6);
2038 outsw(PIOP1(base), &configure, sizeof(configure_t)/2);
2040 if(wlcmd(unit, "config()-configure") == 0)
2043 outw(PIOR1(base), OFFSET_CU);
2044 outw(PIOP1(base), 0); /* ac_status */
2045 outw(PIOP1(base), AC_MCSETUP|AC_CW_EL); /* ac_command */
2046 outw(PIOR1(base), OFFSET_CU + 8);
2047 #if defined(__DragonFly__) || (defined(__FreeBSD__) && __FreeBSD_version >= 300000)
2048 for (ifma = sc->wl_if.if_multiaddrs.lh_first; ifma;
2049 ifma = ifma->ifma_link.le_next) {
2050 if (ifma->ifma_addr->sa_family != AF_LINK)
2053 addrp = LLADDR((struct sockaddr_dl *)ifma->ifma_addr);
2054 outw(PIOP1(base), addrp[0] + (addrp[1] << 8));
2055 outw(PIOP1(base), addrp[2] + (addrp[3] << 8));
2056 outw(PIOP1(base), addrp[4] + (addrp[5] << 8));
2060 ETHER_FIRST_MULTI(step, &sc->wl_ac, enm);
2061 while (enm != NULL) {
2062 unsigned int lo, hi;
2063 /* break if setting a multicast range, else we would crash */
2064 if (bcmp(enm->enm_addrlo, enm->enm_addrhi, 6) != 0) {
2067 lo = (enm->enm_addrlo[3] << 16) + (enm->enm_addrlo[4] << 8)
2068 + enm->enm_addrlo[5];
2069 hi = (enm->enm_addrhi[3] << 16) + (enm->enm_addrhi[4] << 8)
2070 + enm->enm_addrhi[5];
2072 outw(PIOP1(base),enm->enm_addrlo[0] +
2073 (enm->enm_addrlo[1] << 8));
2074 outw(PIOP1(base),enm->enm_addrlo[2] +
2075 ((lo >> 8) & 0xff00));
2076 outw(PIOP1(base), ((lo >> 8) & 0xff) +
2077 ((lo << 8) & 0xff00));
2078 /* #define MCASTDEBUG */
2080 printf("mcast_addr[%d,%d,%d] %x %x %x %x %x %x\n", lo, hi, cnt,
2086 enm->enm_addrlo[5]);
2091 ETHER_NEXT_MULTI(step, enm);
2094 outw(PIOR1(base), OFFSET_CU + 6); /* mc-cnt */
2095 outw(PIOP1(base), cnt * WAVELAN_ADDR_SIZE);
2096 if(wlcmd(unit, "config()-mcaddress") == 0)
2098 #endif /* MULTICAST */
2100 outw(PIOR1(base), OFFSET_CU);
2101 outw(PIOP1(base), 0); /* ac_status */
2102 outw(PIOP1(base), AC_IASETUP|AC_CW_EL); /* ac_command */
2103 outw(PIOR1(base), OFFSET_CU + 6);
2104 outsw(PIOP1(base), sc->wl_addr, WAVELAN_ADDR_SIZE/2);
2106 if(wlcmd(unit, "config()-address") == 0)
2117 * Set channel attention bit and busy wait until command has
2118 * completed. Then acknowledge the command completion.
2121 wlcmd(int unit, char *str)
2123 struct wl_softc *sc = WLSOFTC(unit);
2124 short base = sc->base;
2127 outw(PIOR0(base), OFFSET_SCB + 2); /* address of scb_command */
2128 outw(PIOP0(base), SCB_CU_STRT);
2130 SET_CHAN_ATTN(unit);
2132 outw(PIOR0(base), OFFSET_CU);
2133 for(i = 0; i < 0xffff; i++)
2134 if (inw(PIOP0(base)) & AC_SW_C)
2136 if (i == 0xffff || !(inw(PIOP0(base)) & AC_SW_OK)) {
2137 printf("wl%d: %s failed; status = %d, inw = %x, outw = %x\n",
2138 unit, str, inw(PIOP0(base)) & AC_SW_OK, inw(PIOP0(base)), inw(PIOR0(base)));
2139 outw(PIOR0(base), OFFSET_SCB);
2140 printf("scb_status %x\n", inw(PIOP0(base)));
2141 outw(PIOR0(base), OFFSET_SCB+2);
2142 printf("scb_command %x\n", inw(PIOP0(base)));
2143 outw(PIOR0(base), OFFSET_SCB+4);
2144 printf("scb_cbl %x\n", inw(PIOP0(base)));
2145 outw(PIOR0(base), OFFSET_CU+2);
2146 printf("cu_cmd %x\n", inw(PIOP0(base)));
2150 outw(PIOR0(base), OFFSET_SCB);
2151 if ((inw(PIOP0(base)) & SCB_SW_INT) && (inw(PIOP0(base)) != SCB_SW_CNA)) {
2153 printf("wl%d %s: unexpected final state %x\n",
2154 unit, str, inw(PIOP0(base)));
2162 * wlack: if the 82596 wants attention because it has finished
2163 * sending or receiving a packet, acknowledge its desire and
2164 * return bits indicating the kind of attention. wlack() returns
2165 * these bits so that the caller can service exactly the
2166 * conditions that wlack() acknowledged.
2173 struct wl_softc *sc = WLSOFTC(unit);
2174 short base = sc->base;
2176 outw(PIOR1(base), OFFSET_SCB);
2177 if(!(cmd = (inw(PIOP1(base)) & SCB_SW_INT)))
2180 if (sc->wl_if.if_flags & IFF_DEBUG)
2181 printf("wl%d: doing a wlack()\n",unit);
2183 outw(PIOP1(base), cmd);
2184 SET_CHAN_ATTN(unit);
2185 outw(PIOR0(base), OFFSET_SCB + 2); /* address of scb_command */
2186 for (i = 1000000; inw(PIOP0(base)) && (i-- > 0); );
2188 printf("wl%d wlack(): board not accepting command.\n", unit);
2195 struct wl_softc *sc = WLSOFTC(unit);
2196 short base = sc->base;
2197 u_short tbd_p = OFFSET_TBD;
2203 outw(PIOR1(base), tbd_p);
2204 insw(PIOP1(base), &tbd, sizeof(tbd_t)/2);
2205 sum += (tbd.act_count & ~TBD_SW_EOF);
2206 printf("%d: addr %x, count %d (%d), next %x, base %x\n",
2207 i++, tbd.buffer_addr,
2208 (tbd.act_count & ~TBD_SW_EOF), sum,
2209 tbd.next_tbd_offset, tbd.buffer_base);
2210 if (tbd.act_count & TBD_SW_EOF)
2212 tbd_p = tbd.next_tbd_offset;
2217 wlhdwsleaze(u_short *countp, u_char **mb_pp, struct mbuf **tm_pp, int unit)
2219 struct mbuf *tm_p = *tm_pp;
2220 u_char *mb_p = *mb_pp;
2226 * can we get a run that will be coallesced or
2227 * that terminates before breaking
2230 count += tm_p->m_len;
2231 if (tm_p->m_len & 1)
2233 } while ((tm_p = tm_p->m_next) != (struct mbuf *)0);
2234 if ( (tm_p == (struct mbuf *)0) ||
2235 count > HDW_THRESHOLD) {
2236 *countp = (*tm_pp)->m_len;
2237 *mb_pp = mtod((*tm_pp), u_char *);
2241 /* we need to copy */
2245 cp = (u_char *) t_packet;
2247 bcopy(mtod(tm_p, u_char *), cp, len = tm_p->m_len);
2249 if (count > HDW_THRESHOLD)
2252 if (tm_p->m_next == (struct mbuf *)0)
2254 tm_p = tm_p->m_next;
2257 *mb_pp = (u_char *) t_packet;
2264 wlsftwsleaze(u_short *countp, u_char **mb_pp, struct mbuf **tm_pp, int unit)
2266 struct mbuf *tm_p = *tm_pp;
2268 u_char *cp = (u_char *) t_packet;
2271 /* we need to copy */
2273 bcopy(mtod(tm_p, u_char *), cp, len = tm_p->m_len);
2276 if (tm_p->m_next == (struct mbuf *)0)
2278 tm_p = tm_p->m_next;
2282 *mb_pp = (u_char *) t_packet;
2290 struct wl_softc *sc = WLSOFTC(unit);
2291 short base = sc->base;
2294 printf("wl%d: DCE_STATUS: 0x%x, ", unit,
2295 wlmmcread(base,MMC_DCE_STATUS) & 0x0f);
2296 tmp = wlmmcread(base,MMC_CORRECT_NWID_H) << 8;
2297 tmp |= wlmmcread(base,MMC_CORRECT_NWID_L);
2298 printf("Correct NWID's: %d, ", tmp);
2299 tmp = wlmmcread(base,MMC_WRONG_NWID_H) << 8;
2300 tmp |= wlmmcread(base,MMC_WRONG_NWID_L);
2301 printf("Wrong NWID's: %d\n", tmp);
2302 printf("THR_PRE_SET: 0x%x, ", wlmmcread(base,MMC_THR_PRE_SET));
2303 printf("SIGNAL_LVL: %d, SILENCE_LVL: %d\n",
2304 wlmmcread(base,MMC_SIGNAL_LVL),
2305 wlmmcread(base,MMC_SILENCE_LVL));
2306 printf("SIGN_QUAL: 0x%x, NETW_ID: %x:%x, DES: %d\n",
2307 wlmmcread(base,MMC_SIGN_QUAL),
2308 wlmmcread(base,MMC_NETW_ID_H),
2309 wlmmcread(base,MMC_NETW_ID_L),
2310 wlmmcread(base,MMC_DES_AVAIL));
2314 wlmmcread(u_int base, u_short reg)
2316 while(inw(HASR(base)) & HASR_MMC_BUSY) ;
2317 outw(MMCR(base),reg << 1);
2318 while(inw(HASR(base)) & HASR_MMC_BUSY) ;
2319 return (u_short)inw(MMCR(base)) >> 8;
2325 MMC_WRITE(MMC_FREEZE,1);
2327 * SNR retrieval procedure :
2329 * read signal level : wlmmcread(base, MMC_SIGNAL_LVL);
2330 * read silence level : wlmmcread(base, MMC_SILENCE_LVL);
2332 MMC_WRITE(MMC_FREEZE,0);
2334 * SNR is signal:silence ratio.
2341 ** Reads the psa for the wavelan at (base) into (buf)
2344 wlgetpsa(int base, u_char *buf)
2348 PCMD(base, HACR_DEFAULT & ~HACR_16BITS);
2349 PCMD(base, HACR_DEFAULT & ~HACR_16BITS);
2351 for (i = 0; i < 0x40; i++) {
2352 outw(PIOR2(base), i);
2353 buf[i] = inb(PIOP2(base));
2355 PCMD(base, HACR_DEFAULT);
2356 PCMD(base, HACR_DEFAULT);
2362 ** Writes the psa for wavelan (unit) from the softc back to the
2363 ** board. Updates the CRC and sets the CRC OK flag.
2365 ** Do not call this when the board is operating, as it doesn't
2366 ** preserve the hacr.
2371 struct wl_softc *sc = WLSOFTC(unit);
2372 short base = sc->base;
2376 crc = wlpsacrc(sc->psa); /* calculate CRC of PSA */
2377 sc->psa[WLPSA_CRCLOW] = crc & 0xff;
2378 sc->psa[WLPSA_CRCHIGH] = (crc >> 8) & 0xff;
2379 sc->psa[WLPSA_CRCOK] = 0x55; /* default to 'bad' until programming complete */
2381 oldpri = splimp(); /* ick, long pause */
2383 PCMD(base, HACR_DEFAULT & ~HACR_16BITS);
2384 PCMD(base, HACR_DEFAULT & ~HACR_16BITS);
2386 for (i = 0; i < 0x40; i++) {
2388 outw(PIOR2(base),i); /* write param memory */
2390 outb(PIOP2(base), sc->psa[i]);
2393 outw(PIOR2(base),WLPSA_CRCOK); /* update CRC flag*/
2395 sc->psa[WLPSA_CRCOK] = 0xaa; /* OK now */
2396 outb(PIOP2(base), 0xaa); /* all OK */
2399 PCMD(base, HACR_DEFAULT);
2400 PCMD(base, HACR_DEFAULT);
2406 ** CRC routine provided by Christopher Giordano <cgiordan@gdeb.com>,
2407 ** from original code by Tomi Mikkonen (tomitm@remedy.fi)
2410 static u_int crc16_table[16] = {
2411 0x0000, 0xCC01, 0xD801, 0x1400,
2412 0xF001, 0x3C00, 0x2800, 0xE401,
2413 0xA001, 0x6C00, 0x7800, 0xB401,
2414 0x5000, 0x9C01, 0x8801, 0x4400
2418 wlpsacrc(u_char *buf)
2423 for (i = 0; i < 0x3d; i++, buf++) {
2425 r1 = crc16_table[crc & 0xF];
2426 crc = (crc >> 4) & 0x0FFF;
2427 crc = crc ^ r1 ^ crc16_table[*buf & 0xF];
2430 r1 = crc16_table[crc & 0xF];
2431 crc = (crc >> 4) & 0x0FFF;
2432 crc = crc ^ r1 ^ crc16_table[(*buf >> 4) & 0xF];
2441 * take input packet and cache various radio hw characteristics
2442 * indexed by MAC address.
2444 * Some things to think about:
2445 * note that no space is malloced.
2446 * We might hash the mac address if the cache were bigger.
2447 * It is not clear that the cache is big enough.
2448 * It is also not clear how big it should be.
2449 * The cache is IP-specific. We don't care about that as
2450 * we want it to be IP-specific.
2451 * The last N recv. packets are saved. This will tend
2452 * to reward agents and mobile hosts that beacon.
2453 * That is probably fine for mobile ip.
2456 /* globals for wavelan signal strength cache */
2457 /* this should go into softc structure above.
2460 /* set true if you want to limit cache items to broadcast/mcast
2461 * only packets (not unicast)
2463 static int wl_cache_mcastonly = 1;
2464 SYSCTL_INT(_machdep, OID_AUTO, wl_cache_mcastonly, CTLFLAG_RW,
2465 &wl_cache_mcastonly, 0, "");
2467 /* set true if you want to limit cache items to IP packets only
2469 static int wl_cache_iponly = 1;
2470 SYSCTL_INT(_machdep, OID_AUTO, wl_cache_iponly, CTLFLAG_RW,
2471 &wl_cache_iponly, 0, "");
2473 /* zero out the cache
2476 wl_cache_zero(int unit)
2478 struct wl_softc *sc = WLSOFTC(unit);
2480 bzero(&sc->w_sigcache[0], sizeof(struct w_sigcache) * MAXCACHEITEMS);
2482 sc->w_nextcache = 0;
2483 sc->w_wrapindex = 0;
2486 /* store hw signal info in cache.
2487 * index is MAC address, but an ip src gets stored too
2488 * There are two filters here controllable via sysctl:
2489 * throw out unicast (on by default, but can be turned off)
2490 * throw out non-ip (on by default, but can be turned off)
2493 void wl_cache_store (int unit, int base, struct ether_header *eh,
2496 struct ip *ip = NULL; /* Avoid GCC warning */
2498 int signal, silence;
2499 int w_insertcache; /* computed index for cache entry storage */
2500 struct wl_softc *sc = WLSOFTC(unit);
2501 int ipflag = wl_cache_iponly;
2505 * 2. configurable filter to throw out unicast packets,
2506 * keep multicast only.
2510 /* reject if not IP packet
2512 if ( wl_cache_iponly && (ntohs(eh->ether_type) != 0x800)) {
2516 /* check if broadcast or multicast packet. we toss
2519 if (wl_cache_mcastonly && ((eh->ether_dhost[0] & 1) == 0)) {
2523 /* find the ip header. we want to store the ip_src
2524 * address. use the mtod macro(in mbuf.h)
2525 * to typecast m to struct ip *
2528 ip = mtod(m, struct ip *);
2531 /* do a linear search for a matching MAC address
2532 * in the cache table
2533 * . MAC address is 6 bytes,
2534 * . var w_nextcache holds total number of entries already cached
2536 for(i = 0; i < sc->w_nextcache; i++) {
2537 if (! bcmp(eh->ether_shost, sc->w_sigcache[i].macsrc, 6 )) {
2539 * so we already have this entry,
2540 * update the data, and LRU age
2546 /* did we find a matching mac address?
2547 * if yes, then overwrite a previously existing cache entry
2549 if (i < sc->w_nextcache ) {
2552 /* else, have a new address entry,so
2553 * add this new entry,
2554 * if table full, then we need to replace entry
2558 /* check for space in cache table
2559 * note: w_nextcache also holds number of entries
2560 * added in the cache table
2562 if ( sc->w_nextcache < MAXCACHEITEMS ) {
2563 w_insertcache = sc->w_nextcache;
2565 sc->w_sigitems = sc->w_nextcache;
2567 /* no space found, so simply wrap with wrap index
2568 * and "zap" the next entry
2571 if (sc->w_wrapindex == MAXCACHEITEMS) {
2572 sc->w_wrapindex = 0;
2574 w_insertcache = sc->w_wrapindex++;
2578 /* invariant: w_insertcache now points at some slot
2581 if (w_insertcache < 0 || w_insertcache >= MAXCACHEITEMS) {
2583 "wl_cache_store, bad index: %d of [0..%d], gross cache error\n",
2584 w_insertcache, MAXCACHEITEMS);
2588 /* store items in cache
2591 * .signal (0..63) ,silence (0..63) ,quality (0..15)
2594 sc->w_sigcache[w_insertcache].ipsrc = ip->ip_src.s_addr;
2596 bcopy( eh->ether_shost, sc->w_sigcache[w_insertcache].macsrc, 6);
2597 signal = sc->w_sigcache[w_insertcache].signal = wlmmcread(base, MMC_SIGNAL_LVL) & 0x3f;
2598 silence = sc->w_sigcache[w_insertcache].silence = wlmmcread(base, MMC_SILENCE_LVL) & 0x3f;
2599 sc->w_sigcache[w_insertcache].quality = wlmmcread(base, MMC_SIGN_QUAL) & 0x0f;
2601 sc->w_sigcache[w_insertcache].snr =
2604 sc->w_sigcache[w_insertcache].snr = 0;
2608 #endif /* WLCACHE */
2611 * determine if in all multicast mode or not
2613 * returns: 1 if IFF_ALLMULTI should be set
2618 #if defined(__FreeBSD__) && __FreeBSD_version < 300000 /* not required */
2620 check_allmulti(int unit)
2622 struct wl_softc *sc = WLSOFTC(unit);
2623 short base = sc->base;
2624 struct ether_multi *enm;
2625 struct ether_multistep step;
2627 ETHER_FIRST_MULTI(step, &sc->wl_ac, enm);
2628 while (enm != NULL) {
2629 unsigned int lo, hi;
2631 printf("enm_addrlo %x:%x:%x:%x:%x:%x\n", enm->enm_addrlo[0], enm->enm_addrlo[1],
2632 enm->enm_addrlo[2], enm->enm_addrlo[3], enm->enm_addrlo[4],
2633 enm->enm_addrlo[5]);
2634 printf("enm_addrhi %x:%x:%x:%x:%x:%x\n", enm->enm_addrhi[0], enm->enm_addrhi[1],
2635 enm->enm_addrhi[2], enm->enm_addrhi[3], enm->enm_addrhi[4],
2636 enm->enm_addrhi[5]);
2638 if (bcmp(enm->enm_addrlo, enm->enm_addrhi, 6) != 0) {
2641 ETHER_NEXT_MULTI(step, enm);