1 /* $OpenBSD: if_dc_pci.c,v 1.22 2001/12/13 17:43:03 nate Exp $ */ 2 3 /* 4 * Copyright (c) 1997, 1998, 1999 5 * Bill Paul <wpaul@ee.columbia.edu>. 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. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Bill Paul. 18 * 4. Neither the name of the author nor the names of any co-contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 26 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 32 * THE POSSIBILITY OF SUCH DAMAGE. 33 * 34 * $FreeBSD: src/sys/pci/if_dc.c,v 1.5 2000/01/12 22:24:05 wpaul Exp $ 35 */ 36 37 #include "bpfilter.h" 38 39 #include <sys/param.h> 40 #include <sys/systm.h> 41 #include <sys/mbuf.h> 42 #include <sys/protosw.h> 43 #include <sys/socket.h> 44 #include <sys/ioctl.h> 45 #include <sys/errno.h> 46 #include <sys/malloc.h> 47 #include <sys/kernel.h> 48 #include <sys/device.h> 49 50 #include <net/if.h> 51 #include <net/if_dl.h> 52 #include <net/if_types.h> 53 54 #ifdef INET 55 #include <netinet/in.h> 56 #include <netinet/in_systm.h> 57 #include <netinet/in_var.h> 58 #include <netinet/ip.h> 59 #include <netinet/if_ether.h> 60 #endif 61 62 #include <net/if_media.h> 63 64 #if NBPFILTER > 0 65 #include <net/bpf.h> 66 #endif 67 68 #include <uvm/uvm_extern.h> /* for vtophys */ 69 70 #include <dev/mii/mii.h> 71 #include <dev/mii/miivar.h> 72 73 #include <dev/pci/pcireg.h> 74 #include <dev/pci/pcivar.h> 75 #include <dev/pci/pcidevs.h> 76 77 #define DC_USEIOSPACE 78 79 #include <dev/ic/dcreg.h> 80 81 /* 82 * Various supported device vendors/types and their names. 83 */ 84 struct dc_type dc_devs[] = { 85 { PCI_VENDOR_DEC, PCI_PRODUCT_DEC_21142 }, 86 { PCI_VENDOR_DAVICOM, PCI_PRODUCT_DAVICOM_DM9100 }, 87 { PCI_VENDOR_DAVICOM, PCI_PRODUCT_DAVICOM_DM9102 }, 88 { PCI_VENDOR_ADMTEK, PCI_PRODUCT_ADMTEK_AL981 }, 89 { PCI_VENDOR_ADMTEK, PCI_PRODUCT_ADMTEK_AN983 }, 90 { PCI_VENDOR_ASIX, PCI_PRODUCT_ASIX_AX88140A }, 91 { PCI_VENDOR_MACRONIX, PCI_PRODUCT_MACRONIX_MX98713 }, 92 { PCI_VENDOR_MACRONIX, PCI_PRODUCT_MACRONIX_MX98715 }, 93 { PCI_VENDOR_MACRONIX, PCI_PRODUCT_MACRONIX_MX98727 }, 94 { PCI_VENDOR_COMPEX, PCI_PRODUCT_COMPEX_98713 }, 95 { PCI_VENDOR_LITEON, PCI_PRODUCT_LITEON_PNIC }, 96 { PCI_VENDOR_LITEON, PCI_PRODUCT_LITEON_PNICII }, 97 { PCI_VENDOR_ACCTON, PCI_PRODUCT_ACCTON_EN1217 }, 98 { PCI_VENDOR_ACCTON, PCI_PRODUCT_ACCTON_EN2242 }, 99 { 0, 0 } 100 }; 101 102 int dc_pci_match __P((struct device *, void *, void *)); 103 void dc_pci_attach __P((struct device *, struct device *, void *)); 104 void dc_pci_acpi __P((struct device *, void *)); 105 106 extern void dc_eeprom_width __P((struct dc_softc *)); 107 extern void dc_read_srom __P((struct dc_softc *, int)); 108 extern void dc_parse_21143_srom __P((struct dc_softc *)); 109 110 /* 111 * Probe for a 21143 or clone chip. Check the PCI vendor and device 112 * IDs against our list and return a device name if we find a match. 113 */ 114 int 115 dc_pci_match(parent, match, aux) 116 struct device *parent; 117 void *match, *aux; 118 { 119 struct pci_attach_args *pa = (struct pci_attach_args *)aux; 120 struct dc_type *t; 121 122 for (t = dc_devs; t->dc_vid != 0; t++) { 123 if ((PCI_VENDOR(pa->pa_id) == t->dc_vid) && 124 (PCI_PRODUCT(pa->pa_id) == t->dc_did)) 125 return (1); 126 } 127 return (0); 128 } 129 130 void dc_pci_acpi(self, aux) 131 struct device *self; 132 void *aux; 133 { 134 struct dc_softc *sc = (struct dc_softc *)self; 135 struct pci_attach_args *pa = (struct pci_attach_args *)aux; 136 pci_chipset_tag_t pc = pa->pa_pc; 137 u_int32_t r, cptr; 138 int unit; 139 140 unit = sc->dc_unit; 141 142 /* Find the location of the capabilities block */ 143 cptr = pci_conf_read(pc, pa->pa_tag, DC_PCI_CCAP) & 0xFF; 144 145 r = pci_conf_read(pc, pa->pa_tag, cptr) & 0xFF; 146 if (r == 0x01) { 147 148 r = pci_conf_read(pc, pa->pa_tag, cptr + 4); 149 if (r & DC_PSTATE_D3) { 150 u_int32_t iobase, membase, irq; 151 152 /* Save important PCI config data. */ 153 iobase = pci_conf_read(pc, pa->pa_tag, DC_PCI_CFBIO); 154 membase = pci_conf_read(pc, pa->pa_tag, DC_PCI_CFBMA); 155 irq = pci_conf_read(pc, pa->pa_tag, DC_PCI_CFIT); 156 157 /* Reset the power state. */ 158 printf("dc%d: chip is in D%d power mode " 159 "-- setting to D0\n", unit, r & DC_PSTATE_D3); 160 r &= 0xFFFFFFFC; 161 pci_conf_write(pc, pa->pa_tag, cptr + 4, r); 162 163 /* Restore PCI config data. */ 164 pci_conf_write(pc, pa->pa_tag, DC_PCI_CFBIO, iobase); 165 pci_conf_write(pc, pa->pa_tag, DC_PCI_CFBMA, membase); 166 pci_conf_write(pc, pa->pa_tag, DC_PCI_CFIT, irq); 167 } 168 } 169 return; 170 } 171 172 /* 173 * Attach the interface. Allocate softc structures, do ifmedia 174 * setup and ethernet/BPF attach. 175 */ 176 void dc_pci_attach(parent, self, aux) 177 struct device *parent, *self; 178 void *aux; 179 { 180 int s; 181 const char *intrstr = NULL; 182 u_int32_t command; 183 struct dc_softc *sc = (struct dc_softc *)self; 184 struct pci_attach_args *pa = aux; 185 pci_chipset_tag_t pc = pa->pa_pc; 186 pci_intr_handle_t ih; 187 bus_addr_t iobase; 188 bus_size_t iosize; 189 u_int32_t revision; 190 int found = 0; 191 192 s = splimp(); 193 sc->sc_dmat = pa->pa_dmat; 194 sc->dc_unit = sc->sc_dev.dv_unit; 195 196 /* 197 * Handle power management nonsense. 198 */ 199 dc_pci_acpi(self, aux); 200 201 /* 202 * Map control/status registers. 203 */ 204 command = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 205 command |= PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE | 206 PCI_COMMAND_MASTER_ENABLE; 207 pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, command); 208 command = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 209 210 sc->dc_csid = pci_conf_read(pc, pa->pa_tag, PCI_SUBSYS_ID_REG); 211 212 #ifdef DC_USEIOSPACE 213 if (!(command & PCI_COMMAND_IO_ENABLE)) { 214 printf(": failed to enable I/O ports\n"); 215 goto fail; 216 } 217 if (pci_io_find(pc, pa->pa_tag, DC_PCI_CFBIO, &iobase, &iosize)) { 218 printf(": can't find I/O space\n"); 219 goto fail; 220 } 221 if (bus_space_map(pa->pa_iot, iobase, iosize, 0, &sc->dc_bhandle)) { 222 printf(": can't map I/O space\n"); 223 goto fail; 224 } 225 sc->dc_btag = pa->pa_iot; 226 #else 227 if (!(command & PCI_COMMAND_MEM_ENABLE)) { 228 printf(": failed to enable memory mapping\n"); 229 goto fail; 230 } 231 if (pci_mem_find(pc, pa->pa_tag, DC_PCI_CFBMA, &iobase, &iosize, NULL)){ 232 printf(": can't find mem space\n"); 233 goto fail; 234 } 235 if (bus_space_map(pa->pa_memt, iobase, iosize, 0, &sc->dc_bhandle)) { 236 printf(": can't map mem space\n"); 237 goto fail; 238 } 239 sc->dc_btag = pa->pa_memt; 240 #endif 241 242 /* Allocate interrupt */ 243 if (pci_intr_map(pa, &ih)) { 244 printf(": couldn't map interrupt\n"); 245 goto fail; 246 } 247 intrstr = pci_intr_string(pc, ih); 248 sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, dc_intr, sc, 249 self->dv_xname); 250 if (sc->sc_ih == NULL) { 251 printf(": couldn't establish interrupt"); 252 if (intrstr != NULL) 253 printf(" at %s", intrstr); 254 printf("\n"); 255 goto fail; 256 } 257 printf(": %s", intrstr); 258 259 /* Need this info to decide on a chip type. */ 260 sc->dc_revision = revision = PCI_REVISION(pa->pa_class); 261 262 switch (PCI_VENDOR(pa->pa_id)) { 263 case PCI_VENDOR_DEC: 264 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_DEC_21142) { 265 found = 1; 266 sc->dc_type = DC_TYPE_21143; 267 sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR; 268 sc->dc_flags |= DC_REDUCED_MII_POLL; 269 dc_eeprom_width(sc); 270 dc_read_srom(sc, sc->dc_romwidth); 271 } 272 break; 273 case PCI_VENDOR_DAVICOM: 274 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_DAVICOM_DM9100 || 275 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_DAVICOM_DM9102) { 276 found = 1; 277 sc->dc_type = DC_TYPE_DM9102; 278 sc->dc_flags |= DC_TX_COALESCE|DC_TX_INTR_ALWAYS; 279 sc->dc_flags |= DC_REDUCED_MII_POLL|DC_TX_STORENFWD; 280 sc->dc_pmode = DC_PMODE_MII; 281 282 /* Increase the latency timer value. */ 283 command = pci_conf_read(pc, pa->pa_tag, DC_PCI_CFLT); 284 command &= 0xFFFF00FF; 285 command |= 0x00008000; 286 pci_conf_write(pc, pa->pa_tag, DC_PCI_CFLT, command); 287 } 288 break; 289 case PCI_VENDOR_ADMTEK: 290 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ADMTEK_AL981) { 291 found = 1; 292 sc->dc_type = DC_TYPE_AL981; 293 sc->dc_flags |= DC_TX_USE_TX_INTR; 294 sc->dc_flags |= DC_TX_ADMTEK_WAR; 295 sc->dc_pmode = DC_PMODE_MII; 296 } 297 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ADMTEK_AN983) { 298 found = 1; 299 sc->dc_type = DC_TYPE_AN983; 300 sc->dc_flags |= DC_TX_USE_TX_INTR; 301 sc->dc_flags |= DC_TX_ADMTEK_WAR; 302 sc->dc_pmode = DC_PMODE_MII; 303 } 304 dc_eeprom_width(sc); 305 dc_read_srom(sc, sc->dc_romwidth); 306 break; 307 case PCI_VENDOR_MACRONIX: 308 case PCI_VENDOR_ACCTON: 309 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ACCTON_EN2242) { 310 found = 1; 311 sc->dc_type = DC_TYPE_AN983; 312 sc->dc_flags |= DC_TX_USE_TX_INTR; 313 sc->dc_flags |= DC_TX_ADMTEK_WAR; 314 sc->dc_pmode = DC_PMODE_MII; 315 316 dc_eeprom_width(sc); 317 dc_read_srom(sc, sc->dc_romwidth); 318 } 319 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_MACRONIX_MX98713) { 320 found = 1; 321 if (revision < DC_REVISION_98713A) { 322 sc->dc_type = DC_TYPE_98713; 323 } 324 if (revision >= DC_REVISION_98713A) { 325 sc->dc_type = DC_TYPE_98713A; 326 sc->dc_flags |= DC_21143_NWAY; 327 } 328 sc->dc_flags |= DC_REDUCED_MII_POLL; 329 sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR; 330 } 331 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_MACRONIX_MX98715 || 332 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ACCTON_EN1217) { 333 found = 1; 334 if (revision >= DC_REVISION_98715AEC_C && 335 revision < DC_REVISION_98725) 336 sc->dc_flags |= DC_128BIT_HASH; 337 sc->dc_type = DC_TYPE_987x5; 338 sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR; 339 sc->dc_flags |= DC_REDUCED_MII_POLL|DC_21143_NWAY; 340 } 341 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_MACRONIX_MX98727) { 342 found = 1; 343 sc->dc_type = DC_TYPE_987x5; 344 sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR; 345 sc->dc_flags |= DC_REDUCED_MII_POLL|DC_21143_NWAY; 346 } 347 break; 348 case PCI_VENDOR_COMPEX: 349 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_COMPEX_98713) { 350 found = 1; 351 if (revision < DC_REVISION_98713A) { 352 sc->dc_type = DC_TYPE_98713; 353 sc->dc_flags |= DC_REDUCED_MII_POLL; 354 } 355 if (revision >= DC_REVISION_98713A) 356 sc->dc_type = DC_TYPE_98713A; 357 sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR; 358 } 359 break; 360 case PCI_VENDOR_LITEON: 361 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_LITEON_PNICII) { 362 found = 1; 363 sc->dc_type = DC_TYPE_PNICII; 364 sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR; 365 sc->dc_flags |= DC_REDUCED_MII_POLL|DC_21143_NWAY; 366 sc->dc_flags |= DC_128BIT_HASH; 367 } 368 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_LITEON_PNIC) { 369 found = 1; 370 sc->dc_type = DC_TYPE_PNIC; 371 sc->dc_flags |= DC_TX_STORENFWD|DC_TX_INTR_ALWAYS; 372 sc->dc_flags |= DC_PNIC_RX_BUG_WAR; 373 sc->dc_pnic_rx_buf = malloc(DC_RXLEN * 5, M_DEVBUF, 374 M_NOWAIT); 375 if (revision < DC_REVISION_82C169) 376 sc->dc_pmode = DC_PMODE_SYM; 377 } 378 break; 379 case PCI_VENDOR_ASIX: 380 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ASIX_AX88140A) { 381 found = 1; 382 sc->dc_type = DC_TYPE_ASIX; 383 sc->dc_flags |= DC_TX_USE_TX_INTR|DC_TX_INTR_FIRSTFRAG; 384 sc->dc_flags |= DC_REDUCED_MII_POLL; 385 sc->dc_pmode = DC_PMODE_MII; 386 } 387 break; 388 } 389 if (found == 0) { 390 /* This shouldn't happen if probe has done it's job... */ 391 printf(": unknown device: %x:%x\n", 392 PCI_VENDOR(pa->pa_id), PCI_PRODUCT(pa->pa_id)); 393 goto fail; 394 } 395 396 /* Save the cache line size. */ 397 if (DC_IS_DAVICOM(sc)) 398 sc->dc_cachesize = 0; 399 else 400 sc->dc_cachesize = pci_conf_read(pc, pa->pa_tag, 401 DC_PCI_CFLT) & 0xFF; 402 403 /* Reset the adapter. */ 404 dc_reset(sc); 405 406 /* Take 21143 out of snooze mode */ 407 if (DC_IS_INTEL(sc)) { 408 command = pci_conf_read(pc, pa->pa_tag, DC_PCI_CFDD); 409 command &= ~(DC_CFDD_SNOOZE_MODE|DC_CFDD_SLEEP_MODE); 410 pci_conf_write(pc, pa->pa_tag, DC_PCI_CFDD, command); 411 } 412 413 /* 414 * If we discover later (in dc_attach) that we have an 415 * MII with no PHY, we need to have the 21143 drive the LEDs. 416 * Except there are some systems like the NEC VersaPro NoteBook PC 417 * which have no LEDs, and twiddling these bits has adverse effects 418 * on them. (I.e. you suddenly can't get a link.) 419 * 420 * If mii_attach() returns an error, we leave the DC_TULIP_LEDS 421 * bit set, else we clear it. Since our dc(4) driver is split into 422 * bus-dependent and bus-independent parts, we must do set this bit 423 * here while we are able to do PCI configuration reads. 424 */ 425 if (DC_IS_INTEL(sc)) { 426 if (pci_conf_read(pc, pa->pa_tag, DC_PCI_CSID) != 0x80281033) 427 sc->dc_flags |= DC_TULIP_LEDS; 428 } 429 430 /* 431 * Try to learn something about the supported media. 432 * We know that ASIX and ADMtek and Davicom devices 433 * will *always* be using MII media, so that's a no-brainer. 434 * The tricky ones are the Macronix/PNIC II and the 435 * Intel 21143. 436 */ 437 if (DC_IS_INTEL(sc)) 438 dc_parse_21143_srom(sc); 439 else if (DC_IS_MACRONIX(sc) || DC_IS_PNICII(sc)) { 440 if (sc->dc_type == DC_TYPE_98713) 441 sc->dc_pmode = DC_PMODE_MII; 442 else 443 sc->dc_pmode = DC_PMODE_SYM; 444 } else if (!sc->dc_pmode) 445 sc->dc_pmode = DC_PMODE_MII; 446 447 #ifdef __sparc64__ 448 { 449 extern void myetheraddr __P((u_char *)); 450 myetheraddr(sc->arpcom.ac_enaddr); 451 sc->sc_hasmac = 1; 452 } 453 #endif 454 455 #ifdef SRM_MEDIA 456 sc->dc_srm_media = 0; 457 458 /* Remember the SRM console media setting */ 459 if (DC_IS_INTEL(sc)) { 460 command = pci_conf_read(pc, pa->pa_tag, DC_PCI_CFDD); 461 command &= ~(DC_CFDD_SNOOZE_MODE|DC_CFDD_SLEEP_MODE); 462 switch ((command >> 8) & 0xff) { 463 case 3: 464 sc->dc_srm_media = IFM_10_T; 465 break; 466 case 4: 467 sc->dc_srm_media = IFM_10_T | IFM_FDX; 468 break; 469 case 5: 470 sc->dc_srm_media = IFM_100_TX; 471 break; 472 case 6: 473 sc->dc_srm_media = IFM_100_TX | IFM_FDX; 474 break; 475 } 476 if (sc->dc_srm_media) 477 sc->dc_srm_media |= IFM_ACTIVE | IFM_ETHER; 478 } 479 #endif 480 dc_eeprom_width(sc); 481 dc_attach(sc); 482 483 fail: 484 splx(s); 485 } 486 487 struct cfattach dc_pci_ca = { 488 sizeof(struct dc_softc), dc_pci_match, dc_pci_attach 489 }; 490