Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 34afd638 authored by Jeff Garzik's avatar Jeff Garzik
Browse files

Merge branch 'sis900-wol'

parents 5d06b6be e532c378
Loading
Loading
Loading
Loading
+71 −2
Original line number Diff line number Diff line
/* sis900.c: A SiS 900/7016 PCI Fast Ethernet driver for Linux.
   Copyright 1999 Silicon Integrated System Corporation 
   Revision:	1.08.08 Jan. 22 2005
   Revision:	1.08.09 Sep. 19 2005
   
   Modified from the driver which is originally written by Donald Becker.
   
@@ -17,6 +17,7 @@
   SiS 7014 Single Chip 100BASE-TX/10BASE-T Physical Layer Solution,
   preliminary Rev. 1.0 Jan. 18, 1998

   Rev 1.08.09 Sep. 19 2005 Daniele Venzano add Wake on LAN support
   Rev 1.08.08 Jan. 22 2005 Daniele Venzano use netif_msg for debugging messages
   Rev 1.08.07 Nov.  2 2003 Daniele Venzano <webvenza@libero.it> add suspend/resume support
   Rev 1.08.06 Sep. 24 2002 Mufasa Yang bug fix for Tx timeout & add SiS963 support
@@ -76,7 +77,7 @@
#include "sis900.h"

#define SIS900_MODULE_NAME "sis900"
#define SIS900_DRV_VERSION "v1.08.08 Jan. 22 2005"
#define SIS900_DRV_VERSION "v1.08.09 Sep. 19 2005"

static char version[] __devinitdata =
KERN_INFO "sis900.c: " SIS900_DRV_VERSION "\n";
@@ -538,6 +539,11 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev,
		printk("%2.2x:", (u8)net_dev->dev_addr[i]);
	printk("%2.2x.\n", net_dev->dev_addr[i]);

	/* Detect Wake on Lan support */
	ret = inl(CFGPMC & PMESP);
	if (netif_msg_probe(sis_priv) && (ret & PME_D3C) == 0)
		printk(KERN_INFO "%s: Wake on LAN only available from suspend to RAM.", net_dev->name);

	return 0;

 err_unmap_rx:
@@ -2015,6 +2021,67 @@ static int sis900_nway_reset(struct net_device *net_dev)
	return mii_nway_restart(&sis_priv->mii_info);
}

/**
 *	sis900_set_wol - Set up Wake on Lan registers
 *	@net_dev: the net device to probe
 *	@wol: container for info passed to the driver
 *
 *	Process ethtool command "wol" to setup wake on lan features.
 *	SiS900 supports sending WoL events if a correct packet is received,
 *	but there is no simple way to filter them to only a subset (broadcast,
 *	multicast, unicast or arp).
 */
 
static int sis900_set_wol(struct net_device *net_dev, struct ethtool_wolinfo *wol)
{
	struct sis900_private *sis_priv = net_dev->priv;
	long pmctrl_addr = net_dev->base_addr + pmctrl;
	u32 cfgpmcsr = 0, pmctrl_bits = 0;

	if (wol->wolopts == 0) {
		pci_read_config_dword(sis_priv->pci_dev, CFGPMCSR, &cfgpmcsr);
		cfgpmcsr |= ~PME_EN;
		pci_write_config_dword(sis_priv->pci_dev, CFGPMCSR, cfgpmcsr);
		outl(pmctrl_bits, pmctrl_addr);
		if (netif_msg_wol(sis_priv))
			printk(KERN_DEBUG "%s: Wake on LAN disabled\n", net_dev->name);
		return 0;
	}

	if (wol->wolopts & (WAKE_MAGICSECURE | WAKE_UCAST | WAKE_MCAST
				| WAKE_BCAST | WAKE_ARP))
		return -EINVAL;

	if (wol->wolopts & WAKE_MAGIC)
		pmctrl_bits |= MAGICPKT;
	if (wol->wolopts & WAKE_PHY)
		pmctrl_bits |= LINKON;
	
	outl(pmctrl_bits, pmctrl_addr);

	pci_read_config_dword(sis_priv->pci_dev, CFGPMCSR, &cfgpmcsr);
	cfgpmcsr |= PME_EN;
	pci_write_config_dword(sis_priv->pci_dev, CFGPMCSR, cfgpmcsr);
	if (netif_msg_wol(sis_priv))
		printk(KERN_DEBUG "%s: Wake on LAN enabled\n", net_dev->name);

	return 0;
}

static void sis900_get_wol(struct net_device *net_dev, struct ethtool_wolinfo *wol)
{
	long pmctrl_addr = net_dev->base_addr + pmctrl;
	u32 pmctrl_bits;

	pmctrl_bits = inl(pmctrl_addr);
	if (pmctrl_bits & MAGICPKT)
		wol->wolopts |= WAKE_MAGIC;
	if (pmctrl_bits & LINKON)
		wol->wolopts |= WAKE_PHY;

	wol->supported = (WAKE_PHY | WAKE_MAGIC);
}

static struct ethtool_ops sis900_ethtool_ops = {
	.get_drvinfo 	= sis900_get_drvinfo,
	.get_msglevel	= sis900_get_msglevel,
@@ -2023,6 +2090,8 @@ static struct ethtool_ops sis900_ethtool_ops = {
	.get_settings	= sis900_get_settings,
	.set_settings	= sis900_set_settings,
	.nway_reset	= sis900_nway_reset,
	.get_wol	= sis900_get_wol,
	.set_wol	= sis900_set_wol
};

/**
+45 −0
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ enum sis900_registers {
        rxcfg=0x34,             //Receive Configuration Register
        flctrl=0x38,            //Flow Control Register
        rxlen=0x3c,             //Receive Packet Length Register
        cfgpmcsr=0x44,          //Configuration Power Management Control/Status Register
        rfcr=0x48,              //Receive Filter Control Register
        rfdr=0x4C,              //Receive Filter Data Register
        pmctrl=0xB0,            //Power Management Control Register
@@ -140,6 +141,50 @@ enum sis96x_eeprom_command {
	EEREQ = 0x00000400, EEDONE = 0x00000200, EEGNT = 0x00000100
};

/* PCI Registers */
enum sis900_pci_registers {
	CFGPMC 	 = 0x40,
	CFGPMCSR = 0x44
};

/* Power management capabilities bits */
enum sis900_cfgpmc_register_bits {
	PMVER	= 0x00070000, 
	DSI	= 0x00100000,
	PMESP	= 0xf8000000
};

enum sis900_pmesp_bits {
	PME_D0 = 0x1,
	PME_D1 = 0x2,
	PME_D2 = 0x4,
	PME_D3H = 0x8,
	PME_D3C = 0x10
};

/* Power management control/status bits */
enum sis900_cfgpmcsr_register_bits {
	PMESTS = 0x00004000,
	PME_EN = 0x00000100, // Power management enable
	PWR_STA = 0x00000003 // Current power state
};

/* Wake-on-LAN support. */
enum sis900_power_management_control_register_bits {
	LINKLOSS  = 0x00000001,
	LINKON    = 0x00000002,
	MAGICPKT  = 0x00000400,
	ALGORITHM = 0x00000800,
	FRM1EN    = 0x00100000,
	FRM2EN    = 0x00200000,
	FRM3EN    = 0x00400000,
	FRM1ACS   = 0x01000000,
	FRM2ACS   = 0x02000000,
	FRM3ACS   = 0x04000000,
	WAKEALL   = 0x40000000,
	GATECLK   = 0x80000000
};

/* Management Data I/O (mdio) frame */
#define MIIread         0x6000
#define MIIwrite        0x5002