Line data Source code
1 : /* $OpenBSD: if_atw_pci.c,v 1.18 2015/11/24 17:11:39 mpi Exp $ */
2 : /* $NetBSD: if_atw_pci.c,v 1.7 2004/07/23 07:07:55 dyoung Exp $ */
3 :
4 : /*-
5 : * Copyright (c) 1998, 1999, 2000, 2002 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; Charles M. Hannum; and David Young.
11 : *
12 : * Redistribution and use in source and binary forms, with or without
13 : * modification, are permitted provided that the following conditions
14 : * are met:
15 : * 1. Redistributions of source code must retain the above copyright
16 : * notice, this list of conditions and the following disclaimer.
17 : * 2. Redistributions in binary form must reproduce the above copyright
18 : * notice, this list of conditions and the following disclaimer in the
19 : * documentation and/or other materials provided with the distribution.
20 : *
21 : * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
22 : * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 : * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 : * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
25 : * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 : * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 : * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 : * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 : * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 : * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 : * POSSIBILITY OF SUCH DAMAGE.
32 : */
33 :
34 : /*
35 : * PCI bus front-end for the ADMtek ADM8211 802.11 MAC/BBP chip.
36 : *
37 : * Derived from the ``Tulip'' PCI bus front-end.
38 : */
39 :
40 : #include <sys/param.h>
41 : #include <sys/systm.h>
42 : #include <sys/mbuf.h>
43 : #include <sys/malloc.h>
44 : #include <sys/kernel.h>
45 : #include <sys/socket.h>
46 : #include <sys/ioctl.h>
47 : #include <sys/errno.h>
48 : #include <sys/device.h>
49 : #include <sys/endian.h>
50 :
51 : #include <net/if.h>
52 : #include <net/if_media.h>
53 : #include <netinet/in.h>
54 : #include <netinet/if_ether.h>
55 :
56 : #include <net80211/ieee80211_radiotap.h>
57 : #include <net80211/ieee80211_var.h>
58 :
59 : #include <machine/bus.h>
60 : #include <machine/intr.h>
61 :
62 : #include <dev/ic/atwreg.h>
63 : #include <dev/ic/rf3000reg.h>
64 : #include <dev/ic/si4136reg.h>
65 : #include <dev/ic/atwvar.h>
66 :
67 : #include <dev/pci/pcivar.h>
68 : #include <dev/pci/pcireg.h>
69 : #include <dev/pci/pcidevs.h>
70 :
71 : /*
72 : * PCI configuration space registers used by the ADM8211.
73 : */
74 : #define ATW_PCI_IOBA 0x10 /* i/o mapped base */
75 : #define ATW_PCI_MMBA 0x14 /* memory mapped base */
76 :
77 : struct atw_pci_softc {
78 : struct atw_softc psc_atw; /* real ADM8211 softc */
79 :
80 : pci_intr_handle_t psc_ih; /* interrupt handle */
81 : void *psc_intrcookie;
82 :
83 : pci_chipset_tag_t psc_pc; /* our PCI chipset */
84 : pcitag_t psc_pcitag; /* our PCI tag */
85 : };
86 :
87 : int atw_pci_match(struct device *, void *, void *);
88 : void atw_pci_attach(struct device *, struct device *, void *);
89 : int atw_pci_detach(struct device *, int);
90 :
91 : struct cfattach atw_pci_ca = {
92 : sizeof (struct atw_softc), atw_pci_match, atw_pci_attach, atw_pci_detach,
93 : atw_activate
94 : };
95 :
96 : const struct pci_matchid atw_pci_devices[] = {
97 : { PCI_VENDOR_ADMTEK, PCI_PRODUCT_ADMTEK_ADM8211 },
98 : { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3CRSHPW796 }
99 : };
100 :
101 : int
102 0 : atw_pci_match(struct device *parent, void *match, void *aux)
103 : {
104 0 : return (pci_matchbyid((struct pci_attach_args *)aux, atw_pci_devices,
105 : nitems(atw_pci_devices)));
106 : }
107 :
108 : static int
109 0 : atw_pci_enable(struct atw_softc *sc)
110 : {
111 0 : struct atw_pci_softc *psc = (void *)sc;
112 :
113 : /* Establish the interrupt. */
114 0 : psc->psc_intrcookie = pci_intr_establish(psc->psc_pc, psc->psc_ih,
115 0 : IPL_NET, atw_intr, sc, sc->sc_dev.dv_xname);
116 0 : if (psc->psc_intrcookie == NULL) {
117 0 : printf("%s: unable to establish interrupt\n",
118 : sc->sc_dev.dv_xname);
119 0 : return (1);
120 : }
121 :
122 0 : return (0);
123 0 : }
124 :
125 : static void
126 0 : atw_pci_disable(struct atw_softc *sc)
127 : {
128 0 : struct atw_pci_softc *psc = (void *)sc;
129 :
130 : /* Unhook the interrupt handler. */
131 0 : pci_intr_disestablish(psc->psc_pc, psc->psc_intrcookie);
132 0 : psc->psc_intrcookie = NULL;
133 0 : }
134 :
135 : void
136 0 : atw_pci_attach(struct device *parent, struct device *self, void *aux)
137 : {
138 0 : struct atw_pci_softc *psc = (void *) self;
139 0 : struct atw_softc *sc = &psc->psc_atw;
140 0 : struct pci_attach_args *pa = aux;
141 0 : pci_chipset_tag_t pc = pa->pa_pc;
142 : const char *intrstr = NULL;
143 0 : bus_space_tag_t iot, memt;
144 0 : bus_space_handle_t ioh, memh;
145 0 : bus_size_t iosize, memsize;
146 : int ioh_valid, memh_valid;
147 :
148 0 : psc->psc_pc = pa->pa_pc;
149 0 : psc->psc_pcitag = pa->pa_tag;
150 :
151 : /*
152 : * No power management hooks.
153 : * XXX Maybe we should add some!
154 : */
155 0 : sc->sc_flags |= ATWF_ENABLED;
156 :
157 : /*
158 : * Get revision info, and set some chip-specific variables.
159 : */
160 0 : sc->sc_rev = PCI_REVISION(pa->pa_class);
161 :
162 : /*
163 : * Check to see if the device is in power-save mode, and
164 : * being it out if necessary.
165 : *
166 : * XXX This code comes almost verbatim from if_tlp_pci.c. I do
167 : * not understand it. Tulip clears the "sleep mode" bit in the
168 : * CFDA register, first. There is an equivalent (?) register at the
169 : * same place in the ADM8211, but the docs do not assign its bits
170 : * any meanings. -dcy
171 : */
172 0 : pci_set_powerstate(pc, pa->pa_tag, PCI_PMCSR_STATE_D0);
173 :
174 : /*
175 : * Map the device.
176 : */
177 0 : ioh_valid = (pci_mapreg_map(pa, ATW_PCI_IOBA,
178 : PCI_MAPREG_TYPE_IO, 0,
179 0 : &iot, &ioh, NULL, &iosize, 0) == 0);
180 0 : memh_valid = (pci_mapreg_map(pa, ATW_PCI_MMBA,
181 : PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0,
182 0 : &memt, &memh, NULL, &memsize, 0) == 0);
183 :
184 0 : if (memh_valid) {
185 0 : sc->sc_st = memt;
186 0 : sc->sc_sh = memh;
187 0 : sc->sc_mapsize = memsize;
188 0 : } else if (ioh_valid) {
189 0 : sc->sc_st = iot;
190 0 : sc->sc_sh = ioh;
191 0 : sc->sc_mapsize = iosize;
192 : } else {
193 0 : printf(": unable to map device registers\n");
194 0 : return;
195 : }
196 :
197 0 : sc->sc_dmat = pa->pa_dmat;
198 :
199 : /*
200 : * Get the cacheline size.
201 : */
202 0 : sc->sc_cacheline = PCI_CACHELINE(pci_conf_read(pc, pa->pa_tag,
203 : PCI_BHLC_REG));
204 :
205 : /*
206 : * Get PCI data moving command info.
207 : */
208 0 : if (pa->pa_flags & PCI_FLAGS_MRL_OKAY) /* read line */
209 0 : sc->sc_flags |= ATWF_MRL;
210 0 : if (pa->pa_flags & PCI_FLAGS_MRM_OKAY) /* read multiple */
211 0 : sc->sc_flags |= ATWF_MRM;
212 0 : if (pa->pa_flags & PCI_FLAGS_MWI_OKAY) /* write invalidate */
213 0 : sc->sc_flags |= ATWF_MWI;
214 :
215 : /*
216 : * Map and establish our interrupt.
217 : */
218 0 : if (pci_intr_map(pa, &psc->psc_ih)) {
219 0 : printf(": unable to map interrupt\n");
220 0 : return;
221 : }
222 0 : intrstr = pci_intr_string(pc, psc->psc_ih);
223 0 : psc->psc_intrcookie = pci_intr_establish(pc, psc->psc_ih, IPL_NET,
224 0 : atw_intr, sc, sc->sc_dev.dv_xname);
225 0 : if (psc->psc_intrcookie == NULL) {
226 0 : printf(": unable to establish interrupt");
227 0 : if (intrstr != NULL)
228 0 : printf(" at %s", intrstr);
229 0 : printf("\n");
230 0 : return;
231 : }
232 :
233 0 : printf(": %s\n", intrstr);
234 :
235 0 : sc->sc_enable = atw_pci_enable;
236 0 : sc->sc_disable = atw_pci_disable;
237 :
238 : /*
239 : * Finish off the attach.
240 : */
241 0 : atw_attach(sc);
242 0 : }
243 :
244 : int
245 0 : atw_pci_detach(struct device *self, int flags)
246 : {
247 0 : struct atw_pci_softc *psc = (void *)self;
248 0 : struct atw_softc *sc = &psc->psc_atw;
249 : int rv;
250 :
251 0 : rv = atw_detach(sc);
252 0 : if (rv)
253 0 : return (rv);
254 :
255 0 : if (psc->psc_intrcookie != NULL)
256 0 : pci_intr_disestablish(psc->psc_pc, psc->psc_intrcookie);
257 :
258 0 : bus_space_unmap(sc->sc_st, sc->sc_sh, sc->sc_mapsize);
259 :
260 0 : return (0);
261 0 : }
|