if_an_pccard.c revision 150447
1184610Salfred/*-
2184610Salfred * Copyright (c) 1997, 1998, 1999
3184610Salfred *	Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
4184610Salfred *
5184610Salfred * Redistribution and use in source and binary forms, with or without
6184610Salfred * modification, are permitted provided that the following conditions
7184610Salfred * are met:
8184610Salfred * 1. Redistributions of source code must retain the above copyright
9184610Salfred *    notice, this list of conditions and the following disclaimer.
10184610Salfred * 2. Redistributions in binary form must reproduce the above copyright
11184610Salfred *    notice, this list of conditions and the following disclaimer in the
12184610Salfred *    documentation and/or other materials provided with the distribution.
13184610Salfred * 3. All advertising materials mentioning features or use of this software
14184610Salfred *    must display the following acknowledgement:
15184610Salfred *	This product includes software developed by Bill Paul.
16184610Salfred * 4. Neither the name of the author nor the names of any co-contributors
17184610Salfred *    may be used to endorse or promote products derived from this software
18184610Salfred *    without specific prior written permission.
19184610Salfred *
20184610Salfred * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
21184610Salfred * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22184610Salfred * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23184610Salfred * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
24184610Salfred * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25184610Salfred * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26184610Salfred * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27184610Salfred * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28184610Salfred * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29184610Salfred * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30184610Salfred * THE POSSIBILITY OF SUCH DAMAGE.
31184610Salfred */
32184610Salfred/*
33184610Salfred * Aironet 4500/4800 802.11 PCMCIA/ISA/PCI driver for FreeBSD.
34184610Salfred *
35184610Salfred * Written by Bill Paul <wpaul@ctr.columbia.edu>
36184610Salfred * Electrical Engineering Department
37184610Salfred * Columbia University, New York City
38184610Salfred */
39184610Salfred
40184610Salfred#include <sys/cdefs.h>
41184610Salfred__FBSDID("$FreeBSD: head/sys/dev/an/if_an_pccard.c 150447 2005-09-22 04:49:17Z imp $");
42184610Salfred
43184610Salfred#include "opt_inet.h"
44184610Salfred
45184610Salfred#ifdef INET
46184610Salfred#define ANCACHE
47184610Salfred#endif
48184610Salfred
49184610Salfred#include <sys/param.h>
50184610Salfred#include <sys/systm.h>
51184610Salfred#include <sys/socket.h>
52184610Salfred#include <sys/kernel.h>
53184610Salfred
54184610Salfred#include <sys/module.h>
55184610Salfred#include <sys/bus.h>
56184610Salfred#include <machine/bus.h>
57184610Salfred#include <sys/rman.h>
58184610Salfred#include <sys/lock.h>
59184610Salfred#include <sys/mutex.h>
60184610Salfred#include <machine/resource.h>
61184610Salfred
62184610Salfred#include <net/if.h>
63184610Salfred#include <net/if_arp.h>
64184610Salfred#include <net/ethernet.h>
65184610Salfred#include <net/if_dl.h>
66184610Salfred#include <net/if_types.h>
67184610Salfred#include <net/if_media.h>
68184610Salfred
69184610Salfred#include <dev/an/if_aironet_ieee.h>
70184610Salfred#include <dev/an/if_anreg.h>
71184610Salfred
72184610Salfred#include <dev/pccard/pccardvar.h>
73184610Salfred
74184610Salfred#include "pccarddevs.h"
75184610Salfred#include "card_if.h"
76184610Salfred
77184610Salfred/*
78184610Salfred * Support for PCMCIA cards.
79184610Salfred */
80184610Salfredstatic int  an_pccard_match(device_t);
81184610Salfredstatic int  an_pccard_probe(device_t);
82184610Salfredstatic int  an_pccard_attach(device_t);
83184610Salfred
84184610Salfredstatic device_method_t an_pccard_methods[] = {
85184610Salfred	/* Device interface */
86184610Salfred	DEVMETHOD(device_probe,		pccard_compat_probe),
87184610Salfred	DEVMETHOD(device_attach,	pccard_compat_attach),
88184610Salfred	DEVMETHOD(device_detach,	an_detach),
89184610Salfred	DEVMETHOD(device_shutdown,	an_shutdown),
90184610Salfred
91184610Salfred	/* Card interface */
92184610Salfred	DEVMETHOD(card_compat_match, 	an_pccard_match),
93184610Salfred	DEVMETHOD(card_compat_probe,	an_pccard_probe),
94184610Salfred	DEVMETHOD(card_compat_attach,	an_pccard_attach),
95184610Salfred
96184610Salfred	{ 0, 0 }
97184610Salfred};
98184610Salfred
99184610Salfredstatic driver_t an_pccard_driver = {
100184610Salfred	"an",
101184610Salfred	an_pccard_methods,
102184610Salfred	sizeof(struct an_softc)
103184610Salfred};
104184610Salfred
105184610Salfredstatic devclass_t an_pccard_devclass;
106184610Salfred
107184610SalfredDRIVER_MODULE(an, pccard, an_pccard_driver, an_pccard_devclass, 0, 0);
108184610SalfredMODULE_DEPEND(an, wlan, 1, 1, 1);
109184610Salfred
110184610Salfredstatic const struct pccard_product an_pccard_products[] = {
111184610Salfred	PCMCIA_CARD(AIRONET, PC4800),
112184610Salfred	PCMCIA_CARD(AIRONET, PC4500),
113184610Salfred	PCMCIA_CARD(AIRONET, 350),
114184610Salfred	PCMCIA_CARD(XIRCOM, CWE1130),
115184610Salfred	{ NULL }
116184610Salfred};
117184610Salfred
118184610Salfredstatic int
119184610Salfredan_pccard_match(device_t dev)
120184610Salfred{
121184610Salfred	const struct pccard_product *pp;
122184610Salfred
123184610Salfred	if ((pp = pccard_product_lookup(dev, an_pccard_products,
124184610Salfred	    sizeof(an_pccard_products[0]), NULL)) != NULL) {
125184610Salfred		if (pp->pp_name != NULL)
126184610Salfred			device_set_desc(dev, pp->pp_name);
127184610Salfred		return (0);
128184610Salfred	}
129184610Salfred	return (ENXIO);
130184610Salfred}
131184610Salfred
132184610Salfredstatic int
133184610Salfredan_pccard_probe(device_t dev)
134184610Salfred{
135184610Salfred	int     error;
136184610Salfred
137184610Salfred	error = an_probe(dev); /* 0 is failure for now */
138184610Salfred	if (error != 0) {
139184610Salfred		device_set_desc(dev, "Aironet PC4500/PC4800");
140184610Salfred		error = an_alloc_irq(dev, 0, 0);
141184610Salfred	} else
142184610Salfred	        error = 1;
143184610Salfred	an_release_resources(dev);
144184610Salfred	return (error);
145184610Salfred}
146184610Salfred
147184610Salfred
148184610Salfredstatic int
149184610Salfredan_pccard_attach(device_t dev)
150184610Salfred{
151184610Salfred	struct an_softc *sc = device_get_softc(dev);
152184610Salfred	int flags = device_get_flags(dev);
153184610Salfred	int error;
154184610Salfred
155184610Salfred	an_alloc_port(dev, sc->port_rid, AN_IOSIZ);
156184610Salfred	an_alloc_irq(dev, sc->irq_rid, 0);
157184610Salfred
158184610Salfred	sc->an_bhandle = rman_get_bushandle(sc->port_res);
159184610Salfred	sc->an_btag = rman_get_bustag(sc->port_res);
160184610Salfred	sc->an_dev = dev;
161184610Salfred
162184610Salfred	error = an_attach(sc, device_get_unit(dev), flags);
163184610Salfred	if (error)
164184610Salfred		goto fail;
165184610Salfred
166184610Salfred	/*
167	 * Must setup the interrupt after the an_attach to prevent racing.
168	 */
169	error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET,
170			       an_intr, sc, &sc->irq_handle);
171fail:
172	if (error)
173		an_release_resources(dev);
174	return (error);
175}
176