diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/net/eexpress.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/net/eexpress.c')
-rw-r--r-- | drivers/net/eexpress.c | 1752 |
1 files changed, 1752 insertions, 0 deletions
diff --git a/drivers/net/eexpress.c b/drivers/net/eexpress.c new file mode 100644 index 000000000000..fc8e7947b334 --- /dev/null +++ b/drivers/net/eexpress.c | |||
@@ -0,0 +1,1752 @@ | |||
1 | /* Intel EtherExpress 16 device driver for Linux | ||
2 | * | ||
3 | * Written by John Sullivan, 1995 | ||
4 | * based on original code by Donald Becker, with changes by | ||
5 | * Alan Cox and Pauline Middelink. | ||
6 | * | ||
7 | * Support for 8-bit mode by Zoltan Szilagyi <zoltans@cs.arizona.edu> | ||
8 | * | ||
9 | * Many modifications, and currently maintained, by | ||
10 | * Philip Blundell <philb@gnu.org> | ||
11 | * Added the Compaq LTE Alan Cox <alan@redhat.com> | ||
12 | * Added MCA support Adam Fritzler <mid@auk.cx> | ||
13 | * | ||
14 | * Note - this driver is experimental still - it has problems on faster | ||
15 | * machines. Someone needs to sit down and go through it line by line with | ||
16 | * a databook... | ||
17 | */ | ||
18 | |||
19 | /* The EtherExpress 16 is a fairly simple card, based on a shared-memory | ||
20 | * design using the i82586 Ethernet coprocessor. It bears no relationship, | ||
21 | * as far as I know, to the similarly-named "EtherExpress Pro" range. | ||
22 | * | ||
23 | * Historically, Linux support for these cards has been very bad. However, | ||
24 | * things seem to be getting better slowly. | ||
25 | */ | ||
26 | |||
27 | /* If your card is confused about what sort of interface it has (eg it | ||
28 | * persistently reports "10baseT" when none is fitted), running 'SOFTSET /BART' | ||
29 | * or 'SOFTSET /LISA' from DOS seems to help. | ||
30 | */ | ||
31 | |||
32 | /* Here's the scoop on memory mapping. | ||
33 | * | ||
34 | * There are three ways to access EtherExpress card memory: either using the | ||
35 | * shared-memory mapping, or using PIO through the dataport, or using PIO | ||
36 | * through the "shadow memory" ports. | ||
37 | * | ||
38 | * The shadow memory system works by having the card map some of its memory | ||
39 | * as follows: | ||
40 | * | ||
41 | * (the low five bits of the SMPTR are ignored) | ||
42 | * | ||
43 | * base+0x4000..400f memory at SMPTR+0..15 | ||
44 | * base+0x8000..800f memory at SMPTR+16..31 | ||
45 | * base+0xc000..c007 dubious stuff (memory at SMPTR+16..23 apparently) | ||
46 | * base+0xc008..c00f memory at 0x0008..0x000f | ||
47 | * | ||
48 | * This last set (the one at c008) is particularly handy because the SCB | ||
49 | * lives at 0x0008. So that set of ports gives us easy random access to data | ||
50 | * in the SCB without having to mess around setting up pointers and the like. | ||
51 | * We always use this method to access the SCB (via the scb_xx() functions). | ||
52 | * | ||
53 | * Dataport access works by aiming the appropriate (read or write) pointer | ||
54 | * at the first address you're interested in, and then reading or writing from | ||
55 | * the dataport. The pointers auto-increment after each transfer. We use | ||
56 | * this for data transfer. | ||
57 | * | ||
58 | * We don't use the shared-memory system because it allegedly doesn't work on | ||
59 | * all cards, and because it's a bit more prone to go wrong (it's one more | ||
60 | * thing to configure...). | ||
61 | */ | ||
62 | |||
63 | /* Known bugs: | ||
64 | * | ||
65 | * - The card seems to want to give us two interrupts every time something | ||
66 | * happens, where just one would be better. | ||
67 | */ | ||
68 | |||
69 | /* | ||
70 | * | ||
71 | * Note by Zoltan Szilagyi 10-12-96: | ||
72 | * | ||
73 | * I've succeeded in eliminating the "CU wedged" messages, and hence the | ||
74 | * lockups, which were only occurring with cards running in 8-bit mode ("force | ||
75 | * 8-bit operation" in Intel's SoftSet utility). This version of the driver | ||
76 | * sets the 82586 and the ASIC to 8-bit mode at startup; it also stops the | ||
77 | * CU before submitting a packet for transmission, and then restarts it as soon | ||
78 | * as the process of handing the packet is complete. This is definitely an | ||
79 | * unnecessary slowdown if the card is running in 16-bit mode; therefore one | ||
80 | * should detect 16-bit vs 8-bit mode from the EEPROM settings and act | ||
81 | * accordingly. In 8-bit mode with this bugfix I'm getting about 150 K/s for | ||
82 | * ftp's, which is significantly better than I get in DOS, so the overhead of | ||
83 | * stopping and restarting the CU with each transmit is not prohibitive in | ||
84 | * practice. | ||
85 | * | ||
86 | * Update by David Woodhouse 11/5/99: | ||
87 | * | ||
88 | * I've seen "CU wedged" messages in 16-bit mode, on the Alpha architecture. | ||
89 | * I assume that this is because 16-bit accesses are actually handled as two | ||
90 | * 8-bit accesses. | ||
91 | */ | ||
92 | |||
93 | #ifdef __alpha__ | ||
94 | #define LOCKUP16 1 | ||
95 | #endif | ||
96 | #ifndef LOCKUP16 | ||
97 | #define LOCKUP16 0 | ||
98 | #endif | ||
99 | |||
100 | #include <linux/config.h> | ||
101 | #include <linux/module.h> | ||
102 | #include <linux/kernel.h> | ||
103 | #include <linux/types.h> | ||
104 | #include <linux/fcntl.h> | ||
105 | #include <linux/interrupt.h> | ||
106 | #include <linux/ioport.h> | ||
107 | #include <linux/string.h> | ||
108 | #include <linux/in.h> | ||
109 | #include <linux/delay.h> | ||
110 | #include <linux/errno.h> | ||
111 | #include <linux/init.h> | ||
112 | #include <linux/netdevice.h> | ||
113 | #include <linux/etherdevice.h> | ||
114 | #include <linux/skbuff.h> | ||
115 | #include <linux/slab.h> | ||
116 | #include <linux/mca-legacy.h> | ||
117 | #include <linux/spinlock.h> | ||
118 | #include <linux/bitops.h> | ||
119 | |||
120 | #include <asm/system.h> | ||
121 | #include <asm/io.h> | ||
122 | #include <asm/irq.h> | ||
123 | |||
124 | #ifndef NET_DEBUG | ||
125 | #define NET_DEBUG 4 | ||
126 | #endif | ||
127 | |||
128 | #include "eexpress.h" | ||
129 | |||
130 | #define EEXP_IO_EXTENT 16 | ||
131 | |||
132 | /* | ||
133 | * Private data declarations | ||
134 | */ | ||
135 | |||
136 | struct net_local | ||
137 | { | ||
138 | struct net_device_stats stats; | ||
139 | unsigned long last_tx; /* jiffies when last transmit started */ | ||
140 | unsigned long init_time; /* jiffies when eexp_hw_init586 called */ | ||
141 | unsigned short rx_first; /* first rx buf, same as RX_BUF_START */ | ||
142 | unsigned short rx_last; /* last rx buf */ | ||
143 | unsigned short rx_ptr; /* first rx buf to look at */ | ||
144 | unsigned short tx_head; /* next free tx buf */ | ||
145 | unsigned short tx_reap; /* first in-use tx buf */ | ||
146 | unsigned short tx_tail; /* previous tx buf to tx_head */ | ||
147 | unsigned short tx_link; /* last known-executing tx buf */ | ||
148 | unsigned short last_tx_restart; /* set to tx_link when we | ||
149 | restart the CU */ | ||
150 | unsigned char started; | ||
151 | unsigned short rx_buf_start; | ||
152 | unsigned short rx_buf_end; | ||
153 | unsigned short num_tx_bufs; | ||
154 | unsigned short num_rx_bufs; | ||
155 | unsigned char width; /* 0 for 16bit, 1 for 8bit */ | ||
156 | unsigned char was_promisc; | ||
157 | unsigned char old_mc_count; | ||
158 | spinlock_t lock; | ||
159 | }; | ||
160 | |||
161 | /* This is the code and data that is downloaded to the EtherExpress card's | ||
162 | * memory at boot time. | ||
163 | */ | ||
164 | |||
165 | static unsigned short start_code[] = { | ||
166 | /* 0x0000 */ | ||
167 | 0x0001, /* ISCP: busy - cleared after reset */ | ||
168 | 0x0008,0x0000,0x0000, /* offset,address (lo,hi) of SCB */ | ||
169 | |||
170 | 0x0000,0x0000, /* SCB: status, commands */ | ||
171 | 0x0000,0x0000, /* links to first command block, | ||
172 | first receive descriptor */ | ||
173 | 0x0000,0x0000, /* CRC error, alignment error counts */ | ||
174 | 0x0000,0x0000, /* out of resources, overrun error counts */ | ||
175 | |||
176 | 0x0000,0x0000, /* pad */ | ||
177 | 0x0000,0x0000, | ||
178 | |||
179 | /* 0x20 -- start of 82586 CU program */ | ||
180 | #define CONF_LINK 0x20 | ||
181 | 0x0000,Cmd_Config, | ||
182 | 0x0032, /* link to next command */ | ||
183 | 0x080c, /* 12 bytes follow : fifo threshold=8 */ | ||
184 | 0x2e40, /* don't rx bad frames | ||
185 | * SRDY/ARDY => ext. sync. : preamble len=8 | ||
186 | * take addresses from data buffers | ||
187 | * 6 bytes/address | ||
188 | */ | ||
189 | 0x6000, /* default backoff method & priority | ||
190 | * interframe spacing = 0x60 */ | ||
191 | 0xf200, /* slot time=0x200 | ||
192 | * max collision retry = 0xf */ | ||
193 | #define CONF_PROMISC 0x2e | ||
194 | 0x0000, /* no HDLC : normal CRC : enable broadcast | ||
195 | * disable promiscuous/multicast modes */ | ||
196 | 0x003c, /* minimum frame length = 60 octets) */ | ||
197 | |||
198 | 0x0000,Cmd_SetAddr, | ||
199 | 0x003e, /* link to next command */ | ||
200 | #define CONF_HWADDR 0x38 | ||
201 | 0x0000,0x0000,0x0000, /* hardware address placed here */ | ||
202 | |||
203 | 0x0000,Cmd_MCast, | ||
204 | 0x0076, /* link to next command */ | ||
205 | #define CONF_NR_MULTICAST 0x44 | ||
206 | 0x0000, /* number of multicast addresses */ | ||
207 | #define CONF_MULTICAST 0x46 | ||
208 | 0x0000, 0x0000, 0x0000, /* some addresses */ | ||
209 | 0x0000, 0x0000, 0x0000, | ||
210 | 0x0000, 0x0000, 0x0000, | ||
211 | 0x0000, 0x0000, 0x0000, | ||
212 | 0x0000, 0x0000, 0x0000, | ||
213 | 0x0000, 0x0000, 0x0000, | ||
214 | 0x0000, 0x0000, 0x0000, | ||
215 | 0x0000, 0x0000, 0x0000, | ||
216 | |||
217 | #define CONF_DIAG_RESULT 0x76 | ||
218 | 0x0000, Cmd_Diag, | ||
219 | 0x007c, /* link to next command */ | ||
220 | |||
221 | 0x0000,Cmd_TDR|Cmd_INT, | ||
222 | 0x0084, | ||
223 | #define CONF_TDR_RESULT 0x82 | ||
224 | 0x0000, | ||
225 | |||
226 | 0x0000,Cmd_END|Cmd_Nop, /* end of configure sequence */ | ||
227 | 0x0084 /* dummy link */ | ||
228 | }; | ||
229 | |||
230 | /* maps irq number to EtherExpress magic value */ | ||
231 | static char irqrmap[] = { 0,0,1,2,3,4,0,0,0,1,5,6,0,0,0,0 }; | ||
232 | |||
233 | #ifdef CONFIG_MCA_LEGACY | ||
234 | /* mapping of the first four bits of the second POS register */ | ||
235 | static unsigned short mca_iomap[] = { | ||
236 | 0x270, 0x260, 0x250, 0x240, 0x230, 0x220, 0x210, 0x200, | ||
237 | 0x370, 0x360, 0x350, 0x340, 0x330, 0x320, 0x310, 0x300 | ||
238 | }; | ||
239 | /* bits 5-7 of the second POS register */ | ||
240 | static char mca_irqmap[] = { 12, 9, 3, 4, 5, 10, 11, 15 }; | ||
241 | #endif | ||
242 | |||
243 | /* | ||
244 | * Prototypes for Linux interface | ||
245 | */ | ||
246 | |||
247 | static int eexp_open(struct net_device *dev); | ||
248 | static int eexp_close(struct net_device *dev); | ||
249 | static void eexp_timeout(struct net_device *dev); | ||
250 | static struct net_device_stats *eexp_stats(struct net_device *dev); | ||
251 | static int eexp_xmit(struct sk_buff *buf, struct net_device *dev); | ||
252 | |||
253 | static irqreturn_t eexp_irq(int irq, void *dev_addr, struct pt_regs *regs); | ||
254 | static void eexp_set_multicast(struct net_device *dev); | ||
255 | |||
256 | /* | ||
257 | * Prototypes for hardware access functions | ||
258 | */ | ||
259 | |||
260 | static void eexp_hw_rx_pio(struct net_device *dev); | ||
261 | static void eexp_hw_tx_pio(struct net_device *dev, unsigned short *buf, | ||
262 | unsigned short len); | ||
263 | static int eexp_hw_probe(struct net_device *dev,unsigned short ioaddr); | ||
264 | static unsigned short eexp_hw_readeeprom(unsigned short ioaddr, | ||
265 | unsigned char location); | ||
266 | |||
267 | static unsigned short eexp_hw_lasttxstat(struct net_device *dev); | ||
268 | static void eexp_hw_txrestart(struct net_device *dev); | ||
269 | |||
270 | static void eexp_hw_txinit (struct net_device *dev); | ||
271 | static void eexp_hw_rxinit (struct net_device *dev); | ||
272 | |||
273 | static void eexp_hw_init586 (struct net_device *dev); | ||
274 | static void eexp_setup_filter (struct net_device *dev); | ||
275 | |||
276 | static char *eexp_ifmap[]={"AUI", "BNC", "RJ45"}; | ||
277 | enum eexp_iftype {AUI=0, BNC=1, TPE=2}; | ||
278 | |||
279 | #define STARTED_RU 2 | ||
280 | #define STARTED_CU 1 | ||
281 | |||
282 | /* | ||
283 | * Primitive hardware access functions. | ||
284 | */ | ||
285 | |||
286 | static inline unsigned short scb_status(struct net_device *dev) | ||
287 | { | ||
288 | return inw(dev->base_addr + 0xc008); | ||
289 | } | ||
290 | |||
291 | static inline unsigned short scb_rdcmd(struct net_device *dev) | ||
292 | { | ||
293 | return inw(dev->base_addr + 0xc00a); | ||
294 | } | ||
295 | |||
296 | static inline void scb_command(struct net_device *dev, unsigned short cmd) | ||
297 | { | ||
298 | outw(cmd, dev->base_addr + 0xc00a); | ||
299 | } | ||
300 | |||
301 | static inline void scb_wrcbl(struct net_device *dev, unsigned short val) | ||
302 | { | ||
303 | outw(val, dev->base_addr + 0xc00c); | ||
304 | } | ||
305 | |||
306 | static inline void scb_wrrfa(struct net_device *dev, unsigned short val) | ||
307 | { | ||
308 | outw(val, dev->base_addr + 0xc00e); | ||
309 | } | ||
310 | |||
311 | static inline void set_loopback(struct net_device *dev) | ||
312 | { | ||
313 | outb(inb(dev->base_addr + Config) | 2, dev->base_addr + Config); | ||
314 | } | ||
315 | |||
316 | static inline void clear_loopback(struct net_device *dev) | ||
317 | { | ||
318 | outb(inb(dev->base_addr + Config) & ~2, dev->base_addr + Config); | ||
319 | } | ||
320 | |||
321 | static inline unsigned short int SHADOW(short int addr) | ||
322 | { | ||
323 | addr &= 0x1f; | ||
324 | if (addr > 0xf) addr += 0x3ff0; | ||
325 | return addr + 0x4000; | ||
326 | } | ||
327 | |||
328 | /* | ||
329 | * Linux interface | ||
330 | */ | ||
331 | |||
332 | /* | ||
333 | * checks for presence of EtherExpress card | ||
334 | */ | ||
335 | |||
336 | static int __init do_express_probe(struct net_device *dev) | ||
337 | { | ||
338 | unsigned short *port; | ||
339 | static unsigned short ports[] = { 0x240,0x300,0x310,0x270,0x320,0x340,0 }; | ||
340 | unsigned short ioaddr = dev->base_addr; | ||
341 | int dev_irq = dev->irq; | ||
342 | int err; | ||
343 | |||
344 | SET_MODULE_OWNER(dev); | ||
345 | |||
346 | dev->if_port = 0xff; /* not set */ | ||
347 | |||
348 | #ifdef CONFIG_MCA_LEGACY | ||
349 | if (MCA_bus) { | ||
350 | int slot = 0; | ||
351 | |||
352 | /* | ||
353 | * Only find one card at a time. Subsequent calls | ||
354 | * will find others, however, proper multicard MCA | ||
355 | * probing and setup can't be done with the | ||
356 | * old-style Space.c init routines. -- ASF | ||
357 | */ | ||
358 | while (slot != MCA_NOTFOUND) { | ||
359 | int pos0, pos1; | ||
360 | |||
361 | slot = mca_find_unused_adapter(0x628B, slot); | ||
362 | if (slot == MCA_NOTFOUND) | ||
363 | break; | ||
364 | |||
365 | pos0 = mca_read_stored_pos(slot, 2); | ||
366 | pos1 = mca_read_stored_pos(slot, 3); | ||
367 | ioaddr = mca_iomap[pos1&0xf]; | ||
368 | |||
369 | dev->irq = mca_irqmap[(pos1>>4)&0x7]; | ||
370 | |||
371 | /* | ||
372 | * XXX: Transciever selection is done | ||
373 | * differently on the MCA version. | ||
374 | * How to get it to select something | ||
375 | * other than external/AUI is currently | ||
376 | * unknown. This code is just for looks. -- ASF | ||
377 | */ | ||
378 | if ((pos0 & 0x7) == 0x1) | ||
379 | dev->if_port = AUI; | ||
380 | else if ((pos0 & 0x7) == 0x5) { | ||
381 | if (pos1 & 0x80) | ||
382 | dev->if_port = BNC; | ||
383 | else | ||
384 | dev->if_port = TPE; | ||
385 | } | ||
386 | |||
387 | mca_set_adapter_name(slot, "Intel EtherExpress 16 MCA"); | ||
388 | mca_set_adapter_procfn(slot, NULL, dev); | ||
389 | mca_mark_as_used(slot); | ||
390 | |||
391 | break; | ||
392 | } | ||
393 | } | ||
394 | #endif | ||
395 | if (ioaddr&0xfe00) { | ||
396 | if (!request_region(ioaddr, EEXP_IO_EXTENT, "EtherExpress")) | ||
397 | return -EBUSY; | ||
398 | err = eexp_hw_probe(dev,ioaddr); | ||
399 | release_region(ioaddr, EEXP_IO_EXTENT); | ||
400 | return err; | ||
401 | } else if (ioaddr) | ||
402 | return -ENXIO; | ||
403 | |||
404 | for (port=&ports[0] ; *port ; port++ ) | ||
405 | { | ||
406 | unsigned short sum = 0; | ||
407 | int i; | ||
408 | if (!request_region(*port, EEXP_IO_EXTENT, "EtherExpress")) | ||
409 | continue; | ||
410 | for ( i=0 ; i<4 ; i++ ) | ||
411 | { | ||
412 | unsigned short t; | ||
413 | t = inb(*port + ID_PORT); | ||
414 | sum |= (t>>4) << ((t & 0x03)<<2); | ||
415 | } | ||
416 | if (sum==0xbaba && !eexp_hw_probe(dev,*port)) { | ||
417 | release_region(*port, EEXP_IO_EXTENT); | ||
418 | return 0; | ||
419 | } | ||
420 | release_region(*port, EEXP_IO_EXTENT); | ||
421 | dev->irq = dev_irq; | ||
422 | } | ||
423 | return -ENODEV; | ||
424 | } | ||
425 | |||
426 | #ifndef MODULE | ||
427 | struct net_device * __init express_probe(int unit) | ||
428 | { | ||
429 | struct net_device *dev = alloc_etherdev(sizeof(struct net_local)); | ||
430 | int err; | ||
431 | |||
432 | if (!dev) | ||
433 | return ERR_PTR(-ENOMEM); | ||
434 | |||
435 | sprintf(dev->name, "eth%d", unit); | ||
436 | netdev_boot_setup_check(dev); | ||
437 | |||
438 | err = do_express_probe(dev); | ||
439 | if (!err) { | ||
440 | err = register_netdev(dev); | ||
441 | if (!err) | ||
442 | return dev; | ||
443 | } | ||
444 | free_netdev(dev); | ||
445 | return ERR_PTR(err); | ||
446 | } | ||
447 | #endif | ||
448 | |||
449 | /* | ||
450 | * open and initialize the adapter, ready for use | ||
451 | */ | ||
452 | |||
453 | static int eexp_open(struct net_device *dev) | ||
454 | { | ||
455 | int ret; | ||
456 | unsigned short ioaddr = dev->base_addr; | ||
457 | struct net_local *lp = netdev_priv(dev); | ||
458 | |||
459 | #if NET_DEBUG > 6 | ||
460 | printk(KERN_DEBUG "%s: eexp_open()\n", dev->name); | ||
461 | #endif | ||
462 | |||
463 | if (!dev->irq || !irqrmap[dev->irq]) | ||
464 | return -ENXIO; | ||
465 | |||
466 | ret = request_irq(dev->irq,&eexp_irq,0,dev->name,dev); | ||
467 | if (ret) return ret; | ||
468 | |||
469 | if (!request_region(ioaddr, EEXP_IO_EXTENT, "EtherExpress")) { | ||
470 | printk(KERN_WARNING "EtherExpress io port %x, is busy.\n" | ||
471 | , ioaddr); | ||
472 | goto err_out1; | ||
473 | } | ||
474 | if (!request_region(ioaddr+0x4000, EEXP_IO_EXTENT, "EtherExpress shadow")) { | ||
475 | printk(KERN_WARNING "EtherExpress io port %x, is busy.\n" | ||
476 | , ioaddr+0x4000); | ||
477 | goto err_out2; | ||
478 | } | ||
479 | if (!request_region(ioaddr+0x8000, EEXP_IO_EXTENT, "EtherExpress shadow")) { | ||
480 | printk(KERN_WARNING "EtherExpress io port %x, is busy.\n" | ||
481 | , ioaddr+0x8000); | ||
482 | goto err_out3; | ||
483 | } | ||
484 | if (!request_region(ioaddr+0xc000, EEXP_IO_EXTENT, "EtherExpress shadow")) { | ||
485 | printk(KERN_WARNING "EtherExpress io port %x, is busy.\n" | ||
486 | , ioaddr+0xc000); | ||
487 | goto err_out4; | ||
488 | } | ||
489 | |||
490 | if (lp->width) { | ||
491 | printk("%s: forcing ASIC to 8-bit mode\n", dev->name); | ||
492 | outb(inb(dev->base_addr+Config)&~4, dev->base_addr+Config); | ||
493 | } | ||
494 | |||
495 | eexp_hw_init586(dev); | ||
496 | netif_start_queue(dev); | ||
497 | #if NET_DEBUG > 6 | ||
498 | printk(KERN_DEBUG "%s: leaving eexp_open()\n", dev->name); | ||
499 | #endif | ||
500 | return 0; | ||
501 | |||
502 | err_out4: | ||
503 | release_region(ioaddr+0x8000, EEXP_IO_EXTENT); | ||
504 | err_out3: | ||
505 | release_region(ioaddr+0x4000, EEXP_IO_EXTENT); | ||
506 | err_out2: | ||
507 | release_region(ioaddr, EEXP_IO_EXTENT); | ||
508 | err_out1: | ||
509 | free_irq(dev->irq, dev); | ||
510 | return -EBUSY; | ||
511 | } | ||
512 | |||
513 | /* | ||
514 | * close and disable the interface, leaving the 586 in reset. | ||
515 | */ | ||
516 | |||
517 | static int eexp_close(struct net_device *dev) | ||
518 | { | ||
519 | unsigned short ioaddr = dev->base_addr; | ||
520 | struct net_local *lp = netdev_priv(dev); | ||
521 | |||
522 | int irq = dev->irq; | ||
523 | |||
524 | netif_stop_queue(dev); | ||
525 | |||
526 | outb(SIRQ_dis|irqrmap[irq],ioaddr+SET_IRQ); | ||
527 | lp->started = 0; | ||
528 | scb_command(dev, SCB_CUsuspend|SCB_RUsuspend); | ||
529 | outb(0,ioaddr+SIGNAL_CA); | ||
530 | free_irq(irq,dev); | ||
531 | outb(i586_RST,ioaddr+EEPROM_Ctrl); | ||
532 | release_region(ioaddr, EEXP_IO_EXTENT); | ||
533 | release_region(ioaddr+0x4000, 16); | ||
534 | release_region(ioaddr+0x8000, 16); | ||
535 | release_region(ioaddr+0xc000, 16); | ||
536 | |||
537 | return 0; | ||
538 | } | ||
539 | |||
540 | /* | ||
541 | * Return interface stats | ||
542 | */ | ||
543 | |||
544 | static struct net_device_stats *eexp_stats(struct net_device *dev) | ||
545 | { | ||
546 | struct net_local *lp = netdev_priv(dev); | ||
547 | |||
548 | return &lp->stats; | ||
549 | } | ||
550 | |||
551 | /* | ||
552 | * This gets called when a higher level thinks we are broken. Check that | ||
553 | * nothing has become jammed in the CU. | ||
554 | */ | ||
555 | |||
556 | static void unstick_cu(struct net_device *dev) | ||
557 | { | ||
558 | struct net_local *lp = netdev_priv(dev); | ||
559 | unsigned short ioaddr = dev->base_addr; | ||
560 | |||
561 | if (lp->started) | ||
562 | { | ||
563 | if ((jiffies - dev->trans_start)>50) | ||
564 | { | ||
565 | if (lp->tx_link==lp->last_tx_restart) | ||
566 | { | ||
567 | unsigned short boguscount=200,rsst; | ||
568 | printk(KERN_WARNING "%s: Retransmit timed out, status %04x, resetting...\n", | ||
569 | dev->name, scb_status(dev)); | ||
570 | eexp_hw_txinit(dev); | ||
571 | lp->last_tx_restart = 0; | ||
572 | scb_wrcbl(dev, lp->tx_link); | ||
573 | scb_command(dev, SCB_CUstart); | ||
574 | outb(0,ioaddr+SIGNAL_CA); | ||
575 | while (!SCB_complete(rsst=scb_status(dev))) | ||
576 | { | ||
577 | if (!--boguscount) | ||
578 | { | ||
579 | boguscount=200; | ||
580 | printk(KERN_WARNING "%s: Reset timed out status %04x, retrying...\n", | ||
581 | dev->name,rsst); | ||
582 | scb_wrcbl(dev, lp->tx_link); | ||
583 | scb_command(dev, SCB_CUstart); | ||
584 | outb(0,ioaddr+SIGNAL_CA); | ||
585 | } | ||
586 | } | ||
587 | netif_wake_queue(dev); | ||
588 | } | ||
589 | else | ||
590 | { | ||
591 | unsigned short status = scb_status(dev); | ||
592 | if (SCB_CUdead(status)) | ||
593 | { | ||
594 | unsigned short txstatus = eexp_hw_lasttxstat(dev); | ||
595 | printk(KERN_WARNING "%s: Transmit timed out, CU not active status %04x %04x, restarting...\n", | ||
596 | dev->name, status, txstatus); | ||
597 | eexp_hw_txrestart(dev); | ||
598 | } | ||
599 | else | ||
600 | { | ||
601 | unsigned short txstatus = eexp_hw_lasttxstat(dev); | ||
602 | if (netif_queue_stopped(dev) && !txstatus) | ||
603 | { | ||
604 | printk(KERN_WARNING "%s: CU wedged, status %04x %04x, resetting...\n", | ||
605 | dev->name,status,txstatus); | ||
606 | eexp_hw_init586(dev); | ||
607 | netif_wake_queue(dev); | ||
608 | } | ||
609 | else | ||
610 | { | ||
611 | printk(KERN_WARNING "%s: transmit timed out\n", dev->name); | ||
612 | } | ||
613 | } | ||
614 | } | ||
615 | } | ||
616 | } | ||
617 | else | ||
618 | { | ||
619 | if ((jiffies-lp->init_time)>10) | ||
620 | { | ||
621 | unsigned short status = scb_status(dev); | ||
622 | printk(KERN_WARNING "%s: i82586 startup timed out, status %04x, resetting...\n", | ||
623 | dev->name, status); | ||
624 | eexp_hw_init586(dev); | ||
625 | netif_wake_queue(dev); | ||
626 | } | ||
627 | } | ||
628 | } | ||
629 | |||
630 | static void eexp_timeout(struct net_device *dev) | ||
631 | { | ||
632 | struct net_local *lp = netdev_priv(dev); | ||
633 | #ifdef CONFIG_SMP | ||
634 | unsigned long flags; | ||
635 | #endif | ||
636 | int status; | ||
637 | |||
638 | disable_irq(dev->irq); | ||
639 | |||
640 | /* | ||
641 | * Best would be to use synchronize_irq(); spin_lock() here | ||
642 | * lets make it work first.. | ||
643 | */ | ||
644 | |||
645 | #ifdef CONFIG_SMP | ||
646 | spin_lock_irqsave(&lp->lock, flags); | ||
647 | #endif | ||
648 | |||
649 | status = scb_status(dev); | ||
650 | unstick_cu(dev); | ||
651 | printk(KERN_INFO "%s: transmit timed out, %s?\n", dev->name, | ||
652 | (SCB_complete(status)?"lost interrupt": | ||
653 | "board on fire")); | ||
654 | lp->stats.tx_errors++; | ||
655 | lp->last_tx = jiffies; | ||
656 | if (!SCB_complete(status)) { | ||
657 | scb_command(dev, SCB_CUabort); | ||
658 | outb(0,dev->base_addr+SIGNAL_CA); | ||
659 | } | ||
660 | netif_wake_queue(dev); | ||
661 | #ifdef CONFIG_SMP | ||
662 | spin_unlock_irqrestore(&lp->lock, flags); | ||
663 | #endif | ||
664 | } | ||
665 | |||
666 | /* | ||
667 | * Called to transmit a packet, or to allow us to right ourselves | ||
668 | * if the kernel thinks we've died. | ||
669 | */ | ||
670 | static int eexp_xmit(struct sk_buff *buf, struct net_device *dev) | ||
671 | { | ||
672 | struct net_local *lp = netdev_priv(dev); | ||
673 | short length = buf->len; | ||
674 | #ifdef CONFIG_SMP | ||
675 | unsigned long flags; | ||
676 | #endif | ||
677 | |||
678 | #if NET_DEBUG > 6 | ||
679 | printk(KERN_DEBUG "%s: eexp_xmit()\n", dev->name); | ||
680 | #endif | ||
681 | |||
682 | if (buf->len < ETH_ZLEN) { | ||
683 | buf = skb_padto(buf, ETH_ZLEN); | ||
684 | if (buf == NULL) | ||
685 | return 0; | ||
686 | length = ETH_ZLEN; | ||
687 | } | ||
688 | |||
689 | disable_irq(dev->irq); | ||
690 | |||
691 | /* | ||
692 | * Best would be to use synchronize_irq(); spin_lock() here | ||
693 | * lets make it work first.. | ||
694 | */ | ||
695 | |||
696 | #ifdef CONFIG_SMP | ||
697 | spin_lock_irqsave(&lp->lock, flags); | ||
698 | #endif | ||
699 | |||
700 | { | ||
701 | unsigned short *data = (unsigned short *)buf->data; | ||
702 | |||
703 | lp->stats.tx_bytes += length; | ||
704 | |||
705 | eexp_hw_tx_pio(dev,data,length); | ||
706 | } | ||
707 | dev_kfree_skb(buf); | ||
708 | #ifdef CONFIG_SMP | ||
709 | spin_unlock_irqrestore(&lp->lock, flags); | ||
710 | #endif | ||
711 | enable_irq(dev->irq); | ||
712 | return 0; | ||
713 | } | ||
714 | |||
715 | /* | ||
716 | * Handle an EtherExpress interrupt | ||
717 | * If we've finished initializing, start the RU and CU up. | ||
718 | * If we've already started, reap tx buffers, handle any received packets, | ||
719 | * check to make sure we've not become wedged. | ||
720 | */ | ||
721 | |||
722 | /* | ||
723 | * Handle an EtherExpress interrupt | ||
724 | * If we've finished initializing, start the RU and CU up. | ||
725 | * If we've already started, reap tx buffers, handle any received packets, | ||
726 | * check to make sure we've not become wedged. | ||
727 | */ | ||
728 | |||
729 | static unsigned short eexp_start_irq(struct net_device *dev, | ||
730 | unsigned short status) | ||
731 | { | ||
732 | unsigned short ack_cmd = SCB_ack(status); | ||
733 | struct net_local *lp = netdev_priv(dev); | ||
734 | unsigned short ioaddr = dev->base_addr; | ||
735 | if ((dev->flags & IFF_UP) && !(lp->started & STARTED_CU)) { | ||
736 | short diag_status, tdr_status; | ||
737 | while (SCB_CUstat(status)==2) | ||
738 | status = scb_status(dev); | ||
739 | #if NET_DEBUG > 4 | ||
740 | printk("%s: CU went non-active (status %04x)\n", | ||
741 | dev->name, status); | ||
742 | #endif | ||
743 | |||
744 | outw(CONF_DIAG_RESULT & ~31, ioaddr + SM_PTR); | ||
745 | diag_status = inw(ioaddr + SHADOW(CONF_DIAG_RESULT)); | ||
746 | if (diag_status & 1<<11) { | ||
747 | printk(KERN_WARNING "%s: 82586 failed self-test\n", | ||
748 | dev->name); | ||
749 | } else if (!(diag_status & 1<<13)) { | ||
750 | printk(KERN_WARNING "%s: 82586 self-test failed to complete\n", dev->name); | ||
751 | } | ||
752 | |||
753 | outw(CONF_TDR_RESULT & ~31, ioaddr + SM_PTR); | ||
754 | tdr_status = inw(ioaddr + SHADOW(CONF_TDR_RESULT)); | ||
755 | if (tdr_status & (TDR_SHORT|TDR_OPEN)) { | ||
756 | printk(KERN_WARNING "%s: TDR reports cable %s at %d tick%s\n", dev->name, (tdr_status & TDR_SHORT)?"short":"broken", tdr_status & TDR_TIME, ((tdr_status & TDR_TIME) != 1) ? "s" : ""); | ||
757 | } | ||
758 | else if (tdr_status & TDR_XCVRPROBLEM) { | ||
759 | printk(KERN_WARNING "%s: TDR reports transceiver problem\n", dev->name); | ||
760 | } | ||
761 | else if (tdr_status & TDR_LINKOK) { | ||
762 | #if NET_DEBUG > 4 | ||
763 | printk(KERN_DEBUG "%s: TDR reports link OK\n", dev->name); | ||
764 | #endif | ||
765 | } else { | ||
766 | printk("%s: TDR is ga-ga (status %04x)\n", dev->name, | ||
767 | tdr_status); | ||
768 | } | ||
769 | |||
770 | lp->started |= STARTED_CU; | ||
771 | scb_wrcbl(dev, lp->tx_link); | ||
772 | /* if the RU isn't running, start it now */ | ||
773 | if (!(lp->started & STARTED_RU)) { | ||
774 | ack_cmd |= SCB_RUstart; | ||
775 | scb_wrrfa(dev, lp->rx_buf_start); | ||
776 | lp->rx_ptr = lp->rx_buf_start; | ||
777 | lp->started |= STARTED_RU; | ||
778 | } | ||
779 | ack_cmd |= SCB_CUstart | 0x2000; | ||
780 | } | ||
781 | |||
782 | if ((dev->flags & IFF_UP) && !(lp->started & STARTED_RU) && SCB_RUstat(status)==4) | ||
783 | lp->started|=STARTED_RU; | ||
784 | |||
785 | return ack_cmd; | ||
786 | } | ||
787 | |||
788 | static void eexp_cmd_clear(struct net_device *dev) | ||
789 | { | ||
790 | unsigned long int oldtime = jiffies; | ||
791 | while (scb_rdcmd(dev) && ((jiffies-oldtime)<10)); | ||
792 | if (scb_rdcmd(dev)) { | ||
793 | printk("%s: command didn't clear\n", dev->name); | ||
794 | } | ||
795 | } | ||
796 | |||
797 | static irqreturn_t eexp_irq(int irq, void *dev_info, struct pt_regs *regs) | ||
798 | { | ||
799 | struct net_device *dev = dev_info; | ||
800 | struct net_local *lp; | ||
801 | unsigned short ioaddr,status,ack_cmd; | ||
802 | unsigned short old_read_ptr, old_write_ptr; | ||
803 | |||
804 | if (dev==NULL) | ||
805 | { | ||
806 | printk(KERN_WARNING "eexpress: irq %d for unknown device\n", | ||
807 | irq); | ||
808 | return IRQ_NONE; | ||
809 | } | ||
810 | |||
811 | lp = netdev_priv(dev); | ||
812 | ioaddr = dev->base_addr; | ||
813 | |||
814 | spin_lock(&lp->lock); | ||
815 | |||
816 | old_read_ptr = inw(ioaddr+READ_PTR); | ||
817 | old_write_ptr = inw(ioaddr+WRITE_PTR); | ||
818 | |||
819 | outb(SIRQ_dis|irqrmap[irq],ioaddr+SET_IRQ); | ||
820 | |||
821 | |||
822 | status = scb_status(dev); | ||
823 | |||
824 | #if NET_DEBUG > 4 | ||
825 | printk(KERN_DEBUG "%s: interrupt (status %x)\n", dev->name, status); | ||
826 | #endif | ||
827 | |||
828 | if (lp->started == (STARTED_CU | STARTED_RU)) { | ||
829 | |||
830 | do { | ||
831 | eexp_cmd_clear(dev); | ||
832 | |||
833 | ack_cmd = SCB_ack(status); | ||
834 | scb_command(dev, ack_cmd); | ||
835 | outb(0,ioaddr+SIGNAL_CA); | ||
836 | |||
837 | eexp_cmd_clear(dev); | ||
838 | |||
839 | if (SCB_complete(status)) { | ||
840 | if (!eexp_hw_lasttxstat(dev)) { | ||
841 | printk("%s: tx interrupt but no status\n", dev->name); | ||
842 | } | ||
843 | } | ||
844 | |||
845 | if (SCB_rxdframe(status)) | ||
846 | eexp_hw_rx_pio(dev); | ||
847 | |||
848 | status = scb_status(dev); | ||
849 | } while (status & 0xc000); | ||
850 | |||
851 | if (SCB_RUdead(status)) | ||
852 | { | ||
853 | printk(KERN_WARNING "%s: RU stopped: status %04x\n", | ||
854 | dev->name,status); | ||
855 | #if 0 | ||
856 | printk(KERN_WARNING "%s: cur_rfd=%04x, cur_rbd=%04x\n", dev->name, lp->cur_rfd, lp->cur_rbd); | ||
857 | outw(lp->cur_rfd, ioaddr+READ_PTR); | ||
858 | printk(KERN_WARNING "%s: [%04x]\n", dev->name, inw(ioaddr+DATAPORT)); | ||
859 | outw(lp->cur_rfd+6, ioaddr+READ_PTR); | ||
860 | printk(KERN_WARNING "%s: rbd is %04x\n", dev->name, rbd= inw(ioaddr+DATAPORT)); | ||
861 | outw(rbd, ioaddr+READ_PTR); | ||
862 | printk(KERN_WARNING "%s: [%04x %04x] ", dev->name, inw(ioaddr+DATAPORT), inw(ioaddr+DATAPORT)); | ||
863 | outw(rbd+8, ioaddr+READ_PTR); | ||
864 | printk("[%04x]\n", inw(ioaddr+DATAPORT)); | ||
865 | #endif | ||
866 | lp->stats.rx_errors++; | ||
867 | #if 1 | ||
868 | eexp_hw_rxinit(dev); | ||
869 | #else | ||
870 | lp->cur_rfd = lp->first_rfd; | ||
871 | #endif | ||
872 | scb_wrrfa(dev, lp->rx_buf_start); | ||
873 | scb_command(dev, SCB_RUstart); | ||
874 | outb(0,ioaddr+SIGNAL_CA); | ||
875 | } | ||
876 | } else { | ||
877 | if (status & 0x8000) | ||
878 | ack_cmd = eexp_start_irq(dev, status); | ||
879 | else | ||
880 | ack_cmd = SCB_ack(status); | ||
881 | scb_command(dev, ack_cmd); | ||
882 | outb(0,ioaddr+SIGNAL_CA); | ||
883 | } | ||
884 | |||
885 | eexp_cmd_clear(dev); | ||
886 | |||
887 | outb(SIRQ_en|irqrmap[irq],ioaddr+SET_IRQ); | ||
888 | |||
889 | #if NET_DEBUG > 6 | ||
890 | printk("%s: leaving eexp_irq()\n", dev->name); | ||
891 | #endif | ||
892 | outw(old_read_ptr, ioaddr+READ_PTR); | ||
893 | outw(old_write_ptr, ioaddr+WRITE_PTR); | ||
894 | |||
895 | spin_unlock(&lp->lock); | ||
896 | return IRQ_HANDLED; | ||
897 | } | ||
898 | |||
899 | /* | ||
900 | * Hardware access functions | ||
901 | */ | ||
902 | |||
903 | /* | ||
904 | * Set the cable type to use. | ||
905 | */ | ||
906 | |||
907 | static void eexp_hw_set_interface(struct net_device *dev) | ||
908 | { | ||
909 | unsigned char oldval = inb(dev->base_addr + 0x300e); | ||
910 | oldval &= ~0x82; | ||
911 | switch (dev->if_port) { | ||
912 | case TPE: | ||
913 | oldval |= 0x2; | ||
914 | case BNC: | ||
915 | oldval |= 0x80; | ||
916 | break; | ||
917 | } | ||
918 | outb(oldval, dev->base_addr+0x300e); | ||
919 | mdelay(20); | ||
920 | } | ||
921 | |||
922 | /* | ||
923 | * Check all the receive buffers, and hand any received packets | ||
924 | * to the upper levels. Basic sanity check on each frame | ||
925 | * descriptor, though we don't bother trying to fix broken ones. | ||
926 | */ | ||
927 | |||
928 | static void eexp_hw_rx_pio(struct net_device *dev) | ||
929 | { | ||
930 | struct net_local *lp = netdev_priv(dev); | ||
931 | unsigned short rx_block = lp->rx_ptr; | ||
932 | unsigned short boguscount = lp->num_rx_bufs; | ||
933 | unsigned short ioaddr = dev->base_addr; | ||
934 | unsigned short status; | ||
935 | |||
936 | #if NET_DEBUG > 6 | ||
937 | printk(KERN_DEBUG "%s: eexp_hw_rx()\n", dev->name); | ||
938 | #endif | ||
939 | |||
940 | do { | ||
941 | unsigned short rfd_cmd, rx_next, pbuf, pkt_len; | ||
942 | |||
943 | outw(rx_block, ioaddr + READ_PTR); | ||
944 | status = inw(ioaddr + DATAPORT); | ||
945 | |||
946 | if (FD_Done(status)) | ||
947 | { | ||
948 | rfd_cmd = inw(ioaddr + DATAPORT); | ||
949 | rx_next = inw(ioaddr + DATAPORT); | ||
950 | pbuf = inw(ioaddr + DATAPORT); | ||
951 | |||
952 | outw(pbuf, ioaddr + READ_PTR); | ||
953 | pkt_len = inw(ioaddr + DATAPORT); | ||
954 | |||
955 | if (rfd_cmd!=0x0000) | ||
956 | { | ||
957 | printk(KERN_WARNING "%s: rfd_cmd not zero:0x%04x\n", | ||
958 | dev->name, rfd_cmd); | ||
959 | continue; | ||
960 | } | ||
961 | else if (pbuf!=rx_block+0x16) | ||
962 | { | ||
963 | printk(KERN_WARNING "%s: rfd and rbd out of sync 0x%04x 0x%04x\n", | ||
964 | dev->name, rx_block+0x16, pbuf); | ||
965 | continue; | ||
966 | } | ||
967 | else if ((pkt_len & 0xc000)!=0xc000) | ||
968 | { | ||
969 | printk(KERN_WARNING "%s: EOF or F not set on received buffer (%04x)\n", | ||
970 | dev->name, pkt_len & 0xc000); | ||
971 | continue; | ||
972 | } | ||
973 | else if (!FD_OK(status)) | ||
974 | { | ||
975 | lp->stats.rx_errors++; | ||
976 | if (FD_CRC(status)) | ||
977 | lp->stats.rx_crc_errors++; | ||
978 | if (FD_Align(status)) | ||
979 | lp->stats.rx_frame_errors++; | ||
980 | if (FD_Resrc(status)) | ||
981 | lp->stats.rx_fifo_errors++; | ||
982 | if (FD_DMA(status)) | ||
983 | lp->stats.rx_over_errors++; | ||
984 | if (FD_Short(status)) | ||
985 | lp->stats.rx_length_errors++; | ||
986 | } | ||
987 | else | ||
988 | { | ||
989 | struct sk_buff *skb; | ||
990 | pkt_len &= 0x3fff; | ||
991 | skb = dev_alloc_skb(pkt_len+16); | ||
992 | if (skb == NULL) | ||
993 | { | ||
994 | printk(KERN_WARNING "%s: Memory squeeze, dropping packet\n",dev->name); | ||
995 | lp->stats.rx_dropped++; | ||
996 | break; | ||
997 | } | ||
998 | skb->dev = dev; | ||
999 | skb_reserve(skb, 2); | ||
1000 | outw(pbuf+10, ioaddr+READ_PTR); | ||
1001 | insw(ioaddr+DATAPORT, skb_put(skb,pkt_len),(pkt_len+1)>>1); | ||
1002 | skb->protocol = eth_type_trans(skb,dev); | ||
1003 | netif_rx(skb); | ||
1004 | dev->last_rx = jiffies; | ||
1005 | lp->stats.rx_packets++; | ||
1006 | lp->stats.rx_bytes += pkt_len; | ||
1007 | } | ||
1008 | outw(rx_block, ioaddr+WRITE_PTR); | ||
1009 | outw(0, ioaddr+DATAPORT); | ||
1010 | outw(0, ioaddr+DATAPORT); | ||
1011 | rx_block = rx_next; | ||
1012 | } | ||
1013 | } while (FD_Done(status) && boguscount--); | ||
1014 | lp->rx_ptr = rx_block; | ||
1015 | } | ||
1016 | |||
1017 | /* | ||
1018 | * Hand a packet to the card for transmission | ||
1019 | * If we get here, we MUST have already checked | ||
1020 | * to make sure there is room in the transmit | ||
1021 | * buffer region. | ||
1022 | */ | ||
1023 | |||
1024 | static void eexp_hw_tx_pio(struct net_device *dev, unsigned short *buf, | ||
1025 | unsigned short len) | ||
1026 | { | ||
1027 | struct net_local *lp = netdev_priv(dev); | ||
1028 | unsigned short ioaddr = dev->base_addr; | ||
1029 | |||
1030 | if (LOCKUP16 || lp->width) { | ||
1031 | /* Stop the CU so that there is no chance that it | ||
1032 | jumps off to a bogus address while we are writing the | ||
1033 | pointer to the next transmit packet in 8-bit mode -- | ||
1034 | this eliminates the "CU wedged" errors in 8-bit mode. | ||
1035 | (Zoltan Szilagyi 10-12-96) */ | ||
1036 | scb_command(dev, SCB_CUsuspend); | ||
1037 | outw(0xFFFF, ioaddr+SIGNAL_CA); | ||
1038 | } | ||
1039 | |||
1040 | outw(lp->tx_head, ioaddr + WRITE_PTR); | ||
1041 | |||
1042 | outw(0x0000, ioaddr + DATAPORT); | ||
1043 | outw(Cmd_INT|Cmd_Xmit, ioaddr + DATAPORT); | ||
1044 | outw(lp->tx_head+0x08, ioaddr + DATAPORT); | ||
1045 | outw(lp->tx_head+0x0e, ioaddr + DATAPORT); | ||
1046 | |||
1047 | outw(0x0000, ioaddr + DATAPORT); | ||
1048 | outw(0x0000, ioaddr + DATAPORT); | ||
1049 | outw(lp->tx_head+0x08, ioaddr + DATAPORT); | ||
1050 | |||
1051 | outw(0x8000|len, ioaddr + DATAPORT); | ||
1052 | outw(-1, ioaddr + DATAPORT); | ||
1053 | outw(lp->tx_head+0x16, ioaddr + DATAPORT); | ||
1054 | outw(0, ioaddr + DATAPORT); | ||
1055 | |||
1056 | outsw(ioaddr + DATAPORT, buf, (len+1)>>1); | ||
1057 | |||
1058 | outw(lp->tx_tail+0xc, ioaddr + WRITE_PTR); | ||
1059 | outw(lp->tx_head, ioaddr + DATAPORT); | ||
1060 | |||
1061 | dev->trans_start = jiffies; | ||
1062 | lp->tx_tail = lp->tx_head; | ||
1063 | if (lp->tx_head==TX_BUF_START+((lp->num_tx_bufs-1)*TX_BUF_SIZE)) | ||
1064 | lp->tx_head = TX_BUF_START; | ||
1065 | else | ||
1066 | lp->tx_head += TX_BUF_SIZE; | ||
1067 | if (lp->tx_head != lp->tx_reap) | ||
1068 | netif_wake_queue(dev); | ||
1069 | |||
1070 | if (LOCKUP16 || lp->width) { | ||
1071 | /* Restart the CU so that the packet can actually | ||
1072 | be transmitted. (Zoltan Szilagyi 10-12-96) */ | ||
1073 | scb_command(dev, SCB_CUresume); | ||
1074 | outw(0xFFFF, ioaddr+SIGNAL_CA); | ||
1075 | } | ||
1076 | |||
1077 | lp->stats.tx_packets++; | ||
1078 | lp->last_tx = jiffies; | ||
1079 | } | ||
1080 | |||
1081 | /* | ||
1082 | * Sanity check the suspected EtherExpress card | ||
1083 | * Read hardware address, reset card, size memory and initialize buffer | ||
1084 | * memory pointers. These are held in dev->priv, in case someone has more | ||
1085 | * than one card in a machine. | ||
1086 | */ | ||
1087 | |||
1088 | static int __init eexp_hw_probe(struct net_device *dev, unsigned short ioaddr) | ||
1089 | { | ||
1090 | unsigned short hw_addr[3]; | ||
1091 | unsigned char buswidth; | ||
1092 | unsigned int memory_size; | ||
1093 | int i; | ||
1094 | unsigned short xsum = 0; | ||
1095 | struct net_local *lp = netdev_priv(dev); | ||
1096 | |||
1097 | printk("%s: EtherExpress 16 at %#x ",dev->name,ioaddr); | ||
1098 | |||
1099 | outb(ASIC_RST, ioaddr+EEPROM_Ctrl); | ||
1100 | outb(0, ioaddr+EEPROM_Ctrl); | ||
1101 | udelay(500); | ||
1102 | outb(i586_RST, ioaddr+EEPROM_Ctrl); | ||
1103 | |||
1104 | hw_addr[0] = eexp_hw_readeeprom(ioaddr,2); | ||
1105 | hw_addr[1] = eexp_hw_readeeprom(ioaddr,3); | ||
1106 | hw_addr[2] = eexp_hw_readeeprom(ioaddr,4); | ||
1107 | |||
1108 | /* Standard Address or Compaq LTE Address */ | ||
1109 | if (!((hw_addr[2]==0x00aa && ((hw_addr[1] & 0xff00)==0x0000)) || | ||
1110 | (hw_addr[2]==0x0080 && ((hw_addr[1] & 0xff00)==0x5F00)))) | ||
1111 | { | ||
1112 | printk(" rejected: invalid address %04x%04x%04x\n", | ||
1113 | hw_addr[2],hw_addr[1],hw_addr[0]); | ||
1114 | return -ENODEV; | ||
1115 | } | ||
1116 | |||
1117 | /* Calculate the EEPROM checksum. Carry on anyway if it's bad, | ||
1118 | * though. | ||
1119 | */ | ||
1120 | for (i = 0; i < 64; i++) | ||
1121 | xsum += eexp_hw_readeeprom(ioaddr, i); | ||
1122 | if (xsum != 0xbaba) | ||
1123 | printk(" (bad EEPROM xsum 0x%02x)", xsum); | ||
1124 | |||
1125 | dev->base_addr = ioaddr; | ||
1126 | for ( i=0 ; i<6 ; i++ ) | ||
1127 | dev->dev_addr[i] = ((unsigned char *)hw_addr)[5-i]; | ||
1128 | |||
1129 | { | ||
1130 | static char irqmap[]={0, 9, 3, 4, 5, 10, 11, 0}; | ||
1131 | unsigned short setupval = eexp_hw_readeeprom(ioaddr,0); | ||
1132 | |||
1133 | /* Use the IRQ from EEPROM if none was given */ | ||
1134 | if (!dev->irq) | ||
1135 | dev->irq = irqmap[setupval>>13]; | ||
1136 | |||
1137 | if (dev->if_port == 0xff) { | ||
1138 | dev->if_port = !(setupval & 0x1000) ? AUI : | ||
1139 | eexp_hw_readeeprom(ioaddr,5) & 0x1 ? TPE : BNC; | ||
1140 | } | ||
1141 | |||
1142 | buswidth = !((setupval & 0x400) >> 10); | ||
1143 | } | ||
1144 | |||
1145 | memset(lp, 0, sizeof(struct net_local)); | ||
1146 | spin_lock_init(&lp->lock); | ||
1147 | |||
1148 | printk("(IRQ %d, %s connector, %d-bit bus", dev->irq, | ||
1149 | eexp_ifmap[dev->if_port], buswidth?8:16); | ||
1150 | |||
1151 | if (!request_region(dev->base_addr + 0x300e, 1, "EtherExpress")) | ||
1152 | return -EBUSY; | ||
1153 | |||
1154 | eexp_hw_set_interface(dev); | ||
1155 | |||
1156 | release_region(dev->base_addr + 0x300e, 1); | ||
1157 | |||
1158 | /* Find out how much RAM we have on the card */ | ||
1159 | outw(0, dev->base_addr + WRITE_PTR); | ||
1160 | for (i = 0; i < 32768; i++) | ||
1161 | outw(0, dev->base_addr + DATAPORT); | ||
1162 | |||
1163 | for (memory_size = 0; memory_size < 64; memory_size++) | ||
1164 | { | ||
1165 | outw(memory_size<<10, dev->base_addr + READ_PTR); | ||
1166 | if (inw(dev->base_addr+DATAPORT)) | ||
1167 | break; | ||
1168 | outw(memory_size<<10, dev->base_addr + WRITE_PTR); | ||
1169 | outw(memory_size | 0x5000, dev->base_addr+DATAPORT); | ||
1170 | outw(memory_size<<10, dev->base_addr + READ_PTR); | ||
1171 | if (inw(dev->base_addr+DATAPORT) != (memory_size | 0x5000)) | ||
1172 | break; | ||
1173 | } | ||
1174 | |||
1175 | /* Sort out the number of buffers. We may have 16, 32, 48 or 64k | ||
1176 | * of RAM to play with. | ||
1177 | */ | ||
1178 | lp->num_tx_bufs = 4; | ||
1179 | lp->rx_buf_end = 0x3ff6; | ||
1180 | switch (memory_size) | ||
1181 | { | ||
1182 | case 64: | ||
1183 | lp->rx_buf_end += 0x4000; | ||
1184 | case 48: | ||
1185 | lp->num_tx_bufs += 4; | ||
1186 | lp->rx_buf_end += 0x4000; | ||
1187 | case 32: | ||
1188 | lp->rx_buf_end += 0x4000; | ||
1189 | case 16: | ||
1190 | printk(", %dk RAM)\n", memory_size); | ||
1191 | break; | ||
1192 | default: | ||
1193 | printk(") bad memory size (%dk).\n", memory_size); | ||
1194 | return -ENODEV; | ||
1195 | break; | ||
1196 | } | ||
1197 | |||
1198 | lp->rx_buf_start = TX_BUF_START + (lp->num_tx_bufs*TX_BUF_SIZE); | ||
1199 | lp->width = buswidth; | ||
1200 | |||
1201 | dev->open = eexp_open; | ||
1202 | dev->stop = eexp_close; | ||
1203 | dev->hard_start_xmit = eexp_xmit; | ||
1204 | dev->get_stats = eexp_stats; | ||
1205 | dev->set_multicast_list = &eexp_set_multicast; | ||
1206 | dev->tx_timeout = eexp_timeout; | ||
1207 | dev->watchdog_timeo = 2*HZ; | ||
1208 | return 0; | ||
1209 | } | ||
1210 | |||
1211 | /* | ||
1212 | * Read a word from the EtherExpress on-board serial EEPROM. | ||
1213 | * The EEPROM contains 64 words of 16 bits. | ||
1214 | */ | ||
1215 | static unsigned short __init eexp_hw_readeeprom(unsigned short ioaddr, | ||
1216 | unsigned char location) | ||
1217 | { | ||
1218 | unsigned short cmd = 0x180|(location&0x7f); | ||
1219 | unsigned short rval = 0,wval = EC_CS|i586_RST; | ||
1220 | int i; | ||
1221 | |||
1222 | outb(EC_CS|i586_RST,ioaddr+EEPROM_Ctrl); | ||
1223 | for (i=0x100 ; i ; i>>=1 ) | ||
1224 | { | ||
1225 | if (cmd&i) | ||
1226 | wval |= EC_Wr; | ||
1227 | else | ||
1228 | wval &= ~EC_Wr; | ||
1229 | |||
1230 | outb(wval,ioaddr+EEPROM_Ctrl); | ||
1231 | outb(wval|EC_Clk,ioaddr+EEPROM_Ctrl); | ||
1232 | eeprom_delay(); | ||
1233 | outb(wval,ioaddr+EEPROM_Ctrl); | ||
1234 | eeprom_delay(); | ||
1235 | } | ||
1236 | wval &= ~EC_Wr; | ||
1237 | outb(wval,ioaddr+EEPROM_Ctrl); | ||
1238 | for (i=0x8000 ; i ; i>>=1 ) | ||
1239 | { | ||
1240 | outb(wval|EC_Clk,ioaddr+EEPROM_Ctrl); | ||
1241 | eeprom_delay(); | ||
1242 | if (inb(ioaddr+EEPROM_Ctrl)&EC_Rd) | ||
1243 | rval |= i; | ||
1244 | outb(wval,ioaddr+EEPROM_Ctrl); | ||
1245 | eeprom_delay(); | ||
1246 | } | ||
1247 | wval &= ~EC_CS; | ||
1248 | outb(wval|EC_Clk,ioaddr+EEPROM_Ctrl); | ||
1249 | eeprom_delay(); | ||
1250 | outb(wval,ioaddr+EEPROM_Ctrl); | ||
1251 | eeprom_delay(); | ||
1252 | return rval; | ||
1253 | } | ||
1254 | |||
1255 | /* | ||
1256 | * Reap tx buffers and return last transmit status. | ||
1257 | * if ==0 then either: | ||
1258 | * a) we're not transmitting anything, so why are we here? | ||
1259 | * b) we've died. | ||
1260 | * otherwise, Stat_Busy(return) means we've still got some packets | ||
1261 | * to transmit, Stat_Done(return) means our buffers should be empty | ||
1262 | * again | ||
1263 | */ | ||
1264 | |||
1265 | static unsigned short eexp_hw_lasttxstat(struct net_device *dev) | ||
1266 | { | ||
1267 | struct net_local *lp = netdev_priv(dev); | ||
1268 | unsigned short tx_block = lp->tx_reap; | ||
1269 | unsigned short status; | ||
1270 | |||
1271 | if (!netif_queue_stopped(dev) && lp->tx_head==lp->tx_reap) | ||
1272 | return 0x0000; | ||
1273 | |||
1274 | do | ||
1275 | { | ||
1276 | outw(tx_block & ~31, dev->base_addr + SM_PTR); | ||
1277 | status = inw(dev->base_addr + SHADOW(tx_block)); | ||
1278 | if (!Stat_Done(status)) | ||
1279 | { | ||
1280 | lp->tx_link = tx_block; | ||
1281 | return status; | ||
1282 | } | ||
1283 | else | ||
1284 | { | ||
1285 | lp->last_tx_restart = 0; | ||
1286 | lp->stats.collisions += Stat_NoColl(status); | ||
1287 | if (!Stat_OK(status)) | ||
1288 | { | ||
1289 | char *whatsup = NULL; | ||
1290 | lp->stats.tx_errors++; | ||
1291 | if (Stat_Abort(status)) | ||
1292 | lp->stats.tx_aborted_errors++; | ||
1293 | if (Stat_TNoCar(status)) { | ||
1294 | whatsup = "aborted, no carrier"; | ||
1295 | lp->stats.tx_carrier_errors++; | ||
1296 | } | ||
1297 | if (Stat_TNoCTS(status)) { | ||
1298 | whatsup = "aborted, lost CTS"; | ||
1299 | lp->stats.tx_carrier_errors++; | ||
1300 | } | ||
1301 | if (Stat_TNoDMA(status)) { | ||
1302 | whatsup = "FIFO underran"; | ||
1303 | lp->stats.tx_fifo_errors++; | ||
1304 | } | ||
1305 | if (Stat_TXColl(status)) { | ||
1306 | whatsup = "aborted, too many collisions"; | ||
1307 | lp->stats.tx_aborted_errors++; | ||
1308 | } | ||
1309 | if (whatsup) | ||
1310 | printk(KERN_INFO "%s: transmit %s\n", | ||
1311 | dev->name, whatsup); | ||
1312 | } | ||
1313 | else | ||
1314 | lp->stats.tx_packets++; | ||
1315 | } | ||
1316 | if (tx_block == TX_BUF_START+((lp->num_tx_bufs-1)*TX_BUF_SIZE)) | ||
1317 | lp->tx_reap = tx_block = TX_BUF_START; | ||
1318 | else | ||
1319 | lp->tx_reap = tx_block += TX_BUF_SIZE; | ||
1320 | netif_wake_queue(dev); | ||
1321 | } | ||
1322 | while (lp->tx_reap != lp->tx_head); | ||
1323 | |||
1324 | lp->tx_link = lp->tx_tail + 0x08; | ||
1325 | |||
1326 | return status; | ||
1327 | } | ||
1328 | |||
1329 | /* | ||
1330 | * This should never happen. It is called when some higher routine detects | ||
1331 | * that the CU has stopped, to try to restart it from the last packet we knew | ||
1332 | * we were working on, or the idle loop if we had finished for the time. | ||
1333 | */ | ||
1334 | |||
1335 | static void eexp_hw_txrestart(struct net_device *dev) | ||
1336 | { | ||
1337 | struct net_local *lp = netdev_priv(dev); | ||
1338 | unsigned short ioaddr = dev->base_addr; | ||
1339 | |||
1340 | lp->last_tx_restart = lp->tx_link; | ||
1341 | scb_wrcbl(dev, lp->tx_link); | ||
1342 | scb_command(dev, SCB_CUstart); | ||
1343 | outb(0,ioaddr+SIGNAL_CA); | ||
1344 | |||
1345 | { | ||
1346 | unsigned short boguscount=50,failcount=5; | ||
1347 | while (!scb_status(dev)) | ||
1348 | { | ||
1349 | if (!--boguscount) | ||
1350 | { | ||
1351 | if (--failcount) | ||
1352 | { | ||
1353 | printk(KERN_WARNING "%s: CU start timed out, status %04x, cmd %04x\n", dev->name, scb_status(dev), scb_rdcmd(dev)); | ||
1354 | scb_wrcbl(dev, lp->tx_link); | ||
1355 | scb_command(dev, SCB_CUstart); | ||
1356 | outb(0,ioaddr+SIGNAL_CA); | ||
1357 | boguscount = 100; | ||
1358 | } | ||
1359 | else | ||
1360 | { | ||
1361 | printk(KERN_WARNING "%s: Failed to restart CU, resetting board...\n",dev->name); | ||
1362 | eexp_hw_init586(dev); | ||
1363 | netif_wake_queue(dev); | ||
1364 | return; | ||
1365 | } | ||
1366 | } | ||
1367 | } | ||
1368 | } | ||
1369 | } | ||
1370 | |||
1371 | /* | ||
1372 | * Writes down the list of transmit buffers into card memory. Each | ||
1373 | * entry consists of an 82586 transmit command, followed by a jump | ||
1374 | * pointing to itself. When we want to transmit a packet, we write | ||
1375 | * the data into the appropriate transmit buffer and then modify the | ||
1376 | * preceding jump to point at the new transmit command. This means that | ||
1377 | * the 586 command unit is continuously active. | ||
1378 | */ | ||
1379 | |||
1380 | static void eexp_hw_txinit(struct net_device *dev) | ||
1381 | { | ||
1382 | struct net_local *lp = netdev_priv(dev); | ||
1383 | unsigned short tx_block = TX_BUF_START; | ||
1384 | unsigned short curtbuf; | ||
1385 | unsigned short ioaddr = dev->base_addr; | ||
1386 | |||
1387 | for ( curtbuf=0 ; curtbuf<lp->num_tx_bufs ; curtbuf++ ) | ||
1388 | { | ||
1389 | outw(tx_block, ioaddr + WRITE_PTR); | ||
1390 | |||
1391 | outw(0x0000, ioaddr + DATAPORT); | ||
1392 | outw(Cmd_INT|Cmd_Xmit, ioaddr + DATAPORT); | ||
1393 | outw(tx_block+0x08, ioaddr + DATAPORT); | ||
1394 | outw(tx_block+0x0e, ioaddr + DATAPORT); | ||
1395 | |||
1396 | outw(0x0000, ioaddr + DATAPORT); | ||
1397 | outw(0x0000, ioaddr + DATAPORT); | ||
1398 | outw(tx_block+0x08, ioaddr + DATAPORT); | ||
1399 | |||
1400 | outw(0x8000, ioaddr + DATAPORT); | ||
1401 | outw(-1, ioaddr + DATAPORT); | ||
1402 | outw(tx_block+0x16, ioaddr + DATAPORT); | ||
1403 | outw(0x0000, ioaddr + DATAPORT); | ||
1404 | |||
1405 | tx_block += TX_BUF_SIZE; | ||
1406 | } | ||
1407 | lp->tx_head = TX_BUF_START; | ||
1408 | lp->tx_reap = TX_BUF_START; | ||
1409 | lp->tx_tail = tx_block - TX_BUF_SIZE; | ||
1410 | lp->tx_link = lp->tx_tail + 0x08; | ||
1411 | lp->rx_buf_start = tx_block; | ||
1412 | |||
1413 | } | ||
1414 | |||
1415 | /* | ||
1416 | * Write the circular list of receive buffer descriptors to card memory. | ||
1417 | * The end of the list isn't marked, which means that the 82586 receive | ||
1418 | * unit will loop until buffers become available (this avoids it giving us | ||
1419 | * "out of resources" messages). | ||
1420 | */ | ||
1421 | |||
1422 | static void eexp_hw_rxinit(struct net_device *dev) | ||
1423 | { | ||
1424 | struct net_local *lp = netdev_priv(dev); | ||
1425 | unsigned short rx_block = lp->rx_buf_start; | ||
1426 | unsigned short ioaddr = dev->base_addr; | ||
1427 | |||
1428 | lp->num_rx_bufs = 0; | ||
1429 | lp->rx_first = lp->rx_ptr = rx_block; | ||
1430 | do | ||
1431 | { | ||
1432 | lp->num_rx_bufs++; | ||
1433 | |||
1434 | outw(rx_block, ioaddr + WRITE_PTR); | ||
1435 | |||
1436 | outw(0, ioaddr + DATAPORT); outw(0, ioaddr+DATAPORT); | ||
1437 | outw(rx_block + RX_BUF_SIZE, ioaddr+DATAPORT); | ||
1438 | outw(0xffff, ioaddr+DATAPORT); | ||
1439 | |||
1440 | outw(0x0000, ioaddr+DATAPORT); | ||
1441 | outw(0xdead, ioaddr+DATAPORT); | ||
1442 | outw(0xdead, ioaddr+DATAPORT); | ||
1443 | outw(0xdead, ioaddr+DATAPORT); | ||
1444 | outw(0xdead, ioaddr+DATAPORT); | ||
1445 | outw(0xdead, ioaddr+DATAPORT); | ||
1446 | outw(0xdead, ioaddr+DATAPORT); | ||
1447 | |||
1448 | outw(0x0000, ioaddr+DATAPORT); | ||
1449 | outw(rx_block + RX_BUF_SIZE + 0x16, ioaddr+DATAPORT); | ||
1450 | outw(rx_block + 0x20, ioaddr+DATAPORT); | ||
1451 | outw(0, ioaddr+DATAPORT); | ||
1452 | outw(RX_BUF_SIZE-0x20, ioaddr+DATAPORT); | ||
1453 | |||
1454 | lp->rx_last = rx_block; | ||
1455 | rx_block += RX_BUF_SIZE; | ||
1456 | } while (rx_block <= lp->rx_buf_end-RX_BUF_SIZE); | ||
1457 | |||
1458 | |||
1459 | /* Make first Rx frame descriptor point to first Rx buffer | ||
1460 | descriptor */ | ||
1461 | outw(lp->rx_first + 6, ioaddr+WRITE_PTR); | ||
1462 | outw(lp->rx_first + 0x16, ioaddr+DATAPORT); | ||
1463 | |||
1464 | /* Close Rx frame descriptor ring */ | ||
1465 | outw(lp->rx_last + 4, ioaddr+WRITE_PTR); | ||
1466 | outw(lp->rx_first, ioaddr+DATAPORT); | ||
1467 | |||
1468 | /* Close Rx buffer descriptor ring */ | ||
1469 | outw(lp->rx_last + 0x16 + 2, ioaddr+WRITE_PTR); | ||
1470 | outw(lp->rx_first + 0x16, ioaddr+DATAPORT); | ||
1471 | |||
1472 | } | ||
1473 | |||
1474 | /* | ||
1475 | * Un-reset the 586, and start the configuration sequence. We don't wait for | ||
1476 | * this to finish, but allow the interrupt handler to start the CU and RU for | ||
1477 | * us. We can't start the receive/transmission system up before we know that | ||
1478 | * the hardware is configured correctly. | ||
1479 | */ | ||
1480 | |||
1481 | static void eexp_hw_init586(struct net_device *dev) | ||
1482 | { | ||
1483 | struct net_local *lp = netdev_priv(dev); | ||
1484 | unsigned short ioaddr = dev->base_addr; | ||
1485 | int i; | ||
1486 | |||
1487 | #if NET_DEBUG > 6 | ||
1488 | printk("%s: eexp_hw_init586()\n", dev->name); | ||
1489 | #endif | ||
1490 | |||
1491 | lp->started = 0; | ||
1492 | |||
1493 | set_loopback(dev); | ||
1494 | |||
1495 | outb(SIRQ_dis|irqrmap[dev->irq],ioaddr+SET_IRQ); | ||
1496 | |||
1497 | /* Download the startup code */ | ||
1498 | outw(lp->rx_buf_end & ~31, ioaddr + SM_PTR); | ||
1499 | outw(lp->width?0x0001:0x0000, ioaddr + 0x8006); | ||
1500 | outw(0x0000, ioaddr + 0x8008); | ||
1501 | outw(0x0000, ioaddr + 0x800a); | ||
1502 | outw(0x0000, ioaddr + 0x800c); | ||
1503 | outw(0x0000, ioaddr + 0x800e); | ||
1504 | |||
1505 | for (i = 0; i < (sizeof(start_code)); i+=32) { | ||
1506 | int j; | ||
1507 | outw(i, ioaddr + SM_PTR); | ||
1508 | for (j = 0; j < 16; j+=2) | ||
1509 | outw(start_code[(i+j)/2], | ||
1510 | ioaddr+0x4000+j); | ||
1511 | for (j = 0; j < 16; j+=2) | ||
1512 | outw(start_code[(i+j+16)/2], | ||
1513 | ioaddr+0x8000+j); | ||
1514 | } | ||
1515 | |||
1516 | /* Do we want promiscuous mode or multicast? */ | ||
1517 | outw(CONF_PROMISC & ~31, ioaddr+SM_PTR); | ||
1518 | i = inw(ioaddr+SHADOW(CONF_PROMISC)); | ||
1519 | outw((dev->flags & IFF_PROMISC)?(i|1):(i & ~1), | ||
1520 | ioaddr+SHADOW(CONF_PROMISC)); | ||
1521 | lp->was_promisc = dev->flags & IFF_PROMISC; | ||
1522 | #if 0 | ||
1523 | eexp_setup_filter(dev); | ||
1524 | #endif | ||
1525 | |||
1526 | /* Write our hardware address */ | ||
1527 | outw(CONF_HWADDR & ~31, ioaddr+SM_PTR); | ||
1528 | outw(((unsigned short *)dev->dev_addr)[0], ioaddr+SHADOW(CONF_HWADDR)); | ||
1529 | outw(((unsigned short *)dev->dev_addr)[1], | ||
1530 | ioaddr+SHADOW(CONF_HWADDR+2)); | ||
1531 | outw(((unsigned short *)dev->dev_addr)[2], | ||
1532 | ioaddr+SHADOW(CONF_HWADDR+4)); | ||
1533 | |||
1534 | eexp_hw_txinit(dev); | ||
1535 | eexp_hw_rxinit(dev); | ||
1536 | |||
1537 | outb(0,ioaddr+EEPROM_Ctrl); | ||
1538 | mdelay(5); | ||
1539 | |||
1540 | scb_command(dev, 0xf000); | ||
1541 | outb(0,ioaddr+SIGNAL_CA); | ||
1542 | |||
1543 | outw(0, ioaddr+SM_PTR); | ||
1544 | |||
1545 | { | ||
1546 | unsigned short rboguscount=50,rfailcount=5; | ||
1547 | while (inw(ioaddr+0x4000)) | ||
1548 | { | ||
1549 | if (!--rboguscount) | ||
1550 | { | ||
1551 | printk(KERN_WARNING "%s: i82586 reset timed out, kicking...\n", | ||
1552 | dev->name); | ||
1553 | scb_command(dev, 0); | ||
1554 | outb(0,ioaddr+SIGNAL_CA); | ||
1555 | rboguscount = 100; | ||
1556 | if (!--rfailcount) | ||
1557 | { | ||
1558 | printk(KERN_WARNING "%s: i82586 not responding, giving up.\n", | ||
1559 | dev->name); | ||
1560 | return; | ||
1561 | } | ||
1562 | } | ||
1563 | } | ||
1564 | } | ||
1565 | |||
1566 | scb_wrcbl(dev, CONF_LINK); | ||
1567 | scb_command(dev, 0xf000|SCB_CUstart); | ||
1568 | outb(0,ioaddr+SIGNAL_CA); | ||
1569 | |||
1570 | { | ||
1571 | unsigned short iboguscount=50,ifailcount=5; | ||
1572 | while (!scb_status(dev)) | ||
1573 | { | ||
1574 | if (!--iboguscount) | ||
1575 | { | ||
1576 | if (--ifailcount) | ||
1577 | { | ||
1578 | printk(KERN_WARNING "%s: i82586 initialization timed out, status %04x, cmd %04x\n", | ||
1579 | dev->name, scb_status(dev), scb_rdcmd(dev)); | ||
1580 | scb_wrcbl(dev, CONF_LINK); | ||
1581 | scb_command(dev, 0xf000|SCB_CUstart); | ||
1582 | outb(0,ioaddr+SIGNAL_CA); | ||
1583 | iboguscount = 100; | ||
1584 | } | ||
1585 | else | ||
1586 | { | ||
1587 | printk(KERN_WARNING "%s: Failed to initialize i82586, giving up.\n",dev->name); | ||
1588 | return; | ||
1589 | } | ||
1590 | } | ||
1591 | } | ||
1592 | } | ||
1593 | |||
1594 | clear_loopback(dev); | ||
1595 | outb(SIRQ_en|irqrmap[dev->irq],ioaddr+SET_IRQ); | ||
1596 | |||
1597 | lp->init_time = jiffies; | ||
1598 | #if NET_DEBUG > 6 | ||
1599 | printk("%s: leaving eexp_hw_init586()\n", dev->name); | ||
1600 | #endif | ||
1601 | return; | ||
1602 | } | ||
1603 | |||
1604 | static void eexp_setup_filter(struct net_device *dev) | ||
1605 | { | ||
1606 | struct dev_mc_list *dmi = dev->mc_list; | ||
1607 | unsigned short ioaddr = dev->base_addr; | ||
1608 | int count = dev->mc_count; | ||
1609 | int i; | ||
1610 | if (count > 8) { | ||
1611 | printk(KERN_INFO "%s: too many multicast addresses (%d)\n", | ||
1612 | dev->name, count); | ||
1613 | count = 8; | ||
1614 | } | ||
1615 | |||
1616 | outw(CONF_NR_MULTICAST & ~31, ioaddr+SM_PTR); | ||
1617 | outw(count, ioaddr+SHADOW(CONF_NR_MULTICAST)); | ||
1618 | for (i = 0; i < count; i++) { | ||
1619 | unsigned short *data = (unsigned short *)dmi->dmi_addr; | ||
1620 | if (!dmi) { | ||
1621 | printk(KERN_INFO "%s: too few multicast addresses\n", dev->name); | ||
1622 | break; | ||
1623 | } | ||
1624 | if (dmi->dmi_addrlen != ETH_ALEN) { | ||
1625 | printk(KERN_INFO "%s: invalid multicast address length given.\n", dev->name); | ||
1626 | continue; | ||
1627 | } | ||
1628 | outw((CONF_MULTICAST+(6*i)) & ~31, ioaddr+SM_PTR); | ||
1629 | outw(data[0], ioaddr+SHADOW(CONF_MULTICAST+(6*i))); | ||
1630 | outw((CONF_MULTICAST+(6*i)+2) & ~31, ioaddr+SM_PTR); | ||
1631 | outw(data[1], ioaddr+SHADOW(CONF_MULTICAST+(6*i)+2)); | ||
1632 | outw((CONF_MULTICAST+(6*i)+4) & ~31, ioaddr+SM_PTR); | ||
1633 | outw(data[2], ioaddr+SHADOW(CONF_MULTICAST+(6*i)+4)); | ||
1634 | } | ||
1635 | } | ||
1636 | |||
1637 | /* | ||
1638 | * Set or clear the multicast filter for this adaptor. | ||
1639 | */ | ||
1640 | static void | ||
1641 | eexp_set_multicast(struct net_device *dev) | ||
1642 | { | ||
1643 | unsigned short ioaddr = dev->base_addr; | ||
1644 | struct net_local *lp = netdev_priv(dev); | ||
1645 | int kick = 0, i; | ||
1646 | if ((dev->flags & IFF_PROMISC) != lp->was_promisc) { | ||
1647 | outw(CONF_PROMISC & ~31, ioaddr+SM_PTR); | ||
1648 | i = inw(ioaddr+SHADOW(CONF_PROMISC)); | ||
1649 | outw((dev->flags & IFF_PROMISC)?(i|1):(i & ~1), | ||
1650 | ioaddr+SHADOW(CONF_PROMISC)); | ||
1651 | lp->was_promisc = dev->flags & IFF_PROMISC; | ||
1652 | kick = 1; | ||
1653 | } | ||
1654 | if (!(dev->flags & IFF_PROMISC)) { | ||
1655 | eexp_setup_filter(dev); | ||
1656 | if (lp->old_mc_count != dev->mc_count) { | ||
1657 | kick = 1; | ||
1658 | lp->old_mc_count = dev->mc_count; | ||
1659 | } | ||
1660 | } | ||
1661 | if (kick) { | ||
1662 | unsigned long oj; | ||
1663 | scb_command(dev, SCB_CUsuspend); | ||
1664 | outb(0, ioaddr+SIGNAL_CA); | ||
1665 | outb(0, ioaddr+SIGNAL_CA); | ||
1666 | #if 0 | ||
1667 | printk("%s: waiting for CU to go suspended\n", dev->name); | ||
1668 | #endif | ||
1669 | oj = jiffies; | ||
1670 | while ((SCB_CUstat(scb_status(dev)) == 2) && | ||
1671 | ((jiffies-oj) < 2000)); | ||
1672 | if (SCB_CUstat(scb_status(dev)) == 2) | ||
1673 | printk("%s: warning, CU didn't stop\n", dev->name); | ||
1674 | lp->started &= ~(STARTED_CU); | ||
1675 | scb_wrcbl(dev, CONF_LINK); | ||
1676 | scb_command(dev, SCB_CUstart); | ||
1677 | outb(0, ioaddr+SIGNAL_CA); | ||
1678 | } | ||
1679 | } | ||
1680 | |||
1681 | |||
1682 | /* | ||
1683 | * MODULE stuff | ||
1684 | */ | ||
1685 | |||
1686 | #ifdef MODULE | ||
1687 | |||
1688 | #define EEXP_MAX_CARDS 4 /* max number of cards to support */ | ||
1689 | |||
1690 | static struct net_device *dev_eexp[EEXP_MAX_CARDS]; | ||
1691 | static int irq[EEXP_MAX_CARDS]; | ||
1692 | static int io[EEXP_MAX_CARDS]; | ||
1693 | |||
1694 | module_param_array(io, int, NULL, 0); | ||
1695 | module_param_array(irq, int, NULL, 0); | ||
1696 | MODULE_PARM_DESC(io, "EtherExpress 16 I/O base address(es)"); | ||
1697 | MODULE_PARM_DESC(irq, "EtherExpress 16 IRQ number(s)"); | ||
1698 | MODULE_LICENSE("GPL"); | ||
1699 | |||
1700 | |||
1701 | /* Ideally the user would give us io=, irq= for every card. If any parameters | ||
1702 | * are specified, we verify and then use them. If no parameters are given, we | ||
1703 | * autoprobe for one card only. | ||
1704 | */ | ||
1705 | int init_module(void) | ||
1706 | { | ||
1707 | struct net_device *dev; | ||
1708 | int this_dev, found = 0; | ||
1709 | |||
1710 | for (this_dev = 0; this_dev < EEXP_MAX_CARDS; this_dev++) { | ||
1711 | dev = alloc_etherdev(sizeof(struct net_local)); | ||
1712 | dev->irq = irq[this_dev]; | ||
1713 | dev->base_addr = io[this_dev]; | ||
1714 | if (io[this_dev] == 0) { | ||
1715 | if (this_dev) | ||
1716 | break; | ||
1717 | printk(KERN_NOTICE "eexpress.c: Module autoprobe not recommended, give io=xx.\n"); | ||
1718 | } | ||
1719 | if (do_express_probe(dev) == 0 && register_netdev(dev) == 0) { | ||
1720 | dev_eexp[this_dev] = dev; | ||
1721 | found++; | ||
1722 | continue; | ||
1723 | } | ||
1724 | printk(KERN_WARNING "eexpress.c: Failed to register card at 0x%x.\n", io[this_dev]); | ||
1725 | free_netdev(dev); | ||
1726 | break; | ||
1727 | } | ||
1728 | if (found) | ||
1729 | return 0; | ||
1730 | return -ENXIO; | ||
1731 | } | ||
1732 | |||
1733 | void cleanup_module(void) | ||
1734 | { | ||
1735 | int this_dev; | ||
1736 | |||
1737 | for (this_dev = 0; this_dev < EEXP_MAX_CARDS; this_dev++) { | ||
1738 | struct net_device *dev = dev_eexp[this_dev]; | ||
1739 | if (dev) { | ||
1740 | unregister_netdev(dev); | ||
1741 | free_netdev(dev); | ||
1742 | } | ||
1743 | } | ||
1744 | } | ||
1745 | #endif | ||
1746 | |||
1747 | /* | ||
1748 | * Local Variables: | ||
1749 | * c-file-style: "linux" | ||
1750 | * tab-width: 8 | ||
1751 | * End: | ||
1752 | */ | ||