Example #1
0
void
rtl80x9_mediastatus(struct dp8390_softc *sc, struct ifmediareq *ifmr)
{
	struct ifnet *ifp = &sc->sc_ec.ec_if;
	u_int8_t cr_proto = sc->cr_proto |
	    ((ifp->if_flags & IFF_RUNNING) ? ED_CR_STA : ED_CR_STP);

	/*
	 * Sigh, can detect which media is being used, but can't
	 * detect if we have link or not.
	 */

	/* Set NIC to page 3 registers. */
	NIC_PUT(sc->sc_regt, sc->sc_regh, ED_P0_CR, cr_proto | ED_CR_PAGE_3);

	if (NIC_GET(sc->sc_regt, sc->sc_regh, NERTL_RTL3_CONFIG0) &
	    RTL3_CONFIG0_BNC)
		ifmr->ifm_active = IFM_ETHER|IFM_10_2;
	else {
		ifmr->ifm_active = IFM_ETHER|IFM_10_T;
		if (NIC_GET(sc->sc_regt, sc->sc_regh, NERTL_RTL3_CONFIG3) &
		    RTL3_CONFIG3_FUDUP)
			ifmr->ifm_active |= IFM_FDX;
	}

	/* Set NIC to page 0 registers. */
	NIC_PUT(sc->sc_regt, sc->sc_regh, ED_P0_CR, cr_proto | ED_CR_PAGE_0);
}
Example #2
0
void
rtl80x9_init_card(struct dp8390_softc *sc)
{
	struct ifmedia *ifm = &sc->sc_media;
	struct ifnet *ifp = &sc->sc_ec.ec_if;
	u_int8_t cr_proto = sc->cr_proto |
	    ((ifp->if_flags & IFF_RUNNING) ? ED_CR_STA : ED_CR_STP);
	u_int8_t reg;

	/* Set NIC to page 3 registers. */
	NIC_PUT(sc->sc_regt, sc->sc_regh, ED_P0_CR, cr_proto | ED_CR_PAGE_3);

	/* write enable config1-3. */
	NIC_PUT(sc->sc_regt, sc->sc_regh, NERTL_RTL3_EECR,
	    RTL3_EECR_EEM1|RTL3_EECR_EEM0);

	/* First, set basic media type. */
	reg = NIC_GET(sc->sc_regt, sc->sc_regh, NERTL_RTL3_CONFIG2);
	reg &= ~(RTL3_CONFIG2_PL1|RTL3_CONFIG2_PL0);
	switch (IFM_SUBTYPE(ifm->ifm_cur->ifm_media)) {
	case IFM_AUTO:
		/* Nothing to do; both bits clear == auto-detect. */
		break;

	case IFM_10_T:
		/*
		 * According to docs, this should be:
		 * reg |= RTL3_CONFIG2_PL0;
		 * but this doesn't work, so make it the same as AUTO.
		 */
		break;

	case IFM_10_2:
		reg |= RTL3_CONFIG2_PL1|RTL3_CONFIG2_PL0;
		break;
	}
	NIC_PUT(sc->sc_regt, sc->sc_regh, NERTL_RTL3_CONFIG2, reg);

	/* Now, set duplex mode. */
	reg = NIC_GET(sc->sc_regt, sc->sc_regh, NERTL_RTL3_CONFIG3);
	if (ifm->ifm_cur->ifm_media & IFM_FDX)
		reg |= RTL3_CONFIG3_FUDUP;
	else
		reg &= ~RTL3_CONFIG3_FUDUP;
	NIC_PUT(sc->sc_regt, sc->sc_regh, NERTL_RTL3_CONFIG3, reg);

	/* write disable config1-3 */
	NIC_PUT(sc->sc_regt, sc->sc_regh, NERTL_RTL3_EECR, 0);

	/* Set NIC to page 0 registers. */
	NIC_PUT(sc->sc_regt, sc->sc_regh, ED_P0_CR, cr_proto | ED_CR_PAGE_0);
}
Example #3
0
hide void
mc_reset_txdma(struct mc_softc *sc)
{
	dbdma_command_t *cmd = sc->sc_txdmacmd;
	dbdma_regmap_t *dmareg = sc->sc_txdma;
	u_int8_t maccc;

	/* disable transmitter */
	maccc = NIC_GET(sc, MACE_MACCC);
	NIC_PUT(sc, MACE_MACCC, maccc & ~ENXMT);

	dbdma_reset(dmareg);

	DBDMA_BUILD(cmd, DBDMA_CMD_OUT_LAST, 0, 0, sc->sc_txbuf_phys,
		DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
	cmd++;
	DBDMA_BUILD(cmd, DBDMA_CMD_STOP, 0, 0, 0,
		DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);

	out32rb(&dmareg->d_cmdptrhi, 0);
	out32rb(&dmareg->d_cmdptrlo, kvtop((void *)sc->sc_txdmacmd));

	/* restore old value */
	NIC_PUT(sc, MACE_MACCC, maccc);
}
Example #4
0
hide void
mc_reset_rxdma(struct mc_softc *sc)
{
	dbdma_command_t *cmd = sc->sc_rxdmacmd;
	dbdma_regmap_t *dmareg = sc->sc_rxdma;
	int i;
	u_int8_t maccc;

	/* Disable receiver, reset the DMA channels */
	maccc = NIC_GET(sc, MACE_MACCC);
	NIC_PUT(sc, MACE_MACCC, maccc & ~ENRCV);

	dbdma_reset(dmareg);

	for (i = 0; i < MC_RXDMABUFS; i++) {
		DBDMA_BUILD(cmd, DBDMA_CMD_IN_LAST, 0, ETHERMTU + 22,
			sc->sc_rxbuf_phys + MC_BUFSIZE * i, DBDMA_INT_ALWAYS,
			DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
		cmd++;
	}

	DBDMA_BUILD(cmd, DBDMA_CMD_NOP, 0, 0, 0,
		DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_ALWAYS);
	out32rb(&cmd->d_cmddep, kvtop((void *)sc->sc_rxdmacmd));
	cmd++;

	dbdma_start(dmareg, sc->sc_rxdmacmd);

	sc->sc_tail = 0;

	/* Reenable receiver, reenable DMA */
	NIC_PUT(sc, MACE_MACCC, maccc);
}
Example #5
0
void
mc_reset_rxdma(struct mc_softc *sc)
{
	dbdma_command_t *cmd = sc->sc_rxdmacmd;
	int i;
	u_int8_t maccc;

	/* Disable receiver, reset the DMA channels */
	maccc = NIC_GET(sc, MACE_MACCC);
	NIC_PUT(sc, MACE_MACCC, maccc & ~ENRCV);

	dbdma_reset(sc->sc_rxdma);

	bzero(sc->sc_rxdmacmd, 8 * sizeof(dbdma_command_t));
	for (i = 0; i < MC_RXDMABUFS; i++) {
		DBDMA_BUILD(cmd, DBDMA_CMD_IN_LAST, 0, MACE_BUFLEN,
		    sc->sc_rxbuf_pa + MACE_BUFLEN * i, DBDMA_INT_ALWAYS,
		    DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
		cmd++;
	}

	DBDMA_BUILD(cmd, DBDMA_CMD_NOP, 0, 0, 0,
	    DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_ALWAYS);
	dbdma_st32(&cmd->d_cmddep, sc->sc_rxdbdma->d_paddr);
	cmd++;

	sc->sc_tail = 0;

	dbdma_start(sc->sc_rxdma, sc->sc_rxdbdma);
	/* Reenable receiver, reenable DMA */
	NIC_PUT(sc, MACE_MACCC, maccc);
}
Example #6
0
void
mc_tint(struct mc_softc *sc)
{
	struct ifnet *ifp = &sc->sc_arpcom.ac_if;
	u_int8_t xmtrc, xmtfs;

	xmtrc = NIC_GET(sc, MACE_XMTRC);
	xmtfs = NIC_GET(sc, MACE_XMTFS);

	if ((xmtfs & XMTSV) == 0)
		return;

	if (xmtfs & UFLO) {
		printf("%s: underflow\n", sc->sc_dev.dv_xname);
		mc_reset(sc);
		return;
	}

	if (xmtfs & LCOL) {
		printf("%s: late collision\n", sc->sc_dev.dv_xname);
		ifp->if_oerrors++;
		ifp->if_collisions++;
	}

	if (xmtfs & MORE)
		/* Real number is unknown. */
		ifp->if_collisions += 2;
	else if (xmtfs & ONE)
		ifp->if_collisions++;
	else if (xmtfs & RTRY) {
		printf("%s: excessive collisions\n", sc->sc_dev.dv_xname);
		ifp->if_collisions += 16;
		ifp->if_oerrors++;
	}

	if (xmtfs & LCAR) {
		sc->sc_havecarrier = 0;
		printf("%s: lost carrier\n", sc->sc_dev.dv_xname);
		ifp->if_oerrors++;
	}

	ifp->if_flags &= ~IFF_OACTIVE;
	ifp->if_timer = 0;
	mc_start(ifp);
}
Example #7
0
/*
 * Assume that the SONIC was initialized in MacOS.  This should go away
 * when we can properly get the MAC address on the PBs.
 */
static int
sn_obio_getaddr_kludge(struct sn_softc *sc, u_int8_t *lladdr)
{
	int i, ors = 0;

	/* Shut down NIC */
	NIC_PUT(sc, SNR_CR, CR_RST);
	wbflush();

	NIC_PUT(sc, SNR_CEP, 15); /* For some reason, Apple fills top first. */
	wbflush();
	i = NIC_GET(sc, SNR_CAP2);
	wbflush();

	ors |= i;
	lladdr[5] = i >> 8;
	lladdr[4] = i;

	i = NIC_GET(sc, SNR_CAP1);
	wbflush();

	ors |= i;
	lladdr[3] = i >> 8;
	lladdr[2] = i;

	i = NIC_GET(sc, SNR_CAP0);
	wbflush();

	ors |= i;
	lladdr[1] = i >> 8;
	lladdr[0] = i;

	NIC_PUT(sc, SNR_CR, 0);
	wbflush();

	if (ors == 0)
		return (-1);

	return (0);
}
static void 
camdump(struct sn_softc *sc)
{
	int	i;

	printf("CAM entries:\n");
	NIC_PUT(sc, SNR_CR, CR_RST);
	wbflush();

	for (i = 0; i < 16; i++) {
		ushort  ap2, ap1, ap0;
		NIC_PUT(sc, SNR_CEP, i);
		wbflush();
		ap2 = NIC_GET(sc, SNR_CAP2);
		ap1 = NIC_GET(sc, SNR_CAP1);
		ap0 = NIC_GET(sc, SNR_CAP0);
		printf("%d: ap2=0x%x ap1=0x%x ap0=0x%x\n", i, ap2, ap1, ap0);
	}
	printf("CAM enable 0x%x\n", NIC_GET(sc, SNR_CEP));

	NIC_PUT(sc, SNR_CR, 0);
	wbflush();
}
Example #9
0
int
mc_intr(void *arg)
{
	struct mc_softc *sc = arg;
	struct ifnet *ifp = &sc->sc_arpcom.ac_if;
	u_int8_t ir;

	ir = NIC_GET(sc, MACE_IR) & ~NIC_GET(sc, MACE_IMR);

	if (ir & JAB) {
#ifdef MCDEBUG
		printf("%s: jabber error\n", sc->sc_dev.dv_xname);
#endif
		ifp->if_oerrors++;
	}

	if (ir & BABL) {
#ifdef MCDEBUG
		printf("%s: babble\n", sc->sc_dev.dv_xname);
#endif
		ifp->if_oerrors++;
	 }

	if (ir & CERR) {
#ifdef MCDEBUG
		printf("%s: collision error\n", sc->sc_dev.dv_xname);
#endif
		ifp->if_collisions++;
	 }

	/*
	 * Pretend we have carrier; if we don't this will be cleared
	 * shortly.
	 */
	sc->sc_havecarrier = 1;

	if (ir & XMTINT)
		mc_tint(sc);

	if (ir & RCVINT)
		mc_rint(sc);

	return(1);
}
Example #10
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 {
int
snintr(void *arg)
{
	struct sn_softc *sc = (struct sn_softc *)arg;
	int handled = 0;
	int	isr;

	while ((isr = (NIC_GET(sc, SNR_ISR) & ISR_ALL)) != 0) {
		/* scrub the interrupts that we are going to service */
		NIC_PUT(sc, SNR_ISR, isr);
		handled = 1;
		wbflush();

		if (isr & (ISR_BR | ISR_LCD | ISR_TC))
			printf("%s: unexpected interrupt status 0x%x\n",
			    device_xname(sc->sc_dev), isr);

		if (isr & (ISR_TXDN | ISR_TXER | ISR_PINT))
			sonictxint(sc);

		if (isr & ISR_PKTRX)
			sonicrxint(sc);

		if (isr & (ISR_HBL | ISR_RDE | ISR_RBE | ISR_RBAE | ISR_RFO)) {
			if (isr & ISR_HBL)
				/*
				 * The repeater is not providing a heartbeat.
				 * In itself this isn't harmful, lots of the
				 * cheap repeater hubs don't supply a heartbeat.
				 * So ignore the lack of heartbeat. Its only
				 * if we can't detect a carrier that we have a
				 * problem.
				 */
				;
			if (isr & ISR_RDE)
				printf("%s: receive descriptors exhausted\n",
				    device_xname(sc->sc_dev));
			if (isr & ISR_RBE)
				printf("%s: receive buffers exhausted\n",
				    device_xname(sc->sc_dev));
			if (isr & ISR_RBAE)
				printf("%s: receive buffer area exhausted\n",
				    device_xname(sc->sc_dev));
			if (isr & ISR_RFO)
				printf("%s: receive FIFO overrun\n",
				    device_xname(sc->sc_dev));
		}
		if (isr & (ISR_CRC | ISR_FAE | ISR_MP)) {
#ifdef notdef
			if (isr & ISR_CRC)
				sc->sc_crctally++;
			if (isr & ISR_FAE)
				sc->sc_faetally++;
			if (isr & ISR_MP)
				sc->sc_mptally++;
#endif
		}
		snstart(&sc->sc_if);
	}
	return handled;
}
static void 
camprogram(struct sn_softc *sc)
{
	struct ether_multistep step;
	struct ether_multi *enm;
	struct ifnet *ifp;
	int	timeout;
	int	mcount = 0;

	caminitialise(sc);

	ifp = &sc->sc_if;

	/* Always load our own address first. */
	camentry(sc, mcount, CLLADDR(ifp->if_sadl));
	mcount++;

	/* Assume we won't need allmulti bit. */
	ifp->if_flags &= ~IFF_ALLMULTI;

	/* Loop through multicast addresses */
	ETHER_FIRST_MULTI(step, &sc->sc_ethercom, enm);
	while (enm != NULL) {
		if (mcount == MAXCAM) {
			 ifp->if_flags |= IFF_ALLMULTI;
			 break;
		}

		if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
		    sizeof(enm->enm_addrlo)) != 0) {
			/*
			 * SONIC's CAM is programmed with specific
			 * addresses. It has no way to specify a range.
			 * (Well, thats not exactly true. If the
			 * range is small one could program each addr
			 * within the range as a separate CAM entry)
			 */
			ifp->if_flags |= IFF_ALLMULTI;
			break;
		}

		/* program the CAM with the specified entry */
		camentry(sc, mcount, enm->enm_addrlo);
		mcount++;

		ETHER_NEXT_MULTI(step, enm);
	}

	NIC_PUT(sc, SNR_CDP, LOWER(sc->v_cda));
	NIC_PUT(sc, SNR_CDC, MAXCAM);
	NIC_PUT(sc, SNR_CR, CR_LCAM);
	wbflush();

	timeout = 10000;
	while ((NIC_GET(sc, SNR_CR) & CR_LCAM) && timeout--)
		delay(10);
	if (timeout == 0) {
		/* XXX */
		panic("%s: CAM initialisation failed",
		    device_xname(sc->sc_dev));
	}
	timeout = 10000;
	while (((NIC_GET(sc, SNR_ISR) & ISR_LCD) == 0) && timeout--)
		delay(10);

	if (NIC_GET(sc, SNR_ISR) & ISR_LCD)
		NIC_PUT(sc, SNR_ISR, ISR_LCD);
	else
		printf("%s: CAM initialisation without interrupt\n",
		    device_xname(sc->sc_dev));
}
/*
 * stuff packet into sonic (at splnet)
 */
static inline u_int
sonicput(struct sn_softc *sc, struct mbuf *m0, int mtd_next)
{
	struct mtd *mtdp;
	struct mbuf *m;
	u_char	*buff;
	void	*txp;
	u_int	len = 0;
	u_int	totlen = 0;

#ifdef whyonearthwouldyoudothis
	if (NIC_GET(sc, SNR_CR) & CR_TXP)
		return 0;
#endif

	/* grab the replacement mtd */
	mtdp = &sc->mtda[sc->mtd_free];

	buff = mtdp->mtd_buf;

	/* this packet goes to mtdnext fill in the TDA */
	mtdp->mtd_mbuf = m0;
	txp = mtdp->mtd_txp;

	/* Write to the config word. Every (NTDA/2)+1 packets we set an intr */
	if (sc->mtd_pint == 0) {
		sc->mtd_pint = NTDA/2;
		SWO(sc->bitmode, txp, TXP_CONFIG, TCR_PINT);
	} else {
		sc->mtd_pint--;
		SWO(sc->bitmode, txp, TXP_CONFIG, 0);
	}

	for (m = m0; m; m = m->m_next) {
		u_char *data = mtod(m, u_char *);
		len = m->m_len;
		totlen += len;
		memcpy(buff, data, len);
		buff += len;
	}
	if (totlen >= TXBSIZE) {
		panic("%s: sonicput: packet overflow",
		    device_xname(sc->sc_dev));
	}

	SWO(sc->bitmode, txp, TXP_FRAGOFF + (0 * TXP_FRAGSIZE) + TXP_FPTRLO,
	    LOWER(mtdp->mtd_vbuf));
	SWO(sc->bitmode, txp, TXP_FRAGOFF + (0 * TXP_FRAGSIZE) + TXP_FPTRHI,
	    UPPER(mtdp->mtd_vbuf));

	if (totlen < ETHERMIN + ETHER_HDR_LEN) {
		int pad = ETHERMIN + ETHER_HDR_LEN - totlen;
		memset((char *)mtdp->mtd_buf + totlen, 0, pad);
		totlen = ETHERMIN + ETHER_HDR_LEN;
	}

	SWO(sc->bitmode, txp, TXP_FRAGOFF + (0 * TXP_FRAGSIZE) + TXP_FSIZE,
	    totlen);
	SWO(sc->bitmode, txp, TXP_FRAGCNT, 1);
	SWO(sc->bitmode, txp, TXP_PKTSIZE, totlen);

	/* link onto the next mtd that will be used */
	SWO(sc->bitmode, txp, TXP_FRAGOFF + (1 * TXP_FRAGSIZE) + TXP_FPTRLO,
	    LOWER(sc->mtda[mtd_next].mtd_vtxp) | EOL);

	/*
	 * The previous txp.tlink currently contains a pointer to
	 * our txp | EOL. Want to clear the EOL, so write our
	 * pointer to the previous txp.
	 */
	SWO(sc->bitmode, sc->mtda[sc->mtd_prev].mtd_txp, sc->mtd_tlinko,
	    LOWER(mtdp->mtd_vtxp));

	/* make sure chip is running */
	wbflush();
	NIC_PUT(sc, SNR_CR, CR_TXP);
	wbflush();
	sc->sc_if.if_timer = 5;	/* 5 seconds to watch for failing to transmit */

	return totlen;
}
static int 
sninit(struct sn_softc *sc)
{
	u_long	s_rcr;
	int	s;

	if (sc->sc_if.if_flags & IFF_RUNNING)
		/* already running */
		return 0;

	s = splnet();

	NIC_PUT(sc, SNR_CR, CR_RST);	/* DCR only accessible in reset mode! */

	/* config it */
	NIC_PUT(sc, SNR_DCR, (sc->snr_dcr |
		(sc->bitmode ? DCR_DW32 : DCR_DW16)));
	NIC_PUT(sc, SNR_DCR2, sc->snr_dcr2);

	s_rcr = RCR_BRD | RCR_LBNONE;
	if (sc->sc_if.if_flags & IFF_PROMISC)
		s_rcr |= RCR_PRO;
	if (sc->sc_if.if_flags & IFF_ALLMULTI)
		s_rcr |= RCR_AMC;
	NIC_PUT(sc, SNR_RCR, s_rcr);

#if 0
	NIC_PUT(sc, SNR_IMR, (IMR_PRXEN | IMR_PTXEN | IMR_TXEREN | IMR_LCDEN));
#else
	NIC_PUT(sc, SNR_IMR, IMR_PRXEN | IMR_PTXEN | IMR_TXEREN | IMR_LCDEN |
			     IMR_BREN  | IMR_HBLEN | IMR_RDEEN  | IMR_RBEEN |
			     IMR_RBAEEN | IMR_RFOEN);
#endif

	/* clear pending interrupts */
	NIC_PUT(sc, SNR_ISR, ISR_ALL);

	/* clear tally counters */
	NIC_PUT(sc, SNR_CRCT, -1);
	NIC_PUT(sc, SNR_FAET, -1);
	NIC_PUT(sc, SNR_MPT, -1);

	initialise_tda(sc);
	initialise_rda(sc);
	initialise_rra(sc);

	sn_md_init(sc);			/* MD initialization */

	/* enable the chip */
	NIC_PUT(sc, SNR_CR, 0);
	wbflush();

	/* program the CAM */
	camprogram(sc);

	/* get it to read resource descriptors */
	NIC_PUT(sc, SNR_CR, CR_RRRA);
	wbflush();
	while ((NIC_GET(sc, SNR_CR)) & CR_RRRA)
		continue;

	/* enable rx */
	NIC_PUT(sc, SNR_CR, CR_RXEN);
	wbflush();

	/* flag interface as "running" */
	sc->sc_if.if_flags |= IFF_RUNNING;
	sc->sc_if.if_flags &= ~IFF_OACTIVE;

	splx(s);
	return 0;
}
Example #15
0
void
mc_init(struct mc_softc *sc)
{
	struct ifnet *ifp = &sc->sc_arpcom.ac_if;
	u_int8_t maccc, ladrf[8];
	int s, i;

	s = splnet();

	NIC_PUT(sc, MACE_BIUCC, sc->sc_biucc);
	NIC_PUT(sc, MACE_FIFOCC, sc->sc_fifocc);
	NIC_PUT(sc, MACE_IMR, ~0); /* disable all interrupts */
	NIC_PUT(sc, MACE_PLSCC, sc->sc_plscc);

	NIC_PUT(sc, MACE_UTR, RTRD); /* disable reserved test registers */

	/* set MAC address */
	NIC_PUT(sc, MACE_IAC, ADDRCHG);
	while (NIC_GET(sc, MACE_IAC) & ADDRCHG)
		;
	NIC_PUT(sc, MACE_IAC, PHYADDR);
	for (i = 0; i < ETHER_ADDR_LEN; i++)
		out8rb(sc->sc_reg + MACE_REG(MACE_PADR) + i,
		    sc->sc_enaddr[i]);

	/* set logical address filter */
	mace_calcladrf(sc, ladrf);

	NIC_PUT(sc, MACE_IAC, ADDRCHG);
	while (NIC_GET(sc, MACE_IAC) & ADDRCHG)
		;
	NIC_PUT(sc, MACE_IAC, LOGADDR);
	for (i = 0; i < 8; i++)
		out8rb(sc->sc_reg + MACE_REG(MACE_LADRF) + i,
		    ladrf[i]);

	NIC_PUT(sc, MACE_XMTFC, APADXMT);
	/*
	* No need to autostrip padding on receive... Ethernet frames
	* don't have a length field, unlike 802.3 frames, so the MACE
	* can't figure out the length of the packet anyways.
	*/
	NIC_PUT(sc, MACE_RCVFC, 0);

	maccc = ENXMT | ENRCV;
	if (ifp->if_flags & IFF_PROMISC)
		maccc |= PROM;

	NIC_PUT(sc, MACE_MACCC, maccc);

	mc_reset_rxdma(sc);
	mc_reset_txdma(sc);
	/*
	* Enable all interrupts except receive, since we use the DMA
	* completion interrupt for that.
	*/
	NIC_PUT(sc, MACE_IMR, RCVINTM);

	/* flag interface as "running" */
	ifp->if_flags |= IFF_RUNNING;
	ifp->if_flags &= ~IFF_OACTIVE;

	splx(s);
}
Example #16
0
/*
 * Install interface into kernel networking data structures
 */
static void
sn_obio_attach(struct device *parent, struct device *self, void *aux)
{
	struct obio_attach_args *oa = (struct obio_attach_args *)aux;
	struct sn_softc	*sc = (void *)self;
	u_int8_t myaddr[ETHER_ADDR_LEN];
	int i;

	sc->snr_dcr = DCR_WAIT0 | DCR_DMABLOCK | DCR_RFT16 | DCR_TFT16;
	sc->snr_dcr2 = 0;

	sc->slotno = 9;

	switch (current_mac_model->machineid) {
	case MACH_MACC610:
	case MACH_MACC650:
	case MACH_MACQ610:
	case MACH_MACQ650:
	case MACH_MACQ700:
	case MACH_MACQ800:
	case MACH_MACQ900:
	case MACH_MACQ950:
		sc->snr_dcr |= DCR_EXBUS;
		sc->bitmode = 1;
		break;

	case MACH_MACLC575:
	case MACH_MACP580:
	case MACH_MACQ630:
		break;

	case MACH_MACPB500:
		sc->snr_dcr |= DCR_SYNC | DCR_LBR;
		sc->bitmode = 0;	/* 16 bit interface */
		break;

	default:
		printf(": unsupported machine type\n");
		return;
	}

	sc->sc_regt = oa->oa_tag;

	if (bus_space_map(sc->sc_regt,
	    SONIC_REG_BASE, SN_REGSIZE, 0, &sc->sc_regh)) {
		printf(": failed to map space for SONIC regs.\n");
		return;
	}

	/* regs are addressed as words, big-endian. */
	for (i = 0; i < SN_NREGS; i++) {
		sc->sc_reg_map[i] = (bus_size_t)((i * 4) + 2);
	}

	/*
	 * Kind of kludge this.  Comm-slot cards do not really
	 * have a visible type, as far as I can tell at this time,
	 * so assume that MacOS had it properly configured and use
	 * that configuration.
	 */
	switch (current_mac_model->machineid) {
	case MACH_MACLC575:
	case MACH_MACP580:
	case MACH_MACQ630:
		NIC_PUT(sc, SNR_CR, CR_RST);	wbflush();
		i = NIC_GET(sc, SNR_DCR);
		sc->snr_dcr |= (i & 0xfff0);
		sc->bitmode = (i & DCR_DW) ? 1 : 0;
		break;
	default:
		break;
	}

	if (sn_obio_getaddr(sc, myaddr) &&
	    sn_obio_getaddr_kludge(sc, myaddr)) { /* XXX kludge for PB */
		printf(": failed to get MAC address.\n");
		bus_space_unmap(sc->sc_regt, sc->sc_regh, SN_REGSIZE);
		return;
	}

	printf(": integrated ethernet adapter, ");

	/* snsetup returns 1 if something fails */
	if (snsetup(sc, myaddr)) {
		bus_space_unmap(sc->sc_regt, sc->sc_regh, SN_REGSIZE);
		return;
	}

	if (mac68k_machine.aux_interrupts)
		intr_establish(snintr, sc, 3, sc->sc_dev.dv_xname);
	else
		add_nubus_intr(sc->slotno, IPL_NET, snintr, sc,
		    sc->sc_dev.dv_xname);
}