int
le_put(struct iodesc *desc, void *pkt, size_t len)
{
	int unit = /*nif->nif_unit*/0;
	struct le_softc *sc = &le_softc[unit];
	volatile struct mds *cdm;
	int timo, stat;
#if 0
	int i;
#endif

 le_put_loop:
	timo = 100000;

#ifdef LE_DEBUG
	if (le_debug)
		printf("le%d: le_put called. next_td=%d\n", unit, sc->sc_next_td);
#endif
	stat = lerdcsr(sc, 0);
	lewrcsr(sc, 0, stat & (LE_BABL | LE_MISS | LE_MERR | LE_TINT));
	if (stat & (LE_BABL | LE_CERR | LE_MISS | LE_MERR))
		le_error(unit, "le_put(way before xmit)", stat);
	cdm = &sc->sc_td[sc->sc_next_td];
#if 0
	i = 0;
	while (cdm->flags & LE_OWN) {
		if ((i % 100) == 0)
			printf("le%d: output buffer busy - flags=%x\n",
				unit, cdm->flags);
		if (i++ > 500) break;
	}
	if (cdm->flags & LE_OWN)
		getchar();
#else
	while (cdm->flags & LE_OWN);
#endif
	memcpy(sc->sc_tbuf + (BUFSIZE * sc->sc_next_td), pkt, len);
	if (len < ETHER_MIN_LEN)
		cdm->bcnt = -ETHER_MIN_LEN;
	else
		cdm->bcnt = -len;
	cdm->mcnt = 0;
	cdm->flags |= LE_OWN | LE_STP | LE_ENP;
	stat = lerdcsr(sc, 0);
	if (stat & (LE_BABL | LE_CERR | LE_MISS | LE_MERR))
		le_error(unit, "le_put(before xmit)", stat);
	lewrcsr(sc, 0, LE_TDMD);
	stat = lerdcsr(sc, 0);
	if (stat & (LE_BABL | LE_CERR | LE_MISS | LE_MERR))
		le_error(unit, "le_put(after xmit)", stat);
	do {
		if (--timo == 0) {
			printf("le%d: transmit timeout, stat = 0x%x\n",
				unit, stat);
			if (stat & LE_SERR)
				le_error(unit, "le_put(timeout)", stat);
			if (stat & LE_INIT) {
				printf("le%d: reset and retry packet\n", unit);
				lewrcsr(sc, 0, LE_TINT);	/* sanity */
				leinit();
				goto le_put_loop;
			}
			break;
		}
		stat = lerdcsr(sc, 0);
	} while ((stat & LE_TINT) == 0);
	lewrcsr(sc, 0, LE_TINT);
	if (stat & (LE_BABL |/* LE_CERR |*/ LE_MISS | LE_MERR)) {
		printf("le_put: xmit error, buf %d\n", sc->sc_next_td);
		le_error(unit, "le_put(xmit error)", stat);
	}
	if (++sc->sc_next_td >= NTBUF)
		sc->sc_next_td = 0;
	if (cdm->flags & LE_DEF)
		le_stats[unit].deferred++;
	if (cdm->flags & LE_ONE)
		le_stats[unit].collisions++;
	if (cdm->flags & LE_MORE)
		le_stats[unit].collisions += 2;
	if (cdm->flags & LE_ERR) {
		if (cdm->mcnt & LE_UFLO)
			printf("le%d: transmit underflow\n", unit);
		if (cdm->mcnt & LE_LCOL)
			le_stats[unit].collisions++;
		if (cdm->mcnt & LE_LCAR)
			printf("le%d: lost carrier\n", unit);
		if (cdm->mcnt & LE_RTRY)
			le_stats[unit].collisions += 16;
		return -1;
	}
#ifdef LE_DEBUG
	if (le_debug) {
		printf("le%d: le_put() successful: sent %d\n", unit, len);
		printf("le%d: le_put(): flags: %x mcnt: %x\n", unit,
			(unsigned int) cdm->flags,
			(unsigned int) cdm->mcnt);
	}
#endif
	return len;
}
Example #2
0
int
le_put(struct iodesc *desc, void *pkt, size_t len)
{
	volatile struct lereg1 *ler1 = le_softc.sc_r1;
	volatile struct lereg2 *ler2 = le_softc.sc_r2;
	volatile struct letmd *tmd;
	int     timo = 100000, stat = 0;
	unsigned int a;
	int nifunit = ((struct netif *)desc->io_netif)->nif_unit;

	ler1->ler1_rap = LE_CSR0;
	if (ler1->ler1_rdp & LE_C0_ERR)
		le_error(desc->io_netif, "le_put(way before xmit)", ler1);
	tmd = &ler2->ler2_tmd[le_softc.next_tmd];
	while (tmd->tmd1_bits & LE_T1_OWN) {
		printf("le%d: output buffer busy\n", nifunit);
	}
	memcpy((void *)ler2->ler2_tbuf[le_softc.next_tmd], pkt, len);
	if (len < 64)
		tmd->tmd2 = -64;
	else
		tmd->tmd2 = -len;
	tmd->tmd3 = 0;
	if (ler1->ler1_rdp & LE_C0_ERR)
		le_error(desc->io_netif, "le_put(before xmit)", ler1);
	tmd->tmd1_bits = LE_T1_STP | LE_T1_ENP | LE_T1_OWN;
	a = (u_int)&ler2->ler2_tbuf[le_softc.next_tmd];
	tmd->tmd0 = a & LE_ADDR_LOW_MASK;
	tmd->tmd1_hadr = a >> 16;
	ler1->ler1_rdp = LE_C0_TDMD;
	if (ler1->ler1_rdp & LE_C0_ERR)
		le_error(desc->io_netif, "le_put(after xmit)", ler1);
	do {
		if (--timo == 0) {
			printf("le%d: transmit timeout, stat = 0x%x\n",
			    nifunit, stat);
			if (ler1->ler1_rdp & LE_C0_ERR)
				le_error(desc->io_netif, "le_put(timeout)",
				    ler1);
			break;
		}
		stat = ler1->ler1_rdp;
	} while ((stat & LE_C0_TINT) == 0);
	ler1->ler1_rdp = LE_C0_TINT;
	if (ler1->ler1_rdp & LE_C0_ERR) {
		if ((ler1->ler1_rdp & (LE_C0_BABL | LE_C0_CERR | LE_C0_MISS |
		    LE_C0_MERR)) !=
		    LE_C0_CERR)
			printf("le_put: xmit error, buf %d\n",
			    le_softc.next_tmd);
		le_error(desc->io_netif, "le_put(xmit error)", ler1);
	}
	le_softc.next_tmd = 0;
/*	(le_softc.next_tmd == (LETBUF - 1)) ? 0 : le_softc.next_tmd + 1;*/
	if (tmd->tmd1_bits & LE_T1_DEF)
		le_stats.deferred++;
	if (tmd->tmd1_bits & LE_T1_ONE)
		le_stats.collisions++;
	if (tmd->tmd1_bits & LE_T1_MORE)
		le_stats.collisions += 2;
	if (tmd->tmd1_bits & LE_T1_ERR) {
		printf("le%d: transmit error, error = 0x%x\n", nifunit,
		    tmd->tmd3);
		return -1;
	}
	if (le_debug) {
		printf("le%d: le_put() successful: sent %d\n",
		    nifunit, len);
		printf("le%d: le_put(): tmd1_bits: %x tmd3: %x\n",
		    nifunit,
		    (unsigned int)tmd->tmd1_bits,
		    (unsigned int)tmd->tmd3);
	}
	return len;
}
int
le_poll(struct iodesc *desc, void *pkt, int len)
{
	int unit = /*nif->nif_unit*/0;
	struct le_softc *sc = &le_softc[unit];
	int length;
	volatile struct mds *cdm;
	int stat;

#ifdef LE_DEBUG
	if (/*le_debug*/0)
		printf("le%d: le_poll called. next_rd=%d\n", unit, sc->sc_next_rd);
#endif
	stat = lerdcsr(sc, 0);
	lewrcsr(sc, 0, stat & (LE_BABL | LE_MISS | LE_MERR | LE_RINT));
	cdm = &sc->sc_rd[sc->sc_next_rd];
	if (cdm->flags & LE_OWN)
		return 0;
#ifdef LE_DEBUG
	if (le_debug) {
		printf("next_rd %d\n", sc->sc_next_rd);
		printf("cdm->flags %x\n", cdm->flags);
		printf("cdm->bcnt %x, cdm->mcnt %x\n", cdm->bcnt, cdm->mcnt);
		printf("cdm->rbuf msg %d buf %d\n", cdm->mcnt, -cdm->bcnt );
	}
#endif
	if (stat & (LE_BABL | LE_CERR | LE_MISS | LE_MERR))
		le_error(unit, "le_poll", stat);
	if (cdm->flags & (LE_FRAM | LE_OFLO | LE_CRC | LE_RBUFF)) {
		printf("le%d_poll: rmd status 0x%x\n", unit, cdm->flags);
		length = 0;
		goto cleanup;
	}
	if ((cdm->flags & (LE_STP|LE_ENP)) != (LE_STP|LE_ENP))
		panic("le_poll: chained packet");

	length = cdm->mcnt;
#ifdef LE_DEBUG
	if (le_debug)
		printf("le_poll: length %d\n", length);
#endif
	if (length >= BUFSIZE) {
		length = 0;
		panic("csr0 when bad things happen: %x", stat);
		goto cleanup;
	}
	if (!length)
		goto cleanup;
	length -= 4;

	if (length > 0) {
		/*
		 * If the length of the packet is greater than the size of the
		 * buffer, we have to truncate it, to avoid Bad Things.
		 * XXX Is this the right thing to do?
		 */
		if (length > len)
			length = len;

		memcpy(pkt, sc->sc_rbuf + (BUFSIZE * sc->sc_next_rd), length);
	}

cleanup:
	cdm->mcnt = 0;
	cdm->flags |= LE_OWN;
	if (++sc->sc_next_rd >= NRBUF)
		sc->sc_next_rd = 0;
#ifdef LE_DEBUG
	if (le_debug)
		printf("new next_rd %d\n", sc->sc_next_rd);
#endif

	return length;
}
Example #4
0
int
le_poll(struct iodesc *desc, void  *pkt, int len)
{
	struct lereg1 *ler1 = le_softc.sc_r1;
	struct lereg2 *ler2 = le_softc.sc_r2;
	unsigned int a;
	int     length;
	struct lermd *rmd;


	ler1->ler1_rap = LE_CSR0;
	if ((ler1->ler1_rdp & LE_C0_RINT) != 0)
		ler1->ler1_rdp = LE_C0_RINT;
	rmd = &ler2->ler2_rmd[le_softc.next_rmd];
	if (rmd->rmd1_bits & LE_R1_OWN) {
		return 0;
	}
	if (ler1->ler1_rdp & LE_C0_ERR)
		le_error(desc->io_netif, "le_poll", ler1);
	if (rmd->rmd1_bits & LE_R1_ERR) {
		printf("le%d_poll: rmd status 0x%x\n",
		    ((struct netif *)desc->io_netif)->nif_unit,
		    rmd->rmd1_bits);
		length = 0;
		goto cleanup;
	}
	if ((rmd->rmd1_bits & (LE_R1_STP | LE_R1_ENP)) !=
	    (LE_R1_STP | LE_R1_ENP))
		panic("le_poll: chained packet");

	length = rmd->rmd3;
	if (length >= LEMTU) {
		length = 0;
		panic("csr0 when bad things happen: %x", ler1->ler1_rdp);
		goto cleanup;
	}
	if (length == 0)
		goto cleanup;
	length -= 4;
	if (length > 0) {

		/*
	         * if buffer is smaller than the packet truncate it.
	         * (is this wise?)
	         */
		if (length > len)
			length = len;

		memcpy(pkt, (void *)&ler2->ler2_rbuf[le_softc.next_rmd],
		    length);
	}
cleanup:
	a = (u_int)&ler2->ler2_rbuf[le_softc.next_rmd];
	rmd->rmd0 = a & LE_ADDR_LOW_MASK;
	rmd->rmd1_hadr = a >> 16;
	rmd->rmd2 = -LEMTU;
	le_softc.next_rmd =
	    (le_softc.next_rmd == (LERBUF - 1)) ? 0 : (le_softc.next_rmd + 1);
	rmd->rmd1_bits = LE_R1_OWN;
	return length;
}