Commit 0c83531d authored by Jeff Garzik's avatar Jeff Garzik

Merge luckyluke.devel.redhat.com:/mnt/cvs/BK/linus-2.5

into mandrakesoft.com:/home/jgarzik/repo/net-drivers-2.5
parents 5b3e7241 b24fa762
...@@ -24,6 +24,7 @@ sequences). To utilise this ability, you have to do 8 things: ...@@ -24,6 +24,7 @@ sequences). To utilise this ability, you have to do 8 things:
kernel with the ewrk3 configuration turned off and reboot. kernel with the ewrk3 configuration turned off and reboot.
5) insmod ewrk3.o 5) insmod ewrk3.o
[Alan Cox: Changed this so you can insmod ewrk3.o irq=x io=y] [Alan Cox: Changed this so you can insmod ewrk3.o irq=x io=y]
[Adam Kropelin: Multiple cards now supported by irq=x1,x2 io=y1,y2]
6) run the net startup bits for your new eth?? interface manually 6) run the net startup bits for your new eth?? interface manually
(usually /etc/rc.inet[12] at boot time). (usually /etc/rc.inet[12] at boot time).
7) enjoy! 7) enjoy!
......
...@@ -49,11 +49,13 @@ ...@@ -49,11 +49,13 @@
- Power Management support - Power Management support
v1.18c 1Mar2002 David Ruggiero <jdr@farfalle.com> v1.18c 1Mar2002 David Ruggiero <jdr@farfalle.com>
- Full duplex support - Full duplex support
v1.19 16Oct2002 Zwane Mwaikambo <zwane@linuxpower.ca>
- Additional ethtool features
*/ */
#define DRV_NAME "3c509" #define DRV_NAME "3c509"
#define DRV_VERSION "1.18c" #define DRV_VERSION "1.19"
#define DRV_RELDATE "1Mar2002" #define DRV_RELDATE "16Oct2002"
/* A few values that may be tweaked. */ /* A few values that may be tweaked. */
...@@ -140,9 +142,11 @@ enum RxFilter { ...@@ -140,9 +142,11 @@ enum RxFilter {
#define TX_STATUS 0x0B #define TX_STATUS 0x0B
#define TX_FREE 0x0C /* Remaining free bytes in Tx buffer. */ #define TX_FREE 0x0C /* Remaining free bytes in Tx buffer. */
#define WN0_CONF_CTRL 0x04 /* Window 0: Configuration control register */
#define WN0_ADDR_CONF 0x06 /* Window 0: Address configuration register */
#define WN0_IRQ 0x08 /* Window 0: Set IRQ line in bits 12-15. */ #define WN0_IRQ 0x08 /* Window 0: Set IRQ line in bits 12-15. */
#define WN4_MEDIA 0x0A /* Window 4: Various transcvr/media bits. */ #define WN4_MEDIA 0x0A /* Window 4: Various transcvr/media bits. */
#define MEDIA_TP 0x00C0 /* Enable link beat and jabber for 10baseT. */ #define MEDIA_TP 0x00C0 /* Enable link beat and jabber for 10baseT. */
#define WN4_NETDIAG 0x06 /* Window 4: Net diagnostic */ #define WN4_NETDIAG 0x06 /* Window 4: Net diagnostic */
#define FD_ENABLE 0x8000 /* Enable full-duplex ("external loopback") */ #define FD_ENABLE 0x8000 /* Enable full-duplex ("external loopback") */
...@@ -981,6 +985,119 @@ el3_close(struct net_device *dev) ...@@ -981,6 +985,119 @@ el3_close(struct net_device *dev)
return 0; return 0;
} }
static int
el3_link_ok(struct net_device *dev)
{
int ioaddr = dev->base_addr;
u16 tmp;
EL3WINDOW(4);
tmp = inw(ioaddr + WN4_MEDIA);
EL3WINDOW(1);
return tmp & (1<<11);
}
static int
el3_netdev_get_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd)
{
u16 tmp;
int ioaddr = dev->base_addr;
EL3WINDOW(0);
/* obtain current tranceiver via WN4_MEDIA? */
tmp = inw(ioaddr + WN0_ADDR_CONF);
ecmd->transceiver = XCVR_INTERNAL;
switch (tmp >> 14) {
case 0:
ecmd->port = PORT_TP;
break;
case 1:
ecmd->port = PORT_AUI;
ecmd->transceiver = XCVR_EXTERNAL;
break;
case 3:
ecmd->port = PORT_BNC;
default:
break;
}
ecmd->duplex = DUPLEX_HALF;
ecmd->supported = 0;
tmp = inw(ioaddr + WN0_CONF_CTRL);
if (tmp & (1<<13))
ecmd->supported |= SUPPORTED_AUI;
if (tmp & (1<<12))
ecmd->supported |= SUPPORTED_BNC;
if (tmp & (1<<9)) {
ecmd->supported |= SUPPORTED_TP | SUPPORTED_10baseT_Half |
SUPPORTED_10baseT_Full; /* hmm... */
EL3WINDOW(4);
tmp = inw(ioaddr + WN4_NETDIAG);
if (tmp & FD_ENABLE)
ecmd->duplex = DUPLEX_FULL;
}
ecmd->speed = SPEED_10;
EL3WINDOW(1);
return 0;
}
static int
el3_netdev_set_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd)
{
u16 tmp;
int ioaddr = dev->base_addr;
if (ecmd->speed != SPEED_10)
return -EINVAL;
if ((ecmd->duplex != DUPLEX_HALF) && (ecmd->duplex != DUPLEX_FULL))
return -EINVAL;
if ((ecmd->transceiver != XCVR_INTERNAL) && (ecmd->transceiver != XCVR_EXTERNAL))
return -EINVAL;
/* change XCVR type */
EL3WINDOW(0);
tmp = inw(ioaddr + WN0_ADDR_CONF);
switch (ecmd->port) {
case PORT_TP:
tmp &= ~(3<<14);
dev->if_port = 0;
break;
case PORT_AUI:
tmp |= (1<<14);
dev->if_port = 1;
break;
case PORT_BNC:
tmp |= (3<<14);
dev->if_port = 3;
break;
default:
return -EINVAL;
}
outw(tmp, ioaddr + WN0_ADDR_CONF);
if (dev->if_port == 3) {
/* fire up the DC-DC convertor if BNC gets enabled */
tmp = inw(ioaddr + WN0_ADDR_CONF);
if (tmp & (3 << 14)) {
outw(StartCoax, ioaddr + EL3_CMD);
udelay(800);
} else
return -EIO;
}
EL3WINDOW(4);
tmp = inw(ioaddr + WN4_NETDIAG);
if (ecmd->duplex == DUPLEX_FULL)
tmp |= FD_ENABLE;
else
tmp &= ~FD_ENABLE;
outw(tmp, ioaddr + WN4_NETDIAG);
EL3WINDOW(1);
return 0;
}
/** /**
* netdev_ethtool_ioctl: Handle network interface SIOCETHTOOL ioctls * netdev_ethtool_ioctl: Handle network interface SIOCETHTOOL ioctls
* @dev: network interface on which out-of-band action is to be performed * @dev: network interface on which out-of-band action is to be performed
...@@ -989,9 +1106,11 @@ el3_close(struct net_device *dev) ...@@ -989,9 +1106,11 @@ el3_close(struct net_device *dev)
* Process the various commands of the SIOCETHTOOL interface. * Process the various commands of the SIOCETHTOOL interface.
*/ */
static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr) static int
netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
{ {
u32 ethcmd; u32 ethcmd;
struct el3_private *lp = dev->priv;
/* dev_ioctl() in ../../net/core/dev.c has already checked /* dev_ioctl() in ../../net/core/dev.c has already checked
capable(CAP_NET_ADMIN), so don't bother with that here. */ capable(CAP_NET_ADMIN), so don't bother with that here. */
...@@ -1010,6 +1129,41 @@ static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr) ...@@ -1010,6 +1129,41 @@ static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
return 0; return 0;
} }
/* get settings */
case ETHTOOL_GSET: {
int ret;
struct ethtool_cmd ecmd = { ETHTOOL_GSET };
spin_lock_irq(&lp->lock);
ret = el3_netdev_get_ecmd(dev, &ecmd);
spin_unlock_irq(&lp->lock);
if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
return -EFAULT;
return ret;
}
/* set settings */
case ETHTOOL_SSET: {
int ret;
struct ethtool_cmd ecmd;
if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
return -EFAULT;
spin_lock_irq(&lp->lock);
ret = el3_netdev_set_ecmd(dev, &ecmd);
spin_unlock_irq(&lp->lock);
return ret;
}
/* get link status */
case ETHTOOL_GLINK: {
struct ethtool_value edata = { ETHTOOL_GLINK };
spin_lock_irq(&lp->lock);
edata.data = el3_link_ok(dev);
spin_unlock_irq(&lp->lock);
if (copy_to_user(useraddr, &edata, sizeof(edata)))
return -EFAULT;
return 0;
}
/* get message-level */ /* get message-level */
case ETHTOOL_GMSGLVL: { case ETHTOOL_GMSGLVL: {
struct ethtool_value edata = {ETHTOOL_GMSGLVL}; struct ethtool_value edata = {ETHTOOL_GMSGLVL};
...@@ -1043,7 +1197,8 @@ static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr) ...@@ -1043,7 +1197,8 @@ static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
* Process the various out-of-band ioctls passed to this driver. * Process the various out-of-band ioctls passed to this driver.
*/ */
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)
{ {
int rc = 0; int rc = 0;
...@@ -1060,7 +1215,8 @@ static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) ...@@ -1060,7 +1215,8 @@ static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
return rc; return rc;
} }
static void el3_down(struct net_device *dev) static void
el3_down(struct net_device *dev)
{ {
int ioaddr = dev->base_addr; int ioaddr = dev->base_addr;
...@@ -1077,7 +1233,7 @@ static void el3_down(struct net_device *dev) ...@@ -1077,7 +1233,7 @@ static void el3_down(struct net_device *dev)
/* Turn off thinnet power. Green! */ /* Turn off thinnet power. Green! */
outw(StopCoax, ioaddr + EL3_CMD); outw(StopCoax, ioaddr + EL3_CMD);
else if (dev->if_port == 0) { else if (dev->if_port == 0) {
/* Disable link beat and jabber, if_port may change ere next open(). */ /* Disable link beat and jabber, if_port may change here next open(). */
EL3WINDOW(4); EL3WINDOW(4);
outw(inw(ioaddr + WN4_MEDIA) & ~MEDIA_TP, ioaddr + WN4_MEDIA); outw(inw(ioaddr + WN4_MEDIA) & ~MEDIA_TP, ioaddr + WN4_MEDIA);
} }
...@@ -1087,7 +1243,8 @@ static void el3_down(struct net_device *dev) ...@@ -1087,7 +1243,8 @@ static void el3_down(struct net_device *dev)
update_stats(dev); update_stats(dev);
} }
static void el3_up(struct net_device *dev) static void
el3_up(struct net_device *dev)
{ {
int i, sw_info, net_diag; int i, sw_info, net_diag;
int ioaddr = dev->base_addr; int ioaddr = dev->base_addr;
...@@ -1176,7 +1333,8 @@ static void el3_up(struct net_device *dev) ...@@ -1176,7 +1333,8 @@ static void el3_up(struct net_device *dev)
/* Power Management support functions */ /* Power Management support functions */
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int el3_suspend(struct pm_dev *pdev) static int
el3_suspend(struct pm_dev *pdev)
{ {
unsigned long flags; unsigned long flags;
struct net_device *dev; struct net_device *dev;
...@@ -1202,7 +1360,8 @@ static int el3_suspend(struct pm_dev *pdev) ...@@ -1202,7 +1360,8 @@ static int el3_suspend(struct pm_dev *pdev)
return 0; return 0;
} }
static int el3_resume(struct pm_dev *pdev) static int
el3_resume(struct pm_dev *pdev)
{ {
unsigned long flags; unsigned long flags;
struct net_device *dev; struct net_device *dev;
...@@ -1228,7 +1387,8 @@ static int el3_resume(struct pm_dev *pdev) ...@@ -1228,7 +1387,8 @@ static int el3_resume(struct pm_dev *pdev)
return 0; return 0;
} }
static int el3_pm_callback(struct pm_dev *pdev, pm_request_t rqst, void *data) static int
el3_pm_callback(struct pm_dev *pdev, pm_request_t rqst, void *data)
{ {
switch (rqst) { switch (rqst) {
case PM_SUSPEND: case PM_SUSPEND:
......
...@@ -76,6 +76,7 @@ ...@@ -76,6 +76,7 @@
kernel with the ewrk3 configuration turned off and reboot. kernel with the ewrk3 configuration turned off and reboot.
5) insmod ewrk3.o 5) insmod ewrk3.o
[Alan Cox: Changed this so you can insmod ewrk3.o irq=x io=y] [Alan Cox: Changed this so you can insmod ewrk3.o irq=x io=y]
[Adam Kropelin: now accepts irq=x1,x2 io=y1,y2 for multiple cards]
6) run the net startup bits for your new eth?? interface manually 6) run the net startup bits for your new eth?? interface manually
(usually /etc/rc.inet[12] at boot time). (usually /etc/rc.inet[12] at boot time).
7) enjoy! 7) enjoy!
...@@ -130,10 +131,12 @@ ...@@ -130,10 +131,12 @@
Add new multicasting code. Add new multicasting code.
0.41 20-Jan-96 Fix IRQ set up problem reported by 0.41 20-Jan-96 Fix IRQ set up problem reported by
<kenneth@bbs.sas.ntu.ac.sg>. <kenneth@bbs.sas.ntu.ac.sg>.
0.42 22-Apr-96 Fix alloc_device() bug <jari@markkus2.fimr.fi> 0.42 22-Apr-96 Fix alloc_device() bug <jari@markkus2.fimr.fi>
0.43 16-Aug-96 Update alloc_device() to conform to de4x5.c 0.43 16-Aug-96 Update alloc_device() to conform to de4x5.c
0.44 08-Nov-01 use library crc32 functions <Matt_Domsch@dell.com> 0.44 08-Nov-01 use library crc32 functions <Matt_Domsch@dell.com>
0.45 19-Jul-02 fix unaligned access on alpha <martin@bruli.net> 0.45 19-Jul-02 fix unaligned access on alpha <martin@bruli.net>
0.46 10-Oct-02 cli/sti removal <VDA@port.imtp.ilyichevsk.odessa.ua>
Multiple NIC support when module <akropel1@rochester.rr.com>
========================================================================= =========================================================================
*/ */
...@@ -167,7 +170,7 @@ ...@@ -167,7 +170,7 @@
#include "ewrk3.h" #include "ewrk3.h"
static char version[] __initdata = static char version[] __initdata =
"ewrk3.c:v0.43a 2001/02/04 davies@maniac.ultranet.com\n"; "ewrk3.c:v0.46 2002/10/09 davies@maniac.ultranet.com\n";
#ifdef EWRK3_DEBUG #ifdef EWRK3_DEBUG
static int ewrk3_debug = EWRK3_DEBUG; static int ewrk3_debug = EWRK3_DEBUG;
...@@ -196,6 +199,7 @@ static int ewrk3_debug = 1; ...@@ -196,6 +199,7 @@ static int ewrk3_debug = 1;
#define EWRK3_IOP_INC 0x20 /* I/O address increment */ #define EWRK3_IOP_INC 0x20 /* I/O address increment */
#define EWRK3_TOTAL_SIZE 0x20 /* required I/O address length */ #define EWRK3_TOTAL_SIZE 0x20 /* required I/O address length */
/* If you change this, remember to also change MODULE_PARM array limits */
#ifndef MAX_NUM_EWRK3S #ifndef MAX_NUM_EWRK3S
#define MAX_NUM_EWRK3S 21 #define MAX_NUM_EWRK3S 21
#endif #endif
...@@ -1716,6 +1720,11 @@ static int ewrk3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ...@@ -1716,6 +1720,11 @@ static int ewrk3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
break; break;
case EWRK3_SET_MCA: /* Set a multicast address */ case EWRK3_SET_MCA: /* Set a multicast address */
if (capable(CAP_NET_ADMIN)) { if (capable(CAP_NET_ADMIN)) {
if (ioc->len > 1024)
{
status = -EINVAL;
break;
}
if (copy_from_user(tmp->addr, ioc->data, ETH_ALEN * ioc->len)) { if (copy_from_user(tmp->addr, ioc->data, ETH_ALEN * ioc->len)) {
status = -EFAULT; status = -EFAULT;
break; break;
...@@ -1843,35 +1852,62 @@ static int ewrk3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ...@@ -1843,35 +1852,62 @@ static int ewrk3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
} }
#ifdef MODULE #ifdef MODULE
static struct net_device thisEthwrk; static struct net_device *ewrk3_devs[MAX_NUM_EWRK3S];
static int io = 0x300; /* <--- EDIT THESE LINES FOR YOUR CONFIGURATION */ static int ndevs;
static int irq = 5; /* or use the insmod io= irq= options */ static int io[MAX_NUM_EWRK3S+1] = { 0x300, 0, }; /* <--- EDIT THESE LINES FOR YOUR CONFIGURATION */
static int irq[MAX_NUM_EWRK3S+1] = { 5, 0, }; /* or use the insmod io= irq= options */
MODULE_PARM(io, "i"); /* '21' below should really be 'MAX_NUM_EWRK3S' */
MODULE_PARM(irq, "i"); MODULE_PARM(io, "0-21i");
MODULE_PARM_DESC(io, "EtherWORKS 3 I/O base address"); MODULE_PARM(irq, "0-21i");
MODULE_PARM_DESC(irq, "EtherWORKS 3 IRQ number"); MODULE_PARM_DESC(io, "EtherWORKS 3 I/O base address(es)");
MODULE_PARM_DESC(irq, "EtherWORKS 3 IRQ number(s)");
int init_module(void) int init_module(void)
{ {
thisEthwrk.base_addr = io; int i=0;
thisEthwrk.irq = irq;
thisEthwrk.init = ewrk3_probe; while( io[i] && irq[i] ) {
if (register_netdev(&thisEthwrk) != 0) ewrk3_devs[ndevs] = kmalloc(sizeof(struct net_device), GFP_KERNEL);
return -EIO; if (!ewrk3_devs[ndevs])
return 0; goto error;
memset(ewrk3_devs[ndevs], 0, sizeof(struct net_device));
ewrk3_devs[ndevs]->base_addr = io[i];
ewrk3_devs[ndevs]->irq = irq[i];
ewrk3_devs[ndevs]->init = ewrk3_probe;
if (register_netdev(ewrk3_devs[ndevs]) == 0)
ndevs++;
else
kfree(ewrk3_devs[ndevs]);
i++;
}
return ndevs ? 0 : -EIO;
error:
cleanup_module();
return -ENOMEM;
} }
void cleanup_module(void) void cleanup_module(void)
{ {
unregister_netdev(&thisEthwrk); int i;
if (thisEthwrk.priv) {
kfree(thisEthwrk.priv); for( i=0; i<ndevs; i++ )
thisEthwrk.priv = NULL; {
} unregister_netdev(ewrk3_devs[i]);
thisEthwrk.irq = 0; if (ewrk3_devs[i]->priv) {
kfree(ewrk3_devs[i]->priv);
ewrk3_devs[i]->priv = NULL;
}
ewrk3_devs[i]->irq = 0;
release_region(thisEthwrk.base_addr, EWRK3_TOTAL_SIZE); release_region(ewrk3_devs[i]->base_addr, EWRK3_TOTAL_SIZE);
kfree(ewrk3_devs[i]);
ewrk3_devs[i] = NULL;
}
} }
#endif /* MODULE */ #endif /* MODULE */
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
......
...@@ -243,7 +243,7 @@ unsigned int mii_check_media (struct mii_if_info *mii, ...@@ -243,7 +243,7 @@ unsigned int mii_check_media (struct mii_if_info *mii,
/* figure out media and duplex from advertise and LPA values */ /* figure out media and duplex from advertise and LPA values */
media = mii_nway_result(lpa & advertise); media = mii_nway_result(lpa & advertise);
duplex = (media & (ADVERTISE_100FULL | ADVERTISE_10FULL)) ? 1 : 0; duplex = (media & ADVERTISE_FULL) ? 1 : 0;
if (ok_to_print) if (ok_to_print)
printk(KERN_INFO "%s: link up, %sMbps, %s-duplex, lpa 0x%04X\n", printk(KERN_INFO "%s: link up, %sMbps, %s-duplex, lpa 0x%04X\n",
......
...@@ -253,7 +253,7 @@ static int __init tms_pci_init (void) ...@@ -253,7 +253,7 @@ static int __init tms_pci_init (void)
return 0; return 0;
} }
static void __devexit tms_pci_rmmod (void) static void __exit tms_pci_rmmod (void)
{ {
pci_unregister_driver (&tms_pci_driver); pci_unregister_driver (&tms_pci_driver);
} }
......
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