patch-2.4.20 linux-2.4.20/drivers/net/pcmcia/axnet_cs.c
Next file: linux-2.4.20/drivers/net/pcmcia/fmvj18x_cs.c
Previous file: linux-2.4.20/drivers/net/pcmcia/aironet4500_cs.c
Back to the patch index
Back to the overall index
- Lines: 223
- Date:
Thu Nov 28 15:53:14 2002
- Orig file:
linux-2.4.19/drivers/net/pcmcia/axnet_cs.c
- Orig date:
Fri Dec 21 09:41:54 2001
diff -urN linux-2.4.19/drivers/net/pcmcia/axnet_cs.c linux-2.4.20/drivers/net/pcmcia/axnet_cs.c
@@ -11,8 +11,8 @@
Copyright (C) 2001 David A. Hinds -- dahinds@users.sourceforge.net
- axnet_cs.c 1.24 2001/11/18 02:46:51
-
+ axnet_cs.c 1.28 2002/06/29 06:27:37
+
The network driver code is based on Donald Becker's NE2000 code:
Written 1992,1993 by Donald Becker.
@@ -34,9 +34,11 @@
#include <linux/timer.h>
#include <linux/delay.h>
#include <linux/spinlock.h>
+#include <linux/ethtool.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/byteorder.h>
+#include <asm/uaccess.h>
#include <linux/netdevice.h>
#include "../8390.h"
@@ -53,12 +55,17 @@
#define AXNET_DATAPORT 0x10 /* NatSemi-defined port window offset. */
#define AXNET_RESET 0x1f /* Issue a read to reset, a write to clear. */
#define AXNET_MII_EEP 0x14 /* Offset of MII access port */
+#define AXNET_TEST 0x15 /* Offset of TEST Register port */
+#define AXNET_GPIO 0x17 /* Offset of General Purpose Register Port */
#define AXNET_START_PG 0x40 /* First page of TX buffer */
#define AXNET_STOP_PG 0x80 /* Last page +1 of RX ring */
#define AXNET_RDC_TIMEOUT 0x02 /* Max wait in jiffies for Tx RDC */
+#define IS_AX88190 0x0001
+#define IS_AX88790 0x0002
+
/*====================================================================*/
/* Module parameters */
@@ -78,7 +85,7 @@
INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
static char *version =
-"axnet_cs.c 1.24 2001/11/18 02:46:51 (David Hinds)";
+"axnet_cs.c 1.28 2002/06/29 06:27:37 (David Hinds)";
#else
#define DEBUG(n, args...)
#endif
@@ -115,6 +122,7 @@
static int axdev_init(struct net_device *dev);
static void AX88190_init(struct net_device *dev, int startp);
static int ax_open(struct net_device *dev);
+static int ax_close(struct net_device *dev);
static void ax_interrupt(int irq, void *dev_id, struct pt_regs *regs);
/*====================================================================*/
@@ -129,6 +137,7 @@
u_short link_status;
u_char duplex_flag;
int phy_id;
+ int flags;
} axnet_dev_t;
/*======================================================================
@@ -473,17 +482,37 @@
strcpy(info->node.dev_name, dev->name);
link->dev = &info->node;
- link->state &= ~DEV_CONFIG_PENDING;
- printk(KERN_INFO "%s: Asix AX88190: io %#3lx, irq %d, hw_addr ",
- dev->name, dev->base_addr, dev->irq);
+ if (inb(dev->base_addr + AXNET_TEST) != 0)
+ info->flags |= IS_AX88790;
+ else
+ info->flags |= IS_AX88190;
+
+ printk(KERN_INFO "%s: Asix AX88%d90: io %#3lx, irq %d, hw_addr ",
+ dev->name, ((info->flags & IS_AX88790) ? 7 : 1),
+ dev->base_addr, dev->irq);
for (i = 0; i < 6; i++)
printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));
+ if (info->flags & IS_AX88790)
+ outb(0x10, dev->base_addr + AXNET_GPIO); /* select Internal PHY */
+
for (i = 0; i < 32; i++) {
j = mdio_read(dev->base_addr + AXNET_MII_EEP, i, 1);
if ((j != 0) && (j != 0xffff)) break;
}
+
+ /* Maybe PHY is in power down mode. (PPD_SET = 1)
+ Bit 2 of CCSR is active low. */
+ if (i == 32) {
+ conf_reg_t reg = { 0, CS_WRITE, CISREG_CCSR, 0x04 };
+ CardServices(AccessConfigurationRegister, link->handle, ®);
+ for (i = 0; i < 32; i++) {
+ j = mdio_read(dev->base_addr + AXNET_MII_EEP, i, 1);
+ if ((j != 0) && (j != 0xffff)) break;
+ }
+ }
+
info->phy_id = (i < 32) ? i : -1;
if (i < 32) {
DEBUG(0, " MII transceiver at index %d, status %x.\n", i, j);
@@ -491,12 +520,14 @@
printk(KERN_NOTICE " No MII transceivers found!\n");
}
+ link->state &= ~DEV_CONFIG_PENDING;
return;
cs_failed:
cs_error(link->handle, last_fn, last_ret);
failed:
axnet_release((u_long)link);
+ link->state &= ~DEV_CONFIG_PENDING;
return;
} /* axnet_config */
@@ -555,7 +586,7 @@
}
break;
case CS_EVENT_CARD_INSERTION:
- link->state |= DEV_PRESENT;
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
axnet_config(link);
break;
case CS_EVENT_PM_SUSPEND:
@@ -678,6 +709,7 @@
DEBUG(2, "axnet_close('%s')\n", dev->name);
+ ax_close(dev);
free_irq(dev->irq, dev);
link->open--;
@@ -790,6 +822,26 @@
add_timer(&info->watchdog);
}
+static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
+{
+ u32 ethcmd;
+
+ if (copy_from_user(ðcmd, useraddr, sizeof(ethcmd)))
+ return -EFAULT;
+
+ switch (ethcmd) {
+ case ETHTOOL_GDRVINFO: {
+ struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
+ strncpy(info.driver, "axnet_cs", sizeof(info.driver)-1);
+ if (copy_to_user(useraddr, &info, sizeof(info)))
+ return -EFAULT;
+ return 0;
+ }
+ }
+
+ return -EOPNOTSUPP;
+}
+
/*====================================================================*/
static int axnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
@@ -798,6 +850,8 @@
u16 *data = (u16 *)&rq->ifr_data;
ioaddr_t mii_addr = dev->base_addr + AXNET_MII_EEP;
switch (cmd) {
+ case SIOCETHTOOL:
+ return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
case SIOCDEVPRIVATE:
data[0] = info->phy_id;
case SIOCDEVPRIVATE+1:
@@ -888,7 +942,7 @@
if (serv.Revision != CS_RELEASE_CODE) {
printk(KERN_NOTICE "axnet_cs: Card Services release "
"does not match!\n");
- return -1;
+ return -EINVAL;
}
register_pccard_driver(&dev_info, &axnet_attach, &axnet_detach);
return 0;
@@ -1079,6 +1133,29 @@
return 0;
}
+#define dev_lock(dev) (((struct ei_device *)(dev)->priv)->page_lock)
+
+/**
+ * ax_close - shut down network device
+ * @dev: network device to close
+ *
+ * Opposite of ax_open(). Only used when "ifconfig <devname> down" is done.
+ */
+int ax_close(struct net_device *dev)
+{
+ unsigned long flags;
+
+ /*
+ * Hold the page lock during close
+ */
+
+ spin_lock_irqsave(&dev_lock(dev), flags);
+ AX88190_init(dev, 0);
+ spin_unlock_irqrestore(&dev_lock(dev), flags);
+ netif_stop_queue(dev);
+ return 0;
+}
+
/**
* ei_tx_timeout - handle transmit time out condition
* @dev: network device which has apparently fallen asleep
@@ -1734,8 +1811,6 @@
* not called too often. Must protect against both bh and irq users
*/
-#define dev_lock(dev) (((struct ei_device *)(dev)->priv)->page_lock)
-
static void set_multicast_list(struct net_device *dev)
{
unsigned long flags;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)