Esempio n. 1
0
File: hnddma.c Progetto: ariavie/bcm
void
dma_rxinit(dma_info_t *di)
{
	DMA_TRACE(("%s: dma_rxinit\n", di->name));

	di->rxin = di->rxout = 0;

	/* clear rx descriptor ring */
	BZERO_SM((void*)di->rxd, (di->nrxd * sizeof (dmadd_t)));

	dma_rxenable(di);
	W_REG(&di->regs->rcvaddr, ((uint32)di->rxdpa + di->ddoffset));
}
Esempio n. 2
0
/*
 * Initialize all the chip registers.  If dma mode, init tx and rx dma engines
 * but leave the devcontrol tx and rx (fifos) disabled.
 */
static void
chipinit(struct bcm4xxx *ch, uint options)
{
	etc_info_t *etc;
	bcmenetregs_t *regs;
	uint idx;
	uint i;

	regs = ch->regs;
	etc = ch->etc;
	idx = 0;

	ET_TRACE(("et%d: chipinit\n", etc->unit));

	/* enable crc32 generation */
	OR_REG(ch->osh, &regs->emaccontrol, EMC_CG);

	/* enable one rx interrupt per received frame */
	W_REG(ch->osh, &regs->intrecvlazy, (1 << IRL_FC_SHIFT));

	/* enable 802.3x tx flow control (honor received PAUSE frames) */
	W_REG(ch->osh, &regs->rxconfig, ERC_FE | ERC_UF);

	/* initialize CAM */
	if (etc->promisc || (R_REG(ch->osh, &regs->rxconfig) & ERC_CA))
		OR_REG(ch->osh, &regs->rxconfig, ERC_PE);
	else {
		/* our local address */
		chipwrcam(ch, &etc->cur_etheraddr, idx++);

		/* allmulti or a list of discrete multicast addresses */
		if (etc->allmulti)
			OR_REG(ch->osh, &regs->rxconfig, ERC_AM);
		else if (etc->nmulticast) {
			for (i = 0; i < etc->nmulticast; i++)
				chipwrcam(ch, &etc->multicast[i], idx++);
		}

		/* enable cam */
		OR_REG(ch->osh, &regs->camcontrol, CC_CE);
	}

	/* optionally enable mac-level loopback */
	if (etc->loopbk)
		OR_REG(ch->osh, &regs->rxconfig, ERC_LE);

	/* set max frame lengths - account for possible vlan tag */
	W_REG(ch->osh, &regs->rxmaxlength, ETHER_MAX_LEN + 32);
	W_REG(ch->osh, &regs->txmaxlength, ETHER_MAX_LEN + 32);

	/* set tx watermark */
	W_REG(ch->osh, &regs->txwatermark, 56);

	/*
	 * Optionally, disable phy autonegotiation and force our speed/duplex
	 * or constrain our advertised capabilities.
	 */
	if (etc->forcespeed != ET_AUTO)
		chipphyforce(ch, etc->phyaddr);
	else if (etc->advertise && etc->needautoneg)
		chipphyadvertise(ch, etc->phyaddr);

	if (options & ET_INIT_FULL) {
		/* initialize the tx and rx dma channels */
		dma_txinit(ch->di);
		dma_rxinit(ch->di);

		/* post dma receive buffers */
		dma_rxfill(ch->di);

		/* lastly, enable interrupts */
		if (options & ET_INIT_INTRON)
			et_intrson(etc->et);
	}
	else
		dma_rxenable(ch->di);

	/* turn on the emac */
	OR_REG(ch->osh, &regs->enetcontrol, EC_EE);
}