blob: f07b2e980fbc9b1f300ff9164a78c6f1b418014c [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/* ac3200.c: A driver for the Ansel Communications EISA ethernet adaptor. */
2/*
3 Written 1993, 1994 by Donald Becker.
4 Copyright 1993 United States Government as represented by the Director,
5 National Security Agency. This software may only be used and distributed
6 according to the terms of the GNU General Public License as modified by SRC,
7 incorporated herein by reference.
8
9 The author may be reached as becker@scyld.com, or C/O
10 Scyld Computing Corporation
11 410 Severn Ave., Suite 210
12 Annapolis MD 21403
13
14 This is driver for the Ansel Communications Model 3200 EISA Ethernet LAN
15 Adapter. The programming information is from the users manual, as related
16 by glee@ardnassak.math.clemson.edu.
17
18 Changelog:
19
20 Paul Gortmaker 05/98 : add support for shared mem above 1MB.
21
22 */
23
24static const char version[] =
25 "ac3200.c:v1.01 7/1/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
26
27#include <linux/module.h>
28#include <linux/eisa.h>
29#include <linux/kernel.h>
30#include <linux/errno.h>
31#include <linux/string.h>
32#include <linux/netdevice.h>
33#include <linux/etherdevice.h>
34#include <linux/init.h>
Alexey Dobriyana6b7a402011-06-06 10:43:46 +000035#include <linux/interrupt.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070036
37#include <asm/system.h>
38#include <asm/io.h>
39#include <asm/irq.h>
40
41#include "8390.h"
42
43#define DRV_NAME "ac3200"
44
45/* Offsets from the base address. */
46#define AC_NIC_BASE 0x00
47#define AC_SA_PROM 0x16 /* The station address PROM. */
48#define AC_ADDR0 0x00 /* Prefix station address values. */
Jeff Garzik6aa20a22006-09-13 13:24:59 -040049#define AC_ADDR1 0x40
Linus Torvalds1da177e2005-04-16 15:20:36 -070050#define AC_ADDR2 0x90
51#define AC_ID_PORT 0xC80
52#define AC_EISA_ID 0x0110d305
53#define AC_RESET_PORT 0xC84
54#define AC_RESET 0x00
55#define AC_ENABLE 0x01
56#define AC_CONFIG 0xC90 /* The configuration port. */
57
58#define AC_IO_EXTENT 0x20
59 /* Actually accessed is:
60 * AC_NIC_BASE (0-15)
61 * AC_SA_PROM (0-5)
62 * AC_ID_PORT (0-3)
63 * AC_RESET_PORT
64 * AC_CONFIG
65 */
66
67/* Decoding of the configuration register. */
68static unsigned char config2irqmap[8] __initdata = {15, 12, 11, 10, 9, 7, 5, 3};
69static int addrmap[8] =
70{0xFF0000, 0xFE0000, 0xFD0000, 0xFFF0000, 0xFFE0000, 0xFFC0000, 0xD0000, 0 };
71static const char *port_name[4] = { "10baseT", "invalid", "AUI", "10base2"};
72
73#define config2irq(configval) config2irqmap[((configval) >> 3) & 7]
74#define config2mem(configval) addrmap[(configval) & 7]
75#define config2name(configval) port_name[((configval) >> 6) & 3]
76
77/* First and last 8390 pages. */
78#define AC_START_PG 0x00 /* First page of 8390 TX buffer */
79#define AC_STOP_PG 0x80 /* Last page +1 of the 8390 RX ring */
80
81static int ac_probe1(int ioaddr, struct net_device *dev);
82
83static int ac_open(struct net_device *dev);
84static void ac_reset_8390(struct net_device *dev);
85static void ac_block_input(struct net_device *dev, int count,
86 struct sk_buff *skb, int ring_offset);
87static void ac_block_output(struct net_device *dev, const int count,
88 const unsigned char *buf, const int start_page);
89static void ac_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
90 int ring_page);
91
92static int ac_close_card(struct net_device *dev);
Jeff Garzik6aa20a22006-09-13 13:24:59 -040093
Linus Torvalds1da177e2005-04-16 15:20:36 -070094
95/* Probe for the AC3200.
96
97 The AC3200 can be identified by either the EISA configuration registers,
98 or the unique value in the station address PROM.
99 */
100
101static int __init do_ac3200_probe(struct net_device *dev)
102{
103 unsigned short ioaddr = dev->base_addr;
104 int irq = dev->irq;
105 int mem_start = dev->mem_start;
106
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107 if (ioaddr > 0x1ff) /* Check a single specified location. */
108 return ac_probe1(ioaddr, dev);
109 else if (ioaddr > 0) /* Don't probe at all. */
110 return -ENXIO;
111
112 if ( ! EISA_bus)
113 return -ENXIO;
114
115 for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) {
116 if (ac_probe1(ioaddr, dev) == 0)
117 return 0;
118 dev->irq = irq;
119 dev->mem_start = mem_start;
120 }
121
122 return -ENODEV;
123}
124
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125#ifndef MODULE
126struct net_device * __init ac3200_probe(int unit)
127{
128 struct net_device *dev = alloc_ei_netdev();
129 int err;
130
131 if (!dev)
132 return ERR_PTR(-ENOMEM);
133
134 sprintf(dev->name, "eth%d", unit);
135 netdev_boot_setup_check(dev);
136
137 err = do_ac3200_probe(dev);
138 if (err)
139 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140 return dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141out:
142 free_netdev(dev);
143 return ERR_PTR(err);
144}
145#endif
146
Stephen Hemminger1494f2f2009-03-26 15:11:41 +0000147static const struct net_device_ops ac_netdev_ops = {
148 .ndo_open = ac_open,
149 .ndo_stop = ac_close_card,
150
151 .ndo_start_xmit = ei_start_xmit,
152 .ndo_tx_timeout = ei_tx_timeout,
153 .ndo_get_stats = ei_get_stats,
154 .ndo_set_multicast_list = ei_set_multicast_list,
155 .ndo_validate_addr = eth_validate_addr,
156 .ndo_set_mac_address = eth_mac_addr,
157 .ndo_change_mtu = eth_change_mtu,
158#ifdef CONFIG_NET_POLL_CONTROLLER
159 .ndo_poll_controller = ei_poll,
160#endif
161};
162
Linus Torvalds1da177e2005-04-16 15:20:36 -0700163static int __init ac_probe1(int ioaddr, struct net_device *dev)
164{
165 int i, retval;
166
167 if (!request_region(ioaddr, AC_IO_EXTENT, DRV_NAME))
168 return -EBUSY;
169
170 if (inb_p(ioaddr + AC_ID_PORT) == 0xff) {
171 retval = -ENODEV;
172 goto out;
173 }
174
175 if (inl(ioaddr + AC_ID_PORT) != AC_EISA_ID) {
176 retval = -ENODEV;
177 goto out;
178 }
179
180#ifndef final_version
181 printk(KERN_DEBUG "AC3200 ethercard configuration register is %#02x,"
182 " EISA ID %02x %02x %02x %02x.\n", inb(ioaddr + AC_CONFIG),
183 inb(ioaddr + AC_ID_PORT + 0), inb(ioaddr + AC_ID_PORT + 1),
184 inb(ioaddr + AC_ID_PORT + 2), inb(ioaddr + AC_ID_PORT + 3));
185#endif
186
Joe Perches0795af52007-10-03 17:59:30 -0700187 for (i = 0; i < 6; i++)
188 dev->dev_addr[i] = inb(ioaddr + AC_SA_PROM + i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189
Johannes Berge1749612008-10-27 15:59:26 -0700190 printk(KERN_DEBUG "AC3200 in EISA slot %d, node %pM",
191 ioaddr/0x1000, dev->dev_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192#if 0
193 /* Check the vendor ID/prefix. Redundant after checking the EISA ID */
194 if (inb(ioaddr + AC_SA_PROM + 0) != AC_ADDR0
195 || inb(ioaddr + AC_SA_PROM + 1) != AC_ADDR1
196 || inb(ioaddr + AC_SA_PROM + 2) != AC_ADDR2 ) {
197 printk(", not found (invalid prefix).\n");
198 retval = -ENODEV;
199 goto out;
200 }
201#endif
202
203 /* Assign and allocate the interrupt now. */
204 if (dev->irq == 0) {
205 dev->irq = config2irq(inb(ioaddr + AC_CONFIG));
206 printk(", using");
207 } else {
208 dev->irq = irq_canonicalize(dev->irq);
209 printk(", assigning");
210 }
211
212 retval = request_irq(dev->irq, ei_interrupt, 0, DRV_NAME, dev);
213 if (retval) {
214 printk (" nothing! Unable to get IRQ %d.\n", dev->irq);
Kulikov Vasiliyba80a252010-07-09 02:28:09 +0000215 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216 }
217
218 printk(" IRQ %d, %s port\n", dev->irq, port_name[dev->if_port]);
219
220 dev->base_addr = ioaddr;
221
222#ifdef notyet
223 if (dev->mem_start) { /* Override the value from the board. */
224 for (i = 0; i < 7; i++)
225 if (addrmap[i] == dev->mem_start)
226 break;
227 if (i >= 7)
228 i = 0;
229 outb((inb(ioaddr + AC_CONFIG) & ~7) | i, ioaddr + AC_CONFIG);
230 }
231#endif
232
233 dev->if_port = inb(ioaddr + AC_CONFIG) >> 6;
234 dev->mem_start = config2mem(inb(ioaddr + AC_CONFIG));
235
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400236 printk("%s: AC3200 at %#3x with %dkB memory at physical address %#lx.\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237 dev->name, ioaddr, AC_STOP_PG/4, dev->mem_start);
238
239 /*
240 * BEWARE!! Some dain-bramaged EISA SCUs will allow you to put
241 * the card mem within the region covered by `normal' RAM !!!
242 *
243 * ioremap() will fail in that case.
244 */
245 ei_status.mem = ioremap(dev->mem_start, AC_STOP_PG*0x100);
246 if (!ei_status.mem) {
247 printk(KERN_ERR "ac3200.c: Unable to remap card memory above 1MB !!\n");
248 printk(KERN_ERR "ac3200.c: Try using EISA SCU to set memory below 1MB.\n");
249 printk(KERN_ERR "ac3200.c: Driver NOT installed.\n");
250 retval = -EINVAL;
251 goto out1;
252 }
253 printk("ac3200.c: remapped %dkB card memory to virtual address %p\n",
254 AC_STOP_PG/4, ei_status.mem);
255
256 dev->mem_start = (unsigned long)ei_status.mem;
257 dev->mem_end = dev->mem_start + (AC_STOP_PG - AC_START_PG)*256;
258
259 ei_status.name = "AC3200";
260 ei_status.tx_start_page = AC_START_PG;
261 ei_status.rx_start_page = AC_START_PG + TX_PAGES;
262 ei_status.stop_page = AC_STOP_PG;
263 ei_status.word16 = 1;
264
265 if (ei_debug > 0)
266 printk(version);
267
268 ei_status.reset_8390 = &ac_reset_8390;
269 ei_status.block_input = &ac_block_input;
270 ei_status.block_output = &ac_block_output;
271 ei_status.get_8390_hdr = &ac_get_8390_hdr;
272
Stephen Hemminger1494f2f2009-03-26 15:11:41 +0000273 dev->netdev_ops = &ac_netdev_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274 NS8390_init(dev, 0);
b1fc5502005-05-12 20:11:55 -0400275
276 retval = register_netdev(dev);
277 if (retval)
278 goto out2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279 return 0;
b1fc5502005-05-12 20:11:55 -0400280out2:
281 if (ei_status.reg0)
viro@ftp.linux.org.uk5ac900372005-09-06 01:36:58 +0100282 iounmap(ei_status.mem);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283out1:
284 free_irq(dev->irq, dev);
285out:
286 release_region(ioaddr, AC_IO_EXTENT);
287 return retval;
288}
289
290static int ac_open(struct net_device *dev)
291{
292#ifdef notyet
293 /* Someday we may enable the IRQ and shared memory here. */
294 int ioaddr = dev->base_addr;
295#endif
296
297 ei_open(dev);
298 return 0;
299}
300
301static void ac_reset_8390(struct net_device *dev)
302{
303 ushort ioaddr = dev->base_addr;
304
305 outb(AC_RESET, ioaddr + AC_RESET_PORT);
306 if (ei_debug > 1) printk("resetting AC3200, t=%ld...", jiffies);
307
308 ei_status.txing = 0;
309 outb(AC_ENABLE, ioaddr + AC_RESET_PORT);
310 if (ei_debug > 1) printk("reset done\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311}
312
313/* Grab the 8390 specific header. Similar to the block_input routine, but
314 we don't need to be concerned with ring wrap as the header will be at
315 the start of a page, so we optimize accordingly. */
316
317static void
318ac_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
319{
320 void __iomem *hdr_start = ei_status.mem + ((ring_page - AC_START_PG)<<8);
321 memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
322}
323
324/* Block input and output are easy on shared memory ethercards, the only
325 complication is when the ring buffer wraps. */
326
327static void ac_block_input(struct net_device *dev, int count, struct sk_buff *skb,
328 int ring_offset)
329{
330 void __iomem *start = ei_status.mem + ring_offset - AC_START_PG*256;
331
332 if (ring_offset + count > AC_STOP_PG*256) {
333 /* We must wrap the input move. */
334 int semi_count = AC_STOP_PG*256 - ring_offset;
335 memcpy_fromio(skb->data, start, semi_count);
336 count -= semi_count;
337 memcpy_fromio(skb->data + semi_count,
338 ei_status.mem + TX_PAGES*256, count);
339 } else {
Al Viro4ec03112007-02-09 16:38:30 +0000340 memcpy_fromio(skb->data, start, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341 }
342}
343
344static void ac_block_output(struct net_device *dev, int count,
345 const unsigned char *buf, int start_page)
346{
347 void __iomem *shmem = ei_status.mem + ((start_page - AC_START_PG)<<8);
348
349 memcpy_toio(shmem, buf, count);
350}
351
352static int ac_close_card(struct net_device *dev)
353{
354 if (ei_debug > 1)
355 printk("%s: Shutting down ethercard.\n", dev->name);
356
357#ifdef notyet
358 /* We should someday disable shared memory and interrupts. */
359 outb(0x00, ioaddr + 6); /* Disable interrupts. */
360 free_irq(dev->irq, dev);
361#endif
362
363 ei_close(dev);
364 return 0;
365}
366
367#ifdef MODULE
368#define MAX_AC32_CARDS 4 /* Max number of AC32 cards per module */
369static struct net_device *dev_ac32[MAX_AC32_CARDS];
370static int io[MAX_AC32_CARDS];
371static int irq[MAX_AC32_CARDS];
372static int mem[MAX_AC32_CARDS];
373module_param_array(io, int, NULL, 0);
374module_param_array(irq, int, NULL, 0);
375module_param_array(mem, int, NULL, 0);
376MODULE_PARM_DESC(io, "I/O base address(es)");
377MODULE_PARM_DESC(irq, "IRQ number(s)");
378MODULE_PARM_DESC(mem, "Memory base address(es)");
379MODULE_DESCRIPTION("Ansel AC3200 EISA ethernet driver");
380MODULE_LICENSE("GPL");
381
Jon Schindlere8a1d912008-03-05 18:50:41 -0800382static int __init ac3200_module_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383{
384 struct net_device *dev;
385 int this_dev, found = 0;
386
387 for (this_dev = 0; this_dev < MAX_AC32_CARDS; this_dev++) {
388 if (io[this_dev] == 0 && this_dev != 0)
389 break;
390 dev = alloc_ei_netdev();
391 if (!dev)
392 break;
393 dev->irq = irq[this_dev];
394 dev->base_addr = io[this_dev];
395 dev->mem_start = mem[this_dev]; /* Currently ignored by driver */
396 if (do_ac3200_probe(dev) == 0) {
b1fc5502005-05-12 20:11:55 -0400397 dev_ac32[found++] = dev;
398 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399 }
400 free_netdev(dev);
401 printk(KERN_WARNING "ac3200.c: No ac3200 card found (i/o = 0x%x).\n", io[this_dev]);
402 break;
403 }
404 if (found)
405 return 0;
406 return -ENXIO;
407}
408
Denis Vlasenko64916f12006-01-05 22:45:47 -0800409static void cleanup_card(struct net_device *dev)
410{
411 /* Someday free_irq may be in ac_close_card() */
412 free_irq(dev->irq, dev);
413 release_region(dev->base_addr, AC_IO_EXTENT);
414 iounmap(ei_status.mem);
415}
416
Jon Schindlere8a1d912008-03-05 18:50:41 -0800417static void __exit ac3200_module_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418{
419 int this_dev;
420
421 for (this_dev = 0; this_dev < MAX_AC32_CARDS; this_dev++) {
422 struct net_device *dev = dev_ac32[this_dev];
423 if (dev) {
424 unregister_netdev(dev);
425 cleanup_card(dev);
426 free_netdev(dev);
427 }
428 }
429}
Jon Schindlere8a1d912008-03-05 18:50:41 -0800430module_init(ac3200_module_init);
431module_exit(ac3200_module_exit);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432#endif /* MODULE */