コード例 #1
0
static void
tlp_pci_attach(device_t parent, device_t self, void *aux)
{
	struct tulip_pci_softc *psc = device_private(self);
	struct tulip_softc *sc = &psc->sc_tulip;
	struct pci_attach_args *pa = aux;
	pci_chipset_tag_t pc = pa->pa_pc;
	pci_intr_handle_t ih;
	const char *intrstr = NULL;
	bus_space_tag_t iot, memt;
	bus_space_handle_t ioh, memh;
	int ioh_valid, memh_valid, i, j;
	const struct tulip_pci_product *tpp;
	prop_data_t ea;
	uint8_t enaddr[ETHER_ADDR_LEN];
	uint32_t val = 0;
	pcireg_t reg;
	int error;
	bus_size_t iosize = 0, memsize = 0;

	sc->sc_dev = self;
	sc->sc_devno = pa->pa_device;
	psc->sc_pc = pa->pa_pc;
	psc->sc_pcitag = pa->pa_tag;

	LIST_INIT(&psc->sc_intrslaves);

	tpp = tlp_pci_lookup(pa);
	if (tpp == NULL) {
		printf("\n");
		panic("tlp_pci_attach: impossible");
	}
	sc->sc_chip = tpp->tpp_chip;

	/*
	 * By default, Tulip registers are 8 bytes long (4 bytes
	 * followed by a 4 byte pad).
	 */
	sc->sc_regshift = 3;

	/*
	 * No power management hooks.
	 * XXX Maybe we should add some!
	 */
	sc->sc_flags |= TULIPF_ENABLED;

	/*
	 * Get revision info, and set some chip-specific variables.
	 */
	sc->sc_rev = PCI_REVISION(pa->pa_class);
	switch (sc->sc_chip) {
	case TULIP_CHIP_21140:
		if (sc->sc_rev >= 0x20)
			sc->sc_chip = TULIP_CHIP_21140A;
		break;

	case TULIP_CHIP_21142:
		if (sc->sc_rev >= 0x20)
			sc->sc_chip = TULIP_CHIP_21143;
		break;

	case TULIP_CHIP_82C168:
		if (sc->sc_rev >= 0x20)
			sc->sc_chip = TULIP_CHIP_82C169;
		break;

	case TULIP_CHIP_MX98713:
		if (sc->sc_rev >= 0x10)
			sc->sc_chip = TULIP_CHIP_MX98713A;
		break;

	case TULIP_CHIP_MX98715:
		if (sc->sc_rev >= 0x20)
			sc->sc_chip = TULIP_CHIP_MX98715A;
		if (sc->sc_rev >= 0x25)
			sc->sc_chip = TULIP_CHIP_MX98715AEC_X;
		if (sc->sc_rev >= 0x30)
			sc->sc_chip = TULIP_CHIP_MX98725;
		break;

	case TULIP_CHIP_WB89C840F:
		sc->sc_regshift = 2;
		break;

	case TULIP_CHIP_AN985:
		/*
		 * The AN983 and AN985 are very similar, and are
		 * differentiated by a "signature" register that
		 * is like, but not identical, to a PCI ID register.
		 */
		reg = pci_conf_read(pc, pa->pa_tag, 0x80);
		switch (reg) {
		case 0x09811317:
			sc->sc_chip = TULIP_CHIP_AN985;
			break;

		case 0x09851317:
			sc->sc_chip = TULIP_CHIP_AN983;
			break;

		default:
			/* Unknown -- use default. */
			break;
		}
		break;

	case TULIP_CHIP_AX88140:
		if (sc->sc_rev >= 0x10)
			sc->sc_chip = TULIP_CHIP_AX88141;
		break;

	case TULIP_CHIP_DM9102:
		if (sc->sc_rev >= 0x30)
			sc->sc_chip = TULIP_CHIP_DM9102A;
		break;

	default:
		/* Nothing. */
		break;
	}

	aprint_normal(": %s Ethernet, pass %d.%d\n",
	    tlp_chip_name(sc->sc_chip),
	    (sc->sc_rev >> 4) & 0xf, sc->sc_rev & 0xf);

	switch (sc->sc_chip) {
	case TULIP_CHIP_21040:
		if (sc->sc_rev < 0x20) {
			aprint_normal_dev(self,
			    "21040 must be at least pass 2.0\n");
			return;
		}
		break;

	case TULIP_CHIP_21140:
		if (sc->sc_rev < 0x11) {
			aprint_normal_dev(self,
			    "21140 must be at least pass 1.1\n");
			return;
		}
		break;

	default:
		/* Nothing. */
		break;
	}

	/*
	 * Check to see if the device is in power-save mode, and
	 * being it out if necessary.
	 */
	switch (sc->sc_chip) {
	case TULIP_CHIP_21140:
	case TULIP_CHIP_21140A:
	case TULIP_CHIP_21142:
	case TULIP_CHIP_21143:
	case TULIP_CHIP_MX98713A:
	case TULIP_CHIP_MX98715:
	case TULIP_CHIP_MX98715A:
	case TULIP_CHIP_MX98715AEC_X:
	case TULIP_CHIP_MX98725:
	case TULIP_CHIP_DM9102:
	case TULIP_CHIP_DM9102A:
	case TULIP_CHIP_AX88140:
	case TULIP_CHIP_AX88141:
	case TULIP_CHIP_RS7112:
		/*
		 * Clear the "sleep mode" bit in the CFDA register.
		 */
		reg = pci_conf_read(pc, pa->pa_tag, TULIP_PCI_CFDA);
		if (reg & (CFDA_SLEEP|CFDA_SNOOZE))
			pci_conf_write(pc, pa->pa_tag, TULIP_PCI_CFDA,
			    reg & ~(CFDA_SLEEP|CFDA_SNOOZE));
		break;

	default:
		/* Nothing. */
		break;
	}

	/* power up chip */
	if ((error = pci_activate(pa->pa_pc, pa->pa_tag, self,
	    NULL)) && error != EOPNOTSUPP) {
		aprint_error_dev(self, "cannot activate %d\n",
		    error);
		return;
	}

	/*
	 * Map the device.
	 */

	ioh_valid = (pci_mapreg_map(pa, TULIP_PCI_IOBA,
	    PCI_MAPREG_TYPE_IO, 0,
	    &iot, &ioh, NULL, &iosize) == 0);
	memh_valid = (pci_mapreg_map(pa, TULIP_PCI_MMBA,
	    PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0,
	    &memt, &memh, NULL, &memsize) == 0);
	if (memh_valid) {
		sc->sc_st = memt;
		sc->sc_sh = memh;
		psc->sc_mapsize = memsize;
		if (ioh_valid) {
			bus_space_unmap(iot, ioh, iosize);
			ioh_valid = 0;
		}
	} else if (ioh_valid) {
		sc->sc_st = iot;
		sc->sc_sh = ioh;
		psc->sc_mapsize = iosize;
		if (memh_valid) {
			bus_space_unmap(memt, memh, memsize);
			memh_valid = 0;
		}
	} else {
		aprint_error_dev(self, "unable to map device registers\n");
		goto fail;
	}

	sc->sc_dmat = pa->pa_dmat;

	/*
	 * Make sure bus mastering is enabled.
	 */
	pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
	    pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG) |
	    PCI_COMMAND_MASTER_ENABLE);

	/*
	 * Get the cacheline size.
	 */
	sc->sc_cacheline = PCI_CACHELINE(pci_conf_read(pc, pa->pa_tag,
	    PCI_BHLC_REG));

	/*
	 * Get PCI data moving command info.
	 */
	if (pa->pa_flags & PCI_FLAGS_MRL_OKAY)
		sc->sc_flags |= TULIPF_MRL;
	if (pa->pa_flags & PCI_FLAGS_MRM_OKAY)
		sc->sc_flags |= TULIPF_MRM;
	if (pa->pa_flags & PCI_FLAGS_MWI_OKAY)
		sc->sc_flags |= TULIPF_MWI;

	/*
	 * Read the contents of the Ethernet Address ROM/SROM.
	 */
	switch (sc->sc_chip) {
	case TULIP_CHIP_21040:
		sc->sc_srom_addrbits = 6;
		sc->sc_srom = malloc(TULIP_ROM_SIZE(6), M_DEVBUF, M_NOWAIT);
		TULIP_WRITE(sc, CSR_MIIROM, MIIROM_SROMCS);
		for (i = 0; i < TULIP_ROM_SIZE(6); i++) {
			for (j = 0; j < 10000; j++) {
				val = TULIP_READ(sc, CSR_MIIROM);
				if ((val & MIIROM_DN) == 0)
					break;
			}
			sc->sc_srom[i] = val & MIIROM_DATA;
		}
		break;

	case TULIP_CHIP_82C168:
	case TULIP_CHIP_82C169:
	    {
		sc->sc_srom_addrbits = 2;
		sc->sc_srom = malloc(TULIP_ROM_SIZE(2), M_DEVBUF, M_NOWAIT);

		/*
		 * The Lite-On PNIC stores the Ethernet address in
		 * the first 3 words of the EEPROM.  EEPROM access
		 * is not like the other Tulip chips.
		 */
		for (i = 0; i < 6; i += 2) {
			TULIP_WRITE(sc, CSR_PNIC_SROMCTL,
			    PNIC_SROMCTL_READ | (i >> 1));
			for (j = 0; j < 500; j++) {
				delay(2);
				val = TULIP_READ(sc, CSR_MIIROM);
				if ((val & PNIC_MIIROM_BUSY) == 0)
					break;
			}
			if (val & PNIC_MIIROM_BUSY) {
				aprint_error_dev(self, "EEPROM timed out\n");
				goto fail;
			}
			val &= PNIC_MIIROM_DATA;
			sc->sc_srom[i] = val >> 8;
			sc->sc_srom[i + 1] = val & 0xff;
		}
		break;
	    }

	default:
		/*
		 * XXX This isn't quite the right way to do this; we should
		 * XXX be attempting to fetch the mac-addr property in the
		 * XXX bus-agnostic part of the driver independently.  But
		 * XXX that requires a larger change in the SROM handling
		 * XXX logic, and for now we can at least remove a machine-
		 * XXX dependent wart from the PCI front-end.
		 */
		ea = prop_dictionary_get(device_properties(self),
					 "mac-address");
		if (ea != NULL) {
			extern int tlp_srom_debug;
			KASSERT(prop_object_type(ea) == PROP_TYPE_DATA);
			KASSERT(prop_data_size(ea) == ETHER_ADDR_LEN);

			memcpy(enaddr, prop_data_data_nocopy(ea),
			       ETHER_ADDR_LEN);

			sc->sc_srom_addrbits = 6;
			sc->sc_srom = malloc(TULIP_ROM_SIZE(6), M_DEVBUF,
			    M_NOWAIT|M_ZERO);
			memcpy(sc->sc_srom, enaddr, sizeof(enaddr));
			if (tlp_srom_debug) {
				aprint_normal("SROM CONTENTS:");
				for (i = 0; i < TULIP_ROM_SIZE(6); i++) {
					if ((i % 8) == 0)
						aprint_normal("\n\t");
					aprint_normal("0x%02x ", sc->sc_srom[i]);
				}
				aprint_normal("\n");
			}
			break;
		}

		/* Check for a slaved ROM on a multi-port board. */
		tlp_pci_check_slaved(psc, TULIP_PCI_SHAREDROM,
		    TULIP_PCI_SLAVEROM);
		if (psc->sc_flags & TULIP_PCI_SLAVEROM) {
			sc->sc_srom_addrbits =
			    psc->sc_master->sc_tulip.sc_srom_addrbits;
			sc->sc_srom = psc->sc_master->sc_tulip.sc_srom;
			enaddr[5] +=
			    sc->sc_devno - psc->sc_master->sc_tulip.sc_devno;
		}
		else if (tlp_read_srom(sc) == 0)
			goto cant_cope;
		break;
	}

	/*
	 * Deal with chip/board quirks.  This includes setting up
	 * the mediasw, and extracting the Ethernet address from
	 * the rombuf.
	 */
	switch (sc->sc_chip) {
	case TULIP_CHIP_21040:
		/*
		 * Parse the Ethernet Address ROM.
		 */
		if (tlp_parse_old_srom(sc, enaddr) == 0)
			goto cant_cope;


		/*
		 * All 21040 boards start out with the same
		 * media switch.
		 */
		sc->sc_mediasw = &tlp_21040_mediasw;

		/*
		 * Deal with any quirks this board might have.
		 */
		tlp_pci_get_quirks(psc, enaddr, tlp_pci_21040_quirks);
		break;

	case TULIP_CHIP_21041:
		/* Check for new format SROM. */
		if (tlp_isv_srom_enaddr(sc, enaddr) == 0) {
			/*
			 * Not an ISV SROM; try the old DEC Ethernet Address
			 * ROM format.
			 */
			if (tlp_parse_old_srom(sc, enaddr) == 0)
				goto cant_cope;
		}

		/*
		 * All 21041 boards use the same media switch; they all
		 * work basically the same!  Yippee!
		 */
		sc->sc_mediasw = &tlp_21041_mediasw;

		/*
		 * Deal with any quirks this board might have.
		 */
		tlp_pci_get_quirks(psc, enaddr, tlp_pci_21041_quirks);
		break;

	case TULIP_CHIP_21140:
	case TULIP_CHIP_21140A:
		/* Check for new format SROM. */
		if (tlp_isv_srom_enaddr(sc, enaddr) == 0) {
			/*
			 * Not an ISV SROM; try the old DEC Ethernet Address
			 * ROM format.
			 */
			if (tlp_parse_old_srom(sc, enaddr) == 0)
				goto cant_cope;
		} else {
			/*
			 * We start out with the 2114x ISV media switch.
			 * When we search for quirks, we may change to
			 * a different switch.
			 */
			sc->sc_mediasw = &tlp_2114x_isv_mediasw;
		}

		/*
		 * Deal with any quirks this board might have.
		 */
		tlp_pci_get_quirks(psc, enaddr, tlp_pci_21140_quirks);

		/*
		 * Bail out now if we can't deal with this board.
		 */
		if (sc->sc_mediasw == NULL)
			goto cant_cope;
		break;

	case TULIP_CHIP_21142:
	case TULIP_CHIP_21143:
		/* Check for new format SROM. */
		if (tlp_isv_srom_enaddr(sc, enaddr) == 0) {
			/*
			 * Not an ISV SROM; try the old DEC Ethernet Address
			 * ROM format.
			 */
			if (tlp_parse_old_srom(sc, enaddr) == 0) {
				/*
				 * One last try: just copy the address
				 * from offset 20 and try to look
				 * up quirks.
				 */
				memcpy(enaddr, &sc->sc_srom[20],
				    ETHER_ADDR_LEN);
			}
		} else {
			/*
			 * We start out with the 2114x ISV media switch.
			 * When we search for quirks, we may change to
			 * a different switch.
			 */
			sc->sc_mediasw = &tlp_2114x_isv_mediasw;
		}

		/*
		 * Deal with any quirks this board might have.
		 */
		tlp_pci_get_quirks(psc, enaddr, tlp_pci_21142_quirks);

		/*
		 * Bail out now if we can't deal with this board.
		 */
		if (sc->sc_mediasw == NULL)
			goto cant_cope;
		break;

	case TULIP_CHIP_82C168:
	case TULIP_CHIP_82C169:
		/*
		 * Lite-On PNIC's Ethernet address is the first 6
		 * bytes of its EEPROM.
		 */
		memcpy(enaddr, sc->sc_srom, ETHER_ADDR_LEN);

		/*
		 * Lite-On PNICs always use the same mediasw; we
		 * select MII vs. internal NWAY automatically.
		 */
		sc->sc_mediasw = &tlp_pnic_mediasw;
		break;

	case TULIP_CHIP_MX98713:
		/*
		 * The Macronix MX98713 has an MII and GPIO, but no
		 * internal Nway block.  This chip is basically a
		 * perfect 21140A clone, with the exception of the
		 * a magic register frobbing in order to make the
		 * interface function.
		 */
		if (tlp_isv_srom_enaddr(sc, enaddr)) {
			sc->sc_mediasw = &tlp_2114x_isv_mediasw;
			break;
		}
		/* FALLTHROUGH */

	case TULIP_CHIP_82C115:
		/*
		 * Yippee!  The Lite-On 82C115 is a clone of
		 * the MX98725 (the data sheet even says `MXIC'
		 * on it)!  Imagine that, a clone of a clone.
		 *
		 * The differences are really minimal:
		 *
		 *	- Wake-On-LAN support
		 *	- 128-bit multicast hash table, rather than
		 *	  the standard 512-bit hash table
		 */
		/* FALLTHROUGH */

	case TULIP_CHIP_MX98713A:
	case TULIP_CHIP_MX98715A:
	case TULIP_CHIP_MX98715AEC_X:
	case TULIP_CHIP_MX98725:
		/*
		 * The MX98713A has an MII as well as an internal Nway block,
		 * but no GPIO.  The MX98715 and MX98725 have an internal
		 * Nway block only.
		 *
		 * The internal Nway block, unlike the Lite-On PNIC's, does
		 * just that - performs Nway.  Once autonegotiation completes,
		 * we must program the GPR media information into the chip.
		 *
		 * The byte offset of the Ethernet address is stored at
		 * offset 0x70.
		 */
		memcpy(enaddr, &sc->sc_srom[sc->sc_srom[0x70]], ETHER_ADDR_LEN);
		sc->sc_mediasw = &tlp_pmac_mediasw;
		break;

	case TULIP_CHIP_WB89C840F:
		/*
		 * Winbond 89C840F's Ethernet address is the first
		 * 6 bytes of its EEPROM.
		 */
		memcpy(enaddr, sc->sc_srom, ETHER_ADDR_LEN);

		/*
		 * Winbond 89C840F has an MII attached to the SIO.
		 */
		sc->sc_mediasw = &tlp_sio_mii_mediasw;
		break;

	case TULIP_CHIP_AL981:
		/*
		 * The ADMtek AL981's Ethernet address is located
		 * at offset 8 of its EEPROM.
		 */
		memcpy(enaddr, &sc->sc_srom[8], ETHER_ADDR_LEN);

		/*
		 * ADMtek AL981 has a built-in PHY accessed through
		 * special registers.
		 */
		sc->sc_mediasw = &tlp_al981_mediasw;
		break;

	case TULIP_CHIP_AN983:
	case TULIP_CHIP_AN985:
		/*
		 * The ADMtek AN985's Ethernet address is located
		 * at offset 8 of its EEPROM.
		 */
		memcpy(enaddr, &sc->sc_srom[8], ETHER_ADDR_LEN);

		/*
		 * The ADMtek AN985 can be configured in Single-Chip
		 * mode or MAC-only mode.  Single-Chip uses the built-in
		 * PHY, MAC-only has an external PHY (usually HomePNA).
		 * The selection is based on an EEPROM setting, and both
		 * PHYs are accessed via MII attached to SIO.
		 *
		 * The AN985 "ghosts" the internal PHY onto all
		 * MII addresses, so we have to use a media init
		 * routine that limits the search.
		 * XXX How does this work with MAC-only mode?
		 */
		sc->sc_mediasw = &tlp_an985_mediasw;
		break;

	case TULIP_CHIP_DM9102:
	case TULIP_CHIP_DM9102A:
		/*
		 * Some boards with the Davicom chip have an ISV
		 * SROM (mostly DM9102A boards -- trying to describe
		 * the HomePNA PHY, probably) although the data in
		 * them is generally wrong.  Check for ISV format
		 * and grab the Ethernet address that way, and if
		 * that fails, fall back on grabbing it from an
		 * observed offset of 20 (which is where it would
		 * be in an ISV SROM anyhow, tho ISV can cope with
		 * multi-port boards).
		 */
		if (!tlp_isv_srom_enaddr(sc, enaddr)) {

			prop_data_t eaddrprop;

			eaddrprop = prop_dictionary_get(
				device_properties(self), "mac-address");

			if (eaddrprop != NULL
			    && prop_data_size(eaddrprop) == ETHER_ADDR_LEN)
				memcpy(enaddr,
				    prop_data_data_nocopy(eaddrprop),
				    ETHER_ADDR_LEN);
			else
				memcpy(enaddr, &sc->sc_srom[20],
				    ETHER_ADDR_LEN);
		}

		/*
		 * Davicom chips all have an internal MII interface
		 * and a built-in PHY.  DM9102A also has a an external
		 * MII interface, usually with a HomePNA PHY attached
		 * to it.
		 */
		sc->sc_mediasw = &tlp_dm9102_mediasw;
		break;

	case TULIP_CHIP_AX88140:
	case TULIP_CHIP_AX88141:
		/*
		 * ASIX AX88140/AX88141 Ethernet Address is located at offset
		 * 20 of the SROM.
		 */
		memcpy(enaddr, &sc->sc_srom[20], ETHER_ADDR_LEN);

		/*
		 * ASIX AX88140A/AX88141 chip can have a built-in PHY or
		 * an external MII interface.
		 */
		sc->sc_mediasw = &tlp_asix_mediasw;
		break;

	case TULIP_CHIP_RS7112:
		/*
		 * RS7112 Ethernet Address is located of offset 0x19a
		 * of the SROM
		 */
		memcpy(enaddr, &sc->sc_srom[0x19a], ETHER_ADDR_LEN);

		/* RS7112 chip has a PHY at MII address 1 */
		sc->sc_mediasw = &tlp_rs7112_mediasw;
		break;

	default:
 cant_cope:
		aprint_error_dev(self, "sorry, unable to handle your board\n");
		goto fail;
	}

	/*
	 * Handle shared interrupts.
	 */
	if (psc->sc_flags & TULIP_PCI_SHAREDINTR) {
		if (psc->sc_master)
			psc->sc_flags |= TULIP_PCI_SLAVEINTR;
		else {
			tlp_pci_check_slaved(psc, TULIP_PCI_SHAREDINTR,
			    TULIP_PCI_SLAVEINTR);
			if (psc->sc_master == NULL)
				psc->sc_master = psc;
		}
		LIST_INSERT_HEAD(&psc->sc_master->sc_intrslaves,
		    psc, sc_intrq);
	}

	if (psc->sc_flags & TULIP_PCI_SLAVEINTR) {
		aprint_normal_dev(self, "sharing interrupt with %s\n",
		    device_xname(psc->sc_master->sc_tulip.sc_dev));
	} else {
		/*
		 * Map and establish our interrupt.
		 */
		if (pci_intr_map(pa, &ih)) {
			aprint_error_dev(self, "unable to map interrupt\n");
			goto fail;
		}
		intrstr = pci_intr_string(pc, ih);
		psc->sc_ih = pci_intr_establish(pc, ih, IPL_NET,
		    (psc->sc_flags & TULIP_PCI_SHAREDINTR) ?
		    tlp_pci_shared_intr : tlp_intr, sc);
		if (psc->sc_ih == NULL) {
			aprint_error_dev(self, "unable to establish interrupt");
			if (intrstr != NULL)
				aprint_error(" at %s", intrstr);
			aprint_error("\n");
			goto fail;
		}
		aprint_normal_dev(self, "interrupting at %s\n",
		    intrstr);
	}

	/*
	 * Finish off the attach.
	 */
	error = tlp_attach(sc, enaddr);
	if (error)
		goto fail;
	return;

