xref: /openbsd/sys/dev/cardbus/if_atw_cardbus.c (revision cecf84d4)
1 /*	$OpenBSD: if_atw_cardbus.c,v 1.23 2015/03/14 03:38:47 jsg 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_dl.h>
54 #include <net/if_media.h>
55 
56 #include <netinet/in.h>
57 #include <netinet/if_ether.h>
58 
59 #include <net80211/ieee80211_radiotap.h>
60 #include <net80211/ieee80211_var.h>
61 
62 #if NBPFILTER > 0
63 #include <net/bpf.h>
64 #endif
65 
66 #include <machine/bus.h>
67 #include <machine/intr.h>
68 
69 #include <dev/ic/atwreg.h>
70 #include <dev/ic/si4136reg.h>
71 #include <dev/ic/atwvar.h>
72 
73 #include <dev/pci/pcivar.h>
74 #include <dev/pci/pcireg.h>
75 #include <dev/pci/pcidevs.h>
76 
77 #include <dev/cardbus/cardbusvar.h>
78 
79 /*
80  * PCI configuration space registers used by the ADM8211.
81  */
82 #define	ATW_PCI_IOBA		0x10	/* i/o mapped base */
83 #define	ATW_PCI_MMBA		0x14	/* memory mapped base */
84 
85 struct atw_cardbus_softc {
86 	struct atw_softc sc_atw;	/* real ADM8211 softc */
87 
88 	/* CardBus-specific goo. */
89 	void	*sc_ih;			/* interrupt handle */
90 	cardbus_devfunc_t sc_ct;	/* our CardBus devfuncs */
91 	pcitag_t sc_tag;		/* our CardBus tag */
92 	int	sc_csr;			/* CSR bits */
93 	bus_size_t sc_mapsize;		/* the size of mapped bus space
94 					   region */
95 
96 	int	sc_cben;		/* CardBus enables */
97 	int	sc_bar_reg;		/* which BAR to use */
98 	pcireg_t sc_bar_val;		/* value of the BAR */
99 
100 	int	sc_intrline;		/* interrupt line */
101 	pci_chipset_tag_t sc_pc;
102 };
103 
104 int	atw_cardbus_match(struct device *, void *, void *);
105 void	atw_cardbus_attach(struct device *, struct device *, void *);
106 int	atw_cardbus_detach(struct device *, int);
107 
108 struct cfattach atw_cardbus_ca = {
109 	sizeof(struct atw_cardbus_softc), atw_cardbus_match, atw_cardbus_attach,
110 	    atw_cardbus_detach
111 };
112 
113 void	atw_cardbus_setup(struct atw_cardbus_softc *);
114 
115 int	atw_cardbus_enable(struct atw_softc *);
116 void	atw_cardbus_disable(struct atw_softc *);
117 void	atw_cardbus_power(struct atw_softc *, int);
118 
119 const struct pci_matchid atw_cardbus_devices[] = {
120 	{ PCI_VENDOR_ADMTEK, PCI_PRODUCT_ADMTEK_ADM8211 },
121 	{ PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3CRSHPW796 },
122 };
123 
124 int
125 atw_cardbus_match(struct device *parent, void *match, void *aux)
126 {
127 	return (cardbus_matchbyid((struct cardbus_attach_args *)aux,
128 	    atw_cardbus_devices, nitems(atw_cardbus_devices)));
129 }
130 
131 void
132 atw_cardbus_attach(struct device *parent, struct device *self, void *aux)
133 {
134 	struct atw_cardbus_softc *csc = (void *)self;
135 	struct atw_softc *sc = &csc->sc_atw;
136 	struct cardbus_attach_args *ca = aux;
137 	cardbus_devfunc_t ct = ca->ca_ct;
138 	bus_addr_t adr;
139 
140 	sc->sc_dmat = ca->ca_dmat;
141 	csc->sc_ct = ct;
142 	csc->sc_tag = ca->ca_tag;
143 	csc->sc_pc = ca->ca_pc;
144 
145 	/*
146 	 * Power management hooks.
147 	 */
148 	sc->sc_enable = atw_cardbus_enable;
149 	sc->sc_disable = atw_cardbus_disable;
150 	sc->sc_power = atw_cardbus_power;
151 
152 	/* Get revision info. */
153 	sc->sc_rev = PCI_REVISION(ca->ca_class);
154 
155 #if 0
156 	printf(": signature %08x\n%s",
157 	    pci_conf_read(ca->ca_pc, csc->sc_tag, 0x80),
158 	    sc->sc_dev.dv_xname);
159 #endif
160 
161 	/*
162 	 * Map the device.
163 	 */
164 	csc->sc_csr = PCI_COMMAND_MASTER_ENABLE;
165 	if (Cardbus_mapreg_map(ct, ATW_PCI_MMBA,
166 	    PCI_MAPREG_TYPE_MEM, 0, &sc->sc_st, &sc->sc_sh, &adr,
167 	    &csc->sc_mapsize) == 0) {
168 #if 0
169 		printf(": atw_cardbus_attach mapped %d bytes mem space\n%s",
170 		    csc->sc_mapsize, sc->sc_dev.dv_xname);
171 #endif
172 		csc->sc_cben = CARDBUS_MEM_ENABLE;
173 		csc->sc_csr |= PCI_COMMAND_MEM_ENABLE;
174 		csc->sc_bar_reg = ATW_PCI_MMBA;
175 		csc->sc_bar_val = adr | PCI_MAPREG_TYPE_MEM;
176 	} else if (Cardbus_mapreg_map(ct, ATW_PCI_IOBA,
177 	    PCI_MAPREG_TYPE_IO, 0, &sc->sc_st, &sc->sc_sh, &adr,
178 	    &csc->sc_mapsize) == 0) {
179 #if 0
180 		printf(": atw_cardbus_attach mapped %d bytes I/O space\n%s",
181 		    csc->sc_mapsize, sc->sc_dev.dv_xname);
182 #endif
183 		csc->sc_cben = CARDBUS_IO_ENABLE;
184 		csc->sc_csr |= PCI_COMMAND_IO_ENABLE;
185 		csc->sc_bar_reg = ATW_PCI_IOBA;
186 		csc->sc_bar_val = adr | PCI_MAPREG_TYPE_IO;
187 	} else {
188 		printf(": unable to map device registers\n");
189 		return;
190 	}
191 
192 	/*
193 	 * Bring the chip out of powersave mode and initialize the
194 	 * configuration registers.
195 	 */
196 	atw_cardbus_setup(csc);
197 
198 	/* Remember which interrupt line. */
199 	csc->sc_intrline = ca->ca_intrline;
200 
201 	printf(": revision %d.%d: irq %d\n",
202 	    (sc->sc_rev >> 4) & 0xf, sc->sc_rev & 0xf, csc->sc_intrline);
203 #if 0
204 	/*
205 	 * The CardBus cards will make it to store-and-forward mode as
206 	 * soon as you put them under any kind of load, so just start
207 	 * out there.
208 	 */
209 	sc->sc_txthresh = 3; /* TBD name constant */
210 #endif
211 
212 	/*
213 	 * Finish off the attach.
214 	 */
215 	atw_attach(sc);
216 
217 	ATW_WRITE(sc, ATW_FER, ATW_FER_INTR);
218 
219 	/*
220 	 * Power down the socket.
221 	 */
222 	Cardbus_function_disable(csc->sc_ct);
223 }
224 
225 int
226 atw_cardbus_detach(struct device *self, int flags)
227 {
228 	struct atw_cardbus_softc *csc = (void *)self;
229 	struct atw_softc *sc = &csc->sc_atw;
230 	struct cardbus_devfunc *ct = csc->sc_ct;
231 	int rv;
232 
233 #if defined(DIAGNOSTIC)
234 	if (ct == NULL)
235 		panic("%s: data structure lacks", sc->sc_dev.dv_xname);
236 #endif
237 
238 	rv = atw_detach(sc);
239 	if (rv)
240 		return (rv);
241 
242 	/*
243 	 * Unhook the interrupt handler.
244 	 */
245 	if (csc->sc_ih != NULL)
246 		cardbus_intr_disestablish(ct->ct_cc, ct->ct_cf, csc->sc_ih);
247 
248 	/*
249 	 * Release bus space and close window.
250 	 */
251 	if (csc->sc_bar_reg != 0)
252 		Cardbus_mapreg_unmap(ct, csc->sc_bar_reg,
253 		    sc->sc_st, sc->sc_sh, csc->sc_mapsize);
254 
255 	return (0);
256 }
257 
258 int
259 atw_cardbus_enable(struct atw_softc *sc)
260 {
261 	struct atw_cardbus_softc *csc = (void *) sc;
262 	cardbus_devfunc_t ct = csc->sc_ct;
263 	cardbus_chipset_tag_t cc = ct->ct_cc;
264 	cardbus_function_tag_t cf = ct->ct_cf;
265 
266 	/*
267 	 * Power on the socket.
268 	 */
269 	Cardbus_function_enable(ct);
270 
271 	/*
272 	 * Set up the PCI configuration registers.
273 	 */
274 	atw_cardbus_setup(csc);
275 
276 	/*
277 	 * Map and establish the interrupt.
278 	 */
279 	csc->sc_ih = cardbus_intr_establish(cc, cf, csc->sc_intrline, IPL_NET,
280 	    atw_intr, sc, sc->sc_dev.dv_xname);
281 	if (csc->sc_ih == NULL) {
282 		printf("%s: unable to establish interrupt at %d\n",
283 		    sc->sc_dev.dv_xname, csc->sc_intrline);
284 		Cardbus_function_disable(csc->sc_ct);
285 		return (1);
286 	}
287 
288 	return (0);
289 }
290 
291 void
292 atw_cardbus_disable(struct atw_softc *sc)
293 {
294 	struct atw_cardbus_softc *csc = (void *) sc;
295 	cardbus_devfunc_t ct = csc->sc_ct;
296 	cardbus_chipset_tag_t cc = ct->ct_cc;
297 	cardbus_function_tag_t cf = ct->ct_cf;
298 
299 	/* Unhook the interrupt handler. */
300 	cardbus_intr_disestablish(cc, cf, csc->sc_ih);
301 	csc->sc_ih = NULL;
302 
303 	/* Power down the socket. */
304 	Cardbus_function_disable(ct);
305 }
306 
307 void
308 atw_cardbus_power(struct atw_softc *sc, int why)
309 {
310 	if (why == DVACT_RESUME)
311 		atw_enable(sc);
312 }
313 
314 void
315 atw_cardbus_setup(struct atw_cardbus_softc *csc)
316 {
317 #ifdef notyet
318 	struct atw_softc *sc = &csc->sc_atw;
319 #endif
320 	cardbus_devfunc_t ct = csc->sc_ct;
321 	cardbus_chipset_tag_t cc = ct->ct_cc;
322 	pci_chipset_tag_t pc = csc->sc_pc;
323 	pcireg_t reg;
324 
325 #ifdef notyet
326 	(void)cardbus_setpowerstate(sc->sc_dev.dv_xname, ct, csc->sc_tag,
327 	    PCI_PWR_D0);
328 #endif
329 
330 	/* Program the BAR. */
331 	pci_conf_write(pc, csc->sc_tag, csc->sc_bar_reg,
332 	    csc->sc_bar_val);
333 
334 	/* Make sure the right access type is on the CardBus bridge. */
335 	(*ct->ct_cf->cardbus_ctrl)(cc, csc->sc_cben);
336 	(*ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);
337 
338 	/* Enable the appropriate bits in the PCI CSR. */
339 	reg = pci_conf_read(pc, csc->sc_tag,
340 	    PCI_COMMAND_STATUS_REG);
341 	reg &= ~(PCI_COMMAND_IO_ENABLE|PCI_COMMAND_MEM_ENABLE);
342 	reg |= csc->sc_csr;
343 	pci_conf_write(pc, csc->sc_tag, PCI_COMMAND_STATUS_REG,
344 	    reg);
345 
346 	/*
347 	 * Make sure the latency timer is set to some reasonable
348 	 * value.
349 	 */
350 	reg = pci_conf_read(pc, csc->sc_tag, PCI_BHLC_REG);
351 	if (PCI_LATTIMER(reg) < 0x20) {
352 		reg &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT);
353 		reg |= (0x20 << PCI_LATTIMER_SHIFT);
354 		pci_conf_write(pc, csc->sc_tag, PCI_BHLC_REG, reg);
355 	}
356 }
357