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)); }
/* * 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, ®s->emaccontrol, EMC_CG); /* enable one rx interrupt per received frame */ W_REG(ch->osh, ®s->intrecvlazy, (1 << IRL_FC_SHIFT)); /* enable 802.3x tx flow control (honor received PAUSE frames) */ W_REG(ch->osh, ®s->rxconfig, ERC_FE | ERC_UF); /* initialize CAM */ if (etc->promisc || (R_REG(ch->osh, ®s->rxconfig) & ERC_CA)) OR_REG(ch->osh, ®s->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, ®s->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, ®s->camcontrol, CC_CE); } /* optionally enable mac-level loopback */ if (etc->loopbk) OR_REG(ch->osh, ®s->rxconfig, ERC_LE); /* set max frame lengths - account for possible vlan tag */ W_REG(ch->osh, ®s->rxmaxlength, ETHER_MAX_LEN + 32); W_REG(ch->osh, ®s->txmaxlength, ETHER_MAX_LEN + 32); /* set tx watermark */ W_REG(ch->osh, ®s->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, ®s->enetcontrol, EC_EE); }