1 /* $NetBSD: if_ral_cardbus.c,v 1.15 2009/05/12 12:11:17 cegger Exp $ */
2 /* $OpenBSD: if_ral_cardbus.c,v 1.6 2006/01/09 20:03:31 damien Exp $ */
5 * Copyright (c) 2005, 2006
6 * Damien Bergamini <damien.bergamini@free.fr>
8 * Permission to use, copy, modify, and distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 * CardBus front-end for the Ralink RT2560/RT2561/RT2561S/RT2661 driver.
24 #include <sys/cdefs.h>
25 __KERNEL_RCSID(0, "$NetBSD: if_ral_cardbus.c,v 1.15 2009/05/12 12:11:17 cegger Exp $");
29 #include <sys/param.h>
30 #include <sys/sockio.h>
32 #include <sys/kernel.h>
33 #include <sys/socket.h>
34 #include <sys/systm.h>
35 #include <sys/malloc.h>
36 #include <sys/callout.h>
37 #include <sys/device.h>
43 #include <net/if_dl.h>
44 #include <net/if_media.h>
45 #include <net/if_ether.h>
47 #include <netinet/in.h>
49 #include <net80211/ieee80211_var.h>
50 #include <net80211/ieee80211_amrr.h>
51 #include <net80211/ieee80211_rssadapt.h>
52 #include <net80211/ieee80211_radiotap.h>
54 #include <dev/ic/rt2560var.h>
55 #include <dev/ic/rt2661var.h>
57 #include <dev/pci/pcireg.h>
58 #include <dev/pci/pcivar.h>
59 #include <dev/pci/pcidevs.h>
61 #include <dev/cardbus/cardbusvar.h>
63 static struct ral_opns
{
64 int (*attach
)(void *, int);
65 int (*detach
)(void *);
73 }, ral_rt2661_opns
= {
79 struct ral_cardbus_softc
{
81 struct rt2560_softc sc_rt2560
;
82 struct rt2661_softc sc_rt2661
;
84 #define sc_sc u.sc_rt2560
86 /* cardbus specific goo */
87 struct ral_opns
*sc_opns
;
88 cardbus_devfunc_t sc_ct
;
91 bus_size_t sc_mapsize
;
93 cardbus_intr_line_t sc_intrline
;
96 int ral_cardbus_match(device_t
, cfdata_t
, void *);
97 void ral_cardbus_attach(device_t
, device_t
, void *);
98 int ral_cardbus_detach(device_t
, int);
100 CFATTACH_DECL(ral_cardbus
, sizeof (struct ral_cardbus_softc
),
101 ral_cardbus_match
, ral_cardbus_attach
, ral_cardbus_detach
, NULL
);
103 int ral_cardbus_enable(struct rt2560_softc
*);
104 void ral_cardbus_disable(struct rt2560_softc
*);
105 void ral_cardbus_power(struct rt2560_softc
*, int);
106 void ral_cardbus_setup(struct ral_cardbus_softc
*);
109 ral_cardbus_match(device_t parent
,
110 cfdata_t cfdata
, void *aux
)
112 struct cardbus_attach_args
*ca
= aux
;
114 if (PCI_VENDOR(ca
->ca_id
) == PCI_VENDOR_RALINK
) {
115 switch (PCI_PRODUCT(ca
->ca_id
)) {
116 case PCI_PRODUCT_RALINK_RT2560
:
117 case PCI_PRODUCT_RALINK_RT2561
:
118 case PCI_PRODUCT_RALINK_RT2561S
:
119 case PCI_PRODUCT_RALINK_RT2661
:
130 ral_cardbus_attach(device_t parent
, device_t self
,
133 struct ral_cardbus_softc
*csc
= (struct ral_cardbus_softc
*)self
;
134 struct rt2560_softc
*sc
= &csc
->sc_sc
;
135 struct cardbus_attach_args
*ca
= aux
;
136 cardbus_devfunc_t ct
= ca
->ca_ct
;
141 pci_devinfo(ca
->ca_id
, ca
->ca_class
, 0, devinfo
, sizeof(devinfo
));
142 revision
= PCI_REVISION(ca
->ca_class
);
143 aprint_normal(": %s (rev. 0x%02x)\n", devinfo
, revision
);
146 (CARDBUS_PRODUCT(ca
->ca_id
) == PCI_PRODUCT_RALINK_RT2560
) ?
147 &ral_rt2560_opns
: &ral_rt2661_opns
;
149 sc
->sc_dmat
= ca
->ca_dmat
;
151 csc
->sc_tag
= ca
->ca_tag
;
152 csc
->sc_intrline
= ca
->ca_intrline
;
154 /* power management hooks */
155 sc
->sc_enable
= ral_cardbus_enable
;
156 sc
->sc_disable
= ral_cardbus_disable
;
158 /* map control/status registers */
159 error
= Cardbus_mapreg_map(ct
, CARDBUS_BASE0_REG
,
160 CARDBUS_MAPREG_TYPE_MEM
, 0, &sc
->sc_st
, &sc
->sc_sh
, &base
,
163 printf(": could not map memory space\n");
169 (*cf
->cardbus_mem_open
)(cc
, 0, base
, base
+ csc
->sc_mapsize
);
172 csc
->sc_bar_val
= base
| CARDBUS_MAPREG_TYPE_MEM
;
174 /* set up the PCI configuration registers */
175 ral_cardbus_setup(csc
);
177 (*csc
->sc_opns
->attach
)(sc
, CARDBUS_PRODUCT(ca
->ca_id
));
179 Cardbus_function_disable(ct
);
183 ral_cardbus_detach(device_t self
, int flags
)
185 struct ral_cardbus_softc
*csc
= (struct ral_cardbus_softc
*)self
;
186 struct rt2560_softc
*sc
= &csc
->sc_sc
;
187 cardbus_devfunc_t ct
= csc
->sc_ct
;
188 cardbus_chipset_tag_t cc
= ct
->ct_cc
;
189 cardbus_function_tag_t cf
= ct
->ct_cf
;
192 error
= (*csc
->sc_opns
->detach
)(sc
);
196 /* unhook the interrupt handler */
197 if (csc
->sc_ih
!= NULL
) {
198 cardbus_intr_disestablish(cc
, cf
, csc
->sc_ih
);
202 /* release bus space and close window */
203 Cardbus_mapreg_unmap(ct
, CARDBUS_BASE0_REG
, sc
->sc_st
, sc
->sc_sh
,
210 ral_cardbus_enable(struct rt2560_softc
*sc
)
212 struct ral_cardbus_softc
*csc
= (struct ral_cardbus_softc
*)sc
;
213 cardbus_devfunc_t ct
= csc
->sc_ct
;
214 cardbus_chipset_tag_t cc
= ct
->ct_cc
;
215 cardbus_function_tag_t cf
= ct
->ct_cf
;
217 /* power on the socket */
218 Cardbus_function_enable(ct
);
220 /* setup the PCI configuration registers */
221 ral_cardbus_setup(csc
);
223 /* map and establish the interrupt handler */
224 csc
->sc_ih
= cardbus_intr_establish(cc
, cf
, csc
->sc_intrline
, IPL_NET
,
225 csc
->sc_opns
->intr
, sc
);
226 if (csc
->sc_ih
== NULL
) {
227 aprint_error_dev(&sc
->sc_dev
,
228 "could not establish interrupt\n");
229 Cardbus_function_disable(ct
);
237 ral_cardbus_disable(struct rt2560_softc
*sc
)
239 struct ral_cardbus_softc
*csc
= (struct ral_cardbus_softc
*)sc
;
240 cardbus_devfunc_t ct
= csc
->sc_ct
;
241 cardbus_chipset_tag_t cc
= ct
->ct_cc
;
242 cardbus_function_tag_t cf
= ct
->ct_cf
;
244 /* unhook the interrupt handler */
245 cardbus_intr_disestablish(cc
, cf
, csc
->sc_ih
);
248 /* power down the socket */
249 Cardbus_function_disable(ct
);
253 ral_cardbus_setup(struct ral_cardbus_softc
*csc
)
255 cardbus_devfunc_t ct
= csc
->sc_ct
;
256 cardbus_chipset_tag_t cc
= ct
->ct_cc
;
257 cardbus_function_tag_t cf
= ct
->ct_cf
;
260 /* program the BAR */
261 cardbus_conf_write(cc
, cf
, csc
->sc_tag
, CARDBUS_BASE0_REG
,
264 /* make sure the right access type is on the cardbus bridge */
265 (*cf
->cardbus_ctrl
)(cc
, CARDBUS_MEM_ENABLE
);
266 (*cf
->cardbus_ctrl
)(cc
, CARDBUS_BM_ENABLE
);
268 /* enable the appropriate bits in the PCI CSR */
269 reg
= cardbus_conf_read(cc
, cf
, csc
->sc_tag
,
270 CARDBUS_COMMAND_STATUS_REG
);
271 reg
|= CARDBUS_COMMAND_MASTER_ENABLE
| CARDBUS_COMMAND_MEM_ENABLE
;
272 cardbus_conf_write(cc
, cf
, csc
->sc_tag
, CARDBUS_COMMAND_STATUS_REG
,