* David S. Miller (davem@redhat.com)
* 2.01:
* 11/08/01: Use library crc32 functions (Matt_Domsch@dell.com)
- *
+ *
*/
#undef DEBUG_DRIVER
static char lancestr[] = "LANCE";
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
s16 length; /* Length is 2s complement (negative)! */
u16 misc;
};
-
+
/* The LANCE initialization block, described in databook. */
/* On the Sparc, this block should be on a DMA region */
struct lance_init_block {
u16 rx_len; /* receive len and high addr */
u16 tx_ptr; /* transmit descriptor addr */
u16 tx_len; /* transmit len and high addr */
-
+
/* The Tx and Rx ring entries must aligned on 8-byte boundaries. */
struct lance_rx_desc brx_ring[RX_RING_SIZE];
struct lance_tx_desc btx_ring[TX_RING_SIZE];
-
+
u8 tx_buf [TX_RING_SIZE][TX_BUFF_SIZE];
u8 pad[2]; /* align rx_buf for copy_and_sum(). */
u8 rx_buf [RX_RING_SIZE][RX_BUFF_SIZE];
void __iomem *dregs; /* DMA controller regs. */
struct lance_init_block __iomem *init_block_iomem;
struct lance_init_block *init_block_mem;
-
+
spinlock_t lock;
int rx_new, tx_new;
int rx_old, tx_old;
-
+
struct net_device_stats stats;
struct sbus_dma *ledma; /* If set this points to ledma */
char tpe; /* cable-selection is TPE */
dma_addr_t aib = lp->init_block_dvma;
__u32 leptr;
int i;
-
+
/* Lock out other processes while setting up hardware */
netif_stop_queue(dev);
lp->rx_new = lp->tx_new = 0;
}
/* Setup the initialization block */
-
+
/* Setup rx descriptor pointer */
leptr = LANCE_ADDR(aib + libdesc_offset(brx_ring, 0));
ib->rx_len = (LANCE_LOG_RX_BUFFERS << 13) | (leptr >> 16);
ib->rx_ptr = leptr;
-
+
/* Setup tx descriptor pointer */
leptr = LANCE_ADDR(aib + libdesc_offset(btx_ring, 0));
ib->tx_len = (LANCE_LOG_TX_BUFFERS << 13) | (leptr >> 16);
struct lance_init_block __iomem *ib = lp->init_block_iomem;
u32 leptr;
int i;
-
+
/* Lock out other processes while setting up hardware */
netif_stop_queue(dev);
lp->rx_new = lp->tx_new = 0;
}
/* Setup the initialization block */
-
+
/* Setup rx descriptor pointer */
leptr = libdesc_offset(brx_ring, 0);
sbus_writew((LANCE_LOG_RX_BUFFERS << 13) | (leptr >> 16),
&ib->rx_len);
sbus_writew(leptr, &ib->rx_ptr);
-
+
/* Setup tx descriptor pointer */
leptr = libdesc_offset(btx_ring, 0);
sbus_writew((LANCE_LOG_TX_BUFFERS << 13) | (leptr >> 16),
lp->rx_new = RX_NEXT(entry);
return;
}
-
+
lp->stats.rx_bytes += len;
skb->dev = dev;
/* If we hit a packet not owned by us, stop */
if (bits & LE_T1_OWN)
break;
-
+
if (bits & LE_T1_ERR) {
u16 status = td->misc;
-
+
lp->stats.tx_errors++;
if (status & LE_T3_RTY) lp->stats.tx_aborted_errors++;
if (status & LE_T3_LCOL) lp->stats.tx_window_errors++;
lp->stats.tx_packets++;
}
-
+
j = TX_NEXT(j);
}
lp->tx_old = j;
lp->rx_new = RX_NEXT(entry);
return;
}
-
+
lp->stats.rx_bytes += len;
skb->dev = dev;
/* If we hit a packet not owned by us, stop */
if (bits & LE_T1_OWN)
break;
-
+
if (bits & LE_T1_ERR) {
u16 status = sbus_readw(&td->misc);
-
+
lp->stats.tx_errors++;
if (status & LE_T3_RTY) lp->stats.tx_aborted_errors++;
if (status & LE_T3_LCOL) lp->stats.tx_window_errors++;
lp->stats.tx_packets++;
}
-
+
j = TX_NEXT(j);
}
lp->tx_old = j;
struct net_device *dev = (struct net_device *)dev_id;
struct lance_private *lp = netdev_priv(dev);
int csr0;
-
+
sbus_writew(LE_CSR0, lp->lregs + RAP);
csr0 = sbus_readw(lp->lregs + RDP);
/* Acknowledge all the interrupt sources ASAP */
sbus_writew(csr0 & (LE_C0_INTR | LE_C0_TINT | LE_C0_RINT),
lp->lregs + RDP);
-
+
if ((csr0 & LE_C0_ERR) != 0) {
/* Clear the error condition */
sbus_writew((LE_C0_BABL | LE_C0_ERR | LE_C0_MISS |
LE_C0_CERR | LE_C0_MERR),
lp->lregs + RDP);
}
-
+
if (csr0 & LE_C0_RINT)
lp->rx(dev);
-
+
if (csr0 & LE_C0_TINT)
lp->tx(dev);
-
+
if (csr0 & LE_C0_BABL)
lp->stats.tx_errors++;
STOP_LANCE(lp);
- if (request_irq(dev->irq, &lance_interrupt, SA_SHIRQ,
+ if (request_irq(dev->irq, &lance_interrupt, IRQF_SHARED,
lancestr, (void *) dev)) {
printk(KERN_ERR "Lance: Can't get irq %d\n", dev->irq);
return -EAGAIN;
{
struct lance_private *lp = netdev_priv(dev);
int status;
-
+
STOP_LANCE(lp);
/* On the 4m, reset the dma too */
dev->trans_start = jiffies;
dev_kfree_skb(skb);
-
+
return 0;
}
int i;
u32 crc;
u32 val;
-
+
/* set all multicast bits */
if (dev->flags & IFF_ALLMULTI)
val = ~0;
if (dev->flags & IFF_ALLMULTI)
return;
-
+
/* Add addresses */
for (i = 0; i < dev->mc_count; i++) {
addrs = dmi->dmi_addr;
return 1;
}
-static struct ethtool_ops sparc_lance_ethtool_ops = {
+static const struct ethtool_ops sparc_lance_ethtool_ops = {
.get_drvinfo = sparc_lance_get_drvinfo,
.get_link = sparc_lance_get_link,
};
-static int __init sparc_lance_probe_one(struct sbus_dev *sdev,
- struct sbus_dma *ledma,
- struct sbus_dev *lebuffer)
+static int __devinit sparc_lance_probe_one(struct sbus_dev *sdev,
+ struct sbus_dma *ledma,
+ struct sbus_dev *lebuffer)
{
static unsigned version_printed;
struct net_device *dev;
}
/* On 4m, find the associated dma for the lance chip */
-static inline struct sbus_dma *find_ledma(struct sbus_dev *sdev)
+static struct sbus_dma * __devinit find_ledma(struct sbus_dev *sdev)
{
struct sbus_dma *p;
/* Find all the lance cards on the system and initialize them */
static struct sbus_dev sun4_sdev;
-static int __init sparc_lance_init(void)
+static int __devinit sparc_lance_init(void)
{
if ((idprom->id_machtype == (SM_SUN4|SM_4_330)) ||
(idprom->id_machtype == (SM_SUN4|SM_4_470))) {
- memset(&sun4_sdev, 0, sizeof(sdev));
+ memset(&sun4_sdev, 0, sizeof(struct sbus_dev));
sun4_sdev.reg_addrs[0].phys_addr = sun4_eth_physaddr;
sun4_sdev.irqs[0] = 6;
return sparc_lance_probe_one(&sun4_sdev, NULL, NULL);
static int __exit sunlance_sun4_remove(void)
{
- struct lance_private *lp = dev_get_drvdata(&sun4_sdev->dev);
+ struct lance_private *lp = dev_get_drvdata(&sun4_sdev.ofdev.dev);
struct net_device *net_dev = lp->dev;
unregister_netdevice(net_dev);
- lance_free_hwresources(root_lance_dev);
+ lance_free_hwresources(lp);
free_netdev(net_dev);
- dev_set_drvdata(&sun4_sdev->dev, NULL);
+ dev_set_drvdata(&sun4_sdev.ofdev.dev, NULL);
return 0;
}
static int __devinit sunlance_sbus_probe(struct of_device *dev, const struct of_device_id *match)
{
struct sbus_dev *sdev = to_sbus_device(&dev->dev);
- struct device_node *dp = dev->node;
int err;
- if (!strcmp(dp->name, "le")) {
- err = sparc_lance_probe_one(sdev, NULL, NULL);
- } else if (!strcmp(dp->name, "ledma")) {
- struct sbus_dma *ledma = find_ledma(sdev);
+ if (sdev->parent) {
+ struct of_device *parent = &sdev->parent->ofdev;
- err = sparc_lance_probe_one(sdev->child, ledma, NULL);
- } else {
- BUG_ON(strcmp(dp->name, "lebuffer"));
+ if (!strcmp(parent->node->name, "ledma")) {
+ struct sbus_dma *ledma = find_ledma(to_sbus_device(&parent->dev));
- err = sparc_lance_probe_one(sdev->child, NULL, sdev);
- }
+ err = sparc_lance_probe_one(sdev, ledma, NULL);
+ } else if (!strcmp(parent->node->name, "lebuffer")) {
+ err = sparc_lance_probe_one(sdev, NULL, to_sbus_device(&parent->dev));
+ } else
+ err = sparc_lance_probe_one(sdev, NULL, NULL);
+ } else
+ err = sparc_lance_probe_one(sdev, NULL, NULL);
return err;
}
{
.name = "le",
},
- {
- .name = "ledma",
- },
- {
- .name = "lebuffer",
- },
{},
};