blob: 117b083a10cb9467896bf529f3db3eedc98a38e5 [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
Yum Rayan4638aef42005-05-05 15:14:10 -0700129struct smc_cfg_mem {
130 tuple_t tuple;
131 cisparse_t parse;
132 u_char buf[255];
133};
134
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135/* Special definitions for Megahertz multifunction cards */
136#define MEGAHERTZ_ISR 0x0380
137
138/* Special function registers for Motorola Mariner */
139#define MOT_LAN 0x0000
140#define MOT_UART 0x0020
141#define MOT_EEPROM 0x20
142
143#define MOT_NORMAL \
144(COR_LEVEL_REQ | COR_FUNC_ENA | COR_ADDR_DECODE | COR_IREQ_ENA)
145
146/* Special function registers for Ositech cards */
147#define OSITECH_AUI_CTL 0x0c
148#define OSITECH_PWRDOWN 0x0d
149#define OSITECH_RESET 0x0e
150#define OSITECH_ISR 0x0f
151#define OSITECH_AUI_PWR 0x0c
152#define OSITECH_RESET_ISR 0x0e
153
154#define OSI_AUI_PWR 0x40
155#define OSI_LAN_PWRDOWN 0x02
156#define OSI_MODEM_PWRDOWN 0x01
157#define OSI_LAN_RESET 0x02
158#define OSI_MODEM_RESET 0x01
159
160/* Symbolic constants for the SMC91c9* series chips, from Erik Stahlman. */
161#define BANK_SELECT 14 /* Window select register. */
162#define SMC_SELECT_BANK(x) { outw(x, ioaddr + BANK_SELECT); }
163
164/* Bank 0 registers. */
165#define TCR 0 /* transmit control register */
166#define TCR_CLEAR 0 /* do NOTHING */
167#define TCR_ENABLE 0x0001 /* if this is 1, we can transmit */
168#define TCR_PAD_EN 0x0080 /* pads short packets to 64 bytes */
169#define TCR_MONCSN 0x0400 /* Monitor Carrier. */
170#define TCR_FDUPLX 0x0800 /* Full duplex mode. */
171#define TCR_NORMAL TCR_ENABLE | TCR_PAD_EN
172
173#define EPH 2 /* Ethernet Protocol Handler report. */
174#define EPH_TX_SUC 0x0001
175#define EPH_SNGLCOL 0x0002
176#define EPH_MULCOL 0x0004
177#define EPH_LTX_MULT 0x0008
178#define EPH_16COL 0x0010
179#define EPH_SQET 0x0020
180#define EPH_LTX_BRD 0x0040
181#define EPH_TX_DEFR 0x0080
182#define EPH_LAT_COL 0x0200
183#define EPH_LOST_CAR 0x0400
184#define EPH_EXC_DEF 0x0800
185#define EPH_CTR_ROL 0x1000
186#define EPH_RX_OVRN 0x2000
187#define EPH_LINK_OK 0x4000
188#define EPH_TX_UNRN 0x8000
189#define MEMINFO 8 /* Memory Information Register */
190#define MEMCFG 10 /* Memory Configuration Register */
191
192/* Bank 1 registers. */
193#define CONFIG 0
194#define CFG_MII_SELECT 0x8000 /* 91C100 only */
195#define CFG_NO_WAIT 0x1000
196#define CFG_FULL_STEP 0x0400
197#define CFG_SET_SQLCH 0x0200
198#define CFG_AUI_SELECT 0x0100
199#define CFG_16BIT 0x0080
200#define CFG_DIS_LINK 0x0040
201#define CFG_STATIC 0x0030
202#define CFG_IRQ_SEL_1 0x0004
203#define CFG_IRQ_SEL_0 0x0002
204#define BASE_ADDR 2
205#define ADDR0 4
206#define GENERAL 10
207#define CONTROL 12
208#define CTL_STORE 0x0001
209#define CTL_RELOAD 0x0002
210#define CTL_EE_SELECT 0x0004
211#define CTL_TE_ENABLE 0x0020
212#define CTL_CR_ENABLE 0x0040
213#define CTL_LE_ENABLE 0x0080
214#define CTL_AUTO_RELEASE 0x0800
215#define CTL_POWERDOWN 0x2000
216
217/* Bank 2 registers. */
218#define MMU_CMD 0
219#define MC_ALLOC 0x20 /* or with number of 256 byte packets */
220#define MC_RESET 0x40
221#define MC_RELEASE 0x80 /* remove and release the current rx packet */
222#define MC_FREEPKT 0xA0 /* Release packet in PNR register */
223#define MC_ENQUEUE 0xC0 /* Enqueue the packet for transmit */
224#define PNR_ARR 2
225#define FIFO_PORTS 4
226#define FP_RXEMPTY 0x8000
227#define POINTER 6
228#define PTR_AUTO_INC 0x0040
229#define PTR_READ 0x2000
230#define PTR_AUTOINC 0x4000
231#define PTR_RCV 0x8000
232#define DATA_1 8
233#define INTERRUPT 12
234#define IM_RCV_INT 0x1
235#define IM_TX_INT 0x2
236#define IM_TX_EMPTY_INT 0x4
237#define IM_ALLOC_INT 0x8
238#define IM_RX_OVRN_INT 0x10
239#define IM_EPH_INT 0x20
240
241#define RCR 4
242enum RxCfg { RxAllMulti = 0x0004, RxPromisc = 0x0002,
243 RxEnable = 0x0100, RxStripCRC = 0x0200};
244#define RCR_SOFTRESET 0x8000 /* resets the chip */
245#define RCR_STRIP_CRC 0x200 /* strips CRC */
246#define RCR_ENABLE 0x100 /* IFF this is set, we can receive packets */
247#define RCR_ALMUL 0x4 /* receive all multicast packets */
248#define RCR_PROMISC 0x2 /* enable promiscuous mode */
249
250/* the normal settings for the RCR register : */
251#define RCR_NORMAL (RCR_STRIP_CRC | RCR_ENABLE)
252#define RCR_CLEAR 0x0 /* set it to a base state */
253#define COUNTER 6
254
255/* BANK 3 -- not the same values as in smc9194! */
256#define MULTICAST0 0
257#define MULTICAST2 2
258#define MULTICAST4 4
259#define MULTICAST6 6
260#define MGMT 8
261#define REVISION 0x0a
262
263/* Transmit status bits. */
264#define TS_SUCCESS 0x0001
265#define TS_16COL 0x0010
266#define TS_LATCOL 0x0200
267#define TS_LOSTCAR 0x0400
268
269/* Receive status bits. */
270#define RS_ALGNERR 0x8000
271#define RS_BADCRC 0x2000
272#define RS_ODDFRAME 0x1000
273#define RS_TOOLONG 0x0800
274#define RS_TOOSHORT 0x0400
275#define RS_MULTICAST 0x0001
276#define RS_ERRORS (RS_ALGNERR | RS_BADCRC | RS_TOOLONG | RS_TOOSHORT)
277
278#define set_bits(v, p) outw(inw(p)|(v), (p))
279#define mask_bits(v, p) outw(inw(p)&(v), (p))
280
281/*====================================================================*/
282
Dominik Brodowskicc3b4862005-11-14 21:23:14 +0100283static void smc91c92_detach(struct pcmcia_device *p_dev);
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200284static int smc91c92_config(struct pcmcia_device *link);
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200285static void smc91c92_release(struct pcmcia_device *link);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286
287static int smc_open(struct net_device *dev);
288static int smc_close(struct net_device *dev);
289static int smc_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
290static void smc_tx_timeout(struct net_device *dev);
Stephen Hemmingerdbf02fa2009-08-31 19:50:49 +0000291static netdev_tx_t smc_start_xmit(struct sk_buff *skb,
292 struct net_device *dev);
David Howells7d12e782006-10-05 14:55:46 +0100293static irqreturn_t smc_interrupt(int irq, void *dev_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294static void smc_rx(struct net_device *dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295static void set_rx_mode(struct net_device *dev);
296static int s9k_config(struct net_device *dev, struct ifmap *map);
297static void smc_set_xcvr(struct net_device *dev, int if_port);
298static void smc_reset(struct net_device *dev);
299static void media_check(u_long arg);
Olof Johansson906da802008-02-04 22:27:35 -0800300static void mdio_sync(unsigned int addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301static int mdio_read(struct net_device *dev, int phy_id, int loc);
302static void mdio_write(struct net_device *dev, int phy_id, int loc, int value);
303static int smc_link_ok(struct net_device *dev);
Jeff Garzik7282d492006-09-13 14:30:00 -0400304static const struct ethtool_ops ethtool_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305
Stephen Hemminger9b31b692009-03-20 19:36:10 +0000306static const struct net_device_ops smc_netdev_ops = {
307 .ndo_open = smc_open,
308 .ndo_stop = smc_close,
309 .ndo_start_xmit = smc_start_xmit,
310 .ndo_tx_timeout = smc_tx_timeout,
311 .ndo_set_config = s9k_config,
312 .ndo_set_multicast_list = set_rx_mode,
313 .ndo_do_ioctl = &smc_ioctl,
314 .ndo_change_mtu = eth_change_mtu,
315 .ndo_set_mac_address = eth_mac_addr,
316 .ndo_validate_addr = eth_validate_addr,
317};
318
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319/*======================================================================
320
321 smc91c92_attach() creates an "instance" of the driver, allocating
322 local data structures for one device. The device is registered
323 with Card Services.
324
325======================================================================*/
326
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200327static int smc91c92_probe(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329 struct smc_private *smc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330 struct net_device *dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331
332 DEBUG(0, "smc91c92_attach()\n");
333
334 /* Create new ethernet device */
335 dev = alloc_etherdev(sizeof(struct smc_private));
336 if (!dev)
Dominik Brodowskif8cfa612005-11-14 21:25:51 +0100337 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338 smc = netdev_priv(dev);
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200339 smc->p_dev = link;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340 link->priv = dev;
341
342 spin_lock_init(&smc->lock);
343 link->io.NumPorts1 = 16;
344 link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
345 link->io.IOAddrLines = 4;
Komuro5e7bf8c2007-10-28 11:26:17 +0900346 link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_HANDLE_PRESENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347 link->irq.IRQInfo1 = IRQ_LEVEL_ID;
348 link->irq.Handler = &smc_interrupt;
349 link->irq.Instance = dev;
350 link->conf.Attributes = CONF_ENABLE_IRQ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351 link->conf.IntType = INT_MEMORY_AND_IO;
352
353 /* The SMC91c92-specific entries in the device structure. */
Stephen Hemminger9b31b692009-03-20 19:36:10 +0000354 dev->netdev_ops = &smc_netdev_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355 SET_ETHTOOL_OPS(dev, &ethtool_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356 dev->watchdog_timeo = TX_TIMEOUT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357
358 smc->mii_if.dev = dev;
359 smc->mii_if.mdio_read = mdio_read;
360 smc->mii_if.mdio_write = mdio_write;
361 smc->mii_if.phy_id_mask = 0x1f;
362 smc->mii_if.reg_num_mask = 0x1f;
363
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200364 return smc91c92_config(link);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365} /* smc91c92_attach */
366
367/*======================================================================
368
369 This deletes a driver "instance". The device is de-registered
370 with Card Services. If it has been released, all local data
371 structures are freed. Otherwise, the structures will be freed
372 when the device is released.
373
374======================================================================*/
375
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200376static void smc91c92_detach(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377{
378 struct net_device *dev = link->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379
380 DEBUG(0, "smc91c92_detach(0x%p)\n", link);
381
Dominik Brodowskifd238232006-03-05 10:45:09 +0100382 if (link->dev_node)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383 unregister_netdev(dev);
384
Dominik Brodowskie2d40962006-03-02 00:09:29 +0100385 smc91c92_release(link);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387 free_netdev(dev);
388} /* smc91c92_detach */
389
390/*====================================================================*/
391
392static int cvt_ascii_address(struct net_device *dev, char *s)
393{
394 int i, j, da, c;
395
396 if (strlen(s) != 12)
397 return -1;
398 for (i = 0; i < 6; i++) {
399 da = 0;
400 for (j = 0; j < 2; j++) {
401 c = *s++;
402 da <<= 4;
403 da += ((c >= '0') && (c <= '9')) ?
404 (c - '0') : ((c & 0x0f) + 9);
405 }
406 dev->dev_addr[i] = da;
407 }
408 return 0;
409}
410
411/*====================================================================*/
412
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200413static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414 cisparse_t *parse)
415{
416 int i;
417
Dominik Brodowski4c89e882008-08-03 10:07:45 +0200418 i = pcmcia_get_first_tuple(handle, tuple);
419 if (i != 0)
420 return i;
421 i = pcmcia_get_tuple_data(handle, tuple);
422 if (i != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423 return i;
Dominik Brodowski2f3061e2008-08-31 15:50:33 +0200424 return pcmcia_parse_tuple(tuple, parse);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425}
426
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200427static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428 cisparse_t *parse)
429{
430 int i;
431
Dominik Brodowski4c89e882008-08-03 10:07:45 +0200432 if ((i = pcmcia_get_next_tuple(handle, tuple)) != 0 ||
433 (i = pcmcia_get_tuple_data(handle, tuple)) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434 return i;
Dominik Brodowski2f3061e2008-08-31 15:50:33 +0200435 return pcmcia_parse_tuple(tuple, parse);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436}
437
438/*======================================================================
439
440 Configuration stuff for Megahertz cards
441
442 mhz_3288_power() is used to power up a 3288's ethernet chip.
443 mhz_mfc_config() handles socket setup for multifunction (1144
444 and 3288) cards. mhz_setup() gets a card's hardware ethernet
445 address.
446
447======================================================================*/
448
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200449static int mhz_3288_power(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450{
451 struct net_device *dev = link->priv;
452 struct smc_private *smc = netdev_priv(dev);
453 u_char tmp;
454
455 /* Read the ISR twice... */
456 readb(smc->base+MEGAHERTZ_ISR);
457 udelay(5);
458 readb(smc->base+MEGAHERTZ_ISR);
459
460 /* Pause 200ms... */
461 mdelay(200);
462
463 /* Now read and write the COR... */
464 tmp = readb(smc->base + link->conf.ConfigBase + CISREG_COR);
465 udelay(5);
466 writeb(tmp, smc->base + link->conf.ConfigBase + CISREG_COR);
467
468 return 0;
469}
470
Dominik Brodowskib54bf942008-08-02 14:28:43 +0200471static int mhz_mfc_config_check(struct pcmcia_device *p_dev,
472 cistpl_cftable_entry_t *cf,
Dominik Brodowski8e2fc392008-08-02 15:30:31 +0200473 cistpl_cftable_entry_t *dflt,
Dominik Brodowskiad913c12008-08-02 16:12:00 +0200474 unsigned int vcc,
Dominik Brodowskib54bf942008-08-02 14:28:43 +0200475 void *priv_data)
476{
477 int k;
Dominik Brodowskib54bf942008-08-02 14:28:43 +0200478 p_dev->io.BasePort2 = cf->io.win[0].base;
479 for (k = 0; k < 0x400; k += 0x10) {
480 if (k & 0x80)
481 continue;
482 p_dev->io.BasePort1 = k ^ 0x300;
483 if (!pcmcia_request_io(p_dev, &p_dev->io))
484 return 0;
485 }
486 return -ENODEV;
487}
488
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200489static int mhz_mfc_config(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490{
491 struct net_device *dev = link->priv;
492 struct smc_private *smc = netdev_priv(dev);
Yum Rayan4638aef42005-05-05 15:14:10 -0700493 struct smc_cfg_mem *cfg_mem;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494 win_req_t req;
495 memreq_t mem;
Dominik Brodowskib54bf942008-08-02 14:28:43 +0200496 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497
Yum Rayan4638aef42005-05-05 15:14:10 -0700498 cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL);
499 if (!cfg_mem)
Dominik Brodowski11683862008-08-03 10:22:47 +0200500 return -ENOMEM;
Yum Rayan4638aef42005-05-05 15:14:10 -0700501
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502 link->conf.Attributes |= CONF_ENABLE_SPKR;
503 link->conf.Status = CCSR_AUDIO_ENA;
504 link->irq.Attributes =
505 IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED|IRQ_HANDLE_PRESENT;
506 link->io.IOAddrLines = 16;
507 link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
508 link->io.NumPorts2 = 8;
509
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510 /* The Megahertz combo cards have modem-like CIS entries, so
511 we have to explicitly try a bunch of port combinations. */
Dominik Brodowskib54bf942008-08-02 14:28:43 +0200512 if (pcmcia_loop_config(link, mhz_mfc_config_check, NULL))
Yum Rayan4638aef42005-05-05 15:14:10 -0700513 goto free_cfg_mem;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514 dev->base_addr = link->io.BasePort1;
515
516 /* Allocate a memory window, for accessing the ISR */
517 req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
518 req.Base = req.Size = 0;
519 req.AccessSpeed = 0;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200520 i = pcmcia_request_window(&link, &req, &link->win);
Dominik Brodowski4c89e882008-08-03 10:07:45 +0200521 if (i != 0)
Yum Rayan4638aef42005-05-05 15:14:10 -0700522 goto free_cfg_mem;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523 smc->base = ioremap(req.Base, req.Size);
524 mem.CardOffset = mem.Page = 0;
525 if (smc->manfid == MANFID_MOTOROLA)
526 mem.CardOffset = link->conf.ConfigBase;
527 i = pcmcia_map_mem_page(link->win, &mem);
528
Joe Perches8e95a202009-12-03 07:58:21 +0000529 if ((i == 0) &&
530 (smc->manfid == MANFID_MEGAHERTZ) &&
531 (smc->cardid == PRODID_MEGAHERTZ_EM3288))
532 mhz_3288_power(link);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533
Yum Rayan4638aef42005-05-05 15:14:10 -0700534free_cfg_mem:
535 kfree(cfg_mem);
Dominik Brodowskib54bf942008-08-02 14:28:43 +0200536 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537}
538
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200539static int mhz_setup(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541 struct net_device *dev = link->priv;
Yum Rayan4638aef42005-05-05 15:14:10 -0700542 struct smc_cfg_mem *cfg_mem;
543 tuple_t *tuple;
544 cisparse_t *parse;
545 u_char *buf, *station_addr;
546 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547
Yum Rayan4638aef42005-05-05 15:14:10 -0700548 cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL);
549 if (!cfg_mem)
550 return -1;
551
552 tuple = &cfg_mem->tuple;
553 parse = &cfg_mem->parse;
554 buf = cfg_mem->buf;
555
556 tuple->Attributes = tuple->TupleOffset = 0;
557 tuple->TupleData = (cisdata_t *)buf;
558 tuple->TupleDataMax = 255;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559
560 /* Read the station address from the CIS. It is stored as the last
561 (fourth) string in the Version 1 Version/ID tuple. */
Chuck Ebberta1a98b72008-02-13 19:47:11 -0500562 tuple->DesiredTuple = CISTPL_VERS_1;
Dominik Brodowski4c89e882008-08-03 10:07:45 +0200563 if (first_tuple(link, tuple, parse) != 0) {
Chuck Ebberta1a98b72008-02-13 19:47:11 -0500564 rc = -1;
565 goto free_cfg_mem;
566 }
567 /* Ugh -- the EM1144 card has two VERS_1 tuples!?! */
Dominik Brodowski4c89e882008-08-03 10:07:45 +0200568 if (next_tuple(link, tuple, parse) != 0)
Chuck Ebberta1a98b72008-02-13 19:47:11 -0500569 first_tuple(link, tuple, parse);
570 if (parse->version_1.ns > 3) {
571 station_addr = parse->version_1.str + parse->version_1.ofs[3];
Yum Rayan4638aef42005-05-05 15:14:10 -0700572 if (cvt_ascii_address(dev, station_addr) == 0) {
573 rc = 0;
574 goto free_cfg_mem;
575 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576 }
577
578 /* Another possibility: for the EM3288, in a special tuple */
Yum Rayan4638aef42005-05-05 15:14:10 -0700579 tuple->DesiredTuple = 0x81;
Dominik Brodowski4c89e882008-08-03 10:07:45 +0200580 if (pcmcia_get_first_tuple(link, tuple) != 0) {
Yum Rayan4638aef42005-05-05 15:14:10 -0700581 rc = -1;
582 goto free_cfg_mem;
583 }
Dominik Brodowski4c89e882008-08-03 10:07:45 +0200584 if (pcmcia_get_tuple_data(link, tuple) != 0) {
Yum Rayan4638aef42005-05-05 15:14:10 -0700585 rc = -1;
586 goto free_cfg_mem;
587 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588 buf[12] = '\0';
Yum Rayan4638aef42005-05-05 15:14:10 -0700589 if (cvt_ascii_address(dev, buf) == 0) {
590 rc = 0;
591 goto free_cfg_mem;
592 }
593 rc = -1;
594free_cfg_mem:
595 kfree(cfg_mem);
596 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597}
598
599/*======================================================================
600
601 Configuration stuff for the Motorola Mariner
602
603 mot_config() writes directly to the Mariner configuration
604 registers because the CIS is just bogus.
605
606======================================================================*/
607
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200608static void mot_config(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609{
610 struct net_device *dev = link->priv;
611 struct smc_private *smc = netdev_priv(dev);
Olof Johansson906da802008-02-04 22:27:35 -0800612 unsigned int ioaddr = dev->base_addr;
613 unsigned int iouart = link->io.BasePort2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614
615 /* Set UART base address and force map with COR bit 1 */
616 writeb(iouart & 0xff, smc->base + MOT_UART + CISREG_IOBASE_0);
617 writeb((iouart >> 8) & 0xff, smc->base + MOT_UART + CISREG_IOBASE_1);
618 writeb(MOT_NORMAL, smc->base + MOT_UART + CISREG_COR);
619
620 /* Set SMC base address and force map with COR bit 1 */
621 writeb(ioaddr & 0xff, smc->base + MOT_LAN + CISREG_IOBASE_0);
622 writeb((ioaddr >> 8) & 0xff, smc->base + MOT_LAN + CISREG_IOBASE_1);
623 writeb(MOT_NORMAL, smc->base + MOT_LAN + CISREG_COR);
624
625 /* Wait for things to settle down */
626 mdelay(100);
627}
628
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200629static int mot_setup(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630{
631 struct net_device *dev = link->priv;
Olof Johansson906da802008-02-04 22:27:35 -0800632 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633 int i, wait, loop;
634 u_int addr;
635
636 /* Read Ethernet address from Serial EEPROM */
637
638 for (i = 0; i < 3; i++) {
639 SMC_SELECT_BANK(2);
640 outw(MOT_EEPROM + i, ioaddr + POINTER);
641 SMC_SELECT_BANK(1);
642 outw((CTL_RELOAD | CTL_EE_SELECT), ioaddr + CONTROL);
643
644 for (loop = wait = 0; loop < 200; loop++) {
645 udelay(10);
646 wait = ((CTL_RELOAD | CTL_STORE) & inw(ioaddr + CONTROL));
647 if (wait == 0) break;
648 }
649
650 if (wait)
651 return -1;
652
653 addr = inw(ioaddr + GENERAL);
654 dev->dev_addr[2*i] = addr & 0xff;
655 dev->dev_addr[2*i+1] = (addr >> 8) & 0xff;
656 }
657
658 return 0;
659}
660
661/*====================================================================*/
662
Dominik Brodowskib54bf942008-08-02 14:28:43 +0200663static int smc_configcheck(struct pcmcia_device *p_dev,
664 cistpl_cftable_entry_t *cf,
Dominik Brodowski8e2fc392008-08-02 15:30:31 +0200665 cistpl_cftable_entry_t *dflt,
Dominik Brodowskiad913c12008-08-02 16:12:00 +0200666 unsigned int vcc,
Dominik Brodowskib54bf942008-08-02 14:28:43 +0200667 void *priv_data)
668{
Dominik Brodowskib54bf942008-08-02 14:28:43 +0200669 p_dev->io.BasePort1 = cf->io.win[0].base;
670 p_dev->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
671 return pcmcia_request_io(p_dev, &p_dev->io);
672}
673
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200674static int smc_config(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675{
676 struct net_device *dev = link->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677 int i;
678
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679 link->io.NumPorts1 = 16;
Dominik Brodowskib54bf942008-08-02 14:28:43 +0200680 i = pcmcia_loop_config(link, smc_configcheck, NULL);
681 if (!i)
682 dev->base_addr = link->io.BasePort1;
Yum Rayan4638aef42005-05-05 15:14:10 -0700683
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684 return i;
685}
686
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200687static int smc_setup(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689 struct net_device *dev = link->priv;
Yum Rayan4638aef42005-05-05 15:14:10 -0700690 struct smc_cfg_mem *cfg_mem;
691 tuple_t *tuple;
692 cisparse_t *parse;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693 cistpl_lan_node_id_t *node_id;
Yum Rayan4638aef42005-05-05 15:14:10 -0700694 u_char *buf, *station_addr;
695 int i, rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696
Yum Rayan4638aef42005-05-05 15:14:10 -0700697 cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL);
698 if (!cfg_mem)
Dominik Brodowski11683862008-08-03 10:22:47 +0200699 return -ENOMEM;
Yum Rayan4638aef42005-05-05 15:14:10 -0700700
701 tuple = &cfg_mem->tuple;
702 parse = &cfg_mem->parse;
703 buf = cfg_mem->buf;
704
705 tuple->Attributes = tuple->TupleOffset = 0;
706 tuple->TupleData = (cisdata_t *)buf;
707 tuple->TupleDataMax = 255;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708
709 /* Check for a LAN function extension tuple */
Yum Rayan4638aef42005-05-05 15:14:10 -0700710 tuple->DesiredTuple = CISTPL_FUNCE;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200711 i = first_tuple(link, tuple, parse);
Dominik Brodowski4c89e882008-08-03 10:07:45 +0200712 while (i == 0) {
Yum Rayan4638aef42005-05-05 15:14:10 -0700713 if (parse->funce.type == CISTPL_FUNCE_LAN_NODE_ID)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714 break;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200715 i = next_tuple(link, tuple, parse);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716 }
Dominik Brodowski4c89e882008-08-03 10:07:45 +0200717 if (i == 0) {
Yum Rayan4638aef42005-05-05 15:14:10 -0700718 node_id = (cistpl_lan_node_id_t *)parse->funce.data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719 if (node_id->nb == 6) {
720 for (i = 0; i < 6; i++)
721 dev->dev_addr[i] = node_id->id[i];
Yum Rayan4638aef42005-05-05 15:14:10 -0700722 rc = 0;
723 goto free_cfg_mem;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724 }
725 }
726 /* Try the third string in the Version 1 Version/ID tuple. */
Dominik Brodowskia9606fd2006-06-04 18:06:13 +0200727 if (link->prod_id[2]) {
728 station_addr = link->prod_id[2];
729 if (cvt_ascii_address(dev, station_addr) == 0) {
730 rc = 0;
731 goto free_cfg_mem;
732 }
Yum Rayan4638aef42005-05-05 15:14:10 -0700733 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734
Yum Rayan4638aef42005-05-05 15:14:10 -0700735 rc = -1;
736free_cfg_mem:
737 kfree(cfg_mem);
738 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739}
740
741/*====================================================================*/
742
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200743static int osi_config(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744{
745 struct net_device *dev = link->priv;
Olof Johansson906da802008-02-04 22:27:35 -0800746 static const unsigned int com[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747 int i, j;
748
749 link->conf.Attributes |= CONF_ENABLE_SPKR;
750 link->conf.Status = CCSR_AUDIO_ENA;
751 link->irq.Attributes =
752 IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED|IRQ_HANDLE_PRESENT;
753 link->io.NumPorts1 = 64;
754 link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
755 link->io.NumPorts2 = 8;
756 link->io.IOAddrLines = 16;
757
758 /* Enable Hard Decode, LAN, Modem */
759 link->conf.ConfigIndex = 0x23;
760
761 for (i = j = 0; j < 4; j++) {
762 link->io.BasePort2 = com[j];
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200763 i = pcmcia_request_io(link, &link->io);
Dominik Brodowski4c89e882008-08-03 10:07:45 +0200764 if (i == 0)
765 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766 }
Dominik Brodowski4c89e882008-08-03 10:07:45 +0200767 if (i != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768 /* Fallback: turn off hard decode */
769 link->conf.ConfigIndex = 0x03;
770 link->io.NumPorts2 = 0;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200771 i = pcmcia_request_io(link, &link->io);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772 }
773 dev->base_addr = link->io.BasePort1 + 0x10;
774 return i;
775}
776
Jaswinder Singh Rajput75bf7582009-03-30 20:19:54 +0530777static int osi_load_firmware(struct pcmcia_device *link)
778{
779 const struct firmware *fw;
780 int i, err;
781
782 err = request_firmware(&fw, FIRMWARE_NAME, &link->dev);
783 if (err) {
784 pr_err("Failed to load firmware \"%s\"\n", FIRMWARE_NAME);
785 return err;
786 }
787
788 /* Download the Seven of Diamonds firmware */
789 for (i = 0; i < fw->size; i++) {
790 outb(fw->data[i], link->io.BasePort1 + 2);
791 udelay(50);
792 }
793 release_firmware(fw);
794 return err;
795}
796
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200797static int osi_setup(struct pcmcia_device *link, u_short manfid, u_short cardid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799 struct net_device *dev = link->priv;
Yum Rayan4638aef42005-05-05 15:14:10 -0700800 struct smc_cfg_mem *cfg_mem;
801 tuple_t *tuple;
802 u_char *buf;
803 int i, rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804
Yum Rayan4638aef42005-05-05 15:14:10 -0700805 cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL);
806 if (!cfg_mem)
807 return -1;
808
809 tuple = &cfg_mem->tuple;
810 buf = cfg_mem->buf;
811
812 tuple->Attributes = TUPLE_RETURN_COMMON;
813 tuple->TupleData = (cisdata_t *)buf;
814 tuple->TupleDataMax = 255;
815 tuple->TupleOffset = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816
817 /* Read the station address from tuple 0x90, subtuple 0x04 */
Yum Rayan4638aef42005-05-05 15:14:10 -0700818 tuple->DesiredTuple = 0x90;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200819 i = pcmcia_get_first_tuple(link, tuple);
Dominik Brodowski4c89e882008-08-03 10:07:45 +0200820 while (i == 0) {
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200821 i = pcmcia_get_tuple_data(link, tuple);
Dominik Brodowski4c89e882008-08-03 10:07:45 +0200822 if ((i != 0) || (buf[0] == 0x04))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823 break;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200824 i = pcmcia_get_next_tuple(link, tuple);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825 }
Dominik Brodowski4c89e882008-08-03 10:07:45 +0200826 if (i != 0) {
Yum Rayan4638aef42005-05-05 15:14:10 -0700827 rc = -1;
828 goto free_cfg_mem;
829 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830 for (i = 0; i < 6; i++)
831 dev->dev_addr[i] = buf[i+2];
832
833 if (((manfid == MANFID_OSITECH) &&
834 (cardid == PRODID_OSITECH_SEVEN)) ||
835 ((manfid == MANFID_PSION) &&
836 (cardid == PRODID_PSION_NET100))) {
Jaswinder Singh Rajput75bf7582009-03-30 20:19:54 +0530837 rc = osi_load_firmware(link);
838 if (rc)
839 goto free_cfg_mem;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840 } else if (manfid == MANFID_OSITECH) {
841 /* Make sure both functions are powered up */
842 set_bits(0x300, link->io.BasePort1 + OSITECH_AUI_PWR);
843 /* Now, turn on the interrupt for both card functions */
844 set_bits(0x300, link->io.BasePort1 + OSITECH_RESET_ISR);
845 DEBUG(2, "AUI/PWR: %4.4x RESET/ISR: %4.4x\n",
846 inw(link->io.BasePort1 + OSITECH_AUI_PWR),
847 inw(link->io.BasePort1 + OSITECH_RESET_ISR));
848 }
Yum Rayan4638aef42005-05-05 15:14:10 -0700849 rc = 0;
850free_cfg_mem:
851 kfree(cfg_mem);
852 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853}
854
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200855static int smc91c92_suspend(struct pcmcia_device *link)
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100856{
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100857 struct net_device *dev = link->priv;
858
Dominik Brodowskie2d40962006-03-02 00:09:29 +0100859 if (link->open)
Dominik Brodowski4bbed522006-01-15 11:18:12 +0100860 netif_device_detach(dev);
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100861
862 return 0;
863}
864
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200865static int smc91c92_resume(struct pcmcia_device *link)
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100866{
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100867 struct net_device *dev = link->priv;
868 struct smc_private *smc = netdev_priv(dev);
869 int i;
870
Dominik Brodowskie2d40962006-03-02 00:09:29 +0100871 if ((smc->manfid == MANFID_MEGAHERTZ) &&
872 (smc->cardid == PRODID_MEGAHERTZ_EM3288))
873 mhz_3288_power(link);
874 if (smc->manfid == MANFID_MOTOROLA)
875 mot_config(link);
876 if ((smc->manfid == MANFID_OSITECH) &&
877 (smc->cardid != PRODID_OSITECH_SEVEN)) {
878 /* Power up the card and enable interrupts */
879 set_bits(0x0300, dev->base_addr-0x10+OSITECH_AUI_PWR);
880 set_bits(0x0300, dev->base_addr-0x10+OSITECH_RESET_ISR);
881 }
882 if (((smc->manfid == MANFID_OSITECH) &&
883 (smc->cardid == PRODID_OSITECH_SEVEN)) ||
884 ((smc->manfid == MANFID_PSION) &&
885 (smc->cardid == PRODID_PSION_NET100))) {
Jaswinder Singh Rajput75bf7582009-03-30 20:19:54 +0530886 i = osi_load_firmware(link);
887 if (i) {
888 pr_err("smc91c92_cs: Failed to load firmware\n");
889 return i;
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100890 }
Dominik Brodowskie2d40962006-03-02 00:09:29 +0100891 }
892 if (link->open) {
893 smc_reset(dev);
894 netif_device_attach(dev);
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100895 }
896
897 return 0;
898}
899
900
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901/*======================================================================
902
903 This verifies that the chip is some SMC91cXX variant, and returns
904 the revision code if successful. Otherwise, it returns -ENODEV.
905
906======================================================================*/
907
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200908static int check_sig(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909{
910 struct net_device *dev = link->priv;
Olof Johansson906da802008-02-04 22:27:35 -0800911 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912 int width;
913 u_short s;
914
915 SMC_SELECT_BANK(1);
916 if (inw(ioaddr + BANK_SELECT) >> 8 != 0x33) {
917 /* Try powering up the chip */
918 outw(0, ioaddr + CONTROL);
919 mdelay(55);
920 }
921
922 /* Try setting bus width */
923 width = (link->io.Attributes1 == IO_DATA_PATH_WIDTH_AUTO);
924 s = inb(ioaddr + CONFIG);
925 if (width)
926 s |= CFG_16BIT;
927 else
928 s &= ~CFG_16BIT;
929 outb(s, ioaddr + CONFIG);
930
931 /* Check Base Address Register to make sure bus width is OK */
932 s = inw(ioaddr + BASE_ADDR);
933 if ((inw(ioaddr + BANK_SELECT) >> 8 == 0x33) &&
934 ((s >> 8) != (s & 0xff))) {
935 SMC_SELECT_BANK(3);
936 s = inw(ioaddr + REVISION);
937 return (s & 0xff);
938 }
939
940 if (width) {
Dominik Brodowski4bbed522006-01-15 11:18:12 +0100941 modconf_t mod = {
942 .Attributes = CONF_IO_CHANGE_WIDTH,
943 };
944 printk(KERN_INFO "smc91c92_cs: using 8-bit IO window.\n");
Dominik Brodowski50db3fd2006-01-15 10:05:19 +0100945
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200946 smc91c92_suspend(link);
947 pcmcia_modify_configuration(link, &mod);
948 smc91c92_resume(link);
Dominik Brodowski4bbed522006-01-15 11:18:12 +0100949 return check_sig(link);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950 }
951 return -ENODEV;
952}
953
954/*======================================================================
955
956 smc91c92_config() is scheduled to run after a CARD_INSERTION event
957 is received, to configure the PCMCIA socket, and to make the
958 ethernet device available to the system.
959
960======================================================================*/
961
Dominik Brodowski4c89e882008-08-03 10:07:45 +0200962#define CS_EXIT_TEST(ret, svc, label) \
963if (ret != 0) { \
964 cs_error(link, svc, ret); \
965 goto label; \
966}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200968static int smc91c92_config(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970 struct net_device *dev = link->priv;
971 struct smc_private *smc = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972 char *name;
973 int i, j, rev;
Olof Johansson906da802008-02-04 22:27:35 -0800974 unsigned int ioaddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975 u_long mir;
976
977 DEBUG(0, "smc91c92_config(0x%p)\n", link);
978
Dominik Brodowskiefd50582006-10-25 21:28:53 -0400979 smc->manfid = link->manf_id;
980 smc->cardid = link->card_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982 if ((smc->manfid == MANFID_OSITECH) &&
983 (smc->cardid != PRODID_OSITECH_SEVEN)) {
984 i = osi_config(link);
985 } else if ((smc->manfid == MANFID_MOTOROLA) ||
986 ((smc->manfid == MANFID_MEGAHERTZ) &&
987 ((smc->cardid == PRODID_MEGAHERTZ_VARIOUS) ||
988 (smc->cardid == PRODID_MEGAHERTZ_EM3288)))) {
989 i = mhz_mfc_config(link);
990 } else {
991 i = smc_config(link);
992 }
993 CS_EXIT_TEST(i, RequestIO, config_failed);
994
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200995 i = pcmcia_request_irq(link, &link->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996 CS_EXIT_TEST(i, RequestIRQ, config_failed);
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200997 i = pcmcia_request_configuration(link, &link->conf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998 CS_EXIT_TEST(i, RequestConfiguration, config_failed);
999
1000 if (smc->manfid == MANFID_MOTOROLA)
1001 mot_config(link);
1002
1003 dev->irq = link->irq.AssignedIRQ;
1004
1005 if ((if_port >= 0) && (if_port <= 2))
1006 dev->if_port = if_port;
1007 else
1008 printk(KERN_NOTICE "smc91c92_cs: invalid if_port requested\n");
1009
1010 switch (smc->manfid) {
1011 case MANFID_OSITECH:
1012 case MANFID_PSION:
1013 i = osi_setup(link, smc->manfid, smc->cardid); break;
1014 case MANFID_SMC:
1015 case MANFID_NEW_MEDIA:
1016 i = smc_setup(link); break;
1017 case 0x128: /* For broken Megahertz cards */
1018 case MANFID_MEGAHERTZ:
1019 i = mhz_setup(link); break;
1020 case MANFID_MOTOROLA:
1021 default: /* get the hw address from EEPROM */
1022 i = mot_setup(link); break;
1023 }
1024
1025 if (i != 0) {
1026 printk(KERN_NOTICE "smc91c92_cs: Unable to find hardware address.\n");
1027 goto config_undo;
1028 }
1029
1030 smc->duplex = 0;
1031 smc->rx_ovrn = 0;
1032
1033 rev = check_sig(link);
1034 name = "???";
1035 if (rev > 0)
1036 switch (rev >> 4) {
1037 case 3: name = "92"; break;
1038 case 4: name = ((rev & 15) >= 6) ? "96" : "94"; break;
1039 case 5: name = "95"; break;
1040 case 7: name = "100"; break;
1041 case 8: name = "100-FD"; break;
1042 case 9: name = "110"; break;
1043 }
1044
1045 ioaddr = dev->base_addr;
1046 if (rev > 0) {
1047 u_long mcr;
1048 SMC_SELECT_BANK(0);
1049 mir = inw(ioaddr + MEMINFO) & 0xff;
1050 if (mir == 0xff) mir++;
1051 /* Get scale factor for memory size */
1052 mcr = ((rev >> 4) > 3) ? inw(ioaddr + MEMCFG) : 0x0200;
1053 mir *= 128 * (1<<((mcr >> 9) & 7));
1054 SMC_SELECT_BANK(1);
1055 smc->cfg = inw(ioaddr + CONFIG) & ~CFG_AUI_SELECT;
1056 smc->cfg |= CFG_NO_WAIT | CFG_16BIT | CFG_STATIC;
1057 if (smc->manfid == MANFID_OSITECH)
1058 smc->cfg |= CFG_IRQ_SEL_1 | CFG_IRQ_SEL_0;
1059 if ((rev >> 4) >= 7)
1060 smc->cfg |= CFG_MII_SELECT;
1061 } else
1062 mir = 0;
1063
1064 if (smc->cfg & CFG_MII_SELECT) {
1065 SMC_SELECT_BANK(3);
1066
1067 for (i = 0; i < 32; i++) {
1068 j = mdio_read(dev, i, 1);
1069 if ((j != 0) && (j != 0xffff)) break;
1070 }
1071 smc->mii_if.phy_id = (i < 32) ? i : -1;
1072
1073 SMC_SELECT_BANK(0);
1074 }
1075
Dominik Brodowskifd238232006-03-05 10:45:09 +01001076 link->dev_node = &smc->node;
Dominik Brodowskifba395e2006-03-31 17:21:06 +02001077 SET_NETDEV_DEV(dev, &handle_to_dev(link));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078
1079 if (register_netdev(dev) != 0) {
1080 printk(KERN_ERR "smc91c92_cs: register_netdev() failed\n");
Dominik Brodowskifd238232006-03-05 10:45:09 +01001081 link->dev_node = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082 goto config_undo;
1083 }
1084
1085 strcpy(smc->node.dev_name, dev->name);
1086
1087 printk(KERN_INFO "%s: smc91c%s rev %d: io %#3lx, irq %d, "
Johannes Berge1749612008-10-27 15:59:26 -07001088 "hw_addr %pM\n",
Joe Perches0795af52007-10-03 17:59:30 -07001089 dev->name, name, (rev & 0x0f), dev->base_addr, dev->irq,
Johannes Berge1749612008-10-27 15:59:26 -07001090 dev->dev_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091
1092 if (rev > 0) {
1093 if (mir & 0x3ff)
1094 printk(KERN_INFO " %lu byte", mir);
1095 else
1096 printk(KERN_INFO " %lu kb", mir>>10);
1097 printk(" buffer, %s xcvr\n", (smc->cfg & CFG_MII_SELECT) ?
1098 "MII" : if_names[dev->if_port]);
1099 }
1100
1101 if (smc->cfg & CFG_MII_SELECT) {
1102 if (smc->mii_if.phy_id != -1) {
1103 DEBUG(0, " MII transceiver at index %d, status %x.\n",
1104 smc->mii_if.phy_id, j);
1105 } else {
1106 printk(KERN_NOTICE " No MII transceivers found!\n");
1107 }
1108 }
Dominik Brodowski15b99ac2006-03-31 17:26:06 +02001109 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110
1111config_undo:
1112 unregister_netdev(dev);
1113config_failed: /* CS_EXIT_TEST() calls jump to here... */
1114 smc91c92_release(link);
Dominik Brodowski15b99ac2006-03-31 17:26:06 +02001115 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116} /* smc91c92_config */
1117
1118/*======================================================================
1119
1120 After a card is removed, smc91c92_release() will unregister the net
1121 device, and release the PCMCIA configuration. If the device is
1122 still open, this will be postponed until it is closed.
1123
1124======================================================================*/
1125
Dominik Brodowskifba395e2006-03-31 17:21:06 +02001126static void smc91c92_release(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127{
Dominik Brodowski5f2a71f2006-01-15 09:32:39 +01001128 DEBUG(0, "smc91c92_release(0x%p)\n", link);
1129 if (link->win) {
1130 struct net_device *dev = link->priv;
1131 struct smc_private *smc = netdev_priv(dev);
1132 iounmap(smc->base);
1133 }
Dominik Brodowskifba395e2006-03-31 17:21:06 +02001134 pcmcia_disable_device(link);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135}
1136
1137/*======================================================================
1138
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139 MII interface support for SMC91cXX based cards
1140======================================================================*/
1141
1142#define MDIO_SHIFT_CLK 0x04
1143#define MDIO_DATA_OUT 0x01
1144#define MDIO_DIR_WRITE 0x08
1145#define MDIO_DATA_WRITE0 (MDIO_DIR_WRITE)
1146#define MDIO_DATA_WRITE1 (MDIO_DIR_WRITE | MDIO_DATA_OUT)
1147#define MDIO_DATA_READ 0x02
1148
Olof Johansson906da802008-02-04 22:27:35 -08001149static void mdio_sync(unsigned int addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150{
1151 int bits;
1152 for (bits = 0; bits < 32; bits++) {
1153 outb(MDIO_DATA_WRITE1, addr);
1154 outb(MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, addr);
1155 }
1156}
1157
1158static int mdio_read(struct net_device *dev, int phy_id, int loc)
1159{
Olof Johansson906da802008-02-04 22:27:35 -08001160 unsigned int addr = dev->base_addr + MGMT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161 u_int cmd = (0x06<<10)|(phy_id<<5)|loc;
1162 int i, retval = 0;
1163
1164 mdio_sync(addr);
1165 for (i = 13; i >= 0; i--) {
1166 int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
1167 outb(dat, addr);
1168 outb(dat | MDIO_SHIFT_CLK, addr);
1169 }
1170 for (i = 19; i > 0; i--) {
1171 outb(0, addr);
1172 retval = (retval << 1) | ((inb(addr) & MDIO_DATA_READ) != 0);
1173 outb(MDIO_SHIFT_CLK, addr);
1174 }
1175 return (retval>>1) & 0xffff;
1176}
1177
1178static void mdio_write(struct net_device *dev, int phy_id, int loc, int value)
1179{
Olof Johansson906da802008-02-04 22:27:35 -08001180 unsigned int addr = dev->base_addr + MGMT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181 u_int cmd = (0x05<<28)|(phy_id<<23)|(loc<<18)|(1<<17)|value;
1182 int i;
1183
1184 mdio_sync(addr);
1185 for (i = 31; i >= 0; i--) {
1186 int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
1187 outb(dat, addr);
1188 outb(dat | MDIO_SHIFT_CLK, addr);
1189 }
1190 for (i = 1; i >= 0; i--) {
1191 outb(0, addr);
1192 outb(MDIO_SHIFT_CLK, addr);
1193 }
1194}
1195
1196/*======================================================================
1197
1198 The driver core code, most of which should be common with a
1199 non-PCMCIA implementation.
1200
1201======================================================================*/
1202
1203#ifdef PCMCIA_DEBUG
1204static void smc_dump(struct net_device *dev)
1205{
Olof Johansson906da802008-02-04 22:27:35 -08001206 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207 u_short i, w, save;
1208 save = inw(ioaddr + BANK_SELECT);
1209 for (w = 0; w < 4; w++) {
1210 SMC_SELECT_BANK(w);
1211 printk(KERN_DEBUG "bank %d: ", w);
1212 for (i = 0; i < 14; i += 2)
1213 printk(" %04x", inw(ioaddr + i));
1214 printk("\n");
1215 }
1216 outw(save, ioaddr + BANK_SELECT);
1217}
1218#endif
1219
1220static int smc_open(struct net_device *dev)
1221{
1222 struct smc_private *smc = netdev_priv(dev);
Dominik Brodowskifba395e2006-03-31 17:21:06 +02001223 struct pcmcia_device *link = smc->p_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224
1225#ifdef PCMCIA_DEBUG
1226 DEBUG(0, "%s: smc_open(%p), ID/Window %4.4x.\n",
1227 dev->name, dev, inw(dev->base_addr + BANK_SELECT));
1228 if (pc_debug > 1) smc_dump(dev);
1229#endif
1230
1231 /* Check that the PCMCIA card is still here. */
Dominik Brodowski9940ec32006-03-05 11:04:33 +01001232 if (!pcmcia_dev_present(link))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233 return -ENODEV;
1234 /* Physical device present signature. */
1235 if (check_sig(link) < 0) {
1236 printk("smc91c92_cs: Yikes! Bad chip signature!\n");
1237 return -ENODEV;
1238 }
1239 link->open++;
1240
1241 netif_start_queue(dev);
1242 smc->saved_skb = NULL;
1243 smc->packets_waiting = 0;
1244
1245 smc_reset(dev);
1246 init_timer(&smc->media);
1247 smc->media.function = &media_check;
1248 smc->media.data = (u_long) dev;
1249 smc->media.expires = jiffies + HZ;
1250 add_timer(&smc->media);
1251
1252 return 0;
1253} /* smc_open */
1254
1255/*====================================================================*/
1256
1257static int smc_close(struct net_device *dev)
1258{
1259 struct smc_private *smc = netdev_priv(dev);
Dominik Brodowskifba395e2006-03-31 17:21:06 +02001260 struct pcmcia_device *link = smc->p_dev;
Olof Johansson906da802008-02-04 22:27:35 -08001261 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262
1263 DEBUG(0, "%s: smc_close(), status %4.4x.\n",
1264 dev->name, inw(ioaddr + BANK_SELECT));
1265
1266 netif_stop_queue(dev);
1267
1268 /* Shut off all interrupts, and turn off the Tx and Rx sections.
1269 Don't bother to check for chip present. */
1270 SMC_SELECT_BANK(2); /* Nominally paranoia, but do no assume... */
1271 outw(0, ioaddr + INTERRUPT);
1272 SMC_SELECT_BANK(0);
1273 mask_bits(0xff00, ioaddr + RCR);
1274 mask_bits(0xff00, ioaddr + TCR);
1275
1276 /* Put the chip into power-down mode. */
1277 SMC_SELECT_BANK(1);
1278 outw(CTL_POWERDOWN, ioaddr + CONTROL );
1279
1280 link->open--;
1281 del_timer_sync(&smc->media);
1282
1283 return 0;
1284} /* smc_close */
1285
1286/*======================================================================
1287
1288 Transfer a packet to the hardware and trigger the packet send.
1289 This may be called at either from either the Tx queue code
1290 or the interrupt handler.
1291
1292======================================================================*/
1293
1294static void smc_hardware_send_packet(struct net_device * dev)
1295{
1296 struct smc_private *smc = netdev_priv(dev);
1297 struct sk_buff *skb = smc->saved_skb;
Olof Johansson906da802008-02-04 22:27:35 -08001298 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299 u_char packet_no;
1300
1301 if (!skb) {
1302 printk(KERN_ERR "%s: In XMIT with no packet to send.\n", dev->name);
1303 return;
1304 }
1305
1306 /* There should be a packet slot waiting. */
1307 packet_no = inw(ioaddr + PNR_ARR) >> 8;
1308 if (packet_no & 0x80) {
1309 /* If not, there is a hardware problem! Likely an ejected card. */
1310 printk(KERN_WARNING "%s: 91c92 hardware Tx buffer allocation"
1311 " failed, status %#2.2x.\n", dev->name, packet_no);
1312 dev_kfree_skb_irq(skb);
1313 smc->saved_skb = NULL;
1314 netif_start_queue(dev);
1315 return;
1316 }
1317
Stephen Hemminger6fb72982009-03-20 19:36:09 +00001318 dev->stats.tx_bytes += skb->len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319 /* The card should use the just-allocated buffer. */
1320 outw(packet_no, ioaddr + PNR_ARR);
1321 /* point to the beginning of the packet */
1322 outw(PTR_AUTOINC , ioaddr + POINTER);
1323
1324 /* Send the packet length (+6 for status, length and ctl byte)
1325 and the status word (set to zeros). */
1326 {
1327 u_char *buf = skb->data;
1328 u_int length = skb->len; /* The chip will pad to ethernet min. */
1329
1330 DEBUG(2, "%s: Trying to xmit packet of length %d.\n",
1331 dev->name, length);
1332
1333 /* send the packet length: +6 for status word, length, and ctl */
1334 outw(0, ioaddr + DATA_1);
1335 outw(length + 6, ioaddr + DATA_1);
1336 outsw(ioaddr + DATA_1, buf, length >> 1);
1337
1338 /* The odd last byte, if there is one, goes in the control word. */
1339 outw((length & 1) ? 0x2000 | buf[length-1] : 0, ioaddr + DATA_1);
1340 }
1341
1342 /* Enable the Tx interrupts, both Tx (TxErr) and TxEmpty. */
1343 outw(((IM_TX_INT|IM_TX_EMPTY_INT)<<8) |
1344 (inw(ioaddr + INTERRUPT) & 0xff00),
1345 ioaddr + INTERRUPT);
1346
1347 /* The chip does the rest of the work. */
1348 outw(MC_ENQUEUE , ioaddr + MMU_CMD);
1349
1350 smc->saved_skb = NULL;
1351 dev_kfree_skb_irq(skb);
1352 dev->trans_start = jiffies;
1353 netif_start_queue(dev);
1354 return;
1355}
1356
1357/*====================================================================*/
1358
1359static void smc_tx_timeout(struct net_device *dev)
1360{
1361 struct smc_private *smc = netdev_priv(dev);
Olof Johansson906da802008-02-04 22:27:35 -08001362 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363
1364 printk(KERN_NOTICE "%s: SMC91c92 transmit timed out, "
1365 "Tx_status %2.2x status %4.4x.\n",
1366 dev->name, inw(ioaddr)&0xff, inw(ioaddr + 2));
Stephen Hemminger6fb72982009-03-20 19:36:09 +00001367 dev->stats.tx_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368 smc_reset(dev);
1369 dev->trans_start = jiffies;
1370 smc->saved_skb = NULL;
1371 netif_wake_queue(dev);
1372}
1373
Stephen Hemmingerdbf02fa2009-08-31 19:50:49 +00001374static netdev_tx_t smc_start_xmit(struct sk_buff *skb,
1375 struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376{
1377 struct smc_private *smc = netdev_priv(dev);
Olof Johansson906da802008-02-04 22:27:35 -08001378 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379 u_short num_pages;
1380 short time_out, ir;
Komuro85e27832007-07-23 21:36:06 +09001381 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382
1383 netif_stop_queue(dev);
1384
1385 DEBUG(2, "%s: smc_start_xmit(length = %d) called,"
1386 " status %4.4x.\n", dev->name, skb->len, inw(ioaddr + 2));
1387
1388 if (smc->saved_skb) {
1389 /* THIS SHOULD NEVER HAPPEN. */
Stephen Hemminger6fb72982009-03-20 19:36:09 +00001390 dev->stats.tx_aborted_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391 printk(KERN_DEBUG "%s: Internal error -- sent packet while busy.\n",
1392 dev->name);
Patrick McHardy5b548142009-06-12 06:22:29 +00001393 return NETDEV_TX_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394 }
1395 smc->saved_skb = skb;
1396
1397 num_pages = skb->len >> 8;
1398
1399 if (num_pages > 7) {
1400 printk(KERN_ERR "%s: Far too big packet error.\n", dev->name);
1401 dev_kfree_skb (skb);
1402 smc->saved_skb = NULL;
Stephen Hemminger6fb72982009-03-20 19:36:09 +00001403 dev->stats.tx_dropped++;
Patrick McHardy6ed10652009-06-23 06:03:08 +00001404 return NETDEV_TX_OK; /* Do not re-queue this packet. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405 }
1406 /* A packet is now waiting. */
1407 smc->packets_waiting++;
1408
Komuro85e27832007-07-23 21:36:06 +09001409 spin_lock_irqsave(&smc->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410 SMC_SELECT_BANK(2); /* Paranoia, we should always be in window 2 */
1411
1412 /* need MC_RESET to keep the memory consistent. errata? */
1413 if (smc->rx_ovrn) {
1414 outw(MC_RESET, ioaddr + MMU_CMD);
1415 smc->rx_ovrn = 0;
1416 }
1417
1418 /* Allocate the memory; send the packet now if we win. */
1419 outw(MC_ALLOC | num_pages, ioaddr + MMU_CMD);
1420 for (time_out = MEMORY_WAIT_TIME; time_out >= 0; time_out--) {
1421 ir = inw(ioaddr+INTERRUPT);
1422 if (ir & IM_ALLOC_INT) {
1423 /* Acknowledge the interrupt, send the packet. */
1424 outw((ir&0xff00) | IM_ALLOC_INT, ioaddr + INTERRUPT);
1425 smc_hardware_send_packet(dev); /* Send the packet now.. */
Komuro85e27832007-07-23 21:36:06 +09001426 spin_unlock_irqrestore(&smc->lock, flags);
Patrick McHardy6ed10652009-06-23 06:03:08 +00001427 return NETDEV_TX_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428 }
1429 }
1430
1431 /* Otherwise defer until the Tx-space-allocated interrupt. */
1432 DEBUG(2, "%s: memory allocation deferred.\n", dev->name);
1433 outw((IM_ALLOC_INT << 8) | (ir & 0xff00), ioaddr + INTERRUPT);
Komuro85e27832007-07-23 21:36:06 +09001434 spin_unlock_irqrestore(&smc->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001435
Patrick McHardy6ed10652009-06-23 06:03:08 +00001436 return NETDEV_TX_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437}
1438
1439/*======================================================================
1440
1441 Handle a Tx anomolous event. Entered while in Window 2.
1442
1443======================================================================*/
1444
1445static void smc_tx_err(struct net_device * dev)
1446{
1447 struct smc_private *smc = netdev_priv(dev);
Olof Johansson906da802008-02-04 22:27:35 -08001448 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449 int saved_packet = inw(ioaddr + PNR_ARR) & 0xff;
1450 int packet_no = inw(ioaddr + FIFO_PORTS) & 0x7f;
1451 int tx_status;
1452
1453 /* select this as the packet to read from */
1454 outw(packet_no, ioaddr + PNR_ARR);
1455
1456 /* read the first word from this packet */
1457 outw(PTR_AUTOINC | PTR_READ | 0, ioaddr + POINTER);
1458
1459 tx_status = inw(ioaddr + DATA_1);
1460
Stephen Hemminger6fb72982009-03-20 19:36:09 +00001461 dev->stats.tx_errors++;
1462 if (tx_status & TS_LOSTCAR) dev->stats.tx_carrier_errors++;
1463 if (tx_status & TS_LATCOL) dev->stats.tx_window_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464 if (tx_status & TS_16COL) {
Stephen Hemminger6fb72982009-03-20 19:36:09 +00001465 dev->stats.tx_aborted_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466 smc->tx_err++;
1467 }
1468
1469 if (tx_status & TS_SUCCESS) {
1470 printk(KERN_NOTICE "%s: Successful packet caused error "
1471 "interrupt?\n", dev->name);
1472 }
1473 /* re-enable transmit */
1474 SMC_SELECT_BANK(0);
1475 outw(inw(ioaddr + TCR) | TCR_ENABLE | smc->duplex, ioaddr + TCR);
1476 SMC_SELECT_BANK(2);
1477
1478 outw(MC_FREEPKT, ioaddr + MMU_CMD); /* Free the packet memory. */
1479
1480 /* one less packet waiting for me */
1481 smc->packets_waiting--;
1482
1483 outw(saved_packet, ioaddr + PNR_ARR);
1484 return;
1485}
1486
1487/*====================================================================*/
1488
1489static void smc_eph_irq(struct net_device *dev)
1490{
1491 struct smc_private *smc = netdev_priv(dev);
Olof Johansson906da802008-02-04 22:27:35 -08001492 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493 u_short card_stats, ephs;
1494
1495 SMC_SELECT_BANK(0);
1496 ephs = inw(ioaddr + EPH);
1497 DEBUG(2, "%s: Ethernet protocol handler interrupt, status"
1498 " %4.4x.\n", dev->name, ephs);
1499 /* Could be a counter roll-over warning: update stats. */
1500 card_stats = inw(ioaddr + COUNTER);
1501 /* single collisions */
Stephen Hemminger6fb72982009-03-20 19:36:09 +00001502 dev->stats.collisions += card_stats & 0xF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001503 card_stats >>= 4;
1504 /* multiple collisions */
Stephen Hemminger6fb72982009-03-20 19:36:09 +00001505 dev->stats.collisions += card_stats & 0xF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001506#if 0 /* These are for when linux supports these statistics */
1507 card_stats >>= 4; /* deferred */
1508 card_stats >>= 4; /* excess deferred */
1509#endif
1510 /* If we had a transmit error we must re-enable the transmitter. */
1511 outw(inw(ioaddr + TCR) | TCR_ENABLE | smc->duplex, ioaddr + TCR);
1512
1513 /* Clear a link error interrupt. */
1514 SMC_SELECT_BANK(1);
1515 outw(CTL_AUTO_RELEASE | 0x0000, ioaddr + CONTROL);
1516 outw(CTL_AUTO_RELEASE | CTL_TE_ENABLE | CTL_CR_ENABLE,
1517 ioaddr + CONTROL);
1518 SMC_SELECT_BANK(2);
1519}
1520
1521/*====================================================================*/
1522
David Howells7d12e782006-10-05 14:55:46 +01001523static irqreturn_t smc_interrupt(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524{
1525 struct net_device *dev = dev_id;
1526 struct smc_private *smc = netdev_priv(dev);
Olof Johansson906da802008-02-04 22:27:35 -08001527 unsigned int ioaddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528 u_short saved_bank, saved_pointer, mask, status;
1529 unsigned int handled = 1;
1530 char bogus_cnt = INTR_WORK; /* Work we are willing to do. */
1531
1532 if (!netif_device_present(dev))
1533 return IRQ_NONE;
1534
1535 ioaddr = dev->base_addr;
1536
1537 DEBUG(3, "%s: SMC91c92 interrupt %d at %#x.\n", dev->name,
1538 irq, ioaddr);
1539
Komuro85e27832007-07-23 21:36:06 +09001540 spin_lock(&smc->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541 smc->watchdog = 0;
1542 saved_bank = inw(ioaddr + BANK_SELECT);
1543 if ((saved_bank & 0xff00) != 0x3300) {
1544 /* The device does not exist -- the card could be off-line, or
1545 maybe it has been ejected. */
1546 DEBUG(1, "%s: SMC91c92 interrupt %d for non-existent"
1547 "/ejected device.\n", dev->name, irq);
1548 handled = 0;
1549 goto irq_done;
1550 }
1551
1552 SMC_SELECT_BANK(2);
1553 saved_pointer = inw(ioaddr + POINTER);
1554 mask = inw(ioaddr + INTERRUPT) >> 8;
1555 /* clear all interrupts */
1556 outw(0, ioaddr + INTERRUPT);
1557
1558 do { /* read the status flag, and mask it */
1559 status = inw(ioaddr + INTERRUPT) & 0xff;
1560 DEBUG(3, "%s: Status is %#2.2x (mask %#2.2x).\n", dev->name,
1561 status, mask);
1562 if ((status & mask) == 0) {
1563 if (bogus_cnt == INTR_WORK)
1564 handled = 0;
1565 break;
1566 }
1567 if (status & IM_RCV_INT) {
1568 /* Got a packet(s). */
1569 smc_rx(dev);
1570 }
1571 if (status & IM_TX_INT) {
1572 smc_tx_err(dev);
1573 outw(IM_TX_INT, ioaddr + INTERRUPT);
1574 }
1575 status &= mask;
1576 if (status & IM_TX_EMPTY_INT) {
1577 outw(IM_TX_EMPTY_INT, ioaddr + INTERRUPT);
1578 mask &= ~IM_TX_EMPTY_INT;
Stephen Hemminger6fb72982009-03-20 19:36:09 +00001579 dev->stats.tx_packets += smc->packets_waiting;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001580 smc->packets_waiting = 0;
1581 }
1582 if (status & IM_ALLOC_INT) {
1583 /* Clear this interrupt so it doesn't happen again */
1584 mask &= ~IM_ALLOC_INT;
1585
1586 smc_hardware_send_packet(dev);
1587
1588 /* enable xmit interrupts based on this */
1589 mask |= (IM_TX_EMPTY_INT | IM_TX_INT);
1590
1591 /* and let the card send more packets to me */
1592 netif_wake_queue(dev);
1593 }
1594 if (status & IM_RX_OVRN_INT) {
Stephen Hemminger6fb72982009-03-20 19:36:09 +00001595 dev->stats.rx_errors++;
1596 dev->stats.rx_fifo_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001597 if (smc->duplex)
1598 smc->rx_ovrn = 1; /* need MC_RESET outside smc_interrupt */
1599 outw(IM_RX_OVRN_INT, ioaddr + INTERRUPT);
1600 }
1601 if (status & IM_EPH_INT)
1602 smc_eph_irq(dev);
1603 } while (--bogus_cnt);
1604
1605 DEBUG(3, " Restoring saved registers mask %2.2x bank %4.4x"
1606 " pointer %4.4x.\n", mask, saved_bank, saved_pointer);
1607
1608 /* restore state register */
1609 outw((mask<<8), ioaddr + INTERRUPT);
1610 outw(saved_pointer, ioaddr + POINTER);
1611 SMC_SELECT_BANK(saved_bank);
1612
1613 DEBUG(3, "%s: Exiting interrupt IRQ%d.\n", dev->name, irq);
1614
1615irq_done:
1616
1617 if ((smc->manfid == MANFID_OSITECH) &&
1618 (smc->cardid != PRODID_OSITECH_SEVEN)) {
1619 /* Retrigger interrupt if needed */
1620 mask_bits(0x00ff, ioaddr-0x10+OSITECH_RESET_ISR);
1621 set_bits(0x0300, ioaddr-0x10+OSITECH_RESET_ISR);
1622 }
1623 if (smc->manfid == MANFID_MOTOROLA) {
1624 u_char cor;
1625 cor = readb(smc->base + MOT_UART + CISREG_COR);
1626 writeb(cor & ~COR_IREQ_ENA, smc->base + MOT_UART + CISREG_COR);
1627 writeb(cor, smc->base + MOT_UART + CISREG_COR);
1628 cor = readb(smc->base + MOT_LAN + CISREG_COR);
1629 writeb(cor & ~COR_IREQ_ENA, smc->base + MOT_LAN + CISREG_COR);
1630 writeb(cor, smc->base + MOT_LAN + CISREG_COR);
1631 }
1632#ifdef DOES_NOT_WORK
1633 if (smc->base != NULL) { /* Megahertz MFC's */
1634 readb(smc->base+MEGAHERTZ_ISR);
1635 readb(smc->base+MEGAHERTZ_ISR);
1636 }
1637#endif
Komuro85e27832007-07-23 21:36:06 +09001638 spin_unlock(&smc->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001639 return IRQ_RETVAL(handled);
1640}
1641
1642/*====================================================================*/
1643
1644static void smc_rx(struct net_device *dev)
1645{
Olof Johansson906da802008-02-04 22:27:35 -08001646 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001647 int rx_status;
1648 int packet_length; /* Caution: not frame length, rather words
1649 to transfer from the chip. */
1650
1651 /* Assertion: we are in Window 2. */
1652
1653 if (inw(ioaddr + FIFO_PORTS) & FP_RXEMPTY) {
1654 printk(KERN_ERR "%s: smc_rx() with nothing on Rx FIFO.\n",
1655 dev->name);
1656 return;
1657 }
1658
1659 /* Reset the read pointer, and read the status and packet length. */
1660 outw(PTR_READ | PTR_RCV | PTR_AUTOINC, ioaddr + POINTER);
1661 rx_status = inw(ioaddr + DATA_1);
1662 packet_length = inw(ioaddr + DATA_1) & 0x07ff;
1663
1664 DEBUG(2, "%s: Receive status %4.4x length %d.\n",
1665 dev->name, rx_status, packet_length);
1666
1667 if (!(rx_status & RS_ERRORS)) {
1668 /* do stuff to make a new packet */
1669 struct sk_buff *skb;
1670
1671 /* Note: packet_length adds 5 or 6 extra bytes here! */
1672 skb = dev_alloc_skb(packet_length+2);
1673
1674 if (skb == NULL) {
1675 DEBUG(1, "%s: Low memory, packet dropped.\n", dev->name);
Stephen Hemminger6fb72982009-03-20 19:36:09 +00001676 dev->stats.rx_dropped++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677 outw(MC_RELEASE, ioaddr + MMU_CMD);
1678 return;
1679 }
1680
1681 packet_length -= (rx_status & RS_ODDFRAME ? 5 : 6);
1682 skb_reserve(skb, 2);
1683 insw(ioaddr+DATA_1, skb_put(skb, packet_length),
1684 (packet_length+1)>>1);
1685 skb->protocol = eth_type_trans(skb, dev);
1686
Linus Torvalds1da177e2005-04-16 15:20:36 -07001687 netif_rx(skb);
1688 dev->last_rx = jiffies;
Stephen Hemminger6fb72982009-03-20 19:36:09 +00001689 dev->stats.rx_packets++;
1690 dev->stats.rx_bytes += packet_length;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691 if (rx_status & RS_MULTICAST)
Stephen Hemminger6fb72982009-03-20 19:36:09 +00001692 dev->stats.multicast++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001693 } else {
1694 /* error ... */
Stephen Hemminger6fb72982009-03-20 19:36:09 +00001695 dev->stats.rx_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696
Stephen Hemminger6fb72982009-03-20 19:36:09 +00001697 if (rx_status & RS_ALGNERR) dev->stats.rx_frame_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001698 if (rx_status & (RS_TOOSHORT | RS_TOOLONG))
Stephen Hemminger6fb72982009-03-20 19:36:09 +00001699 dev->stats.rx_length_errors++;
1700 if (rx_status & RS_BADCRC) dev->stats.rx_crc_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001701 }
1702 /* Let the MMU free the memory of this packet. */
1703 outw(MC_RELEASE, ioaddr + MMU_CMD);
1704
1705 return;
1706}
1707
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708/*======================================================================
1709
1710 Calculate values for the hardware multicast filter hash table.
1711
1712======================================================================*/
1713
1714static void fill_multicast_tbl(int count, struct dev_mc_list *addrs,
1715 u_char *multicast_table)
1716{
1717 struct dev_mc_list *mc_addr;
1718
Komurobb53d6d2005-10-03 22:03:28 -04001719 for (mc_addr = addrs; mc_addr && count-- > 0; mc_addr = mc_addr->next) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001720 u_int position = ether_crc(6, mc_addr->dmi_addr);
1721#ifndef final_version /* Verify multicast address. */
1722 if ((mc_addr->dmi_addr[0] & 1) == 0)
1723 continue;
1724#endif
1725 multicast_table[position >> 29] |= 1 << ((position >> 26) & 7);
1726 }
1727}
1728
1729/*======================================================================
1730
1731 Set the receive mode.
1732
1733 This routine is used by both the protocol level to notify us of
1734 promiscuous/multicast mode changes, and by the open/reset code to
1735 initialize the Rx registers. We always set the multicast list and
1736 leave the receiver running.
1737
1738======================================================================*/
1739
1740static void set_rx_mode(struct net_device *dev)
1741{
Olof Johansson906da802008-02-04 22:27:35 -08001742 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001743 struct smc_private *smc = netdev_priv(dev);
1744 u_int multicast_table[ 2 ] = { 0, };
1745 unsigned long flags;
1746 u_short rx_cfg_setting;
1747
1748 if (dev->flags & IFF_PROMISC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001749 rx_cfg_setting = RxStripCRC | RxEnable | RxPromisc | RxAllMulti;
1750 } else if (dev->flags & IFF_ALLMULTI)
1751 rx_cfg_setting = RxStripCRC | RxEnable | RxAllMulti;
1752 else {
1753 if (dev->mc_count) {
1754 fill_multicast_tbl(dev->mc_count, dev->mc_list,
1755 (u_char *)multicast_table);
1756 }
1757 rx_cfg_setting = RxStripCRC | RxEnable;
1758 }
1759
1760 /* Load MC table and Rx setting into the chip without interrupts. */
1761 spin_lock_irqsave(&smc->lock, flags);
1762 SMC_SELECT_BANK(3);
1763 outl(multicast_table[0], ioaddr + MULTICAST0);
1764 outl(multicast_table[1], ioaddr + MULTICAST4);
1765 SMC_SELECT_BANK(0);
1766 outw(rx_cfg_setting, ioaddr + RCR);
1767 SMC_SELECT_BANK(2);
1768 spin_unlock_irqrestore(&smc->lock, flags);
1769
1770 return;
1771}
1772
1773/*======================================================================
1774
1775 Senses when a card's config changes. Here, it's coax or TP.
1776
1777======================================================================*/
1778
1779static int s9k_config(struct net_device *dev, struct ifmap *map)
1780{
1781 struct smc_private *smc = netdev_priv(dev);
1782 if ((map->port != (u_char)(-1)) && (map->port != dev->if_port)) {
1783 if (smc->cfg & CFG_MII_SELECT)
1784 return -EOPNOTSUPP;
1785 else if (map->port > 2)
1786 return -EINVAL;
1787 dev->if_port = map->port;
1788 printk(KERN_INFO "%s: switched to %s port\n",
1789 dev->name, if_names[dev->if_port]);
1790 smc_reset(dev);
1791 }
1792 return 0;
1793}
1794
1795/*======================================================================
1796
1797 Reset the chip, reloading every register that might be corrupted.
1798
1799======================================================================*/
1800
1801/*
1802 Set transceiver type, perhaps to something other than what the user
1803 specified in dev->if_port.
1804*/
1805static void smc_set_xcvr(struct net_device *dev, int if_port)
1806{
1807 struct smc_private *smc = netdev_priv(dev);
Olof Johansson906da802008-02-04 22:27:35 -08001808 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001809 u_short saved_bank;
1810
1811 saved_bank = inw(ioaddr + BANK_SELECT);
1812 SMC_SELECT_BANK(1);
1813 if (if_port == 2) {
1814 outw(smc->cfg | CFG_AUI_SELECT, ioaddr + CONFIG);
1815 if ((smc->manfid == MANFID_OSITECH) &&
1816 (smc->cardid != PRODID_OSITECH_SEVEN))
1817 set_bits(OSI_AUI_PWR, ioaddr - 0x10 + OSITECH_AUI_PWR);
1818 smc->media_status = ((dev->if_port == 0) ? 0x0001 : 0x0002);
1819 } else {
1820 outw(smc->cfg, ioaddr + CONFIG);
1821 if ((smc->manfid == MANFID_OSITECH) &&
1822 (smc->cardid != PRODID_OSITECH_SEVEN))
1823 mask_bits(~OSI_AUI_PWR, ioaddr - 0x10 + OSITECH_AUI_PWR);
1824 smc->media_status = ((dev->if_port == 0) ? 0x0012 : 0x4001);
1825 }
1826 SMC_SELECT_BANK(saved_bank);
1827}
1828
1829static void smc_reset(struct net_device *dev)
1830{
Olof Johansson906da802008-02-04 22:27:35 -08001831 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001832 struct smc_private *smc = netdev_priv(dev);
1833 int i;
1834
1835 DEBUG(0, "%s: smc91c92 reset called.\n", dev->name);
1836
1837 /* The first interaction must be a write to bring the chip out
1838 of sleep mode. */
1839 SMC_SELECT_BANK(0);
1840 /* Reset the chip. */
1841 outw(RCR_SOFTRESET, ioaddr + RCR);
1842 udelay(10);
1843
1844 /* Clear the transmit and receive configuration registers. */
1845 outw(RCR_CLEAR, ioaddr + RCR);
1846 outw(TCR_CLEAR, ioaddr + TCR);
1847
1848 /* Set the Window 1 control, configuration and station addr registers.
1849 No point in writing the I/O base register ;-> */
1850 SMC_SELECT_BANK(1);
Andreas Mohrd6e05ed2006-06-26 18:35:02 +02001851 /* Automatically release successfully transmitted packets,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852 Accept link errors, counter and Tx error interrupts. */
1853 outw(CTL_AUTO_RELEASE | CTL_TE_ENABLE | CTL_CR_ENABLE,
1854 ioaddr + CONTROL);
1855 smc_set_xcvr(dev, dev->if_port);
1856 if ((smc->manfid == MANFID_OSITECH) &&
1857 (smc->cardid != PRODID_OSITECH_SEVEN))
1858 outw((dev->if_port == 2 ? OSI_AUI_PWR : 0) |
1859 (inw(ioaddr-0x10+OSITECH_AUI_PWR) & 0xff00),
1860 ioaddr - 0x10 + OSITECH_AUI_PWR);
1861
1862 /* Fill in the physical address. The databook is wrong about the order! */
1863 for (i = 0; i < 6; i += 2)
1864 outw((dev->dev_addr[i+1]<<8)+dev->dev_addr[i],
1865 ioaddr + ADDR0 + i);
1866
1867 /* Reset the MMU */
1868 SMC_SELECT_BANK(2);
1869 outw(MC_RESET, ioaddr + MMU_CMD);
1870 outw(0, ioaddr + INTERRUPT);
1871
1872 /* Re-enable the chip. */
1873 SMC_SELECT_BANK(0);
1874 outw(((smc->cfg & CFG_MII_SELECT) ? 0 : TCR_MONCSN) |
1875 TCR_ENABLE | TCR_PAD_EN | smc->duplex, ioaddr + TCR);
1876 set_rx_mode(dev);
1877
1878 if (smc->cfg & CFG_MII_SELECT) {
1879 SMC_SELECT_BANK(3);
1880
1881 /* Reset MII */
1882 mdio_write(dev, smc->mii_if.phy_id, 0, 0x8000);
1883
1884 /* Advertise 100F, 100H, 10F, 10H */
1885 mdio_write(dev, smc->mii_if.phy_id, 4, 0x01e1);
1886
1887 /* Restart MII autonegotiation */
1888 mdio_write(dev, smc->mii_if.phy_id, 0, 0x0000);
1889 mdio_write(dev, smc->mii_if.phy_id, 0, 0x1200);
1890 }
1891
1892 /* Enable interrupts. */
1893 SMC_SELECT_BANK(2);
1894 outw((IM_EPH_INT | IM_RX_OVRN_INT | IM_RCV_INT) << 8,
1895 ioaddr + INTERRUPT);
1896}
1897
1898/*======================================================================
1899
1900 Media selection timer routine
1901
1902======================================================================*/
1903
1904static void media_check(u_long arg)
1905{
1906 struct net_device *dev = (struct net_device *) arg;
1907 struct smc_private *smc = netdev_priv(dev);
Olof Johansson906da802008-02-04 22:27:35 -08001908 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001909 u_short i, media, saved_bank;
1910 u_short link;
Komuro85e27832007-07-23 21:36:06 +09001911 unsigned long flags;
1912
1913 spin_lock_irqsave(&smc->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001914
1915 saved_bank = inw(ioaddr + BANK_SELECT);
1916
1917 if (!netif_device_present(dev))
1918 goto reschedule;
1919
1920 SMC_SELECT_BANK(2);
1921
1922 /* need MC_RESET to keep the memory consistent. errata? */
1923 if (smc->rx_ovrn) {
1924 outw(MC_RESET, ioaddr + MMU_CMD);
1925 smc->rx_ovrn = 0;
1926 }
1927 i = inw(ioaddr + INTERRUPT);
1928 SMC_SELECT_BANK(0);
1929 media = inw(ioaddr + EPH) & EPH_LINK_OK;
1930 SMC_SELECT_BANK(1);
1931 media |= (inw(ioaddr + CONFIG) & CFG_AUI_SELECT) ? 2 : 1;
1932
1933 /* Check for pending interrupt with watchdog flag set: with
1934 this, we can limp along even if the interrupt is blocked */
1935 if (smc->watchdog++ && ((i>>8) & i)) {
1936 if (!smc->fast_poll)
1937 printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name);
Komuroe363d132007-02-10 11:57:35 +09001938 smc_interrupt(dev->irq, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001939 smc->fast_poll = HZ;
1940 }
1941 if (smc->fast_poll) {
1942 smc->fast_poll--;
1943 smc->media.expires = jiffies + HZ/100;
1944 add_timer(&smc->media);
1945 SMC_SELECT_BANK(saved_bank);
Komuro85e27832007-07-23 21:36:06 +09001946 spin_unlock_irqrestore(&smc->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001947 return;
1948 }
1949
1950 if (smc->cfg & CFG_MII_SELECT) {
1951 if (smc->mii_if.phy_id < 0)
1952 goto reschedule;
1953
1954 SMC_SELECT_BANK(3);
1955 link = mdio_read(dev, smc->mii_if.phy_id, 1);
1956 if (!link || (link == 0xffff)) {
1957 printk(KERN_INFO "%s: MII is missing!\n", dev->name);
1958 smc->mii_if.phy_id = -1;
1959 goto reschedule;
1960 }
1961
1962 link &= 0x0004;
1963 if (link != smc->link_status) {
1964 u_short p = mdio_read(dev, smc->mii_if.phy_id, 5);
1965 printk(KERN_INFO "%s: %s link beat\n", dev->name,
1966 (link) ? "found" : "lost");
1967 smc->duplex = (((p & 0x0100) || ((p & 0x1c0) == 0x40))
1968 ? TCR_FDUPLX : 0);
1969 if (link) {
1970 printk(KERN_INFO "%s: autonegotiation complete: "
1971 "%sbaseT-%cD selected\n", dev->name,
1972 ((p & 0x0180) ? "100" : "10"),
1973 (smc->duplex ? 'F' : 'H'));
1974 }
1975 SMC_SELECT_BANK(0);
1976 outw(inw(ioaddr + TCR) | smc->duplex, ioaddr + TCR);
1977 smc->link_status = link;
1978 }
1979 goto reschedule;
1980 }
1981
1982 /* Ignore collisions unless we've had no rx's recently */
Marcelo Feitoza Parisi4851d3a2005-07-15 10:00:41 -07001983 if (time_after(jiffies, dev->last_rx + HZ)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001984 if (smc->tx_err || (smc->media_status & EPH_16COL))
1985 media |= EPH_16COL;
1986 }
1987 smc->tx_err = 0;
1988
1989 if (media != smc->media_status) {
1990 if ((media & smc->media_status & 1) &&
1991 ((smc->media_status ^ media) & EPH_LINK_OK))
1992 printk(KERN_INFO "%s: %s link beat\n", dev->name,
1993 (smc->media_status & EPH_LINK_OK ? "lost" : "found"));
1994 else if ((media & smc->media_status & 2) &&
1995 ((smc->media_status ^ media) & EPH_16COL))
1996 printk(KERN_INFO "%s: coax cable %s\n", dev->name,
1997 (media & EPH_16COL ? "problem" : "ok"));
1998 if (dev->if_port == 0) {
1999 if (media & 1) {
2000 if (media & EPH_LINK_OK)
2001 printk(KERN_INFO "%s: flipped to 10baseT\n",
2002 dev->name);
2003 else
2004 smc_set_xcvr(dev, 2);
2005 } else {
2006 if (media & EPH_16COL)
2007 smc_set_xcvr(dev, 1);
2008 else
2009 printk(KERN_INFO "%s: flipped to 10base2\n",
2010 dev->name);
2011 }
2012 }
2013 smc->media_status = media;
2014 }
2015
2016reschedule:
2017 smc->media.expires = jiffies + HZ;
2018 add_timer(&smc->media);
2019 SMC_SELECT_BANK(saved_bank);
Komuro85e27832007-07-23 21:36:06 +09002020 spin_unlock_irqrestore(&smc->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002021}
2022
2023static int smc_link_ok(struct net_device *dev)
2024{
Olof Johansson906da802008-02-04 22:27:35 -08002025 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002026 struct smc_private *smc = netdev_priv(dev);
2027
2028 if (smc->cfg & CFG_MII_SELECT) {
2029 return mii_link_ok(&smc->mii_if);
2030 } else {
2031 SMC_SELECT_BANK(0);
2032 return inw(ioaddr + EPH) & EPH_LINK_OK;
2033 }
2034}
2035
2036static int smc_netdev_get_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd)
2037{
2038 u16 tmp;
Olof Johansson906da802008-02-04 22:27:35 -08002039 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002040
2041 ecmd->supported = (SUPPORTED_TP | SUPPORTED_AUI |
2042 SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full);
2043
2044 SMC_SELECT_BANK(1);
2045 tmp = inw(ioaddr + CONFIG);
2046 ecmd->port = (tmp & CFG_AUI_SELECT) ? PORT_AUI : PORT_TP;
2047 ecmd->transceiver = XCVR_INTERNAL;
2048 ecmd->speed = SPEED_10;
2049 ecmd->phy_address = ioaddr + MGMT;
2050
2051 SMC_SELECT_BANK(0);
2052 tmp = inw(ioaddr + TCR);
2053 ecmd->duplex = (tmp & TCR_FDUPLX) ? DUPLEX_FULL : DUPLEX_HALF;
2054
2055 return 0;
2056}
2057
2058static int smc_netdev_set_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd)
2059{
2060 u16 tmp;
Olof Johansson906da802008-02-04 22:27:35 -08002061 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002062
2063 if (ecmd->speed != SPEED_10)
2064 return -EINVAL;
2065 if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL)
2066 return -EINVAL;
2067 if (ecmd->port != PORT_TP && ecmd->port != PORT_AUI)
2068 return -EINVAL;
2069 if (ecmd->transceiver != XCVR_INTERNAL)
2070 return -EINVAL;
2071
2072 if (ecmd->port == PORT_AUI)
2073 smc_set_xcvr(dev, 1);
2074 else
2075 smc_set_xcvr(dev, 0);
2076
2077 SMC_SELECT_BANK(0);
2078 tmp = inw(ioaddr + TCR);
2079 if (ecmd->duplex == DUPLEX_FULL)
2080 tmp |= TCR_FDUPLX;
2081 else
2082 tmp &= ~TCR_FDUPLX;
2083 outw(tmp, ioaddr + TCR);
2084
2085 return 0;
2086}
2087
2088static int check_if_running(struct net_device *dev)
2089{
2090 if (!netif_running(dev))
2091 return -EINVAL;
2092 return 0;
2093}
2094
2095static void smc_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
2096{
2097 strcpy(info->driver, DRV_NAME);
2098 strcpy(info->version, DRV_VERSION);
2099}
2100
2101static int smc_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
2102{
2103 struct smc_private *smc = netdev_priv(dev);
Olof Johansson906da802008-02-04 22:27:35 -08002104 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002105 u16 saved_bank = inw(ioaddr + BANK_SELECT);
2106 int ret;
2107
Linus Torvalds1da177e2005-04-16 15:20:36 -07002108 spin_lock_irq(&smc->lock);
Komuro85e27832007-07-23 21:36:06 +09002109 SMC_SELECT_BANK(3);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002110 if (smc->cfg & CFG_MII_SELECT)
2111 ret = mii_ethtool_gset(&smc->mii_if, ecmd);
2112 else
2113 ret = smc_netdev_get_ecmd(dev, ecmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002114 SMC_SELECT_BANK(saved_bank);
Komuro85e27832007-07-23 21:36:06 +09002115 spin_unlock_irq(&smc->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002116 return ret;
2117}
2118
2119static int smc_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
2120{
2121 struct smc_private *smc = netdev_priv(dev);
Olof Johansson906da802008-02-04 22:27:35 -08002122 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002123 u16 saved_bank = inw(ioaddr + BANK_SELECT);
2124 int ret;
2125
Linus Torvalds1da177e2005-04-16 15:20:36 -07002126 spin_lock_irq(&smc->lock);
Komuro85e27832007-07-23 21:36:06 +09002127 SMC_SELECT_BANK(3);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002128 if (smc->cfg & CFG_MII_SELECT)
2129 ret = mii_ethtool_sset(&smc->mii_if, ecmd);
2130 else
2131 ret = smc_netdev_set_ecmd(dev, ecmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002132 SMC_SELECT_BANK(saved_bank);
Komuro85e27832007-07-23 21:36:06 +09002133 spin_unlock_irq(&smc->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002134 return ret;
2135}
2136
2137static u32 smc_get_link(struct net_device *dev)
2138{
2139 struct smc_private *smc = netdev_priv(dev);
Olof Johansson906da802008-02-04 22:27:35 -08002140 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002141 u16 saved_bank = inw(ioaddr + BANK_SELECT);
2142 u32 ret;
2143
Linus Torvalds1da177e2005-04-16 15:20:36 -07002144 spin_lock_irq(&smc->lock);
Komuro85e27832007-07-23 21:36:06 +09002145 SMC_SELECT_BANK(3);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002146 ret = smc_link_ok(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002147 SMC_SELECT_BANK(saved_bank);
Komuro85e27832007-07-23 21:36:06 +09002148 spin_unlock_irq(&smc->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002149 return ret;
2150}
2151
2152#ifdef PCMCIA_DEBUG
2153static u32 smc_get_msglevel(struct net_device *dev)
2154{
2155 return pc_debug;
2156}
2157
2158static void smc_set_msglevel(struct net_device *dev, u32 val)
2159{
2160 pc_debug = val;
2161}
2162#endif
2163
2164static int smc_nway_reset(struct net_device *dev)
2165{
2166 struct smc_private *smc = netdev_priv(dev);
2167 if (smc->cfg & CFG_MII_SELECT) {
Olof Johansson906da802008-02-04 22:27:35 -08002168 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169 u16 saved_bank = inw(ioaddr + BANK_SELECT);
2170 int res;
2171
2172 SMC_SELECT_BANK(3);
2173 res = mii_nway_restart(&smc->mii_if);
2174 SMC_SELECT_BANK(saved_bank);
2175
2176 return res;
2177 } else
2178 return -EOPNOTSUPP;
2179}
2180
Jeff Garzik7282d492006-09-13 14:30:00 -04002181static const struct ethtool_ops ethtool_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002182 .begin = check_if_running,
2183 .get_drvinfo = smc_get_drvinfo,
2184 .get_settings = smc_get_settings,
2185 .set_settings = smc_set_settings,
2186 .get_link = smc_get_link,
2187#ifdef PCMCIA_DEBUG
2188 .get_msglevel = smc_get_msglevel,
2189 .set_msglevel = smc_set_msglevel,
2190#endif
2191 .nway_reset = smc_nway_reset,
2192};
2193
2194static int smc_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
2195{
2196 struct smc_private *smc = netdev_priv(dev);
2197 struct mii_ioctl_data *mii = if_mii(rq);
2198 int rc = 0;
2199 u16 saved_bank;
Olof Johansson906da802008-02-04 22:27:35 -08002200 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002201
2202 if (!netif_running(dev))
2203 return -EINVAL;
2204
2205 spin_lock_irq(&smc->lock);
2206 saved_bank = inw(ioaddr + BANK_SELECT);
2207 SMC_SELECT_BANK(3);
2208 rc = generic_mii_ioctl(&smc->mii_if, mii, cmd, NULL);
2209 SMC_SELECT_BANK(saved_bank);
2210 spin_unlock_irq(&smc->lock);
2211 return rc;
2212}
2213
Dominik Brodowski5c672222005-06-27 16:28:27 -07002214static struct pcmcia_device_id smc91c92_ids[] = {
2215 PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0109, 0x0501),
2216 PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0140, 0x000a),
2217 PCMCIA_PFC_DEVICE_PROD_ID123(0, "MEGAHERTZ", "CC/XJEM3288", "DATA/FAX/CELL ETHERNET MODEM", 0xf510db04, 0x04cd2988, 0x46a52d63),
2218 PCMCIA_PFC_DEVICE_PROD_ID123(0, "MEGAHERTZ", "CC/XJEM3336", "DATA/FAX/CELL ETHERNET MODEM", 0xf510db04, 0x0143b773, 0x46a52d63),
2219 PCMCIA_PFC_DEVICE_PROD_ID123(0, "MEGAHERTZ", "EM1144T", "PCMCIA MODEM", 0xf510db04, 0x856d66c8, 0xbd6c43ef),
2220 PCMCIA_PFC_DEVICE_PROD_ID123(0, "MEGAHERTZ", "XJEM1144/CCEM1144", "PCMCIA MODEM", 0xf510db04, 0x52d21e1e, 0xbd6c43ef),
2221 PCMCIA_PFC_DEVICE_PROD_ID12(0, "Gateway 2000", "XJEM3336", 0xdd9989be, 0x662c394c),
2222 PCMCIA_PFC_DEVICE_PROD_ID12(0, "MEGAHERTZ", "XJEM1144/CCEM1144", 0xf510db04, 0x52d21e1e),
Komurod277ad02005-07-28 01:07:24 -07002223 PCMCIA_PFC_DEVICE_PROD_ID12(0, "Ositech", "Trumpcard:Jack of Diamonds Modem+Ethernet", 0xc2f80cd, 0x656947b9),
2224 PCMCIA_PFC_DEVICE_PROD_ID12(0, "Ositech", "Trumpcard:Jack of Hearts Modem+Ethernet", 0xc2f80cd, 0xdc9ba5ed),
Dominik Brodowski5c672222005-06-27 16:28:27 -07002225 PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x016c, 0x0020),
2226 PCMCIA_DEVICE_MANF_CARD(0x016c, 0x0023),
2227 PCMCIA_DEVICE_PROD_ID123("BASICS by New Media Corporation", "Ethernet", "SMC91C94", 0x23c78a9d, 0x00b2e941, 0xcef397fb),
2228 PCMCIA_DEVICE_PROD_ID12("ARGOSY", "Fast Ethernet PCCard", 0x78f308dc, 0xdcea68bc),
2229 PCMCIA_DEVICE_PROD_ID12("dit Co., Ltd.", "PC Card-10/100BTX", 0xe59365c8, 0x6a2161d1),
2230 PCMCIA_DEVICE_PROD_ID12("DYNALINK", "L100C", 0x6a26d1cf, 0xc16ce9c5),
2231 PCMCIA_DEVICE_PROD_ID12("Farallon", "Farallon Enet", 0x58d93fc4, 0x244734e9),
2232 PCMCIA_DEVICE_PROD_ID12("Megahertz", "CC10BT/2", 0x33234748, 0x3c95b953),
2233 PCMCIA_DEVICE_PROD_ID12("MELCO/SMC", "LPC-TX", 0xa2cd8e6d, 0x42da662a),
Komurod277ad02005-07-28 01:07:24 -07002234 PCMCIA_DEVICE_PROD_ID12("Ositech", "Trumpcard:Four of Diamonds Ethernet", 0xc2f80cd, 0xb3466314),
2235 PCMCIA_DEVICE_PROD_ID12("Ositech", "Trumpcard:Seven of Diamonds Ethernet", 0xc2f80cd, 0x194b650a),
Dominik Brodowski5c672222005-06-27 16:28:27 -07002236 PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Fast Ethernet PCCard", 0x281f1c5d, 0xdcea68bc),
2237 PCMCIA_DEVICE_PROD_ID12("Psion", "10Mb Ethernet", 0x4ef00b21, 0x844be9e9),
2238 PCMCIA_DEVICE_PROD_ID12("SMC", "EtherEZ Ethernet 8020", 0xc4f8b18b, 0x4a0eeb2d),
2239 /* These conflict with other cards! */
2240 /* PCMCIA_DEVICE_MANF_CARD(0x0186, 0x0100), */
2241 /* PCMCIA_DEVICE_MANF_CARD(0x8a01, 0xc1ab), */
2242 PCMCIA_DEVICE_NULL,
2243};
2244MODULE_DEVICE_TABLE(pcmcia, smc91c92_ids);
2245
Linus Torvalds1da177e2005-04-16 15:20:36 -07002246static struct pcmcia_driver smc91c92_cs_driver = {
2247 .owner = THIS_MODULE,
2248 .drv = {
2249 .name = "smc91c92_cs",
2250 },
Dominik Brodowski15b99ac2006-03-31 17:26:06 +02002251 .probe = smc91c92_probe,
Dominik Brodowskicc3b4862005-11-14 21:23:14 +01002252 .remove = smc91c92_detach,
Dominik Brodowski5c672222005-06-27 16:28:27 -07002253 .id_table = smc91c92_ids,
Dominik Brodowski98e4c282005-11-14 21:21:18 +01002254 .suspend = smc91c92_suspend,
2255 .resume = smc91c92_resume,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002256};
2257
2258static int __init init_smc91c92_cs(void)
2259{
2260 return pcmcia_register_driver(&smc91c92_cs_driver);
2261}
2262
2263static void __exit exit_smc91c92_cs(void)
2264{
2265 pcmcia_unregister_driver(&smc91c92_cs_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002266}
2267
2268module_init(init_smc91c92_cs);
2269module_exit(exit_smc91c92_cs);