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/clock.h>
250 #include <machine/md_var.h>
251 #include <sys/rman.h>
254 #include <net/if_arp.h>
255 #include <net/ethernet.h>
256 #include <net/if_dl.h>
257 #include <net/if_media.h>
258 #include <net/if_types.h>
260 #include <netinet/in.h>
261 #include <netinet/in_systm.h>
262 #include <netinet/in_var.h>
263 #include <netinet/ip.h>
264 #include <netinet/if_ether.h>
268 #include <dev/pccard/pccardvar.h>
271 #include <dev/cnw/if_cnwioctl.h>
272 #include <dev/cnw/if_cnwreg.h>
275 #define CNW_DOMAIN 0x100
277 int cnw_domain = (int)CNW_DOMAIN; /* Domain */
279 #ifndef CNW_SCRAMBLEKEY
280 #define CNW_SCRAMBLEKEY 0
282 int cnw_skey = CNW_SCRAMBLEKEY; /* Scramble key */
284 #define ONE_AT_A_TIME
286 #ifndef MEMORY_MAPPED
287 #define MEMORY_MAPPED
291 struct ifnet *sc_ifp;
292 struct ifmedia ifmedia;
294 struct cnwstats sc_stats;
295 int sc_domain; /* Netwave domain */
296 int sc_skey; /* Netwave scramble key */
298 struct resource * mem_res;
299 struct resource * irq;
301 bus_addr_t sc_memoff; /* ...offset */
302 bus_space_tag_t sc_memt; /* ...bus_space tag */
303 bus_space_handle_t sc_memh; /* ...bus_space handle */
308 struct timeval sc_txlast; /* When the last xmit was made */
309 int sc_active; /* Currently xmitting a packet */
313 static void cnw_freebsd_init (void *);
314 static void cnw_stop (struct cnw_softc *);
316 static int cnw_pccard_probe (device_t);
317 static int cnw_pccard_attach (device_t);
318 static int cnw_pccard_detach (device_t);
319 static void cnw_shutdown (device_t);
320 static int cnw_alloc (device_t);
321 static void cnw_free (device_t);
323 static device_method_t cnw_pccard_methods[] = {
324 /* Device interface */
325 DEVMETHOD(device_probe, cnw_pccard_probe),
326 DEVMETHOD(device_attach, cnw_pccard_attach),
327 DEVMETHOD(device_detach, cnw_pccard_detach),
328 DEVMETHOD(device_shutdown, cnw_shutdown),
333 static driver_t cnw_pccard_driver = {
336 sizeof(struct cnw_softc)
339 static devclass_t cnw_pccard_devclass;
341 DRIVER_MODULE(cnw, pccard, cnw_pccard_driver, cnw_pccard_devclass, 0, 0);
342 MODULE_DEPEND(cnw, ether, 1, 1, 1);
344 #endif /* !defined(__FreeBSD__) */
346 void cnw_reset(struct cnw_softc *);
347 void cnw_init(struct cnw_softc *);
348 #if !defined(__FreeBSD__)
349 int cnw_enable(struct cnw_softc *sc);
350 void cnw_disable(struct cnw_softc *sc);
351 void cnw_config(struct cnw_softc *sc, u_int8_t *);
353 void cnw_start(struct ifnet *);
354 void cnw_transmit(struct cnw_softc *, struct mbuf *);
355 struct mbuf *cnw_read(struct cnw_softc *);
356 void cnw_recv(struct cnw_softc *);
357 #if !defined(__FreeBSD__)
358 int cnw_intr(void *arg);
360 void cnw_intr(void *arg);
362 int cnw_ioctl(struct ifnet *, u_long, caddr_t);
363 void cnw_watchdog(struct ifnet *);
364 static int cnw_setdomain(struct cnw_softc *, int);
365 static int cnw_setkey(struct cnw_softc *, int);
367 /* ---------------------------------------------------------------- */
370 static int wait_WOC(struct cnw_softc *, int);
371 static int read16(struct cnw_softc *, int);
372 static int cnw_cmd(struct cnw_softc *, int, int, int, int);
375 * Wait until the WOC (Write Operation Complete) bit in the
376 * ASR (Adapter Status Register) is asserted.
380 struct cnw_softc *sc;
385 for (i = 0; i < 5000; i++) {
386 #ifndef MEMORY_MAPPED
387 asr = bus_space_read_1(sc->sc_iot, sc->sc_ioh, CNW_REG_ASR);
389 asr = bus_space_read_1(sc->sc_memt, sc->sc_memh,
390 sc->sc_memoff + CNW_IOM_OFF + CNW_REG_ASR);
392 if (asr & CNW_ASR_WOC)
397 #if !defined(__FreeBSD__)
398 printf("%s: wedged at line %d\n", sc->sc_dev.dv_xname, line);
400 device_printf(sc->dev, "wedged at line %d\n", line);
404 #define WAIT_WOC(sc) wait_WOC(sc, __LINE__)
408 * Read a 16 bit value from the card.
412 struct cnw_softc *sc;
416 int offs = sc->sc_memoff + offset;
418 /* This could presumably be done more efficient with
419 * bus_space_read_2(), but I don't know anything about the
420 * byte sex guarantees... Besides, this is pretty cheap as
423 lo = bus_space_read_1(sc->sc_memt, sc->sc_memh, offs);
424 hi = bus_space_read_1(sc->sc_memt, sc->sc_memh, offs + 1);
425 return ((hi << 8) | lo);
430 * Send a command to the card by writing it to the command buffer.
433 cnw_cmd(sc, cmd, count, arg1, arg2)
434 struct cnw_softc *sc;
435 int cmd, count, arg1, arg2;
437 int ptr = sc->sc_memoff + CNW_EREG_CB;
439 if (wait_WOC(sc, 0)) {
440 #if !defined(__FreeBSD__)
441 printf("%s: wedged when issuing cmd 0x%x\n",
442 sc->sc_dev.dv_xname, cmd);
444 device_printf(sc->dev, "wedged when issuing cmd 0x%x\n", cmd);
447 * We'll continue anyway, as that's probably the best
448 * thing we can do; at least the user knows there's a
449 * problem, and can reset the interface with ifconfig
454 bus_space_write_1(sc->sc_memt, sc->sc_memh, ptr, cmd);
456 bus_space_write_1(sc->sc_memt, sc->sc_memh, ptr + 1, arg1);
458 bus_space_write_1(sc->sc_memt, sc->sc_memh,
461 bus_space_write_1(sc->sc_memt, sc->sc_memh,
462 ptr + count + 1, CNW_CMD_EOC);
465 #define CNW_CMD0(sc, cmd) \
466 do { cnw_cmd(sc, cmd, 0, 0, 0); } while (0)
467 #define CNW_CMD1(sc, cmd, arg1) \
468 do { cnw_cmd(sc, cmd, 1, arg1 , 0); } while (0)
469 #define CNW_CMD2(sc, cmd, arg1, arg2) \
470 do { cnw_cmd(sc, cmd, 2, arg1, arg2); } while (0)
472 /* ---------------------------------------------------------------- */
475 * Reset the hardware.
479 struct cnw_softc *sc;
482 if (sc->sc_ethercom.ec_if.if_flags & IFF_DEBUG)
483 printf("%s: resetting\n", sc->sc_dev.dv_xname);
486 #ifndef MEMORY_MAPPED
487 bus_space_write_1(sc->sc_iot, sc->sc_ioh, CNW_REG_PMR, CNW_PMR_RESET);
489 bus_space_write_1(sc->sc_memt, sc->sc_memh,
490 sc->sc_memoff + CNW_IOM_OFF + CNW_REG_PMR, CNW_PMR_RESET);
492 bus_space_write_1(sc->sc_memt, sc->sc_memh,
493 sc->sc_memoff + CNW_EREG_ASCC, CNW_ASR_WOC);
494 #ifndef MEMORY_MAPPED
495 bus_space_write_1(sc->sc_iot, sc->sc_ioh, CNW_REG_PMR, 0);
497 bus_space_write_1(sc->sc_memt, sc->sc_memh,
498 sc->sc_memoff + CNW_IOM_OFF + CNW_REG_PMR, 0);
504 * Initialize the card.
508 struct cnw_softc *sc;
510 #if !defined(__FreeBSD__)
511 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
513 struct ifnet *ifp = sc->sc_ifp;
515 const u_int8_t rxmode =
516 CNW_RXCONF_RXENA | CNW_RXCONF_BCAST | CNW_RXCONF_AMP;
521 /* Issue a NOP to check the card */
522 CNW_CMD0(sc, CNW_CMD_NOP);
524 /* Set up receive configuration */
525 CNW_CMD1(sc, CNW_CMD_SRC,
526 rxmode | ((ifp->if_flags & IFF_PROMISC) ? CNW_RXCONF_PRO : 0));
528 /* Set up transmit configuration */
529 CNW_CMD1(sc, CNW_CMD_STC, CNW_TXCONF_TXENA);
532 CNW_CMD2(sc, CNW_CMD_SMD, sc->sc_domain, sc->sc_domain >> 8);
534 /* Set scramble key */
535 CNW_CMD2(sc, CNW_CMD_SSK, sc->sc_skey, sc->sc_skey >> 8);
537 /* Enable interrupts */
539 #ifndef MEMORY_MAPPED
540 bus_space_write_1(sc->sc_iot, sc->sc_ioh,
541 CNW_REG_IMR, CNW_IMR_IENA | CNW_IMR_RFU1);
543 bus_space_write_1(sc->sc_memt, sc->sc_memh,
544 sc->sc_memoff + CNW_IOM_OFF + CNW_REG_IMR,
545 CNW_IMR_IENA | CNW_IMR_RFU1);
548 /* Enable receiver */
549 CNW_CMD0(sc, CNW_CMD_ER);
551 /* "Set the IENA bit in COR" */
553 #ifndef MEMORY_MAPPED
554 bus_space_write_1(sc->sc_iot, sc->sc_ioh, CNW_REG_COR,
555 CNW_COR_IENA | CNW_COR_LVLREQ);
557 bus_space_write_1(sc->sc_memt, sc->sc_memh,
558 sc->sc_memoff + CNW_IOM_OFF + CNW_REG_COR,
559 CNW_COR_IENA | CNW_COR_LVLREQ);
564 #if !defined(__FreeBSD__)
566 * Enable and initialize the card.
570 struct cnw_softc *sc;
572 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
574 if ((ifp->if_flags & IFF_RUNNING) != 0)
577 sc->sc_ih = pcmcia_intr_establish(sc->sc_pf, IPL_NET, cnw_intr, sc);
578 if (sc->sc_ih == NULL) {
579 printf("%s: couldn't establish interrupt handler\n",
580 sc->sc_dev.dv_xname);
583 if (pcmcia_function_enable(sc->sc_pf) != 0) {
584 printf("%s: couldn't enable card\n", sc->sc_dev.dv_xname);
587 sc->sc_resource |= CNW_RES_PCIC;
589 ifp->if_flags &= ~IFF_OACTIVE;
590 ifp->if_flags |= IFF_RUNNING;
596 * Stop and disable the card.
600 struct cnw_softc *sc;
602 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
604 if ((ifp->if_flags & IFF_RUNNING) == 0)
607 pcmcia_function_disable(sc->sc_pf);
608 sc->sc_resource &= ~CNW_RES_PCIC;
609 pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih);
610 ifp->if_flags &= ~IFF_RUNNING;
615 * Match the hardware we handle.
618 cnw_match(parent, match, aux)
619 struct device *parent;
620 struct cfdata *match;
623 struct pcmcia_attach_args *pa = aux;
625 if (pa->manufacturer == PCMCIA_VENDOR_XIRCOM &&
626 pa->product == PCMCIA_PRODUCT_XIRCOM_CNW_801)
628 if (pa->manufacturer == PCMCIA_VENDOR_XIRCOM &&
629 pa->product == PCMCIA_PRODUCT_XIRCOM_CNW_802)
639 cnw_attach(parent, self, aux)
640 struct device *parent, *self;
643 struct cnw_softc *sc = (void *) self;
644 struct pcmcia_attach_args *pa = aux;
645 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
646 u_int8_t macaddr[ETHER_ADDR_LEN];
652 /* Enable the card */
654 pcmcia_function_init(sc->sc_pf, sc->sc_pf->cfe_head.sqh_first);
655 if (pcmcia_function_enable(sc->sc_pf)) {
656 printf(": function enable failed\n");
659 sc->sc_resource |= CNW_RES_PCIC;
661 /* Map I/O register and "memory" */
662 #ifndef MEMORY_MAPPED
663 if (pcmcia_io_alloc(sc->sc_pf, 0, CNW_IO_SIZE, CNW_IO_SIZE,
664 &sc->sc_pcioh) != 0) {
665 printf(": can't allocate i/o space\n");
668 if (pcmcia_io_map(sc->sc_pf, PCMCIA_WIDTH_IO16, 0,
669 CNW_IO_SIZE, &sc->sc_pcioh, &sc->sc_iowin) != 0) {
670 printf(": can't map i/o space\n");
671 pcmcia_io_free(sc->sc_pf, &sc->sc_pcioh);
674 sc->sc_iot = sc->sc_pcioh.iot;
675 sc->sc_ioh = sc->sc_pcioh.ioh;
676 sc->sc_resource |= CNW_RES_IO;
678 #ifndef MEMORY_MAPPED
679 memsize = CNW_MEM_SIZE;
681 memsize = CNW_MEM_SIZE + CNW_IOM_SIZE;
683 if (pcmcia_mem_alloc(sc->sc_pf, memsize, &sc->sc_pcmemh) != 0) {
684 printf(": can't allocate memory\n");
687 if (pcmcia_mem_map(sc->sc_pf, PCMCIA_WIDTH_MEM8|PCMCIA_MEM_COMMON,
688 CNW_MEM_ADDR, memsize, &sc->sc_pcmemh, &sc->sc_memoff,
689 &sc->sc_memwin) != 0) {
690 printf(": can't map memory\n");
691 pcmcia_mem_free(sc->sc_pf, &sc->sc_pcmemh);
694 sc->sc_memt = sc->sc_pcmemh.memt;
695 sc->sc_memh = sc->sc_pcmemh.memh;
696 sc->sc_resource |= CNW_RES_MEM;
697 switch (pa->product) {
698 case PCMCIA_PRODUCT_XIRCOM_CNW_801:
699 printf(": %s\n", PCMCIA_STR_XIRCOM_CNW_801);
701 case PCMCIA_PRODUCT_XIRCOM_CNW_802:
702 printf(": %s\n", PCMCIA_STR_XIRCOM_CNW_802);
706 /* Finish setup of softc */
707 sc->sc_domain = cnw_domain;
708 sc->sc_skey = cnw_skey;
710 /* Get MAC address */
712 for (i = 0; i < ETHER_ADDR_LEN; i++)
713 macaddr[i] = bus_space_read_1(sc->sc_memt, sc->sc_memh,
714 sc->sc_memoff + CNW_EREG_PA + i);
715 printf("%s: address %s\n", sc->sc_dev.dv_xname,
716 ether_sprintf(macaddr));
718 /* Set up ifnet structure */
719 bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
721 ifp->if_start = cnw_start;
722 ifp->if_ioctl = cnw_ioctl;
723 ifp->if_watchdog = cnw_watchdog;
724 ifp->if_flags = IFF_BROADCAST | IFF_MULTICAST | IFF_SIMPLEX |
727 /* Attach the interface */
729 ether_ifattach(ifp, macaddr);
731 bpfattach(&sc->sc_ethercom.ec_if.if_bpf, ifp, DLT_EN10MB,
732 sizeof(struct ether_header));
734 sc->sc_resource |= CNW_RES_NET;
736 ifp->if_baudrate = IF_Mbps(1);
738 /* Disable the card now, and turn it on when the interface goes up */
739 pcmcia_function_disable(sc->sc_pf);
740 sc->sc_resource &= ~CNW_RES_PCIC;
744 #ifndef MEMORY_MAPPED
745 if ((sc->sc_resource & CNW_RES_IO) != 0) {
746 pcmcia_io_unmap(sc->sc_pf, sc->sc_iowin);
747 pcmcia_io_free(sc->sc_pf, &sc->sc_pcioh);
748 sc->sc_resource &= ~CNW_RES_IO;
751 if ((sc->sc_resource & CNW_RES_PCIC) != 0) {
752 pcmcia_function_disable(sc->sc_pf);
753 sc->sc_resource &= ~CNW_RES_PCIC;
756 #endif /* !defined(__FreeBSD__) */
759 * Start outputting on the interface.
765 struct cnw_softc *sc = ifp->if_softc;
774 if (sc->sc_ethercom.ec_if.if_flags & IFF_DEBUG)
775 printf("%s: cnw_start\n", ifp->if_xname);
776 #if defined(__FreeBSD__)
777 if (ifp->if_drv_flags & IFF_DRV_OACTIVE)
779 if (ifp->if_flags & IFF_OACTIVE)
781 printf("%s: cnw_start reentered\n", ifp->if_xname);
784 #if defined(__FreeBSD__)
788 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
790 ifp->if_flags |= IFF_OACTIVE;
796 now.tv_sec -= sc->sc_txlast.tv_sec;
797 now.tv_usec -= sc->sc_txlast.tv_usec;
798 if (now.tv_usec < 0) {
799 now.tv_usec += 1000000;
804 * Don't ship this packet out until the last
805 * packet has left the building.
806 * If we have not tried to send a packet for 1/5
807 * a second then we assume we lost an interrupt,
808 * lets go on and send the next packet anyhow.
810 * I suppose we could check to see if it is okay
811 * to put additional packets on the card (beyond
812 * the one already waiting to be sent) but I don't
813 * think we would get any improvement in speed as
814 * we should have ample time to put the next packet
815 * on while this one is going out.
817 if (sc->sc_active && now.tv_sec == 0 && now.tv_usec < 200000)
821 /* Make sure the link integrity field is on */
823 lif = bus_space_read_1(sc->sc_memt, sc->sc_memh,
824 sc->sc_memoff + CNW_EREG_LIF);
827 if (sc->sc_ethercom.ec_if.if_flags & IFF_DEBUG)
828 printf("%s: link integrity %d\n", lif);
833 /* Is there any buffer space available on the card? */
835 #ifndef MEMORY_MAPPED
836 asr = bus_space_read_1(sc->sc_iot, sc->sc_ioh, CNW_REG_ASR);
838 asr = bus_space_read_1(sc->sc_memt, sc->sc_memh,
839 sc->sc_memoff + CNW_IOM_OFF + CNW_REG_ASR);
841 if (!(asr & CNW_ASR_TXBA)) {
843 if (sc->sc_ethercom.ec_if.if_flags & IFF_DEBUG)
844 printf("%s: no buffer space\n", ifp->if_xname);
849 sc->sc_stats.nws_tx++;
851 IF_DEQUEUE(&ifp->if_snd, m0);
855 #if !defined(__FreeBSD__)
858 bpf_mtap(ifp->if_bpf, m0);
864 cnw_transmit(sc, m0);
866 ifp->if_timer = 3; /* start watchdog timer */
868 microtime(&sc->sc_txlast);
872 #if defined(__FreeBSD__)
873 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
875 ifp->if_flags &= ~IFF_OACTIVE;
884 struct cnw_softc *sc;
887 int buffer, bufsize, bufoffset, bufptr, bufspace, len, mbytes, n;
890 /* Get buffer info from card */
891 buffer = read16(sc, CNW_EREG_TDP);
892 bufsize = read16(sc, CNW_EREG_TDP + 2);
893 bufoffset = read16(sc, CNW_EREG_TDP + 4);
895 if (sc->sc_ethercom.ec_if.if_flags & IFF_DEBUG)
896 printf("%s: cnw_transmit b=0x%x s=%d o=0x%x\n",
897 sc->sc_dev.dv_xname, buffer, bufsize, bufoffset);
900 /* Copy data from mbuf chain to card buffers */
901 bufptr = sc->sc_memoff + buffer + bufoffset;
905 mptr = mtod(m, u_int8_t *);
910 buffer = read16(sc, buffer);
911 bufptr = sc->sc_memoff + buffer + bufoffset;
914 if (sc->sc_ethercom.ec_if.if_flags & IFF_DEBUG)
915 printf("%s: next buffer @0x%x\n",
916 sc->sc_dev.dv_xname, buffer);
919 n = mbytes <= bufspace ? mbytes : bufspace;
920 bus_space_write_region_1(sc->sc_memt, sc->sc_memh,
930 /* Issue transmit command */
931 CNW_CMD2(sc, CNW_CMD_TL, len, len >> 8);
936 * Pull a packet from the card into an mbuf chain.
940 struct cnw_softc *sc;
942 struct mbuf *m, *top, **mp;
943 int totbytes, buffer, bufbytes, bufptr, mbytes, n;
947 totbytes = read16(sc, CNW_EREG_RDP);
949 if (sc->sc_ethercom.ec_if.if_flags & IFF_DEBUG)
950 printf("%s: recv %d bytes\n", sc->sc_dev.dv_xname, totbytes);
952 buffer = CNW_EREG_RDP + 2;
954 bufptr = 0; /* XXX make gcc happy */
956 MGETHDR(m, M_DONTWAIT, MT_DATA);
959 #if !defined(__FreeBSD__)
960 m->m_pkthdr.rcvif = &sc->sc_ethercom.ec_if;
962 m->m_pkthdr.rcvif = sc->sc_ifp;
964 m->m_pkthdr.len = totbytes;
969 while (totbytes > 0) {
971 MGET(m, M_DONTWAIT, MT_DATA);
978 if (totbytes >= MINCLSIZE) {
979 MCLGET(m, M_DONTWAIT);
980 if ((m->m_flags & M_EXT) == 0) {
988 int pad = ALIGN(sizeof(struct ether_header)) -
989 sizeof(struct ether_header);
993 mptr = mtod(m, u_int8_t *);
994 mbytes = m->m_len = min(totbytes, mbytes);
998 buffer = read16(sc, buffer);
999 bufbytes = read16(sc, buffer + 2);
1000 bufptr = sc->sc_memoff + buffer +
1001 read16(sc, buffer + 4);
1003 if (sc->sc_ethercom.ec_if.if_flags & IFF_DEBUG)
1004 printf("%s: %d bytes @0x%x+0x%x\n",
1005 sc->sc_dev.dv_xname, bufbytes,
1006 buffer, bufptr - buffer -
1010 n = mbytes <= bufbytes ? mbytes : bufbytes;
1011 bus_space_read_region_1(sc->sc_memt, sc->sc_memh,
1027 * Handle received packets.
1031 struct cnw_softc *sc;
1034 #if !defined(__FreeBSD__)
1035 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1037 struct ifnet *ifp = sc->sc_ifp;
1043 rser = bus_space_read_1(sc->sc_memt, sc->sc_memh,
1044 sc->sc_memoff + CNW_EREG_RSER);
1045 if (!(rser & CNW_RSER_RXAVAIL))
1048 /* Pull packet off card */
1051 /* Acknowledge packet */
1052 CNW_CMD0(sc, CNW_CMD_SRP);
1054 /* Did we manage to get the packet from the interface? */
1061 #if !defined(__FreeBSD__)
1064 bpf_mtap(ifp->if_bpf, m);
1068 /* Pass the packet up. */
1069 (*ifp->if_input)(ifp, m);
1075 * Interrupt handler.
1077 #if !defined(__FreeBSD__)
1085 struct cnw_softc *sc = arg;
1086 #if !defined(__FreeBSD__)
1087 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1089 struct ifnet *ifp = sc->sc_ifp;
1091 int ret, status, rser, tser;
1094 #if !defined(__FreeBSD__)
1095 if ((sc->sc_ethercom.ec_if.if_flags & IFF_RUNNING) == 0 ||
1096 (sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
1099 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
1102 ifp->if_timer = 0; /* stop watchdog timer */
1107 #ifndef MEMORY_MAPPED
1108 status = bus_space_read_1(sc->sc_iot, sc->sc_ioh,
1111 status = bus_space_read_1(sc->sc_memt, sc->sc_memh,
1112 sc->sc_memoff + CNW_IOM_OFF + CNW_REG_CCSR);
1115 #if !defined(__FreeBSD__)
1116 if (!(status & 0x02)) {
1118 printf("%s: spurious interrupt\n",
1119 sc->sc_dev.dv_xname);
1123 if (!(status & 0x02)) {
1125 device_printf(sc->dev, "spurious interrupt\n");
1131 #ifndef MEMORY_MAPPED
1132 status = bus_space_read_1(sc->sc_iot, sc->sc_ioh, CNW_REG_ASR);
1134 status = bus_space_read_1(sc->sc_memt, sc->sc_memh,
1135 sc->sc_memoff + CNW_IOM_OFF + CNW_REG_ASR);
1138 /* Anything to receive? */
1139 if (status & CNW_ASR_RXRDY) {
1140 sc->sc_stats.nws_rx++;
1145 if (status & CNW_ASR_RXERR) {
1147 * I get a *lot* of spurious receive errors
1148 * (many per second), even when the interface
1149 * is quiescent, so we don't increment
1152 rser = bus_space_read_1(sc->sc_memt, sc->sc_memh,
1153 sc->sc_memoff + CNW_EREG_RSER);
1156 sc->sc_stats.nws_rxerr++;
1157 if (rser & CNW_RSER_RXBIG)
1158 sc->sc_stats.nws_rxframe++;
1159 if (rser & CNW_RSER_RXCRC)
1160 sc->sc_stats.nws_rxcrcerror++;
1161 if (rser & CNW_RSER_RXOVERRUN)
1162 sc->sc_stats.nws_rxoverrun++;
1163 if (rser & CNW_RSER_RXOVERFLOW)
1164 sc->sc_stats.nws_rxoverflow++;
1165 if (rser & CNW_RSER_RXERR)
1166 sc->sc_stats.nws_rxerrors++;
1167 if (rser & CNW_RSER_RXAVAIL)
1168 sc->sc_stats.nws_rxavail++;
1170 /* Clear error bits in RSER */
1172 bus_space_write_1(sc->sc_memt, sc->sc_memh,
1173 sc->sc_memoff + CNW_EREG_RSERW,
1175 (rser & (CNW_RSER_RXCRC | CNW_RSER_RXBIG)));
1176 /* Clear RXERR in ASR */
1178 bus_space_write_1(sc->sc_memt, sc->sc_memh,
1179 sc->sc_memoff + CNW_EREG_ASCC, CNW_ASR_RXERR);
1183 if (status & CNW_ASR_TXDN) {
1184 tser = bus_space_read_1(sc->sc_memt, sc->sc_memh,
1188 if (tser & CNW_TSER_TXERR)
1189 sc->sc_stats.nws_txerrors++;
1190 if (tser & CNW_TSER_TXNOAP)
1191 sc->sc_stats.nws_txlostcd++;
1192 if (tser & CNW_TSER_TXGU)
1193 sc->sc_stats.nws_txabort++;
1195 if (tser & CNW_TSER_TXOK) {
1196 sc->sc_stats.nws_txokay++;
1197 sc->sc_stats.nws_txretries[status & 0xf]++;
1199 bus_space_write_1(sc->sc_memt, sc->sc_memh,
1200 sc->sc_memoff + CNW_EREG_TSERW,
1201 CNW_TSER_TXOK | CNW_TSER_RTRY);
1204 if (tser & CNW_TSER_ERROR) {
1207 bus_space_write_1(sc->sc_memt, sc->sc_memh,
1208 sc->sc_memoff + CNW_EREG_TSERW,
1209 (tser & CNW_TSER_ERROR) |
1214 #if defined(__FreeBSD__)
1215 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1217 ifp->if_flags &= ~IFF_OACTIVE;
1220 /* Continue to send packets from the queue */
1221 #if !defined(__FreeBSD__)
1222 cnw_start(&sc->sc_ethercom.ec_if);
1233 * Handle device ioctls.
1236 cnw_ioctl(ifp, cmd, data)
1241 struct cnw_softc *sc = ifp->if_softc;
1242 #if !defined(__FreeBSD__)
1243 struct ifaddr *ifa = (struct ifaddr *)data;
1245 struct ifreq *ifr = (struct ifreq *)data;
1247 #if __FreeBSD__ >= 5
1248 struct thread *td = curthread; /* XXX */
1250 struct proc *td = curproc; /*XXX*/
1255 #if defined(__FreeBSD__)
1265 #if !defined(__FreeBSD__)
1266 if (!(ifp->if_flags & IFF_RUNNING) &&
1267 (error = cnw_enable(sc)) != 0)
1269 ifp->if_flags |= IFF_UP;
1270 switch (ifa->ifa_addr->sa_family) {
1274 arp_ifinit(&sc->sc_ethercom.ec_if, ifa);
1282 error = ether_ioctl(ifp, cmd, data);
1287 #if !defined(__FreeBSD__)
1288 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == IFF_RUNNING) {
1290 * The interface is marked down and it is running, so
1294 } else if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == IFF_UP){
1296 * The interface is marked up and it is stopped, so
1299 error = cnw_enable(sc);
1301 /* IFF_PROMISC may be changed */
1305 if (ifp->if_flags & IFF_UP) {
1306 cnw_freebsd_init(sc);
1308 if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
1311 cnw_freebsd_init(sc);
1320 #if !defined(__FreeBSD__)
1321 /* Update our multicast list. */
1322 error = (cmd == SIOCADDMULTI) ?
1323 ether_addmulti(ifr, &sc->sc_ethercom) :
1324 ether_delmulti(ifr, &sc->sc_ethercom);
1325 if (error == ENETRESET || error == 0) {
1335 case SIOCGCNWDOMAIN:
1336 ((struct ifreq *)data)->ifr_domain = sc->sc_domain;
1339 case SIOCSCNWDOMAIN:
1340 #if !defined(__FreeBSD__)
1341 error = suser(p->p_ucred, &p->p_acflag);
1347 error = cnw_setdomain(sc, ifr->ifr_domain);
1351 #if !defined(__FreeBSD__)
1352 error = suser(p->p_ucred, &p->p_acflag);
1358 error = cnw_setkey(sc, (int)ifr->ifr_key);
1361 case SIOCGCNWSTATUS:
1362 #if !defined(__FreeBSD__)
1363 error = suser(p->p_ucred, &p->p_acflag);
1369 #if !defined(__FreeBSD__)
1370 if ((ifp->if_flags & IFF_RUNNING) == 0)
1372 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
1375 bus_space_read_region_1(sc->sc_memt, sc->sc_memh,
1376 sc->sc_memoff + CNW_EREG_CB,
1377 ((struct cnwstatus *)data)->data,
1378 sizeof(((struct cnwstatus *)data)->data));
1382 bcopy((void *)&sc->sc_stats,
1383 (void *)&(((struct cnwistats *)data)->stats),
1384 sizeof(struct cnwstats));
1398 * Device timeout/watchdog routine. Entered if the device neglects to
1399 * generate an interrupt after a transmit has been started on it.
1405 struct cnw_softc *sc = ifp->if_softc;
1407 #if !defined(__FreeBSD__)
1408 printf("%s: device timeout; card reset\n", sc->sc_dev.dv_xname);
1412 device_printf(sc->dev, "device timeout; card reset\n");
1414 cnw_freebsd_init(sc);
1419 cnw_setdomain(sc, domain)
1420 struct cnw_softc *sc;
1425 if (domain & ~0x1ff)
1429 CNW_CMD2(sc, CNW_CMD_SMD, domain, domain >> 8);
1432 sc->sc_domain = domain;
1438 struct cnw_softc *sc;
1447 CNW_CMD2(sc, CNW_CMD_SSK, key, key >> 8);
1454 #if !defined(__FreeBSD__)
1456 cnw_activate(self, act)
1457 struct device *self;
1460 struct cnw_softc *sc = (struct cnw_softc *)self;
1465 case DVACT_ACTIVATE:
1469 case DVACT_DEACTIVATE:
1470 if_deactivate(&sc->sc_ethercom.ec_if);
1478 cnw_detach(self, flags)
1479 struct device *self;
1482 struct cnw_softc *sc = (struct cnw_softc *)self;
1483 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1485 /* cnw_disable() checks IFF_DRV_RUNNING */
1488 if ((sc->sc_resource & CNW_RES_NET) != 0) {
1492 ether_ifdetach(ifp);
1496 #ifndef MEMORY_MAPPED
1497 /* unmap and free our i/o windows */
1498 if ((sc->sc_resource & CNW_RES_IO) != 0) {
1499 pcmcia_io_unmap(sc->sc_pf, sc->sc_iowin);
1500 pcmcia_io_free(sc->sc_pf, &sc->sc_pcioh);
1504 /* unmap and free our memory windows */
1505 if ((sc->sc_resource & CNW_RES_MEM) != 0) {
1506 pcmcia_mem_unmap(sc->sc_pf, sc->sc_memwin);
1507 pcmcia_mem_free(sc->sc_pf, &sc->sc_pcmemh);
1514 #if defined(__FreeBSD__)
1515 static void cnw_freebsd_init(xsc)
1518 struct cnw_softc *sc = xsc;
1519 struct ifnet *ifp = sc->sc_ifp;
1529 if (ifp->if_drv_flags & IFF_DRV_RUNNING)
1533 ifp->if_drv_flags |= IFF_DRV_RUNNING;
1534 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1536 /* sc->cnw_stat_ch = timeout(cnw_inquire, sc, hz * 60); */
1545 static void cnw_stop(sc)
1546 struct cnw_softc *sc;
1556 ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
1561 static int cnw_pccard_probe(dev)
1564 struct cnw_softc *sc;
1567 sc = device_get_softc(dev);
1570 error = cnw_alloc(dev);
1574 device_set_desc(dev, "Netwave AirSurfer Wireless LAN");
1580 static int cnw_pccard_detach(dev)
1583 struct cnw_softc *sc;
1591 sc = device_get_softc(dev);
1595 device_printf(dev, "already unloaded\n");
1601 ether_ifdetach(ifp);
1612 static int cnw_pccard_attach(device_t dev)
1614 struct cnw_softc *sc;
1619 sc = device_get_softc(dev);
1620 ifp = sc->sc_ifp = if_alloc(IFT_ETHER);
1622 device_printf(dev, "if_alloc() failed\n");
1627 error = cnw_alloc(dev);
1629 device_printf(dev, "cnw_alloc() failed! (%d)\n", error);
1634 error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET,
1635 cnw_intr, sc, &sc->cnw_intrhand);
1638 device_printf(dev, "bus_setup_intr() failed! (%d)\n", error);
1644 /* Set initial values */
1645 sc->sc_domain = cnw_domain;
1646 sc->sc_skey = cnw_skey;
1648 /* Reset the NIC. */
1651 /* Get MAC address */
1652 for (i=0; i< ETHER_ADDR_LEN; i++) {
1653 eaddr[i] = bus_space_read_1(sc->sc_memt, sc->sc_memh,
1654 sc->sc_memoff + CNW_EREG_PA + i);
1658 if_initname(ifp, device_get_name(dev), device_get_unit(dev));
1660 ifp->if_mtu = ETHERMTU;
1661 ifp->if_flags = (IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST
1663 ifp->if_ioctl = cnw_ioctl;
1664 ifp->if_start = cnw_start;
1665 /* ifp->if_watchdog = 0; */
1666 ifp->if_watchdog = cnw_watchdog;
1667 ifp->if_init = cnw_freebsd_init;
1668 ifp->if_baudrate = 1 * 1000* 1000;
1669 ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
1671 cnw_freebsd_init(sc);
1675 * Call MI attach routine.
1677 ether_ifattach(ifp, eaddr);
1678 /* callout_handle_init(&sc->cnw_stat_ch); */
1683 static void cnw_shutdown(dev)
1686 struct cnw_softc *sc;
1688 sc = device_get_softc(dev);
1694 static int cnw_alloc(dev)
1697 struct cnw_softc *sc = device_get_softc(dev);
1702 sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
1705 device_printf(dev, "Cannot allocate attribute memory\n");
1708 sc->sc_memt = rman_get_bustag(sc->mem_res);
1709 sc->sc_memh = rman_get_bushandle(sc->mem_res);
1712 error = CARD_SET_MEMORY_OFFSET(device_get_parent(dev),
1713 dev, rid, CNW_MEM_ADDR, NULL);
1716 "CARD_SET_MEMORY_OFFSET returned 0x%0x", error);
1720 error = CARD_SET_RES_FLAGS(device_get_parent(dev), dev,
1721 SYS_RES_MEMORY, rid, PCCARD_A_MEM_8BIT);
1724 "CARD_SET_RES_FLAGS returned 0x%0x\n", error);
1729 sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
1731 device_printf(dev, "No irq?!\n");
1741 static void cnw_free(dev)
1744 struct cnw_softc *sc = device_get_softc(dev);
1746 if (sc->mem_res != NULL) {
1747 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
1750 if (sc->irq != NULL) {
1751 bus_teardown_intr(dev, sc->irq, sc->cnw_intrhand);
1752 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq);
1759 #endif /* FreeBSD */