xref: /openbsd/sys/dev/cardbus/if_atw_cardbus.c (revision 771fbea0)
1 /*	$OpenBSD: if_atw_cardbus.c,v 1.24 2015/11/24 17:11:39 mpi Exp $	*/
2 /*	$NetBSD: if_atw_cardbus.c,v 1.9 2004/07/23 07:07:55 dyoung Exp $	*/
3 
4 /*-
5  * Copyright (c) 1999, 2000, 2003 The NetBSD Foundation, Inc.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to The NetBSD Foundation
9  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
10  * NASA Ames Research Center.  This code was adapted for the ADMtek ADM8211
11  * by David Young.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  * 1. Redistributions of source code must retain the above copyright
17  *    notice, this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the
20  *    documentation and/or other materials provided with the distribution.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
23  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
26  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 /*
36  * CardBus bus front-end for the ADMtek ADM8211 802.11 MAC/BBP driver.
37  */
38 
39 #include "bpfilter.h"
40 
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/mbuf.h>
44 #include <sys/malloc.h>
45 #include <sys/kernel.h>
46 #include <sys/socket.h>
47 #include <sys/ioctl.h>
48 #include <sys/errno.h>
49 #include <sys/device.h>
50 #include <sys/endian.h>
51 
52 #include <net/if.h>
53 #include <net/if_media.h>
54 
55 #include <netinet/in.h>
56 #include <netinet/if_ether.h>
57 
58 #include <net80211/ieee80211_radiotap.h>
59 #include <net80211/ieee80211_var.h>
60 
61 #if NBPFILTER > 0
62 #include <net/bpf.h>
63 #endif
64 
65 #include <machine/bus.h>
66 #include <machine/intr.h>
67 
68 #include <dev/ic/atwreg.h>
69 #include <dev/ic/si4136reg.h>
70 #include <dev/ic/atwvar.h>
71 
72 #include <dev/pci/pcivar.h>
73 #include <dev/pci/pcireg.h>
74 #include <dev/pci/pcidevs.h>
75 
76 #include <dev/cardbus/cardbusvar.h>
77 
78 /*
79  * PCI configuration space registers used by the ADM8211.
80  */
81 #define	ATW_PCI_IOBA		0x10	/* i/o mapped base */
82 #define	ATW_PCI_MMBA		0x14	/* memory mapped base */
83 
84 struct atw_cardbus_softc {
85 	struct atw_softc sc_atw;	/* real ADM8211 softc */
86 
87 	/* CardBus-specific goo. */
88 	void	*sc_ih;			/* interrupt handle */
89 	cardbus_devfunc_t sc_ct;	/* our CardBus devfuncs */
90 	pcitag_t sc_tag;		/* our CardBus tag */
91 	int	sc_csr;			/* CSR bits */
92 	bus_size_t sc_mapsize;		/* the size of mapped bus space
93 					   region */
94 
95 	int	sc_cben;		/* CardBus enables */
96 	int	sc_bar_reg;		/* which BAR to use */
97 	pcireg_t sc_bar_val;		/* value of the BAR */
98 
99 	int	sc_intrline;		/* interrupt line */
100 	pci_chipset_tag_t sc_pc;
101 };
102 
103 int	atw_cardbus_match(struct device *, void *, void *);
104 void	atw_cardbus_attach(struct device *, struct device *, void *);
105 int	atw_cardbus_detach(struct device *, int);
106 
107 struct cfattach atw_cardbus_ca = {
108 	sizeof(struct atw_cardbus_softc), atw_cardbus_match, atw_cardbus_attach,
109 	    atw_cardbus_detach
110 };
111 
112 void	atw_cardbus_setup(struct atw_cardbus_softc *);
113 
114 int	atw_cardbus_enable(struct atw_softc *);
115 void	atw_cardbus_disable(struct atw_softc *);
116 void	atw_cardbus_power(struct atw_softc *, int);
117 
118 const struct pci_matchid atw_cardbus_devices[] = {
119 	{ PCI_VENDOR_ADMTEK, PCI_PRODUCT_ADMTEK_ADM8211 },
120 	{ PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3CRSHPW796 },
121 };
122 
123 int
124 atw_cardbus_match(struct device *parent, void *match, void *aux)
125 {
126 	return (cardbus_matchbyid((struct cardbus_attach_args *)aux,
127 	    atw_cardbus_devices, nitems(atw_cardbus_devices)));
128 }
129 
130 void
131 atw_cardbus_attach(struct device *parent, struct device *self, void *aux)
132 {
133 	struct atw_cardbus_softc *csc = (void *)self;
134 	struct atw_softc *sc = &csc->sc_atw;
135 	struct cardbus_attach_args *ca = aux;
136 	cardbus_devfunc_t ct = ca->ca_ct;
137 	bus_addr_t adr;
138 
139 	sc->sc_dmat = ca->ca_dmat;
140 	csc->sc_ct = ct;
141 	csc->sc_tag = ca->ca_tag;
142 	csc->sc_pc = ca->ca_pc;
143 
144 	/*
145 	 * Power management hooks.
146 	 */
147 	sc->sc_enable = atw_cardbus_enable;
148 	sc->sc_disable = atw_cardbus_disable;
149 	sc->sc_power = atw_cardbus_power;
150 
151 	/* Get revision info. */
152 	sc->sc_rev = PCI_REVISION(ca->ca_class);
153 
154 #if 0
155 	printf(": signature %08x\n%s",
156 	    pci_conf_read(ca->ca_pc, csc->sc_tag, 0x80),
157 	    sc->sc_dev.dv_xname);
158 #endif
159 
160 	/*
161 	 * Map the device.
162 	 */
163 	csc->sc_csr = PCI_COMMAND_MASTER_ENABLE;
164 	if (Cardbus_mapreg_map(ct, ATW_PCI_MMBA,
165 	    PCI_MAPREG_TYPE_MEM, 0, &sc->sc_st, &sc->sc_sh, &adr,
166 	    &csc->sc_mapsize) == 0) {
167 #if 0
168 		printf(": atw_cardbus_attach mapped %d bytes mem space\n%s",
169 		    csc->sc_mapsize, sc->sc_dev.dv_xname);
170 #endif
171 		csc->sc_cben = CARDBUS_MEM_ENABLE;
172 		csc->sc_csr |= PCI_COMMAND_MEM_ENABLE;
173 		csc->sc_bar_reg = ATW_PCI_MMBA;
174 		csc->sc_bar_val = adr | PCI_MAPREG_TYPE_MEM;
175 	} else if (Cardbus_mapreg_map(ct, ATW_PCI_IOBA,
176 	    PCI_MAPREG_TYPE_IO, 0, &sc->sc_st, &sc->sc_sh, &adr,
177 	    &csc->sc_mapsize) == 0) {
178 #if 0
179 		printf(": atw_cardbus_attach mapped %d bytes I/O space\n%s",
180 		    csc->sc_mapsize, sc->sc_dev.dv_xname);
181 #endif
182 		csc->sc_cben = CARDBUS_IO_ENABLE;
183 		csc->sc_csr |= PCI_COMMAND_IO_ENABLE;
184 		csc->sc_bar_reg = ATW_PCI_IOBA;
185 		csc->sc_bar_val = adr | PCI_MAPREG_TYPE_IO;
186 	} else {
187 		printf(": unable to map device registers\n");
188 		return;
189 	}
190 
191 	/*
192 	 * Bring the chip out of powersave mode and initialize the
193 	 * configuration registers.
194 	 */
195 	atw_cardbus_setup(csc);
196 
197 	/* Remember which interrupt line. */
198 	csc->sc_intrline = ca->ca_intrline;
199 
200 	printf(": revision %d.%d: irq %d\n",
201 	    (sc->sc_rev >> 4) & 0xf, sc->sc_rev & 0xf, csc->sc_intrline);
202 #if 0
203 	/*
204 	 * The CardBus cards will make it to store-and-forward mode as
205 	 * soon as you put them under any kind of load, so just start
206 	 * out there.
207 	 */
208 	sc->sc_txthresh = 3; /* TBD name constant */
209 #endif
210 
211 	/*
212 	 * Finish off the attach.
213 	 */
214 	atw_attach(sc);
215 
216 	ATW_WRITE(sc, ATW_FER, ATW_FER_INTR);
217 
218 	/*
219 	 * Power down the socket.
220 	 */
221 	Cardbus_function_disable(csc->sc_ct);
222 }
223 
224 int
225 atw_cardbus_detach(struct device *self, int flags)
226 {
227 	struct atw_cardbus_softc *csc = (void *)self;
228 	struct atw_softc *sc = &csc->sc_atw;
229 	struct cardbus_devfunc *ct = csc->sc_ct;
230 	int rv;
231 
232 #if defined(DIAGNOSTIC)
233 	if (ct == NULL)
234 		panic("%s: data structure lacks", sc->sc_dev.dv_xname);
235 #endif
236 
237 	rv = atw_detach(sc);
238 	if (rv)
239 		return (rv);
240 
241 	/*
242 	 * Unhook the interrupt handler.
243 	 */
244 	if (csc->sc_ih != NULL)
245 		cardbus_intr_disestablish(ct->ct_cc, ct->ct_cf, csc->sc_ih);
246 
247 	/*
248 	 * Release bus space and close window.
249 	 */
250 	if (csc->sc_bar_reg != 0)
251 		Cardbus_mapreg_unmap(ct, csc->sc_bar_reg,
252 		    sc->sc_st, sc->sc_sh, csc->sc_mapsize);
253 
254 	return (0);
255 }
256 
257 int
258 atw_cardbus_enable(struct atw_softc *sc)
259 {
260 	struct atw_cardbus_softc *csc = (void *) sc;
261 	cardbus_devfunc_t ct = csc->sc_ct;
262 	cardbus_chipset_tag_t cc = ct->ct_cc;
263 	cardbus_function_tag_t cf = ct->ct_cf;
264 
265 	/*
266 	 * Power on the socket.
267 	 */
268 	Cardbus_function_enable(ct);
269 
270 	/*
271 	 * Set up the PCI configuration registers.
272 	 */
273 	atw_cardbus_setup(csc);
274 
275 	/*
276 	 * Map and establish the interrupt.
277 	 */
278 	csc->sc_ih = cardbus_intr_establish(cc, cf, csc->sc_intrline, IPL_NET,
279 	    atw_intr, sc, sc->sc_dev.dv_xname);
280 	if (csc->sc_ih == NULL) {
281 		printf("%s: unable to establish interrupt at %d\n",
282 		    sc->sc_dev.dv_xname, csc->sc_intrline);
283 		Cardbus_function_disable(csc->sc_ct);
284 		return (1);
285 	}
286 
287 	return (0);
288 }
289 
290 void
291 atw_cardbus_disable(struct atw_softc *sc)
292 {
293 	struct atw_cardbus_softc *csc = (void *) sc;
294 	cardbus_devfunc_t ct = csc->sc_ct;
295 	cardbus_chipset_tag_t cc = ct->ct_cc;
296 	cardbus_function_tag_t cf = ct->ct_cf;
297 
298 	/* Unhook the interrupt handler. */
299 	cardbus_intr_disestablish(cc, cf, csc->sc_ih);
300 	csc->sc_ih = NULL;
301 
302 	/* Power down the socket. */
303 	Cardbus_function_disable(ct);
304 }
305 
306 void
307 atw_cardbus_power(struct atw_softc *sc, int why)
308 {
309 	if (why == DVACT_RESUME)
310 		atw_enable(sc);
311 }
312 
313 void
314 atw_cardbus_setup(struct atw_cardbus_softc *csc)
315 {
316 #ifdef notyet
317 	struct atw_softc *sc = &csc->sc_atw;
318 #endif
319 	cardbus_devfunc_t ct = csc->sc_ct;
320 	cardbus_chipset_tag_t cc = ct->ct_cc;
321 	pci_chipset_tag_t pc = csc->sc_pc;
322 	pcireg_t reg;
323 
324 #ifdef notyet
325 	(void)cardbus_setpowerstate(sc->sc_dev.dv_xname, ct, csc->sc_tag,
326 	    PCI_PWR_D0);
327 #endif
328 
329 	/* Program the BAR. */
330 	pci_conf_write(pc, csc->sc_tag, csc->sc_bar_reg,
331 	    csc->sc_bar_val);
332 
333 	/* Make sure the right access type is on the CardBus bridge. */
334 	(*ct->ct_cf->cardbus_ctrl)(cc, csc->sc_cben);
335 	(*ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);
336 
337 	/* Enable the appropriate bits in the PCI CSR. */
338 	reg = pci_conf_read(pc, csc->sc_tag,
339 	    PCI_COMMAND_STATUS_REG);
340 	reg &= ~(PCI_COMMAND_IO_ENABLE|PCI_COMMAND_MEM_ENABLE);
341 	reg |= csc->sc_csr;
342 	pci_conf_write(pc, csc->sc_tag, PCI_COMMAND_STATUS_REG,
343 	    reg);
344 
345 	/*
346 	 * Make sure the latency timer is set to some reasonable
347 	 * value.
348 	 */
349 	reg = pci_conf_read(pc, csc->sc_tag, PCI_BHLC_REG);
350 	if (PCI_LATTIMER(reg) < 0x20) {
351 		reg &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT);
352 		reg |= (0x20 << PCI_LATTIMER_SHIFT);
353 		pci_conf_write(pc, csc->sc_tag, PCI_BHLC_REG, reg);
354 	}
355 }
356