1 /* $NetBSD: if_cnw.c,v 1.15 2000/10/16 10:26:41 itojun Exp $ */
7 * Copyright (c) 1998 The NetBSD Foundation, Inc.
10 * This code is derived from software contributed to The NetBSD Foundation
11 * by Michael Eriksson.
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 * 3. All advertising materials mentioning features or use of this software
22 * must display the following acknowledgement:
23 * This product includes software developed by the NetBSD
24 * Foundation, Inc. and its contributors.
25 * 4. Neither the name of The NetBSD Foundation nor the names of its
26 * contributors may be used to endorse or promote products derived
27 * from this software without specific prior written permission.
29 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
30 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
31 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
32 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
33 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
34 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
35 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
36 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
37 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39 * POSSIBILITY OF SUCH DAMAGE.
43 * Copyright (c) 1996, 1997 Berkeley Software Design, Inc.
44 * All rights reserved.
46 * Redistribution and use in source and binary forms, with or without
47 * modification, are permitted provided that this notice is retained,
48 * the conditions in the following notices are met, and terms applying
49 * to contributors in the following notices also apply to Berkeley
50 * Software Design, Inc.
52 * 1. Redistributions of source code must retain the above copyright
53 * notice, this list of conditions and the following disclaimer.
54 * 2. Redistributions in binary form must reproduce the above copyright
55 * notice, this list of conditions and the following disclaimer in the
56 * documentation and/or other materials provided with the distribution.
57 * 3. All advertising materials mentioning features or use of this software
58 * must display the following acknowledgement:
59 * This product includes software developed by
60 * Berkeley Software Design, Inc.
61 * 4. Neither the name of the Berkeley Software Design, Inc. nor the names
62 * of its contributors may be used to endorse or promote products derived
63 * from this software without specific prior written permission.
65 * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN, INC. ``AS IS'' AND
66 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
67 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
68 * ARE DISCLAIMED. IN NO EVENT SHALL BERKELEY SOFTWARE DESIGN, INC. BE LIABLE
69 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
70 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
71 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
72 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
73 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
74 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
77 * Paul Borman, December 1996
79 * This driver is derived from a generic frame work which is
80 * Copyright(c) 1994,1995,1996
81 * Yoichi Shinoda, Yoshitaka Tokugawa, WIDE Project, Wildboar Project
82 * and Foretune. All rights reserved.
84 * A linux driver was used as the "hardware reference manual" (i.e.,
85 * to determine registers and a general outline of how the card works)
86 * That driver is publically available and copyright
88 * John Markus Bjørndalen
89 * Department of Computer Science
90 * University of Tromsø
92 * johnm@staff.cs.uit.no, http://www.cs.uit.no/~johnm/
96 * This is a driver for the Xircom CreditCard Netwave (also known as
97 * the Netwave Airsurfer) wireless LAN PCMCIA adapter.
99 * When this driver was developed, the Linux Netwave driver was used
100 * as a hardware manual. That driver is Copyright (c) 1997 University
101 * of Tromsø, Norway. It is part of the Linix pcmcia-cs package that
103 * http://hyper.stanford.edu/HyperNews/get/pcmcia/home.html. The most
104 * recent version of the pcmcia-cs package when this driver was
107 * Unfortunately, a lot of explicit numeric constants were used in the
108 * Linux driver. I have tried to use symbolic names whenever possible,
109 * but since I don't have any real hardware documentation, there's
110 * still one or two "magic numbers" :-(.
112 * Driver limitations: This driver doesn't do multicasting or receiver
113 * promiscuity, because of missing hardware documentation. I couldn't
114 * get receiver promiscuity to work, and I haven't even tried
115 * multicast. Volunteers are welcome, of course :-).
118 #if !defined(__FreeBSD__)
119 #include "opt_inet.h"
120 #include "bpfilter.h"
122 #include <sys/param.h>
123 #include <sys/systm.h>
124 #include <sys/device.h>
125 #include <sys/socket.h>
126 #include <sys/mbuf.h>
127 #include <sys/ioctl.h>
128 #include <sys/proc.h>
132 #include <dev/pcmcia/if_cnwreg.h>
133 #include <dev/pcmcia/if_cnwioctl.h>
135 #include <dev/pcmcia/pcmciareg.h>
136 #include <dev/pcmcia/pcmciavar.h>
137 #include <dev/pcmcia/pcmciadevs.h>
139 #include <net/if_dl.h>
140 #include <net/if_ether.h>
143 #include <netinet/in.h>
144 #include <netinet/in_systm.h>
145 #include <netinet/in_var.h>
146 #include <netinet/ip.h>
147 #include <netinet/if_inarp.h>
152 #include <net/bpfdesc.h>
156 * Let these be patchable variables, initialized from macros that can
157 * be set in the kernel config file. Someone with lots of spare time
158 * could probably write a nice Netwave configuration program to do
159 * this a little bit more elegantly :-).
162 #define CNW_DOMAIN 0x100
164 int cnw_domain = CNW_DOMAIN; /* Domain */
165 #ifndef CNW_SCRAMBLEKEY
166 #define CNW_SCRAMBLEKEY 0
168 int cnw_skey = CNW_SCRAMBLEKEY; /* Scramble key */
171 * The card appears to work much better when we only allow one packet
172 * "in the air" at a time. This is done by not allowing another packet
173 * on the card, even if there is room. Turning this off will allow the
174 * driver to stuff packets on the card as soon as a transmit buffer is
175 * available. This does increase the number of collisions, though.
176 * We can que a second packet if there are transmit buffers available,
177 * but we do not actually send the packet until the last packet has
180 #define ONE_AT_A_TIME
183 * Netwave cards choke if we try to use io memory address >= 0x400.
184 * Even though, CIS tuple does not talk about this.
185 * Use memory mapped access.
187 #define MEMORY_MAPPED
189 int cnw_match(struct device *, struct cfdata *, void *);
190 void cnw_attach(struct device *, struct device *, void *);
191 int cnw_detach(struct device *, int);
193 int cnw_activate(struct device *, enum devact);
196 struct device sc_dev; /* Device glue (must be first) */
197 struct ethercom sc_ethercom; /* Ethernet common part */
198 int sc_domain; /* Netwave domain */
199 int sc_skey; /* Netwave scramble key */
200 struct cnwstats sc_stats;
202 /* PCMCIA-specific stuff */
203 struct pcmcia_function *sc_pf; /* PCMCIA function */
204 #ifndef MEMORY_MAPPED
205 struct pcmcia_io_handle sc_pcioh; /* PCMCIA I/O space handle */
206 int sc_iowin; /* ...window */
207 bus_space_tag_t sc_iot; /* ...bus_space tag */
208 bus_space_handle_t sc_ioh; /* ...bus_space handle */
210 struct pcmcia_mem_handle sc_pcmemh; /* PCMCIA memory handle */
211 bus_addr_t sc_memoff; /* ...offset */
212 int sc_memwin; /* ...window */
213 bus_space_tag_t sc_memt; /* ...bus_space tag */
214 bus_space_handle_t sc_memh; /* ...bus_space handle */
215 void *sc_ih; /* Interrupt cookie */
216 struct timeval sc_txlast; /* When the last xmit was made */
217 int sc_active; /* Currently xmitting a packet */
219 int sc_resource; /* Resources alloc'ed on attach */
220 #define CNW_RES_PCIC 1
222 #define CNW_RES_MEM 4
223 #define CNW_RES_NET 8
226 struct cfattach cnw_ca = {
227 sizeof(struct cnw_softc), cnw_match, cnw_attach, cnw_detach,
233 #include <sys/param.h>
234 #include <sys/systm.h>
235 #include <sys/sockio.h>
236 #include <sys/mbuf.h>
237 #include <sys/malloc.h>
238 #include <sys/kernel.h>
239 #include <sys/proc.h>
240 #include <sys/ucred.h>
241 #include <sys/socket.h>
242 #include <sys/module.h>
244 #include <sys/syslog.h>
245 #include <sys/sysctl.h>
247 #include <machine/bus.h>
248 #include <machine/resource.h>
249 #include <machine/md_var.h>
250 #include <sys/rman.h>
253 #include <net/if_arp.h>
254 #include <net/ethernet.h>
255 #include <net/if_dl.h>
256 #include <net/if_media.h>
257 #include <net/if_types.h>
259 #include <netinet/in.h>
260 #include <netinet/in_systm.h>
261 #include <netinet/in_var.h>
262 #include <netinet/ip.h>
263 #include <netinet/if_ether.h>
267 #include <dev/pccard/pccardvar.h>
270 #include <dev/cnw/if_cnwioctl.h>
271 #include <dev/cnw/if_cnwreg.h>
274 #define CNW_DOMAIN 0x100
276 int cnw_domain = (int)CNW_DOMAIN; /* Domain */
278 #ifndef CNW_SCRAMBLEKEY
279 #define CNW_SCRAMBLEKEY 0
281 int cnw_skey = CNW_SCRAMBLEKEY; /* Scramble key */
283 #define ONE_AT_A_TIME
285 #ifndef MEMORY_MAPPED
286 #define MEMORY_MAPPED
290 struct ifnet *sc_ifp;
291 struct ifmedia ifmedia;
293 struct cnwstats sc_stats;
294 int sc_domain; /* Netwave domain */
295 int sc_skey; /* Netwave scramble key */
297 struct resource * mem_res;
298 struct resource * irq;
300 bus_addr_t sc_memoff; /* ...offset */
301 bus_space_tag_t sc_memt; /* ...bus_space tag */
302 bus_space_handle_t sc_memh; /* ...bus_space handle */
307 struct timeval sc_txlast; /* When the last xmit was made */
308 int sc_active; /* Currently xmitting a packet */
312 static void cnw_freebsd_init (void *);
313 static void cnw_stop (struct cnw_softc *);
315 static int cnw_pccard_probe (device_t);
316 static int cnw_pccard_attach (device_t);
317 static int cnw_pccard_detach (device_t);
318 static void cnw_shutdown (device_t);
319 static int cnw_alloc (device_t);
320 static void cnw_free (device_t);
322 static device_method_t cnw_pccard_methods[] = {
323 /* Device interface */
324 DEVMETHOD(device_probe, cnw_pccard_probe),
325 DEVMETHOD(device_attach, cnw_pccard_attach),
326 DEVMETHOD(device_detach, cnw_pccard_detach),
327 DEVMETHOD(device_shutdown, cnw_shutdown),
332 static driver_t cnw_pccard_driver = {
335 sizeof(struct cnw_softc)
338 static devclass_t cnw_pccard_devclass;
340 DRIVER_MODULE(cnw, pccard, cnw_pccard_driver, cnw_pccard_devclass, 0, 0);
341 MODULE_DEPEND(cnw, ether, 1, 1, 1);
343 #endif /* !defined(__FreeBSD__) */
345 void cnw_reset(struct cnw_softc *);
346 void cnw_init(struct cnw_softc *);
347 #if !defined(__FreeBSD__)
348 int cnw_enable(struct cnw_softc *sc);
349 void cnw_disable(struct cnw_softc *sc);
350 void cnw_config(struct cnw_softc *sc, u_int8_t *);
352 void cnw_start(struct ifnet *);
353 void cnw_transmit(struct cnw_softc *, struct mbuf *);
354 struct mbuf *cnw_read(struct cnw_softc *);
355 void cnw_recv(struct cnw_softc *);
356 #if !defined(__FreeBSD__)
357 int cnw_intr(void *arg);
359 void cnw_intr(void *arg);
361 int cnw_ioctl(struct ifnet *, u_long, caddr_t);
362 void cnw_watchdog(struct ifnet *);
363 static int cnw_setdomain(struct cnw_softc *, int);
364 static int cnw_setkey(struct cnw_softc *, int);
366 /* ---------------------------------------------------------------- */
369 static int wait_WOC(struct cnw_softc *, int);
370 static int read16(struct cnw_softc *, int);
371 static int cnw_cmd(struct cnw_softc *, int, int, int, int);
374 * Wait until the WOC (Write Operation Complete) bit in the
375 * ASR (Adapter Status Register) is asserted.
379 struct cnw_softc *sc;
384 for (i = 0; i < 5000; i++) {
385 #ifndef MEMORY_MAPPED
386 asr = bus_space_read_1(sc->sc_iot, sc->sc_ioh, CNW_REG_ASR);
388 asr = bus_space_read_1(sc->sc_memt, sc->sc_memh,
389 sc->sc_memoff + CNW_IOM_OFF + CNW_REG_ASR);
391 if (asr & CNW_ASR_WOC)
396 #if !defined(__FreeBSD__)
397 printf("%s: wedged at line %d\n", sc->sc_dev.dv_xname, line);
399 device_printf(sc->dev, "wedged at line %d\n", line);
403 #define WAIT_WOC(sc) wait_WOC(sc, __LINE__)
407 * Read a 16 bit value from the card.
411 struct cnw_softc *sc;
415 int offs = sc->sc_memoff + offset;
417 /* This could presumably be done more efficient with
418 * bus_space_read_2(), but I don't know anything about the
419 * byte sex guarantees... Besides, this is pretty cheap as
422 lo = bus_space_read_1(sc->sc_memt, sc->sc_memh, offs);
423 hi = bus_space_read_1(sc->sc_memt, sc->sc_memh, offs + 1);
424 return ((hi << 8) | lo);
429 * Send a command to the card by writing it to the command buffer.
432 cnw_cmd(sc, cmd, count, arg1, arg2)
433 struct cnw_softc *sc;
434 int cmd, count, arg1, arg2;
436 int ptr = sc->sc_memoff + CNW_EREG_CB;
438 if (wait_WOC(sc, 0)) {
439 #if !defined(__FreeBSD__)
440 printf("%s: wedged when issuing cmd 0x%x\n",
441 sc->sc_dev.dv_xname, cmd);
443 device_printf(sc->dev, "wedged when issuing cmd 0x%x\n", cmd);
446 * We'll continue anyway, as that's probably the best
447 * thing we can do; at least the user knows there's a
448 * problem, and can reset the interface with ifconfig
453 bus_space_write_1(sc->sc_memt, sc->sc_memh, ptr, cmd);
455 bus_space_write_1(sc->sc_memt, sc->sc_memh, ptr + 1, arg1);
457 bus_space_write_1(sc->sc_memt, sc->sc_memh,
460 bus_space_write_1(sc->sc_memt, sc->sc_memh,
461 ptr + count + 1, CNW_CMD_EOC);
464 #define CNW_CMD0(sc, cmd) \
465 do { cnw_cmd(sc, cmd, 0, 0, 0); } while (0)
466 #define CNW_CMD1(sc, cmd, arg1) \
467 do { cnw_cmd(sc, cmd, 1, arg1 , 0); } while (0)
468 #define CNW_CMD2(sc, cmd, arg1, arg2) \
469 do { cnw_cmd(sc, cmd, 2, arg1, arg2); } while (0)
471 /* ---------------------------------------------------------------- */
474 * Reset the hardware.
478 struct cnw_softc *sc;
481 if (sc->sc_ethercom.ec_if.if_flags & IFF_DEBUG)
482 printf("%s: resetting\n", sc->sc_dev.dv_xname);
485 #ifndef MEMORY_MAPPED
486 bus_space_write_1(sc->sc_iot, sc->sc_ioh, CNW_REG_PMR, CNW_PMR_RESET);
488 bus_space_write_1(sc->sc_memt, sc->sc_memh,
489 sc->sc_memoff + CNW_IOM_OFF + CNW_REG_PMR, CNW_PMR_RESET);
491 bus_space_write_1(sc->sc_memt, sc->sc_memh,
492 sc->sc_memoff + CNW_EREG_ASCC, CNW_ASR_WOC);
493 #ifndef MEMORY_MAPPED
494 bus_space_write_1(sc->sc_iot, sc->sc_ioh, CNW_REG_PMR, 0);
496 bus_space_write_1(sc->sc_memt, sc->sc_memh,
497 sc->sc_memoff + CNW_IOM_OFF + CNW_REG_PMR, 0);
503 * Initialize the card.
507 struct cnw_softc *sc;
509 #if !defined(__FreeBSD__)
510 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
512 struct ifnet *ifp = sc->sc_ifp;
514 const u_int8_t rxmode =
515 CNW_RXCONF_RXENA | CNW_RXCONF_BCAST | CNW_RXCONF_AMP;
520 /* Issue a NOP to check the card */
521 CNW_CMD0(sc, CNW_CMD_NOP);
523 /* Set up receive configuration */
524 CNW_CMD1(sc, CNW_CMD_SRC,
525 rxmode | ((ifp->if_flags & IFF_PROMISC) ? CNW_RXCONF_PRO : 0));
527 /* Set up transmit configuration */
528 CNW_CMD1(sc, CNW_CMD_STC, CNW_TXCONF_TXENA);
531 CNW_CMD2(sc, CNW_CMD_SMD, sc->sc_domain, sc->sc_domain >> 8);
533 /* Set scramble key */
534 CNW_CMD2(sc, CNW_CMD_SSK, sc->sc_skey, sc->sc_skey >> 8);
536 /* Enable interrupts */
538 #ifndef MEMORY_MAPPED
539 bus_space_write_1(sc->sc_iot, sc->sc_ioh,
540 CNW_REG_IMR, CNW_IMR_IENA | CNW_IMR_RFU1);
542 bus_space_write_1(sc->sc_memt, sc->sc_memh,
543 sc->sc_memoff + CNW_IOM_OFF + CNW_REG_IMR,
544 CNW_IMR_IENA | CNW_IMR_RFU1);
547 /* Enable receiver */
548 CNW_CMD0(sc, CNW_CMD_ER);
550 /* "Set the IENA bit in COR" */
552 #ifndef MEMORY_MAPPED
553 bus_space_write_1(sc->sc_iot, sc->sc_ioh, CNW_REG_COR,
554 CNW_COR_IENA | CNW_COR_LVLREQ);
556 bus_space_write_1(sc->sc_memt, sc->sc_memh,
557 sc->sc_memoff + CNW_IOM_OFF + CNW_REG_COR,
558 CNW_COR_IENA | CNW_COR_LVLREQ);
563 #if !defined(__FreeBSD__)
565 * Enable and initialize the card.
569 struct cnw_softc *sc;
571 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
573 if ((ifp->if_flags & IFF_RUNNING) != 0)
576 sc->sc_ih = pcmcia_intr_establish(sc->sc_pf, IPL_NET, cnw_intr, sc);
577 if (sc->sc_ih == NULL) {
578 printf("%s: couldn't establish interrupt handler\n",
579 sc->sc_dev.dv_xname);
582 if (pcmcia_function_enable(sc->sc_pf) != 0) {
583 printf("%s: couldn't enable card\n", sc->sc_dev.dv_xname);
586 sc->sc_resource |= CNW_RES_PCIC;
588 ifp->if_flags &= ~IFF_OACTIVE;
589 ifp->if_flags |= IFF_RUNNING;
595 * Stop and disable the card.
599 struct cnw_softc *sc;
601 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
603 if ((ifp->if_flags & IFF_RUNNING) == 0)
606 pcmcia_function_disable(sc->sc_pf);
607 sc->sc_resource &= ~CNW_RES_PCIC;
608 pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih);
609 ifp->if_flags &= ~IFF_RUNNING;
614 * Match the hardware we handle.
617 cnw_match(parent, match, aux)
618 struct device *parent;
619 struct cfdata *match;
622 struct pcmcia_attach_args *pa = aux;
624 if (pa->manufacturer == PCMCIA_VENDOR_XIRCOM &&
625 pa->product == PCMCIA_PRODUCT_XIRCOM_CNW_801)
627 if (pa->manufacturer == PCMCIA_VENDOR_XIRCOM &&
628 pa->product == PCMCIA_PRODUCT_XIRCOM_CNW_802)
638 cnw_attach(parent, self, aux)
639 struct device *parent, *self;
642 struct cnw_softc *sc = (void *) self;
643 struct pcmcia_attach_args *pa = aux;
644 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
645 u_int8_t macaddr[ETHER_ADDR_LEN];
651 /* Enable the card */
653 pcmcia_function_init(sc->sc_pf, sc->sc_pf->cfe_head.sqh_first);
654 if (pcmcia_function_enable(sc->sc_pf)) {
655 printf(": function enable failed\n");
658 sc->sc_resource |= CNW_RES_PCIC;
660 /* Map I/O register and "memory" */
661 #ifndef MEMORY_MAPPED
662 if (pcmcia_io_alloc(sc->sc_pf, 0, CNW_IO_SIZE, CNW_IO_SIZE,
663 &sc->sc_pcioh) != 0) {
664 printf(": can't allocate i/o space\n");
667 if (pcmcia_io_map(sc->sc_pf, PCMCIA_WIDTH_IO16, 0,
668 CNW_IO_SIZE, &sc->sc_pcioh, &sc->sc_iowin) != 0) {
669 printf(": can't map i/o space\n");
670 pcmcia_io_free(sc->sc_pf, &sc->sc_pcioh);
673 sc->sc_iot = sc->sc_pcioh.iot;
674 sc->sc_ioh = sc->sc_pcioh.ioh;
675 sc->sc_resource |= CNW_RES_IO;
677 #ifndef MEMORY_MAPPED
678 memsize = CNW_MEM_SIZE;
680 memsize = CNW_MEM_SIZE + CNW_IOM_SIZE;
682 if (pcmcia_mem_alloc(sc->sc_pf, memsize, &sc->sc_pcmemh) != 0) {
683 printf(": can't allocate memory\n");
686 if (pcmcia_mem_map(sc->sc_pf, PCMCIA_WIDTH_MEM8|PCMCIA_MEM_COMMON,
687 CNW_MEM_ADDR, memsize, &sc->sc_pcmemh, &sc->sc_memoff,
688 &sc->sc_memwin) != 0) {
689 printf(": can't map memory\n");
690 pcmcia_mem_free(sc->sc_pf, &sc->sc_pcmemh);
693 sc->sc_memt = sc->sc_pcmemh.memt;
694 sc->sc_memh = sc->sc_pcmemh.memh;
695 sc->sc_resource |= CNW_RES_MEM;
696 switch (pa->product) {
697 case PCMCIA_PRODUCT_XIRCOM_CNW_801:
698 printf(": %s\n", PCMCIA_STR_XIRCOM_CNW_801);
700 case PCMCIA_PRODUCT_XIRCOM_CNW_802:
701 printf(": %s\n", PCMCIA_STR_XIRCOM_CNW_802);
705 /* Finish setup of softc */
706 sc->sc_domain = cnw_domain;
707 sc->sc_skey = cnw_skey;
709 /* Get MAC address */
711 for (i = 0; i < ETHER_ADDR_LEN; i++)
712 macaddr[i] = bus_space_read_1(sc->sc_memt, sc->sc_memh,
713 sc->sc_memoff + CNW_EREG_PA + i);
714 printf("%s: address %s\n", sc->sc_dev.dv_xname,
715 ether_sprintf(macaddr));
717 /* Set up ifnet structure */
718 bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
720 ifp->if_start = cnw_start;
721 ifp->if_ioctl = cnw_ioctl;
722 ifp->if_watchdog = cnw_watchdog;
723 ifp->if_flags = IFF_BROADCAST | IFF_MULTICAST | IFF_SIMPLEX |
726 /* Attach the interface */
728 ether_ifattach(ifp, macaddr);
730 bpfattach(&sc->sc_ethercom.ec_if.if_bpf, ifp, DLT_EN10MB,
731 sizeof(struct ether_header));
733 sc->sc_resource |= CNW_RES_NET;
735 ifp->if_baudrate = IF_Mbps(1);
737 /* Disable the card now, and turn it on when the interface goes up */
738 pcmcia_function_disable(sc->sc_pf);
739 sc->sc_resource &= ~CNW_RES_PCIC;
743 #ifndef MEMORY_MAPPED
744 if ((sc->sc_resource & CNW_RES_IO) != 0) {
745 pcmcia_io_unmap(sc->sc_pf, sc->sc_iowin);
746 pcmcia_io_free(sc->sc_pf, &sc->sc_pcioh);
747 sc->sc_resource &= ~CNW_RES_IO;
750 if ((sc->sc_resource & CNW_RES_PCIC) != 0) {
751 pcmcia_function_disable(sc->sc_pf);
752 sc->sc_resource &= ~CNW_RES_PCIC;
755 #endif /* !defined(__FreeBSD__) */
758 * Start outputting on the interface.
764 struct cnw_softc *sc = ifp->if_softc;
773 if (sc->sc_ethercom.ec_if.if_flags & IFF_DEBUG)
774 printf("%s: cnw_start\n", ifp->if_xname);
775 #if defined(__FreeBSD__)
776 if (ifp->if_drv_flags & IFF_DRV_OACTIVE)
778 if (ifp->if_flags & IFF_OACTIVE)
780 printf("%s: cnw_start reentered\n", ifp->if_xname);
783 #if defined(__FreeBSD__)
787 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
789 ifp->if_flags |= IFF_OACTIVE;
795 now.tv_sec -= sc->sc_txlast.tv_sec;
796 now.tv_usec -= sc->sc_txlast.tv_usec;
797 if (now.tv_usec < 0) {
798 now.tv_usec += 1000000;
803 * Don't ship this packet out until the last
804 * packet has left the building.
805 * If we have not tried to send a packet for 1/5
806 * a second then we assume we lost an interrupt,
807 * lets go on and send the next packet anyhow.
809 * I suppose we could check to see if it is okay
810 * to put additional packets on the card (beyond
811 * the one already waiting to be sent) but I don't
812 * think we would get any improvement in speed as
813 * we should have ample time to put the next packet
814 * on while this one is going out.
816 if (sc->sc_active && now.tv_sec == 0 && now.tv_usec < 200000)
820 /* Make sure the link integrity field is on */
822 lif = bus_space_read_1(sc->sc_memt, sc->sc_memh,
823 sc->sc_memoff + CNW_EREG_LIF);
826 if (sc->sc_ethercom.ec_if.if_flags & IFF_DEBUG)
827 printf("%s: link integrity %d\n", lif);
832 /* Is there any buffer space available on the card? */
834 #ifndef MEMORY_MAPPED
835 asr = bus_space_read_1(sc->sc_iot, sc->sc_ioh, CNW_REG_ASR);
837 asr = bus_space_read_1(sc->sc_memt, sc->sc_memh,
838 sc->sc_memoff + CNW_IOM_OFF + CNW_REG_ASR);
840 if (!(asr & CNW_ASR_TXBA)) {
842 if (sc->sc_ethercom.ec_if.if_flags & IFF_DEBUG)
843 printf("%s: no buffer space\n", ifp->if_xname);
848 sc->sc_stats.nws_tx++;
850 IF_DEQUEUE(&ifp->if_snd, m0);
854 #if !defined(__FreeBSD__)
857 bpf_mtap(ifp->if_bpf, m0);
863 cnw_transmit(sc, m0);
865 ifp->if_timer = 3; /* start watchdog timer */
867 microtime(&sc->sc_txlast);
871 #if defined(__FreeBSD__)
872 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
874 ifp->if_flags &= ~IFF_OACTIVE;
883 struct cnw_softc *sc;
886 int buffer, bufsize, bufoffset, bufptr, bufspace, len, mbytes, n;
889 /* Get buffer info from card */
890 buffer = read16(sc, CNW_EREG_TDP);
891 bufsize = read16(sc, CNW_EREG_TDP + 2);
892 bufoffset = read16(sc, CNW_EREG_TDP + 4);
894 if (sc->sc_ethercom.ec_if.if_flags & IFF_DEBUG)
895 printf("%s: cnw_transmit b=0x%x s=%d o=0x%x\n",
896 sc->sc_dev.dv_xname, buffer, bufsize, bufoffset);
899 /* Copy data from mbuf chain to card buffers */
900 bufptr = sc->sc_memoff + buffer + bufoffset;
904 mptr = mtod(m, u_int8_t *);
909 buffer = read16(sc, buffer);
910 bufptr = sc->sc_memoff + buffer + bufoffset;
913 if (sc->sc_ethercom.ec_if.if_flags & IFF_DEBUG)
914 printf("%s: next buffer @0x%x\n",
915 sc->sc_dev.dv_xname, buffer);
918 n = mbytes <= bufspace ? mbytes : bufspace;
919 bus_space_write_region_1(sc->sc_memt, sc->sc_memh,
929 /* Issue transmit command */
930 CNW_CMD2(sc, CNW_CMD_TL, len, len >> 8);
935 * Pull a packet from the card into an mbuf chain.
939 struct cnw_softc *sc;
941 struct mbuf *m, *top, **mp;
942 int totbytes, buffer, bufbytes, bufptr, mbytes, n;
946 totbytes = read16(sc, CNW_EREG_RDP);
948 if (sc->sc_ethercom.ec_if.if_flags & IFF_DEBUG)
949 printf("%s: recv %d bytes\n", sc->sc_dev.dv_xname, totbytes);
951 buffer = CNW_EREG_RDP + 2;
953 bufptr = 0; /* XXX make gcc happy */
955 MGETHDR(m, M_DONTWAIT, MT_DATA);
958 #if !defined(__FreeBSD__)
959 m->m_pkthdr.rcvif = &sc->sc_ethercom.ec_if;
961 m->m_pkthdr.rcvif = sc->sc_ifp;
963 m->m_pkthdr.len = totbytes;
968 while (totbytes > 0) {
970 MGET(m, M_DONTWAIT, MT_DATA);
977 if (totbytes >= MINCLSIZE) {
978 MCLGET(m, M_DONTWAIT);
979 if ((m->m_flags & M_EXT) == 0) {
987 int pad = ALIGN(sizeof(struct ether_header)) -
988 sizeof(struct ether_header);
992 mptr = mtod(m, u_int8_t *);
993 mbytes = m->m_len = min(totbytes, mbytes);
997 buffer = read16(sc, buffer);
998 bufbytes = read16(sc, buffer + 2);
999 bufptr = sc->sc_memoff + buffer +
1000 read16(sc, buffer + 4);
1002 if (sc->sc_ethercom.ec_if.if_flags & IFF_DEBUG)
1003 printf("%s: %d bytes @0x%x+0x%x\n",
1004 sc->sc_dev.dv_xname, bufbytes,
1005 buffer, bufptr - buffer -
1009 n = mbytes <= bufbytes ? mbytes : bufbytes;
1010 bus_space_read_region_1(sc->sc_memt, sc->sc_memh,
1026 * Handle received packets.
1030 struct cnw_softc *sc;
1033 #if !defined(__FreeBSD__)
1034 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1036 struct ifnet *ifp = sc->sc_ifp;
1042 rser = bus_space_read_1(sc->sc_memt, sc->sc_memh,
1043 sc->sc_memoff + CNW_EREG_RSER);
1044 if (!(rser & CNW_RSER_RXAVAIL))
1047 /* Pull packet off card */
1050 /* Acknowledge packet */
1051 CNW_CMD0(sc, CNW_CMD_SRP);
1053 /* Did we manage to get the packet from the interface? */
1060 #if !defined(__FreeBSD__)
1063 bpf_mtap(ifp->if_bpf, m);
1067 /* Pass the packet up. */
1068 (*ifp->if_input)(ifp, m);
1074 * Interrupt handler.
1076 #if !defined(__FreeBSD__)
1084 struct cnw_softc *sc = arg;
1085 #if !defined(__FreeBSD__)
1086 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1088 struct ifnet *ifp = sc->sc_ifp;
1090 int ret, status, rser, tser;
1093 #if !defined(__FreeBSD__)
1094 if ((sc->sc_ethercom.ec_if.if_flags & IFF_RUNNING) == 0 ||
1095 (sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
1098 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
1101 ifp->if_timer = 0; /* stop watchdog timer */
1106 #ifndef MEMORY_MAPPED
1107 status = bus_space_read_1(sc->sc_iot, sc->sc_ioh,
1110 status = bus_space_read_1(sc->sc_memt, sc->sc_memh,
1111 sc->sc_memoff + CNW_IOM_OFF + CNW_REG_CCSR);
1114 #if !defined(__FreeBSD__)
1115 if (!(status & 0x02)) {
1117 printf("%s: spurious interrupt\n",
1118 sc->sc_dev.dv_xname);
1122 if (!(status & 0x02)) {
1124 device_printf(sc->dev, "spurious interrupt\n");
1130 #ifndef MEMORY_MAPPED
1131 status = bus_space_read_1(sc->sc_iot, sc->sc_ioh, CNW_REG_ASR);
1133 status = bus_space_read_1(sc->sc_memt, sc->sc_memh,
1134 sc->sc_memoff + CNW_IOM_OFF + CNW_REG_ASR);
1137 /* Anything to receive? */
1138 if (status & CNW_ASR_RXRDY) {
1139 sc->sc_stats.nws_rx++;
1144 if (status & CNW_ASR_RXERR) {
1146 * I get a *lot* of spurious receive errors
1147 * (many per second), even when the interface
1148 * is quiescent, so we don't increment
1151 rser = bus_space_read_1(sc->sc_memt, sc->sc_memh,
1152 sc->sc_memoff + CNW_EREG_RSER);
1155 sc->sc_stats.nws_rxerr++;
1156 if (rser & CNW_RSER_RXBIG)
1157 sc->sc_stats.nws_rxframe++;
1158 if (rser & CNW_RSER_RXCRC)
1159 sc->sc_stats.nws_rxcrcerror++;
1160 if (rser & CNW_RSER_RXOVERRUN)
1161 sc->sc_stats.nws_rxoverrun++;
1162 if (rser & CNW_RSER_RXOVERFLOW)
1163 sc->sc_stats.nws_rxoverflow++;
1164 if (rser & CNW_RSER_RXERR)
1165 sc->sc_stats.nws_rxerrors++;
1166 if (rser & CNW_RSER_RXAVAIL)
1167 sc->sc_stats.nws_rxavail++;
1169 /* Clear error bits in RSER */
1171 bus_space_write_1(sc->sc_memt, sc->sc_memh,
1172 sc->sc_memoff + CNW_EREG_RSERW,
1174 (rser & (CNW_RSER_RXCRC | CNW_RSER_RXBIG)));
1175 /* Clear RXERR in ASR */
1177 bus_space_write_1(sc->sc_memt, sc->sc_memh,
1178 sc->sc_memoff + CNW_EREG_ASCC, CNW_ASR_RXERR);
1182 if (status & CNW_ASR_TXDN) {
1183 tser = bus_space_read_1(sc->sc_memt, sc->sc_memh,
1187 if (tser & CNW_TSER_TXERR)
1188 sc->sc_stats.nws_txerrors++;
1189 if (tser & CNW_TSER_TXNOAP)
1190 sc->sc_stats.nws_txlostcd++;
1191 if (tser & CNW_TSER_TXGU)
1192 sc->sc_stats.nws_txabort++;
1194 if (tser & CNW_TSER_TXOK) {
1195 sc->sc_stats.nws_txokay++;
1196 sc->sc_stats.nws_txretries[status & 0xf]++;
1198 bus_space_write_1(sc->sc_memt, sc->sc_memh,
1199 sc->sc_memoff + CNW_EREG_TSERW,
1200 CNW_TSER_TXOK | CNW_TSER_RTRY);
1203 if (tser & CNW_TSER_ERROR) {
1206 bus_space_write_1(sc->sc_memt, sc->sc_memh,
1207 sc->sc_memoff + CNW_EREG_TSERW,
1208 (tser & CNW_TSER_ERROR) |
1213 #if defined(__FreeBSD__)
1214 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1216 ifp->if_flags &= ~IFF_OACTIVE;
1219 /* Continue to send packets from the queue */
1220 #if !defined(__FreeBSD__)
1221 cnw_start(&sc->sc_ethercom.ec_if);
1232 * Handle device ioctls.
1235 cnw_ioctl(ifp, cmd, data)
1240 struct cnw_softc *sc = ifp->if_softc;
1241 #if !defined(__FreeBSD__)
1242 struct ifaddr *ifa = (struct ifaddr *)data;
1244 struct ifreq *ifr = (struct ifreq *)data;
1246 #if __FreeBSD__ >= 5
1247 struct thread *td = curthread; /* XXX */
1249 struct proc *td = curproc; /*XXX*/
1254 #if defined(__FreeBSD__)
1264 #if !defined(__FreeBSD__)
1265 if (!(ifp->if_flags & IFF_RUNNING) &&
1266 (error = cnw_enable(sc)) != 0)
1268 ifp->if_flags |= IFF_UP;
1269 switch (ifa->ifa_addr->sa_family) {
1273 arp_ifinit(&sc->sc_ethercom.ec_if, ifa);
1281 error = ether_ioctl(ifp, cmd, data);
1286 #if !defined(__FreeBSD__)
1287 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == IFF_RUNNING) {
1289 * The interface is marked down and it is running, so
1293 } else if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == IFF_UP){
1295 * The interface is marked up and it is stopped, so
1298 error = cnw_enable(sc);
1300 /* IFF_PROMISC may be changed */
1304 if (ifp->if_flags & IFF_UP) {
1305 cnw_freebsd_init(sc);
1307 if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
1310 cnw_freebsd_init(sc);
1319 #if !defined(__FreeBSD__)
1320 /* Update our multicast list. */
1321 error = (cmd == SIOCADDMULTI) ?
1322 ether_addmulti(ifr, &sc->sc_ethercom) :
1323 ether_delmulti(ifr, &sc->sc_ethercom);
1324 if (error == ENETRESET || error == 0) {
1334 case SIOCGCNWDOMAIN:
1335 ((struct ifreq *)data)->ifr_domain = sc->sc_domain;
1338 case SIOCSCNWDOMAIN:
1339 #if !defined(__FreeBSD__)
1340 error = suser(p->p_ucred, &p->p_acflag);
1346 error = cnw_setdomain(sc, ifr->ifr_domain);
1350 #if !defined(__FreeBSD__)
1351 error = suser(p->p_ucred, &p->p_acflag);
1357 error = cnw_setkey(sc, (int)ifr->ifr_key);
1360 case SIOCGCNWSTATUS:
1361 #if !defined(__FreeBSD__)
1362 error = suser(p->p_ucred, &p->p_acflag);
1368 #if !defined(__FreeBSD__)
1369 if ((ifp->if_flags & IFF_RUNNING) == 0)
1371 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
1374 bus_space_read_region_1(sc->sc_memt, sc->sc_memh,
1375 sc->sc_memoff + CNW_EREG_CB,
1376 ((struct cnwstatus *)data)->data,
1377 sizeof(((struct cnwstatus *)data)->data));
1381 bcopy((void *)&sc->sc_stats,
1382 (void *)&(((struct cnwistats *)data)->stats),
1383 sizeof(struct cnwstats));
1397 * Device timeout/watchdog routine. Entered if the device neglects to
1398 * generate an interrupt after a transmit has been started on it.
1404 struct cnw_softc *sc = ifp->if_softc;
1406 #if !defined(__FreeBSD__)
1407 printf("%s: device timeout; card reset\n", sc->sc_dev.dv_xname);
1411 device_printf(sc->dev, "device timeout; card reset\n");
1413 cnw_freebsd_init(sc);
1418 cnw_setdomain(sc, domain)
1419 struct cnw_softc *sc;
1424 if (domain & ~0x1ff)
1428 CNW_CMD2(sc, CNW_CMD_SMD, domain, domain >> 8);
1431 sc->sc_domain = domain;
1437 struct cnw_softc *sc;
1446 CNW_CMD2(sc, CNW_CMD_SSK, key, key >> 8);
1453 #if !defined(__FreeBSD__)
1455 cnw_activate(self, act)
1456 struct device *self;
1459 struct cnw_softc *sc = (struct cnw_softc *)self;
1464 case DVACT_ACTIVATE:
1468 case DVACT_DEACTIVATE:
1469 if_deactivate(&sc->sc_ethercom.ec_if);
1477 cnw_detach(self, flags)
1478 struct device *self;
1481 struct cnw_softc *sc = (struct cnw_softc *)self;
1482 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1484 /* cnw_disable() checks IFF_DRV_RUNNING */
1487 if ((sc->sc_resource & CNW_RES_NET) != 0) {
1491 ether_ifdetach(ifp);
1495 #ifndef MEMORY_MAPPED
1496 /* unmap and free our i/o windows */
1497 if ((sc->sc_resource & CNW_RES_IO) != 0) {
1498 pcmcia_io_unmap(sc->sc_pf, sc->sc_iowin);
1499 pcmcia_io_free(sc->sc_pf, &sc->sc_pcioh);
1503 /* unmap and free our memory windows */
1504 if ((sc->sc_resource & CNW_RES_MEM) != 0) {
1505 pcmcia_mem_unmap(sc->sc_pf, sc->sc_memwin);
1506 pcmcia_mem_free(sc->sc_pf, &sc->sc_pcmemh);
1513 #if defined(__FreeBSD__)
1514 static void cnw_freebsd_init(xsc)
1517 struct cnw_softc *sc = xsc;
1518 struct ifnet *ifp = sc->sc_ifp;
1528 if (ifp->if_drv_flags & IFF_DRV_RUNNING)
1532 ifp->if_drv_flags |= IFF_DRV_RUNNING;
1533 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1535 /* sc->cnw_stat_ch = timeout(cnw_inquire, sc, hz * 60); */
1544 static void cnw_stop(sc)
1545 struct cnw_softc *sc;
1555 ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
1560 static int cnw_pccard_probe(dev)
1563 struct cnw_softc *sc;
1566 sc = device_get_softc(dev);
1569 error = cnw_alloc(dev);
1573 device_set_desc(dev, "Netwave AirSurfer Wireless LAN");
1579 static int cnw_pccard_detach(dev)
1582 struct cnw_softc *sc;
1590 sc = device_get_softc(dev);
1594 device_printf(dev, "already unloaded\n");
1600 ether_ifdetach(ifp);
1611 static int cnw_pccard_attach(device_t dev)
1613 struct cnw_softc *sc;
1618 sc = device_get_softc(dev);
1619 ifp = sc->sc_ifp = if_alloc(IFT_ETHER);
1621 device_printf(dev, "if_alloc() failed\n");
1626 error = cnw_alloc(dev);
1628 device_printf(dev, "cnw_alloc() failed! (%d)\n", error);
1633 error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET,
1634 cnw_intr, sc, &sc->cnw_intrhand);
1637 device_printf(dev, "bus_setup_intr() failed! (%d)\n", error);
1643 /* Set initial values */
1644 sc->sc_domain = cnw_domain;
1645 sc->sc_skey = cnw_skey;
1647 /* Reset the NIC. */
1650 /* Get MAC address */
1651 for (i=0; i< ETHER_ADDR_LEN; i++) {
1652 eaddr[i] = bus_space_read_1(sc->sc_memt, sc->sc_memh,
1653 sc->sc_memoff + CNW_EREG_PA + i);
1657 if_initname(ifp, device_get_name(dev), device_get_unit(dev));
1659 ifp->if_mtu = ETHERMTU;
1660 ifp->if_flags = (IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST
1662 ifp->if_ioctl = cnw_ioctl;
1663 ifp->if_start = cnw_start;
1664 /* ifp->if_watchdog = 0; */
1665 ifp->if_watchdog = cnw_watchdog;
1666 ifp->if_init = cnw_freebsd_init;
1667 ifp->if_baudrate = 1 * 1000* 1000;
1668 ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
1670 cnw_freebsd_init(sc);
1674 * Call MI attach routine.
1676 ether_ifattach(ifp, eaddr);
1677 /* callout_handle_init(&sc->cnw_stat_ch); */
1682 static void cnw_shutdown(dev)
1685 struct cnw_softc *sc;
1687 sc = device_get_softc(dev);
1693 static int cnw_alloc(dev)
1696 struct cnw_softc *sc = device_get_softc(dev);
1701 sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
1704 device_printf(dev, "Cannot allocate attribute memory\n");
1707 sc->sc_memt = rman_get_bustag(sc->mem_res);
1708 sc->sc_memh = rman_get_bushandle(sc->mem_res);
1711 error = CARD_SET_MEMORY_OFFSET(device_get_parent(dev),
1712 dev, rid, CNW_MEM_ADDR, NULL);
1715 "CARD_SET_MEMORY_OFFSET returned 0x%0x", error);
1719 error = CARD_SET_RES_FLAGS(device_get_parent(dev), dev,
1720 SYS_RES_MEMORY, rid, PCCARD_A_MEM_8BIT);
1723 "CARD_SET_RES_FLAGS returned 0x%0x\n", error);
1728 sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
1730 device_printf(dev, "No irq?!\n");
1740 static void cnw_free(dev)
1743 struct cnw_softc *sc = device_get_softc(dev);
1745 if (sc->mem_res != NULL) {
1746 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
1749 if (sc->irq != NULL) {
1750 bus_teardown_intr(dev, sc->irq, sc->cnw_intrhand);
1751 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq);
1758 #endif /* FreeBSD */