xref: /openbsd-src/sys/dev/pci/if_wi_pci.c (revision 3a3fbb3f2e2521ab7c4a56b7ff7462ebd9095ec5)
1 /*	$OpenBSD: if_wi_pci.c,v 1.12 2001/12/20 17:48:25 mickey Exp $	*/
2 
3 /*
4  * Copyright (c) 2001 Todd C. Miller <Todd.Miller@courtesan.com>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
19  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
21  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 /*
30  * Copyright (c) 1997, 1998, 1999
31  *	Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
32  *
33  * Redistribution and use in source and binary forms, with or without
34  * modification, are permitted provided that the following conditions
35  * are met:
36  * 1. Redistributions of source code must retain the above copyright
37  *    notice, this list of conditions and the following disclaimer.
38  * 2. Redistributions in binary form must reproduce the above copyright
39  *    notice, this list of conditions and the following disclaimer in the
40  *    documentation and/or other materials provided with the distribution.
41  * 3. All advertising materials mentioning features or use of this software
42  *    must display the following acknowledgement:
43  *	This product includes software developed by Bill Paul.
44  * 4. Neither the name of the author nor the names of any co-contributors
45  *    may be used to endorse or promote products derived from this software
46  *    without specific prior written permission.
47  *
48  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
49  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
52  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
53  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
54  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
55  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
56  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
57  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
58  * THE POSSIBILITY OF SUCH DAMAGE.
59  */
60 
61 /*
62  * This is a PCI shim for the Wavelan wireless network driver.
63  * It works with PCI adaptors based on the PLX 9050 and PLX 9052
64  * PCI to "dumb bus" bridge chip.  It has been tested with the
65  * Global Sun Technology GL24110P02 (aka Linksys WDT11), 3Com 3CRWE777A,
66  * and Netgear MA301.  It is also expected to work with the
67  * Global Sun GL24110P and Eumitcom WL11000P.
68  *
69  * All we do here is handle the PCI match and attach, set up an
70  * interrupt handler entry point, and setup the PLX chip for level
71  * interrupts and config index 1.
72  *
73  * The PLX 9052 provides us with multiple PCI address space mappings.
74  * The primary mappings at PCI registers 0x10 (mem) and 0x14 (I/O) are for
75  * the PLX chip itself, *NOT* the pcmcia card.
76  * The PLX 9052 provides 4 local address space registers: 0x18, 0x1C,
77  * 0x20, and 0x24.  The mem and I/O spaces for the PCMCIA card are
78  * mapped to 0x18 and 0x1C respectively.
79  *
80  * The datasheet may be downloaded from PLX (though you do have to register)
81  * http://www.plxtech.com/products/toolbox/9050.htm
82  */
83 
84 #include <sys/param.h>
85 #include <sys/systm.h>
86 #include <sys/device.h>
87 #include <sys/timeout.h>
88 #include <sys/socket.h>
89 
90 #include <net/if.h>
91 #include <net/if_dl.h>
92 #include <net/if_media.h>
93 
94 #ifdef INET
95 #include <netinet/in.h>
96 #include <netinet/if_ether.h>
97 #endif
98 
99 #include <net/if_ieee80211.h>
100 
101 #include <machine/bus.h>
102 
103 #include <dev/pci/pcireg.h>
104 #include <dev/pci/pcivar.h>
105 #include <dev/pci/pcidevs.h>
106 
107 #include <dev/ic/if_wireg.h>
108 #include <dev/ic/if_wi_ieee.h>
109 #include <dev/ic/if_wivar.h>
110 
111 #define WI_PCI_CBMA		0x10
112 #define WI_PCI_PLX_LOMEM	0x10	/* PLX chip membase */
113 #define WI_PCI_PLX_LOIO		0x14	/* PLX chip iobase */
114 #define WI_PCI_LOMEM		0x18	/* ISA membase */
115 #define WI_PCI_LOIO		0x1C	/* ISA iobase */
116 
117 const struct wi_pci_product *wi_pci_lookup __P((struct pci_attach_args *pa));
118 int	wi_pci_match	__P((struct device *, void *, void *));
119 void	wi_pci_attach	__P((struct device *, struct device *, void *));
120 int	wi_intr		__P((void *));
121 int	wi_attach	__P((struct wi_softc *, int));
122 
123 struct cfattach wi_pci_ca = {
124 	sizeof (struct wi_softc), wi_pci_match, wi_pci_attach
125 };
126 
127 static const struct wi_pci_product {
128 	pci_vendor_id_t pp_vendor;
129 	pci_product_id_t pp_product;
130 	int pp_plx;
131 } wi_pci_products[] = {
132 	{ PCI_VENDOR_GLOBALSUN, PCI_PRODUCT_GLOBALSUN_GL24110P, 1 },
133 	{ PCI_VENDOR_GLOBALSUN, PCI_PRODUCT_GLOBALSUN_GL24110P02, 1 },
134 	{ PCI_VENDOR_EUMITCOM, PCI_PRODUCT_EUMITCOM_WL11000P, 1 },
135 	{ PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3CRWE777A, 1 },
136 	{ PCI_VENDOR_NETGEAR, PCI_PRODUCT_NETGEAR_MA301, 1 },
137 	{ PCI_VENDOR_INTERSIL, PCI_PRODUCT_INTERSIL_MINI_PCI_WLAN, 0 },
138 	{ 0, 0 }
139 };
140 
141 const struct wi_pci_product *
142 wi_pci_lookup(pa)
143 	struct pci_attach_args *pa;
144 {
145 	const struct wi_pci_product *pp;
146 
147 	for (pp = wi_pci_products; pp->pp_product != 0; pp++) {
148 		if (PCI_VENDOR(pa->pa_id) == pp->pp_vendor &&
149 		    PCI_PRODUCT(pa->pa_id) == pp->pp_product)
150 			return (pp);
151 	}
152 
153 	return (NULL);
154 }
155 
156 int
157 wi_pci_match(parent, match, aux)
158 	struct device *parent;
159 	void *match;
160 	void *aux;
161 {
162 	return (wi_pci_lookup(aux) != NULL);
163 }
164 
165 void
166 wi_pci_attach(parent, self, aux)
167 	struct device *parent;
168 	struct device *self;
169 	void *aux;
170 {
171 	struct wi_softc *sc = (struct wi_softc *)self;
172 	struct pci_attach_args *pa = aux;
173 	const struct wi_pci_product *pp;
174 	pci_intr_handle_t ih;
175 	bus_space_handle_t ioh, memh;
176 	bus_space_tag_t iot = pa->pa_iot;
177 	bus_space_tag_t memt = pa->pa_memt;
178 	pci_chipset_tag_t pc = pa->pa_pc;
179 	pcireg_t csr;
180 	const char *intrstr;
181 
182 	pp = wi_pci_lookup(pa);
183 	if (pp->pp_plx) {
184 		/* Map memory and I/O registers. */
185 		if (pci_mapreg_map(pa, WI_PCI_LOMEM, PCI_MAPREG_TYPE_MEM, 0,
186 		    &memt, &memh, NULL, NULL, 0) != 0) {
187 			printf(": can't map mem space\n");
188 			return;
189 		}
190 		if (pci_mapreg_map(pa, WI_PCI_LOIO, PCI_MAPREG_TYPE_IO, 0,
191 		    &iot, &ioh, NULL, NULL, 0) != 0) {
192 			printf(": can't map I/O space\n");
193 			return;
194 		}
195 	} else {
196 		if (pci_mapreg_map(pa, WI_PCI_CBMA, PCI_MAPREG_TYPE_MEM,
197 		    0, &iot, &ioh, NULL, NULL, 0) != 0) {
198 			printf(": can't map mem space\n");
199 			return;
200 		}
201 
202 		memt = iot;
203 		memh = ioh;
204 		sc->sc_pci = 1;
205 	}
206 
207 	sc->wi_btag = iot;
208 	sc->wi_bhandle = ioh;
209 
210 	/* Enable the card. */
211 	csr = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
212 	pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
213 	    csr | PCI_COMMAND_MASTER_ENABLE);
214 
215 	/* Make sure interrupts are disabled. */
216 	CSR_WRITE_2(sc, WI_INT_EN, 0);
217 	CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
218 
219 	/* Map and establish the interrupt. */
220 	if (pci_intr_map(pa, &ih)) {
221 		printf(": couldn't map interrupt\n");
222 		return;
223 	}
224 	intrstr = pci_intr_string(pc, ih);
225 	sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, wi_intr, sc,
226 	    sc->sc_dev.dv_xname);
227 	if (sc->sc_ih == NULL) {
228 		printf(": couldn't establish interrupt");
229 		if (intrstr != NULL)
230 			printf(" at %s", intrstr);
231 		printf("\n");
232 		return;
233 	}
234 	printf(": %s", intrstr);
235 
236 	if (pp->pp_plx) {
237 		/*
238 		 * Setup the PLX chip for level interrupts and config index 1
239 		 * XXX - should really reset the PLX chip too.
240 		 */
241 		bus_space_write_1(memt, memh,
242 		    WI_PLX_COR_OFFSET, WI_PLX_COR_VALUE);
243 
244 		wi_attach(sc, 1);
245 	} else {
246 		bus_space_write_2(iot, ioh, WI_PCI_COR, WI_PCI_SOFT_RESET);
247 		DELAY(100*1000); /* 100 m sec */
248 		bus_space_write_2(iot, ioh, WI_PCI_COR, 0x0);
249 		DELAY(100*1000); /* 100 m sec */
250 
251 		wi_attach(sc, 0);
252 	}
253 }
254