예제 #1
0
static int
ed_pci_attach(device_t dev)
{
        struct ed_softc *sc = device_get_softc(dev);
        int flags = 0;
        int error;

        error = ed_probe_Novell_generic(dev, PCIR_MAPS, flags);
        if (error)
                return (error);

        error = ed_alloc_irq(dev, 0, RF_SHAREABLE);
        if (error) {
                ed_release_resources(dev);
                return (error);
        }

        error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET,
                               edintr, sc, &sc->irq_handle);
        if (error) {
                ed_release_resources(dev);
                return (error);
        }

	error = ed_attach(sc, device_get_unit(dev), flags);

	return (error);
}
예제 #2
0
int
ed_probe_Novell(device_t dev, int port_rid, int flags)
{
	struct ed_softc *sc = device_get_softc(dev);
	int	error;

	error = ed_alloc_port(dev, port_rid, ED_NOVELL_IO_PORTS);
	if (error)
		return (error);

	sc->asic_offset = ED_NOVELL_ASIC_OFFSET;
	sc->nic_offset  = ED_NOVELL_NIC_OFFSET;

	return ed_probe_Novell_generic(dev, flags);
}
예제 #3
0
/*
 * Special setup for TC5299J
 */
static int
ed_pccard_tc5299j(device_t dev, const struct ed_product *pp)
{
	int	error, i, id;
	char *ts;
	struct	ed_softc *sc = device_get_softc(dev);

	if (!(pp->flags & NE2000DVF_TC5299J))
		return (ENXIO);

	if (bootverbose)
		device_printf(dev, "Checking Tc5299j\n");

	error = ed_probe_Novell_generic(dev, device_get_flags(dev));
	if (bootverbose)
		device_printf(dev, "Novell generic probe failed: %d\n", error);
	if (error != 0)
		return (error);

	/*
	 * Check to see if we have a MII PHY ID at any address.  All TC5299J
	 * devices have MII and a PHY, so we use this to weed out chips that
	 * would otherwise make it through the tests we have after this point.
	 */
	sc->mii_bitbang_ops = &ed_pccard_tc5299j_mii_bitbang_ops;
	for (i = 0; i < 32; i++) {
		id = ed_miibus_readreg(dev, i, MII_PHYIDR1);
		if (id != 0 && id != 0xffff)
			break;
	}
	if (i == 32)
		return (ENXIO);
	ts = "TC5299J";
	if (ed_pccard_rom_mac(dev, sc->enaddr) == 0)
		return (ENXIO);
	sc->vendor = ED_VENDOR_NOVELL;
	sc->type = ED_TYPE_NE2000;
	sc->chip_type = ED_CHIP_TYPE_TC5299J;
	sc->type_str = ts;
	return (0);
}
예제 #4
0
int
ed_probe_RTL80x9(device_t dev, int port_rid, int flags)
{
	struct ed_softc *sc = device_get_softc(dev);
	char *ts;
	int error;

	if ((error = ed_alloc_port(dev, port_rid, ED_NOVELL_IO_PORTS)))
		return (error);
	
	sc->asic_offset = ED_NOVELL_ASIC_OFFSET;
	sc->nic_offset  = ED_NOVELL_NIC_OFFSET;

	if (ed_nic_inb(sc, ED_P0_CR) & (ED_CR_PS0 | ED_CR_PS1))
		ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP);

	if (ed_nic_inb(sc, ED_RTL80X9_80X9ID0) != ED_RTL80X9_ID0)
		return (ENXIO);

	switch (ed_nic_inb(sc, ED_RTL80X9_80X9ID1)) {
	case ED_RTL8019_ID1:
		sc->chip_type = ED_CHIP_TYPE_RTL8019;
		ts = "RTL8019";
		break;
	case ED_RTL8029_ID1:
		sc->chip_type = ED_CHIP_TYPE_RTL8029;
		ts = "RTL8029";
		break;
	default:
		return (ENXIO);
	}

	if ((error = ed_probe_Novell_generic(dev, flags)))
		return (error);

	sc->type_str = ts;
	sc->sc_media_ioctl = &ed_rtl80x9_media_ioctl;
	ifmedia_init(&sc->ifmedia, 0, ed_rtl_set_media, ed_rtl_get_media);

	ifmedia_add(&sc->ifmedia, IFM_ETHER | IFM_10_T | IFM_FDX, 0, 0);
	ifmedia_add(&sc->ifmedia, IFM_ETHER | IFM_10_T, 0, 0);
	ifmedia_add(&sc->ifmedia, IFM_ETHER | IFM_10_2, 0, 0);
	ifmedia_add(&sc->ifmedia, IFM_ETHER | IFM_10_5, 0, 0);
	ifmedia_add(&sc->ifmedia, IFM_ETHER | IFM_AUTO, 0, 0);

	ed_nic_barrier(sc, ED_P0_CR, 1,
	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
	ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_3 | ED_CR_STP);
	ed_nic_barrier(sc, ED_P0_CR, 1,
	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);

	switch (ed_nic_inb(sc, ED_RTL80X9_CONFIG2) & ED_RTL80X9_CF2_MEDIA) {
	case ED_RTL80X9_CF2_AUTO:
		ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_AUTO);
		break;
	case ED_RTL80X9_CF2_10_5:
		ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_10_5);
		break;
	case ED_RTL80X9_CF2_10_2:
		ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_10_2);
		break;
	case ED_RTL80X9_CF2_10_T:
		ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_10_T |
		    ((ed_nic_inb(sc, ED_RTL80X9_CONFIG3)
		    & ED_RTL80X9_CF3_FUDUP) ? IFM_FDX : 0));
		break;
	}
	return (0);
}
예제 #5
0
/*
 * Probe the Ethernet MAC addrees for PCMCIA Linksys EtherFast 10/100 
 * and compatible cards (DL10019C Ethernet controller).
 */
