Line data Source code
1 : /* $OpenBSD: if_ral_pci.c,v 1.26 2017/05/31 03:45:15 jsg Exp $ */
2 :
3 : /*-
4 : * Copyright (c) 2005-2010 Damien Bergamini <damien.bergamini@free.fr>
5 : *
6 : * Permission to use, copy, modify, and distribute this software for any
7 : * purpose with or without fee is hereby granted, provided that the above
8 : * copyright notice and this permission notice appear in all copies.
9 : *
10 : * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 : * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 : * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 : * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 : * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 : * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 : * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 : */
18 :
19 : /*
20 : * PCI front-end for the Ralink RT2560/RT2561/RT2860/RT3090 driver.
21 : */
22 :
23 : #include "bpfilter.h"
24 :
25 : #include <sys/param.h>
26 : #include <sys/sockio.h>
27 : #include <sys/mbuf.h>
28 : #include <sys/kernel.h>
29 : #include <sys/socket.h>
30 : #include <sys/systm.h>
31 : #include <sys/malloc.h>
32 : #include <sys/timeout.h>
33 : #include <sys/device.h>
34 :
35 : #include <machine/bus.h>
36 : #include <machine/intr.h>
37 :
38 : #include <net/if.h>
39 : #include <net/if_media.h>
40 :
41 : #include <netinet/in.h>
42 : #include <netinet/if_ether.h>
43 :
44 : #include <net80211/ieee80211_var.h>
45 : #include <net80211/ieee80211_amrr.h>
46 : #include <net80211/ieee80211_radiotap.h>
47 :
48 : #include <dev/ic/rt2560var.h>
49 : #include <dev/ic/rt2661var.h>
50 : #include <dev/ic/rt2860var.h>
51 :
52 : #include <dev/pci/pcireg.h>
53 : #include <dev/pci/pcivar.h>
54 : #include <dev/pci/pcidevs.h>
55 :
56 : static struct ral_opns {
57 : int (*attach)(void *, int);
58 : int (*detach)(void *);
59 : void (*suspend)(void *);
60 : void (*wakeup)(void *);
61 : int (*intr)(void *);
62 :
63 : } ral_rt2560_opns = {
64 : rt2560_attach,
65 : rt2560_detach,
66 : rt2560_suspend,
67 : rt2560_wakeup,
68 : rt2560_intr
69 :
70 : }, ral_rt2661_opns = {
71 : rt2661_attach,
72 : rt2661_detach,
73 : rt2661_suspend,
74 : rt2661_wakeup,
75 : rt2661_intr
76 :
77 : }, ral_rt2860_opns = {
78 : rt2860_attach,
79 : rt2860_detach,
80 : rt2860_suspend,
81 : rt2860_wakeup,
82 : rt2860_intr
83 : };
84 :
85 : struct ral_pci_softc {
86 : union {
87 : struct rt2560_softc sc_rt2560;
88 : struct rt2661_softc sc_rt2661;
89 : struct rt2860_softc sc_rt2860;
90 : } u;
91 : #define sc_sc u.sc_rt2560
92 :
93 : /* PCI specific goo */
94 : struct ral_opns *sc_opns;
95 : pci_chipset_tag_t sc_pc;
96 : void *sc_ih;
97 : bus_size_t sc_mapsize;
98 : };
99 :
100 : /* Base Address Register */
101 : #define RAL_PCI_BAR0 0x10
102 :
103 : int ral_pci_match(struct device *, void *, void *);
104 : void ral_pci_attach(struct device *, struct device *, void *);
105 : int ral_pci_detach(struct device *, int);
106 : int ral_pci_activate(struct device *, int);
107 : void ral_pci_wakeup(struct ral_pci_softc *);
108 :
109 : struct cfattach ral_pci_ca = {
110 : sizeof (struct ral_pci_softc), ral_pci_match, ral_pci_attach,
111 : ral_pci_detach, ral_pci_activate
112 : };
113 :
114 : const struct pci_matchid ral_pci_devices[] = {
115 : { PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT2560 },
116 : { PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT2561 },
117 : { PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT2561S },
118 : { PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT2661 },
119 : { PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT2860 },
120 : { PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT2890 },
121 : { PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT2760 },
122 : { PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT2790 },
123 : { PCI_VENDOR_AWT, PCI_PRODUCT_AWT_RT2890 },
124 : { PCI_VENDOR_EDIMAX, PCI_PRODUCT_EDIMAX_RT2860_1 },
125 : { PCI_VENDOR_EDIMAX, PCI_PRODUCT_EDIMAX_RT2860_2 },
126 : { PCI_VENDOR_EDIMAX, PCI_PRODUCT_EDIMAX_RT2860_3 },
127 : { PCI_VENDOR_EDIMAX, PCI_PRODUCT_EDIMAX_RT2860_4 },
128 : { PCI_VENDOR_EDIMAX, PCI_PRODUCT_EDIMAX_RT2860_5 },
129 : { PCI_VENDOR_EDIMAX, PCI_PRODUCT_EDIMAX_RT2860_6 },
130 : { PCI_VENDOR_EDIMAX, PCI_PRODUCT_EDIMAX_RT2860_7 },
131 : { PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT3060 },
132 : { PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT3062 },
133 : { PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT3090 },
134 : { PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT3091 },
135 : { PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT3092 },
136 : { PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT3562 },
137 : { PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT3592 },
138 : { PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT3593 },
139 : { PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT5360 },
140 : { PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT5390 },
141 : { PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT5392 },
142 : { PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT5390_1 },
143 : { PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT5390_2 },
144 : { PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT5390_3 }
145 : };
146 :
147 : int
148 0 : ral_pci_match(struct device *parent, void *match, void *aux)
149 : {
150 0 : return (pci_matchbyid((struct pci_attach_args *)aux, ral_pci_devices,
151 : nitems(ral_pci_devices)));
152 : }
153 :
154 : void
155 0 : ral_pci_attach(struct device *parent, struct device *self, void *aux)
156 : {
157 0 : struct ral_pci_softc *psc = (struct ral_pci_softc *)self;
158 0 : struct rt2560_softc *sc = &psc->sc_sc;
159 0 : struct pci_attach_args *pa = aux;
160 : const char *intrstr;
161 0 : pci_intr_handle_t ih;
162 : pcireg_t memtype;
163 : int error;
164 :
165 0 : if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_RALINK) {
166 0 : switch (PCI_PRODUCT(pa->pa_id)) {
167 : case PCI_PRODUCT_RALINK_RT2560:
168 0 : psc->sc_opns = &ral_rt2560_opns;
169 0 : break;
170 : case PCI_PRODUCT_RALINK_RT2561:
171 : case PCI_PRODUCT_RALINK_RT2561S:
172 : case PCI_PRODUCT_RALINK_RT2661:
173 0 : psc->sc_opns = &ral_rt2661_opns;
174 0 : break;
175 : default:
176 0 : psc->sc_opns = &ral_rt2860_opns;
177 0 : break;
178 : }
179 : } else {
180 : /* all other vendors are RT2860 only */
181 0 : psc->sc_opns = &ral_rt2860_opns;
182 : }
183 0 : sc->sc_dmat = pa->pa_dmat;
184 0 : psc->sc_pc = pa->pa_pc;
185 :
186 : /* map control/status registers */
187 0 : memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, RAL_PCI_BAR0);
188 0 : error = pci_mapreg_map(pa, RAL_PCI_BAR0, memtype, 0, &sc->sc_st,
189 0 : &sc->sc_sh, NULL, &psc->sc_mapsize, 0);
190 0 : if (error != 0) {
191 0 : printf(": can't map mem space\n");
192 0 : return;
193 : }
194 :
195 0 : if (pci_intr_map(pa, &ih) != 0) {
196 0 : printf(": can't map interrupt\n");
197 0 : return;
198 : }
199 :
200 0 : intrstr = pci_intr_string(psc->sc_pc, ih);
201 0 : psc->sc_ih = pci_intr_establish(psc->sc_pc, ih, IPL_NET,
202 0 : psc->sc_opns->intr, sc, sc->sc_dev.dv_xname);
203 0 : if (psc->sc_ih == NULL) {
204 0 : printf(": can't establish interrupt");
205 0 : if (intrstr != NULL)
206 0 : printf(" at %s", intrstr);
207 0 : printf("\n");
208 0 : return;
209 : }
210 0 : printf(": %s", intrstr);
211 :
212 0 : (*psc->sc_opns->attach)(sc, PCI_PRODUCT(pa->pa_id));
213 0 : }
214 :
215 : int
216 0 : ral_pci_detach(struct device *self, int flags)
217 : {
218 0 : struct ral_pci_softc *psc = (struct ral_pci_softc *)self;
219 0 : struct rt2560_softc *sc = &psc->sc_sc;
220 : int error;
221 :
222 0 : if (psc->sc_ih != NULL) {
223 0 : pci_intr_disestablish(psc->sc_pc, psc->sc_ih);
224 :
225 0 : error = (*psc->sc_opns->detach)(sc);
226 0 : if (error != 0)
227 0 : return error;
228 : }
229 :
230 0 : if (psc->sc_mapsize > 0)
231 0 : bus_space_unmap(sc->sc_st, sc->sc_sh, psc->sc_mapsize);
232 :
233 0 : return 0;
234 0 : }
235 :
236 : int
237 0 : ral_pci_activate(struct device *self, int act)
238 : {
239 0 : struct ral_pci_softc *psc = (struct ral_pci_softc *)self;
240 0 : struct rt2560_softc *sc = &psc->sc_sc;
241 :
242 0 : switch (act) {
243 : case DVACT_SUSPEND:
244 0 : (*psc->sc_opns->suspend)(sc);
245 0 : break;
246 : case DVACT_WAKEUP:
247 0 : ral_pci_wakeup(psc);
248 0 : break;
249 : }
250 0 : return 0;
251 : }
252 :
253 : void
254 0 : ral_pci_wakeup(struct ral_pci_softc *psc)
255 : {
256 0 : struct rt2560_softc *sc = &psc->sc_sc;
257 : int s;
258 :
259 0 : s = splnet();
260 0 : (*psc->sc_opns->wakeup)(sc);
261 0 : splx(s);
262 0 : }
|