blob: 20f48296efcb28f2f83356e1925b6de53e4e44e9 [file] [log] [blame]
Francois Romieu890e8d02005-07-30 13:08:43 +02001/*
2 sis190.c: Silicon Integrated Systems SiS190 ethernet driver
3
4 Copyright (c) 2003 K.M. Liu <kmliu@sis.com>
5 Copyright (c) 2003, 2004 Jeff Garzik <jgarzik@pobox.com>
6 Copyright (c) 2003, 2004, 2005 Francois Romieu <romieu@fr.zoreil.com>
7
Francois Romieu40292fb2005-07-30 13:12:06 +02008 Based on r8169.c, tg3.c, 8139cp.c, skge.c, epic100.c and SiS 190/191
9 genuine driver.
Francois Romieu890e8d02005-07-30 13:08:43 +020010
11 This software may be used and distributed according to the terms of
12 the GNU General Public License (GPL), incorporated herein by reference.
13 Drivers based on or derived from this code fall under the GPL and must
14 retain the authorship, copyright and license notice. This file is not
15 a complete program and may only be used when the entire operating
16 system is licensed under the GPL.
17
18 See the file COPYING in this distribution for more information.
19
20 */
21
22#include <linux/module.h>
23#include <linux/moduleparam.h>
24#include <linux/netdevice.h>
Francois Romieu43afb942005-07-30 13:10:21 +020025#include <linux/rtnetlink.h>
Francois Romieu890e8d02005-07-30 13:08:43 +020026#include <linux/etherdevice.h>
27#include <linux/ethtool.h>
28#include <linux/pci.h>
29#include <linux/mii.h>
30#include <linux/delay.h>
31#include <linux/crc32.h>
32#include <linux/dma-mapping.h>
33#include <asm/irq.h>
34
35#define net_drv(p, arg...) if (netif_msg_drv(p)) \
36 printk(arg)
37#define net_probe(p, arg...) if (netif_msg_probe(p)) \
38 printk(arg)
39#define net_link(p, arg...) if (netif_msg_link(p)) \
40 printk(arg)
41#define net_intr(p, arg...) if (netif_msg_intr(p)) \
42 printk(arg)
43#define net_tx_err(p, arg...) if (netif_msg_tx_err(p)) \
44 printk(arg)
45
Francois Romieufcb98212005-07-30 13:15:22 +020046#define PHY_MAX_ADDR 32
47#define PHY_ID_ANY 0x1f
48#define MII_REG_ANY 0x1f
49
Stephen Hemmingerbea33482007-10-03 16:41:36 -070050#define DRV_VERSION "1.2"
Francois Romieu890e8d02005-07-30 13:08:43 +020051#define DRV_NAME "sis190"
52#define SIS190_DRIVER_NAME DRV_NAME " Gigabit Ethernet driver " DRV_VERSION
53#define PFX DRV_NAME ": "
54
Francois Romieu890e8d02005-07-30 13:08:43 +020055#define sis190_rx_skb netif_rx
56#define sis190_rx_quota(count, quota) count
Francois Romieu890e8d02005-07-30 13:08:43 +020057
58#define MAC_ADDR_LEN 6
59
Francois Romieubcad5e52005-07-30 13:13:47 +020060#define NUM_TX_DESC 64 /* [8..1024] */
61#define NUM_RX_DESC 64 /* [8..8192] */
Francois Romieu890e8d02005-07-30 13:08:43 +020062#define TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc))
63#define RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc))
64#define RX_BUF_SIZE 1536
Francois Romieu8b5641d2005-07-30 13:13:03 +020065#define RX_BUF_MASK 0xfff8
Francois Romieu890e8d02005-07-30 13:08:43 +020066
67#define SIS190_REGS_SIZE 0x80
68#define SIS190_TX_TIMEOUT (6*HZ)
69#define SIS190_PHY_TIMEOUT (10*HZ)
70#define SIS190_MSG_DEFAULT (NETIF_MSG_DRV | NETIF_MSG_PROBE | \
71 NETIF_MSG_LINK | NETIF_MSG_IFUP | \
72 NETIF_MSG_IFDOWN)
73
74/* Enhanced PHY access register bit definitions */
75#define EhnMIIread 0x0000
76#define EhnMIIwrite 0x0020
77#define EhnMIIdataShift 16
78#define EhnMIIpmdShift 6 /* 7016 only */
79#define EhnMIIregShift 11
80#define EhnMIIreq 0x0010
81#define EhnMIInotDone 0x0010
82
83/* Write/read MMIO register */
84#define SIS_W8(reg, val) writeb ((val), ioaddr + (reg))
85#define SIS_W16(reg, val) writew ((val), ioaddr + (reg))
86#define SIS_W32(reg, val) writel ((val), ioaddr + (reg))
87#define SIS_R8(reg) readb (ioaddr + (reg))
88#define SIS_R16(reg) readw (ioaddr + (reg))
89#define SIS_R32(reg) readl (ioaddr + (reg))
90
91#define SIS_PCI_COMMIT() SIS_R32(IntrControl)
92
93enum sis190_registers {
94 TxControl = 0x00,
95 TxDescStartAddr = 0x04,
Francois Romieu188f23b2005-07-30 13:11:43 +020096 rsv0 = 0x08, // reserved
97 TxSts = 0x0c, // unused (Control/Status)
Francois Romieu890e8d02005-07-30 13:08:43 +020098 RxControl = 0x10,
99 RxDescStartAddr = 0x14,
Francois Romieu188f23b2005-07-30 13:11:43 +0200100 rsv1 = 0x18, // reserved
101 RxSts = 0x1c, // unused
Francois Romieu890e8d02005-07-30 13:08:43 +0200102 IntrStatus = 0x20,
103 IntrMask = 0x24,
104 IntrControl = 0x28,
Francois Romieu188f23b2005-07-30 13:11:43 +0200105 IntrTimer = 0x2c, // unused (Interupt Timer)
106 PMControl = 0x30, // unused (Power Mgmt Control/Status)
107 rsv2 = 0x34, // reserved
Francois Romieu890e8d02005-07-30 13:08:43 +0200108 ROMControl = 0x38,
109 ROMInterface = 0x3c,
110 StationControl = 0x40,
111 GMIIControl = 0x44,
Francois Romieu188f23b2005-07-30 13:11:43 +0200112 GIoCR = 0x48, // unused (GMAC IO Compensation)
113 GIoCtrl = 0x4c, // unused (GMAC IO Control)
Francois Romieu890e8d02005-07-30 13:08:43 +0200114 TxMacControl = 0x50,
Francois Romieu188f23b2005-07-30 13:11:43 +0200115 TxLimit = 0x54, // unused (Tx MAC Timer/TryLimit)
116 RGDelay = 0x58, // unused (RGMII Tx Internal Delay)
117 rsv3 = 0x5c, // reserved
Francois Romieu890e8d02005-07-30 13:08:43 +0200118 RxMacControl = 0x60,
119 RxMacAddr = 0x62,
120 RxHashTable = 0x68,
121 // Undocumented = 0x6c,
Francois Romieu188f23b2005-07-30 13:11:43 +0200122 RxWolCtrl = 0x70,
123 RxWolData = 0x74, // unused (Rx WOL Data Access)
124 RxMPSControl = 0x78, // unused (Rx MPS Control)
125 rsv4 = 0x7c, // reserved
Francois Romieu890e8d02005-07-30 13:08:43 +0200126};
127
128enum sis190_register_content {
129 /* IntrStatus */
130 SoftInt = 0x40000000, // unused
131 Timeup = 0x20000000, // unused
132 PauseFrame = 0x00080000, // unused
133 MagicPacket = 0x00040000, // unused
134 WakeupFrame = 0x00020000, // unused
135 LinkChange = 0x00010000,
136 RxQEmpty = 0x00000080,
137 RxQInt = 0x00000040,
138 TxQ1Empty = 0x00000020, // unused
139 TxQ1Int = 0x00000010,
140 TxQ0Empty = 0x00000008, // unused
141 TxQ0Int = 0x00000004,
142 RxHalt = 0x00000002,
143 TxHalt = 0x00000001,
144
Francois Romieu890e8d02005-07-30 13:08:43 +0200145 /* {Rx/Tx}CmdBits */
146 CmdReset = 0x10,
147 CmdRxEnb = 0x08, // unused
148 CmdTxEnb = 0x01,
149 RxBufEmpty = 0x01, // unused
150
151 /* Cfg9346Bits */
152 Cfg9346_Lock = 0x00, // unused
153 Cfg9346_Unlock = 0xc0, // unused
154
155 /* RxMacControl */
156 AcceptErr = 0x20, // unused
157 AcceptRunt = 0x10, // unused
158 AcceptBroadcast = 0x0800,
159 AcceptMulticast = 0x0400,
160 AcceptMyPhys = 0x0200,
161 AcceptAllPhys = 0x0100,
162
163 /* RxConfigBits */
164 RxCfgFIFOShift = 13,
165 RxCfgDMAShift = 8, // 0x1a in RxControl ?
166
167 /* TxConfigBits */
168 TxInterFrameGapShift = 24,
169 TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */
170
Francois Romieu890e8d02005-07-30 13:08:43 +0200171 LinkStatus = 0x02, // unused
172 FullDup = 0x01, // unused
173
174 /* TBICSRBit */
175 TBILinkOK = 0x02000000, // unused
176};
177
178struct TxDesc {
Francois Romieu3cec93c2005-07-30 13:14:18 +0200179 __le32 PSize;
180 __le32 status;
181 __le32 addr;
182 __le32 size;
Francois Romieu890e8d02005-07-30 13:08:43 +0200183};
184
185struct RxDesc {
Francois Romieu3cec93c2005-07-30 13:14:18 +0200186 __le32 PSize;
187 __le32 status;
188 __le32 addr;
189 __le32 size;
Francois Romieu890e8d02005-07-30 13:08:43 +0200190};
191
192enum _DescStatusBit {
193 /* _Desc.status */
Francois Romieubcad5e52005-07-30 13:13:47 +0200194 OWNbit = 0x80000000, // RXOWN/TXOWN
195 INTbit = 0x40000000, // RXINT/TXINT
196 CRCbit = 0x00020000, // CRCOFF/CRCEN
197 PADbit = 0x00010000, // PREADD/PADEN
Francois Romieu890e8d02005-07-30 13:08:43 +0200198 /* _Desc.size */
Francois Romieubcad5e52005-07-30 13:13:47 +0200199 RingEnd = 0x80000000,
200 /* TxDesc.status */
201 LSEN = 0x08000000, // TSO ? -- FR
202 IPCS = 0x04000000,
203 TCPCS = 0x02000000,
204 UDPCS = 0x01000000,
205 BSTEN = 0x00800000,
206 EXTEN = 0x00400000,
207 DEFEN = 0x00200000,
208 BKFEN = 0x00100000,
209 CRSEN = 0x00080000,
210 COLEN = 0x00040000,
211 THOL3 = 0x30000000,
212 THOL2 = 0x20000000,
213 THOL1 = 0x10000000,
214 THOL0 = 0x00000000,
215 /* RxDesc.status */
216 IPON = 0x20000000,
217 TCPON = 0x10000000,
218 UDPON = 0x08000000,
219 Wakup = 0x00400000,
220 Magic = 0x00200000,
221 Pause = 0x00100000,
222 DEFbit = 0x00200000,
223 BCAST = 0x000c0000,
224 MCAST = 0x00080000,
225 UCAST = 0x00040000,
226 /* RxDesc.PSize */
227 TAGON = 0x80000000,
228 RxDescCountMask = 0x7f000000, // multi-desc pkt when > 1 ? -- FR
229 ABORT = 0x00800000,
230 SHORT = 0x00400000,
231 LIMIT = 0x00200000,
232 MIIER = 0x00100000,
233 OVRUN = 0x00080000,
234 NIBON = 0x00040000,
235 COLON = 0x00020000,
236 CRCOK = 0x00010000,
Francois Romieu890e8d02005-07-30 13:08:43 +0200237 RxSizeMask = 0x0000ffff
Francois Romieubcad5e52005-07-30 13:13:47 +0200238 /*
239 * The asic could apparently do vlan, TSO, jumbo (sis191 only) and
240 * provide two (unused with Linux) Tx queues. No publically
241 * available documentation alas.
242 */
Francois Romieu890e8d02005-07-30 13:08:43 +0200243};
244
Francois Romieu40292fb2005-07-30 13:12:06 +0200245enum sis190_eeprom_access_register_bits {
246 EECS = 0x00000001, // unused
247 EECLK = 0x00000002, // unused
248 EEDO = 0x00000008, // unused
249 EEDI = 0x00000004, // unused
250 EEREQ = 0x00000080,
251 EEROP = 0x00000200,
252 EEWOP = 0x00000100 // unused
253};
254
Francois Romieu830fb7d2005-07-30 13:12:37 +0200255/* EEPROM Addresses */
256enum sis190_eeprom_address {
257 EEPROMSignature = 0x00,
258 EEPROMCLK = 0x01, // unused
259 EEPROMInfo = 0x02,
260 EEPROMMACAddr = 0x03
261};
262
Francois Romieu900eb9d2005-09-03 00:55:27 +0200263enum sis190_feature {
264 F_HAS_RGMII = 1,
Francois Romieuc3d6f1f2005-09-03 00:56:57 +0200265 F_PHY_88E1111 = 2,
266 F_PHY_BCM5461 = 4
Francois Romieu900eb9d2005-09-03 00:55:27 +0200267};
268
Francois Romieu890e8d02005-07-30 13:08:43 +0200269struct sis190_private {
270 void __iomem *mmio_addr;
271 struct pci_dev *pci_dev;
David Howellsc4028952006-11-22 14:57:56 +0000272 struct net_device *dev;
Francois Romieu890e8d02005-07-30 13:08:43 +0200273 spinlock_t lock;
274 u32 rx_buf_sz;
275 u32 cur_rx;
276 u32 cur_tx;
277 u32 dirty_rx;
278 u32 dirty_tx;
279 dma_addr_t rx_dma;
280 dma_addr_t tx_dma;
281 struct RxDesc *RxDescRing;
282 struct TxDesc *TxDescRing;
283 struct sk_buff *Rx_skbuff[NUM_RX_DESC];
284 struct sk_buff *Tx_skbuff[NUM_TX_DESC];
285 struct work_struct phy_task;
286 struct timer_list timer;
287 u32 msg_enable;
Francois Romieu43afb942005-07-30 13:10:21 +0200288 struct mii_if_info mii_if;
Francois Romieufcb98212005-07-30 13:15:22 +0200289 struct list_head first_phy;
Francois Romieu900eb9d2005-09-03 00:55:27 +0200290 u32 features;
Francois Romieufcb98212005-07-30 13:15:22 +0200291};
292
293struct sis190_phy {
294 struct list_head list;
295 int phy_id;
296 u16 id[2];
297 u16 status;
298 u8 type;
299};
300
301enum sis190_phy_type {
302 UNKNOWN = 0x00,
303 HOME = 0x01,
304 LAN = 0x02,
305 MIX = 0x03
306};
307
308static struct mii_chip_info {
309 const char *name;
310 u16 id[2];
311 unsigned int type;
Francois Romieu900eb9d2005-09-03 00:55:27 +0200312 u32 feature;
Francois Romieufcb98212005-07-30 13:15:22 +0200313} mii_chip_table[] = {
Francois Romieuc3d6f1f2005-09-03 00:56:57 +0200314 { "Broadcom PHY BCM5461", { 0x0020, 0x60c0 }, LAN, F_PHY_BCM5461 },
Francois Romieubd7a4442007-03-29 00:18:50 +0200315 { "Broadcom PHY AC131", { 0x0143, 0xbc70 }, LAN, 0 },
Francois Romieu900eb9d2005-09-03 00:55:27 +0200316 { "Agere PHY ET1101B", { 0x0282, 0xf010 }, LAN, 0 },
317 { "Marvell PHY 88E1111", { 0x0141, 0x0cc0 }, LAN, F_PHY_88E1111 },
318 { "Realtek PHY RTL8201", { 0x0000, 0x8200 }, LAN, 0 },
Francois Romieufcb98212005-07-30 13:15:22 +0200319 { NULL, }
Francois Romieu890e8d02005-07-30 13:08:43 +0200320};
321
Jesper Juhl3c6bee12006-01-09 20:54:01 -0800322static const struct {
Francois Romieu890e8d02005-07-30 13:08:43 +0200323 const char *name;
Francois Romieu890e8d02005-07-30 13:08:43 +0200324} sis_chip_info[] = {
Francois Romieue7976372005-09-03 00:57:51 +0200325 { "SiS 190 PCI Fast Ethernet adapter" },
326 { "SiS 191 PCI Gigabit Ethernet adapter" },
Francois Romieu890e8d02005-07-30 13:08:43 +0200327};
328
Jeff Garzik8ee8e922008-01-30 04:00:40 -0500329static struct pci_device_id sis190_pci_tbl[] = {
Francois Romieu890e8d02005-07-30 13:08:43 +0200330 { PCI_DEVICE(PCI_VENDOR_ID_SI, 0x0190), 0, 0, 0 },
Francois Romieue7976372005-09-03 00:57:51 +0200331 { PCI_DEVICE(PCI_VENDOR_ID_SI, 0x0191), 0, 0, 1 },
Francois Romieu890e8d02005-07-30 13:08:43 +0200332 { 0, },
333};
334
335MODULE_DEVICE_TABLE(pci, sis190_pci_tbl);
336
337static int rx_copybreak = 200;
338
339static struct {
340 u32 msg_enable;
341} debug = { -1 };
342
343MODULE_DESCRIPTION("SiS sis190 Gigabit Ethernet driver");
344module_param(rx_copybreak, int, 0);
345MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames");
346module_param_named(debug, debug.msg_enable, int, 0);
347MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)");
348MODULE_AUTHOR("K.M. Liu <kmliu@sis.com>, Ueimor <romieu@fr.zoreil.com>");
349MODULE_VERSION(DRV_VERSION);
350MODULE_LICENSE("GPL");
351
352static const u32 sis190_intr_mask =
Francois Romieu21461382005-09-03 00:54:25 +0200353 RxQEmpty | RxQInt | TxQ1Int | TxQ0Int | RxHalt | TxHalt | LinkChange;
Francois Romieu890e8d02005-07-30 13:08:43 +0200354
355/*
356 * Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
357 * The chips use a 64 element hash table based on the Ethernet CRC.
358 */
Arjan van de Venf71e1302006-03-03 21:33:57 -0500359static const int multicast_filter_limit = 32;
Francois Romieu890e8d02005-07-30 13:08:43 +0200360
361static void __mdio_cmd(void __iomem *ioaddr, u32 ctl)
362{
363 unsigned int i;
364
365 SIS_W32(GMIIControl, ctl);
366
367 msleep(1);
368
369 for (i = 0; i < 100; i++) {
370 if (!(SIS_R32(GMIIControl) & EhnMIInotDone))
371 break;
372 msleep(1);
373 }
374
Francois Romieu7bf3f232007-11-17 16:56:43 +0100375 if (i > 99)
Francois Romieu890e8d02005-07-30 13:08:43 +0200376 printk(KERN_ERR PFX "PHY command failed !\n");
377}
378
Francois Romieu9ede1092005-07-30 13:14:38 +0200379static void mdio_write(void __iomem *ioaddr, int phy_id, int reg, int val)
Francois Romieu890e8d02005-07-30 13:08:43 +0200380{
Francois Romieu890e8d02005-07-30 13:08:43 +0200381 __mdio_cmd(ioaddr, EhnMIIreq | EhnMIIwrite |
Francois Romieu9ede1092005-07-30 13:14:38 +0200382 (((u32) reg) << EhnMIIregShift) | (phy_id << EhnMIIpmdShift) |
Francois Romieu890e8d02005-07-30 13:08:43 +0200383 (((u32) val) << EhnMIIdataShift));
384}
385
Francois Romieu9ede1092005-07-30 13:14:38 +0200386static int mdio_read(void __iomem *ioaddr, int phy_id, int reg)
Francois Romieu890e8d02005-07-30 13:08:43 +0200387{
Francois Romieu890e8d02005-07-30 13:08:43 +0200388 __mdio_cmd(ioaddr, EhnMIIreq | EhnMIIread |
Francois Romieu9ede1092005-07-30 13:14:38 +0200389 (((u32) reg) << EhnMIIregShift) | (phy_id << EhnMIIpmdShift));
Francois Romieu890e8d02005-07-30 13:08:43 +0200390
391 return (u16) (SIS_R32(GMIIControl) >> EhnMIIdataShift);
392}
393
Francois Romieu43afb942005-07-30 13:10:21 +0200394static void __mdio_write(struct net_device *dev, int phy_id, int reg, int val)
395{
396 struct sis190_private *tp = netdev_priv(dev);
397
Francois Romieu9ede1092005-07-30 13:14:38 +0200398 mdio_write(tp->mmio_addr, phy_id, reg, val);
Francois Romieu43afb942005-07-30 13:10:21 +0200399}
400
401static int __mdio_read(struct net_device *dev, int phy_id, int reg)
402{
403 struct sis190_private *tp = netdev_priv(dev);
404
Francois Romieu9ede1092005-07-30 13:14:38 +0200405 return mdio_read(tp->mmio_addr, phy_id, reg);
Francois Romieu43afb942005-07-30 13:10:21 +0200406}
407
Francois Romieufc10c392005-07-30 13:15:01 +0200408static u16 mdio_read_latched(void __iomem *ioaddr, int phy_id, int reg)
409{
410 mdio_read(ioaddr, phy_id, reg);
411 return mdio_read(ioaddr, phy_id, reg);
412}
413
Francois Romieu40292fb2005-07-30 13:12:06 +0200414static u16 __devinit sis190_read_eeprom(void __iomem *ioaddr, u32 reg)
Francois Romieu890e8d02005-07-30 13:08:43 +0200415{
Francois Romieu40292fb2005-07-30 13:12:06 +0200416 u16 data = 0xffff;
Francois Romieu890e8d02005-07-30 13:08:43 +0200417 unsigned int i;
Francois Romieu890e8d02005-07-30 13:08:43 +0200418
419 if (!(SIS_R32(ROMControl) & 0x0002))
420 return 0;
421
Francois Romieu40292fb2005-07-30 13:12:06 +0200422 SIS_W32(ROMInterface, EEREQ | EEROP | (reg << 10));
Francois Romieu890e8d02005-07-30 13:08:43 +0200423
424 for (i = 0; i < 200; i++) {
Francois Romieu40292fb2005-07-30 13:12:06 +0200425 if (!(SIS_R32(ROMInterface) & EEREQ)) {
426 data = (SIS_R32(ROMInterface) & 0xffff0000) >> 16;
Francois Romieu890e8d02005-07-30 13:08:43 +0200427 break;
Francois Romieu40292fb2005-07-30 13:12:06 +0200428 }
Francois Romieu890e8d02005-07-30 13:08:43 +0200429 msleep(1);
430 }
431
Francois Romieu890e8d02005-07-30 13:08:43 +0200432 return data;
433}
434
435static void sis190_irq_mask_and_ack(void __iomem *ioaddr)
436{
437 SIS_W32(IntrMask, 0x00);
438 SIS_W32(IntrStatus, 0xffffffff);
439 SIS_PCI_COMMIT();
440}
441
442static void sis190_asic_down(void __iomem *ioaddr)
443{
444 /* Stop the chip's Tx and Rx DMA processes. */
445
446 SIS_W32(TxControl, 0x1a00);
447 SIS_W32(RxControl, 0x1a00);
448
449 sis190_irq_mask_and_ack(ioaddr);
450}
451
452static void sis190_mark_as_last_descriptor(struct RxDesc *desc)
453{
454 desc->size |= cpu_to_le32(RingEnd);
455}
456
457static inline void sis190_give_to_asic(struct RxDesc *desc, u32 rx_buf_sz)
458{
459 u32 eor = le32_to_cpu(desc->size) & RingEnd;
460
461 desc->PSize = 0x0;
Francois Romieu8b5641d2005-07-30 13:13:03 +0200462 desc->size = cpu_to_le32((rx_buf_sz & RX_BUF_MASK) | eor);
Francois Romieu890e8d02005-07-30 13:08:43 +0200463 wmb();
464 desc->status = cpu_to_le32(OWNbit | INTbit);
465}
466
467static inline void sis190_map_to_asic(struct RxDesc *desc, dma_addr_t mapping,
468 u32 rx_buf_sz)
469{
470 desc->addr = cpu_to_le32(mapping);
471 sis190_give_to_asic(desc, rx_buf_sz);
472}
473
474static inline void sis190_make_unusable_by_asic(struct RxDesc *desc)
475{
476 desc->PSize = 0x0;
Al Viro961994a2007-12-15 01:44:33 +0000477 desc->addr = cpu_to_le32(0xdeadbeef);
Francois Romieu890e8d02005-07-30 13:08:43 +0200478 desc->size &= cpu_to_le32(RingEnd);
479 wmb();
480 desc->status = 0x0;
481}
482
Stephen Hemminger35aeb782008-04-27 14:54:32 +0200483static struct sk_buff *sis190_alloc_rx_skb(struct sis190_private *tp,
484 struct RxDesc *desc)
Francois Romieu890e8d02005-07-30 13:08:43 +0200485{
Stephen Hemminger35aeb782008-04-27 14:54:32 +0200486 u32 rx_buf_sz = tp->rx_buf_sz;
Francois Romieu890e8d02005-07-30 13:08:43 +0200487 struct sk_buff *skb;
Francois Romieu890e8d02005-07-30 13:08:43 +0200488
Stephen Hemminger35aeb782008-04-27 14:54:32 +0200489 skb = netdev_alloc_skb(tp->dev, rx_buf_sz);
Stephen Hemminger4709aa52008-04-27 14:36:59 +0200490 if (likely(skb)) {
491 dma_addr_t mapping;
Francois Romieu890e8d02005-07-30 13:08:43 +0200492
Stephen Hemminger35aeb782008-04-27 14:54:32 +0200493 mapping = pci_map_single(tp->pci_dev, skb->data, tp->rx_buf_sz,
Stephen Hemminger4709aa52008-04-27 14:36:59 +0200494 PCI_DMA_FROMDEVICE);
495 sis190_map_to_asic(desc, mapping, rx_buf_sz);
496 } else
497 sis190_make_unusable_by_asic(desc);
Francois Romieu890e8d02005-07-30 13:08:43 +0200498
Stephen Hemminger4709aa52008-04-27 14:36:59 +0200499 return skb;
Francois Romieu890e8d02005-07-30 13:08:43 +0200500}
501
502static u32 sis190_rx_fill(struct sis190_private *tp, struct net_device *dev,
503 u32 start, u32 end)
504{
505 u32 cur;
506
507 for (cur = start; cur < end; cur++) {
Stephen Hemminger4709aa52008-04-27 14:36:59 +0200508 unsigned int i = cur % NUM_RX_DESC;
Francois Romieu890e8d02005-07-30 13:08:43 +0200509
510 if (tp->Rx_skbuff[i])
511 continue;
512
Stephen Hemminger35aeb782008-04-27 14:54:32 +0200513 tp->Rx_skbuff[i] = sis190_alloc_rx_skb(tp, tp->RxDescRing + i);
514
Stephen Hemminger4709aa52008-04-27 14:36:59 +0200515 if (!tp->Rx_skbuff[i])
Francois Romieu890e8d02005-07-30 13:08:43 +0200516 break;
517 }
518 return cur - start;
519}
520
Francois Romieu47e47812008-04-27 17:59:52 +0200521static bool sis190_try_rx_copy(struct sis190_private *tp,
522 struct sk_buff **sk_buff, int pkt_size,
523 dma_addr_t addr)
Francois Romieu890e8d02005-07-30 13:08:43 +0200524{
Francois Romieu47e47812008-04-27 17:59:52 +0200525 struct sk_buff *skb;
526 bool done = false;
Francois Romieu890e8d02005-07-30 13:08:43 +0200527
Francois Romieu47e47812008-04-27 17:59:52 +0200528 if (pkt_size >= rx_copybreak)
529 goto out;
Francois Romieu890e8d02005-07-30 13:08:43 +0200530
Francois Romieu47e47812008-04-27 17:59:52 +0200531 skb = netdev_alloc_skb(tp->dev, pkt_size + 2);
532 if (!skb)
533 goto out;
534
535 pci_dma_sync_single_for_device(tp->pci_dev, addr, pkt_size,
536 PCI_DMA_FROMDEVICE);
537 skb_reserve(skb, 2);
538 skb_copy_to_linear_data(skb, sk_buff[0]->data, pkt_size);
539 *sk_buff = skb;
540 done = true;
541out:
542 return done;
Francois Romieu890e8d02005-07-30 13:08:43 +0200543}
544
Francois Romieubcad5e52005-07-30 13:13:47 +0200545static inline int sis190_rx_pkt_err(u32 status, struct net_device_stats *stats)
546{
547#define ErrMask (OVRUN | SHORT | LIMIT | MIIER | NIBON | COLON | ABORT)
548
549 if ((status & CRCOK) && !(status & ErrMask))
550 return 0;
551
552 if (!(status & CRCOK))
553 stats->rx_crc_errors++;
554 else if (status & OVRUN)
555 stats->rx_over_errors++;
556 else if (status & (SHORT | LIMIT))
557 stats->rx_length_errors++;
558 else if (status & (MIIER | NIBON | COLON))
559 stats->rx_frame_errors++;
560
561 stats->rx_errors++;
562 return -1;
563}
564
Francois Romieu890e8d02005-07-30 13:08:43 +0200565static int sis190_rx_interrupt(struct net_device *dev,
566 struct sis190_private *tp, void __iomem *ioaddr)
567{
Jeff Garzik09f75cd2007-10-03 17:41:50 -0700568 struct net_device_stats *stats = &dev->stats;
Francois Romieu890e8d02005-07-30 13:08:43 +0200569 u32 rx_left, cur_rx = tp->cur_rx;
570 u32 delta, count;
571
572 rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx;
573 rx_left = sis190_rx_quota(rx_left, (u32) dev->quota);
574
575 for (; rx_left > 0; rx_left--, cur_rx++) {
576 unsigned int entry = cur_rx % NUM_RX_DESC;
577 struct RxDesc *desc = tp->RxDescRing + entry;
578 u32 status;
579
Al Viro961994a2007-12-15 01:44:33 +0000580 if (le32_to_cpu(desc->status) & OWNbit)
Francois Romieu890e8d02005-07-30 13:08:43 +0200581 break;
582
583 status = le32_to_cpu(desc->PSize);
584
585 // net_intr(tp, KERN_INFO "%s: Rx PSize = %08x.\n", dev->name,
586 // status);
587
Francois Romieubcad5e52005-07-30 13:13:47 +0200588 if (sis190_rx_pkt_err(status, stats) < 0)
Francois Romieu890e8d02005-07-30 13:08:43 +0200589 sis190_give_to_asic(desc, tp->rx_buf_sz);
Francois Romieubcad5e52005-07-30 13:13:47 +0200590 else {
Francois Romieu890e8d02005-07-30 13:08:43 +0200591 struct sk_buff *skb = tp->Rx_skbuff[entry];
Francois Romieu47e47812008-04-27 17:59:52 +0200592 dma_addr_t addr = le32_to_cpu(desc->addr);
Francois Romieu890e8d02005-07-30 13:08:43 +0200593 int pkt_size = (status & RxSizeMask) - 4;
Francois Romieu47e47812008-04-27 17:59:52 +0200594 struct pci_dev *pdev = tp->pci_dev;
Francois Romieu890e8d02005-07-30 13:08:43 +0200595
596 if (unlikely(pkt_size > tp->rx_buf_sz)) {
597 net_intr(tp, KERN_INFO
598 "%s: (frag) status = %08x.\n",
599 dev->name, status);
600 stats->rx_dropped++;
601 stats->rx_length_errors++;
602 sis190_give_to_asic(desc, tp->rx_buf_sz);
603 continue;
604 }
605
Francois Romieu890e8d02005-07-30 13:08:43 +0200606
Francois Romieu47e47812008-04-27 17:59:52 +0200607 if (sis190_try_rx_copy(tp, &skb, pkt_size, addr)) {
608 pci_dma_sync_single_for_device(pdev, addr,
609 tp->rx_buf_sz, PCI_DMA_FROMDEVICE);
610 sis190_give_to_asic(desc, tp->rx_buf_sz);
611 } else {
612 pci_unmap_single(pdev, addr, tp->rx_buf_sz,
613 PCI_DMA_FROMDEVICE);
Francois Romieu890e8d02005-07-30 13:08:43 +0200614 tp->Rx_skbuff[entry] = NULL;
615 sis190_make_unusable_by_asic(desc);
616 }
617
Francois Romieu890e8d02005-07-30 13:08:43 +0200618 skb_put(skb, pkt_size);
619 skb->protocol = eth_type_trans(skb, dev);
620
621 sis190_rx_skb(skb);
622
623 dev->last_rx = jiffies;
Francois Romieu890e8d02005-07-30 13:08:43 +0200624 stats->rx_packets++;
Francois Romieubcad5e52005-07-30 13:13:47 +0200625 stats->rx_bytes += pkt_size;
626 if ((status & BCAST) == MCAST)
627 stats->multicast++;
Francois Romieu890e8d02005-07-30 13:08:43 +0200628 }
629 }
630 count = cur_rx - tp->cur_rx;
631 tp->cur_rx = cur_rx;
632
633 delta = sis190_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx);
634 if (!delta && count && netif_msg_intr(tp))
635 printk(KERN_INFO "%s: no Rx buffer allocated.\n", dev->name);
636 tp->dirty_rx += delta;
637
638 if (((tp->dirty_rx + NUM_RX_DESC) == tp->cur_rx) && netif_msg_intr(tp))
639 printk(KERN_EMERG "%s: Rx buffers exhausted.\n", dev->name);
640
641 return count;
642}
643
644static void sis190_unmap_tx_skb(struct pci_dev *pdev, struct sk_buff *skb,
645 struct TxDesc *desc)
646{
647 unsigned int len;
648
649 len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
650
651 pci_unmap_single(pdev, le32_to_cpu(desc->addr), len, PCI_DMA_TODEVICE);
652
653 memset(desc, 0x00, sizeof(*desc));
654}
655
656static void sis190_tx_interrupt(struct net_device *dev,
657 struct sis190_private *tp, void __iomem *ioaddr)
658{
659 u32 pending, dirty_tx = tp->dirty_tx;
660 /*
661 * It would not be needed if queueing was allowed to be enabled
662 * again too early (hint: think preempt and unclocked smp systems).
663 */
664 unsigned int queue_stopped;
665
666 smp_rmb();
667 pending = tp->cur_tx - dirty_tx;
668 queue_stopped = (pending == NUM_TX_DESC);
669
670 for (; pending; pending--, dirty_tx++) {
671 unsigned int entry = dirty_tx % NUM_TX_DESC;
672 struct TxDesc *txd = tp->TxDescRing + entry;
673 struct sk_buff *skb;
674
675 if (le32_to_cpu(txd->status) & OWNbit)
676 break;
677
678 skb = tp->Tx_skbuff[entry];
679
Jeff Garzik09f75cd2007-10-03 17:41:50 -0700680 dev->stats.tx_packets++;
681 dev->stats.tx_bytes += skb->len;
Francois Romieu890e8d02005-07-30 13:08:43 +0200682
683 sis190_unmap_tx_skb(tp->pci_dev, skb, txd);
684 tp->Tx_skbuff[entry] = NULL;
685 dev_kfree_skb_irq(skb);
686 }
687
688 if (tp->dirty_tx != dirty_tx) {
689 tp->dirty_tx = dirty_tx;
690 smp_wmb();
691 if (queue_stopped)
692 netif_wake_queue(dev);
693 }
694}
695
696/*
697 * The interrupt handler does all of the Rx thread work and cleans up after
698 * the Tx thread.
699 */
David Howells7d12e782006-10-05 14:55:46 +0100700static irqreturn_t sis190_interrupt(int irq, void *__dev)
Francois Romieu890e8d02005-07-30 13:08:43 +0200701{
702 struct net_device *dev = __dev;
703 struct sis190_private *tp = netdev_priv(dev);
704 void __iomem *ioaddr = tp->mmio_addr;
705 unsigned int handled = 0;
706 u32 status;
707
708 status = SIS_R32(IntrStatus);
709
710 if ((status == 0xffffffff) || !status)
711 goto out;
712
713 handled = 1;
714
715 if (unlikely(!netif_running(dev))) {
716 sis190_asic_down(ioaddr);
717 goto out;
718 }
719
720 SIS_W32(IntrStatus, status);
721
722 // net_intr(tp, KERN_INFO "%s: status = %08x.\n", dev->name, status);
723
724 if (status & LinkChange) {
725 net_intr(tp, KERN_INFO "%s: link change.\n", dev->name);
726 schedule_work(&tp->phy_task);
727 }
728
729 if (status & RxQInt)
730 sis190_rx_interrupt(dev, tp, ioaddr);
731
732 if (status & TxQ0Int)
733 sis190_tx_interrupt(dev, tp, ioaddr);
734out:
735 return IRQ_RETVAL(handled);
736}
737
Francois Romieu4405d3b2005-07-30 13:09:20 +0200738#ifdef CONFIG_NET_POLL_CONTROLLER
739static void sis190_netpoll(struct net_device *dev)
740{
741 struct sis190_private *tp = netdev_priv(dev);
742 struct pci_dev *pdev = tp->pci_dev;
743
744 disable_irq(pdev->irq);
David Howells7d12e782006-10-05 14:55:46 +0100745 sis190_interrupt(pdev->irq, dev);
Francois Romieu4405d3b2005-07-30 13:09:20 +0200746 enable_irq(pdev->irq);
747}
748#endif
749
Francois Romieu890e8d02005-07-30 13:08:43 +0200750static void sis190_free_rx_skb(struct sis190_private *tp,
751 struct sk_buff **sk_buff, struct RxDesc *desc)
752{
753 struct pci_dev *pdev = tp->pci_dev;
754
755 pci_unmap_single(pdev, le32_to_cpu(desc->addr), tp->rx_buf_sz,
756 PCI_DMA_FROMDEVICE);
757 dev_kfree_skb(*sk_buff);
758 *sk_buff = NULL;
759 sis190_make_unusable_by_asic(desc);
760}
761
762static void sis190_rx_clear(struct sis190_private *tp)
763{
764 unsigned int i;
765
766 for (i = 0; i < NUM_RX_DESC; i++) {
767 if (!tp->Rx_skbuff[i])
768 continue;
769 sis190_free_rx_skb(tp, tp->Rx_skbuff + i, tp->RxDescRing + i);
770 }
771}
772
773static void sis190_init_ring_indexes(struct sis190_private *tp)
774{
775 tp->dirty_tx = tp->dirty_rx = tp->cur_tx = tp->cur_rx = 0;
776}
777
778static int sis190_init_ring(struct net_device *dev)
779{
780 struct sis190_private *tp = netdev_priv(dev);
781
782 sis190_init_ring_indexes(tp);
783
784 memset(tp->Tx_skbuff, 0x0, NUM_TX_DESC * sizeof(struct sk_buff *));
785 memset(tp->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *));
786
787 if (sis190_rx_fill(tp, dev, 0, NUM_RX_DESC) != NUM_RX_DESC)
788 goto err_rx_clear;
789
790 sis190_mark_as_last_descriptor(tp->RxDescRing + NUM_RX_DESC - 1);
791
792 return 0;
793
794err_rx_clear:
795 sis190_rx_clear(tp);
796 return -ENOMEM;
797}
798
799static void sis190_set_rx_mode(struct net_device *dev)
800{
801 struct sis190_private *tp = netdev_priv(dev);
802 void __iomem *ioaddr = tp->mmio_addr;
803 unsigned long flags;
804 u32 mc_filter[2]; /* Multicast hash filter */
805 u16 rx_mode;
806
807 if (dev->flags & IFF_PROMISC) {
Francois Romieu890e8d02005-07-30 13:08:43 +0200808 rx_mode =
809 AcceptBroadcast | AcceptMulticast | AcceptMyPhys |
810 AcceptAllPhys;
811 mc_filter[1] = mc_filter[0] = 0xffffffff;
812 } else if ((dev->mc_count > multicast_filter_limit) ||
813 (dev->flags & IFF_ALLMULTI)) {
814 /* Too many to filter perfectly -- accept all multicasts. */
815 rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
816 mc_filter[1] = mc_filter[0] = 0xffffffff;
817 } else {
818 struct dev_mc_list *mclist;
819 unsigned int i;
820
821 rx_mode = AcceptBroadcast | AcceptMyPhys;
822 mc_filter[1] = mc_filter[0] = 0;
823 for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
824 i++, mclist = mclist->next) {
825 int bit_nr =
Aurelien Jarno8fee5f52005-10-05 23:29:58 +0200826 ether_crc(ETH_ALEN, mclist->dmi_addr) & 0x3f;
Francois Romieu890e8d02005-07-30 13:08:43 +0200827 mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
828 rx_mode |= AcceptMulticast;
829 }
830 }
831
832 spin_lock_irqsave(&tp->lock, flags);
833
834 SIS_W16(RxMacControl, rx_mode | 0x2);
835 SIS_W32(RxHashTable, mc_filter[0]);
836 SIS_W32(RxHashTable + 4, mc_filter[1]);
837
838 spin_unlock_irqrestore(&tp->lock, flags);
839}
840
841static void sis190_soft_reset(void __iomem *ioaddr)
842{
843 SIS_W32(IntrControl, 0x8000);
844 SIS_PCI_COMMIT();
Francois Romieu890e8d02005-07-30 13:08:43 +0200845 SIS_W32(IntrControl, 0x0);
846 sis190_asic_down(ioaddr);
Francois Romieu890e8d02005-07-30 13:08:43 +0200847}
848
849static void sis190_hw_start(struct net_device *dev)
850{
851 struct sis190_private *tp = netdev_priv(dev);
852 void __iomem *ioaddr = tp->mmio_addr;
853
854 sis190_soft_reset(ioaddr);
855
856 SIS_W32(TxDescStartAddr, tp->tx_dma);
857 SIS_W32(RxDescStartAddr, tp->rx_dma);
858
859 SIS_W32(IntrStatus, 0xffffffff);
860 SIS_W32(IntrMask, 0x0);
Francois Romieu890e8d02005-07-30 13:08:43 +0200861 SIS_W32(GMIIControl, 0x0);
862 SIS_W32(TxMacControl, 0x60);
863 SIS_W16(RxMacControl, 0x02);
864 SIS_W32(RxHashTable, 0x0);
865 SIS_W32(0x6c, 0x0);
Francois Romieu188f23b2005-07-30 13:11:43 +0200866 SIS_W32(RxWolCtrl, 0x0);
867 SIS_W32(RxWolData, 0x0);
Francois Romieu890e8d02005-07-30 13:08:43 +0200868
869 SIS_PCI_COMMIT();
870
871 sis190_set_rx_mode(dev);
872
873 /* Enable all known interrupts by setting the interrupt mask. */
874 SIS_W32(IntrMask, sis190_intr_mask);
875
876 SIS_W32(TxControl, 0x1a00 | CmdTxEnb);
877 SIS_W32(RxControl, 0x1a1d);
878
879 netif_start_queue(dev);
880}
881
David Howellsc4028952006-11-22 14:57:56 +0000882static void sis190_phy_task(struct work_struct *work)
Francois Romieu890e8d02005-07-30 13:08:43 +0200883{
David Howellsc4028952006-11-22 14:57:56 +0000884 struct sis190_private *tp =
885 container_of(work, struct sis190_private, phy_task);
886 struct net_device *dev = tp->dev;
Francois Romieu890e8d02005-07-30 13:08:43 +0200887 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu9ede1092005-07-30 13:14:38 +0200888 int phy_id = tp->mii_if.phy_id;
Francois Romieu890e8d02005-07-30 13:08:43 +0200889 u16 val;
890
Francois Romieu43afb942005-07-30 13:10:21 +0200891 rtnl_lock();
892
Francois Romieuc014f6c2007-02-15 23:37:29 +0100893 if (!netif_running(dev))
894 goto out_unlock;
895
Francois Romieu9ede1092005-07-30 13:14:38 +0200896 val = mdio_read(ioaddr, phy_id, MII_BMCR);
Francois Romieu890e8d02005-07-30 13:08:43 +0200897 if (val & BMCR_RESET) {
898 // FIXME: needlessly high ? -- FR 02/07/2005
899 mod_timer(&tp->timer, jiffies + HZ/10);
Francois Romieufc10c392005-07-30 13:15:01 +0200900 } else if (!(mdio_read_latched(ioaddr, phy_id, MII_BMSR) &
901 BMSR_ANEGCOMPLETE)) {
Francois Romieu21461382005-09-03 00:54:25 +0200902 netif_carrier_off(dev);
Francois Romieuc34ebba2007-11-18 22:04:05 +0100903 net_link(tp, KERN_WARNING "%s: auto-negotiating...\n",
904 dev->name);
Francois Romieu890e8d02005-07-30 13:08:43 +0200905 mod_timer(&tp->timer, jiffies + SIS190_PHY_TIMEOUT);
906 } else {
907 /* Rejoice ! */
908 struct {
909 int val;
Francois Romieu6614a6d2005-09-03 00:56:16 +0200910 u32 ctl;
Francois Romieu890e8d02005-07-30 13:08:43 +0200911 const char *msg;
Francois Romieu890e8d02005-07-30 13:08:43 +0200912 } reg31[] = {
Francois Romieu6614a6d2005-09-03 00:56:16 +0200913 { LPA_1000XFULL | LPA_SLCT, 0x07000c00 | 0x00001000,
914 "1000 Mbps Full Duplex" },
915 { LPA_1000XHALF | LPA_SLCT, 0x07000c00,
916 "1000 Mbps Half Duplex" },
917 { LPA_100FULL, 0x04000800 | 0x00001000,
918 "100 Mbps Full Duplex" },
919 { LPA_100HALF, 0x04000800,
920 "100 Mbps Half Duplex" },
921 { LPA_10FULL, 0x04000400 | 0x00001000,
922 "10 Mbps Full Duplex" },
923 { LPA_10HALF, 0x04000400,
924 "10 Mbps Half Duplex" },
925 { 0, 0x04000400, "unknown" }
926 }, *p;
Francois Romieu8348b4d2005-07-30 13:16:14 +0200927 u16 adv;
Francois Romieu890e8d02005-07-30 13:08:43 +0200928
Francois Romieu9ede1092005-07-30 13:14:38 +0200929 val = mdio_read(ioaddr, phy_id, 0x1f);
Francois Romieu890e8d02005-07-30 13:08:43 +0200930 net_link(tp, KERN_INFO "%s: mii ext = %04x.\n", dev->name, val);
931
Francois Romieu9ede1092005-07-30 13:14:38 +0200932 val = mdio_read(ioaddr, phy_id, MII_LPA);
Francois Romieu8348b4d2005-07-30 13:16:14 +0200933 adv = mdio_read(ioaddr, phy_id, MII_ADVERTISE);
934 net_link(tp, KERN_INFO "%s: mii lpa = %04x adv = %04x.\n",
935 dev->name, val, adv);
936
937 val &= adv;
Francois Romieu890e8d02005-07-30 13:08:43 +0200938
Francois Romieu6614a6d2005-09-03 00:56:16 +0200939 for (p = reg31; p->val; p++) {
Francois Romieu890e8d02005-07-30 13:08:43 +0200940 if ((val & p->val) == p->val)
941 break;
942 }
Francois Romieu6614a6d2005-09-03 00:56:16 +0200943
944 p->ctl |= SIS_R32(StationControl) & ~0x0f001c00;
945
Francois Romieuc3d6f1f2005-09-03 00:56:57 +0200946 if ((tp->features & F_HAS_RGMII) &&
947 (tp->features & F_PHY_BCM5461)) {
948 // Set Tx Delay in RGMII mode.
949 mdio_write(ioaddr, phy_id, 0x18, 0xf1c7);
950 udelay(200);
951 mdio_write(ioaddr, phy_id, 0x1c, 0x8c00);
952 p->ctl |= 0x03000000;
953 }
954
Francois Romieu6614a6d2005-09-03 00:56:16 +0200955 SIS_W32(StationControl, p->ctl);
956
Francois Romieuc3d6f1f2005-09-03 00:56:57 +0200957 if (tp->features & F_HAS_RGMII) {
958 SIS_W32(RGDelay, 0x0441);
959 SIS_W32(RGDelay, 0x0440);
960 }
961
Francois Romieu890e8d02005-07-30 13:08:43 +0200962 net_link(tp, KERN_INFO "%s: link on %s mode.\n", dev->name,
963 p->msg);
964 netif_carrier_on(dev);
965 }
Francois Romieu43afb942005-07-30 13:10:21 +0200966
Francois Romieuc014f6c2007-02-15 23:37:29 +0100967out_unlock:
Francois Romieu43afb942005-07-30 13:10:21 +0200968 rtnl_unlock();
Francois Romieu890e8d02005-07-30 13:08:43 +0200969}
970
971static void sis190_phy_timer(unsigned long __opaque)
972{
973 struct net_device *dev = (struct net_device *)__opaque;
974 struct sis190_private *tp = netdev_priv(dev);
975
976 if (likely(netif_running(dev)))
977 schedule_work(&tp->phy_task);
978}
979
980static inline void sis190_delete_timer(struct net_device *dev)
981{
982 struct sis190_private *tp = netdev_priv(dev);
983
984 del_timer_sync(&tp->timer);
985}
986
987static inline void sis190_request_timer(struct net_device *dev)
988{
989 struct sis190_private *tp = netdev_priv(dev);
990 struct timer_list *timer = &tp->timer;
991
992 init_timer(timer);
993 timer->expires = jiffies + SIS190_PHY_TIMEOUT;
994 timer->data = (unsigned long)dev;
995 timer->function = sis190_phy_timer;
996 add_timer(timer);
997}
998
999static void sis190_set_rxbufsize(struct sis190_private *tp,
1000 struct net_device *dev)
1001{
1002 unsigned int mtu = dev->mtu;
1003
1004 tp->rx_buf_sz = (mtu > RX_BUF_SIZE) ? mtu + ETH_HLEN + 8 : RX_BUF_SIZE;
Francois Romieu8b5641d2005-07-30 13:13:03 +02001005 /* RxDesc->size has a licence to kill the lower bits */
1006 if (tp->rx_buf_sz & 0x07) {
1007 tp->rx_buf_sz += 8;
1008 tp->rx_buf_sz &= RX_BUF_MASK;
1009 }
Francois Romieu890e8d02005-07-30 13:08:43 +02001010}
1011
1012static int sis190_open(struct net_device *dev)
1013{
1014 struct sis190_private *tp = netdev_priv(dev);
1015 struct pci_dev *pdev = tp->pci_dev;
1016 int rc = -ENOMEM;
1017
1018 sis190_set_rxbufsize(tp, dev);
1019
1020 /*
1021 * Rx and Tx descriptors need 256 bytes alignment.
1022 * pci_alloc_consistent() guarantees a stronger alignment.
1023 */
1024 tp->TxDescRing = pci_alloc_consistent(pdev, TX_RING_BYTES, &tp->tx_dma);
1025 if (!tp->TxDescRing)
1026 goto out;
1027
1028 tp->RxDescRing = pci_alloc_consistent(pdev, RX_RING_BYTES, &tp->rx_dma);
1029 if (!tp->RxDescRing)
1030 goto err_free_tx_0;
1031
1032 rc = sis190_init_ring(dev);
1033 if (rc < 0)
1034 goto err_free_rx_1;
1035
Francois Romieu890e8d02005-07-30 13:08:43 +02001036 sis190_request_timer(dev);
1037
Thomas Gleixner1fb9df52006-07-01 19:29:39 -07001038 rc = request_irq(dev->irq, sis190_interrupt, IRQF_SHARED, dev->name, dev);
Francois Romieu890e8d02005-07-30 13:08:43 +02001039 if (rc < 0)
1040 goto err_release_timer_2;
1041
1042 sis190_hw_start(dev);
1043out:
1044 return rc;
1045
1046err_release_timer_2:
1047 sis190_delete_timer(dev);
1048 sis190_rx_clear(tp);
1049err_free_rx_1:
1050 pci_free_consistent(tp->pci_dev, RX_RING_BYTES, tp->RxDescRing,
1051 tp->rx_dma);
1052err_free_tx_0:
1053 pci_free_consistent(tp->pci_dev, TX_RING_BYTES, tp->TxDescRing,
1054 tp->tx_dma);
1055 goto out;
1056}
1057
1058static void sis190_tx_clear(struct sis190_private *tp)
1059{
1060 unsigned int i;
1061
1062 for (i = 0; i < NUM_TX_DESC; i++) {
1063 struct sk_buff *skb = tp->Tx_skbuff[i];
1064
1065 if (!skb)
1066 continue;
1067
1068 sis190_unmap_tx_skb(tp->pci_dev, skb, tp->TxDescRing + i);
1069 tp->Tx_skbuff[i] = NULL;
1070 dev_kfree_skb(skb);
1071
Jeff Garzik09f75cd2007-10-03 17:41:50 -07001072 tp->dev->stats.tx_dropped++;
Francois Romieu890e8d02005-07-30 13:08:43 +02001073 }
1074 tp->cur_tx = tp->dirty_tx = 0;
1075}
1076
1077static void sis190_down(struct net_device *dev)
1078{
1079 struct sis190_private *tp = netdev_priv(dev);
1080 void __iomem *ioaddr = tp->mmio_addr;
1081 unsigned int poll_locked = 0;
1082
1083 sis190_delete_timer(dev);
1084
1085 netif_stop_queue(dev);
1086
Francois Romieu890e8d02005-07-30 13:08:43 +02001087 do {
1088 spin_lock_irq(&tp->lock);
1089
1090 sis190_asic_down(ioaddr);
1091
1092 spin_unlock_irq(&tp->lock);
1093
1094 synchronize_irq(dev->irq);
1095
Stephen Hemmingerbea33482007-10-03 16:41:36 -07001096 if (!poll_locked)
Francois Romieu890e8d02005-07-30 13:08:43 +02001097 poll_locked++;
Francois Romieu890e8d02005-07-30 13:08:43 +02001098
1099 synchronize_sched();
1100
1101 } while (SIS_R32(IntrMask));
1102
1103 sis190_tx_clear(tp);
1104 sis190_rx_clear(tp);
1105}
1106
1107static int sis190_close(struct net_device *dev)
1108{
1109 struct sis190_private *tp = netdev_priv(dev);
1110 struct pci_dev *pdev = tp->pci_dev;
1111
1112 sis190_down(dev);
1113
1114 free_irq(dev->irq, dev);
1115
Francois Romieu890e8d02005-07-30 13:08:43 +02001116 pci_free_consistent(pdev, TX_RING_BYTES, tp->TxDescRing, tp->tx_dma);
1117 pci_free_consistent(pdev, RX_RING_BYTES, tp->RxDescRing, tp->rx_dma);
1118
1119 tp->TxDescRing = NULL;
1120 tp->RxDescRing = NULL;
1121
1122 return 0;
1123}
1124
1125static int sis190_start_xmit(struct sk_buff *skb, struct net_device *dev)
1126{
1127 struct sis190_private *tp = netdev_priv(dev);
1128 void __iomem *ioaddr = tp->mmio_addr;
1129 u32 len, entry, dirty_tx;
1130 struct TxDesc *desc;
1131 dma_addr_t mapping;
1132
1133 if (unlikely(skb->len < ETH_ZLEN)) {
Herbert Xu5b057c62006-06-23 02:06:41 -07001134 if (skb_padto(skb, ETH_ZLEN)) {
Jeff Garzik09f75cd2007-10-03 17:41:50 -07001135 dev->stats.tx_dropped++;
Francois Romieu890e8d02005-07-30 13:08:43 +02001136 goto out;
1137 }
1138 len = ETH_ZLEN;
1139 } else {
1140 len = skb->len;
1141 }
1142
1143 entry = tp->cur_tx % NUM_TX_DESC;
1144 desc = tp->TxDescRing + entry;
1145
1146 if (unlikely(le32_to_cpu(desc->status) & OWNbit)) {
1147 netif_stop_queue(dev);
1148 net_tx_err(tp, KERN_ERR PFX
1149 "%s: BUG! Tx Ring full when queue awake!\n",
1150 dev->name);
1151 return NETDEV_TX_BUSY;
1152 }
1153
1154 mapping = pci_map_single(tp->pci_dev, skb->data, len, PCI_DMA_TODEVICE);
1155
1156 tp->Tx_skbuff[entry] = skb;
1157
1158 desc->PSize = cpu_to_le32(len);
1159 desc->addr = cpu_to_le32(mapping);
1160
1161 desc->size = cpu_to_le32(len);
1162 if (entry == (NUM_TX_DESC - 1))
1163 desc->size |= cpu_to_le32(RingEnd);
1164
1165 wmb();
1166
1167 desc->status = cpu_to_le32(OWNbit | INTbit | DEFbit | CRCbit | PADbit);
1168
1169 tp->cur_tx++;
1170
1171 smp_wmb();
1172
1173 SIS_W32(TxControl, 0x1a00 | CmdReset | CmdTxEnb);
1174
1175 dev->trans_start = jiffies;
1176
1177 dirty_tx = tp->dirty_tx;
1178 if ((tp->cur_tx - NUM_TX_DESC) == dirty_tx) {
1179 netif_stop_queue(dev);
1180 smp_rmb();
1181 if (dirty_tx != tp->dirty_tx)
1182 netif_wake_queue(dev);
1183 }
1184out:
1185 return NETDEV_TX_OK;
1186}
1187
Francois Romieufcb98212005-07-30 13:15:22 +02001188static void sis190_free_phy(struct list_head *first_phy)
1189{
1190 struct sis190_phy *cur, *next;
1191
1192 list_for_each_entry_safe(cur, next, first_phy, list) {
1193 kfree(cur);
1194 }
1195}
1196
1197/**
1198 * sis190_default_phy - Select default PHY for sis190 mac.
1199 * @dev: the net device to probe for
1200 *
1201 * Select first detected PHY with link as default.
1202 * If no one is link on, select PHY whose types is HOME as default.
1203 * If HOME doesn't exist, select LAN.
1204 */
1205static u16 sis190_default_phy(struct net_device *dev)
1206{
1207 struct sis190_phy *phy, *phy_home, *phy_default, *phy_lan;
1208 struct sis190_private *tp = netdev_priv(dev);
1209 struct mii_if_info *mii_if = &tp->mii_if;
1210 void __iomem *ioaddr = tp->mmio_addr;
1211 u16 status;
1212
1213 phy_home = phy_default = phy_lan = NULL;
1214
1215 list_for_each_entry(phy, &tp->first_phy, list) {
1216 status = mdio_read_latched(ioaddr, phy->phy_id, MII_BMSR);
1217
1218 // Link ON & Not select default PHY & not ghost PHY.
1219 if ((status & BMSR_LSTATUS) &&
1220 !phy_default &&
1221 (phy->type != UNKNOWN)) {
1222 phy_default = phy;
1223 } else {
1224 status = mdio_read(ioaddr, phy->phy_id, MII_BMCR);
1225 mdio_write(ioaddr, phy->phy_id, MII_BMCR,
1226 status | BMCR_ANENABLE | BMCR_ISOLATE);
1227 if (phy->type == HOME)
1228 phy_home = phy;
1229 else if (phy->type == LAN)
1230 phy_lan = phy;
1231 }
1232 }
1233
1234 if (!phy_default) {
1235 if (phy_home)
1236 phy_default = phy_home;
1237 else if (phy_lan)
1238 phy_default = phy_lan;
1239 else
1240 phy_default = list_entry(&tp->first_phy,
1241 struct sis190_phy, list);
1242 }
1243
1244 if (mii_if->phy_id != phy_default->phy_id) {
1245 mii_if->phy_id = phy_default->phy_id;
1246 net_probe(tp, KERN_INFO
1247 "%s: Using transceiver at address %d as default.\n",
Francois Romieu3690b6c2005-08-26 00:30:37 +02001248 pci_name(tp->pci_dev), mii_if->phy_id);
Francois Romieufcb98212005-07-30 13:15:22 +02001249 }
1250
1251 status = mdio_read(ioaddr, mii_if->phy_id, MII_BMCR);
1252 status &= (~BMCR_ISOLATE);
1253
1254 mdio_write(ioaddr, mii_if->phy_id, MII_BMCR, status);
1255 status = mdio_read_latched(ioaddr, mii_if->phy_id, MII_BMSR);
1256
1257 return status;
1258}
1259
1260static void sis190_init_phy(struct net_device *dev, struct sis190_private *tp,
1261 struct sis190_phy *phy, unsigned int phy_id,
1262 u16 mii_status)
1263{
1264 void __iomem *ioaddr = tp->mmio_addr;
1265 struct mii_chip_info *p;
1266
1267 INIT_LIST_HEAD(&phy->list);
1268 phy->status = mii_status;
1269 phy->phy_id = phy_id;
1270
1271 phy->id[0] = mdio_read(ioaddr, phy_id, MII_PHYSID1);
1272 phy->id[1] = mdio_read(ioaddr, phy_id, MII_PHYSID2);
1273
1274 for (p = mii_chip_table; p->type; p++) {
1275 if ((p->id[0] == phy->id[0]) &&
1276 (p->id[1] == (phy->id[1] & 0xfff0))) {
1277 break;
1278 }
1279 }
1280
1281 if (p->id[1]) {
1282 phy->type = (p->type == MIX) ?
1283 ((mii_status & (BMSR_100FULL | BMSR_100HALF)) ?
1284 LAN : HOME) : p->type;
Francois Romieu900eb9d2005-09-03 00:55:27 +02001285 tp->features |= p->feature;
Francois Romieufcb98212005-07-30 13:15:22 +02001286 } else
1287 phy->type = UNKNOWN;
1288
1289 net_probe(tp, KERN_INFO "%s: %s transceiver at address %d.\n",
Francois Romieu3690b6c2005-08-26 00:30:37 +02001290 pci_name(tp->pci_dev),
1291 (phy->type == UNKNOWN) ? "Unknown PHY" : p->name, phy_id);
Francois Romieufcb98212005-07-30 13:15:22 +02001292}
1293
Francois Romieu900eb9d2005-09-03 00:55:27 +02001294static void sis190_mii_probe_88e1111_fixup(struct sis190_private *tp)
1295{
1296 if (tp->features & F_PHY_88E1111) {
1297 void __iomem *ioaddr = tp->mmio_addr;
1298 int phy_id = tp->mii_if.phy_id;
1299 u16 reg[2][2] = {
1300 { 0x808b, 0x0ce1 },
1301 { 0x808f, 0x0c60 }
1302 }, *p;
1303
1304 p = (tp->features & F_HAS_RGMII) ? reg[0] : reg[1];
1305
1306 mdio_write(ioaddr, phy_id, 0x1b, p[0]);
1307 udelay(200);
1308 mdio_write(ioaddr, phy_id, 0x14, p[1]);
1309 udelay(200);
1310 }
1311}
1312
Francois Romieufcb98212005-07-30 13:15:22 +02001313/**
1314 * sis190_mii_probe - Probe MII PHY for sis190
1315 * @dev: the net device to probe for
1316 *
1317 * Search for total of 32 possible mii phy addresses.
1318 * Identify and set current phy if found one,
1319 * return error if it failed to found.
1320 */
1321static int __devinit sis190_mii_probe(struct net_device *dev)
1322{
1323 struct sis190_private *tp = netdev_priv(dev);
1324 struct mii_if_info *mii_if = &tp->mii_if;
1325 void __iomem *ioaddr = tp->mmio_addr;
1326 int phy_id;
1327 int rc = 0;
1328
1329 INIT_LIST_HEAD(&tp->first_phy);
1330
1331 for (phy_id = 0; phy_id < PHY_MAX_ADDR; phy_id++) {
1332 struct sis190_phy *phy;
1333 u16 status;
1334
1335 status = mdio_read_latched(ioaddr, phy_id, MII_BMSR);
1336
1337 // Try next mii if the current one is not accessible.
1338 if (status == 0xffff || status == 0x0000)
1339 continue;
1340
1341 phy = kmalloc(sizeof(*phy), GFP_KERNEL);
1342 if (!phy) {
1343 sis190_free_phy(&tp->first_phy);
1344 rc = -ENOMEM;
1345 goto out;
1346 }
1347
1348 sis190_init_phy(dev, tp, phy, phy_id, status);
1349
1350 list_add(&tp->first_phy, &phy->list);
1351 }
1352
1353 if (list_empty(&tp->first_phy)) {
1354 net_probe(tp, KERN_INFO "%s: No MII transceivers found!\n",
Francois Romieu3690b6c2005-08-26 00:30:37 +02001355 pci_name(tp->pci_dev));
Francois Romieufcb98212005-07-30 13:15:22 +02001356 rc = -EIO;
1357 goto out;
1358 }
1359
1360 /* Select default PHY for mac */
1361 sis190_default_phy(dev);
1362
Francois Romieu900eb9d2005-09-03 00:55:27 +02001363 sis190_mii_probe_88e1111_fixup(tp);
1364
Francois Romieufcb98212005-07-30 13:15:22 +02001365 mii_if->dev = dev;
1366 mii_if->mdio_read = __mdio_read;
1367 mii_if->mdio_write = __mdio_write;
1368 mii_if->phy_id_mask = PHY_ID_ANY;
1369 mii_if->reg_num_mask = MII_REG_ANY;
1370out:
1371 return rc;
1372}
1373
Adrian Bunkc2b75f02007-12-11 23:23:56 +01001374static void sis190_mii_remove(struct net_device *dev)
Francois Romieufcb98212005-07-30 13:15:22 +02001375{
1376 struct sis190_private *tp = netdev_priv(dev);
1377
1378 sis190_free_phy(&tp->first_phy);
1379}
1380
Francois Romieu890e8d02005-07-30 13:08:43 +02001381static void sis190_release_board(struct pci_dev *pdev)
1382{
1383 struct net_device *dev = pci_get_drvdata(pdev);
1384 struct sis190_private *tp = netdev_priv(dev);
1385
1386 iounmap(tp->mmio_addr);
1387 pci_release_regions(pdev);
1388 pci_disable_device(pdev);
1389 free_netdev(dev);
1390}
1391
1392static struct net_device * __devinit sis190_init_board(struct pci_dev *pdev)
1393{
1394 struct sis190_private *tp;
1395 struct net_device *dev;
1396 void __iomem *ioaddr;
1397 int rc;
1398
1399 dev = alloc_etherdev(sizeof(*tp));
1400 if (!dev) {
1401 net_drv(&debug, KERN_ERR PFX "unable to alloc new ethernet\n");
1402 rc = -ENOMEM;
1403 goto err_out_0;
1404 }
1405
Francois Romieu890e8d02005-07-30 13:08:43 +02001406 SET_NETDEV_DEV(dev, &pdev->dev);
1407
1408 tp = netdev_priv(dev);
David Howellsc4028952006-11-22 14:57:56 +00001409 tp->dev = dev;
Francois Romieu890e8d02005-07-30 13:08:43 +02001410 tp->msg_enable = netif_msg_init(debug.msg_enable, SIS190_MSG_DEFAULT);
1411
1412 rc = pci_enable_device(pdev);
1413 if (rc < 0) {
1414 net_probe(tp, KERN_ERR "%s: enable failure\n", pci_name(pdev));
1415 goto err_free_dev_1;
1416 }
1417
1418 rc = -ENODEV;
1419
1420 if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
1421 net_probe(tp, KERN_ERR "%s: region #0 is no MMIO resource.\n",
1422 pci_name(pdev));
1423 goto err_pci_disable_2;
1424 }
1425 if (pci_resource_len(pdev, 0) < SIS190_REGS_SIZE) {
1426 net_probe(tp, KERN_ERR "%s: invalid PCI region size(s).\n",
1427 pci_name(pdev));
1428 goto err_pci_disable_2;
1429 }
1430
1431 rc = pci_request_regions(pdev, DRV_NAME);
1432 if (rc < 0) {
1433 net_probe(tp, KERN_ERR PFX "%s: could not request regions.\n",
1434 pci_name(pdev));
1435 goto err_pci_disable_2;
1436 }
1437
1438 rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
1439 if (rc < 0) {
1440 net_probe(tp, KERN_ERR "%s: DMA configuration failed.\n",
1441 pci_name(pdev));
1442 goto err_free_res_3;
1443 }
1444
1445 pci_set_master(pdev);
1446
1447 ioaddr = ioremap(pci_resource_start(pdev, 0), SIS190_REGS_SIZE);
1448 if (!ioaddr) {
1449 net_probe(tp, KERN_ERR "%s: cannot remap MMIO, aborting\n",
1450 pci_name(pdev));
1451 rc = -EIO;
1452 goto err_free_res_3;
1453 }
1454
1455 tp->pci_dev = pdev;
1456 tp->mmio_addr = ioaddr;
1457
1458 sis190_irq_mask_and_ack(ioaddr);
1459
1460 sis190_soft_reset(ioaddr);
1461out:
1462 return dev;
1463
1464err_free_res_3:
1465 pci_release_regions(pdev);
1466err_pci_disable_2:
1467 pci_disable_device(pdev);
1468err_free_dev_1:
1469 free_netdev(dev);
1470err_out_0:
1471 dev = ERR_PTR(rc);
1472 goto out;
1473}
1474
1475static void sis190_tx_timeout(struct net_device *dev)
1476{
1477 struct sis190_private *tp = netdev_priv(dev);
1478 void __iomem *ioaddr = tp->mmio_addr;
1479 u8 tmp8;
1480
1481 /* Disable Tx, if not already */
1482 tmp8 = SIS_R8(TxControl);
1483 if (tmp8 & CmdTxEnb)
1484 SIS_W8(TxControl, tmp8 & ~CmdTxEnb);
1485
Francois Romieu188f23b2005-07-30 13:11:43 +02001486
1487 net_tx_err(tp, KERN_INFO "%s: Transmit timeout, status %08x %08x.\n",
1488 dev->name, SIS_R32(TxControl), SIS_R32(TxSts));
1489
Francois Romieu890e8d02005-07-30 13:08:43 +02001490 /* Disable interrupts by clearing the interrupt mask. */
1491 SIS_W32(IntrMask, 0x0000);
1492
1493 /* Stop a shared interrupt from scavenging while we are. */
1494 spin_lock_irq(&tp->lock);
1495 sis190_tx_clear(tp);
1496 spin_unlock_irq(&tp->lock);
1497
1498 /* ...and finally, reset everything. */
1499 sis190_hw_start(dev);
1500
1501 netif_wake_queue(dev);
1502}
1503
Francois Romieu900eb9d2005-09-03 00:55:27 +02001504static void sis190_set_rgmii(struct sis190_private *tp, u8 reg)
1505{
1506 tp->features |= (reg & 0x80) ? F_HAS_RGMII : 0;
1507}
1508
Francois Romieu830fb7d2005-07-30 13:12:37 +02001509static int __devinit sis190_get_mac_addr_from_eeprom(struct pci_dev *pdev,
1510 struct net_device *dev)
1511{
1512 struct sis190_private *tp = netdev_priv(dev);
1513 void __iomem *ioaddr = tp->mmio_addr;
1514 u16 sig;
1515 int i;
1516
1517 net_probe(tp, KERN_INFO "%s: Read MAC address from EEPROM\n",
1518 pci_name(pdev));
1519
1520 /* Check to see if there is a sane EEPROM */
1521 sig = (u16) sis190_read_eeprom(ioaddr, EEPROMSignature);
1522
1523 if ((sig == 0xffff) || (sig == 0x0000)) {
1524 net_probe(tp, KERN_INFO "%s: Error EEPROM read %x.\n",
1525 pci_name(pdev), sig);
1526 return -EIO;
1527 }
1528
1529 /* Get MAC address from EEPROM */
1530 for (i = 0; i < MAC_ADDR_LEN / 2; i++) {
Al Viro961994a2007-12-15 01:44:33 +00001531 u16 w = sis190_read_eeprom(ioaddr, EEPROMMACAddr + i);
Francois Romieu830fb7d2005-07-30 13:12:37 +02001532
Al Viro961994a2007-12-15 01:44:33 +00001533 ((__le16 *)dev->dev_addr)[i] = cpu_to_le16(w);
Francois Romieu830fb7d2005-07-30 13:12:37 +02001534 }
1535
Francois Romieu900eb9d2005-09-03 00:55:27 +02001536 sis190_set_rgmii(tp, sis190_read_eeprom(ioaddr, EEPROMInfo));
1537
Francois Romieu830fb7d2005-07-30 13:12:37 +02001538 return 0;
1539}
1540
1541/**
Francois Romieuebc71642007-12-04 22:58:41 +01001542 * sis190_get_mac_addr_from_apc - Get MAC address for SiS96x model
Francois Romieu830fb7d2005-07-30 13:12:37 +02001543 * @pdev: PCI device
1544 * @dev: network device to get address for
1545 *
Francois Romieuebc71642007-12-04 22:58:41 +01001546 * SiS96x model, use APC CMOS RAM to store MAC address.
Francois Romieu830fb7d2005-07-30 13:12:37 +02001547 * APC CMOS RAM is accessed through ISA bridge.
1548 * MAC address is read into @net_dev->dev_addr.
1549 */
1550static int __devinit sis190_get_mac_addr_from_apc(struct pci_dev *pdev,
1551 struct net_device *dev)
1552{
Francois Romieuebc71642007-12-04 22:58:41 +01001553 static const u16 __devinitdata ids[] = { 0x0965, 0x0966, 0x0968 };
Francois Romieu830fb7d2005-07-30 13:12:37 +02001554 struct sis190_private *tp = netdev_priv(dev);
1555 struct pci_dev *isa_bridge;
1556 u8 reg, tmp8;
Francois Romieuebc71642007-12-04 22:58:41 +01001557 unsigned int i;
Francois Romieu830fb7d2005-07-30 13:12:37 +02001558
1559 net_probe(tp, KERN_INFO "%s: Read MAC address from APC.\n",
1560 pci_name(pdev));
1561
Francois Romieuebc71642007-12-04 22:58:41 +01001562 for (i = 0; i < ARRAY_SIZE(ids); i++) {
1563 isa_bridge = pci_get_device(PCI_VENDOR_ID_SI, ids[i], NULL);
1564 if (isa_bridge)
1565 break;
1566 }
Neil Muller8eb7ad62007-08-01 17:52:04 +02001567
Francois Romieu830fb7d2005-07-30 13:12:37 +02001568 if (!isa_bridge) {
1569 net_probe(tp, KERN_INFO "%s: Can not find ISA bridge.\n",
1570 pci_name(pdev));
1571 return -EIO;
1572 }
1573
1574 /* Enable port 78h & 79h to access APC Registers. */
1575 pci_read_config_byte(isa_bridge, 0x48, &tmp8);
1576 reg = (tmp8 & ~0x02);
1577 pci_write_config_byte(isa_bridge, 0x48, reg);
1578 udelay(50);
1579 pci_read_config_byte(isa_bridge, 0x48, &reg);
1580
1581 for (i = 0; i < MAC_ADDR_LEN; i++) {
1582 outb(0x9 + i, 0x78);
1583 dev->dev_addr[i] = inb(0x79);
1584 }
1585
1586 outb(0x12, 0x78);
1587 reg = inb(0x79);
1588
Francois Romieu900eb9d2005-09-03 00:55:27 +02001589 sis190_set_rgmii(tp, reg);
1590
Francois Romieu830fb7d2005-07-30 13:12:37 +02001591 /* Restore the value to ISA Bridge */
1592 pci_write_config_byte(isa_bridge, 0x48, tmp8);
1593 pci_dev_put(isa_bridge);
1594
1595 return 0;
1596}
1597
1598/**
1599 * sis190_init_rxfilter - Initialize the Rx filter
1600 * @dev: network device to initialize
1601 *
1602 * Set receive filter address to our MAC address
1603 * and enable packet filtering.
1604 */
1605static inline void sis190_init_rxfilter(struct net_device *dev)
1606{
1607 struct sis190_private *tp = netdev_priv(dev);
1608 void __iomem *ioaddr = tp->mmio_addr;
1609 u16 ctl;
1610 int i;
1611
1612 ctl = SIS_R16(RxMacControl);
1613 /*
1614 * Disable packet filtering before setting filter.
1615 * Note: SiS's driver writes 32 bits but RxMacControl is 16 bits
1616 * only and followed by RxMacAddr (6 bytes). Strange. -- FR
1617 */
1618 SIS_W16(RxMacControl, ctl & ~0x0f00);
1619
1620 for (i = 0; i < MAC_ADDR_LEN; i++)
1621 SIS_W8(RxMacAddr + i, dev->dev_addr[i]);
1622
1623 SIS_W16(RxMacControl, ctl);
1624 SIS_PCI_COMMIT();
1625}
1626
Sergio Luisd785ad72008-02-10 17:56:25 -03001627static int __devinit sis190_get_mac_addr(struct pci_dev *pdev,
1628 struct net_device *dev)
Francois Romieu830fb7d2005-07-30 13:12:37 +02001629{
Francois Romieu563e0ae2008-02-18 21:20:32 +01001630 int rc;
Francois Romieu830fb7d2005-07-30 13:12:37 +02001631
Francois Romieu563e0ae2008-02-18 21:20:32 +01001632 rc = sis190_get_mac_addr_from_eeprom(pdev, dev);
1633 if (rc < 0) {
1634 u8 reg;
Francois Romieu830fb7d2005-07-30 13:12:37 +02001635
Francois Romieu563e0ae2008-02-18 21:20:32 +01001636 pci_read_config_byte(pdev, 0x73, &reg);
1637
1638 if (reg & 0x00000001)
1639 rc = sis190_get_mac_addr_from_apc(pdev, dev);
1640 }
1641 return rc;
Francois Romieu830fb7d2005-07-30 13:12:37 +02001642}
1643
Francois Romieu890e8d02005-07-30 13:08:43 +02001644static void sis190_set_speed_auto(struct net_device *dev)
1645{
1646 struct sis190_private *tp = netdev_priv(dev);
1647 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu9ede1092005-07-30 13:14:38 +02001648 int phy_id = tp->mii_if.phy_id;
Francois Romieu890e8d02005-07-30 13:08:43 +02001649 int val;
1650
1651 net_link(tp, KERN_INFO "%s: Enabling Auto-negotiation.\n", dev->name);
1652
Francois Romieu9ede1092005-07-30 13:14:38 +02001653 val = mdio_read(ioaddr, phy_id, MII_ADVERTISE);
Francois Romieu890e8d02005-07-30 13:08:43 +02001654
1655 // Enable 10/100 Full/Half Mode, leave MII_ADVERTISE bit4:0
1656 // unchanged.
Francois Romieu9ede1092005-07-30 13:14:38 +02001657 mdio_write(ioaddr, phy_id, MII_ADVERTISE, (val & ADVERTISE_SLCT) |
Francois Romieu890e8d02005-07-30 13:08:43 +02001658 ADVERTISE_100FULL | ADVERTISE_10FULL |
1659 ADVERTISE_100HALF | ADVERTISE_10HALF);
1660
1661 // Enable 1000 Full Mode.
Francois Romieu9ede1092005-07-30 13:14:38 +02001662 mdio_write(ioaddr, phy_id, MII_CTRL1000, ADVERTISE_1000FULL);
Francois Romieu890e8d02005-07-30 13:08:43 +02001663
1664 // Enable auto-negotiation and restart auto-negotiation.
Francois Romieu9ede1092005-07-30 13:14:38 +02001665 mdio_write(ioaddr, phy_id, MII_BMCR,
Francois Romieu890e8d02005-07-30 13:08:43 +02001666 BMCR_ANENABLE | BMCR_ANRESTART | BMCR_RESET);
1667}
1668
Francois Romieu43afb942005-07-30 13:10:21 +02001669static int sis190_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
1670{
1671 struct sis190_private *tp = netdev_priv(dev);
1672
1673 return mii_ethtool_gset(&tp->mii_if, cmd);
1674}
1675
1676static int sis190_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
1677{
1678 struct sis190_private *tp = netdev_priv(dev);
1679
1680 return mii_ethtool_sset(&tp->mii_if, cmd);
1681}
1682
Francois Romieu890e8d02005-07-30 13:08:43 +02001683static void sis190_get_drvinfo(struct net_device *dev,
1684 struct ethtool_drvinfo *info)
1685{
1686 struct sis190_private *tp = netdev_priv(dev);
1687
1688 strcpy(info->driver, DRV_NAME);
1689 strcpy(info->version, DRV_VERSION);
1690 strcpy(info->bus_info, pci_name(tp->pci_dev));
1691}
1692
1693static int sis190_get_regs_len(struct net_device *dev)
1694{
1695 return SIS190_REGS_SIZE;
1696}
1697
1698static void sis190_get_regs(struct net_device *dev, struct ethtool_regs *regs,
1699 void *p)
1700{
1701 struct sis190_private *tp = netdev_priv(dev);
1702 unsigned long flags;
1703
1704 if (regs->len > SIS190_REGS_SIZE)
1705 regs->len = SIS190_REGS_SIZE;
1706
1707 spin_lock_irqsave(&tp->lock, flags);
1708 memcpy_fromio(p, tp->mmio_addr, regs->len);
1709 spin_unlock_irqrestore(&tp->lock, flags);
1710}
1711
Francois Romieu43afb942005-07-30 13:10:21 +02001712static int sis190_nway_reset(struct net_device *dev)
1713{
1714 struct sis190_private *tp = netdev_priv(dev);
1715
1716 return mii_nway_restart(&tp->mii_if);
1717}
1718
Francois Romieu890e8d02005-07-30 13:08:43 +02001719static u32 sis190_get_msglevel(struct net_device *dev)
1720{
1721 struct sis190_private *tp = netdev_priv(dev);
1722
1723 return tp->msg_enable;
1724}
1725
1726static void sis190_set_msglevel(struct net_device *dev, u32 value)
1727{
1728 struct sis190_private *tp = netdev_priv(dev);
1729
1730 tp->msg_enable = value;
1731}
1732
Jeff Garzik7282d492006-09-13 14:30:00 -04001733static const struct ethtool_ops sis190_ethtool_ops = {
Francois Romieu43afb942005-07-30 13:10:21 +02001734 .get_settings = sis190_get_settings,
1735 .set_settings = sis190_set_settings,
Francois Romieu890e8d02005-07-30 13:08:43 +02001736 .get_drvinfo = sis190_get_drvinfo,
1737 .get_regs_len = sis190_get_regs_len,
1738 .get_regs = sis190_get_regs,
1739 .get_link = ethtool_op_get_link,
1740 .get_msglevel = sis190_get_msglevel,
1741 .set_msglevel = sis190_set_msglevel,
Francois Romieu43afb942005-07-30 13:10:21 +02001742 .nway_reset = sis190_nway_reset,
Francois Romieu890e8d02005-07-30 13:08:43 +02001743};
1744
Francois Romieu43afb942005-07-30 13:10:21 +02001745static int sis190_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1746{
1747 struct sis190_private *tp = netdev_priv(dev);
1748
1749 return !netif_running(dev) ? -EINVAL :
1750 generic_mii_ioctl(&tp->mii_if, if_mii(ifr), cmd, NULL);
1751}
1752
Francois Romieu890e8d02005-07-30 13:08:43 +02001753static int __devinit sis190_init_one(struct pci_dev *pdev,
1754 const struct pci_device_id *ent)
1755{
1756 static int printed_version = 0;
1757 struct sis190_private *tp;
1758 struct net_device *dev;
1759 void __iomem *ioaddr;
Francois Romieu830fb7d2005-07-30 13:12:37 +02001760 int rc;
Joe Perches0795af52007-10-03 17:59:30 -07001761 DECLARE_MAC_BUF(mac);
Francois Romieu890e8d02005-07-30 13:08:43 +02001762
1763 if (!printed_version) {
1764 net_drv(&debug, KERN_INFO SIS190_DRIVER_NAME " loaded.\n");
1765 printed_version = 1;
1766 }
1767
1768 dev = sis190_init_board(pdev);
1769 if (IS_ERR(dev)) {
1770 rc = PTR_ERR(dev);
1771 goto out;
1772 }
1773
Francois Romieu10487fb2006-02-16 22:17:00 +01001774 pci_set_drvdata(pdev, dev);
1775
Francois Romieu890e8d02005-07-30 13:08:43 +02001776 tp = netdev_priv(dev);
1777 ioaddr = tp->mmio_addr;
1778
Francois Romieu830fb7d2005-07-30 13:12:37 +02001779 rc = sis190_get_mac_addr(pdev, dev);
1780 if (rc < 0)
1781 goto err_release_board;
Francois Romieu890e8d02005-07-30 13:08:43 +02001782
Francois Romieu830fb7d2005-07-30 13:12:37 +02001783 sis190_init_rxfilter(dev);
Francois Romieu890e8d02005-07-30 13:08:43 +02001784
David Howellsc4028952006-11-22 14:57:56 +00001785 INIT_WORK(&tp->phy_task, sis190_phy_task);
Francois Romieu890e8d02005-07-30 13:08:43 +02001786
1787 dev->open = sis190_open;
1788 dev->stop = sis190_close;
Francois Romieu43afb942005-07-30 13:10:21 +02001789 dev->do_ioctl = sis190_ioctl;
Francois Romieu890e8d02005-07-30 13:08:43 +02001790 dev->tx_timeout = sis190_tx_timeout;
1791 dev->watchdog_timeo = SIS190_TX_TIMEOUT;
1792 dev->hard_start_xmit = sis190_start_xmit;
Francois Romieu4405d3b2005-07-30 13:09:20 +02001793#ifdef CONFIG_NET_POLL_CONTROLLER
1794 dev->poll_controller = sis190_netpoll;
1795#endif
Francois Romieu890e8d02005-07-30 13:08:43 +02001796 dev->set_multicast_list = sis190_set_rx_mode;
1797 SET_ETHTOOL_OPS(dev, &sis190_ethtool_ops);
1798 dev->irq = pdev->irq;
1799 dev->base_addr = (unsigned long) 0xdead;
1800
1801 spin_lock_init(&tp->lock);
Francois Romieu890e8d02005-07-30 13:08:43 +02001802
Francois Romieufcb98212005-07-30 13:15:22 +02001803 rc = sis190_mii_probe(dev);
1804 if (rc < 0)
Francois Romieu3690b6c2005-08-26 00:30:37 +02001805 goto err_release_board;
1806
1807 rc = register_netdev(dev);
1808 if (rc < 0)
1809 goto err_remove_mii;
1810
Francois Romieu890e8d02005-07-30 13:08:43 +02001811 net_probe(tp, KERN_INFO "%s: %s at %p (IRQ: %d), "
Joe Perches0795af52007-10-03 17:59:30 -07001812 "%s\n",
1813 pci_name(pdev), sis_chip_info[ent->driver_data].name,
1814 ioaddr, dev->irq, print_mac(mac, dev->dev_addr));
Francois Romieu890e8d02005-07-30 13:08:43 +02001815
Francois Romieu900eb9d2005-09-03 00:55:27 +02001816 net_probe(tp, KERN_INFO "%s: %s mode.\n", dev->name,
1817 (tp->features & F_HAS_RGMII) ? "RGMII" : "GMII");
1818
Francois Romieu890e8d02005-07-30 13:08:43 +02001819 netif_carrier_off(dev);
1820
1821 sis190_set_speed_auto(dev);
1822out:
1823 return rc;
Francois Romieu830fb7d2005-07-30 13:12:37 +02001824
Francois Romieu3690b6c2005-08-26 00:30:37 +02001825err_remove_mii:
1826 sis190_mii_remove(dev);
Francois Romieu830fb7d2005-07-30 13:12:37 +02001827err_release_board:
1828 sis190_release_board(pdev);
1829 goto out;
Francois Romieu890e8d02005-07-30 13:08:43 +02001830}
1831
1832static void __devexit sis190_remove_one(struct pci_dev *pdev)
1833{
1834 struct net_device *dev = pci_get_drvdata(pdev);
1835
Francois Romieufcb98212005-07-30 13:15:22 +02001836 sis190_mii_remove(dev);
Francois Romieuc014f6c2007-02-15 23:37:29 +01001837 flush_scheduled_work();
Francois Romieu890e8d02005-07-30 13:08:43 +02001838 unregister_netdev(dev);
1839 sis190_release_board(pdev);
1840 pci_set_drvdata(pdev, NULL);
1841}
1842
1843static struct pci_driver sis190_pci_driver = {
1844 .name = DRV_NAME,
1845 .id_table = sis190_pci_tbl,
1846 .probe = sis190_init_one,
1847 .remove = __devexit_p(sis190_remove_one),
1848};
1849
1850static int __init sis190_init_module(void)
1851{
Jeff Garzik29917622006-08-19 17:48:59 -04001852 return pci_register_driver(&sis190_pci_driver);
Francois Romieu890e8d02005-07-30 13:08:43 +02001853}
1854
1855static void __exit sis190_cleanup_module(void)
1856{
1857 pci_unregister_driver(&sis190_pci_driver);
1858}
1859
1860module_init(sis190_init_module);
1861module_exit(sis190_cleanup_module);