blob: 859f8bec292b600061b23eea2322bbfe5e8d082f [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/* cs89x0.c: A Crystal Semiconductor (Now Cirrus Logic) CS89[02]0
Joe Perches204a38a2012-05-18 12:56:27 +00002 * driver for linux.
3 * Written 1996 by Russell Nelson, with reference to skeleton.c
4 * written 1993-1994 by Donald Becker.
5 *
6 * This software may be used and distributed according to the terms
7 * of the GNU General Public License, incorporated herein by reference.
8 *
9 * The author may be reached at nelson@crynwr.com, Crynwr
10 * Software, 521 Pleasant Valley Rd., Potsdam, NY 13676
11 *
12 * Other contributors:
13 * Mike Cruse : mcruse@cti-ltd.com
14 * Russ Nelson
15 * Melody Lee : ethernet@crystal.cirrus.com
16 * Alan Cox
17 * Andrew Morton
18 * Oskar Schirmer : oskar@scara.com
19 * Deepak Saxena : dsaxena@plexity.net
20 * Dmitry Pervushin : dpervushin@ru.mvista.com
21 * Deepak Saxena : dsaxena@plexity.net
22 * Domenico Andreoli : cavokz@gmail.com
Linus Torvalds1da177e2005-04-16 15:20:36 -070023 */
24
Linus Torvalds1da177e2005-04-16 15:20:36 -070025
26/*
27 * Set this to zero to disable DMA code
28 *
29 * Note that even if DMA is turned off we still support the 'dma' and 'use_dma'
30 * module options so we don't break any startup scripts.
31 */
Lennert Buytenhek91e1c462006-01-11 12:17:34 -080032#ifndef CONFIG_ISA_DMA_API
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#define ALLOW_DMA 0
34#else
35#define ALLOW_DMA 1
36#endif
37
38/*
39 * Set this to zero to remove all the debug statements via
40 * dead code elimination
41 */
42#define DEBUGGING 1
43
Joe Perches204a38a2012-05-18 12:56:27 +000044/* Sources:
45 * Crynwr packet driver epktisa.
46 * Crystal Semiconductor data sheets.
47 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070048
Joe Perchesdd92b9a2012-05-18 12:56:28 +000049#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
50
Jaccon Bastiaansene9460a92012-01-26 21:46:15 +010051#include <linux/module.h>
52#include <linux/printk.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070053#include <linux/errno.h>
54#include <linux/netdevice.h>
55#include <linux/etherdevice.h>
Jaccon Bastiaansene9460a92012-01-26 21:46:15 +010056#include <linux/platform_device.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070057#include <linux/kernel.h>
58#include <linux/types.h>
59#include <linux/fcntl.h>
60#include <linux/interrupt.h>
61#include <linux/ioport.h>
62#include <linux/in.h>
63#include <linux/skbuff.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070064#include <linux/spinlock.h>
65#include <linux/string.h>
66#include <linux/init.h>
67#include <linux/bitops.h>
68#include <linux/delay.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090069#include <linux/gfp.h>
Joe Perchesca034bc2012-05-18 12:56:29 +000070#include <linux/io.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070071
Al Viro7625d482005-09-26 05:25:59 +010072#include <asm/irq.h>
Jaccon Bastiaansene9460a92012-01-26 21:46:15 +010073#include <linux/atomic.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070074#if ALLOW_DMA
75#include <asm/dma.h>
76#endif
77
78#include "cs89x0.h"
79
Joe Perches808e9a72012-05-18 12:56:30 +000080#define cs89_dbg(val, level, fmt, ...) \
81do { \
82 if (val <= net_debug) \
83 pr_##level(fmt, ##__VA_ARGS__); \
84} while (0)
85
Linus Torvalds1da177e2005-04-16 15:20:36 -070086static char version[] __initdata =
Joe Perches808e9a72012-05-18 12:56:30 +000087 "v2.4.3-pre1 Russell Nelson <nelson@crynwr.com>, Andrew Morton";
Linus Torvalds1da177e2005-04-16 15:20:36 -070088
89#define DRV_NAME "cs89x0"
90
91/* First, a few definitions that the brave might change.
Joe Perches204a38a2012-05-18 12:56:27 +000092 * A zero-terminated list of I/O addresses to be probed. Some special flags..
93 * Addr & 1 = Read back the address port, look for signature and reset
94 * the page window before probing
95 * Addr & 3 = Reset the page window and probe
96 * The CLPS eval board has the Cirrus chip at 0x80090300, in ARM IO space,
97 * but it is possible that a Cirrus board could be plugged into the ISA
98 * slots.
99 */
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400100/* The cs8900 has 4 IRQ pins, software selectable. cs8900_irq_map maps
Joe Perches204a38a2012-05-18 12:56:27 +0000101 * them to system IRQ numbers. This mapping is card specific and is set to
102 * the configuration of the Cirrus Eval board for this chip.
103 */
Christoph Eggeref3cf9f2010-07-14 13:40:36 -0700104#if defined(CONFIG_MACH_IXDP2351)
Jaccon Bastiaansene9460a92012-01-26 21:46:15 +0100105#define CS89x0_NONISA_IRQ
Joe Perchesca034bc2012-05-18 12:56:29 +0000106static unsigned int netcard_portlist[] __used __initdata = {
107 IXDP2351_VIRT_CS8900_BASE, 0
108};
109static unsigned int cs8900_irq_map[] = {
110 IRQ_IXDP2351_CS8900, 0, 0, 0
111};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112#elif defined(CONFIG_ARCH_IXDP2X01)
Jaccon Bastiaansene9460a92012-01-26 21:46:15 +0100113#define CS89x0_NONISA_IRQ
Joe Perchesca034bc2012-05-18 12:56:29 +0000114static unsigned int netcard_portlist[] __used __initdata = {
115 IXDP2X01_CS8900_VIRT_BASE, 0
116};
117static unsigned int cs8900_irq_map[] = {
118 IRQ_IXDP2X01_CS8900, 0, 0, 0
119};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120#else
Jaccon Bastiaansene9460a92012-01-26 21:46:15 +0100121#ifndef CONFIG_CS89x0_PLATFORM
Joe Perchesca034bc2012-05-18 12:56:29 +0000122static unsigned int netcard_portlist[] __used __initdata = {
123 0x300, 0x320, 0x340, 0x360, 0x200, 0x220, 0x240,
124 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0
125};
126static unsigned int cs8900_irq_map[] = {
127 10, 11, 12, 5
128};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129#endif
Jaccon Bastiaansene9460a92012-01-26 21:46:15 +0100130#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131
132#if DEBUGGING
133static unsigned int net_debug = DEBUGGING;
134#else
135#define net_debug 0 /* gcc will remove all the debug code for us */
136#endif
137
138/* The number of low I/O ports used by the ethercard. */
139#define NETCARD_IO_EXTENT 16
140
141/* we allow the user to override various values normally set in the EEPROM */
142#define FORCE_RJ45 0x0001 /* pick one of these three */
143#define FORCE_AUI 0x0002
144#define FORCE_BNC 0x0004
145
146#define FORCE_AUTO 0x0010 /* pick one of these three */
147#define FORCE_HALF 0x0020
148#define FORCE_FULL 0x0030
149
150/* Information that need to be kept for each board. */
151struct net_local {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152 int chip_type; /* one of: CS8900, CS8920, CS8920M */
153 char chip_revision; /* revision letter of the chip ('A'...) */
154 int send_cmd; /* the proper send command: TX_NOW, TX_AFTER_381, or TX_AFTER_ALL */
155 int auto_neg_cnf; /* auto-negotiation word from EEPROM */
156 int adapter_cnf; /* adapter configuration from EEPROM */
157 int isa_config; /* ISA configuration from EEPROM */
158 int irq_map; /* IRQ map from EEPROM */
159 int rx_mode; /* what mode are we in? 0, RX_MULTCAST_ACCEPT, or RX_ALL_ACCEPT */
160 int curr_rx_cfg; /* a copy of PP_RxCFG */
161 int linectl; /* either 0 or LOW_RX_SQUELCH, depending on configuration. */
162 int send_underrun; /* keep track of how many underruns in a row we get */
163 int force; /* force various values; see FORCE* above. */
164 spinlock_t lock;
Jaccon Bastiaansen09dcd602012-05-17 07:11:42 +0000165 void __iomem *virt_addr;/* CS89x0 virtual address. */
166 unsigned long size; /* Length of CS89x0 memory region. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167#if ALLOW_DMA
168 int use_dma; /* Flag: we're using dma */
169 int dma; /* DMA channel */
170 int dmasize; /* 16 or 64 */
171 unsigned char *dma_buff; /* points to the beginning of the buffer */
172 unsigned char *end_dma_buff; /* points to the end of the buffer */
173 unsigned char *rx_dma_ptr; /* points to the next packet */
174#endif
175};
176
177/* Index to functions, as function prototypes. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178static int net_open(struct net_device *dev);
Stephen Hemminger613573252009-08-31 19:50:58 +0000179static netdev_tx_t net_send_packet(struct sk_buff *skb, struct net_device *dev);
David Howells7d12e782006-10-05 14:55:46 +0100180static irqreturn_t net_interrupt(int irq, void *dev_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181static void set_multicast_list(struct net_device *dev);
182static void net_timeout(struct net_device *dev);
183static void net_rx(struct net_device *dev);
184static int net_close(struct net_device *dev);
185static struct net_device_stats *net_get_stats(struct net_device *dev);
186static void reset_chip(struct net_device *dev);
187static int get_eeprom_data(struct net_device *dev, int off, int len, int *buffer);
188static int get_eeprom_cksum(int off, int len, int *buffer);
189static int set_mac_address(struct net_device *dev, void *addr);
Kulikov Vasiliy661a16c2010-07-05 02:13:15 +0000190static void count_rx_errors(int status, struct net_device *dev);
Deepak Saxena6f519162005-09-09 13:02:07 -0700191#ifdef CONFIG_NET_POLL_CONTROLLER
192static void net_poll_controller(struct net_device *dev);
193#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194#if ALLOW_DMA
195static void get_dma_channel(struct net_device *dev);
196static void release_dma_buff(struct net_local *lp);
197#endif
198
199/* Example routines you must write ;->. */
200#define tx_done(dev) 1
201
202/*
203 * Permit 'cs89x0_dma=N' in the kernel boot environment
204 */
Jaccon Bastiaansen09dcd602012-05-17 07:11:42 +0000205#if !defined(MODULE)
206#if ALLOW_DMA
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207static int g_cs89x0_dma;
208
209static int __init dma_fn(char *str)
210{
Joe Perches204a38a2012-05-18 12:56:27 +0000211 g_cs89x0_dma = simple_strtol(str, NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212 return 1;
213}
214
215__setup("cs89x0_dma=", dma_fn);
Jaccon Bastiaansen09dcd602012-05-17 07:11:42 +0000216#endif /* ALLOW_DMA */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218static int g_cs89x0_media__force;
219
220static int __init media_fn(char *str)
221{
Joe Perchesca034bc2012-05-18 12:56:29 +0000222 if (!strcmp(str, "rj45"))
223 g_cs89x0_media__force = FORCE_RJ45;
224 else if (!strcmp(str, "aui"))
225 g_cs89x0_media__force = FORCE_AUI;
226 else if (!strcmp(str, "bnc"))
227 g_cs89x0_media__force = FORCE_BNC;
228
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229 return 1;
230}
231
232__setup("cs89x0_media=", media_fn);
Jaccon Bastiaansene9460a92012-01-26 21:46:15 +0100233#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234
Deepak Saxena9c878962006-01-14 13:21:18 -0800235#if defined(CONFIG_MACH_IXDP2351)
236static u16
237readword(unsigned long base_addr, int portno)
238{
239 return __raw_readw(base_addr + (portno << 1));
240}
241
242static void
243writeword(unsigned long base_addr, int portno, u16 value)
244{
245 __raw_writew(value, base_addr + (portno << 1));
246}
247#elif defined(CONFIG_ARCH_IXDP2X01)
Lennert Buytenheka07f0db2006-01-14 13:21:17 -0800248static u16
Lennert Buytenhek3b68d702006-01-08 01:01:11 -0800249readword(unsigned long base_addr, int portno)
250{
Lennert Buytenheka07f0db2006-01-14 13:21:17 -0800251 return __raw_readl(base_addr + (portno << 1));
Lennert Buytenhek3b68d702006-01-08 01:01:11 -0800252}
253
254static void
Lennert Buytenheka07f0db2006-01-14 13:21:17 -0800255writeword(unsigned long base_addr, int portno, u16 value)
Lennert Buytenhek3b68d702006-01-08 01:01:11 -0800256{
Lennert Buytenheka07f0db2006-01-14 13:21:17 -0800257 __raw_writel(value, base_addr + (portno << 1));
Lennert Buytenhek3b68d702006-01-08 01:01:11 -0800258}
Lennert Buytenhek3b68d702006-01-08 01:01:11 -0800259#endif
Lennert Buytenhek0d5affc2006-01-08 01:01:09 -0800260
Jaccon Bastiaansen09dcd602012-05-17 07:11:42 +0000261static void readwords(struct net_local *lp, int portno, void *buf, int length)
Lennert Buytenhek084f7462006-01-08 01:01:12 -0800262{
263 u8 *buf8 = (u8 *)buf;
264
265 do {
Lennert Buytenheka07f0db2006-01-14 13:21:17 -0800266 u16 tmp16;
Lennert Buytenhek084f7462006-01-08 01:01:12 -0800267
Jaccon Bastiaansen09dcd602012-05-17 07:11:42 +0000268 tmp16 = ioread16(lp->virt_addr + portno);
Lennert Buytenheka07f0db2006-01-14 13:21:17 -0800269 *buf8++ = (u8)tmp16;
270 *buf8++ = (u8)(tmp16 >> 8);
Lennert Buytenhek084f7462006-01-08 01:01:12 -0800271 } while (--length);
272}
273
Jaccon Bastiaansen09dcd602012-05-17 07:11:42 +0000274static void writewords(struct net_local *lp, int portno, void *buf, int length)
Lennert Buytenhek084f7462006-01-08 01:01:12 -0800275{
276 u8 *buf8 = (u8 *)buf;
277
278 do {
Lennert Buytenheka07f0db2006-01-14 13:21:17 -0800279 u16 tmp16;
Lennert Buytenhek084f7462006-01-08 01:01:12 -0800280
Lennert Buytenheka07f0db2006-01-14 13:21:17 -0800281 tmp16 = *buf8++;
282 tmp16 |= (*buf8++) << 8;
Jaccon Bastiaansen09dcd602012-05-17 07:11:42 +0000283 iowrite16(tmp16, lp->virt_addr + portno);
Lennert Buytenhek084f7462006-01-08 01:01:12 -0800284 } while (--length);
285}
286
Lennert Buytenheka07f0db2006-01-14 13:21:17 -0800287static u16
288readreg(struct net_device *dev, u16 regno)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289{
Jaccon Bastiaansen09dcd602012-05-17 07:11:42 +0000290 struct net_local *lp = netdev_priv(dev);
291
292 iowrite16(regno, lp->virt_addr + ADD_PORT);
293 return ioread16(lp->virt_addr + DATA_PORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294}
295
296static void
Lennert Buytenheka07f0db2006-01-14 13:21:17 -0800297writereg(struct net_device *dev, u16 regno, u16 value)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298{
Jaccon Bastiaansen09dcd602012-05-17 07:11:42 +0000299 struct net_local *lp = netdev_priv(dev);
300
301 iowrite16(regno, lp->virt_addr + ADD_PORT);
302 iowrite16(value, lp->virt_addr + DATA_PORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303}
304
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305static int __init
306wait_eeprom_ready(struct net_device *dev)
307{
308 int timeout = jiffies;
Joe Perches204a38a2012-05-18 12:56:27 +0000309 /* check to see if the EEPROM is ready,
310 * a timeout is used just in case EEPROM is ready when
311 * SI_BUSY in the PP_SelfST is clear
312 */
313 while (readreg(dev, PP_SelfST) & SI_BUSY)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314 if (jiffies - timeout >= 40)
315 return -1;
316 return 0;
317}
318
319static int __init
320get_eeprom_data(struct net_device *dev, int off, int len, int *buffer)
321{
322 int i;
323
Joe Perches808e9a72012-05-18 12:56:30 +0000324 cs89_dbg(3, info, "EEPROM data from %x for %x:\n", off, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325 for (i = 0; i < len; i++) {
Joe Perchesca034bc2012-05-18 12:56:29 +0000326 if (wait_eeprom_ready(dev) < 0)
327 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328 /* Now send the EEPROM read command and EEPROM location to read */
329 writereg(dev, PP_EECMD, (off + i) | EEPROM_READ_CMD);
Joe Perchesca034bc2012-05-18 12:56:29 +0000330 if (wait_eeprom_ready(dev) < 0)
331 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332 buffer[i] = readreg(dev, PP_EEData);
Joe Perches808e9a72012-05-18 12:56:30 +0000333 cs89_dbg(3, cont, "%04x ", buffer[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334 }
Joe Perches808e9a72012-05-18 12:56:30 +0000335 cs89_dbg(3, cont, "\n");
Joe Perches204a38a2012-05-18 12:56:27 +0000336 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337}
338
339static int __init
340get_eeprom_cksum(int off, int len, int *buffer)
341{
342 int i, cksum;
343
344 cksum = 0;
345 for (i = 0; i < len; i++)
346 cksum += buffer[i];
347 cksum &= 0xffff;
348 if (cksum == 0)
349 return 0;
350 return -1;
351}
352
Deepak Saxena6f519162005-09-09 13:02:07 -0700353#ifdef CONFIG_NET_POLL_CONTROLLER
354/*
355 * Polling receive - used by netconsole and other diagnostic tools
356 * to allow network i/o with interrupts disabled.
357 */
358static void net_poll_controller(struct net_device *dev)
359{
360 disable_irq(dev->irq);
David Howells7d12e782006-10-05 14:55:46 +0100361 net_interrupt(dev->irq, dev);
Deepak Saxena6f519162005-09-09 13:02:07 -0700362 enable_irq(dev->irq);
363}
364#endif
365
Stephen Hemminger15d23e72009-03-26 15:11:43 +0000366static const struct net_device_ops net_ops = {
367 .ndo_open = net_open,
368 .ndo_stop = net_close,
369 .ndo_tx_timeout = net_timeout,
Joe Perches204a38a2012-05-18 12:56:27 +0000370 .ndo_start_xmit = net_send_packet,
Stephen Hemminger15d23e72009-03-26 15:11:43 +0000371 .ndo_get_stats = net_get_stats,
Jiri Pirkoafc4b132011-08-16 06:29:01 +0000372 .ndo_set_rx_mode = set_multicast_list,
Joe Perches204a38a2012-05-18 12:56:27 +0000373 .ndo_set_mac_address = set_mac_address,
Stephen Hemminger15d23e72009-03-26 15:11:43 +0000374#ifdef CONFIG_NET_POLL_CONTROLLER
375 .ndo_poll_controller = net_poll_controller,
376#endif
377 .ndo_change_mtu = eth_change_mtu,
378 .ndo_validate_addr = eth_validate_addr,
379};
380
Joe Perches204a38a2012-05-18 12:56:27 +0000381/* This is the real probe routine.
382 * Linux has a history of friendly device probes on the ISA bus.
383 * A good device probes avoids doing writes, and
384 * verifies that the correct device exists and functions.
385 * Return 0 on success.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387static int __init
Jaccon Bastiaansen09dcd602012-05-17 07:11:42 +0000388cs89x0_probe1(struct net_device *dev, void __iomem *ioaddr, int modular)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389{
390 struct net_local *lp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 int i;
Denis Vlasenko01bdc032005-07-31 22:34:50 -0700392 int tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393 unsigned rev_type = 0;
394 int eeprom_buff[CHKSUM_LEN];
395 int retval;
396
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397 /* Initialize the device structure. */
398 if (!modular) {
399 memset(lp, 0, sizeof(*lp));
400 spin_lock_init(&lp->lock);
401#ifndef MODULE
402#if ALLOW_DMA
403 if (g_cs89x0_dma) {
404 lp->use_dma = 1;
405 lp->dma = g_cs89x0_dma;
406 lp->dmasize = 16; /* Could make this an option... */
407 }
408#endif
409 lp->force = g_cs89x0_media__force;
410#endif
Joe Perches204a38a2012-05-18 12:56:27 +0000411 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412
Joe Perchesdd92b9a2012-05-18 12:56:28 +0000413 pr_debug("PP_addr at %p[%x]: 0x%x\n",
414 ioaddr, ADD_PORT, ioread16(ioaddr + ADD_PORT));
Jaccon Bastiaansen09dcd602012-05-17 07:11:42 +0000415 iowrite16(PP_ChipID, ioaddr + ADD_PORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416
Jaccon Bastiaansen09dcd602012-05-17 07:11:42 +0000417 tmp = ioread16(ioaddr + DATA_PORT);
Denis Vlasenko01bdc032005-07-31 22:34:50 -0700418 if (tmp != CHIP_EISA_ID_SIG) {
Joe Perchesdd92b9a2012-05-18 12:56:28 +0000419 pr_debug("%s: incorrect signature at %p[%x]: 0x%x!="
420 CHIP_EISA_ID_SIG_STR "\n",
421 dev->name, ioaddr, DATA_PORT, tmp);
Joe Perches204a38a2012-05-18 12:56:27 +0000422 retval = -ENODEV;
Jaccon Bastiaansen09dcd602012-05-17 07:11:42 +0000423 goto out1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424 }
425
Jaccon Bastiaansen09dcd602012-05-17 07:11:42 +0000426 lp->virt_addr = ioaddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427
428 /* get the chip type */
429 rev_type = readreg(dev, PRODUCT_ID_ADD);
Joe Perches204a38a2012-05-18 12:56:27 +0000430 lp->chip_type = rev_type & ~REVISON_BITS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431 lp->chip_revision = ((rev_type & REVISON_BITS) >> 8) + 'A';
432
433 /* Check the chip type and revision in order to set the correct send command
Joe Perches204a38a2012-05-18 12:56:27 +0000434 CS8920 revision C and CS8900 revision F can use the faster send. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435 lp->send_cmd = TX_AFTER_381;
436 if (lp->chip_type == CS8900 && lp->chip_revision >= 'F')
437 lp->send_cmd = TX_NOW;
438 if (lp->chip_type != CS8900 && lp->chip_revision >= 'C')
439 lp->send_cmd = TX_NOW;
440
Joe Perches808e9a72012-05-18 12:56:30 +0000441 pr_info_once("%s\n", version);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442
Joe Perchesdd92b9a2012-05-18 12:56:28 +0000443 pr_info("%s: cs89%c0%s rev %c found at %p ",
444 dev->name,
445 lp->chip_type == CS8900 ? '0' : '2',
446 lp->chip_type == CS8920M ? "M" : "",
447 lp->chip_revision,
448 lp->virt_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449
450 reset_chip(dev);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400451
Joe Perches204a38a2012-05-18 12:56:27 +0000452 /* Here we read the current configuration of the chip.
453 * If there is no Extended EEPROM then the idea is to not disturb
454 * the chip configuration, it should have been correctly setup by
455 * automatic EEPROM read on reset. So, if the chip says it read
456 * the EEPROM the driver will always do *something* instead of
457 * complain that adapter_cnf is 0.
458 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459
Joe Perches204a38a2012-05-18 12:56:27 +0000460 if ((readreg(dev, PP_SelfST) & (EEPROM_OK | EEPROM_PRESENT)) ==
Joe Perchesca034bc2012-05-18 12:56:29 +0000461 (EEPROM_OK | EEPROM_PRESENT)) {
Joe Perches204a38a2012-05-18 12:56:27 +0000462 /* Load the MAC. */
463 for (i = 0; i < ETH_ALEN / 2; i++) {
464 unsigned int Addr;
465 Addr = readreg(dev, PP_IA + i * 2);
466 dev->dev_addr[i * 2] = Addr & 0xFF;
467 dev->dev_addr[i * 2 + 1] = Addr >> 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400469
Joe Perches204a38a2012-05-18 12:56:27 +0000470 /* Load the Adapter Configuration.
471 * Note: Barring any more specific information from some
472 * other source (ie EEPROM+Schematics), we would not know
473 * how to operate a 10Base2 interface on the AUI port.
474 * However, since we do read the status of HCB1 and use
475 * settings that always result in calls to control_dc_dc(dev,0)
476 * a BNC interface should work if the enable pin
477 * (dc/dc converter) is on HCB1.
478 * It will be called AUI however.
479 */
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400480
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481 lp->adapter_cnf = 0;
482 i = readreg(dev, PP_LineCTL);
483 /* Preserve the setting of the HCB1 pin. */
Joe Perches204a38a2012-05-18 12:56:27 +0000484 if ((i & (HCB1 | HCB1_ENBL)) == (HCB1 | HCB1_ENBL))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485 lp->adapter_cnf |= A_CNF_DC_DC_POLARITY;
486 /* Save the sqelch bit */
487 if ((i & LOW_RX_SQUELCH) == LOW_RX_SQUELCH)
488 lp->adapter_cnf |= A_CNF_EXTND_10B_2 | A_CNF_LOW_RX_SQUELCH;
489 /* Check if the card is in 10Base-t only mode */
490 if ((i & (AUI_ONLY | AUTO_AUI_10BASET)) == 0)
491 lp->adapter_cnf |= A_CNF_10B_T | A_CNF_MEDIA_10B_T;
492 /* Check if the card is in AUI only mode */
493 if ((i & (AUI_ONLY | AUTO_AUI_10BASET)) == AUI_ONLY)
494 lp->adapter_cnf |= A_CNF_AUI | A_CNF_MEDIA_AUI;
495 /* Check if the card is in Auto mode. */
496 if ((i & (AUI_ONLY | AUTO_AUI_10BASET)) == AUTO_AUI_10BASET)
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400497 lp->adapter_cnf |= A_CNF_AUI | A_CNF_10B_T |
Joe Perches204a38a2012-05-18 12:56:27 +0000498 A_CNF_MEDIA_AUI | A_CNF_MEDIA_10B_T | A_CNF_MEDIA_AUTO;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400499
Joe Perches808e9a72012-05-18 12:56:30 +0000500 cs89_dbg(1, info, "%s: PP_LineCTL=0x%x, adapter_cnf=0x%x\n",
501 dev->name, i, lp->adapter_cnf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502
503 /* IRQ. Other chips already probe, see below. */
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400504 if (lp->chip_type == CS8900)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505 lp->isa_config = readreg(dev, PP_CS8900_ISAINT) & INT_NO_MASK;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400506
Joe Perches808e9a72012-05-18 12:56:30 +0000507 pr_cont("[Cirrus EEPROM] ");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508 }
509
Joe Perches808e9a72012-05-18 12:56:30 +0000510 pr_cont("\n");
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400511
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512 /* First check to see if an EEPROM is attached. */
Christoph Eggeref3cf9f2010-07-14 13:40:36 -0700513
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514 if ((readreg(dev, PP_SelfST) & EEPROM_PRESENT) == 0)
Joe Perchesdd92b9a2012-05-18 12:56:28 +0000515 pr_warn("No EEPROM, relying on command line....\n");
Joe Perches204a38a2012-05-18 12:56:27 +0000516 else if (get_eeprom_data(dev, START_EEPROM_DATA, CHKSUM_LEN, eeprom_buff) < 0) {
Joe Perchesdd92b9a2012-05-18 12:56:28 +0000517 pr_warn("EEPROM read failed, relying on command line\n");
Joe Perches204a38a2012-05-18 12:56:27 +0000518 } else if (get_eeprom_cksum(START_EEPROM_DATA, CHKSUM_LEN, eeprom_buff) < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519 /* Check if the chip was able to read its own configuration starting
520 at 0 in the EEPROM*/
521 if ((readreg(dev, PP_SelfST) & (EEPROM_OK | EEPROM_PRESENT)) !=
Joe Perches204a38a2012-05-18 12:56:27 +0000522 (EEPROM_OK | EEPROM_PRESENT))
Joe Perchesdd92b9a2012-05-18 12:56:28 +0000523 pr_warn("Extended EEPROM checksum bad and no Cirrus EEPROM, relying on command line\n");
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400524
Joe Perches204a38a2012-05-18 12:56:27 +0000525 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526 /* This reads an extended EEPROM that is not documented
Joe Perches204a38a2012-05-18 12:56:27 +0000527 * in the CS8900 datasheet.
528 */
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400529
Joe Perches204a38a2012-05-18 12:56:27 +0000530 /* get transmission control word but keep the autonegotiation bits */
Joe Perchesca034bc2012-05-18 12:56:29 +0000531 if (!lp->auto_neg_cnf)
532 lp->auto_neg_cnf = eeprom_buff[AUTO_NEG_CNF_OFFSET / 2];
Joe Perches204a38a2012-05-18 12:56:27 +0000533 /* Store adapter configuration */
Joe Perchesca034bc2012-05-18 12:56:29 +0000534 if (!lp->adapter_cnf)
535 lp->adapter_cnf = eeprom_buff[ADAPTER_CNF_OFFSET / 2];
Joe Perches204a38a2012-05-18 12:56:27 +0000536 /* Store ISA configuration */
Joe Perchesca034bc2012-05-18 12:56:29 +0000537 lp->isa_config = eeprom_buff[ISA_CNF_OFFSET / 2];
538 dev->mem_start = eeprom_buff[PACKET_PAGE_OFFSET / 2] << 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539
Joe Perches204a38a2012-05-18 12:56:27 +0000540 /* eeprom_buff has 32-bit ints, so we can't just memcpy it */
541 /* store the initial memory base address */
542 for (i = 0; i < ETH_ALEN / 2; i++) {
543 dev->dev_addr[i * 2] = eeprom_buff[i];
544 dev->dev_addr[i * 2 + 1] = eeprom_buff[i] >> 8;
545 }
Joe Perches808e9a72012-05-18 12:56:30 +0000546 cs89_dbg(1, debug, "%s: new adapter_cnf: 0x%x\n",
547 dev->name, lp->adapter_cnf);
Joe Perches204a38a2012-05-18 12:56:27 +0000548 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549
Joe Perches204a38a2012-05-18 12:56:27 +0000550 /* allow them to force multiple transceivers. If they force multiple, autosense */
551 {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552 int count = 0;
Joe Perchesca034bc2012-05-18 12:56:29 +0000553 if (lp->force & FORCE_RJ45) {
554 lp->adapter_cnf |= A_CNF_10B_T;
555 count++;
556 }
557 if (lp->force & FORCE_AUI) {
558 lp->adapter_cnf |= A_CNF_AUI;
559 count++;
560 }
561 if (lp->force & FORCE_BNC) {
562 lp->adapter_cnf |= A_CNF_10B_2;
563 count++;
564 }
565 if (count > 1)
566 lp->adapter_cnf |= A_CNF_MEDIA_AUTO;
567 else if (lp->force & FORCE_RJ45)
568 lp->adapter_cnf |= A_CNF_MEDIA_10B_T;
569 else if (lp->force & FORCE_AUI)
570 lp->adapter_cnf |= A_CNF_MEDIA_AUI;
571 else if (lp->force & FORCE_BNC)
572 lp->adapter_cnf |= A_CNF_MEDIA_10B_2;
Joe Perches204a38a2012-05-18 12:56:27 +0000573 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574
Joe Perches808e9a72012-05-18 12:56:30 +0000575 cs89_dbg(1, debug, "%s: after force 0x%x, adapter_cnf=0x%x\n",
576 dev->name, lp->force, lp->adapter_cnf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577
Joe Perches204a38a2012-05-18 12:56:27 +0000578 /* FIXME: We don't let you set dc-dc polarity or low RX squelch from the command line: add it here */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579
Joe Perches204a38a2012-05-18 12:56:27 +0000580 /* FIXME: We don't let you set the IMM bit from the command line: add it to lp->auto_neg_cnf here */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581
Joe Perches204a38a2012-05-18 12:56:27 +0000582 /* FIXME: we don't set the Ethernet address on the command line. Use
583 * ifconfig IFACE hw ether AABBCCDDEEFF
584 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585
Joe Perchesdd92b9a2012-05-18 12:56:28 +0000586 pr_info("media %s%s%s",
587 (lp->adapter_cnf & A_CNF_10B_T) ? "RJ-45," : "",
588 (lp->adapter_cnf & A_CNF_AUI) ? "AUI," : "",
589 (lp->adapter_cnf & A_CNF_10B_2) ? "BNC," : "");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590
591 lp->irq_map = 0xffff;
592
593 /* If this is a CS8900 then no pnp soft */
594 if (lp->chip_type != CS8900 &&
595 /* Check if the ISA IRQ has been set */
Joe Perches204a38a2012-05-18 12:56:27 +0000596 (i = readreg(dev, PP_CS8920_ISAINT) & 0xff,
597 (i != 0 && i < CS8920_NO_INTS))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598 if (!dev->irq)
599 dev->irq = i;
600 } else {
601 i = lp->isa_config & INT_NO_MASK;
Jaccon Bastiaansene9460a92012-01-26 21:46:15 +0100602#ifndef CONFIG_CS89x0_PLATFORM
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603 if (lp->chip_type == CS8900) {
Jaccon Bastiaansene9460a92012-01-26 21:46:15 +0100604#ifdef CS89x0_NONISA_IRQ
Joe Perches204a38a2012-05-18 12:56:27 +0000605 i = cs8900_irq_map[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606#else
607 /* Translate the IRQ using the IRQ mapping table. */
Denis Chengff8ac602007-09-02 18:30:18 +0800608 if (i >= ARRAY_SIZE(cs8900_irq_map))
Joe Perchesdd92b9a2012-05-18 12:56:28 +0000609 pr_err("invalid ISA interrupt number %d\n", i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610 else
611 i = cs8900_irq_map[i];
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400612
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613 lp->irq_map = CS8900_IRQ_MAP; /* fixed IRQ map for CS8900 */
614 } else {
615 int irq_map_buff[IRQ_MAP_LEN/2];
616
617 if (get_eeprom_data(dev, IRQ_MAP_EEPROM_DATA,
Joe Perches204a38a2012-05-18 12:56:27 +0000618 IRQ_MAP_LEN / 2,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 irq_map_buff) >= 0) {
620 if ((irq_map_buff[0] & 0xff) == PNP_IRQ_FRMT)
Joe Perchesca034bc2012-05-18 12:56:29 +0000621 lp->irq_map = ((irq_map_buff[0] >> 8) |
622 (irq_map_buff[1] << 8));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623 }
624#endif
625 }
Jaccon Bastiaansene9460a92012-01-26 21:46:15 +0100626#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627 if (!dev->irq)
628 dev->irq = i;
629 }
630
Joe Perches808e9a72012-05-18 12:56:30 +0000631 pr_cont(" IRQ %d", dev->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632
633#if ALLOW_DMA
634 if (lp->use_dma) {
635 get_dma_channel(dev);
Joe Perches808e9a72012-05-18 12:56:30 +0000636 pr_cont(", DMA %d", dev->dma);
Joe Perchesca034bc2012-05-18 12:56:29 +0000637 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638#endif
Joe Perches808e9a72012-05-18 12:56:30 +0000639 pr_cont(", programmed I/O");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640
641 /* print the ethernet address. */
Joe Perches808e9a72012-05-18 12:56:30 +0000642 pr_cont(", MAC %pM\n", dev->dev_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643
Stephen Hemminger15d23e72009-03-26 15:11:43 +0000644 dev->netdev_ops = &net_ops;
645 dev->watchdog_timeo = HZ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646
Joe Perches808e9a72012-05-18 12:56:30 +0000647 cs89_dbg(0, info, "cs89x0_probe1() successful\n");
b1fc5502005-05-12 20:11:55 -0400648
649 retval = register_netdev(dev);
650 if (retval)
Jaccon Bastiaansen09dcd602012-05-17 07:11:42 +0000651 goto out2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652 return 0;
653out2:
Jaccon Bastiaansen09dcd602012-05-17 07:11:42 +0000654 iowrite16(PP_ChipID, lp->virt_addr + ADD_PORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655out1:
656 return retval;
657}
658
Jaccon Bastiaansen09dcd602012-05-17 07:11:42 +0000659#ifndef CONFIG_CS89x0_PLATFORM
660/*
661 * This function converts the I/O port addres used by the cs89x0_probe() and
662 * init_module() functions to the I/O memory address used by the
663 * cs89x0_probe1() function.
664 */
665static int __init
666cs89x0_ioport_probe(struct net_device *dev, unsigned long ioport, int modular)
667{
668 struct net_local *lp = netdev_priv(dev);
669 int ret;
670 void __iomem *io_mem;
671
672 if (!lp)
673 return -ENOMEM;
674
675 dev->base_addr = ioport;
676
677 if (!request_region(ioport, NETCARD_IO_EXTENT, DRV_NAME)) {
678 ret = -EBUSY;
679 goto out;
680 }
681
682 io_mem = ioport_map(ioport & ~3, NETCARD_IO_EXTENT);
683 if (!io_mem) {
684 ret = -ENOMEM;
685 goto release;
686 }
687
688 /* if they give us an odd I/O address, then do ONE write to
Joe Perches204a38a2012-05-18 12:56:27 +0000689 * the address port, to get it back to address zero, where we
690 * expect to find the EISA signature word. An IO with a base of 0x3
691 * will skip the test for the ADD_PORT.
692 */
Jaccon Bastiaansen09dcd602012-05-17 07:11:42 +0000693 if (ioport & 1) {
Joe Perches808e9a72012-05-18 12:56:30 +0000694 cs89_dbg(1, info, "%s: odd ioaddr 0x%lx\n", dev->name, ioport);
Joe Perchesca034bc2012-05-18 12:56:29 +0000695 if ((ioport & 2) != 2) {
Jaccon Bastiaansen09dcd602012-05-17 07:11:42 +0000696 if ((ioread16(io_mem + ADD_PORT) & ADD_MASK) !=
697 ADD_SIG) {
Joe Perchesdd92b9a2012-05-18 12:56:28 +0000698 pr_err("%s: bad signature 0x%x\n",
699 dev->name, ioread16(io_mem + ADD_PORT));
Jaccon Bastiaansen09dcd602012-05-17 07:11:42 +0000700 ret = -ENODEV;
701 goto unmap;
702 }
Joe Perchesca034bc2012-05-18 12:56:29 +0000703 }
Jaccon Bastiaansen09dcd602012-05-17 07:11:42 +0000704 }
705
706 ret = cs89x0_probe1(dev, io_mem, modular);
707 if (!ret)
708 goto out;
709unmap:
710 ioport_unmap(io_mem);
711release:
712 release_region(ioport, NETCARD_IO_EXTENT);
713out:
714 return ret;
715}
716
717#ifndef MODULE
718/* Check for a network adaptor of this type, and return '0' iff one exists.
Joe Perches204a38a2012-05-18 12:56:27 +0000719 * If dev->base_addr == 0, probe all likely locations.
720 * If dev->base_addr == 1, always return failure.
721 * If dev->base_addr == 2, allocate space for the device and return success
722 * (detachable devices only).
723 * Return 0 on success.
724 */
Jaccon Bastiaansen09dcd602012-05-17 07:11:42 +0000725
726struct net_device * __init cs89x0_probe(int unit)
727{
728 struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
729 unsigned *port;
730 int err = 0;
731 int irq;
732 int io;
733
734 if (!dev)
735 return ERR_PTR(-ENODEV);
736
737 sprintf(dev->name, "eth%d", unit);
738 netdev_boot_setup_check(dev);
739 io = dev->base_addr;
740 irq = dev->irq;
741
Joe Perches808e9a72012-05-18 12:56:30 +0000742 cs89_dbg(0, info, "cs89x0_probe(0x%x)\n", io);
Jaccon Bastiaansen09dcd602012-05-17 07:11:42 +0000743
744 if (io > 0x1ff) { /* Check a single specified location. */
745 err = cs89x0_ioport_probe(dev, io, 0);
746 } else if (io != 0) { /* Don't probe at all. */
747 err = -ENXIO;
748 } else {
749 for (port = netcard_portlist; *port; port++) {
750 if (cs89x0_ioport_probe(dev, *port, 0) == 0)
751 break;
752 dev->irq = irq;
753 }
754 if (!*port)
755 err = -ENODEV;
756 }
757 if (err)
758 goto out;
759 return dev;
760out:
761 free_netdev(dev);
Joe Perchesdd92b9a2012-05-18 12:56:28 +0000762 pr_warn("no cs8900 or cs8920 detected. Be sure to disable PnP with SETUP\n");
Jaccon Bastiaansen09dcd602012-05-17 07:11:42 +0000763 return ERR_PTR(err);
764}
765#endif
766#endif
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400767
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768/*********************************
769 * This page contains DMA routines
Joe Perches204a38a2012-05-18 12:56:27 +0000770 *********************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771
772#if ALLOW_DMA
773
Joe Perchesca034bc2012-05-18 12:56:29 +0000774#define dma_page_eq(ptr1, ptr2) ((long)(ptr1) >> 17 == (long)(ptr2) >> 17)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775
776static void
777get_dma_channel(struct net_device *dev)
778{
779 struct net_local *lp = netdev_priv(dev);
780
781 if (lp->dma) {
782 dev->dma = lp->dma;
783 lp->isa_config |= ISA_RxDMA;
784 } else {
785 if ((lp->isa_config & ANY_ISA_DMA) == 0)
786 return;
787 dev->dma = lp->isa_config & DMA_NO_MASK;
788 if (lp->chip_type == CS8900)
789 dev->dma += 5;
790 if (dev->dma < 5 || dev->dma > 7) {
791 lp->isa_config &= ~ANY_ISA_DMA;
792 return;
793 }
794 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795}
796
797static void
798write_dma(struct net_device *dev, int chip_type, int dma)
799{
800 struct net_local *lp = netdev_priv(dev);
801 if ((lp->isa_config & ANY_ISA_DMA) == 0)
802 return;
Joe Perchesca034bc2012-05-18 12:56:29 +0000803 if (chip_type == CS8900)
804 writereg(dev, PP_CS8900_ISADMA, dma - 5);
805 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806 writereg(dev, PP_CS8920_ISADMA, dma);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807}
808
809static void
810set_dma_cfg(struct net_device *dev)
811{
812 struct net_local *lp = netdev_priv(dev);
813
814 if (lp->use_dma) {
815 if ((lp->isa_config & ANY_ISA_DMA) == 0) {
Joe Perches808e9a72012-05-18 12:56:30 +0000816 cs89_dbg(3, err, "set_dma_cfg(): no DMA\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817 return;
818 }
819 if (lp->isa_config & ISA_RxDMA) {
820 lp->curr_rx_cfg |= RX_DMA_ONLY;
Joe Perches808e9a72012-05-18 12:56:30 +0000821 cs89_dbg(3, info, "set_dma_cfg(): RX_DMA_ONLY\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822 } else {
823 lp->curr_rx_cfg |= AUTO_RX_DMA; /* not that we support it... */
Joe Perches808e9a72012-05-18 12:56:30 +0000824 cs89_dbg(3, info, "set_dma_cfg(): AUTO_RX_DMA\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825 }
826 }
827}
828
829static int
830dma_bufcfg(struct net_device *dev)
831{
832 struct net_local *lp = netdev_priv(dev);
833 if (lp->use_dma)
Joe Perches204a38a2012-05-18 12:56:27 +0000834 return (lp->isa_config & ANY_ISA_DMA) ? RX_DMA_ENBL : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835 else
836 return 0;
837}
838
839static int
840dma_busctl(struct net_device *dev)
841{
842 int retval = 0;
843 struct net_local *lp = netdev_priv(dev);
844 if (lp->use_dma) {
845 if (lp->isa_config & ANY_ISA_DMA)
846 retval |= RESET_RX_DMA; /* Reset the DMA pointer */
847 if (lp->isa_config & DMA_BURST)
848 retval |= DMA_BURST_MODE; /* Does ISA config specify DMA burst ? */
849 if (lp->dmasize == 64)
850 retval |= RX_DMA_SIZE_64K; /* did they ask for 64K? */
851 retval |= MEMORY_ON; /* we need memory enabled to use DMA. */
852 }
853 return retval;
854}
855
856static void
857dma_rx(struct net_device *dev)
858{
859 struct net_local *lp = netdev_priv(dev);
860 struct sk_buff *skb;
861 int status, length;
862 unsigned char *bp = lp->rx_dma_ptr;
863
Joe Perchesca034bc2012-05-18 12:56:29 +0000864 status = bp[0] + (bp[1] << 8);
865 length = bp[2] + (bp[3] << 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866 bp += 4;
Joe Perches808e9a72012-05-18 12:56:30 +0000867
868 cs89_dbg(5, debug, "%s: receiving DMA packet at %lx, status %x, length %x\n",
869 dev->name, (unsigned long)bp, status, length);
870
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871 if ((status & RX_OK) == 0) {
Kulikov Vasiliy661a16c2010-07-05 02:13:15 +0000872 count_rx_errors(status, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873 goto skip_this_frame;
874 }
875
876 /* Malloc up new buffer. */
Pradeep A Dalvi21a4e462012-02-05 02:50:10 +0000877 skb = netdev_alloc_skb(dev, length + 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878 if (skb == NULL) {
Joe Perches808e9a72012-05-18 12:56:30 +0000879 /* I don't think we want to do this to a stressed system */
880 cs89_dbg(0, err, "%s: Memory squeeze, dropping packet\n",
881 dev->name);
Kulikov Vasiliy661a16c2010-07-05 02:13:15 +0000882 dev->stats.rx_dropped++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883
884 /* AKPM: advance bp to the next frame */
885skip_this_frame:
886 bp += (length + 3) & ~3;
Joe Perchesca034bc2012-05-18 12:56:29 +0000887 if (bp >= lp->end_dma_buff)
888 bp -= lp->dmasize * 1024;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889 lp->rx_dma_ptr = bp;
890 return;
891 }
892 skb_reserve(skb, 2); /* longword align L3 header */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893
894 if (bp + length > lp->end_dma_buff) {
895 int semi_cnt = lp->end_dma_buff - bp;
Joe Perches204a38a2012-05-18 12:56:27 +0000896 memcpy(skb_put(skb, semi_cnt), bp, semi_cnt);
897 memcpy(skb_put(skb, length - semi_cnt), lp->dma_buff,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700898 length - semi_cnt);
899 } else {
Joe Perches204a38a2012-05-18 12:56:27 +0000900 memcpy(skb_put(skb, length), bp, length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901 }
902 bp += (length + 3) & ~3;
Joe Perchesca034bc2012-05-18 12:56:29 +0000903 if (bp >= lp->end_dma_buff)
904 bp -= lp->dmasize*1024;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905 lp->rx_dma_ptr = bp;
906
Joe Perches808e9a72012-05-18 12:56:30 +0000907 cs89_dbg(3, info, "%s: received %d byte DMA packet of type %x\n",
908 dev->name, length,
909 ((skb->data[ETH_ALEN + ETH_ALEN] << 8) |
910 skb->data[ETH_ALEN + ETH_ALEN + 1]));
911
Joe Perches204a38a2012-05-18 12:56:27 +0000912 skb->protocol = eth_type_trans(skb, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 netif_rx(skb);
Kulikov Vasiliy661a16c2010-07-05 02:13:15 +0000914 dev->stats.rx_packets++;
915 dev->stats.rx_bytes += length;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916}
917
918#endif /* ALLOW_DMA */
919
Hannes Ederdac499f2008-12-25 23:56:45 -0800920static void __init reset_chip(struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921{
Gilles Chanteperdrix0ac4ed92008-09-26 15:44:43 +0100922#if !defined(CONFIG_MACH_MX31ADS)
Domenico Andreolid181a612011-03-14 03:46:53 +0000923#if !defined(CS89x0_NONISA_IRQ)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924 struct net_local *lp = netdev_priv(dev);
Domenico Andreolid181a612011-03-14 03:46:53 +0000925#endif /* CS89x0_NONISA_IRQ */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926 int reset_start_time;
927
928 writereg(dev, PP_SelfCTL, readreg(dev, PP_SelfCTL) | POWER_ON_RESET);
929
930 /* wait 30 ms */
931 msleep(30);
932
Domenico Andreolid181a612011-03-14 03:46:53 +0000933#if !defined(CS89x0_NONISA_IRQ)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934 if (lp->chip_type != CS8900) {
935 /* Hardware problem requires PNP registers to be reconfigured after a reset */
Jaccon Bastiaansen09dcd602012-05-17 07:11:42 +0000936 iowrite16(PP_CS8920_ISAINT, lp->virt_addr + ADD_PORT);
937 iowrite8(dev->irq, lp->virt_addr + DATA_PORT);
938 iowrite8(0, lp->virt_addr + DATA_PORT + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939
Jaccon Bastiaansen09dcd602012-05-17 07:11:42 +0000940 iowrite16(PP_CS8920_ISAMemB, lp->virt_addr + ADD_PORT);
941 iowrite8((dev->mem_start >> 16) & 0xff,
942 lp->virt_addr + DATA_PORT);
943 iowrite8((dev->mem_start >> 8) & 0xff,
944 lp->virt_addr + DATA_PORT + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945 }
Domenico Andreolid181a612011-03-14 03:46:53 +0000946#endif /* CS89x0_NONISA_IRQ */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947
948 /* Wait until the chip is reset */
949 reset_start_time = jiffies;
Joe Perchesca034bc2012-05-18 12:56:29 +0000950 while ((readreg(dev, PP_SelfST) & INIT_DONE) == 0 &&
951 jiffies - reset_start_time < 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952 ;
Gilles Chanteperdrix0ac4ed92008-09-26 15:44:43 +0100953#endif /* !CONFIG_MACH_MX31ADS */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954}
955
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400956
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957static void
958control_dc_dc(struct net_device *dev, int on_not_off)
959{
960 struct net_local *lp = netdev_priv(dev);
961 unsigned int selfcontrol;
962 int timenow = jiffies;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400963 /* control the DC to DC convertor in the SelfControl register.
Joe Perchesca034bc2012-05-18 12:56:29 +0000964 * Note: This is hooked up to a general purpose pin, might not
965 * always be a DC to DC convertor.
966 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967
968 selfcontrol = HCB1_ENBL; /* Enable the HCB1 bit as an output */
969 if (((lp->adapter_cnf & A_CNF_DC_DC_POLARITY) != 0) ^ on_not_off)
970 selfcontrol |= HCB1;
971 else
972 selfcontrol &= ~HCB1;
973 writereg(dev, PP_SelfCTL, selfcontrol);
974
975 /* Wait for the DC/DC converter to power up - 500ms */
976 while (jiffies - timenow < HZ)
977 ;
978}
979
980#define DETECTED_NONE 0
981#define DETECTED_RJ45H 1
982#define DETECTED_RJ45F 2
983#define DETECTED_AUI 3
984#define DETECTED_BNC 4
985
986static int
987detect_tp(struct net_device *dev)
988{
989 struct net_local *lp = netdev_priv(dev);
990 int timenow = jiffies;
991 int fdx;
992
Joe Perches808e9a72012-05-18 12:56:30 +0000993 cs89_dbg(1, debug, "%s: Attempting TP\n", dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994
Joe Perchesca034bc2012-05-18 12:56:29 +0000995 /* If connected to another full duplex capable 10-Base-T card
996 * the link pulses seem to be lost when the auto detect bit in
997 * the LineCTL is set. To overcome this the auto detect bit will
998 * be cleared whilst testing the 10-Base-T interface. This would
999 * not be necessary for the sparrow chip but is simpler to do it
1000 * anyway.
1001 */
Joe Perches204a38a2012-05-18 12:56:27 +00001002 writereg(dev, PP_LineCTL, lp->linectl & ~AUI_ONLY);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003 control_dc_dc(dev, 0);
1004
Joe Perchesca034bc2012-05-18 12:56:29 +00001005 /* Delay for the hardware to work out if the TP cable is present
1006 * - 150ms
1007 */
1008 for (timenow = jiffies; jiffies - timenow < 15;)
Joe Perches204a38a2012-05-18 12:56:27 +00001009 ;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010 if ((readreg(dev, PP_LineST) & LINK_OK) == 0)
1011 return DETECTED_NONE;
1012
1013 if (lp->chip_type == CS8900) {
Joe Perches204a38a2012-05-18 12:56:27 +00001014 switch (lp->force & 0xf0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015#if 0
Joe Perches204a38a2012-05-18 12:56:27 +00001016 case FORCE_AUTO:
Joe Perches808e9a72012-05-18 12:56:30 +00001017 pr_info("%s: cs8900 doesn't autonegotiate\n",
1018 dev->name);
Joe Perches204a38a2012-05-18 12:56:27 +00001019 return DETECTED_NONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020#endif
Joe Perches204a38a2012-05-18 12:56:27 +00001021 /* CS8900 doesn't support AUTO, change to HALF*/
1022 case FORCE_AUTO:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 lp->force &= ~FORCE_AUTO;
Joe Perches204a38a2012-05-18 12:56:27 +00001024 lp->force |= FORCE_HALF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025 break;
1026 case FORCE_HALF:
1027 break;
Joe Perches204a38a2012-05-18 12:56:27 +00001028 case FORCE_FULL:
Joe Perchesca034bc2012-05-18 12:56:29 +00001029 writereg(dev, PP_TestCTL,
1030 readreg(dev, PP_TestCTL) | FDX_8900);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 break;
Joe Perches204a38a2012-05-18 12:56:27 +00001032 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 fdx = readreg(dev, PP_TestCTL) & FDX_8900;
1034 } else {
1035 switch (lp->force & 0xf0) {
1036 case FORCE_AUTO:
1037 lp->auto_neg_cnf = AUTO_NEG_ENABLE;
1038 break;
1039 case FORCE_HALF:
1040 lp->auto_neg_cnf = 0;
1041 break;
1042 case FORCE_FULL:
1043 lp->auto_neg_cnf = RE_NEG_NOW | ALLOW_FDX;
1044 break;
Joe Perches204a38a2012-05-18 12:56:27 +00001045 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046
1047 writereg(dev, PP_AutoNegCTL, lp->auto_neg_cnf & AUTO_NEG_MASK);
1048
1049 if ((lp->auto_neg_cnf & AUTO_NEG_BITS) == AUTO_NEG_ENABLE) {
Joe Perchesdd92b9a2012-05-18 12:56:28 +00001050 pr_info("%s: negotiating duplex...\n", dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051 while (readreg(dev, PP_AutoNegST) & AUTO_NEG_BUSY) {
1052 if (jiffies - timenow > 4000) {
Joe Perchesdd92b9a2012-05-18 12:56:28 +00001053 pr_err("**** Full / half duplex auto-negotiation timed out ****\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054 break;
1055 }
1056 }
1057 }
1058 fdx = readreg(dev, PP_AutoNegST) & FDX_ACTIVE;
1059 }
1060 if (fdx)
1061 return DETECTED_RJ45F;
1062 else
1063 return DETECTED_RJ45H;
1064}
1065
1066/* send a test packet - return true if carrier bits are ok */
1067static int
1068send_test_pkt(struct net_device *dev)
1069{
Jaccon Bastiaansen09dcd602012-05-17 07:11:42 +00001070 struct net_local *lp = netdev_priv(dev);
Joe Perchesca034bc2012-05-18 12:56:29 +00001071 char test_packet[] = {
1072 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1073 0, 46, /* A 46 in network order */
1074 0, 0, /* DSAP=0 & SSAP=0 fields */
1075 0xf3, 0 /* Control (Test Req + P bit set) */
1076 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077 long timenow = jiffies;
1078
1079 writereg(dev, PP_LineCTL, readreg(dev, PP_LineCTL) | SERIAL_TX_ON);
1080
Joe Perches204a38a2012-05-18 12:56:27 +00001081 memcpy(test_packet, dev->dev_addr, ETH_ALEN);
1082 memcpy(test_packet + ETH_ALEN, dev->dev_addr, ETH_ALEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083
Jaccon Bastiaansen09dcd602012-05-17 07:11:42 +00001084 iowrite16(TX_AFTER_ALL, lp->virt_addr + TX_CMD_PORT);
1085 iowrite16(ETH_ZLEN, lp->virt_addr + TX_LEN_PORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086
1087 /* Test to see if the chip has allocated memory for the packet */
1088 while (jiffies - timenow < 5)
1089 if (readreg(dev, PP_BusST) & READY_FOR_TX_NOW)
1090 break;
1091 if (jiffies - timenow >= 5)
1092 return 0; /* this shouldn't happen */
1093
1094 /* Write the contents of the packet */
Joe Perchesca034bc2012-05-18 12:56:29 +00001095 writewords(lp, TX_FRAME_PORT, test_packet, (ETH_ZLEN + 1) >> 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096
Joe Perches808e9a72012-05-18 12:56:30 +00001097 cs89_dbg(1, debug, "Sending test packet ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098 /* wait a couple of jiffies for packet to be received */
Joe Perchesca034bc2012-05-18 12:56:29 +00001099 for (timenow = jiffies; jiffies - timenow < 3;)
Joe Perches204a38a2012-05-18 12:56:27 +00001100 ;
1101 if ((readreg(dev, PP_TxEvent) & TX_SEND_OK_BITS) == TX_OK) {
Joe Perches808e9a72012-05-18 12:56:30 +00001102 cs89_dbg(1, cont, "succeeded\n");
Joe Perches204a38a2012-05-18 12:56:27 +00001103 return 1;
1104 }
Joe Perches808e9a72012-05-18 12:56:30 +00001105 cs89_dbg(1, cont, "failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106 return 0;
1107}
1108
1109
1110static int
1111detect_aui(struct net_device *dev)
1112{
1113 struct net_local *lp = netdev_priv(dev);
1114
Joe Perches808e9a72012-05-18 12:56:30 +00001115 cs89_dbg(1, debug, "%s: Attempting AUI\n", dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116 control_dc_dc(dev, 0);
1117
Joe Perches204a38a2012-05-18 12:56:27 +00001118 writereg(dev, PP_LineCTL, (lp->linectl & ~AUTO_AUI_10BASET) | AUI_ONLY);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119
1120 if (send_test_pkt(dev))
1121 return DETECTED_AUI;
1122 else
1123 return DETECTED_NONE;
1124}
1125
1126static int
1127detect_bnc(struct net_device *dev)
1128{
1129 struct net_local *lp = netdev_priv(dev);
1130
Joe Perches808e9a72012-05-18 12:56:30 +00001131 cs89_dbg(1, debug, "%s: Attempting BNC\n", dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132 control_dc_dc(dev, 1);
1133
Joe Perches204a38a2012-05-18 12:56:27 +00001134 writereg(dev, PP_LineCTL, (lp->linectl & ~AUTO_AUI_10BASET) | AUI_ONLY);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135
1136 if (send_test_pkt(dev))
1137 return DETECTED_BNC;
1138 else
1139 return DETECTED_NONE;
1140}
1141
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001142
Linus Torvalds1da177e2005-04-16 15:20:36 -07001143static void
1144write_irq(struct net_device *dev, int chip_type, int irq)
1145{
1146 int i;
1147
1148 if (chip_type == CS8900) {
Jaccon Bastiaansene9460a92012-01-26 21:46:15 +01001149#ifndef CONFIG_CS89x0_PLATFORM
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150 /* Search the mapping table for the corresponding IRQ pin. */
Denis Chengff8ac602007-09-02 18:30:18 +08001151 for (i = 0; i != ARRAY_SIZE(cs8900_irq_map); i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152 if (cs8900_irq_map[i] == irq)
1153 break;
1154 /* Not found */
Denis Chengff8ac602007-09-02 18:30:18 +08001155 if (i == ARRAY_SIZE(cs8900_irq_map))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156 i = 3;
Jaccon Bastiaansene9460a92012-01-26 21:46:15 +01001157#else
1158 /* INTRQ0 pin is used for interrupt generation. */
1159 i = 0;
1160#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161 writereg(dev, PP_CS8900_ISAINT, i);
1162 } else {
1163 writereg(dev, PP_CS8920_ISAINT, irq);
1164 }
1165}
1166
1167/* Open/initialize the board. This is called (in the current kernel)
1168 sometime after booting when the 'ifconfig' program is run.
1169
1170 This routine should set everything up anew at each open, even
1171 registers that "should" only need to be set once at boot, so that
1172 there is non-reboot way to recover if something goes wrong.
Joe Perches204a38a2012-05-18 12:56:27 +00001173*/
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174
1175/* AKPM: do we need to do any locking here? */
1176
1177static int
1178net_open(struct net_device *dev)
1179{
1180 struct net_local *lp = netdev_priv(dev);
1181 int result = 0;
1182 int i;
1183 int ret;
1184
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185 if (dev->irq < 2) {
1186 /* Allow interrupts to be generated by the chip */
1187/* Cirrus' release had this: */
1188#if 0
Joe Perches204a38a2012-05-18 12:56:27 +00001189 writereg(dev, PP_BusCTL, readreg(dev, PP_BusCTL) | ENABLE_IRQ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190#endif
1191/* And 2.3.47 had this: */
1192 writereg(dev, PP_BusCTL, ENABLE_IRQ | MEMORY_ON);
1193
1194 for (i = 2; i < CS8920_NO_INTS; i++) {
1195 if ((1 << i) & lp->irq_map) {
Joe Perchesca034bc2012-05-18 12:56:29 +00001196 if (request_irq(i, net_interrupt, 0, dev->name,
1197 dev) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198 dev->irq = i;
1199 write_irq(dev, lp->chip_type, i);
1200 /* writereg(dev, PP_BufCFG, GENERATE_SW_INTERRUPT); */
1201 break;
1202 }
1203 }
1204 }
1205
1206 if (i >= CS8920_NO_INTS) {
1207 writereg(dev, PP_BusCTL, 0); /* disable interrupts. */
Joe Perchesdd92b9a2012-05-18 12:56:28 +00001208 pr_err("can't get an interrupt\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209 ret = -EAGAIN;
1210 goto bad_out;
1211 }
Joe Perchesca034bc2012-05-18 12:56:29 +00001212 } else {
Jaccon Bastiaansene9460a92012-01-26 21:46:15 +01001213#if !defined(CS89x0_NONISA_IRQ) && !defined(CONFIG_CS89x0_PLATFORM)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214 if (((1 << dev->irq) & lp->irq_map) == 0) {
Joe Perchesdd92b9a2012-05-18 12:56:28 +00001215 pr_err("%s: IRQ %d is not in our map of allowable IRQs, which is %x\n",
Joe Perches204a38a2012-05-18 12:56:27 +00001216 dev->name, dev->irq, lp->irq_map);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217 ret = -EAGAIN;
1218 goto bad_out;
1219 }
1220#endif
1221/* FIXME: Cirrus' release had this: */
Joe Perches204a38a2012-05-18 12:56:27 +00001222 writereg(dev, PP_BusCTL, readreg(dev, PP_BusCTL)|ENABLE_IRQ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223/* And 2.3.47 had this: */
1224#if 0
1225 writereg(dev, PP_BusCTL, ENABLE_IRQ | MEMORY_ON);
1226#endif
1227 write_irq(dev, lp->chip_type, dev->irq);
Joe Perchesa0607fd2009-11-18 23:29:17 -08001228 ret = request_irq(dev->irq, net_interrupt, 0, dev->name, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229 if (ret) {
Joe Perchesdd92b9a2012-05-18 12:56:28 +00001230 pr_err("request_irq(%d) failed\n", dev->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231 goto bad_out;
1232 }
1233 }
1234
1235#if ALLOW_DMA
Joe Perchesca034bc2012-05-18 12:56:29 +00001236 if (lp->use_dma && (lp->isa_config & ANY_ISA_DMA)) {
1237 unsigned long flags;
1238 lp->dma_buff = (unsigned char *)__get_dma_pages(GFP_KERNEL,
1239 get_order(lp->dmasize * 1024));
1240 if (!lp->dma_buff) {
1241 pr_err("%s: cannot get %dK memory for DMA\n",
1242 dev->name, lp->dmasize);
1243 goto release_irq;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244 }
Joe Perches808e9a72012-05-18 12:56:30 +00001245 cs89_dbg(1, debug, "%s: dma %lx %lx\n",
1246 dev->name,
1247 (unsigned long)lp->dma_buff,
1248 (unsigned long)isa_virt_to_bus(lp->dma_buff));
Joe Perchesca034bc2012-05-18 12:56:29 +00001249 if ((unsigned long)lp->dma_buff >= MAX_DMA_ADDRESS ||
1250 !dma_page_eq(lp->dma_buff,
1251 lp->dma_buff + lp->dmasize * 1024 - 1)) {
1252 pr_err("%s: not usable as DMA buffer\n", dev->name);
1253 goto release_irq;
1254 }
1255 memset(lp->dma_buff, 0, lp->dmasize * 1024); /* Why? */
1256 if (request_dma(dev->dma, dev->name)) {
1257 pr_err("%s: cannot get dma channel %d\n",
1258 dev->name, dev->dma);
1259 goto release_irq;
1260 }
1261 write_dma(dev, lp->chip_type, dev->dma);
1262 lp->rx_dma_ptr = lp->dma_buff;
1263 lp->end_dma_buff = lp->dma_buff + lp->dmasize * 1024;
1264 spin_lock_irqsave(&lp->lock, flags);
1265 disable_dma(dev->dma);
1266 clear_dma_ff(dev->dma);
1267 set_dma_mode(dev->dma, DMA_RX_MODE); /* auto_init as well */
1268 set_dma_addr(dev->dma, isa_virt_to_bus(lp->dma_buff));
1269 set_dma_count(dev->dma, lp->dmasize * 1024);
1270 enable_dma(dev->dma);
1271 spin_unlock_irqrestore(&lp->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272 }
1273#endif /* ALLOW_DMA */
1274
1275 /* set the Ethernet address */
Joe Perches204a38a2012-05-18 12:56:27 +00001276 for (i = 0; i < ETH_ALEN / 2; i++)
Joe Perchesca034bc2012-05-18 12:56:29 +00001277 writereg(dev, PP_IA + i * 2,
1278 (dev->dev_addr[i * 2] |
1279 (dev->dev_addr[i * 2 + 1] << 8)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280
1281 /* while we're testing the interface, leave interrupts disabled */
1282 writereg(dev, PP_BusCTL, MEMORY_ON);
1283
1284 /* Set the LineCTL quintuplet based on adapter configuration read from EEPROM */
Joe Perchesca034bc2012-05-18 12:56:29 +00001285 if ((lp->adapter_cnf & A_CNF_EXTND_10B_2) &&
1286 (lp->adapter_cnf & A_CNF_LOW_RX_SQUELCH))
Joe Perches204a38a2012-05-18 12:56:27 +00001287 lp->linectl = LOW_RX_SQUELCH;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288 else
Joe Perches204a38a2012-05-18 12:56:27 +00001289 lp->linectl = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290
Joe Perches204a38a2012-05-18 12:56:27 +00001291 /* check to make sure that they have the "right" hardware available */
1292 switch (lp->adapter_cnf & A_CNF_MEDIA_TYPE) {
Joe Perchesca034bc2012-05-18 12:56:29 +00001293 case A_CNF_MEDIA_10B_T:
1294 result = lp->adapter_cnf & A_CNF_10B_T;
1295 break;
1296 case A_CNF_MEDIA_AUI:
1297 result = lp->adapter_cnf & A_CNF_AUI;
1298 break;
1299 case A_CNF_MEDIA_10B_2:
1300 result = lp->adapter_cnf & A_CNF_10B_2;
1301 break;
1302 default:
1303 result = lp->adapter_cnf & (A_CNF_10B_T |
1304 A_CNF_AUI |
1305 A_CNF_10B_2);
Joe Perches204a38a2012-05-18 12:56:27 +00001306 }
1307 if (!result) {
Joe Perchesdd92b9a2012-05-18 12:56:28 +00001308 pr_err("%s: EEPROM is configured for unavailable media\n",
1309 dev->name);
Wang Chen17a94402008-05-30 11:18:55 +08001310release_dma:
1311#if ALLOW_DMA
1312 free_dma(dev->dma);
Wang Chen17a94402008-05-30 11:18:55 +08001313release_irq:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314 release_dma_buff(lp);
1315#endif
Joe Perchesca034bc2012-05-18 12:56:29 +00001316 writereg(dev, PP_LineCTL,
1317 readreg(dev, PP_LineCTL) & ~(SERIAL_TX_ON | SERIAL_RX_ON));
Joe Perches204a38a2012-05-18 12:56:27 +00001318 free_irq(dev->irq, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319 ret = -EAGAIN;
1320 goto bad_out;
1321 }
1322
Joe Perches204a38a2012-05-18 12:56:27 +00001323 /* set the hardware to the configured choice */
1324 switch (lp->adapter_cnf & A_CNF_MEDIA_TYPE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325 case A_CNF_MEDIA_10B_T:
Joe Perches204a38a2012-05-18 12:56:27 +00001326 result = detect_tp(dev);
1327 if (result == DETECTED_NONE) {
Joe Perchesdd92b9a2012-05-18 12:56:28 +00001328 pr_warn("%s: 10Base-T (RJ-45) has no cable\n",
1329 dev->name);
Joe Perches204a38a2012-05-18 12:56:27 +00001330 if (lp->auto_neg_cnf & IMM_BIT) /* check "ignore missing media" bit */
1331 result = DETECTED_RJ45H; /* Yes! I don't care if I see a link pulse */
1332 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333 break;
1334 case A_CNF_MEDIA_AUI:
Joe Perches204a38a2012-05-18 12:56:27 +00001335 result = detect_aui(dev);
1336 if (result == DETECTED_NONE) {
Joe Perchesdd92b9a2012-05-18 12:56:28 +00001337 pr_warn("%s: 10Base-5 (AUI) has no cable\n", dev->name);
Joe Perches204a38a2012-05-18 12:56:27 +00001338 if (lp->auto_neg_cnf & IMM_BIT) /* check "ignore missing media" bit */
1339 result = DETECTED_AUI; /* Yes! I don't care if I see a carrrier */
1340 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341 break;
1342 case A_CNF_MEDIA_10B_2:
Joe Perches204a38a2012-05-18 12:56:27 +00001343 result = detect_bnc(dev);
1344 if (result == DETECTED_NONE) {
Joe Perchesdd92b9a2012-05-18 12:56:28 +00001345 pr_warn("%s: 10Base-2 (BNC) has no cable\n", dev->name);
Joe Perches204a38a2012-05-18 12:56:27 +00001346 if (lp->auto_neg_cnf & IMM_BIT) /* check "ignore missing media" bit */
1347 result = DETECTED_BNC; /* Yes! I don't care if I can xmit a packet */
1348 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349 break;
1350 case A_CNF_MEDIA_AUTO:
1351 writereg(dev, PP_LineCTL, lp->linectl | AUTO_AUI_10BASET);
Joe Perchesca034bc2012-05-18 12:56:29 +00001352 if (lp->adapter_cnf & A_CNF_10B_T) {
1353 result = detect_tp(dev);
1354 if (result != DETECTED_NONE)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355 break;
Joe Perchesca034bc2012-05-18 12:56:29 +00001356 }
1357 if (lp->adapter_cnf & A_CNF_AUI) {
1358 result = detect_aui(dev);
1359 if (result != DETECTED_NONE)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360 break;
Joe Perchesca034bc2012-05-18 12:56:29 +00001361 }
1362 if (lp->adapter_cnf & A_CNF_10B_2) {
1363 result = detect_bnc(dev);
1364 if (result != DETECTED_NONE)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365 break;
Joe Perchesca034bc2012-05-18 12:56:29 +00001366 }
Joe Perchesdd92b9a2012-05-18 12:56:28 +00001367 pr_err("%s: no media detected\n", dev->name);
Wang Chen17a94402008-05-30 11:18:55 +08001368 goto release_dma;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369 }
Joe Perches204a38a2012-05-18 12:56:27 +00001370 switch (result) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371 case DETECTED_NONE:
Joe Perchesdd92b9a2012-05-18 12:56:28 +00001372 pr_err("%s: no network cable attached to configured media\n",
1373 dev->name);
Wang Chen17a94402008-05-30 11:18:55 +08001374 goto release_dma;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375 case DETECTED_RJ45H:
Joe Perchesdd92b9a2012-05-18 12:56:28 +00001376 pr_info("%s: using half-duplex 10Base-T (RJ-45)\n", dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377 break;
1378 case DETECTED_RJ45F:
Joe Perchesdd92b9a2012-05-18 12:56:28 +00001379 pr_info("%s: using full-duplex 10Base-T (RJ-45)\n", dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380 break;
1381 case DETECTED_AUI:
Joe Perchesdd92b9a2012-05-18 12:56:28 +00001382 pr_info("%s: using 10Base-5 (AUI)\n", dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001383 break;
1384 case DETECTED_BNC:
Joe Perchesdd92b9a2012-05-18 12:56:28 +00001385 pr_info("%s: using 10Base-2 (BNC)\n", dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386 break;
1387 }
1388
1389 /* Turn on both receive and transmit operations */
Joe Perchesca034bc2012-05-18 12:56:29 +00001390 writereg(dev, PP_LineCTL,
1391 readreg(dev, PP_LineCTL) | SERIAL_RX_ON | SERIAL_TX_ON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392
1393 /* Receive only error free packets addressed to this card */
1394 lp->rx_mode = 0;
1395 writereg(dev, PP_RxCTL, DEF_RX_ACCEPT);
1396
1397 lp->curr_rx_cfg = RX_OK_ENBL | RX_CRC_ERROR_ENBL;
1398
1399 if (lp->isa_config & STREAM_TRANSFER)
1400 lp->curr_rx_cfg |= RX_STREAM_ENBL;
1401#if ALLOW_DMA
1402 set_dma_cfg(dev);
1403#endif
1404 writereg(dev, PP_RxCFG, lp->curr_rx_cfg);
1405
Joe Perchesca034bc2012-05-18 12:56:29 +00001406 writereg(dev, PP_TxCFG, (TX_LOST_CRS_ENBL |
1407 TX_SQE_ERROR_ENBL |
1408 TX_OK_ENBL |
1409 TX_LATE_COL_ENBL |
1410 TX_JBR_ENBL |
1411 TX_ANY_COL_ENBL |
1412 TX_16_COL_ENBL));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413
Joe Perchesca034bc2012-05-18 12:56:29 +00001414 writereg(dev, PP_BufCFG, (READY_FOR_TX_ENBL |
1415 RX_MISS_COUNT_OVRFLOW_ENBL |
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416#if ALLOW_DMA
Joe Perchesca034bc2012-05-18 12:56:29 +00001417 dma_bufcfg(dev) |
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418#endif
Joe Perchesca034bc2012-05-18 12:56:29 +00001419 TX_COL_COUNT_OVRFLOW_ENBL |
1420 TX_UNDERRUN_ENBL));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421
1422 /* now that we've got our act together, enable everything */
Joe Perchesca034bc2012-05-18 12:56:29 +00001423 writereg(dev, PP_BusCTL, (ENABLE_IRQ
1424 | (dev->mem_start ? MEMORY_ON : 0) /* turn memory on */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425#if ALLOW_DMA
Joe Perchesca034bc2012-05-18 12:56:29 +00001426 | dma_busctl(dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001427#endif
Joe Perchesca034bc2012-05-18 12:56:29 +00001428 ));
Joe Perches204a38a2012-05-18 12:56:27 +00001429 netif_start_queue(dev);
Joe Perches808e9a72012-05-18 12:56:30 +00001430 cs89_dbg(1, debug, "net_open() succeeded\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431 return 0;
1432bad_out:
1433 return ret;
1434}
1435
1436static void net_timeout(struct net_device *dev)
1437{
1438 /* If we get here, some higher level has decided we are broken.
1439 There should really be a "kick me" function call instead. */
Joe Perches808e9a72012-05-18 12:56:30 +00001440 cs89_dbg(0, err, "%s: transmit timed out, %s?\n",
1441 dev->name,
1442 tx_done(dev) ? "IRQ conflict" : "network cable problem");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443 /* Try to restart the adaptor. */
1444 netif_wake_queue(dev);
1445}
1446
Joe Perches204a38a2012-05-18 12:56:27 +00001447static netdev_tx_t net_send_packet(struct sk_buff *skb, struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448{
1449 struct net_local *lp = netdev_priv(dev);
Dongdong Deng79fbe132009-07-12 20:27:06 +00001450 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451
Joe Perches808e9a72012-05-18 12:56:30 +00001452 cs89_dbg(3, debug, "%s: sent %d byte packet of type %x\n",
1453 dev->name, skb->len,
1454 ((skb->data[ETH_ALEN + ETH_ALEN] << 8) |
1455 skb->data[ETH_ALEN + ETH_ALEN + 1]));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456
1457 /* keep the upload from being interrupted, since we
Joe Perchesca034bc2012-05-18 12:56:29 +00001458 * ask the chip to start transmitting before the
1459 * whole packet has been completely uploaded.
1460 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461
Dongdong Deng79fbe132009-07-12 20:27:06 +00001462 spin_lock_irqsave(&lp->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463 netif_stop_queue(dev);
1464
1465 /* initiate a transmit sequence */
Jaccon Bastiaansen09dcd602012-05-17 07:11:42 +00001466 iowrite16(lp->send_cmd, lp->virt_addr + TX_CMD_PORT);
1467 iowrite16(skb->len, lp->virt_addr + TX_LEN_PORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468
1469 /* Test to see if the chip has allocated memory for the packet */
1470 if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) {
Joe Perches204a38a2012-05-18 12:56:27 +00001471 /* Gasp! It hasn't. But that shouldn't happen since
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472 * we're waiting for TxOk, so return 1 and requeue this packet.
1473 */
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001474
Dongdong Deng79fbe132009-07-12 20:27:06 +00001475 spin_unlock_irqrestore(&lp->lock, flags);
Joe Perches808e9a72012-05-18 12:56:30 +00001476 cs89_dbg(0, err, "Tx buffer not free!\n");
Patrick McHardy5b548142009-06-12 06:22:29 +00001477 return NETDEV_TX_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478 }
1479 /* Write the contents of the packet */
Joe Perchesca034bc2012-05-18 12:56:29 +00001480 writewords(lp, TX_FRAME_PORT, skb->data, (skb->len + 1) >> 1);
Dongdong Deng79fbe132009-07-12 20:27:06 +00001481 spin_unlock_irqrestore(&lp->lock, flags);
Kulikov Vasiliy661a16c2010-07-05 02:13:15 +00001482 dev->stats.tx_bytes += skb->len;
Joe Perches204a38a2012-05-18 12:56:27 +00001483 dev_kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484
Joe Perches204a38a2012-05-18 12:56:27 +00001485 /* We DO NOT call netif_wake_queue() here.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486 * We also DO NOT call netif_start_queue().
1487 *
1488 * Either of these would cause another bottom half run through
Joe Perchesca034bc2012-05-18 12:56:29 +00001489 * net_send_packet() before this packet has fully gone out.
1490 * That causes us to hit the "Gasp!" above and the send is rescheduled.
1491 * it runs like a dog. We just return and wait for the Tx completion
1492 * interrupt handler to restart the netdevice layer
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493 */
1494
Patrick McHardy6ed10652009-06-23 06:03:08 +00001495 return NETDEV_TX_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496}
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001497
Linus Torvalds1da177e2005-04-16 15:20:36 -07001498/* The typical workload of the driver:
Joe Perches204a38a2012-05-18 12:56:27 +00001499 * Handle the network interface interrupts.
1500 */
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001501
David Howells7d12e782006-10-05 14:55:46 +01001502static irqreturn_t net_interrupt(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001503{
1504 struct net_device *dev = dev_id;
1505 struct net_local *lp;
Jaccon Bastiaansen09dcd602012-05-17 07:11:42 +00001506 int status;
Joe Perches204a38a2012-05-18 12:56:27 +00001507 int handled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001508
Linus Torvalds1da177e2005-04-16 15:20:36 -07001509 lp = netdev_priv(dev);
1510
1511 /* we MUST read all the events out of the ISQ, otherwise we'll never
Joe Perches204a38a2012-05-18 12:56:27 +00001512 * get interrupted again. As a consequence, we can't have any limit
1513 * on the number of times we loop in the interrupt handler. The
1514 * hardware guarantees that eventually we'll run out of events. Of
1515 * course, if you're on a slow machine, and packets are arriving
1516 * faster than you can read them off, you're screwed. Hasta la
1517 * vista, baby!
1518 */
Jaccon Bastiaansen09dcd602012-05-17 07:11:42 +00001519 while ((status = ioread16(lp->virt_addr + ISQ_PORT))) {
Joe Perches808e9a72012-05-18 12:56:30 +00001520 cs89_dbg(4, debug, "%s: event=%04x\n", dev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521 handled = 1;
Joe Perches204a38a2012-05-18 12:56:27 +00001522 switch (status & ISQ_EVENT_MASK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523 case ISQ_RECEIVER_EVENT:
1524 /* Got a packet(s). */
1525 net_rx(dev);
1526 break;
1527 case ISQ_TRANSMITTER_EVENT:
Kulikov Vasiliy661a16c2010-07-05 02:13:15 +00001528 dev->stats.tx_packets++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001529 netif_wake_queue(dev); /* Inform upper layers. */
Joe Perches204a38a2012-05-18 12:56:27 +00001530 if ((status & (TX_OK |
1531 TX_LOST_CRS |
1532 TX_SQE_ERROR |
1533 TX_LATE_COL |
1534 TX_16_COL)) != TX_OK) {
Kulikov Vasiliy661a16c2010-07-05 02:13:15 +00001535 if ((status & TX_OK) == 0)
1536 dev->stats.tx_errors++;
1537 if (status & TX_LOST_CRS)
1538 dev->stats.tx_carrier_errors++;
1539 if (status & TX_SQE_ERROR)
1540 dev->stats.tx_heartbeat_errors++;
1541 if (status & TX_LATE_COL)
1542 dev->stats.tx_window_errors++;
1543 if (status & TX_16_COL)
1544 dev->stats.tx_aborted_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001545 }
1546 break;
1547 case ISQ_BUFFER_EVENT:
1548 if (status & READY_FOR_TX) {
1549 /* we tried to transmit a packet earlier,
Joe Perches204a38a2012-05-18 12:56:27 +00001550 * but inexplicably ran out of buffers.
1551 * That shouldn't happen since we only ever
1552 * load one packet. Shrug. Do the right
1553 * thing anyway.
1554 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001555 netif_wake_queue(dev); /* Inform upper layers. */
1556 }
1557 if (status & TX_UNDERRUN) {
Joe Perches808e9a72012-05-18 12:56:30 +00001558 cs89_dbg(0, err, "%s: transmit underrun\n",
1559 dev->name);
Joe Perches204a38a2012-05-18 12:56:27 +00001560 lp->send_underrun++;
Joe Perchesca034bc2012-05-18 12:56:29 +00001561 if (lp->send_underrun == 3)
1562 lp->send_cmd = TX_AFTER_381;
1563 else if (lp->send_underrun == 6)
1564 lp->send_cmd = TX_AFTER_ALL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001565 /* transmit cycle is done, although
Joe Perches204a38a2012-05-18 12:56:27 +00001566 * frame wasn't transmitted - this
1567 * avoids having to wait for the upper
1568 * layers to timeout on us, in the
1569 * event of a tx underrun
1570 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001571 netif_wake_queue(dev); /* Inform upper layers. */
Joe Perches204a38a2012-05-18 12:56:27 +00001572 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001573#if ALLOW_DMA
1574 if (lp->use_dma && (status & RX_DMA)) {
1575 int count = readreg(dev, PP_DmaFrameCnt);
Joe Perches204a38a2012-05-18 12:56:27 +00001576 while (count) {
Joe Perches808e9a72012-05-18 12:56:30 +00001577 cs89_dbg(5, debug,
1578 "%s: receiving %d DMA frames\n",
1579 dev->name, count);
1580 if (count > 1)
1581 cs89_dbg(2, debug,
1582 "%s: receiving %d DMA frames\n",
1583 dev->name, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584 dma_rx(dev);
1585 if (--count == 0)
1586 count = readreg(dev, PP_DmaFrameCnt);
Joe Perches808e9a72012-05-18 12:56:30 +00001587 if (count > 0)
1588 cs89_dbg(2, debug,
1589 "%s: continuing with %d DMA frames\n",
1590 dev->name, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001591 }
1592 }
1593#endif
1594 break;
1595 case ISQ_RX_MISS_EVENT:
Kulikov Vasiliy661a16c2010-07-05 02:13:15 +00001596 dev->stats.rx_missed_errors += (status >> 6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001597 break;
1598 case ISQ_TX_COL_EVENT:
Kulikov Vasiliy661a16c2010-07-05 02:13:15 +00001599 dev->stats.collisions += (status >> 6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001600 break;
1601 }
1602 }
1603 return IRQ_RETVAL(handled);
1604}
1605
1606static void
Kulikov Vasiliy661a16c2010-07-05 02:13:15 +00001607count_rx_errors(int status, struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001608{
Kulikov Vasiliy661a16c2010-07-05 02:13:15 +00001609 dev->stats.rx_errors++;
1610 if (status & RX_RUNT)
1611 dev->stats.rx_length_errors++;
1612 if (status & RX_EXTRA_DATA)
1613 dev->stats.rx_length_errors++;
Joe Perchesca034bc2012-05-18 12:56:29 +00001614 if ((status & RX_CRC_ERROR) && !(status & (RX_EXTRA_DATA | RX_RUNT)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615 /* per str 172 */
Kulikov Vasiliy661a16c2010-07-05 02:13:15 +00001616 dev->stats.rx_crc_errors++;
1617 if (status & RX_DRIBBLE)
1618 dev->stats.rx_frame_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001619}
1620
1621/* We have a good packet(s), get it/them out of the buffers. */
1622static void
1623net_rx(struct net_device *dev)
1624{
Jaccon Bastiaansen09dcd602012-05-17 07:11:42 +00001625 struct net_local *lp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626 struct sk_buff *skb;
1627 int status, length;
1628
Jaccon Bastiaansen09dcd602012-05-17 07:11:42 +00001629 status = ioread16(lp->virt_addr + RX_FRAME_PORT);
1630 length = ioread16(lp->virt_addr + RX_FRAME_PORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631
1632 if ((status & RX_OK) == 0) {
Kulikov Vasiliy661a16c2010-07-05 02:13:15 +00001633 count_rx_errors(status, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001634 return;
1635 }
1636
1637 /* Malloc up new buffer. */
Pradeep A Dalvi21a4e462012-02-05 02:50:10 +00001638 skb = netdev_alloc_skb(dev, length + 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001639 if (skb == NULL) {
1640#if 0 /* Again, this seems a cruel thing to do */
Joe Perchesdd92b9a2012-05-18 12:56:28 +00001641 pr_warn("%s: Memory squeeze, dropping packet\n", dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001642#endif
Kulikov Vasiliy661a16c2010-07-05 02:13:15 +00001643 dev->stats.rx_dropped++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644 return;
1645 }
1646 skb_reserve(skb, 2); /* longword align L3 header */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001647
Jaccon Bastiaansen09dcd602012-05-17 07:11:42 +00001648 readwords(lp, RX_FRAME_PORT, skb_put(skb, length), length >> 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001649 if (length & 1)
Jaccon Bastiaansen09dcd602012-05-17 07:11:42 +00001650 skb->data[length-1] = ioread16(lp->virt_addr + RX_FRAME_PORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001651
Joe Perches808e9a72012-05-18 12:56:30 +00001652 cs89_dbg(3, debug, "%s: received %d byte packet of type %x\n",
1653 dev->name, length,
1654 (skb->data[ETH_ALEN + ETH_ALEN] << 8) |
1655 skb->data[ETH_ALEN + ETH_ALEN + 1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001656
Joe Perches204a38a2012-05-18 12:56:27 +00001657 skb->protocol = eth_type_trans(skb, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658 netif_rx(skb);
Kulikov Vasiliy661a16c2010-07-05 02:13:15 +00001659 dev->stats.rx_packets++;
1660 dev->stats.rx_bytes += length;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001661}
1662
1663#if ALLOW_DMA
1664static void release_dma_buff(struct net_local *lp)
1665{
1666 if (lp->dma_buff) {
Joe Perchesca034bc2012-05-18 12:56:29 +00001667 free_pages((unsigned long)(lp->dma_buff),
1668 get_order(lp->dmasize * 1024));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001669 lp->dma_buff = NULL;
1670 }
1671}
1672#endif
1673
1674/* The inverse routine to net_open(). */
1675static int
1676net_close(struct net_device *dev)
1677{
1678#if ALLOW_DMA
1679 struct net_local *lp = netdev_priv(dev);
1680#endif
1681
1682 netif_stop_queue(dev);
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001683
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684 writereg(dev, PP_RxCFG, 0);
1685 writereg(dev, PP_TxCFG, 0);
1686 writereg(dev, PP_BufCFG, 0);
1687 writereg(dev, PP_BusCTL, 0);
1688
1689 free_irq(dev->irq, dev);
1690
1691#if ALLOW_DMA
1692 if (lp->use_dma && lp->dma) {
1693 free_dma(dev->dma);
1694 release_dma_buff(lp);
1695 }
1696#endif
1697
1698 /* Update the statistics here. */
1699 return 0;
1700}
1701
Joe Perches204a38a2012-05-18 12:56:27 +00001702/* Get the current statistics.
1703 * This may be called with the card open or closed.
1704 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705static struct net_device_stats *
1706net_get_stats(struct net_device *dev)
1707{
1708 struct net_local *lp = netdev_priv(dev);
1709 unsigned long flags;
1710
1711 spin_lock_irqsave(&lp->lock, flags);
1712 /* Update the statistics from the device registers. */
Kulikov Vasiliy661a16c2010-07-05 02:13:15 +00001713 dev->stats.rx_missed_errors += (readreg(dev, PP_RxMiss) >> 6);
1714 dev->stats.collisions += (readreg(dev, PP_TxCol) >> 6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715 spin_unlock_irqrestore(&lp->lock, flags);
1716
Kulikov Vasiliy661a16c2010-07-05 02:13:15 +00001717 return &dev->stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718}
1719
1720static void set_multicast_list(struct net_device *dev)
1721{
1722 struct net_local *lp = netdev_priv(dev);
1723 unsigned long flags;
1724
1725 spin_lock_irqsave(&lp->lock, flags);
Joe Perchesca034bc2012-05-18 12:56:29 +00001726 if (dev->flags & IFF_PROMISC)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001727 lp->rx_mode = RX_ALL_ACCEPT;
Jiri Pirkoe1d44472010-02-17 11:09:31 +00001728 else if ((dev->flags & IFF_ALLMULTI) || !netdev_mc_empty(dev))
Joe Perchesca034bc2012-05-18 12:56:29 +00001729 /* The multicast-accept list is initialized to accept-all,
1730 * and we rely on higher-level filtering for now.
1731 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001732 lp->rx_mode = RX_MULTCAST_ACCEPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733 else
1734 lp->rx_mode = 0;
1735
1736 writereg(dev, PP_RxCTL, DEF_RX_ACCEPT | lp->rx_mode);
1737
Joe Perchesca034bc2012-05-18 12:56:29 +00001738 /* in promiscuous mode, we accept errored packets,
1739 * so we have to enable interrupts on them also
1740 */
1741 writereg(dev, PP_RxCFG,
1742 (lp->curr_rx_cfg |
1743 (lp->rx_mode == RX_ALL_ACCEPT)
1744 ? (RX_CRC_ERROR_ENBL | RX_RUNT_ENBL | RX_EXTRA_DATA_ENBL)
1745 : 0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001746 spin_unlock_irqrestore(&lp->lock, flags);
1747}
1748
Linus Torvalds1da177e2005-04-16 15:20:36 -07001749static int set_mac_address(struct net_device *dev, void *p)
1750{
1751 int i;
1752 struct sockaddr *addr = p;
1753
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754 if (netif_running(dev))
1755 return -EBUSY;
1756
1757 memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
1758
Joe Perches808e9a72012-05-18 12:56:30 +00001759 cs89_dbg(0, debug, "%s: Setting MAC address to %pM\n",
1760 dev->name, dev->dev_addr);
Johannes Berge1749612008-10-27 15:59:26 -07001761
Linus Torvalds1da177e2005-04-16 15:20:36 -07001762 /* set the Ethernet address */
Joe Perches204a38a2012-05-18 12:56:27 +00001763 for (i = 0; i < ETH_ALEN / 2; i++)
Joe Perchesca034bc2012-05-18 12:56:29 +00001764 writereg(dev, PP_IA + i * 2,
1765 (dev->dev_addr[i * 2] |
1766 (dev->dev_addr[i * 2 + 1] << 8)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001767
1768 return 0;
1769}
1770
Jaccon Bastiaansene9460a92012-01-26 21:46:15 +01001771#if defined(MODULE) && !defined(CONFIG_CS89x0_PLATFORM)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001772
1773static struct net_device *dev_cs89x0;
1774
Joe Perches204a38a2012-05-18 12:56:27 +00001775/* Support the 'debug' module parm even if we're compiled for non-debug to
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001776 * avoid breaking someone's startup scripts
Linus Torvalds1da177e2005-04-16 15:20:36 -07001777 */
1778
1779static int io;
1780static int irq;
1781static int debug;
1782static char media[8];
Joe Perches204a38a2012-05-18 12:56:27 +00001783static int duplex = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001784
1785static int use_dma; /* These generate unused var warnings if ALLOW_DMA = 0 */
1786static int dma;
Joe Perches204a38a2012-05-18 12:56:27 +00001787static int dmasize = 16; /* or 64 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001788
1789module_param(io, int, 0);
1790module_param(irq, int, 0);
1791module_param(debug, int, 0);
1792module_param_string(media, media, sizeof(media), 0);
1793module_param(duplex, int, 0);
1794module_param(dma , int, 0);
1795module_param(dmasize , int, 0);
1796module_param(use_dma , int, 0);
1797MODULE_PARM_DESC(io, "cs89x0 I/O base address");
1798MODULE_PARM_DESC(irq, "cs89x0 IRQ number");
1799#if DEBUGGING
1800MODULE_PARM_DESC(debug, "cs89x0 debug level (0-6)");
1801#else
1802MODULE_PARM_DESC(debug, "(ignored)");
1803#endif
1804MODULE_PARM_DESC(media, "Set cs89x0 adapter(s) media type(s) (rj45,bnc,aui)");
1805/* No other value than -1 for duplex seems to be currently interpreted */
1806MODULE_PARM_DESC(duplex, "(ignored)");
1807#if ALLOW_DMA
1808MODULE_PARM_DESC(dma , "cs89x0 ISA DMA channel; ignored if use_dma=0");
1809MODULE_PARM_DESC(dmasize , "cs89x0 DMA size in kB (16,64); ignored if use_dma=0");
1810MODULE_PARM_DESC(use_dma , "cs89x0 using DMA (0-1)");
1811#else
1812MODULE_PARM_DESC(dma , "(ignored)");
1813MODULE_PARM_DESC(dmasize , "(ignored)");
1814MODULE_PARM_DESC(use_dma , "(ignored)");
1815#endif
1816
Francois Camie1f8e872008-10-15 22:01:59 -07001817MODULE_AUTHOR("Mike Cruse, Russwll Nelson <nelson@crynwr.com>, Andrew Morton");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001818MODULE_LICENSE("GPL");
1819
Linus Torvalds1da177e2005-04-16 15:20:36 -07001820/*
Joe Perches204a38a2012-05-18 12:56:27 +00001821 * media=t - specify media type
1822 * or media=2
1823 * or media=aui
1824 * or medai=auto
1825 * duplex=0 - specify forced half/full/autonegotiate duplex
1826 * debug=# - debug level
1827 *
1828 * Default Chip Configuration:
1829 * DMA Burst = enabled
1830 * IOCHRDY Enabled = enabled
1831 * UseSA = enabled
1832 * CS8900 defaults to half-duplex if not specified on command-line
1833 * CS8920 defaults to autoneg if not specified on command-line
1834 * Use reset defaults for other config parameters
1835 *
1836 * Assumptions:
1837 * media type specified is supported (circuitry is present)
1838 * if memory address is > 1MB, then required mem decode hw is present
1839 * if 10B-2, then agent other than driver will enable DC/DC converter
1840 * (hw or software util)
1841 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842
Andrew Mortone26c1292006-08-14 22:59:59 -07001843int __init init_module(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001844{
1845 struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
1846 struct net_local *lp;
1847 int ret = 0;
1848
1849#if DEBUGGING
1850 net_debug = debug;
1851#else
1852 debug = 0;
1853#endif
1854 if (!dev)
1855 return -ENOMEM;
1856
1857 dev->irq = irq;
1858 dev->base_addr = io;
1859 lp = netdev_priv(dev);
1860
1861#if ALLOW_DMA
1862 if (use_dma) {
1863 lp->use_dma = use_dma;
1864 lp->dma = dma;
1865 lp->dmasize = dmasize;
1866 }
1867#endif
1868
1869 spin_lock_init(&lp->lock);
1870
Joe Perches204a38a2012-05-18 12:56:27 +00001871 /* boy, they'd better get these right */
1872 if (!strcmp(media, "rj45"))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001873 lp->adapter_cnf = A_CNF_MEDIA_10B_T | A_CNF_10B_T;
1874 else if (!strcmp(media, "aui"))
1875 lp->adapter_cnf = A_CNF_MEDIA_AUI | A_CNF_AUI;
1876 else if (!strcmp(media, "bnc"))
1877 lp->adapter_cnf = A_CNF_MEDIA_10B_2 | A_CNF_10B_2;
1878 else
1879 lp->adapter_cnf = A_CNF_MEDIA_10B_T | A_CNF_10B_T;
1880
Joe Perches204a38a2012-05-18 12:56:27 +00001881 if (duplex == -1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001882 lp->auto_neg_cnf = AUTO_NEG_ENABLE;
1883
Joe Perches204a38a2012-05-18 12:56:27 +00001884 if (io == 0) {
Joe Perchesdd92b9a2012-05-18 12:56:28 +00001885 pr_err("Module autoprobing not allowed\n");
1886 pr_err("Append io=0xNNN\n");
Joe Perches204a38a2012-05-18 12:56:27 +00001887 ret = -EPERM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001888 goto out;
Joe Perches204a38a2012-05-18 12:56:27 +00001889 } else if (io <= 0x1ff) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890 ret = -ENXIO;
1891 goto out;
1892 }
1893
1894#if ALLOW_DMA
1895 if (use_dma && dmasize != 16 && dmasize != 64) {
Joe Perchesdd92b9a2012-05-18 12:56:28 +00001896 pr_err("dma size must be either 16K or 64K, not %dK\n",
1897 dmasize);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001898 ret = -EPERM;
1899 goto out;
1900 }
1901#endif
Jaccon Bastiaansen09dcd602012-05-17 07:11:42 +00001902 ret = cs89x0_ioport_probe(dev, io, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001903 if (ret)
1904 goto out;
1905
Linus Torvalds1da177e2005-04-16 15:20:36 -07001906 dev_cs89x0 = dev;
1907 return 0;
1908out:
1909 free_netdev(dev);
1910 return ret;
1911}
1912
Al Viroafc8eb42006-06-14 18:50:53 -04001913void __exit
Linus Torvalds1da177e2005-04-16 15:20:36 -07001914cleanup_module(void)
1915{
Jaccon Bastiaansen09dcd602012-05-17 07:11:42 +00001916 struct net_local *lp = netdev_priv(dev_cs89x0);
1917
Linus Torvalds1da177e2005-04-16 15:20:36 -07001918 unregister_netdev(dev_cs89x0);
Jaccon Bastiaansen09dcd602012-05-17 07:11:42 +00001919 iowrite16(PP_ChipID, lp->virt_addr + ADD_PORT);
1920 ioport_unmap(lp->virt_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001921 release_region(dev_cs89x0->base_addr, NETCARD_IO_EXTENT);
1922 free_netdev(dev_cs89x0);
1923}
Jaccon Bastiaansene9460a92012-01-26 21:46:15 +01001924#endif /* MODULE && !CONFIG_CS89x0_PLATFORM */
1925
1926#ifdef CONFIG_CS89x0_PLATFORM
1927static int __init cs89x0_platform_probe(struct platform_device *pdev)
1928{
1929 struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
1930 struct net_local *lp;
1931 struct resource *mem_res;
Jaccon Bastiaansen09dcd602012-05-17 07:11:42 +00001932 void __iomem *virt_addr;
Jaccon Bastiaansene9460a92012-01-26 21:46:15 +01001933 int err;
1934
1935 if (!dev)
1936 return -ENOMEM;
1937
1938 lp = netdev_priv(dev);
1939
1940 mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1941 dev->irq = platform_get_irq(pdev, 0);
1942 if (mem_res == NULL || dev->irq <= 0) {
Joe Perchesca034bc2012-05-18 12:56:29 +00001943 dev_warn(&dev->dev, "memory/interrupt resource missing\n");
Jaccon Bastiaansene9460a92012-01-26 21:46:15 +01001944 err = -ENXIO;
1945 goto free;
1946 }
1947
Jaccon Bastiaansene9460a92012-01-26 21:46:15 +01001948 lp->size = resource_size(mem_res);
Jaccon Bastiaansen09dcd602012-05-17 07:11:42 +00001949 if (!request_mem_region(mem_res->start, lp->size, DRV_NAME)) {
Joe Perchesca034bc2012-05-18 12:56:29 +00001950 dev_warn(&dev->dev, "request_mem_region() failed\n");
Jaccon Bastiaansene9460a92012-01-26 21:46:15 +01001951 err = -EBUSY;
1952 goto free;
1953 }
1954
Jaccon Bastiaansen09dcd602012-05-17 07:11:42 +00001955 virt_addr = ioremap(mem_res->start, lp->size);
1956 if (!virt_addr) {
Joe Perchesca034bc2012-05-18 12:56:29 +00001957 dev_warn(&dev->dev, "ioremap() failed\n");
Jaccon Bastiaansene9460a92012-01-26 21:46:15 +01001958 err = -ENOMEM;
1959 goto release;
1960 }
1961
Jaccon Bastiaansen09dcd602012-05-17 07:11:42 +00001962 err = cs89x0_probe1(dev, virt_addr, 0);
Jaccon Bastiaansene9460a92012-01-26 21:46:15 +01001963 if (err) {
Joe Perchesca034bc2012-05-18 12:56:29 +00001964 dev_warn(&dev->dev, "no cs8900 or cs8920 detected\n");
Jaccon Bastiaansene9460a92012-01-26 21:46:15 +01001965 goto unmap;
1966 }
1967
1968 platform_set_drvdata(pdev, dev);
1969 return 0;
1970
1971unmap:
Jaccon Bastiaansen09dcd602012-05-17 07:11:42 +00001972 iounmap(virt_addr);
Jaccon Bastiaansene9460a92012-01-26 21:46:15 +01001973release:
Jaccon Bastiaansen09dcd602012-05-17 07:11:42 +00001974 release_mem_region(mem_res->start, lp->size);
Jaccon Bastiaansene9460a92012-01-26 21:46:15 +01001975free:
1976 free_netdev(dev);
1977 return err;
1978}
1979
1980static int cs89x0_platform_remove(struct platform_device *pdev)
1981{
1982 struct net_device *dev = platform_get_drvdata(pdev);
1983 struct net_local *lp = netdev_priv(dev);
Jaccon Bastiaansen09dcd602012-05-17 07:11:42 +00001984 struct resource *mem_res;
Jaccon Bastiaansene9460a92012-01-26 21:46:15 +01001985
Joe Perches204a38a2012-05-18 12:56:27 +00001986 /* This platform_get_resource() call will not return NULL, because
Jaccon Bastiaansen09dcd602012-05-17 07:11:42 +00001987 * the same call in cs89x0_platform_probe() has returned a non NULL
1988 * value.
1989 */
1990 mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
Jaccon Bastiaansene9460a92012-01-26 21:46:15 +01001991 unregister_netdev(dev);
1992 iounmap(lp->virt_addr);
Jaccon Bastiaansen09dcd602012-05-17 07:11:42 +00001993 release_mem_region(mem_res->start, lp->size);
Jaccon Bastiaansene9460a92012-01-26 21:46:15 +01001994 free_netdev(dev);
1995 return 0;
1996}
1997
1998static struct platform_driver cs89x0_driver = {
1999 .driver = {
2000 .name = DRV_NAME,
2001 .owner = THIS_MODULE,
2002 },
2003 .remove = cs89x0_platform_remove,
2004};
2005
2006static int __init cs89x0_init(void)
2007{
2008 return platform_driver_probe(&cs89x0_driver, cs89x0_platform_probe);
2009}
2010
2011module_init(cs89x0_init);
2012
2013static void __exit cs89x0_cleanup(void)
2014{
2015 platform_driver_unregister(&cs89x0_driver);
2016}
2017
2018module_exit(cs89x0_cleanup);
2019
2020#endif /* CONFIG_CS89x0_PLATFORM */