Esempio n. 1
0
void
ed_enable_16bit_access(struct ed_softc *sc)
{
	if (sc->isa16bit && sc->vendor == ED_VENDOR_WD_SMC) {
		ed_asic_outb(sc, ED_WD_LAAR,
		     sc->wd_laar_proto | ED_WD_LAAR_M16EN);
		if (sc->chip_type == ED_CHIP_TYPE_WD790)
			ed_asic_outb(sc, ED_WD_MSR, ED_WD_MSR_MENB);
	}
}
Esempio n. 2
0
void
ed_disable_16bit_access(struct ed_softc *sc)
{
	/*
	 * Disable 16 bit access to shared memory
	 */
	if (sc->isa16bit && sc->vendor == ED_VENDOR_WD_SMC) {
		if (sc->chip_type == ED_CHIP_TYPE_WD790)
			ed_asic_outb(sc, ED_WD_MSR, 0x00);
		ed_asic_outb(sc, ED_WD_LAAR,
		    sc->wd_laar_proto & ~ED_WD_LAAR_M16EN);
	}
}
static void
ed_3c503_mediachg(struct ed_softc *sc)
{
	struct ifnet *ifp = sc->ifp;

	/*
	 * If this is a 3Com board, the tranceiver must be software enabled
	 * (there is no settable hardware default).
	 */
	if (ifp->if_flags & IFF_LINK2)
		ed_asic_outb(sc, ED_3COM_CR, 0);
	else
		ed_asic_outb(sc, ED_3COM_CR, ED_3COM_CR_XSEL);
}
Esempio n. 4
0
/*
 * MII bus support routines.
 */
