patch-2.4.20 linux-2.4.20/drivers/net/8139too.c
Next file: linux-2.4.20/drivers/net/Config.in
Previous file: linux-2.4.20/drivers/net/8139cp.c
Back to the patch index
Back to the overall index
- Lines: 419
- Date:
Thu Nov 28 15:53:13 2002
- Orig file:
linux-2.4.19/drivers/net/8139too.c
- Orig date:
Fri Aug 2 17:39:44 2002
diff -urN linux-2.4.19/drivers/net/8139too.c linux-2.4.20/drivers/net/8139too.c
@@ -92,7 +92,7 @@
*/
#define DRV_NAME "8139too"
-#define DRV_VERSION "0.9.25"
+#define DRV_VERSION "0.9.26"
#include <linux/config.h>
@@ -201,6 +201,8 @@
HAS_LNK_CHNG = 0x040000,
};
+#define RTL_NUM_STATS 4 /* number of ETHTOOL_GSTATS u64's */
+#define RTL_REGS_VER 1 /* version of reg. data in ETHTOOL_GREGS */
#define RTL_MIN_IO_SIZE 0x80
#define RTL8139B_IO_SIZE 256
@@ -219,6 +221,8 @@
FE2000VX,
ALLIED8139,
RTL8129,
+ FNW3603TX,
+ FNW3800TX,
} board_t;
@@ -238,6 +242,8 @@
{ "AboCom FE2000VX (RealTek RTL8139)", RTL8139_CAPS },
{ "Allied Telesyn 8139 CardBus", RTL8139_CAPS },
{ "RealTek RTL8129", RTL8129_CAPS },
+ { "Planex FNW-3603-TX 10/100 CardBus", RTL8139_CAPS },
+ { "Planex FNW-3800-TX 10/100 CardBus", RTL8139_CAPS },
};
@@ -252,6 +258,8 @@
{0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DFE690TXD },
{0x13d1, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, FE2000VX },
{0x1259, 0xa117, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ALLIED8139 },
+ {0x14ea, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, FNW3603TX },
+ {0x14ea, 0xab07, PCI_ANY_ID, PCI_ANY_ID, 0, 0, FNW3800TX },
#ifdef CONFIG_8139TOO_8129
{0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 },
@@ -269,6 +277,14 @@
};
MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl);
+static struct {
+ const char str[ETH_GSTRING_LEN];
+} ethtool_stats_keys[] = {
+ { "early_rx" },
+ { "tx_buf_mapped" },
+ { "tx_timeouts" },
+ { "rx_lost_in_ring" },
+};
/* The rest of these values should never change. */
@@ -446,7 +462,7 @@
/* Twister tuning parameters from RealTek.
- Completely undocumented, but required to tune bad links. */
+ Completely undocumented, but required to tune bad links on some boards. */
enum CSCRBits {
CSCR_LinkOKBit = 0x0400,
CSCR_LinkChangeBit = 0x0800,
@@ -461,10 +477,14 @@
Cfg9346_Unlock = 0xC0,
};
+#ifdef CONFIG_8139TOO_TUNE_TWISTER
+
+enum TwisterParamVals {
+ PARA78_default = 0x78fa8388,
+ PARA7c_default = 0xcb38de43, /* param[0][3] */
+ PARA7c_xxx = 0xcb38de43,
+};
-#define PARA78_default 0x78fa8388
-#define PARA7c_default 0xcb38de43 /* param[0][3] */
-#define PARA7c_xxx 0xcb38de43
static const unsigned long param[4][4] = {
{0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43},
{0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83},
@@ -472,6 +492,8 @@
{0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83}
};
+#endif /* CONFIG_8139TOO_TUNE_TWISTER */
+
typedef enum {
CH_8139 = 0,
CH_8139_K,
@@ -556,7 +578,6 @@
signed char phys[4]; /* MII device addresses. */
char twistie, twist_row, twist_col; /* Twister tune state. */
unsigned int default_port:4; /* Last dev->if_port value. */
- unsigned int medialock:1; /* Don't sense media type. */
spinlock_t lock;
chip_t chipset;
pid_t thr_pid;
@@ -566,6 +587,7 @@
struct rtl_extra_stats xstats;
int time_to_die;
struct mii_if_info mii;
+ unsigned int regs_len;
};
MODULE_AUTHOR ("Jeff Garzik <jgarzik@mandrakesoft.com>");
@@ -807,6 +829,7 @@
ioaddr = (void *) pio_start;
dev->base_addr = pio_start;
tp->mmio_addr = ioaddr;
+ tp->regs_len = pio_len;
#else
/* ioremap MMIO region */
ioaddr = ioremap (mmio_start, mmio_len);
@@ -817,6 +840,7 @@
}
dev->base_addr = (long) ioaddr;
tp->mmio_addr = ioaddr;
+ tp->regs_len = mmio_len;
#endif /* USE_IO_OPS */
/* Bring old chips out of low-power mode. */
@@ -961,6 +985,8 @@
tp->mii.dev = dev;
tp->mii.mdio_read = mdio_read;
tp->mii.mdio_write = mdio_write;
+ tp->mii.phy_id_mask = 0x3f;
+ tp->mii.reg_num_mask = 0x1f;
/* dev is fully set up and ready to use now */
DPRINTK("about to register device named %s (%p)...\n", dev->name, dev);
@@ -1016,7 +1042,7 @@
tp->mii.full_duplex = (option & 0x210) ? 1 : 0;
tp->default_port = option & 0xFF;
if (tp->default_port)
- tp->medialock = 1;
+ tp->mii.force_media = 1;
}
if (board_idx < MAX_UNITS && full_duplex[board_idx] > 0)
tp->mii.full_duplex = full_duplex[board_idx];
@@ -1024,7 +1050,7 @@
printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name);
/* Changing the MII-advertised media because might prevent
re-connection. */
- tp->mii.duplex_lock = 1;
+ tp->mii.force_media = 1;
}
if (tp->default_port) {
printk(KERN_INFO " Forcing %dMbps %s-duplex operation.\n",
@@ -1281,9 +1307,9 @@
}
- tp->mii.full_duplex = tp->mii.duplex_lock;
+ tp->mii.full_duplex = tp->mii.force_media;
tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000;
- tp->twistie = 1;
+ tp->twistie = (tp->chipset == CH_8139_K) ? 1 : 0;
tp->time_to_die = 0;
rtl8139_init_ring (dev);
@@ -1512,7 +1538,7 @@
mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA);
- if (!tp->mii.duplex_lock && mii_lpa != 0xffff) {
+ if (!tp->mii.force_media && mii_lpa != 0xffff) {
int duplex = (mii_lpa & LPA_100FULL)
|| (mii_lpa & 0x01C0) == 0x0040;
if (tp->mii.full_duplex != duplex) {
@@ -1722,10 +1748,6 @@
tp->stats.tx_carrier_errors++;
if (txstatus & TxOutOfWindow)
tp->stats.tx_window_errors++;
-#ifdef ETHER_STATS
- if ((txstatus & 0x0f000000) == 0x0f000000)
- tp->stats.collisions16++;
-#endif
} else {
if (txstatus & TxUnderrun) {
/* Add 64 to the Tx FIFO threshold. */
@@ -1765,7 +1787,7 @@
struct rtl8139_private *tp, void *ioaddr)
{
u8 tmp8;
-#ifndef CONFIG_8139_NEW_RX_RESET
+#ifdef CONFIG_8139_OLD_RX_RESET
int tmp_work;
#endif
@@ -1788,7 +1810,7 @@
tp->xstats.rx_lost_in_ring++;
}
-#ifdef CONFIG_8139_NEW_RX_RESET
+#ifndef CONFIG_8139_OLD_RX_RESET
tmp8 = RTL_R8 (ChipCmd);
RTL_W8 (ChipCmd, tmp8 & ~CmdRxEnb);
RTL_W8 (ChipCmd, tmp8);
@@ -1975,7 +1997,7 @@
/* Really link-change on new chips. */
int lpar = RTL_R16 (NWayLPAR);
int duplex = (lpar & LPA_100FULL) || (lpar & 0x01C0) == 0x0040
- || tp->mii.duplex_lock;
+ || tp->mii.force_media;
if (tp->mii.full_duplex != duplex) {
tp->mii.full_duplex = duplex;
#if 0
@@ -2231,6 +2253,7 @@
strcpy (info.driver, DRV_NAME);
strcpy (info.version, DRV_VERSION);
strcpy (info.bus_info, np->pci_dev->slot_name);
+ info.regdump_len = np->regs_len;
if (copy_to_user (useraddr, &info, sizeof (info)))
return -EFAULT;
return 0;
@@ -2310,6 +2333,104 @@
return rc;
}
+/* TODO: we are too slack to do reg dumping for pio, for now */
+#ifndef CONFIG_8139TOO_PIO
+ /* NIC register dump */
+ case ETHTOOL_GREGS: {
+ struct ethtool_regs regs;
+ unsigned int regs_len = np->regs_len;
+ u8 *regbuf = kmalloc(regs_len, GFP_KERNEL);
+ int rc;
+
+ if (!regbuf)
+ return -ENOMEM;
+ memset(regbuf, 0, regs_len);
+
+ rc = copy_from_user(®s, useraddr, sizeof(regs));
+ if (rc) {
+ rc = -EFAULT;
+ goto err_out_gregs;
+ }
+
+ if (regs.len > regs_len)
+ regs.len = regs_len;
+ if (regs.len < regs_len) {
+ rc = -EINVAL;
+ goto err_out_gregs;
+ }
+
+ regs.version = RTL_REGS_VER;
+ rc = copy_to_user(useraddr, ®s, sizeof(regs));
+ if (rc) {
+ rc = -EFAULT;
+ goto err_out_gregs;
+ }
+
+ useraddr += offsetof(struct ethtool_regs, data);
+
+ spin_lock_irq(&np->lock);
+ memcpy_fromio(regbuf, np->mmio_addr, regs_len);
+ spin_unlock_irq(&np->lock);
+
+ if (copy_to_user(useraddr, regbuf, regs_len))
+ rc = -EFAULT;
+
+err_out_gregs:
+ kfree(regbuf);
+ return rc;
+ }
+#endif /* CONFIG_8139TOO_PIO */
+
+ /* get string list(s) */
+ case ETHTOOL_GSTRINGS: {
+ struct ethtool_gstrings estr = { ETHTOOL_GSTRINGS };
+
+ if (copy_from_user(&estr, useraddr, sizeof(estr)))
+ return -EFAULT;
+ if (estr.string_set != ETH_SS_STATS)
+ return -EINVAL;
+
+ estr.len = RTL_NUM_STATS;
+ if (copy_to_user(useraddr, &estr, sizeof(estr)))
+ return -EFAULT;
+ if (copy_to_user(useraddr + sizeof(estr),
+ ðtool_stats_keys,
+ sizeof(ethtool_stats_keys)))
+ return -EFAULT;
+ return 0;
+ }
+
+ /* get NIC-specific statistics */
+ case ETHTOOL_GSTATS: {
+ struct ethtool_stats estats = { ETHTOOL_GSTATS };
+ u64 *tmp_stats;
+ const unsigned int sz = sizeof(u64) * RTL_NUM_STATS;
+ int i;
+
+ estats.n_stats = RTL_NUM_STATS;
+ if (copy_to_user(useraddr, &estats, sizeof(estats)))
+ return -EFAULT;
+
+ tmp_stats = kmalloc(sz, GFP_KERNEL);
+ if (!tmp_stats)
+ return -ENOMEM;
+ memset(tmp_stats, 0, sz);
+
+ i = 0;
+ tmp_stats[i++] = np->xstats.early_rx;
+ tmp_stats[i++] = np->xstats.tx_buf_mapped;
+ tmp_stats[i++] = np->xstats.tx_timeouts;
+ tmp_stats[i++] = np->xstats.rx_lost_in_ring;
+ if (i != RTL_NUM_STATS)
+ BUG();
+
+ i = copy_to_user(useraddr + sizeof(estats), tmp_stats, sz);
+ kfree(tmp_stats);
+
+ if (i)
+ return -EFAULT;
+ return 0;
+ }
default:
break;
}
@@ -2318,61 +2439,22 @@
}
-static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
+static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
- struct rtl8139_private *tp = dev->priv;
- struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data;
- int rc = 0;
- int phy = tp->phys[0] & 0x3f;
+ struct rtl8139_private *np = dev->priv;
+ struct mii_ioctl_data *data = (struct mii_ioctl_data *) & rq->ifr_data;
+ int rc;
if (!netif_running(dev))
return -EINVAL;
- if (cmd != SIOCETHTOOL) {
- /* With SIOCETHTOOL, this would corrupt the pointer. */
- data->phy_id &= 0x3f;
- data->reg_num &= 0x1f;
- }
-
- switch (cmd) {
- case SIOCETHTOOL:
- return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
-
- case SIOCGMIIPHY: /* Get the address of the PHY in use. */
- case SIOCDEVPRIVATE: /* binary compat, remove in 2.5 */
- data->phy_id = phy;
- /* Fall Through */
-
- case SIOCGMIIREG: /* Read the specified MII register. */
- case SIOCDEVPRIVATE+1: /* binary compat, remove in 2.5 */
- data->val_out = mdio_read (dev, data->phy_id, data->reg_num);
- break;
+ if (cmd == SIOCETHTOOL)
+ rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
- case SIOCSMIIREG: /* Write the specified MII register */
- case SIOCDEVPRIVATE+2: /* binary compat, remove in 2.5 */
- if (!capable (CAP_NET_ADMIN)) {
- rc = -EPERM;
- break;
- }
-
- if (data->phy_id == phy) {
- u16 value = data->val_in;
- switch (data->reg_num) {
- case 0:
- /* Check for autonegotiation on or reset. */
- tp->medialock = (value & 0x9000) ? 0 : 1;
- if (tp->medialock)
- tp->mii.full_duplex = (value & 0x0100) ? 1 : 0;
- break;
- case 4: tp->mii.advertising = value; break;
- }
- }
- mdio_write(dev, data->phy_id, data->reg_num, data->val_in);
- break;
-
- default:
- rc = -EOPNOTSUPP;
- break;
+ else {
+ spin_lock_irq(&np->lock);
+ rc = generic_mii_ioctl(&np->mii, data, cmd, NULL);
+ spin_unlock_irq(&np->lock);
}
return rc;
@@ -2500,13 +2582,13 @@
static struct pci_driver rtl8139_pci_driver = {
- name: DRV_NAME,
- id_table: rtl8139_pci_tbl,
- probe: rtl8139_init_one,
- remove: __devexit_p(rtl8139_remove_one),
+ .name = DRV_NAME,
+ .id_table = rtl8139_pci_tbl,
+ .probe = rtl8139_init_one,
+ .remove = __devexit_p(rtl8139_remove_one),
#ifdef CONFIG_PM
- suspend: rtl8139_suspend,
- resume: rtl8139_resume,
+ .suspend = rtl8139_suspend,
+ .resume = rtl8139_resume,
#endif /* CONFIG_PM */
};
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)