* (from the mac68k project) introduced dhd's support for 16-bit cards.
*
* (C) 1996,1998 by Thomas Bogendoerfer (tsbogend@alpha.franken.de)
- *
+ *
* This driver is based on work from Andreas Busse, but most of
* the code is rewritten.
- *
+ *
* (C) 1995 by Andreas Busse (andy@waldorf-gmbh.de)
*
* Core code included by system sonic drivers
{
struct sonic_local *lp = netdev_priv(dev);
int i;
-
+
if (sonic_debug > 2)
printk("sonic_open: initializing sonic driver.\n");
- /*
- * We don't need to deal with auto-irq stuff since we
- * hardwire the sonic interrupt.
- */
-/*
- * XXX Horrible work around: We install sonic_interrupt as fast interrupt.
- * This means that during execution of the handler interrupt are disabled
- * covering another bug otherwise corrupting data. This doesn't mean
- * this glue works ok under all situations.
- *
- * Note (dhd): this also appears to prevent lockups on the Macintrash
- * when more than one Ethernet card is installed (knock on wood)
- *
- * Note (fthain): whether the above is still true is anyones guess. Certainly
- * the buffer handling algorithms will not tolerate re-entrance without some
- * mutual exclusion added. Anyway, the memcpy has now been eliminated from the
- * rx code to make this a faster "fast interrupt".
- */
- if (request_irq(dev->irq, &sonic_interrupt, SONIC_IRQ_FLAG, "sonic", dev)) {
- printk(KERN_ERR "\n%s: unable to get IRQ %d .\n", dev->name, dev->irq);
- return -EAGAIN;
- }
-
for (i = 0; i < SONIC_NUM_RRS; i++) {
struct sk_buff *skb = dev_alloc_skb(SONIC_RBSIZE + 2);
if (skb == NULL) {
dev->name);
return -ENOMEM;
}
- skb->dev = dev;
/* align IP header unless DMA requires otherwise */
if (SONIC_BUS_SCALE(lp->dma_bitmode) == 2)
skb_reserve(skb, 2);
}
}
- free_irq(dev->irq, dev); /* release the IRQ */
-
return 0;
}
{
struct sonic_local *lp = netdev_priv(dev);
int i;
- /* Stop the interrupts for this */
+ /*
+ * put the Sonic into software-reset mode and
+ * disable all interrupts before releasing DMA buffers
+ */
SONIC_WRITE(SONIC_IMR, 0);
+ SONIC_WRITE(SONIC_ISR, 0x7fff);
+ SONIC_WRITE(SONIC_CMD, SONIC_CR_RST);
/* We could resend the original skbs. Easier to re-initialise. */
for (i = 0; i < SONIC_NUM_TDS; i++) {
if(lp->tx_laddr[i]) {
/* Try to restart the adaptor. */
sonic_init(dev);
lp->stats.tx_errors++;
- dev->trans_start = jiffies;
+ dev->trans_start = jiffies; /* prevent tx timeout */
netif_wake_queue(dev);
}
length = skb->len;
if (length < ETH_ZLEN) {
- skb = skb_padto(skb, ETH_ZLEN);
- if (skb == NULL)
- return 0;
+ if (skb_padto(skb, ETH_ZLEN))
+ return NETDEV_TX_OK;
length = ETH_ZLEN;
}
if (!laddr) {
printk(KERN_ERR "%s: failed to map tx DMA buffer.\n", dev->name);
dev_kfree_skb(skb);
- return 1;
+ return NETDEV_TX_BUSY;
}
-
+
sonic_tda_put(dev, entry, SONIC_TD_STATUS, 0); /* clear status */
sonic_tda_put(dev, entry, SONIC_TD_FRAG_COUNT, 1); /* single fragment */
sonic_tda_put(dev, entry, SONIC_TD_PKTSIZE, length); /* length of packet */
SONIC_WRITE(SONIC_CMD, SONIC_CR_TXP);
- dev->trans_start = jiffies;
-
- return 0;
+ return NETDEV_TX_OK;
}
/*
* The typical workload of the driver:
* Handle the network interface interrupts.
*/
-static irqreturn_t sonic_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t sonic_interrupt(int irq, void *dev_id)
{
- struct net_device *dev = (struct net_device *) dev_id;
+ struct net_device *dev = dev_id;
struct sonic_local *lp = netdev_priv(dev);
int status;
- if (dev == NULL) {
- printk(KERN_ERR "sonic_interrupt: irq %d for unknown device.\n", irq);
- return IRQ_NONE;
- }
-
if (!(status = SONIC_READ(SONIC_ISR) & SONIC_IMR_DEFAULT))
return IRQ_NONE;
lp->stats.rx_dropped++;
break;
}
- new_skb->dev = dev;
/* provide 16 byte IP header alignment unless DMA requires otherwise */
if(SONIC_BUS_SCALE(lp->dma_bitmode) == 2)
- skb_reserve(new_skb, 2);
+ skb_reserve(new_skb, 2);
new_laddr = dma_map_single(lp->device, skb_put(new_skb, SONIC_RBSIZE),
SONIC_RBSIZE, DMA_FROM_DEVICE);
skb_trim(used_skb, pkt_len);
used_skb->protocol = eth_type_trans(used_skb, dev);
netif_rx(used_skb);
- dev->last_rx = jiffies;
lp->stats.rx_packets++;
lp->stats.rx_bytes += pkt_len;
{
struct sonic_local *lp = netdev_priv(dev);
unsigned int rcr;
- struct dev_mc_list *dmi = dev->mc_list;
+ struct netdev_hw_addr *ha;
unsigned char *addr;
int i;
if (dev->flags & IFF_PROMISC) { /* set promiscuous mode */
rcr |= SONIC_RCR_PRO;
} else {
- if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 15)) {
+ if ((dev->flags & IFF_ALLMULTI) ||
+ (netdev_mc_count(dev) > 15)) {
rcr |= SONIC_RCR_AMC;
} else {
if (sonic_debug > 2)
- printk("sonic_multicast_list: mc_count %d\n", dev->mc_count);
+ printk("sonic_multicast_list: mc_count %d\n",
+ netdev_mc_count(dev));
sonic_set_cam_enable(dev, 1); /* always enable our own address */
- for (i = 1; i <= dev->mc_count; i++) {
- addr = dmi->dmi_addr;
- dmi = dmi->next;
+ i = 1;
+ netdev_for_each_mc_addr(ha, dev) {
+ addr = ha->addr;
sonic_cda_put(dev, i, SONIC_CD_CAP0, addr[1] << 8 | addr[0]);
sonic_cda_put(dev, i, SONIC_CD_CAP1, addr[3] << 8 | addr[2]);
sonic_cda_put(dev, i, SONIC_CD_CAP2, addr[5] << 8 | addr[4]);
sonic_set_cam_enable(dev, sonic_get_cam_enable(dev) | (1 << i));
+ i++;
}
SONIC_WRITE(SONIC_CDC, 16);
/* issue Load CAM command */
SONIC_BUS_SCALE(lp->dma_bitmode)) & 0xffff;
lp->cur_rwp = (lp->rra_laddr + (SONIC_NUM_RRS - 1) * SIZEOF_SONIC_RR *
SONIC_BUS_SCALE(lp->dma_bitmode)) & 0xffff;
-
+
SONIC_WRITE(SONIC_RSA, lp->rra_laddr & 0xffff);
SONIC_WRITE(SONIC_REA, lp->rra_end);
SONIC_WRITE(SONIC_RRP, lp->rra_laddr & 0xffff);
/* load the resource pointers */
if (sonic_debug > 3)
printk("sonic_init: issuing RRRA command\n");
-
+
SONIC_WRITE(SONIC_CMD, SONIC_CR_RRRA);
i = 0;
while (i++ < 100) {
if (sonic_debug > 2)
printk("sonic_init: status=%x i=%d\n", SONIC_READ(SONIC_CMD), i);
-
+
/*
* Initialize the receive descriptors so that they
* become a circular linked list, ie. let the last
* descriptor point to the first again.
*/
if (sonic_debug > 2)
- printk("sonic_init: initialize receive descriptors\n");
+ printk("sonic_init: initialize receive descriptors\n");
for (i=0; i<SONIC_NUM_RDS; i++) {
sonic_rda_put(dev, i, SONIC_RD_STATUS, 0);
sonic_rda_put(dev, i, SONIC_RD_PKTLEN, 0);
SONIC_WRITE(SONIC_URDA, lp->rda_laddr >> 16);
SONIC_WRITE(SONIC_CRDA, lp->rda_laddr & 0xffff);
- /*
+ /*
* initialize transmit descriptors
*/
if (sonic_debug > 2)
SONIC_WRITE(SONIC_CTDA, lp->tda_laddr & 0xffff);
lp->cur_tx = lp->next_tx = 0;
lp->eol_tx = SONIC_NUM_TDS - 1;
-
+
/*
* put our own address to CAM desc[0]
*/