Commit 47229b82 authored by Jeff Garzik's avatar Jeff Garzik

Merge mandrakesoft.com:/home/jgarzik/repo/linus-2.5

into mandrakesoft.com:/home/jgarzik/repo/net-drivers-2.5
parents 3dcf3431 52ef1eac
......@@ -27,8 +27,6 @@
TODO, in rough priority order:
* Test Tx checksumming thoroughly
* dev->tx_timeout
* Support forcing media type with a module parameter,
like dl2k.c/sundance.c
* Constants (module parms?) for Rx work limit
* Complete reset on PciErr
* Consider Rx interrupt mitigation using TimerIntr
......@@ -49,8 +47,8 @@
*/
#define DRV_NAME "8139cp"
#define DRV_VERSION "0.2.1"
#define DRV_RELDATE "Aug 9, 2002"
#define DRV_VERSION "0.3.0"
#define DRV_RELDATE "Sep 29, 2002"
#include <linux/config.h>
......@@ -107,6 +105,11 @@ MODULE_PARM_DESC (multicast_filter_limit, "8139cp: maximum number of filtered mu
#define PFX DRV_NAME ": "
#ifndef TRUE
#define FALSE 0
#define TRUE (!FALSE)
#endif
#define CP_DEF_MSG_ENABLE (NETIF_MSG_DRV | \
NETIF_MSG_PROBE | \
NETIF_MSG_LINK)
......@@ -678,7 +681,7 @@ static void cp_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
if (status & (TxOK | TxErr | TxEmpty | SWInt))
cp_tx(cp);
if (status & LinkChg)
mii_check_media(&cp->mii_if, netif_msg_link(cp));
mii_check_media(&cp->mii_if, netif_msg_link(cp), FALSE);
if (status & PciErr) {
u16 pci_status;
......@@ -988,8 +991,6 @@ static struct net_device_stats *cp_get_stats(struct net_device *dev)
static void cp_stop_hw (struct cp_private *cp)
{
struct net_device *dev = cp->dev;
cpw16(IntrMask, 0);
cpr16(IntrMask);
cpw8(Cmd, 0);
......@@ -1195,7 +1196,7 @@ static int cp_open (struct net_device *dev)
goto err_out_hw;
netif_carrier_off(dev);
mii_check_media(&cp->mii_if, netif_msg_link(cp));
mii_check_media(&cp->mii_if, netif_msg_link(cp), TRUE);
netif_start_queue(dev);
return 0;
......@@ -1654,33 +1655,18 @@ static int cp_ethtool_ioctl (struct cp_private *cp, void *useraddr)
static int cp_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
{
struct cp_private *cp = dev->priv;
struct mii_ioctl_data *mii;
int rc = 0;
struct mii_ioctl_data *mii = (struct mii_ioctl_data *) &rq->ifr_data;
int rc;
mii = (struct mii_ioctl_data *) &rq->ifr_data;
if (!netif_running(dev))
return -EINVAL;
if (cmd != SIOCETHTOOL)
mii->reg_num &= 0x1f;
switch (cmd) {
case SIOCETHTOOL:
if (cmd == SIOCETHTOOL)
return cp_ethtool_ioctl(cp, (void *) rq->ifr_data);
case SIOCGMIIPHY: /* Get the address of the PHY in use. */
mii->phy_id = CP_INTERNAL_PHY;
/* Fall Through */
case SIOCGMIIREG: /* Read the specified MII register. */
mii->val_out = mdio_read (dev, CP_INTERNAL_PHY, mii->reg_num);
break;
default:
rc = -EOPNOTSUPP;
break;
}
rc = generic_mii_ioctl(dev, &cp->mii_if, mii, cmd);
if (rc == 1) /* we don't care about duplex change, fixup rc */
rc = 0;
return rc;
}
......@@ -1818,6 +1804,8 @@ static int __devinit cp_init_one (struct pci_dev *pdev,
cp->mii_if.mdio_read = mdio_read;
cp->mii_if.mdio_write = mdio_write;
cp->mii_if.phy_id = CP_INTERNAL_PHY;
cp->mii_if.phy_id_mask = 0x1f;
cp->mii_if.reg_num_mask = 0x1f;
cp_set_rxbufsize(cp);
rc = pci_enable_device(pdev);
......
......@@ -578,7 +578,6 @@ struct rtl8139_private {
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;
......@@ -986,6 +985,8 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
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);
......@@ -1041,7 +1042,7 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
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];
......@@ -1049,7 +1050,7 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
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",
......@@ -1306,7 +1307,7 @@ static int rtl8139_open (struct net_device *dev)
}
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 = (tp->chipset == CH_8139_K) ? 1 : 0;
tp->time_to_die = 0;
......@@ -1537,7 +1538,7 @@ static inline void rtl8139_thread_iter (struct net_device *dev,
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) {
......@@ -1995,7 +1996,7 @@ static void rtl8139_weird_interrupt (struct net_device *dev,
/* 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
......@@ -2439,58 +2440,25 @@ static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
}
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. */
data->phy_id = phy;
/* Fall Through */
case SIOCGMIIREG: /* Read the specified MII register. */
data->val_out = mdio_read (dev, data->phy_id, data->reg_num);
break;
case SIOCSMIIREG: /* Write the specified MII register */
if (!capable (CAP_NET_ADMIN)) {
rc = -EPERM;
break;
}
if (cmd == SIOCETHTOOL)
rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
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;
else {
spin_lock_irq(&np->lock);
rc = generic_mii_ioctl(dev, &np->mii, data, cmd);
spin_unlock_irq(&np->lock);
default:
rc = -EOPNOTSUPP;
break;
if (rc == 1) /* don't care about duplex change, fix up rc */
rc = 0;
}
return rc;
......
......@@ -429,6 +429,8 @@ static int __devinit epic_init_one (struct pci_dev *pdev,
ep->mii.dev = dev;
ep->mii.mdio_read = mdio_read;
ep->mii.mdio_write = mdio_write;
ep->mii.phy_id_mask = 0x1f;
ep->mii.reg_num_mask = 0x1f;
ring_space = pci_alloc_consistent(pdev, TX_TOTAL_SIZE, &ring_dma);
if (!ring_space)
......@@ -523,7 +525,7 @@ static int __devinit epic_init_one (struct pci_dev *pdev,
/* The lower four bits are the media type. */
if (duplex) {
ep->mii.duplex_lock = ep->mii.full_duplex = 1;
ep->mii.force_media = ep->mii.full_duplex = 1;
printk(KERN_INFO DRV_NAME "(%s): Forced full duplex operation requested.\n",
pdev->slot_name);
}
......@@ -854,7 +856,7 @@ static void check_media(struct net_device *dev)
int negotiated = mii_lpa & ep->mii.advertising;
int duplex = (negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040;
if (ep->mii.duplex_lock)
if (ep->mii.force_media)
return;
if (mii_lpa == 0xffff) /* Bogus read */
return;
......@@ -1426,63 +1428,36 @@ static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
struct epic_private *ep = dev->priv;
struct epic_private *np = dev->priv;
long ioaddr = dev->base_addr;
struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data;
int rc;
switch(cmd) {
case SIOCETHTOOL:
return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
/* power-up, if interface is down */
if (! netif_running(dev)) {
outl(0x0200, ioaddr + GENCTL);
outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
}
case SIOCGMIIPHY: /* Get address of MII PHY in use. */
data->phy_id = ep->phys[0] & 0x1f;
/* Fall Through */
/* ethtool commands */
if (cmd == SIOCETHTOOL)
rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
case SIOCGMIIREG: /* Read MII PHY register. */
if (! netif_running(dev)) {
outl(0x0200, ioaddr + GENCTL);
outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
}
data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f);
#if 0 /* Just leave on if the ioctl() is ever used. */
if (! netif_running(dev)) {
outl(0x0008, ioaddr + GENCTL);
outl((inl(ioaddr + NVCTL) & ~0x483C) | 0x0000, ioaddr + NVCTL);
}
#endif
return 0;
/* all other ioctls (the SIOC[GS]MIIxxx ioctls) */
else {
spin_lock_irq(&np->lock);
rc = generic_mii_ioctl(dev, &np->mii, data, cmd);
spin_unlock_irq(&np->lock);
if (rc == 1) /* don't care about duplex change, fixup rc */
rc = 0;
}
case SIOCSMIIREG: /* Write MII PHY register. */
if (!capable(CAP_NET_ADMIN))
return -EPERM;
if (! netif_running(dev)) {
outl(0x0200, ioaddr + GENCTL);
outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
}
if (data->phy_id == ep->phys[0]) {
u16 value = data->val_in;
switch (data->reg_num) {
case 0:
/* Check for autonegotiation on or reset. */
ep->mii.duplex_lock = (value & 0x9000) ? 0 : 1;
if (ep->mii.duplex_lock)
ep->mii.full_duplex = (value & 0x0100) ? 1 : 0;
break;
case 4: ep->mii.advertising = value; break;
}
/* Perhaps check_duplex(dev), depending on chip semantics. */
}
mdio_write(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
#if 0 /* Leave on if the ioctl() is used. */
if (! netif_running(dev)) {
outl(0x0008, ioaddr + GENCTL);
outl((inl(ioaddr + NVCTL) & ~0x483C) | 0x0000, ioaddr + NVCTL);
}
#endif
return 0;
default:
return -EOPNOTSUPP;
/* power-down, if interface is down */
if (! netif_running(dev)) {
outl(0x0008, ioaddr + GENCTL);
outl((inl(ioaddr + NVCTL) & ~0x483C) | 0x0000, ioaddr + NVCTL);
}
return rc;
}
......
......@@ -559,6 +559,8 @@ static int __devinit fealnx_init_one(struct pci_dev *pdev,
np->mii.dev = dev;
np->mii.mdio_read = mdio_read;
np->mii.mdio_write = mdio_write;
np->mii.phy_id_mask = 0x1f;
np->mii.reg_num_mask = 0x1f;
ring_space = pci_alloc_consistent(pdev, RX_TOTAL_SIZE, &ring_dma);
if (!ring_space) {
......@@ -654,7 +656,7 @@ static int __devinit fealnx_init_one(struct pci_dev *pdev,
mdio_write(dev, np->phys[0], MII_ADVERTISE, ADVERTISE_FULL);
else
writel(ADVERTISE_FULL, dev->base_addr + ANARANLPAR);
np->mii.duplex_lock = 1;
np->mii.force_media = 1;
}
/* The chip-specific entries in the device structure. */
......@@ -956,7 +958,7 @@ static int netdev_open(struct net_device *dev)
// 89/9/1 modify,
// np->crvalue = 0x00e40001; /* tx store and forward, tx/rx enable */
np->crvalue |= 0x00e40001; /* tx store and forward, tx/rx enable */
np->mii.full_duplex = np->mii.duplex_lock;
np->mii.full_duplex = np->mii.force_media;
getlinkstatus(dev);
if (np->linkok)
getlinktype(dev);
......@@ -1833,28 +1835,25 @@ static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
struct netdev_private *np = dev->priv;
struct mii_ioctl_data *data = (struct mii_ioctl_data *) & rq->ifr_data;
int rc;
switch (cmd) {
case SIOCETHTOOL:
return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
case SIOCGMIIPHY: /* Get address of MII PHY in use. */
data->phy_id = ((struct netdev_private *) dev->priv)->phys[0] & 0x1f;
/* Fall Through */
if (!netif_running(dev))
return -EINVAL;
case SIOCGMIIREG: /* Read MII PHY register. */
data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f);
return 0;
if (cmd == SIOCETHTOOL)
rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
case SIOCSMIIREG: /* Write MII PHY register. */
if (!capable(CAP_NET_ADMIN))
return -EPERM;
mdio_write(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
return 0;
default:
return -EOPNOTSUPP;
else {
spin_lock_irq(&np->lock);
rc = generic_mii_ioctl(dev, &np->mii, data, cmd);
spin_unlock_irq(&np->lock);
if (rc == 1) /* don't care about duplex change, fix up rc */
rc = 0;
}
return rc;
}
......
......@@ -3,7 +3,27 @@
mii.c: MII interface library
Maintained by Jeff Garzik <jgarzik@mandrakesoft.com>
Copyright 2001 Jeff Garzik
Copyright 2001,2002 Jeff Garzik
Various code came from myson803.c and other files by
Donald Becker. Copyright:
Written 1998-2002 by Donald Becker.
This software may be used and distributed according
to the terms of the GNU General Public License (GPL),
incorporated herein by reference. Drivers based on
or derived from this code fall under the GPL and must
retain the authorship, copyright and license notice.
This file is not a complete program and may only be
used when the entire operating system is licensed
under the GPL.
The author may be reached as becker@scyld.com, or C/O
Scyld Computing Corporation
410 Severn Ave., Suite 210
Annapolis MD 21403
*/
......@@ -122,7 +142,7 @@ int mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd)
bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
mii->mdio_write(dev, mii->phy_id, MII_BMCR, bmcr);
mii->duplex_lock = 0;
mii->force_media = 0;
} else {
u32 bmcr, tmp;
......@@ -139,7 +159,7 @@ int mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd)
if (bmcr != tmp)
mii->mdio_write(dev, mii->phy_id, MII_BMCR, tmp);
mii->duplex_lock = 1;
mii->force_media = 1;
}
return 0;
}
......@@ -178,13 +198,15 @@ void mii_check_link (struct mii_if_info *mii)
netif_carrier_off(mii->dev);
}
unsigned int mii_check_media (struct mii_if_info *mii, unsigned int ok_to_print)
unsigned int mii_check_media (struct mii_if_info *mii,
unsigned int ok_to_print,
unsigned int init_media)
{
unsigned int old_carrier, new_carrier;
int advertise, lpa, media, duplex;
/* if forced media, go no further */
if (mii->duplex_lock)
if (mii->force_media)
return 0; /* duplex did not change */
/* check current and old link status */
......@@ -194,7 +216,7 @@ unsigned int mii_check_media (struct mii_if_info *mii, unsigned int ok_to_print)
/* if carrier state did not change, this is a "bounce",
* just exit as everything is already set correctly
*/
if (old_carrier == new_carrier)
if ((!init_media) && (old_carrier == new_carrier))
return 0; /* duplex did not change */
/* no carrier, nothing much to do */
......@@ -211,7 +233,7 @@ unsigned int mii_check_media (struct mii_if_info *mii, unsigned int ok_to_print)
netif_carrier_on(mii->dev);
/* get MII advertise and LPA values */
if (mii->advertising)
if ((!init_media) && (mii->advertising))
advertise = mii->advertising;
else {
advertise = mii->mdio_read(mii->dev, mii->phy_id, MII_ADVERTISE);
......@@ -231,7 +253,7 @@ unsigned int mii_check_media (struct mii_if_info *mii, unsigned int ok_to_print)
duplex ? "full" : "half",
lpa);
if (mii->full_duplex != duplex) {
if ((init_media) || (mii->full_duplex != duplex)) {
mii->full_duplex = duplex;
return 1; /* duplex changed */
}
......@@ -239,6 +261,73 @@ unsigned int mii_check_media (struct mii_if_info *mii, unsigned int ok_to_print)
return 0; /* duplex did not change */
}
int generic_mii_ioctl(struct net_device *dev, struct mii_if_info *mii_if,
struct mii_ioctl_data *mii_data, int cmd)
{
int rc = 0;
unsigned int duplex_changed = 0;
mii_data->phy_id &= mii_if->phy_id_mask;
mii_data->reg_num &= mii_if->reg_num_mask;
switch(cmd) {
case SIOCGMIIPHY:
mii_data->phy_id = mii_if->phy_id;
/* fall through */
case SIOCGMIIREG:
mii_data->val_out =
mii_if->mdio_read(dev, mii_data->phy_id,
mii_data->reg_num);
break;
case SIOCSMIIREG: {
u16 val = mii_data->val_in;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
if (mii_data->phy_id == mii_if->phy_id) {
switch(mii_data->reg_num) {
case MII_BMCR: {
unsigned int new_duplex = 0;
if (val & (BMCR_RESET|BMCR_ANENABLE))
mii_if->force_media = 1;
else
mii_if->force_media = 0;
if (mii_if->force_media &&
(val & BMCR_FULLDPLX))
new_duplex = 1;
if (mii_if->full_duplex != new_duplex) {
duplex_changed = 1;
mii_if->full_duplex = new_duplex;
}
break;
}
case MII_ADVERTISE:
mii_if->advertising = val;
break;
default:
/* do nothing */
break;
}
}
mii_if->mdio_write(dev, mii_data->phy_id,
mii_data->reg_num, val);
break;
}
default:
rc = -EOPNOTSUPP;
break;
}
if ((rc == 0) && (duplex_changed))
rc = 1;
return rc;
}
MODULE_AUTHOR ("Jeff Garzik <jgarzik@mandrakesoft.com>");
MODULE_DESCRIPTION ("MII hardware support library");
MODULE_LICENSE("GPL");
......@@ -249,4 +338,5 @@ EXPORT_SYMBOL(mii_ethtool_gset);
EXPORT_SYMBOL(mii_ethtool_sset);
EXPORT_SYMBOL(mii_check_link);
EXPORT_SYMBOL(mii_check_media);
EXPORT_SYMBOL(generic_mii_ioctl);
......@@ -573,6 +573,8 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
np->mii_if.dev = dev;
np->mii_if.mdio_read = mdio_read;
np->mii_if.mdio_write = mdio_write;
np->mii_if.phy_id_mask = 0x1f;
np->mii_if.reg_num_mask = 0x1f;
/* The chip-specific entries in the device structure. */
dev->open = &netdev_open;
......@@ -1550,27 +1552,25 @@ static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data;
switch(cmd) {
case SIOCETHTOOL:
return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
case SIOCGMIIPHY: /* Get address of MII PHY in use. */
data->phy_id = ((struct netdev_private *)dev->priv)->phys[0] & 0x1f;
/* Fall Through */
case SIOCGMIIREG: /* Read MII PHY register. */
data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f);
return 0;
case SIOCSMIIREG: /* Write MII PHY register. */
if (!capable(CAP_NET_ADMIN))
return -EPERM;
mdio_write(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
return 0;
default:
return -EOPNOTSUPP;
struct netdev_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)
rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
else {
spin_lock_irq(&np->lock);
rc = generic_mii_ioctl(dev, &np->mii_if, data, cmd);
spin_unlock_irq(&np->lock);
if (rc == 1) /* don't care about duplex change, fix up rc */
rc = 0;
}
return rc;
}
static int netdev_close(struct net_device *dev)
......
......@@ -473,7 +473,7 @@ static int __devinit w840_probe1 (struct pci_dev *pdev,
np->mii_if.full_duplex = 1;
if (np->mii_if.full_duplex)
np->mii_if.duplex_lock = 1;
np->mii_if.force_media = 1;
/* The chip-specific entries in the device structure. */
dev->open = &netdev_open;
......@@ -773,7 +773,7 @@ static int update_link(struct net_device *dev)
duplex = (negotiated & LPA_100FULL) || ((negotiated & 0x02C0) == LPA_10FULL);
fasteth = negotiated & 0x380;
}
duplex |= np->mii_if.duplex_lock;
duplex |= np->mii_if.force_media;
/* remove fastether and fullduplex */
result = np->csr6 & ~0x20000200;
if (duplex)
......
......@@ -516,7 +516,7 @@ static void via_rhine_rx(struct net_device *dev);
static void via_rhine_error(struct net_device *dev, int intr_status);
static void via_rhine_set_rx_mode(struct net_device *dev);
static struct net_device_stats *via_rhine_get_stats(struct net_device *dev);
static int via_rhine_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
static int via_rhine_close(struct net_device *dev);
static inline void clear_tally_counters(long ioaddr);
......@@ -715,6 +715,8 @@ static int __devinit via_rhine_init_one (struct pci_dev *pdev,
np->mii_if.dev = dev;
np->mii_if.mdio_read = mdio_read;
np->mii_if.mdio_write = mdio_write;
np->mii_if.phy_id_mask = 0x1f;
np->mii_if.reg_num_mask = 0x1f;
if (dev->mem_start)
option = dev->mem_start;
......@@ -731,7 +733,7 @@ static int __devinit via_rhine_init_one (struct pci_dev *pdev,
if (np->mii_if.full_duplex) {
printk(KERN_INFO "%s: Set to forced full duplex, autonegotiation"
" disabled.\n", dev->name);
np->mii_if.duplex_lock = 1;
np->mii_if.force_media = 1;
}
/* The chip-specific entries in the device structure. */
......@@ -740,7 +742,7 @@ static int __devinit via_rhine_init_one (struct pci_dev *pdev,
dev->stop = via_rhine_close;
dev->get_stats = via_rhine_get_stats;
dev->set_multicast_list = via_rhine_set_rx_mode;
dev->do_ioctl = via_rhine_ioctl;
dev->do_ioctl = netdev_ioctl;
dev->tx_timeout = via_rhine_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
if (np->drv_flags & ReqTxAlign)
......@@ -1001,7 +1003,7 @@ static void init_registers(struct net_device *dev)
ioaddr + IntrEnable);
np->chip_cmd = CmdStart|CmdTxOn|CmdRxOn|CmdNoTxPoll;
if (np->mii_if.duplex_lock)
if (np->mii_if.force_media)
np->chip_cmd |= CmdFDuplex;
writew(np->chip_cmd, ioaddr + ChipCmd);
......@@ -1043,7 +1045,7 @@ static void mdio_write(struct net_device *dev, int phy_id, int regnum, int value
switch (regnum) {
case MII_BMCR: /* Is user forcing speed/duplex? */
if (value & 0x9000) /* Autonegotiation. */
np->mii_if.duplex_lock = 0;
np->mii_if.force_media = 0;
else
np->mii_if.full_duplex = (value & 0x0100) ? 1 : 0;
break;
......@@ -1114,7 +1116,7 @@ static void via_rhine_check_duplex(struct net_device *dev)
int negotiated = mii_lpa & np->mii_if.advertising;
int duplex;
if (np->mii_if.duplex_lock || mii_lpa == 0xffff)
if (np->mii_if.force_media || mii_lpa == 0xffff)
return;
duplex = (negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040;
if (np->mii_if.full_duplex != duplex) {
......@@ -1586,7 +1588,7 @@ static void via_rhine_set_rx_mode(struct net_device *dev)
writeb(np->rx_thresh | rx_mode, ioaddr + RxConfig);
}
static int via_rhine_ethtool_ioctl (struct net_device *dev, void *useraddr)
static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
{
struct netdev_private *np = dev->priv;
u32 ethcmd;
......@@ -1669,41 +1671,28 @@ static int via_rhine_ethtool_ioctl (struct net_device *dev, void *useraddr)
return -EOPNOTSUPP;
}
static int via_rhine_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
struct netdev_private *np = dev->priv;
struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data;
unsigned long flags;
int retval;
if (cmd == SIOCETHTOOL)
return via_rhine_ethtool_ioctl(dev, (void *) rq->ifr_data);
struct mii_ioctl_data *data = (struct mii_ioctl_data *) & rq->ifr_data;
int rc;
spin_lock_irqsave(&np->lock, flags);
retval = 0;
switch(cmd) {
case SIOCGMIIPHY: /* Get address of MII PHY in use. */
data->phy_id = np->phys[0] & 0x1f;
/* Fall Through */
if (!netif_running(dev))
return -EINVAL;
case SIOCGMIIREG: /* Read MII PHY register. */
data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f);
break;
if (cmd == SIOCETHTOOL)
rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
case SIOCSMIIREG: /* Write MII PHY register. */
if (!capable(CAP_NET_ADMIN)) {
retval = -EPERM;
break;
}
mdio_write(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
break;
default:
retval = -EOPNOTSUPP;
else {
spin_lock_irq(&np->lock);
rc = generic_mii_ioctl(dev, &np->mii_if, data, cmd);
spin_unlock_irq(&np->lock);
if (rc == 1) /* don't care about duplex change, fix up rc */
rc = 0;
}
spin_unlock_irqrestore(&np->lock, flags);
return retval;
return rc;
}
static int via_rhine_close(struct net_device *dev)
......
......@@ -107,9 +107,11 @@
struct mii_if_info {
int phy_id;
int advertising;
int phy_id_mask;
int reg_num_mask;
unsigned int full_duplex : 1;
unsigned int duplex_lock : 1;
unsigned int full_duplex : 1; /* is full duplex? */
unsigned int force_media : 1; /* is autoneg. disabled? */
struct net_device *dev;
int (*mdio_read) (struct net_device *dev, int phy_id, int location);
......@@ -117,13 +119,19 @@ struct mii_if_info {
};
struct ethtool_cmd;
struct mii_ioctl_data;
extern int mii_link_ok (struct mii_if_info *mii);
extern int mii_nway_restart (struct mii_if_info *mii);
extern int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd);
extern int mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd);
extern void mii_check_link (struct mii_if_info *mii);
extern unsigned int mii_check_media (struct mii_if_info *mii, unsigned int ok_to_print);
extern unsigned int mii_check_media (struct mii_if_info *mii,
unsigned int ok_to_print,
unsigned int init_media);
extern int generic_mii_ioctl(struct net_device *dev, struct mii_if_info *mii_if,
struct mii_ioctl_data *mii_data, int cmd);
/* This structure is used in all SIOCxMIIxxx ioctl calls */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment