Exemplo n.º 1
0
void
le_reset(int unit, u_char *myea)
{
	struct le_softc *sc = &le_softc[unit];
	u_long a;
	int timo = 100000;

#ifdef LE_DEBUG
	if (le_debug) {
		printf("le%d: le_reset called\n", unit);
		printf("     r0=%x, r1=%x, mem=%x, addr=%x:%x:%x:%x:%x:%x\n",
		       sc->sc_r0, sc->sc_r1, sc->sc_mem,
		       sc->sc_addr[0], sc->sc_addr[1], sc->sc_addr[2],
		       sc->sc_addr[3], sc->sc_addr[4], sc->sc_addr[5]);
	}
#endif
	lewrcsr(sc, 0, LE_STOP);
	for (timo = 1000; timo; timo--);

	sc->sc_next_rd = sc->sc_next_td = 0;

	/* Set up LANCE init block. */
	lememinit(sc);

	if (myea)
		bcopy(sc->sc_addr, myea, ETHER_ADDR_LEN);

	/* Turn on byte swapping. */
	lewrcsr(sc, 3, LE_BSWP);

	/* Give LANCE the physical address of its init block. */
	a = LANCE_ADDR(sc, sc->sc_init);
	lewrcsr(sc, 1, a);
	lewrcsr(sc, 2, (a >> 16) & 0xff);

#ifdef LE_DEBUG
	if (le_debug)
		printf("le%d: before init\n", unit);
#endif

	/* Try to initialize the LANCE. */
	lewrcsr(sc, 0, LE_INIT);

	/* Wait for initialization to finish. */
	for (timo = 100000; timo; timo--)
		if (lerdcsr(sc, 0) & LE_IDON)
			break;

	if (lerdcsr(sc, 0) & LE_IDON) {
		/* Start the LANCE. */
		lewrcsr(sc, 0, LE_INEA | LE_STRT | LE_IDON);
	} else
		printf("le%d: card failed to initialize\n", unit);

#ifdef LE_DEBUG
	if (le_debug)
		printf("le%d: after init\n", unit);
#endif
}
Exemplo n.º 2
0
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;
}
Exemplo n.º 3
0
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;
}