Annotation of sys/dev/cardbus/if_acx_cardbus.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: if_acx_cardbus.c,v 1.11 2006/11/10 20:20:04 damien Exp $ */
2:
3: /*
4: * Copyright (c) 2006 Claudio Jeker <claudio@openbsd.org>
5: * Copyright (c) 2005, 2006
6: * Damien Bergamini <damien.bergamini@free.fr>
7: *
8: * Permission to use, copy, modify, and distribute this software for any
9: * purpose with or without fee is hereby granted, provided that the above
10: * copyright notice and this permission notice appear in all copies.
11: *
12: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19: */
20:
21: /*
22: * CardBus front-end for the Texas Instruments ACX driver
23: */
24:
25: #include "bpfilter.h"
26:
27: #include <sys/param.h>
28: #include <sys/sockio.h>
29: #include <sys/mbuf.h>
30: #include <sys/kernel.h>
31: #include <sys/socket.h>
32: #include <sys/systm.h>
33: #include <sys/malloc.h>
34: #include <sys/timeout.h>
35: #include <sys/device.h>
36:
37: #include <machine/bus.h>
38: #include <machine/intr.h>
39:
40: #include <net/if.h>
41: #include <net/if_dl.h>
42: #include <net/if_media.h>
43:
44: #ifdef INET
45: #include <netinet/in.h>
46: #include <netinet/if_ether.h>
47: #endif
48:
49: #include <net80211/ieee80211_var.h>
50: #include <net80211/ieee80211_amrr.h>
51: #include <net80211/ieee80211_radiotap.h>
52:
53: #include <dev/ic/acxvar.h>
54: #include <dev/ic/acxreg.h>
55:
56: #include <dev/pci/pcireg.h>
57: #include <dev/pci/pcivar.h>
58: #include <dev/pci/pcidevs.h>
59:
60: #include <dev/cardbus/cardbusvar.h>
61:
62: struct acx_cardbus_softc {
63: struct acx_softc sc_acx;
64:
65: /* cardbus specific goo */
66: cardbus_devfunc_t sc_ct;
67: cardbustag_t sc_tag;
68: void *sc_ih;
69: bus_size_t sc_mapsize1;
70: bus_size_t sc_mapsize2;
71: pcireg_t sc_iobar_val; /* acx100 only */
72: pcireg_t sc_bar1_val;
73: pcireg_t sc_bar2_val;
74: int sc_intrline;
75:
76: /* hack for ACX100A */
77: bus_space_tag_t sc_io_bt;
78: bus_space_handle_t sc_io_bh;
79: bus_size_t sc_iomapsize;
80: };
81:
82: int acx_cardbus_match(struct device *, void *, void *);
83: void acx_cardbus_attach(struct device *, struct device *, void *);
84: int acx_cardbus_detach(struct device *, int);
85:
86: struct cfattach acx_cardbus_ca = {
87: sizeof (struct acx_cardbus_softc), acx_cardbus_match,
88: acx_cardbus_attach, acx_cardbus_detach
89: };
90:
91: static const struct cardbus_matchid acx_cardbus_devices[] = {
92: { PCI_VENDOR_TI, PCI_PRODUCT_TI_ACX100A },
93: { PCI_VENDOR_TI, PCI_PRODUCT_TI_ACX100B },
94: { PCI_VENDOR_TI, PCI_PRODUCT_TI_ACX111 },
95: };
96:
97: int acx_cardbus_enable(struct acx_softc *);
98: void acx_cardbus_disable(struct acx_softc *);
99: void acx_cardbus_power(struct acx_softc *, int);
100: void acx_cardbus_setup(struct acx_cardbus_softc *);
101:
102: int
103: acx_cardbus_match(struct device *parent, void *match, void *aux)
104: {
105: return (cardbus_matchbyid((struct cardbus_attach_args *)aux,
106: acx_cardbus_devices,
107: sizeof (acx_cardbus_devices) / sizeof (acx_cardbus_devices[0])));
108: }
109:
110: void
111: acx_cardbus_attach(struct device *parent, struct device *self, void *aux)
112: {
113: struct acx_cardbus_softc *csc = (struct acx_cardbus_softc *)self;
114: struct acx_softc *sc = &csc->sc_acx;
115: struct cardbus_attach_args *ca = aux;
116: cardbus_devfunc_t ct = ca->ca_ct;
117: bus_addr_t base;
118: int error, b1 = CARDBUS_BASE0_REG, b2 = CARDBUS_BASE1_REG;
119:
120: sc->sc_dmat = ca->ca_dmat;
121: csc->sc_ct = ct;
122: csc->sc_tag = ca->ca_tag;
123: csc->sc_intrline = ca->ca_intrline;
124:
125: /* power management hooks */
126: sc->sc_enable = acx_cardbus_enable;
127: sc->sc_disable = acx_cardbus_disable;
128: sc->sc_power = acx_cardbus_power;
129:
130: if (CARDBUS_PRODUCT(ca->ca_id) == PCI_PRODUCT_TI_ACX100A) {
131: /* first map I/O space as seen in the dragonfly code */
132: error = Cardbus_mapreg_map(ct, CARDBUS_BASE0_REG,
133: CARDBUS_MAPREG_TYPE_IO, 0, &csc->sc_io_bt, &csc->sc_io_bh,
134: &base, &csc->sc_iomapsize);
135: if (error != 0) {
136: printf(": could not map i/o space\n");
137: return;
138: }
139: csc->sc_iobar_val = base | CARDBUS_MAPREG_TYPE_IO;
140: b1 = CARDBUS_BASE1_REG;
141: b2 = CARDBUS_BASE2_REG;
142: }
143:
144: /* map control/status registers */
145: error = Cardbus_mapreg_map(ct, b1, CARDBUS_MAPREG_TYPE_MEM, 0,
146: &sc->sc_mem1_bt, &sc->sc_mem1_bh, &base, &csc->sc_mapsize1);
147: if (error != 0) {
148: printf(": could not map memory1 space\n");
149: return;
150: }
151:
152: csc->sc_bar1_val = base | CARDBUS_MAPREG_TYPE_MEM;
153:
154: /* map the other memory region */
155: error = Cardbus_mapreg_map(ct, b2, CARDBUS_MAPREG_TYPE_MEM, 0,
156: &sc->sc_mem2_bt, &sc->sc_mem2_bh, &base, &csc->sc_mapsize2);
157: if (error != 0) {
158: printf(": could not map memory2 space\n");
159: return;
160: }
161:
162: csc->sc_bar2_val = base | CARDBUS_MAPREG_TYPE_MEM;
163:
164: /* set up the PCI configuration registers */
165: acx_cardbus_setup(csc);
166:
167: printf(": irq %d\n", csc->sc_intrline);
168:
169: if (CARDBUS_PRODUCT(ca->ca_id) == PCI_PRODUCT_TI_ACX111)
170: acx111_set_param(sc);
171: else
172: acx100_set_param(sc);
173:
174: acx_attach(sc);
175:
176: Cardbus_function_disable(ct);
177: }
178:
179: int
180: acx_cardbus_detach(struct device *self, int flags)
181: {
182: struct acx_cardbus_softc *csc = (struct acx_cardbus_softc *)self;
183: struct acx_softc *sc = &csc->sc_acx;
184: cardbus_devfunc_t ct = csc->sc_ct;
185: cardbus_chipset_tag_t cc = ct->ct_cc;
186: cardbus_function_tag_t cf = ct->ct_cf;
187: int error, b1 = CARDBUS_BASE0_REG, b2 = CARDBUS_BASE1_REG;
188:
189: error = acx_detach(sc);
190: if (error != 0)
191: return (error);
192:
193: /* unhook the interrupt handler */
194: if (csc->sc_ih != NULL) {
195: cardbus_intr_disestablish(cc, cf, csc->sc_ih);
196: csc->sc_ih = NULL;
197: }
198:
199: /* release bus space and close window */
200: if (csc->sc_iomapsize) {
201: b1 = CARDBUS_BASE1_REG;
202: b2 = CARDBUS_BASE2_REG;
203: }
204: Cardbus_mapreg_unmap(ct, b1, sc->sc_mem1_bt,
205: sc->sc_mem1_bh, csc->sc_mapsize1);
206: Cardbus_mapreg_unmap(ct, b2, sc->sc_mem2_bt,
207: sc->sc_mem2_bh, csc->sc_mapsize2);
208: if (csc->sc_iomapsize)
209: Cardbus_mapreg_unmap(ct, CARDBUS_BASE0_REG, csc->sc_io_bt,
210: csc->sc_io_bh, csc->sc_iomapsize);
211:
212: return (0);
213: }
214:
215: int
216: acx_cardbus_enable(struct acx_softc *sc)
217: {
218: struct acx_cardbus_softc *csc = (struct acx_cardbus_softc *)sc;
219: cardbus_devfunc_t ct = csc->sc_ct;
220: cardbus_chipset_tag_t cc = ct->ct_cc;
221: cardbus_function_tag_t cf = ct->ct_cf;
222:
223: /* power on the socket */
224: Cardbus_function_enable(ct);
225:
226: /* setup the PCI configuration registers */
227: acx_cardbus_setup(csc);
228:
229: /* map and establish the interrupt handler */
230: csc->sc_ih = cardbus_intr_establish(cc, cf, csc->sc_intrline, IPL_NET,
231: acx_intr, sc, sc->sc_dev.dv_xname);
232: if (csc->sc_ih == NULL) {
233: printf("%s: could not establish interrupt at %d\n",
234: sc->sc_dev.dv_xname, csc->sc_intrline);
235: Cardbus_function_disable(ct);
236: return (1);
237: }
238:
239: return (0);
240: }
241:
242: void
243: acx_cardbus_disable(struct acx_softc *sc)
244: {
245: struct acx_cardbus_softc *csc = (struct acx_cardbus_softc *)sc;
246: cardbus_devfunc_t ct = csc->sc_ct;
247: cardbus_chipset_tag_t cc = ct->ct_cc;
248: cardbus_function_tag_t cf = ct->ct_cf;
249:
250: /* unhook the interrupt handler */
251: cardbus_intr_disestablish(cc, cf, csc->sc_ih);
252: csc->sc_ih = NULL;
253:
254: /* power down the socket */
255: Cardbus_function_disable(ct);
256: }
257:
258: void
259: acx_cardbus_power(struct acx_softc *sc, int why)
260: {
261: struct acx_cardbus_softc *csc = (struct acx_cardbus_softc *)sc;
262:
263: if (why == PWR_RESUME) {
264: /* kick the PCI configuration registers */
265: acx_cardbus_setup(csc);
266: }
267: }
268:
269: void
270: acx_cardbus_setup(struct acx_cardbus_softc *csc)
271: {
272: cardbus_devfunc_t ct = csc->sc_ct;
273: cardbus_chipset_tag_t cc = ct->ct_cc;
274: cardbus_function_tag_t cf = ct->ct_cf;
275: pcireg_t reg;
276: int b1 = CARDBUS_BASE0_REG, b2 = CARDBUS_BASE1_REG;
277:
278: if (csc->sc_iobar_val) {
279: cardbus_conf_write(cc, cf, csc->sc_tag, CARDBUS_BASE0_REG,
280: csc->sc_bar1_val);
281: b1 = CARDBUS_BASE1_REG;
282: b2 = CARDBUS_BASE2_REG;
283: /* (*cf->cardbus_ctrl)(cc, CARDBUS_IO_ENABLE); */
284: }
285:
286: /* program the BAR */
287: cardbus_conf_write(cc, cf, csc->sc_tag, b1, csc->sc_bar1_val);
288: cardbus_conf_write(cc, cf, csc->sc_tag, b2, csc->sc_bar2_val);
289:
290: /* make sure the right access type is on the cardbus bridge */
291: (*cf->cardbus_ctrl)(cc, CARDBUS_MEM_ENABLE);
292: (*cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);
293:
294: /* enable the appropriate bits in the PCI CSR */
295: reg = cardbus_conf_read(cc, cf, csc->sc_tag,
296: CARDBUS_COMMAND_STATUS_REG);
297: reg |= CARDBUS_COMMAND_MASTER_ENABLE | CARDBUS_COMMAND_MEM_ENABLE;
298: #if 0
299: if (csc->sc_iobar_val)
300: reg |= CARDBUS_COMMAND_IO_ENABLE;
301: #endif
302: cardbus_conf_write(cc, cf, csc->sc_tag, CARDBUS_COMMAND_STATUS_REG,
303: reg);
304: }
CVSweb