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