Make all network interrupt service routines MPSAFE part 1/3.
[dragonfly.git] / sys / dev / netif / wl / if_wl.c
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.26 2005/11/28 17:13:44 dillon Exp $ */
3 /* 
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
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
11  *
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.
22  * 
23  */
24 /*
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
30  *
31  * 2.2 update:
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.
38  * 2.2.1 update:
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
43  *                      7/14/97 jrb
44  *
45  * Work done:
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.
51  *
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).
60  *
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.  
82  *
83  * sample config:
84  *
85  * device wl0 at isa? port 0x300 net irq ?
86  *
87  * Ifdefs:
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
96  *
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...
103  *
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.
122  * --RAB 1997/06/08.
123  */
124
125 #define MULTICAST  1
126
127 /* 
128  *      Olivetti PC586 Mach Ethernet driver v1.0
129  *      Copyright Ing. C. Olivetti & C. S.p.A. 1988, 1989
130  *      All rights reserved.
131  *
132  */ 
133
134 /*
135   Copyright 1988, 1989 by Olivetti Advanced Technology Center, Inc.,
136 Cupertino, California.
137
138                 All Rights Reserved
139
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.
147
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.
155 */
156
157 /*
158   Copyright 1988, 1989 by Intel Corporation, Santa Clara, California.
159
160                 All Rights Reserved
161
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.
169
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.
177 */
178
179 /*
180  * NOTE:
181  *              by rvb:
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.
190  */
191
192 #include "opt_wavelan.h"
193 #include "opt_inet.h"
194
195 #include <sys/param.h>
196 #include <sys/systm.h>
197 #include <sys/sockio.h>
198 #include <sys/mbuf.h>
199 #include <sys/socket.h>
200 #include <sys/syslog.h>
201 #include <sys/proc.h>
202 #include <sys/serialize.h>
203 #include <sys/thread2.h>
204
205 #include <sys/kernel.h>
206 #include <sys/sysctl.h>
207
208 #include <machine/bus.h>
209 #include <machine/resource.h>
210 #include <sys/bus.h>
211 #include <sys/rman.h>
212
213 #include <net/ethernet.h>
214 #include <net/if.h>
215 #include <net/if_arp.h>
216 #include <net/ifq_var.h>
217 #include <net/if_dl.h>
218
219 #ifdef INET
220 #include <netinet/in.h>
221 #include <netinet/in_systm.h>
222 #include <netinet/ip.h>
223 #include <netinet/if_ether.h>
224 #endif
225
226 #include <net/bpf.h>
227
228 #include <bus/isa/isavar.h>
229 #include <bus/isa/i386/isa_device.h>
230 #include "if_wl_i82586.h"       /* Definitions for the Intel chip */
231
232 /* was 1000 in original, fed to DELAY(x) */
233 #define DELAYCONST      1000
234 #include "if_wl.h"
235 #include <machine/if_wl_wavelan.h>
236
237 static char     t_packet[ETHERMTU + sizeof(struct ether_header) + sizeof(long)];
238
239 struct wl_softc{ 
240     struct      arpcom  wl_ac;                  /* Ethernet common part */
241 #define wl_if   wl_ac.ac_if                     /* network visible interface */
242 #define wl_addr wl_ac.ac_enaddr                 /* hardware address */
243     u_char      psa[0x40];
244     u_char      nwid[2];        /* current radio modem nwid */
245     short       base;
246     int         flags;
247     int         tbusy;          /* flag to determine if xmit is busy */
248     u_short     begin_fd;
249     u_short     end_fd;
250     u_short     end_rbd;
251     u_short     hacr;           /* latest host adapter CR command */
252     short       mode;
253     u_char      chan24;         /* 2.4 Gz: channel number/EEPROM Area # */
254     u_short     freq24;         /* 2.4 Gz: resulting frequency  */
255     int         rid_ioport;
256     int         rid_irq;
257     struct      resource *res_ioport;
258     struct      resource *res_irq;
259     void        *intr_handle;
260     struct      callout watchdog_ch;
261 #ifdef WLCACHE
262     int         w_sigitems;     /* number of cached entries */
263     /*  array of cache entries */
264     struct w_sigcache w_sigcache[ MAXCACHEITEMS ];            
265     int w_nextcache;            /* next free cache entry */    
266     int w_wrapindex;            /* next "free" cache entry */
267 #endif
268 };
269
270 /*
271  * XXX  The Wavelan appears to be prone to dropping stuff if you talk to
272  * it too fast.  This disgusting hack inserts a delay after each packet
273  * is queued which helps avoid this behaviour on fast systems.
274  */
275 static int      wl_xmit_delay = 250;
276 SYSCTL_INT(_machdep, OID_AUTO, wl_xmit_delay, CTLFLAG_RW, &wl_xmit_delay, 0, "");
277
278 /* 
279  * not XXX, but ZZZ (bizarre).
280  * promiscuous mode can be toggled to ignore NWIDs.  By default,
281  * it does not.  Caution should be exercised about combining
282  * this mode with IFF_ALLMULTI which puts this driver in
283  * promiscuous mode.
284  */
285 static int      wl_ignore_nwid = 0;
286 SYSCTL_INT(_machdep, OID_AUTO, wl_ignore_nwid, CTLFLAG_RW, &wl_ignore_nwid, 0, "");
287
288 /*
289  * Emit diagnostics about transmission problems
290  */
291 static int      xmt_watch = 0;
292 SYSCTL_INT(_machdep, OID_AUTO, wl_xmit_watch, CTLFLAG_RW, &xmt_watch, 0, "");
293
294 /*
295  * Collect SNR statistics
296  */
297 static int      gathersnr = 0;
298 SYSCTL_INT(_machdep, OID_AUTO, wl_gather_snr, CTLFLAG_RW, &gathersnr, 0, "");
299
300 static int      wlprobe(device_t);
301 static int      wlattach(device_t);
302 static int      wldetach(device_t);
303 static int      wl_alloc_resources(device_t);
304 static void     wl_free_resources(device_t);
305 static void     wlstart(struct ifnet *);
306 static void     wlinit(void *);
307 static int      wlioctl(struct ifnet *, u_long, caddr_t, struct ucred *);
308 static timeout_t wlwatchdog;
309 static void     wlintr(void *);
310 static void     wlxmt(struct wl_softc *, struct mbuf *);
311 static int      wldiag(struct wl_softc *); 
312 static int      wlconfig(struct wl_softc *); 
313 static int      wlcmd(struct wl_softc *, const char *);
314 static void     wlmmcstat(struct wl_softc *);
315 static u_short  wlbldru(struct wl_softc *);
316 static u_short  wlmmcread(u_int, u_short);
317 static void     wlinitmmc(struct wl_softc *);
318 static int      wlhwrst(struct wl_softc *);
319 static void     wlrustrt(struct wl_softc *);
320 static void     wlbldcu(struct wl_softc *);
321 static int      wlack(struct wl_softc *);
322 static int      wlread(struct wl_softc *, u_short);
323 static void     getsnr(struct wl_softc *);
324 static void     wlrcv(struct wl_softc *);
325 static int      wlrequeue(struct wl_softc *, u_short);
326 static void     wlsftwsleaze(u_short *, u_char **, struct mbuf **);
327 static void     wlhdwsleaze(u_short *, u_char **, struct mbuf **);
328 static void     wltbd(struct wl_softc *);
329 static void     wlgetpsa(int, u_char *);
330 static void     wlsetpsa(struct wl_softc *);
331 static u_short  wlpsacrc(u_char *);
332 static void     wldump(struct wl_softc *);
333 #ifdef WLCACHE
334 static void     wl_cache_store(struct wl_softc *, int, struct ether_header *,
335                                struct mbuf *);
336 static void     wl_cache_zero(struct wl_softc *);
337 #endif
338 #ifdef MULTICAST
339 # if defined(__FreeBSD__) && __FreeBSD_version < 300000
340 static int      check_allmulti(struct wl_softc *);
341 # endif
342 #endif
343
344 static device_method_t wl_methods[] = {
345         DEVMETHOD(device_probe,         wlprobe),
346         DEVMETHOD(device_attach,        wlattach),
347         DEVMETHOD(device_detach,        wldetach),
348         { 0, 0 }
349 };
350
351 static driver_t wl_driver = {
352         "wl",
353         wl_methods,
354         sizeof(struct wl_softc)
355 };
356
357 devclass_t wl_devclass;
358 DECLARE_DUMMY_MODULE(if_wl);
359 DRIVER_MODULE(wl, isa, wl_driver, wl_devclass, 0, 0);
360 MODULE_DEPEND(wl, isa, 1, 1, 1);
361
362 static struct isa_pnp_id wl_ids[] = {
363         { 0, NULL }
364 };
365
366 /* array for maping irq numbers to values for the irq parameter register */
367 static int irqvals[16] = { 
368     0, 0, 0, 0x01, 0x02, 0x04, 0, 0x08, 0, 0, 0x10, 0x20, 0x40, 0, 0, 0x80 
369 };
370
371 /*
372  * wlprobe:
373  *
374  *      This function "probes" or checks for the WaveLAN board on the bus to
375  *      see if it is there.  As far as I can tell, the best break between this
376  *      routine and the attach code is to simply determine whether the board
377  *      is configured in properly.  Currently my approach to this is to write
378  *      and read a word from the SRAM on the board being probed.  If the word
379  *      comes back properly then we assume the board is there.  The config
380  *      code expects to see a successful return from the probe routine before
381  *      attach will be called.
382  */
383 static int
384 wlprobe(device_t dev)
385 {
386     struct wl_softc     *sc;
387     short               base;
388     const char          *str = "wl%d: board out of range [0..%d]\n";
389     u_char              inbuf[100];
390     int                 irq, error;
391
392     error = ISA_PNP_PROBE(device_get_parent(dev), dev, wl_ids);
393     if (error == ENXIO || error == 0)
394         return (error);
395
396     sc = device_get_softc(dev);
397     error = wl_alloc_resources(dev);
398     if (error)
399         return error;
400
401     base = rman_get_start(sc->res_ioport);
402
403     /* TBD. not true.
404      * regular CMD() will not work, since no softc yet 
405      */
406 #define PCMD(base, hacr) outw((base), (hacr))
407
408     PCMD(base, HACR_RESET);                     /* reset the board */
409     DELAY(DELAYCONST);                          /* >> 4 clocks at 6MHz */
410     PCMD(base, HACR_RESET);                     /* reset the board */
411     DELAY(DELAYCONST);                          /* >> 4 clocks at 6MHz */
412
413     /* clear reset command and set PIO#1 in autoincrement mode */
414     PCMD(base, HACR_DEFAULT);
415     PCMD(base, HACR_DEFAULT);
416     outw(PIOR1(base), 0);                       /* go to beginning of RAM */
417     outsw(PIOP1(base), str, strlen(str)/2+1);   /* write string */
418     
419     outw(PIOR1(base), 0);                       /* rewind */
420     insw(PIOP1(base), inbuf, strlen(str)/2+1);  /* read result */
421     
422     if (bcmp(str, inbuf, strlen(str))) {
423         error = ENXIO;
424         goto fail;
425     }
426
427     sc->chan24 = 0;                             /* 2.4 Gz: config channel */
428     sc->freq24 = 0;                             /* 2.4 Gz: frequency    */
429
430     /* read the PSA from the board into temporary storage */
431     wlgetpsa(base, inbuf);
432
433     /* We read the IRQ value from the PSA on the board. */
434     for (irq = 15; irq >= 0; irq--)
435         if (irqvals[irq] == inbuf[WLPSA_IRQNO])
436             break;
437     if ((irq == 0) || (irqvals[irq] == 0)){
438         device_printf(dev, "PSA corrupt (invalid IRQ value)\n");
439     } else {
440         u_long sirq, dummy;
441
442         /*
443          * If the IRQ requested by the PSA is already claimed by another
444          * device, the board won't work, but the user can still access the
445          * driver to change the IRQ.
446          */
447         if (bus_get_resource(dev, SYS_RES_IRQ, 0, &sirq, &dummy))
448             goto fail;
449         if (irq != (int)sirq)
450             device_printf(dev, "board is configured for interrupt %d\n", irq);
451     }
452     error = 0;
453
454 fail:
455     wl_free_resources(dev);
456     return (error);
457 }
458
459 /*
460  * wlattach:
461  *
462  *      This function attaches a WaveLAN board to the "system".  The rest of
463  *      runtime structures are initialized here (this routine is called after
464  *      a successful probe of the board).  Once the ethernet address is read
465  *      and stored, the board's ifnet structure is attached and readied.
466  */
467 static int
468 wlattach(device_t dev)
469 {
470     struct wl_softc     *sc;
471     short               base;
472     int                 i, j, error;
473     struct ifnet        *ifp;
474
475     sc = device_get_softc(dev);
476
477     ifp = &sc->wl_if;
478     if_initname(ifp, device_get_name(dev), device_get_unit(dev));
479
480     error = wl_alloc_resources(dev);
481     if (error)
482         return error;
483
484     base = rman_get_start(sc->res_ioport);
485
486 #ifdef WLDEBUG
487     device_printf(dev, "%s: base %x, unit %d\n",
488                   __func__, base, device_get_unit(dev));
489 #endif
490
491     sc->base = base;
492     sc->flags = 0;
493     sc->mode = 0;
494     sc->hacr = HACR_RESET;
495     callout_init(&sc->watchdog_ch);
496     CMD(sc);                            /* reset the board */
497     DELAY(DELAYCONST);                  /* >> 4 clocks at 6MHz */
498         
499     /* clear reset command and set PIO#2 in parameter access mode */
500     sc->hacr = (HACR_DEFAULT & ~HACR_16BITS);
501     CMD(sc);
502
503     /* Read the PSA from the board for our later reference */
504     wlgetpsa(base, sc->psa);
505
506     /* fetch NWID */
507     sc->nwid[0] = sc->psa[WLPSA_NWID];
508     sc->nwid[1] = sc->psa[WLPSA_NWID+1];
509     
510     /* fetch MAC address - decide which one first */
511     if (sc->psa[WLPSA_MACSEL] & 1) {
512         j = WLPSA_LOCALMAC;
513     } else {
514         j = WLPSA_UNIMAC;
515     }
516     for(i=0; i < WAVELAN_ADDR_SIZE; ++i) {
517         sc->wl_addr[i] = sc->psa[j + i];
518     }
519
520     /* enter normal 16 bit mode operation */
521     sc->hacr = HACR_DEFAULT;
522     CMD(sc);
523
524     wlinitmmc(sc);
525     outw(PIOR1(base), OFFSET_SCB + 8);  /* address of scb_crcerrs */
526     outw(PIOP1(base), 0);                       /* clear scb_crcerrs */
527     outw(PIOP1(base), 0);                       /* clear scb_alnerrs */
528     outw(PIOP1(base), 0);                       /* clear scb_rscerrs */
529     outw(PIOP1(base), 0);                       /* clear scb_ovrnerrs */
530
531     ifp->if_softc = sc;
532     ifp->if_mtu = WAVELAN_MTU;
533     ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
534 #ifdef    WLDEBUG
535     ifp->if_flags |= IFF_DEBUG;
536 #endif
537 #if     MULTICAST
538     ifp->if_flags |= IFF_MULTICAST;
539 #endif  /* MULTICAST */
540     ifp->if_init = wlinit;
541     ifp->if_start = wlstart;
542     ifp->if_ioctl = wlioctl;
543     ifp->if_timer = 0;   /* paranoia */
544     /* no entries
545        ifp->if_watchdog
546        ifp->if_done
547        ifp->if_reset
548        */
549     ifq_set_maxlen(&ifp->if_snd, IFQ_MAXLEN);
550     ifq_set_ready(&ifp->if_snd);
551     ether_ifattach(ifp, sc->wl_ac.ac_enaddr, NULL);
552
553     if (sc->freq24) 
554         printf(", Freq %d MHz",sc->freq24);             /* 2.4 Gz       */
555     printf("\n");                                       /* 2.4 Gz       */
556
557     error = bus_setup_intr(dev, sc->res_irq, INTR_NETSAFE,
558                            wlintr, sc, &sc->intr_handle, 
559                            ifp->if_serializer);
560     if (error) {
561         device_printf(dev, "setup irq fail!\n");
562         ether_ifdetach(ifp);
563         wl_free_resources(dev);
564         return error;
565     }
566
567     if (bootverbose)
568         wldump(sc);
569     return 0;
570 }
571
572 static int
573 wldetach(device_t dev)
574 {
575     struct wl_softc *sc = device_get_softc(dev);
576     device_t parent = device_get_parent(dev);
577     struct ifnet *ifp = &sc->wl_if;
578
579     lwkt_serialize_enter(ifp->if_serializer);
580     ether_ifdetach(ifp);
581
582     /* reset the board */
583     sc->hacr = HACR_RESET;
584     CMD(sc);
585     sc->hacr = HACR_DEFAULT;
586     CMD(sc);
587
588     if (sc->intr_handle != NULL) {
589         BUS_TEARDOWN_INTR(parent, dev, sc->res_irq, sc->intr_handle);
590         sc->intr_handle = NULL;
591     }
592
593     bus_generic_detach(dev);
594
595     wl_free_resources(dev);
596     lwkt_serialize_exit(ifp->if_serializer);
597     return (0);
598 }
599
600 static int
601 wl_alloc_resources(device_t dev)
602 {
603     struct wl_softc *sc = device_get_softc(dev);
604     int ports = 16;             /* Number of ports */
605
606     sc->res_ioport = bus_alloc_resource(dev, SYS_RES_IOPORT,
607         &sc->rid_ioport, 0ul, ~0ul, ports, RF_ACTIVE);
608     if (sc->res_ioport == NULL)
609         goto fail;
610
611     sc->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
612         &sc->rid_irq, RF_SHAREABLE | RF_ACTIVE);
613     if (sc->res_irq == NULL)
614         goto fail;
615     return (0);
616
617 fail:
618     wl_free_resources(dev);
619     return (ENXIO);
620 }
621
622 static void
623 wl_free_resources(device_t dev)
624 {
625     struct wl_softc *sc = device_get_softc(dev);
626
627     if (sc->res_irq != 0) {
628         bus_deactivate_resource(dev, SYS_RES_IRQ, sc->rid_irq, sc->res_irq);
629         bus_release_resource(dev, SYS_RES_IRQ, sc->rid_irq, sc->res_irq);
630         sc->res_irq = 0;
631     }
632     if (sc->res_ioport != 0) {
633         bus_deactivate_resource(dev, SYS_RES_IOPORT,
634             sc->rid_ioport, sc->res_ioport);
635         bus_release_resource(dev, SYS_RES_IOPORT,
636             sc->rid_ioport, sc->res_ioport);
637         sc->res_ioport = 0;
638     }
639 }
640
641 /*
642  * Print out interesting information about the 82596.
643  */
644 static void
645 wldump(struct wl_softc *sc)
646 {
647     int         base = sc->base;
648     int         i;
649         
650     if_printf(&sc->wl_if, "hasr %04x\n", inw(HASR(base)));
651         
652     if_printf(&sc->wl_if, "scb at %04x:\n ", OFFSET_SCB);
653     outw(PIOR1(base), OFFSET_SCB);
654     for(i = 0; i < 8; i++)
655         printf("%04x ", inw(PIOP1(base)));
656     printf("\n");
657         
658     if_printf(&sc->wl_if, "cu at %04x:\n ", OFFSET_CU);
659     outw(PIOR1(base), OFFSET_CU);
660     for(i = 0; i < 8; i++)
661         printf("%04x ", inw(PIOP1(base)));
662     printf("\n");
663         
664     if_printf(&sc->wl_if, "tbd at %04x:\n ", OFFSET_TBD);
665     outw(PIOR1(base), OFFSET_TBD);
666     for(i = 0; i < 4; i++)
667         printf("%04x ", inw(PIOP1(base)));
668     printf("\n");
669 }
670
671 /* Initialize the Modem Management Controller */
672 static void
673 wlinitmmc(struct wl_softc *sc)
674 {
675     int         base = sc->base;
676     int         configured;
677     int         mode = sc->mode;
678     int         i;                              /* 2.4 Gz               */
679         
680     /* enter 8 bit operation */
681     sc->hacr = (HACR_DEFAULT & ~HACR_16BITS);
682     CMD(sc);
683
684     configured = sc->psa[WLPSA_CONFIGURED] & 1;
685         
686     /*
687      * Set default modem control parameters.  Taken from NCR document
688      *  407-0024326 Rev. A 
689      */
690     MMC_WRITE(MMC_JABBER_ENABLE, 0x01);
691     MMC_WRITE(MMC_ANTEN_SEL, 0x02);
692     MMC_WRITE(MMC_IFS, 0x20);
693     MMC_WRITE(MMC_MOD_DELAY, 0x04);
694     MMC_WRITE(MMC_JAM_TIME, 0x38);
695     MMC_WRITE(MMC_DECAY_PRM, 0x00);             /* obsolete ? */
696     MMC_WRITE(MMC_DECAY_UPDAT_PRM, 0x00);
697     if (!configured) {
698         MMC_WRITE(MMC_LOOPT_SEL, 0x00);
699         if (sc->psa[WLPSA_COMPATNO] & 1) {
700             MMC_WRITE(MMC_THR_PRE_SET, 0x01);   /* 0x04 for AT and 0x01 for MCA */
701         } else {
702             MMC_WRITE(MMC_THR_PRE_SET, 0x04);   /* 0x04 for AT and 0x01 for MCA */
703         }
704         MMC_WRITE(MMC_QUALITY_THR, 0x03);
705     } else {
706         /* use configuration defaults from parameter storage area */
707         if (sc->psa[WLPSA_NWIDENABLE] & 1) {
708             if ((mode & (MOD_PROM | MOD_ENAL)) && wl_ignore_nwid) {
709                 MMC_WRITE(MMC_LOOPT_SEL, 0x40);
710             } else {
711                 MMC_WRITE(MMC_LOOPT_SEL, 0x00);
712             }
713         } else {
714             MMC_WRITE(MMC_LOOPT_SEL, 0x40);     /* disable network id check */
715         }
716         MMC_WRITE(MMC_THR_PRE_SET, sc->psa[WLPSA_THRESH]);
717         MMC_WRITE(MMC_QUALITY_THR, sc->psa[WLPSA_QUALTHRESH]);
718     }
719     MMC_WRITE(MMC_FREEZE, 0x00);
720     MMC_WRITE(MMC_ENCR_ENABLE, 0x00);
721
722     MMC_WRITE(MMC_NETW_ID_L,sc->nwid[1]);       /* set NWID */
723     MMC_WRITE(MMC_NETW_ID_H,sc->nwid[0]);
724
725     /* enter normal 16 bit mode operation */
726     sc->hacr = HACR_DEFAULT;
727     CMD(sc);
728     CMD(sc);                                    /* virtualpc1 needs this! */
729
730     if (sc->psa[WLPSA_COMPATNO]==               /* 2.4 Gz: half-card ver     */
731                 WLPSA_COMPATNO_WL24B) {         /* 2.4 Gz                    */
732         i=sc->chan24<<4;                        /* 2.4 Gz: position ch #     */
733         MMC_WRITE(MMC_EEADDR,i+0x0f);           /* 2.4 Gz: named ch, wc=16   */
734         MMC_WRITE(MMC_EECTRL,MMC_EECTRL_DWLD+   /* 2.4 Gz: Download Synths   */
735                         MMC_EECTRL_EEOP_READ);  /* 2.4 Gz: Read EEPROM       */
736         for (i=0; i<1000; ++i) {                /* 2.4 Gz: wait for download */
737             DELAY(40);                          /* 2.4 Gz             */
738             if ((wlmmcread(base,MMC_EECTRLstat) /* 2.4 Gz: check DWLD and    */
739                 &(MMC_EECTRLstat_DWLD           /* 2.4 Gz:       EEBUSY      */
740                  +MMC_EECTRLstat_EEBUSY))==0)   /* 2.4 Gz:                   */
741                 break;                          /* 2.4 Gz: download finished */
742         }                                       /* 2.4 Gz                    */
743         if (i==1000) {
744             if_printf(&sc->wl_if,
745                       "synth load failed\n");   /* 2.4 Gz       */
746         }
747         MMC_WRITE(MMC_EEADDR,0x61);             /* 2.4 Gz: default pwr, wc=2 */
748         MMC_WRITE(MMC_EECTRL,MMC_EECTRL_DWLD+   /* 2.4 Gz: Download Xmit Pwr */
749                         MMC_EECTRL_EEOP_READ);  /* 2.4 Gz: Read EEPROM       */
750         for (i=0; i<1000; ++i) {                /* 2.4 Gz: wait for download */
751             DELAY(40);                          /* 2.4 Gz             */
752             if ((wlmmcread(base,MMC_EECTRLstat) /* 2.4 Gz: check DWLD and    */
753                 &(MMC_EECTRLstat_DWLD           /* 2.4 Gz:       EEBUSY      */
754                  +MMC_EECTRLstat_EEBUSY))==0)   /* 2.4 Gz:                   */
755                 break;                          /* 2.4 Gz: download finished */
756         }                                       /* 2.4 Gz                    */
757         if (i==1000) {
758             if_printf(&sc->wl_if,
759                       "xmit pwr load failed\n");/* 2.4 Gz            */
760         }
761         MMC_WRITE(MMC_ANALCTRL,                 /* 2.4 Gz: EXT ant+polarity  */
762                         MMC_ANALCTRL_ANTPOL +   /* 2.4 Gz:                   */
763                         MMC_ANALCTRL_EXTANT);   /* 2.4 Gz:                   */
764         i=sc->chan24<<4;                        /* 2.4 Gz: position ch #     */
765         MMC_WRITE(MMC_EEADDR,i);                /* 2.4 Gz: get frequency     */
766         MMC_WRITE(MMC_EECTRL,                   /* 2.4 Gz: EEPROM read      */
767                         MMC_EECTRL_EEOP_READ);  /* 2.4 Gz:                  */
768         DELAY(40);                              /* 2.4 Gz                    */
769         i = wlmmcread(base,MMC_EEDATALrv)       /* 2.4 Gz: freq val          */
770           + (wlmmcread(base,MMC_EEDATAHrv)<<8); /* 2.4 Gz                    */
771         sc->freq24 = (i>>6)+2400;               /* 2.4 Gz: save real freq    */
772     }
773 }
774
775 /*
776  * wlinit:
777  *
778  *      Another routine that interfaces the "if" layer to this driver.  
779  *      Simply resets the structures that are used by "upper layers".  
780  *      As well as calling wlhwrst that does reset the WaveLAN board.
781  *
782  * input        : softc pointer for this interface
783  * output       : structures (if structs) and board are reset
784  *
785  */     
786 static void
787 wlinit(void *xsc)
788 {
789     struct wl_softc *sc = xsc;
790     struct ifnet        *ifp = &sc->wl_if;
791     int                 stat;
792
793 #ifdef WLDEBUG
794     if (ifp->if_flags & IFF_DEBUG)
795         if_printf(ifp, "entered wlinit()\n");
796 #endif
797     if ((stat = wlhwrst(sc)) == TRUE) {
798         ifp->if_flags |= IFF_RUNNING;   /* same as DSF_RUNNING */
799         /* 
800          * OACTIVE is used by upper-level routines
801          * and must be set
802          */
803         ifp->if_flags &= ~IFF_OACTIVE;  /* same as tbusy below */
804                 
805         sc->flags |= DSF_RUNNING;
806         sc->tbusy = 0;
807         callout_stop(&sc->watchdog_ch);
808                 
809         wlstart(ifp);
810     } else {
811         if_printf(ifp, "init(): trouble resetting board.\n");
812     }
813 }
814
815 /*
816  * wlhwrst:
817  *
818  *      This routine resets the WaveLAN board that corresponds to the 
819  *      board number passed in.
820  *
821  * input        : softc pointer for this interface
822  * output       : board is reset
823  *
824  */
825 static int
826 wlhwrst(struct wl_softc *sc)
827 {
828 #ifdef WLDEBUG
829     if (sc->wl_if.if_flags & IFF_DEBUG)
830         if_printf(&sc->wl_if, "entered wlhwrst()\n");
831 #endif
832     sc->hacr = HACR_RESET;
833     CMD(sc);                    /* reset the board */
834         
835     /* clear reset command and set PIO#1 in autoincrement mode */
836     sc->hacr = HACR_DEFAULT;
837     CMD(sc);
838
839 #ifdef  WLDEBUG
840     if (sc->wl_if.if_flags & IFF_DEBUG)
841         wlmmcstat(sc);          /* Display MMC registers */
842 #endif  /* WLDEBUG */
843     wlbldcu(sc);                /* set up command unit structures */
844     
845     if (wldiag(sc) == 0)
846         return(0);
847     
848     if (wlconfig(sc) == 0)
849             return(0);
850     /* 
851      * insert code for loopback test here
852      */
853     wlrustrt(sc);               /* start receive unit */
854
855     /* enable interrupts */
856     sc->hacr = (HACR_DEFAULT | HACR_INTRON);
857     CMD(sc);
858     
859     return(1);
860 }
861
862 /*
863  * wlbldcu:
864  *
865  *      This function builds up the command unit structures.  It inits
866  *      the scp, iscp, scb, cb, tbd, and tbuf.
867  *
868  */
869 static void
870 wlbldcu(struct wl_softc *sc)
871 {
872     short               base = sc->base;
873     scp_t               scp;
874     iscp_t              iscp;
875     scb_t               scb;
876     ac_t                cb;
877     tbd_t               tbd;
878     int         i;
879
880     bzero(&scp, sizeof(scp));
881     scp.scp_sysbus = 0;
882     scp.scp_iscp = OFFSET_ISCP;
883     scp.scp_iscp_base = 0;
884     outw(PIOR1(base), OFFSET_SCP);
885     outsw(PIOP1(base), &scp, sizeof(scp_t)/2);
886
887     bzero(&iscp, sizeof(iscp));
888     iscp.iscp_busy = 1;
889     iscp.iscp_scb_offset = OFFSET_SCB;
890     iscp.iscp_scb = 0;
891     iscp.iscp_scb_base = 0;
892     outw(PIOR1(base), OFFSET_ISCP);
893     outsw(PIOP1(base), &iscp, sizeof(iscp_t)/2);
894
895     scb.scb_status = 0;
896     scb.scb_command = SCB_RESET;
897     scb.scb_cbl_offset = OFFSET_CU;
898     scb.scb_rfa_offset = OFFSET_RU;
899     scb.scb_crcerrs = 0;
900     scb.scb_alnerrs = 0;
901     scb.scb_rscerrs = 0;
902     scb.scb_ovrnerrs = 0;
903     outw(PIOR1(base), OFFSET_SCB);
904     outsw(PIOP1(base), &scb, sizeof(scb_t)/2);
905
906     SET_CHAN_ATTN(sc);
907
908     outw(PIOR0(base), OFFSET_ISCP + 0); /* address of iscp_busy */
909     for (i = 1000000; inw(PIOP0(base)) && (i-- > 0); );
910     if (i <= 0) if_printf(&sc->wl_if, "bldcu(): iscp_busy timeout.\n");
911     outw(PIOR0(base), OFFSET_SCB + 0);  /* address of scb_status */
912     for (i = STATUS_TRIES; i-- > 0; ) {
913         if (inw(PIOP0(base)) == (SCB_SW_CX|SCB_SW_CNA)) 
914             break;
915     }
916     if (i <= 0)
917         if_printf(&sc->wl_if, "bldcu(): not ready after reset.\n");
918     wlack(sc);
919
920     cb.ac_status = 0;
921     cb.ac_command = AC_CW_EL;           /* NOP */
922     cb.ac_link_offset = OFFSET_CU;
923     outw(PIOR1(base), OFFSET_CU);
924     outsw(PIOP1(base), &cb, 6/2);
925
926     tbd.act_count = 0;
927     tbd.next_tbd_offset = I82586NULL;
928     tbd.buffer_addr = 0;
929     tbd.buffer_base = 0;
930     outw(PIOR1(base), OFFSET_TBD);
931     outsw(PIOP1(base), &tbd, sizeof(tbd_t)/2);
932 }
933
934 /*
935  * wlstart:
936  *
937  *      send a packet
938  *
939  * input        : pointer the appropriate "if" struct
940  * output       : stuff sent to board if any there
941  *
942  */
943 static void
944 wlstart(struct ifnet *ifp)
945 {
946     struct mbuf                 *m;
947     struct wl_softc     *sc = ifp->if_softc;
948     short                       base = sc->base;
949     int                         scb_status, cu_status, scb_command;
950
951 #ifdef WLDEBUG
952     if (ifp->if_flags & IFF_DEBUG)
953         if_printf(ifp, "entered wlstart()\n");
954 #endif
955
956     outw(PIOR1(base), OFFSET_CU);
957     cu_status = inw(PIOP1(base));
958     outw(PIOR0(base),OFFSET_SCB + 0);   /* scb_status */
959     scb_status = inw(PIOP0(base));
960     outw(PIOR0(base), OFFSET_SCB + 2);
961     scb_command = inw(PIOP0(base));
962
963     /*
964      * don't need OACTIVE check as tbusy here checks to see
965      * if we are already busy 
966      */
967     if (sc->tbusy) {
968         if((scb_status & 0x0700) == SCB_CUS_IDLE &&
969            (cu_status & AC_SW_B) == 0){
970             sc->tbusy = 0;
971             callout_stop(&sc->watchdog_ch);
972             ifp->if_flags &= ~IFF_OACTIVE;
973             /*
974              * This is probably just a race.  The xmt'r is just
975              * became idle but WE have masked interrupts so ...
976              */
977 #ifdef WLDEBUG
978             if_printf(ifp, "CU idle, scb %04x %04x cu %04x\n",
979                       scb_status, scb_command, cu_status);
980 #endif 
981             if (xmt_watch) if_printf(ifp, "!!\n");
982         } else {
983             return;     /* genuinely still busy */
984         }
985     } else if((scb_status & 0x0700) == SCB_CUS_ACTV ||
986               (cu_status & AC_SW_B)){
987 #ifdef WLDEBUG
988         if_printf(ifp, "CU unexpectedly busy; scb %04x cu %04x\n",
989                   scb_status, cu_status);
990 #endif
991         if (xmt_watch) if_printf(ifp, "busy?!");
992         return;         /* hey, why are we busy? */
993     }
994
995     /* get ourselves some data */
996     ifp = &(sc->wl_if);
997     m = ifq_dequeue(&ifp->if_snd, NULL);
998     if (m != NULL) {
999         BPF_MTAP(ifp, m);
1000         sc->tbusy++;
1001         /* set the watchdog timer so that if the board
1002          * fails to interrupt we will restart
1003          */
1004         /* try 10 ticks, not very long */
1005         callout_reset(&sc->watchdog_ch, 10, wlwatchdog, sc);
1006         ifp->if_flags |= IFF_OACTIVE;
1007         ifp->if_opackets++;
1008         wlxmt(sc, m);
1009     } else {
1010         ifp->if_flags &= ~IFF_OACTIVE;
1011     }
1012 }
1013
1014 /*
1015  * wlread:
1016  *
1017  *      This routine does the actual copy of data (including ethernet header
1018  *      structure) from the WaveLAN to an mbuf chain that will be passed up
1019  *      to the "if" (network interface) layer.  NOTE:  we currently
1020  *      don't handle trailer protocols, so if that is needed, it will
1021  *      (at least in part) be added here.  For simplicities sake, this
1022  *      routine copies the receive buffers from the board into a local (stack)
1023  *      buffer until the frame has been copied from the board.  Once in
1024  *      the local buffer, the contents are copied to an mbuf chain that
1025  *      is then enqueued onto the appropriate "if" queue.
1026  *
1027  * input        : softc pointer for this interface and
1028  *                an frame descriptor address
1029  * output       : the packet is put into an mbuf chain, and passed up
1030  * assumes      : if any errors occur, packet is "dropped on the floor"
1031  *
1032  */
1033 static int
1034 wlread(struct wl_softc *sc, u_short fd_p)
1035 {
1036     struct ifnet        *ifp = &sc->wl_if;
1037     short                       base = sc->base;
1038     fd_t                        fd;
1039     struct ether_header         eh;
1040     struct mbuf                 *m, *tm;
1041     rbd_t                       rbd;
1042     u_char                      *mb_p;
1043     u_short                     mlen, len, clen;
1044     u_short                     bytes_in_msg, bytes_in_mbuf, bytes;
1045
1046
1047 #ifdef WLDEBUG
1048     if (ifp->if_flags & IFF_DEBUG)
1049         if_printf(ifp, "entered wlread()\n");
1050 #endif
1051     if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
1052         if_printf(ifp, "read(): board is not running.\n");
1053         sc->hacr &= ~HACR_INTRON;
1054         CMD(sc);                /* turn off interrupts */
1055     }
1056     /* read ether_header info out of device memory. doesn't
1057      * go into mbuf.  goes directly into eh structure
1058      */
1059     len = sizeof(struct ether_header);  /* 14 bytes */
1060     outw(PIOR1(base), fd_p);
1061     insw(PIOP1(base), &fd, (sizeof(fd_t) - len)/2);
1062     insw(PIOP1(base), &eh, (len-2)/2);
1063     eh.ether_type = ntohs(inw(PIOP1(base)));
1064 #ifdef WLDEBUG
1065     if (ifp->if_flags & IFF_DEBUG)
1066         if_printf(ifp, "wlread: rcv packet, type is %x\n", eh.ether_type);
1067 #endif 
1068     /*
1069      * WARNING.  above is done now in ether_input, above may be
1070      * useful for debug. jrb
1071      */
1072     eh.ether_type = htons(eh.ether_type);
1073
1074     if (fd.rbd_offset == I82586NULL) {
1075         if_printf(ifp, "read(): Invalid buffer\n");
1076         if (wlhwrst(sc) != TRUE)
1077             if_printf(ifp, "read(): hwrst trouble.\n");
1078         return 0;
1079     }
1080
1081     outw(PIOR1(base), fd.rbd_offset);
1082     insw(PIOP1(base), &rbd, sizeof(rbd_t)/2);
1083     bytes_in_msg = rbd.status & RBD_SW_COUNT;
1084     MGETHDR(m, MB_DONTWAIT, MT_DATA);
1085     tm = m;
1086     if (m == NULL) {
1087         /*
1088          * not only do we want to return, we need to drop the packet on
1089          * the floor to clear the interrupt.
1090          *
1091          */
1092         if (wlhwrst(sc) != TRUE) {
1093             sc->hacr &= ~HACR_INTRON;
1094             CMD(sc);            /* turn off interrupts */
1095             if_printf(ifp, "read(): hwrst trouble.\n");
1096         }
1097         return 0;
1098     }
1099     m->m_next = (struct mbuf *) 0;
1100     m->m_pkthdr.rcvif = ifp;
1101     m->m_pkthdr.len = 0; /* don't know this yet */
1102     m->m_len = MHLEN;
1103
1104     /* always use a cluster. jrb 
1105      */
1106     MCLGET(m, MB_DONTWAIT);
1107     if (m->m_flags & M_EXT) {
1108         m->m_len = MCLBYTES;
1109     }
1110     else {
1111         m_freem(m);
1112         if (wlhwrst(sc) != TRUE) {
1113             sc->hacr &= ~HACR_INTRON;
1114             CMD(sc);            /* turn off interrupts */
1115             if_printf(ifp, "read(): hwrst trouble.\n");
1116         }
1117         return 0;
1118     }
1119
1120     mlen = 0;
1121     clen = mlen;
1122     bytes_in_mbuf = m->m_len - sizeof(eh);
1123     mb_p = mtod(tm, u_char *);
1124     bytes = min(bytes_in_mbuf, bytes_in_msg);
1125     bcopy(&eh, mb_p, sizeof(eh));
1126     mb_p += sizeof(eh);
1127     for (;;) {
1128         if (bytes & 1) {
1129             len = bytes + 1;
1130         } else {
1131             len = bytes;
1132         }
1133         outw(PIOR1(base), rbd.buffer_addr);
1134         insw(PIOP1(base), mb_p, len/2);
1135         clen += bytes;
1136         mlen += bytes;
1137
1138         if (!(bytes_in_mbuf -= bytes)) {
1139             MGET(tm->m_next, MB_DONTWAIT, MT_DATA);
1140             tm = tm->m_next;
1141             if (tm == (struct mbuf *)0) {
1142                 m_freem(m);
1143                 if_printf(ifp, "read(): No mbuf nth\n");
1144                 if (wlhwrst(sc) != TRUE) {
1145                     sc->hacr &= ~HACR_INTRON;
1146                     CMD(sc);  /* turn off interrupts */
1147                     if_printf(ifp, "read(): hwrst trouble.\n");
1148                 }
1149                 return 0;
1150             }
1151             mlen = 0;
1152             tm->m_len = MLEN;
1153             bytes_in_mbuf = MLEN;
1154             mb_p = mtod(tm, u_char *);
1155         } else {
1156             mb_p += bytes;
1157         }
1158
1159         if (!(bytes_in_msg  -= bytes)) {
1160             if (rbd.status & RBD_SW_EOF ||
1161                 rbd.next_rbd_offset == I82586NULL) {
1162                 tm->m_len = mlen;
1163                 break;
1164             } else {
1165                 outw(PIOR1(base), rbd.next_rbd_offset);
1166                 insw(PIOP1(base), &rbd, sizeof(rbd_t)/2);
1167                 bytes_in_msg = rbd.status & RBD_SW_COUNT;
1168             }
1169         } else {
1170             rbd.buffer_addr += bytes;
1171         }
1172
1173         bytes = min(bytes_in_mbuf, bytes_in_msg);
1174     }
1175
1176     m->m_pkthdr.len = clen;
1177
1178     /*
1179      * If hw is in promiscuous mode (note that I said hardware, not if
1180      * IFF_PROMISC is set in ifnet flags), then if this is a unicast
1181      * packet and the MAC dst is not us, drop it.  This check in normally
1182      * inside ether_input(), but IFF_MULTI causes hw promisc without
1183      * a bpf listener, so this is wrong.
1184      *          Greg Troxel <gdt@ir.bbn.com>, 1998-08-07
1185      */
1186     /*
1187      * TBD: also discard packets where NWID does not match.
1188      * However, there does not appear to be a way to read the nwid
1189      * for a received packet.  -gdt 1998-08-07
1190      */
1191     if (
1192 #ifdef WL_USE_IFNET_PROMISC_CHECK /* not defined */
1193         (ifp->if_flags & (IFF_PROMISC|IFF_ALLMULTI))
1194 #else
1195         /* hw is in promisc mode if this is true */
1196         (sc->mode & (MOD_PROM | MOD_ENAL))
1197 #endif
1198         &&
1199         (eh.ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */
1200         bcmp(eh.ether_dhost, sc->wl_ac.ac_enaddr,
1201              sizeof(eh.ether_dhost)) != 0 ) {
1202       m_freem(m);
1203       return 1;
1204     }
1205
1206 #ifdef WLDEBUG
1207     if (ifp->if_flags & IFF_DEBUG)
1208         if_printf(ifp, "wlrecv %d bytes\n", clen);
1209 #endif
1210
1211 #ifdef WLCACHE
1212     wl_cache_store(sc, base, &eh, m);
1213 #endif
1214
1215     /*
1216      * received packet is now in a chain of mbuf's.  next step is
1217      * to pass the packet upwards.
1218      *
1219      */
1220     ifp->if_input(ifp, m);
1221     return 1;
1222 }
1223
1224 /*
1225  * wlioctl:
1226  *
1227  *      This routine processes an ioctl request from the "if" layer
1228  *      above.
1229  *
1230  * input        : pointer the appropriate "if" struct, command and data
1231  * output       : based on command appropriate action is taken on the
1232  *                WaveLAN board(s) or related structures
1233  * return       : error is returned containing exit conditions
1234  *
1235  */
1236 static int
1237 wlioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cred)
1238 {
1239     struct ifreq        *ifr = (struct ifreq *)data;
1240     struct wl_softc     *sc = ifp->if_softc;
1241     short               base = sc->base;
1242     short               mode = 0;
1243     int                 error = 0;
1244     int                 irq, irqval, i, isroot, size;
1245     caddr_t             up;
1246     char *              cpt;
1247     struct thread *td = curthread; /* XXX */
1248         
1249
1250 #ifdef WLDEBUG
1251     if (ifp->if_flags & IFF_DEBUG)
1252         if_printf(ifp, "entered wlioctl()\n");
1253 #endif
1254     switch (cmd) {
1255     case SIOCSIFFLAGS:
1256         if (ifp->if_flags & IFF_ALLMULTI) {
1257             mode |= MOD_ENAL;
1258         }
1259         if (ifp->if_flags & IFF_PROMISC) {
1260             mode |= MOD_PROM;
1261         }
1262         if(ifp->if_flags & IFF_LINK0) {
1263             mode |= MOD_PROM;
1264         }
1265         /*
1266          * force a complete reset if the recieve multicast/
1267          * promiscuous mode changes so that these take 
1268          * effect immediately.
1269          *
1270          */
1271         if (sc->mode != mode) {
1272             sc->mode = mode;
1273             if (sc->flags & DSF_RUNNING) {
1274                 sc->flags &= ~DSF_RUNNING;
1275                 wlinit(sc);
1276             }
1277         }
1278         /* if interface is marked DOWN and still running then
1279          * stop it.
1280          */
1281         if ((ifp->if_flags & IFF_UP) == 0 && sc->flags & DSF_RUNNING) {
1282             if_printf(ifp, "ioctl(): board is not running\n");
1283             sc->flags &= ~DSF_RUNNING;
1284             sc->hacr &= ~HACR_INTRON;
1285             CMD(sc);              /* turn off interrupts */
1286         } 
1287         /* else if interface is UP and RUNNING, start it
1288                 */
1289         else if (ifp->if_flags & IFF_UP && (sc->flags & DSF_RUNNING) == 0) {
1290             wlinit(sc);
1291         }
1292   
1293         /* if WLDEBUG set on interface, then printf rf-modem regs
1294         */
1295         if(ifp->if_flags & IFF_DEBUG)
1296             wlmmcstat(sc);
1297         break;
1298 #if     MULTICAST
1299     case SIOCADDMULTI:
1300     case SIOCDELMULTI:
1301
1302 #if defined(__FreeBSD__) && __FreeBSD_version < 300000
1303         if (cmd == SIOCADDMULTI) {
1304             error = ether_addmulti(ifr, &sc->wl_ac);
1305         }
1306         else {
1307             error = ether_delmulti(ifr, &sc->wl_ac);
1308         }
1309
1310         /* see if we should be in all multicast mode
1311          * note that 82586 cannot do that, must simulate with
1312          * promiscuous mode
1313          */
1314         if (check_allmulti(sc)) {
1315                 ifp->if_flags |=  IFF_ALLMULTI;
1316                 sc->mode |= MOD_ENAL;
1317                 sc->flags &= ~DSF_RUNNING;
1318                 wlinit(sc);
1319                 error = 0;
1320                 break;
1321         }
1322
1323         if (error == ENETRESET) {
1324             if(sc->flags & DSF_RUNNING) {
1325                 sc->flags &= ~DSF_RUNNING;
1326                 wlinit(sc);
1327             }
1328             error = 0;
1329         }
1330 #else
1331         wlinit(sc);
1332 #endif
1333         break;
1334 #endif  /* MULTICAST */
1335
1336     /* DEVICE SPECIFIC */
1337
1338
1339         /* copy the PSA out to the caller */
1340     case SIOCGWLPSA:
1341         /* pointer to buffer in user space */
1342         up = (void *)ifr->ifr_data;
1343         /* work out if they're root */
1344         isroot = (suser(td) == 0);
1345         
1346         for (i = 0; i < 0x40; i++) {
1347             /* don't hand the DES key out to non-root users */
1348             if ((i > WLPSA_DESKEY) && (i < (WLPSA_DESKEY + 8)) && !isroot)
1349                 continue;
1350             if (subyte((up + i), sc->psa[i]))
1351                 return(EFAULT);
1352         }
1353         break;
1354
1355
1356         /* copy the PSA in from the caller; we only copy _some_ values */
1357     case SIOCSWLPSA:
1358         /* root only */
1359         if ((error = suser(td)))
1360             break;
1361         error = EINVAL; /* assume the worst */
1362         /* pointer to buffer in user space containing data */
1363         up = (void *)ifr->ifr_data;
1364         
1365         /* check validity of input range */
1366         for (i = 0; i < 0x40; i++)
1367             if (fubyte(up + i) < 0)
1368                 return(EFAULT);
1369
1370         /* check IRQ value */
1371         irqval = fubyte(up+WLPSA_IRQNO);
1372         for (irq = 15; irq >= 0; irq--)
1373             if(irqvals[irq] == irqval)
1374                 break;
1375         if (irq == 0)                   /* oops */
1376             break;
1377         /* new IRQ */
1378         sc->psa[WLPSA_IRQNO] = irqval;
1379
1380         /* local MAC */
1381         for (i = 0; i < 6; i++)
1382             sc->psa[WLPSA_LOCALMAC+i] = fubyte(up+WLPSA_LOCALMAC+i);
1383                 
1384         /* MAC select */        
1385         sc->psa[WLPSA_MACSEL] = fubyte(up+WLPSA_MACSEL);
1386         
1387         /* default nwid */
1388         sc->psa[WLPSA_NWID] = fubyte(up+WLPSA_NWID);
1389         sc->psa[WLPSA_NWID+1] = fubyte(up+WLPSA_NWID+1);
1390
1391         error = 0;
1392         wlsetpsa(sc);           /* update the PSA */
1393         break;
1394
1395
1396         /* get the current NWID out of the sc since we stored it there */
1397     case SIOCGWLCNWID:
1398         ifr->ifr_data = (caddr_t) (sc->nwid[0] << 8 | sc->nwid[1]);
1399         break;
1400
1401
1402         /*
1403          * change the nwid dynamically.  This
1404          * ONLY changes the radio modem and does not
1405          * change the PSA.
1406          *
1407          * 2 steps:
1408          *      1. save in softc "soft registers"
1409          *      2. save in radio modem (MMC)
1410          */
1411     case SIOCSWLCNWID:
1412         /* root only */
1413         if ((error = suser(td)))
1414             break;
1415         if (!(ifp->if_flags & IFF_UP)) {
1416             error = EIO;        /* only allowed while up */
1417         } else {
1418             /* 
1419              * soft c nwid shadows radio modem setting
1420              */
1421             sc->nwid[0] = (int)ifr->ifr_data >> 8;
1422             sc->nwid[1] = (int)ifr->ifr_data & 0xff;
1423             MMC_WRITE(MMC_NETW_ID_L,sc->nwid[1]);
1424             MMC_WRITE(MMC_NETW_ID_H,sc->nwid[0]);
1425         }
1426         break;
1427
1428         /* copy the EEPROM in 2.4 Gz WaveMODEM  out to the caller */
1429     case SIOCGWLEEPROM:
1430         /* root only */
1431         if ((error = suser(td)))
1432             break;
1433         /* pointer to buffer in user space */
1434         up = (void *)ifr->ifr_data;
1435         
1436         for (i=0x00; i<0x80; ++i) {             /* 2.4 Gz: size of EEPROM   */
1437             MMC_WRITE(MMC_EEADDR,i);            /* 2.4 Gz: get frequency    */
1438             MMC_WRITE(MMC_EECTRL,               /* 2.4 Gz: EEPROM read      */
1439                         MMC_EECTRL_EEOP_READ);  /* 2.4 Gz:                  */
1440             DELAY(40);                          /* 2.4 Gz                   */
1441             if (subyte(up + 2*i  ,              /* 2.4 Gz: pass low byte of */
1442                  wlmmcread(base,MMC_EEDATALrv)) /* 2.4 Gz: EEPROM word      */
1443                ) return(EFAULT);                /* 2.4 Gz:                  */
1444             if (subyte(up + 2*i+1,              /* 2.4 Gz: pass hi byte of  */
1445                  wlmmcread(base,MMC_EEDATALrv)) /* 2.4 Gz: EEPROM word      */
1446                ) return(EFAULT);                /* 2.4 Gz:                  */
1447         }
1448         break;
1449
1450 #ifdef WLCACHE
1451         /* zero (Delete) the wl cache */
1452     case SIOCDWLCACHE:
1453         /* root only */
1454         if ((error = suser(td)))
1455             break;
1456         wl_cache_zero(sc);
1457         break;
1458
1459         /* read out the number of used cache elements */
1460     case SIOCGWLCITEM:
1461         ifr->ifr_data = (caddr_t) sc->w_sigitems;
1462         break;
1463
1464         /* read out the wl cache */
1465     case SIOCGWLCACHE:
1466         /* pointer to buffer in user space */
1467         up = (void *)ifr->ifr_data;
1468         cpt = (char *) &sc->w_sigcache[0];
1469         size = sc->w_sigitems * sizeof(struct w_sigcache);
1470         
1471         for (i = 0; i < size; i++) {
1472             if (subyte((up + i), *cpt++))
1473                 return(EFAULT);
1474         }
1475         break;
1476 #endif
1477
1478     default:
1479         error = ether_ioctl(ifp, cmd, data);
1480         break;
1481     }
1482     return (error);
1483 }
1484
1485 /*
1486  * wlwatchdog():
1487  *
1488  * Called if the timer set in wlstart expires before an interrupt is received
1489  * from the wavelan.   It seems to lose interrupts sometimes.
1490  * The watchdog routine gets called if the transmitter failed to interrupt
1491  *
1492  * input        : which board is timing out
1493  * output       : board reset 
1494  *
1495  */
1496 static void
1497 wlwatchdog(void *vsc)
1498 {
1499     struct wl_softc *sc = vsc;
1500     struct ifnet *ifp = &sc->wl_if;
1501
1502     lwkt_serialize_enter(ifp->if_serializer);
1503     log(LOG_ERR, "%s: wavelan device timeout on xmit\n", sc->wl_if.if_xname);
1504     sc->wl_if.if_oerrors++;
1505     wlinit(sc);
1506     lwkt_serialize_exit(ifp->if_serializer);
1507 }
1508
1509 /*
1510  * wlintr:
1511  *
1512  *      This function is the interrupt handler for the WaveLAN
1513  *      board.  This routine will be called whenever either a packet
1514  *      is received, or a packet has successfully been transfered and
1515  *      the unit is ready to transmit another packet.
1516  *
1517  * input        : softc pointer for this interface
1518  * output       : either a packet is received, or a packet is transfered
1519  *
1520  */
1521 static void
1522 wlintr(void *arg)
1523 {
1524     struct wl_softc *sc = arg;
1525     struct ifnet *ifp = &sc->wl_if;
1526     short               base = sc->base;
1527     int                 ac_status;
1528     u_short             int_type, int_type1;
1529
1530 #ifdef WLDEBUG
1531     if (ifp->if_flags & IFF_DEBUG)
1532         if_printf(ifp, "wlintr() called\n");
1533 #endif
1534
1535     if((int_type = inw(HASR(base))) & HASR_MMC_INTR) {
1536         /* handle interrupt from the modem management controler */
1537         /* This will clear the interrupt condition */ 
1538         (void) wlmmcread(base,MMC_DCE_STATUS); /* ignored for now */
1539     }
1540
1541     if(!(int_type & HASR_INTR)){        /* return if no interrupt from 82586 */
1542         /* commented out. jrb.  it happens when reinit occurs
1543            if_printf(ifp, "%s: int_type %x, dump follows\n",
1544                      __func__, int_type);
1545            wldump(sc);
1546            */
1547         return;
1548     }
1549
1550     if (gathersnr)
1551         getsnr(sc);
1552     for(;;) {
1553         outw(PIOR0(base), OFFSET_SCB + 0);      /* get scb status */
1554         int_type = (inw(PIOP0(base)) & SCB_SW_INT);
1555         if (int_type == 0)                      /* no interrupts left */
1556             break;
1557
1558         int_type1 = wlack(sc);                  /* acknowledge interrupt(s) */
1559         /* make sure no bits disappeared (others may appear) */
1560         if ((int_type & int_type1) != int_type) {
1561             if_printf(ifp, "wlack() int bits disappeared: "
1562                       "%04x != int_type %04x\n", int_type1, int_type);
1563         }
1564         int_type = int_type1;                   /* go with the new status */
1565         /* 
1566          * incoming packet
1567          */
1568         if (int_type & SCB_SW_FR) {
1569             ifp->if_ipackets++;
1570             wlrcv(sc);
1571         }
1572         /*
1573          * receiver not ready
1574          */
1575         if (int_type & SCB_SW_RNR) {
1576             ifp->if_ierrors++;
1577 #ifdef  WLDEBUG
1578             if (ifp->if_flags & IFF_DEBUG) {
1579                 if_printf(ifp, "intr(): receiver overrun! begin_fd = %x\n",
1580                           sc->begin_fd);
1581             }
1582 #endif
1583             wlrustrt(sc);
1584         }
1585         /*
1586          * CU not ready
1587          */
1588         if (int_type & SCB_SW_CNA) {
1589             /*
1590              * At present, we don't care about CNA's.  We
1591              * believe they are a side effect of XMT.
1592              */
1593         }
1594         if (int_type & SCB_SW_CX) {
1595             /*
1596              * At present, we only request Interrupt for
1597              * XMT.
1598              */
1599             outw(PIOR1(base), OFFSET_CU);       /* get command status */
1600             ac_status = inw(PIOP1(base));
1601
1602             if (xmt_watch) {                    /* report some anomalies */
1603
1604                 if (sc->tbusy == 0) {
1605                     if_printf(ifp, "xmt intr but not busy, CU %04x\n",
1606                               ac_status);
1607                 }
1608                 if (ac_status == 0) {
1609                     if_printf(ifp, "xmt intr but ac_status == 0\n");
1610                 }
1611                 if (ac_status & AC_SW_A) {
1612                     if_printf(ifp, "xmt aborted\n");
1613                 }
1614 #ifdef  notdef
1615                 if (ac_status & TC_CARRIER) {
1616                     if_printf(ifp, "no carrier\n");
1617                 }
1618 #endif  /* notdef */
1619                 if (ac_status & TC_CLS) {
1620                     if_printf(ifp, "no CTS\n");
1621                 }
1622                 if (ac_status & TC_DMA) {
1623                     if_printf(ifp, "DMA underrun\n");
1624                 }
1625                 if (ac_status & TC_DEFER) {
1626                     if_printf(ifp, "xmt deferred\n");
1627                 }
1628                 if (ac_status & TC_SQE) {
1629                     if_printf(ifp, "heart beat\n");
1630                 }
1631                 if (ac_status & TC_COLLISION) {
1632                     if_printf(ifp, "too many collisions\n");
1633                 }
1634             }
1635             /* if the transmit actually failed, or returned some status */
1636             if ((!(ac_status & AC_SW_OK)) || (ac_status & 0xfff)) {
1637                 if (ac_status & (TC_COLLISION | TC_CLS | TC_DMA)) {
1638                     ifp->if_oerrors++;
1639                 }
1640
1641                 /* count collisions */
1642                 ifp->if_collisions += (ac_status & 0xf);
1643                 /* if TC_COLLISION set and collision count zero, 16 collisions */
1644                 if ((ac_status & 0x20) == 0x20) {
1645                     ifp->if_collisions += 0x10;
1646                 }
1647             }
1648             sc->tbusy = 0;
1649             callout_stop(&sc->watchdog_ch);
1650             ifp->if_flags &= ~IFF_OACTIVE;
1651             wlstart(ifp);
1652         }
1653     }
1654 }
1655
1656 /*
1657  * wlrcv:
1658  *
1659  *      This routine is called by the interrupt handler to initiate a
1660  *      packet transfer from the board to the "if" layer above this
1661  *      driver.  This routine checks if a buffer has been successfully
1662  *      received by the WaveLAN.  If so, the routine wlread is called
1663  *      to do the actual transfer of the board data (including the
1664  *      ethernet header) into a packet (consisting of an mbuf chain).
1665  *
1666  * input        : softc pointer for this interface
1667  * output       : if a packet is available, it is "sent up"
1668  *
1669  */
1670 static void
1671 wlrcv(struct wl_softc *sc)
1672 {
1673     short       base = sc->base;
1674     u_short     fd_p, status, offset, link_offset;
1675
1676 #ifdef WLDEBUG
1677     if (sc->wl_if.if_flags & IFF_DEBUG)
1678         if_printf(&sc->wl_if, "entered wlrcv()\n");
1679 #endif
1680     for (fd_p = sc->begin_fd; fd_p != I82586NULL; fd_p = sc->begin_fd) {
1681
1682         outw(PIOR0(base), fd_p + 0);    /* address of status */
1683         status = inw(PIOP0(base));
1684         outw(PIOR1(base), fd_p + 4);    /* address of link_offset */
1685         link_offset = inw(PIOP1(base));
1686         offset = inw(PIOP1(base));      /* rbd_offset */
1687         if (status == 0xffff || offset == 0xffff /*I82586NULL*/) {
1688             if (wlhwrst(sc) != TRUE)
1689                 if_printf(&sc->wl_if, "rcv(): hwrst ffff trouble.\n");
1690             return;
1691         } else if (status & AC_SW_C) {
1692             if (status == (RFD_DONE|RFD_RSC)) {
1693                 /* lost one */
1694 #ifdef  WLDEBUG
1695                 if (sc->wl_if.if_flags & IFF_DEBUG)
1696                     if_printf(&sc->wl_if, "RCV: RSC %x\n", status);
1697 #endif
1698                 sc->wl_if.if_ierrors++;
1699             } else if (!(status & RFD_OK)) {
1700                 if_printf(&sc->wl_if, "RCV: !OK %x\n", status);
1701                 sc->wl_if.if_ierrors++;
1702             } else if (status & 0xfff) {        /* can't happen */
1703                 if_printf(&sc->wl_if, "RCV: ERRs %x\n", status);
1704                 sc->wl_if.if_ierrors++;
1705             } else if (!wlread(sc, fd_p))
1706                 return;
1707
1708             if (!wlrequeue(sc, fd_p)) {
1709                 /* abort on chain error */
1710                 if (wlhwrst(sc) != TRUE)
1711                     if_printf(&sc->wl_if, "rcv(): hwrst trouble.\n");
1712                 return;
1713             }
1714             sc->begin_fd = link_offset;
1715         } else {
1716             break;
1717         }
1718     }
1719 }
1720
1721 /*
1722  * wlrequeue:
1723  *
1724  *      This routine puts rbd's used in the last receive back onto the
1725  *      free list for the next receive.
1726  *
1727  */
1728 static int
1729 wlrequeue(struct wl_softc *sc, u_short fd_p)
1730 {
1731     short               base = sc->base;
1732     fd_t                fd;
1733     u_short             l_rbdp, f_rbdp, rbd_offset;
1734
1735     outw(PIOR0(base), fd_p + 6);
1736     rbd_offset = inw(PIOP0(base));
1737     if ((f_rbdp = rbd_offset) != I82586NULL) {
1738         l_rbdp = f_rbdp;
1739         for(;;) {
1740             outw(PIOR0(base), l_rbdp + 0);      /* address of status */
1741             if(inw(PIOP0(base)) & RBD_SW_EOF)
1742                 break;
1743             outw(PIOP0(base), 0);
1744             outw(PIOR0(base), l_rbdp + 2);      /* next_rbd_offset */
1745             if((l_rbdp = inw(PIOP0(base))) == I82586NULL)
1746                 break;
1747         }
1748         outw(PIOP0(base), 0);
1749         outw(PIOR0(base), l_rbdp + 2);          /* next_rbd_offset */
1750         outw(PIOP0(base), I82586NULL);
1751         outw(PIOR0(base), l_rbdp + 8);          /* address of size */
1752         outw(PIOP0(base), inw(PIOP0(base)) | AC_CW_EL);
1753         outw(PIOR0(base), sc->end_rbd + 2);
1754         outw(PIOP0(base), f_rbdp);              /* end_rbd->next_rbd_offset */
1755         outw(PIOR0(base), sc->end_rbd + 8);     /* size */
1756         outw(PIOP0(base), inw(PIOP0(base)) & ~AC_CW_EL);
1757         sc->end_rbd = l_rbdp;
1758     }
1759
1760     fd.status = 0;
1761     fd.command = AC_CW_EL;
1762     fd.link_offset = I82586NULL;
1763     fd.rbd_offset = I82586NULL;
1764     outw(PIOR1(base), fd_p);
1765     outsw(PIOP1(base), &fd, 8/2);
1766     
1767     outw(PIOR1(base), sc->end_fd + 2);  /* addr of command */
1768     outw(PIOP1(base), 0);               /* command = 0 */
1769     outw(PIOP1(base), fd_p);            /* end_fd->link_offset = fd_p */
1770     sc->end_fd = fd_p;
1771
1772     return 1;
1773 }
1774
1775 #ifdef  WLDEBUG
1776 static int xmt_debug = 0;
1777 #endif  /* WLDEBUG */
1778
1779 /*
1780  * wlxmt:
1781  *
1782  *      This routine fills in the appropriate registers and memory
1783  *      locations on the WaveLAN board and starts the board off on
1784  *      the transmit.
1785  *
1786  * input        : softc pointer for this interface, and a pointer to the mbuf
1787  * output       : board memory and registers are set for xfer and attention
1788  *
1789  */
1790 static void
1791 wlxmt(struct wl_softc *sc, struct mbuf *m)
1792 {
1793     u_short             xmtdata_p = OFFSET_TBUF;
1794     u_short             xmtshort_p;
1795     struct      mbuf                    *tm_p = m;
1796     struct ether_header *eh_p = mtod(m, struct ether_header *);
1797     u_char                              *mb_p = mtod(m, u_char *) + sizeof(struct ether_header);
1798     u_short                             count = m->m_len - sizeof(struct ether_header);
1799     ac_t                                cb;
1800     u_short                             tbd_p = OFFSET_TBD;
1801     u_short                             len, clen = 0;
1802     short                               base = sc->base;
1803     int                                 spin;
1804         
1805 #ifdef WLDEBUG
1806     if (sc->wl_if.if_flags & IFF_DEBUG)
1807         if_printf(&sc->wl_if, "entered wlxmt()\n");
1808 #endif
1809
1810     cb.ac_status = 0;
1811     cb.ac_command = (AC_CW_EL|AC_TRANSMIT|AC_CW_I);
1812     cb.ac_link_offset = I82586NULL;
1813     outw(PIOR1(base), OFFSET_CU);
1814     outsw(PIOP1(base), &cb, 6/2);
1815     outw(PIOP1(base), OFFSET_TBD);      /* cb.cmd.transmit.tbd_offset */
1816     outsw(PIOP1(base), eh_p->ether_dhost, WAVELAN_ADDR_SIZE/2);
1817     outw(PIOP1(base), eh_p->ether_type);
1818
1819 #ifdef  WLDEBUG
1820     if (sc->wl_if.if_flags & IFF_DEBUG) {
1821         if (xmt_debug) {
1822             if_printf(&sc->wl_if, "XMT    mbuf: L%d @%p ", count, (void *)mb_p);
1823             printf("ether type %x\n", eh_p->ether_type);
1824         }
1825     }
1826 #endif  /* WLDEBUG */
1827     outw(PIOR0(base), OFFSET_TBD);
1828     outw(PIOP0(base), 0);               /* act_count */
1829     outw(PIOR1(base), OFFSET_TBD + 4);
1830     outw(PIOP1(base), xmtdata_p);       /* buffer_addr */
1831     outw(PIOP1(base), 0);               /* buffer_base */
1832     for (;;) {
1833         if (count) {
1834             if (clen + count > WAVELAN_MTU)
1835                 break;
1836             if (count & 1)
1837                 len = count + 1;
1838             else
1839                 len = count;
1840             outw(PIOR1(base), xmtdata_p);
1841             outsw(PIOP1(base), mb_p, len/2);
1842             clen += count;
1843             outw(PIOR0(base), tbd_p);  /* address of act_count */
1844             outw(PIOP0(base), inw(PIOP0(base)) + count);
1845             xmtdata_p += len;
1846             if ((tm_p = tm_p->m_next) == (struct mbuf *)0)
1847                 break;
1848             if (count & 1) {
1849                 /* go to the next descriptor */
1850                 outw(PIOR0(base), tbd_p + 2);
1851                 tbd_p += sizeof (tbd_t);
1852                 outw(PIOP0(base), tbd_p); /* next_tbd_offset */
1853                 outw(PIOR0(base), tbd_p);
1854                 outw(PIOP0(base), 0);   /* act_count */
1855                 outw(PIOR1(base), tbd_p + 4);
1856                 outw(PIOP1(base), xmtdata_p); /* buffer_addr */
1857                 outw(PIOP1(base), 0);         /* buffer_base */
1858                 /* at the end -> coallesce remaining mbufs */
1859                 if (tbd_p == OFFSET_TBD + (N_TBD-1) * sizeof (tbd_t)) {
1860                     wlsftwsleaze(&count, &mb_p, &tm_p);
1861                     continue;
1862                 }
1863                 /* next mbuf short -> coallesce as needed */
1864                 if ( (tm_p->m_next == (struct mbuf *) 0) ||
1865 #define HDW_THRESHOLD 55
1866                      tm_p->m_len > HDW_THRESHOLD)
1867                     /* ok */;
1868                 else {
1869                     wlhdwsleaze(&count, &mb_p, &tm_p);
1870                     continue;
1871                 }
1872             }
1873         } else if ((tm_p = tm_p->m_next) == (struct mbuf *)0)
1874             break;
1875         count = tm_p->m_len;
1876         mb_p = mtod(tm_p, u_char *);
1877 #ifdef  WLDEBUG
1878         if (sc->wl_if.if_flags & IFF_DEBUG)
1879             if (xmt_debug)
1880                 if_printf(&sc->wl_if, "mbuf+ L%d @%p ", count, (void *)mb_p);
1881 #endif  /* WLDEBUG */
1882     }
1883 #ifdef  WLDEBUG
1884     if (sc->wl_if.if_flags & IFF_DEBUG)
1885         if (xmt_debug)
1886             if_printf(&sc->wl_if, "CLEN = %d\n", clen);
1887 #endif  /* WLDEBUG */
1888     outw(PIOR0(base), tbd_p);
1889     if (clen < ETHERMIN) {
1890         outw(PIOP0(base), inw(PIOP0(base)) + ETHERMIN - clen);
1891         outw(PIOR1(base), xmtdata_p);
1892         for (xmtshort_p = xmtdata_p; clen < ETHERMIN; clen += 2)
1893             outw(PIOP1(base), 0);
1894     }   
1895     outw(PIOP0(base), inw(PIOP0(base)) | TBD_SW_EOF);
1896     outw(PIOR0(base), tbd_p + 2);
1897     outw(PIOP0(base), I82586NULL);
1898 #ifdef  WLDEBUG
1899     if (sc->wl_if.if_flags & IFF_DEBUG) {
1900         if (xmt_debug) {
1901             wltbd(sc);
1902             printf("\n");
1903         }
1904     }
1905 #endif  /* WLDEBUG */
1906
1907     outw(PIOR0(base), OFFSET_SCB + 2);  /* address of scb_command */
1908     /* 
1909      * wait for 586 to clear previous command, complain if it takes
1910      * too long
1911      */
1912     for (spin = 1;;spin = (spin + 1) % 10000) {
1913         if (inw(PIOP0(base)) == 0) {            /* it's done, we can go */
1914             break;
1915         }
1916         if ((spin == 0) && xmt_watch) {         /* not waking up, and we care */
1917             if_printf(&sc->wl_if, "slow accepting xmit\n");
1918         }
1919     }
1920     outw(PIOP0(base), SCB_CU_STRT);             /* new command */
1921     SET_CHAN_ATTN(sc);
1922     
1923     m_freem(m);
1924
1925     /* XXX 
1926      * Pause to avoid transmit overrun problems.
1927      * The required delay tends to vary with platform type, and may be
1928      * related to interrupt loss.
1929      */
1930     if (wl_xmit_delay) {
1931         DELAY(wl_xmit_delay);
1932     }
1933 }
1934
1935 /*
1936  * wlbldru:
1937  *
1938  *      This function builds the linear linked lists of fd's and
1939  *      rbd's.  Based on page 4-32 of 1986 Intel microcom handbook.
1940  *
1941  */
1942 static u_short
1943 wlbldru(struct wl_softc *sc)
1944 {
1945     short       base = sc->base;
1946     fd_t        fd;
1947     rbd_t       rbd;
1948     u_short     fd_p = OFFSET_RU;
1949     u_short     rbd_p = OFFSET_RBD;
1950     int         i;
1951
1952     sc->begin_fd = fd_p;
1953     for(i = 0; i < N_FD; i++) {
1954         fd.status = 0;
1955         fd.command = 0;
1956         fd.link_offset = fd_p + sizeof(fd_t);
1957         fd.rbd_offset = I82586NULL;
1958         outw(PIOR1(base), fd_p);
1959         outsw(PIOP1(base), &fd, 8/2);
1960         fd_p = fd.link_offset;
1961     }
1962     fd_p -= sizeof(fd_t);
1963     sc->end_fd = fd_p;
1964     outw(PIOR1(base), fd_p + 2);
1965     outw(PIOP1(base), AC_CW_EL);        /* command */
1966     outw(PIOP1(base), I82586NULL);      /* link_offset */
1967     fd_p = OFFSET_RU;
1968     
1969     outw(PIOR0(base), fd_p + 6);        /* address of rbd_offset */
1970     outw(PIOP0(base), rbd_p);
1971     outw(PIOR1(base), rbd_p);
1972     for(i = 0; i < N_RBD; i++) {
1973         rbd.status = 0;
1974         rbd.buffer_addr = rbd_p + sizeof(rbd_t) + 2;
1975         rbd.buffer_base = 0;
1976         rbd.size = RCVBUFSIZE;
1977         if (i != N_RBD-1) {
1978             rbd_p += sizeof(ru_t);
1979             rbd.next_rbd_offset = rbd_p;
1980         } else {
1981             rbd.next_rbd_offset = I82586NULL;
1982             rbd.size |= AC_CW_EL;
1983             sc->end_rbd = rbd_p;
1984         }
1985         outsw(PIOP1(base), &rbd, sizeof(rbd_t)/2);
1986         outw(PIOR1(base), rbd_p);
1987     }
1988     return sc->begin_fd;
1989 }
1990
1991 /*
1992  * wlrustrt:
1993  *
1994  *      This routine starts the receive unit running.  First checks if the
1995  *      board is actually ready, then the board is instructed to receive
1996  *      packets again.
1997  *
1998  */
1999 static void
2000 wlrustrt(struct wl_softc *sc)
2001 {
2002     short               base = sc->base;
2003     u_short             rfa;
2004
2005 #ifdef WLDEBUG
2006     if (sc->wl_if.if_flags & IFF_DEBUG)
2007         if_printf(&sc->wl_if, "entered wlrustrt()\n");
2008 #endif
2009     outw(PIOR0(base), OFFSET_SCB);
2010     if (inw(PIOP0(base)) & SCB_RUS_READY){
2011         if_printf(&sc->wl_if, "wlrustrt: RUS_READY\n");
2012         return;
2013     }
2014
2015     outw(PIOR0(base), OFFSET_SCB + 2);
2016     outw(PIOP0(base), SCB_RU_STRT);             /* command */
2017     rfa = wlbldru(sc);
2018     outw(PIOR0(base), OFFSET_SCB + 6);  /* address of scb_rfa_offset */
2019     outw(PIOP0(base), rfa);
2020
2021     SET_CHAN_ATTN(sc);
2022 }
2023
2024 /*
2025  * wldiag:
2026  *
2027  *      This routine does a 586 op-code number 7, and obtains the
2028  *      diagnose status for the WaveLAN.
2029  *
2030  */
2031 static int
2032 wldiag(struct wl_softc *sc)
2033 {
2034     short base = sc->base;
2035     short status;
2036
2037 #ifdef WLDEBUG
2038     if (sc->wl_if.if_flags & IFF_DEBUG)
2039         if_printf(&sc->wl_if, "entered wldiag()\n");
2040 #endif
2041     outw(PIOR0(base), OFFSET_SCB);
2042     status = inw(PIOP0(base));
2043     if (status & SCB_SW_INT) {
2044                 /* state is 2000 which seems ok
2045                    if_printf(&sc->wl_if, "diag(): unexpected initial state %\n",
2046                    inw(PIOP0(base)));
2047                 */
2048         wlack(sc);
2049     }
2050     outw(PIOR1(base), OFFSET_CU);
2051     outw(PIOP1(base), 0);                       /* ac_status */
2052     outw(PIOP1(base), AC_DIAGNOSE|AC_CW_EL);/* ac_command */
2053     if(wlcmd(sc, "diag()") == 0)
2054         return 0;
2055     outw(PIOR0(base), OFFSET_CU);
2056     if (inw(PIOP0(base)) & 0x0800) {
2057         if_printf(&sc->wl_if, "i82586 Self Test failed!\n");
2058         return 0;
2059     }
2060     return TRUE;
2061 }
2062
2063 /*
2064  * wlconfig:
2065  *
2066  *      This routine does a standard config of the WaveLAN board.
2067  *
2068  */
2069 static int
2070 wlconfig(struct wl_softc *sc)
2071 {
2072     configure_t configure;
2073     short base = sc->base;
2074
2075 #if     MULTICAST
2076 #if defined(__DragonFly__) || (defined(__FreeBSD__) && __FreeBSD_version >= 300000)
2077     struct ifmultiaddr *ifma;
2078     u_char *addrp;
2079 #else
2080     struct ether_multi *enm;
2081     struct ether_multistep step;
2082 #endif
2083     int cnt = 0;
2084 #endif  /* MULTICAST */
2085
2086 #ifdef WLDEBUG
2087     if (sc->wl_if.if_flags & IFF_DEBUG)
2088         if_printf(&sc->wl_if, "entered wlconfig()\n");
2089 #endif
2090     outw(PIOR0(base), OFFSET_SCB);
2091     if (inw(PIOP0(base)) & SCB_SW_INT) {
2092         /*
2093           if_printf(&sc->wl_if, "config(): unexpected initial state %x\n",
2094           inw(PIOP0(base)));
2095           */
2096     }
2097     wlack(sc);
2098
2099     outw(PIOR1(base), OFFSET_CU);
2100     outw(PIOP1(base), 0);                               /* ac_status */
2101     outw(PIOP1(base), AC_CONFIGURE|AC_CW_EL);   /* ac_command */
2102
2103 /* jrb hack */
2104     configure.fifolim_bytecnt   = 0x080c;
2105     configure.addrlen_mode      = 0x0600;
2106     configure.linprio_interframe        = 0x2060;
2107     configure.slot_time         = 0xf200;
2108     configure.hardware          = 0x0008;       /* tx even w/o CD */
2109     configure.min_frame_len     = 0x0040;
2110 #if 0
2111     /* This is the configuration block suggested by Marc Meertens
2112      * <mmeerten@obelix.utrecht.NCR.COM> in an e-mail message to John
2113      * Ioannidis on 10 Nov 92.
2114      */
2115     configure.fifolim_bytecnt   = 0x040c;
2116     configure.addrlen_mode      = 0x0600;
2117     configure.linprio_interframe        = 0x2060;
2118     configure.slot_time         = 0xf000;
2119     configure.hardware          = 0x0008;       /* tx even w/o CD */
2120     configure.min_frame_len     = 0x0040;
2121 #else
2122     /*
2123      * below is the default board configuration from p2-28 from 586 book
2124      */
2125     configure.fifolim_bytecnt   = 0x080c;
2126     configure.addrlen_mode      = 0x2600;
2127     configure.linprio_interframe        = 0x7820;       /* IFS=120, ACS=2 */
2128     configure.slot_time         = 0xf00c;       /* slottime=12    */
2129     configure.hardware          = 0x0008;       /* tx even w/o CD */
2130     configure.min_frame_len     = 0x0040;
2131 #endif
2132     if(sc->mode & (MOD_PROM | MOD_ENAL)) {
2133         configure.hardware |= 1;
2134     }
2135     outw(PIOR1(base), OFFSET_CU + 6);
2136     outsw(PIOP1(base), &configure, sizeof(configure_t)/2);
2137
2138     if(wlcmd(sc, "config()-configure") == 0)
2139         return 0;
2140 #if     MULTICAST
2141     outw(PIOR1(base), OFFSET_CU);
2142     outw(PIOP1(base), 0);                               /* ac_status */
2143     outw(PIOP1(base), AC_MCSETUP|AC_CW_EL);             /* ac_command */
2144     outw(PIOR1(base), OFFSET_CU + 8);
2145 #if defined(__DragonFly__) || (defined(__FreeBSD__) && __FreeBSD_version >= 300000)
2146     LIST_FOREACH(ifma, &sc->wl_if.if_multiaddrs, ifma_link) {
2147         if (ifma->ifma_addr->sa_family != AF_LINK)
2148             continue;
2149         
2150         addrp = LLADDR((struct sockaddr_dl *)ifma->ifma_addr);
2151         outw(PIOP1(base), addrp[0] + (addrp[1] << 8));
2152         outw(PIOP1(base), addrp[2] + (addrp[3] << 8));
2153         outw(PIOP1(base), addrp[4] + (addrp[5] << 8));
2154         ++cnt;
2155     }
2156 #else
2157     ETHER_FIRST_MULTI(step, &sc->wl_ac, enm);
2158     while (enm != NULL) {
2159         unsigned int lo, hi;
2160         /* break if setting a multicast range, else we would crash */
2161         if (bcmp(enm->enm_addrlo, enm->enm_addrhi, 6) != 0) {
2162                 break;
2163         }
2164         lo = (enm->enm_addrlo[3] << 16) + (enm->enm_addrlo[4] << 8)
2165             + enm->enm_addrlo[5];
2166         hi = (enm->enm_addrhi[3] << 16) + (enm->enm_addrhi[4] << 8)
2167             + enm->enm_addrhi[5];
2168         while(lo <= hi) {
2169             outw(PIOP1(base),enm->enm_addrlo[0] +
2170                  (enm->enm_addrlo[1] << 8));
2171             outw(PIOP1(base),enm->enm_addrlo[2] +
2172                  ((lo >> 8) & 0xff00));
2173             outw(PIOP1(base), ((lo >> 8) & 0xff) +
2174                  ((lo << 8) & 0xff00));
2175 /* #define MCASTDEBUG */
2176 #ifdef MCASTDEBUG
2177 printf("mcast_addr[%d,%d,%d] %x %x %x %x %x %x\n", lo, hi, cnt,
2178                 enm->enm_addrlo[0],
2179                 enm->enm_addrlo[1],
2180                 enm->enm_addrlo[2],
2181                 enm->enm_addrlo[3],
2182                 enm->enm_addrlo[4],
2183                 enm->enm_addrlo[5]);
2184 #endif
2185             ++cnt;
2186             ++lo;
2187         }
2188         ETHER_NEXT_MULTI(step, enm);
2189     }
2190 #endif
2191     outw(PIOR1(base), OFFSET_CU + 6);           /* mc-cnt */
2192     outw(PIOP1(base), cnt * WAVELAN_ADDR_SIZE);
2193     if(wlcmd(sc, "config()-mcaddress") == 0)
2194         return 0;
2195 #endif  /* MULTICAST */
2196
2197     outw(PIOR1(base), OFFSET_CU);
2198     outw(PIOP1(base), 0);                               /* ac_status */
2199     outw(PIOP1(base), AC_IASETUP|AC_CW_EL);             /* ac_command */
2200     outw(PIOR1(base), OFFSET_CU + 6);
2201     outsw(PIOP1(base), sc->wl_addr, WAVELAN_ADDR_SIZE/2);
2202
2203     if(wlcmd(sc, "config()-address") == 0)
2204         return(0);
2205
2206     wlinitmmc(sc);
2207
2208     return(1);
2209 }
2210
2211 /*
2212  * wlcmd:
2213  *
2214  * Set channel attention bit and busy wait until command has
2215  * completed. Then acknowledge the command completion.
2216  */
2217 static int
2218 wlcmd(struct wl_softc *sc, const char *str)
2219 {
2220     short base = sc->base;
2221     int i;
2222         
2223     outw(PIOR0(base), OFFSET_SCB + 2);  /* address of scb_command */
2224     outw(PIOP0(base), SCB_CU_STRT);
2225     
2226     SET_CHAN_ATTN(sc);
2227     
2228     outw(PIOR0(base), OFFSET_CU);
2229     for(i = 0; i < 0xffff; i++)
2230         if (inw(PIOP0(base)) & AC_SW_C)
2231             break;
2232     if (i == 0xffff || !(inw(PIOP0(base)) & AC_SW_OK)) {
2233         if_printf(&sc->wl_if, "%s failed; status = %d, inw = %x, outw = %x\n",
2234                   str, inw(PIOP0(base)) & AC_SW_OK, inw(PIOP0(base)),
2235                   inw(PIOR0(base)));
2236         outw(PIOR0(base), OFFSET_SCB);
2237         printf("scb_status %x\n", inw(PIOP0(base)));
2238         outw(PIOR0(base), OFFSET_SCB+2);
2239         printf("scb_command %x\n", inw(PIOP0(base)));
2240         outw(PIOR0(base), OFFSET_SCB+4);
2241         printf("scb_cbl %x\n", inw(PIOP0(base)));
2242         outw(PIOR0(base), OFFSET_CU+2);
2243         printf("cu_cmd %x\n", inw(PIOP0(base)));
2244         return(0);
2245     }
2246
2247     outw(PIOR0(base), OFFSET_SCB);
2248     if ((inw(PIOP0(base)) & SCB_SW_INT) && (inw(PIOP0(base)) != SCB_SW_CNA)) {
2249         /*
2250           if_printf(&sc->wl_if, "%s: unexpected final state %x\n",
2251           str, inw(PIOP0(base)));
2252           */
2253     }
2254     wlack(sc);
2255     return(TRUE);
2256 }       
2257
2258 /*
2259  * wlack: if the 82596 wants attention because it has finished
2260  * sending or receiving a packet, acknowledge its desire and
2261  * return bits indicating the kind of attention. wlack() returns
2262  * these bits so that the caller can service exactly the
2263  * conditions that wlack() acknowledged.
2264  */
2265 static int
2266 wlack(struct wl_softc *sc)
2267 {
2268     int i;
2269     u_short cmd;
2270     short base = sc->base;
2271
2272     outw(PIOR1(base), OFFSET_SCB);
2273     if(!(cmd = (inw(PIOP1(base)) & SCB_SW_INT)))
2274         return(0);
2275 #ifdef WLDEBUG
2276     if (sc->wl_if.if_flags & IFF_DEBUG)
2277         if_printf(&sc->wl_if, "doing a wlack()\n");
2278 #endif
2279     outw(PIOP1(base), cmd);
2280     SET_CHAN_ATTN(sc);
2281     outw(PIOR0(base), OFFSET_SCB + 2);  /* address of scb_command */
2282     for (i = 1000000; inw(PIOP0(base)) && (i-- > 0); );
2283     if (i < 1)
2284         if_printf(&sc->wl_if, "wlack(): board not accepting command.\n");
2285     return(cmd);
2286 }
2287
2288 static void
2289 wltbd(struct wl_softc *sc)
2290 {
2291     short               base = sc->base;
2292     u_short             tbd_p = OFFSET_TBD;
2293     tbd_t               tbd;
2294     int                 i = 0;
2295     int                 sum = 0;
2296
2297     for (;;) {
2298         outw(PIOR1(base), tbd_p);
2299         insw(PIOP1(base), &tbd, sizeof(tbd_t)/2);
2300         sum += (tbd.act_count & ~TBD_SW_EOF);
2301         printf("%d: addr %x, count %d (%d), next %x, base %x\n",
2302                i++, tbd.buffer_addr,
2303                (tbd.act_count & ~TBD_SW_EOF), sum,
2304                tbd.next_tbd_offset, tbd.buffer_base);
2305         if (tbd.act_count & TBD_SW_EOF)
2306             break;
2307         tbd_p = tbd.next_tbd_offset;
2308     }
2309 }
2310
2311 static void
2312 wlhdwsleaze(u_short *countp, u_char **mb_pp, struct mbuf **tm_pp)
2313 {
2314     struct mbuf *tm_p = *tm_pp;
2315     u_char              *mb_p = *mb_pp;
2316     u_short             count = 0;
2317     u_char              *cp;
2318     int         len;
2319
2320     /*
2321      * can we get a run that will be coallesced or
2322      * that terminates before breaking
2323      */
2324     do {
2325         count += tm_p->m_len;
2326         if (tm_p->m_len & 1)
2327             break;
2328     } while ((tm_p = tm_p->m_next) != (struct mbuf *)0);
2329     if ( (tm_p == (struct mbuf *)0) ||
2330          count > HDW_THRESHOLD) {
2331         *countp = (*tm_pp)->m_len;
2332         *mb_pp = mtod((*tm_pp), u_char *);
2333         return;
2334     }
2335
2336     /* we need to copy */
2337     tm_p = *tm_pp;
2338     mb_p = *mb_pp;
2339     count = 0;
2340     cp = (u_char *) t_packet;
2341     for (;;) {
2342         bcopy(mtod(tm_p, u_char *), cp, len = tm_p->m_len);
2343         count += len;
2344         if (count > HDW_THRESHOLD)
2345                         break;
2346         cp += len;
2347         if (tm_p->m_next == (struct mbuf *)0)
2348             break;
2349         tm_p = tm_p->m_next;
2350     }
2351     *countp = count;
2352     *mb_pp = (u_char *) t_packet;
2353     *tm_pp = tm_p;
2354 }
2355
2356 static void
2357 wlsftwsleaze(u_short *countp, u_char **mb_pp, struct mbuf **tm_pp)
2358 {
2359     struct mbuf *tm_p = *tm_pp;
2360     u_short             count = 0;
2361     u_char              *cp = (u_char *) t_packet;
2362     int                 len;
2363
2364     /* we need to copy */
2365     for (;;) {
2366         bcopy(mtod(tm_p, u_char *), cp, len = tm_p->m_len);
2367         count += len;
2368         cp += len;
2369         if (tm_p->m_next == (struct mbuf *)0)
2370             break;
2371         tm_p = tm_p->m_next;
2372     }
2373
2374     *countp = count;
2375     *mb_pp = (u_char *) t_packet;
2376     *tm_pp = tm_p;
2377 }
2378
2379 static void
2380 wlmmcstat(struct wl_softc *sc)
2381 {
2382     short       base = sc->base;
2383     u_short tmp;
2384
2385     if_printf(&sc->wl_if, "DCE_STATUS: 0x%x, ",
2386               wlmmcread(base,MMC_DCE_STATUS) & 0x0f);
2387     tmp = wlmmcread(base,MMC_CORRECT_NWID_H) << 8;
2388     tmp |= wlmmcread(base,MMC_CORRECT_NWID_L);
2389     printf("Correct NWID's: %d, ", tmp);
2390     tmp = wlmmcread(base,MMC_WRONG_NWID_H) << 8;
2391     tmp |= wlmmcread(base,MMC_WRONG_NWID_L);
2392     printf("Wrong NWID's: %d\n", tmp);
2393     printf("THR_PRE_SET: 0x%x, ", wlmmcread(base,MMC_THR_PRE_SET));
2394     printf("SIGNAL_LVL: %d, SILENCE_LVL: %d\n", 
2395            wlmmcread(base,MMC_SIGNAL_LVL),
2396            wlmmcread(base,MMC_SILENCE_LVL));
2397     printf("SIGN_QUAL: 0x%x, NETW_ID: %x:%x, DES: %d\n",
2398            wlmmcread(base,MMC_SIGN_QUAL),
2399            wlmmcread(base,MMC_NETW_ID_H),
2400            wlmmcread(base,MMC_NETW_ID_L),
2401            wlmmcread(base,MMC_DES_AVAIL));
2402 }
2403
2404 static u_short
2405 wlmmcread(u_int base, u_short reg)
2406 {
2407     while(inw(HASR(base)) & HASR_MMC_BUSY) ;
2408     outw(MMCR(base),reg << 1);
2409     while(inw(HASR(base)) & HASR_MMC_BUSY) ;
2410     return (u_short)inw(MMCR(base)) >> 8;
2411 }
2412
2413 static void
2414 getsnr(struct wl_softc *sc)
2415 {
2416     MMC_WRITE(MMC_FREEZE,1);
2417     /* 
2418      * SNR retrieval procedure :
2419      *
2420      * read signal level : wlmmcread(base, MMC_SIGNAL_LVL);
2421      * read silence level : wlmmcread(base, MMC_SILENCE_LVL);
2422      */
2423     MMC_WRITE(MMC_FREEZE,0);
2424     /*
2425      * SNR is signal:silence ratio.
2426      */
2427 }
2428
2429 /*
2430 ** wlgetpsa
2431 **
2432 ** Reads the psa for the wavelan at (base) into (buf)
2433 */
2434 static void
2435 wlgetpsa(int base, u_char *buf)
2436 {
2437     int i;
2438
2439     PCMD(base, HACR_DEFAULT & ~HACR_16BITS);
2440     PCMD(base, HACR_DEFAULT & ~HACR_16BITS);
2441
2442     for (i = 0; i < 0x40; i++) {
2443         outw(PIOR2(base), i);
2444         buf[i] = inb(PIOP2(base));
2445     }
2446     PCMD(base, HACR_DEFAULT);
2447     PCMD(base, HACR_DEFAULT);
2448 }
2449
2450 /*
2451 ** wlsetpsa
2452 **
2453 ** Writes the psa for wavelan (unit) from the softc back to the
2454 ** board.  Updates the CRC and sets the CRC OK flag.
2455 **
2456 ** Do not call this when the board is operating, as it doesn't 
2457 ** preserve the hacr.
2458 */
2459 static void
2460 wlsetpsa(struct wl_softc *sc)
2461 {
2462     short       base = sc->base;
2463     int         i;
2464     u_short     crc;
2465
2466     crc = wlpsacrc(sc->psa);    /* calculate CRC of PSA */
2467     sc->psa[WLPSA_CRCLOW] = crc & 0xff;
2468     sc->psa[WLPSA_CRCHIGH] = (crc >> 8) & 0xff;
2469     sc->psa[WLPSA_CRCOK] = 0x55;        /* default to 'bad' until programming complete */
2470
2471     PCMD(base, HACR_DEFAULT & ~HACR_16BITS);
2472     PCMD(base, HACR_DEFAULT & ~HACR_16BITS);
2473     
2474     for (i = 0; i < 0x40; i++) {
2475         DELAY(DELAYCONST);
2476         outw(PIOR2(base),i);  /* write param memory */
2477         DELAY(DELAYCONST);
2478         outb(PIOP2(base), sc->psa[i]);
2479     }
2480     DELAY(DELAYCONST);
2481     outw(PIOR2(base),WLPSA_CRCOK);  /* update CRC flag*/
2482     DELAY(DELAYCONST);
2483     sc->psa[WLPSA_CRCOK] = 0xaa;        /* OK now */
2484     outb(PIOP2(base), 0xaa);    /* all OK */
2485     DELAY(DELAYCONST);
2486     
2487     PCMD(base, HACR_DEFAULT);
2488     PCMD(base, HACR_DEFAULT);
2489 }
2490
2491 /* 
2492 ** CRC routine provided by Christopher Giordano <cgiordan@gdeb.com>,
2493 ** from original code by Tomi Mikkonen (tomitm@remedy.fi)
2494 */
2495
2496 static u_int crc16_table[16] = { 
2497     0x0000, 0xCC01, 0xD801, 0x1400,
2498     0xF001, 0x3C00, 0x2800, 0xE401,
2499     0xA001, 0x6C00, 0x7800, 0xB401,
2500     0x5000, 0x9C01, 0x8801, 0x4400 
2501 };
2502
2503 static u_short
2504 wlpsacrc(u_char *buf)
2505 {
2506     u_short     crc = 0;
2507     int         i, r1;
2508     
2509     for (i = 0; i < 0x3d; i++, buf++) {
2510         /* lower 4 bits */
2511         r1 = crc16_table[crc & 0xF];
2512         crc = (crc >> 4) & 0x0FFF;
2513         crc = crc ^ r1 ^ crc16_table[*buf & 0xF];
2514         
2515         /* upper 4 bits */
2516         r1 = crc16_table[crc & 0xF];
2517         crc = (crc >> 4) & 0x0FFF;
2518         crc = crc ^ r1 ^ crc16_table[(*buf >> 4) & 0xF];
2519     }
2520     return(crc);
2521 }
2522 #ifdef WLCACHE
2523
2524 /*
2525  * wl_cache_store
2526  *
2527  * take input packet and cache various radio hw characteristics
2528  * indexed by MAC address.
2529  *
2530  * Some things to think about:
2531  *      note that no space is malloced. 
2532  *      We might hash the mac address if the cache were bigger.
2533  *      It is not clear that the cache is big enough.
2534  *              It is also not clear how big it should be.
2535  *      The cache is IP-specific.  We don't care about that as
2536  *              we want it to be IP-specific.
2537  *      The last N recv. packets are saved.  This will tend
2538  *              to reward agents and mobile hosts that beacon.
2539  *              That is probably fine for mobile ip.
2540  */
2541
2542 /* globals for wavelan signal strength cache */
2543 /* this should go into softc structure above. 
2544 */
2545
2546 /* set true if you want to limit cache items to broadcast/mcast 
2547  * only packets (not unicast)
2548  */
2549 static int wl_cache_mcastonly = 1;
2550 SYSCTL_INT(_machdep, OID_AUTO, wl_cache_mcastonly, CTLFLAG_RW, 
2551         &wl_cache_mcastonly, 0, "");
2552
2553 /* set true if you want to limit cache items to IP packets only
2554 */
2555 static int wl_cache_iponly = 1;
2556 SYSCTL_INT(_machdep, OID_AUTO, wl_cache_iponly, CTLFLAG_RW, 
2557         &wl_cache_iponly, 0, "");
2558
2559 /* zero out the cache
2560 */
2561 static void
2562 wl_cache_zero(struct wl_softc *sc)
2563 {
2564         bzero(&sc->w_sigcache[0], sizeof(struct w_sigcache) * MAXCACHEITEMS);
2565         sc->w_sigitems = 0;
2566         sc->w_nextcache = 0;
2567         sc->w_wrapindex = 0;
2568 }
2569
2570 /* store hw signal info in cache.
2571  * index is MAC address, but an ip src gets stored too
2572  * There are two filters here controllable via sysctl:
2573  *      throw out unicast (on by default, but can be turned off)
2574  *      throw out non-ip (on by default, but can be turned off)
2575  */
2576 static
2577 void wl_cache_store (struct wl_softc *sc, int base, struct ether_header *eh,
2578                      struct mbuf *m)
2579 {
2580         struct ip *ip = NULL;   /* Avoid GCC warning */
2581         int i;
2582         int signal, silence;
2583         int w_insertcache;   /* computed index for cache entry storage */
2584         int ipflag = wl_cache_iponly;
2585
2586         /* filters:
2587          * 1. ip only
2588          * 2. configurable filter to throw out unicast packets,
2589          * keep multicast only.
2590          */
2591  
2592 #ifdef INET
2593         /* reject if not IP packet
2594         */
2595         if ( wl_cache_iponly && (ntohs(eh->ether_type) != 0x800)) {
2596                 return;
2597         }
2598
2599         /* check if broadcast or multicast packet.  we toss
2600          * unicast packets
2601          */
2602         if (wl_cache_mcastonly && ((eh->ether_dhost[0] & 1) == 0)) {
2603                 return;
2604         }
2605
2606         /* find the ip header.  we want to store the ip_src
2607          * address.  use the mtod macro(in mbuf.h) 
2608          * to typecast m to struct ip *
2609          */
2610         if (ipflag) {
2611                 ip = mtod(m, struct ip *);
2612         }
2613         
2614         /* do a linear search for a matching MAC address 
2615          * in the cache table
2616          * . MAC address is 6 bytes,
2617          * . var w_nextcache holds total number of entries already cached
2618          */
2619         for(i = 0; i < sc->w_nextcache; i++) {
2620                 if (! bcmp(eh->ether_shost, sc->w_sigcache[i].macsrc,  6 )) {
2621                         /* Match!,
2622                          * so we already have this entry,
2623                          * update the data, and LRU age
2624                          */
2625                         break;  
2626                 }
2627         }
2628
2629         /* did we find a matching mac address?
2630          * if yes, then overwrite a previously existing cache entry
2631          */
2632         if (i <  sc->w_nextcache )   {
2633                 w_insertcache = i; 
2634         }
2635         /* else, have a new address entry,so
2636          * add this new entry,
2637          * if table full, then we need to replace entry
2638          */
2639         else    {                          
2640
2641                 /* check for space in cache table 
2642                  * note: w_nextcache also holds number of entries
2643                  * added in the cache table 
2644                  */
2645                 if ( sc->w_nextcache < MAXCACHEITEMS ) {
2646                         w_insertcache = sc->w_nextcache;
2647                         sc->w_nextcache++;                 
2648                         sc->w_sigitems = sc->w_nextcache;
2649                 }
2650                 /* no space found, so simply wrap with wrap index
2651                  * and "zap" the next entry
2652                  */
2653                 else {
2654                         if (sc->w_wrapindex == MAXCACHEITEMS) {
2655                                 sc->w_wrapindex = 0;
2656                         }
2657                         w_insertcache = sc->w_wrapindex++;
2658                 }
2659         }
2660
2661         /* invariant: w_insertcache now points at some slot
2662          * in cache.
2663          */
2664         if (w_insertcache < 0 || w_insertcache >= MAXCACHEITEMS) {
2665                 log(LOG_ERR, 
2666                         "wl_cache_store, bad index: %d of [0..%d], gross cache error\n",
2667                         w_insertcache, MAXCACHEITEMS);
2668                 return;
2669         }
2670
2671         /*  store items in cache
2672          *  .ipsrc
2673          *  .macsrc
2674          *  .signal (0..63) ,silence (0..63) ,quality (0..15)
2675          */
2676         if (ipflag) {
2677                 sc->w_sigcache[w_insertcache].ipsrc = ip->ip_src.s_addr;
2678         }
2679         bcopy( eh->ether_shost, sc->w_sigcache[w_insertcache].macsrc,  6);
2680         signal = sc->w_sigcache[w_insertcache].signal  = wlmmcread(base, MMC_SIGNAL_LVL) & 0x3f;
2681         silence = sc->w_sigcache[w_insertcache].silence = wlmmcread(base, MMC_SILENCE_LVL) & 0x3f;
2682         sc->w_sigcache[w_insertcache].quality = wlmmcread(base, MMC_SIGN_QUAL) & 0x0f;
2683         if (signal > 0)
2684                 sc->w_sigcache[w_insertcache].snr = 
2685                         signal - silence;
2686         else
2687                 sc->w_sigcache[w_insertcache].snr = 0;
2688 #endif /* INET */
2689
2690 }
2691 #endif /* WLCACHE */
2692
2693 /*
2694  * determine if in all multicast mode or not
2695  * 
2696  * returns: 1 if IFF_ALLMULTI should be set
2697  *          else 0
2698  */
2699 #ifdef MULTICAST
2700
2701 #if defined(__FreeBSD__) && __FreeBSD_version < 300000  /* not required */
2702 static int
2703 check_allmulti(struct wl_softc *sc)
2704 {
2705     short  base = sc->base;
2706     struct ether_multi *enm;
2707     struct ether_multistep step;
2708
2709     ETHER_FIRST_MULTI(step, &sc->wl_ac, enm);
2710     while (enm != NULL) {
2711         unsigned int lo, hi;
2712 #ifdef MDEBUG
2713                 printf("enm_addrlo %x:%x:%x:%x:%x:%x\n", enm->enm_addrlo[0], enm->enm_addrlo[1],
2714                 enm->enm_addrlo[2], enm->enm_addrlo[3], enm->enm_addrlo[4],
2715                 enm->enm_addrlo[5]);
2716                 printf("enm_addrhi %x:%x:%x:%x:%x:%x\n", enm->enm_addrhi[0], enm->enm_addrhi[1],
2717                 enm->enm_addrhi[2], enm->enm_addrhi[3], enm->enm_addrhi[4],
2718                 enm->enm_addrhi[5]);
2719 #endif
2720         if (bcmp(enm->enm_addrlo, enm->enm_addrhi, 6) != 0) {
2721                 return(1);
2722         }
2723         ETHER_NEXT_MULTI(step, enm);
2724     }
2725     return(0);
2726 }
2727 #endif
2728 #endif