if_cnw.c revision 1.31
1/*	$NetBSD: if_cnw.c,v 1.31 2005/02/27 00:27:43 perry Exp $	*/
2
3/*-
4 * Copyright (c) 1998, 2004 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Michael Eriksson.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 *    must display the following acknowledgement:
20 *	This product includes software developed by the NetBSD
21 *	Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 *    contributors may be used to endorse or promote products derived
24 *    from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39/*
40 * Copyright (c) 1996, 1997 Berkeley Software Design, Inc.
41 * All rights reserved.
42 *
43 * Redistribution and use in source and binary forms, with or without
44 * modification, are permitted provided that this notice is retained,
45 * the conditions in the following notices are met, and terms applying
46 * to contributors in the following notices also apply to Berkeley
47 * Software Design, Inc.
48 *
49 * 1. Redistributions of source code must retain the above copyright
50 *    notice, this list of conditions and the following disclaimer.
51 * 2. Redistributions in binary form must reproduce the above copyright
52 *    notice, this list of conditions and the following disclaimer in the
53 *    documentation and/or other materials provided with the distribution.
54 * 3. All advertising materials mentioning features or use of this software
55 *    must display the following acknowledgement:
56 *      This product includes software developed by
57 *	Berkeley Software Design, Inc.
58 * 4. Neither the name of the Berkeley Software Design, Inc. nor the names
59 *    of its contributors may be used to endorse or promote products derived
60 *    from this software without specific prior written permission.
61 *
62 * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN, INC. ``AS IS'' AND
63 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
64 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
65 * ARE DISCLAIMED.  IN NO EVENT SHALL BERKELEY SOFTWARE DESIGN, INC. BE LIABLE
66 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
67 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
68 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
69 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
70 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
71 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
72 * SUCH DAMAGE.
73 *
74 * Paul Borman, December 1996
75 *
76 * This driver is derived from a generic frame work which is
77 * Copyright(c) 1994,1995,1996
78 * Yoichi Shinoda, Yoshitaka Tokugawa, WIDE Project, Wildboar Project
79 * and Foretune.  All rights reserved.
80 *
81 * A linux driver was used as the "hardware reference manual" (i.e.,
82 * to determine registers and a general outline of how the card works)
83 * That driver is publically available and copyright
84 *
85 * John Markus Bj�rndalen
86 * Department of Computer Science
87 * University of Troms�
88 * Norway
89 * johnm@staff.cs.uit.no, http://www.cs.uit.no/~johnm/
90 */
91
92/*
93 * This is a driver for the Xircom CreditCard Netwave (also known as
94 * the Netwave Airsurfer) wireless LAN PCMCIA adapter.
95 *
96 * When this driver was developed, the Linux Netwave driver was used
97 * as a hardware manual. That driver is Copyright (c) 1997 University
98 * of Troms�, Norway. It is part of the Linux pcmcia-cs package that
99 * can be found at http://pcmcia-cs.sourceforge.net/. The most recent
100 * version of the pcmcia-cs package when this driver was written was
101 * 3.0.6.
102 *
103 * Unfortunately, a lot of explicit numeric constants were used in the
104 * Linux driver. I have tried to use symbolic names whenever possible,
105 * but since I don't have any real hardware documentation, there's
106 * still one or two "magic numbers" :-(.
107 *
108 * Driver limitations: This driver doesn't do multicasting or receiver
109 * promiscuity, because of missing hardware documentation. I couldn't
110 * get receiver promiscuity to work, and I haven't even tried
111 * multicast. Volunteers are welcome, of course :-).
112 */
113
114#include <sys/cdefs.h>
115__KERNEL_RCSID(0, "$NetBSD: if_cnw.c,v 1.31 2005/02/27 00:27:43 perry Exp $");
116
117#include "opt_inet.h"
118#include "bpfilter.h"
119
120#include <sys/param.h>
121#include <sys/systm.h>
122#include <sys/device.h>
123#include <sys/socket.h>
124#include <sys/mbuf.h>
125#include <sys/ioctl.h>
126#include <sys/proc.h>
127
128#include <net/if.h>
129
130#include <dev/pcmcia/if_cnwreg.h>
131#include <dev/pcmcia/if_cnwioctl.h>
132
133#include <dev/pcmcia/pcmciareg.h>
134#include <dev/pcmcia/pcmciavar.h>
135#include <dev/pcmcia/pcmciadevs.h>
136
137#include <net/if_dl.h>
138#include <net/if_ether.h>
139
140#ifdef INET
141#include <netinet/in.h>
142#include <netinet/in_systm.h>
143#include <netinet/in_var.h>
144#include <netinet/ip.h>
145#include <netinet/if_inarp.h>
146#endif
147
148#if NBPFILTER > 0
149#include <net/bpf.h>
150#include <net/bpfdesc.h>
151#endif
152
153/*
154 * Let these be patchable variables, initialized from macros that can
155 * be set in the kernel config file. Someone with lots of spare time
156 * could probably write a nice Netwave configuration program to do
157 * this a little bit more elegantly :-).
158 */
159#ifndef CNW_DOMAIN
160#define CNW_DOMAIN	0x100
161#endif
162int cnw_domain = CNW_DOMAIN;		/* Domain */
163#ifndef CNW_SCRAMBLEKEY
164#define CNW_SCRAMBLEKEY 0
165#endif
166int cnw_skey = CNW_SCRAMBLEKEY;		/* Scramble key */
167
168/*
169 * The card appears to work much better when we only allow one packet
170 * "in the air" at a time.  This is done by not allowing another packet
171 * on the card, even if there is room.  Turning this off will allow the
172 * driver to stuff packets on the card as soon as a transmit buffer is
173 * available.  This does increase the number of collisions, though.
174 * We can que a second packet if there are transmit buffers available,
175 * but we do not actually send the packet until the last packet has
176 * been written.
177 */
178#define	ONE_AT_A_TIME
179
180/*
181 * Netwave cards choke if we try to use io memory address >= 0x400.
182 * Even though, CIS tuple does not talk about this.
183 * Use memory mapped access.
184 */
185#define MEMORY_MAPPED
186
187int	cnw_match(struct device *, struct cfdata *, void *);
188void	cnw_attach(struct device *, struct device *, void *);
189int	cnw_detach(struct device *, int);
190
191int	cnw_activate(struct device *, enum devact);
192
193struct cnw_softc {
194	struct device sc_dev;		    /* Device glue (must be first) */
195	struct ethercom sc_ethercom;	    /* Ethernet common part */
196	int sc_domain;			    /* Netwave domain */
197	int sc_skey;			    /* Netwave scramble key */
198	struct cnwstats sc_stats;
199
200	/* PCMCIA-specific stuff */
201	struct pcmcia_function *sc_pf;	    /* PCMCIA function */
202#ifndef MEMORY_MAPPED
203	struct pcmcia_io_handle sc_pcioh;   /* PCMCIA I/O space handle */
204	int sc_iowin;			    /*   ...window */
205	bus_space_tag_t sc_iot;		    /*   ...bus_space tag */
206	bus_space_handle_t sc_ioh;	    /*   ...bus_space handle */
207#endif
208	struct pcmcia_mem_handle sc_pcmemh; /* PCMCIA memory handle */
209	bus_size_t sc_memoff;		    /*   ...offset */
210	int sc_memwin;			    /*   ...window */
211	bus_space_tag_t sc_memt;	    /*   ...bus_space tag */
212	bus_space_handle_t sc_memh;	    /*   ...bus_space handle */
213	void *sc_ih;			    /* Interrupt cookie */
214	struct timeval sc_txlast;	    /* When the last xmit was made */
215	int sc_active;			    /* Currently xmitting a packet */
216
217	int sc_resource;		    /* Resources alloc'ed on attach */
218#define CNW_RES_PCIC	1
219#define CNW_RES_IO	2
220#define CNW_RES_MEM	4
221#define CNW_RES_NET	8
222};
223
224CFATTACH_DECL(cnw, sizeof(struct cnw_softc),
225    cnw_match, cnw_attach, cnw_detach, cnw_activate);
226
227void cnw_reset(struct cnw_softc *);
228void cnw_init(struct cnw_softc *);
229int cnw_enable(struct cnw_softc *sc);
230void cnw_disable(struct cnw_softc *sc);
231void cnw_config(struct cnw_softc *sc, u_int8_t *);
232void cnw_start(struct ifnet *);
233void cnw_transmit(struct cnw_softc *, struct mbuf *);
234struct mbuf *cnw_read(struct cnw_softc *);
235void cnw_recv(struct cnw_softc *);
236int cnw_intr(void *arg);
237int cnw_ioctl(struct ifnet *, u_long, caddr_t);
238void cnw_watchdog(struct ifnet *);
239static int cnw_setdomain(struct cnw_softc *, int);
240static int cnw_setkey(struct cnw_softc *, int);
241
242/* ---------------------------------------------------------------- */
243
244/* Help routines */
245static int wait_WOC(struct cnw_softc *, int);
246static int read16(struct cnw_softc *, int);
247static int cnw_cmd(struct cnw_softc *, int, int, int, int);
248
249/*
250 * Wait until the WOC (Write Operation Complete) bit in the
251 * ASR (Adapter Status Register) is asserted.
252 */
253static int
254wait_WOC(sc, line)
255	struct cnw_softc *sc;
256	int line;
257{
258	int i, asr;
259
260	for (i = 0; i < 5000; i++) {
261#ifndef MEMORY_MAPPED
262		asr = bus_space_read_1(sc->sc_iot, sc->sc_ioh, CNW_REG_ASR);
263#else
264		asr = bus_space_read_1(sc->sc_memt, sc->sc_memh,
265		    sc->sc_memoff + CNW_IOM_OFF + CNW_REG_ASR);
266#endif
267		if (asr & CNW_ASR_WOC)
268			return (0);
269		DELAY(100);
270	}
271	if (line > 0)
272		printf("%s: wedged at line %d\n", sc->sc_dev.dv_xname, line);
273	return (1);
274}
275#define WAIT_WOC(sc) wait_WOC(sc, __LINE__)
276
277
278/*
279 * Read a 16 bit value from the card.
280 */
281static int
282read16(sc, offset)
283	struct cnw_softc *sc;
284	int offset;
285{
286	int hi, lo;
287	int offs = sc->sc_memoff + offset;
288
289	/* This could presumably be done more efficient with
290	 * bus_space_read_2(), but I don't know anything about the
291	 * byte sex guarantees... Besides, this is pretty cheap as
292	 * well :-)
293	 */
294	lo = bus_space_read_1(sc->sc_memt, sc->sc_memh, offs);
295	hi = bus_space_read_1(sc->sc_memt, sc->sc_memh, offs + 1);
296	return ((hi << 8) | lo);
297}
298
299
300/*
301 * Send a command to the card by writing it to the command buffer.
302 */
303int
304cnw_cmd(sc, cmd, count, arg1, arg2)
305	struct cnw_softc *sc;
306	int cmd, count, arg1, arg2;
307{
308	int ptr = sc->sc_memoff + CNW_EREG_CB;
309
310	if (wait_WOC(sc, 0)) {
311		printf("%s: wedged when issuing cmd 0x%x\n",
312		    sc->sc_dev.dv_xname, cmd);
313		/*
314		 * We'll continue anyway, as that's probably the best
315		 * thing we can do; at least the user knows there's a
316		 * problem, and can reset the interface with ifconfig
317		 * down/up.
318		 */
319	}
320
321	bus_space_write_1(sc->sc_memt, sc->sc_memh, ptr, cmd);
322	if (count > 0) {
323		bus_space_write_1(sc->sc_memt, sc->sc_memh, ptr + 1, arg1);
324		if (count > 1)
325			bus_space_write_1(sc->sc_memt, sc->sc_memh,
326			    ptr + 2, arg2);
327	}
328	bus_space_write_1(sc->sc_memt, sc->sc_memh,
329	    ptr + count + 1, CNW_CMD_EOC);
330	return (0);
331}
332#define CNW_CMD0(sc, cmd) \
333    do { cnw_cmd(sc, cmd, 0, 0, 0); } while (0)
334#define CNW_CMD1(sc, cmd, arg1)	\
335    do { cnw_cmd(sc, cmd, 1, arg1 , 0); } while (0)
336#define CNW_CMD2(sc, cmd, arg1, arg2) \
337    do { cnw_cmd(sc, cmd, 2, arg1, arg2); } while (0)
338
339/* ---------------------------------------------------------------- */
340
341/*
342 * Reset the hardware.
343 */
344void
345cnw_reset(sc)
346	struct cnw_softc *sc;
347{
348#ifdef CNW_DEBUG
349	if (sc->sc_ethercom.ec_if.if_flags & IFF_DEBUG)
350		printf("%s: resetting\n", sc->sc_dev.dv_xname);
351#endif
352	wait_WOC(sc, 0);
353#ifndef MEMORY_MAPPED
354	bus_space_write_1(sc->sc_iot, sc->sc_ioh, CNW_REG_PMR, CNW_PMR_RESET);
355#else
356	bus_space_write_1(sc->sc_memt, sc->sc_memh,
357	    sc->sc_memoff + CNW_IOM_OFF + CNW_REG_PMR, CNW_PMR_RESET);
358#endif
359	bus_space_write_1(sc->sc_memt, sc->sc_memh,
360	    sc->sc_memoff + CNW_EREG_ASCC, CNW_ASR_WOC);
361#ifndef MEMORY_MAPPED
362	bus_space_write_1(sc->sc_iot, sc->sc_ioh, CNW_REG_PMR, 0);
363#else
364	bus_space_write_1(sc->sc_memt, sc->sc_memh,
365	    sc->sc_memoff + CNW_IOM_OFF + CNW_REG_PMR, 0);
366#endif
367}
368
369
370/*
371 * Initialize the card.
372 */
373void
374cnw_init(sc)
375	struct cnw_softc *sc;
376{
377	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
378	const u_int8_t rxmode =
379	    CNW_RXCONF_RXENA | CNW_RXCONF_BCAST | CNW_RXCONF_AMP;
380
381	/* Reset the card */
382	cnw_reset(sc);
383
384	/* Issue a NOP to check the card */
385	CNW_CMD0(sc, CNW_CMD_NOP);
386
387	/* Set up receive configuration */
388	CNW_CMD1(sc, CNW_CMD_SRC,
389	    rxmode | ((ifp->if_flags & IFF_PROMISC) ? CNW_RXCONF_PRO : 0));
390
391	/* Set up transmit configuration */
392	CNW_CMD1(sc, CNW_CMD_STC, CNW_TXCONF_TXENA);
393
394	/* Set domain */
395	CNW_CMD2(sc, CNW_CMD_SMD, sc->sc_domain, sc->sc_domain >> 8);
396
397	/* Set scramble key */
398	CNW_CMD2(sc, CNW_CMD_SSK, sc->sc_skey, sc->sc_skey >> 8);
399
400	/* Enable interrupts */
401	WAIT_WOC(sc);
402#ifndef MEMORY_MAPPED
403	bus_space_write_1(sc->sc_iot, sc->sc_ioh,
404	    CNW_REG_IMR, CNW_IMR_IENA | CNW_IMR_RFU1);
405#else
406	bus_space_write_1(sc->sc_memt, sc->sc_memh,
407	    sc->sc_memoff + CNW_IOM_OFF + CNW_REG_IMR,
408	    CNW_IMR_IENA | CNW_IMR_RFU1);
409#endif
410
411	/* Enable receiver */
412	CNW_CMD0(sc, CNW_CMD_ER);
413
414	/* "Set the IENA bit in COR" */
415	WAIT_WOC(sc);
416#ifndef MEMORY_MAPPED
417	bus_space_write_1(sc->sc_iot, sc->sc_ioh, CNW_REG_COR,
418	    CNW_COR_IENA | CNW_COR_LVLREQ);
419#else
420	bus_space_write_1(sc->sc_memt, sc->sc_memh,
421	    sc->sc_memoff + CNW_IOM_OFF + CNW_REG_COR,
422	    CNW_COR_IENA | CNW_COR_LVLREQ);
423#endif
424}
425
426
427/*
428 * Enable and initialize the card.
429 */
430int
431cnw_enable(sc)
432	struct cnw_softc *sc;
433{
434	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
435
436	if ((ifp->if_flags & IFF_RUNNING) != 0)
437		return (0);
438
439	sc->sc_ih = pcmcia_intr_establish(sc->sc_pf, IPL_NET, cnw_intr, sc);
440	if (sc->sc_ih == NULL) {
441		printf("%s: couldn't establish interrupt handler\n",
442		    sc->sc_dev.dv_xname);
443		return (EIO);
444	}
445	if (pcmcia_function_enable(sc->sc_pf) != 0) {
446		printf("%s: couldn't enable card\n", sc->sc_dev.dv_xname);
447		return (EIO);
448	}
449	sc->sc_resource |= CNW_RES_PCIC;
450	cnw_init(sc);
451	ifp->if_flags &= ~IFF_OACTIVE;
452	ifp->if_flags |= IFF_RUNNING;
453	return (0);
454}
455
456
457/*
458 * Stop and disable the card.
459 */
460void
461cnw_disable(sc)
462	struct cnw_softc *sc;
463{
464	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
465
466	if ((ifp->if_flags & IFF_RUNNING) == 0)
467		return;
468
469	pcmcia_function_disable(sc->sc_pf);
470	sc->sc_resource &= ~CNW_RES_PCIC;
471	pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih);
472	ifp->if_flags &= ~IFF_RUNNING;
473	ifp->if_timer = 0;
474}
475
476
477/*
478 * Match the hardware we handle.
479 */
480int
481cnw_match(parent, match, aux)
482	struct device *parent;
483	struct cfdata *match;
484	void *aux;
485{
486	struct pcmcia_attach_args *pa = aux;
487
488	if (pa->manufacturer == PCMCIA_VENDOR_XIRCOM &&
489	    pa->product == PCMCIA_PRODUCT_XIRCOM_CNW_801)
490		return 1;
491	if (pa->manufacturer == PCMCIA_VENDOR_XIRCOM &&
492	    pa->product == PCMCIA_PRODUCT_XIRCOM_CNW_802)
493		return 1;
494	return 0;
495}
496
497
498/*
499 * Attach the card.
500 */
501void
502cnw_attach(parent, self, aux)
503	struct device  *parent, *self;
504	void           *aux;
505{
506	struct cnw_softc *sc = (void *) self;
507	struct pcmcia_attach_args *pa = aux;
508	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
509	u_int8_t macaddr[ETHER_ADDR_LEN];
510	int i;
511	bus_size_t memsize;
512
513	sc->sc_resource = 0;
514
515	/* Enable the card */
516	sc->sc_pf = pa->pf;
517	pcmcia_function_init(sc->sc_pf, SIMPLEQ_FIRST(&sc->sc_pf->cfe_head));
518	if (pcmcia_function_enable(sc->sc_pf)) {
519		printf("%s: function enable failed\n", self->dv_xname);
520		return;
521	}
522	sc->sc_resource |= CNW_RES_PCIC;
523
524	/* Map I/O register and "memory" */
525#ifndef MEMORY_MAPPED
526	if (pcmcia_io_alloc(sc->sc_pf, 0, CNW_IO_SIZE, CNW_IO_SIZE,
527	    &sc->sc_pcioh) != 0) {
528		printf("%s: can't allocate i/o space\n", self->dv_xname);
529		goto fail;
530	}
531	if (pcmcia_io_map(sc->sc_pf, PCMCIA_WIDTH_IO16, &sc->sc_pcioh,
532	    &sc->sc_iowin) != 0) {
533		printf("%s: can't map i/o space\n", self->dv_xname);
534		pcmcia_io_free(sc->sc_pf, &sc->sc_pcioh);
535		goto fail;
536	}
537	sc->sc_iot = sc->sc_pcioh.iot;
538	sc->sc_ioh = sc->sc_pcioh.ioh;
539	sc->sc_resource |= CNW_RES_IO;
540#endif
541#ifndef MEMORY_MAPPED
542	memsize = CNW_MEM_SIZE;
543#else
544	memsize = CNW_MEM_SIZE + CNW_IOM_SIZE;
545#endif
546	if (pcmcia_mem_alloc(sc->sc_pf, memsize, &sc->sc_pcmemh) != 0) {
547		printf("%s: can't allocate memory\n", self->dv_xname);
548		goto fail;
549	}
550	if (pcmcia_mem_map(sc->sc_pf, PCMCIA_WIDTH_MEM8|PCMCIA_MEM_COMMON,
551	    CNW_MEM_ADDR, memsize, &sc->sc_pcmemh, &sc->sc_memoff,
552	    &sc->sc_memwin) != 0) {
553		printf("%s: can't map memory\n", self->dv_xname);
554		pcmcia_mem_free(sc->sc_pf, &sc->sc_pcmemh);
555		goto fail;
556	}
557	sc->sc_memt = sc->sc_pcmemh.memt;
558	sc->sc_memh = sc->sc_pcmemh.memh;
559	sc->sc_resource |= CNW_RES_MEM;
560
561	/* Finish setup of softc */
562	sc->sc_domain = cnw_domain;
563	sc->sc_skey = cnw_skey;
564
565	/* Get MAC address */
566	cnw_reset(sc);
567	for (i = 0; i < ETHER_ADDR_LEN; i++)
568		macaddr[i] = bus_space_read_1(sc->sc_memt, sc->sc_memh,
569		    sc->sc_memoff + CNW_EREG_PA + i);
570	printf("%s: address %s\n", sc->sc_dev.dv_xname,
571	    ether_sprintf(macaddr));
572
573	/* Set up ifnet structure */
574	strcpy(ifp->if_xname, sc->sc_dev.dv_xname);
575	ifp->if_softc = sc;
576	ifp->if_start = cnw_start;
577	ifp->if_ioctl = cnw_ioctl;
578	ifp->if_watchdog = cnw_watchdog;
579	ifp->if_flags = IFF_BROADCAST | IFF_MULTICAST | IFF_SIMPLEX |
580	    IFF_NOTRAILERS;
581	IFQ_SET_READY(&ifp->if_snd);
582
583	/* Attach the interface */
584	if_attach(ifp);
585	ether_ifattach(ifp, macaddr);
586
587	sc->sc_resource |= CNW_RES_NET;
588
589	ifp->if_baudrate = IF_Mbps(1);
590
591	/* Disable the card now, and turn it on when the interface goes up */
592	pcmcia_function_disable(sc->sc_pf);
593	sc->sc_resource &= ~CNW_RES_PCIC;
594	return;
595
596fail:
597#ifndef MEMORY_MAPPED
598	if ((sc->sc_resource & CNW_RES_IO) != 0) {
599		pcmcia_io_unmap(sc->sc_pf, sc->sc_iowin);
600		pcmcia_io_free(sc->sc_pf, &sc->sc_pcioh);
601		sc->sc_resource &= ~CNW_RES_IO;
602	}
603#endif
604	if ((sc->sc_resource & CNW_RES_PCIC) != 0) {
605		pcmcia_function_disable(sc->sc_pf);
606		sc->sc_resource &= ~CNW_RES_PCIC;
607	}
608}
609
610/*
611 * Start outputting on the interface.
612 */
613void
614cnw_start(ifp)
615	struct ifnet *ifp;
616{
617	struct cnw_softc *sc = ifp->if_softc;
618	struct mbuf *m0;
619	int lif;
620	int asr;
621#ifdef ONE_AT_A_TIME
622	struct timeval now;
623#endif
624
625#ifdef CNW_DEBUG
626	if (sc->sc_ethercom.ec_if.if_flags & IFF_DEBUG)
627		printf("%s: cnw_start\n", ifp->if_xname);
628	if (ifp->if_flags & IFF_OACTIVE)
629		printf("%s: cnw_start reentered\n", ifp->if_xname);
630#endif
631
632	ifp->if_flags |= IFF_OACTIVE;
633
634	for (;;) {
635#ifdef ONE_AT_A_TIME
636		microtime(&now);
637		now.tv_sec -= sc->sc_txlast.tv_sec;
638		now.tv_usec -= sc->sc_txlast.tv_usec;
639		if (now.tv_usec < 0) {
640			now.tv_usec += 1000000;
641			now.tv_sec--;
642		}
643
644		/*
645		 * Don't ship this packet out until the last
646		 * packet has left the building.
647		 * If we have not tried to send a packet for 1/5
648		 * a second then we assume we lost an interrupt,
649		 * lets go on and send the next packet anyhow.
650		 *
651		 * I suppose we could check to see if it is okay
652		 * to put additional packets on the card (beyond
653		 * the one already waiting to be sent) but I don't
654		 * think we would get any improvement in speed as
655		 * we should have ample time to put the next packet
656		 * on while this one is going out.
657		 */
658		if (sc->sc_active && now.tv_sec == 0 && now.tv_usec < 200000)
659			break;
660#endif
661
662		/* Make sure the link integrity field is on */
663		WAIT_WOC(sc);
664		lif = bus_space_read_1(sc->sc_memt, sc->sc_memh,
665		    sc->sc_memoff + CNW_EREG_LIF);
666		if (lif == 0) {
667#ifdef CNW_DEBUG
668			if (sc->sc_ethercom.ec_if.if_flags & IFF_DEBUG)
669				printf("%s: link integrity %d\n", lif);
670#endif
671			break;
672		}
673
674		/* Is there any buffer space available on the card? */
675		WAIT_WOC(sc);
676#ifndef MEMORY_MAPPED
677		asr = bus_space_read_1(sc->sc_iot, sc->sc_ioh, CNW_REG_ASR);
678#else
679		asr = bus_space_read_1(sc->sc_memt, sc->sc_memh,
680		    sc->sc_memoff + CNW_IOM_OFF + CNW_REG_ASR);
681#endif
682		if (!(asr & CNW_ASR_TXBA)) {
683#ifdef CNW_DEBUG
684			if (sc->sc_ethercom.ec_if.if_flags & IFF_DEBUG)
685				printf("%s: no buffer space\n", ifp->if_xname);
686#endif
687			break;
688		}
689
690		sc->sc_stats.nws_tx++;
691
692		IFQ_DEQUEUE(&ifp->if_snd, m0);
693		if (m0 == 0)
694			break;
695
696#if NBPFILTER > 0
697		if (ifp->if_bpf)
698			bpf_mtap(ifp->if_bpf, m0);
699#endif
700
701		cnw_transmit(sc, m0);
702		++ifp->if_opackets;
703		ifp->if_timer = 3; /* start watchdog timer */
704
705		microtime(&sc->sc_txlast);
706		sc->sc_active = 1;
707	}
708
709	ifp->if_flags &= ~IFF_OACTIVE;
710}
711
712/*
713 * Transmit a packet.
714 */
715void
716cnw_transmit(sc, m0)
717	struct cnw_softc *sc;
718	struct mbuf *m0;
719{
720	int buffer, bufsize, bufoffset, bufptr, bufspace, len, mbytes, n;
721	struct mbuf *m;
722	u_int8_t *mptr;
723
724	/* Get buffer info from card */
725	buffer = read16(sc, CNW_EREG_TDP);
726	bufsize = read16(sc, CNW_EREG_TDP + 2);
727	bufoffset = read16(sc, CNW_EREG_TDP + 4);
728#ifdef CNW_DEBUG
729	if (sc->sc_ethercom.ec_if.if_flags & IFF_DEBUG)
730		printf("%s: cnw_transmit b=0x%x s=%d o=0x%x\n",
731		    sc->sc_dev.dv_xname, buffer, bufsize, bufoffset);
732#endif
733
734	/* Copy data from mbuf chain to card buffers */
735	bufptr = sc->sc_memoff + buffer + bufoffset;
736	bufspace = bufsize;
737	len = 0;
738	for (m = m0; m; ) {
739		mptr = mtod(m, u_int8_t *);
740		mbytes = m->m_len;
741		len += mbytes;
742		while (mbytes > 0) {
743			if (bufspace == 0) {
744				buffer = read16(sc, buffer);
745				bufptr = sc->sc_memoff + buffer + bufoffset;
746				bufspace = bufsize;
747#ifdef CNW_DEBUG
748				if (sc->sc_ethercom.ec_if.if_flags & IFF_DEBUG)
749					printf("%s:   next buffer @0x%x\n",
750					    sc->sc_dev.dv_xname, buffer);
751#endif
752			}
753			n = mbytes <= bufspace ? mbytes : bufspace;
754			bus_space_write_region_1(sc->sc_memt, sc->sc_memh,
755			    bufptr, mptr, n);
756			bufptr += n;
757			bufspace -= n;
758			mptr += n;
759			mbytes -= n;
760		}
761		MFREE(m, m0);
762		m = m0;
763	}
764
765	/* Issue transmit command */
766	CNW_CMD2(sc, CNW_CMD_TL, len, len >> 8);
767}
768
769
770/*
771 * Pull a packet from the card into an mbuf chain.
772 */
773struct mbuf *
774cnw_read(sc)
775	struct cnw_softc *sc;
776{
777	struct mbuf *m, *top, **mp;
778	int totbytes, buffer, bufbytes, bufptr, mbytes, n;
779	u_int8_t *mptr;
780
781	WAIT_WOC(sc);
782	totbytes = read16(sc, CNW_EREG_RDP);
783#ifdef CNW_DEBUG
784	if (sc->sc_ethercom.ec_if.if_flags & IFF_DEBUG)
785		printf("%s: recv %d bytes\n", sc->sc_dev.dv_xname, totbytes);
786#endif
787	buffer = CNW_EREG_RDP + 2;
788	bufbytes = 0;
789	bufptr = 0; /* XXX make gcc happy */
790
791	MGETHDR(m, M_DONTWAIT, MT_DATA);
792	if (m == 0)
793		return (0);
794	m->m_pkthdr.rcvif = &sc->sc_ethercom.ec_if;
795	m->m_pkthdr.len = totbytes;
796	mbytes = MHLEN;
797	top = 0;
798	mp = &top;
799
800	while (totbytes > 0) {
801		if (top) {
802			MGET(m, M_DONTWAIT, MT_DATA);
803			if (m == 0) {
804				m_freem(top);
805				return (0);
806			}
807			mbytes = MLEN;
808		}
809		if (totbytes >= MINCLSIZE) {
810			MCLGET(m, M_DONTWAIT);
811			if ((m->m_flags & M_EXT) == 0) {
812				m_free(m);
813				m_freem(top);
814				return (0);
815			}
816			mbytes = MCLBYTES;
817		}
818		if (!top) {
819			int pad = ALIGN(sizeof(struct ether_header)) -
820			    sizeof(struct ether_header);
821			m->m_data += pad;
822			mbytes -= pad;
823		}
824		mptr = mtod(m, u_int8_t *);
825		mbytes = m->m_len = min(totbytes, mbytes);
826		totbytes -= mbytes;
827		while (mbytes > 0) {
828			if (bufbytes == 0) {
829				buffer = read16(sc, buffer);
830				bufbytes = read16(sc, buffer + 2);
831				bufptr = sc->sc_memoff + buffer +
832				    read16(sc, buffer + 4);
833#ifdef CNW_DEBUG
834				if (sc->sc_ethercom.ec_if.if_flags & IFF_DEBUG)
835					printf("%s:   %d bytes @0x%x+0x%x\n",
836					    sc->sc_dev.dv_xname, bufbytes,
837					    buffer, bufptr - buffer -
838					    sc->sc_memoff);
839#endif
840			}
841			n = mbytes <= bufbytes ? mbytes : bufbytes;
842			bus_space_read_region_1(sc->sc_memt, sc->sc_memh,
843			    bufptr, mptr, n);
844			bufbytes -= n;
845			bufptr += n;
846			mbytes -= n;
847			mptr += n;
848		}
849		*mp = m;
850		mp = &m->m_next;
851	}
852
853	return (top);
854}
855
856
857/*
858 * Handle received packets.
859 */
860void
861cnw_recv(sc)
862	struct cnw_softc *sc;
863{
864	int rser;
865	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
866	struct mbuf *m;
867
868	for (;;) {
869		WAIT_WOC(sc);
870		rser = bus_space_read_1(sc->sc_memt, sc->sc_memh,
871		    sc->sc_memoff + CNW_EREG_RSER);
872		if (!(rser & CNW_RSER_RXAVAIL))
873			return;
874
875		/* Pull packet off card */
876		m = cnw_read(sc);
877
878		/* Acknowledge packet */
879		CNW_CMD0(sc, CNW_CMD_SRP);
880
881		/* Did we manage to get the packet from the interface? */
882		if (m == 0) {
883			++ifp->if_ierrors;
884			return;
885		}
886		++ifp->if_ipackets;
887
888#if NBPFILTER > 0
889		if (ifp->if_bpf)
890			bpf_mtap(ifp->if_bpf, m);
891#endif
892
893		/* Pass the packet up. */
894		(*ifp->if_input)(ifp, m);
895	}
896}
897
898
899/*
900 * Interrupt handler.
901 */
902int
903cnw_intr(arg)
904	void *arg;
905{
906	struct cnw_softc *sc = arg;
907	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
908	int ret, status, rser, tser;
909
910	if ((sc->sc_ethercom.ec_if.if_flags & IFF_RUNNING) == 0 ||
911	    (sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
912		return (0);
913	ifp->if_timer = 0;	/* stop watchdog timer */
914
915	ret = 0;
916	for (;;) {
917		WAIT_WOC(sc);
918#ifndef MEMORY_MAPPED
919		status = bus_space_read_1(sc->sc_iot, sc->sc_ioh,
920		    CNW_REG_CCSR);
921#else
922		status = bus_space_read_1(sc->sc_memt, sc->sc_memh,
923		    sc->sc_memoff + CNW_IOM_OFF + CNW_REG_CCSR);
924#endif
925		if (!(status & 0x02)) {
926			if (ret == 0)
927				printf("%s: spurious interrupt\n",
928				    sc->sc_dev.dv_xname);
929			return (ret);
930		}
931		ret = 1;
932#ifndef MEMORY_MAPPED
933		status = bus_space_read_1(sc->sc_iot, sc->sc_ioh, CNW_REG_ASR);
934#else
935		status = bus_space_read_1(sc->sc_memt, sc->sc_memh,
936		    sc->sc_memoff + CNW_IOM_OFF + CNW_REG_ASR);
937#endif
938
939		/* Anything to receive? */
940		if (status & CNW_ASR_RXRDY) {
941			sc->sc_stats.nws_rx++;
942			cnw_recv(sc);
943		}
944
945		/* Receive error */
946		if (status & CNW_ASR_RXERR) {
947			/*
948			 * I get a *lot* of spurious receive errors
949			 * (many per second), even when the interface
950			 * is quiescent, so we don't increment
951			 * if_ierrors here.
952			 */
953			rser = bus_space_read_1(sc->sc_memt, sc->sc_memh,
954			    sc->sc_memoff + CNW_EREG_RSER);
955
956			/* RX statistics */
957			sc->sc_stats.nws_rxerr++;
958			if (rser & CNW_RSER_RXBIG)
959				sc->sc_stats.nws_rxframe++;
960			if (rser & CNW_RSER_RXCRC)
961				sc->sc_stats.nws_rxcrcerror++;
962			if (rser & CNW_RSER_RXOVERRUN)
963				sc->sc_stats.nws_rxoverrun++;
964			if (rser & CNW_RSER_RXOVERFLOW)
965				sc->sc_stats.nws_rxoverflow++;
966			if (rser & CNW_RSER_RXERR)
967				sc->sc_stats.nws_rxerrors++;
968			if (rser & CNW_RSER_RXAVAIL)
969				sc->sc_stats.nws_rxavail++;
970
971			/* Clear error bits in RSER */
972			WAIT_WOC(sc);
973			bus_space_write_1(sc->sc_memt, sc->sc_memh,
974			    sc->sc_memoff + CNW_EREG_RSERW,
975			    CNW_RSER_RXERR |
976			    (rser & (CNW_RSER_RXCRC | CNW_RSER_RXBIG)));
977			/* Clear RXERR in ASR */
978			WAIT_WOC(sc);
979			bus_space_write_1(sc->sc_memt, sc->sc_memh,
980			    sc->sc_memoff + CNW_EREG_ASCC, CNW_ASR_RXERR);
981		}
982
983		/* Transmit done */
984		if (status & CNW_ASR_TXDN) {
985			tser = bus_space_read_1(sc->sc_memt, sc->sc_memh,
986						CNW_EREG_TSER);
987
988			/* TX statistics */
989			if (tser & CNW_TSER_TXERR)
990				sc->sc_stats.nws_txerrors++;
991			if (tser & CNW_TSER_TXNOAP)
992				sc->sc_stats.nws_txlostcd++;
993			if (tser & CNW_TSER_TXGU)
994				sc->sc_stats.nws_txabort++;
995
996			if (tser & CNW_TSER_TXOK) {
997				sc->sc_stats.nws_txokay++;
998				sc->sc_stats.nws_txretries[status & 0xf]++;
999				WAIT_WOC(sc);
1000				bus_space_write_1(sc->sc_memt, sc->sc_memh,
1001				    sc->sc_memoff + CNW_EREG_TSERW,
1002				    CNW_TSER_TXOK | CNW_TSER_RTRY);
1003			}
1004
1005			if (tser & CNW_TSER_ERROR) {
1006				++ifp->if_oerrors;
1007				WAIT_WOC(sc);
1008				bus_space_write_1(sc->sc_memt, sc->sc_memh,
1009				    sc->sc_memoff + CNW_EREG_TSERW,
1010				    (tser & CNW_TSER_ERROR) |
1011				    CNW_TSER_RTRY);
1012			}
1013
1014			sc->sc_active = 0;
1015			ifp->if_flags &= ~IFF_OACTIVE;
1016
1017			/* Continue to send packets from the queue */
1018			cnw_start(&sc->sc_ethercom.ec_if);
1019		}
1020
1021	}
1022}
1023
1024
1025/*
1026 * Handle device ioctls.
1027 */
1028int
1029cnw_ioctl(ifp, cmd, data)
1030	struct ifnet *ifp;
1031	u_long cmd;
1032	caddr_t data;
1033{
1034	struct cnw_softc *sc = ifp->if_softc;
1035	struct ifaddr *ifa = (struct ifaddr *)data;
1036	struct ifreq *ifr = (struct ifreq *)data;
1037	int s, error = 0;
1038	struct proc *p = curproc;	/*XXX*/
1039
1040	s = splnet();
1041
1042	switch (cmd) {
1043
1044	case SIOCSIFADDR:
1045		if (!(ifp->if_flags & IFF_RUNNING) &&
1046		    (error = cnw_enable(sc)) != 0)
1047			break;
1048		ifp->if_flags |= IFF_UP;
1049		switch (ifa->ifa_addr->sa_family) {
1050#ifdef INET
1051		case AF_INET:
1052			cnw_init(sc);
1053			arp_ifinit(&sc->sc_ethercom.ec_if, ifa);
1054			break;
1055#endif
1056		default:
1057			cnw_init(sc);
1058			break;
1059		}
1060		break;
1061
1062	case SIOCSIFFLAGS:
1063		if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == IFF_RUNNING) {
1064			/*
1065			 * The interface is marked down and it is running, so
1066			 * stop it.
1067			 */
1068			cnw_disable(sc);
1069		} else if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == IFF_UP){
1070			/*
1071			 * The interface is marked up and it is stopped, so
1072			 * start it.
1073			 */
1074			error = cnw_enable(sc);
1075		} else {
1076			/* IFF_PROMISC may be changed */
1077			cnw_init(sc);
1078		}
1079		break;
1080
1081	case SIOCADDMULTI:
1082	case SIOCDELMULTI:
1083		/* Update our multicast list. */
1084		error = (cmd == SIOCADDMULTI) ?
1085		    ether_addmulti(ifr, &sc->sc_ethercom) :
1086		    ether_delmulti(ifr, &sc->sc_ethercom);
1087		if (error == ENETRESET) {
1088			if (ifp->if_flags & IFF_RUNNING)
1089				cnw_init(sc);
1090			error = 0;
1091		}
1092		break;
1093
1094	case SIOCGCNWDOMAIN:
1095		((struct ifreq *)data)->ifr_domain = sc->sc_domain;
1096		break;
1097
1098	case SIOCSCNWDOMAIN:
1099		error = suser(p->p_ucred, &p->p_acflag);
1100		if (error)
1101			break;
1102		error = cnw_setdomain(sc, ifr->ifr_domain);
1103		break;
1104
1105	case SIOCSCNWKEY:
1106		error = suser(p->p_ucred, &p->p_acflag);
1107		if (error)
1108			break;
1109		error = cnw_setkey(sc, ifr->ifr_key);
1110		break;
1111
1112	case SIOCGCNWSTATUS:
1113		error = suser(p->p_ucred, &p->p_acflag);
1114		if (error)
1115			break;
1116		if ((ifp->if_flags & IFF_RUNNING) == 0)
1117			break;
1118		bus_space_read_region_1(sc->sc_memt, sc->sc_memh,
1119		    sc->sc_memoff + CNW_EREG_CB,
1120		    ((struct cnwstatus *)data)->data,
1121		    sizeof(((struct cnwstatus *)data)->data));
1122		break;
1123
1124	case SIOCGCNWSTATS:
1125		memcpy((void *)&(((struct cnwistats *)data)->stats),
1126		    (void *)&sc->sc_stats, sizeof(struct cnwstats));
1127			break;
1128
1129	default:
1130		error = EINVAL;
1131		break;
1132	}
1133
1134	splx(s);
1135	return (error);
1136}
1137
1138
1139/*
1140 * Device timeout/watchdog routine. Entered if the device neglects to
1141 * generate an interrupt after a transmit has been started on it.
1142 */
1143void
1144cnw_watchdog(ifp)
1145	struct ifnet *ifp;
1146{
1147	struct cnw_softc *sc = ifp->if_softc;
1148
1149	printf("%s: device timeout; card reset\n", sc->sc_dev.dv_xname);
1150	++ifp->if_oerrors;
1151	cnw_init(sc);
1152}
1153
1154int
1155cnw_setdomain(sc, domain)
1156	struct cnw_softc *sc;
1157	int domain;
1158{
1159	int s;
1160
1161	if (domain & ~0x1ff)
1162		return EINVAL;
1163
1164	s = splnet();
1165	CNW_CMD2(sc, CNW_CMD_SMD, domain, domain >> 8);
1166	splx(s);
1167
1168	sc->sc_domain = domain;
1169	return 0;
1170}
1171
1172int
1173cnw_setkey(sc, key)
1174	struct cnw_softc *sc;
1175	int key;
1176{
1177	int s;
1178
1179	if (key & ~0xffff)
1180		return EINVAL;
1181
1182	s = splnet();
1183	CNW_CMD2(sc, CNW_CMD_SSK, key, key >> 8);
1184	splx(s);
1185
1186	sc->sc_skey = key;
1187	return 0;
1188}
1189
1190int
1191cnw_activate(self, act)
1192	struct device *self;
1193	enum devact act;
1194{
1195	struct cnw_softc *sc = (struct cnw_softc *)self;
1196	int rv = 0, s;
1197
1198	s = splnet();
1199	switch (act) {
1200	case DVACT_ACTIVATE:
1201		rv = EOPNOTSUPP;
1202		break;
1203
1204	case DVACT_DEACTIVATE:
1205		if_deactivate(&sc->sc_ethercom.ec_if);
1206		break;
1207	}
1208	splx(s);
1209	return (rv);
1210}
1211
1212int
1213cnw_detach(self, flags)
1214	struct device *self;
1215	int flags;
1216{
1217	struct cnw_softc *sc = (struct cnw_softc *)self;
1218	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1219
1220	/* cnw_disable() checks IFF_RUNNING */
1221	cnw_disable(sc);
1222
1223	if ((sc->sc_resource & CNW_RES_NET) != 0) {
1224		ether_ifdetach(ifp);
1225		if_detach(ifp);
1226	}
1227
1228#ifndef MEMORY_MAPPED
1229	/* unmap and free our i/o windows */
1230	if ((sc->sc_resource & CNW_RES_IO) != 0) {
1231		pcmcia_io_unmap(sc->sc_pf, sc->sc_iowin);
1232		pcmcia_io_free(sc->sc_pf, &sc->sc_pcioh);
1233	}
1234#endif
1235
1236	/* unmap and free our memory windows */
1237	if ((sc->sc_resource & CNW_RES_MEM) != 0) {
1238		pcmcia_mem_unmap(sc->sc_pf, sc->sc_memwin);
1239		pcmcia_mem_free(sc->sc_pf, &sc->sc_pcmemh);
1240	}
1241
1242	return (0);
1243}
1244