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