/* * from MAC docs: * "Note that the MAC address is stored in the registers in Hexadecimal * form. For example, to set the MAC Address to: AC-DE-48-00-00-80 * would require writing 0xAC (octet 0) to address 0x0B (high byte of * Mac_addr[15:0]), 0xDE (octet 1) to address 0x0A (Low byte of * Mac_addr[15:0]), 0x48 (octet 2) to address 0x0D (high byte of * Mac_addr[15:0]), 0x00 (octet 3) to address 0x0C (Low byte of * Mac_addr[15:0]), 0x00 (octet 4) to address 0x0F (high byte of * Mac_addr[15:0]), and 0x80 (octet 5) to address * 0x0E (Low byte of * Mac_addr[15:0]).
*/
tmp = dnet_readw_mac(bp, DNET_INTERNAL_MAC_ADDR_0_REG);
*((__be16 *)addr) = cpu_to_be16(tmp);
tmp = dnet_readw_mac(bp, DNET_INTERNAL_MAC_ADDR_1_REG);
*((__be16 *)(addr + 2)) = cpu_to_be16(tmp);
tmp = dnet_readw_mac(bp, DNET_INTERNAL_MAC_ADDR_2_REG);
*((__be16 *)(addr + 4)) = cpu_to_be16(tmp);
if (is_valid_ether_addr(addr))
eth_hw_addr_set(bp->dev, addr);
}
staticint dnet_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
{ struct dnet *bp = bus->priv;
u16 value;
while (!(dnet_readw_mac(bp, DNET_INTERNAL_GMII_MNG_CTL_REG)
& DNET_INTERNAL_GMII_MNG_CMD_FIN))
cpu_relax();
/* only 5 bits allowed for phy-addr and reg_offset */
mii_id &= 0x1f;
regnum &= 0x1f;
/* prepare reg_value for a read */
value = (mii_id << 8);
value |= regnum;
/* write control word */
dnet_writew_mac(bp, DNET_INTERNAL_GMII_MNG_CTL_REG, value);
/* wait for end of transfer */ while (!(dnet_readw_mac(bp, DNET_INTERNAL_GMII_MNG_CTL_REG)
& DNET_INTERNAL_GMII_MNG_CMD_FIN))
cpu_relax();
value = dnet_readw_mac(bp, DNET_INTERNAL_GMII_MNG_DAT_REG);
/* find the first phy */
phydev = phy_find_first(bp->mii_bus);
if (!phydev) {
printk(KERN_ERR "%s: no PHY found\n", dev->name); return -ENODEV;
}
/* TODO : add pin_irq */
/* attach the mac to the phy */ if (bp->capabilities & DNET_HAS_RMII) {
phydev = phy_connect(dev, phydev_name(phydev),
&dnet_handle_link_change,
PHY_INTERFACE_MODE_RMII);
} else {
phydev = phy_connect(dev, phydev_name(phydev),
&dnet_handle_link_change,
PHY_INTERFACE_MODE_MII);
}
if (IS_ERR(phydev)) {
printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); return PTR_ERR(phydev);
}
/* mask with MAC supported features */ if (bp->capabilities & DNET_HAS_GIGABIT)
phy_set_max_speed(phydev, SPEED_1000); else
phy_set_max_speed(phydev, SPEED_100);
phy_support_asym_pause(phydev);
bp->link = 0;
bp->speed = 0;
bp->duplex = -1;
return 0;
}
staticint dnet_mii_init(struct dnet *bp)
{ int err;
bp->mii_bus = mdiobus_alloc(); if (bp->mii_bus == NULL) return -ENOMEM;
/* For Neptune board: LINK1000 as Link LED and TX as activity LED */ staticint dnet_phy_marvell_fixup(struct phy_device *phydev)
{ return phy_write(phydev, 0x18, 0x4148);
}
/* read and clear the DNET irq (clear on read) */
int_src = dnet_readl(bp, INTR_SRC);
int_enable = dnet_readl(bp, INTR_ENB);
int_current = int_src & int_enable;
/* restart the queue if we had stopped it for TX fifo almost full */ if (int_current & DNET_INTR_SRC_TX_FIFOAE) {
int_enable = dnet_readl(bp, INTR_ENB);
int_enable &= ~DNET_INTR_ENB_TX_FIFOAE;
dnet_writel(bp, int_enable, INTR_ENB);
netif_wake_queue(dev);
handled = 1;
}
/* RX FIFO error checking */ if (int_current &
(DNET_INTR_SRC_RX_CMDFIFOFF | DNET_INTR_SRC_RX_DATAFIFOFF)) {
printk(KERN_ERR "%s: RX fifo error %x, irq %x\n", __func__,
dnet_readl(bp, RX_STATUS), int_current); /* we can only flush the RX FIFOs */
dnet_writel(bp, DNET_SYS_CTL_RXFIFOFLUSH, SYS_CTL);
ndelay(500);
dnet_writel(bp, 0, SYS_CTL);
handled = 1;
}
/* TX FIFO error checking */ if (int_current &
(DNET_INTR_SRC_TX_FIFOFULL | DNET_INTR_SRC_TX_DISCFRM)) {
printk(KERN_ERR "%s: TX fifo error %x, irq %x\n", __func__,
dnet_readl(bp, TX_STATUS), int_current); /* we can only flush the TX FIFOs */
dnet_writel(bp, DNET_SYS_CTL_TXFIFOFLUSH, SYS_CTL);
ndelay(500);
dnet_writel(bp, 0, SYS_CTL);
handled = 1;
}
if (int_current & DNET_INTR_SRC_RX_CMDFIFOAF) { if (napi_schedule_prep(&bp->napi)) { /* * There's no point taking any more interrupts * until we have processed the buffers
*/ /* Disable Rx interrupts and schedule NAPI poll */
int_enable = dnet_readl(bp, INTR_ENB);
int_enable &= ~DNET_INTR_SRC_RX_CMDFIFOAF;
dnet_writel(bp, int_enable, INTR_ENB);
__napi_schedule(&bp->napi);
}
handled = 1;
}
if (!handled)
pr_debug("%s: irq %x remains\n", __func__, int_current);
spin_unlock_irqrestore(&bp->lock, flags);
return IRQ_RETVAL(handled);
}
#ifdef DEBUG staticinlinevoid dnet_print_skb(struct sk_buff *skb)
{ int k;
printk(KERN_DEBUG PFX "data:"); for (k = 0; k < skb->len; k++)
printk(" %02x", (unsignedint)skb->data[k]);
printk("\n");
} #else #define dnet_print_skb(skb) do {} while (0) #endif
/* check if there is enough room for the current frame */ if (wrsz < (DNET_FIFO_SIZE - dnet_readl(bp, TX_FIFO_WCNT))) { for (i = 0; i < wrsz; i++)
dnet_writel(bp, *bufp++, TX_DATA_FIFO);
/* * inform MAC that a packet's written and ready to be * shipped out
*/
dnet_writel(bp, tx_cmd, TX_LEN_FIFO);
}
staticvoid dnet_reset_hw(struct dnet *bp)
{ /* put ts_mac in IDLE state i.e. disable rx/tx */
dnet_writew_mac(bp, DNET_INTERNAL_MODE_REG, DNET_INTERNAL_MODE_FCEN);
/* * RX FIFO almost full threshold: only cmd FIFO almost full is * implemented for RX side
*/
dnet_writel(bp, DNET_FIFO_RX_CMD_AF_TH, RX_FIFO_TH); /* * TX FIFO almost empty threshold: only data FIFO almost empty * is implemented for TX side
*/
dnet_writel(bp, DNET_FIFO_TX_DATA_AE_TH, TX_FIFO_TH);
if (!is_valid_ether_addr(dev->dev_addr)) { /* choose a random ethernet address */
eth_hw_addr_random(dev);
__dnet_set_hwaddr(bp);
}
err = register_netdev(dev); if (err) {
dev_err(&pdev->dev, "Cannot register net device, aborting.\n"); goto err_out_free_irq;
}
/* register the PHY board fixup (for Marvell 88E1111) */
err = phy_register_fixup_for_uid(0x01410cc0, 0xfffffff0,
dnet_phy_marvell_fixup); /* we can live without it, so just issue a warning */ if (err)
dev_warn(&pdev->dev, "Cannot register PHY board fixup.\n");
err = dnet_mii_init(bp); if (err) goto err_out_unregister_netdev;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.