1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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>
35
36#include <asm/system.h>
37#include <asm/io.h>
38#include <asm/irq.h>
39
40#include "8390.h"
41
42#define DRV_NAME "ac3200"
43
44
45#define AC_NIC_BASE 0x00
46#define AC_SA_PROM 0x16
47#define AC_ADDR0 0x00
48#define AC_ADDR1 0x40
49#define AC_ADDR2 0x90
50#define AC_ID_PORT 0xC80
51#define AC_EISA_ID 0x0110d305
52#define AC_RESET_PORT 0xC84
53#define AC_RESET 0x00
54#define AC_ENABLE 0x01
55#define AC_CONFIG 0xC90
56
57#define AC_IO_EXTENT 0x20
58
59
60
61
62
63
64
65
66
67static unsigned char config2irqmap[8] __initdata = {15, 12, 11, 10, 9, 7, 5, 3};
68static int addrmap[8] =
69{0xFF0000, 0xFE0000, 0xFD0000, 0xFFF0000, 0xFFE0000, 0xFFC0000, 0xD0000, 0 };
70static const char *port_name[4] = { "10baseT", "invalid", "AUI", "10base2"};
71
72#define config2irq(configval) config2irqmap[((configval) >> 3) & 7]
73#define config2mem(configval) addrmap[(configval) & 7]
74#define config2name(configval) port_name[((configval) >> 6) & 3]
75
76
77#define AC_START_PG 0x00
78#define AC_STOP_PG 0x80
79
80static int ac_probe1(int ioaddr, struct net_device *dev);
81
82static int ac_open(struct net_device *dev);
83static void ac_reset_8390(struct net_device *dev);
84static void ac_block_input(struct net_device *dev, int count,
85 struct sk_buff *skb, int ring_offset);
86static void ac_block_output(struct net_device *dev, const int count,
87 const unsigned char *buf, const int start_page);
88static void ac_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
89 int ring_page);
90
91static int ac_close_card(struct net_device *dev);
92
93
94
95
96
97
98
99
100static int __init do_ac3200_probe(struct net_device *dev)
101{
102 unsigned short ioaddr = dev->base_addr;
103 int irq = dev->irq;
104 int mem_start = dev->mem_start;
105
106 if (ioaddr > 0x1ff)
107 return ac_probe1(ioaddr, dev);
108 else if (ioaddr > 0)
109 return -ENXIO;
110
111 if ( ! EISA_bus)
112 return -ENXIO;
113
114 for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) {
115 if (ac_probe1(ioaddr, dev) == 0)
116 return 0;
117 dev->irq = irq;
118 dev->mem_start = mem_start;
119 }
120
121 return -ENODEV;
122}
123
124#ifndef MODULE
125struct net_device * __init ac3200_probe(int unit)
126{
127 struct net_device *dev = alloc_ei_netdev();
128 int err;
129
130 if (!dev)
131 return ERR_PTR(-ENOMEM);
132
133 sprintf(dev->name, "eth%d", unit);
134 netdev_boot_setup_check(dev);
135
136 err = do_ac3200_probe(dev);
137 if (err)
138 goto out;
139 return dev;
140out:
141 free_netdev(dev);
142 return ERR_PTR(err);
143}
144#endif
145
146static const struct net_device_ops ac_netdev_ops = {
147 .ndo_open = ac_open,
148 .ndo_stop = ac_close_card,
149
150 .ndo_start_xmit = ei_start_xmit,
151 .ndo_tx_timeout = ei_tx_timeout,
152 .ndo_get_stats = ei_get_stats,
153 .ndo_set_multicast_list = ei_set_multicast_list,
154 .ndo_validate_addr = eth_validate_addr,
155 .ndo_set_mac_address = eth_mac_addr,
156 .ndo_change_mtu = eth_change_mtu,
157#ifdef CONFIG_NET_POLL_CONTROLLER
158 .ndo_poll_controller = ei_poll,
159#endif
160};
161
162static int __init ac_probe1(int ioaddr, struct net_device *dev)
163{
164 int i, retval;
165
166 if (!request_region(ioaddr, AC_IO_EXTENT, DRV_NAME))
167 return -EBUSY;
168
169 if (inb_p(ioaddr + AC_ID_PORT) == 0xff) {
170 retval = -ENODEV;
171 goto out;
172 }
173
174 if (inl(ioaddr + AC_ID_PORT) != AC_EISA_ID) {
175 retval = -ENODEV;
176 goto out;
177 }
178
179#ifndef final_version
180 printk(KERN_DEBUG "AC3200 ethercard configuration register is %#02x,"
181 " EISA ID %02x %02x %02x %02x.\n", inb(ioaddr + AC_CONFIG),
182 inb(ioaddr + AC_ID_PORT + 0), inb(ioaddr + AC_ID_PORT + 1),
183 inb(ioaddr + AC_ID_PORT + 2), inb(ioaddr + AC_ID_PORT + 3));
184#endif
185
186 for (i = 0; i < 6; i++)
187 dev->dev_addr[i] = inb(ioaddr + AC_SA_PROM + i);
188
189 printk(KERN_DEBUG "AC3200 in EISA slot %d, node %pM",
190 ioaddr/0x1000, dev->dev_addr);
191#if 0
192
193 if (inb(ioaddr + AC_SA_PROM + 0) != AC_ADDR0
194 || inb(ioaddr + AC_SA_PROM + 1) != AC_ADDR1
195 || inb(ioaddr + AC_SA_PROM + 2) != AC_ADDR2 ) {
196 printk(", not found (invalid prefix).\n");
197 retval = -ENODEV;
198 goto out;
199 }
200#endif
201
202
203 if (dev->irq == 0) {
204 dev->irq = config2irq(inb(ioaddr + AC_CONFIG));
205 printk(", using");
206 } else {
207 dev->irq = irq_canonicalize(dev->irq);
208 printk(", assigning");
209 }
210
211 retval = request_irq(dev->irq, ei_interrupt, 0, DRV_NAME, dev);
212 if (retval) {
213 printk (" nothing! Unable to get IRQ %d.\n", dev->irq);
214 goto out1;
215 }
216
217 printk(" IRQ %d, %s port\n", dev->irq, port_name[dev->if_port]);
218
219 dev->base_addr = ioaddr;
220
221#ifdef notyet
222 if (dev->mem_start) {
223 for (i = 0; i < 7; i++)
224 if (addrmap[i] == dev->mem_start)
225 break;
226 if (i >= 7)
227 i = 0;
228 outb((inb(ioaddr + AC_CONFIG) & ~7) | i, ioaddr + AC_CONFIG);
229 }
230#endif
231
232 dev->if_port = inb(ioaddr + AC_CONFIG) >> 6;
233 dev->mem_start = config2mem(inb(ioaddr + AC_CONFIG));
234
235 printk("%s: AC3200 at %#3x with %dkB memory at physical address %#lx.\n",
236 dev->name, ioaddr, AC_STOP_PG/4, dev->mem_start);
237
238
239
240
241
242
243
244 ei_status.mem = ioremap(dev->mem_start, AC_STOP_PG*0x100);
245 if (!ei_status.mem) {
246 printk(KERN_ERR "ac3200.c: Unable to remap card memory above 1MB !!\n");
247 printk(KERN_ERR "ac3200.c: Try using EISA SCU to set memory below 1MB.\n");
248 printk(KERN_ERR "ac3200.c: Driver NOT installed.\n");
249 retval = -EINVAL;
250 goto out1;
251 }
252 printk("ac3200.c: remapped %dkB card memory to virtual address %p\n",
253 AC_STOP_PG/4, ei_status.mem);
254
255 dev->mem_start = (unsigned long)ei_status.mem;
256 dev->mem_end = dev->mem_start + (AC_STOP_PG - AC_START_PG)*256;
257
258 ei_status.name = "AC3200";
259 ei_status.tx_start_page = AC_START_PG;
260 ei_status.rx_start_page = AC_START_PG + TX_PAGES;
261 ei_status.stop_page = AC_STOP_PG;
262 ei_status.word16 = 1;
263
264 if (ei_debug > 0)
265 printk(version);
266
267 ei_status.reset_8390 = &ac_reset_8390;
268 ei_status.block_input = &ac_block_input;
269 ei_status.block_output = &ac_block_output;
270 ei_status.get_8390_hdr = &ac_get_8390_hdr;
271
272 dev->netdev_ops = &ac_netdev_ops;
273 NS8390_init(dev, 0);
274
275 retval = register_netdev(dev);
276 if (retval)
277 goto out2;
278 return 0;
279out2:
280 if (ei_status.reg0)
281 iounmap(ei_status.mem);
282out1:
283 free_irq(dev->irq, dev);
284out:
285 release_region(ioaddr, AC_IO_EXTENT);
286 return retval;
287}
288
289static int ac_open(struct net_device *dev)
290{
291#ifdef notyet
292
293 int ioaddr = dev->base_addr;
294#endif
295
296 ei_open(dev);
297 return 0;
298}
299
300static void ac_reset_8390(struct net_device *dev)
301{
302 ushort ioaddr = dev->base_addr;
303
304 outb(AC_RESET, ioaddr + AC_RESET_PORT);
305 if (ei_debug > 1) printk("resetting AC3200, t=%ld...", jiffies);
306
307 ei_status.txing = 0;
308 outb(AC_ENABLE, ioaddr + AC_RESET_PORT);
309 if (ei_debug > 1) printk("reset done\n");
310
311 return;
312}
313
314
315
316
317
318static void
319ac_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
320{
321 void __iomem *hdr_start = ei_status.mem + ((ring_page - AC_START_PG)<<8);
322 memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
323}
324
325
326
327
328static void ac_block_input(struct net_device *dev, int count, struct sk_buff *skb,
329 int ring_offset)
330{
331 void __iomem *start = ei_status.mem + ring_offset - AC_START_PG*256;
332
333 if (ring_offset + count > AC_STOP_PG*256) {
334
335 int semi_count = AC_STOP_PG*256 - ring_offset;
336 memcpy_fromio(skb->data, start, semi_count);
337 count -= semi_count;
338 memcpy_fromio(skb->data + semi_count,
339 ei_status.mem + TX_PAGES*256, count);
340 } else {
341 memcpy_fromio(skb->data, start, count);
342 }
343}
344
345static void ac_block_output(struct net_device *dev, int count,
346 const unsigned char *buf, int start_page)
347{
348 void __iomem *shmem = ei_status.mem + ((start_page - AC_START_PG)<<8);
349
350 memcpy_toio(shmem, buf, count);
351}
352
353static int ac_close_card(struct net_device *dev)
354{
355 if (ei_debug > 1)
356 printk("%s: Shutting down ethercard.\n", dev->name);
357
358#ifdef notyet
359
360 outb(0x00, ioaddr + 6);
361 free_irq(dev->irq, dev);
362#endif
363
364 ei_close(dev);
365 return 0;
366}
367
368#ifdef MODULE
369#define MAX_AC32_CARDS 4
370static struct net_device *dev_ac32[MAX_AC32_CARDS];
371static int io[MAX_AC32_CARDS];
372static int irq[MAX_AC32_CARDS];
373static int mem[MAX_AC32_CARDS];
374module_param_array(io, int, NULL, 0);
375module_param_array(irq, int, NULL, 0);
376module_param_array(mem, int, NULL, 0);
377MODULE_PARM_DESC(io, "I/O base address(es)");
378MODULE_PARM_DESC(irq, "IRQ number(s)");
379MODULE_PARM_DESC(mem, "Memory base address(es)");
380MODULE_DESCRIPTION("Ansel AC3200 EISA ethernet driver");
381MODULE_LICENSE("GPL");
382
383static int __init ac3200_module_init(void)
384{
385 struct net_device *dev;
386 int this_dev, found = 0;
387
388 for (this_dev = 0; this_dev < MAX_AC32_CARDS; this_dev++) {
389 if (io[this_dev] == 0 && this_dev != 0)
390 break;
391 dev = alloc_ei_netdev();
392 if (!dev)
393 break;
394 dev->irq = irq[this_dev];
395 dev->base_addr = io[this_dev];
396 dev->mem_start = mem[this_dev];
397 if (do_ac3200_probe(dev) == 0) {
398 dev_ac32[found++] = dev;
399 continue;
400 }
401 free_netdev(dev);
402 printk(KERN_WARNING "ac3200.c: No ac3200 card found (i/o = 0x%x).\n", io[this_dev]);
403 break;
404 }
405 if (found)
406 return 0;
407 return -ENXIO;
408}
409
410static void cleanup_card(struct net_device *dev)
411{
412
413 free_irq(dev->irq, dev);
414 release_region(dev->base_addr, AC_IO_EXTENT);
415 iounmap(ei_status.mem);
416}
417
418static void __exit ac3200_module_exit(void)
419{
420 int this_dev;
421
422 for (this_dev = 0; this_dev < MAX_AC32_CARDS; this_dev++) {
423 struct net_device *dev = dev_ac32[this_dev];
424 if (dev) {
425 unregister_netdev(dev);
426 cleanup_card(dev);
427 free_netdev(dev);
428 }
429 }
430}
431module_init(ac3200_module_init);
432module_exit(ac3200_module_exit);
433#endif
434