#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/init.h>
-#include <linux/bitops.h>
#include <asm/uaccess.h>
#include <asm/processor.h> /* Processor type for cache alignment. */
+#include <asm/bitops.h>
#include <asm/io.h>
#include <linux/delay.h>
#include <linux/spinlock.h>
static struct net_device_stats *get_stats(struct net_device *dev);
static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
static int netdev_close(struct net_device *dev);
-static struct ethtool_ops ethtool_ops;
+
+
static int __devinit sundance_probe1 (struct pci_dev *pdev,
const struct pci_device_id *ent)
dev->base_addr = ioaddr;
dev->irq = irq;
- np = netdev_priv(dev);
+ np = dev->priv;
np->pci_dev = pdev;
np->chip_id = chip_idx;
np->msg_enable = (1 << debug) - 1;
dev->get_stats = &get_stats;
dev->set_multicast_list = &set_rx_mode;
dev->do_ioctl = &netdev_ioctl;
- SET_ETHTOOL_OPS(dev, ðtool_ops);
dev->tx_timeout = &tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
dev->change_mtu = &change_mtu;
static int mdio_read(struct net_device *dev, int phy_id, int location)
{
- struct netdev_private *np = netdev_priv(dev);
+ struct netdev_private *np = dev->priv;
long mdio_addr = dev->base_addr + MIICtrl;
int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location;
int i, retval = 0;
static void mdio_write(struct net_device *dev, int phy_id, int location, int value)
{
- struct netdev_private *np = netdev_priv(dev);
+ struct netdev_private *np = dev->priv;
long mdio_addr = dev->base_addr + MIICtrl;
int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location<<18) | value;
int i;
static int netdev_open(struct net_device *dev)
{
- struct netdev_private *np = netdev_priv(dev);
+ struct netdev_private *np = dev->priv;
long ioaddr = dev->base_addr;
int i;
if (dev->if_port == 0)
dev->if_port = np->default_port;
- spin_lock_init(&np->mcastlock);
+ np->mcastlock = SPIN_LOCK_UNLOCKED;
set_rx_mode(dev);
writew(0, ioaddr + IntrEnable);
static void check_duplex(struct net_device *dev)
{
- struct netdev_private *np = netdev_priv(dev);
+ struct netdev_private *np = dev->priv;
long ioaddr = dev->base_addr;
int mii_lpa = mdio_read(dev, np->phys[0], MII_LPA);
int negotiated = mii_lpa & np->mii_if.advertising;
static void netdev_timer(unsigned long data)
{
struct net_device *dev = (struct net_device *)data;
- struct netdev_private *np = netdev_priv(dev);
+ struct netdev_private *np = dev->priv;
long ioaddr = dev->base_addr;
int next_tick = 10*HZ;
static void tx_timeout(struct net_device *dev)
{
- struct netdev_private *np = netdev_priv(dev);
+ struct netdev_private *np = dev->priv;
long ioaddr = dev->base_addr;
unsigned long flag;
/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
static void init_ring(struct net_device *dev)
{
- struct netdev_private *np = netdev_priv(dev);
+ struct netdev_private *np = dev->priv;
int i;
np->cur_rx = np->cur_tx = 0;
static void tx_poll (unsigned long data)
{
struct net_device *dev = (struct net_device *)data;
- struct netdev_private *np = netdev_priv(dev);
+ struct netdev_private *np = dev->priv;
unsigned head = np->cur_task % TX_RING_SIZE;
struct netdev_desc *txdesc =
&np->tx_ring[(np->cur_tx - 1) % TX_RING_SIZE];
static int
start_tx (struct sk_buff *skb, struct net_device *dev)
{
- struct netdev_private *np = netdev_priv(dev);
+ struct netdev_private *np = dev->priv;
struct netdev_desc *txdesc;
unsigned entry;
static int
reset_tx (struct net_device *dev)
{
- struct netdev_private *np = netdev_priv(dev);
+ struct netdev_private *np = dev->priv;
long ioaddr = dev->base_addr;
struct sk_buff *skb;
int i;
int handled = 0;
ioaddr = dev->base_addr;
- np = netdev_priv(dev);
+ np = dev->priv;
do {
int intr_status = readw(ioaddr + IntrStatus);
static void rx_poll(unsigned long data)
{
struct net_device *dev = (struct net_device *)data;
- struct netdev_private *np = netdev_priv(dev);
+ struct netdev_private *np = dev->priv;
int entry = np->cur_rx % RX_RING_SIZE;
int boguscnt = np->budget;
long ioaddr = dev->base_addr;
static void refill_rx (struct net_device *dev)
{
- struct netdev_private *np = netdev_priv(dev);
+ struct netdev_private *np = dev->priv;
int entry;
int cnt = 0;
static void netdev_error(struct net_device *dev, int intr_status)
{
long ioaddr = dev->base_addr;
- struct netdev_private *np = netdev_priv(dev);
+ struct netdev_private *np = dev->priv;
u16 mii_ctl, mii_advertise, mii_lpa;
int speed;
static struct net_device_stats *get_stats(struct net_device *dev)
{
- struct netdev_private *np = netdev_priv(dev);
+ struct netdev_private *np = dev->priv;
long ioaddr = dev->base_addr;
int i;
static void set_rx_mode(struct net_device *dev)
{
long ioaddr = dev->base_addr;
- struct netdev_private *np = netdev_priv(dev);
+ struct netdev_private *np = dev->priv;
u16 mc_filter[4]; /* Multicast hash filter */
u32 rx_mode;
int i;
writew(addr16, dev->base_addr + StationAddr+4);
return 0;
}
+
-static int check_if_running(struct net_device *dev)
-{
- if (!netif_running(dev))
- return -EINVAL;
- return 0;
-}
-
-static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+static int netdev_ethtool_ioctl(struct net_device *dev, void __user *useraddr)
{
- struct netdev_private *np = netdev_priv(dev);
- strcpy(info->driver, DRV_NAME);
- strcpy(info->version, DRV_VERSION);
- strcpy(info->bus_info, pci_name(np->pci_dev));
-}
+ struct netdev_private *np = dev->priv;
+ u32 ethcmd;
+
+ if (copy_from_user(ðcmd, useraddr, sizeof(ethcmd)))
+ return -EFAULT;
+
+ switch (ethcmd) {
+ /* get constant driver settings/info */
+ case ETHTOOL_GDRVINFO: {
+ struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
+ strcpy(info.driver, DRV_NAME);
+ strcpy(info.version, DRV_VERSION);
+ strcpy(info.bus_info, pci_name(np->pci_dev));
+ memset(&info.fw_version, 0, sizeof(info.fw_version));
+ if (copy_to_user(useraddr, &info, sizeof(info)))
+ return -EFAULT;
+ return 0;
+ }
-static int get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
-{
- struct netdev_private *np = netdev_priv(dev);
- spin_lock_irq(&np->lock);
- mii_ethtool_gset(&np->mii_if, ecmd);
- spin_unlock_irq(&np->lock);
- return 0;
-}
+ /* get media settings */
+ case ETHTOOL_GSET: {
+ struct ethtool_cmd ecmd = { ETHTOOL_GSET };
+ spin_lock_irq(&np->lock);
+ mii_ethtool_gset(&np->mii_if, &ecmd);
+ spin_unlock_irq(&np->lock);
+ if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
+ return -EFAULT;
+ return 0;
+ }
+ /* set media settings */
+ case ETHTOOL_SSET: {
+ int r;
+ struct ethtool_cmd ecmd;
+ if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
+ return -EFAULT;
+ spin_lock_irq(&np->lock);
+ r = mii_ethtool_sset(&np->mii_if, &ecmd);
+ spin_unlock_irq(&np->lock);
+ return r;
+ }
-static int set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
-{
- struct netdev_private *np = netdev_priv(dev);
- int res;
- spin_lock_irq(&np->lock);
- res = mii_ethtool_sset(&np->mii_if, ecmd);
- spin_unlock_irq(&np->lock);
- return res;
-}
+ /* restart autonegotiation */
+ case ETHTOOL_NWAY_RST: {
+ return mii_nway_restart(&np->mii_if);
+ }
-static int nway_reset(struct net_device *dev)
-{
- struct netdev_private *np = netdev_priv(dev);
- return mii_nway_restart(&np->mii_if);
-}
+ /* get link status */
+ case ETHTOOL_GLINK: {
+ struct ethtool_value edata = {ETHTOOL_GLINK};
+ edata.data = mii_link_ok(&np->mii_if);
+ if (copy_to_user(useraddr, &edata, sizeof(edata)))
+ return -EFAULT;
+ return 0;
+ }
-static u32 get_link(struct net_device *dev)
-{
- struct netdev_private *np = netdev_priv(dev);
- return mii_link_ok(&np->mii_if);
-}
+ /* get message-level */
+ case ETHTOOL_GMSGLVL: {
+ struct ethtool_value edata = {ETHTOOL_GMSGLVL};
+ edata.data = np->msg_enable;
+ if (copy_to_user(useraddr, &edata, sizeof(edata)))
+ return -EFAULT;
+ return 0;
+ }
+ /* set message-level */
+ case ETHTOOL_SMSGLVL: {
+ struct ethtool_value edata;
+ if (copy_from_user(&edata, useraddr, sizeof(edata)))
+ return -EFAULT;
+ np->msg_enable = edata.data;
+ return 0;
+ }
-static u32 get_msglevel(struct net_device *dev)
-{
- struct netdev_private *np = netdev_priv(dev);
- return np->msg_enable;
-}
+ default:
+ return -EOPNOTSUPP;
-static void set_msglevel(struct net_device *dev, u32 val)
-{
- struct netdev_private *np = netdev_priv(dev);
- np->msg_enable = val;
+ }
}
-static struct ethtool_ops ethtool_ops = {
- .begin = check_if_running,
- .get_drvinfo = get_drvinfo,
- .get_settings = get_settings,
- .set_settings = set_settings,
- .nway_reset = nway_reset,
- .get_link = get_link,
- .get_msglevel = get_msglevel,
- .set_msglevel = set_msglevel,
-};
-
static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
- struct netdev_private *np = netdev_priv(dev);
+ struct netdev_private *np = dev->priv;
int rc;
int i;
long ioaddr = dev->base_addr;
if (!netif_running(dev))
return -EINVAL;
- spin_lock_irq(&np->lock);
- rc = generic_mii_ioctl(&np->mii_if, if_mii(rq), cmd, NULL);
- spin_unlock_irq(&np->lock);
+ if (cmd == SIOCETHTOOL)
+ rc = netdev_ethtool_ioctl(dev, rq->ifr_data);
+
+ else {
+ spin_lock_irq(&np->lock);
+ rc = generic_mii_ioctl(&np->mii_if, if_mii(rq), cmd, NULL);
+ spin_unlock_irq(&np->lock);
+ }
switch (cmd) {
case SIOCDEVPRIVATE:
for (i=0; i<TX_RING_SIZE; i++) {
static int netdev_close(struct net_device *dev)
{
long ioaddr = dev->base_addr;
- struct netdev_private *np = netdev_priv(dev);
+ struct netdev_private *np = dev->priv;
struct sk_buff *skb;
int i;
struct net_device *dev = pci_get_drvdata(pdev);
if (dev) {
- struct netdev_private *np = netdev_priv(dev);
+ struct netdev_private *np = dev->priv;
unregister_netdev(dev);
pci_free_consistent(pdev, RX_TOTAL_SIZE, np->rx_ring,