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