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