static int
ed_miibus_readreg(device_t dev, int phy, int reg)
{
	struct ed_softc *sc;
	int val;
	uint8_t cr = 0;

	sc = device_get_softc(dev);
	/*
	 * The AX88790 has an interesting quirk.  It has an internal phy that
	 * needs a special bit set to access, but can also have additional
	 * external PHYs set for things like HomeNET media.  When accessing
	 * the internal PHY, a bit has to be set, when accessing the external
	 * PHYs, it must be clear.  See Errata 1, page 51, in the AX88790
	 * datasheet for more details.
	 *
	 * Also, PHYs above 16 appear to be phantoms on some cards, but not
	 * others.  Registers read for this are often the same as prior values
	 * read.  Filter all register requests to 17-31.
	 */
	if (sc->chip_type == ED_CHIP_TYPE_AX88790) {
		if (phy > 0x10)
			return (0);
		if (phy == 0x10)
			ed_asic_outb(sc, ED_AX88X90_GPIO,
			    ED_AX88X90_GPIO_INT_PHY);
		else
			ed_asic_outb(sc, ED_AX88X90_GPIO, 0);
		ed_asic_barrier(sc, ED_AX88X90_GPIO, 1,
		    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
	} else if (sc->chip_type == ED_CHIP_TYPE_TC5299J) {
		/* Select page 3. */
		ed_nic_barrier(sc, ED_P0_CR, 1,
		    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
		cr = ed_nic_inb(sc, ED_P0_CR);
		ed_nic_outb(sc, ED_P0_CR, cr | ED_CR_PAGE_3);
		ed_nic_barrier(sc, ED_P0_CR, 1,
		    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
	}
	val = mii_bitbang_readreg(dev, sc->mii_bitbang_ops, phy, reg);
	if (sc->chip_type == ED_CHIP_TYPE_TC5299J) {
		/* Restore prior page. */
		ed_nic_outb(sc, ED_P0_CR, cr);
		ed_nic_barrier(sc, ED_P0_CR, 1,
	    	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
	}
	return (val);
}
Esempio n. 5
0
static void
ed_pccard_tick(struct ed_softc *sc)
{
	struct mii_data *mii;
	int media = 0;

	ED_ASSERT_LOCKED(sc);
	if (sc->miibus != NULL) {
		mii = device_get_softc(sc->miibus);
		media = mii->mii_media_status;
		mii_tick(mii);
		if (mii->mii_media_status & IFM_ACTIVE &&
		    media != mii->mii_media_status) {
			if (sc->chip_type == ED_CHIP_TYPE_DL10022) {
				ed_asic_outb(sc, ED_DL10022_DIAG,
				    (mii->mii_media_active & IFM_FDX) ?
				    ED_DL10022_COLLISON_DIS : 0);
#ifdef notyet
			} else if (sc->chip_type == ED_CHIP_TYPE_DL10019) {
				write_asic(sc, ED_DL10019_MAGIC,
				    (mii->mii_media_active & IFM_FDX) ?
				    DL19FDUPLX : 0);
#endif
			}
		}
		
	}
}
Esempio n. 6
0
static void
ed_pccard_dl100xx_mii_reset(struct ed_softc *sc)
{
	if (sc->chip_type != ED_CHIP_TYPE_DL10022)
		return;

	ed_asic_outb(sc, ED_DL100XX_MIIBUS, ED_DL10022_MII_RESET2);
	DELAY(10);
	ed_asic_outb(sc, ED_DL100XX_MIIBUS,
	    ED_DL10022_MII_RESET2 | ED_DL10022_MII_RESET1);
	DELAY(10);
	ed_asic_outb(sc, ED_DL100XX_MIIBUS, ED_DL10022_MII_RESET2);
	DELAY(10);
	ed_asic_outb(sc, ED_DL100XX_MIIBUS,
	    ED_DL10022_MII_RESET2 | ED_DL10022_MII_RESET1);
	DELAY(10);
	ed_asic_outb(sc, ED_DL100XX_MIIBUS, 0);
}
Esempio n. 7
0
static void
ed_pccard_ax88x90_mii_bitbang_write(device_t dev, uint32_t val)
{
	struct ed_softc *sc;

	sc = device_get_softc(dev);

	ed_asic_outb(sc, ED_AX88X90_MIIBUS, val);
	ed_asic_barrier(sc, ED_AX88X90_MIIBUS, 1,
	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
}
Esempio n. 8
0
static int
ed_miibus_writereg(device_t dev, int phy, int reg, int data)
{
	struct ed_softc *sc;
	uint8_t cr = 0;

	sc = device_get_softc(dev);
	/* See ed_miibus_readreg for details */
	if (sc->chip_type == ED_CHIP_TYPE_AX88790) {
		if (phy > 0x10)
			return (0);
		if (phy == 0x10)
			ed_asic_outb(sc, ED_AX88X90_GPIO,
			    ED_AX88X90_GPIO_INT_PHY);
		else
			ed_asic_outb(sc, ED_AX88X90_GPIO, 0);
		ed_asic_barrier(sc, ED_AX88X90_GPIO, 1,
		    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
	} else if (sc->chip_type == ED_CHIP_TYPE_TC5299J) {
		/* Select page 3. */
		ed_nic_barrier(sc, ED_P0_CR, 1,
		    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
		cr = ed_nic_inb(sc, ED_P0_CR);
		ed_nic_outb(sc, ED_P0_CR, cr | ED_CR_PAGE_3);
		ed_nic_barrier(sc, ED_P0_CR, 1,
		    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
	}
	mii_bitbang_writereg(dev, sc->mii_bitbang_ops, phy, reg, data);
	if (sc->chip_type == ED_CHIP_TYPE_TC5299J) {
		/* Restore prior page. */
		ed_nic_outb(sc, ED_P0_CR, cr);
		ed_nic_barrier(sc, ED_P0_CR, 1,
	    	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
	}
	return (0);
}
Esempio n. 9
0
static void
ed_pccard_ax88x90_reset(struct ed_softc *sc)
{
	int i;

	/* Reset Card */
	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_STP | ED_CR_PAGE_0);
	ed_nic_barrier(sc, ED_P0_CR, 1,
	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
	ed_asic_outb(sc, ED_NOVELL_RESET, ed_asic_inb(sc, ED_NOVELL_RESET));

	/* Wait for the RST bit to assert, but cap it at 10ms */
	for (i = 10000; !(ed_nic_inb(sc, ED_P0_ISR) & ED_ISR_RST) && i > 0;
	     i--)
		continue;
	ed_nic_outb(sc, ED_P0_ISR, ED_ISR_RST);	/* ACK INTR */
	if (i == 0)
		device_printf(sc->dev, "Reset didn't finish\n");
}
Esempio n. 10
0
/*
 * Probe and vendor-specific initialization routine for SIC boards
 */
int
ed_probe_SIC(device_t dev, int port_rid, int flags)
{
    struct ed_softc *sc = device_get_softc(dev);
    int	error;
    int	i;
    u_int	memsize;
    u_long	pmem;
    u_char	sum;

    error = ed_alloc_port(dev, 0, ED_SIC_IO_PORTS);
    if (error)
        return (error);

    sc->asic_offset = ED_SIC_ASIC_OFFSET;
    sc->nic_offset  = ED_SIC_NIC_OFFSET;

    memsize = 16384;
    /* XXX Needs to allow different msize */
    error = ed_alloc_memory(dev, 0, memsize);
    if (error)
        return (error);

    sc->mem_start = 0;
    sc->mem_size  = memsize;

    pmem = rman_get_start(sc->mem_res);
    error = ed_isa_mem_ok(dev, pmem, memsize);
    if (error)
        return (error);

    /* Reset card to force it into a known state. */
    ed_asic_outb(sc, 0, 0x00);
    DELAY(100);

    /*
     * Here we check the card ROM, if the checksum passes, and the
     * type code and ethernet address check out, then we know we have
     * an SIC card.
     */
    ed_asic_outb(sc, 0, 0x81);
    DELAY(100);

    sum = bus_space_read_1(sc->mem_bst, sc->mem_bsh, 6);
    for (i = 0; i < ETHER_ADDR_LEN; i++)
        sum ^= (sc->enaddr[i] =
                    bus_space_read_1(sc->mem_bst, sc->mem_bsh, i));
#ifdef ED_DEBUG
    device_printf(dev, "ed_probe_sic: got address %6D\n",
                  sc->enaddr, ":");
#endif
    if (sum != 0)
        return (ENXIO);
    if ((sc->enaddr[0] | sc->enaddr[1] | sc->enaddr[2]) == 0)
        return (ENXIO);

    sc->vendor   = ED_VENDOR_SIC;
    sc->type_str = "SIC";
    sc->isa16bit = 0;
    sc->cr_proto = 0;

    /*
     * SIC RAM page 0x0000-0x3fff(or 0x7fff)
     */
    ed_asic_outb(sc, 0, 0x80);
    DELAY(100);

    error = ed_clear_memory(dev);
    if (error)
        return (error);

    sc->mem_shared = 1;
    sc->mem_end = sc->mem_start + sc->mem_size;

    /*
     * allocate one xmit buffer if < 16k, two buffers otherwise
     */
    if ((sc->mem_size < 16384) || (flags & ED_FLAGS_NO_MULTI_BUFFERING))
        sc->txb_cnt = 1;
    else
        sc->txb_cnt = 2;
    sc->tx_page_start = 0;

    sc->rec_page_start = sc->tx_page_start + ED_TXBUF_SIZE * sc->txb_cnt;
    sc->rec_page_stop = sc->tx_page_start + sc->mem_size / ED_PAGE_SIZE;

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

    sc->sc_write_mbufs = ed_shmem_write_mbufs;
    return (0);
}
Esempio n. 11
0
/*
 * Probe and vendor-specific initialization routine for NE1000/2000 boards
 */
int
ed_probe_Novell_generic(device_t dev, int flags)
{
	struct ed_softc *sc = device_get_softc(dev);
	u_int   memsize;
	int	error;
	u_char  tmp;
	static char test_pattern[32] = "THIS is A memory TEST pattern";
	char    test_buffer[32];

	/* Reset the board */
	if (ED_FLAGS_GETTYPE(flags) == ED_FLAGS_GWETHER) {
		ed_asic_outb(sc, ED_NOVELL_RESET, 0);
		DELAY(200);
	}
	tmp = ed_asic_inb(sc, ED_NOVELL_RESET);

	/*
	 * I don't know if this is necessary; probably cruft leftover from
	 * Clarkson packet driver code. Doesn't do a thing on the boards I've
	 * tested. -DG
	 */
	ed_asic_outb(sc, ED_NOVELL_RESET, tmp);
	DELAY(5000);

	/*
	 * This is needed because some NE clones apparently don't reset the
	 * NIC properly (or the NIC chip doesn't reset fully on power-up) XXX
	 * - this makes the probe invasive! ...Done against my better
	 * judgement. -DLG
	 */
	ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP);
	DELAY(5000);

	/* Make sure that we really have an 8390 based board */
	if (!ed_probe_generic8390(sc))
		return (ENXIO);

	sc->vendor = ED_VENDOR_NOVELL;
	sc->mem_shared = 0;
	sc->cr_proto = ED_CR_RD2;

	/*
	 * Test the ability to read and write to the NIC memory. This has the
	 * side affect of determining if this is an NE1000 or an NE2000.
	 */

	/*
	 * This prevents packets from being stored in the NIC memory when the
	 * readmem routine turns on the start bit in the CR.
	 */
	ed_nic_outb(sc, ED_P0_RCR, ED_RCR_MON);

	/* Temporarily initialize DCR for byte operations */
	ed_nic_outb(sc, ED_P0_DCR, ED_DCR_FT1 | ED_DCR_LS);

	ed_nic_outb(sc, ED_P0_PSTART, 8192 / ED_PAGE_SIZE);
	ed_nic_outb(sc, ED_P0_PSTOP, 16384 / ED_PAGE_SIZE);

	/*
	 * Some devices identify themselves.  Some of those devices
	 * can't handle being probed, so we allow forcing a mode.  If
	 * these flags are set, force it, otherwise probe.
	 */
	if (flags & ED_FLAGS_FORCE_8BIT_MODE) {
		sc->isa16bit = 0;
		sc->type = ED_TYPE_NE1000;
		sc->type_str = "NE1000";
	} else if (flags & ED_FLAGS_FORCE_16BIT_MODE) {
		sc->isa16bit = 1;
		sc->type = ED_TYPE_NE2000;
		sc->type_str = "NE2000";
		ed_nic_outb(sc, ED_P0_DCR, ED_DCR_WTS | ED_DCR_FT1 | ED_DCR_LS);
		ed_nic_outb(sc, ED_P0_PSTART, 16384 / ED_PAGE_SIZE);
		ed_nic_outb(sc, ED_P0_PSTOP, 32768 / ED_PAGE_SIZE);
	} else {
		/*
		 * Write a test pattern in byte mode. If this fails, then there
		 * probably isn't any memory at 8k - which likely means that the board
		 * is an NE2000.
		 */
		ed_pio_writemem(sc, test_pattern, 8192, sizeof(test_pattern));
		ed_pio_readmem(sc, 8192, test_buffer, sizeof(test_pattern));

		if (bcmp(test_pattern, test_buffer, sizeof(test_pattern)) == 0) {
			sc->type = ED_TYPE_NE1000;
			sc->type_str = "NE1000";
			sc->isa16bit = 0;
		} else {
			/* Not an NE1000 - try NE2000 */
			sc->isa16bit = 1;
			ed_nic_outb(sc, ED_P0_DCR, ED_DCR_WTS | ED_DCR_FT1 | ED_DCR_LS);
			ed_nic_outb(sc, ED_P0_PSTART, 16384 / ED_PAGE_SIZE);
			ed_nic_outb(sc, ED_P0_PSTOP, 32768 / ED_PAGE_SIZE);
			/*
			 * Write a test pattern in word mode. If this also fails, then
			 * we don't know what this board is.
			 */
			ed_pio_writemem(sc, test_pattern, 16384, sizeof(test_pattern));
			ed_pio_readmem(sc, 16384, test_buffer, sizeof(test_pattern));
			if (bcmp(test_pattern, test_buffer, sizeof(test_pattern)) == 0) {
				sc->type = ED_TYPE_NE2000;
				sc->type_str = "NE2000";
			} else {
				return (ENXIO);
			}
		}
	}
	sc->chip_type = ED_CHIP_TYPE_DP8390;

	/* 8k of memory plus an additional 8k if 16bit */
	memsize = 8192 + sc->isa16bit * 8192;
	sc->mem_size = memsize;

	/* NIC memory doesn't start at zero on an NE board */
	/* The start address is tied to the bus width */
	sc->mem_start = 8192 + sc->isa16bit * 8192;
	sc->mem_end = sc->mem_start + memsize;
	sc->tx_page_start = memsize / ED_PAGE_SIZE;

	if (ED_FLAGS_GETTYPE(flags) == ED_FLAGS_GWETHER) {
		error = ed_probe_gwether(dev);
		if (error)
			return (error);
	}

	/*
	 * Use one xmit buffer if < 16k, two buffers otherwise (if not told
	 * otherwise).
	 */
	if ((memsize < 16384) || (flags & ED_FLAGS_NO_MULTI_BUFFERING))
		sc->txb_cnt = 1;
	else
		sc->txb_cnt = 2;

	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;
	/* clear any pending interrupts that might have occurred above */
	ed_nic_outb(sc, ED_P0_ISR, 0xff);

	sc->sc_write_mbufs = ed_pio_write_mbufs;
	return (0);
}
/*
 * Probe and vendor-specific initialization routine for 3Com 3c503 boards
 */
int
ed_probe_3Com(device_t dev, int port_rid, int flags)
{
	struct ed_softc *sc = device_get_softc(dev);
	int	error;
	int     i;
	u_int   memsize;
	u_char  isa16bit;
	u_long	conf_maddr, conf_msize, irq, junk, pmem;

	error = ed_alloc_port(dev, 0, ED_3COM_IO_PORTS);
	if (error)
		return (error);

	sc->asic_offset = ED_3COM_ASIC_OFFSET;
	sc->nic_offset  = ED_3COM_NIC_OFFSET;

	/*
	 * Verify that the kernel configured I/O address matches the board
	 * configured address
	 */
	switch (ed_asic_inb(sc, ED_3COM_BCFR)) {
	case ED_3COM_BCFR_300:
		if (rman_get_start(sc->port_res) != 0x300)
			return (ENXIO);
		break;
	case ED_3COM_BCFR_310:
		if (rman_get_start(sc->port_res) != 0x310)
			return (ENXIO);
		break;
	case ED_3COM_BCFR_330:
		if (rman_get_start(sc->port_res) != 0x330)
			return (ENXIO);
		break;
	case ED_3COM_BCFR_350:
		if (rman_get_start(sc->port_res) != 0x350)
			return (ENXIO);
		break;
	case ED_3COM_BCFR_250:
		if (rman_get_start(sc->port_res) != 0x250)
			return (ENXIO);
		break;
	case ED_3COM_BCFR_280:
		if (rman_get_start(sc->port_res) != 0x280)
			return (ENXIO);
		break;
	case ED_3COM_BCFR_2A0:
		if (rman_get_start(sc->port_res) != 0x2a0)
			return (ENXIO);
		break;
	case ED_3COM_BCFR_2E0:
		if (rman_get_start(sc->port_res) != 0x2e0)
			return (ENXIO);
		break;
	default:
		return (ENXIO);
	}

	error = bus_get_resource(dev, SYS_RES_MEMORY, 0,
				 &conf_maddr, &conf_msize);
	if (error)
		return (error);

	/*
	 * Verify that the kernel shared memory address matches the board
	 * configured address.
	 */
	switch (ed_asic_inb(sc, ED_3COM_PCFR)) {
	case ED_3COM_PCFR_DC000:
		if (conf_maddr != 0xdc000)
			return (ENXIO);
		break;
	case ED_3COM_PCFR_D8000:
		if (conf_maddr != 0xd8000)
			return (ENXIO);
		break;
	case ED_3COM_PCFR_CC000:
		if (conf_maddr != 0xcc000)
			return (ENXIO);
		break;
	case ED_3COM_PCFR_C8000:
		if (conf_maddr != 0xc8000)
			return (ENXIO);
		break;
	default:
		return (ENXIO);
	}


	/*
	 * Reset NIC and ASIC. Enable on-board transceiver throughout reset
	 * sequence because it'll lock up if the cable isn't connected if we
	 * don't.
	 */
	ed_asic_outb(sc, ED_3COM_CR, ED_3COM_CR_RST | ED_3COM_CR_XSEL);

	/*
	 * Wait for a while, then un-reset it
	 */
	DELAY(50);

	/*
	 * The 3Com ASIC defaults to rather strange settings for the CR after
	 * a reset - it's important to set it again after the following outb
	 * (this is done when we map the PROM below).
	 */
	ed_asic_outb(sc, ED_3COM_CR, ED_3COM_CR_XSEL);

	/*
	 * Wait a bit for the NIC to recover from the reset
	 */
	DELAY(5000);

	sc->vendor = ED_VENDOR_3COM;
	sc->type_str = "3c503";
	sc->mem_shared = 1;
	sc->cr_proto = ED_CR_RD2;

	/*
	 * Hmmm...a 16bit 3Com board has 16k of memory, but only an 8k window
	 * to it.
	 */
	memsize = 8192;

	/*
	 * Get station address from on-board ROM
	 */

	/*
	 * First, map ethernet address PROM over the top of where the NIC
	 * registers normally appear.
	 */
	ed_asic_outb(sc, ED_3COM_CR, ED_3COM_CR_EALO | ED_3COM_CR_XSEL);

	for (i = 0; i < ETHER_ADDR_LEN; ++i)
		sc->enaddr[i] = ed_nic_inb(sc, i);

	/*
	 * Unmap PROM - select NIC registers. The proper setting of the
	 * tranceiver is set in ed_init so that the attach code is given a
	 * chance to set the default based on a compile-time config option
	 */
	ed_asic_outb(sc, ED_3COM_CR, ED_3COM_CR_XSEL);

	/*
	 * Determine if this is an 8bit or 16bit board
	 */

	/*
	 * select page 0 registers
	 */
	ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP);

	/*
	 * Attempt to clear WTS bit. If it doesn't clear, then this is a 16bit
	 * board.
	 */
	ed_nic_outb(sc, ED_P0_DCR, 0);

	/*
	 * select page 2 registers
	 */
	ed_nic_outb(sc, ED_P0_CR, ED_CR_PAGE_2 | ED_CR_RD2 | ED_CR_STP);

	/*
	 * The 3c503 forces the WTS bit to a one if this is a 16bit board
	 */
	if (ed_nic_inb(sc, ED_P2_DCR) & ED_DCR_WTS)
		isa16bit = 1;
	else
		isa16bit = 0;

	/*
	 * select page 0 registers
	 */
	ed_nic_outb(sc, ED_P2_CR, ED_CR_RD2 | ED_CR_STP);

	error = ed_alloc_memory(dev, 0, memsize);
	if (error)
		return (error);

	pmem = rman_get_start(sc->mem_res);
	error = ed_isa_mem_ok(dev, pmem, memsize);
	if (error)
		return (error);

	sc->mem_start = 0;
	sc->mem_size = memsize;
	sc->mem_end = sc->mem_start + memsize;

	/*
	 * We have an entire 8k window to put the transmit buffers on the
	 * 16bit boards. But since the 16bit 3c503's shared memory is only
	 * fast enough to overlap the loading of one full-size packet, trying
	 * to load more than 2 buffers can actually leave the transmitter idle
	 * during the load. So 2 seems the best value. (Although a mix of
	 * variable-sized packets might change this assumption. Nonetheless,
	 * we optimize for linear transfers of same-size packets.)
	 */
	if (isa16bit) {
		if (flags & ED_FLAGS_NO_MULTI_BUFFERING)
			sc->txb_cnt = 1;
		else
			sc->txb_cnt = 2;

		sc->tx_page_start = ED_3COM_TX_PAGE_OFFSET_16BIT;
		sc->rec_page_start = ED_3COM_RX_PAGE_OFFSET_16BIT;
		sc->rec_page_stop = memsize / ED_PAGE_SIZE +
		    ED_3COM_RX_PAGE_OFFSET_16BIT;
		sc->mem_ring = sc->mem_start;
	} else {
		sc->txb_cnt = 1;
		sc->tx_page_start = ED_3COM_TX_PAGE_OFFSET_8BIT;
		sc->rec_page_start = ED_TXBUF_SIZE + ED_3COM_TX_PAGE_OFFSET_8BIT;
		sc->rec_page_stop = memsize / ED_PAGE_SIZE +
		    ED_3COM_TX_PAGE_OFFSET_8BIT;
		sc->mem_ring = sc->mem_start + (ED_PAGE_SIZE * ED_TXBUF_SIZE);
	}

	sc->isa16bit = isa16bit;

	/*
	 * Initialize GA page start/stop registers. Probably only needed if
	 * doing DMA, but what the hell.
	 */
	ed_asic_outb(sc, ED_3COM_PSTR, sc->rec_page_start);
	ed_asic_outb(sc, ED_3COM_PSPR, sc->rec_page_stop);

	/*
	 * Set IRQ. 3c503 only allows a choice of irq 2-5.
	 */
	error = bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, &junk);
	if (error)
		return (error);

	switch (irq) {
	case 2:
	case 9:
		ed_asic_outb(sc, ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ2);
		break;
	case 3:
		ed_asic_outb(sc, ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ3);
		break;
	case 4:
		ed_asic_outb(sc, ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ4);
		break;
	case 5:
		ed_asic_outb(sc, ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ5);
		break;
	default:
		device_printf(dev, "Invalid irq configuration (%ld) must be 3-5,9 for 3c503\n",
			      irq);
		return (ENXIO);
	}

	/*
	 * Initialize GA configuration register. Set bank and enable shared
	 * mem.
	 */
	ed_asic_outb(sc, ED_3COM_GACFR, ED_3COM_GACFR_RSEL |
	    ED_3COM_GACFR_MBS0);

	/*
	 * Initialize "Vector Pointer" registers. These gawd-awful things are
	 * compared to 20 bits of the address on ISA, and if they match, the
	 * shared memory is disabled. We set them to 0xffff0...allegedly the
	 * reset vector.
	 */
	ed_asic_outb(sc, ED_3COM_VPTR2, 0xff);
	ed_asic_outb(sc, ED_3COM_VPTR1, 0xff);
	ed_asic_outb(sc, ED_3COM_VPTR0, 0x00);

	error = ed_clear_memory(dev);
	if (error == 0) {
		sc->sc_mediachg = ed_3c503_mediachg;
		sc->sc_write_mbufs = ed_shmem_write_mbufs;
	}
	return (error);
}