fail:
	if (psc->sc_ih != NULL) {
		pci_intr_disestablish(psc->sc_pc, psc->sc_ih);
		psc->sc_ih = NULL;
	}

	if (ioh_valid)
		bus_space_unmap(iot, ioh, iosize);
	if (memh_valid)
		bus_space_unmap(memt, memh, memsize);
	psc->sc_mapsize = 0;
	return;
}
コード例 #2
0
ファイル: if_tlp_eisa.c プロジェクト: yazshel/netbsd-kernel
static void
tlp_eisa_attach(device_t parent, device_t self, void *aux)
{
    static const u_int8_t testpat[] =
    { 0xff, 0, 0x55, 0xaa, 0xff, 0, 0x55, 0xaa };
    struct tulip_eisa_softc *esc = device_private(self);
    struct tulip_softc *sc = &esc->sc_tulip;
    struct eisa_attach_args *ea = aux;
    eisa_chipset_tag_t ec = ea->ea_ec;
    eisa_intr_handle_t ih;
    bus_space_tag_t iot = ea->ea_iot;
    bus_space_handle_t ioh;
    const char *intrstr;
    const struct tulip_eisa_product *tep;
    u_int8_t enaddr[ETHER_ADDR_LEN], tmpbuf[sizeof(testpat)];
    u_int32_t val;
    int irq, i, cnt;
    char intrbuf[EISA_INTRSTR_LEN];

    /*
     * Map the device.
     */
    if (bus_space_map(iot, EISA_SLOT_ADDR(ea->ea_slot),
                      EISA_SLOT_SIZE, 0, &ioh)) {
        printf(": unable to map I/O space\n");
        return;
    }

    sc->sc_dev = self;
    sc->sc_st = iot;
    sc->sc_sh = ioh;

    tep = tlp_eisa_lookup(ea);
    if (tep == NULL) {
        printf("\n");
        panic("tlp_eisa_attach: impossible");
    }
    sc->sc_chip = tep->tep_chip;

    /*
     * DE425's registers are 16 bytes long; the PCI configuration
     * space registers are interleaved in the I/O space.
     */
    sc->sc_regshift = 4;

    /*
     * No power management hooks.
     */
    sc->sc_flags |= TULIPF_ENABLED;

    /*
     * CBIO must map the EISA slot, and I/O access and Bus Mastering
     * must be enabled.
     */
    bus_space_write_4(iot, ioh, DE425_CBIO, EISA_SLOT_ADDR(ea->ea_slot));
    bus_space_write_4(iot, ioh, DE425_CFCS,
                      bus_space_read_4(iot, ioh, DE425_CFCS) |
                      PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MASTER_ENABLE);

    /*
     * Get revision info.
     */
    sc->sc_rev = bus_space_read_4(iot, ioh, DE425_CFRV) & 0xff;

    printf(": %s Ethernet, pass %d.%d\n",
           tep->tep_name, (sc->sc_rev >> 4) & 0xf, sc->sc_rev & 0xf);

    sc->sc_dmat = ea->ea_dmat;

    /*
     * EISA doesn't have a cache line register.
     */
    sc->sc_cacheline = 0;

    /*
     * Find the beginning of the Ethernet Address ROM.
     */
    for (i = 0, cnt = 0; i < sizeof(testpat) && cnt < 32; cnt++) {
        tmpbuf[i] = bus_space_read_1(iot, ioh, DE425_ENETROM);
        if (tmpbuf[i] == testpat[i])
            i++;
        else
            i = 0;
    }

    /*
     * ...and now read the contents of the Ethernet Address ROM.
     */
    sc->sc_srom = malloc(32, M_DEVBUF, M_WAITOK|M_ZERO);
    for (i = 0; i < 32; i++)
        sc->sc_srom[i] = bus_space_read_1(iot, ioh, DE425_ENETROM);

    /*
     * None of the DE425 boards have the new-style SROMs.
     */
    if (tlp_parse_old_srom(sc, enaddr) == 0) {
        aprint_error_dev(self, "unable to decode old-style SROM\n");
        return;
    }

    /*
     * All DE425 boards use the 21040 media switch.
     */
    sc->sc_mediasw = &tlp_21040_mediasw;

    /*
     * Figure out which IRQ we want to use, and determine if it's
     * edge- or level-triggered.
     */
    val = bus_space_read_4(iot, ioh, DE425_CFG0);
    irq = tlp_eisa_irqs[(val >> 1) & 0x03];

    /*
     * Map and establish our interrupt.
     */
    if (eisa_intr_map(ec, irq, &ih)) {
        aprint_error_dev(self, "unable to map interrupt (%u)\n",
                         irq);
        return;
    }
    intrstr = eisa_intr_string(ec, ih, intrbuf, sizeof(intrbuf));
    esc->sc_ih = eisa_intr_establish(ec, ih,
                                     (val & 0x01) ? IST_EDGE : IST_LEVEL, IPL_NET, tlp_intr, sc);
    if (esc->sc_ih == NULL) {
        aprint_error_dev(self, "unable to establish interrupt");
        if (intrstr != NULL)
            aprint_error(" at %s", intrstr);
        aprint_error("\n");
        return;
    }
    if (intrstr != NULL)
        aprint_normal_dev(self, "interrupting at %s\n", intrstr);

    /*
     * Finish off the attach.
     */
    tlp_attach(sc, enaddr);
}