1 /* $OpenBSD: if_malo_cardbus.c,v 1.13 2022/04/06 18:59:28 naddy 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 const 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 malo_cardbus_match(struct device *parent, void *match, void *aux)
81 {
82 return (cardbus_matchbyid(aux, malo_cardbus_devices,
83 sizeof (malo_cardbus_devices) / sizeof (malo_cardbus_devices[0])));
84 }
85
86 void
87 malo_cardbus_attach(struct device *parent, struct device *self, void *aux)
88 {
89 struct malo_cardbus_softc *csc = (struct malo_cardbus_softc *)self;
90 struct cardbus_attach_args *ca = aux;
91 struct malo_softc *sc = &csc->sc_malo;
92 cardbus_devfunc_t ct = ca->ca_ct;
93 bus_addr_t base;
94 int error;
95
96 sc->sc_dmat = ca->ca_dmat;
97 csc->sc_ct = ct;
98 csc->sc_tag = ca->ca_tag;
99 csc->sc_intrline = ca->ca_intrline;
100 csc->sc_pc = ca->ca_pc;
101
102 /* power management hooks */
103 sc->sc_enable = malo_cardbus_enable;
104 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 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 if (error != 0) {
114 printf(": can't map mem1 space\n");
115 return;
116 }
117 csc->sc_bar1_val = base | PCI_MAPREG_TYPE_MEM;
118
119 /* map control/status registers */
120 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 if (error != 0) {
124 printf(": can't map mem2 space\n");
125 Cardbus_mapreg_unmap(ct, CARDBUS_BASE0_REG, sc->sc_mem1_bt,
126 sc->sc_mem1_bh, csc->sc_mapsize1);
127 return;
128 }
129 csc->sc_bar2_val = base | PCI_MAPREG_TYPE_MEM;
130
131 /* set up the PCI configuration registers */
132 malo_cardbus_setup(csc);
133
134 printf(": irq %d", csc->sc_intrline);
135
136 error = malo_attach(sc);
137 if (error != 0)
138 malo_cardbus_detach(&sc->sc_dev, 0);
139
140 Cardbus_function_disable(ct);
141 }
142
143 int
144 malo_cardbus_detach(struct device *self, int flags)
145 {
146 struct malo_cardbus_softc *csc = (struct malo_cardbus_softc *)self;
147 struct malo_softc *sc = &csc->sc_malo;
148 cardbus_devfunc_t ct = csc->sc_ct;
149 cardbus_chipset_tag_t cc = ct->ct_cc;
150 cardbus_function_tag_t cf = ct->ct_cf;
151 int error;
152
153 error = malo_detach(sc);
154 if (error != 0)
155 return (error);
156
157 /* unhook the interrupt handler */
158 if (csc->sc_ih != NULL) {
159 cardbus_intr_disestablish(cc, cf, csc->sc_ih);
160 csc->sc_ih = NULL;
161 }
162
163 /* release bus space and close window */
164 Cardbus_mapreg_unmap(ct, CARDBUS_BASE0_REG, sc->sc_mem1_bt,
165 sc->sc_mem1_bh, csc->sc_mapsize1);
166 Cardbus_mapreg_unmap(ct, CARDBUS_BASE1_REG, sc->sc_mem2_bt,
167 sc->sc_mem2_bh, csc->sc_mapsize2);
168
169 return (0);
170 }
171
172 void
173 malo_cardbus_setup(struct malo_cardbus_softc *csc)
174 {
175 cardbus_devfunc_t ct = csc->sc_ct;
176 cardbus_chipset_tag_t cc = ct->ct_cc;
177 pci_chipset_tag_t pc = csc->sc_pc;
178 cardbus_function_tag_t cf = ct->ct_cf;
179 pcireg_t reg;
180
181 /* program the BAR */
182 pci_conf_write(pc, csc->sc_tag, CARDBUS_BASE0_REG,
183 csc->sc_bar1_val);
184 pci_conf_write(pc, csc->sc_tag, CARDBUS_BASE1_REG,
185 csc->sc_bar2_val);
186
187 /* make sure the right access type is on the cardbus bridge */
188 (*cf->cardbus_ctrl)(cc, CARDBUS_MEM_ENABLE);
189 (*cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);
190
191 /* enable the appropriate bits in the PCI CSR */
192 reg = pci_conf_read(pc, csc->sc_tag,
193 PCI_COMMAND_STATUS_REG);
194 reg |= PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_MEM_ENABLE;
195 pci_conf_write(pc, csc->sc_tag, PCI_COMMAND_STATUS_REG,
196 reg);
197 }
198
199 int
200 malo_cardbus_enable(struct malo_softc *sc)
201 {
202 struct malo_cardbus_softc *csc = (struct malo_cardbus_softc *)sc;
203 cardbus_devfunc_t ct = csc->sc_ct;
204 cardbus_chipset_tag_t cc = ct->ct_cc;
205 cardbus_function_tag_t cf = ct->ct_cf;
206
207 /* power on the socket */
208 Cardbus_function_enable(ct);
209
210 /* setup the PCI configuration registers */
211 malo_cardbus_setup(csc);
212
213 /* map and establish the interrupt handler */
214 csc->sc_ih = cardbus_intr_establish(cc, cf, csc->sc_intrline, IPL_NET,
215 malo_intr, sc, sc->sc_dev.dv_xname);
216 if (csc->sc_ih == NULL) {
217 printf("%s: could not establish interrupt at %d\n",
218 sc->sc_dev.dv_xname, csc->sc_intrline);
219 Cardbus_function_disable(ct);
220 return (1);
221 }
222
223 return (0);
224 }
225
226 void
227 malo_cardbus_disable(struct malo_softc *sc)
228 {
229 struct malo_cardbus_softc *csc = (struct malo_cardbus_softc *)sc;
230 cardbus_devfunc_t ct = csc->sc_ct;
231 cardbus_chipset_tag_t cc = ct->ct_cc;
232 cardbus_function_tag_t cf = ct->ct_cf;
233
234 /* unhook the interrupt handler */
235 cardbus_intr_disestablish(cc, cf, csc->sc_ih);
236 csc->sc_ih = NULL;
237
238 /* power down the socket */
239 Cardbus_function_disable(ct);
240 }
Cache object: 92fc3b4cafd95736d12ed1b1ad256a89
|