static int
ed_pccard_dl100xx(device_t dev, const struct ed_product *pp)
{
	struct ed_softc *sc = device_get_softc(dev);
	u_char sum;
	uint8_t id;
	u_int   memsize;
	int i, error;

	if (!(pp->flags & NE2000DVF_DL100XX))
		return (ENXIO);
	if (bootverbose)
		device_printf(dev, "Trying DL100xx\n");
	error = ed_probe_Novell_generic(dev, device_get_flags(dev));
	if (bootverbose && error)
		device_printf(dev, "Novell generic probe failed: %d\n", error);
	if (error != 0)
		return (error);

	/*
	 * Linksys registers(offset from ASIC base)
	 *
	 * 0x04-0x09 : Physical Address Register 0-5 (PAR0-PAR5)
	 * 0x0A      : Card ID Register (CIR)
	 * 0x0B      : Check Sum Register (SR)
	 */
	for (sum = 0, i = 0x04; i < 0x0c; i++)
		sum += ed_asic_inb(sc, i);
	if (sum != 0xff) {
		if (bootverbose)
			device_printf(dev, "Bad checksum %#x\n", sum);
		return (ENXIO);		/* invalid DL10019C */
	}
	if (bootverbose)
		device_printf(dev, "CIR is %d\n", ed_asic_inb(sc, 0xa));
	for (i = 0; i < ETHER_ADDR_LEN; i++)
		sc->enaddr[i] = ed_asic_inb(sc, 0x04 + i);
	ed_nic_outb(sc, ED_P0_DCR, ED_DCR_WTS | ED_DCR_FT1 | ED_DCR_LS);
	id = ed_asic_inb(sc, 0xf);
	sc->isa16bit = 1;
	/*
	 * Hard code values based on the datasheet.  We're NE-2000 compatible
	 * NIC with 24kb of packet memory starting at 24k offset.  These
	 * cards also work with 16k at 16k, but don't work with 24k at 16k
	 * or 32k at 16k.
	 */
	sc->type = ED_TYPE_NE2000;
	sc->mem_start = 24 * 1024;
	memsize = sc->mem_size = 24 * 1024;
	sc->mem_end = sc->mem_start + memsize;
	sc->tx_page_start = memsize / ED_PAGE_SIZE;
	sc->txb_cnt = 3;
	sc->rec_page_start = sc->tx_page_start + sc->txb_cnt * ED_TXBUF_SIZE;
	sc->rec_page_stop = sc->tx_page_start + memsize / ED_PAGE_SIZE;

	sc->mem_ring = sc->mem_start + sc->txb_cnt * ED_PAGE_SIZE * ED_TXBUF_SIZE;

	ed_nic_outb(sc, ED_P0_PSTART, sc->mem_start / ED_PAGE_SIZE);
	ed_nic_outb(sc, ED_P0_PSTOP, sc->mem_end / ED_PAGE_SIZE);
	sc->vendor = ED_VENDOR_NOVELL;
	sc->chip_type = (id & 0x90) == 0x90 ?
	    ED_CHIP_TYPE_DL10022 : ED_CHIP_TYPE_DL10019;
	sc->type_str = ((id & 0x90) == 0x90) ? "DL10022" : "DL10019";
	sc->mii_bitbang_ops = &ed_pccard_dl100xx_mii_bitbang_ops;
	return (0);
}
예제 #6
0
static int
ed_pccard_attach(device_t dev)
{
	u_char sum;
	u_char enaddr[ETHER_ADDR_LEN];
	const struct ed_product *pp;
	int	error, i, flags, port_rid, modem_rid;
	struct ed_softc *sc = device_get_softc(dev);
	u_long size;
	static uint16_t *intr_vals[] = {NULL, NULL};

	sc->dev = dev;
	if ((pp = (const struct ed_product *) pccard_product_lookup(dev, 
	    (const struct pccard_product *) ed_pccard_products,
		 sizeof(ed_pccard_products[0]), NULL)) == NULL) {
		printf("Can't find\n");
		return (ENXIO);
	}
	modem_rid = port_rid = -1;
	if (pp->flags & NE2000DVF_MODEM) {
		for (i = 0; i < 4; i++) {
			size = bus_get_resource_count(dev, SYS_RES_IOPORT, i);
			if (size == ED_NOVELL_IO_PORTS)
				port_rid = i;
			else if (size == 8)
				modem_rid = i;
		}
		if (port_rid == -1) {
			device_printf(dev, "Cannot locate my ports!\n");
			return (ENXIO);
		}
	} else {
		port_rid = 0;
	}
	/* Allocate the port resource during setup. */
	error = ed_alloc_port(dev, port_rid, ED_NOVELL_IO_PORTS);
	if (error) {
		printf("alloc_port failed\n");
		return (error);
	}
	if (rman_get_size(sc->port_res) == ED_NOVELL_IO_PORTS / 2) {
		port_rid++;
		sc->port_res2 = bus_alloc_resource(dev, SYS_RES_IOPORT,
		    &port_rid, 0ul, ~0ul, 1, RF_ACTIVE);
		if (sc->port_res2 == NULL ||
		    rman_get_size(sc->port_res2) != ED_NOVELL_IO_PORTS / 2) {
			error = ENXIO;
			goto bad;
		}
	}
	error = ed_alloc_irq(dev, 0, 0);
	if (error)
		goto bad;

	/*
	 * Determine which chipset we are.  Almost all the PC Card chipsets
	 * have the Novel ASIC and NIC offsets.  There's 2 known cards that
	 * follow the WD80x3 conventions, which are handled as a special case.
	 */
	sc->asic_offset = ED_NOVELL_ASIC_OFFSET;
	sc->nic_offset  = ED_NOVELL_NIC_OFFSET;
	error = ENXIO;
	flags = device_get_flags(dev);
	if (error != 0)
		error = ed_pccard_dl100xx(dev, pp);
	if (error != 0)
		error = ed_pccard_ax88x90(dev, pp);
	if (error != 0)
		error = ed_pccard_tc5299j(dev, pp);
	if (error != 0) {
		error = ed_probe_Novell_generic(dev, flags);
		printf("Novell generic probe failed: %d\n", error);
	}
	if (error != 0 && (pp->flags & NE2000DVF_TOSHIBA)) {
		flags |= ED_FLAGS_TOSH_ETHER;
		flags |= ED_FLAGS_PCCARD;
		sc->asic_offset = ED_WD_ASIC_OFFSET;
		sc->nic_offset  = ED_WD_NIC_OFFSET;
		error = ed_probe_WD80x3_generic(dev, flags, intr_vals);
	}
	if (error)
		goto bad;

	/*
	 * There are several ways to get the MAC address for the card.
	 * Some of the above probe routines can fill in the enaddr.  If
	 * not, we run through a number of 'well known' locations:
	 *	(1) From the PC Card FUNCE
	 *	(2) From offset 0 in the shared memory
	 *	(3) From a hinted offset in attribute memory
	 *	(4) From 0xff0 in attribute memory
	 * If we can't get a non-zero MAC address from this list, we fail.
	 */
	for (i = 0, sum = 0; i < ETHER_ADDR_LEN; i++)
		sum |= sc->enaddr[i];
	if (sum == 0) {
		pccard_get_ether(dev, enaddr);
		if (bootverbose)
			device_printf(dev, "CIS MAC %6D\n", enaddr, ":");
		for (i = 0, sum = 0; i < ETHER_ADDR_LEN; i++)
			sum |= enaddr[i];
		if (sum == 0 && ed_pccard_rom_mac(dev, enaddr)) {
			if (bootverbose)
				device_printf(dev, "ROM mac %6D\n", enaddr,
				    ":");
			sum++;
		}
		if (sum == 0 && pp->flags & NE2000DVF_ENADDR) {
			for (i = 0; i < ETHER_ADDR_LEN; i++) {
				pccard_attr_read_1(dev, pp->enoff + i * 2,
				    enaddr + i);
				sum |= enaddr[i];
			}
			if (bootverbose)
				device_printf(dev, "Hint %x MAC %6D\n",
				    pp->enoff, enaddr, ":");
		}
		if (sum == 0) {
			for (i = 0; i < ETHER_ADDR_LEN; i++) {
				pccard_attr_read_1(dev, ED_DEFAULT_MAC_OFFSET +
				    i * 2, enaddr + i);
				sum |= enaddr[i];
			}
			if (bootverbose)
				device_printf(dev, "Fallback MAC %6D\n",
				    enaddr, ":");
		}
		if (sum == 0) {
			device_printf(dev, "Cannot extract MAC address.\n");
			ed_release_resources(dev);
			return (ENXIO);
		}
		bcopy(enaddr, sc->enaddr, ETHER_ADDR_LEN);
	}

	error = ed_attach(dev);
	if (error)
		goto bad;
 	if (sc->chip_type == ED_CHIP_TYPE_DL10019 ||
	    sc->chip_type == ED_CHIP_TYPE_DL10022) {
		/* Try to attach an MII bus, but ignore errors. */
		ed_pccard_dl100xx_mii_reset(sc);
		(void)mii_attach(dev, &sc->miibus, sc->ifp, ed_ifmedia_upd,
		    ed_ifmedia_sts, BMSR_DEFCAPMASK, MII_PHY_ANY,
		    MII_OFFSET_ANY, MIIF_FORCEANEG);
	} else if (sc->chip_type == ED_CHIP_TYPE_AX88190 ||
	    sc->chip_type == ED_CHIP_TYPE_AX88790 ||
	    sc->chip_type == ED_CHIP_TYPE_TC5299J) {
		error = mii_attach(dev, &sc->miibus, sc->ifp, ed_ifmedia_upd,
		    ed_ifmedia_sts, BMSR_DEFCAPMASK, MII_PHY_ANY,
		    MII_OFFSET_ANY, MIIF_FORCEANEG);
		if (error != 0) {
			device_printf(dev, "attaching PHYs failed\n");
			goto bad;
		}
	}
	if (sc->miibus != NULL) {
		sc->sc_tick = ed_pccard_tick;
		sc->sc_mediachg = ed_pccard_mediachg;
		sc->sc_media_ioctl = ed_pccard_media_ioctl;
		ed_pccard_kick_phy(sc);
	} else {
		ed_gen_ifmedia_init(sc);
	}
	if (modem_rid != -1)
		ed_pccard_add_modem(dev);

	error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET | INTR_MPSAFE,
	    NULL, edintr, sc, &sc->irq_handle);
	if (error) {
		device_printf(dev, "setup intr failed %d \n", error);
		goto bad;
	}	      

	return (0);
bad:
	ed_detach(dev);
	return (error);
}