+#if (DEBUG & DBG_TX_RING_DUMP)
+/*! dump the tx ring to syslog */
+STATIC void
+dump_tx_ring(struct r6040_private *lp)
+{
+ int i;
+ struct r6040_descriptor *ptr;
+
+ printk(KERN_INFO "%s: nr_desc x%x tx_ring %p tx_ring_dma %08x "
+ "tx_insert %p tx_remove %p\n",
+ DRV_NAME, TX_DCNT, lp->tx_ring, lp->tx_ring_dma,
+ lp->tx_insert_ptr, lp->tx_remove_ptr);
+
+ if (lp->tx_ring) {
+ for(i=0, ptr=lp->tx_ring; i < TX_DCNT; i++, ptr++) {
+ printk(KERN_INFO "%s: %d. descr: status x%x len x%x "
+ "ndesc %08x vbufp %p vndescp %p skb_ptr %p\n",
+ DRV_NAME, i, ptr->status, ptr->len,
+ ptr->ndesc, ptr->vbufp, ptr->vndescp, ptr->skb_ptr);
+ }
+ }
+}
+#endif /* #if (DEBUG & DBG_TX_RING_DUMP) */
+
+void r6040_init_txbufs(struct net_device *dev)
+{
+ struct r6040_private *lp = netdev_priv(dev);
+
+ lp->tx_free_desc = TX_DCNT;
+
+ lp->tx_remove_ptr = lp->tx_insert_ptr = lp->tx_ring;
+ r6040_init_ring_desc(lp->tx_ring, lp->tx_ring_dma, TX_DCNT);
+
+#if (DEBUG & DBG_TX_RING_DUMP)
+ if (debug & DBG_TX_RING_DUMP) {
+ dump_tx_ring(lp);
+ }
+#endif
+}
+
+#if (DEBUG & DBG_RX_RING_DUMP)
+/*! dump the rx ring to syslog */
+STATIC void
+dump_rx_ring(struct r6040_private *lp)
+{
+ int i;
+ struct r6040_descriptor *ptr;
+
+ printk(KERN_INFO "%s: nr_desc x%x rx_ring %p rx_ring_dma %08x "
+ "rx_insert %p rx_remove %p\n",
+ DRV_NAME, RX_DCNT, lp->rx_ring, lp->rx_ring_dma,
+ lp->rx_insert_ptr, lp->rx_remove_ptr);
+
+ if (lp->rx_ring) {
+ for(i=0, ptr=lp->rx_ring; i < RX_DCNT; i++, ptr++) {
+ printk(KERN_INFO "%s: %d. descr: status x%x len x%x "
+ "ndesc %08x vbufp %p vndescp %p skb_ptr %p\n",
+ DRV_NAME, i, ptr->status, ptr->len,
+ ptr->ndesc, ptr->vbufp, ptr->vndescp, ptr->skb_ptr);
+ }
+ }
+}
+#endif /* #if (DEBUG & DBG_TX_RING_DUMP) */
+
+int r6040_alloc_rxbufs(struct net_device *dev)
+{
+ struct r6040_private *lp = netdev_priv(dev);
+ struct r6040_descriptor *desc;
+ struct sk_buff *skb;
+ int rc;
+
+ lp->rx_remove_ptr = lp->rx_insert_ptr = lp->rx_ring;
+ r6040_init_ring_desc(lp->rx_ring, lp->rx_ring_dma, RX_DCNT);
+
+ /* alloc skbs for the rx descriptors */
+ desc = lp->rx_ring;
+ do {
+ if (!(skb=netdev_alloc_skb(dev, MAX_BUF_SIZE))) {
+ err("failed to alloc skb for rx\n");
+ rc = -ENOMEM;
+ goto err_exit;
+ }
+ desc->skb_ptr = skb;
+ desc->buf = cpu_to_le32(pci_map_single(lp->pdev,
+ desc->skb_ptr->data,
+ MAX_BUF_SIZE, PCI_DMA_FROMDEVICE));
+ desc->status = DESC_STATUS_OWNER_MAC;
+ desc = desc->vndescp;
+ } while (desc != lp->rx_ring);
+
+#if (DEBUG & DBG_RX_RING_DUMP)
+ if (debug & DBG_RX_RING_DUMP) {
+ dump_rx_ring(lp);
+ }
+#endif
+
+ return 0;
+
+err_exit:
+ /* dealloc all previously allocated skb */
+ r6040_free_rxbufs(dev);
+ return rc;
+}
+
+/*! reset MAC and set all registers */
+void r6040_init_mac_regs(struct r6040_private *lp)
+{
+ void __iomem *ioaddr = lp->base;
+ int limit;
+ char obuf[3*ETH_ALEN] __attribute__ ((unused));
+
+ /* Mask Off Interrupt */
+ iowrite16(MSK_INT, ioaddr + MIER);
+
+ /* reset MAC */
+ iowrite16(MAC_RST, ioaddr + MCR1);
+ udelay(100);
+ limit=2048;
+ while ((ioread16(ioaddr + MCR1) & MAC_RST) && limit-- > 0);
+
+ /* Reset internal state machine */
+ iowrite16(2, ioaddr + MAC_SM);
+ iowrite16(0, ioaddr + MAC_SM);
+ udelay(5000);
+
+ /* Restore MAC Addresses */
+ r6040_multicast_list(lp->dev);
+
+ /* TODO: restore multcast and hash table */
+
+ /* MAC Bus Control Register */
+ iowrite16(MBCR_DEFAULT, ioaddr + MBCR);
+
+ /* Buffer Size Register */
+ iowrite16(MAX_BUF_SIZE, ioaddr + MR_BSR);
+
+ /* write tx ring start address */
+ iowrite16(lp->tx_ring_dma, ioaddr + MTD_SA0);
+ iowrite16(lp->tx_ring_dma >> 16, ioaddr + MTD_SA1);
+
+ /* write rx ring start address */
+ iowrite16(lp->rx_ring_dma, ioaddr + MRD_SA0);
+ iowrite16(lp->rx_ring_dma >> 16, ioaddr + MRD_SA1);
+
+ /* set interrupt waiting time and packet numbers */
+ iowrite16(0, ioaddr + MT_ICR);
+ iowrite16(0, ioaddr + MR_ICR);
+
+ /* enable interrupts */
+ iowrite16(INT_MASK, ioaddr + MIER);
+
+ /* enable tx and rx */
+ iowrite16(lp->mcr0 | 0x0002, ioaddr);
+
+ /* let TX poll the descriptors - we may got called by r6040_tx_timeout which has left
+ some unsent tx buffers */
+ iowrite16(0x01, ioaddr + MTPR);
+}
+
+void r6040_tx_timeout(struct net_device *dev)
+{
+ struct r6040_private *priv = netdev_priv(dev);
+ void __iomem *ioaddr = priv->base;
+
+ /* we read MISR, which clears on read (i.e. we may loose an RX interupt,
+ but this is an error anyhow ... */
+ printk(KERN_WARNING "%s: transmit timed out, int enable %4.4x "
+ "status %4.4x, PHY status %4.4x\n",
+ dev->name, ioread16(ioaddr + MIER),
+ ioread16(ioaddr + MISR),
+ mdio_read(dev, priv->mii_if.phy_id, MII_BMSR));