Line data Source code
1 : /* $OpenBSD: if_malo_cardbus.c,v 1.12 2013/12/06 21:03:02 deraadt Exp $ */
2 :
3 : /*
4 : * Copyright (c) 2006 Claudio Jeker <claudio@openbsd.org>
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 : #include "bpfilter.h"
20 :
21 : #include <sys/param.h>
22 : #include <sys/mbuf.h>
23 : #include <sys/socket.h>
24 : #include <sys/systm.h>
25 : #include <sys/timeout.h>
26 :
27 : #include <net/if.h>
28 : #include <net/if_media.h>
29 :
30 : #include <netinet/in.h>
31 : #include <netinet/if_ether.h>
32 :
33 : #include <net80211/ieee80211_var.h>
34 : #include <net80211/ieee80211_radiotap.h>
35 :
36 : #include <dev/pci/pcireg.h>
37 : #include <dev/pci/pcivar.h>
38 : #include <dev/pci/pcidevs.h>
39 :
40 : #include <dev/cardbus/cardbusvar.h>
41 :
42 : #include <dev/ic/malo.h>
43 :
44 : struct malo_cardbus_softc {
45 : struct malo_softc sc_malo;
46 :
47 : /* cardbus specific goo */
48 : cardbus_devfunc_t sc_ct;
49 : pcitag_t sc_tag;
50 : void *sc_ih;
51 :
52 : bus_size_t sc_mapsize1;
53 : bus_size_t sc_mapsize2;
54 : pcireg_t sc_bar1_val;
55 : pcireg_t sc_bar2_val;
56 : int sc_intrline;
57 : pci_chipset_tag_t sc_pc;
58 : };
59 :
60 : int malo_cardbus_match(struct device *parent, void *match, void *aux);
61 : void malo_cardbus_attach(struct device *parent, struct device *self,
62 : void *aux);
63 : int malo_cardbus_detach(struct device *self, int flags);
64 : void malo_cardbus_setup(struct malo_cardbus_softc *csc);
65 : int malo_cardbus_enable(struct malo_softc *sc);
66 : void malo_cardbus_disable(struct malo_softc *sc);
67 :
68 : struct cfattach malo_cardbus_ca = {
69 : sizeof (struct malo_cardbus_softc), malo_cardbus_match,
70 : malo_cardbus_attach, malo_cardbus_detach
71 : };
72 :
73 : static const struct pci_matchid malo_cardbus_devices[] = {
74 : { PCI_VENDOR_MARVELL, PCI_PRODUCT_MARVELL_88W8310 },
75 : { PCI_VENDOR_MARVELL, PCI_PRODUCT_MARVELL_88W8335_1 },
76 : { PCI_VENDOR_MARVELL, PCI_PRODUCT_MARVELL_88W8335_2 }
77 : };
78 :
79 : int
80 0 : malo_cardbus_match(struct device *parent, void *match, void *aux)
81 : {
82 0 : return (cardbus_matchbyid(aux, malo_cardbus_devices,
83 : sizeof (malo_cardbus_devices) / sizeof (malo_cardbus_devices[0])));
84 : }
85 :
86 : void
87 0 : malo_cardbus_attach(struct device *parent, struct device *self, void *aux)
88 : {
89 0 : struct malo_cardbus_softc *csc = (struct malo_cardbus_softc *)self;
90 0 : struct cardbus_attach_args *ca = aux;
91 0 : struct malo_softc *sc = &csc->sc_malo;
92 0 : cardbus_devfunc_t ct = ca->ca_ct;
93 0 : bus_addr_t base;
94 : int error;
95 :
96 0 : sc->sc_dmat = ca->ca_dmat;
97 0 : csc->sc_ct = ct;
98 0 : csc->sc_tag = ca->ca_tag;
99 0 : csc->sc_intrline = ca->ca_intrline;
100 0 : csc->sc_pc = ca->ca_pc;
101 :
102 : /* power management hooks */
103 0 : sc->sc_enable = malo_cardbus_enable;
104 0 : sc->sc_disable = malo_cardbus_disable;
105 : #if 0
106 : sc->sc_power = malo_cardbus_power;
107 : #endif
108 :
109 : /* map control/status registers */
110 0 : error = Cardbus_mapreg_map(ct, CARDBUS_BASE0_REG,
111 : PCI_MAPREG_TYPE_MEM, 0, &sc->sc_mem1_bt,
112 : &sc->sc_mem1_bh, &base, &csc->sc_mapsize1);
113 0 : if (error != 0) {
114 0 : printf(": can't map mem1 space\n");
115 0 : return;
116 : }
117 0 : csc->sc_bar1_val = base | PCI_MAPREG_TYPE_MEM;
118 :
119 : /* map control/status registers */
120 0 : error = Cardbus_mapreg_map(ct, CARDBUS_BASE1_REG,
121 : PCI_MAPREG_TYPE_MEM, 0, &sc->sc_mem2_bt,
122 : &sc->sc_mem2_bh, &base, &csc->sc_mapsize2);
123 0 : if (error != 0) {
124 0 : printf(": can't map mem2 space\n");
125 0 : Cardbus_mapreg_unmap(ct, CARDBUS_BASE0_REG, sc->sc_mem1_bt,
126 : sc->sc_mem1_bh, csc->sc_mapsize1);
127 0 : return;
128 : }
129 0 : csc->sc_bar2_val = base | PCI_MAPREG_TYPE_MEM;
130 :
131 : /* set up the PCI configuration registers */
132 0 : malo_cardbus_setup(csc);
133 :
134 0 : printf(": irq %d", csc->sc_intrline);
135 :
136 0 : error = malo_attach(sc);
137 0 : if (error != 0)
138 0 : malo_cardbus_detach(&sc->sc_dev, 0);
139 :
140 0 : Cardbus_function_disable(ct);
141 0 : }
142 :
143 : int
144 0 : malo_cardbus_detach(struct device *self, int flags)
145 : {
146 0 : struct malo_cardbus_softc *csc = (struct malo_cardbus_softc *)self;
147 0 : struct malo_softc *sc = &csc->sc_malo;
148 0 : cardbus_devfunc_t ct = csc->sc_ct;
149 0 : cardbus_chipset_tag_t cc = ct->ct_cc;
150 0 : cardbus_function_tag_t cf = ct->ct_cf;
151 : int error;
152 :
153 0 : error = malo_detach(sc);
154 0 : if (error != 0)
155 0 : return (error);
156 :
157 : /* unhook the interrupt handler */
158 0 : if (csc->sc_ih != NULL) {
159 0 : cardbus_intr_disestablish(cc, cf, csc->sc_ih);
160 0 : csc->sc_ih = NULL;
161 0 : }
162 :
163 : /* release bus space and close window */
164 0 : Cardbus_mapreg_unmap(ct, CARDBUS_BASE0_REG, sc->sc_mem1_bt,
165 : sc->sc_mem1_bh, csc->sc_mapsize1);
166 0 : Cardbus_mapreg_unmap(ct, CARDBUS_BASE1_REG, sc->sc_mem2_bt,
167 : sc->sc_mem2_bh, csc->sc_mapsize2);
168 :
169 0 : return (0);
170 0 : }
171 :
172 : void
173 0 : malo_cardbus_setup(struct malo_cardbus_softc *csc)
174 : {
175 0 : cardbus_devfunc_t ct = csc->sc_ct;
176 0 : cardbus_chipset_tag_t cc = ct->ct_cc;
177 0 : pci_chipset_tag_t pc = csc->sc_pc;
178 0 : cardbus_function_tag_t cf = ct->ct_cf;
179 : pcireg_t reg;
180 :
181 : /* program the BAR */
182 0 : pci_conf_write(pc, csc->sc_tag, CARDBUS_BASE0_REG,
183 0 : csc->sc_bar1_val);
184 0 : pci_conf_write(pc, csc->sc_tag, CARDBUS_BASE1_REG,
185 0 : csc->sc_bar2_val);
186 :
187 : /* make sure the right access type is on the cardbus bridge */
188 0 : (*cf->cardbus_ctrl)(cc, CARDBUS_MEM_ENABLE);
189 0 : (*cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);
190 :
191 : /* enable the appropriate bits in the PCI CSR */
192 0 : reg = pci_conf_read(pc, csc->sc_tag,
193 : PCI_COMMAND_STATUS_REG);
194 0 : reg |= PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_MEM_ENABLE;
195 0 : pci_conf_write(pc, csc->sc_tag, PCI_COMMAND_STATUS_REG,
196 : reg);
197 0 : }
198 :
199 : int
200 0 : malo_cardbus_enable(struct malo_softc *sc)
201 : {
202 0 : struct malo_cardbus_softc *csc = (struct malo_cardbus_softc *)sc;
203 0 : cardbus_devfunc_t ct = csc->sc_ct;
204 0 : cardbus_chipset_tag_t cc = ct->ct_cc;
205 0 : cardbus_function_tag_t cf = ct->ct_cf;
206 :
207 : /* power on the socket */
208 0 : Cardbus_function_enable(ct);
209 :
210 : /* setup the PCI configuration registers */
211 0 : malo_cardbus_setup(csc);
212 :
213 : /* map and establish the interrupt handler */
214 0 : csc->sc_ih = cardbus_intr_establish(cc, cf, csc->sc_intrline, IPL_NET,
215 0 : malo_intr, sc, sc->sc_dev.dv_xname);
216 0 : if (csc->sc_ih == NULL) {
217 0 : printf("%s: could not establish interrupt at %d\n",
218 0 : sc->sc_dev.dv_xname, csc->sc_intrline);
219 0 : Cardbus_function_disable(ct);
220 0 : return (1);
221 : }
222 :
223 0 : return (0);
224 0 : }
225 :
226 : void
227 0 : malo_cardbus_disable(struct malo_softc *sc)
228 : {
229 0 : struct malo_cardbus_softc *csc = (struct malo_cardbus_softc *)sc;
230 0 : cardbus_devfunc_t ct = csc->sc_ct;
231 0 : cardbus_chipset_tag_t cc = ct->ct_cc;
232 0 : cardbus_function_tag_t cf = ct->ct_cf;
233 :
234 : /* unhook the interrupt handler */
235 0 : cardbus_intr_disestablish(cc, cf, csc->sc_ih);
236 0 : csc->sc_ih = NULL;
237 :
238 : /* power down the socket */
239 0 : Cardbus_function_disable(ct);
240 0 : }
|