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