Esempio n. 1
0
File: if_sq.c Progetto: MarginC/kame
/* Set up data to get the interface up and running. */
int
sq_init(struct ifnet *ifp)
{
	int i;
	u_int32_t reg;
	struct sq_softc *sc = ifp->if_softc;

	/* Cancel any in-progress I/O */
	sq_stop(ifp, 0);

	sc->sc_nextrx = 0;

	sc->sc_nfreetx = SQ_NTXDESC;
	sc->sc_nexttx = sc->sc_prevtx = 0;

	SQ_TRACE(SQ_RESET, 0, 0, sc->sc_nfreetx);

	/* Set into 8003 mode, bank 0 to program ethernet address */
	bus_space_write_1(sc->sc_regt, sc->sc_regh, SEEQ_TXCMD, TXCMD_BANK0);

	/* Now write the address */
	for (i = 0; i < ETHER_ADDR_LEN; i++)
		bus_space_write_1(sc->sc_regt, sc->sc_regh, i,
		    sc->sc_enaddr[i]);

	sc->sc_rxcmd = RXCMD_IE_CRC |
		       RXCMD_IE_DRIB |
		       RXCMD_IE_SHORT |
		       RXCMD_IE_END |
		       RXCMD_IE_GOOD;

	/*
	 * Set the receive filter -- this will add some bits to the
	 * prototype RXCMD register.  Do this before setting the
	 * transmit config register, since we might need to switch
	 * banks.
	 */
	sq_set_filter(sc);

	/* Set up Seeq transmit command register */
	bus_space_write_1(sc->sc_regt, sc->sc_regh, SEEQ_TXCMD,
						    TXCMD_IE_UFLOW |
						    TXCMD_IE_COLL |
						    TXCMD_IE_16COLL |
						    TXCMD_IE_GOOD);

	/* Now write the receive command register. */
	bus_space_write_1(sc->sc_regt, sc->sc_regh, SEEQ_RXCMD, sc->sc_rxcmd);

	/* Set up HPC ethernet DMA config */
	reg = bus_space_read_4(sc->sc_hpct, sc->sc_hpch, HPC_ENETR_DMACFG);
	bus_space_write_4(sc->sc_hpct, sc->sc_hpch, HPC_ENETR_DMACFG,
			    	reg | ENETR_DMACFG_FIX_RXDC |
				ENETR_DMACFG_FIX_INTR |
				ENETR_DMACFG_FIX_EOP);

	/* Pass the start of the receive ring to the HPC */
	bus_space_write_4(sc->sc_hpct, sc->sc_hpch, HPC_ENETR_NDBP,
						    SQ_CDRXADDR(sc, 0));

	/* And turn on the HPC ethernet receive channel */
	bus_space_write_4(sc->sc_hpct, sc->sc_hpch, HPC_ENETR_CTL,
						    ENETR_CTL_ACTIVE);

	ifp->if_flags |= IFF_RUNNING;
	ifp->if_flags &= ~IFF_OACTIVE;

	return 0;
}
Esempio n. 2
0
File: if_sq.c Progetto: MarginC/kame
static int
sq_rxintr(struct sq_softc *sc)
{
	int count = 0;
	struct mbuf* m;
	int i, framelen;
	u_int8_t pktstat;
	u_int32_t status;
	int new_end, orig_end;
	struct ifnet *ifp = &sc->sc_ethercom.ec_if;

	for(i = sc->sc_nextrx;; i = SQ_NEXTRX(i)) {
		SQ_CDRXSYNC(sc, i, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);

		/* If this is a CPU-owned buffer, we're at the end of the list */
		if (sc->sc_rxdesc[i].hdd_ctl & HDD_CTL_OWN) {
#if 0
			u_int32_t reg;

			reg = bus_space_read_4(sc->sc_hpct, sc->sc_hpch,
			    HPC_ENETR_CTL);
			printf("%s: rxintr: done at %d (ctl %08x)\n",
			    sc->sc_dev.dv_xname, i, reg);
#endif
			break;
		}

		count++;

		m = sc->sc_rxmbuf[i];
		framelen = m->m_ext.ext_size -
		    HDD_CTL_BYTECNT(sc->sc_rxdesc[i].hdd_ctl) - 3;

		/* Now sync the actual packet data */
		bus_dmamap_sync(sc->sc_dmat, sc->sc_rxmap[i], 0,
		    sc->sc_rxmap[i]->dm_mapsize, BUS_DMASYNC_POSTREAD);

		pktstat = *((u_int8_t*)m->m_data + framelen + 2);

		if ((pktstat & RXSTAT_GOOD) == 0) {
			ifp->if_ierrors++;

			if (pktstat & RXSTAT_OFLOW)
				printf("%s: receive FIFO overflow\n",
				    sc->sc_dev.dv_xname);

			bus_dmamap_sync(sc->sc_dmat, sc->sc_rxmap[i], 0,
			    sc->sc_rxmap[i]->dm_mapsize,
			    BUS_DMASYNC_PREREAD);
			SQ_INIT_RXDESC(sc, i);
			continue;
		}

		if (sq_add_rxbuf(sc, i) != 0) {
			ifp->if_ierrors++;
			bus_dmamap_sync(sc->sc_dmat, sc->sc_rxmap[i], 0,
			    sc->sc_rxmap[i]->dm_mapsize,
			    BUS_DMASYNC_PREREAD);
			SQ_INIT_RXDESC(sc, i);
			continue;
		}


		m->m_data += 2;
		m->m_pkthdr.rcvif = ifp;
		m->m_pkthdr.len = m->m_len = framelen;

		ifp->if_ipackets++;

#if 0
		printf("%s: sq_rxintr: buf %d len %d\n", sc->sc_dev.dv_xname,
		    i, framelen);
#endif

#if NBPFILTER > 0
		if (ifp->if_bpf)
			bpf_mtap(ifp->if_bpf, m);
#endif
		(*ifp->if_input)(ifp, m);
	}


	/* If anything happened, move ring start/end pointers to new spot */
	if (i != sc->sc_nextrx) {
		new_end = SQ_PREVRX(i);
		sc->sc_rxdesc[new_end].hdd_ctl |= HDD_CTL_EOCHAIN;
		SQ_CDRXSYNC(sc, new_end, BUS_DMASYNC_PREREAD |
		    BUS_DMASYNC_PREWRITE);

		orig_end = SQ_PREVRX(sc->sc_nextrx);
		sc->sc_rxdesc[orig_end].hdd_ctl &= ~HDD_CTL_EOCHAIN;
		SQ_CDRXSYNC(sc, orig_end, BUS_DMASYNC_PREREAD |
		    BUS_DMASYNC_PREWRITE);

		sc->sc_nextrx = i;
	}

	status = bus_space_read_4(sc->sc_hpct, sc->sc_hpch, HPC_ENETR_CTL);

	/* If receive channel is stopped, restart it... */
	if ((status & ENETR_CTL_ACTIVE) == 0) {
		/* Pass the start of the receive ring to the HPC */
		bus_space_write_4(sc->sc_hpct, sc->sc_hpch,
		    HPC_ENETR_NDBP, SQ_CDRXADDR(sc, sc->sc_nextrx));

		/* And turn on the HPC ethernet receive channel */
		bus_space_write_4(sc->sc_hpct, sc->sc_hpch, HPC_ENETR_CTL,
		    ENETR_CTL_ACTIVE);
	}

	return count;
}
Esempio n. 3
0
/* Set up data to get the interface up and running. */
int
sq_init(struct ifnet *ifp)
{
	int i;
	struct sq_softc *sc = ifp->if_softc;

	/* Cancel any in-progress I/O */
	sq_stop(ifp, 0);

	sc->sc_nextrx = 0;

	sc->sc_nfreetx = SQ_NTXDESC;
	sc->sc_nexttx = sc->sc_prevtx = 0;

	SQ_TRACE(SQ_RESET, sc, 0, 0);

	/* Set into 8003 mode, bank 0 to program ethernet address */
	sq_seeq_write(sc, SEEQ_TXCMD, TXCMD_BANK0);

	/* Now write the address */
	for (i = 0; i < ETHER_ADDR_LEN; i++)
		sq_seeq_write(sc, i, sc->sc_enaddr[i]);

	sc->sc_rxcmd =
	    RXCMD_IE_CRC |
	    RXCMD_IE_DRIB |
	    RXCMD_IE_SHORT |
	    RXCMD_IE_END |
	    RXCMD_IE_GOOD;

	/*
	 * Set the receive filter -- this will add some bits to the
	 * prototype RXCMD register.  Do this before setting the
	 * transmit config register, since we might need to switch
	 * banks.
	 */
	sq_set_filter(sc);

	/* Set up Seeq transmit command register */
	sq_seeq_write(sc, SEEQ_TXCMD,
	    TXCMD_IE_UFLOW |
	    TXCMD_IE_COLL |
	    TXCMD_IE_16COLL |
	    TXCMD_IE_GOOD);

	/* Now write the receive command register. */
	sq_seeq_write(sc, SEEQ_RXCMD, sc->sc_rxcmd);

	/*
	 * Set up HPC ethernet PIO and DMA configurations.
	 *
	 * The PROM appears to do most of this for the onboard HPC3, but
	 * not for the Challenge S's IOPLUS chip. We copy how the onboard
	 * chip is configured and assume that it's correct for both.
	 */
	if (sc->hpc_regs->revision == 3) {
		uint32_t dmareg, pioreg;

		pioreg =
		    HPC3_ENETR_PIOCFG_P1(1) |
		    HPC3_ENETR_PIOCFG_P2(6) |
		    HPC3_ENETR_PIOCFG_P3(1);

		dmareg =
		    HPC3_ENETR_DMACFG_D1(6) |
		    HPC3_ENETR_DMACFG_D2(2) |
		    HPC3_ENETR_DMACFG_D3(0) |
		    HPC3_ENETR_DMACFG_FIX_RXDC |
		    HPC3_ENETR_DMACFG_FIX_INTR |
		    HPC3_ENETR_DMACFG_FIX_EOP |
		    HPC3_ENETR_DMACFG_TIMEOUT;

		sq_hpc_write(sc, HPC3_ENETR_PIOCFG, pioreg);
		sq_hpc_write(sc, HPC3_ENETR_DMACFG, dmareg);
	}

	/* Pass the start of the receive ring to the HPC */
	sq_hpc_write(sc, sc->hpc_regs->enetr_ndbp, SQ_CDRXADDR(sc, 0));

	/* And turn on the HPC ethernet receive channel */
	sq_hpc_write(sc, sc->hpc_regs->enetr_ctl,
	    sc->hpc_regs->enetr_ctl_active);

	/*
	 * Turn off delayed receive interrupts on HPC1.
	 * (see Hollywood HPC Specification 2.1.4.3)
	 */
	if (sc->hpc_regs->revision != 3)
		sq_hpc_write(sc, HPC1_ENET_INTDELAY, HPC1_ENET_INTDELAY_OFF);

	ifp->if_flags |= IFF_RUNNING;
	ifp->if_flags &= ~IFF_OACTIVE;

	return 0;
}