blob: df92bcde9bcf24c2b7f523bdc0ea6b63706b043e [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*======================================================================
2
3 A PCMCIA ethernet driver for SMC91c92-based cards.
4
5 This driver supports Megahertz PCMCIA ethernet cards; and
6 Megahertz, Motorola, Ositech, and Psion Dacom ethernet/modem
7 multifunction cards.
8
9 Copyright (C) 1999 David A. Hinds -- dahinds@users.sourceforge.net
10
11 smc91c92_cs.c 1.122 2002/10/25 06:26:39
12
13 This driver contains code written by Donald Becker
14 (becker@scyld.com), Rowan Hughes (x-csrdh@jcu.edu.au),
15 David Hinds (dahinds@users.sourceforge.net), and Erik Stahlman
16 (erik@vt.edu). Donald wrote the SMC 91c92 code using parts of
17 Erik's SMC 91c94 driver. Rowan wrote a similar driver, and I've
18 incorporated some parts of his driver here. I (Dave) wrote most
19 of the PCMCIA glue code, and the Ositech support code. Kelly
20 Stephens (kstephen@holli.com) added support for the Motorola
21 Mariner, with help from Allen Brost.
22
23 This software may be used and distributed according to the terms of
24 the GNU General Public License, incorporated herein by reference.
25
26======================================================================*/
27
28#include <linux/module.h>
29#include <linux/kernel.h>
30#include <linux/init.h>
31#include <linux/slab.h>
32#include <linux/string.h>
33#include <linux/timer.h>
34#include <linux/interrupt.h>
35#include <linux/delay.h>
36#include <linux/crc32.h>
37#include <linux/netdevice.h>
38#include <linux/etherdevice.h>
39#include <linux/skbuff.h>
40#include <linux/if_arp.h>
41#include <linux/ioport.h>
42#include <linux/ethtool.h>
43#include <linux/mii.h>
Marcelo Feitoza Parisi4851d3a2005-07-15 10:00:41 -070044#include <linux/jiffies.h>
Jaswinder Singh Rajput75bf7582009-03-30 20:19:54 +053045#include <linux/firmware.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070046
Linus Torvalds1da177e2005-04-16 15:20:36 -070047#include <pcmcia/cs_types.h>
48#include <pcmcia/cs.h>
49#include <pcmcia/cistpl.h>
50#include <pcmcia/cisreg.h>
51#include <pcmcia/ciscode.h>
52#include <pcmcia/ds.h>
Dominik Brodowski50db3fd2006-01-15 10:05:19 +010053#include <pcmcia/ss.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070054
55#include <asm/io.h>
56#include <asm/system.h>
57#include <asm/uaccess.h>
58
Linus Torvalds1da177e2005-04-16 15:20:36 -070059/*====================================================================*/
60
Arjan van de Venf71e1302006-03-03 21:33:57 -050061static const char *if_names[] = { "auto", "10baseT", "10base2"};
Linus Torvalds1da177e2005-04-16 15:20:36 -070062
Jaswinder Singh Rajput75bf7582009-03-30 20:19:54 +053063/* Firmware name */
64#define FIRMWARE_NAME "ositech/Xilinx7OD.bin"
65
Linus Torvalds1da177e2005-04-16 15:20:36 -070066/* Module parameters */
67
68MODULE_DESCRIPTION("SMC 91c92 series PCMCIA ethernet driver");
69MODULE_LICENSE("GPL");
Jaswinder Singh Rajput75bf7582009-03-30 20:19:54 +053070MODULE_FIRMWARE(FIRMWARE_NAME);
Linus Torvalds1da177e2005-04-16 15:20:36 -070071
72#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0)
73
74/*
75 Transceiver/media type.
76 0 = auto
77 1 = 10baseT (and autoselect if #define AUTOSELECT),
78 2 = AUI/10base2,
79*/
80INT_MODULE_PARM(if_port, 0);
81
82#ifdef PCMCIA_DEBUG
83INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
84static const char *version =
Andy Gospodarekd5b20692006-09-11 17:39:18 -040085"smc91c92_cs.c 1.123 2006/11/09 Donald Becker, becker@scyld.com.\n";
Linus Torvalds1da177e2005-04-16 15:20:36 -070086#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
87#else
88#define DEBUG(n, args...)
89#endif
90
91#define DRV_NAME "smc91c92_cs"
Andy Gospodarekd5b20692006-09-11 17:39:18 -040092#define DRV_VERSION "1.123"
Linus Torvalds1da177e2005-04-16 15:20:36 -070093
94/*====================================================================*/
95
96/* Operational parameter that usually are not changed. */
97
98/* Time in jiffies before concluding Tx hung */
99#define TX_TIMEOUT ((400*HZ)/1000)
100
101/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
102#define INTR_WORK 4
103
104/* Times to check the check the chip before concluding that it doesn't
105 currently have room for another Tx packet. */
106#define MEMORY_WAIT_TIME 8
107
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108struct smc_private {
Dominik Brodowskifd238232006-03-05 10:45:09 +0100109 struct pcmcia_device *p_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110 spinlock_t lock;
111 u_short manfid;
112 u_short cardid;
Stephen Hemminger6fb72982009-03-20 19:36:09 +0000113
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114 dev_node_t node;
115 struct sk_buff *saved_skb;
116 int packets_waiting;
117 void __iomem *base;
118 u_short cfg;
119 struct timer_list media;
120 int watchdog, tx_err;
121 u_short media_status;
122 u_short fast_poll;
123 u_short link_status;
124 struct mii_if_info mii_if;
125 int duplex;
126 int rx_ovrn;
127};
128
129/* Special definitions for Megahertz multifunction cards */
130#define MEGAHERTZ_ISR 0x0380
131
132/* Special function registers for Motorola Mariner */
133#define MOT_LAN 0x0000
134#define MOT_UART 0x0020
135#define MOT_EEPROM 0x20
136
137#define MOT_NORMAL \
138(COR_LEVEL_REQ | COR_FUNC_ENA | COR_ADDR_DECODE | COR_IREQ_ENA)
139
140/* Special function registers for Ositech cards */
141#define OSITECH_AUI_CTL 0x0c
142#define OSITECH_PWRDOWN 0x0d
143#define OSITECH_RESET 0x0e
144#define OSITECH_ISR 0x0f
145#define OSITECH_AUI_PWR 0x0c
146#define OSITECH_RESET_ISR 0x0e
147
148#define OSI_AUI_PWR 0x40
149#define OSI_LAN_PWRDOWN 0x02
150#define OSI_MODEM_PWRDOWN 0x01
151#define OSI_LAN_RESET 0x02
152#define OSI_MODEM_RESET 0x01
153
154/* Symbolic constants for the SMC91c9* series chips, from Erik Stahlman. */
155#define BANK_SELECT 14 /* Window select register. */
156#define SMC_SELECT_BANK(x) { outw(x, ioaddr + BANK_SELECT); }
157
158/* Bank 0 registers. */
159#define TCR 0 /* transmit control register */
160#define TCR_CLEAR 0 /* do NOTHING */
161#define TCR_ENABLE 0x0001 /* if this is 1, we can transmit */
162#define TCR_PAD_EN 0x0080 /* pads short packets to 64 bytes */
163#define TCR_MONCSN 0x0400 /* Monitor Carrier. */
164#define TCR_FDUPLX 0x0800 /* Full duplex mode. */
165#define TCR_NORMAL TCR_ENABLE | TCR_PAD_EN
166
167#define EPH 2 /* Ethernet Protocol Handler report. */
168#define EPH_TX_SUC 0x0001
169#define EPH_SNGLCOL 0x0002
170#define EPH_MULCOL 0x0004
171#define EPH_LTX_MULT 0x0008
172#define EPH_16COL 0x0010
173#define EPH_SQET 0x0020
174#define EPH_LTX_BRD 0x0040
175#define EPH_TX_DEFR 0x0080
176#define EPH_LAT_COL 0x0200
177#define EPH_LOST_CAR 0x0400
178#define EPH_EXC_DEF 0x0800
179#define EPH_CTR_ROL 0x1000
180#define EPH_RX_OVRN 0x2000
181#define EPH_LINK_OK 0x4000
182#define EPH_TX_UNRN 0x8000
183#define MEMINFO 8 /* Memory Information Register */
184#define MEMCFG 10 /* Memory Configuration Register */
185
186/* Bank 1 registers. */
187#define CONFIG 0
188#define CFG_MII_SELECT 0x8000 /* 91C100 only */
189#define CFG_NO_WAIT 0x1000
190#define CFG_FULL_STEP 0x0400
191#define CFG_SET_SQLCH 0x0200
192#define CFG_AUI_SELECT 0x0100
193#define CFG_16BIT 0x0080
194#define CFG_DIS_LINK 0x0040
195#define CFG_STATIC 0x0030
196#define CFG_IRQ_SEL_1 0x0004
197#define CFG_IRQ_SEL_0 0x0002
198#define BASE_ADDR 2
199#define ADDR0 4
200#define GENERAL 10
201#define CONTROL 12
202#define CTL_STORE 0x0001
203#define CTL_RELOAD 0x0002
204#define CTL_EE_SELECT 0x0004
205#define CTL_TE_ENABLE 0x0020
206#define CTL_CR_ENABLE 0x0040
207#define CTL_LE_ENABLE 0x0080
208#define CTL_AUTO_RELEASE 0x0800
209#define CTL_POWERDOWN 0x2000
210
211/* Bank 2 registers. */
212#define MMU_CMD 0
213#define MC_ALLOC 0x20 /* or with number of 256 byte packets */
214#define MC_RESET 0x40
215#define MC_RELEASE 0x80 /* remove and release the current rx packet */
216#define MC_FREEPKT 0xA0 /* Release packet in PNR register */
217#define MC_ENQUEUE 0xC0 /* Enqueue the packet for transmit */
218#define PNR_ARR 2
219#define FIFO_PORTS 4
220#define FP_RXEMPTY 0x8000
221#define POINTER 6
222#define PTR_AUTO_INC 0x0040
223#define PTR_READ 0x2000
224#define PTR_AUTOINC 0x4000
225#define PTR_RCV 0x8000
226#define DATA_1 8
227#define INTERRUPT 12
228#define IM_RCV_INT 0x1
229#define IM_TX_INT 0x2
230#define IM_TX_EMPTY_INT 0x4
231#define IM_ALLOC_INT 0x8
232#define IM_RX_OVRN_INT 0x10
233#define IM_EPH_INT 0x20
234
235#define RCR 4
236enum RxCfg { RxAllMulti = 0x0004, RxPromisc = 0x0002,
237 RxEnable = 0x0100, RxStripCRC = 0x0200};
238#define RCR_SOFTRESET 0x8000 /* resets the chip */
239#define RCR_STRIP_CRC 0x200 /* strips CRC */
240#define RCR_ENABLE 0x100 /* IFF this is set, we can receive packets */
241#define RCR_ALMUL 0x4 /* receive all multicast packets */
242#define RCR_PROMISC 0x2 /* enable promiscuous mode */
243
244/* the normal settings for the RCR register : */
245#define RCR_NORMAL (RCR_STRIP_CRC | RCR_ENABLE)
246#define RCR_CLEAR 0x0 /* set it to a base state */
247#define COUNTER 6
248
249/* BANK 3 -- not the same values as in smc9194! */
250#define MULTICAST0 0
251#define MULTICAST2 2
252#define MULTICAST4 4
253#define MULTICAST6 6
254#define MGMT 8
255#define REVISION 0x0a
256
257/* Transmit status bits. */
258#define TS_SUCCESS 0x0001
259#define TS_16COL 0x0010
260#define TS_LATCOL 0x0200
261#define TS_LOSTCAR 0x0400
262
263/* Receive status bits. */
264#define RS_ALGNERR 0x8000
265#define RS_BADCRC 0x2000
266#define RS_ODDFRAME 0x1000
267#define RS_TOOLONG 0x0800
268#define RS_TOOSHORT 0x0400
269#define RS_MULTICAST 0x0001
270#define RS_ERRORS (RS_ALGNERR | RS_BADCRC | RS_TOOLONG | RS_TOOSHORT)
271
272#define set_bits(v, p) outw(inw(p)|(v), (p))
273#define mask_bits(v, p) outw(inw(p)&(v), (p))
274
275/*====================================================================*/
276
Dominik Brodowskicc3b4862005-11-14 21:23:14 +0100277static void smc91c92_detach(struct pcmcia_device *p_dev);
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200278static int smc91c92_config(struct pcmcia_device *link);
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200279static void smc91c92_release(struct pcmcia_device *link);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280
281static int smc_open(struct net_device *dev);
282static int smc_close(struct net_device *dev);
283static int smc_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
284static void smc_tx_timeout(struct net_device *dev);
Stephen Hemmingerdbf02fa2009-08-31 19:50:49 +0000285static netdev_tx_t smc_start_xmit(struct sk_buff *skb,
286 struct net_device *dev);
David Howells7d12e782006-10-05 14:55:46 +0100287static irqreturn_t smc_interrupt(int irq, void *dev_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288static void smc_rx(struct net_device *dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289static void set_rx_mode(struct net_device *dev);
290static int s9k_config(struct net_device *dev, struct ifmap *map);
291static void smc_set_xcvr(struct net_device *dev, int if_port);
292static void smc_reset(struct net_device *dev);
293static void media_check(u_long arg);
Olof Johansson906da802008-02-04 22:27:35 -0800294static void mdio_sync(unsigned int addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295static int mdio_read(struct net_device *dev, int phy_id, int loc);
296static void mdio_write(struct net_device *dev, int phy_id, int loc, int value);
297static int smc_link_ok(struct net_device *dev);
Jeff Garzik7282d492006-09-13 14:30:00 -0400298static const struct ethtool_ops ethtool_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299
Stephen Hemminger9b31b692009-03-20 19:36:10 +0000300static const struct net_device_ops smc_netdev_ops = {
301 .ndo_open = smc_open,
302 .ndo_stop = smc_close,
303 .ndo_start_xmit = smc_start_xmit,
304 .ndo_tx_timeout = smc_tx_timeout,
305 .ndo_set_config = s9k_config,
306 .ndo_set_multicast_list = set_rx_mode,
307 .ndo_do_ioctl = &smc_ioctl,
308 .ndo_change_mtu = eth_change_mtu,
309 .ndo_set_mac_address = eth_mac_addr,
310 .ndo_validate_addr = eth_validate_addr,
311};
312
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313/*======================================================================
314
315 smc91c92_attach() creates an "instance" of the driver, allocating
316 local data structures for one device. The device is registered
317 with Card Services.
318
319======================================================================*/
320
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200321static int smc91c92_probe(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323 struct smc_private *smc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324 struct net_device *dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325
326 DEBUG(0, "smc91c92_attach()\n");
327
328 /* Create new ethernet device */
329 dev = alloc_etherdev(sizeof(struct smc_private));
330 if (!dev)
Dominik Brodowskif8cfa612005-11-14 21:25:51 +0100331 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332 smc = netdev_priv(dev);
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200333 smc->p_dev = link;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334 link->priv = dev;
335
336 spin_lock_init(&smc->lock);
337 link->io.NumPorts1 = 16;
338 link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
339 link->io.IOAddrLines = 4;
Komuro5e7bf8c2007-10-28 11:26:17 +0900340 link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_HANDLE_PRESENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341 link->irq.IRQInfo1 = IRQ_LEVEL_ID;
342 link->irq.Handler = &smc_interrupt;
343 link->irq.Instance = dev;
344 link->conf.Attributes = CONF_ENABLE_IRQ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345 link->conf.IntType = INT_MEMORY_AND_IO;
346
347 /* The SMC91c92-specific entries in the device structure. */
Stephen Hemminger9b31b692009-03-20 19:36:10 +0000348 dev->netdev_ops = &smc_netdev_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349 SET_ETHTOOL_OPS(dev, &ethtool_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350 dev->watchdog_timeo = TX_TIMEOUT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351
352 smc->mii_if.dev = dev;
353 smc->mii_if.mdio_read = mdio_read;
354 smc->mii_if.mdio_write = mdio_write;
355 smc->mii_if.phy_id_mask = 0x1f;
356 smc->mii_if.reg_num_mask = 0x1f;
357
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200358 return smc91c92_config(link);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359} /* smc91c92_attach */
360
361/*======================================================================
362
363 This deletes a driver "instance". The device is de-registered
364 with Card Services. If it has been released, all local data
365 structures are freed. Otherwise, the structures will be freed
366 when the device is released.
367
368======================================================================*/
369
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200370static void smc91c92_detach(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371{
372 struct net_device *dev = link->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373
374 DEBUG(0, "smc91c92_detach(0x%p)\n", link);
375
Dominik Brodowskifd238232006-03-05 10:45:09 +0100376 if (link->dev_node)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377 unregister_netdev(dev);
378
Dominik Brodowskie2d40962006-03-02 00:09:29 +0100379 smc91c92_release(link);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381 free_netdev(dev);
382} /* smc91c92_detach */
383
384/*====================================================================*/
385
386static int cvt_ascii_address(struct net_device *dev, char *s)
387{
388 int i, j, da, c;
389
390 if (strlen(s) != 12)
391 return -1;
392 for (i = 0; i < 6; i++) {
393 da = 0;
394 for (j = 0; j < 2; j++) {
395 c = *s++;
396 da <<= 4;
397 da += ((c >= '0') && (c <= '9')) ?
398 (c - '0') : ((c & 0x0f) + 9);
399 }
400 dev->dev_addr[i] = da;
401 }
402 return 0;
403}
404
Dominik Brodowskidddfbd82009-10-18 23:54:24 +0200405/*====================================================================
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406
407 Configuration stuff for Megahertz cards
408
409 mhz_3288_power() is used to power up a 3288's ethernet chip.
410 mhz_mfc_config() handles socket setup for multifunction (1144
411 and 3288) cards. mhz_setup() gets a card's hardware ethernet
412 address.
413
414======================================================================*/
415
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200416static int mhz_3288_power(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417{
418 struct net_device *dev = link->priv;
419 struct smc_private *smc = netdev_priv(dev);
420 u_char tmp;
421
422 /* Read the ISR twice... */
423 readb(smc->base+MEGAHERTZ_ISR);
424 udelay(5);
425 readb(smc->base+MEGAHERTZ_ISR);
426
427 /* Pause 200ms... */
428 mdelay(200);
429
430 /* Now read and write the COR... */
431 tmp = readb(smc->base + link->conf.ConfigBase + CISREG_COR);
432 udelay(5);
433 writeb(tmp, smc->base + link->conf.ConfigBase + CISREG_COR);
434
435 return 0;
436}
437
Dominik Brodowskib54bf942008-08-02 14:28:43 +0200438static int mhz_mfc_config_check(struct pcmcia_device *p_dev,
439 cistpl_cftable_entry_t *cf,
Dominik Brodowski8e2fc392008-08-02 15:30:31 +0200440 cistpl_cftable_entry_t *dflt,
Dominik Brodowskiad913c12008-08-02 16:12:00 +0200441 unsigned int vcc,
Dominik Brodowskib54bf942008-08-02 14:28:43 +0200442 void *priv_data)
443{
444 int k;
Dominik Brodowskib54bf942008-08-02 14:28:43 +0200445 p_dev->io.BasePort2 = cf->io.win[0].base;
446 for (k = 0; k < 0x400; k += 0x10) {
447 if (k & 0x80)
448 continue;
449 p_dev->io.BasePort1 = k ^ 0x300;
450 if (!pcmcia_request_io(p_dev, &p_dev->io))
451 return 0;
452 }
453 return -ENODEV;
454}
455
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200456static int mhz_mfc_config(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457{
458 struct net_device *dev = link->priv;
459 struct smc_private *smc = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460 win_req_t req;
461 memreq_t mem;
Dominik Brodowskib54bf942008-08-02 14:28:43 +0200462 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463
464 link->conf.Attributes |= CONF_ENABLE_SPKR;
465 link->conf.Status = CCSR_AUDIO_ENA;
466 link->irq.Attributes =
467 IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED|IRQ_HANDLE_PRESENT;
468 link->io.IOAddrLines = 16;
469 link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
470 link->io.NumPorts2 = 8;
471
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472 /* The Megahertz combo cards have modem-like CIS entries, so
473 we have to explicitly try a bunch of port combinations. */
Dominik Brodowskib54bf942008-08-02 14:28:43 +0200474 if (pcmcia_loop_config(link, mhz_mfc_config_check, NULL))
Dominik Brodowskidddfbd82009-10-18 23:54:24 +0200475 return -ENODEV;
476
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477 dev->base_addr = link->io.BasePort1;
478
479 /* Allocate a memory window, for accessing the ISR */
480 req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
481 req.Base = req.Size = 0;
482 req.AccessSpeed = 0;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200483 i = pcmcia_request_window(&link, &req, &link->win);
Dominik Brodowski4c89e882008-08-03 10:07:45 +0200484 if (i != 0)
Dominik Brodowskidddfbd82009-10-18 23:54:24 +0200485 return -ENODEV;
486
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487 smc->base = ioremap(req.Base, req.Size);
488 mem.CardOffset = mem.Page = 0;
489 if (smc->manfid == MANFID_MOTOROLA)
490 mem.CardOffset = link->conf.ConfigBase;
491 i = pcmcia_map_mem_page(link->win, &mem);
492
Dominik Brodowski4c89e882008-08-03 10:07:45 +0200493 if ((i == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494 && (smc->manfid == MANFID_MEGAHERTZ)
495 && (smc->cardid == PRODID_MEGAHERTZ_EM3288))
496 mhz_3288_power(link);
497
Dominik Brodowskidddfbd82009-10-18 23:54:24 +0200498 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499}
500
Dominik Brodowskidddfbd82009-10-18 23:54:24 +0200501static int pcmcia_get_versmac(struct pcmcia_device *p_dev,
502 tuple_t *tuple,
503 void *priv)
504{
505 struct net_device *dev = priv;
506 cisparse_t parse;
507
508 if (pcmcia_parse_tuple(tuple, &parse))
509 return -EINVAL;
510
511 if ((parse.version_1.ns > 3) &&
512 (cvt_ascii_address(dev,
513 (parse.version_1.str + parse.version_1.ofs[3]))))
514 return 0;
515
516 return -EINVAL;
517};
518
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200519static int mhz_setup(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521 struct net_device *dev = link->priv;
Dominik Brodowskidddfbd82009-10-18 23:54:24 +0200522 size_t len;
523 u8 *buf;
Yum Rayan4638aef42005-05-05 15:14:10 -0700524 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525
Dominik Brodowski7d2e8d02009-10-18 18:22:32 +0200526 /* Read the station address from the CIS. It is stored as the last
527 (fourth) string in the Version 1 Version/ID tuple. */
528 if ((link->prod_id[3]) &&
529 (cvt_ascii_address(dev, link->prod_id[3]) == 0))
530 return 0;
531
532 /* Workarounds for broken cards start here. */
Dominik Brodowski7d2e8d02009-10-18 18:22:32 +0200533 /* Ugh -- the EM1144 card has two VERS_1 tuples!?! */
Dominik Brodowskidddfbd82009-10-18 23:54:24 +0200534 if (!pcmcia_loop_tuple(link, CISTPL_VERS_1, pcmcia_get_versmac, dev))
535 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536
537 /* Another possibility: for the EM3288, in a special tuple */
Yum Rayan4638aef42005-05-05 15:14:10 -0700538 rc = -1;
Dominik Brodowskidddfbd82009-10-18 23:54:24 +0200539 len = pcmcia_get_tuple(link, 0x81, &buf);
540 if (buf && len >= 13) {
541 buf[12] = '\0';
542 if (cvt_ascii_address(dev, buf))
543 rc = 0;
544 }
545 kfree(buf);
546
547 return rc;
548};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549
550/*======================================================================
551
552 Configuration stuff for the Motorola Mariner
553
554 mot_config() writes directly to the Mariner configuration
555 registers because the CIS is just bogus.
556
557======================================================================*/
558
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200559static void mot_config(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560{
561 struct net_device *dev = link->priv;
562 struct smc_private *smc = netdev_priv(dev);
Olof Johansson906da802008-02-04 22:27:35 -0800563 unsigned int ioaddr = dev->base_addr;
564 unsigned int iouart = link->io.BasePort2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565
566 /* Set UART base address and force map with COR bit 1 */
567 writeb(iouart & 0xff, smc->base + MOT_UART + CISREG_IOBASE_0);
568 writeb((iouart >> 8) & 0xff, smc->base + MOT_UART + CISREG_IOBASE_1);
569 writeb(MOT_NORMAL, smc->base + MOT_UART + CISREG_COR);
570
571 /* Set SMC base address and force map with COR bit 1 */
572 writeb(ioaddr & 0xff, smc->base + MOT_LAN + CISREG_IOBASE_0);
573 writeb((ioaddr >> 8) & 0xff, smc->base + MOT_LAN + CISREG_IOBASE_1);
574 writeb(MOT_NORMAL, smc->base + MOT_LAN + CISREG_COR);
575
576 /* Wait for things to settle down */
577 mdelay(100);
578}
579
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200580static int mot_setup(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581{
582 struct net_device *dev = link->priv;
Olof Johansson906da802008-02-04 22:27:35 -0800583 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584 int i, wait, loop;
585 u_int addr;
586
587 /* Read Ethernet address from Serial EEPROM */
588
589 for (i = 0; i < 3; i++) {
590 SMC_SELECT_BANK(2);
591 outw(MOT_EEPROM + i, ioaddr + POINTER);
592 SMC_SELECT_BANK(1);
593 outw((CTL_RELOAD | CTL_EE_SELECT), ioaddr + CONTROL);
594
595 for (loop = wait = 0; loop < 200; loop++) {
596 udelay(10);
597 wait = ((CTL_RELOAD | CTL_STORE) & inw(ioaddr + CONTROL));
598 if (wait == 0) break;
599 }
600
601 if (wait)
602 return -1;
603
604 addr = inw(ioaddr + GENERAL);
605 dev->dev_addr[2*i] = addr & 0xff;
606 dev->dev_addr[2*i+1] = (addr >> 8) & 0xff;
607 }
608
609 return 0;
610}
611
612/*====================================================================*/
613
Dominik Brodowskib54bf942008-08-02 14:28:43 +0200614static int smc_configcheck(struct pcmcia_device *p_dev,
615 cistpl_cftable_entry_t *cf,
Dominik Brodowski8e2fc392008-08-02 15:30:31 +0200616 cistpl_cftable_entry_t *dflt,
Dominik Brodowskiad913c12008-08-02 16:12:00 +0200617 unsigned int vcc,
Dominik Brodowskib54bf942008-08-02 14:28:43 +0200618 void *priv_data)
619{
Dominik Brodowskib54bf942008-08-02 14:28:43 +0200620 p_dev->io.BasePort1 = cf->io.win[0].base;
621 p_dev->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
622 return pcmcia_request_io(p_dev, &p_dev->io);
623}
624
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200625static int smc_config(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626{
627 struct net_device *dev = link->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628 int i;
629
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630 link->io.NumPorts1 = 16;
Dominik Brodowskib54bf942008-08-02 14:28:43 +0200631 i = pcmcia_loop_config(link, smc_configcheck, NULL);
632 if (!i)
633 dev->base_addr = link->io.BasePort1;
Yum Rayan4638aef42005-05-05 15:14:10 -0700634
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635 return i;
636}
637
Dominik Brodowskidddfbd82009-10-18 23:54:24 +0200638
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200639static int smc_setup(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641 struct net_device *dev = link->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642
643 /* Check for a LAN function extension tuple */
Dominik Brodowskidddfbd82009-10-18 23:54:24 +0200644 if (!pcmcia_get_mac_from_cis(link, dev))
645 return 0;
646
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647 /* Try the third string in the Version 1 Version/ID tuple. */
Dominik Brodowskia9606fd2006-06-04 18:06:13 +0200648 if (link->prod_id[2]) {
Dominik Brodowskidddfbd82009-10-18 23:54:24 +0200649 if (cvt_ascii_address(dev, link->prod_id[2]) == 0)
650 return 0;
Yum Rayan4638aef42005-05-05 15:14:10 -0700651 }
Dominik Brodowskidddfbd82009-10-18 23:54:24 +0200652 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653}
654
655/*====================================================================*/
656
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200657static int osi_config(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658{
659 struct net_device *dev = link->priv;
Olof Johansson906da802008-02-04 22:27:35 -0800660 static const unsigned int com[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661 int i, j;
662
663 link->conf.Attributes |= CONF_ENABLE_SPKR;
664 link->conf.Status = CCSR_AUDIO_ENA;
665 link->irq.Attributes =
666 IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED|IRQ_HANDLE_PRESENT;
667 link->io.NumPorts1 = 64;
668 link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
669 link->io.NumPorts2 = 8;
670 link->io.IOAddrLines = 16;
671
672 /* Enable Hard Decode, LAN, Modem */
673 link->conf.ConfigIndex = 0x23;
674
675 for (i = j = 0; j < 4; j++) {
676 link->io.BasePort2 = com[j];
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200677 i = pcmcia_request_io(link, &link->io);
Dominik Brodowski4c89e882008-08-03 10:07:45 +0200678 if (i == 0)
679 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680 }
Dominik Brodowski4c89e882008-08-03 10:07:45 +0200681 if (i != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682 /* Fallback: turn off hard decode */
683 link->conf.ConfigIndex = 0x03;
684 link->io.NumPorts2 = 0;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200685 i = pcmcia_request_io(link, &link->io);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686 }
687 dev->base_addr = link->io.BasePort1 + 0x10;
688 return i;
689}
690
Jaswinder Singh Rajput75bf7582009-03-30 20:19:54 +0530691static int osi_load_firmware(struct pcmcia_device *link)
692{
693 const struct firmware *fw;
694 int i, err;
695
696 err = request_firmware(&fw, FIRMWARE_NAME, &link->dev);
697 if (err) {
698 pr_err("Failed to load firmware \"%s\"\n", FIRMWARE_NAME);
699 return err;
700 }
701
702 /* Download the Seven of Diamonds firmware */
703 for (i = 0; i < fw->size; i++) {
704 outb(fw->data[i], link->io.BasePort1 + 2);
705 udelay(50);
706 }
707 release_firmware(fw);
708 return err;
709}
710
Dominik Brodowskidddfbd82009-10-18 23:54:24 +0200711static int pcmcia_osi_mac(struct pcmcia_device *p_dev,
712 tuple_t *tuple,
713 void *priv)
714{
715 struct net_device *dev = priv;
716 int i;
717
718 if (tuple->TupleDataLen < 8)
719 return -EINVAL;
720 if (tuple->TupleData[0] != 0x04)
721 return -EINVAL;
722 for (i = 0; i < 6; i++)
723 dev->dev_addr[i] = tuple->TupleData[i+2];
724 return 0;
725};
726
727
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200728static int osi_setup(struct pcmcia_device *link, u_short manfid, u_short cardid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730 struct net_device *dev = link->priv;
Dominik Brodowskidddfbd82009-10-18 23:54:24 +0200731 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732
733 /* Read the station address from tuple 0x90, subtuple 0x04 */
Dominik Brodowskidddfbd82009-10-18 23:54:24 +0200734 if (pcmcia_loop_tuple(link, 0x90, pcmcia_osi_mac, dev))
735 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736
737 if (((manfid == MANFID_OSITECH) &&
738 (cardid == PRODID_OSITECH_SEVEN)) ||
739 ((manfid == MANFID_PSION) &&
740 (cardid == PRODID_PSION_NET100))) {
Jaswinder Singh Rajput75bf7582009-03-30 20:19:54 +0530741 rc = osi_load_firmware(link);
742 if (rc)
Dominik Brodowskidddfbd82009-10-18 23:54:24 +0200743 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744 } else if (manfid == MANFID_OSITECH) {
745 /* Make sure both functions are powered up */
746 set_bits(0x300, link->io.BasePort1 + OSITECH_AUI_PWR);
747 /* Now, turn on the interrupt for both card functions */
748 set_bits(0x300, link->io.BasePort1 + OSITECH_RESET_ISR);
749 DEBUG(2, "AUI/PWR: %4.4x RESET/ISR: %4.4x\n",
750 inw(link->io.BasePort1 + OSITECH_AUI_PWR),
751 inw(link->io.BasePort1 + OSITECH_RESET_ISR));
752 }
Dominik Brodowskidddfbd82009-10-18 23:54:24 +0200753 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754}
755
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200756static int smc91c92_suspend(struct pcmcia_device *link)
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100757{
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100758 struct net_device *dev = link->priv;
759
Dominik Brodowskie2d40962006-03-02 00:09:29 +0100760 if (link->open)
Dominik Brodowski4bbed522006-01-15 11:18:12 +0100761 netif_device_detach(dev);
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100762
763 return 0;
764}
765
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200766static int smc91c92_resume(struct pcmcia_device *link)
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100767{
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100768 struct net_device *dev = link->priv;
769 struct smc_private *smc = netdev_priv(dev);
770 int i;
771
Dominik Brodowskie2d40962006-03-02 00:09:29 +0100772 if ((smc->manfid == MANFID_MEGAHERTZ) &&
773 (smc->cardid == PRODID_MEGAHERTZ_EM3288))
774 mhz_3288_power(link);
775 if (smc->manfid == MANFID_MOTOROLA)
776 mot_config(link);
777 if ((smc->manfid == MANFID_OSITECH) &&
778 (smc->cardid != PRODID_OSITECH_SEVEN)) {
779 /* Power up the card and enable interrupts */
780 set_bits(0x0300, dev->base_addr-0x10+OSITECH_AUI_PWR);
781 set_bits(0x0300, dev->base_addr-0x10+OSITECH_RESET_ISR);
782 }
783 if (((smc->manfid == MANFID_OSITECH) &&
784 (smc->cardid == PRODID_OSITECH_SEVEN)) ||
785 ((smc->manfid == MANFID_PSION) &&
786 (smc->cardid == PRODID_PSION_NET100))) {
Jaswinder Singh Rajput75bf7582009-03-30 20:19:54 +0530787 i = osi_load_firmware(link);
788 if (i) {
789 pr_err("smc91c92_cs: Failed to load firmware\n");
790 return i;
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100791 }
Dominik Brodowskie2d40962006-03-02 00:09:29 +0100792 }
793 if (link->open) {
794 smc_reset(dev);
795 netif_device_attach(dev);
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100796 }
797
798 return 0;
799}
800
801
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802/*======================================================================
803
804 This verifies that the chip is some SMC91cXX variant, and returns
805 the revision code if successful. Otherwise, it returns -ENODEV.
806
807======================================================================*/
808
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200809static int check_sig(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810{
811 struct net_device *dev = link->priv;
Olof Johansson906da802008-02-04 22:27:35 -0800812 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813 int width;
814 u_short s;
815
816 SMC_SELECT_BANK(1);
817 if (inw(ioaddr + BANK_SELECT) >> 8 != 0x33) {
818 /* Try powering up the chip */
819 outw(0, ioaddr + CONTROL);
820 mdelay(55);
821 }
822
823 /* Try setting bus width */
824 width = (link->io.Attributes1 == IO_DATA_PATH_WIDTH_AUTO);
825 s = inb(ioaddr + CONFIG);
826 if (width)
827 s |= CFG_16BIT;
828 else
829 s &= ~CFG_16BIT;
830 outb(s, ioaddr + CONFIG);
831
832 /* Check Base Address Register to make sure bus width is OK */
833 s = inw(ioaddr + BASE_ADDR);
834 if ((inw(ioaddr + BANK_SELECT) >> 8 == 0x33) &&
835 ((s >> 8) != (s & 0xff))) {
836 SMC_SELECT_BANK(3);
837 s = inw(ioaddr + REVISION);
838 return (s & 0xff);
839 }
840
841 if (width) {
Dominik Brodowski4bbed522006-01-15 11:18:12 +0100842 modconf_t mod = {
843 .Attributes = CONF_IO_CHANGE_WIDTH,
844 };
845 printk(KERN_INFO "smc91c92_cs: using 8-bit IO window.\n");
Dominik Brodowski50db3fd2006-01-15 10:05:19 +0100846
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200847 smc91c92_suspend(link);
848 pcmcia_modify_configuration(link, &mod);
849 smc91c92_resume(link);
Dominik Brodowski4bbed522006-01-15 11:18:12 +0100850 return check_sig(link);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851 }
852 return -ENODEV;
853}
854
855/*======================================================================
856
857 smc91c92_config() is scheduled to run after a CARD_INSERTION event
858 is received, to configure the PCMCIA socket, and to make the
859 ethernet device available to the system.
860
861======================================================================*/
862
Dominik Brodowski4c89e882008-08-03 10:07:45 +0200863#define CS_EXIT_TEST(ret, svc, label) \
864if (ret != 0) { \
865 cs_error(link, svc, ret); \
866 goto label; \
867}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200869static int smc91c92_config(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871 struct net_device *dev = link->priv;
872 struct smc_private *smc = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873 char *name;
874 int i, j, rev;
Olof Johansson906da802008-02-04 22:27:35 -0800875 unsigned int ioaddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876 u_long mir;
877
878 DEBUG(0, "smc91c92_config(0x%p)\n", link);
879
Dominik Brodowskiefd50582006-10-25 21:28:53 -0400880 smc->manfid = link->manf_id;
881 smc->cardid = link->card_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883 if ((smc->manfid == MANFID_OSITECH) &&
884 (smc->cardid != PRODID_OSITECH_SEVEN)) {
885 i = osi_config(link);
886 } else if ((smc->manfid == MANFID_MOTOROLA) ||
887 ((smc->manfid == MANFID_MEGAHERTZ) &&
888 ((smc->cardid == PRODID_MEGAHERTZ_VARIOUS) ||
889 (smc->cardid == PRODID_MEGAHERTZ_EM3288)))) {
890 i = mhz_mfc_config(link);
891 } else {
892 i = smc_config(link);
893 }
894 CS_EXIT_TEST(i, RequestIO, config_failed);
895
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200896 i = pcmcia_request_irq(link, &link->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897 CS_EXIT_TEST(i, RequestIRQ, config_failed);
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200898 i = pcmcia_request_configuration(link, &link->conf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899 CS_EXIT_TEST(i, RequestConfiguration, config_failed);
900
901 if (smc->manfid == MANFID_MOTOROLA)
902 mot_config(link);
903
904 dev->irq = link->irq.AssignedIRQ;
905
906 if ((if_port >= 0) && (if_port <= 2))
907 dev->if_port = if_port;
908 else
909 printk(KERN_NOTICE "smc91c92_cs: invalid if_port requested\n");
910
911 switch (smc->manfid) {
912 case MANFID_OSITECH:
913 case MANFID_PSION:
914 i = osi_setup(link, smc->manfid, smc->cardid); break;
915 case MANFID_SMC:
916 case MANFID_NEW_MEDIA:
917 i = smc_setup(link); break;
918 case 0x128: /* For broken Megahertz cards */
919 case MANFID_MEGAHERTZ:
920 i = mhz_setup(link); break;
921 case MANFID_MOTOROLA:
922 default: /* get the hw address from EEPROM */
923 i = mot_setup(link); break;
924 }
925
926 if (i != 0) {
927 printk(KERN_NOTICE "smc91c92_cs: Unable to find hardware address.\n");
928 goto config_undo;
929 }
930
931 smc->duplex = 0;
932 smc->rx_ovrn = 0;
933
934 rev = check_sig(link);
935 name = "???";
936 if (rev > 0)
937 switch (rev >> 4) {
938 case 3: name = "92"; break;
939 case 4: name = ((rev & 15) >= 6) ? "96" : "94"; break;
940 case 5: name = "95"; break;
941 case 7: name = "100"; break;
942 case 8: name = "100-FD"; break;
943 case 9: name = "110"; break;
944 }
945
946 ioaddr = dev->base_addr;
947 if (rev > 0) {
948 u_long mcr;
949 SMC_SELECT_BANK(0);
950 mir = inw(ioaddr + MEMINFO) & 0xff;
951 if (mir == 0xff) mir++;
952 /* Get scale factor for memory size */
953 mcr = ((rev >> 4) > 3) ? inw(ioaddr + MEMCFG) : 0x0200;
954 mir *= 128 * (1<<((mcr >> 9) & 7));
955 SMC_SELECT_BANK(1);
956 smc->cfg = inw(ioaddr + CONFIG) & ~CFG_AUI_SELECT;
957 smc->cfg |= CFG_NO_WAIT | CFG_16BIT | CFG_STATIC;
958 if (smc->manfid == MANFID_OSITECH)
959 smc->cfg |= CFG_IRQ_SEL_1 | CFG_IRQ_SEL_0;
960 if ((rev >> 4) >= 7)
961 smc->cfg |= CFG_MII_SELECT;
962 } else
963 mir = 0;
964
965 if (smc->cfg & CFG_MII_SELECT) {
966 SMC_SELECT_BANK(3);
967
968 for (i = 0; i < 32; i++) {
969 j = mdio_read(dev, i, 1);
970 if ((j != 0) && (j != 0xffff)) break;
971 }
972 smc->mii_if.phy_id = (i < 32) ? i : -1;
973
974 SMC_SELECT_BANK(0);
975 }
976
Dominik Brodowskifd238232006-03-05 10:45:09 +0100977 link->dev_node = &smc->node;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200978 SET_NETDEV_DEV(dev, &handle_to_dev(link));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979
980 if (register_netdev(dev) != 0) {
981 printk(KERN_ERR "smc91c92_cs: register_netdev() failed\n");
Dominik Brodowskifd238232006-03-05 10:45:09 +0100982 link->dev_node = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983 goto config_undo;
984 }
985
986 strcpy(smc->node.dev_name, dev->name);
987
988 printk(KERN_INFO "%s: smc91c%s rev %d: io %#3lx, irq %d, "
Johannes Berge1749612008-10-27 15:59:26 -0700989 "hw_addr %pM\n",
Joe Perches0795af52007-10-03 17:59:30 -0700990 dev->name, name, (rev & 0x0f), dev->base_addr, dev->irq,
Johannes Berge1749612008-10-27 15:59:26 -0700991 dev->dev_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992
993 if (rev > 0) {
994 if (mir & 0x3ff)
995 printk(KERN_INFO " %lu byte", mir);
996 else
997 printk(KERN_INFO " %lu kb", mir>>10);
998 printk(" buffer, %s xcvr\n", (smc->cfg & CFG_MII_SELECT) ?
999 "MII" : if_names[dev->if_port]);
1000 }
1001
1002 if (smc->cfg & CFG_MII_SELECT) {
1003 if (smc->mii_if.phy_id != -1) {
1004 DEBUG(0, " MII transceiver at index %d, status %x.\n",
1005 smc->mii_if.phy_id, j);
1006 } else {
1007 printk(KERN_NOTICE " No MII transceivers found!\n");
1008 }
1009 }
Dominik Brodowski15b99ac2006-03-31 17:26:06 +02001010 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011
1012config_undo:
1013 unregister_netdev(dev);
1014config_failed: /* CS_EXIT_TEST() calls jump to here... */
1015 smc91c92_release(link);
Dominik Brodowski15b99ac2006-03-31 17:26:06 +02001016 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017} /* smc91c92_config */
1018
1019/*======================================================================
1020
1021 After a card is removed, smc91c92_release() will unregister the net
1022 device, and release the PCMCIA configuration. If the device is
1023 still open, this will be postponed until it is closed.
1024
1025======================================================================*/
1026
Dominik Brodowskifba395e2006-03-31 17:21:06 +02001027static void smc91c92_release(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028{
Dominik Brodowski5f2a71f2006-01-15 09:32:39 +01001029 DEBUG(0, "smc91c92_release(0x%p)\n", link);
1030 if (link->win) {
1031 struct net_device *dev = link->priv;
1032 struct smc_private *smc = netdev_priv(dev);
1033 iounmap(smc->base);
1034 }
Dominik Brodowskifba395e2006-03-31 17:21:06 +02001035 pcmcia_disable_device(link);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036}
1037
1038/*======================================================================
1039
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040 MII interface support for SMC91cXX based cards
1041======================================================================*/
1042
1043#define MDIO_SHIFT_CLK 0x04
1044#define MDIO_DATA_OUT 0x01
1045#define MDIO_DIR_WRITE 0x08
1046#define MDIO_DATA_WRITE0 (MDIO_DIR_WRITE)
1047#define MDIO_DATA_WRITE1 (MDIO_DIR_WRITE | MDIO_DATA_OUT)
1048#define MDIO_DATA_READ 0x02
1049
Olof Johansson906da802008-02-04 22:27:35 -08001050static void mdio_sync(unsigned int addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051{
1052 int bits;
1053 for (bits = 0; bits < 32; bits++) {
1054 outb(MDIO_DATA_WRITE1, addr);
1055 outb(MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, addr);
1056 }
1057}
1058
1059static int mdio_read(struct net_device *dev, int phy_id, int loc)
1060{
Olof Johansson906da802008-02-04 22:27:35 -08001061 unsigned int addr = dev->base_addr + MGMT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 u_int cmd = (0x06<<10)|(phy_id<<5)|loc;
1063 int i, retval = 0;
1064
1065 mdio_sync(addr);
1066 for (i = 13; i >= 0; i--) {
1067 int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
1068 outb(dat, addr);
1069 outb(dat | MDIO_SHIFT_CLK, addr);
1070 }
1071 for (i = 19; i > 0; i--) {
1072 outb(0, addr);
1073 retval = (retval << 1) | ((inb(addr) & MDIO_DATA_READ) != 0);
1074 outb(MDIO_SHIFT_CLK, addr);
1075 }
1076 return (retval>>1) & 0xffff;
1077}
1078
1079static void mdio_write(struct net_device *dev, int phy_id, int loc, int value)
1080{
Olof Johansson906da802008-02-04 22:27:35 -08001081 unsigned int addr = dev->base_addr + MGMT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082 u_int cmd = (0x05<<28)|(phy_id<<23)|(loc<<18)|(1<<17)|value;
1083 int i;
1084
1085 mdio_sync(addr);
1086 for (i = 31; i >= 0; i--) {
1087 int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
1088 outb(dat, addr);
1089 outb(dat | MDIO_SHIFT_CLK, addr);
1090 }
1091 for (i = 1; i >= 0; i--) {
1092 outb(0, addr);
1093 outb(MDIO_SHIFT_CLK, addr);
1094 }
1095}
1096
1097/*======================================================================
1098
1099 The driver core code, most of which should be common with a
1100 non-PCMCIA implementation.
1101
1102======================================================================*/
1103
1104#ifdef PCMCIA_DEBUG
1105static void smc_dump(struct net_device *dev)
1106{
Olof Johansson906da802008-02-04 22:27:35 -08001107 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108 u_short i, w, save;
1109 save = inw(ioaddr + BANK_SELECT);
1110 for (w = 0; w < 4; w++) {
1111 SMC_SELECT_BANK(w);
1112 printk(KERN_DEBUG "bank %d: ", w);
1113 for (i = 0; i < 14; i += 2)
1114 printk(" %04x", inw(ioaddr + i));
1115 printk("\n");
1116 }
1117 outw(save, ioaddr + BANK_SELECT);
1118}
1119#endif
1120
1121static int smc_open(struct net_device *dev)
1122{
1123 struct smc_private *smc = netdev_priv(dev);
Dominik Brodowskifba395e2006-03-31 17:21:06 +02001124 struct pcmcia_device *link = smc->p_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125
1126#ifdef PCMCIA_DEBUG
1127 DEBUG(0, "%s: smc_open(%p), ID/Window %4.4x.\n",
1128 dev->name, dev, inw(dev->base_addr + BANK_SELECT));
1129 if (pc_debug > 1) smc_dump(dev);
1130#endif
1131
1132 /* Check that the PCMCIA card is still here. */
Dominik Brodowski9940ec32006-03-05 11:04:33 +01001133 if (!pcmcia_dev_present(link))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134 return -ENODEV;
1135 /* Physical device present signature. */
1136 if (check_sig(link) < 0) {
1137 printk("smc91c92_cs: Yikes! Bad chip signature!\n");
1138 return -ENODEV;
1139 }
1140 link->open++;
1141
1142 netif_start_queue(dev);
1143 smc->saved_skb = NULL;
1144 smc->packets_waiting = 0;
1145
1146 smc_reset(dev);
1147 init_timer(&smc->media);
1148 smc->media.function = &media_check;
1149 smc->media.data = (u_long) dev;
1150 smc->media.expires = jiffies + HZ;
1151 add_timer(&smc->media);
1152
1153 return 0;
1154} /* smc_open */
1155
1156/*====================================================================*/
1157
1158static int smc_close(struct net_device *dev)
1159{
1160 struct smc_private *smc = netdev_priv(dev);
Dominik Brodowskifba395e2006-03-31 17:21:06 +02001161 struct pcmcia_device *link = smc->p_dev;
Olof Johansson906da802008-02-04 22:27:35 -08001162 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163
1164 DEBUG(0, "%s: smc_close(), status %4.4x.\n",
1165 dev->name, inw(ioaddr + BANK_SELECT));
1166
1167 netif_stop_queue(dev);
1168
1169 /* Shut off all interrupts, and turn off the Tx and Rx sections.
1170 Don't bother to check for chip present. */
1171 SMC_SELECT_BANK(2); /* Nominally paranoia, but do no assume... */
1172 outw(0, ioaddr + INTERRUPT);
1173 SMC_SELECT_BANK(0);
1174 mask_bits(0xff00, ioaddr + RCR);
1175 mask_bits(0xff00, ioaddr + TCR);
1176
1177 /* Put the chip into power-down mode. */
1178 SMC_SELECT_BANK(1);
1179 outw(CTL_POWERDOWN, ioaddr + CONTROL );
1180
1181 link->open--;
1182 del_timer_sync(&smc->media);
1183
1184 return 0;
1185} /* smc_close */
1186
1187/*======================================================================
1188
1189 Transfer a packet to the hardware and trigger the packet send.
1190 This may be called at either from either the Tx queue code
1191 or the interrupt handler.
1192
1193======================================================================*/
1194
1195static void smc_hardware_send_packet(struct net_device * dev)
1196{
1197 struct smc_private *smc = netdev_priv(dev);
1198 struct sk_buff *skb = smc->saved_skb;
Olof Johansson906da802008-02-04 22:27:35 -08001199 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200 u_char packet_no;
1201
1202 if (!skb) {
1203 printk(KERN_ERR "%s: In XMIT with no packet to send.\n", dev->name);
1204 return;
1205 }
1206
1207 /* There should be a packet slot waiting. */
1208 packet_no = inw(ioaddr + PNR_ARR) >> 8;
1209 if (packet_no & 0x80) {
1210 /* If not, there is a hardware problem! Likely an ejected card. */
1211 printk(KERN_WARNING "%s: 91c92 hardware Tx buffer allocation"
1212 " failed, status %#2.2x.\n", dev->name, packet_no);
1213 dev_kfree_skb_irq(skb);
1214 smc->saved_skb = NULL;
1215 netif_start_queue(dev);
1216 return;
1217 }
1218
Stephen Hemminger6fb72982009-03-20 19:36:09 +00001219 dev->stats.tx_bytes += skb->len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220 /* The card should use the just-allocated buffer. */
1221 outw(packet_no, ioaddr + PNR_ARR);
1222 /* point to the beginning of the packet */
1223 outw(PTR_AUTOINC , ioaddr + POINTER);
1224
1225 /* Send the packet length (+6 for status, length and ctl byte)
1226 and the status word (set to zeros). */
1227 {
1228 u_char *buf = skb->data;
1229 u_int length = skb->len; /* The chip will pad to ethernet min. */
1230
1231 DEBUG(2, "%s: Trying to xmit packet of length %d.\n",
1232 dev->name, length);
1233
1234 /* send the packet length: +6 for status word, length, and ctl */
1235 outw(0, ioaddr + DATA_1);
1236 outw(length + 6, ioaddr + DATA_1);
1237 outsw(ioaddr + DATA_1, buf, length >> 1);
1238
1239 /* The odd last byte, if there is one, goes in the control word. */
1240 outw((length & 1) ? 0x2000 | buf[length-1] : 0, ioaddr + DATA_1);
1241 }
1242
1243 /* Enable the Tx interrupts, both Tx (TxErr) and TxEmpty. */
1244 outw(((IM_TX_INT|IM_TX_EMPTY_INT)<<8) |
1245 (inw(ioaddr + INTERRUPT) & 0xff00),
1246 ioaddr + INTERRUPT);
1247
1248 /* The chip does the rest of the work. */
1249 outw(MC_ENQUEUE , ioaddr + MMU_CMD);
1250
1251 smc->saved_skb = NULL;
1252 dev_kfree_skb_irq(skb);
1253 dev->trans_start = jiffies;
1254 netif_start_queue(dev);
1255 return;
1256}
1257
1258/*====================================================================*/
1259
1260static void smc_tx_timeout(struct net_device *dev)
1261{
1262 struct smc_private *smc = netdev_priv(dev);
Olof Johansson906da802008-02-04 22:27:35 -08001263 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264
1265 printk(KERN_NOTICE "%s: SMC91c92 transmit timed out, "
1266 "Tx_status %2.2x status %4.4x.\n",
1267 dev->name, inw(ioaddr)&0xff, inw(ioaddr + 2));
Stephen Hemminger6fb72982009-03-20 19:36:09 +00001268 dev->stats.tx_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001269 smc_reset(dev);
1270 dev->trans_start = jiffies;
1271 smc->saved_skb = NULL;
1272 netif_wake_queue(dev);
1273}
1274
Stephen Hemmingerdbf02fa2009-08-31 19:50:49 +00001275static netdev_tx_t smc_start_xmit(struct sk_buff *skb,
1276 struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277{
1278 struct smc_private *smc = netdev_priv(dev);
Olof Johansson906da802008-02-04 22:27:35 -08001279 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280 u_short num_pages;
1281 short time_out, ir;
Komuro85e27832007-07-23 21:36:06 +09001282 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001283
1284 netif_stop_queue(dev);
1285
1286 DEBUG(2, "%s: smc_start_xmit(length = %d) called,"
1287 " status %4.4x.\n", dev->name, skb->len, inw(ioaddr + 2));
1288
1289 if (smc->saved_skb) {
1290 /* THIS SHOULD NEVER HAPPEN. */
Stephen Hemminger6fb72982009-03-20 19:36:09 +00001291 dev->stats.tx_aborted_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292 printk(KERN_DEBUG "%s: Internal error -- sent packet while busy.\n",
1293 dev->name);
Patrick McHardy5b548142009-06-12 06:22:29 +00001294 return NETDEV_TX_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295 }
1296 smc->saved_skb = skb;
1297
1298 num_pages = skb->len >> 8;
1299
1300 if (num_pages > 7) {
1301 printk(KERN_ERR "%s: Far too big packet error.\n", dev->name);
1302 dev_kfree_skb (skb);
1303 smc->saved_skb = NULL;
Stephen Hemminger6fb72982009-03-20 19:36:09 +00001304 dev->stats.tx_dropped++;
Patrick McHardy6ed10652009-06-23 06:03:08 +00001305 return NETDEV_TX_OK; /* Do not re-queue this packet. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306 }
1307 /* A packet is now waiting. */
1308 smc->packets_waiting++;
1309
Komuro85e27832007-07-23 21:36:06 +09001310 spin_lock_irqsave(&smc->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311 SMC_SELECT_BANK(2); /* Paranoia, we should always be in window 2 */
1312
1313 /* need MC_RESET to keep the memory consistent. errata? */
1314 if (smc->rx_ovrn) {
1315 outw(MC_RESET, ioaddr + MMU_CMD);
1316 smc->rx_ovrn = 0;
1317 }
1318
1319 /* Allocate the memory; send the packet now if we win. */
1320 outw(MC_ALLOC | num_pages, ioaddr + MMU_CMD);
1321 for (time_out = MEMORY_WAIT_TIME; time_out >= 0; time_out--) {
1322 ir = inw(ioaddr+INTERRUPT);
1323 if (ir & IM_ALLOC_INT) {
1324 /* Acknowledge the interrupt, send the packet. */
1325 outw((ir&0xff00) | IM_ALLOC_INT, ioaddr + INTERRUPT);
1326 smc_hardware_send_packet(dev); /* Send the packet now.. */
Komuro85e27832007-07-23 21:36:06 +09001327 spin_unlock_irqrestore(&smc->lock, flags);
Patrick McHardy6ed10652009-06-23 06:03:08 +00001328 return NETDEV_TX_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329 }
1330 }
1331
1332 /* Otherwise defer until the Tx-space-allocated interrupt. */
1333 DEBUG(2, "%s: memory allocation deferred.\n", dev->name);
1334 outw((IM_ALLOC_INT << 8) | (ir & 0xff00), ioaddr + INTERRUPT);
Komuro85e27832007-07-23 21:36:06 +09001335 spin_unlock_irqrestore(&smc->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336
Patrick McHardy6ed10652009-06-23 06:03:08 +00001337 return NETDEV_TX_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338}
1339
1340/*======================================================================
1341
1342 Handle a Tx anomolous event. Entered while in Window 2.
1343
1344======================================================================*/
1345
1346static void smc_tx_err(struct net_device * dev)
1347{
1348 struct smc_private *smc = netdev_priv(dev);
Olof Johansson906da802008-02-04 22:27:35 -08001349 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001350 int saved_packet = inw(ioaddr + PNR_ARR) & 0xff;
1351 int packet_no = inw(ioaddr + FIFO_PORTS) & 0x7f;
1352 int tx_status;
1353
1354 /* select this as the packet to read from */
1355 outw(packet_no, ioaddr + PNR_ARR);
1356
1357 /* read the first word from this packet */
1358 outw(PTR_AUTOINC | PTR_READ | 0, ioaddr + POINTER);
1359
1360 tx_status = inw(ioaddr + DATA_1);
1361
Stephen Hemminger6fb72982009-03-20 19:36:09 +00001362 dev->stats.tx_errors++;
1363 if (tx_status & TS_LOSTCAR) dev->stats.tx_carrier_errors++;
1364 if (tx_status & TS_LATCOL) dev->stats.tx_window_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365 if (tx_status & TS_16COL) {
Stephen Hemminger6fb72982009-03-20 19:36:09 +00001366 dev->stats.tx_aborted_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367 smc->tx_err++;
1368 }
1369
1370 if (tx_status & TS_SUCCESS) {
1371 printk(KERN_NOTICE "%s: Successful packet caused error "
1372 "interrupt?\n", dev->name);
1373 }
1374 /* re-enable transmit */
1375 SMC_SELECT_BANK(0);
1376 outw(inw(ioaddr + TCR) | TCR_ENABLE | smc->duplex, ioaddr + TCR);
1377 SMC_SELECT_BANK(2);
1378
1379 outw(MC_FREEPKT, ioaddr + MMU_CMD); /* Free the packet memory. */
1380
1381 /* one less packet waiting for me */
1382 smc->packets_waiting--;
1383
1384 outw(saved_packet, ioaddr + PNR_ARR);
1385 return;
1386}
1387
1388/*====================================================================*/
1389
1390static void smc_eph_irq(struct net_device *dev)
1391{
1392 struct smc_private *smc = netdev_priv(dev);
Olof Johansson906da802008-02-04 22:27:35 -08001393 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394 u_short card_stats, ephs;
1395
1396 SMC_SELECT_BANK(0);
1397 ephs = inw(ioaddr + EPH);
1398 DEBUG(2, "%s: Ethernet protocol handler interrupt, status"
1399 " %4.4x.\n", dev->name, ephs);
1400 /* Could be a counter roll-over warning: update stats. */
1401 card_stats = inw(ioaddr + COUNTER);
1402 /* single collisions */
Stephen Hemminger6fb72982009-03-20 19:36:09 +00001403 dev->stats.collisions += card_stats & 0xF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404 card_stats >>= 4;
1405 /* multiple collisions */
Stephen Hemminger6fb72982009-03-20 19:36:09 +00001406 dev->stats.collisions += card_stats & 0xF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407#if 0 /* These are for when linux supports these statistics */
1408 card_stats >>= 4; /* deferred */
1409 card_stats >>= 4; /* excess deferred */
1410#endif
1411 /* If we had a transmit error we must re-enable the transmitter. */
1412 outw(inw(ioaddr + TCR) | TCR_ENABLE | smc->duplex, ioaddr + TCR);
1413
1414 /* Clear a link error interrupt. */
1415 SMC_SELECT_BANK(1);
1416 outw(CTL_AUTO_RELEASE | 0x0000, ioaddr + CONTROL);
1417 outw(CTL_AUTO_RELEASE | CTL_TE_ENABLE | CTL_CR_ENABLE,
1418 ioaddr + CONTROL);
1419 SMC_SELECT_BANK(2);
1420}
1421
1422/*====================================================================*/
1423
David Howells7d12e782006-10-05 14:55:46 +01001424static irqreturn_t smc_interrupt(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425{
1426 struct net_device *dev = dev_id;
1427 struct smc_private *smc = netdev_priv(dev);
Olof Johansson906da802008-02-04 22:27:35 -08001428 unsigned int ioaddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429 u_short saved_bank, saved_pointer, mask, status;
1430 unsigned int handled = 1;
1431 char bogus_cnt = INTR_WORK; /* Work we are willing to do. */
1432
1433 if (!netif_device_present(dev))
1434 return IRQ_NONE;
1435
1436 ioaddr = dev->base_addr;
1437
1438 DEBUG(3, "%s: SMC91c92 interrupt %d at %#x.\n", dev->name,
1439 irq, ioaddr);
1440
Komuro85e27832007-07-23 21:36:06 +09001441 spin_lock(&smc->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001442 smc->watchdog = 0;
1443 saved_bank = inw(ioaddr + BANK_SELECT);
1444 if ((saved_bank & 0xff00) != 0x3300) {
1445 /* The device does not exist -- the card could be off-line, or
1446 maybe it has been ejected. */
1447 DEBUG(1, "%s: SMC91c92 interrupt %d for non-existent"
1448 "/ejected device.\n", dev->name, irq);
1449 handled = 0;
1450 goto irq_done;
1451 }
1452
1453 SMC_SELECT_BANK(2);
1454 saved_pointer = inw(ioaddr + POINTER);
1455 mask = inw(ioaddr + INTERRUPT) >> 8;
1456 /* clear all interrupts */
1457 outw(0, ioaddr + INTERRUPT);
1458
1459 do { /* read the status flag, and mask it */
1460 status = inw(ioaddr + INTERRUPT) & 0xff;
1461 DEBUG(3, "%s: Status is %#2.2x (mask %#2.2x).\n", dev->name,
1462 status, mask);
1463 if ((status & mask) == 0) {
1464 if (bogus_cnt == INTR_WORK)
1465 handled = 0;
1466 break;
1467 }
1468 if (status & IM_RCV_INT) {
1469 /* Got a packet(s). */
1470 smc_rx(dev);
1471 }
1472 if (status & IM_TX_INT) {
1473 smc_tx_err(dev);
1474 outw(IM_TX_INT, ioaddr + INTERRUPT);
1475 }
1476 status &= mask;
1477 if (status & IM_TX_EMPTY_INT) {
1478 outw(IM_TX_EMPTY_INT, ioaddr + INTERRUPT);
1479 mask &= ~IM_TX_EMPTY_INT;
Stephen Hemminger6fb72982009-03-20 19:36:09 +00001480 dev->stats.tx_packets += smc->packets_waiting;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481 smc->packets_waiting = 0;
1482 }
1483 if (status & IM_ALLOC_INT) {
1484 /* Clear this interrupt so it doesn't happen again */
1485 mask &= ~IM_ALLOC_INT;
1486
1487 smc_hardware_send_packet(dev);
1488
1489 /* enable xmit interrupts based on this */
1490 mask |= (IM_TX_EMPTY_INT | IM_TX_INT);
1491
1492 /* and let the card send more packets to me */
1493 netif_wake_queue(dev);
1494 }
1495 if (status & IM_RX_OVRN_INT) {
Stephen Hemminger6fb72982009-03-20 19:36:09 +00001496 dev->stats.rx_errors++;
1497 dev->stats.rx_fifo_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001498 if (smc->duplex)
1499 smc->rx_ovrn = 1; /* need MC_RESET outside smc_interrupt */
1500 outw(IM_RX_OVRN_INT, ioaddr + INTERRUPT);
1501 }
1502 if (status & IM_EPH_INT)
1503 smc_eph_irq(dev);
1504 } while (--bogus_cnt);
1505
1506 DEBUG(3, " Restoring saved registers mask %2.2x bank %4.4x"
1507 " pointer %4.4x.\n", mask, saved_bank, saved_pointer);
1508
1509 /* restore state register */
1510 outw((mask<<8), ioaddr + INTERRUPT);
1511 outw(saved_pointer, ioaddr + POINTER);
1512 SMC_SELECT_BANK(saved_bank);
1513
1514 DEBUG(3, "%s: Exiting interrupt IRQ%d.\n", dev->name, irq);
1515
1516irq_done:
1517
1518 if ((smc->manfid == MANFID_OSITECH) &&
1519 (smc->cardid != PRODID_OSITECH_SEVEN)) {
1520 /* Retrigger interrupt if needed */
1521 mask_bits(0x00ff, ioaddr-0x10+OSITECH_RESET_ISR);
1522 set_bits(0x0300, ioaddr-0x10+OSITECH_RESET_ISR);
1523 }
1524 if (smc->manfid == MANFID_MOTOROLA) {
1525 u_char cor;
1526 cor = readb(smc->base + MOT_UART + CISREG_COR);
1527 writeb(cor & ~COR_IREQ_ENA, smc->base + MOT_UART + CISREG_COR);
1528 writeb(cor, smc->base + MOT_UART + CISREG_COR);
1529 cor = readb(smc->base + MOT_LAN + CISREG_COR);
1530 writeb(cor & ~COR_IREQ_ENA, smc->base + MOT_LAN + CISREG_COR);
1531 writeb(cor, smc->base + MOT_LAN + CISREG_COR);
1532 }
1533#ifdef DOES_NOT_WORK
1534 if (smc->base != NULL) { /* Megahertz MFC's */
1535 readb(smc->base+MEGAHERTZ_ISR);
1536 readb(smc->base+MEGAHERTZ_ISR);
1537 }
1538#endif
Komuro85e27832007-07-23 21:36:06 +09001539 spin_unlock(&smc->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540 return IRQ_RETVAL(handled);
1541}
1542
1543/*====================================================================*/
1544
1545static void smc_rx(struct net_device *dev)
1546{
Olof Johansson906da802008-02-04 22:27:35 -08001547 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548 int rx_status;
1549 int packet_length; /* Caution: not frame length, rather words
1550 to transfer from the chip. */
1551
1552 /* Assertion: we are in Window 2. */
1553
1554 if (inw(ioaddr + FIFO_PORTS) & FP_RXEMPTY) {
1555 printk(KERN_ERR "%s: smc_rx() with nothing on Rx FIFO.\n",
1556 dev->name);
1557 return;
1558 }
1559
1560 /* Reset the read pointer, and read the status and packet length. */
1561 outw(PTR_READ | PTR_RCV | PTR_AUTOINC, ioaddr + POINTER);
1562 rx_status = inw(ioaddr + DATA_1);
1563 packet_length = inw(ioaddr + DATA_1) & 0x07ff;
1564
1565 DEBUG(2, "%s: Receive status %4.4x length %d.\n",
1566 dev->name, rx_status, packet_length);
1567
1568 if (!(rx_status & RS_ERRORS)) {
1569 /* do stuff to make a new packet */
1570 struct sk_buff *skb;
1571
1572 /* Note: packet_length adds 5 or 6 extra bytes here! */
1573 skb = dev_alloc_skb(packet_length+2);
1574
1575 if (skb == NULL) {
1576 DEBUG(1, "%s: Low memory, packet dropped.\n", dev->name);
Stephen Hemminger6fb72982009-03-20 19:36:09 +00001577 dev->stats.rx_dropped++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001578 outw(MC_RELEASE, ioaddr + MMU_CMD);
1579 return;
1580 }
1581
1582 packet_length -= (rx_status & RS_ODDFRAME ? 5 : 6);
1583 skb_reserve(skb, 2);
1584 insw(ioaddr+DATA_1, skb_put(skb, packet_length),
1585 (packet_length+1)>>1);
1586 skb->protocol = eth_type_trans(skb, dev);
1587
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588 netif_rx(skb);
1589 dev->last_rx = jiffies;
Stephen Hemminger6fb72982009-03-20 19:36:09 +00001590 dev->stats.rx_packets++;
1591 dev->stats.rx_bytes += packet_length;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592 if (rx_status & RS_MULTICAST)
Stephen Hemminger6fb72982009-03-20 19:36:09 +00001593 dev->stats.multicast++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001594 } else {
1595 /* error ... */
Stephen Hemminger6fb72982009-03-20 19:36:09 +00001596 dev->stats.rx_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001597
Stephen Hemminger6fb72982009-03-20 19:36:09 +00001598 if (rx_status & RS_ALGNERR) dev->stats.rx_frame_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001599 if (rx_status & (RS_TOOSHORT | RS_TOOLONG))
Stephen Hemminger6fb72982009-03-20 19:36:09 +00001600 dev->stats.rx_length_errors++;
1601 if (rx_status & RS_BADCRC) dev->stats.rx_crc_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602 }
1603 /* Let the MMU free the memory of this packet. */
1604 outw(MC_RELEASE, ioaddr + MMU_CMD);
1605
1606 return;
1607}
1608
Linus Torvalds1da177e2005-04-16 15:20:36 -07001609/*======================================================================
1610
1611 Calculate values for the hardware multicast filter hash table.
1612
1613======================================================================*/
1614
1615static void fill_multicast_tbl(int count, struct dev_mc_list *addrs,
1616 u_char *multicast_table)
1617{
1618 struct dev_mc_list *mc_addr;
1619
Komurobb53d6d2005-10-03 22:03:28 -04001620 for (mc_addr = addrs; mc_addr && count-- > 0; mc_addr = mc_addr->next) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001621 u_int position = ether_crc(6, mc_addr->dmi_addr);
1622#ifndef final_version /* Verify multicast address. */
1623 if ((mc_addr->dmi_addr[0] & 1) == 0)
1624 continue;
1625#endif
1626 multicast_table[position >> 29] |= 1 << ((position >> 26) & 7);
1627 }
1628}
1629
1630/*======================================================================
1631
1632 Set the receive mode.
1633
1634 This routine is used by both the protocol level to notify us of
1635 promiscuous/multicast mode changes, and by the open/reset code to
1636 initialize the Rx registers. We always set the multicast list and
1637 leave the receiver running.
1638
1639======================================================================*/
1640
1641static void set_rx_mode(struct net_device *dev)
1642{
Olof Johansson906da802008-02-04 22:27:35 -08001643 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644 struct smc_private *smc = netdev_priv(dev);
1645 u_int multicast_table[ 2 ] = { 0, };
1646 unsigned long flags;
1647 u_short rx_cfg_setting;
1648
1649 if (dev->flags & IFF_PROMISC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001650 rx_cfg_setting = RxStripCRC | RxEnable | RxPromisc | RxAllMulti;
1651 } else if (dev->flags & IFF_ALLMULTI)
1652 rx_cfg_setting = RxStripCRC | RxEnable | RxAllMulti;
1653 else {
1654 if (dev->mc_count) {
1655 fill_multicast_tbl(dev->mc_count, dev->mc_list,
1656 (u_char *)multicast_table);
1657 }
1658 rx_cfg_setting = RxStripCRC | RxEnable;
1659 }
1660
1661 /* Load MC table and Rx setting into the chip without interrupts. */
1662 spin_lock_irqsave(&smc->lock, flags);
1663 SMC_SELECT_BANK(3);
1664 outl(multicast_table[0], ioaddr + MULTICAST0);
1665 outl(multicast_table[1], ioaddr + MULTICAST4);
1666 SMC_SELECT_BANK(0);
1667 outw(rx_cfg_setting, ioaddr + RCR);
1668 SMC_SELECT_BANK(2);
1669 spin_unlock_irqrestore(&smc->lock, flags);
1670
1671 return;
1672}
1673
1674/*======================================================================
1675
1676 Senses when a card's config changes. Here, it's coax or TP.
1677
1678======================================================================*/
1679
1680static int s9k_config(struct net_device *dev, struct ifmap *map)
1681{
1682 struct smc_private *smc = netdev_priv(dev);
1683 if ((map->port != (u_char)(-1)) && (map->port != dev->if_port)) {
1684 if (smc->cfg & CFG_MII_SELECT)
1685 return -EOPNOTSUPP;
1686 else if (map->port > 2)
1687 return -EINVAL;
1688 dev->if_port = map->port;
1689 printk(KERN_INFO "%s: switched to %s port\n",
1690 dev->name, if_names[dev->if_port]);
1691 smc_reset(dev);
1692 }
1693 return 0;
1694}
1695
1696/*======================================================================
1697
1698 Reset the chip, reloading every register that might be corrupted.
1699
1700======================================================================*/
1701
1702/*
1703 Set transceiver type, perhaps to something other than what the user
1704 specified in dev->if_port.
1705*/
1706static void smc_set_xcvr(struct net_device *dev, int if_port)
1707{
1708 struct smc_private *smc = netdev_priv(dev);
Olof Johansson906da802008-02-04 22:27:35 -08001709 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710 u_short saved_bank;
1711
1712 saved_bank = inw(ioaddr + BANK_SELECT);
1713 SMC_SELECT_BANK(1);
1714 if (if_port == 2) {
1715 outw(smc->cfg | CFG_AUI_SELECT, ioaddr + CONFIG);
1716 if ((smc->manfid == MANFID_OSITECH) &&
1717 (smc->cardid != PRODID_OSITECH_SEVEN))
1718 set_bits(OSI_AUI_PWR, ioaddr - 0x10 + OSITECH_AUI_PWR);
1719 smc->media_status = ((dev->if_port == 0) ? 0x0001 : 0x0002);
1720 } else {
1721 outw(smc->cfg, ioaddr + CONFIG);
1722 if ((smc->manfid == MANFID_OSITECH) &&
1723 (smc->cardid != PRODID_OSITECH_SEVEN))
1724 mask_bits(~OSI_AUI_PWR, ioaddr - 0x10 + OSITECH_AUI_PWR);
1725 smc->media_status = ((dev->if_port == 0) ? 0x0012 : 0x4001);
1726 }
1727 SMC_SELECT_BANK(saved_bank);
1728}
1729
1730static void smc_reset(struct net_device *dev)
1731{
Olof Johansson906da802008-02-04 22:27:35 -08001732 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733 struct smc_private *smc = netdev_priv(dev);
1734 int i;
1735
1736 DEBUG(0, "%s: smc91c92 reset called.\n", dev->name);
1737
1738 /* The first interaction must be a write to bring the chip out
1739 of sleep mode. */
1740 SMC_SELECT_BANK(0);
1741 /* Reset the chip. */
1742 outw(RCR_SOFTRESET, ioaddr + RCR);
1743 udelay(10);
1744
1745 /* Clear the transmit and receive configuration registers. */
1746 outw(RCR_CLEAR, ioaddr + RCR);
1747 outw(TCR_CLEAR, ioaddr + TCR);
1748
1749 /* Set the Window 1 control, configuration and station addr registers.
1750 No point in writing the I/O base register ;-> */
1751 SMC_SELECT_BANK(1);
Andreas Mohrd6e05ed2006-06-26 18:35:02 +02001752 /* Automatically release successfully transmitted packets,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753 Accept link errors, counter and Tx error interrupts. */
1754 outw(CTL_AUTO_RELEASE | CTL_TE_ENABLE | CTL_CR_ENABLE,
1755 ioaddr + CONTROL);
1756 smc_set_xcvr(dev, dev->if_port);
1757 if ((smc->manfid == MANFID_OSITECH) &&
1758 (smc->cardid != PRODID_OSITECH_SEVEN))
1759 outw((dev->if_port == 2 ? OSI_AUI_PWR : 0) |
1760 (inw(ioaddr-0x10+OSITECH_AUI_PWR) & 0xff00),
1761 ioaddr - 0x10 + OSITECH_AUI_PWR);
1762
1763 /* Fill in the physical address. The databook is wrong about the order! */
1764 for (i = 0; i < 6; i += 2)
1765 outw((dev->dev_addr[i+1]<<8)+dev->dev_addr[i],
1766 ioaddr + ADDR0 + i);
1767
1768 /* Reset the MMU */
1769 SMC_SELECT_BANK(2);
1770 outw(MC_RESET, ioaddr + MMU_CMD);
1771 outw(0, ioaddr + INTERRUPT);
1772
1773 /* Re-enable the chip. */
1774 SMC_SELECT_BANK(0);
1775 outw(((smc->cfg & CFG_MII_SELECT) ? 0 : TCR_MONCSN) |
1776 TCR_ENABLE | TCR_PAD_EN | smc->duplex, ioaddr + TCR);
1777 set_rx_mode(dev);
1778
1779 if (smc->cfg & CFG_MII_SELECT) {
1780 SMC_SELECT_BANK(3);
1781
1782 /* Reset MII */
1783 mdio_write(dev, smc->mii_if.phy_id, 0, 0x8000);
1784
1785 /* Advertise 100F, 100H, 10F, 10H */
1786 mdio_write(dev, smc->mii_if.phy_id, 4, 0x01e1);
1787
1788 /* Restart MII autonegotiation */
1789 mdio_write(dev, smc->mii_if.phy_id, 0, 0x0000);
1790 mdio_write(dev, smc->mii_if.phy_id, 0, 0x1200);
1791 }
1792
1793 /* Enable interrupts. */
1794 SMC_SELECT_BANK(2);
1795 outw((IM_EPH_INT | IM_RX_OVRN_INT | IM_RCV_INT) << 8,
1796 ioaddr + INTERRUPT);
1797}
1798
1799/*======================================================================
1800
1801 Media selection timer routine
1802
1803======================================================================*/
1804
1805static void media_check(u_long arg)
1806{
1807 struct net_device *dev = (struct net_device *) arg;
1808 struct smc_private *smc = netdev_priv(dev);
Olof Johansson906da802008-02-04 22:27:35 -08001809 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001810 u_short i, media, saved_bank;
1811 u_short link;
Komuro85e27832007-07-23 21:36:06 +09001812 unsigned long flags;
1813
1814 spin_lock_irqsave(&smc->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001815
1816 saved_bank = inw(ioaddr + BANK_SELECT);
1817
1818 if (!netif_device_present(dev))
1819 goto reschedule;
1820
1821 SMC_SELECT_BANK(2);
1822
1823 /* need MC_RESET to keep the memory consistent. errata? */
1824 if (smc->rx_ovrn) {
1825 outw(MC_RESET, ioaddr + MMU_CMD);
1826 smc->rx_ovrn = 0;
1827 }
1828 i = inw(ioaddr + INTERRUPT);
1829 SMC_SELECT_BANK(0);
1830 media = inw(ioaddr + EPH) & EPH_LINK_OK;
1831 SMC_SELECT_BANK(1);
1832 media |= (inw(ioaddr + CONFIG) & CFG_AUI_SELECT) ? 2 : 1;
1833
1834 /* Check for pending interrupt with watchdog flag set: with
1835 this, we can limp along even if the interrupt is blocked */
1836 if (smc->watchdog++ && ((i>>8) & i)) {
1837 if (!smc->fast_poll)
1838 printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name);
Komuroe363d132007-02-10 11:57:35 +09001839 smc_interrupt(dev->irq, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001840 smc->fast_poll = HZ;
1841 }
1842 if (smc->fast_poll) {
1843 smc->fast_poll--;
1844 smc->media.expires = jiffies + HZ/100;
1845 add_timer(&smc->media);
1846 SMC_SELECT_BANK(saved_bank);
Komuro85e27832007-07-23 21:36:06 +09001847 spin_unlock_irqrestore(&smc->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001848 return;
1849 }
1850
1851 if (smc->cfg & CFG_MII_SELECT) {
1852 if (smc->mii_if.phy_id < 0)
1853 goto reschedule;
1854
1855 SMC_SELECT_BANK(3);
1856 link = mdio_read(dev, smc->mii_if.phy_id, 1);
1857 if (!link || (link == 0xffff)) {
1858 printk(KERN_INFO "%s: MII is missing!\n", dev->name);
1859 smc->mii_if.phy_id = -1;
1860 goto reschedule;
1861 }
1862
1863 link &= 0x0004;
1864 if (link != smc->link_status) {
1865 u_short p = mdio_read(dev, smc->mii_if.phy_id, 5);
1866 printk(KERN_INFO "%s: %s link beat\n", dev->name,
1867 (link) ? "found" : "lost");
1868 smc->duplex = (((p & 0x0100) || ((p & 0x1c0) == 0x40))
1869 ? TCR_FDUPLX : 0);
1870 if (link) {
1871 printk(KERN_INFO "%s: autonegotiation complete: "
1872 "%sbaseT-%cD selected\n", dev->name,
1873 ((p & 0x0180) ? "100" : "10"),
1874 (smc->duplex ? 'F' : 'H'));
1875 }
1876 SMC_SELECT_BANK(0);
1877 outw(inw(ioaddr + TCR) | smc->duplex, ioaddr + TCR);
1878 smc->link_status = link;
1879 }
1880 goto reschedule;
1881 }
1882
1883 /* Ignore collisions unless we've had no rx's recently */
Marcelo Feitoza Parisi4851d3a2005-07-15 10:00:41 -07001884 if (time_after(jiffies, dev->last_rx + HZ)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001885 if (smc->tx_err || (smc->media_status & EPH_16COL))
1886 media |= EPH_16COL;
1887 }
1888 smc->tx_err = 0;
1889
1890 if (media != smc->media_status) {
1891 if ((media & smc->media_status & 1) &&
1892 ((smc->media_status ^ media) & EPH_LINK_OK))
1893 printk(KERN_INFO "%s: %s link beat\n", dev->name,
1894 (smc->media_status & EPH_LINK_OK ? "lost" : "found"));
1895 else if ((media & smc->media_status & 2) &&
1896 ((smc->media_status ^ media) & EPH_16COL))
1897 printk(KERN_INFO "%s: coax cable %s\n", dev->name,
1898 (media & EPH_16COL ? "problem" : "ok"));
1899 if (dev->if_port == 0) {
1900 if (media & 1) {
1901 if (media & EPH_LINK_OK)
1902 printk(KERN_INFO "%s: flipped to 10baseT\n",
1903 dev->name);
1904 else
1905 smc_set_xcvr(dev, 2);
1906 } else {
1907 if (media & EPH_16COL)
1908 smc_set_xcvr(dev, 1);
1909 else
1910 printk(KERN_INFO "%s: flipped to 10base2\n",
1911 dev->name);
1912 }
1913 }
1914 smc->media_status = media;
1915 }
1916
1917reschedule:
1918 smc->media.expires = jiffies + HZ;
1919 add_timer(&smc->media);
1920 SMC_SELECT_BANK(saved_bank);
Komuro85e27832007-07-23 21:36:06 +09001921 spin_unlock_irqrestore(&smc->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001922}
1923
1924static int smc_link_ok(struct net_device *dev)
1925{
Olof Johansson906da802008-02-04 22:27:35 -08001926 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001927 struct smc_private *smc = netdev_priv(dev);
1928
1929 if (smc->cfg & CFG_MII_SELECT) {
1930 return mii_link_ok(&smc->mii_if);
1931 } else {
1932 SMC_SELECT_BANK(0);
1933 return inw(ioaddr + EPH) & EPH_LINK_OK;
1934 }
1935}
1936
1937static int smc_netdev_get_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd)
1938{
1939 u16 tmp;
Olof Johansson906da802008-02-04 22:27:35 -08001940 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001941
1942 ecmd->supported = (SUPPORTED_TP | SUPPORTED_AUI |
1943 SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full);
1944
1945 SMC_SELECT_BANK(1);
1946 tmp = inw(ioaddr + CONFIG);
1947 ecmd->port = (tmp & CFG_AUI_SELECT) ? PORT_AUI : PORT_TP;
1948 ecmd->transceiver = XCVR_INTERNAL;
1949 ecmd->speed = SPEED_10;
1950 ecmd->phy_address = ioaddr + MGMT;
1951
1952 SMC_SELECT_BANK(0);
1953 tmp = inw(ioaddr + TCR);
1954 ecmd->duplex = (tmp & TCR_FDUPLX) ? DUPLEX_FULL : DUPLEX_HALF;
1955
1956 return 0;
1957}
1958
1959static int smc_netdev_set_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd)
1960{
1961 u16 tmp;
Olof Johansson906da802008-02-04 22:27:35 -08001962 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001963
1964 if (ecmd->speed != SPEED_10)
1965 return -EINVAL;
1966 if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL)
1967 return -EINVAL;
1968 if (ecmd->port != PORT_TP && ecmd->port != PORT_AUI)
1969 return -EINVAL;
1970 if (ecmd->transceiver != XCVR_INTERNAL)
1971 return -EINVAL;
1972
1973 if (ecmd->port == PORT_AUI)
1974 smc_set_xcvr(dev, 1);
1975 else
1976 smc_set_xcvr(dev, 0);
1977
1978 SMC_SELECT_BANK(0);
1979 tmp = inw(ioaddr + TCR);
1980 if (ecmd->duplex == DUPLEX_FULL)
1981 tmp |= TCR_FDUPLX;
1982 else
1983 tmp &= ~TCR_FDUPLX;
1984 outw(tmp, ioaddr + TCR);
1985
1986 return 0;
1987}
1988
1989static int check_if_running(struct net_device *dev)
1990{
1991 if (!netif_running(dev))
1992 return -EINVAL;
1993 return 0;
1994}
1995
1996static void smc_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
1997{
1998 strcpy(info->driver, DRV_NAME);
1999 strcpy(info->version, DRV_VERSION);
2000}
2001
2002static int smc_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
2003{
2004 struct smc_private *smc = netdev_priv(dev);
Olof Johansson906da802008-02-04 22:27:35 -08002005 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002006 u16 saved_bank = inw(ioaddr + BANK_SELECT);
2007 int ret;
2008
Linus Torvalds1da177e2005-04-16 15:20:36 -07002009 spin_lock_irq(&smc->lock);
Komuro85e27832007-07-23 21:36:06 +09002010 SMC_SELECT_BANK(3);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002011 if (smc->cfg & CFG_MII_SELECT)
2012 ret = mii_ethtool_gset(&smc->mii_if, ecmd);
2013 else
2014 ret = smc_netdev_get_ecmd(dev, ecmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002015 SMC_SELECT_BANK(saved_bank);
Komuro85e27832007-07-23 21:36:06 +09002016 spin_unlock_irq(&smc->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002017 return ret;
2018}
2019
2020static int smc_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
2021{
2022 struct smc_private *smc = netdev_priv(dev);
Olof Johansson906da802008-02-04 22:27:35 -08002023 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002024 u16 saved_bank = inw(ioaddr + BANK_SELECT);
2025 int ret;
2026
Linus Torvalds1da177e2005-04-16 15:20:36 -07002027 spin_lock_irq(&smc->lock);
Komuro85e27832007-07-23 21:36:06 +09002028 SMC_SELECT_BANK(3);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002029 if (smc->cfg & CFG_MII_SELECT)
2030 ret = mii_ethtool_sset(&smc->mii_if, ecmd);
2031 else
2032 ret = smc_netdev_set_ecmd(dev, ecmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033 SMC_SELECT_BANK(saved_bank);
Komuro85e27832007-07-23 21:36:06 +09002034 spin_unlock_irq(&smc->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002035 return ret;
2036}
2037
2038static u32 smc_get_link(struct net_device *dev)
2039{
2040 struct smc_private *smc = netdev_priv(dev);
Olof Johansson906da802008-02-04 22:27:35 -08002041 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002042 u16 saved_bank = inw(ioaddr + BANK_SELECT);
2043 u32 ret;
2044
Linus Torvalds1da177e2005-04-16 15:20:36 -07002045 spin_lock_irq(&smc->lock);
Komuro85e27832007-07-23 21:36:06 +09002046 SMC_SELECT_BANK(3);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002047 ret = smc_link_ok(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002048 SMC_SELECT_BANK(saved_bank);
Komuro85e27832007-07-23 21:36:06 +09002049 spin_unlock_irq(&smc->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002050 return ret;
2051}
2052
2053#ifdef PCMCIA_DEBUG
2054static u32 smc_get_msglevel(struct net_device *dev)
2055{
2056 return pc_debug;
2057}
2058
2059static void smc_set_msglevel(struct net_device *dev, u32 val)
2060{
2061 pc_debug = val;
2062}
2063#endif
2064
2065static int smc_nway_reset(struct net_device *dev)
2066{
2067 struct smc_private *smc = netdev_priv(dev);
2068 if (smc->cfg & CFG_MII_SELECT) {
Olof Johansson906da802008-02-04 22:27:35 -08002069 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002070 u16 saved_bank = inw(ioaddr + BANK_SELECT);
2071 int res;
2072
2073 SMC_SELECT_BANK(3);
2074 res = mii_nway_restart(&smc->mii_if);
2075 SMC_SELECT_BANK(saved_bank);
2076
2077 return res;
2078 } else
2079 return -EOPNOTSUPP;
2080}
2081
Jeff Garzik7282d492006-09-13 14:30:00 -04002082static const struct ethtool_ops ethtool_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002083 .begin = check_if_running,
2084 .get_drvinfo = smc_get_drvinfo,
2085 .get_settings = smc_get_settings,
2086 .set_settings = smc_set_settings,
2087 .get_link = smc_get_link,
2088#ifdef PCMCIA_DEBUG
2089 .get_msglevel = smc_get_msglevel,
2090 .set_msglevel = smc_set_msglevel,
2091#endif
2092 .nway_reset = smc_nway_reset,
2093};
2094
2095static int smc_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
2096{
2097 struct smc_private *smc = netdev_priv(dev);
2098 struct mii_ioctl_data *mii = if_mii(rq);
2099 int rc = 0;
2100 u16 saved_bank;
Olof Johansson906da802008-02-04 22:27:35 -08002101 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002102
2103 if (!netif_running(dev))
2104 return -EINVAL;
2105
2106 spin_lock_irq(&smc->lock);
2107 saved_bank = inw(ioaddr + BANK_SELECT);
2108 SMC_SELECT_BANK(3);
2109 rc = generic_mii_ioctl(&smc->mii_if, mii, cmd, NULL);
2110 SMC_SELECT_BANK(saved_bank);
2111 spin_unlock_irq(&smc->lock);
2112 return rc;
2113}
2114
Dominik Brodowski5c672222005-06-27 16:28:27 -07002115static struct pcmcia_device_id smc91c92_ids[] = {
2116 PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0109, 0x0501),
2117 PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0140, 0x000a),
2118 PCMCIA_PFC_DEVICE_PROD_ID123(0, "MEGAHERTZ", "CC/XJEM3288", "DATA/FAX/CELL ETHERNET MODEM", 0xf510db04, 0x04cd2988, 0x46a52d63),
2119 PCMCIA_PFC_DEVICE_PROD_ID123(0, "MEGAHERTZ", "CC/XJEM3336", "DATA/FAX/CELL ETHERNET MODEM", 0xf510db04, 0x0143b773, 0x46a52d63),
2120 PCMCIA_PFC_DEVICE_PROD_ID123(0, "MEGAHERTZ", "EM1144T", "PCMCIA MODEM", 0xf510db04, 0x856d66c8, 0xbd6c43ef),
2121 PCMCIA_PFC_DEVICE_PROD_ID123(0, "MEGAHERTZ", "XJEM1144/CCEM1144", "PCMCIA MODEM", 0xf510db04, 0x52d21e1e, 0xbd6c43ef),
2122 PCMCIA_PFC_DEVICE_PROD_ID12(0, "Gateway 2000", "XJEM3336", 0xdd9989be, 0x662c394c),
2123 PCMCIA_PFC_DEVICE_PROD_ID12(0, "MEGAHERTZ", "XJEM1144/CCEM1144", 0xf510db04, 0x52d21e1e),
Komurod277ad02005-07-28 01:07:24 -07002124 PCMCIA_PFC_DEVICE_PROD_ID12(0, "Ositech", "Trumpcard:Jack of Diamonds Modem+Ethernet", 0xc2f80cd, 0x656947b9),
2125 PCMCIA_PFC_DEVICE_PROD_ID12(0, "Ositech", "Trumpcard:Jack of Hearts Modem+Ethernet", 0xc2f80cd, 0xdc9ba5ed),
Dominik Brodowski5c672222005-06-27 16:28:27 -07002126 PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x016c, 0x0020),
2127 PCMCIA_DEVICE_MANF_CARD(0x016c, 0x0023),
2128 PCMCIA_DEVICE_PROD_ID123("BASICS by New Media Corporation", "Ethernet", "SMC91C94", 0x23c78a9d, 0x00b2e941, 0xcef397fb),
2129 PCMCIA_DEVICE_PROD_ID12("ARGOSY", "Fast Ethernet PCCard", 0x78f308dc, 0xdcea68bc),
2130 PCMCIA_DEVICE_PROD_ID12("dit Co., Ltd.", "PC Card-10/100BTX", 0xe59365c8, 0x6a2161d1),
2131 PCMCIA_DEVICE_PROD_ID12("DYNALINK", "L100C", 0x6a26d1cf, 0xc16ce9c5),
2132 PCMCIA_DEVICE_PROD_ID12("Farallon", "Farallon Enet", 0x58d93fc4, 0x244734e9),
2133 PCMCIA_DEVICE_PROD_ID12("Megahertz", "CC10BT/2", 0x33234748, 0x3c95b953),
2134 PCMCIA_DEVICE_PROD_ID12("MELCO/SMC", "LPC-TX", 0xa2cd8e6d, 0x42da662a),
Komurod277ad02005-07-28 01:07:24 -07002135 PCMCIA_DEVICE_PROD_ID12("Ositech", "Trumpcard:Four of Diamonds Ethernet", 0xc2f80cd, 0xb3466314),
2136 PCMCIA_DEVICE_PROD_ID12("Ositech", "Trumpcard:Seven of Diamonds Ethernet", 0xc2f80cd, 0x194b650a),
Dominik Brodowski5c672222005-06-27 16:28:27 -07002137 PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Fast Ethernet PCCard", 0x281f1c5d, 0xdcea68bc),
2138 PCMCIA_DEVICE_PROD_ID12("Psion", "10Mb Ethernet", 0x4ef00b21, 0x844be9e9),
2139 PCMCIA_DEVICE_PROD_ID12("SMC", "EtherEZ Ethernet 8020", 0xc4f8b18b, 0x4a0eeb2d),
2140 /* These conflict with other cards! */
2141 /* PCMCIA_DEVICE_MANF_CARD(0x0186, 0x0100), */
2142 /* PCMCIA_DEVICE_MANF_CARD(0x8a01, 0xc1ab), */
2143 PCMCIA_DEVICE_NULL,
2144};
2145MODULE_DEVICE_TABLE(pcmcia, smc91c92_ids);
2146
Linus Torvalds1da177e2005-04-16 15:20:36 -07002147static struct pcmcia_driver smc91c92_cs_driver = {
2148 .owner = THIS_MODULE,
2149 .drv = {
2150 .name = "smc91c92_cs",
2151 },
Dominik Brodowski15b99ac2006-03-31 17:26:06 +02002152 .probe = smc91c92_probe,
Dominik Brodowskicc3b4862005-11-14 21:23:14 +01002153 .remove = smc91c92_detach,
Dominik Brodowski5c672222005-06-27 16:28:27 -07002154 .id_table = smc91c92_ids,
Dominik Brodowski98e4c282005-11-14 21:21:18 +01002155 .suspend = smc91c92_suspend,
2156 .resume = smc91c92_resume,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002157};
2158
2159static int __init init_smc91c92_cs(void)
2160{
2161 return pcmcia_register_driver(&smc91c92_cs_driver);
2162}
2163
2164static void __exit exit_smc91c92_cs(void)
2165{
2166 pcmcia_unregister_driver(&smc91c92_cs_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002167}
2168
2169module_init(init_smc91c92_cs);
2170module_exit(exit_smc91c92_cs);