if_dc_pci.c revision 1.28
1/* $OpenBSD: if_dc_pci.c,v 1.28 2002/03/14 01:26:58 millert 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 <dev/mii/mii.h> 69#include <dev/mii/miivar.h> 70 71#include <dev/pci/pcireg.h> 72#include <dev/pci/pcivar.h> 73#include <dev/pci/pcidevs.h> 74 75#define DC_USEIOSPACE 76 77#include <dev/ic/dcreg.h> 78 79/* 80 * Various supported device vendors/types and their names. 81 */ 82struct dc_type dc_devs[] = { 83 { PCI_VENDOR_DEC, PCI_PRODUCT_DEC_21140 }, 84 { PCI_VENDOR_DEC, PCI_PRODUCT_DEC_21142 }, 85 { PCI_VENDOR_DAVICOM, PCI_PRODUCT_DAVICOM_DM9100 }, 86 { PCI_VENDOR_DAVICOM, PCI_PRODUCT_DAVICOM_DM9102 }, 87 { PCI_VENDOR_ADMTEK, PCI_PRODUCT_ADMTEK_AL981 }, 88 { PCI_VENDOR_ADMTEK, PCI_PRODUCT_ADMTEK_AN983 }, 89 { PCI_VENDOR_ASIX, PCI_PRODUCT_ASIX_AX88140A }, 90 { PCI_VENDOR_MACRONIX, PCI_PRODUCT_MACRONIX_MX98713 }, 91 { PCI_VENDOR_MACRONIX, PCI_PRODUCT_MACRONIX_MX98715 }, 92 { PCI_VENDOR_MACRONIX, PCI_PRODUCT_MACRONIX_MX98727 }, 93 { PCI_VENDOR_COMPEX, PCI_PRODUCT_COMPEX_98713 }, 94 { PCI_VENDOR_LITEON, PCI_PRODUCT_LITEON_PNIC }, 95 { PCI_VENDOR_LITEON, PCI_PRODUCT_LITEON_PNICII }, 96 { PCI_VENDOR_ACCTON, PCI_PRODUCT_ACCTON_EN1217 }, 97 { PCI_VENDOR_ACCTON, PCI_PRODUCT_ACCTON_EN2242 }, 98 { 0, 0 } 99}; 100 101int dc_pci_match(struct device *, void *, void *); 102void dc_pci_attach(struct device *, struct device *, void *); 103void dc_pci_acpi(struct device *, void *); 104 105extern void dc_eeprom_width(struct dc_softc *); 106extern void dc_read_srom(struct dc_softc *, int); 107extern void dc_parse_21143_srom(struct dc_softc *); 108 109/* 110 * Probe for a 21143 or clone chip. Check the PCI vendor and device 111 * IDs against our list and return a device name if we find a match. 112 */ 113int 114dc_pci_match(parent, match, aux) 115 struct device *parent; 116 void *match, *aux; 117{ 118 struct pci_attach_args *pa = (struct pci_attach_args *)aux; 119 struct dc_type *t; 120 121 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_DEC && 122 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_DEC_21140) 123 return (1); 124 125 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_DEC && 126 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_DEC_21142 && 127 PCI_REVISION(pa->pa_class) == 0x21) 128 return (1); 129 130 for (t = dc_devs; t->dc_vid != 0; t++) { 131 if ((PCI_VENDOR(pa->pa_id) == t->dc_vid) && 132 (PCI_PRODUCT(pa->pa_id) == t->dc_did)) { 133#ifdef __alpha__ 134 return (1); 135#else 136 return (2); 137#endif 138 } 139 } 140 141 return (0); 142} 143 144void dc_pci_acpi(self, aux) 145 struct device *self; 146 void *aux; 147{ 148 struct dc_softc *sc = (struct dc_softc *)self; 149 struct pci_attach_args *pa = (struct pci_attach_args *)aux; 150 pci_chipset_tag_t pc = pa->pa_pc; 151 u_int32_t r, cptr; 152 int unit; 153 154 unit = sc->dc_unit; 155 156 /* Find the location of the capabilities block */ 157 cptr = pci_conf_read(pc, pa->pa_tag, DC_PCI_CCAP) & 0xFF; 158 159 r = pci_conf_read(pc, pa->pa_tag, cptr) & 0xFF; 160 if (r == 0x01) { 161 162 r = pci_conf_read(pc, pa->pa_tag, cptr + 4); 163 if (r & DC_PSTATE_D3) { 164 u_int32_t iobase, membase, irq; 165 166 /* Save important PCI config data. */ 167 iobase = pci_conf_read(pc, pa->pa_tag, DC_PCI_CFBIO); 168 membase = pci_conf_read(pc, pa->pa_tag, DC_PCI_CFBMA); 169 irq = pci_conf_read(pc, pa->pa_tag, DC_PCI_CFIT); 170 171 /* Reset the power state. */ 172 printf("dc%d: chip is in D%d power mode " 173 "-- setting to D0\n", unit, r & DC_PSTATE_D3); 174 r &= 0xFFFFFFFC; 175 pci_conf_write(pc, pa->pa_tag, cptr + 4, r); 176 177 /* Restore PCI config data. */ 178 pci_conf_write(pc, pa->pa_tag, DC_PCI_CFBIO, iobase); 179 pci_conf_write(pc, pa->pa_tag, DC_PCI_CFBMA, membase); 180 pci_conf_write(pc, pa->pa_tag, DC_PCI_CFIT, irq); 181 } 182 } 183 return; 184} 185 186/* 187 * Attach the interface. Allocate softc structures, do ifmedia 188 * setup and ethernet/BPF attach. 189 */ 190void dc_pci_attach(parent, self, aux) 191 struct device *parent, *self; 192 void *aux; 193{ 194 int s; 195 const char *intrstr = NULL; 196 u_int32_t command; 197 struct dc_softc *sc = (struct dc_softc *)self; 198 struct pci_attach_args *pa = aux; 199 pci_chipset_tag_t pc = pa->pa_pc; 200 pci_intr_handle_t ih; 201 bus_addr_t iobase; 202 bus_size_t iosize; 203 u_int32_t revision; 204 int found = 0; 205 206 s = splimp(); 207 sc->sc_dmat = pa->pa_dmat; 208 sc->dc_unit = sc->sc_dev.dv_unit; 209 210 /* 211 * Handle power management nonsense. 212 */ 213 dc_pci_acpi(self, aux); 214 215 /* 216 * Map control/status registers. 217 */ 218 command = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 219 command |= PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE | 220 PCI_COMMAND_MASTER_ENABLE; 221 pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, command); 222 command = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 223 224 sc->dc_csid = pci_conf_read(pc, pa->pa_tag, PCI_SUBSYS_ID_REG); 225 226#ifdef DC_USEIOSPACE 227 if (!(command & PCI_COMMAND_IO_ENABLE)) { 228 printf(": failed to enable I/O ports\n"); 229 goto fail; 230 } 231 if (pci_io_find(pc, pa->pa_tag, DC_PCI_CFBIO, &iobase, &iosize)) { 232 printf(": can't find I/O space\n"); 233 goto fail; 234 } 235 if (bus_space_map(pa->pa_iot, iobase, iosize, 0, &sc->dc_bhandle)) { 236 printf(": can't map I/O space\n"); 237 goto fail; 238 } 239 sc->dc_btag = pa->pa_iot; 240#else 241 if (!(command & PCI_COMMAND_MEM_ENABLE)) { 242 printf(": failed to enable memory mapping\n"); 243 goto fail; 244 } 245 if (pci_mem_find(pc, pa->pa_tag, DC_PCI_CFBMA, &iobase, &iosize, NULL)){ 246 printf(": can't find mem space\n"); 247 goto fail; 248 } 249 if (bus_space_map(pa->pa_memt, iobase, iosize, 0, &sc->dc_bhandle)) { 250 printf(": can't map mem space\n"); 251 goto fail; 252 } 253 sc->dc_btag = pa->pa_memt; 254#endif 255 256 /* Allocate interrupt */ 257 if (pci_intr_map(pa, &ih)) { 258 printf(": couldn't map interrupt\n"); 259 goto fail; 260 } 261 intrstr = pci_intr_string(pc, ih); 262 sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, dc_intr, sc, 263 self->dv_xname); 264 if (sc->sc_ih == NULL) { 265 printf(": couldn't establish interrupt"); 266 if (intrstr != NULL) 267 printf(" at %s", intrstr); 268 printf("\n"); 269 goto fail; 270 } 271 printf(": %s", intrstr); 272 273 /* Need this info to decide on a chip type. */ 274 sc->dc_revision = revision = PCI_REVISION(pa->pa_class); 275 276 switch (PCI_VENDOR(pa->pa_id)) { 277 case PCI_VENDOR_DEC: 278 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_DEC_21140 || 279 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_DEC_21142) { 280 found = 1; 281 sc->dc_type = DC_TYPE_21143; 282 sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR; 283 sc->dc_flags |= DC_REDUCED_MII_POLL; 284 dc_eeprom_width(sc); 285 dc_read_srom(sc, sc->dc_romwidth); 286 } 287 break; 288 case PCI_VENDOR_DAVICOM: 289 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_DAVICOM_DM9100 || 290 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_DAVICOM_DM9102) { 291 found = 1; 292 sc->dc_type = DC_TYPE_DM9102; 293 sc->dc_flags |= DC_TX_COALESCE|DC_TX_INTR_ALWAYS; 294 sc->dc_flags |= DC_REDUCED_MII_POLL|DC_TX_STORENFWD; 295 sc->dc_pmode = DC_PMODE_MII; 296 297 /* Increase the latency timer value. */ 298 command = pci_conf_read(pc, pa->pa_tag, DC_PCI_CFLT); 299 command &= 0xFFFF00FF; 300 command |= 0x00008000; 301 pci_conf_write(pc, pa->pa_tag, DC_PCI_CFLT, command); 302 } 303 break; 304 case PCI_VENDOR_ADMTEK: 305 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ADMTEK_AL981) { 306 found = 1; 307 sc->dc_type = DC_TYPE_AL981; 308 sc->dc_flags |= DC_TX_USE_TX_INTR; 309 sc->dc_flags |= DC_TX_ADMTEK_WAR; 310 sc->dc_pmode = DC_PMODE_MII; 311 } 312 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ADMTEK_AN983) { 313 found = 1; 314 sc->dc_type = DC_TYPE_AN983; 315 sc->dc_flags |= DC_TX_USE_TX_INTR; 316 sc->dc_flags |= DC_TX_ADMTEK_WAR; 317 sc->dc_pmode = DC_PMODE_MII; 318 } 319 dc_eeprom_width(sc); 320 dc_read_srom(sc, sc->dc_romwidth); 321 break; 322 case PCI_VENDOR_MACRONIX: 323 case PCI_VENDOR_ACCTON: 324 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ACCTON_EN2242) { 325 found = 1; 326 sc->dc_type = DC_TYPE_AN983; 327 sc->dc_flags |= DC_TX_USE_TX_INTR; 328 sc->dc_flags |= DC_TX_ADMTEK_WAR; 329 sc->dc_pmode = DC_PMODE_MII; 330 331 dc_eeprom_width(sc); 332 dc_read_srom(sc, sc->dc_romwidth); 333 } 334 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_MACRONIX_MX98713) { 335 found = 1; 336 if (revision < DC_REVISION_98713A) { 337 sc->dc_type = DC_TYPE_98713; 338 } 339 if (revision >= DC_REVISION_98713A) { 340 sc->dc_type = DC_TYPE_98713A; 341 sc->dc_flags |= DC_21143_NWAY; 342 } 343 sc->dc_flags |= DC_REDUCED_MII_POLL; 344 sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR; 345 } 346 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_MACRONIX_MX98715 || 347 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ACCTON_EN1217) { 348 found = 1; 349 if (revision >= DC_REVISION_98715AEC_C && 350 revision < DC_REVISION_98725) 351 sc->dc_flags |= DC_128BIT_HASH; 352 sc->dc_type = DC_TYPE_987x5; 353 sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR; 354 sc->dc_flags |= DC_REDUCED_MII_POLL|DC_21143_NWAY; 355 } 356 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_MACRONIX_MX98727) { 357 found = 1; 358 sc->dc_type = DC_TYPE_987x5; 359 sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR; 360 sc->dc_flags |= DC_REDUCED_MII_POLL|DC_21143_NWAY; 361 } 362 break; 363 case PCI_VENDOR_COMPEX: 364 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_COMPEX_98713) { 365 found = 1; 366 if (revision < DC_REVISION_98713A) { 367 sc->dc_type = DC_TYPE_98713; 368 sc->dc_flags |= DC_REDUCED_MII_POLL; 369 } 370 if (revision >= DC_REVISION_98713A) 371 sc->dc_type = DC_TYPE_98713A; 372 sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR; 373 } 374 break; 375 case PCI_VENDOR_LITEON: 376 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_LITEON_PNICII) { 377 found = 1; 378 sc->dc_type = DC_TYPE_PNICII; 379 sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR; 380 sc->dc_flags |= DC_REDUCED_MII_POLL|DC_21143_NWAY; 381 sc->dc_flags |= DC_128BIT_HASH; 382 } 383 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_LITEON_PNIC) { 384 found = 1; 385 sc->dc_type = DC_TYPE_PNIC; 386 sc->dc_flags |= DC_TX_STORENFWD|DC_TX_INTR_ALWAYS; 387 sc->dc_flags |= DC_PNIC_RX_BUG_WAR; 388 sc->dc_pnic_rx_buf = malloc(DC_RXLEN * 5, M_DEVBUF, 389 M_NOWAIT); 390 if (sc->dc_pnic_rx_buf == NULL) 391 panic("dc_pci_attach"); 392 if (revision < DC_REVISION_82C169) 393 sc->dc_pmode = DC_PMODE_SYM; 394 } 395 break; 396 case PCI_VENDOR_ASIX: 397 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ASIX_AX88140A) { 398 found = 1; 399 sc->dc_type = DC_TYPE_ASIX; 400 sc->dc_flags |= DC_TX_USE_TX_INTR|DC_TX_INTR_FIRSTFRAG; 401 sc->dc_flags |= DC_REDUCED_MII_POLL; 402 sc->dc_pmode = DC_PMODE_MII; 403 } 404 break; 405 } 406 if (found == 0) { 407 /* This shouldn't happen if probe has done it's job... */ 408 printf(": unknown device: %x:%x\n", 409 PCI_VENDOR(pa->pa_id), PCI_PRODUCT(pa->pa_id)); 410 goto fail; 411 } 412 413 /* Save the cache line size. */ 414 if (DC_IS_DAVICOM(sc)) 415 sc->dc_cachesize = 0; 416 else 417 sc->dc_cachesize = pci_conf_read(pc, pa->pa_tag, 418 DC_PCI_CFLT) & 0xFF; 419 420 /* Reset the adapter. */ 421 dc_reset(sc); 422 423 /* Take 21143 out of snooze mode */ 424 if (DC_IS_INTEL(sc)) { 425 command = pci_conf_read(pc, pa->pa_tag, DC_PCI_CFDD); 426 command &= ~(DC_CFDD_SNOOZE_MODE|DC_CFDD_SLEEP_MODE); 427 pci_conf_write(pc, pa->pa_tag, DC_PCI_CFDD, command); 428 } 429 430 /* 431 * If we discover later (in dc_attach) that we have an 432 * MII with no PHY, we need to have the 21143 drive the LEDs. 433 * Except there are some systems like the NEC VersaPro NoteBook PC 434 * which have no LEDs, and twiddling these bits has adverse effects 435 * on them. (I.e. you suddenly can't get a link.) 436 * 437 * If mii_attach() returns an error, we leave the DC_TULIP_LEDS 438 * bit set, else we clear it. Since our dc(4) driver is split into 439 * bus-dependent and bus-independent parts, we must do set this bit 440 * here while we are able to do PCI configuration reads. 441 */ 442 if (DC_IS_INTEL(sc)) { 443 if (pci_conf_read(pc, pa->pa_tag, DC_PCI_CSID) != 0x80281033) 444 sc->dc_flags |= DC_TULIP_LEDS; 445 } 446 447 /* 448 * Try to learn something about the supported media. 449 * We know that ASIX and ADMtek and Davicom devices 450 * will *always* be using MII media, so that's a no-brainer. 451 * The tricky ones are the Macronix/PNIC II and the 452 * Intel 21143. 453 */ 454 if (DC_IS_INTEL(sc)) 455 dc_parse_21143_srom(sc); 456 else if (DC_IS_MACRONIX(sc) || DC_IS_PNICII(sc)) { 457 if (sc->dc_type == DC_TYPE_98713) 458 sc->dc_pmode = DC_PMODE_MII; 459 else 460 sc->dc_pmode = DC_PMODE_SYM; 461 } else if (!sc->dc_pmode) 462 sc->dc_pmode = DC_PMODE_MII; 463 464#ifdef __sparc64__ 465 { 466 extern void myetheraddr(u_char *); 467 myetheraddr(sc->arpcom.ac_enaddr); 468 sc->sc_hasmac = 1; 469 } 470#endif 471 472#ifdef SRM_MEDIA 473 sc->dc_srm_media = 0; 474 475 /* Remember the SRM console media setting */ 476 if (DC_IS_INTEL(sc)) { 477 command = pci_conf_read(pc, pa->pa_tag, DC_PCI_CFDD); 478 command &= ~(DC_CFDD_SNOOZE_MODE|DC_CFDD_SLEEP_MODE); 479 switch ((command >> 8) & 0xff) { 480 case 3: 481 sc->dc_srm_media = IFM_10_T; 482 break; 483 case 4: 484 sc->dc_srm_media = IFM_10_T | IFM_FDX; 485 break; 486 case 5: 487 sc->dc_srm_media = IFM_100_TX; 488 break; 489 case 6: 490 sc->dc_srm_media = IFM_100_TX | IFM_FDX; 491 break; 492 } 493 if (sc->dc_srm_media) 494 sc->dc_srm_media |= IFM_ACTIVE | IFM_ETHER; 495 } 496#endif 497 dc_eeprom_width(sc); 498 dc_attach(sc); 499 500fail: 501 splx(s); 502} 503 504struct cfattach dc_pci_ca = { 505 sizeof(struct dc_softc), dc_pci_match, dc_pci_attach 506}; 507