blob: 0b22e75633a29e86b1e2910d0ed95c1b19f589a1 [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 Romieu890e8d02005-07-30 13:08:43 +0200902 net_link(tp, KERN_WARNING "%s: PHY reset until link up.\n",
903 dev->name);
Francois Romieu21461382005-09-03 00:54:25 +0200904 netif_carrier_off(dev);
Francois Romieu9ede1092005-07-30 13:14:38 +0200905 mdio_write(ioaddr, phy_id, MII_BMCR, val | BMCR_RESET);
Francois Romieu890e8d02005-07-30 13:08:43 +0200906 mod_timer(&tp->timer, jiffies + SIS190_PHY_TIMEOUT);
907 } else {
908 /* Rejoice ! */
909 struct {
910 int val;
Francois Romieu6614a6d2005-09-03 00:56:16 +0200911 u32 ctl;
Francois Romieu890e8d02005-07-30 13:08:43 +0200912 const char *msg;
Francois Romieu890e8d02005-07-30 13:08:43 +0200913 } reg31[] = {
Francois Romieu6614a6d2005-09-03 00:56:16 +0200914 { LPA_1000XFULL | LPA_SLCT, 0x07000c00 | 0x00001000,
915 "1000 Mbps Full Duplex" },
916 { LPA_1000XHALF | LPA_SLCT, 0x07000c00,
917 "1000 Mbps Half Duplex" },
918 { LPA_100FULL, 0x04000800 | 0x00001000,
919 "100 Mbps Full Duplex" },
920 { LPA_100HALF, 0x04000800,
921 "100 Mbps Half Duplex" },
922 { LPA_10FULL, 0x04000400 | 0x00001000,
923 "10 Mbps Full Duplex" },
924 { LPA_10HALF, 0x04000400,
925 "10 Mbps Half Duplex" },
926 { 0, 0x04000400, "unknown" }
927 }, *p;
Francois Romieu8348b4d2005-07-30 13:16:14 +0200928 u16 adv;
Francois Romieu890e8d02005-07-30 13:08:43 +0200929
Francois Romieu9ede1092005-07-30 13:14:38 +0200930 val = mdio_read(ioaddr, phy_id, 0x1f);
Francois Romieu890e8d02005-07-30 13:08:43 +0200931 net_link(tp, KERN_INFO "%s: mii ext = %04x.\n", dev->name, val);
932
Francois Romieu9ede1092005-07-30 13:14:38 +0200933 val = mdio_read(ioaddr, phy_id, MII_LPA);
Francois Romieu8348b4d2005-07-30 13:16:14 +0200934 adv = mdio_read(ioaddr, phy_id, MII_ADVERTISE);
935 net_link(tp, KERN_INFO "%s: mii lpa = %04x adv = %04x.\n",
936 dev->name, val, adv);
937
938 val &= adv;
Francois Romieu890e8d02005-07-30 13:08:43 +0200939
Francois Romieu6614a6d2005-09-03 00:56:16 +0200940 for (p = reg31; p->val; p++) {
Francois Romieu890e8d02005-07-30 13:08:43 +0200941 if ((val & p->val) == p->val)
942 break;
943 }
Francois Romieu6614a6d2005-09-03 00:56:16 +0200944
945 p->ctl |= SIS_R32(StationControl) & ~0x0f001c00;
946
Francois Romieuc3d6f1f2005-09-03 00:56:57 +0200947 if ((tp->features & F_HAS_RGMII) &&
948 (tp->features & F_PHY_BCM5461)) {
949 // Set Tx Delay in RGMII mode.
950 mdio_write(ioaddr, phy_id, 0x18, 0xf1c7);
951 udelay(200);
952 mdio_write(ioaddr, phy_id, 0x1c, 0x8c00);
953 p->ctl |= 0x03000000;
954 }
955
Francois Romieu6614a6d2005-09-03 00:56:16 +0200956 SIS_W32(StationControl, p->ctl);
957
Francois Romieuc3d6f1f2005-09-03 00:56:57 +0200958 if (tp->features & F_HAS_RGMII) {
959 SIS_W32(RGDelay, 0x0441);
960 SIS_W32(RGDelay, 0x0440);
961 }
962
Francois Romieu890e8d02005-07-30 13:08:43 +0200963 net_link(tp, KERN_INFO "%s: link on %s mode.\n", dev->name,
964 p->msg);
965 netif_carrier_on(dev);
966 }
Francois Romieu43afb942005-07-30 13:10:21 +0200967
Francois Romieuc014f6c2007-02-15 23:37:29 +0100968out_unlock:
Francois Romieu43afb942005-07-30 13:10:21 +0200969 rtnl_unlock();
Francois Romieu890e8d02005-07-30 13:08:43 +0200970}
971
972static void sis190_phy_timer(unsigned long __opaque)
973{
974 struct net_device *dev = (struct net_device *)__opaque;
975 struct sis190_private *tp = netdev_priv(dev);
976
977 if (likely(netif_running(dev)))
978 schedule_work(&tp->phy_task);
979}
980
981static inline void sis190_delete_timer(struct net_device *dev)
982{
983 struct sis190_private *tp = netdev_priv(dev);
984
985 del_timer_sync(&tp->timer);
986}
987
988static inline void sis190_request_timer(struct net_device *dev)
989{
990 struct sis190_private *tp = netdev_priv(dev);
991 struct timer_list *timer = &tp->timer;
992
993 init_timer(timer);
994 timer->expires = jiffies + SIS190_PHY_TIMEOUT;
995 timer->data = (unsigned long)dev;
996 timer->function = sis190_phy_timer;
997 add_timer(timer);
998}
999
1000static void sis190_set_rxbufsize(struct sis190_private *tp,
1001 struct net_device *dev)
1002{
1003 unsigned int mtu = dev->mtu;
1004
1005 tp->rx_buf_sz = (mtu > RX_BUF_SIZE) ? mtu + ETH_HLEN + 8 : RX_BUF_SIZE;
Francois Romieu8b5641d2005-07-30 13:13:03 +02001006 /* RxDesc->size has a licence to kill the lower bits */
1007 if (tp->rx_buf_sz & 0x07) {
1008 tp->rx_buf_sz += 8;
1009 tp->rx_buf_sz &= RX_BUF_MASK;
1010 }
Francois Romieu890e8d02005-07-30 13:08:43 +02001011}
1012
1013static int sis190_open(struct net_device *dev)
1014{
1015 struct sis190_private *tp = netdev_priv(dev);
1016 struct pci_dev *pdev = tp->pci_dev;
1017 int rc = -ENOMEM;
1018
1019 sis190_set_rxbufsize(tp, dev);
1020
1021 /*
1022 * Rx and Tx descriptors need 256 bytes alignment.
1023 * pci_alloc_consistent() guarantees a stronger alignment.
1024 */
1025 tp->TxDescRing = pci_alloc_consistent(pdev, TX_RING_BYTES, &tp->tx_dma);
1026 if (!tp->TxDescRing)
1027 goto out;
1028
1029 tp->RxDescRing = pci_alloc_consistent(pdev, RX_RING_BYTES, &tp->rx_dma);
1030 if (!tp->RxDescRing)
1031 goto err_free_tx_0;
1032
1033 rc = sis190_init_ring(dev);
1034 if (rc < 0)
1035 goto err_free_rx_1;
1036
Francois Romieu890e8d02005-07-30 13:08:43 +02001037 sis190_request_timer(dev);
1038
Thomas Gleixner1fb9df52006-07-01 19:29:39 -07001039 rc = request_irq(dev->irq, sis190_interrupt, IRQF_SHARED, dev->name, dev);
Francois Romieu890e8d02005-07-30 13:08:43 +02001040 if (rc < 0)
1041 goto err_release_timer_2;
1042
1043 sis190_hw_start(dev);
1044out:
1045 return rc;
1046
1047err_release_timer_2:
1048 sis190_delete_timer(dev);
1049 sis190_rx_clear(tp);
1050err_free_rx_1:
1051 pci_free_consistent(tp->pci_dev, RX_RING_BYTES, tp->RxDescRing,
1052 tp->rx_dma);
1053err_free_tx_0:
1054 pci_free_consistent(tp->pci_dev, TX_RING_BYTES, tp->TxDescRing,
1055 tp->tx_dma);
1056 goto out;
1057}
1058
1059static void sis190_tx_clear(struct sis190_private *tp)
1060{
1061 unsigned int i;
1062
1063 for (i = 0; i < NUM_TX_DESC; i++) {
1064 struct sk_buff *skb = tp->Tx_skbuff[i];
1065
1066 if (!skb)
1067 continue;
1068
1069 sis190_unmap_tx_skb(tp->pci_dev, skb, tp->TxDescRing + i);
1070 tp->Tx_skbuff[i] = NULL;
1071 dev_kfree_skb(skb);
1072
Jeff Garzik09f75cd2007-10-03 17:41:50 -07001073 tp->dev->stats.tx_dropped++;
Francois Romieu890e8d02005-07-30 13:08:43 +02001074 }
1075 tp->cur_tx = tp->dirty_tx = 0;
1076}
1077
1078static void sis190_down(struct net_device *dev)
1079{
1080 struct sis190_private *tp = netdev_priv(dev);
1081 void __iomem *ioaddr = tp->mmio_addr;
1082 unsigned int poll_locked = 0;
1083
1084 sis190_delete_timer(dev);
1085
1086 netif_stop_queue(dev);
1087
Francois Romieu890e8d02005-07-30 13:08:43 +02001088 do {
1089 spin_lock_irq(&tp->lock);
1090
1091 sis190_asic_down(ioaddr);
1092
1093 spin_unlock_irq(&tp->lock);
1094
1095 synchronize_irq(dev->irq);
1096
Stephen Hemmingerbea33482007-10-03 16:41:36 -07001097 if (!poll_locked)
Francois Romieu890e8d02005-07-30 13:08:43 +02001098 poll_locked++;
Francois Romieu890e8d02005-07-30 13:08:43 +02001099
1100 synchronize_sched();
1101
1102 } while (SIS_R32(IntrMask));
1103
1104 sis190_tx_clear(tp);
1105 sis190_rx_clear(tp);
1106}
1107
1108static int sis190_close(struct net_device *dev)
1109{
1110 struct sis190_private *tp = netdev_priv(dev);
1111 struct pci_dev *pdev = tp->pci_dev;
1112
1113 sis190_down(dev);
1114
1115 free_irq(dev->irq, dev);
1116
Francois Romieu890e8d02005-07-30 13:08:43 +02001117 pci_free_consistent(pdev, TX_RING_BYTES, tp->TxDescRing, tp->tx_dma);
1118 pci_free_consistent(pdev, RX_RING_BYTES, tp->RxDescRing, tp->rx_dma);
1119
1120 tp->TxDescRing = NULL;
1121 tp->RxDescRing = NULL;
1122
1123 return 0;
1124}
1125
1126static int sis190_start_xmit(struct sk_buff *skb, struct net_device *dev)
1127{
1128 struct sis190_private *tp = netdev_priv(dev);
1129 void __iomem *ioaddr = tp->mmio_addr;
1130 u32 len, entry, dirty_tx;
1131 struct TxDesc *desc;
1132 dma_addr_t mapping;
1133
1134 if (unlikely(skb->len < ETH_ZLEN)) {
Herbert Xu5b057c62006-06-23 02:06:41 -07001135 if (skb_padto(skb, ETH_ZLEN)) {
Jeff Garzik09f75cd2007-10-03 17:41:50 -07001136 dev->stats.tx_dropped++;
Francois Romieu890e8d02005-07-30 13:08:43 +02001137 goto out;
1138 }
1139 len = ETH_ZLEN;
1140 } else {
1141 len = skb->len;
1142 }
1143
1144 entry = tp->cur_tx % NUM_TX_DESC;
1145 desc = tp->TxDescRing + entry;
1146
1147 if (unlikely(le32_to_cpu(desc->status) & OWNbit)) {
1148 netif_stop_queue(dev);
1149 net_tx_err(tp, KERN_ERR PFX
1150 "%s: BUG! Tx Ring full when queue awake!\n",
1151 dev->name);
1152 return NETDEV_TX_BUSY;
1153 }
1154
1155 mapping = pci_map_single(tp->pci_dev, skb->data, len, PCI_DMA_TODEVICE);
1156
1157 tp->Tx_skbuff[entry] = skb;
1158
1159 desc->PSize = cpu_to_le32(len);
1160 desc->addr = cpu_to_le32(mapping);
1161
1162 desc->size = cpu_to_le32(len);
1163 if (entry == (NUM_TX_DESC - 1))
1164 desc->size |= cpu_to_le32(RingEnd);
1165
1166 wmb();
1167
1168 desc->status = cpu_to_le32(OWNbit | INTbit | DEFbit | CRCbit | PADbit);
1169
1170 tp->cur_tx++;
1171
1172 smp_wmb();
1173
1174 SIS_W32(TxControl, 0x1a00 | CmdReset | CmdTxEnb);
1175
1176 dev->trans_start = jiffies;
1177
1178 dirty_tx = tp->dirty_tx;
1179 if ((tp->cur_tx - NUM_TX_DESC) == dirty_tx) {
1180 netif_stop_queue(dev);
1181 smp_rmb();
1182 if (dirty_tx != tp->dirty_tx)
1183 netif_wake_queue(dev);
1184 }
1185out:
1186 return NETDEV_TX_OK;
1187}
1188
Francois Romieufcb98212005-07-30 13:15:22 +02001189static void sis190_free_phy(struct list_head *first_phy)
1190{
1191 struct sis190_phy *cur, *next;
1192
1193 list_for_each_entry_safe(cur, next, first_phy, list) {
1194 kfree(cur);
1195 }
1196}
1197
1198/**
1199 * sis190_default_phy - Select default PHY for sis190 mac.
1200 * @dev: the net device to probe for
1201 *
1202 * Select first detected PHY with link as default.
1203 * If no one is link on, select PHY whose types is HOME as default.
1204 * If HOME doesn't exist, select LAN.
1205 */
1206static u16 sis190_default_phy(struct net_device *dev)
1207{
1208 struct sis190_phy *phy, *phy_home, *phy_default, *phy_lan;
1209 struct sis190_private *tp = netdev_priv(dev);
1210 struct mii_if_info *mii_if = &tp->mii_if;
1211 void __iomem *ioaddr = tp->mmio_addr;
1212 u16 status;
1213
1214 phy_home = phy_default = phy_lan = NULL;
1215
1216 list_for_each_entry(phy, &tp->first_phy, list) {
1217 status = mdio_read_latched(ioaddr, phy->phy_id, MII_BMSR);
1218
1219 // Link ON & Not select default PHY & not ghost PHY.
1220 if ((status & BMSR_LSTATUS) &&
1221 !phy_default &&
1222 (phy->type != UNKNOWN)) {
1223 phy_default = phy;
1224 } else {
1225 status = mdio_read(ioaddr, phy->phy_id, MII_BMCR);
1226 mdio_write(ioaddr, phy->phy_id, MII_BMCR,
1227 status | BMCR_ANENABLE | BMCR_ISOLATE);
1228 if (phy->type == HOME)
1229 phy_home = phy;
1230 else if (phy->type == LAN)
1231 phy_lan = phy;
1232 }
1233 }
1234
1235 if (!phy_default) {
1236 if (phy_home)
1237 phy_default = phy_home;
1238 else if (phy_lan)
1239 phy_default = phy_lan;
1240 else
1241 phy_default = list_entry(&tp->first_phy,
1242 struct sis190_phy, list);
1243 }
1244
1245 if (mii_if->phy_id != phy_default->phy_id) {
1246 mii_if->phy_id = phy_default->phy_id;
1247 net_probe(tp, KERN_INFO
1248 "%s: Using transceiver at address %d as default.\n",
Francois Romieu3690b6c2005-08-26 00:30:37 +02001249 pci_name(tp->pci_dev), mii_if->phy_id);
Francois Romieufcb98212005-07-30 13:15:22 +02001250 }
1251
1252 status = mdio_read(ioaddr, mii_if->phy_id, MII_BMCR);
1253 status &= (~BMCR_ISOLATE);
1254
1255 mdio_write(ioaddr, mii_if->phy_id, MII_BMCR, status);
1256 status = mdio_read_latched(ioaddr, mii_if->phy_id, MII_BMSR);
1257
1258 return status;
1259}
1260
1261static void sis190_init_phy(struct net_device *dev, struct sis190_private *tp,
1262 struct sis190_phy *phy, unsigned int phy_id,
1263 u16 mii_status)
1264{
1265 void __iomem *ioaddr = tp->mmio_addr;
1266 struct mii_chip_info *p;
1267
1268 INIT_LIST_HEAD(&phy->list);
1269 phy->status = mii_status;
1270 phy->phy_id = phy_id;
1271
1272 phy->id[0] = mdio_read(ioaddr, phy_id, MII_PHYSID1);
1273 phy->id[1] = mdio_read(ioaddr, phy_id, MII_PHYSID2);
1274
1275 for (p = mii_chip_table; p->type; p++) {
1276 if ((p->id[0] == phy->id[0]) &&
1277 (p->id[1] == (phy->id[1] & 0xfff0))) {
1278 break;
1279 }
1280 }
1281
1282 if (p->id[1]) {
1283 phy->type = (p->type == MIX) ?
1284 ((mii_status & (BMSR_100FULL | BMSR_100HALF)) ?
1285 LAN : HOME) : p->type;
Francois Romieu900eb9d2005-09-03 00:55:27 +02001286 tp->features |= p->feature;
Francois Romieufcb98212005-07-30 13:15:22 +02001287 } else
1288 phy->type = UNKNOWN;
1289
1290 net_probe(tp, KERN_INFO "%s: %s transceiver at address %d.\n",
Francois Romieu3690b6c2005-08-26 00:30:37 +02001291 pci_name(tp->pci_dev),
1292 (phy->type == UNKNOWN) ? "Unknown PHY" : p->name, phy_id);
Francois Romieufcb98212005-07-30 13:15:22 +02001293}
1294
Francois Romieu900eb9d2005-09-03 00:55:27 +02001295static void sis190_mii_probe_88e1111_fixup(struct sis190_private *tp)
1296{
1297 if (tp->features & F_PHY_88E1111) {
1298 void __iomem *ioaddr = tp->mmio_addr;
1299 int phy_id = tp->mii_if.phy_id;
1300 u16 reg[2][2] = {
1301 { 0x808b, 0x0ce1 },
1302 { 0x808f, 0x0c60 }
1303 }, *p;
1304
1305 p = (tp->features & F_HAS_RGMII) ? reg[0] : reg[1];
1306
1307 mdio_write(ioaddr, phy_id, 0x1b, p[0]);
1308 udelay(200);
1309 mdio_write(ioaddr, phy_id, 0x14, p[1]);
1310 udelay(200);
1311 }
1312}
1313
Francois Romieufcb98212005-07-30 13:15:22 +02001314/**
1315 * sis190_mii_probe - Probe MII PHY for sis190
1316 * @dev: the net device to probe for
1317 *
1318 * Search for total of 32 possible mii phy addresses.
1319 * Identify and set current phy if found one,
1320 * return error if it failed to found.
1321 */
1322static int __devinit sis190_mii_probe(struct net_device *dev)
1323{
1324 struct sis190_private *tp = netdev_priv(dev);
1325 struct mii_if_info *mii_if = &tp->mii_if;
1326 void __iomem *ioaddr = tp->mmio_addr;
1327 int phy_id;
1328 int rc = 0;
1329
1330 INIT_LIST_HEAD(&tp->first_phy);
1331
1332 for (phy_id = 0; phy_id < PHY_MAX_ADDR; phy_id++) {
1333 struct sis190_phy *phy;
1334 u16 status;
1335
1336 status = mdio_read_latched(ioaddr, phy_id, MII_BMSR);
1337
1338 // Try next mii if the current one is not accessible.
1339 if (status == 0xffff || status == 0x0000)
1340 continue;
1341
1342 phy = kmalloc(sizeof(*phy), GFP_KERNEL);
1343 if (!phy) {
1344 sis190_free_phy(&tp->first_phy);
1345 rc = -ENOMEM;
1346 goto out;
1347 }
1348
1349 sis190_init_phy(dev, tp, phy, phy_id, status);
1350
1351 list_add(&tp->first_phy, &phy->list);
1352 }
1353
1354 if (list_empty(&tp->first_phy)) {
1355 net_probe(tp, KERN_INFO "%s: No MII transceivers found!\n",
Francois Romieu3690b6c2005-08-26 00:30:37 +02001356 pci_name(tp->pci_dev));
Francois Romieufcb98212005-07-30 13:15:22 +02001357 rc = -EIO;
1358 goto out;
1359 }
1360
1361 /* Select default PHY for mac */
1362 sis190_default_phy(dev);
1363
Francois Romieu900eb9d2005-09-03 00:55:27 +02001364 sis190_mii_probe_88e1111_fixup(tp);
1365
Francois Romieufcb98212005-07-30 13:15:22 +02001366 mii_if->dev = dev;
1367 mii_if->mdio_read = __mdio_read;
1368 mii_if->mdio_write = __mdio_write;
1369 mii_if->phy_id_mask = PHY_ID_ANY;
1370 mii_if->reg_num_mask = MII_REG_ANY;
1371out:
1372 return rc;
1373}
1374
Adrian Bunkc2b75f02007-12-11 23:23:56 +01001375static void sis190_mii_remove(struct net_device *dev)
Francois Romieufcb98212005-07-30 13:15:22 +02001376{
1377 struct sis190_private *tp = netdev_priv(dev);
1378
1379 sis190_free_phy(&tp->first_phy);
1380}
1381
Francois Romieu890e8d02005-07-30 13:08:43 +02001382static void sis190_release_board(struct pci_dev *pdev)
1383{
1384 struct net_device *dev = pci_get_drvdata(pdev);
1385 struct sis190_private *tp = netdev_priv(dev);
1386
1387 iounmap(tp->mmio_addr);
1388 pci_release_regions(pdev);
1389 pci_disable_device(pdev);
1390 free_netdev(dev);
1391}
1392
1393static struct net_device * __devinit sis190_init_board(struct pci_dev *pdev)
1394{
1395 struct sis190_private *tp;
1396 struct net_device *dev;
1397 void __iomem *ioaddr;
1398 int rc;
1399
1400 dev = alloc_etherdev(sizeof(*tp));
1401 if (!dev) {
1402 net_drv(&debug, KERN_ERR PFX "unable to alloc new ethernet\n");
1403 rc = -ENOMEM;
1404 goto err_out_0;
1405 }
1406
Francois Romieu890e8d02005-07-30 13:08:43 +02001407 SET_NETDEV_DEV(dev, &pdev->dev);
1408
1409 tp = netdev_priv(dev);
David Howellsc4028952006-11-22 14:57:56 +00001410 tp->dev = dev;
Francois Romieu890e8d02005-07-30 13:08:43 +02001411 tp->msg_enable = netif_msg_init(debug.msg_enable, SIS190_MSG_DEFAULT);
1412
1413 rc = pci_enable_device(pdev);
1414 if (rc < 0) {
1415 net_probe(tp, KERN_ERR "%s: enable failure\n", pci_name(pdev));
1416 goto err_free_dev_1;
1417 }
1418
1419 rc = -ENODEV;
1420
1421 if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
1422 net_probe(tp, KERN_ERR "%s: region #0 is no MMIO resource.\n",
1423 pci_name(pdev));
1424 goto err_pci_disable_2;
1425 }
1426 if (pci_resource_len(pdev, 0) < SIS190_REGS_SIZE) {
1427 net_probe(tp, KERN_ERR "%s: invalid PCI region size(s).\n",
1428 pci_name(pdev));
1429 goto err_pci_disable_2;
1430 }
1431
1432 rc = pci_request_regions(pdev, DRV_NAME);
1433 if (rc < 0) {
1434 net_probe(tp, KERN_ERR PFX "%s: could not request regions.\n",
1435 pci_name(pdev));
1436 goto err_pci_disable_2;
1437 }
1438
1439 rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
1440 if (rc < 0) {
1441 net_probe(tp, KERN_ERR "%s: DMA configuration failed.\n",
1442 pci_name(pdev));
1443 goto err_free_res_3;
1444 }
1445
1446 pci_set_master(pdev);
1447
1448 ioaddr = ioremap(pci_resource_start(pdev, 0), SIS190_REGS_SIZE);
1449 if (!ioaddr) {
1450 net_probe(tp, KERN_ERR "%s: cannot remap MMIO, aborting\n",
1451 pci_name(pdev));
1452 rc = -EIO;
1453 goto err_free_res_3;
1454 }
1455
1456 tp->pci_dev = pdev;
1457 tp->mmio_addr = ioaddr;
1458
1459 sis190_irq_mask_and_ack(ioaddr);
1460
1461 sis190_soft_reset(ioaddr);
1462out:
1463 return dev;
1464
1465err_free_res_3:
1466 pci_release_regions(pdev);
1467err_pci_disable_2:
1468 pci_disable_device(pdev);
1469err_free_dev_1:
1470 free_netdev(dev);
1471err_out_0:
1472 dev = ERR_PTR(rc);
1473 goto out;
1474}
1475
1476static void sis190_tx_timeout(struct net_device *dev)
1477{
1478 struct sis190_private *tp = netdev_priv(dev);
1479 void __iomem *ioaddr = tp->mmio_addr;
1480 u8 tmp8;
1481
1482 /* Disable Tx, if not already */
1483 tmp8 = SIS_R8(TxControl);
1484 if (tmp8 & CmdTxEnb)
1485 SIS_W8(TxControl, tmp8 & ~CmdTxEnb);
1486
Francois Romieu188f23b2005-07-30 13:11:43 +02001487
1488 net_tx_err(tp, KERN_INFO "%s: Transmit timeout, status %08x %08x.\n",
1489 dev->name, SIS_R32(TxControl), SIS_R32(TxSts));
1490
Francois Romieu890e8d02005-07-30 13:08:43 +02001491 /* Disable interrupts by clearing the interrupt mask. */
1492 SIS_W32(IntrMask, 0x0000);
1493
1494 /* Stop a shared interrupt from scavenging while we are. */
1495 spin_lock_irq(&tp->lock);
1496 sis190_tx_clear(tp);
1497 spin_unlock_irq(&tp->lock);
1498
1499 /* ...and finally, reset everything. */
1500 sis190_hw_start(dev);
1501
1502 netif_wake_queue(dev);
1503}
1504
Francois Romieu900eb9d2005-09-03 00:55:27 +02001505static void sis190_set_rgmii(struct sis190_private *tp, u8 reg)
1506{
1507 tp->features |= (reg & 0x80) ? F_HAS_RGMII : 0;
1508}
1509
Francois Romieu830fb7d2005-07-30 13:12:37 +02001510static int __devinit sis190_get_mac_addr_from_eeprom(struct pci_dev *pdev,
1511 struct net_device *dev)
1512{
1513 struct sis190_private *tp = netdev_priv(dev);
1514 void __iomem *ioaddr = tp->mmio_addr;
1515 u16 sig;
1516 int i;
1517
1518 net_probe(tp, KERN_INFO "%s: Read MAC address from EEPROM\n",
1519 pci_name(pdev));
1520
1521 /* Check to see if there is a sane EEPROM */
1522 sig = (u16) sis190_read_eeprom(ioaddr, EEPROMSignature);
1523
1524 if ((sig == 0xffff) || (sig == 0x0000)) {
1525 net_probe(tp, KERN_INFO "%s: Error EEPROM read %x.\n",
1526 pci_name(pdev), sig);
1527 return -EIO;
1528 }
1529
1530 /* Get MAC address from EEPROM */
1531 for (i = 0; i < MAC_ADDR_LEN / 2; i++) {
Al Viro961994a2007-12-15 01:44:33 +00001532 u16 w = sis190_read_eeprom(ioaddr, EEPROMMACAddr + i);
Francois Romieu830fb7d2005-07-30 13:12:37 +02001533
Al Viro961994a2007-12-15 01:44:33 +00001534 ((__le16 *)dev->dev_addr)[i] = cpu_to_le16(w);
Francois Romieu830fb7d2005-07-30 13:12:37 +02001535 }
1536
Francois Romieu900eb9d2005-09-03 00:55:27 +02001537 sis190_set_rgmii(tp, sis190_read_eeprom(ioaddr, EEPROMInfo));
1538
Francois Romieu830fb7d2005-07-30 13:12:37 +02001539 return 0;
1540}
1541
1542/**
Francois Romieuebc71642007-12-04 22:58:41 +01001543 * sis190_get_mac_addr_from_apc - Get MAC address for SiS96x model
Francois Romieu830fb7d2005-07-30 13:12:37 +02001544 * @pdev: PCI device
1545 * @dev: network device to get address for
1546 *
Francois Romieuebc71642007-12-04 22:58:41 +01001547 * SiS96x model, use APC CMOS RAM to store MAC address.
Francois Romieu830fb7d2005-07-30 13:12:37 +02001548 * APC CMOS RAM is accessed through ISA bridge.
1549 * MAC address is read into @net_dev->dev_addr.
1550 */
1551static int __devinit sis190_get_mac_addr_from_apc(struct pci_dev *pdev,
1552 struct net_device *dev)
1553{
Francois Romieuebc71642007-12-04 22:58:41 +01001554 static const u16 __devinitdata ids[] = { 0x0965, 0x0966, 0x0968 };
Francois Romieu830fb7d2005-07-30 13:12:37 +02001555 struct sis190_private *tp = netdev_priv(dev);
1556 struct pci_dev *isa_bridge;
1557 u8 reg, tmp8;
Francois Romieuebc71642007-12-04 22:58:41 +01001558 unsigned int i;
Francois Romieu830fb7d2005-07-30 13:12:37 +02001559
1560 net_probe(tp, KERN_INFO "%s: Read MAC address from APC.\n",
1561 pci_name(pdev));
1562
Francois Romieuebc71642007-12-04 22:58:41 +01001563 for (i = 0; i < ARRAY_SIZE(ids); i++) {
1564 isa_bridge = pci_get_device(PCI_VENDOR_ID_SI, ids[i], NULL);
1565 if (isa_bridge)
1566 break;
1567 }
Neil Muller8eb7ad62007-08-01 17:52:04 +02001568
Francois Romieu830fb7d2005-07-30 13:12:37 +02001569 if (!isa_bridge) {
1570 net_probe(tp, KERN_INFO "%s: Can not find ISA bridge.\n",
1571 pci_name(pdev));
1572 return -EIO;
1573 }
1574
1575 /* Enable port 78h & 79h to access APC Registers. */
1576 pci_read_config_byte(isa_bridge, 0x48, &tmp8);
1577 reg = (tmp8 & ~0x02);
1578 pci_write_config_byte(isa_bridge, 0x48, reg);
1579 udelay(50);
1580 pci_read_config_byte(isa_bridge, 0x48, &reg);
1581
1582 for (i = 0; i < MAC_ADDR_LEN; i++) {
1583 outb(0x9 + i, 0x78);
1584 dev->dev_addr[i] = inb(0x79);
1585 }
1586
1587 outb(0x12, 0x78);
1588 reg = inb(0x79);
1589
Francois Romieu900eb9d2005-09-03 00:55:27 +02001590 sis190_set_rgmii(tp, reg);
1591
Francois Romieu830fb7d2005-07-30 13:12:37 +02001592 /* Restore the value to ISA Bridge */
1593 pci_write_config_byte(isa_bridge, 0x48, tmp8);
1594 pci_dev_put(isa_bridge);
1595
1596 return 0;
1597}
1598
1599/**
1600 * sis190_init_rxfilter - Initialize the Rx filter
1601 * @dev: network device to initialize
1602 *
1603 * Set receive filter address to our MAC address
1604 * and enable packet filtering.
1605 */
1606static inline void sis190_init_rxfilter(struct net_device *dev)
1607{
1608 struct sis190_private *tp = netdev_priv(dev);
1609 void __iomem *ioaddr = tp->mmio_addr;
1610 u16 ctl;
1611 int i;
1612
1613 ctl = SIS_R16(RxMacControl);
1614 /*
1615 * Disable packet filtering before setting filter.
1616 * Note: SiS's driver writes 32 bits but RxMacControl is 16 bits
1617 * only and followed by RxMacAddr (6 bytes). Strange. -- FR
1618 */
1619 SIS_W16(RxMacControl, ctl & ~0x0f00);
1620
1621 for (i = 0; i < MAC_ADDR_LEN; i++)
1622 SIS_W8(RxMacAddr + i, dev->dev_addr[i]);
1623
1624 SIS_W16(RxMacControl, ctl);
1625 SIS_PCI_COMMIT();
1626}
1627
Sergio Luisd785ad72008-02-10 17:56:25 -03001628static int __devinit sis190_get_mac_addr(struct pci_dev *pdev,
1629 struct net_device *dev)
Francois Romieu830fb7d2005-07-30 13:12:37 +02001630{
Francois Romieu563e0ae2008-02-18 21:20:32 +01001631 int rc;
Francois Romieu830fb7d2005-07-30 13:12:37 +02001632
Francois Romieu563e0ae2008-02-18 21:20:32 +01001633 rc = sis190_get_mac_addr_from_eeprom(pdev, dev);
1634 if (rc < 0) {
1635 u8 reg;
Francois Romieu830fb7d2005-07-30 13:12:37 +02001636
Francois Romieu563e0ae2008-02-18 21:20:32 +01001637 pci_read_config_byte(pdev, 0x73, &reg);
1638
1639 if (reg & 0x00000001)
1640 rc = sis190_get_mac_addr_from_apc(pdev, dev);
1641 }
1642 return rc;
Francois Romieu830fb7d2005-07-30 13:12:37 +02001643}
1644
Francois Romieu890e8d02005-07-30 13:08:43 +02001645static void sis190_set_speed_auto(struct net_device *dev)
1646{
1647 struct sis190_private *tp = netdev_priv(dev);
1648 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu9ede1092005-07-30 13:14:38 +02001649 int phy_id = tp->mii_if.phy_id;
Francois Romieu890e8d02005-07-30 13:08:43 +02001650 int val;
1651
1652 net_link(tp, KERN_INFO "%s: Enabling Auto-negotiation.\n", dev->name);
1653
Francois Romieu9ede1092005-07-30 13:14:38 +02001654 val = mdio_read(ioaddr, phy_id, MII_ADVERTISE);
Francois Romieu890e8d02005-07-30 13:08:43 +02001655
1656 // Enable 10/100 Full/Half Mode, leave MII_ADVERTISE bit4:0
1657 // unchanged.
Francois Romieu9ede1092005-07-30 13:14:38 +02001658 mdio_write(ioaddr, phy_id, MII_ADVERTISE, (val & ADVERTISE_SLCT) |
Francois Romieu890e8d02005-07-30 13:08:43 +02001659 ADVERTISE_100FULL | ADVERTISE_10FULL |
1660 ADVERTISE_100HALF | ADVERTISE_10HALF);
1661
1662 // Enable 1000 Full Mode.
Francois Romieu9ede1092005-07-30 13:14:38 +02001663 mdio_write(ioaddr, phy_id, MII_CTRL1000, ADVERTISE_1000FULL);
Francois Romieu890e8d02005-07-30 13:08:43 +02001664
1665 // Enable auto-negotiation and restart auto-negotiation.
Francois Romieu9ede1092005-07-30 13:14:38 +02001666 mdio_write(ioaddr, phy_id, MII_BMCR,
Francois Romieu890e8d02005-07-30 13:08:43 +02001667 BMCR_ANENABLE | BMCR_ANRESTART | BMCR_RESET);
1668}
1669
Francois Romieu43afb942005-07-30 13:10:21 +02001670static int sis190_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
1671{
1672 struct sis190_private *tp = netdev_priv(dev);
1673
1674 return mii_ethtool_gset(&tp->mii_if, cmd);
1675}
1676
1677static int sis190_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
1678{
1679 struct sis190_private *tp = netdev_priv(dev);
1680
1681 return mii_ethtool_sset(&tp->mii_if, cmd);
1682}
1683
Francois Romieu890e8d02005-07-30 13:08:43 +02001684static void sis190_get_drvinfo(struct net_device *dev,
1685 struct ethtool_drvinfo *info)
1686{
1687 struct sis190_private *tp = netdev_priv(dev);
1688
1689 strcpy(info->driver, DRV_NAME);
1690 strcpy(info->version, DRV_VERSION);
1691 strcpy(info->bus_info, pci_name(tp->pci_dev));
1692}
1693
1694static int sis190_get_regs_len(struct net_device *dev)
1695{
1696 return SIS190_REGS_SIZE;
1697}
1698
1699static void sis190_get_regs(struct net_device *dev, struct ethtool_regs *regs,
1700 void *p)
1701{
1702 struct sis190_private *tp = netdev_priv(dev);
1703 unsigned long flags;
1704
1705 if (regs->len > SIS190_REGS_SIZE)
1706 regs->len = SIS190_REGS_SIZE;
1707
1708 spin_lock_irqsave(&tp->lock, flags);
1709 memcpy_fromio(p, tp->mmio_addr, regs->len);
1710 spin_unlock_irqrestore(&tp->lock, flags);
1711}
1712
Francois Romieu43afb942005-07-30 13:10:21 +02001713static int sis190_nway_reset(struct net_device *dev)
1714{
1715 struct sis190_private *tp = netdev_priv(dev);
1716
1717 return mii_nway_restart(&tp->mii_if);
1718}
1719
Francois Romieu890e8d02005-07-30 13:08:43 +02001720static u32 sis190_get_msglevel(struct net_device *dev)
1721{
1722 struct sis190_private *tp = netdev_priv(dev);
1723
1724 return tp->msg_enable;
1725}
1726
1727static void sis190_set_msglevel(struct net_device *dev, u32 value)
1728{
1729 struct sis190_private *tp = netdev_priv(dev);
1730
1731 tp->msg_enable = value;
1732}
1733
Jeff Garzik7282d492006-09-13 14:30:00 -04001734static const struct ethtool_ops sis190_ethtool_ops = {
Francois Romieu43afb942005-07-30 13:10:21 +02001735 .get_settings = sis190_get_settings,
1736 .set_settings = sis190_set_settings,
Francois Romieu890e8d02005-07-30 13:08:43 +02001737 .get_drvinfo = sis190_get_drvinfo,
1738 .get_regs_len = sis190_get_regs_len,
1739 .get_regs = sis190_get_regs,
1740 .get_link = ethtool_op_get_link,
1741 .get_msglevel = sis190_get_msglevel,
1742 .set_msglevel = sis190_set_msglevel,
Francois Romieu43afb942005-07-30 13:10:21 +02001743 .nway_reset = sis190_nway_reset,
Francois Romieu890e8d02005-07-30 13:08:43 +02001744};
1745
Francois Romieu43afb942005-07-30 13:10:21 +02001746static int sis190_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1747{
1748 struct sis190_private *tp = netdev_priv(dev);
1749
1750 return !netif_running(dev) ? -EINVAL :
1751 generic_mii_ioctl(&tp->mii_if, if_mii(ifr), cmd, NULL);
1752}
1753
Francois Romieu890e8d02005-07-30 13:08:43 +02001754static int __devinit sis190_init_one(struct pci_dev *pdev,
1755 const struct pci_device_id *ent)
1756{
1757 static int printed_version = 0;
1758 struct sis190_private *tp;
1759 struct net_device *dev;
1760 void __iomem *ioaddr;
Francois Romieu830fb7d2005-07-30 13:12:37 +02001761 int rc;
Joe Perches0795af52007-10-03 17:59:30 -07001762 DECLARE_MAC_BUF(mac);
Francois Romieu890e8d02005-07-30 13:08:43 +02001763
1764 if (!printed_version) {
1765 net_drv(&debug, KERN_INFO SIS190_DRIVER_NAME " loaded.\n");
1766 printed_version = 1;
1767 }
1768
1769 dev = sis190_init_board(pdev);
1770 if (IS_ERR(dev)) {
1771 rc = PTR_ERR(dev);
1772 goto out;
1773 }
1774
Francois Romieu10487fb2006-02-16 22:17:00 +01001775 pci_set_drvdata(pdev, dev);
1776
Francois Romieu890e8d02005-07-30 13:08:43 +02001777 tp = netdev_priv(dev);
1778 ioaddr = tp->mmio_addr;
1779
Francois Romieu830fb7d2005-07-30 13:12:37 +02001780 rc = sis190_get_mac_addr(pdev, dev);
1781 if (rc < 0)
1782 goto err_release_board;
Francois Romieu890e8d02005-07-30 13:08:43 +02001783
Francois Romieu830fb7d2005-07-30 13:12:37 +02001784 sis190_init_rxfilter(dev);
Francois Romieu890e8d02005-07-30 13:08:43 +02001785
David Howellsc4028952006-11-22 14:57:56 +00001786 INIT_WORK(&tp->phy_task, sis190_phy_task);
Francois Romieu890e8d02005-07-30 13:08:43 +02001787
1788 dev->open = sis190_open;
1789 dev->stop = sis190_close;
Francois Romieu43afb942005-07-30 13:10:21 +02001790 dev->do_ioctl = sis190_ioctl;
Francois Romieu890e8d02005-07-30 13:08:43 +02001791 dev->tx_timeout = sis190_tx_timeout;
1792 dev->watchdog_timeo = SIS190_TX_TIMEOUT;
1793 dev->hard_start_xmit = sis190_start_xmit;
Francois Romieu4405d3b2005-07-30 13:09:20 +02001794#ifdef CONFIG_NET_POLL_CONTROLLER
1795 dev->poll_controller = sis190_netpoll;
1796#endif
Francois Romieu890e8d02005-07-30 13:08:43 +02001797 dev->set_multicast_list = sis190_set_rx_mode;
1798 SET_ETHTOOL_OPS(dev, &sis190_ethtool_ops);
1799 dev->irq = pdev->irq;
1800 dev->base_addr = (unsigned long) 0xdead;
1801
1802 spin_lock_init(&tp->lock);
Francois Romieu890e8d02005-07-30 13:08:43 +02001803
Francois Romieufcb98212005-07-30 13:15:22 +02001804 rc = sis190_mii_probe(dev);
1805 if (rc < 0)
Francois Romieu3690b6c2005-08-26 00:30:37 +02001806 goto err_release_board;
1807
1808 rc = register_netdev(dev);
1809 if (rc < 0)
1810 goto err_remove_mii;
1811
Francois Romieu890e8d02005-07-30 13:08:43 +02001812 net_probe(tp, KERN_INFO "%s: %s at %p (IRQ: %d), "
Joe Perches0795af52007-10-03 17:59:30 -07001813 "%s\n",
1814 pci_name(pdev), sis_chip_info[ent->driver_data].name,
1815 ioaddr, dev->irq, print_mac(mac, dev->dev_addr));
Francois Romieu890e8d02005-07-30 13:08:43 +02001816
Francois Romieu900eb9d2005-09-03 00:55:27 +02001817 net_probe(tp, KERN_INFO "%s: %s mode.\n", dev->name,
1818 (tp->features & F_HAS_RGMII) ? "RGMII" : "GMII");
1819
Francois Romieu890e8d02005-07-30 13:08:43 +02001820 netif_carrier_off(dev);
1821
1822 sis190_set_speed_auto(dev);
1823out:
1824 return rc;
Francois Romieu830fb7d2005-07-30 13:12:37 +02001825
Francois Romieu3690b6c2005-08-26 00:30:37 +02001826err_remove_mii:
1827 sis190_mii_remove(dev);
Francois Romieu830fb7d2005-07-30 13:12:37 +02001828err_release_board:
1829 sis190_release_board(pdev);
1830 goto out;
Francois Romieu890e8d02005-07-30 13:08:43 +02001831}
1832
1833static void __devexit sis190_remove_one(struct pci_dev *pdev)
1834{
1835 struct net_device *dev = pci_get_drvdata(pdev);
1836
Francois Romieufcb98212005-07-30 13:15:22 +02001837 sis190_mii_remove(dev);
Francois Romieuc014f6c2007-02-15 23:37:29 +01001838 flush_scheduled_work();
Francois Romieu890e8d02005-07-30 13:08:43 +02001839 unregister_netdev(dev);
1840 sis190_release_board(pdev);
1841 pci_set_drvdata(pdev, NULL);
1842}
1843
1844static struct pci_driver sis190_pci_driver = {
1845 .name = DRV_NAME,
1846 .id_table = sis190_pci_tbl,
1847 .probe = sis190_init_one,
1848 .remove = __devexit_p(sis190_remove_one),
1849};
1850
1851static int __init sis190_init_module(void)
1852{
Jeff Garzik29917622006-08-19 17:48:59 -04001853 return pci_register_driver(&sis190_pci_driver);
Francois Romieu890e8d02005-07-30 13:08:43 +02001854}
1855
1856static void __exit sis190_cleanup_module(void)
1857{
1858 pci_unregister_driver(&sis190_pci_driver);
1859}
1860
1861module_init(sis190_init_module);
1862module_exit(sis190_cleanup_module);