Esempio n. 1
0
void
ec_attach(struct device *parent, struct device *self, void *aux)
{
	struct ec_softc *esc = (struct ec_softc *)self;
	struct dp8390_softc *sc = &esc->sc_dp8390;
	struct isa_attach_args *ia = aux;
	bus_space_tag_t nict, asict, memt;
	bus_space_handle_t nich, asich, memh;
	bus_size_t memsize;
	u_int8_t tmp;
	int i;

	printf("\n");

	nict = asict = ia->ia_iot;
	memt = ia->ia_memt;

	/*
	 * Hmm, a 16-bit card has 16k of memory, but only an 8k window
	 * to it.
	 */
	memsize = 8192;

	/* Map the NIC space. */
	if (bus_space_map(nict, ia->ia_iobase + ELINK2_NIC_OFFSET,
	    ELINK2_NIC_PORTS, 0, &nich)) {
		printf("%s: can't map nic i/o space\n",
		    sc->sc_dev.dv_xname);
		return;
	}

	/* Map the ASIC space. */
	if (bus_space_map(asict, ia->ia_iobase + ELINK2_ASIC_OFFSET,
	    ELINK2_ASIC_PORTS, 0, &asich)) {
		printf("%s: can't map asic i/o space\n",
		    sc->sc_dev.dv_xname);
		return;
	}

	/* Map the memory space. */
	if (bus_space_map(memt, ia->ia_maddr, memsize, 0, &memh)) {
		printf("%s: can't map shared memory\n",
		    sc->sc_dev.dv_xname);
		return;
	}

	esc->sc_asict = asict;
	esc->sc_asich = asich;

	sc->sc_regt = nict;
	sc->sc_regh = nich;

	sc->sc_buft = memt;
	sc->sc_bufh = memh;

	/* Interface is always enabled. */
	sc->sc_enabled = 1;

	/* Registers are linear. */
	for (i = 0; i < 16; i++)
		sc->sc_reg_map[i] = i;

	/* Now we can use the NIC_{GET,PUT}() macros. */

	/*
	 * Reset NIC and ASIC.  Enable on-board transeiver throughout
	 * reset sequence since it will lock up if the cable isn't
	 * connected if we don't.
	 */
	bus_space_write_1(asict, asich, ELINK2_CR,
	    ELINK2_CR_RST | ELINK2_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 write (this is done when we map the PROM below).
	 */
	bus_space_write_1(asict, asich, ELINK2_CR, ELINK2_CR_XSEL);

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

	/*
	 * Get the station address from on-board ROM.
	 *
	 * First, map Ethernet address PROM over the top of where the NIC
	 * registers normally appear.
	 */
	bus_space_write_1(asict, asich, ELINK2_CR,
	    ELINK2_CR_XSEL | ELINK2_CR_EALO);

	for (i = 0; i < ETHER_ADDR_LEN; i++)
		sc->sc_arpcom.ac_enaddr[i] = NIC_GET(nict, nich, i);

	/*
	 * Unmap PROM - select NIC registers.  The proper setting of the
	 * transciever is set in later in ec_init_card() via dp8390_init().
	 */
	bus_space_write_1(asict, asich, ELINK2_CR, ELINK2_CR_XSEL);

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

	/* Select page 0 registers. */
	NIC_PUT(nict, nich, ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STP);

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

	/* Select page 2 registers. */
	NIC_PUT(nict, nich, ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_2 | ED_CR_STP);

	/* The 3c503 forces the WTS bit to a one if this is a 16-bit board. */
	if (NIC_GET(nict, nich, ED_P2_DCR) & ED_DCR_WTS)
		esc->sc_16bitp = 1;
	else
		esc->sc_16bitp = 0;

	printf("%s: 3Com 3c503 Ethernet (%s-bit)",
	    sc->sc_dev.dv_xname, esc->sc_16bitp ? "16" : "8");

	/* Select page 0 registers. */
	NIC_PUT(nict, nich, ED_P2_CR, ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STP);

	sc->cr_proto = ED_CR_RD2;

	/*
	 * DCR gets:
	 *
	 *	FIFO threshold to 8, No auto-init Remote DMA,
	 *	byte order=80x86.
	 *
	 * 16-bit cards also get word-wide DMA transfers.
	 */
	sc->dcr_reg = ED_DCR_FT1 | ED_DCR_LS |
	    (esc->sc_16bitp ? ED_DCR_WTS : 0);

	sc->test_mem = ec_fake_test_mem;
	sc->ring_copy = ec_ring_copy;
	sc->write_mbuf = ec_write_mbuf;
	sc->read_hdr = ec_read_hdr;

	sc->sc_media_init = ec_media_init;

	sc->sc_mediachange = ec_mediachange;
	sc->sc_mediastatus = ec_mediastatus;

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

	/* Do generic parts of attach. */
	if (dp8390_config(sc)) {
		printf(": configuration failed\n");
		return;
	}

	/*
	 * We need to override the way dp8390_config() set up our
	 * shared memory.
	 *
	 * We have an entire 8k window to put the transmit buffers on the
	 * 16-bit 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 (esc->sc_16bitp) {
		if (sc->sc_dev.dv_cfdata->cf_flags & DP8390_NO_MULTI_BUFFERING)
			sc->txb_cnt = 1;
		else
			sc->txb_cnt = 2;

		sc->tx_page_start = ELINK2_TX_PAGE_OFFSET_16BIT;
		sc->rec_page_start = ELINK2_RX_PAGE_OFFSET_16BIT;
		sc->rec_page_stop = (memsize >> ED_PAGE_SHIFT) + 
		    sc->rec_page_start;
		sc->mem_ring = sc->mem_start;
	} else {
void
ed_zbus_attach(device_t parent, device_t self, void *aux)
{
	struct ed_zbus_softc *zsc = device_private(self);
	struct dp8390_softc *sc = &zsc->sc_dp8390;
	struct zbus_args *zap = aux;
	bus_space_handle_t promh;
	bus_addr_t memaddr, promaddr, regaddr;
	int i;

	zsc->sc_bst.base = (bus_addr_t)zap->va;
	zsc->sc_bst.absm = &amiga_bus_stride_1;

	if (zap->manid == HYDRA_MANID) {
		regaddr = HYDRA_REGADDR;
		memaddr = HYDRA_MEMADDR;
		promaddr = HYDRA_PROMADDR;
	} else {
		regaddr = ASDG_REGADDR;
		memaddr = ASDG_MEMADDR;
		promaddr = ASDG_PROMADDR;
	}

	sc->sc_dev = self;
	sc->sc_regt = &zsc->sc_bst;
	sc->sc_buft = &zsc->sc_bst;

	if (bus_space_map(sc->sc_regt, regaddr, 0x20, 0, &sc->sc_regh)) {
		aprint_error_dev(self, "can't map i/o space\n");
		return;
	}

	if (bus_space_map(sc->sc_buft, memaddr, ED_ZBUS_MEMSIZE, 0,
	    &sc->sc_bufh)) {
		aprint_error_dev(self, "can't map buffer space\n");
		return;
	}

	/* SRAM buffer size is always 16K */
	sc->mem_start = 0;
	sc->mem_size = ED_ZBUS_MEMSIZE;

	/*
	 * Read the ethernet address from the PROM.
	 * Interrupts must be inactive when reading the PROM, as the
	 * interrupt line is shared with one of its address lines.
	 */

	NIC_PUT(sc->sc_regt, sc->sc_regh, ED_P0_IMR, 0x00);
	NIC_PUT(sc->sc_regt, sc->sc_regh, ED_P0_ISR, 0xff);

	if (bus_space_map(&zsc->sc_bst, promaddr, ETHER_ADDR_LEN * 2, 0,
	    &promh) == 0) {
		for (i = 0; i < ETHER_ADDR_LEN; i++)
			sc->sc_enaddr[i] =
			    bus_space_read_1(&zsc->sc_bst, promh, i * 2);

		bus_space_unmap(&zsc->sc_bst, promh, ETHER_ADDR_LEN * 2);
	}

	/* Initialize sc_reg_map[]. Registers have stride 2 on the bus. */
	for (i = 0; i < 16; i++)
		sc->sc_reg_map[i] = i << 1;

	/*
	 * Set 2 word FIFO threshold, no auto-init Remote DMA,
	 * byte order 68k, word-wide DMA xfers.
	 */
	sc->dcr_reg = ED_DCR_FT0 | ED_DCR_WTS | ED_DCR_LS | ED_DCR_BOS;

	/* Remote DMA abort .*/
	sc->cr_proto = ED_CR_RD2;

	/*
	 * Override all functions which deal with the buffer, because
	 * this implementation only allows 16-bit buffer accesses.
	 */
	sc->test_mem = ed_zbus_test_mem;
	sc->read_hdr = ed_zbus_read_hdr;
	sc->ring_copy = ed_zbus_ring_copy;
	sc->write_mbuf = ed_zbus_write_mbuf;

	sc->sc_flags = device_cfdata(self)->cf_flags;
	sc->is790 = 0;
	sc->sc_media_init = dp8390_media_init;
	sc->sc_enabled = 1;

	/* Do generic DS8390/WD83C690 config. */
	if (dp8390_config(sc)) {
		bus_space_unmap(sc->sc_buft, sc->sc_bufh, ED_ZBUS_MEMSIZE);
		bus_space_unmap(sc->sc_regt, sc->sc_regh, 0x10);
		return;
	}

	/* establish level 2 interrupt handler */
	zsc->sc_isr.isr_intr = dp8390_intr;
	zsc->sc_isr.isr_arg = sc;
	zsc->sc_isr.isr_ipl = 2;
	add_isr(&zsc->sc_isr);
}