xref: /linux/drivers/net/ethernet/sis/sis900.c (revision 621cde16e49b3ecf7d59a8106a20aaebfb4a59a9)
18c7de408SJeff Kirsher /* sis900.c: A SiS 900/7016 PCI Fast Ethernet driver for Linux.
28c7de408SJeff Kirsher    Copyright 1999 Silicon Integrated System Corporation
38c7de408SJeff Kirsher    Revision:	1.08.10 Apr. 2 2006
48c7de408SJeff Kirsher 
58c7de408SJeff Kirsher    Modified from the driver which is originally written by Donald Becker.
68c7de408SJeff Kirsher 
78c7de408SJeff Kirsher    This software may be used and distributed according to the terms
88c7de408SJeff Kirsher    of the GNU General Public License (GPL), incorporated herein by reference.
98c7de408SJeff Kirsher    Drivers based on this skeleton fall under the GPL and must retain
108c7de408SJeff Kirsher    the authorship (implicit copyright) notice.
118c7de408SJeff Kirsher 
128c7de408SJeff Kirsher    References:
138c7de408SJeff Kirsher    SiS 7016 Fast Ethernet PCI Bus 10/100 Mbps LAN Controller with OnNow Support,
148c7de408SJeff Kirsher    preliminary Rev. 1.0 Jan. 14, 1998
158c7de408SJeff Kirsher    SiS 900 Fast Ethernet PCI Bus 10/100 Mbps LAN Single Chip with OnNow Support,
168c7de408SJeff Kirsher    preliminary Rev. 1.0 Nov. 10, 1998
178c7de408SJeff Kirsher    SiS 7014 Single Chip 100BASE-TX/10BASE-T Physical Layer Solution,
188c7de408SJeff Kirsher    preliminary Rev. 1.0 Jan. 18, 1998
198c7de408SJeff Kirsher 
208c7de408SJeff Kirsher    Rev 1.08.10 Apr.  2 2006 Daniele Venzano add vlan (jumbo packets) support
218c7de408SJeff Kirsher    Rev 1.08.09 Sep. 19 2005 Daniele Venzano add Wake on LAN support
228c7de408SJeff Kirsher    Rev 1.08.08 Jan. 22 2005 Daniele Venzano use netif_msg for debugging messages
238c7de408SJeff Kirsher    Rev 1.08.07 Nov.  2 2003 Daniele Venzano <venza@brownhat.org> add suspend/resume support
248c7de408SJeff Kirsher    Rev 1.08.06 Sep. 24 2002 Mufasa Yang bug fix for Tx timeout & add SiS963 support
258c7de408SJeff Kirsher    Rev 1.08.05 Jun.  6 2002 Mufasa Yang bug fix for read_eeprom & Tx descriptor over-boundary
268c7de408SJeff Kirsher    Rev 1.08.04 Apr. 25 2002 Mufasa Yang <mufasa@sis.com.tw> added SiS962 support
278c7de408SJeff Kirsher    Rev 1.08.03 Feb.  1 2002 Matt Domsch <Matt_Domsch@dell.com> update to use library crc32 function
288c7de408SJeff Kirsher    Rev 1.08.02 Nov. 30 2001 Hui-Fen Hsu workaround for EDB & bug fix for dhcp problem
298c7de408SJeff Kirsher    Rev 1.08.01 Aug. 25 2001 Hui-Fen Hsu update for 630ET & workaround for ICS1893 PHY
308c7de408SJeff Kirsher    Rev 1.08.00 Jun. 11 2001 Hui-Fen Hsu workaround for RTL8201 PHY and some bug fix
318c7de408SJeff Kirsher    Rev 1.07.11 Apr.  2 2001 Hui-Fen Hsu updates PCI drivers to use the new pci_set_dma_mask for kernel 2.4.3
328c7de408SJeff Kirsher    Rev 1.07.10 Mar.  1 2001 Hui-Fen Hsu <hfhsu@sis.com.tw> some bug fix & 635M/B support
338c7de408SJeff Kirsher    Rev 1.07.09 Feb.  9 2001 Dave Jones <davej@suse.de> PCI enable cleanup
348c7de408SJeff Kirsher    Rev 1.07.08 Jan.  8 2001 Lei-Chun Chang added RTL8201 PHY support
358c7de408SJeff Kirsher    Rev 1.07.07 Nov. 29 2000 Lei-Chun Chang added kernel-doc extractable documentation and 630 workaround fix
368c7de408SJeff Kirsher    Rev 1.07.06 Nov.  7 2000 Jeff Garzik <jgarzik@pobox.com> some bug fix and cleaning
378c7de408SJeff Kirsher    Rev 1.07.05 Nov.  6 2000 metapirat<metapirat@gmx.de> contribute media type select by ifconfig
388c7de408SJeff Kirsher    Rev 1.07.04 Sep.  6 2000 Lei-Chun Chang added ICS1893 PHY support
398c7de408SJeff Kirsher    Rev 1.07.03 Aug. 24 2000 Lei-Chun Chang (lcchang@sis.com.tw) modified 630E equalizer workaround rule
408c7de408SJeff Kirsher    Rev 1.07.01 Aug. 08 2000 Ollie Lho minor update for SiS 630E and SiS 630E A1
418c7de408SJeff Kirsher    Rev 1.07    Mar. 07 2000 Ollie Lho bug fix in Rx buffer ring
428c7de408SJeff Kirsher    Rev 1.06.04 Feb. 11 2000 Jeff Garzik <jgarzik@pobox.com> softnet and init for kernel 2.4
438c7de408SJeff Kirsher    Rev 1.06.03 Dec. 23 1999 Ollie Lho Third release
448c7de408SJeff Kirsher    Rev 1.06.02 Nov. 23 1999 Ollie Lho bug in mac probing fixed
458c7de408SJeff Kirsher    Rev 1.06.01 Nov. 16 1999 Ollie Lho CRC calculation provide by Joseph Zbiciak (im14u2c@primenet.com)
468c7de408SJeff Kirsher    Rev 1.06 Nov. 4 1999 Ollie Lho (ollie@sis.com.tw) Second release
478c7de408SJeff Kirsher    Rev 1.05.05 Oct. 29 1999 Ollie Lho (ollie@sis.com.tw) Single buffer Tx/Rx
488c7de408SJeff Kirsher    Chin-Shan Li (lcs@sis.com.tw) Added AMD Am79c901 HomePNA PHY support
498c7de408SJeff Kirsher    Rev 1.05 Aug. 7 1999 Jim Huang (cmhuang@sis.com.tw) Initial release
508c7de408SJeff Kirsher */
518c7de408SJeff Kirsher 
528c7de408SJeff Kirsher #include <linux/module.h>
538c7de408SJeff Kirsher #include <linux/moduleparam.h>
548c7de408SJeff Kirsher #include <linux/kernel.h>
558c7de408SJeff Kirsher #include <linux/sched.h>
568c7de408SJeff Kirsher #include <linux/string.h>
578c7de408SJeff Kirsher #include <linux/timer.h>
588c7de408SJeff Kirsher #include <linux/errno.h>
598c7de408SJeff Kirsher #include <linux/ioport.h>
608c7de408SJeff Kirsher #include <linux/slab.h>
618c7de408SJeff Kirsher #include <linux/interrupt.h>
628c7de408SJeff Kirsher #include <linux/pci.h>
638c7de408SJeff Kirsher #include <linux/netdevice.h>
648c7de408SJeff Kirsher #include <linux/init.h>
658c7de408SJeff Kirsher #include <linux/mii.h>
668c7de408SJeff Kirsher #include <linux/etherdevice.h>
678c7de408SJeff Kirsher #include <linux/skbuff.h>
688c7de408SJeff Kirsher #include <linux/delay.h>
698c7de408SJeff Kirsher #include <linux/ethtool.h>
708c7de408SJeff Kirsher #include <linux/crc32.h>
718c7de408SJeff Kirsher #include <linux/bitops.h>
728c7de408SJeff Kirsher #include <linux/dma-mapping.h>
738c7de408SJeff Kirsher 
748c7de408SJeff Kirsher #include <asm/processor.h>      /* Processor type for cache alignment. */
758c7de408SJeff Kirsher #include <asm/io.h>
768c7de408SJeff Kirsher #include <asm/irq.h>
777c0f6ba6SLinus Torvalds #include <linux/uaccess.h>	/* User space memory access functions */
788c7de408SJeff Kirsher 
798c7de408SJeff Kirsher #include "sis900.h"
808c7de408SJeff Kirsher 
818c7de408SJeff Kirsher #define SIS900_MODULE_NAME "sis900"
828c7de408SJeff Kirsher #define SIS900_DRV_VERSION "v1.08.10 Apr. 2 2006"
838c7de408SJeff Kirsher 
84369e1231SBill Pemberton static const char version[] =
858c7de408SJeff Kirsher 	KERN_INFO "sis900.c: " SIS900_DRV_VERSION "\n";
868c7de408SJeff Kirsher 
878c7de408SJeff Kirsher static int max_interrupt_work = 40;
888c7de408SJeff Kirsher static int multicast_filter_limit = 128;
898c7de408SJeff Kirsher 
908c7de408SJeff Kirsher static int sis900_debug = -1; /* Use SIS900_DEF_MSG as value */
918c7de408SJeff Kirsher 
928c7de408SJeff Kirsher #define SIS900_DEF_MSG \
938c7de408SJeff Kirsher 	(NETIF_MSG_DRV		| \
948c7de408SJeff Kirsher 	 NETIF_MSG_LINK		| \
958c7de408SJeff Kirsher 	 NETIF_MSG_RX_ERR	| \
968c7de408SJeff Kirsher 	 NETIF_MSG_TX_ERR)
978c7de408SJeff Kirsher 
988c7de408SJeff Kirsher /* Time in jiffies before concluding the transmitter is hung. */
998c7de408SJeff Kirsher #define TX_TIMEOUT  (4*HZ)
1008c7de408SJeff Kirsher 
1018c7de408SJeff Kirsher enum {
1028c7de408SJeff Kirsher 	SIS_900 = 0,
1038c7de408SJeff Kirsher 	SIS_7016
1048c7de408SJeff Kirsher };
1058c7de408SJeff Kirsher static const char * card_names[] = {
1068c7de408SJeff Kirsher 	"SiS 900 PCI Fast Ethernet",
1078c7de408SJeff Kirsher 	"SiS 7016 PCI Fast Ethernet"
1088c7de408SJeff Kirsher };
1099baa3c34SBenoit Taine 
1109baa3c34SBenoit Taine static const struct pci_device_id sis900_pci_tbl[] = {
1118c7de408SJeff Kirsher 	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_900,
1128c7de408SJeff Kirsher 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS_900},
1138c7de408SJeff Kirsher 	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_7016,
1148c7de408SJeff Kirsher 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS_7016},
1158c7de408SJeff Kirsher 	{0,}
1168c7de408SJeff Kirsher };
1178c7de408SJeff Kirsher MODULE_DEVICE_TABLE (pci, sis900_pci_tbl);
1188c7de408SJeff Kirsher 
1198c7de408SJeff Kirsher static void sis900_read_mode(struct net_device *net_dev, int *speed, int *duplex);
1208c7de408SJeff Kirsher 
1218c7de408SJeff Kirsher static const struct mii_chip_info {
1228c7de408SJeff Kirsher 	const char * name;
1238c7de408SJeff Kirsher 	u16 phy_id0;
1248c7de408SJeff Kirsher 	u16 phy_id1;
1258c7de408SJeff Kirsher 	u8  phy_types;
1268c7de408SJeff Kirsher #define	HOME 	0x0001
1278c7de408SJeff Kirsher #define LAN	0x0002
1288c7de408SJeff Kirsher #define MIX	0x0003
1298c7de408SJeff Kirsher #define UNKNOWN	0x0
1308c7de408SJeff Kirsher } mii_chip_table[] = {
1318c7de408SJeff Kirsher 	{ "SiS 900 Internal MII PHY", 		0x001d, 0x8000, LAN },
1328c7de408SJeff Kirsher 	{ "SiS 7014 Physical Layer Solution", 	0x0016, 0xf830, LAN },
1338c7de408SJeff Kirsher 	{ "SiS 900 on Foxconn 661 7MI",         0x0143, 0xBC70, LAN },
1348c7de408SJeff Kirsher 	{ "Altimata AC101LF PHY",               0x0022, 0x5520, LAN },
1358c7de408SJeff Kirsher 	{ "ADM 7001 LAN PHY",			0x002e, 0xcc60, LAN },
1368c7de408SJeff Kirsher 	{ "AMD 79C901 10BASE-T PHY",  		0x0000, 0x6B70, LAN },
1378c7de408SJeff Kirsher 	{ "AMD 79C901 HomePNA PHY",		0x0000, 0x6B90, HOME},
1388c7de408SJeff Kirsher 	{ "ICS LAN PHY",			0x0015, 0xF440, LAN },
1398c7de408SJeff Kirsher 	{ "ICS LAN PHY",			0x0143, 0xBC70, LAN },
1408c7de408SJeff Kirsher 	{ "NS 83851 PHY",			0x2000, 0x5C20, MIX },
1418c7de408SJeff Kirsher 	{ "NS 83847 PHY",                       0x2000, 0x5C30, MIX },
1428c7de408SJeff Kirsher 	{ "Realtek RTL8201 PHY",		0x0000, 0x8200, LAN },
1438c7de408SJeff Kirsher 	{ "VIA 6103 PHY",			0x0101, 0x8f20, LAN },
1448c7de408SJeff Kirsher 	{NULL,},
1458c7de408SJeff Kirsher };
1468c7de408SJeff Kirsher 
1478c7de408SJeff Kirsher struct mii_phy {
1488c7de408SJeff Kirsher 	struct mii_phy * next;
1498c7de408SJeff Kirsher 	int phy_addr;
1508c7de408SJeff Kirsher 	u16 phy_id0;
1518c7de408SJeff Kirsher 	u16 phy_id1;
1528c7de408SJeff Kirsher 	u16 status;
1538c7de408SJeff Kirsher 	u8  phy_types;
1548c7de408SJeff Kirsher };
1558c7de408SJeff Kirsher 
1568c7de408SJeff Kirsher typedef struct _BufferDesc {
1578c7de408SJeff Kirsher 	u32 link;
1588c7de408SJeff Kirsher 	u32 cmdsts;
1598c7de408SJeff Kirsher 	u32 bufptr;
1608c7de408SJeff Kirsher } BufferDesc;
1618c7de408SJeff Kirsher 
1628c7de408SJeff Kirsher struct sis900_private {
1638c7de408SJeff Kirsher 	struct pci_dev * pci_dev;
1648c7de408SJeff Kirsher 
1658c7de408SJeff Kirsher 	spinlock_t lock;
1668c7de408SJeff Kirsher 
1678c7de408SJeff Kirsher 	struct mii_phy * mii;
1688c7de408SJeff Kirsher 	struct mii_phy * first_mii; /* record the first mii structure */
1698c7de408SJeff Kirsher 	unsigned int cur_phy;
1708c7de408SJeff Kirsher 	struct mii_if_info mii_info;
1718c7de408SJeff Kirsher 
17257d6d456SFrancois Romieu 	void __iomem	*ioaddr;
17357d6d456SFrancois Romieu 
1748c7de408SJeff Kirsher 	struct timer_list timer; /* Link status detection timer. */
1758c7de408SJeff Kirsher 	u8 autong_complete; /* 1: auto-negotiate complete  */
1768c7de408SJeff Kirsher 
1778c7de408SJeff Kirsher 	u32 msg_enable;
1788c7de408SJeff Kirsher 
1793f8b6fb7SMasahiro Yamada 	unsigned int cur_rx, dirty_rx; /* producer/consumer pointers for Tx/Rx ring */
1808c7de408SJeff Kirsher 	unsigned int cur_tx, dirty_tx;
1818c7de408SJeff Kirsher 
1828c7de408SJeff Kirsher 	/* The saved address of a sent/receive-in-place packet buffer */
1838c7de408SJeff Kirsher 	struct sk_buff *tx_skbuff[NUM_TX_DESC];
1848c7de408SJeff Kirsher 	struct sk_buff *rx_skbuff[NUM_RX_DESC];
1858c7de408SJeff Kirsher 	BufferDesc *tx_ring;
1868c7de408SJeff Kirsher 	BufferDesc *rx_ring;
1878c7de408SJeff Kirsher 
1888c7de408SJeff Kirsher 	dma_addr_t tx_ring_dma;
1898c7de408SJeff Kirsher 	dma_addr_t rx_ring_dma;
1908c7de408SJeff Kirsher 
1918c7de408SJeff Kirsher 	unsigned int tx_full; /* The Tx queue is full. */
1928c7de408SJeff Kirsher 	u8 host_bridge_rev;
1938c7de408SJeff Kirsher 	u8 chipset_rev;
194cd8ae207SSergej Benilov 	/* EEPROM data */
195cd8ae207SSergej Benilov 	int eeprom_size;
1968c7de408SJeff Kirsher };
1978c7de408SJeff Kirsher 
1988c7de408SJeff Kirsher MODULE_AUTHOR("Jim Huang <cmhuang@sis.com.tw>, Ollie Lho <ollie@sis.com.tw>");
1998c7de408SJeff Kirsher MODULE_DESCRIPTION("SiS 900 PCI Fast Ethernet driver");
2008c7de408SJeff Kirsher MODULE_LICENSE("GPL");
2018c7de408SJeff Kirsher 
2028c7de408SJeff Kirsher module_param(multicast_filter_limit, int, 0444);
2038c7de408SJeff Kirsher module_param(max_interrupt_work, int, 0444);
2048c7de408SJeff Kirsher module_param(sis900_debug, int, 0444);
2058c7de408SJeff Kirsher MODULE_PARM_DESC(multicast_filter_limit, "SiS 900/7016 maximum number of filtered multicast addresses");
2068c7de408SJeff Kirsher MODULE_PARM_DESC(max_interrupt_work, "SiS 900/7016 maximum events handled per interrupt");
2078c7de408SJeff Kirsher MODULE_PARM_DESC(sis900_debug, "SiS 900/7016 bitmapped debugging message level");
2088c7de408SJeff Kirsher 
20957d6d456SFrancois Romieu #define sw32(reg, val)	iowrite32(val, ioaddr + (reg))
21057d6d456SFrancois Romieu #define sw8(reg, val)	iowrite8(val, ioaddr + (reg))
21157d6d456SFrancois Romieu #define sr32(reg)	ioread32(ioaddr + (reg))
21257d6d456SFrancois Romieu #define sr16(reg)	ioread16(ioaddr + (reg))
21357d6d456SFrancois Romieu 
2148c7de408SJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER
2158c7de408SJeff Kirsher static void sis900_poll(struct net_device *dev);
2168c7de408SJeff Kirsher #endif
2178c7de408SJeff Kirsher static int sis900_open(struct net_device *net_dev);
2188c7de408SJeff Kirsher static int sis900_mii_probe (struct net_device * net_dev);
2198c7de408SJeff Kirsher static void sis900_init_rxfilter (struct net_device * net_dev);
22057d6d456SFrancois Romieu static u16 read_eeprom(void __iomem *ioaddr, int location);
2218c7de408SJeff Kirsher static int mdio_read(struct net_device *net_dev, int phy_id, int location);
2228c7de408SJeff Kirsher static void mdio_write(struct net_device *net_dev, int phy_id, int location, int val);
223fd71e13bSKees Cook static void sis900_timer(struct timer_list *t);
2248c7de408SJeff Kirsher static void sis900_check_mode (struct net_device *net_dev, struct mii_phy *mii_phy);
2250290bd29SMichael S. Tsirkin static void sis900_tx_timeout(struct net_device *net_dev, unsigned int txqueue);
2268c7de408SJeff Kirsher static void sis900_init_tx_ring(struct net_device *net_dev);
2278c7de408SJeff Kirsher static void sis900_init_rx_ring(struct net_device *net_dev);
2288c7de408SJeff Kirsher static netdev_tx_t sis900_start_xmit(struct sk_buff *skb,
2298c7de408SJeff Kirsher 				     struct net_device *net_dev);
2308c7de408SJeff Kirsher static int sis900_rx(struct net_device *net_dev);
2318c7de408SJeff Kirsher static void sis900_finish_xmit (struct net_device *net_dev);
2328c7de408SJeff Kirsher static irqreturn_t sis900_interrupt(int irq, void *dev_instance);
2338c7de408SJeff Kirsher static int sis900_close(struct net_device *net_dev);
2348c7de408SJeff Kirsher static int mii_ioctl(struct net_device *net_dev, struct ifreq *rq, int cmd);
2358c7de408SJeff Kirsher static u16 sis900_mcast_bitnr(u8 *addr, u8 revision);
2368c7de408SJeff Kirsher static void set_rx_mode(struct net_device *net_dev);
2378c7de408SJeff Kirsher static void sis900_reset(struct net_device *net_dev);
2388c7de408SJeff Kirsher static void sis630_set_eq(struct net_device *net_dev, u8 revision);
2398c7de408SJeff Kirsher static int sis900_set_config(struct net_device *dev, struct ifmap *map);
2408c7de408SJeff Kirsher static u16 sis900_default_phy(struct net_device * net_dev);
2418c7de408SJeff Kirsher static void sis900_set_capability( struct net_device *net_dev ,struct mii_phy *phy);
2428c7de408SJeff Kirsher static u16 sis900_reset_phy(struct net_device *net_dev, int phy_addr);
2438c7de408SJeff Kirsher static void sis900_auto_negotiate(struct net_device *net_dev, int phy_addr);
24457d6d456SFrancois Romieu static void sis900_set_mode(struct sis900_private *, int speed, int duplex);
2458c7de408SJeff Kirsher static const struct ethtool_ops sis900_ethtool_ops;
2468c7de408SJeff Kirsher 
2478c7de408SJeff Kirsher /**
2488c7de408SJeff Kirsher  *	sis900_get_mac_addr - Get MAC address for stand alone SiS900 model
2498c7de408SJeff Kirsher  *	@pci_dev: the sis900 pci device
2508c7de408SJeff Kirsher  *	@net_dev: the net device to get address for
2518c7de408SJeff Kirsher  *
2528c7de408SJeff Kirsher  *	Older SiS900 and friends, use EEPROM to store MAC address.
253aaeb6cdfSJiri Pirko  *	MAC address is read from read_eeprom() into @net_dev->dev_addr.
2548c7de408SJeff Kirsher  */
2558c7de408SJeff Kirsher 
sis900_get_mac_addr(struct pci_dev * pci_dev,struct net_device * net_dev)256369e1231SBill Pemberton static int sis900_get_mac_addr(struct pci_dev *pci_dev,
257369e1231SBill Pemberton 			       struct net_device *net_dev)
2588c7de408SJeff Kirsher {
25957d6d456SFrancois Romieu 	struct sis900_private *sis_priv = netdev_priv(net_dev);
26057d6d456SFrancois Romieu 	void __iomem *ioaddr = sis_priv->ioaddr;
261923ca6f6SJakub Kicinski 	u16 addr[ETH_ALEN / 2];
2628c7de408SJeff Kirsher 	u16 signature;
2638c7de408SJeff Kirsher 	int i;
2648c7de408SJeff Kirsher 
2658c7de408SJeff Kirsher 	/* check to see if we have sane EEPROM */
2668c7de408SJeff Kirsher 	signature = (u16) read_eeprom(ioaddr, EEPROMSignature);
2678c7de408SJeff Kirsher 	if (signature == 0xffff || signature == 0x0000) {
26879f5943aSSergej Benilov 		printk (KERN_WARNING "%s: Error EEPROM read %x\n",
2698c7de408SJeff Kirsher 			pci_name(pci_dev), signature);
2708c7de408SJeff Kirsher 		return 0;
2718c7de408SJeff Kirsher 	}
2728c7de408SJeff Kirsher 
2738c7de408SJeff Kirsher 	/* get MAC address from EEPROM */
2748c7de408SJeff Kirsher 	for (i = 0; i < 3; i++)
275923ca6f6SJakub Kicinski 	        addr[i] = read_eeprom(ioaddr, i+EEPROMMACAddr);
276923ca6f6SJakub Kicinski 	eth_hw_addr_set(net_dev, (u8 *)addr);
2778c7de408SJeff Kirsher 
2788c7de408SJeff Kirsher 	return 1;
2798c7de408SJeff Kirsher }
2808c7de408SJeff Kirsher 
2818c7de408SJeff Kirsher /**
2828c7de408SJeff Kirsher  *	sis630e_get_mac_addr - Get MAC address for SiS630E model
2838c7de408SJeff Kirsher  *	@pci_dev: the sis900 pci device
2848c7de408SJeff Kirsher  *	@net_dev: the net device to get address for
2858c7de408SJeff Kirsher  *
2868c7de408SJeff Kirsher  *	SiS630E model, use APC CMOS RAM to store MAC address.
2878c7de408SJeff Kirsher  *	APC CMOS RAM is accessed through ISA bridge.
288aaeb6cdfSJiri Pirko  *	MAC address is read into @net_dev->dev_addr.
2898c7de408SJeff Kirsher  */
2908c7de408SJeff Kirsher 
sis630e_get_mac_addr(struct pci_dev * pci_dev,struct net_device * net_dev)291369e1231SBill Pemberton static int sis630e_get_mac_addr(struct pci_dev *pci_dev,
2928c7de408SJeff Kirsher 				struct net_device *net_dev)
2938c7de408SJeff Kirsher {
2948c7de408SJeff Kirsher 	struct pci_dev *isa_bridge = NULL;
29574fad215SJakub Kicinski 	u8 addr[ETH_ALEN];
2968c7de408SJeff Kirsher 	u8 reg;
2978c7de408SJeff Kirsher 	int i;
2988c7de408SJeff Kirsher 
2998c7de408SJeff Kirsher 	isa_bridge = pci_get_device(PCI_VENDOR_ID_SI, 0x0008, isa_bridge);
3008c7de408SJeff Kirsher 	if (!isa_bridge)
3018c7de408SJeff Kirsher 		isa_bridge = pci_get_device(PCI_VENDOR_ID_SI, 0x0018, isa_bridge);
3028c7de408SJeff Kirsher 	if (!isa_bridge) {
3038c7de408SJeff Kirsher 		printk(KERN_WARNING "%s: Can not find ISA bridge\n",
3048c7de408SJeff Kirsher 		       pci_name(pci_dev));
3058c7de408SJeff Kirsher 		return 0;
3068c7de408SJeff Kirsher 	}
3078c7de408SJeff Kirsher 	pci_read_config_byte(isa_bridge, 0x48, &reg);
3088c7de408SJeff Kirsher 	pci_write_config_byte(isa_bridge, 0x48, reg | 0x40);
3098c7de408SJeff Kirsher 
3108c7de408SJeff Kirsher 	for (i = 0; i < 6; i++) {
3118c7de408SJeff Kirsher 		outb(0x09 + i, 0x70);
31274fad215SJakub Kicinski 		addr[i] = inb(0x71);
3138c7de408SJeff Kirsher 	}
31474fad215SJakub Kicinski 	eth_hw_addr_set(net_dev, addr);
3158c7de408SJeff Kirsher 
3168c7de408SJeff Kirsher 	pci_write_config_byte(isa_bridge, 0x48, reg & ~0x40);
3178c7de408SJeff Kirsher 	pci_dev_put(isa_bridge);
3188c7de408SJeff Kirsher 
3198c7de408SJeff Kirsher 	return 1;
3208c7de408SJeff Kirsher }
3218c7de408SJeff Kirsher 
3228c7de408SJeff Kirsher 
3238c7de408SJeff Kirsher /**
3248c7de408SJeff Kirsher  *	sis635_get_mac_addr - Get MAC address for SIS635 model
3258c7de408SJeff Kirsher  *	@pci_dev: the sis900 pci device
3268c7de408SJeff Kirsher  *	@net_dev: the net device to get address for
3278c7de408SJeff Kirsher  *
3288c7de408SJeff Kirsher  *	SiS635 model, set MAC Reload Bit to load Mac address from APC
3298c7de408SJeff Kirsher  *	to rfdr. rfdr is accessed through rfcr. MAC address is read into
330aaeb6cdfSJiri Pirko  *	@net_dev->dev_addr.
3318c7de408SJeff Kirsher  */
3328c7de408SJeff Kirsher 
sis635_get_mac_addr(struct pci_dev * pci_dev,struct net_device * net_dev)333369e1231SBill Pemberton static int sis635_get_mac_addr(struct pci_dev *pci_dev,
3348c7de408SJeff Kirsher 			       struct net_device *net_dev)
3358c7de408SJeff Kirsher {
33657d6d456SFrancois Romieu 	struct sis900_private *sis_priv = netdev_priv(net_dev);
33757d6d456SFrancois Romieu 	void __iomem *ioaddr = sis_priv->ioaddr;
338923ca6f6SJakub Kicinski 	u16 addr[ETH_ALEN / 2];
3398c7de408SJeff Kirsher 	u32 rfcrSave;
3408c7de408SJeff Kirsher 	u32 i;
3418c7de408SJeff Kirsher 
34257d6d456SFrancois Romieu 	rfcrSave = sr32(rfcr);
3438c7de408SJeff Kirsher 
34457d6d456SFrancois Romieu 	sw32(cr, rfcrSave | RELOAD);
34557d6d456SFrancois Romieu 	sw32(cr, 0);
3468c7de408SJeff Kirsher 
3478c7de408SJeff Kirsher 	/* disable packet filtering before setting filter */
34857d6d456SFrancois Romieu 	sw32(rfcr, rfcrSave & ~RFEN);
3498c7de408SJeff Kirsher 
3508c7de408SJeff Kirsher 	/* load MAC addr to filter data register */
3518c7de408SJeff Kirsher 	for (i = 0 ; i < 3 ; i++) {
35257d6d456SFrancois Romieu 		sw32(rfcr, (i << RFADDR_shift));
353923ca6f6SJakub Kicinski 		addr[i] = sr16(rfdr);
3548c7de408SJeff Kirsher 	}
355923ca6f6SJakub Kicinski 	eth_hw_addr_set(net_dev, (u8 *)addr);
3568c7de408SJeff Kirsher 
3578c7de408SJeff Kirsher 	/* enable packet filtering */
35857d6d456SFrancois Romieu 	sw32(rfcr, rfcrSave | RFEN);
3598c7de408SJeff Kirsher 
3608c7de408SJeff Kirsher 	return 1;
3618c7de408SJeff Kirsher }
3628c7de408SJeff Kirsher 
3638c7de408SJeff Kirsher /**
3648c7de408SJeff Kirsher  *	sis96x_get_mac_addr - Get MAC address for SiS962 or SiS963 model
3658c7de408SJeff Kirsher  *	@pci_dev: the sis900 pci device
3668c7de408SJeff Kirsher  *	@net_dev: the net device to get address for
3678c7de408SJeff Kirsher  *
3688c7de408SJeff Kirsher  *	SiS962 or SiS963 model, use EEPROM to store MAC address. And EEPROM
3698c7de408SJeff Kirsher  *	is shared by
37079f5943aSSergej Benilov  *	LAN and 1394. When accessing EEPROM, send EEREQ signal to hardware first
371ee7dd773SSergej Benilov  *	and wait for EEGNT. If EEGNT is ON, EEPROM is permitted to be accessed
37279f5943aSSergej Benilov  *	by LAN, otherwise it is not. After MAC address is read from EEPROM, send
3738c7de408SJeff Kirsher  *	EEDONE signal to refuse EEPROM access by LAN.
3748c7de408SJeff Kirsher  *	The EEPROM map of SiS962 or SiS963 is different to SiS900.
3758c7de408SJeff Kirsher  *	The signature field in SiS962 or SiS963 spec is meaningless.
376aaeb6cdfSJiri Pirko  *	MAC address is read into @net_dev->dev_addr.
3778c7de408SJeff Kirsher  */
3788c7de408SJeff Kirsher 
sis96x_get_mac_addr(struct pci_dev * pci_dev,struct net_device * net_dev)379369e1231SBill Pemberton static int sis96x_get_mac_addr(struct pci_dev *pci_dev,
3808c7de408SJeff Kirsher 			       struct net_device *net_dev)
3818c7de408SJeff Kirsher {
38257d6d456SFrancois Romieu 	struct sis900_private *sis_priv = netdev_priv(net_dev);
38357d6d456SFrancois Romieu 	void __iomem *ioaddr = sis_priv->ioaddr;
384923ca6f6SJakub Kicinski 	u16 addr[ETH_ALEN / 2];
38557d6d456SFrancois Romieu 	int wait, rc = 0;
3868c7de408SJeff Kirsher 
38757d6d456SFrancois Romieu 	sw32(mear, EEREQ);
38857d6d456SFrancois Romieu 	for (wait = 0; wait < 2000; wait++) {
38957d6d456SFrancois Romieu 		if (sr32(mear) & EEGNT) {
39057d6d456SFrancois Romieu 			int i;
3918c7de408SJeff Kirsher 
3928c7de408SJeff Kirsher 			/* get MAC address from EEPROM */
3938c7de408SJeff Kirsher 			for (i = 0; i < 3; i++)
394923ca6f6SJakub Kicinski 			        addr[i] = read_eeprom(ioaddr, i + EEPROMMACAddr);
395923ca6f6SJakub Kicinski 			eth_hw_addr_set(net_dev, (u8 *)addr);
3968c7de408SJeff Kirsher 
39757d6d456SFrancois Romieu 			rc = 1;
39857d6d456SFrancois Romieu 			break;
39957d6d456SFrancois Romieu 		}
4008c7de408SJeff Kirsher 		udelay(1);
4018c7de408SJeff Kirsher 	}
40257d6d456SFrancois Romieu 	sw32(mear, EEDONE);
40357d6d456SFrancois Romieu 	return rc;
4048c7de408SJeff Kirsher }
4058c7de408SJeff Kirsher 
4068c7de408SJeff Kirsher static const struct net_device_ops sis900_netdev_ops = {
4078c7de408SJeff Kirsher 	.ndo_open		 = sis900_open,
4088c7de408SJeff Kirsher 	.ndo_stop		= sis900_close,
4098c7de408SJeff Kirsher 	.ndo_start_xmit		= sis900_start_xmit,
4108c7de408SJeff Kirsher 	.ndo_set_config		= sis900_set_config,
411afc4b13dSJiri Pirko 	.ndo_set_rx_mode	= set_rx_mode,
4128c7de408SJeff Kirsher 	.ndo_validate_addr	= eth_validate_addr,
4138c7de408SJeff Kirsher 	.ndo_set_mac_address 	= eth_mac_addr,
414a7605370SArnd Bergmann 	.ndo_eth_ioctl		= mii_ioctl,
4158c7de408SJeff Kirsher 	.ndo_tx_timeout		= sis900_tx_timeout,
4168c7de408SJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER
4178c7de408SJeff Kirsher         .ndo_poll_controller	= sis900_poll,
4188c7de408SJeff Kirsher #endif
4198c7de408SJeff Kirsher };
4208c7de408SJeff Kirsher 
4218c7de408SJeff Kirsher /**
4228c7de408SJeff Kirsher  *	sis900_probe - Probe for sis900 device
4238c7de408SJeff Kirsher  *	@pci_dev: the sis900 pci device
4248c7de408SJeff Kirsher  *	@pci_id: the pci device ID
4258c7de408SJeff Kirsher  *
4268c7de408SJeff Kirsher  *	Check and probe sis900 net device for @pci_dev.
4278c7de408SJeff Kirsher  *	Get mac address according to the chip revision,
4288c7de408SJeff Kirsher  *	and assign SiS900-specific entries in the device structure.
4298c7de408SJeff Kirsher  *	ie: sis900_open(), sis900_start_xmit(), sis900_close(), etc.
4308c7de408SJeff Kirsher  */
4318c7de408SJeff Kirsher 
sis900_probe(struct pci_dev * pci_dev,const struct pci_device_id * pci_id)432369e1231SBill Pemberton static int sis900_probe(struct pci_dev *pci_dev,
4338c7de408SJeff Kirsher 			const struct pci_device_id *pci_id)
4348c7de408SJeff Kirsher {
4358c7de408SJeff Kirsher 	struct sis900_private *sis_priv;
4368c7de408SJeff Kirsher 	struct net_device *net_dev;
4378c7de408SJeff Kirsher 	struct pci_dev *dev;
4388c7de408SJeff Kirsher 	dma_addr_t ring_dma;
4398c7de408SJeff Kirsher 	void *ring_space;
44057d6d456SFrancois Romieu 	void __iomem *ioaddr;
4418c7de408SJeff Kirsher 	int i, ret;
4428c7de408SJeff Kirsher 	const char *card_name = card_names[pci_id->driver_data];
4438c7de408SJeff Kirsher 	const char *dev_name = pci_name(pci_dev);
4448c7de408SJeff Kirsher 
4458c7de408SJeff Kirsher /* when built into the kernel, we only print version if device is found */
4468c7de408SJeff Kirsher #ifndef MODULE
4478c7de408SJeff Kirsher 	static int printed_version;
4488c7de408SJeff Kirsher 	if (!printed_version++)
4498c7de408SJeff Kirsher 		printk(version);
4508c7de408SJeff Kirsher #endif
4518c7de408SJeff Kirsher 
4528c7de408SJeff Kirsher 	/* setup various bits in PCI command register */
45389fb62fdSWang Hai 	ret = pcim_enable_device(pci_dev);
4548c7de408SJeff Kirsher 	if(ret) return ret;
4558c7de408SJeff Kirsher 
456256ca744SChristophe JAILLET 	i = dma_set_mask(&pci_dev->dev, DMA_BIT_MASK(32));
4578c7de408SJeff Kirsher 	if(i){
4588c7de408SJeff Kirsher 		printk(KERN_ERR "sis900.c: architecture does not support "
4598c7de408SJeff Kirsher 			"32bit PCI busmaster DMA\n");
4608c7de408SJeff Kirsher 		return i;
4618c7de408SJeff Kirsher 	}
4628c7de408SJeff Kirsher 
4638c7de408SJeff Kirsher 	pci_set_master(pci_dev);
4648c7de408SJeff Kirsher 
4658c7de408SJeff Kirsher 	net_dev = alloc_etherdev(sizeof(struct sis900_private));
4668c7de408SJeff Kirsher 	if (!net_dev)
4678c7de408SJeff Kirsher 		return -ENOMEM;
4688c7de408SJeff Kirsher 	SET_NETDEV_DEV(net_dev, &pci_dev->dev);
4698c7de408SJeff Kirsher 
4708c7de408SJeff Kirsher 	/* We do a request_region() to register /proc/ioports info. */
4718c7de408SJeff Kirsher 	ret = pci_request_regions(pci_dev, "sis900");
4728c7de408SJeff Kirsher 	if (ret)
4738c7de408SJeff Kirsher 		goto err_out;
4748c7de408SJeff Kirsher 
47557d6d456SFrancois Romieu 	/* IO region. */
47657d6d456SFrancois Romieu 	ioaddr = pci_iomap(pci_dev, 0, 0);
4770968a9d1SPeter Senna Tschudin 	if (!ioaddr) {
4780968a9d1SPeter Senna Tschudin 		ret = -ENOMEM;
47989fb62fdSWang Hai 		goto err_out;
4800968a9d1SPeter Senna Tschudin 	}
48157d6d456SFrancois Romieu 
4828c7de408SJeff Kirsher 	sis_priv = netdev_priv(net_dev);
48357d6d456SFrancois Romieu 	sis_priv->ioaddr = ioaddr;
4848c7de408SJeff Kirsher 	sis_priv->pci_dev = pci_dev;
4858c7de408SJeff Kirsher 	spin_lock_init(&sis_priv->lock);
4868c7de408SJeff Kirsher 
487cd8ae207SSergej Benilov 	sis_priv->eeprom_size = 24;
488cd8ae207SSergej Benilov 
4898c7de408SJeff Kirsher 	pci_set_drvdata(pci_dev, net_dev);
4908c7de408SJeff Kirsher 
491256ca744SChristophe JAILLET 	ring_space = dma_alloc_coherent(&pci_dev->dev, TX_TOTAL_SIZE,
492256ca744SChristophe JAILLET 					&ring_dma, GFP_KERNEL);
4938c7de408SJeff Kirsher 	if (!ring_space) {
4948c7de408SJeff Kirsher 		ret = -ENOMEM;
49557d6d456SFrancois Romieu 		goto err_out_unmap;
4968c7de408SJeff Kirsher 	}
4978c7de408SJeff Kirsher 	sis_priv->tx_ring = ring_space;
4988c7de408SJeff Kirsher 	sis_priv->tx_ring_dma = ring_dma;
4998c7de408SJeff Kirsher 
500256ca744SChristophe JAILLET 	ring_space = dma_alloc_coherent(&pci_dev->dev, RX_TOTAL_SIZE,
501256ca744SChristophe JAILLET 					&ring_dma, GFP_KERNEL);
5028c7de408SJeff Kirsher 	if (!ring_space) {
5038c7de408SJeff Kirsher 		ret = -ENOMEM;
5048c7de408SJeff Kirsher 		goto err_unmap_tx;
5058c7de408SJeff Kirsher 	}
5068c7de408SJeff Kirsher 	sis_priv->rx_ring = ring_space;
5078c7de408SJeff Kirsher 	sis_priv->rx_ring_dma = ring_dma;
5088c7de408SJeff Kirsher 
5098c7de408SJeff Kirsher 	/* The SiS900-specific entries in the device structure. */
5108c7de408SJeff Kirsher 	net_dev->netdev_ops = &sis900_netdev_ops;
5118c7de408SJeff Kirsher 	net_dev->watchdog_timeo = TX_TIMEOUT;
5128c7de408SJeff Kirsher 	net_dev->ethtool_ops = &sis900_ethtool_ops;
5138c7de408SJeff Kirsher 
5148c7de408SJeff Kirsher 	if (sis900_debug > 0)
5158c7de408SJeff Kirsher 		sis_priv->msg_enable = sis900_debug;
5168c7de408SJeff Kirsher 	else
5178c7de408SJeff Kirsher 		sis_priv->msg_enable = SIS900_DEF_MSG;
5188c7de408SJeff Kirsher 
5198c7de408SJeff Kirsher 	sis_priv->mii_info.dev = net_dev;
5208c7de408SJeff Kirsher 	sis_priv->mii_info.mdio_read = mdio_read;
5218c7de408SJeff Kirsher 	sis_priv->mii_info.mdio_write = mdio_write;
5228c7de408SJeff Kirsher 	sis_priv->mii_info.phy_id_mask = 0x1f;
5238c7de408SJeff Kirsher 	sis_priv->mii_info.reg_num_mask = 0x1f;
5248c7de408SJeff Kirsher 
5258c7de408SJeff Kirsher 	/* Get Mac address according to the chip revision */
5268c7de408SJeff Kirsher 	sis_priv->chipset_rev = pci_dev->revision;
5278c7de408SJeff Kirsher 	if(netif_msg_probe(sis_priv))
5288c7de408SJeff Kirsher 		printk(KERN_DEBUG "%s: detected revision %2.2x, "
5298c7de408SJeff Kirsher 				"trying to get MAC address...\n",
5308c7de408SJeff Kirsher 				dev_name, sis_priv->chipset_rev);
5318c7de408SJeff Kirsher 
5328c7de408SJeff Kirsher 	ret = 0;
5338c7de408SJeff Kirsher 	if (sis_priv->chipset_rev == SIS630E_900_REV)
5348c7de408SJeff Kirsher 		ret = sis630e_get_mac_addr(pci_dev, net_dev);
5358c7de408SJeff Kirsher 	else if ((sis_priv->chipset_rev > 0x81) && (sis_priv->chipset_rev <= 0x90) )
5368c7de408SJeff Kirsher 		ret = sis635_get_mac_addr(pci_dev, net_dev);
5378c7de408SJeff Kirsher 	else if (sis_priv->chipset_rev == SIS96x_900_REV)
5388c7de408SJeff Kirsher 		ret = sis96x_get_mac_addr(pci_dev, net_dev);
5398c7de408SJeff Kirsher 	else
5408c7de408SJeff Kirsher 		ret = sis900_get_mac_addr(pci_dev, net_dev);
5418c7de408SJeff Kirsher 
5428c7de408SJeff Kirsher 	if (!ret || !is_valid_ether_addr(net_dev->dev_addr)) {
543f2cedb63SDanny Kukawka 		eth_hw_addr_random(net_dev);
5448c7de408SJeff Kirsher 		printk(KERN_WARNING "%s: Unreadable or invalid MAC address,"
5458c7de408SJeff Kirsher 				"using random generated one\n", dev_name);
5468c7de408SJeff Kirsher 	}
5478c7de408SJeff Kirsher 
5488c7de408SJeff Kirsher 	/* 630ET : set the mii access mode as software-mode */
5498c7de408SJeff Kirsher 	if (sis_priv->chipset_rev == SIS630ET_900_REV)
55057d6d456SFrancois Romieu 		sw32(cr, ACCESSMODE | sr32(cr));
5518c7de408SJeff Kirsher 
5528c7de408SJeff Kirsher 	/* probe for mii transceiver */
5538c7de408SJeff Kirsher 	if (sis900_mii_probe(net_dev) == 0) {
5548c7de408SJeff Kirsher 		printk(KERN_WARNING "%s: Error probing MII device.\n",
5558c7de408SJeff Kirsher 		       dev_name);
5568c7de408SJeff Kirsher 		ret = -ENODEV;
5578c7de408SJeff Kirsher 		goto err_unmap_rx;
5588c7de408SJeff Kirsher 	}
5598c7de408SJeff Kirsher 
5608c7de408SJeff Kirsher 	/* save our host bridge revision */
5618c7de408SJeff Kirsher 	dev = pci_get_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_630, NULL);
5628c7de408SJeff Kirsher 	if (dev) {
5638c7de408SJeff Kirsher 		sis_priv->host_bridge_rev = dev->revision;
5648c7de408SJeff Kirsher 		pci_dev_put(dev);
5658c7de408SJeff Kirsher 	}
5668c7de408SJeff Kirsher 
5678c7de408SJeff Kirsher 	ret = register_netdev(net_dev);
5688c7de408SJeff Kirsher 	if (ret)
5698c7de408SJeff Kirsher 		goto err_unmap_rx;
5708c7de408SJeff Kirsher 
5718c7de408SJeff Kirsher 	/* print some information about our NIC */
57257d6d456SFrancois Romieu 	printk(KERN_INFO "%s: %s at 0x%p, IRQ %d, %pM\n",
57357d6d456SFrancois Romieu 	       net_dev->name, card_name, ioaddr, pci_dev->irq,
5748c7de408SJeff Kirsher 	       net_dev->dev_addr);
5758c7de408SJeff Kirsher 
5768c7de408SJeff Kirsher 	/* Detect Wake on Lan support */
57757d6d456SFrancois Romieu 	ret = (sr32(CFGPMC) & PMESP) >> 27;
5788c7de408SJeff Kirsher 	if (netif_msg_probe(sis_priv) && (ret & PME_D3C) == 0)
5798c7de408SJeff Kirsher 		printk(KERN_INFO "%s: Wake on LAN only available from suspend to RAM.", net_dev->name);
5808c7de408SJeff Kirsher 
5818c7de408SJeff Kirsher 	return 0;
5828c7de408SJeff Kirsher 
5838c7de408SJeff Kirsher err_unmap_rx:
584256ca744SChristophe JAILLET 	dma_free_coherent(&pci_dev->dev, RX_TOTAL_SIZE, sis_priv->rx_ring,
5858c7de408SJeff Kirsher 			  sis_priv->rx_ring_dma);
5868c7de408SJeff Kirsher err_unmap_tx:
587256ca744SChristophe JAILLET 	dma_free_coherent(&pci_dev->dev, TX_TOTAL_SIZE, sis_priv->tx_ring,
5888c7de408SJeff Kirsher 			  sis_priv->tx_ring_dma);
58957d6d456SFrancois Romieu err_out_unmap:
59057d6d456SFrancois Romieu 	pci_iounmap(pci_dev, ioaddr);
5918c7de408SJeff Kirsher  err_out:
5928c7de408SJeff Kirsher 	free_netdev(net_dev);
5938c7de408SJeff Kirsher 	return ret;
5948c7de408SJeff Kirsher }
5958c7de408SJeff Kirsher 
5968c7de408SJeff Kirsher /**
5978c7de408SJeff Kirsher  *	sis900_mii_probe - Probe MII PHY for sis900
5988c7de408SJeff Kirsher  *	@net_dev: the net device to probe for
5998c7de408SJeff Kirsher  *
6008c7de408SJeff Kirsher  *	Search for total of 32 possible mii phy addresses.
6018c7de408SJeff Kirsher  *	Identify and set current phy if found one,
6028c7de408SJeff Kirsher  *	return error if it failed to found.
6038c7de408SJeff Kirsher  */
6048c7de408SJeff Kirsher 
sis900_mii_probe(struct net_device * net_dev)605369e1231SBill Pemberton static int sis900_mii_probe(struct net_device *net_dev)
6068c7de408SJeff Kirsher {
6078c7de408SJeff Kirsher 	struct sis900_private *sis_priv = netdev_priv(net_dev);
6088c7de408SJeff Kirsher 	const char *dev_name = pci_name(sis_priv->pci_dev);
6098c7de408SJeff Kirsher 	u16 poll_bit = MII_STAT_LINK, status = 0;
6108c7de408SJeff Kirsher 	unsigned long timeout = jiffies + 5 * HZ;
6118c7de408SJeff Kirsher 	int phy_addr;
6128c7de408SJeff Kirsher 
6138c7de408SJeff Kirsher 	sis_priv->mii = NULL;
6148c7de408SJeff Kirsher 
6158c7de408SJeff Kirsher 	/* search for total of 32 possible mii phy addresses */
6168c7de408SJeff Kirsher 	for (phy_addr = 0; phy_addr < 32; phy_addr++) {
6178c7de408SJeff Kirsher 		struct mii_phy * mii_phy = NULL;
6188c7de408SJeff Kirsher 		u16 mii_status;
6198c7de408SJeff Kirsher 		int i;
6208c7de408SJeff Kirsher 
6218c7de408SJeff Kirsher 		mii_phy = NULL;
6228c7de408SJeff Kirsher 		for(i = 0; i < 2; i++)
6238c7de408SJeff Kirsher 			mii_status = mdio_read(net_dev, phy_addr, MII_STATUS);
6248c7de408SJeff Kirsher 
6258c7de408SJeff Kirsher 		if (mii_status == 0xffff || mii_status == 0x0000) {
6268c7de408SJeff Kirsher 			if (netif_msg_probe(sis_priv))
6278c7de408SJeff Kirsher 				printk(KERN_DEBUG "%s: MII at address %d"
6288c7de408SJeff Kirsher 						" not accessible\n",
6298c7de408SJeff Kirsher 						dev_name, phy_addr);
6308c7de408SJeff Kirsher 			continue;
6318c7de408SJeff Kirsher 		}
6328c7de408SJeff Kirsher 
6338c7de408SJeff Kirsher 		if ((mii_phy = kmalloc(sizeof(struct mii_phy), GFP_KERNEL)) == NULL) {
6348c7de408SJeff Kirsher 			mii_phy = sis_priv->first_mii;
6358c7de408SJeff Kirsher 			while (mii_phy) {
6368c7de408SJeff Kirsher 				struct mii_phy *phy;
6378c7de408SJeff Kirsher 				phy = mii_phy;
6388c7de408SJeff Kirsher 				mii_phy = mii_phy->next;
6398c7de408SJeff Kirsher 				kfree(phy);
6408c7de408SJeff Kirsher 			}
6418c7de408SJeff Kirsher 			return 0;
6428c7de408SJeff Kirsher 		}
6438c7de408SJeff Kirsher 
6448c7de408SJeff Kirsher 		mii_phy->phy_id0 = mdio_read(net_dev, phy_addr, MII_PHY_ID0);
6458c7de408SJeff Kirsher 		mii_phy->phy_id1 = mdio_read(net_dev, phy_addr, MII_PHY_ID1);
6468c7de408SJeff Kirsher 		mii_phy->phy_addr = phy_addr;
6478c7de408SJeff Kirsher 		mii_phy->status = mii_status;
6488c7de408SJeff Kirsher 		mii_phy->next = sis_priv->mii;
6498c7de408SJeff Kirsher 		sis_priv->mii = mii_phy;
6508c7de408SJeff Kirsher 		sis_priv->first_mii = mii_phy;
6518c7de408SJeff Kirsher 
6528c7de408SJeff Kirsher 		for (i = 0; mii_chip_table[i].phy_id1; i++)
6538c7de408SJeff Kirsher 			if ((mii_phy->phy_id0 == mii_chip_table[i].phy_id0 ) &&
6548c7de408SJeff Kirsher 			    ((mii_phy->phy_id1 & 0xFFF0) == mii_chip_table[i].phy_id1)){
6558c7de408SJeff Kirsher 				mii_phy->phy_types = mii_chip_table[i].phy_types;
6568c7de408SJeff Kirsher 				if (mii_chip_table[i].phy_types == MIX)
6578c7de408SJeff Kirsher 					mii_phy->phy_types =
6588c7de408SJeff Kirsher 					    (mii_status & (MII_STAT_CAN_TX_FDX | MII_STAT_CAN_TX)) ? LAN : HOME;
6598c7de408SJeff Kirsher 				printk(KERN_INFO "%s: %s transceiver found "
6608c7de408SJeff Kirsher 							"at address %d.\n",
6618c7de408SJeff Kirsher 							dev_name,
6628c7de408SJeff Kirsher 							mii_chip_table[i].name,
6638c7de408SJeff Kirsher 							phy_addr);
6648c7de408SJeff Kirsher 				break;
6658c7de408SJeff Kirsher 			}
6668c7de408SJeff Kirsher 
6678c7de408SJeff Kirsher 		if( !mii_chip_table[i].phy_id1 ) {
6688c7de408SJeff Kirsher 			printk(KERN_INFO "%s: Unknown PHY transceiver found at address %d.\n",
6698c7de408SJeff Kirsher 			       dev_name, phy_addr);
6708c7de408SJeff Kirsher 			mii_phy->phy_types = UNKNOWN;
6718c7de408SJeff Kirsher 		}
6728c7de408SJeff Kirsher 	}
6738c7de408SJeff Kirsher 
6748c7de408SJeff Kirsher 	if (sis_priv->mii == NULL) {
6758c7de408SJeff Kirsher 		printk(KERN_INFO "%s: No MII transceivers found!\n", dev_name);
6768c7de408SJeff Kirsher 		return 0;
6778c7de408SJeff Kirsher 	}
6788c7de408SJeff Kirsher 
6798c7de408SJeff Kirsher 	/* select default PHY for mac */
6808c7de408SJeff Kirsher 	sis_priv->mii = NULL;
6818c7de408SJeff Kirsher 	sis900_default_phy( net_dev );
6828c7de408SJeff Kirsher 
6838c7de408SJeff Kirsher 	/* Reset phy if default phy is internal sis900 */
6848c7de408SJeff Kirsher         if ((sis_priv->mii->phy_id0 == 0x001D) &&
6858c7de408SJeff Kirsher 	    ((sis_priv->mii->phy_id1&0xFFF0) == 0x8000))
6868c7de408SJeff Kirsher 		status = sis900_reset_phy(net_dev, sis_priv->cur_phy);
6878c7de408SJeff Kirsher 
6888c7de408SJeff Kirsher         /* workaround for ICS1893 PHY */
6898c7de408SJeff Kirsher         if ((sis_priv->mii->phy_id0 == 0x0015) &&
6908c7de408SJeff Kirsher             ((sis_priv->mii->phy_id1&0xFFF0) == 0xF440))
6918c7de408SJeff Kirsher 		mdio_write(net_dev, sis_priv->cur_phy, 0x0018, 0xD200);
6928c7de408SJeff Kirsher 
6938c7de408SJeff Kirsher 	if(status & MII_STAT_LINK){
6948c7de408SJeff Kirsher 		while (poll_bit) {
6958c7de408SJeff Kirsher 			yield();
6968c7de408SJeff Kirsher 
6978c7de408SJeff Kirsher 			poll_bit ^= (mdio_read(net_dev, sis_priv->cur_phy, MII_STATUS) & poll_bit);
6988c7de408SJeff Kirsher 			if (time_after_eq(jiffies, timeout)) {
6998c7de408SJeff Kirsher 				printk(KERN_WARNING "%s: reset phy and link down now\n",
7008c7de408SJeff Kirsher 				       dev_name);
7018c7de408SJeff Kirsher 				return -ETIME;
7028c7de408SJeff Kirsher 			}
7038c7de408SJeff Kirsher 		}
7048c7de408SJeff Kirsher 	}
7058c7de408SJeff Kirsher 
7068c7de408SJeff Kirsher 	if (sis_priv->chipset_rev == SIS630E_900_REV) {
7078c7de408SJeff Kirsher 		/* SiS 630E has some bugs on default value of PHY registers */
7088c7de408SJeff Kirsher 		mdio_write(net_dev, sis_priv->cur_phy, MII_ANADV, 0x05e1);
7098c7de408SJeff Kirsher 		mdio_write(net_dev, sis_priv->cur_phy, MII_CONFIG1, 0x22);
7108c7de408SJeff Kirsher 		mdio_write(net_dev, sis_priv->cur_phy, MII_CONFIG2, 0xff00);
7118c7de408SJeff Kirsher 		mdio_write(net_dev, sis_priv->cur_phy, MII_MASK, 0xffc0);
7128c7de408SJeff Kirsher 		//mdio_write(net_dev, sis_priv->cur_phy, MII_CONTROL, 0x1000);
7138c7de408SJeff Kirsher 	}
7148c7de408SJeff Kirsher 
7158c7de408SJeff Kirsher 	if (sis_priv->mii->status & MII_STAT_LINK)
7168c7de408SJeff Kirsher 		netif_carrier_on(net_dev);
7178c7de408SJeff Kirsher 	else
7188c7de408SJeff Kirsher 		netif_carrier_off(net_dev);
7198c7de408SJeff Kirsher 
7208c7de408SJeff Kirsher 	return 1;
7218c7de408SJeff Kirsher }
7228c7de408SJeff Kirsher 
7238c7de408SJeff Kirsher /**
7248c7de408SJeff Kirsher  *	sis900_default_phy - Select default PHY for sis900 mac.
7258c7de408SJeff Kirsher  *	@net_dev: the net device to probe for
7268c7de408SJeff Kirsher  *
7278c7de408SJeff Kirsher  *	Select first detected PHY with link as default.
7288c7de408SJeff Kirsher  *	If no one is link on, select PHY whose types is HOME as default.
7298c7de408SJeff Kirsher  *	If HOME doesn't exist, select LAN.
7308c7de408SJeff Kirsher  */
7318c7de408SJeff Kirsher 
sis900_default_phy(struct net_device * net_dev)7328c7de408SJeff Kirsher static u16 sis900_default_phy(struct net_device * net_dev)
7338c7de408SJeff Kirsher {
7348c7de408SJeff Kirsher 	struct sis900_private *sis_priv = netdev_priv(net_dev);
7358c7de408SJeff Kirsher 	struct mii_phy *phy = NULL, *phy_home = NULL,
7368c7de408SJeff Kirsher 		*default_phy = NULL, *phy_lan = NULL;
7378c7de408SJeff Kirsher 	u16 status;
7388c7de408SJeff Kirsher 
7398c7de408SJeff Kirsher         for (phy=sis_priv->first_mii; phy; phy=phy->next) {
7408c7de408SJeff Kirsher 		status = mdio_read(net_dev, phy->phy_addr, MII_STATUS);
7418c7de408SJeff Kirsher 		status = mdio_read(net_dev, phy->phy_addr, MII_STATUS);
7428c7de408SJeff Kirsher 
7438c7de408SJeff Kirsher 		/* Link ON & Not select default PHY & not ghost PHY */
7448c7de408SJeff Kirsher 		if ((status & MII_STAT_LINK) && !default_phy &&
74568cfe9a2SColin Ian King 		    (phy->phy_types != UNKNOWN)) {
7468c7de408SJeff Kirsher 			default_phy = phy;
74768cfe9a2SColin Ian King 		} else {
7488c7de408SJeff Kirsher 			status = mdio_read(net_dev, phy->phy_addr, MII_CONTROL);
7498c7de408SJeff Kirsher 			mdio_write(net_dev, phy->phy_addr, MII_CONTROL,
7508c7de408SJeff Kirsher 				status | MII_CNTL_AUTO | MII_CNTL_ISOLATE);
7518c7de408SJeff Kirsher 			if (phy->phy_types == HOME)
7528c7de408SJeff Kirsher 				phy_home = phy;
7538c7de408SJeff Kirsher 			else if(phy->phy_types == LAN)
7548c7de408SJeff Kirsher 				phy_lan = phy;
7558c7de408SJeff Kirsher 		}
7568c7de408SJeff Kirsher 	}
7578c7de408SJeff Kirsher 
7588c7de408SJeff Kirsher 	if (!default_phy && phy_home)
7598c7de408SJeff Kirsher 		default_phy = phy_home;
7608c7de408SJeff Kirsher 	else if (!default_phy && phy_lan)
7618c7de408SJeff Kirsher 		default_phy = phy_lan;
7628c7de408SJeff Kirsher 	else if (!default_phy)
7638c7de408SJeff Kirsher 		default_phy = sis_priv->first_mii;
7648c7de408SJeff Kirsher 
7658c7de408SJeff Kirsher 	if (sis_priv->mii != default_phy) {
7668c7de408SJeff Kirsher 		sis_priv->mii = default_phy;
7678c7de408SJeff Kirsher 		sis_priv->cur_phy = default_phy->phy_addr;
7688c7de408SJeff Kirsher 		printk(KERN_INFO "%s: Using transceiver found at address %d as default\n",
7698c7de408SJeff Kirsher 		       pci_name(sis_priv->pci_dev), sis_priv->cur_phy);
7708c7de408SJeff Kirsher 	}
7718c7de408SJeff Kirsher 
7728c7de408SJeff Kirsher 	sis_priv->mii_info.phy_id = sis_priv->cur_phy;
7738c7de408SJeff Kirsher 
7748c7de408SJeff Kirsher 	status = mdio_read(net_dev, sis_priv->cur_phy, MII_CONTROL);
7758c7de408SJeff Kirsher 	status &= (~MII_CNTL_ISOLATE);
7768c7de408SJeff Kirsher 
7778c7de408SJeff Kirsher 	mdio_write(net_dev, sis_priv->cur_phy, MII_CONTROL, status);
7788c7de408SJeff Kirsher 	status = mdio_read(net_dev, sis_priv->cur_phy, MII_STATUS);
7798c7de408SJeff Kirsher 	status = mdio_read(net_dev, sis_priv->cur_phy, MII_STATUS);
7808c7de408SJeff Kirsher 
7818c7de408SJeff Kirsher 	return status;
7828c7de408SJeff Kirsher }
7838c7de408SJeff Kirsher 
7848c7de408SJeff Kirsher 
7858c7de408SJeff Kirsher /**
7868c7de408SJeff Kirsher  * 	sis900_set_capability - set the media capability of network adapter.
7878c7de408SJeff Kirsher  *	@net_dev : the net device to probe for
7888c7de408SJeff Kirsher  *	@phy : default PHY
7898c7de408SJeff Kirsher  *
7908c7de408SJeff Kirsher  *	Set the media capability of network adapter according to
7918c7de408SJeff Kirsher  *	mii status register. It's necessary before auto-negotiate.
7928c7de408SJeff Kirsher  */
7938c7de408SJeff Kirsher 
sis900_set_capability(struct net_device * net_dev,struct mii_phy * phy)7948c7de408SJeff Kirsher static void sis900_set_capability(struct net_device *net_dev, struct mii_phy *phy)
7958c7de408SJeff Kirsher {
7968c7de408SJeff Kirsher 	u16 cap;
7978c7de408SJeff Kirsher 
7987c8c0291SJesse Brandeburg 	mdio_read(net_dev, phy->phy_addr, MII_STATUS);
7997c8c0291SJesse Brandeburg 	mdio_read(net_dev, phy->phy_addr, MII_STATUS);
8008c7de408SJeff Kirsher 
8018c7de408SJeff Kirsher 	cap = MII_NWAY_CSMA_CD |
8028c7de408SJeff Kirsher 		((phy->status & MII_STAT_CAN_TX_FDX)? MII_NWAY_TX_FDX:0) |
8038c7de408SJeff Kirsher 		((phy->status & MII_STAT_CAN_TX)    ? MII_NWAY_TX:0) |
8048c7de408SJeff Kirsher 		((phy->status & MII_STAT_CAN_T_FDX) ? MII_NWAY_T_FDX:0)|
8058c7de408SJeff Kirsher 		((phy->status & MII_STAT_CAN_T)     ? MII_NWAY_T:0);
8068c7de408SJeff Kirsher 
8078c7de408SJeff Kirsher 	mdio_write(net_dev, phy->phy_addr, MII_ANADV, cap);
8088c7de408SJeff Kirsher }
8098c7de408SJeff Kirsher 
8108c7de408SJeff Kirsher 
8118c7de408SJeff Kirsher /* Delay between EEPROM clock transitions. */
81257d6d456SFrancois Romieu #define eeprom_delay()	sr32(mear)
8138c7de408SJeff Kirsher 
8148c7de408SJeff Kirsher /**
8158c7de408SJeff Kirsher  *	read_eeprom - Read Serial EEPROM
8168c7de408SJeff Kirsher  *	@ioaddr: base i/o address
8178c7de408SJeff Kirsher  *	@location: the EEPROM location to read
8188c7de408SJeff Kirsher  *
8198c7de408SJeff Kirsher  *	Read Serial EEPROM through EEPROM Access Register.
8208c7de408SJeff Kirsher  *	Note that location is in word (16 bits) unit
8218c7de408SJeff Kirsher  */
8228c7de408SJeff Kirsher 
read_eeprom(void __iomem * ioaddr,int location)823369e1231SBill Pemberton static u16 read_eeprom(void __iomem *ioaddr, int location)
8248c7de408SJeff Kirsher {
82557d6d456SFrancois Romieu 	u32 read_cmd = location | EEread;
8268c7de408SJeff Kirsher 	int i;
8278c7de408SJeff Kirsher 	u16 retval = 0;
8288c7de408SJeff Kirsher 
82957d6d456SFrancois Romieu 	sw32(mear, 0);
8308c7de408SJeff Kirsher 	eeprom_delay();
83157d6d456SFrancois Romieu 	sw32(mear, EECS);
8328c7de408SJeff Kirsher 	eeprom_delay();
8338c7de408SJeff Kirsher 
8348c7de408SJeff Kirsher 	/* Shift the read command (9) bits out. */
8358c7de408SJeff Kirsher 	for (i = 8; i >= 0; i--) {
8368c7de408SJeff Kirsher 		u32 dataval = (read_cmd & (1 << i)) ? EEDI | EECS : EECS;
83757d6d456SFrancois Romieu 
83857d6d456SFrancois Romieu 		sw32(mear, dataval);
8398c7de408SJeff Kirsher 		eeprom_delay();
84057d6d456SFrancois Romieu 		sw32(mear, dataval | EECLK);
8418c7de408SJeff Kirsher 		eeprom_delay();
8428c7de408SJeff Kirsher 	}
84357d6d456SFrancois Romieu 	sw32(mear, EECS);
8448c7de408SJeff Kirsher 	eeprom_delay();
8458c7de408SJeff Kirsher 
8468c7de408SJeff Kirsher 	/* read the 16-bits data in */
8478c7de408SJeff Kirsher 	for (i = 16; i > 0; i--) {
84857d6d456SFrancois Romieu 		sw32(mear, EECS);
8498c7de408SJeff Kirsher 		eeprom_delay();
85057d6d456SFrancois Romieu 		sw32(mear, EECS | EECLK);
8518c7de408SJeff Kirsher 		eeprom_delay();
85257d6d456SFrancois Romieu 		retval = (retval << 1) | ((sr32(mear) & EEDO) ? 1 : 0);
8538c7de408SJeff Kirsher 		eeprom_delay();
8548c7de408SJeff Kirsher 	}
8558c7de408SJeff Kirsher 
8568c7de408SJeff Kirsher 	/* Terminate the EEPROM access. */
85757d6d456SFrancois Romieu 	sw32(mear, 0);
8588c7de408SJeff Kirsher 	eeprom_delay();
8598c7de408SJeff Kirsher 
8608c7de408SJeff Kirsher 	return retval;
8618c7de408SJeff Kirsher }
8628c7de408SJeff Kirsher 
8638c7de408SJeff Kirsher /* Read and write the MII management registers using software-generated
8648c7de408SJeff Kirsher    serial MDIO protocol. Note that the command bits and data bits are
8658c7de408SJeff Kirsher    send out separately */
86657d6d456SFrancois Romieu #define mdio_delay()	sr32(mear)
8678c7de408SJeff Kirsher 
mdio_idle(struct sis900_private * sp)86857d6d456SFrancois Romieu static void mdio_idle(struct sis900_private *sp)
8698c7de408SJeff Kirsher {
87057d6d456SFrancois Romieu 	void __iomem *ioaddr = sp->ioaddr;
87157d6d456SFrancois Romieu 
87257d6d456SFrancois Romieu 	sw32(mear, MDIO | MDDIR);
8738c7de408SJeff Kirsher 	mdio_delay();
87457d6d456SFrancois Romieu 	sw32(mear, MDIO | MDDIR | MDC);
8758c7de408SJeff Kirsher }
8768c7de408SJeff Kirsher 
87757d6d456SFrancois Romieu /* Synchronize the MII management interface by shifting 32 one bits out. */
mdio_reset(struct sis900_private * sp)87857d6d456SFrancois Romieu static void mdio_reset(struct sis900_private *sp)
8798c7de408SJeff Kirsher {
88057d6d456SFrancois Romieu 	void __iomem *ioaddr = sp->ioaddr;
8818c7de408SJeff Kirsher 	int i;
8828c7de408SJeff Kirsher 
8838c7de408SJeff Kirsher 	for (i = 31; i >= 0; i--) {
88457d6d456SFrancois Romieu 		sw32(mear, MDDIR | MDIO);
8858c7de408SJeff Kirsher 		mdio_delay();
88657d6d456SFrancois Romieu 		sw32(mear, MDDIR | MDIO | MDC);
8878c7de408SJeff Kirsher 		mdio_delay();
8888c7de408SJeff Kirsher 	}
8898c7de408SJeff Kirsher }
8908c7de408SJeff Kirsher 
8918c7de408SJeff Kirsher /**
8928c7de408SJeff Kirsher  *	mdio_read - read MII PHY register
8938c7de408SJeff Kirsher  *	@net_dev: the net device to read
8948c7de408SJeff Kirsher  *	@phy_id: the phy address to read
895ee7dd773SSergej Benilov  *	@location: the phy register id to read
8968c7de408SJeff Kirsher  *
8978c7de408SJeff Kirsher  *	Read MII registers through MDIO and MDC
8988c7de408SJeff Kirsher  *	using MDIO management frame structure and protocol(defined by ISO/IEC).
8998c7de408SJeff Kirsher  *	Please see SiS7014 or ICS spec
9008c7de408SJeff Kirsher  */
9018c7de408SJeff Kirsher 
mdio_read(struct net_device * net_dev,int phy_id,int location)9028c7de408SJeff Kirsher static int mdio_read(struct net_device *net_dev, int phy_id, int location)
9038c7de408SJeff Kirsher {
9048c7de408SJeff Kirsher 	int mii_cmd = MIIread|(phy_id<<MIIpmdShift)|(location<<MIIregShift);
90557d6d456SFrancois Romieu 	struct sis900_private *sp = netdev_priv(net_dev);
90657d6d456SFrancois Romieu 	void __iomem *ioaddr = sp->ioaddr;
9078c7de408SJeff Kirsher 	u16 retval = 0;
9088c7de408SJeff Kirsher 	int i;
9098c7de408SJeff Kirsher 
91057d6d456SFrancois Romieu 	mdio_reset(sp);
91157d6d456SFrancois Romieu 	mdio_idle(sp);
9128c7de408SJeff Kirsher 
9138c7de408SJeff Kirsher 	for (i = 15; i >= 0; i--) {
9148c7de408SJeff Kirsher 		int dataval = (mii_cmd & (1 << i)) ? MDDIR | MDIO : MDDIR;
91557d6d456SFrancois Romieu 
91657d6d456SFrancois Romieu 		sw32(mear, dataval);
9178c7de408SJeff Kirsher 		mdio_delay();
91857d6d456SFrancois Romieu 		sw32(mear, dataval | MDC);
9198c7de408SJeff Kirsher 		mdio_delay();
9208c7de408SJeff Kirsher 	}
9218c7de408SJeff Kirsher 
9228c7de408SJeff Kirsher 	/* Read the 16 data bits. */
9238c7de408SJeff Kirsher 	for (i = 16; i > 0; i--) {
92457d6d456SFrancois Romieu 		sw32(mear, 0);
9258c7de408SJeff Kirsher 		mdio_delay();
92657d6d456SFrancois Romieu 		retval = (retval << 1) | ((sr32(mear) & MDIO) ? 1 : 0);
92757d6d456SFrancois Romieu 		sw32(mear, MDC);
9288c7de408SJeff Kirsher 		mdio_delay();
9298c7de408SJeff Kirsher 	}
93057d6d456SFrancois Romieu 	sw32(mear, 0x00);
9318c7de408SJeff Kirsher 
9328c7de408SJeff Kirsher 	return retval;
9338c7de408SJeff Kirsher }
9348c7de408SJeff Kirsher 
9358c7de408SJeff Kirsher /**
9368c7de408SJeff Kirsher  *	mdio_write - write MII PHY register
9378c7de408SJeff Kirsher  *	@net_dev: the net device to write
9388c7de408SJeff Kirsher  *	@phy_id: the phy address to write
939ee7dd773SSergej Benilov  *	@location: the phy register id to write
9408c7de408SJeff Kirsher  *	@value: the register value to write with
9418c7de408SJeff Kirsher  *
9428c7de408SJeff Kirsher  *	Write MII registers with @value through MDIO and MDC
9438c7de408SJeff Kirsher  *	using MDIO management frame structure and protocol(defined by ISO/IEC)
9448c7de408SJeff Kirsher  *	please see SiS7014 or ICS spec
9458c7de408SJeff Kirsher  */
9468c7de408SJeff Kirsher 
mdio_write(struct net_device * net_dev,int phy_id,int location,int value)9478c7de408SJeff Kirsher static void mdio_write(struct net_device *net_dev, int phy_id, int location,
9488c7de408SJeff Kirsher 			int value)
9498c7de408SJeff Kirsher {
9508c7de408SJeff Kirsher 	int mii_cmd = MIIwrite|(phy_id<<MIIpmdShift)|(location<<MIIregShift);
95157d6d456SFrancois Romieu 	struct sis900_private *sp = netdev_priv(net_dev);
95257d6d456SFrancois Romieu 	void __iomem *ioaddr = sp->ioaddr;
9538c7de408SJeff Kirsher 	int i;
9548c7de408SJeff Kirsher 
95557d6d456SFrancois Romieu 	mdio_reset(sp);
95657d6d456SFrancois Romieu 	mdio_idle(sp);
9578c7de408SJeff Kirsher 
9588c7de408SJeff Kirsher 	/* Shift the command bits out. */
9598c7de408SJeff Kirsher 	for (i = 15; i >= 0; i--) {
9608c7de408SJeff Kirsher 		int dataval = (mii_cmd & (1 << i)) ? MDDIR | MDIO : MDDIR;
96157d6d456SFrancois Romieu 
96257d6d456SFrancois Romieu 		sw8(mear, dataval);
9638c7de408SJeff Kirsher 		mdio_delay();
96457d6d456SFrancois Romieu 		sw8(mear, dataval | MDC);
9658c7de408SJeff Kirsher 		mdio_delay();
9668c7de408SJeff Kirsher 	}
9678c7de408SJeff Kirsher 	mdio_delay();
9688c7de408SJeff Kirsher 
9698c7de408SJeff Kirsher 	/* Shift the value bits out. */
9708c7de408SJeff Kirsher 	for (i = 15; i >= 0; i--) {
9718c7de408SJeff Kirsher 		int dataval = (value & (1 << i)) ? MDDIR | MDIO : MDDIR;
97257d6d456SFrancois Romieu 
97357d6d456SFrancois Romieu 		sw32(mear, dataval);
9748c7de408SJeff Kirsher 		mdio_delay();
97557d6d456SFrancois Romieu 		sw32(mear, dataval | MDC);
9768c7de408SJeff Kirsher 		mdio_delay();
9778c7de408SJeff Kirsher 	}
9788c7de408SJeff Kirsher 	mdio_delay();
9798c7de408SJeff Kirsher 
9808c7de408SJeff Kirsher 	/* Clear out extra bits. */
9818c7de408SJeff Kirsher 	for (i = 2; i > 0; i--) {
98257d6d456SFrancois Romieu 		sw8(mear, 0);
9838c7de408SJeff Kirsher 		mdio_delay();
98457d6d456SFrancois Romieu 		sw8(mear, MDC);
9858c7de408SJeff Kirsher 		mdio_delay();
9868c7de408SJeff Kirsher 	}
98757d6d456SFrancois Romieu 	sw32(mear, 0x00);
9888c7de408SJeff Kirsher }
9898c7de408SJeff Kirsher 
9908c7de408SJeff Kirsher 
9918c7de408SJeff Kirsher /**
9928c7de408SJeff Kirsher  *	sis900_reset_phy - reset sis900 mii phy.
9938c7de408SJeff Kirsher  *	@net_dev: the net device to write
9948c7de408SJeff Kirsher  *	@phy_addr: default phy address
9958c7de408SJeff Kirsher  *
9968c7de408SJeff Kirsher  *	Some specific phy can't work properly without reset.
9978c7de408SJeff Kirsher  *	This function will be called during initialization and
9988c7de408SJeff Kirsher  *	link status change from ON to DOWN.
9998c7de408SJeff Kirsher  */
10008c7de408SJeff Kirsher 
sis900_reset_phy(struct net_device * net_dev,int phy_addr)10018c7de408SJeff Kirsher static u16 sis900_reset_phy(struct net_device *net_dev, int phy_addr)
10028c7de408SJeff Kirsher {
10038c7de408SJeff Kirsher 	int i;
10048c7de408SJeff Kirsher 	u16 status;
10058c7de408SJeff Kirsher 
10068c7de408SJeff Kirsher 	for (i = 0; i < 2; i++)
10078c7de408SJeff Kirsher 		status = mdio_read(net_dev, phy_addr, MII_STATUS);
10088c7de408SJeff Kirsher 
10098c7de408SJeff Kirsher 	mdio_write( net_dev, phy_addr, MII_CONTROL, MII_CNTL_RESET );
10108c7de408SJeff Kirsher 
10118c7de408SJeff Kirsher 	return status;
10128c7de408SJeff Kirsher }
10138c7de408SJeff Kirsher 
10148c7de408SJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER
10158c7de408SJeff Kirsher /*
10168c7de408SJeff Kirsher  * Polling 'interrupt' - used by things like netconsole to send skbs
10178c7de408SJeff Kirsher  * without having to re-enable interrupts. It's not called while
10188c7de408SJeff Kirsher  * the interrupt routine is executing.
10198c7de408SJeff Kirsher */
sis900_poll(struct net_device * dev)10208c7de408SJeff Kirsher static void sis900_poll(struct net_device *dev)
10218c7de408SJeff Kirsher {
102257d6d456SFrancois Romieu 	struct sis900_private *sp = netdev_priv(dev);
102357d6d456SFrancois Romieu 	const int irq = sp->pci_dev->irq;
102457d6d456SFrancois Romieu 
102557d6d456SFrancois Romieu 	disable_irq(irq);
102657d6d456SFrancois Romieu 	sis900_interrupt(irq, dev);
102757d6d456SFrancois Romieu 	enable_irq(irq);
10288c7de408SJeff Kirsher }
10298c7de408SJeff Kirsher #endif
10308c7de408SJeff Kirsher 
10318c7de408SJeff Kirsher /**
10328c7de408SJeff Kirsher  *	sis900_open - open sis900 device
10338c7de408SJeff Kirsher  *	@net_dev: the net device to open
10348c7de408SJeff Kirsher  *
10358c7de408SJeff Kirsher  *	Do some initialization and start net interface.
10368c7de408SJeff Kirsher  *	enable interrupts and set sis900 timer.
10378c7de408SJeff Kirsher  */
10388c7de408SJeff Kirsher 
10398c7de408SJeff Kirsher static int
sis900_open(struct net_device * net_dev)10408c7de408SJeff Kirsher sis900_open(struct net_device *net_dev)
10418c7de408SJeff Kirsher {
10428c7de408SJeff Kirsher 	struct sis900_private *sis_priv = netdev_priv(net_dev);
104357d6d456SFrancois Romieu 	void __iomem *ioaddr = sis_priv->ioaddr;
10448c7de408SJeff Kirsher 	int ret;
10458c7de408SJeff Kirsher 
10468c7de408SJeff Kirsher 	/* Soft reset the chip. */
10478c7de408SJeff Kirsher 	sis900_reset(net_dev);
10488c7de408SJeff Kirsher 
10498c7de408SJeff Kirsher 	/* Equalizer workaround Rule */
10508c7de408SJeff Kirsher 	sis630_set_eq(net_dev, sis_priv->chipset_rev);
10518c7de408SJeff Kirsher 
105257d6d456SFrancois Romieu 	ret = request_irq(sis_priv->pci_dev->irq, sis900_interrupt, IRQF_SHARED,
10538c7de408SJeff Kirsher 			  net_dev->name, net_dev);
10548c7de408SJeff Kirsher 	if (ret)
10558c7de408SJeff Kirsher 		return ret;
10568c7de408SJeff Kirsher 
10578c7de408SJeff Kirsher 	sis900_init_rxfilter(net_dev);
10588c7de408SJeff Kirsher 
10598c7de408SJeff Kirsher 	sis900_init_tx_ring(net_dev);
10608c7de408SJeff Kirsher 	sis900_init_rx_ring(net_dev);
10618c7de408SJeff Kirsher 
10628c7de408SJeff Kirsher 	set_rx_mode(net_dev);
10638c7de408SJeff Kirsher 
10648c7de408SJeff Kirsher 	netif_start_queue(net_dev);
10658c7de408SJeff Kirsher 
10668c7de408SJeff Kirsher 	/* Workaround for EDB */
106757d6d456SFrancois Romieu 	sis900_set_mode(sis_priv, HW_SPEED_10_MBPS, FDX_CAPABLE_HALF_SELECTED);
10688c7de408SJeff Kirsher 
10698c7de408SJeff Kirsher 	/* Enable all known interrupts by setting the interrupt mask. */
1070ee7dd773SSergej Benilov 	sw32(imr, RxSOVR | RxORN | RxERR | RxOK | TxURN | TxERR | TxDESC);
107157d6d456SFrancois Romieu 	sw32(cr, RxENA | sr32(cr));
107257d6d456SFrancois Romieu 	sw32(ier, IE);
10738c7de408SJeff Kirsher 
10748c7de408SJeff Kirsher 	sis900_check_mode(net_dev, sis_priv->mii);
10758c7de408SJeff Kirsher 
10768c7de408SJeff Kirsher 	/* Set the timer to switch to check for link beat and perhaps switch
10778c7de408SJeff Kirsher 	   to an alternate media type. */
1078fd71e13bSKees Cook 	timer_setup(&sis_priv->timer, sis900_timer, 0);
10798c7de408SJeff Kirsher 	sis_priv->timer.expires = jiffies + HZ;
10808c7de408SJeff Kirsher 	add_timer(&sis_priv->timer);
10818c7de408SJeff Kirsher 
10828c7de408SJeff Kirsher 	return 0;
10838c7de408SJeff Kirsher }
10848c7de408SJeff Kirsher 
10858c7de408SJeff Kirsher /**
10868c7de408SJeff Kirsher  *	sis900_init_rxfilter - Initialize the Rx filter
10878c7de408SJeff Kirsher  *	@net_dev: the net device to initialize for
10888c7de408SJeff Kirsher  *
10898c7de408SJeff Kirsher  *	Set receive filter address to our MAC address
10908c7de408SJeff Kirsher  *	and enable packet filtering.
10918c7de408SJeff Kirsher  */
10928c7de408SJeff Kirsher 
10938c7de408SJeff Kirsher static void
sis900_init_rxfilter(struct net_device * net_dev)10948c7de408SJeff Kirsher sis900_init_rxfilter (struct net_device * net_dev)
10958c7de408SJeff Kirsher {
10968c7de408SJeff Kirsher 	struct sis900_private *sis_priv = netdev_priv(net_dev);
109757d6d456SFrancois Romieu 	void __iomem *ioaddr = sis_priv->ioaddr;
10988c7de408SJeff Kirsher 	u32 rfcrSave;
10998c7de408SJeff Kirsher 	u32 i;
11008c7de408SJeff Kirsher 
110157d6d456SFrancois Romieu 	rfcrSave = sr32(rfcr);
11028c7de408SJeff Kirsher 
11038c7de408SJeff Kirsher 	/* disable packet filtering before setting filter */
110457d6d456SFrancois Romieu 	sw32(rfcr, rfcrSave & ~RFEN);
11058c7de408SJeff Kirsher 
11068c7de408SJeff Kirsher 	/* load MAC addr to filter data register */
11078c7de408SJeff Kirsher 	for (i = 0 ; i < 3 ; i++) {
110876660757SJakub Kicinski 		u32 w = (u32) *((const u16 *)(net_dev->dev_addr)+i);
11098c7de408SJeff Kirsher 
111057d6d456SFrancois Romieu 		sw32(rfcr, i << RFADDR_shift);
111157d6d456SFrancois Romieu 		sw32(rfdr, w);
11128c7de408SJeff Kirsher 
11138c7de408SJeff Kirsher 		if (netif_msg_hw(sis_priv)) {
1114ee7dd773SSergej Benilov 			printk(KERN_DEBUG "%s: Receive Filter Address[%d]=%x\n",
111557d6d456SFrancois Romieu 			       net_dev->name, i, sr32(rfdr));
11168c7de408SJeff Kirsher 		}
11178c7de408SJeff Kirsher 	}
11188c7de408SJeff Kirsher 
11198c7de408SJeff Kirsher 	/* enable packet filtering */
112057d6d456SFrancois Romieu 	sw32(rfcr, rfcrSave | RFEN);
11218c7de408SJeff Kirsher }
11228c7de408SJeff Kirsher 
11238c7de408SJeff Kirsher /**
11248c7de408SJeff Kirsher  *	sis900_init_tx_ring - Initialize the Tx descriptor ring
11258c7de408SJeff Kirsher  *	@net_dev: the net device to initialize for
11268c7de408SJeff Kirsher  *
11278c7de408SJeff Kirsher  *	Initialize the Tx descriptor ring,
11288c7de408SJeff Kirsher  */
11298c7de408SJeff Kirsher 
11308c7de408SJeff Kirsher static void
sis900_init_tx_ring(struct net_device * net_dev)11318c7de408SJeff Kirsher sis900_init_tx_ring(struct net_device *net_dev)
11328c7de408SJeff Kirsher {
11338c7de408SJeff Kirsher 	struct sis900_private *sis_priv = netdev_priv(net_dev);
113457d6d456SFrancois Romieu 	void __iomem *ioaddr = sis_priv->ioaddr;
11358c7de408SJeff Kirsher 	int i;
11368c7de408SJeff Kirsher 
11378c7de408SJeff Kirsher 	sis_priv->tx_full = 0;
11388c7de408SJeff Kirsher 	sis_priv->dirty_tx = sis_priv->cur_tx = 0;
11398c7de408SJeff Kirsher 
11408c7de408SJeff Kirsher 	for (i = 0; i < NUM_TX_DESC; i++) {
11418c7de408SJeff Kirsher 		sis_priv->tx_skbuff[i] = NULL;
11428c7de408SJeff Kirsher 
11438c7de408SJeff Kirsher 		sis_priv->tx_ring[i].link = sis_priv->tx_ring_dma +
11448c7de408SJeff Kirsher 			((i+1)%NUM_TX_DESC)*sizeof(BufferDesc);
11458c7de408SJeff Kirsher 		sis_priv->tx_ring[i].cmdsts = 0;
11468c7de408SJeff Kirsher 		sis_priv->tx_ring[i].bufptr = 0;
11478c7de408SJeff Kirsher 	}
11488c7de408SJeff Kirsher 
11498c7de408SJeff Kirsher 	/* load Transmit Descriptor Register */
115057d6d456SFrancois Romieu 	sw32(txdp, sis_priv->tx_ring_dma);
11518c7de408SJeff Kirsher 	if (netif_msg_hw(sis_priv))
11528c7de408SJeff Kirsher 		printk(KERN_DEBUG "%s: TX descriptor register loaded with: %8.8x\n",
115357d6d456SFrancois Romieu 		       net_dev->name, sr32(txdp));
11548c7de408SJeff Kirsher }
11558c7de408SJeff Kirsher 
11568c7de408SJeff Kirsher /**
11578c7de408SJeff Kirsher  *	sis900_init_rx_ring - Initialize the Rx descriptor ring
11588c7de408SJeff Kirsher  *	@net_dev: the net device to initialize for
11598c7de408SJeff Kirsher  *
11608c7de408SJeff Kirsher  *	Initialize the Rx descriptor ring,
1161ee7dd773SSergej Benilov  *	and pre-allocate receive buffers (socket buffer)
11628c7de408SJeff Kirsher  */
11638c7de408SJeff Kirsher 
11648c7de408SJeff Kirsher static void
sis900_init_rx_ring(struct net_device * net_dev)11658c7de408SJeff Kirsher sis900_init_rx_ring(struct net_device *net_dev)
11668c7de408SJeff Kirsher {
11678c7de408SJeff Kirsher 	struct sis900_private *sis_priv = netdev_priv(net_dev);
116857d6d456SFrancois Romieu 	void __iomem *ioaddr = sis_priv->ioaddr;
11698c7de408SJeff Kirsher 	int i;
11708c7de408SJeff Kirsher 
11718c7de408SJeff Kirsher 	sis_priv->cur_rx = 0;
11728c7de408SJeff Kirsher 	sis_priv->dirty_rx = 0;
11738c7de408SJeff Kirsher 
11748c7de408SJeff Kirsher 	/* init RX descriptor */
11758c7de408SJeff Kirsher 	for (i = 0; i < NUM_RX_DESC; i++) {
11768c7de408SJeff Kirsher 		sis_priv->rx_skbuff[i] = NULL;
11778c7de408SJeff Kirsher 
11788c7de408SJeff Kirsher 		sis_priv->rx_ring[i].link = sis_priv->rx_ring_dma +
11798c7de408SJeff Kirsher 			((i+1)%NUM_RX_DESC)*sizeof(BufferDesc);
11808c7de408SJeff Kirsher 		sis_priv->rx_ring[i].cmdsts = 0;
11818c7de408SJeff Kirsher 		sis_priv->rx_ring[i].bufptr = 0;
11828c7de408SJeff Kirsher 	}
11838c7de408SJeff Kirsher 
11848c7de408SJeff Kirsher 	/* allocate sock buffers */
11858c7de408SJeff Kirsher 	for (i = 0; i < NUM_RX_DESC; i++) {
11868c7de408SJeff Kirsher 		struct sk_buff *skb;
11878c7de408SJeff Kirsher 
1188dae2e9f4SPradeep A. Dalvi 		if ((skb = netdev_alloc_skb(net_dev, RX_BUF_SIZE)) == NULL) {
11898c7de408SJeff Kirsher 			/* not enough memory for skbuff, this makes a "hole"
11908c7de408SJeff Kirsher 			   on the buffer ring, it is not clear how the
11918c7de408SJeff Kirsher 			   hardware will react to this kind of degenerated
11928c7de408SJeff Kirsher 			   buffer */
11938c7de408SJeff Kirsher 			break;
11948c7de408SJeff Kirsher 		}
11958c7de408SJeff Kirsher 		sis_priv->rx_skbuff[i] = skb;
11968c7de408SJeff Kirsher 		sis_priv->rx_ring[i].cmdsts = RX_BUF_SIZE;
1197256ca744SChristophe JAILLET 		sis_priv->rx_ring[i].bufptr = dma_map_single(&sis_priv->pci_dev->dev,
1198256ca744SChristophe JAILLET 							     skb->data,
1199256ca744SChristophe JAILLET 							     RX_BUF_SIZE,
1200256ca744SChristophe JAILLET 							     DMA_FROM_DEVICE);
1201256ca744SChristophe JAILLET 		if (unlikely(dma_mapping_error(&sis_priv->pci_dev->dev,
12021e8edc2aSDenis Kirjanov 					       sis_priv->rx_ring[i].bufptr))) {
12031e8edc2aSDenis Kirjanov 			dev_kfree_skb(skb);
12041e8edc2aSDenis Kirjanov 			sis_priv->rx_skbuff[i] = NULL;
12051e8edc2aSDenis Kirjanov 			break;
12061e8edc2aSDenis Kirjanov 		}
12078c7de408SJeff Kirsher 	}
12088c7de408SJeff Kirsher 	sis_priv->dirty_rx = (unsigned int) (i - NUM_RX_DESC);
12098c7de408SJeff Kirsher 
12108c7de408SJeff Kirsher 	/* load Receive Descriptor Register */
121157d6d456SFrancois Romieu 	sw32(rxdp, sis_priv->rx_ring_dma);
12128c7de408SJeff Kirsher 	if (netif_msg_hw(sis_priv))
12138c7de408SJeff Kirsher 		printk(KERN_DEBUG "%s: RX descriptor register loaded with: %8.8x\n",
121457d6d456SFrancois Romieu 		       net_dev->name, sr32(rxdp));
12158c7de408SJeff Kirsher }
12168c7de408SJeff Kirsher 
12178c7de408SJeff Kirsher /**
12188c7de408SJeff Kirsher  *	sis630_set_eq - set phy equalizer value for 630 LAN
12198c7de408SJeff Kirsher  *	@net_dev: the net device to set equalizer value
12208c7de408SJeff Kirsher  *	@revision: 630 LAN revision number
12218c7de408SJeff Kirsher  *
12228c7de408SJeff Kirsher  *	630E equalizer workaround rule(Cyrus Huang 08/15)
12238c7de408SJeff Kirsher  *	PHY register 14h(Test)
12248c7de408SJeff Kirsher  *	Bit 14: 0 -- Automatically detect (default)
12258c7de408SJeff Kirsher  *		1 -- Manually set Equalizer filter
12268c7de408SJeff Kirsher  *	Bit 13: 0 -- (Default)
12278c7de408SJeff Kirsher  *		1 -- Speed up convergence of equalizer setting
12288c7de408SJeff Kirsher  *	Bit 9 : 0 -- (Default)
12298c7de408SJeff Kirsher  *		1 -- Disable Baseline Wander
12308c7de408SJeff Kirsher  *	Bit 3~7   -- Equalizer filter setting
12318c7de408SJeff Kirsher  *	Link ON: Set Bit 9, 13 to 1, Bit 14 to 0
12328c7de408SJeff Kirsher  *	Then calculate equalizer value
12338c7de408SJeff Kirsher  *	Then set equalizer value, and set Bit 14 to 1, Bit 9 to 0
12348c7de408SJeff Kirsher  *	Link Off:Set Bit 13 to 1, Bit 14 to 0
12358c7de408SJeff Kirsher  *	Calculate Equalizer value:
12368c7de408SJeff Kirsher  *	When Link is ON and Bit 14 is 0, SIS900PHY will auto-detect proper equalizer value.
12378c7de408SJeff Kirsher  *	When the equalizer is stable, this value is not a fixed value. It will be within
12388c7de408SJeff Kirsher  *	a small range(eg. 7~9). Then we get a minimum and a maximum value(eg. min=7, max=9)
12398c7de408SJeff Kirsher  *	0 <= max <= 4  --> set equalizer to max
12408c7de408SJeff Kirsher  *	5 <= max <= 14 --> set equalizer to max+1 or set equalizer to max+2 if max == min
12418c7de408SJeff Kirsher  *	max >= 15      --> set equalizer to max+5 or set equalizer to max+6 if max == min
12428c7de408SJeff Kirsher  */
12438c7de408SJeff Kirsher 
sis630_set_eq(struct net_device * net_dev,u8 revision)12448c7de408SJeff Kirsher static void sis630_set_eq(struct net_device *net_dev, u8 revision)
12458c7de408SJeff Kirsher {
12468c7de408SJeff Kirsher 	struct sis900_private *sis_priv = netdev_priv(net_dev);
12478c7de408SJeff Kirsher 	u16 reg14h, eq_value=0, max_value=0, min_value=0;
12488c7de408SJeff Kirsher 	int i, maxcount=10;
12498c7de408SJeff Kirsher 
12508c7de408SJeff Kirsher 	if ( !(revision == SIS630E_900_REV || revision == SIS630EA1_900_REV ||
12518c7de408SJeff Kirsher 	       revision == SIS630A_900_REV || revision ==  SIS630ET_900_REV) )
12528c7de408SJeff Kirsher 		return;
12538c7de408SJeff Kirsher 
12548c7de408SJeff Kirsher 	if (netif_carrier_ok(net_dev)) {
12558c7de408SJeff Kirsher 		reg14h = mdio_read(net_dev, sis_priv->cur_phy, MII_RESV);
12568c7de408SJeff Kirsher 		mdio_write(net_dev, sis_priv->cur_phy, MII_RESV,
12578c7de408SJeff Kirsher 					(0x2200 | reg14h) & 0xBFFF);
12588c7de408SJeff Kirsher 		for (i=0; i < maxcount; i++) {
12598c7de408SJeff Kirsher 			eq_value = (0x00F8 & mdio_read(net_dev,
12608c7de408SJeff Kirsher 					sis_priv->cur_phy, MII_RESV)) >> 3;
12618c7de408SJeff Kirsher 			if (i == 0)
12628c7de408SJeff Kirsher 				max_value=min_value=eq_value;
12638c7de408SJeff Kirsher 			max_value = (eq_value > max_value) ?
12648c7de408SJeff Kirsher 						eq_value : max_value;
12658c7de408SJeff Kirsher 			min_value = (eq_value < min_value) ?
12668c7de408SJeff Kirsher 						eq_value : min_value;
12678c7de408SJeff Kirsher 		}
12688c7de408SJeff Kirsher 		/* 630E rule to determine the equalizer value */
12698c7de408SJeff Kirsher 		if (revision == SIS630E_900_REV || revision == SIS630EA1_900_REV ||
12708c7de408SJeff Kirsher 		    revision == SIS630ET_900_REV) {
12718c7de408SJeff Kirsher 			if (max_value < 5)
12728c7de408SJeff Kirsher 				eq_value = max_value;
12738c7de408SJeff Kirsher 			else if (max_value >= 5 && max_value < 15)
12748c7de408SJeff Kirsher 				eq_value = (max_value == min_value) ?
12758c7de408SJeff Kirsher 						max_value+2 : max_value+1;
12768c7de408SJeff Kirsher 			else if (max_value >= 15)
12778c7de408SJeff Kirsher 				eq_value=(max_value == min_value) ?
12788c7de408SJeff Kirsher 						max_value+6 : max_value+5;
12798c7de408SJeff Kirsher 		}
12808c7de408SJeff Kirsher 		/* 630B0&B1 rule to determine the equalizer value */
12818c7de408SJeff Kirsher 		if (revision == SIS630A_900_REV &&
12828c7de408SJeff Kirsher 		    (sis_priv->host_bridge_rev == SIS630B0 ||
12838c7de408SJeff Kirsher 		     sis_priv->host_bridge_rev == SIS630B1)) {
12848c7de408SJeff Kirsher 			if (max_value == 0)
12858c7de408SJeff Kirsher 				eq_value = 3;
12868c7de408SJeff Kirsher 			else
12878c7de408SJeff Kirsher 				eq_value = (max_value + min_value + 1)/2;
12888c7de408SJeff Kirsher 		}
12898c7de408SJeff Kirsher 		/* write equalizer value and setting */
12908c7de408SJeff Kirsher 		reg14h = mdio_read(net_dev, sis_priv->cur_phy, MII_RESV);
12918c7de408SJeff Kirsher 		reg14h = (reg14h & 0xFF07) | ((eq_value << 3) & 0x00F8);
12928c7de408SJeff Kirsher 		reg14h = (reg14h | 0x6000) & 0xFDFF;
12938c7de408SJeff Kirsher 		mdio_write(net_dev, sis_priv->cur_phy, MII_RESV, reg14h);
12948c7de408SJeff Kirsher 	} else {
12958c7de408SJeff Kirsher 		reg14h = mdio_read(net_dev, sis_priv->cur_phy, MII_RESV);
12968c7de408SJeff Kirsher 		if (revision == SIS630A_900_REV &&
12978c7de408SJeff Kirsher 		    (sis_priv->host_bridge_rev == SIS630B0 ||
12988c7de408SJeff Kirsher 		     sis_priv->host_bridge_rev == SIS630B1))
12998c7de408SJeff Kirsher 			mdio_write(net_dev, sis_priv->cur_phy, MII_RESV,
13008c7de408SJeff Kirsher 						(reg14h | 0x2200) & 0xBFFF);
13018c7de408SJeff Kirsher 		else
13028c7de408SJeff Kirsher 			mdio_write(net_dev, sis_priv->cur_phy, MII_RESV,
13038c7de408SJeff Kirsher 						(reg14h | 0x2000) & 0xBFFF);
13048c7de408SJeff Kirsher 	}
13058c7de408SJeff Kirsher }
13068c7de408SJeff Kirsher 
13078c7de408SJeff Kirsher /**
13088c7de408SJeff Kirsher  *	sis900_timer - sis900 timer routine
1309d0ea5cbdSJesse Brandeburg  *	@t: timer list containing a pointer to sis900 net device
13108c7de408SJeff Kirsher  *
13118c7de408SJeff Kirsher  *	On each timer ticks we check two things,
13128c7de408SJeff Kirsher  *	link status (ON/OFF) and link mode (10/100/Full/Half)
13138c7de408SJeff Kirsher  */
13148c7de408SJeff Kirsher 
sis900_timer(struct timer_list * t)1315fd71e13bSKees Cook static void sis900_timer(struct timer_list *t)
13168c7de408SJeff Kirsher {
1317fd71e13bSKees Cook 	struct sis900_private *sis_priv = from_timer(sis_priv, t, timer);
1318fd71e13bSKees Cook 	struct net_device *net_dev = sis_priv->mii_info.dev;
13198c7de408SJeff Kirsher 	struct mii_phy *mii_phy = sis_priv->mii;
13208c7de408SJeff Kirsher 	static const int next_tick = 5*HZ;
132178f1ccc4SDenis Kirjanov 	int speed = 0, duplex = 0;
13228c7de408SJeff Kirsher 	u16 status;
13238c7de408SJeff Kirsher 
13248c7de408SJeff Kirsher 	status = mdio_read(net_dev, sis_priv->cur_phy, MII_STATUS);
13258c7de408SJeff Kirsher 	status = mdio_read(net_dev, sis_priv->cur_phy, MII_STATUS);
13268c7de408SJeff Kirsher 
13278c7de408SJeff Kirsher 	/* Link OFF -> ON */
13288c7de408SJeff Kirsher 	if (!netif_carrier_ok(net_dev)) {
13298c7de408SJeff Kirsher 	LookForLink:
13308c7de408SJeff Kirsher 		/* Search for new PHY */
13318c7de408SJeff Kirsher 		status = sis900_default_phy(net_dev);
13328c7de408SJeff Kirsher 		mii_phy = sis_priv->mii;
13338c7de408SJeff Kirsher 
133478f1ccc4SDenis Kirjanov 		if (status & MII_STAT_LINK) {
133578f1ccc4SDenis Kirjanov 			WARN_ON(!(status & MII_STAT_AUTO_DONE));
133678f1ccc4SDenis Kirjanov 
133778f1ccc4SDenis Kirjanov 			sis900_read_mode(net_dev, &speed, &duplex);
133878f1ccc4SDenis Kirjanov 			if (duplex) {
133978f1ccc4SDenis Kirjanov 				sis900_set_mode(sis_priv, speed, duplex);
134078f1ccc4SDenis Kirjanov 				sis630_set_eq(net_dev, sis_priv->chipset_rev);
134178f1ccc4SDenis Kirjanov 				netif_carrier_on(net_dev);
134278f1ccc4SDenis Kirjanov 			}
134378f1ccc4SDenis Kirjanov 		}
13448c7de408SJeff Kirsher 	} else {
13458c7de408SJeff Kirsher 	/* Link ON -> OFF */
13468c7de408SJeff Kirsher                 if (!(status & MII_STAT_LINK)){
13478c7de408SJeff Kirsher 			netif_carrier_off(net_dev);
13488c7de408SJeff Kirsher 			if(netif_msg_link(sis_priv))
13498c7de408SJeff Kirsher 				printk(KERN_INFO "%s: Media Link Off\n", net_dev->name);
13508c7de408SJeff Kirsher 
13518c7de408SJeff Kirsher 			/* Change mode issue */
13528c7de408SJeff Kirsher 			if ((mii_phy->phy_id0 == 0x001D) &&
13538c7de408SJeff Kirsher 				((mii_phy->phy_id1 & 0xFFF0) == 0x8000))
13548c7de408SJeff Kirsher 					sis900_reset_phy(net_dev,  sis_priv->cur_phy);
13558c7de408SJeff Kirsher 
13568c7de408SJeff Kirsher 			sis630_set_eq(net_dev, sis_priv->chipset_rev);
13578c7de408SJeff Kirsher 
13588c7de408SJeff Kirsher 			goto LookForLink;
13598c7de408SJeff Kirsher                 }
13608c7de408SJeff Kirsher 	}
13618c7de408SJeff Kirsher 
13628c7de408SJeff Kirsher 	sis_priv->timer.expires = jiffies + next_tick;
13638c7de408SJeff Kirsher 	add_timer(&sis_priv->timer);
13648c7de408SJeff Kirsher }
13658c7de408SJeff Kirsher 
13668c7de408SJeff Kirsher /**
13678c7de408SJeff Kirsher  *	sis900_check_mode - check the media mode for sis900
13688c7de408SJeff Kirsher  *	@net_dev: the net device to be checked
13698c7de408SJeff Kirsher  *	@mii_phy: the mii phy
13708c7de408SJeff Kirsher  *
13718c7de408SJeff Kirsher  *	Older driver gets the media mode from mii status output
13728c7de408SJeff Kirsher  *	register. Now we set our media capability and auto-negotiate
13738c7de408SJeff Kirsher  *	to get the upper bound of speed and duplex between two ends.
13748c7de408SJeff Kirsher  *	If the types of mii phy is HOME, it doesn't need to auto-negotiate
13758c7de408SJeff Kirsher  *	and autong_complete should be set to 1.
13768c7de408SJeff Kirsher  */
13778c7de408SJeff Kirsher 
sis900_check_mode(struct net_device * net_dev,struct mii_phy * mii_phy)13788c7de408SJeff Kirsher static void sis900_check_mode(struct net_device *net_dev, struct mii_phy *mii_phy)
13798c7de408SJeff Kirsher {
13808c7de408SJeff Kirsher 	struct sis900_private *sis_priv = netdev_priv(net_dev);
138157d6d456SFrancois Romieu 	void __iomem *ioaddr = sis_priv->ioaddr;
13828c7de408SJeff Kirsher 	int speed, duplex;
13838c7de408SJeff Kirsher 
13848c7de408SJeff Kirsher 	if (mii_phy->phy_types == LAN) {
138557d6d456SFrancois Romieu 		sw32(cfg, ~EXD & sr32(cfg));
13868c7de408SJeff Kirsher 		sis900_set_capability(net_dev , mii_phy);
13878c7de408SJeff Kirsher 		sis900_auto_negotiate(net_dev, sis_priv->cur_phy);
13888c7de408SJeff Kirsher 	} else {
138957d6d456SFrancois Romieu 		sw32(cfg, EXD | sr32(cfg));
13908c7de408SJeff Kirsher 		speed = HW_SPEED_HOME;
13918c7de408SJeff Kirsher 		duplex = FDX_CAPABLE_HALF_SELECTED;
139257d6d456SFrancois Romieu 		sis900_set_mode(sis_priv, speed, duplex);
13938c7de408SJeff Kirsher 		sis_priv->autong_complete = 1;
13948c7de408SJeff Kirsher 	}
13958c7de408SJeff Kirsher }
13968c7de408SJeff Kirsher 
13978c7de408SJeff Kirsher /**
13988c7de408SJeff Kirsher  *	sis900_set_mode - Set the media mode of mac register.
139957d6d456SFrancois Romieu  *	@sp:     the device private data
14008c7de408SJeff Kirsher  *	@speed : the transmit speed to be determined
14018c7de408SJeff Kirsher  *	@duplex: the duplex mode to be determined
14028c7de408SJeff Kirsher  *
14038c7de408SJeff Kirsher  *	Set the media mode of mac register txcfg/rxcfg according to
14048c7de408SJeff Kirsher  *	speed and duplex of phy. Bit EDB_MASTER_EN indicates the EDB
14058c7de408SJeff Kirsher  *	bus is used instead of PCI bus. When this bit is set 1, the
14068c7de408SJeff Kirsher  *	Max DMA Burst Size for TX/RX DMA should be no larger than 16
14078c7de408SJeff Kirsher  *	double words.
14088c7de408SJeff Kirsher  */
14098c7de408SJeff Kirsher 
sis900_set_mode(struct sis900_private * sp,int speed,int duplex)141057d6d456SFrancois Romieu static void sis900_set_mode(struct sis900_private *sp, int speed, int duplex)
14118c7de408SJeff Kirsher {
141257d6d456SFrancois Romieu 	void __iomem *ioaddr = sp->ioaddr;
14138c7de408SJeff Kirsher 	u32 tx_flags = 0, rx_flags = 0;
14148c7de408SJeff Kirsher 
141557d6d456SFrancois Romieu 	if (sr32( cfg) & EDB_MASTER_EN) {
14168c7de408SJeff Kirsher 		tx_flags = TxATP | (DMA_BURST_64 << TxMXDMA_shift) |
14178c7de408SJeff Kirsher 					(TX_FILL_THRESH << TxFILLT_shift);
14188c7de408SJeff Kirsher 		rx_flags = DMA_BURST_64 << RxMXDMA_shift;
14198c7de408SJeff Kirsher 	} else {
14208c7de408SJeff Kirsher 		tx_flags = TxATP | (DMA_BURST_512 << TxMXDMA_shift) |
14218c7de408SJeff Kirsher 					(TX_FILL_THRESH << TxFILLT_shift);
14228c7de408SJeff Kirsher 		rx_flags = DMA_BURST_512 << RxMXDMA_shift;
14238c7de408SJeff Kirsher 	}
14248c7de408SJeff Kirsher 
14258c7de408SJeff Kirsher 	if (speed == HW_SPEED_HOME || speed == HW_SPEED_10_MBPS) {
14268c7de408SJeff Kirsher 		rx_flags |= (RxDRNT_10 << RxDRNT_shift);
14278c7de408SJeff Kirsher 		tx_flags |= (TxDRNT_10 << TxDRNT_shift);
14288c7de408SJeff Kirsher 	} else {
14298c7de408SJeff Kirsher 		rx_flags |= (RxDRNT_100 << RxDRNT_shift);
14308c7de408SJeff Kirsher 		tx_flags |= (TxDRNT_100 << TxDRNT_shift);
14318c7de408SJeff Kirsher 	}
14328c7de408SJeff Kirsher 
14338c7de408SJeff Kirsher 	if (duplex == FDX_CAPABLE_FULL_SELECTED) {
14348c7de408SJeff Kirsher 		tx_flags |= (TxCSI | TxHBI);
14358c7de408SJeff Kirsher 		rx_flags |= RxATX;
14368c7de408SJeff Kirsher 	}
14378c7de408SJeff Kirsher 
1438547e530aSJavier Martinez Canillas #if IS_ENABLED(CONFIG_VLAN_8021Q)
14398c7de408SJeff Kirsher 	/* Can accept Jumbo packet */
14408c7de408SJeff Kirsher 	rx_flags |= RxAJAB;
14418c7de408SJeff Kirsher #endif
14428c7de408SJeff Kirsher 
144357d6d456SFrancois Romieu 	sw32(txcfg, tx_flags);
144457d6d456SFrancois Romieu 	sw32(rxcfg, rx_flags);
14458c7de408SJeff Kirsher }
14468c7de408SJeff Kirsher 
14478c7de408SJeff Kirsher /**
14488c7de408SJeff Kirsher  *	sis900_auto_negotiate - Set the Auto-Negotiation Enable/Reset bit.
14498c7de408SJeff Kirsher  *	@net_dev: the net device to read mode for
14508c7de408SJeff Kirsher  *	@phy_addr: mii phy address
14518c7de408SJeff Kirsher  *
14528c7de408SJeff Kirsher  *	If the adapter is link-on, set the auto-negotiate enable/reset bit.
14538c7de408SJeff Kirsher  *	autong_complete should be set to 0 when starting auto-negotiation.
14548c7de408SJeff Kirsher  *	autong_complete should be set to 1 if we didn't start auto-negotiation.
14558c7de408SJeff Kirsher  *	sis900_timer will wait for link on again if autong_complete = 0.
14568c7de408SJeff Kirsher  */
14578c7de408SJeff Kirsher 
sis900_auto_negotiate(struct net_device * net_dev,int phy_addr)14588c7de408SJeff Kirsher static void sis900_auto_negotiate(struct net_device *net_dev, int phy_addr)
14598c7de408SJeff Kirsher {
14608c7de408SJeff Kirsher 	struct sis900_private *sis_priv = netdev_priv(net_dev);
14618c7de408SJeff Kirsher 	int i = 0;
14628c7de408SJeff Kirsher 	u32 status;
14638c7de408SJeff Kirsher 
14648c7de408SJeff Kirsher 	for (i = 0; i < 2; i++)
14658c7de408SJeff Kirsher 		status = mdio_read(net_dev, phy_addr, MII_STATUS);
14668c7de408SJeff Kirsher 
14678c7de408SJeff Kirsher 	if (!(status & MII_STAT_LINK)){
14688c7de408SJeff Kirsher 		if(netif_msg_link(sis_priv))
14698c7de408SJeff Kirsher 			printk(KERN_INFO "%s: Media Link Off\n", net_dev->name);
14708c7de408SJeff Kirsher 		sis_priv->autong_complete = 1;
14718c7de408SJeff Kirsher 		netif_carrier_off(net_dev);
14728c7de408SJeff Kirsher 		return;
14738c7de408SJeff Kirsher 	}
14748c7de408SJeff Kirsher 
14758c7de408SJeff Kirsher 	/* (Re)start AutoNegotiate */
14768c7de408SJeff Kirsher 	mdio_write(net_dev, phy_addr, MII_CONTROL,
14778c7de408SJeff Kirsher 		   MII_CNTL_AUTO | MII_CNTL_RST_AUTO);
14788c7de408SJeff Kirsher 	sis_priv->autong_complete = 0;
14798c7de408SJeff Kirsher }
14808c7de408SJeff Kirsher 
14818c7de408SJeff Kirsher 
14828c7de408SJeff Kirsher /**
14838c7de408SJeff Kirsher  *	sis900_read_mode - read media mode for sis900 internal phy
14848c7de408SJeff Kirsher  *	@net_dev: the net device to read mode for
14858c7de408SJeff Kirsher  *	@speed  : the transmit speed to be determined
14868c7de408SJeff Kirsher  *	@duplex : the duplex mode to be determined
14878c7de408SJeff Kirsher  *
14888c7de408SJeff Kirsher  *	The capability of remote end will be put in mii register autorec
14898c7de408SJeff Kirsher  *	after auto-negotiation. Use AND operation to get the upper bound
14908c7de408SJeff Kirsher  *	of speed and duplex between two ends.
14918c7de408SJeff Kirsher  */
14928c7de408SJeff Kirsher 
sis900_read_mode(struct net_device * net_dev,int * speed,int * duplex)14938c7de408SJeff Kirsher static void sis900_read_mode(struct net_device *net_dev, int *speed, int *duplex)
14948c7de408SJeff Kirsher {
14958c7de408SJeff Kirsher 	struct sis900_private *sis_priv = netdev_priv(net_dev);
14968c7de408SJeff Kirsher 	struct mii_phy *phy = sis_priv->mii;
14978c7de408SJeff Kirsher 	int phy_addr = sis_priv->cur_phy;
14988c7de408SJeff Kirsher 	u32 status;
14998c7de408SJeff Kirsher 	u16 autoadv, autorec;
15008c7de408SJeff Kirsher 	int i;
15018c7de408SJeff Kirsher 
15028c7de408SJeff Kirsher 	for (i = 0; i < 2; i++)
15038c7de408SJeff Kirsher 		status = mdio_read(net_dev, phy_addr, MII_STATUS);
15048c7de408SJeff Kirsher 
15058c7de408SJeff Kirsher 	if (!(status & MII_STAT_LINK))
15068c7de408SJeff Kirsher 		return;
15078c7de408SJeff Kirsher 
15088c7de408SJeff Kirsher 	/* AutoNegotiate completed */
15098c7de408SJeff Kirsher 	autoadv = mdio_read(net_dev, phy_addr, MII_ANADV);
15108c7de408SJeff Kirsher 	autorec = mdio_read(net_dev, phy_addr, MII_ANLPAR);
15118c7de408SJeff Kirsher 	status = autoadv & autorec;
15128c7de408SJeff Kirsher 
15138c7de408SJeff Kirsher 	*speed = HW_SPEED_10_MBPS;
15148c7de408SJeff Kirsher 	*duplex = FDX_CAPABLE_HALF_SELECTED;
15158c7de408SJeff Kirsher 
15168c7de408SJeff Kirsher 	if (status & (MII_NWAY_TX | MII_NWAY_TX_FDX))
15178c7de408SJeff Kirsher 		*speed = HW_SPEED_100_MBPS;
15188c7de408SJeff Kirsher 	if (status & ( MII_NWAY_TX_FDX | MII_NWAY_T_FDX))
15198c7de408SJeff Kirsher 		*duplex = FDX_CAPABLE_FULL_SELECTED;
15208c7de408SJeff Kirsher 
15218c7de408SJeff Kirsher 	sis_priv->autong_complete = 1;
15228c7de408SJeff Kirsher 
15238c7de408SJeff Kirsher 	/* Workaround for Realtek RTL8201 PHY issue */
15248c7de408SJeff Kirsher 	if ((phy->phy_id0 == 0x0000) && ((phy->phy_id1 & 0xFFF0) == 0x8200)) {
15258c7de408SJeff Kirsher 		if (mdio_read(net_dev, phy_addr, MII_CONTROL) & MII_CNTL_FDX)
15268c7de408SJeff Kirsher 			*duplex = FDX_CAPABLE_FULL_SELECTED;
15278c7de408SJeff Kirsher 		if (mdio_read(net_dev, phy_addr, 0x0019) & 0x01)
15288c7de408SJeff Kirsher 			*speed = HW_SPEED_100_MBPS;
15298c7de408SJeff Kirsher 	}
15308c7de408SJeff Kirsher 
15318c7de408SJeff Kirsher 	if(netif_msg_link(sis_priv))
15328c7de408SJeff Kirsher 		printk(KERN_INFO "%s: Media Link On %s %s-duplex\n",
15338c7de408SJeff Kirsher 	       				net_dev->name,
15348c7de408SJeff Kirsher 	       				*speed == HW_SPEED_100_MBPS ?
15358c7de408SJeff Kirsher 	       					"100mbps" : "10mbps",
15368c7de408SJeff Kirsher 	       				*duplex == FDX_CAPABLE_FULL_SELECTED ?
15378c7de408SJeff Kirsher 	       					"full" : "half");
15388c7de408SJeff Kirsher }
15398c7de408SJeff Kirsher 
15408c7de408SJeff Kirsher /**
15418c7de408SJeff Kirsher  *	sis900_tx_timeout - sis900 transmit timeout routine
15428c7de408SJeff Kirsher  *	@net_dev: the net device to transmit
1543d0ea5cbdSJesse Brandeburg  *	@txqueue: index of hanging queue
15448c7de408SJeff Kirsher  *
15458c7de408SJeff Kirsher  *	print transmit timeout status
15468c7de408SJeff Kirsher  *	disable interrupts and do some tasks
15478c7de408SJeff Kirsher  */
15488c7de408SJeff Kirsher 
sis900_tx_timeout(struct net_device * net_dev,unsigned int txqueue)15490290bd29SMichael S. Tsirkin static void sis900_tx_timeout(struct net_device *net_dev, unsigned int txqueue)
15508c7de408SJeff Kirsher {
15518c7de408SJeff Kirsher 	struct sis900_private *sis_priv = netdev_priv(net_dev);
155257d6d456SFrancois Romieu 	void __iomem *ioaddr = sis_priv->ioaddr;
15538c7de408SJeff Kirsher 	unsigned long flags;
15548c7de408SJeff Kirsher 	int i;
15558c7de408SJeff Kirsher 
155657d6d456SFrancois Romieu 	if (netif_msg_tx_err(sis_priv)) {
15578c7de408SJeff Kirsher 		printk(KERN_INFO "%s: Transmit timeout, status %8.8x %8.8x\n",
155857d6d456SFrancois Romieu 			net_dev->name, sr32(cr), sr32(isr));
155957d6d456SFrancois Romieu 	}
15608c7de408SJeff Kirsher 
15618c7de408SJeff Kirsher 	/* Disable interrupts by clearing the interrupt mask. */
156257d6d456SFrancois Romieu 	sw32(imr, 0x0000);
15638c7de408SJeff Kirsher 
15648c7de408SJeff Kirsher 	/* use spinlock to prevent interrupt handler accessing buffer ring */
15658c7de408SJeff Kirsher 	spin_lock_irqsave(&sis_priv->lock, flags);
15668c7de408SJeff Kirsher 
15678c7de408SJeff Kirsher 	/* discard unsent packets */
15688c7de408SJeff Kirsher 	sis_priv->dirty_tx = sis_priv->cur_tx = 0;
15698c7de408SJeff Kirsher 	for (i = 0; i < NUM_TX_DESC; i++) {
15708c7de408SJeff Kirsher 		struct sk_buff *skb = sis_priv->tx_skbuff[i];
15718c7de408SJeff Kirsher 
15728c7de408SJeff Kirsher 		if (skb) {
1573256ca744SChristophe JAILLET 			dma_unmap_single(&sis_priv->pci_dev->dev,
1574256ca744SChristophe JAILLET 					 sis_priv->tx_ring[i].bufptr,
1575256ca744SChristophe JAILLET 					 skb->len, DMA_TO_DEVICE);
15768c7de408SJeff Kirsher 			dev_kfree_skb_irq(skb);
15778c7de408SJeff Kirsher 			sis_priv->tx_skbuff[i] = NULL;
15788c7de408SJeff Kirsher 			sis_priv->tx_ring[i].cmdsts = 0;
15798c7de408SJeff Kirsher 			sis_priv->tx_ring[i].bufptr = 0;
15808c7de408SJeff Kirsher 			net_dev->stats.tx_dropped++;
15818c7de408SJeff Kirsher 		}
15828c7de408SJeff Kirsher 	}
15838c7de408SJeff Kirsher 	sis_priv->tx_full = 0;
15848c7de408SJeff Kirsher 	netif_wake_queue(net_dev);
15858c7de408SJeff Kirsher 
15868c7de408SJeff Kirsher 	spin_unlock_irqrestore(&sis_priv->lock, flags);
15878c7de408SJeff Kirsher 
1588860e9538SFlorian Westphal 	netif_trans_update(net_dev); /* prevent tx timeout */
15898c7de408SJeff Kirsher 
15908c7de408SJeff Kirsher 	/* load Transmit Descriptor Register */
159157d6d456SFrancois Romieu 	sw32(txdp, sis_priv->tx_ring_dma);
15928c7de408SJeff Kirsher 
15938c7de408SJeff Kirsher 	/* Enable all known interrupts by setting the interrupt mask. */
1594ee7dd773SSergej Benilov 	sw32(imr, RxSOVR | RxORN | RxERR | RxOK | TxURN | TxERR | TxDESC);
15958c7de408SJeff Kirsher }
15968c7de408SJeff Kirsher 
15978c7de408SJeff Kirsher /**
15988c7de408SJeff Kirsher  *	sis900_start_xmit - sis900 start transmit routine
15998c7de408SJeff Kirsher  *	@skb: socket buffer pointer to put the data being transmitted
16008c7de408SJeff Kirsher  *	@net_dev: the net device to transmit with
16018c7de408SJeff Kirsher  *
16028c7de408SJeff Kirsher  *	Set the transmit buffer descriptor,
16038c7de408SJeff Kirsher  *	and write TxENA to enable transmit state machine.
16048c7de408SJeff Kirsher  *	tell upper layer if the buffer is full
16058c7de408SJeff Kirsher  */
16068c7de408SJeff Kirsher 
16078c7de408SJeff Kirsher static netdev_tx_t
sis900_start_xmit(struct sk_buff * skb,struct net_device * net_dev)16088c7de408SJeff Kirsher sis900_start_xmit(struct sk_buff *skb, struct net_device *net_dev)
16098c7de408SJeff Kirsher {
16108c7de408SJeff Kirsher 	struct sis900_private *sis_priv = netdev_priv(net_dev);
161157d6d456SFrancois Romieu 	void __iomem *ioaddr = sis_priv->ioaddr;
16128c7de408SJeff Kirsher 	unsigned int  entry;
16138c7de408SJeff Kirsher 	unsigned long flags;
16148c7de408SJeff Kirsher 	unsigned int  index_cur_tx, index_dirty_tx;
16158c7de408SJeff Kirsher 	unsigned int  count_dirty_tx;
16168c7de408SJeff Kirsher 
16178c7de408SJeff Kirsher 	spin_lock_irqsave(&sis_priv->lock, flags);
16188c7de408SJeff Kirsher 
16198c7de408SJeff Kirsher 	/* Calculate the next Tx descriptor entry. */
16208c7de408SJeff Kirsher 	entry = sis_priv->cur_tx % NUM_TX_DESC;
16218c7de408SJeff Kirsher 	sis_priv->tx_skbuff[entry] = skb;
16228c7de408SJeff Kirsher 
16238c7de408SJeff Kirsher 	/* set the transmit buffer descriptor and enable Transmit State Machine */
1624256ca744SChristophe JAILLET 	sis_priv->tx_ring[entry].bufptr = dma_map_single(&sis_priv->pci_dev->dev,
1625256ca744SChristophe JAILLET 							 skb->data, skb->len,
1626256ca744SChristophe JAILLET 							 DMA_TO_DEVICE);
1627256ca744SChristophe JAILLET 	if (unlikely(dma_mapping_error(&sis_priv->pci_dev->dev,
16281e8edc2aSDenis Kirjanov 				       sis_priv->tx_ring[entry].bufptr))) {
1629828f56f6SEric W. Biederman 			dev_kfree_skb_any(skb);
16301e8edc2aSDenis Kirjanov 			sis_priv->tx_skbuff[entry] = NULL;
16311e8edc2aSDenis Kirjanov 			net_dev->stats.tx_dropped++;
16321e8edc2aSDenis Kirjanov 			spin_unlock_irqrestore(&sis_priv->lock, flags);
16331e8edc2aSDenis Kirjanov 			return NETDEV_TX_OK;
16341e8edc2aSDenis Kirjanov 	}
16358ac8a010SSergej Benilov 	sis_priv->tx_ring[entry].cmdsts = (OWN | INTR | skb->len);
163657d6d456SFrancois Romieu 	sw32(cr, TxENA | sr32(cr));
16378c7de408SJeff Kirsher 
16388c7de408SJeff Kirsher 	sis_priv->cur_tx ++;
16398c7de408SJeff Kirsher 	index_cur_tx = sis_priv->cur_tx;
16408c7de408SJeff Kirsher 	index_dirty_tx = sis_priv->dirty_tx;
16418c7de408SJeff Kirsher 
16428c7de408SJeff Kirsher 	for (count_dirty_tx = 0; index_cur_tx != index_dirty_tx; index_dirty_tx++)
16438c7de408SJeff Kirsher 		count_dirty_tx ++;
16448c7de408SJeff Kirsher 
16458c7de408SJeff Kirsher 	if (index_cur_tx == index_dirty_tx) {
16468c7de408SJeff Kirsher 		/* dirty_tx is met in the cycle of cur_tx, buffer full */
16478c7de408SJeff Kirsher 		sis_priv->tx_full = 1;
16488c7de408SJeff Kirsher 		netif_stop_queue(net_dev);
16498c7de408SJeff Kirsher 	} else if (count_dirty_tx < NUM_TX_DESC) {
16508c7de408SJeff Kirsher 		/* Typical path, tell upper layer that more transmission is possible */
16518c7de408SJeff Kirsher 		netif_start_queue(net_dev);
16528c7de408SJeff Kirsher 	} else {
16538c7de408SJeff Kirsher 		/* buffer full, tell upper layer no more transmission */
16548c7de408SJeff Kirsher 		sis_priv->tx_full = 1;
16558c7de408SJeff Kirsher 		netif_stop_queue(net_dev);
16568c7de408SJeff Kirsher 	}
16578c7de408SJeff Kirsher 
16588c7de408SJeff Kirsher 	spin_unlock_irqrestore(&sis_priv->lock, flags);
16598c7de408SJeff Kirsher 
16608c7de408SJeff Kirsher 	if (netif_msg_tx_queued(sis_priv))
16618c7de408SJeff Kirsher 		printk(KERN_DEBUG "%s: Queued Tx packet at %p size %d "
16628c7de408SJeff Kirsher 		       "to slot %d.\n",
16638c7de408SJeff Kirsher 		       net_dev->name, skb->data, (int)skb->len, entry);
16648c7de408SJeff Kirsher 
16658c7de408SJeff Kirsher 	return NETDEV_TX_OK;
16668c7de408SJeff Kirsher }
16678c7de408SJeff Kirsher 
16688c7de408SJeff Kirsher /**
16698c7de408SJeff Kirsher  *	sis900_interrupt - sis900 interrupt handler
16708c7de408SJeff Kirsher  *	@irq: the irq number
16718c7de408SJeff Kirsher  *	@dev_instance: the client data object
16728c7de408SJeff Kirsher  *
16738c7de408SJeff Kirsher  *	The interrupt handler does all of the Rx thread work,
16748c7de408SJeff Kirsher  *	and cleans up after the Tx thread
16758c7de408SJeff Kirsher  */
16768c7de408SJeff Kirsher 
sis900_interrupt(int irq,void * dev_instance)16778c7de408SJeff Kirsher static irqreturn_t sis900_interrupt(int irq, void *dev_instance)
16788c7de408SJeff Kirsher {
16798c7de408SJeff Kirsher 	struct net_device *net_dev = dev_instance;
16808c7de408SJeff Kirsher 	struct sis900_private *sis_priv = netdev_priv(net_dev);
16818c7de408SJeff Kirsher 	int boguscnt = max_interrupt_work;
168257d6d456SFrancois Romieu 	void __iomem *ioaddr = sis_priv->ioaddr;
16838c7de408SJeff Kirsher 	u32 status;
16848c7de408SJeff Kirsher 	unsigned int handled = 0;
16858c7de408SJeff Kirsher 
16868c7de408SJeff Kirsher 	spin_lock (&sis_priv->lock);
16878c7de408SJeff Kirsher 
16888c7de408SJeff Kirsher 	do {
168957d6d456SFrancois Romieu 		status = sr32(isr);
16908c7de408SJeff Kirsher 
1691ee7dd773SSergej Benilov 		if ((status & (HIBERR|TxURN|TxERR|TxDESC|RxORN|RxERR|RxOK)) == 0)
1692ee7dd773SSergej Benilov 			/* nothing interesting happened */
16938c7de408SJeff Kirsher 			break;
16948c7de408SJeff Kirsher 		handled = 1;
16958c7de408SJeff Kirsher 
16968c7de408SJeff Kirsher 		/* why dow't we break after Tx/Rx case ?? keyword: full-duplex */
16978c7de408SJeff Kirsher 		if (status & (RxORN | RxERR | RxOK))
16988c7de408SJeff Kirsher 			/* Rx interrupt */
16998c7de408SJeff Kirsher 			sis900_rx(net_dev);
17008c7de408SJeff Kirsher 
1701ee7dd773SSergej Benilov 		if (status & (TxURN | TxERR | TxDESC))
17028c7de408SJeff Kirsher 			/* Tx interrupt */
17038c7de408SJeff Kirsher 			sis900_finish_xmit(net_dev);
17048c7de408SJeff Kirsher 
17058c7de408SJeff Kirsher 		/* something strange happened !!! */
17068c7de408SJeff Kirsher 		if (status & HIBERR) {
17078c7de408SJeff Kirsher 			if(netif_msg_intr(sis_priv))
17088c7de408SJeff Kirsher 				printk(KERN_INFO "%s: Abnormal interrupt, "
17098c7de408SJeff Kirsher 					"status %#8.8x.\n", net_dev->name, status);
17108c7de408SJeff Kirsher 			break;
17118c7de408SJeff Kirsher 		}
17128c7de408SJeff Kirsher 		if (--boguscnt < 0) {
17138c7de408SJeff Kirsher 			if(netif_msg_intr(sis_priv))
17148c7de408SJeff Kirsher 				printk(KERN_INFO "%s: Too much work at interrupt, "
17158c7de408SJeff Kirsher 					"interrupt status = %#8.8x.\n",
17168c7de408SJeff Kirsher 					net_dev->name, status);
17178c7de408SJeff Kirsher 			break;
17188c7de408SJeff Kirsher 		}
17198c7de408SJeff Kirsher 	} while (1);
17208c7de408SJeff Kirsher 
17218c7de408SJeff Kirsher 	if(netif_msg_intr(sis_priv))
17228c7de408SJeff Kirsher 		printk(KERN_DEBUG "%s: exiting interrupt, "
17238e33a52fSJoe Perches 		       "interrupt status = %#8.8x\n",
172457d6d456SFrancois Romieu 		       net_dev->name, sr32(isr));
17258c7de408SJeff Kirsher 
17268c7de408SJeff Kirsher 	spin_unlock (&sis_priv->lock);
17278c7de408SJeff Kirsher 	return IRQ_RETVAL(handled);
17288c7de408SJeff Kirsher }
17298c7de408SJeff Kirsher 
17308c7de408SJeff Kirsher /**
17318c7de408SJeff Kirsher  *	sis900_rx - sis900 receive routine
17328c7de408SJeff Kirsher  *	@net_dev: the net device which receives data
17338c7de408SJeff Kirsher  *
17348c7de408SJeff Kirsher  *	Process receive interrupt events,
17358c7de408SJeff Kirsher  *	put buffer to higher layer and refill buffer pool
17368c7de408SJeff Kirsher  *	Note: This function is called by interrupt handler,
17378c7de408SJeff Kirsher  *	don't do "too much" work here
17388c7de408SJeff Kirsher  */
17398c7de408SJeff Kirsher 
sis900_rx(struct net_device * net_dev)17408c7de408SJeff Kirsher static int sis900_rx(struct net_device *net_dev)
17418c7de408SJeff Kirsher {
17428c7de408SJeff Kirsher 	struct sis900_private *sis_priv = netdev_priv(net_dev);
174357d6d456SFrancois Romieu 	void __iomem *ioaddr = sis_priv->ioaddr;
17448c7de408SJeff Kirsher 	unsigned int entry = sis_priv->cur_rx % NUM_RX_DESC;
17458c7de408SJeff Kirsher 	u32 rx_status = sis_priv->rx_ring[entry].cmdsts;
17468c7de408SJeff Kirsher 	int rx_work_limit;
17478c7de408SJeff Kirsher 
17488c7de408SJeff Kirsher 	if (netif_msg_rx_status(sis_priv))
17498c7de408SJeff Kirsher 		printk(KERN_DEBUG "sis900_rx, cur_rx:%4.4d, dirty_rx:%4.4d "
17508c7de408SJeff Kirsher 		       "status:0x%8.8x\n",
17518c7de408SJeff Kirsher 		       sis_priv->cur_rx, sis_priv->dirty_rx, rx_status);
17528c7de408SJeff Kirsher 	rx_work_limit = sis_priv->dirty_rx + NUM_RX_DESC - sis_priv->cur_rx;
17538c7de408SJeff Kirsher 
17548c7de408SJeff Kirsher 	while (rx_status & OWN) {
17558c7de408SJeff Kirsher 		unsigned int rx_size;
17568c7de408SJeff Kirsher 		unsigned int data_size;
17578c7de408SJeff Kirsher 
17588c7de408SJeff Kirsher 		if (--rx_work_limit < 0)
17598c7de408SJeff Kirsher 			break;
17608c7de408SJeff Kirsher 
17618c7de408SJeff Kirsher 		data_size = rx_status & DSIZE;
17628c7de408SJeff Kirsher 		rx_size = data_size - CRC_SIZE;
17638c7de408SJeff Kirsher 
1764547e530aSJavier Martinez Canillas #if IS_ENABLED(CONFIG_VLAN_8021Q)
17658c7de408SJeff Kirsher 		/* ``TOOLONG'' flag means jumbo packet received. */
17668c7de408SJeff Kirsher 		if ((rx_status & TOOLONG) && data_size <= MAX_FRAME_SIZE)
17678c7de408SJeff Kirsher 			rx_status &= (~ ((unsigned int)TOOLONG));
17688c7de408SJeff Kirsher #endif
17698c7de408SJeff Kirsher 
17708c7de408SJeff Kirsher 		if (rx_status & (ABORT|OVERRUN|TOOLONG|RUNT|RXISERR|CRCERR|FAERR)) {
17718c7de408SJeff Kirsher 			/* corrupted packet received */
17728c7de408SJeff Kirsher 			if (netif_msg_rx_err(sis_priv))
17738c7de408SJeff Kirsher 				printk(KERN_DEBUG "%s: Corrupted packet "
17748c7de408SJeff Kirsher 				       "received, buffer status = 0x%8.8x/%d.\n",
17758c7de408SJeff Kirsher 				       net_dev->name, rx_status, data_size);
17768c7de408SJeff Kirsher 			net_dev->stats.rx_errors++;
17778c7de408SJeff Kirsher 			if (rx_status & OVERRUN)
17788c7de408SJeff Kirsher 				net_dev->stats.rx_over_errors++;
17798c7de408SJeff Kirsher 			if (rx_status & (TOOLONG|RUNT))
17808c7de408SJeff Kirsher 				net_dev->stats.rx_length_errors++;
17818c7de408SJeff Kirsher 			if (rx_status & (RXISERR | FAERR))
17828c7de408SJeff Kirsher 				net_dev->stats.rx_frame_errors++;
17838c7de408SJeff Kirsher 			if (rx_status & CRCERR)
17848c7de408SJeff Kirsher 				net_dev->stats.rx_crc_errors++;
17858c7de408SJeff Kirsher 			/* reset buffer descriptor state */
17868c7de408SJeff Kirsher 			sis_priv->rx_ring[entry].cmdsts = RX_BUF_SIZE;
17878c7de408SJeff Kirsher 		} else {
17888c7de408SJeff Kirsher 			struct sk_buff * skb;
17898c7de408SJeff Kirsher 			struct sk_buff * rx_skb;
17908c7de408SJeff Kirsher 
1791256ca744SChristophe JAILLET 			dma_unmap_single(&sis_priv->pci_dev->dev,
1792256ca744SChristophe JAILLET 					 sis_priv->rx_ring[entry].bufptr,
1793256ca744SChristophe JAILLET 					 RX_BUF_SIZE, DMA_FROM_DEVICE);
17948c7de408SJeff Kirsher 
17958c7de408SJeff Kirsher 			/* refill the Rx buffer, what if there is not enough
17968c7de408SJeff Kirsher 			 * memory for new socket buffer ?? */
1797dae2e9f4SPradeep A. Dalvi 			if ((skb = netdev_alloc_skb(net_dev, RX_BUF_SIZE)) == NULL) {
17988c7de408SJeff Kirsher 				/*
17998c7de408SJeff Kirsher 				 * Not enough memory to refill the buffer
18008c7de408SJeff Kirsher 				 * so we need to recycle the old one so
18018c7de408SJeff Kirsher 				 * as to avoid creating a memory hole
18028c7de408SJeff Kirsher 				 * in the rx ring
18038c7de408SJeff Kirsher 				 */
18048c7de408SJeff Kirsher 				skb = sis_priv->rx_skbuff[entry];
18058c7de408SJeff Kirsher 				net_dev->stats.rx_dropped++;
18068c7de408SJeff Kirsher 				goto refill_rx_ring;
18078c7de408SJeff Kirsher 			}
18088c7de408SJeff Kirsher 
18098c7de408SJeff Kirsher 			/* This situation should never happen, but due to
18108c7de408SJeff Kirsher 			   some unknown bugs, it is possible that
18118c7de408SJeff Kirsher 			   we are working on NULL sk_buff :-( */
18128c7de408SJeff Kirsher 			if (sis_priv->rx_skbuff[entry] == NULL) {
18138c7de408SJeff Kirsher 				if (netif_msg_rx_err(sis_priv))
18148c7de408SJeff Kirsher 					printk(KERN_WARNING "%s: NULL pointer "
18158c7de408SJeff Kirsher 					      "encountered in Rx ring\n"
18168c7de408SJeff Kirsher 					      "cur_rx:%4.4d, dirty_rx:%4.4d\n",
18178c7de408SJeff Kirsher 					      net_dev->name, sis_priv->cur_rx,
18188c7de408SJeff Kirsher 					      sis_priv->dirty_rx);
18198c7de408SJeff Kirsher 				dev_kfree_skb(skb);
18208c7de408SJeff Kirsher 				break;
18218c7de408SJeff Kirsher 			}
18228c7de408SJeff Kirsher 
18238c7de408SJeff Kirsher 			/* give the socket buffer to upper layers */
18248c7de408SJeff Kirsher 			rx_skb = sis_priv->rx_skbuff[entry];
18258c7de408SJeff Kirsher 			skb_put(rx_skb, rx_size);
18268c7de408SJeff Kirsher 			rx_skb->protocol = eth_type_trans(rx_skb, net_dev);
18278c7de408SJeff Kirsher 			netif_rx(rx_skb);
18288c7de408SJeff Kirsher 
18298c7de408SJeff Kirsher 			/* some network statistics */
18308c7de408SJeff Kirsher 			if ((rx_status & BCAST) == MCAST)
18318c7de408SJeff Kirsher 				net_dev->stats.multicast++;
18328c7de408SJeff Kirsher 			net_dev->stats.rx_bytes += rx_size;
18338c7de408SJeff Kirsher 			net_dev->stats.rx_packets++;
18348c7de408SJeff Kirsher 			sis_priv->dirty_rx++;
18358c7de408SJeff Kirsher refill_rx_ring:
18368c7de408SJeff Kirsher 			sis_priv->rx_skbuff[entry] = skb;
18378c7de408SJeff Kirsher 			sis_priv->rx_ring[entry].cmdsts = RX_BUF_SIZE;
18388c7de408SJeff Kirsher 			sis_priv->rx_ring[entry].bufptr =
1839256ca744SChristophe JAILLET 				dma_map_single(&sis_priv->pci_dev->dev,
1840256ca744SChristophe JAILLET 					       skb->data, RX_BUF_SIZE,
1841256ca744SChristophe JAILLET 					       DMA_FROM_DEVICE);
1842256ca744SChristophe JAILLET 			if (unlikely(dma_mapping_error(&sis_priv->pci_dev->dev,
18431e8edc2aSDenis Kirjanov 						       sis_priv->rx_ring[entry].bufptr))) {
18441e8edc2aSDenis Kirjanov 				dev_kfree_skb_irq(skb);
18451e8edc2aSDenis Kirjanov 				sis_priv->rx_skbuff[entry] = NULL;
18461e8edc2aSDenis Kirjanov 				break;
18471e8edc2aSDenis Kirjanov 			}
18488c7de408SJeff Kirsher 		}
18498c7de408SJeff Kirsher 		sis_priv->cur_rx++;
18508c7de408SJeff Kirsher 		entry = sis_priv->cur_rx % NUM_RX_DESC;
18518c7de408SJeff Kirsher 		rx_status = sis_priv->rx_ring[entry].cmdsts;
18528c7de408SJeff Kirsher 	} // while
18538c7de408SJeff Kirsher 
18548c7de408SJeff Kirsher 	/* refill the Rx buffer, what if the rate of refilling is slower
18558c7de408SJeff Kirsher 	 * than consuming ?? */
18568c7de408SJeff Kirsher 	for (; sis_priv->cur_rx != sis_priv->dirty_rx; sis_priv->dirty_rx++) {
18578c7de408SJeff Kirsher 		struct sk_buff *skb;
18588c7de408SJeff Kirsher 
18598c7de408SJeff Kirsher 		entry = sis_priv->dirty_rx % NUM_RX_DESC;
18608c7de408SJeff Kirsher 
18618c7de408SJeff Kirsher 		if (sis_priv->rx_skbuff[entry] == NULL) {
1862720a43efSJoe Perches 			skb = netdev_alloc_skb(net_dev, RX_BUF_SIZE);
1863720a43efSJoe Perches 			if (skb == NULL) {
18648c7de408SJeff Kirsher 				/* not enough memory for skbuff, this makes a
18658c7de408SJeff Kirsher 				 * "hole" on the buffer ring, it is not clear
18668c7de408SJeff Kirsher 				 * how the hardware will react to this kind
18678c7de408SJeff Kirsher 				 * of degenerated buffer */
18688c7de408SJeff Kirsher 				net_dev->stats.rx_dropped++;
18698c7de408SJeff Kirsher 				break;
18708c7de408SJeff Kirsher 			}
18718c7de408SJeff Kirsher 			sis_priv->rx_skbuff[entry] = skb;
18728c7de408SJeff Kirsher 			sis_priv->rx_ring[entry].cmdsts = RX_BUF_SIZE;
18738c7de408SJeff Kirsher 			sis_priv->rx_ring[entry].bufptr =
1874256ca744SChristophe JAILLET 				dma_map_single(&sis_priv->pci_dev->dev,
1875256ca744SChristophe JAILLET 					       skb->data, RX_BUF_SIZE,
1876256ca744SChristophe JAILLET 					       DMA_FROM_DEVICE);
1877256ca744SChristophe JAILLET 			if (unlikely(dma_mapping_error(&sis_priv->pci_dev->dev,
18781e8edc2aSDenis Kirjanov 						       sis_priv->rx_ring[entry].bufptr))) {
18791e8edc2aSDenis Kirjanov 				dev_kfree_skb_irq(skb);
18801e8edc2aSDenis Kirjanov 				sis_priv->rx_skbuff[entry] = NULL;
18811e8edc2aSDenis Kirjanov 				break;
18821e8edc2aSDenis Kirjanov 			}
18838c7de408SJeff Kirsher 		}
18848c7de408SJeff Kirsher 	}
18858c7de408SJeff Kirsher 	/* re-enable the potentially idle receive state matchine */
188657d6d456SFrancois Romieu 	sw32(cr , RxENA | sr32(cr));
18878c7de408SJeff Kirsher 
18888c7de408SJeff Kirsher 	return 0;
18898c7de408SJeff Kirsher }
18908c7de408SJeff Kirsher 
18918c7de408SJeff Kirsher /**
18928c7de408SJeff Kirsher  *	sis900_finish_xmit - finish up transmission of packets
18938c7de408SJeff Kirsher  *	@net_dev: the net device to be transmitted on
18948c7de408SJeff Kirsher  *
18958c7de408SJeff Kirsher  *	Check for error condition and free socket buffer etc
18968c7de408SJeff Kirsher  *	schedule for more transmission as needed
18978c7de408SJeff Kirsher  *	Note: This function is called by interrupt handler,
18988c7de408SJeff Kirsher  *	don't do "too much" work here
18998c7de408SJeff Kirsher  */
19008c7de408SJeff Kirsher 
sis900_finish_xmit(struct net_device * net_dev)19018c7de408SJeff Kirsher static void sis900_finish_xmit (struct net_device *net_dev)
19028c7de408SJeff Kirsher {
19038c7de408SJeff Kirsher 	struct sis900_private *sis_priv = netdev_priv(net_dev);
19048c7de408SJeff Kirsher 
19058c7de408SJeff Kirsher 	for (; sis_priv->dirty_tx != sis_priv->cur_tx; sis_priv->dirty_tx++) {
19068c7de408SJeff Kirsher 		struct sk_buff *skb;
19078c7de408SJeff Kirsher 		unsigned int entry;
19088c7de408SJeff Kirsher 		u32 tx_status;
19098c7de408SJeff Kirsher 
19108c7de408SJeff Kirsher 		entry = sis_priv->dirty_tx % NUM_TX_DESC;
19118c7de408SJeff Kirsher 		tx_status = sis_priv->tx_ring[entry].cmdsts;
19128c7de408SJeff Kirsher 
19138c7de408SJeff Kirsher 		if (tx_status & OWN) {
19148c7de408SJeff Kirsher 			/* The packet is not transmitted yet (owned by hardware) !
19158ac8a010SSergej Benilov 			 * Note: this is an almost impossible condition
1916ee7dd773SSergej Benilov 			 * on TxDESC interrupt ('descriptor interrupt') */
19178c7de408SJeff Kirsher 			break;
19188c7de408SJeff Kirsher 		}
19198c7de408SJeff Kirsher 
19208c7de408SJeff Kirsher 		if (tx_status & (ABORT | UNDERRUN | OWCOLL)) {
19218c7de408SJeff Kirsher 			/* packet unsuccessfully transmitted */
19228c7de408SJeff Kirsher 			if (netif_msg_tx_err(sis_priv))
19238c7de408SJeff Kirsher 				printk(KERN_DEBUG "%s: Transmit "
19248c7de408SJeff Kirsher 				       "error, Tx status %8.8x.\n",
19258c7de408SJeff Kirsher 				       net_dev->name, tx_status);
19268c7de408SJeff Kirsher 			net_dev->stats.tx_errors++;
19278c7de408SJeff Kirsher 			if (tx_status & UNDERRUN)
19288c7de408SJeff Kirsher 				net_dev->stats.tx_fifo_errors++;
19298c7de408SJeff Kirsher 			if (tx_status & ABORT)
19308c7de408SJeff Kirsher 				net_dev->stats.tx_aborted_errors++;
19318c7de408SJeff Kirsher 			if (tx_status & NOCARRIER)
19328c7de408SJeff Kirsher 				net_dev->stats.tx_carrier_errors++;
19338c7de408SJeff Kirsher 			if (tx_status & OWCOLL)
19348c7de408SJeff Kirsher 				net_dev->stats.tx_window_errors++;
19358c7de408SJeff Kirsher 		} else {
19368c7de408SJeff Kirsher 			/* packet successfully transmitted */
19378c7de408SJeff Kirsher 			net_dev->stats.collisions += (tx_status & COLCNT) >> 16;
19388c7de408SJeff Kirsher 			net_dev->stats.tx_bytes += tx_status & DSIZE;
19398c7de408SJeff Kirsher 			net_dev->stats.tx_packets++;
19408c7de408SJeff Kirsher 		}
19418c7de408SJeff Kirsher 		/* Free the original skb. */
19428c7de408SJeff Kirsher 		skb = sis_priv->tx_skbuff[entry];
1943256ca744SChristophe JAILLET 		dma_unmap_single(&sis_priv->pci_dev->dev,
19448c7de408SJeff Kirsher 				 sis_priv->tx_ring[entry].bufptr, skb->len,
1945256ca744SChristophe JAILLET 				 DMA_TO_DEVICE);
1946e78042ebSYang Wei 		dev_consume_skb_irq(skb);
19478c7de408SJeff Kirsher 		sis_priv->tx_skbuff[entry] = NULL;
19488c7de408SJeff Kirsher 		sis_priv->tx_ring[entry].bufptr = 0;
19498c7de408SJeff Kirsher 		sis_priv->tx_ring[entry].cmdsts = 0;
19508c7de408SJeff Kirsher 	}
19518c7de408SJeff Kirsher 
19528c7de408SJeff Kirsher 	if (sis_priv->tx_full && netif_queue_stopped(net_dev) &&
19538c7de408SJeff Kirsher 	    sis_priv->cur_tx - sis_priv->dirty_tx < NUM_TX_DESC - 4) {
19548c7de408SJeff Kirsher 		/* The ring is no longer full, clear tx_full and schedule
19558c7de408SJeff Kirsher 		 * more transmission by netif_wake_queue(net_dev) */
19568c7de408SJeff Kirsher 		sis_priv->tx_full = 0;
19578c7de408SJeff Kirsher 		netif_wake_queue (net_dev);
19588c7de408SJeff Kirsher 	}
19598c7de408SJeff Kirsher }
19608c7de408SJeff Kirsher 
19618c7de408SJeff Kirsher /**
19628c7de408SJeff Kirsher  *	sis900_close - close sis900 device
19638c7de408SJeff Kirsher  *	@net_dev: the net device to be closed
19648c7de408SJeff Kirsher  *
19658c7de408SJeff Kirsher  *	Disable interrupts, stop the Tx and Rx Status Machine
19668c7de408SJeff Kirsher  *	free Tx and RX socket buffer
19678c7de408SJeff Kirsher  */
19688c7de408SJeff Kirsher 
sis900_close(struct net_device * net_dev)19698c7de408SJeff Kirsher static int sis900_close(struct net_device *net_dev)
19708c7de408SJeff Kirsher {
19718c7de408SJeff Kirsher 	struct sis900_private *sis_priv = netdev_priv(net_dev);
197257d6d456SFrancois Romieu 	struct pci_dev *pdev = sis_priv->pci_dev;
197357d6d456SFrancois Romieu 	void __iomem *ioaddr = sis_priv->ioaddr;
19748c7de408SJeff Kirsher 	struct sk_buff *skb;
19758c7de408SJeff Kirsher 	int i;
19768c7de408SJeff Kirsher 
19778c7de408SJeff Kirsher 	netif_stop_queue(net_dev);
19788c7de408SJeff Kirsher 
19798c7de408SJeff Kirsher 	/* Disable interrupts by clearing the interrupt mask. */
198057d6d456SFrancois Romieu 	sw32(imr, 0x0000);
198157d6d456SFrancois Romieu 	sw32(ier, 0x0000);
19828c7de408SJeff Kirsher 
19838c7de408SJeff Kirsher 	/* Stop the chip's Tx and Rx Status Machine */
198457d6d456SFrancois Romieu 	sw32(cr, RxDIS | TxDIS | sr32(cr));
19858c7de408SJeff Kirsher 
19868c7de408SJeff Kirsher 	del_timer(&sis_priv->timer);
19878c7de408SJeff Kirsher 
198857d6d456SFrancois Romieu 	free_irq(pdev->irq, net_dev);
19898c7de408SJeff Kirsher 
19908c7de408SJeff Kirsher 	/* Free Tx and RX skbuff */
19918c7de408SJeff Kirsher 	for (i = 0; i < NUM_RX_DESC; i++) {
19928c7de408SJeff Kirsher 		skb = sis_priv->rx_skbuff[i];
19938c7de408SJeff Kirsher 		if (skb) {
1994256ca744SChristophe JAILLET 			dma_unmap_single(&pdev->dev,
1995256ca744SChristophe JAILLET 					 sis_priv->rx_ring[i].bufptr,
1996256ca744SChristophe JAILLET 					 RX_BUF_SIZE, DMA_FROM_DEVICE);
19978c7de408SJeff Kirsher 			dev_kfree_skb(skb);
19988c7de408SJeff Kirsher 			sis_priv->rx_skbuff[i] = NULL;
19998c7de408SJeff Kirsher 		}
20008c7de408SJeff Kirsher 	}
20018c7de408SJeff Kirsher 	for (i = 0; i < NUM_TX_DESC; i++) {
20028c7de408SJeff Kirsher 		skb = sis_priv->tx_skbuff[i];
20038c7de408SJeff Kirsher 		if (skb) {
2004256ca744SChristophe JAILLET 			dma_unmap_single(&pdev->dev,
2005256ca744SChristophe JAILLET 					 sis_priv->tx_ring[i].bufptr,
2006256ca744SChristophe JAILLET 					 skb->len, DMA_TO_DEVICE);
20078c7de408SJeff Kirsher 			dev_kfree_skb(skb);
20088c7de408SJeff Kirsher 			sis_priv->tx_skbuff[i] = NULL;
20098c7de408SJeff Kirsher 		}
20108c7de408SJeff Kirsher 	}
20118c7de408SJeff Kirsher 
20128c7de408SJeff Kirsher 	/* Green! Put the chip in low-power mode. */
20138c7de408SJeff Kirsher 
20148c7de408SJeff Kirsher 	return 0;
20158c7de408SJeff Kirsher }
20168c7de408SJeff Kirsher 
20178c7de408SJeff Kirsher /**
20188c7de408SJeff Kirsher  *	sis900_get_drvinfo - Return information about driver
20198c7de408SJeff Kirsher  *	@net_dev: the net device to probe
20208c7de408SJeff Kirsher  *	@info: container for info returned
20218c7de408SJeff Kirsher  *
20228c7de408SJeff Kirsher  *	Process ethtool command such as "ehtool -i" to show information
20238c7de408SJeff Kirsher  */
20248c7de408SJeff Kirsher 
sis900_get_drvinfo(struct net_device * net_dev,struct ethtool_drvinfo * info)20258c7de408SJeff Kirsher static void sis900_get_drvinfo(struct net_device *net_dev,
20268c7de408SJeff Kirsher 			       struct ethtool_drvinfo *info)
20278c7de408SJeff Kirsher {
20288c7de408SJeff Kirsher 	struct sis900_private *sis_priv = netdev_priv(net_dev);
20298c7de408SJeff Kirsher 
2030f029c781SWolfram Sang 	strscpy(info->driver, SIS900_MODULE_NAME, sizeof(info->driver));
2031f029c781SWolfram Sang 	strscpy(info->version, SIS900_DRV_VERSION, sizeof(info->version));
2032f029c781SWolfram Sang 	strscpy(info->bus_info, pci_name(sis_priv->pci_dev),
203323020ab3SRick Jones 		sizeof(info->bus_info));
20348c7de408SJeff Kirsher }
20358c7de408SJeff Kirsher 
sis900_get_msglevel(struct net_device * net_dev)20368c7de408SJeff Kirsher static u32 sis900_get_msglevel(struct net_device *net_dev)
20378c7de408SJeff Kirsher {
20388c7de408SJeff Kirsher 	struct sis900_private *sis_priv = netdev_priv(net_dev);
20398c7de408SJeff Kirsher 	return sis_priv->msg_enable;
20408c7de408SJeff Kirsher }
20418c7de408SJeff Kirsher 
sis900_set_msglevel(struct net_device * net_dev,u32 value)20428c7de408SJeff Kirsher static void sis900_set_msglevel(struct net_device *net_dev, u32 value)
20438c7de408SJeff Kirsher {
20448c7de408SJeff Kirsher 	struct sis900_private *sis_priv = netdev_priv(net_dev);
20458c7de408SJeff Kirsher 	sis_priv->msg_enable = value;
20468c7de408SJeff Kirsher }
20478c7de408SJeff Kirsher 
sis900_get_link(struct net_device * net_dev)20488c7de408SJeff Kirsher static u32 sis900_get_link(struct net_device *net_dev)
20498c7de408SJeff Kirsher {
20508c7de408SJeff Kirsher 	struct sis900_private *sis_priv = netdev_priv(net_dev);
20518c7de408SJeff Kirsher 	return mii_link_ok(&sis_priv->mii_info);
20528c7de408SJeff Kirsher }
20538c7de408SJeff Kirsher 
sis900_get_link_ksettings(struct net_device * net_dev,struct ethtool_link_ksettings * cmd)20547d59e319SPhilippe Reynes static int sis900_get_link_ksettings(struct net_device *net_dev,
20557d59e319SPhilippe Reynes 				     struct ethtool_link_ksettings *cmd)
20568c7de408SJeff Kirsher {
20578c7de408SJeff Kirsher 	struct sis900_private *sis_priv = netdev_priv(net_dev);
20588c7de408SJeff Kirsher 	spin_lock_irq(&sis_priv->lock);
20597d59e319SPhilippe Reynes 	mii_ethtool_get_link_ksettings(&sis_priv->mii_info, cmd);
20608c7de408SJeff Kirsher 	spin_unlock_irq(&sis_priv->lock);
20618c7de408SJeff Kirsher 	return 0;
20628c7de408SJeff Kirsher }
20638c7de408SJeff Kirsher 
sis900_set_link_ksettings(struct net_device * net_dev,const struct ethtool_link_ksettings * cmd)20647d59e319SPhilippe Reynes static int sis900_set_link_ksettings(struct net_device *net_dev,
20657d59e319SPhilippe Reynes 				     const struct ethtool_link_ksettings *cmd)
20668c7de408SJeff Kirsher {
20678c7de408SJeff Kirsher 	struct sis900_private *sis_priv = netdev_priv(net_dev);
20688c7de408SJeff Kirsher 	int rt;
20698c7de408SJeff Kirsher 	spin_lock_irq(&sis_priv->lock);
20707d59e319SPhilippe Reynes 	rt = mii_ethtool_set_link_ksettings(&sis_priv->mii_info, cmd);
20718c7de408SJeff Kirsher 	spin_unlock_irq(&sis_priv->lock);
20728c7de408SJeff Kirsher 	return rt;
20738c7de408SJeff Kirsher }
20748c7de408SJeff Kirsher 
sis900_nway_reset(struct net_device * net_dev)20758c7de408SJeff Kirsher static int sis900_nway_reset(struct net_device *net_dev)
20768c7de408SJeff Kirsher {
20778c7de408SJeff Kirsher 	struct sis900_private *sis_priv = netdev_priv(net_dev);
20788c7de408SJeff Kirsher 	return mii_nway_restart(&sis_priv->mii_info);
20798c7de408SJeff Kirsher }
20808c7de408SJeff Kirsher 
20818c7de408SJeff Kirsher /**
20828c7de408SJeff Kirsher  *	sis900_set_wol - Set up Wake on Lan registers
20838c7de408SJeff Kirsher  *	@net_dev: the net device to probe
20848c7de408SJeff Kirsher  *	@wol: container for info passed to the driver
20858c7de408SJeff Kirsher  *
20868c7de408SJeff Kirsher  *	Process ethtool command "wol" to setup wake on lan features.
20878c7de408SJeff Kirsher  *	SiS900 supports sending WoL events if a correct packet is received,
20888c7de408SJeff Kirsher  *	but there is no simple way to filter them to only a subset (broadcast,
20898c7de408SJeff Kirsher  *	multicast, unicast or arp).
20908c7de408SJeff Kirsher  */
20918c7de408SJeff Kirsher 
sis900_set_wol(struct net_device * net_dev,struct ethtool_wolinfo * wol)20928c7de408SJeff Kirsher static int sis900_set_wol(struct net_device *net_dev, struct ethtool_wolinfo *wol)
20938c7de408SJeff Kirsher {
20948c7de408SJeff Kirsher 	struct sis900_private *sis_priv = netdev_priv(net_dev);
209557d6d456SFrancois Romieu 	void __iomem *ioaddr = sis_priv->ioaddr;
20968c7de408SJeff Kirsher 	u32 cfgpmcsr = 0, pmctrl_bits = 0;
20978c7de408SJeff Kirsher 
20988c7de408SJeff Kirsher 	if (wol->wolopts == 0) {
20998c7de408SJeff Kirsher 		pci_read_config_dword(sis_priv->pci_dev, CFGPMCSR, &cfgpmcsr);
21008c7de408SJeff Kirsher 		cfgpmcsr &= ~PME_EN;
21018c7de408SJeff Kirsher 		pci_write_config_dword(sis_priv->pci_dev, CFGPMCSR, cfgpmcsr);
210257d6d456SFrancois Romieu 		sw32(pmctrl, pmctrl_bits);
21038c7de408SJeff Kirsher 		if (netif_msg_wol(sis_priv))
21048c7de408SJeff Kirsher 			printk(KERN_DEBUG "%s: Wake on LAN disabled\n", net_dev->name);
21058c7de408SJeff Kirsher 		return 0;
21068c7de408SJeff Kirsher 	}
21078c7de408SJeff Kirsher 
21088c7de408SJeff Kirsher 	if (wol->wolopts & (WAKE_MAGICSECURE | WAKE_UCAST | WAKE_MCAST
21098c7de408SJeff Kirsher 				| WAKE_BCAST | WAKE_ARP))
21108c7de408SJeff Kirsher 		return -EINVAL;
21118c7de408SJeff Kirsher 
21128c7de408SJeff Kirsher 	if (wol->wolopts & WAKE_MAGIC)
21138c7de408SJeff Kirsher 		pmctrl_bits |= MAGICPKT;
21148c7de408SJeff Kirsher 	if (wol->wolopts & WAKE_PHY)
21158c7de408SJeff Kirsher 		pmctrl_bits |= LINKON;
21168c7de408SJeff Kirsher 
211757d6d456SFrancois Romieu 	sw32(pmctrl, pmctrl_bits);
21188c7de408SJeff Kirsher 
21198c7de408SJeff Kirsher 	pci_read_config_dword(sis_priv->pci_dev, CFGPMCSR, &cfgpmcsr);
21208c7de408SJeff Kirsher 	cfgpmcsr |= PME_EN;
21218c7de408SJeff Kirsher 	pci_write_config_dword(sis_priv->pci_dev, CFGPMCSR, cfgpmcsr);
21228c7de408SJeff Kirsher 	if (netif_msg_wol(sis_priv))
21238c7de408SJeff Kirsher 		printk(KERN_DEBUG "%s: Wake on LAN enabled\n", net_dev->name);
21248c7de408SJeff Kirsher 
21258c7de408SJeff Kirsher 	return 0;
21268c7de408SJeff Kirsher }
21278c7de408SJeff Kirsher 
sis900_get_wol(struct net_device * net_dev,struct ethtool_wolinfo * wol)21288c7de408SJeff Kirsher static void sis900_get_wol(struct net_device *net_dev, struct ethtool_wolinfo *wol)
21298c7de408SJeff Kirsher {
213057d6d456SFrancois Romieu 	struct sis900_private *sp = netdev_priv(net_dev);
213157d6d456SFrancois Romieu 	void __iomem *ioaddr = sp->ioaddr;
21328c7de408SJeff Kirsher 	u32 pmctrl_bits;
21338c7de408SJeff Kirsher 
213457d6d456SFrancois Romieu 	pmctrl_bits = sr32(pmctrl);
21358c7de408SJeff Kirsher 	if (pmctrl_bits & MAGICPKT)
21368c7de408SJeff Kirsher 		wol->wolopts |= WAKE_MAGIC;
21378c7de408SJeff Kirsher 	if (pmctrl_bits & LINKON)
21388c7de408SJeff Kirsher 		wol->wolopts |= WAKE_PHY;
21398c7de408SJeff Kirsher 
21408c7de408SJeff Kirsher 	wol->supported = (WAKE_PHY | WAKE_MAGIC);
21418c7de408SJeff Kirsher }
21428c7de408SJeff Kirsher 
sis900_get_eeprom_len(struct net_device * dev)2143cd8ae207SSergej Benilov static int sis900_get_eeprom_len(struct net_device *dev)
2144cd8ae207SSergej Benilov {
2145cd8ae207SSergej Benilov 	struct sis900_private *sis_priv = netdev_priv(dev);
2146cd8ae207SSergej Benilov 
2147cd8ae207SSergej Benilov 	return sis_priv->eeprom_size;
2148cd8ae207SSergej Benilov }
2149cd8ae207SSergej Benilov 
sis900_read_eeprom(struct net_device * net_dev,u8 * buf)2150cd8ae207SSergej Benilov static int sis900_read_eeprom(struct net_device *net_dev, u8 *buf)
2151cd8ae207SSergej Benilov {
2152cd8ae207SSergej Benilov 	struct sis900_private *sis_priv = netdev_priv(net_dev);
2153cd8ae207SSergej Benilov 	void __iomem *ioaddr = sis_priv->ioaddr;
2154cd8ae207SSergej Benilov 	int wait, ret = -EAGAIN;
2155cd8ae207SSergej Benilov 	u16 signature;
2156cd8ae207SSergej Benilov 	u16 *ebuf = (u16 *)buf;
2157cd8ae207SSergej Benilov 	int i;
2158cd8ae207SSergej Benilov 
2159cd8ae207SSergej Benilov 	if (sis_priv->chipset_rev == SIS96x_900_REV) {
2160cd8ae207SSergej Benilov 		sw32(mear, EEREQ);
2161cd8ae207SSergej Benilov 		for (wait = 0; wait < 2000; wait++) {
2162cd8ae207SSergej Benilov 			if (sr32(mear) & EEGNT) {
2163cd8ae207SSergej Benilov 				/* read 16 bits, and index by 16 bits */
2164cd8ae207SSergej Benilov 				for (i = 0; i < sis_priv->eeprom_size / 2; i++)
2165cd8ae207SSergej Benilov 					ebuf[i] = (u16)read_eeprom(ioaddr, i);
2166cd8ae207SSergej Benilov 				ret = 0;
2167cd8ae207SSergej Benilov 				break;
2168cd8ae207SSergej Benilov 			}
2169cd8ae207SSergej Benilov 			udelay(1);
2170cd8ae207SSergej Benilov 		}
2171cd8ae207SSergej Benilov 		sw32(mear, EEDONE);
2172cd8ae207SSergej Benilov 	} else {
2173cd8ae207SSergej Benilov 		signature = (u16)read_eeprom(ioaddr, EEPROMSignature);
2174cd8ae207SSergej Benilov 		if (signature != 0xffff && signature != 0x0000) {
2175cd8ae207SSergej Benilov 			/* read 16 bits, and index by 16 bits */
2176cd8ae207SSergej Benilov 			for (i = 0; i < sis_priv->eeprom_size / 2; i++)
2177cd8ae207SSergej Benilov 				ebuf[i] = (u16)read_eeprom(ioaddr, i);
2178cd8ae207SSergej Benilov 			ret = 0;
2179cd8ae207SSergej Benilov 		}
2180cd8ae207SSergej Benilov 	}
2181cd8ae207SSergej Benilov 	return ret;
2182cd8ae207SSergej Benilov }
2183cd8ae207SSergej Benilov 
2184cd8ae207SSergej Benilov #define SIS900_EEPROM_MAGIC	0xBABE
sis900_get_eeprom(struct net_device * dev,struct ethtool_eeprom * eeprom,u8 * data)2185cd8ae207SSergej Benilov static int sis900_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data)
2186cd8ae207SSergej Benilov {
2187cd8ae207SSergej Benilov 	struct sis900_private *sis_priv = netdev_priv(dev);
2188cd8ae207SSergej Benilov 	u8 *eebuf;
2189cd8ae207SSergej Benilov 	int res;
2190cd8ae207SSergej Benilov 
2191cd8ae207SSergej Benilov 	eebuf = kmalloc(sis_priv->eeprom_size, GFP_KERNEL);
2192cd8ae207SSergej Benilov 	if (!eebuf)
2193cd8ae207SSergej Benilov 		return -ENOMEM;
2194cd8ae207SSergej Benilov 
2195cd8ae207SSergej Benilov 	eeprom->magic = SIS900_EEPROM_MAGIC;
2196cd8ae207SSergej Benilov 	spin_lock_irq(&sis_priv->lock);
2197cd8ae207SSergej Benilov 	res = sis900_read_eeprom(dev, eebuf);
2198cd8ae207SSergej Benilov 	spin_unlock_irq(&sis_priv->lock);
2199cd8ae207SSergej Benilov 	if (!res)
2200cd8ae207SSergej Benilov 		memcpy(data, eebuf + eeprom->offset, eeprom->len);
2201cd8ae207SSergej Benilov 	kfree(eebuf);
2202cd8ae207SSergej Benilov 	return res;
2203cd8ae207SSergej Benilov }
2204cd8ae207SSergej Benilov 
22058c7de408SJeff Kirsher static const struct ethtool_ops sis900_ethtool_ops = {
22068c7de408SJeff Kirsher 	.get_drvinfo 	= sis900_get_drvinfo,
22078c7de408SJeff Kirsher 	.get_msglevel	= sis900_get_msglevel,
22088c7de408SJeff Kirsher 	.set_msglevel	= sis900_set_msglevel,
22098c7de408SJeff Kirsher 	.get_link	= sis900_get_link,
22108c7de408SJeff Kirsher 	.nway_reset	= sis900_nway_reset,
22118c7de408SJeff Kirsher 	.get_wol	= sis900_get_wol,
22127d59e319SPhilippe Reynes 	.set_wol	= sis900_set_wol,
22137d59e319SPhilippe Reynes 	.get_link_ksettings = sis900_get_link_ksettings,
22147d59e319SPhilippe Reynes 	.set_link_ksettings = sis900_set_link_ksettings,
2215cd8ae207SSergej Benilov 	.get_eeprom_len = sis900_get_eeprom_len,
2216cd8ae207SSergej Benilov 	.get_eeprom = sis900_get_eeprom,
22178c7de408SJeff Kirsher };
22188c7de408SJeff Kirsher 
22198c7de408SJeff Kirsher /**
22208c7de408SJeff Kirsher  *	mii_ioctl - process MII i/o control command
22218c7de408SJeff Kirsher  *	@net_dev: the net device to command for
22228c7de408SJeff Kirsher  *	@rq: parameter for command
22238c7de408SJeff Kirsher  *	@cmd: the i/o command
22248c7de408SJeff Kirsher  *
22258c7de408SJeff Kirsher  *	Process MII command like read/write MII register
22268c7de408SJeff Kirsher  */
22278c7de408SJeff Kirsher 
mii_ioctl(struct net_device * net_dev,struct ifreq * rq,int cmd)22288c7de408SJeff Kirsher static int mii_ioctl(struct net_device *net_dev, struct ifreq *rq, int cmd)
22298c7de408SJeff Kirsher {
22308c7de408SJeff Kirsher 	struct sis900_private *sis_priv = netdev_priv(net_dev);
22318c7de408SJeff Kirsher 	struct mii_ioctl_data *data = if_mii(rq);
22328c7de408SJeff Kirsher 
22338c7de408SJeff Kirsher 	switch(cmd) {
22348c7de408SJeff Kirsher 	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
22358c7de408SJeff Kirsher 		data->phy_id = sis_priv->mii->phy_addr;
2236df561f66SGustavo A. R. Silva 		fallthrough;
22378c7de408SJeff Kirsher 
22388c7de408SJeff Kirsher 	case SIOCGMIIREG:		/* Read MII PHY register. */
22398c7de408SJeff Kirsher 		data->val_out = mdio_read(net_dev, data->phy_id & 0x1f, data->reg_num & 0x1f);
22408c7de408SJeff Kirsher 		return 0;
22418c7de408SJeff Kirsher 
22428c7de408SJeff Kirsher 	case SIOCSMIIREG:		/* Write MII PHY register. */
22438c7de408SJeff Kirsher 		mdio_write(net_dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
22448c7de408SJeff Kirsher 		return 0;
22458c7de408SJeff Kirsher 	default:
22468c7de408SJeff Kirsher 		return -EOPNOTSUPP;
22478c7de408SJeff Kirsher 	}
22488c7de408SJeff Kirsher }
22498c7de408SJeff Kirsher 
22508c7de408SJeff Kirsher /**
22518c7de408SJeff Kirsher  *	sis900_set_config - Set media type by net_device.set_config
22528c7de408SJeff Kirsher  *	@dev: the net device for media type change
22538c7de408SJeff Kirsher  *	@map: ifmap passed by ifconfig
22548c7de408SJeff Kirsher  *
22558c7de408SJeff Kirsher  *	Set media type to 10baseT, 100baseT or 0(for auto) by ifconfig
22568c7de408SJeff Kirsher  *	we support only port changes. All other runtime configuration
22578c7de408SJeff Kirsher  *	changes will be ignored
22588c7de408SJeff Kirsher  */
22598c7de408SJeff Kirsher 
sis900_set_config(struct net_device * dev,struct ifmap * map)22608c7de408SJeff Kirsher static int sis900_set_config(struct net_device *dev, struct ifmap *map)
22618c7de408SJeff Kirsher {
22628c7de408SJeff Kirsher 	struct sis900_private *sis_priv = netdev_priv(dev);
22638c7de408SJeff Kirsher 	struct mii_phy *mii_phy = sis_priv->mii;
22648c7de408SJeff Kirsher 
22658c7de408SJeff Kirsher 	u16 status;
22668c7de408SJeff Kirsher 
22678c7de408SJeff Kirsher 	if ((map->port != (u_char)(-1)) && (map->port != dev->if_port)) {
22688c7de408SJeff Kirsher 		/* we switch on the ifmap->port field. I couldn't find anything
22698c7de408SJeff Kirsher 		 * like a definition or standard for the values of that field.
22708c7de408SJeff Kirsher 		 * I think the meaning of those values is device specific. But
22718c7de408SJeff Kirsher 		 * since I would like to change the media type via the ifconfig
22728c7de408SJeff Kirsher 		 * command I use the definition from linux/netdevice.h
22738c7de408SJeff Kirsher 		 * (which seems to be different from the ifport(pcmcia) definition) */
22748c7de408SJeff Kirsher 		switch(map->port){
22758c7de408SJeff Kirsher 		case IF_PORT_UNKNOWN: /* use auto here */
2276*8d8b1a42SEric Dumazet 			WRITE_ONCE(dev->if_port, map->port);
22778c7de408SJeff Kirsher 			/* we are going to change the media type, so the Link
22788c7de408SJeff Kirsher 			 * will be temporary down and we need to reflect that
22798c7de408SJeff Kirsher 			 * here. When the Link comes up again, it will be
22808c7de408SJeff Kirsher 			 * sensed by the sis_timer procedure, which also does
22818c7de408SJeff Kirsher 			 * all the rest for us */
22828c7de408SJeff Kirsher 			netif_carrier_off(dev);
22838c7de408SJeff Kirsher 
22848c7de408SJeff Kirsher 			/* read current state */
22858c7de408SJeff Kirsher 			status = mdio_read(dev, mii_phy->phy_addr, MII_CONTROL);
22868c7de408SJeff Kirsher 
22878c7de408SJeff Kirsher 			/* enable auto negotiation and reset the negotioation
22888c7de408SJeff Kirsher 			 * (I don't really know what the auto negatiotiation
22898c7de408SJeff Kirsher 			 * reset really means, but it sounds for me right to
22908c7de408SJeff Kirsher 			 * do one here) */
22918c7de408SJeff Kirsher 			mdio_write(dev, mii_phy->phy_addr,
22928c7de408SJeff Kirsher 				   MII_CONTROL, status | MII_CNTL_AUTO | MII_CNTL_RST_AUTO);
22938c7de408SJeff Kirsher 
22948c7de408SJeff Kirsher 			break;
22958c7de408SJeff Kirsher 
22968c7de408SJeff Kirsher 		case IF_PORT_10BASET: /* 10BaseT */
2297*8d8b1a42SEric Dumazet 			WRITE_ONCE(dev->if_port, map->port);
22988c7de408SJeff Kirsher 
22998c7de408SJeff Kirsher 			/* we are going to change the media type, so the Link
23008c7de408SJeff Kirsher 			 * will be temporary down and we need to reflect that
23018c7de408SJeff Kirsher 			 * here. When the Link comes up again, it will be
23028c7de408SJeff Kirsher 			 * sensed by the sis_timer procedure, which also does
23038c7de408SJeff Kirsher 			 * all the rest for us */
23048c7de408SJeff Kirsher 			netif_carrier_off(dev);
23058c7de408SJeff Kirsher 
23068c7de408SJeff Kirsher 			/* set Speed to 10Mbps */
23078c7de408SJeff Kirsher 			/* read current state */
23088c7de408SJeff Kirsher 			status = mdio_read(dev, mii_phy->phy_addr, MII_CONTROL);
23098c7de408SJeff Kirsher 
23108c7de408SJeff Kirsher 			/* disable auto negotiation and force 10MBit mode*/
23118c7de408SJeff Kirsher 			mdio_write(dev, mii_phy->phy_addr,
23128c7de408SJeff Kirsher 				   MII_CONTROL, status & ~(MII_CNTL_SPEED |
23138c7de408SJeff Kirsher 					MII_CNTL_AUTO));
23148c7de408SJeff Kirsher 			break;
23158c7de408SJeff Kirsher 
23168c7de408SJeff Kirsher 		case IF_PORT_100BASET: /* 100BaseT */
23178c7de408SJeff Kirsher 		case IF_PORT_100BASETX: /* 100BaseTx */
2318*8d8b1a42SEric Dumazet 			WRITE_ONCE(dev->if_port, map->port);
23198c7de408SJeff Kirsher 
23208c7de408SJeff Kirsher 			/* we are going to change the media type, so the Link
23218c7de408SJeff Kirsher 			 * will be temporary down and we need to reflect that
23228c7de408SJeff Kirsher 			 * here. When the Link comes up again, it will be
23238c7de408SJeff Kirsher 			 * sensed by the sis_timer procedure, which also does
23248c7de408SJeff Kirsher 			 * all the rest for us */
23258c7de408SJeff Kirsher 			netif_carrier_off(dev);
23268c7de408SJeff Kirsher 
23278c7de408SJeff Kirsher 			/* set Speed to 100Mbps */
23288c7de408SJeff Kirsher 			/* disable auto negotiation and enable 100MBit Mode */
23298c7de408SJeff Kirsher 			status = mdio_read(dev, mii_phy->phy_addr, MII_CONTROL);
23308c7de408SJeff Kirsher 			mdio_write(dev, mii_phy->phy_addr,
23318c7de408SJeff Kirsher 				   MII_CONTROL, (status & ~MII_CNTL_SPEED) |
23328c7de408SJeff Kirsher 				   MII_CNTL_SPEED);
23338c7de408SJeff Kirsher 
23348c7de408SJeff Kirsher 			break;
23358c7de408SJeff Kirsher 
23368c7de408SJeff Kirsher 		case IF_PORT_10BASE2: /* 10Base2 */
23378c7de408SJeff Kirsher 		case IF_PORT_AUI: /* AUI */
23388c7de408SJeff Kirsher 		case IF_PORT_100BASEFX: /* 100BaseFx */
23398c7de408SJeff Kirsher 			/* These Modes are not supported (are they?)*/
23408c7de408SJeff Kirsher 			return -EOPNOTSUPP;
23418c7de408SJeff Kirsher 
23428c7de408SJeff Kirsher 		default:
23438c7de408SJeff Kirsher 			return -EINVAL;
23448c7de408SJeff Kirsher 		}
23458c7de408SJeff Kirsher 	}
23468c7de408SJeff Kirsher 	return 0;
23478c7de408SJeff Kirsher }
23488c7de408SJeff Kirsher 
23498c7de408SJeff Kirsher /**
23508c7de408SJeff Kirsher  *	sis900_mcast_bitnr - compute hashtable index
23518c7de408SJeff Kirsher  *	@addr: multicast address
23528c7de408SJeff Kirsher  *	@revision: revision id of chip
23538c7de408SJeff Kirsher  *
23548c7de408SJeff Kirsher  *	SiS 900 uses the most sigificant 7 bits to index a 128 bits multicast
23558c7de408SJeff Kirsher  *	hash table, which makes this function a little bit different from other drivers
23568c7de408SJeff Kirsher  *	SiS 900 B0 & 635 M/B uses the most significat 8 bits to index 256 bits
23578c7de408SJeff Kirsher  *   	multicast hash table.
23588c7de408SJeff Kirsher  */
23598c7de408SJeff Kirsher 
sis900_mcast_bitnr(u8 * addr,u8 revision)23608c7de408SJeff Kirsher static inline u16 sis900_mcast_bitnr(u8 *addr, u8 revision)
23618c7de408SJeff Kirsher {
23628c7de408SJeff Kirsher 
23638c7de408SJeff Kirsher 	u32 crc = ether_crc(6, addr);
23648c7de408SJeff Kirsher 
23658c7de408SJeff Kirsher 	/* leave 8 or 7 most siginifant bits */
23668c7de408SJeff Kirsher 	if ((revision >= SIS635A_900_REV) || (revision == SIS900B_900_REV))
23678c7de408SJeff Kirsher 		return (int)(crc >> 24);
23688c7de408SJeff Kirsher 	else
23698c7de408SJeff Kirsher 		return (int)(crc >> 25);
23708c7de408SJeff Kirsher }
23718c7de408SJeff Kirsher 
23728c7de408SJeff Kirsher /**
23738c7de408SJeff Kirsher  *	set_rx_mode - Set SiS900 receive mode
23748c7de408SJeff Kirsher  *	@net_dev: the net device to be set
23758c7de408SJeff Kirsher  *
23768c7de408SJeff Kirsher  *	Set SiS900 receive mode for promiscuous, multicast, or broadcast mode.
23778c7de408SJeff Kirsher  *	And set the appropriate multicast filter.
23788c7de408SJeff Kirsher  *	Multicast hash table changes from 128 to 256 bits for 635M/B & 900B0.
23798c7de408SJeff Kirsher  */
23808c7de408SJeff Kirsher 
set_rx_mode(struct net_device * net_dev)23818c7de408SJeff Kirsher static void set_rx_mode(struct net_device *net_dev)
23828c7de408SJeff Kirsher {
23838c7de408SJeff Kirsher 	struct sis900_private *sis_priv = netdev_priv(net_dev);
238457d6d456SFrancois Romieu 	void __iomem *ioaddr = sis_priv->ioaddr;
23858c7de408SJeff Kirsher 	u16 mc_filter[16] = {0};	/* 256/128 bits multicast hash table */
23868c7de408SJeff Kirsher 	int i, table_entries;
23878c7de408SJeff Kirsher 	u32 rx_mode;
23888c7de408SJeff Kirsher 
23898c7de408SJeff Kirsher 	/* 635 Hash Table entries = 256(2^16) */
23908c7de408SJeff Kirsher 	if((sis_priv->chipset_rev >= SIS635A_900_REV) ||
23918c7de408SJeff Kirsher 			(sis_priv->chipset_rev == SIS900B_900_REV))
23928c7de408SJeff Kirsher 		table_entries = 16;
23938c7de408SJeff Kirsher 	else
23948c7de408SJeff Kirsher 		table_entries = 8;
23958c7de408SJeff Kirsher 
23968c7de408SJeff Kirsher 	if (net_dev->flags & IFF_PROMISC) {
23978c7de408SJeff Kirsher 		/* Accept any kinds of packets */
23988c7de408SJeff Kirsher 		rx_mode = RFPromiscuous;
23998c7de408SJeff Kirsher 		for (i = 0; i < table_entries; i++)
24008c7de408SJeff Kirsher 			mc_filter[i] = 0xffff;
24018c7de408SJeff Kirsher 	} else if ((netdev_mc_count(net_dev) > multicast_filter_limit) ||
24028c7de408SJeff Kirsher 		   (net_dev->flags & IFF_ALLMULTI)) {
24038c7de408SJeff Kirsher 		/* too many multicast addresses or accept all multicast packet */
24048c7de408SJeff Kirsher 		rx_mode = RFAAB | RFAAM;
24058c7de408SJeff Kirsher 		for (i = 0; i < table_entries; i++)
24068c7de408SJeff Kirsher 			mc_filter[i] = 0xffff;
24078c7de408SJeff Kirsher 	} else {
24088c7de408SJeff Kirsher 		/* Accept Broadcast packet, destination address matchs our
24098c7de408SJeff Kirsher 		 * MAC address, use Receive Filter to reject unwanted MCAST
24108c7de408SJeff Kirsher 		 * packets */
24118c7de408SJeff Kirsher 		struct netdev_hw_addr *ha;
24128c7de408SJeff Kirsher 		rx_mode = RFAAB;
24138c7de408SJeff Kirsher 
24148c7de408SJeff Kirsher 		netdev_for_each_mc_addr(ha, net_dev) {
24158c7de408SJeff Kirsher 			unsigned int bit_nr;
24168c7de408SJeff Kirsher 
24178c7de408SJeff Kirsher 			bit_nr = sis900_mcast_bitnr(ha->addr,
24188c7de408SJeff Kirsher 						    sis_priv->chipset_rev);
24198c7de408SJeff Kirsher 			mc_filter[bit_nr >> 4] |= (1 << (bit_nr & 0xf));
24208c7de408SJeff Kirsher 		}
24218c7de408SJeff Kirsher 	}
24228c7de408SJeff Kirsher 
24238c7de408SJeff Kirsher 	/* update Multicast Hash Table in Receive Filter */
24248c7de408SJeff Kirsher 	for (i = 0; i < table_entries; i++) {
24258c7de408SJeff Kirsher                 /* why plus 0x04 ??, That makes the correct value for hash table. */
242657d6d456SFrancois Romieu 		sw32(rfcr, (u32)(0x00000004 + i) << RFADDR_shift);
242757d6d456SFrancois Romieu 		sw32(rfdr, mc_filter[i]);
24288c7de408SJeff Kirsher 	}
24298c7de408SJeff Kirsher 
243057d6d456SFrancois Romieu 	sw32(rfcr, RFEN | rx_mode);
24318c7de408SJeff Kirsher 
24328c7de408SJeff Kirsher 	/* sis900 is capable of looping back packets at MAC level for
24338c7de408SJeff Kirsher 	 * debugging purpose */
24348c7de408SJeff Kirsher 	if (net_dev->flags & IFF_LOOPBACK) {
24358c7de408SJeff Kirsher 		u32 cr_saved;
24368c7de408SJeff Kirsher 		/* We must disable Tx/Rx before setting loopback mode */
243757d6d456SFrancois Romieu 		cr_saved = sr32(cr);
243857d6d456SFrancois Romieu 		sw32(cr, cr_saved | TxDIS | RxDIS);
24398c7de408SJeff Kirsher 		/* enable loopback */
244057d6d456SFrancois Romieu 		sw32(txcfg, sr32(txcfg) | TxMLB);
244157d6d456SFrancois Romieu 		sw32(rxcfg, sr32(rxcfg) | RxATX);
24428c7de408SJeff Kirsher 		/* restore cr */
244357d6d456SFrancois Romieu 		sw32(cr, cr_saved);
24448c7de408SJeff Kirsher 	}
24458c7de408SJeff Kirsher }
24468c7de408SJeff Kirsher 
24478c7de408SJeff Kirsher /**
24488c7de408SJeff Kirsher  *	sis900_reset - Reset sis900 MAC
24498c7de408SJeff Kirsher  *	@net_dev: the net device to reset
24508c7de408SJeff Kirsher  *
24518c7de408SJeff Kirsher  *	reset sis900 MAC and wait until finished
24528c7de408SJeff Kirsher  *	reset through command register
24538c7de408SJeff Kirsher  *	change backoff algorithm for 900B0 & 635 M/B
24548c7de408SJeff Kirsher  */
24558c7de408SJeff Kirsher 
sis900_reset(struct net_device * net_dev)24568c7de408SJeff Kirsher static void sis900_reset(struct net_device *net_dev)
24578c7de408SJeff Kirsher {
24588c7de408SJeff Kirsher 	struct sis900_private *sis_priv = netdev_priv(net_dev);
245957d6d456SFrancois Romieu 	void __iomem *ioaddr = sis_priv->ioaddr;
24608c7de408SJeff Kirsher 	u32 status = TxRCMP | RxRCMP;
246157d6d456SFrancois Romieu 	int i;
24628c7de408SJeff Kirsher 
246357d6d456SFrancois Romieu 	sw32(ier, 0);
246457d6d456SFrancois Romieu 	sw32(imr, 0);
246557d6d456SFrancois Romieu 	sw32(rfcr, 0);
24668c7de408SJeff Kirsher 
246757d6d456SFrancois Romieu 	sw32(cr, RxRESET | TxRESET | RESET | sr32(cr));
24688c7de408SJeff Kirsher 
24698c7de408SJeff Kirsher 	/* Check that the chip has finished the reset. */
247057d6d456SFrancois Romieu 	for (i = 0; status && (i < 1000); i++)
247157d6d456SFrancois Romieu 		status ^= sr32(isr) & status;
24728c7de408SJeff Kirsher 
247357d6d456SFrancois Romieu 	if (sis_priv->chipset_rev >= SIS635A_900_REV ||
247457d6d456SFrancois Romieu 	    sis_priv->chipset_rev == SIS900B_900_REV)
247557d6d456SFrancois Romieu 		sw32(cfg, PESEL | RND_CNT);
24768c7de408SJeff Kirsher 	else
247757d6d456SFrancois Romieu 		sw32(cfg, PESEL);
24788c7de408SJeff Kirsher }
24798c7de408SJeff Kirsher 
24808c7de408SJeff Kirsher /**
24818c7de408SJeff Kirsher  *	sis900_remove - Remove sis900 device
24828c7de408SJeff Kirsher  *	@pci_dev: the pci device to be removed
24838c7de408SJeff Kirsher  *
24848c7de408SJeff Kirsher  *	remove and release SiS900 net device
24858c7de408SJeff Kirsher  */
24868c7de408SJeff Kirsher 
sis900_remove(struct pci_dev * pci_dev)2487369e1231SBill Pemberton static void sis900_remove(struct pci_dev *pci_dev)
24888c7de408SJeff Kirsher {
24898c7de408SJeff Kirsher 	struct net_device *net_dev = pci_get_drvdata(pci_dev);
24908c7de408SJeff Kirsher 	struct sis900_private *sis_priv = netdev_priv(net_dev);
249157d6d456SFrancois Romieu 
249257d6d456SFrancois Romieu 	unregister_netdev(net_dev);
24938c7de408SJeff Kirsher 
24948c7de408SJeff Kirsher 	while (sis_priv->first_mii) {
249557d6d456SFrancois Romieu 		struct mii_phy *phy = sis_priv->first_mii;
249657d6d456SFrancois Romieu 
24978c7de408SJeff Kirsher 		sis_priv->first_mii = phy->next;
24988c7de408SJeff Kirsher 		kfree(phy);
24998c7de408SJeff Kirsher 	}
25008c7de408SJeff Kirsher 
2501256ca744SChristophe JAILLET 	dma_free_coherent(&pci_dev->dev, RX_TOTAL_SIZE, sis_priv->rx_ring,
25028c7de408SJeff Kirsher 			  sis_priv->rx_ring_dma);
2503256ca744SChristophe JAILLET 	dma_free_coherent(&pci_dev->dev, TX_TOTAL_SIZE, sis_priv->tx_ring,
25048c7de408SJeff Kirsher 			  sis_priv->tx_ring_dma);
250557d6d456SFrancois Romieu 	pci_iounmap(pci_dev, sis_priv->ioaddr);
25068c7de408SJeff Kirsher 	free_netdev(net_dev);
25078c7de408SJeff Kirsher }
25088c7de408SJeff Kirsher 
sis900_suspend(struct device * dev)25097fa8bb48SVaibhav Gupta static int __maybe_unused sis900_suspend(struct device *dev)
25108c7de408SJeff Kirsher {
25117fa8bb48SVaibhav Gupta 	struct net_device *net_dev = dev_get_drvdata(dev);
251257d6d456SFrancois Romieu 	struct sis900_private *sis_priv = netdev_priv(net_dev);
251357d6d456SFrancois Romieu 	void __iomem *ioaddr = sis_priv->ioaddr;
25148c7de408SJeff Kirsher 
25158c7de408SJeff Kirsher 	if(!netif_running(net_dev))
25168c7de408SJeff Kirsher 		return 0;
25178c7de408SJeff Kirsher 
25188c7de408SJeff Kirsher 	netif_stop_queue(net_dev);
25198c7de408SJeff Kirsher 	netif_device_detach(net_dev);
25208c7de408SJeff Kirsher 
25218c7de408SJeff Kirsher 	/* Stop the chip's Tx and Rx Status Machine */
252257d6d456SFrancois Romieu 	sw32(cr, RxDIS | TxDIS | sr32(cr));
25238c7de408SJeff Kirsher 
25248c7de408SJeff Kirsher 	return 0;
25258c7de408SJeff Kirsher }
25268c7de408SJeff Kirsher 
sis900_resume(struct device * dev)25277fa8bb48SVaibhav Gupta static int __maybe_unused sis900_resume(struct device *dev)
25288c7de408SJeff Kirsher {
25297fa8bb48SVaibhav Gupta 	struct net_device *net_dev = dev_get_drvdata(dev);
25308c7de408SJeff Kirsher 	struct sis900_private *sis_priv = netdev_priv(net_dev);
253157d6d456SFrancois Romieu 	void __iomem *ioaddr = sis_priv->ioaddr;
25328c7de408SJeff Kirsher 
25338c7de408SJeff Kirsher 	if(!netif_running(net_dev))
25348c7de408SJeff Kirsher 		return 0;
25358c7de408SJeff Kirsher 
25368c7de408SJeff Kirsher 	sis900_init_rxfilter(net_dev);
25378c7de408SJeff Kirsher 
25388c7de408SJeff Kirsher 	sis900_init_tx_ring(net_dev);
25398c7de408SJeff Kirsher 	sis900_init_rx_ring(net_dev);
25408c7de408SJeff Kirsher 
25418c7de408SJeff Kirsher 	set_rx_mode(net_dev);
25428c7de408SJeff Kirsher 
25438c7de408SJeff Kirsher 	netif_device_attach(net_dev);
25448c7de408SJeff Kirsher 	netif_start_queue(net_dev);
25458c7de408SJeff Kirsher 
25468c7de408SJeff Kirsher 	/* Workaround for EDB */
25478495c0daSFrancois Romieu 	sis900_set_mode(sis_priv, HW_SPEED_10_MBPS, FDX_CAPABLE_HALF_SELECTED);
25488c7de408SJeff Kirsher 
25498c7de408SJeff Kirsher 	/* Enable all known interrupts by setting the interrupt mask. */
2550ee7dd773SSergej Benilov 	sw32(imr, RxSOVR | RxORN | RxERR | RxOK | TxURN | TxERR | TxDESC);
255157d6d456SFrancois Romieu 	sw32(cr, RxENA | sr32(cr));
255257d6d456SFrancois Romieu 	sw32(ier, IE);
25538c7de408SJeff Kirsher 
25548c7de408SJeff Kirsher 	sis900_check_mode(net_dev, sis_priv->mii);
25558c7de408SJeff Kirsher 
25568c7de408SJeff Kirsher 	return 0;
25578c7de408SJeff Kirsher }
25587fa8bb48SVaibhav Gupta 
25597fa8bb48SVaibhav Gupta static SIMPLE_DEV_PM_OPS(sis900_pm_ops, sis900_suspend, sis900_resume);
25608c7de408SJeff Kirsher 
25618c7de408SJeff Kirsher static struct pci_driver sis900_pci_driver = {
25628c7de408SJeff Kirsher 	.name		= SIS900_MODULE_NAME,
25638c7de408SJeff Kirsher 	.id_table	= sis900_pci_tbl,
25648c7de408SJeff Kirsher 	.probe		= sis900_probe,
2565369e1231SBill Pemberton 	.remove		= sis900_remove,
25667fa8bb48SVaibhav Gupta 	.driver.pm	= &sis900_pm_ops,
25678c7de408SJeff Kirsher };
25688c7de408SJeff Kirsher 
sis900_init_module(void)25698c7de408SJeff Kirsher static int __init sis900_init_module(void)
25708c7de408SJeff Kirsher {
25718c7de408SJeff Kirsher /* when a module, this is printed whether or not devices are found in probe */
25728c7de408SJeff Kirsher #ifdef MODULE
25738c7de408SJeff Kirsher 	printk(version);
25748c7de408SJeff Kirsher #endif
25758c7de408SJeff Kirsher 
25768c7de408SJeff Kirsher 	return pci_register_driver(&sis900_pci_driver);
25778c7de408SJeff Kirsher }
25788c7de408SJeff Kirsher 
sis900_cleanup_module(void)25798c7de408SJeff Kirsher static void __exit sis900_cleanup_module(void)
25808c7de408SJeff Kirsher {
25818c7de408SJeff Kirsher 	pci_unregister_driver(&sis900_pci_driver);
25828c7de408SJeff Kirsher }
25838c7de408SJeff Kirsher 
25848c7de408SJeff Kirsher module_init(sis900_init_module);
25858c7de408SJeff Kirsher module_exit(sis900_cleanup_module);
25868c7de408SJeff Kirsher 
2587