#include <linux/delay.h>
#include <linux/spinlock.h>
#include <linux/dma-mapping.h>
+#include <linux/bitops.h>
#include <asm/processor.h>
-#include <asm/bitops.h>
#include <asm/io.h>
#include <asm/dma.h>
#include <asm/uaccess.h>
static const struct ethtool_ops netdev_ethtool_ops;
static u16 read_srom_word(long, int);
static irqreturn_t uli526x_interrupt(int, void *);
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void uli526x_poll(struct net_device *dev);
+#endif
static void uli526x_descriptor_init(struct uli526x_board_info *, unsigned long);
static void allocate_rx_buffer(struct uli526x_board_info *);
static void update_cr6(u32, unsigned long);
struct uli526x_board_info *db; /* board information structure */
struct net_device *dev;
int i, err;
- DECLARE_MAC_BUF(mac);
ULI526X_DBUG(0, "uli526x_init_one()", 0);
dev->get_stats = &uli526x_get_stats;
dev->set_multicast_list = &uli526x_set_filter_mode;
dev->ethtool_ops = &netdev_ethtool_ops;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ dev->poll_controller = &uli526x_poll;
+#endif
spin_lock_init(&db->lock);
if (err)
goto err_out_res;
- printk(KERN_INFO "%s: ULi M%04lx at pci%s, %s, irq %d.\n",
+ printk(KERN_INFO "%s: ULi M%04lx at pci%s, %pM, irq %d.\n",
dev->name,ent->driver_data >> 16,pci_name(pdev),
- print_mac(mac, dev->dev_addr), dev->irq);
+ dev->dev_addr, dev->irq);
pci_set_master(pdev);
ULI526X_DBUG(0, "uli526x_open", 0);
- ret = request_irq(dev->irq, &uli526x_interrupt, IRQF_SHARED, dev->name, dev);
- if (ret)
- return ret;
-
/* system variable init */
db->cr6_data = CR6_DEFAULT | uli526x_cr6_user_set;
db->tx_packet_cnt = 0;
/* Initialize ULI526X board */
uli526x_init(dev);
+ ret = request_irq(dev->irq, &uli526x_interrupt, IRQF_SHARED, dev->name, dev);
+ if (ret)
+ return ret;
+
/* Active System Interface */
netif_wake_queue(dev);
struct uli526x_board_info *db = netdev_priv(dev);
unsigned long ioaddr = db->ioaddr;
u8 phy_tmp;
+ u8 timeout;
u16 phy_value;
u16 phy_reg_reset;
+
ULI526X_DBUG(0, "uli526x_init()", 0);
/* Reset M526x MAC controller */
/* Parser SROM and media mode */
db->media_mode = uli526x_media_mode;
- /* Phyxcer capability setting */
+ /* phyxcer capability setting */
phy_reg_reset = phy_read(db->ioaddr, db->phy_addr, 0, db->chip_id);
phy_reg_reset = (phy_reg_reset | 0x8000);
phy_write(db->ioaddr, db->phy_addr, 0, phy_reg_reset, db->chip_id);
+
+ /* See IEEE 802.3-2002.pdf (Section 2, Chapter "22.2.4 Management
+ * functions") or phy data sheet for details on phy reset
+ */
udelay(500);
+ timeout = 10;
+ while (timeout-- &&
+ phy_read(db->ioaddr, db->phy_addr, 0, db->chip_id) & 0x8000)
+ udelay(100);
/* Process Phyxcer Media Mode */
uli526x_set_phyxcer(db);
db->cr5_data = inl(ioaddr + DCR5);
outl(db->cr5_data, ioaddr + DCR5);
if ( !(db->cr5_data & 0x180c1) ) {
- spin_unlock_irqrestore(&db->lock, flags);
+ /* Restore CR7 to enable interrupt mask */
outl(db->cr7_data, ioaddr + DCR7);
+ spin_unlock_irqrestore(&db->lock, flags);
return IRQ_HANDLED;
}
return IRQ_HANDLED;
}
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void uli526x_poll(struct net_device *dev)
+{
+ /* ISR grabs the irqsave lock, so this should be safe */
+ uli526x_interrupt(dev->irq, dev);
+}
+#endif
/*
* Free TX resource after TX complete
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
- dev->last_rx = jiffies;
db->stats.rx_packets++;
db->stats.rx_bytes += rxlen;
static void uli526x_set_filter_mode(struct net_device * dev)
{
- struct uli526x_board_info *db = dev->priv;
+ struct uli526x_board_info *db = netdev_priv(dev);
unsigned long flags;
ULI526X_DBUG(0, "uli526x_set_filter_mode()", 0);
* This setup frame initialize ULI526X address filter mode
*/
+#ifdef __BIG_ENDIAN
+#define FLT_SHIFT 16
+#else
+#define FLT_SHIFT 0
+#endif
+
static void send_filter_frame(struct net_device *dev, int mc_cnt)
{
struct uli526x_board_info *db = netdev_priv(dev);
/* Node address */
addrptr = (u16 *) dev->dev_addr;
- *suptr++ = addrptr[0];
- *suptr++ = addrptr[1];
- *suptr++ = addrptr[2];
+ *suptr++ = addrptr[0] << FLT_SHIFT;
+ *suptr++ = addrptr[1] << FLT_SHIFT;
+ *suptr++ = addrptr[2] << FLT_SHIFT;
/* broadcast address */
- *suptr++ = 0xffff;
- *suptr++ = 0xffff;
- *suptr++ = 0xffff;
+ *suptr++ = 0xffff << FLT_SHIFT;
+ *suptr++ = 0xffff << FLT_SHIFT;
+ *suptr++ = 0xffff << FLT_SHIFT;
/* fit the multicast address */
for (mcptr = dev->mc_list, i = 0; i < mc_cnt; i++, mcptr = mcptr->next) {
addrptr = (u16 *) mcptr->dmi_addr;
- *suptr++ = addrptr[0];
- *suptr++ = addrptr[1];
- *suptr++ = addrptr[2];
+ *suptr++ = addrptr[0] << FLT_SHIFT;
+ *suptr++ = addrptr[1] << FLT_SHIFT;
+ *suptr++ = addrptr[2] << FLT_SHIFT;
}
for (; i<14; i++) {
- *suptr++ = 0xffff;
- *suptr++ = 0xffff;
- *suptr++ = 0xffff;
+ *suptr++ = 0xffff << FLT_SHIFT;
+ *suptr++ = 0xffff << FLT_SHIFT;
+ *suptr++ = 0xffff << FLT_SHIFT;
}
/* prepare the setup frame */