1 /* $NetBSD: if_an_pcmcia.c,v 1.39 2009/05/12 14:42:18 cegger Exp $ */
4 * Copyright (c) 2000, 2004 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: if_an_pcmcia.c,v 1.39 2009/05/12 14:42:18 cegger Exp $");
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/callout.h>
39 #include <sys/socket.h>
40 #include <sys/ioctl.h>
41 #include <sys/errno.h>
42 #include <sys/syslog.h>
43 #include <sys/select.h>
44 #include <sys/device.h>
47 #include <net/if_dl.h>
48 #include <net/if_ether.h>
49 #include <net/if_media.h>
51 #include <net80211/ieee80211_netbsd.h>
52 #include <net80211/ieee80211_var.h>
58 #include <dev/ic/anreg.h>
59 #include <dev/ic/anvar.h>
61 #include <dev/pcmcia/pcmciareg.h>
62 #include <dev/pcmcia/pcmciavar.h>
63 #include <dev/pcmcia/pcmciadevs.h>
65 static int an_pcmcia_match(device_t
, cfdata_t
, void *);
66 static int an_pcmcia_validate_config(struct pcmcia_config_entry
*);
67 static void an_pcmcia_attach(device_t
, device_t
, void *);
68 static int an_pcmcia_detach(device_t
, int);
69 static int an_pcmcia_enable(struct an_softc
*);
70 static void an_pcmcia_disable(struct an_softc
*);
72 struct an_pcmcia_softc
{
73 struct an_softc sc_an
; /* real "an" softc */
75 /* PCMCIA-specific goo */
76 struct pcmcia_io_handle sc_pcioh
; /* PCMCIA i/o space info */
77 int sc_io_window
; /* our i/o window */
78 struct pcmcia_function
*sc_pf
; /* our PCMCIA function */
79 void *sc_ih
; /* interrupt handle */
82 #define AN_PCMCIA_ATTACHED 3
85 CFATTACH_DECL_NEW(an_pcmcia
, sizeof(struct an_pcmcia_softc
),
86 an_pcmcia_match
, an_pcmcia_attach
, an_pcmcia_detach
, an_activate
);
88 static const struct pcmcia_product an_pcmcia_products
[] = {
89 { PCMCIA_VENDOR_AIRONET
, PCMCIA_PRODUCT_AIRONET_PC4800
,
90 PCMCIA_CIS_AIRONET_PC4800
},
91 { PCMCIA_VENDOR_AIRONET
, PCMCIA_PRODUCT_AIRONET_PC4500
,
92 PCMCIA_CIS_AIRONET_PC4500
},
93 { PCMCIA_VENDOR_AIRONET
, PCMCIA_PRODUCT_AIRONET_350
,
94 PCMCIA_CIS_AIRONET_350
},
96 static const size_t an_pcmcia_nproducts
=
97 sizeof(an_pcmcia_products
) / sizeof(an_pcmcia_products
[0]);
100 an_pcmcia_match(device_t parent
, cfdata_t match
,
103 struct pcmcia_attach_args
*pa
= aux
;
105 if (pcmcia_product_lookup(pa
, an_pcmcia_products
, an_pcmcia_nproducts
,
106 sizeof(an_pcmcia_products
[0]), NULL
))
112 an_pcmcia_validate_config(struct pcmcia_config_entry
*cfe
)
114 if (cfe
->iftype
!= PCMCIA_IFTYPE_IO
||
115 cfe
->num_iospace
< 1)
121 an_pcmcia_attach(struct device
*parent
, device_t self
,
124 struct an_pcmcia_softc
*psc
= device_private(self
);
125 struct an_softc
*sc
= &psc
->sc_an
;
126 struct pcmcia_attach_args
*pa
= aux
;
127 struct pcmcia_config_entry
*cfe
;
133 error
= pcmcia_function_configure(pa
->pf
, an_pcmcia_validate_config
);
135 aprint_error_dev(self
, "configure failed, error=%d\n",
141 sc
->sc_iot
= cfe
->iospace
[0].handle
.iot
;
142 sc
->sc_ioh
= cfe
->iospace
[0].handle
.ioh
;
144 error
= an_pcmcia_enable(sc
);
149 sc
->sc_enable
= an_pcmcia_enable
;
150 sc
->sc_disable
= an_pcmcia_disable
;
152 error
= an_attach(sc
);
154 aprint_error_dev(self
, "failed to attach controller\n");
158 if (pmf_device_register(self
, NULL
, NULL
))
159 pmf_class_network_register(self
, &sc
->sc_if
);
161 aprint_error_dev(self
, "couldn't establish power handler\n");
163 an_pcmcia_disable(sc
);
165 psc
->sc_state
= AN_PCMCIA_ATTACHED
;
169 an_pcmcia_disable(sc
);
172 pcmcia_function_unconfigure(pa
->pf
);
177 an_pcmcia_detach(device_t self
, int flags
)
179 struct an_pcmcia_softc
*psc
= device_private(self
);
182 if (psc
->sc_state
!= AN_PCMCIA_ATTACHED
)
185 pmf_device_deregister(self
);
187 error
= an_detach(&psc
->sc_an
);
191 pcmcia_function_unconfigure(psc
->sc_pf
);
197 an_pcmcia_enable(struct an_softc
*sc
)
199 struct an_pcmcia_softc
*psc
= (void *)sc
;
202 /* establish the interrupt. */
203 psc
->sc_ih
= pcmcia_intr_establish(psc
->sc_pf
, IPL_NET
, an_intr
, sc
);
207 error
= pcmcia_function_enable(psc
->sc_pf
);
209 pcmcia_intr_disestablish(psc
->sc_pf
, psc
->sc_ih
);
217 an_pcmcia_disable(struct an_softc
*sc
)
219 struct an_pcmcia_softc
*psc
= (void *)sc
;
221 pcmcia_function_disable(psc
->sc_pf
);
222 pcmcia_intr_disestablish(psc
->sc_pf
, psc
->sc_ih
);