Annotation of sys/dev/cardbus/if_pgt_cardbus.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: if_pgt_cardbus.c,v 1.7 2006/11/11 10:28:20 maja Exp $ */
2:
3: /*
4: * Copyright (c) 2006 Marcus Glocker <mglocker@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: /*
20: * CardBus front-end for the PrismGT
21: */
22:
23: #include "bpfilter.h"
24:
25: #include <sys/param.h>
26: #include <sys/sockio.h>
27: #include <sys/mbuf.h>
28: #include <sys/kernel.h>
29: #include <sys/socket.h>
30: #include <sys/systm.h>
31: #include <sys/malloc.h>
32: #include <sys/timeout.h>
33: #include <sys/device.h>
34:
35: #include <machine/bus.h>
36: #include <machine/intr.h>
37:
38: #include <net/if.h>
39: #include <net/if_dl.h>
40: #include <net/if_media.h>
41:
42: #include <netinet/in.h>
43: #include <netinet/if_ether.h>
44:
45: #include <net80211/ieee80211_var.h>
46: #include <net80211/ieee80211_radiotap.h>
47:
48: #include <dev/ic/pgtreg.h>
49: #include <dev/ic/pgtvar.h>
50:
51: #include <dev/pci/pcireg.h>
52: #include <dev/pci/pcivar.h>
53: #include <dev/pci/pcidevs.h>
54:
55: #include <dev/cardbus/cardbusvar.h>
56:
57: struct pgt_cardbus_softc {
58: struct pgt_softc sc_pgt;
59: cardbus_devfunc_t sc_ct;
60: cardbustag_t sc_tag;
61: int sc_intrline;
62:
63: void *sc_ih;
64: bus_size_t sc_mapsize;
65: pcireg_t sc_bar0_val;
66: };
67:
68: int pgt_cardbus_match(struct device *, void *, void *);
69: void pgt_cardbus_attach(struct device *, struct device *, void *);
70: int pgt_cardbus_detach(struct device *, int);
71: int pgt_cardbus_enable(struct pgt_softc *);
72: void pgt_cardbus_disable(struct pgt_softc *);
73: void pgt_cardbus_power(struct pgt_softc *, int);
74: void pgt_cardbus_setup(struct pgt_cardbus_softc *);
75:
76: struct cfattach pgt_cardbus_ca = {
77: sizeof(struct pgt_cardbus_softc), pgt_cardbus_match, pgt_cardbus_attach,
78: pgt_cardbus_detach
79: };
80:
81: const struct cardbus_matchid pgt_cardbus_devices[] = {
82: { PCI_VENDOR_INTERSIL, PCI_PRODUCT_INTERSIL_ISL3877 },
83: { PCI_VENDOR_INTERSIL, PCI_PRODUCT_INTERSIL_ISL3890 },
84: { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3CRWE154G72 }
85: };
86:
87: int
88: pgt_cardbus_match(struct device *parent, void *match, void *aux)
89: {
90: return (cardbus_matchbyid((struct cardbus_attach_args *)aux,
91: pgt_cardbus_devices,
92: sizeof(pgt_cardbus_devices) / sizeof(pgt_cardbus_devices[0])));
93: }
94:
95: void
96: pgt_cardbus_attach(struct device *parent, struct device *self, void *aux)
97: {
98: struct pgt_cardbus_softc *csc = (struct pgt_cardbus_softc *)self;
99: struct pgt_softc *sc = &csc->sc_pgt;
100: struct cardbus_attach_args *ca = aux;
101: cardbus_devfunc_t ct = ca->ca_ct;
102: bus_addr_t base;
103: int error;
104:
105: sc->sc_dmat = ca->ca_dmat;
106: csc->sc_ct = ct;
107: csc->sc_tag = ca->ca_tag;
108: csc->sc_intrline = ca->ca_intrline;
109:
110: /* power management hooks */
111: sc->sc_enable = pgt_cardbus_enable;
112: sc->sc_disable = pgt_cardbus_disable;
113: sc->sc_power = pgt_cardbus_power;
114:
115: /* remember chipset */
116: if (CARDBUS_PRODUCT(ca->ca_id) == PCI_PRODUCT_INTERSIL_ISL3877)
117: sc->sc_flags |= SC_ISL3877;
118:
119: /* map control / status registers */
120: error = Cardbus_mapreg_map(ct, CARDBUS_BASE0_REG,
121: PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0,
122: &sc->sc_iotag, &sc->sc_iohandle, &base, &csc->sc_mapsize);
123: if (error != 0) {
124: printf(": could not map memory space\n");
125: return;
126: }
127: csc->sc_bar0_val = base | CARDBUS_MAPREG_TYPE_MEM;
128:
129: /* disable all interrupts */
130: bus_space_write_4(sc->sc_iotag, sc->sc_iohandle, PGT_REG_INT_EN, 0);
131: (void)bus_space_read_4(sc->sc_iotag, sc->sc_iohandle, PGT_REG_INT_EN);
132: DELAY(PGT_WRITEIO_DELAY);
133:
134: /* set up the PCI configuration registers */
135: pgt_cardbus_setup(csc);
136:
137: printf(": irq %d\n", csc->sc_intrline);
138:
139: if (rootvp == NULL)
140: mountroothook_establish(pgt_attach, sc);
141: else
142: pgt_attach(sc);
143: }
144:
145: int
146: pgt_cardbus_detach(struct device *self, int flags)
147: {
148: struct pgt_cardbus_softc *csc = (struct pgt_cardbus_softc *)self;
149: struct pgt_softc *sc = &csc->sc_pgt;
150: cardbus_devfunc_t ct = csc->sc_ct;
151: cardbus_chipset_tag_t cc = ct->ct_cc;
152: cardbus_function_tag_t cf = ct->ct_cf;
153: int error;
154:
155: error = pgt_detach(sc);
156: if (error != 0)
157: return (error);
158:
159: /* unhook the interrupt handler */
160: if (csc->sc_ih != NULL) {
161: cardbus_intr_disestablish(cc, cf, csc->sc_ih);
162: csc->sc_ih = NULL;
163: }
164:
165: /* release bus space and close window */
166: Cardbus_mapreg_unmap(ct, CARDBUS_BASE0_REG,
167: sc->sc_iotag, sc->sc_iohandle, csc->sc_mapsize);
168:
169: return (0);
170: }
171:
172: int
173: pgt_cardbus_enable(struct pgt_softc *sc)
174: {
175: struct pgt_cardbus_softc *csc = (struct pgt_cardbus_softc *)sc;
176: cardbus_devfunc_t ct = csc->sc_ct;
177: cardbus_chipset_tag_t cc = ct->ct_cc;
178: cardbus_function_tag_t cf = ct->ct_cf;
179:
180: /* power on the socket */
181: Cardbus_function_enable(ct);
182:
183: /* setup the PCI configuration registers */
184: pgt_cardbus_setup(csc);
185:
186: /* map and establish the interrupt handler */
187: csc->sc_ih = cardbus_intr_establish(cc, cf, csc->sc_intrline, IPL_NET,
188: pgt_intr, sc, sc->sc_dev.dv_xname);
189: if (csc->sc_ih == NULL) {
190: printf("%s: could not establish interrupt at %d\n",
191: sc->sc_dev.dv_xname, csc->sc_intrline);
192: Cardbus_function_disable(ct);
193: return (1);
194: }
195:
196: return (0);
197: }
198:
199: void
200: pgt_cardbus_disable(struct pgt_softc *sc)
201: {
202: struct pgt_cardbus_softc *csc = (struct pgt_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: /* unhook the interrupt handler */
208: cardbus_intr_disestablish(cc, cf, csc->sc_ih);
209: csc->sc_ih = NULL;
210:
211: /* power down the socket */
212: Cardbus_function_disable(ct);
213: }
214:
215: void
216: pgt_cardbus_power(struct pgt_softc *sc, int why)
217: {
218: if (why == PWR_RESUME)
219: if (sc->sc_enable != NULL)
220: (*sc->sc_enable)(sc);
221: if (why == PWR_SUSPEND)
222: if (sc->sc_disable != NULL)
223: (*sc->sc_disable)(sc);
224: }
225:
226: void
227: pgt_cardbus_setup(struct pgt_cardbus_softc *csc)
228: {
229: cardbus_devfunc_t ct = csc->sc_ct;
230: cardbus_chipset_tag_t cc = ct->ct_cc;
231: cardbus_function_tag_t cf = ct->ct_cf;
232: pcireg_t reg;
233:
234: /* program the BAR */
235: cardbus_conf_write(cc, cf, csc->sc_tag, CARDBUS_BASE0_REG,
236: csc->sc_bar0_val);
237:
238: /* make sure the right access type is on the cardbus bridge */
239: (*cf->cardbus_ctrl)(cc, CARDBUS_MEM_ENABLE);
240: (*cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);
241:
242: /* enable the appropriate bits in the PCI CSR */
243: reg = cardbus_conf_read(cc, cf, csc->sc_tag,
244: CARDBUS_COMMAND_STATUS_REG);
245: reg |= CARDBUS_COMMAND_MASTER_ENABLE | CARDBUS_COMMAND_MEM_ENABLE;
246: cardbus_conf_write(cc, cf, csc->sc_tag, CARDBUS_COMMAND_STATUS_REG,
247: reg);
248: }
CVSweb