File: | obj-scan-build/../linux/src/drivers/net/eexpress.c |
Location: | line 721, column 3 |
Description: | Assigned value is garbage or undefined |
1 | /* $Id: eexpress.c,v 1.1 1999/04/26 05:52:09 tb Exp $ | |||
2 | * | |||
3 | * Intel EtherExpress device driver for Linux | |||
4 | * | |||
5 | * Original version written 1993 by Donald Becker | |||
6 | * Modularized by Pauline Middelink <middelin@polyware.iaf.nl> | |||
7 | * Changed to support io= irq= by Alan Cox <Alan.Cox@linux.org> | |||
8 | * Reworked 1995 by John Sullivan <js10039@cam.ac.uk> | |||
9 | * More fixes by Philip Blundell <pjb27@cam.ac.uk> | |||
10 | * Added the Compaq LTE Alan Cox <alan@redhat.com> | |||
11 | * | |||
12 | * Note - this driver is experimental still - it has problems on faster | |||
13 | * machines. Someone needs to sit down and go through it line by line with | |||
14 | * a databook... | |||
15 | */ | |||
16 | ||||
17 | /* | |||
18 | * The original EtherExpress driver was just about usable, but | |||
19 | * suffered from a long startup delay, a hard limit of 16k memory | |||
20 | * usage on the card (EtherExpress 16s have either 32k or 64k), | |||
21 | * and random locks under load. The last was particularly annoying | |||
22 | * and made running eXceed/W preferable to Linux/XFree. After hacking | |||
23 | * through the driver for a couple of days, I had fixed most of the | |||
24 | * card handling errors, at the expense of turning the code into | |||
25 | * a complete jungle, but still hadn't tracked down the lock-ups. | |||
26 | * I had hoped these would be an IP bug, but failed to reproduce them | |||
27 | * under other drivers, so decided to start from scratch and rewrite | |||
28 | * the driver cleanly. And here it is. | |||
29 | * | |||
30 | * It's still not quite there, but self-corrects a lot more problems. | |||
31 | * the 'CU wedged, resetting...' message shouldn't happen at all, but | |||
32 | * at least we recover. It still locks occasionally, any ideas welcome. | |||
33 | * | |||
34 | * The original startup delay experienced by some people was due to the | |||
35 | * first ARP request for the address of the default router getting lost. | |||
36 | * (mostly the reply we were getting back was arriving before our | |||
37 | * hardware address was set up, or before the configuration sequence | |||
38 | * had told the card NOT to strip of the frame header). If you a long | |||
39 | * startup delay, you may have lost this ARP request/reply, although | |||
40 | * the original cause has been fixed. However, it is more likely that | |||
41 | * you've just locked under this version. | |||
42 | * | |||
43 | * The main changes are in the 586 initialization procedure (which was | |||
44 | * just broken before - the EExp is a strange beasty and needs careful | |||
45 | * handling) the receive buffer handling (we now use a non-terminating | |||
46 | * circular list of buffers, which stops the card giving us out-of- | |||
47 | * resources errors), and the transmit code. The driver is also more | |||
48 | * structured, and I have tried to keep the kernel interface separate | |||
49 | * from the hardware interface (although some routines naturally want | |||
50 | * to do both). | |||
51 | * | |||
52 | * John Sullivan | |||
53 | * | |||
54 | * 18/5/95: | |||
55 | * | |||
56 | * The lock-ups seem to happen when you access card memory after a 586 | |||
57 | * reset. This happens only 1 in 12 resets, on a random basis, and | |||
58 | * completely locks the machine. As far as I can see there is no | |||
59 | * workaround possible - the only thing to be done is make sure we | |||
60 | * never reset the card *after* booting the kernel - once at probe time | |||
61 | * must be sufficient, and we'll just have to put up with that failing | |||
62 | * occasionally (or buy a new NIC). By the way, this looks like a | |||
63 | * definite card bug, since Intel's own driver for DOS does exactly the | |||
64 | * same. | |||
65 | * | |||
66 | * This bug makes switching in and out of promiscuous mode a risky | |||
67 | * business, since we must do a 586 reset each time. | |||
68 | */ | |||
69 | ||||
70 | /* | |||
71 | * Sources: | |||
72 | * | |||
73 | * The original eexpress.c by Donald Becker | |||
74 | * Sources: the Crynwr EtherExpress driver source. | |||
75 | * the Intel Microcommunications Databook Vol.1 1990 | |||
76 | * | |||
77 | * wavelan.c and i82586.h | |||
78 | * This was invaluable for the complete '586 configuration details | |||
79 | * and command format. | |||
80 | * | |||
81 | * The Crynwr sources (again) | |||
82 | * Not as useful as the Wavelan driver, but then I had eexpress.c to | |||
83 | * go off. | |||
84 | * | |||
85 | * The Intel EtherExpress 16 ethernet card | |||
86 | * Provided the only reason I want to see a working etherexpress driver. | |||
87 | * A lot of fixes came from just observing how the card (mis)behaves when | |||
88 | * you prod it. | |||
89 | * | |||
90 | */ | |||
91 | ||||
92 | static char version[] = | |||
93 | "eexpress.c: v0.10 04-May-95 John Sullivan <js10039@cam.ac.uk>\n" | |||
94 | " v0.14 19-May-96 Philip Blundell <phil@tazenda.demon.co.uk>\n" | |||
95 | " v0.15 04-Aug-98 Alan Cox <alan@redhat.com>\n"; | |||
96 | ||||
97 | #include <linux/module.h> | |||
98 | ||||
99 | #include <linux/kernel.h> | |||
100 | #include <linux/sched.h> | |||
101 | #include <linux/types.h> | |||
102 | #include <linux/fcntl.h> | |||
103 | #include <linux/interrupt.h> | |||
104 | #include <linux/ptrace.h> | |||
105 | #include <linux/ioport.h> | |||
106 | #include <linux/string.h> | |||
107 | #include <linux/in.h> | |||
108 | #include <asm/system.h> | |||
109 | #include <asm/bitops.h> | |||
110 | #include <asm/io.h> | |||
111 | #include <asm/dma.h> | |||
112 | #include <linux/delay.h> | |||
113 | #include <linux/errno.h> | |||
114 | ||||
115 | #include <linux/netdevice.h> | |||
116 | #include <linux/etherdevice.h> | |||
117 | #include <linux/skbuff.h> | |||
118 | #include <linux/malloc.h> | |||
119 | ||||
120 | /* | |||
121 | * Not actually used yet - may be implemented when the driver has | |||
122 | * been debugged! | |||
123 | * | |||
124 | * Debug Level Driver Status | |||
125 | * 0 Final release | |||
126 | * 1 Beta test | |||
127 | * 2 | |||
128 | * 3 | |||
129 | * 4 Report timeouts & 586 errors (normal debug level) | |||
130 | * 5 Report all major events | |||
131 | * 6 Dump sent/received packet contents | |||
132 | * 7 Report function entry/exit | |||
133 | */ | |||
134 | ||||
135 | #ifndef NET_DEBUG4 | |||
136 | #define NET_DEBUG4 4 | |||
137 | #endif | |||
138 | static unsigned int net_debug = NET_DEBUG4; | |||
139 | ||||
140 | #undef F_DEB | |||
141 | ||||
142 | #include "eth82586.h" | |||
143 | ||||
144 | #define PRIV(x)((struct net_local *)(x)->priv) ((struct net_local *)(x)->priv) | |||
145 | #define EEXP_IO_EXTENT16 16 | |||
146 | ||||
147 | /* | |||
148 | * Private data declarations | |||
149 | */ | |||
150 | ||||
151 | struct net_local | |||
152 | { | |||
153 | struct enet_statistics stats; | |||
154 | unsigned long init_time; /* jiffies when eexp_hw_init586 called */ | |||
155 | unsigned short rx_first; /* first rx buf, same as RX_BUF_START */ | |||
156 | unsigned short rx_last; /* last rx buf */ | |||
157 | unsigned short tx_head; /* next free tx buf */ | |||
158 | unsigned short tx_reap; /* first in-use tx buf */ | |||
159 | unsigned short tx_tail; /* previous tx buf to tx_head */ | |||
160 | unsigned short tx_link; /* last known-executing tx buf */ | |||
161 | unsigned short last_tx_restart; /* set to tx_link when we restart the CU */ | |||
162 | unsigned char started; | |||
163 | unsigned char promisc; | |||
164 | unsigned short rx_buf_start; | |||
165 | unsigned short rx_buf_end; | |||
166 | unsigned short num_tx_bufs; | |||
167 | unsigned short num_rx_bufs; | |||
168 | }; | |||
169 | ||||
170 | unsigned short start_code[] = { | |||
171 | 0x0000, /* SCP: set bus to 16 bits */ | |||
172 | 0x0000,0x0000, /* junk */ | |||
173 | 0x0000,0x0000, /* address of ISCP (lo,hi) */ | |||
174 | ||||
175 | 0x0001, /* ISCP: busy - cleared after reset */ | |||
176 | 0x0008,0x0000,0x0000, /* offset,address (lo,hi) of SCB */ | |||
177 | ||||
178 | 0x0000,0x0000, /* SCB: status, commands */ | |||
179 | 0x0000,0x0000, /* links to first command block, first receive descriptor */ | |||
180 | 0x0000,0x0000, /* CRC error, alignment error counts */ | |||
181 | 0x0000,0x0000, /* out of resources, overrun error counts */ | |||
182 | ||||
183 | 0x0000,0x0000, /* pad */ | |||
184 | 0x0000,0x0000, | |||
185 | ||||
186 | 0x0000,Cmd_Config0x0002, /* startup configure sequence, at 0x0020 */ | |||
187 | 0x0032, /* link to next command */ | |||
188 | 0x080c, /* 12 bytes follow : fifo threshold=8 */ | |||
189 | 0x2e40, /* don't rx bad frames : SRDY/ARDY => ext. sync. : preamble len=8 | |||
190 | * take addresses from data buffers : 6 bytes/address */ | |||
191 | 0x6000, /* default backoff method & priority : interframe spacing = 0x60 */ | |||
192 | 0xf200, /* slot time=0x200 : max collision retry = 0xf */ | |||
193 | 0x0000, /* no HDLC : normal CRC : enable broadcast : disable promiscuous/multicast modes */ | |||
194 | 0x003c, /* minimum frame length = 60 octets) */ | |||
195 | ||||
196 | 0x0000,Cmd_INT0x2000|Cmd_SetAddr0x0001, | |||
197 | 0x003e, /* link to next command */ | |||
198 | 0x0000,0x0000,0x0000, /* hardware address placed here, 0x0038 */ | |||
199 | 0x0000,Cmd_END0x8000|Cmd_Nop0x0000, /* end of configure sequence */ | |||
200 | 0x003e, | |||
201 | ||||
202 | 0x0000 | |||
203 | ||||
204 | }; | |||
205 | ||||
206 | #define CONF_LINK0x0020 0x0020 | |||
207 | #define CONF_HW_ADDR0x0038 0x0038 | |||
208 | ||||
209 | /* maps irq number to EtherExpress magic value */ | |||
210 | static char irqrmap[] = { 0,0,1,2,3,4,0,0,0,1,5,6,0,0,0,0 }; | |||
211 | ||||
212 | /* | |||
213 | * Prototypes for Linux interface | |||
214 | */ | |||
215 | ||||
216 | extern int express_probe(struct devicelinux_device *dev); | |||
217 | static int eexp_open (struct devicelinux_device *dev); | |||
218 | static int eexp_close(struct devicelinux_device *dev); | |||
219 | static struct enet_statistics *eexp_stats(struct devicelinux_device *dev); | |||
220 | static int eexp_xmit (struct sk_buff *buf, struct devicelinux_device *dev); | |||
221 | ||||
222 | static void eexp_irq (int irq, void *dev_addr, struct pt_regs *regs); | |||
223 | static void eexp_set_multicast(struct devicelinux_device *dev); | |||
224 | ||||
225 | /* | |||
226 | * Prototypes for hardware access functions | |||
227 | */ | |||
228 | ||||
229 | static void eexp_hw_rx (struct devicelinux_device *dev); | |||
230 | static void eexp_hw_tx (struct devicelinux_device *dev, unsigned short *buf, unsigned short len); | |||
231 | static int eexp_hw_probe (struct devicelinux_device *dev,unsigned short ioaddr); | |||
232 | static unsigned short eexp_hw_readeeprom(unsigned short ioaddr, unsigned char location); | |||
233 | ||||
234 | static unsigned short eexp_hw_lasttxstat(struct devicelinux_device *dev); | |||
235 | static void eexp_hw_txrestart (struct devicelinux_device *dev); | |||
236 | ||||
237 | static void eexp_hw_txinit (struct devicelinux_device *dev); | |||
238 | static void eexp_hw_rxinit (struct devicelinux_device *dev); | |||
239 | ||||
240 | static void eexp_hw_init586 (struct devicelinux_device *dev); | |||
241 | static void eexp_hw_ASICrst (struct devicelinux_device *dev); | |||
242 | ||||
243 | /* | |||
244 | * Linux interface | |||
245 | */ | |||
246 | ||||
247 | /* | |||
248 | * checks for presence of EtherExpress card | |||
249 | */ | |||
250 | ||||
251 | int express_probe(struct devicelinux_device *dev) | |||
252 | { | |||
253 | unsigned short *port,ports[] = { 0x0300,0x0270,0x0320,0x0340,0 }; | |||
254 | unsigned short ioaddr = dev->base_addr; | |||
255 | ||||
256 | if (ioaddr&0xfe00) | |||
| ||||
257 | return eexp_hw_probe(dev,ioaddr); | |||
258 | else if (ioaddr) | |||
259 | return ENXIO6; | |||
260 | ||||
261 | for ( port=&ports[0] ; *port ; port++ ) | |||
262 | { | |||
263 | unsigned short sum = 0; | |||
264 | int i; | |||
265 | for ( i=0 ; i<4 ; i++ ) | |||
266 | { | |||
267 | unsigned short t; | |||
268 | t = inb(*port + ID_PORT)((__builtin_constant_p((*port + 0x000f)) && (*port + 0x000f ) < 256) ? __inbc(*port + 0x000f) : __inb(*port + 0x000f)); | |||
269 | sum |= (t>>4) << ((t & 0x03)<<2); | |||
270 | } | |||
271 | if (sum==0xbaba && !eexp_hw_probe(dev,*port)) | |||
272 | return 0; | |||
273 | } | |||
274 | return ENODEV19; | |||
275 | } | |||
276 | ||||
277 | /* | |||
278 | * open and initialize the adapter, ready for use | |||
279 | */ | |||
280 | ||||
281 | static int eexp_open(struct devicelinux_device *dev) | |||
282 | { | |||
283 | int irq = dev->irq; | |||
284 | unsigned short ioaddr = dev->base_addr; | |||
285 | ||||
286 | #if NET_DEBUG4 > 6 | |||
287 | printk(KERN_DEBUG"<7>" "%s: eexp_open()\n", dev->name); | |||
288 | #endif | |||
289 | ||||
290 | if (!irq || !irqrmap[irq]) | |||
291 | return -ENXIO6; | |||
292 | ||||
293 | if (irq2dev_map[irq] || | |||
294 | /* more consistent, surely? */ | |||
295 | ((irq2dev_map[irq]=dev),0) || | |||
296 | request_irq(irq,&eexp_irq,0,"eexpress",NULL((void *) 0))) | |||
297 | return -EAGAIN11; | |||
298 | ||||
299 | request_region(ioaddr, EEXP_IO_EXTENT16, "eexpress"); | |||
300 | dev->tbusy = 0; | |||
301 | dev->interrupt = 0; | |||
302 | eexp_hw_init586(dev); | |||
303 | dev->start = 1; | |||
304 | MOD_INC_USE_COUNTdo { } while (0); | |||
305 | #if NET_DEBUG4 > 6 | |||
306 | printk(KERN_DEBUG"<7>" "%s: leaving eexp_open()\n", dev->name); | |||
307 | #endif | |||
308 | return 0; | |||
309 | } | |||
310 | ||||
311 | /* | |||
312 | * close and disable the interface, leaving | |||
313 | * the 586 in reset | |||
314 | */ | |||
315 | static int eexp_close(struct devicelinux_device *dev) | |||
316 | { | |||
317 | unsigned short ioaddr = dev->base_addr; | |||
318 | int irq = dev->irq; | |||
319 | ||||
320 | dev->tbusy = 1; | |||
321 | dev->start = 0; | |||
322 | ||||
323 | outb(SIRQ_dis|irqrmap[irq],ioaddr+SET_IRQ)((__builtin_constant_p((ioaddr+0x0007)) && (ioaddr+0x0007 ) < 256) ? __outbc((0x00|irqrmap[irq]),(ioaddr+0x0007)) : __outb ((0x00|irqrmap[irq]),(ioaddr+0x0007))); | |||
324 | PRIV(dev)((struct net_local *)(dev)->priv)->started = 0; | |||
325 | outw(SCB_CUsuspend|SCB_RUsuspend,ioaddr+SCB_CMD)((__builtin_constant_p((ioaddr+0xc00a)) && (ioaddr+0xc00a ) < 256) ? __outwc((0x0300|0x0030),(ioaddr+0xc00a)) : __outw ((0x0300|0x0030),(ioaddr+0xc00a))); | |||
326 | outb(0,ioaddr+SIGNAL_CA)((__builtin_constant_p((ioaddr+0x0006)) && (ioaddr+0x0006 ) < 256) ? __outbc((0),(ioaddr+0x0006)) : __outb((0),(ioaddr +0x0006))); | |||
327 | free_irq(irq,NULL((void *) 0)); | |||
328 | irq2dev_map[irq] = NULL((void *) 0); | |||
329 | outb(i586_RST,ioaddr+EEPROM_Ctrl)((__builtin_constant_p((ioaddr+0x000e)) && (ioaddr+0x000e ) < 256) ? __outbc((0x80),(ioaddr+0x000e)) : __outb((0x80) ,(ioaddr+0x000e))); | |||
330 | release_region(ioaddr,16); | |||
331 | MOD_DEC_USE_COUNTdo { } while (0); | |||
332 | return 0; | |||
333 | } | |||
334 | ||||
335 | /* | |||
336 | * Return interface stats | |||
337 | */ | |||
338 | ||||
339 | static struct enet_statistics *eexp_stats(struct devicelinux_device *dev) | |||
340 | { | |||
341 | struct net_local *lp = (struct net_local *)dev->priv; | |||
342 | ||||
343 | /* | |||
344 | * Hmmm, this looks a little too easy... The card maintains | |||
345 | * some stats in the SCB, and I'm not convinced we're | |||
346 | * incrementing the most sensible statistics when the card | |||
347 | * returns an error (esp. slow DMA, out-of-resources) | |||
348 | */ | |||
349 | return &lp->stats; | |||
350 | } | |||
351 | ||||
352 | /* | |||
353 | * Called to transmit a packet, or to allow us to right ourselves | |||
354 | * if the kernel thinks we've died. | |||
355 | */ | |||
356 | ||||
357 | static int eexp_xmit(struct sk_buff *buf, struct devicelinux_device *dev) | |||
358 | { | |||
359 | struct net_local *lp = (struct net_local *)dev->priv; | |||
360 | unsigned short ioaddr = dev->base_addr; | |||
361 | ||||
362 | #if NET_DEBUG4 > 6 | |||
363 | printk(KERN_DEBUG"<7>" "%s: eexp_xmit()\n", dev->name); | |||
364 | #endif | |||
365 | ||||
366 | outb(SIRQ_dis|irqrmap[dev->irq],ioaddr+SET_IRQ)((__builtin_constant_p((ioaddr+0x0007)) && (ioaddr+0x0007 ) < 256) ? __outbc((0x00|irqrmap[dev->irq]),(ioaddr+0x0007 )) : __outb((0x00|irqrmap[dev->irq]),(ioaddr+0x0007))); | |||
367 | if (dev->tbusy) | |||
368 | { | |||
369 | /* This will happen, but hopefully not as often as when | |||
370 | * tbusy==0. If it happens too much, we probably ought | |||
371 | * to think about unwedging ourselves... | |||
372 | */ | |||
373 | if (test_bit(0,(void *)&PRIV(dev)((struct net_local *)(dev)->priv)->started)) | |||
374 | { | |||
375 | if ((jiffies - dev->trans_start)>5) | |||
376 | { | |||
377 | if (lp->tx_link==lp->last_tx_restart) | |||
378 | { | |||
379 | unsigned short boguscount=200,rsst; | |||
380 | printk(KERN_WARNING"<4>" "%s: Retransmit timed out, status %04x, resetting...\n", | |||
381 | dev->name,inw(ioaddr+SCB_STATUS)((__builtin_constant_p((ioaddr+0xc008)) && (ioaddr+0xc008 ) < 256) ? __inwc(ioaddr+0xc008) : __inw(ioaddr+0xc008))); | |||
382 | eexp_hw_txinit(dev); | |||
383 | lp->last_tx_restart = 0; | |||
384 | outw(lp->tx_link,ioaddr+SCB_CBL)((__builtin_constant_p((ioaddr+0xc00c)) && (ioaddr+0xc00c ) < 256) ? __outwc((lp->tx_link),(ioaddr+0xc00c)) : __outw ((lp->tx_link),(ioaddr+0xc00c))); | |||
385 | outw(0,ioaddr+SCB_STATUS)((__builtin_constant_p((ioaddr+0xc008)) && (ioaddr+0xc008 ) < 256) ? __outwc((0),(ioaddr+0xc008)) : __outw((0),(ioaddr +0xc008))); | |||
386 | outw(SCB_CUstart,ioaddr+SCB_CMD)((__builtin_constant_p((ioaddr+0xc00a)) && (ioaddr+0xc00a ) < 256) ? __outwc((0x0100),(ioaddr+0xc00a)) : __outw((0x0100 ),(ioaddr+0xc00a))); | |||
387 | outb(0,ioaddr+SIGNAL_CA)((__builtin_constant_p((ioaddr+0x0006)) && (ioaddr+0x0006 ) < 256) ? __outbc((0),(ioaddr+0x0006)) : __outb((0),(ioaddr +0x0006))); | |||
388 | while (!SCB_complete(rsst=inw(ioaddr+SCB_STATUS))((rsst=((__builtin_constant_p((ioaddr+0xc008)) && (ioaddr +0xc008) < 256) ? __inwc(ioaddr+0xc008) : __inw(ioaddr+0xc008 ))&0x8000)!=0)) | |||
389 | { | |||
390 | if (!--boguscount) | |||
391 | { | |||
392 | boguscount=200; | |||
393 | printk(KERN_WARNING"<4>" "%s: Reset timed out status %04x, retrying...\n", | |||
394 | dev->name,rsst); | |||
395 | outw(lp->tx_link,ioaddr+SCB_CBL)((__builtin_constant_p((ioaddr+0xc00c)) && (ioaddr+0xc00c ) < 256) ? __outwc((lp->tx_link),(ioaddr+0xc00c)) : __outw ((lp->tx_link),(ioaddr+0xc00c))); | |||
396 | outw(0,ioaddr+SCB_STATUS)((__builtin_constant_p((ioaddr+0xc008)) && (ioaddr+0xc008 ) < 256) ? __outwc((0),(ioaddr+0xc008)) : __outw((0),(ioaddr +0xc008))); | |||
397 | outw(SCB_CUstart,ioaddr+SCB_CMD)((__builtin_constant_p((ioaddr+0xc00a)) && (ioaddr+0xc00a ) < 256) ? __outwc((0x0100),(ioaddr+0xc00a)) : __outw((0x0100 ),(ioaddr+0xc00a))); | |||
398 | outb(0,ioaddr+SIGNAL_CA)((__builtin_constant_p((ioaddr+0x0006)) && (ioaddr+0x0006 ) < 256) ? __outbc((0),(ioaddr+0x0006)) : __outb((0),(ioaddr +0x0006))); | |||
399 | } | |||
400 | } | |||
401 | dev->tbusy = 0; | |||
402 | mark_bh(NET_BH); | |||
403 | } | |||
404 | else | |||
405 | { | |||
406 | unsigned short status = inw(ioaddr+SCB_STATUS)((__builtin_constant_p((ioaddr+0xc008)) && (ioaddr+0xc008 ) < 256) ? __inwc(ioaddr+0xc008) : __inw(ioaddr+0xc008)); | |||
407 | if (SCB_CUdead(status)((status&0x2000)!=0)) | |||
408 | { | |||
409 | unsigned short txstatus = eexp_hw_lasttxstat(dev); | |||
410 | printk(KERN_WARNING"<4>" "%s: Transmit timed out, CU not active status %04x %04x, restarting...\n", | |||
411 | dev->name, status, txstatus); | |||
412 | eexp_hw_txrestart(dev); | |||
413 | } | |||
414 | else | |||
415 | { | |||
416 | unsigned short txstatus = eexp_hw_lasttxstat(dev); | |||
417 | if (dev->tbusy && !txstatus) | |||
418 | { | |||
419 | printk(KERN_WARNING"<4>" "%s: CU wedged, status %04x %04x, resetting...\n", | |||
420 | dev->name,status,txstatus); | |||
421 | eexp_hw_init586(dev); | |||
422 | dev->tbusy = 0; | |||
423 | mark_bh(NET_BH); | |||
424 | } | |||
425 | } | |||
426 | } | |||
427 | } | |||
428 | } | |||
429 | else | |||
430 | { | |||
431 | if ((jiffies-lp->init_time)>10) | |||
432 | { | |||
433 | unsigned short status = inw(ioaddr+SCB_STATUS)((__builtin_constant_p((ioaddr+0xc008)) && (ioaddr+0xc008 ) < 256) ? __inwc(ioaddr+0xc008) : __inw(ioaddr+0xc008)); | |||
434 | printk(KERN_WARNING"<4>" "%s: i82586 startup timed out, status %04x, resetting...\n", | |||
435 | dev->name, status); | |||
436 | eexp_hw_init586(dev); | |||
437 | dev->tbusy = 0; | |||
438 | mark_bh(NET_BH); | |||
439 | } | |||
440 | } | |||
441 | } | |||
442 | ||||
443 | if (buf==NULL((void *) 0)) | |||
444 | { | |||
445 | unsigned short status = inw(ioaddr+SCB_STATUS)((__builtin_constant_p((ioaddr+0xc008)) && (ioaddr+0xc008 ) < 256) ? __inwc(ioaddr+0xc008) : __inw(ioaddr+0xc008)); | |||
446 | unsigned short txstatus = eexp_hw_lasttxstat(dev); | |||
447 | if (SCB_CUdead(status)((status&0x2000)!=0)) | |||
448 | { | |||
449 | printk(KERN_WARNING"<4>" "%s: CU has died! status %04x %04x, attempting to restart...\n", | |||
450 | dev->name, status, txstatus); | |||
451 | lp->stats.tx_errors++; | |||
452 | eexp_hw_txrestart(dev); | |||
453 | } | |||
454 | dev_tint(dev); | |||
455 | outb(SIRQ_en|irqrmap[dev->irq],ioaddr+SET_IRQ)((__builtin_constant_p((ioaddr+0x0007)) && (ioaddr+0x0007 ) < 256) ? __outbc((0x08|irqrmap[dev->irq]),(ioaddr+0x0007 )) : __outb((0x08|irqrmap[dev->irq]),(ioaddr+0x0007))); | |||
456 | dev_kfree_skb(buf, FREE_WRITE0); | |||
457 | return 0; | |||
458 | } | |||
459 | ||||
460 | if (set_bit(0,(void *)&dev->tbusy)) | |||
461 | { | |||
462 | lp->stats.tx_dropped++; | |||
463 | } | |||
464 | else | |||
465 | { | |||
466 | unsigned short length = (ETH_ZLEN60 < buf->len) ? buf->len : ETH_ZLEN60; | |||
467 | unsigned short *data = (unsigned short *)buf->data; | |||
468 | ||||
469 | outb(SIRQ_dis|irqrmap[dev->irq],ioaddr+SET_IRQ)((__builtin_constant_p((ioaddr+0x0007)) && (ioaddr+0x0007 ) < 256) ? __outbc((0x00|irqrmap[dev->irq]),(ioaddr+0x0007 )) : __outb((0x00|irqrmap[dev->irq]),(ioaddr+0x0007))); | |||
470 | eexp_hw_tx(dev,data,length); | |||
471 | outb(SIRQ_en|irqrmap[dev->irq],ioaddr+SET_IRQ)((__builtin_constant_p((ioaddr+0x0007)) && (ioaddr+0x0007 ) < 256) ? __outbc((0x08|irqrmap[dev->irq]),(ioaddr+0x0007 )) : __outb((0x08|irqrmap[dev->irq]),(ioaddr+0x0007))); | |||
472 | } | |||
473 | dev_kfree_skb(buf, FREE_WRITE0); | |||
474 | outb(SIRQ_en|irqrmap[dev->irq],ioaddr+SET_IRQ)((__builtin_constant_p((ioaddr+0x0007)) && (ioaddr+0x0007 ) < 256) ? __outbc((0x08|irqrmap[dev->irq]),(ioaddr+0x0007 )) : __outb((0x08|irqrmap[dev->irq]),(ioaddr+0x0007))); | |||
475 | return 0; | |||
476 | } | |||
477 | ||||
478 | /* | |||
479 | * Handle an EtherExpress interrupt | |||
480 | * If we've finished initializing, start the RU and CU up. | |||
481 | * If we've already started, reap tx buffers, handle any received packets, | |||
482 | * check to make sure we've not become wedged. | |||
483 | */ | |||
484 | ||||
485 | static void eexp_irq(int irq, void *dev_info, struct pt_regs *regs) | |||
486 | { | |||
487 | struct devicelinux_device *dev = irq2dev_map[irq]; | |||
488 | struct net_local *lp; | |||
489 | unsigned short ioaddr,status,ack_cmd; | |||
490 | unsigned short old_rp,old_wp; | |||
491 | ||||
492 | if (dev==NULL((void *) 0)) | |||
493 | { | |||
494 | printk(KERN_WARNING"<4>" "net_interrupt(): irq %d for unknown device caught by EExpress\n",irq); | |||
495 | return; | |||
496 | } | |||
497 | ||||
498 | #if NET_DEBUG4 > 6 | |||
499 | printk(KERN_DEBUG"<7>" "%s: interrupt\n", dev->name); | |||
500 | #endif | |||
501 | ||||
502 | dev->interrupt = 1; /* should this be reset on exit? */ | |||
503 | ||||
504 | lp = (struct net_local *)dev->priv; | |||
505 | ioaddr = dev->base_addr; | |||
506 | ||||
507 | outb(SIRQ_dis|irqrmap[irq],ioaddr+SET_IRQ)((__builtin_constant_p((ioaddr+0x0007)) && (ioaddr+0x0007 ) < 256) ? __outbc((0x00|irqrmap[irq]),(ioaddr+0x0007)) : __outb ((0x00|irqrmap[irq]),(ioaddr+0x0007))); | |||
508 | old_rp = inw(ioaddr+READ_PTR)((__builtin_constant_p((ioaddr+0x0004)) && (ioaddr+0x0004 ) < 256) ? __inwc(ioaddr+0x0004) : __inw(ioaddr+0x0004)); | |||
509 | old_wp = inw(ioaddr+WRITE_PTR)((__builtin_constant_p((ioaddr+0x0002)) && (ioaddr+0x0002 ) < 256) ? __inwc(ioaddr+0x0002) : __inw(ioaddr+0x0002)); | |||
510 | status = inw(ioaddr+SCB_STATUS)((__builtin_constant_p((ioaddr+0xc008)) && (ioaddr+0xc008 ) < 256) ? __inwc(ioaddr+0xc008) : __inw(ioaddr+0xc008)); | |||
511 | ack_cmd = SCB_ack(status)(status & 0xf000); | |||
512 | ||||
513 | if (PRIV(dev)((struct net_local *)(dev)->priv)->started==0 && SCB_complete(status)((status&0x8000)!=0)) | |||
514 | { | |||
515 | #if NET_DEBUG4 > 4 | |||
516 | printk(KERN_DEBUG"<7>" "%s: SCBcomplete event received\n", dev->name); | |||
517 | #endif | |||
518 | while (SCB_CUstat(status)((status&0x0300)>>8)==2) | |||
519 | status = inw_p(ioaddr+SCB_STATUS)((__builtin_constant_p((ioaddr+0xc008)) && (ioaddr+0xc008 ) < 256) ? __inwc_p(ioaddr+0xc008) : __inw_p(ioaddr+0xc008 )); | |||
520 | #if NET_DEBUG4 > 4 | |||
521 | printk(KERN_DEBUG"<7>" "%s: CU went non-active (status = %08x)\n", dev->name, status); | |||
522 | #endif | |||
523 | PRIV(dev)((struct net_local *)(dev)->priv)->started=1; | |||
524 | outw_p(lp->tx_link,ioaddr+SCB_CBL)((__builtin_constant_p((ioaddr+0xc00c)) && (ioaddr+0xc00c ) < 256) ? __outwc_p((lp->tx_link),(ioaddr+0xc00c)) : __outw_p ((lp->tx_link),(ioaddr+0xc00c))); | |||
525 | outw_p(PRIV(dev)->rx_buf_start,ioaddr+SCB_RFA)((__builtin_constant_p((ioaddr+0xc00e)) && (ioaddr+0xc00e ) < 256) ? __outwc_p((((struct net_local *)(dev)->priv) ->rx_buf_start),(ioaddr+0xc00e)) : __outw_p((((struct net_local *)(dev)->priv)->rx_buf_start),(ioaddr+0xc00e))); | |||
526 | ack_cmd |= SCB_CUstart0x0100 | SCB_RUstart0x0010; | |||
527 | } | |||
528 | else if (PRIV(dev)((struct net_local *)(dev)->priv)->started) | |||
529 | { | |||
530 | unsigned short txstatus; | |||
531 | txstatus = eexp_hw_lasttxstat(dev); | |||
532 | } | |||
533 | ||||
534 | if (SCB_rxdframe(status)((status&0x4000)!=0)) | |||
535 | { | |||
536 | eexp_hw_rx(dev); | |||
537 | } | |||
538 | ||||
539 | if ((PRIV(dev)((struct net_local *)(dev)->priv)->started&2)!=0 && SCB_RUstat(status)((status&0x0070)>>4)!=4) | |||
540 | { | |||
541 | printk(KERN_WARNING"<4>" "%s: RU stopped status %04x, restarting...\n", | |||
542 | dev->name,status); | |||
543 | lp->stats.rx_errors++; | |||
544 | eexp_hw_rxinit(dev); | |||
545 | outw(PRIV(dev)->rx_buf_start,ioaddr+SCB_RFA)((__builtin_constant_p((ioaddr+0xc00e)) && (ioaddr+0xc00e ) < 256) ? __outwc((((struct net_local *)(dev)->priv)-> rx_buf_start),(ioaddr+0xc00e)) : __outw((((struct net_local * )(dev)->priv)->rx_buf_start),(ioaddr+0xc00e))); | |||
546 | ack_cmd |= SCB_RUstart0x0010; | |||
547 | } | |||
548 | else if (PRIV(dev)((struct net_local *)(dev)->priv)->started==1 && SCB_RUstat(status)((status&0x0070)>>4)==4) | |||
549 | PRIV(dev)((struct net_local *)(dev)->priv)->started|=2; | |||
550 | ||||
551 | outw(ack_cmd,ioaddr+SCB_CMD)((__builtin_constant_p((ioaddr+0xc00a)) && (ioaddr+0xc00a ) < 256) ? __outwc((ack_cmd),(ioaddr+0xc00a)) : __outw((ack_cmd ),(ioaddr+0xc00a))); | |||
552 | outb(0,ioaddr+SIGNAL_CA)((__builtin_constant_p((ioaddr+0x0006)) && (ioaddr+0x0006 ) < 256) ? __outbc((0),(ioaddr+0x0006)) : __outb((0),(ioaddr +0x0006))); | |||
553 | outw(old_rp,ioaddr+READ_PTR)((__builtin_constant_p((ioaddr+0x0004)) && (ioaddr+0x0004 ) < 256) ? __outwc((old_rp),(ioaddr+0x0004)) : __outw((old_rp ),(ioaddr+0x0004))); | |||
554 | outw(old_wp,ioaddr+WRITE_PTR)((__builtin_constant_p((ioaddr+0x0002)) && (ioaddr+0x0002 ) < 256) ? __outwc((old_wp),(ioaddr+0x0002)) : __outw((old_wp ),(ioaddr+0x0002))); | |||
555 | outb(SIRQ_en|irqrmap[irq],ioaddr+SET_IRQ)((__builtin_constant_p((ioaddr+0x0007)) && (ioaddr+0x0007 ) < 256) ? __outbc((0x08|irqrmap[irq]),(ioaddr+0x0007)) : __outb ((0x08|irqrmap[irq]),(ioaddr+0x0007))); | |||
556 | dev->interrupt = 0; | |||
557 | #if NET_DEBUG4 > 6 | |||
558 | printk(KERN_DEBUG"<7>" "%s: leaving eexp_irq()\n", dev->name); | |||
559 | #endif | |||
560 | return; | |||
561 | } | |||
562 | ||||
563 | /* | |||
564 | * Hardware access functions | |||
565 | */ | |||
566 | ||||
567 | /* | |||
568 | * Check all the receive buffers, and hand any received packets | |||
569 | * to the upper levels. Basic sanity check on each frame | |||
570 | * descriptor | |||
571 | */ | |||
572 | ||||
573 | static void eexp_hw_rx(struct devicelinux_device *dev) | |||
574 | { | |||
575 | struct net_local *lp = (struct net_local *)dev->priv; | |||
576 | unsigned short ioaddr = dev->base_addr; | |||
577 | unsigned short old_wp = inw(ioaddr+WRITE_PTR)((__builtin_constant_p((ioaddr+0x0002)) && (ioaddr+0x0002 ) < 256) ? __inwc(ioaddr+0x0002) : __inw(ioaddr+0x0002)); | |||
578 | unsigned short old_rp = inw(ioaddr+READ_PTR)((__builtin_constant_p((ioaddr+0x0004)) && (ioaddr+0x0004 ) < 256) ? __inwc(ioaddr+0x0004) : __inw(ioaddr+0x0004)); | |||
579 | unsigned short rx_block = lp->rx_first; | |||
580 | unsigned short boguscount = lp->num_rx_bufs; | |||
581 | ||||
582 | #if NET_DEBUG4 > 6 | |||
583 | printk(KERN_DEBUG"<7>" "%s: eexp_hw_rx()\n", dev->name); | |||
584 | #endif | |||
585 | ||||
586 | while (outw(rx_block,ioaddr+READ_PTR)((__builtin_constant_p((ioaddr+0x0004)) && (ioaddr+0x0004 ) < 256) ? __outwc((rx_block),(ioaddr+0x0004)) : __outw((rx_block ),(ioaddr+0x0004))),boguscount--) | |||
587 | { | |||
588 | unsigned short status = inw(ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __inwc(ioaddr) : __inw(ioaddr)); | |||
589 | unsigned short rfd_cmd = inw(ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __inwc(ioaddr) : __inw(ioaddr)); | |||
590 | unsigned short rx_next = inw(ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __inwc(ioaddr) : __inw(ioaddr)); | |||
591 | unsigned short pbuf = inw(ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __inwc(ioaddr) : __inw(ioaddr)); | |||
592 | unsigned short pkt_len; | |||
593 | ||||
594 | if (FD_Done(status)((status&0x8000)!=0)) | |||
595 | { | |||
596 | outw(pbuf,ioaddr+READ_PTR)((__builtin_constant_p((ioaddr+0x0004)) && (ioaddr+0x0004 ) < 256) ? __outwc((pbuf),(ioaddr+0x0004)) : __outw((pbuf) ,(ioaddr+0x0004))); | |||
597 | pkt_len = inw(ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __inwc(ioaddr) : __inw(ioaddr)); | |||
598 | ||||
599 | if (rfd_cmd!=0x0000 || pbuf!=rx_block+0x16 | |||
600 | || (pkt_len & 0xc000)!=0xc000) | |||
601 | { | |||
602 | printk(KERN_WARNING"<4>" "%s: Rx frame at %04x corrupted, status %04x, cmd %04x, " | |||
603 | "next %04x, pbuf %04x, len %04x\n",dev->name,rx_block, | |||
604 | status,rfd_cmd,rx_next,pbuf,pkt_len); | |||
605 | boguscount++; | |||
606 | continue; | |||
607 | } | |||
608 | else if (!FD_OK(status)((status&0x2000)!=0)) | |||
609 | { | |||
610 | lp->stats.rx_errors++; | |||
611 | if (FD_CRC(status)((status&0x0800)!=0)) | |||
612 | lp->stats.rx_crc_errors++; | |||
613 | if (FD_Align(status)((status&0x0400)!=0)) | |||
614 | lp->stats.rx_frame_errors++; | |||
615 | if (FD_Resrc(status)((status&0x0200)!=0)) | |||
616 | lp->stats.rx_fifo_errors++; | |||
617 | if (FD_DMA(status)((status&0x0100)!=0)) | |||
618 | lp->stats.rx_over_errors++; | |||
619 | if (FD_Short(status)((status&0x0080)!=0)) | |||
620 | lp->stats.rx_length_errors++; | |||
621 | } | |||
622 | else | |||
623 | { | |||
624 | struct sk_buff *skb; | |||
625 | pkt_len &= 0x3fff; | |||
626 | skb = dev_alloc_skb(pkt_len+16); | |||
627 | if (skb == NULL((void *) 0)) | |||
628 | { | |||
629 | printk(KERN_WARNING"<4>" "%s: Memory squeeze, dropping packet\n",dev->name); | |||
630 | lp->stats.rx_dropped++; | |||
631 | break; | |||
632 | } | |||
633 | skb->dev = dev; | |||
634 | skb_reserve(skb, 2); | |||
635 | outw(pbuf+10,ioaddr+READ_PTR)((__builtin_constant_p((ioaddr+0x0004)) && (ioaddr+0x0004 ) < 256) ? __outwc((pbuf+10),(ioaddr+0x0004)) : __outw((pbuf +10),(ioaddr+0x0004))); | |||
636 | insw(ioaddr,skb_put(skb,pkt_len),(pkt_len+1)>>1); | |||
637 | skb->protocol = eth_type_trans(skb,dev)((unsigned short)0); | |||
638 | netif_rx(skb); | |||
639 | lp->stats.rx_packets++; | |||
640 | } | |||
641 | outw(rx_block,ioaddr+WRITE_PTR)((__builtin_constant_p((ioaddr+0x0002)) && (ioaddr+0x0002 ) < 256) ? __outwc((rx_block),(ioaddr+0x0002)) : __outw((rx_block ),(ioaddr+0x0002))); | |||
642 | outw(0x0000,ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __outwc((0x0000),(ioaddr)) : __outw((0x0000),(ioaddr))); | |||
643 | outw(0x0000,ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __outwc((0x0000),(ioaddr)) : __outw((0x0000),(ioaddr))); | |||
644 | } | |||
645 | rx_block = rx_next; | |||
646 | } | |||
647 | outw(old_rp,ioaddr+READ_PTR)((__builtin_constant_p((ioaddr+0x0004)) && (ioaddr+0x0004 ) < 256) ? __outwc((old_rp),(ioaddr+0x0004)) : __outw((old_rp ),(ioaddr+0x0004))); | |||
648 | outw(old_wp,ioaddr+WRITE_PTR)((__builtin_constant_p((ioaddr+0x0002)) && (ioaddr+0x0002 ) < 256) ? __outwc((old_wp),(ioaddr+0x0002)) : __outw((old_wp ),(ioaddr+0x0002))); | |||
649 | } | |||
650 | ||||
651 | /* | |||
652 | * Hand a packet to the card for transmission | |||
653 | * If we get here, we MUST have already checked | |||
654 | * to make sure there is room in the transmit | |||
655 | * buffer region | |||
656 | */ | |||
657 | ||||
658 | static void eexp_hw_tx(struct devicelinux_device *dev, unsigned short *buf, unsigned short len) | |||
659 | { | |||
660 | struct net_local *lp = (struct net_local *)dev->priv; | |||
661 | unsigned short ioaddr = dev->base_addr; | |||
662 | unsigned short old_wp = inw(ioaddr+WRITE_PTR)((__builtin_constant_p((ioaddr+0x0002)) && (ioaddr+0x0002 ) < 256) ? __inwc(ioaddr+0x0002) : __inw(ioaddr+0x0002)); | |||
663 | ||||
664 | outw(lp->tx_head,ioaddr+WRITE_PTR)((__builtin_constant_p((ioaddr+0x0002)) && (ioaddr+0x0002 ) < 256) ? __outwc((lp->tx_head),(ioaddr+0x0002)) : __outw ((lp->tx_head),(ioaddr+0x0002))); | |||
665 | outw(0x0000,ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __outwc((0x0000),(ioaddr)) : __outw((0x0000),(ioaddr))); | |||
666 | outw(Cmd_INT|Cmd_Xmit,ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __outwc((0x2000|0x0004),(ioaddr)) : __outw((0x2000|0x0004 ),(ioaddr))); | |||
667 | outw(lp->tx_head+0x08,ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __outwc((lp->tx_head+0x08),(ioaddr)) : __outw((lp-> tx_head+0x08),(ioaddr))); | |||
668 | outw(lp->tx_head+0x0e,ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __outwc((lp->tx_head+0x0e),(ioaddr)) : __outw((lp-> tx_head+0x0e),(ioaddr))); | |||
669 | outw(0x0000,ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __outwc((0x0000),(ioaddr)) : __outw((0x0000),(ioaddr))); | |||
670 | outw(0x0000,ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __outwc((0x0000),(ioaddr)) : __outw((0x0000),(ioaddr))); | |||
671 | outw(lp->tx_head+0x08,ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __outwc((lp->tx_head+0x08),(ioaddr)) : __outw((lp-> tx_head+0x08),(ioaddr))); | |||
672 | outw(0x8000|len,ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __outwc((0x8000|len),(ioaddr)) : __outw((0x8000|len),(ioaddr ))); | |||
673 | outw(-1,ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __outwc((-1),(ioaddr)) : __outw((-1),(ioaddr))); | |||
674 | outw(lp->tx_head+0x16,ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __outwc((lp->tx_head+0x16),(ioaddr)) : __outw((lp-> tx_head+0x16),(ioaddr))); | |||
675 | outw(0,ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __outwc((0),(ioaddr)) : __outw((0),(ioaddr))); | |||
676 | outsw(ioaddr,buf,(len+1)>>1); | |||
677 | outw(lp->tx_tail+0x0c,ioaddr+WRITE_PTR)((__builtin_constant_p((ioaddr+0x0002)) && (ioaddr+0x0002 ) < 256) ? __outwc((lp->tx_tail+0x0c),(ioaddr+0x0002)) : __outw((lp->tx_tail+0x0c),(ioaddr+0x0002))); | |||
678 | outw(lp->tx_head,ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __outwc((lp->tx_head),(ioaddr)) : __outw((lp->tx_head ),(ioaddr))); | |||
679 | dev->trans_start = jiffies; | |||
680 | lp->tx_tail = lp->tx_head; | |||
681 | if (lp->tx_head==TX_BUF_START0x0100+((lp->num_tx_bufs-1)*TX_BUF_SIZE((24 +1514 +31)&~0x1f))) | |||
682 | lp->tx_head = TX_BUF_START0x0100; | |||
683 | else | |||
684 | lp->tx_head += TX_BUF_SIZE((24 +1514 +31)&~0x1f); | |||
685 | if (lp->tx_head != lp->tx_reap) | |||
686 | dev->tbusy = 0; | |||
687 | outw(old_wp,ioaddr+WRITE_PTR)((__builtin_constant_p((ioaddr+0x0002)) && (ioaddr+0x0002 ) < 256) ? __outwc((old_wp),(ioaddr+0x0002)) : __outw((old_wp ),(ioaddr+0x0002))); | |||
688 | } | |||
689 | ||||
690 | /* | |||
691 | * Sanity check the suspected EtherExpress card | |||
692 | * Read hardware address, reset card, size memory and | |||
693 | * initialize buffer memory pointers. These should | |||
694 | * probably be held in dev->priv, in case someone has 2 | |||
695 | * differently configured cards in their box (Arghhh!) | |||
696 | */ | |||
697 | ||||
698 | static int eexp_hw_probe(struct devicelinux_device *dev, unsigned short ioaddr) | |||
699 | { | |||
700 | unsigned short hw_addr[3]; | |||
701 | int i; | |||
702 | unsigned char *chw_addr = (unsigned char *)hw_addr; | |||
703 | ||||
704 | printk("%s: EtherExpress at %#x, ",dev->name,ioaddr); | |||
705 | ||||
706 | hw_addr[0] = eexp_hw_readeeprom(ioaddr,2); | |||
707 | hw_addr[1] = eexp_hw_readeeprom(ioaddr,3); | |||
708 | hw_addr[2] = eexp_hw_readeeprom(ioaddr,4); | |||
709 | ||||
710 | /* Standard Address or Compaq LTE Address */ | |||
711 | if (!((hw_addr[2]==0x00aa && ((hw_addr[1] & 0xff00)==0x0000)) || | |||
712 | (hw_addr[2]==0x0080 && ((hw_addr[1] & 0xff00)==0x5F00)))) | |||
713 | { | |||
714 | printk("rejected: invalid address %04x%04x%04x\n", | |||
715 | hw_addr[2],hw_addr[1],hw_addr[0]); | |||
716 | return -ENODEV19; | |||
717 | } | |||
718 | ||||
719 | dev->base_addr = ioaddr; | |||
720 | for ( i=0 ; i<6 ; i++ ) | |||
721 | dev->dev_addr[i] = chw_addr[5-i]; | |||
| ||||
722 | ||||
723 | { | |||
724 | char irqmap[]={0, 9, 3, 4, 5, 10, 11, 0}; | |||
725 | char *ifmap[]={"AUI", "BNC", "10baseT"}; | |||
726 | enum iftype {AUI=0, BNC=1, TP=2}; | |||
727 | unsigned short setupval = eexp_hw_readeeprom(ioaddr,0); | |||
728 | ||||
729 | dev->irq = irqmap[setupval>>13]; | |||
730 | dev->if_port = !(setupval & 0x1000) ? AUI : | |||
731 | eexp_hw_readeeprom(ioaddr,5) & 0x1 ? TP : BNC; | |||
732 | ||||
733 | printk("IRQ %d, Interface %s, ",dev->irq,ifmap[dev->if_port]); | |||
734 | ||||
735 | outb(SIRQ_dis|irqrmap[dev->irq],ioaddr+SET_IRQ)((__builtin_constant_p((ioaddr+0x0007)) && (ioaddr+0x0007 ) < 256) ? __outbc((0x00|irqrmap[dev->irq]),(ioaddr+0x0007 )) : __outb((0x00|irqrmap[dev->irq]),(ioaddr+0x0007))); | |||
736 | outb(0,ioaddr+SET_IRQ)((__builtin_constant_p((ioaddr+0x0007)) && (ioaddr+0x0007 ) < 256) ? __outbc((0),(ioaddr+0x0007)) : __outb((0),(ioaddr +0x0007))); | |||
737 | } | |||
738 | ||||
739 | dev->priv = kmalloclinux_kmalloc(sizeof(struct net_local), GFP_KERNEL0x03); | |||
740 | if (!dev->priv) | |||
741 | return -ENOMEM12; | |||
742 | ||||
743 | memset(dev->priv, 0, sizeof(struct net_local))(__builtin_constant_p(0) ? (__builtin_constant_p((sizeof(struct net_local))) ? __constant_c_and_count_memset(((dev->priv) ),((0x01010101UL*(unsigned char)(0))),((sizeof(struct net_local )))) : __constant_c_memset(((dev->priv)),((0x01010101UL*(unsigned char)(0))),((sizeof(struct net_local))))) : (__builtin_constant_p ((sizeof(struct net_local))) ? __memset_generic((((dev->priv ))),(((0))),(((sizeof(struct net_local))))) : __memset_generic (((dev->priv)),((0)),((sizeof(struct net_local)))))); | |||
744 | ||||
745 | eexp_hw_ASICrst(dev); | |||
746 | ||||
747 | { | |||
748 | unsigned short i586mso = 0x023e; | |||
749 | unsigned short old_wp,old_rp,old_a0,old_a1; | |||
750 | unsigned short a0_0,a1_0,a0_1,a1_1; | |||
751 | ||||
752 | old_wp = inw(ioaddr+WRITE_PTR)((__builtin_constant_p((ioaddr+0x0002)) && (ioaddr+0x0002 ) < 256) ? __inwc(ioaddr+0x0002) : __inw(ioaddr+0x0002)); | |||
753 | old_rp = inw(ioaddr+READ_PTR)((__builtin_constant_p((ioaddr+0x0004)) && (ioaddr+0x0004 ) < 256) ? __inwc(ioaddr+0x0004) : __inw(ioaddr+0x0004)); | |||
754 | outw(0x8000+i586mso,ioaddr+READ_PTR)((__builtin_constant_p((ioaddr+0x0004)) && (ioaddr+0x0004 ) < 256) ? __outwc((0x8000 +i586mso),(ioaddr+0x0004)) : __outw ((0x8000 +i586mso),(ioaddr+0x0004))); | |||
755 | old_a1 = inw(ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __inwc(ioaddr) : __inw(ioaddr)); | |||
756 | outw(i586mso,ioaddr+READ_PTR)((__builtin_constant_p((ioaddr+0x0004)) && (ioaddr+0x0004 ) < 256) ? __outwc((i586mso),(ioaddr+0x0004)) : __outw((i586mso ),(ioaddr+0x0004))); | |||
757 | old_a0 = inw(ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __inwc(ioaddr) : __inw(ioaddr)); | |||
758 | outw(i586mso,ioaddr+WRITE_PTR)((__builtin_constant_p((ioaddr+0x0002)) && (ioaddr+0x0002 ) < 256) ? __outwc((i586mso),(ioaddr+0x0002)) : __outw((i586mso ),(ioaddr+0x0002))); | |||
759 | outw(0x55aa,ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __outwc((0x55aa),(ioaddr)) : __outw((0x55aa),(ioaddr))); | |||
760 | outw(i586mso,ioaddr+READ_PTR)((__builtin_constant_p((ioaddr+0x0004)) && (ioaddr+0x0004 ) < 256) ? __outwc((i586mso),(ioaddr+0x0004)) : __outw((i586mso ),(ioaddr+0x0004))); | |||
761 | a0_0 = inw(ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __inwc(ioaddr) : __inw(ioaddr)); | |||
762 | outw(0x8000+i586mso,ioaddr+WRITE_PTR)((__builtin_constant_p((ioaddr+0x0002)) && (ioaddr+0x0002 ) < 256) ? __outwc((0x8000 +i586mso),(ioaddr+0x0002)) : __outw ((0x8000 +i586mso),(ioaddr+0x0002))); | |||
763 | outw(0x5a5a,ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __outwc((0x5a5a),(ioaddr)) : __outw((0x5a5a),(ioaddr))); | |||
764 | outw(0x8000+i586mso,ioaddr+READ_PTR)((__builtin_constant_p((ioaddr+0x0004)) && (ioaddr+0x0004 ) < 256) ? __outwc((0x8000 +i586mso),(ioaddr+0x0004)) : __outw ((0x8000 +i586mso),(ioaddr+0x0004))); | |||
765 | a1_0 = inw(ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __inwc(ioaddr) : __inw(ioaddr)); | |||
766 | outw(i586mso,ioaddr+READ_PTR)((__builtin_constant_p((ioaddr+0x0004)) && (ioaddr+0x0004 ) < 256) ? __outwc((i586mso),(ioaddr+0x0004)) : __outw((i586mso ),(ioaddr+0x0004))); | |||
767 | a0_1 = inw(ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __inwc(ioaddr) : __inw(ioaddr)); | |||
768 | outw(i586mso,ioaddr+WRITE_PTR)((__builtin_constant_p((ioaddr+0x0002)) && (ioaddr+0x0002 ) < 256) ? __outwc((i586mso),(ioaddr+0x0002)) : __outw((i586mso ),(ioaddr+0x0002))); | |||
769 | outw(0x1234,ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __outwc((0x1234),(ioaddr)) : __outw((0x1234),(ioaddr))); | |||
770 | outw(0x8000+i586mso,ioaddr+READ_PTR)((__builtin_constant_p((ioaddr+0x0004)) && (ioaddr+0x0004 ) < 256) ? __outwc((0x8000 +i586mso),(ioaddr+0x0004)) : __outw ((0x8000 +i586mso),(ioaddr+0x0004))); | |||
771 | a1_1 = inw(ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __inwc(ioaddr) : __inw(ioaddr)); | |||
772 | ||||
773 | if ((a0_0 != a0_1) || (a1_0 != a1_1) || | |||
774 | (a1_0 != 0x5a5a) || (a0_0 != 0x55aa)) | |||
775 | { | |||
776 | printk("32k\n"); | |||
777 | PRIV(dev)((struct net_local *)(dev)->priv)->rx_buf_end = 0x7ff6; | |||
778 | PRIV(dev)((struct net_local *)(dev)->priv)->num_tx_bufs = 4; | |||
779 | } | |||
780 | else | |||
781 | { | |||
782 | printk("64k\n"); | |||
783 | PRIV(dev)((struct net_local *)(dev)->priv)->num_tx_bufs = 8; | |||
784 | PRIV(dev)((struct net_local *)(dev)->priv)->rx_buf_start = TX_BUF_START0x0100 + (PRIV(dev)((struct net_local *)(dev)->priv)->num_tx_bufs*TX_BUF_SIZE((24 +1514 +31)&~0x1f)); | |||
785 | PRIV(dev)((struct net_local *)(dev)->priv)->rx_buf_end = 0xfff6; | |||
786 | } | |||
787 | ||||
788 | outw(0x8000+i586mso,ioaddr+WRITE_PTR)((__builtin_constant_p((ioaddr+0x0002)) && (ioaddr+0x0002 ) < 256) ? __outwc((0x8000 +i586mso),(ioaddr+0x0002)) : __outw ((0x8000 +i586mso),(ioaddr+0x0002))); | |||
789 | outw(old_a1,ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __outwc((old_a1),(ioaddr)) : __outw((old_a1),(ioaddr))); | |||
790 | outw(i586mso,ioaddr+WRITE_PTR)((__builtin_constant_p((ioaddr+0x0002)) && (ioaddr+0x0002 ) < 256) ? __outwc((i586mso),(ioaddr+0x0002)) : __outw((i586mso ),(ioaddr+0x0002))); | |||
791 | outw(old_a0,ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __outwc((old_a0),(ioaddr)) : __outw((old_a0),(ioaddr))); | |||
792 | outw(old_wp,ioaddr+WRITE_PTR)((__builtin_constant_p((ioaddr+0x0002)) && (ioaddr+0x0002 ) < 256) ? __outwc((old_wp),(ioaddr+0x0002)) : __outw((old_wp ),(ioaddr+0x0002))); | |||
793 | outw(old_rp,ioaddr+READ_PTR)((__builtin_constant_p((ioaddr+0x0004)) && (ioaddr+0x0004 ) < 256) ? __outwc((old_rp),(ioaddr+0x0004)) : __outw((old_rp ),(ioaddr+0x0004))); | |||
794 | } | |||
795 | ||||
796 | if (net_debug) | |||
797 | printk(version); | |||
798 | dev->open = eexp_open; | |||
799 | dev->stop = eexp_close; | |||
800 | dev->hard_start_xmit = eexp_xmit; | |||
801 | dev->get_stats = eexp_stats; | |||
802 | dev->set_multicast_list = &eexp_set_multicast; | |||
803 | ether_setup(dev); | |||
804 | return 0; | |||
805 | } | |||
806 | ||||
807 | /* | |||
808 | * Read a word from eeprom location (0-63?) | |||
809 | */ | |||
810 | static unsigned short eexp_hw_readeeprom(unsigned short ioaddr, unsigned char location) | |||
811 | { | |||
812 | unsigned short cmd = 0x180|(location&0x7f); | |||
813 | unsigned short rval = 0,wval = EC_CS0x02|i586_RST0x80; | |||
814 | int i; | |||
815 | ||||
816 | outb(EC_CS|i586_RST,ioaddr+EEPROM_Ctrl)((__builtin_constant_p((ioaddr+0x000e)) && (ioaddr+0x000e ) < 256) ? __outbc((0x02|0x80),(ioaddr+0x000e)) : __outb(( 0x02|0x80),(ioaddr+0x000e))); | |||
817 | for ( i=0x100 ; i ; i>>=1 ) | |||
818 | { | |||
819 | if (cmd&i) | |||
820 | wval |= EC_Wr0x04; | |||
821 | else | |||
822 | wval &= ~EC_Wr0x04; | |||
823 | ||||
824 | outb(wval,ioaddr+EEPROM_Ctrl)((__builtin_constant_p((ioaddr+0x000e)) && (ioaddr+0x000e ) < 256) ? __outbc((wval),(ioaddr+0x000e)) : __outb((wval) ,(ioaddr+0x000e))); | |||
825 | outb(wval|EC_Clk,ioaddr+EEPROM_Ctrl)((__builtin_constant_p((ioaddr+0x000e)) && (ioaddr+0x000e ) < 256) ? __outbc((wval|0x01),(ioaddr+0x000e)) : __outb(( wval|0x01),(ioaddr+0x000e))); | |||
826 | eeprom_delay(){ int _i = 40; while (--_i>0) { __asm__ __volatile__("outb %al,$0x80" ); }}; | |||
827 | outb(wval,ioaddr+EEPROM_Ctrl)((__builtin_constant_p((ioaddr+0x000e)) && (ioaddr+0x000e ) < 256) ? __outbc((wval),(ioaddr+0x000e)) : __outb((wval) ,(ioaddr+0x000e))); | |||
828 | eeprom_delay(){ int _i = 40; while (--_i>0) { __asm__ __volatile__("outb %al,$0x80" ); }}; | |||
829 | } | |||
830 | wval &= ~EC_Wr0x04; | |||
831 | outb(wval,ioaddr+EEPROM_Ctrl)((__builtin_constant_p((ioaddr+0x000e)) && (ioaddr+0x000e ) < 256) ? __outbc((wval),(ioaddr+0x000e)) : __outb((wval) ,(ioaddr+0x000e))); | |||
832 | for ( i=0x8000 ; i ; i>>=1 ) | |||
833 | { | |||
834 | outb(wval|EC_Clk,ioaddr+EEPROM_Ctrl)((__builtin_constant_p((ioaddr+0x000e)) && (ioaddr+0x000e ) < 256) ? __outbc((wval|0x01),(ioaddr+0x000e)) : __outb(( wval|0x01),(ioaddr+0x000e))); | |||
835 | eeprom_delay(){ int _i = 40; while (--_i>0) { __asm__ __volatile__("outb %al,$0x80" ); }}; | |||
836 | if (inb(ioaddr+EEPROM_Ctrl)((__builtin_constant_p((ioaddr+0x000e)) && (ioaddr+0x000e ) < 256) ? __inbc(ioaddr+0x000e) : __inb(ioaddr+0x000e))&EC_Rd0x08) | |||
837 | rval |= i; | |||
838 | outb(wval,ioaddr+EEPROM_Ctrl)((__builtin_constant_p((ioaddr+0x000e)) && (ioaddr+0x000e ) < 256) ? __outbc((wval),(ioaddr+0x000e)) : __outb((wval) ,(ioaddr+0x000e))); | |||
839 | eeprom_delay(){ int _i = 40; while (--_i>0) { __asm__ __volatile__("outb %al,$0x80" ); }}; | |||
840 | } | |||
841 | wval &= ~EC_CS0x02; | |||
842 | outb(wval|EC_Clk,ioaddr+EEPROM_Ctrl)((__builtin_constant_p((ioaddr+0x000e)) && (ioaddr+0x000e ) < 256) ? __outbc((wval|0x01),(ioaddr+0x000e)) : __outb(( wval|0x01),(ioaddr+0x000e))); | |||
843 | eeprom_delay(){ int _i = 40; while (--_i>0) { __asm__ __volatile__("outb %al,$0x80" ); }}; | |||
844 | outb(wval,ioaddr+EEPROM_Ctrl)((__builtin_constant_p((ioaddr+0x000e)) && (ioaddr+0x000e ) < 256) ? __outbc((wval),(ioaddr+0x000e)) : __outb((wval) ,(ioaddr+0x000e))); | |||
845 | eeprom_delay(){ int _i = 40; while (--_i>0) { __asm__ __volatile__("outb %al,$0x80" ); }}; | |||
846 | return rval; | |||
847 | } | |||
848 | ||||
849 | /* | |||
850 | * Reap tx buffers and return last transmit status. | |||
851 | * if ==0 then either: | |||
852 | * a) we're not transmitting anything, so why are we here? | |||
853 | * b) we've died. | |||
854 | * otherwise, Stat_Busy(return) means we've still got some packets | |||
855 | * to transmit, Stat_Done(return) means our buffers should be empty | |||
856 | * again | |||
857 | */ | |||
858 | ||||
859 | static unsigned short eexp_hw_lasttxstat(struct devicelinux_device *dev) | |||
860 | { | |||
861 | struct net_local *lp = (struct net_local *)dev->priv; | |||
862 | unsigned short ioaddr = dev->base_addr; | |||
863 | unsigned short old_rp = inw(ioaddr+READ_PTR)((__builtin_constant_p((ioaddr+0x0004)) && (ioaddr+0x0004 ) < 256) ? __inwc(ioaddr+0x0004) : __inw(ioaddr+0x0004)); | |||
864 | unsigned short old_wp = inw(ioaddr+WRITE_PTR)((__builtin_constant_p((ioaddr+0x0002)) && (ioaddr+0x0002 ) < 256) ? __inwc(ioaddr+0x0002) : __inw(ioaddr+0x0002)); | |||
865 | unsigned short tx_block = lp->tx_reap; | |||
866 | unsigned short status; | |||
867 | ||||
868 | if (!test_bit(0,(void *)&dev->tbusy) && lp->tx_head==lp->tx_reap) | |||
869 | return 0x0000; | |||
870 | ||||
871 | do | |||
872 | { | |||
873 | outw(tx_block,ioaddr+READ_PTR)((__builtin_constant_p((ioaddr+0x0004)) && (ioaddr+0x0004 ) < 256) ? __outwc((tx_block),(ioaddr+0x0004)) : __outw((tx_block ),(ioaddr+0x0004))); | |||
874 | status = inw(ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __inwc(ioaddr) : __inw(ioaddr)); | |||
875 | if (!Stat_Done(status)((status&0x8000)!=0)) | |||
876 | { | |||
877 | lp->tx_link = tx_block; | |||
878 | outw(old_rp,ioaddr+READ_PTR)((__builtin_constant_p((ioaddr+0x0004)) && (ioaddr+0x0004 ) < 256) ? __outwc((old_rp),(ioaddr+0x0004)) : __outw((old_rp ),(ioaddr+0x0004))); | |||
879 | outw(old_wp,ioaddr+WRITE_PTR)((__builtin_constant_p((ioaddr+0x0002)) && (ioaddr+0x0002 ) < 256) ? __outwc((old_wp),(ioaddr+0x0002)) : __outw((old_wp ),(ioaddr+0x0002))); | |||
880 | return status; | |||
881 | } | |||
882 | else | |||
883 | { | |||
884 | lp->last_tx_restart = 0; | |||
885 | lp->stats.collisions += Stat_NoColl(status)(status&0x000f); | |||
886 | if (!Stat_OK(status)((status&0x2000)!=0)) | |||
887 | { | |||
888 | if (Stat_Abort(status)((status&0x1000)!=0)) | |||
889 | lp->stats.tx_aborted_errors++; | |||
890 | if (Stat_TNoCar(status)((status&0x0400)!=0) || Stat_TNoCTS(status)((status&0x0200)!=0)) | |||
891 | lp->stats.tx_carrier_errors++; | |||
892 | if (Stat_TNoDMA(status)((status&0x0100)!=0)) | |||
893 | lp->stats.tx_fifo_errors++; | |||
894 | } | |||
895 | else | |||
896 | lp->stats.tx_packets++; | |||
897 | } | |||
898 | if (tx_block == TX_BUF_START0x0100+((lp->num_tx_bufs-1)*TX_BUF_SIZE((24 +1514 +31)&~0x1f))) | |||
899 | lp->tx_reap = tx_block = TX_BUF_START0x0100; | |||
900 | else | |||
901 | lp->tx_reap = tx_block += TX_BUF_SIZE((24 +1514 +31)&~0x1f); | |||
902 | dev->tbusy = 0; | |||
903 | mark_bh(NET_BH); | |||
904 | } | |||
905 | while (lp->tx_reap != lp->tx_head); | |||
906 | ||||
907 | lp->tx_link = lp->tx_tail + 0x08; | |||
908 | outw(old_rp,ioaddr+READ_PTR)((__builtin_constant_p((ioaddr+0x0004)) && (ioaddr+0x0004 ) < 256) ? __outwc((old_rp),(ioaddr+0x0004)) : __outw((old_rp ),(ioaddr+0x0004))); | |||
909 | outw(old_wp,ioaddr+WRITE_PTR)((__builtin_constant_p((ioaddr+0x0002)) && (ioaddr+0x0002 ) < 256) ? __outwc((old_wp),(ioaddr+0x0002)) : __outw((old_wp ),(ioaddr+0x0002))); | |||
910 | ||||
911 | return status; | |||
912 | } | |||
913 | ||||
914 | /* | |||
915 | * This should never happen. It is called when some higher | |||
916 | * routine detects the CU has stopped, to try to restart | |||
917 | * it from the last packet we knew we were working on, | |||
918 | * or the idle loop if we had finished for the time. | |||
919 | */ | |||
920 | ||||
921 | static void eexp_hw_txrestart(struct devicelinux_device *dev) | |||
922 | { | |||
923 | struct net_local *lp = (struct net_local *)dev->priv; | |||
924 | unsigned short ioaddr = dev->base_addr; | |||
925 | ||||
926 | lp->last_tx_restart = lp->tx_link; | |||
927 | outw(lp->tx_link,ioaddr+SCB_CBL)((__builtin_constant_p((ioaddr+0xc00c)) && (ioaddr+0xc00c ) < 256) ? __outwc((lp->tx_link),(ioaddr+0xc00c)) : __outw ((lp->tx_link),(ioaddr+0xc00c))); | |||
928 | outw(SCB_CUstart,ioaddr+SCB_CMD)((__builtin_constant_p((ioaddr+0xc00a)) && (ioaddr+0xc00a ) < 256) ? __outwc((0x0100),(ioaddr+0xc00a)) : __outw((0x0100 ),(ioaddr+0xc00a))); | |||
929 | outw(0,ioaddr+SCB_STATUS)((__builtin_constant_p((ioaddr+0xc008)) && (ioaddr+0xc008 ) < 256) ? __outwc((0),(ioaddr+0xc008)) : __outw((0),(ioaddr +0xc008))); | |||
930 | outb(0,ioaddr+SIGNAL_CA)((__builtin_constant_p((ioaddr+0x0006)) && (ioaddr+0x0006 ) < 256) ? __outbc((0),(ioaddr+0x0006)) : __outb((0),(ioaddr +0x0006))); | |||
931 | ||||
932 | { | |||
933 | unsigned short boguscount=50,failcount=5; | |||
934 | while (!inw(ioaddr+SCB_STATUS)((__builtin_constant_p((ioaddr+0xc008)) && (ioaddr+0xc008 ) < 256) ? __inwc(ioaddr+0xc008) : __inw(ioaddr+0xc008))) | |||
935 | { | |||
936 | if (!--boguscount) | |||
937 | { | |||
938 | if (--failcount) | |||
939 | { | |||
940 | printk(KERN_WARNING"<4>" "%s: CU start timed out, status %04x, cmd %04x\n", | |||
941 | dev->name, inw(ioaddr+SCB_STATUS)((__builtin_constant_p((ioaddr+0xc008)) && (ioaddr+0xc008 ) < 256) ? __inwc(ioaddr+0xc008) : __inw(ioaddr+0xc008)), inw(ioaddr+SCB_CMD)((__builtin_constant_p((ioaddr+0xc00a)) && (ioaddr+0xc00a ) < 256) ? __inwc(ioaddr+0xc00a) : __inw(ioaddr+0xc00a))); | |||
942 | outw(lp->tx_link,ioaddr+SCB_CBL)((__builtin_constant_p((ioaddr+0xc00c)) && (ioaddr+0xc00c ) < 256) ? __outwc((lp->tx_link),(ioaddr+0xc00c)) : __outw ((lp->tx_link),(ioaddr+0xc00c))); | |||
943 | outw(0,ioaddr+SCB_STATUS)((__builtin_constant_p((ioaddr+0xc008)) && (ioaddr+0xc008 ) < 256) ? __outwc((0),(ioaddr+0xc008)) : __outw((0),(ioaddr +0xc008))); | |||
944 | outw(SCB_CUstart,ioaddr+SCB_CMD)((__builtin_constant_p((ioaddr+0xc00a)) && (ioaddr+0xc00a ) < 256) ? __outwc((0x0100),(ioaddr+0xc00a)) : __outw((0x0100 ),(ioaddr+0xc00a))); | |||
945 | outb(0,ioaddr+SIGNAL_CA)((__builtin_constant_p((ioaddr+0x0006)) && (ioaddr+0x0006 ) < 256) ? __outbc((0),(ioaddr+0x0006)) : __outb((0),(ioaddr +0x0006))); | |||
946 | boguscount = 100; | |||
947 | } | |||
948 | else | |||
949 | { | |||
950 | printk(KERN_WARNING"<4>" "%s: Failed to restart CU, resetting board...\n",dev->name); | |||
951 | eexp_hw_init586(dev); | |||
952 | dev->tbusy = 0; | |||
953 | mark_bh(NET_BH); | |||
954 | return; | |||
955 | } | |||
956 | } | |||
957 | } | |||
958 | } | |||
959 | } | |||
960 | ||||
961 | /* | |||
962 | * Writes down the list of transmit buffers into card | |||
963 | * memory. Initial separate, repeated transmits link | |||
964 | * them into a circular list, such that the CU can | |||
965 | * be constantly active, and unlink them as we reap | |||
966 | * transmitted packet buffers, so the CU doesn't loop | |||
967 | * and endlessly transmit packets. (Try hacking the driver | |||
968 | * to send continuous broadcast messages, say ARP requests | |||
969 | * on a subnet with Windows boxes running on Novell and | |||
970 | * LAN Workplace with EMM386. Amusing to watch them all die | |||
971 | * horribly leaving the Linux boxes up!) | |||
972 | */ | |||
973 | ||||
974 | static void eexp_hw_txinit(struct devicelinux_device *dev) | |||
975 | { | |||
976 | struct net_local *lp = (struct net_local *)dev->priv; | |||
977 | unsigned short ioaddr = dev->base_addr; | |||
978 | unsigned short old_wp = inw(ioaddr+WRITE_PTR)((__builtin_constant_p((ioaddr+0x0002)) && (ioaddr+0x0002 ) < 256) ? __inwc(ioaddr+0x0002) : __inw(ioaddr+0x0002)); | |||
979 | unsigned short tx_block = TX_BUF_START0x0100; | |||
980 | unsigned short curtbuf; | |||
981 | ||||
982 | for ( curtbuf=0 ; curtbuf<lp->num_tx_bufs ; curtbuf++ ) | |||
983 | { | |||
984 | outw(tx_block,ioaddr+WRITE_PTR)((__builtin_constant_p((ioaddr+0x0002)) && (ioaddr+0x0002 ) < 256) ? __outwc((tx_block),(ioaddr+0x0002)) : __outw((tx_block ),(ioaddr+0x0002))); | |||
985 | outw(0x0000,ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __outwc((0x0000),(ioaddr)) : __outw((0x0000),(ioaddr))); | |||
986 | outw(Cmd_INT|Cmd_Xmit,ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __outwc((0x2000|0x0004),(ioaddr)) : __outw((0x2000|0x0004 ),(ioaddr))); | |||
987 | outw(tx_block+0x08,ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __outwc((tx_block+0x08),(ioaddr)) : __outw((tx_block+0x08 ),(ioaddr))); | |||
988 | outw(tx_block+0x0e,ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __outwc((tx_block+0x0e),(ioaddr)) : __outw((tx_block+0x0e ),(ioaddr))); | |||
989 | outw(0x0000,ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __outwc((0x0000),(ioaddr)) : __outw((0x0000),(ioaddr))); | |||
990 | outw(0x0000,ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __outwc((0x0000),(ioaddr)) : __outw((0x0000),(ioaddr))); | |||
991 | outw(tx_block+0x08,ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __outwc((tx_block+0x08),(ioaddr)) : __outw((tx_block+0x08 ),(ioaddr))); | |||
992 | outw(0x8000,ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __outwc((0x8000),(ioaddr)) : __outw((0x8000),(ioaddr))); | |||
993 | outw(-1,ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __outwc((-1),(ioaddr)) : __outw((-1),(ioaddr))); | |||
994 | outw(tx_block+0x16,ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __outwc((tx_block+0x16),(ioaddr)) : __outw((tx_block+0x16 ),(ioaddr))); | |||
995 | outw(0x0000,ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __outwc((0x0000),(ioaddr)) : __outw((0x0000),(ioaddr))); | |||
996 | tx_block += TX_BUF_SIZE((24 +1514 +31)&~0x1f); | |||
997 | } | |||
998 | lp->tx_head = TX_BUF_START0x0100; | |||
999 | lp->tx_reap = TX_BUF_START0x0100; | |||
1000 | lp->tx_tail = tx_block - TX_BUF_SIZE((24 +1514 +31)&~0x1f); | |||
1001 | lp->tx_link = lp->tx_tail + 0x08; | |||
1002 | lp->rx_buf_start = tx_block; | |||
1003 | outw(old_wp,ioaddr+WRITE_PTR)((__builtin_constant_p((ioaddr+0x0002)) && (ioaddr+0x0002 ) < 256) ? __outwc((old_wp),(ioaddr+0x0002)) : __outw((old_wp ),(ioaddr+0x0002))); | |||
1004 | } | |||
1005 | ||||
1006 | /* is this a standard test pattern, or dbecker randomness? */ | |||
1007 | ||||
1008 | unsigned short rx_words[] = | |||
1009 | { | |||
1010 | 0xfeed,0xf00d,0xf001,0x0505,0x2424,0x6565,0xdeaf | |||
1011 | }; | |||
1012 | ||||
1013 | /* | |||
1014 | * Write the circular list of receive buffer descriptors to | |||
1015 | * card memory. Note, we no longer mark the end of the list, | |||
1016 | * so if all the buffers fill up, the 82586 will loop until | |||
1017 | * we free one. This may sound dodgy, but it works, and | |||
1018 | * it makes the error detection in the interrupt handler | |||
1019 | * a lot simpler. | |||
1020 | */ | |||
1021 | ||||
1022 | static void eexp_hw_rxinit(struct devicelinux_device *dev) | |||
1023 | { | |||
1024 | struct net_local *lp = (struct net_local *)dev->priv; | |||
1025 | unsigned short ioaddr = dev->base_addr; | |||
1026 | unsigned short old_wp = inw(ioaddr+WRITE_PTR)((__builtin_constant_p((ioaddr+0x0002)) && (ioaddr+0x0002 ) < 256) ? __inwc(ioaddr+0x0002) : __inw(ioaddr+0x0002)); | |||
1027 | unsigned short rx_block = lp->rx_buf_start; | |||
1028 | ||||
1029 | lp->num_rx_bufs = 0; | |||
1030 | lp->rx_first = rx_block; | |||
1031 | do | |||
1032 | { | |||
1033 | lp->num_rx_bufs++; | |||
1034 | outw(rx_block,ioaddr+WRITE_PTR)((__builtin_constant_p((ioaddr+0x0002)) && (ioaddr+0x0002 ) < 256) ? __outwc((rx_block),(ioaddr+0x0002)) : __outw((rx_block ),(ioaddr+0x0002))); | |||
1035 | outw(0x0000,ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __outwc((0x0000),(ioaddr)) : __outw((0x0000),(ioaddr))); | |||
1036 | outw(0x0000,ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __outwc((0x0000),(ioaddr)) : __outw((0x0000),(ioaddr))); | |||
1037 | outw(rx_block+RX_BUF_SIZE,ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __outwc((rx_block+((32 +1514 +31)&~0x1f)),(ioaddr)) : __outw((rx_block+((32 +1514 +31)&~0x1f)),(ioaddr))); | |||
1038 | outw(rx_block+0x16,ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __outwc((rx_block+0x16),(ioaddr)) : __outw((rx_block+0x16 ),(ioaddr))); | |||
1039 | outsw(ioaddr, rx_words, sizeof(rx_words)>>1); | |||
1040 | outw(0x8000,ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __outwc((0x8000),(ioaddr)) : __outw((0x8000),(ioaddr))); | |||
1041 | outw(-1,ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __outwc((-1),(ioaddr)) : __outw((-1),(ioaddr))); | |||
1042 | outw(rx_block+0x20,ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __outwc((rx_block+0x20),(ioaddr)) : __outw((rx_block+0x20 ),(ioaddr))); | |||
1043 | outw(0x0000,ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __outwc((0x0000),(ioaddr)) : __outw((0x0000),(ioaddr))); | |||
1044 | outw(0x8000|(RX_BUF_SIZE-0x20),ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __outwc((0x8000|(((32 +1514 +31)&~0x1f)-0x20)),(ioaddr )) : __outw((0x8000|(((32 +1514 +31)&~0x1f)-0x20)),(ioaddr ))); | |||
1045 | lp->rx_last = rx_block; | |||
1046 | rx_block += RX_BUF_SIZE((32 +1514 +31)&~0x1f); | |||
1047 | } while (rx_block <= lp->rx_buf_end-RX_BUF_SIZE((32 +1514 +31)&~0x1f)); | |||
1048 | ||||
1049 | outw(lp->rx_last+4,ioaddr+WRITE_PTR)((__builtin_constant_p((ioaddr+0x0002)) && (ioaddr+0x0002 ) < 256) ? __outwc((lp->rx_last+4),(ioaddr+0x0002)) : __outw ((lp->rx_last+4),(ioaddr+0x0002))); | |||
1050 | outw(lp->rx_first,ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __outwc((lp->rx_first),(ioaddr)) : __outw((lp->rx_first ),(ioaddr))); | |||
1051 | ||||
1052 | outw(old_wp,ioaddr+WRITE_PTR)((__builtin_constant_p((ioaddr+0x0002)) && (ioaddr+0x0002 ) < 256) ? __outwc((old_wp),(ioaddr+0x0002)) : __outw((old_wp ),(ioaddr+0x0002))); | |||
1053 | } | |||
1054 | ||||
1055 | /* | |||
1056 | * Reset the 586, fill memory (including calls to | |||
1057 | * eexp_hw_[(rx)(tx)]init()) unreset, and start | |||
1058 | * the configuration sequence. We don't wait for this | |||
1059 | * to finish, but allow the interrupt handler to start | |||
1060 | * the CU and RU for us. We can't start the receive/ | |||
1061 | * transmission system up before we know that the | |||
1062 | * hardware is configured correctly | |||
1063 | */ | |||
1064 | static void eexp_hw_init586(struct devicelinux_device *dev) | |||
1065 | { | |||
1066 | struct net_local *lp = (struct net_local *)dev->priv; | |||
1067 | unsigned short ioaddr = dev->base_addr; | |||
1068 | ||||
1069 | #if NET_DEBUG4 > 6 | |||
1070 | printk("%s: eexp_hw_init586()\n", dev->name); | |||
1071 | #endif | |||
1072 | ||||
1073 | lp->started = 0; | |||
1074 | set_loopback((__builtin_constant_p((ioaddr+0x000d)) && (ioaddr+0x000d ) < 256) ? __outbc((((__builtin_constant_p((ioaddr+0x000d) ) && (ioaddr+0x000d) < 256) ? __inbc(ioaddr+0x000d ) : __inb(ioaddr+0x000d))|0x02),(ioaddr+0x000d)) : __outb(((( __builtin_constant_p((ioaddr+0x000d)) && (ioaddr+0x000d ) < 256) ? __inbc(ioaddr+0x000d) : __inb(ioaddr+0x000d))|0x02 ),(ioaddr+0x000d))); | |||
1075 | ||||
1076 | outb(SIRQ_dis|irqrmap[dev->irq],ioaddr+SET_IRQ)((__builtin_constant_p((ioaddr+0x0007)) && (ioaddr+0x0007 ) < 256) ? __outbc((0x00|irqrmap[dev->irq]),(ioaddr+0x0007 )) : __outb((0x00|irqrmap[dev->irq]),(ioaddr+0x0007))); | |||
1077 | outb_p(i586_RST,ioaddr+EEPROM_Ctrl)((__builtin_constant_p((ioaddr+0x000e)) && (ioaddr+0x000e ) < 256) ? __outbc_p((0x80),(ioaddr+0x000e)) : __outb_p((0x80 ),(ioaddr+0x000e))); | |||
1078 | udelay(2000)(__builtin_constant_p(2000) ? __const_udelay((2000) * 0x10c6ul ) : __udelay(2000)); /* delay 20ms */ | |||
1079 | { | |||
1080 | unsigned long ofs; | |||
1081 | for (ofs = 0; ofs < lp->rx_buf_end; ofs += 32) { | |||
1082 | unsigned long i; | |||
1083 | outw_p(ofs, ioaddr+SM_PTR)((__builtin_constant_p((ioaddr+0x0008)) && (ioaddr+0x0008 ) < 256) ? __outwc_p((ofs),(ioaddr+0x0008)) : __outw_p((ofs ),(ioaddr+0x0008))); | |||
1084 | for (i = 0; i < 16; i++) { | |||
1085 | outw_p(0, ioaddr+SM_ADDR(i<<1))((__builtin_constant_p((ioaddr+(0x4000 +((i<<1&0x10 )<<10)+(i<<1&0xf)))) && (ioaddr+(0x4000 +((i<<1&0x10)<<10)+(i<<1&0xf))) < 256) ? __outwc_p((0),(ioaddr+(0x4000 +((i<<1&0x10) <<10)+(i<<1&0xf)))) : __outw_p((0),(ioaddr+(0x4000 +((i<<1&0x10)<<10)+(i<<1&0xf))))); | |||
1086 | } | |||
1087 | } | |||
1088 | } | |||
1089 | ||||
1090 | outw_p(lp->rx_buf_end,ioaddr+WRITE_PTR)((__builtin_constant_p((ioaddr+0x0002)) && (ioaddr+0x0002 ) < 256) ? __outwc_p((lp->rx_buf_end),(ioaddr+0x0002)) : __outw_p((lp->rx_buf_end),(ioaddr+0x0002))); | |||
1091 | start_code[28] = (dev->flags & IFF_PROMISC0x100)?(start_code[28] | 1):(start_code[28] & ~1); | |||
1092 | lp->promisc = dev->flags & IFF_PROMISC0x100; | |||
1093 | /* We may die here */ | |||
1094 | outsw(ioaddr, start_code, sizeof(start_code)>>1); | |||
1095 | outw(CONF_HW_ADDR,ioaddr+WRITE_PTR)((__builtin_constant_p((ioaddr+0x0002)) && (ioaddr+0x0002 ) < 256) ? __outwc((0x0038),(ioaddr+0x0002)) : __outw((0x0038 ),(ioaddr+0x0002))); | |||
1096 | outsw(ioaddr,dev->dev_addr,3); | |||
1097 | eexp_hw_txinit(dev); | |||
1098 | eexp_hw_rxinit(dev); | |||
1099 | outw(0,ioaddr+WRITE_PTR)((__builtin_constant_p((ioaddr+0x0002)) && (ioaddr+0x0002 ) < 256) ? __outwc((0),(ioaddr+0x0002)) : __outw((0),(ioaddr +0x0002))); | |||
1100 | outw(1,ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __outwc((1),(ioaddr)) : __outw((1),(ioaddr))); | |||
1101 | outb(0,ioaddr+EEPROM_Ctrl)((__builtin_constant_p((ioaddr+0x000e)) && (ioaddr+0x000e ) < 256) ? __outbc((0),(ioaddr+0x000e)) : __outb((0),(ioaddr +0x000e))); | |||
1102 | outw(0,ioaddr+SCB_CMD)((__builtin_constant_p((ioaddr+0xc00a)) && (ioaddr+0xc00a ) < 256) ? __outwc((0),(ioaddr+0xc00a)) : __outw((0),(ioaddr +0xc00a))); | |||
1103 | outb(0,ioaddr+SIGNAL_CA)((__builtin_constant_p((ioaddr+0x0006)) && (ioaddr+0x0006 ) < 256) ? __outbc((0),(ioaddr+0x0006)) : __outb((0),(ioaddr +0x0006))); | |||
1104 | { | |||
1105 | unsigned short rboguscount=50,rfailcount=5; | |||
1106 | while (outw(0,ioaddr+READ_PTR)((__builtin_constant_p((ioaddr+0x0004)) && (ioaddr+0x0004 ) < 256) ? __outwc((0),(ioaddr+0x0004)) : __outw((0),(ioaddr +0x0004))),inw(ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __inwc(ioaddr) : __inw(ioaddr))) | |||
1107 | { | |||
1108 | if (!--rboguscount) | |||
1109 | { | |||
1110 | printk(KERN_WARNING"<4>" "%s: i82586 reset timed out, kicking...\n", | |||
1111 | dev->name); | |||
1112 | outw(0,ioaddr+SCB_CMD)((__builtin_constant_p((ioaddr+0xc00a)) && (ioaddr+0xc00a ) < 256) ? __outwc((0),(ioaddr+0xc00a)) : __outw((0),(ioaddr +0xc00a))); | |||
1113 | outb(0,ioaddr+SIGNAL_CA)((__builtin_constant_p((ioaddr+0x0006)) && (ioaddr+0x0006 ) < 256) ? __outbc((0),(ioaddr+0x0006)) : __outb((0),(ioaddr +0x0006))); | |||
1114 | rboguscount = 100; | |||
1115 | if (!--rfailcount) | |||
1116 | { | |||
1117 | printk(KERN_WARNING"<4>" "%s: i82586 not responding, giving up.\n", | |||
1118 | dev->name); | |||
1119 | return; | |||
1120 | } | |||
1121 | } | |||
1122 | } | |||
1123 | } | |||
1124 | ||||
1125 | outw(CONF_LINK,ioaddr+SCB_CBL)((__builtin_constant_p((ioaddr+0xc00c)) && (ioaddr+0xc00c ) < 256) ? __outwc((0x0020),(ioaddr+0xc00c)) : __outw((0x0020 ),(ioaddr+0xc00c))); | |||
1126 | outw(0,ioaddr+SCB_STATUS)((__builtin_constant_p((ioaddr+0xc008)) && (ioaddr+0xc008 ) < 256) ? __outwc((0),(ioaddr+0xc008)) : __outw((0),(ioaddr +0xc008))); | |||
1127 | outw(0xf000|SCB_CUstart,ioaddr+SCB_CMD)((__builtin_constant_p((ioaddr+0xc00a)) && (ioaddr+0xc00a ) < 256) ? __outwc((0xf000|0x0100),(ioaddr+0xc00a)) : __outw ((0xf000|0x0100),(ioaddr+0xc00a))); | |||
1128 | outb(0,ioaddr+SIGNAL_CA)((__builtin_constant_p((ioaddr+0x0006)) && (ioaddr+0x0006 ) < 256) ? __outbc((0),(ioaddr+0x0006)) : __outb((0),(ioaddr +0x0006))); | |||
1129 | { | |||
1130 | unsigned short iboguscount=50,ifailcount=5; | |||
1131 | while (!inw(ioaddr+SCB_STATUS)((__builtin_constant_p((ioaddr+0xc008)) && (ioaddr+0xc008 ) < 256) ? __inwc(ioaddr+0xc008) : __inw(ioaddr+0xc008))) | |||
1132 | { | |||
1133 | if (!--iboguscount) | |||
1134 | { | |||
1135 | if (--ifailcount) | |||
1136 | { | |||
1137 | printk(KERN_WARNING"<4>" "%s: i82586 initialization timed out, status %04x, cmd %04x\n", | |||
1138 | dev->name, inw(ioaddr+SCB_STATUS)((__builtin_constant_p((ioaddr+0xc008)) && (ioaddr+0xc008 ) < 256) ? __inwc(ioaddr+0xc008) : __inw(ioaddr+0xc008)), inw(ioaddr+SCB_CMD)((__builtin_constant_p((ioaddr+0xc00a)) && (ioaddr+0xc00a ) < 256) ? __inwc(ioaddr+0xc00a) : __inw(ioaddr+0xc00a))); | |||
1139 | outw(CONF_LINK,ioaddr+SCB_CBL)((__builtin_constant_p((ioaddr+0xc00c)) && (ioaddr+0xc00c ) < 256) ? __outwc((0x0020),(ioaddr+0xc00c)) : __outw((0x0020 ),(ioaddr+0xc00c))); | |||
1140 | outw(0,ioaddr+SCB_STATUS)((__builtin_constant_p((ioaddr+0xc008)) && (ioaddr+0xc008 ) < 256) ? __outwc((0),(ioaddr+0xc008)) : __outw((0),(ioaddr +0xc008))); | |||
1141 | outw(0xf000|SCB_CUstart,ioaddr+SCB_CMD)((__builtin_constant_p((ioaddr+0xc00a)) && (ioaddr+0xc00a ) < 256) ? __outwc((0xf000|0x0100),(ioaddr+0xc00a)) : __outw ((0xf000|0x0100),(ioaddr+0xc00a))); | |||
1142 | outb(0,ioaddr+SIGNAL_CA)((__builtin_constant_p((ioaddr+0x0006)) && (ioaddr+0x0006 ) < 256) ? __outbc((0),(ioaddr+0x0006)) : __outb((0),(ioaddr +0x0006))); | |||
1143 | iboguscount = 100; | |||
1144 | } | |||
1145 | else | |||
1146 | { | |||
1147 | printk(KERN_WARNING"<4>" "%s: Failed to initialize i82586, giving up.\n",dev->name); | |||
1148 | return; | |||
1149 | } | |||
1150 | } | |||
1151 | } | |||
1152 | } | |||
1153 | ||||
1154 | outb(SIRQ_en|irqrmap[dev->irq],ioaddr+SET_IRQ)((__builtin_constant_p((ioaddr+0x0007)) && (ioaddr+0x0007 ) < 256) ? __outbc((0x08|irqrmap[dev->irq]),(ioaddr+0x0007 )) : __outb((0x08|irqrmap[dev->irq]),(ioaddr+0x0007))); | |||
1155 | clear_loopback((__builtin_constant_p((ioaddr+0x000d)) && (ioaddr+0x000d ) < 256) ? __outbc((((__builtin_constant_p((ioaddr+0x000d) ) && (ioaddr+0x000d) < 256) ? __inbc(ioaddr+0x000d ) : __inb(ioaddr+0x000d))&0xfd),(ioaddr+0x000d)) : __outb ((((__builtin_constant_p((ioaddr+0x000d)) && (ioaddr+ 0x000d) < 256) ? __inbc(ioaddr+0x000d) : __inb(ioaddr+0x000d ))&0xfd),(ioaddr+0x000d))); | |||
1156 | lp->init_time = jiffies; | |||
1157 | #if NET_DEBUG4 > 6 | |||
1158 | printk("%s: leaving eexp_hw_init586()\n", dev->name); | |||
1159 | #endif | |||
1160 | return; | |||
1161 | } | |||
1162 | ||||
1163 | /* | |||
1164 | * completely reset the EtherExpress hardware. We will most likely get | |||
1165 | * an interrupt during this whether we want one or not. It is best, | |||
1166 | * therefore, to call this while we don't have a request_irq() on. | |||
1167 | */ | |||
1168 | ||||
1169 | static void eexp_hw_ASICrst(struct devicelinux_device *dev) | |||
1170 | { | |||
1171 | unsigned short ioaddr = dev->base_addr; | |||
1172 | unsigned short wrval = 0x0001,succount=0,boguscount=500; | |||
1173 | ||||
1174 | outb(SIRQ_dis|irqrmap[dev->irq],ioaddr+SET_IRQ)((__builtin_constant_p((ioaddr+0x0007)) && (ioaddr+0x0007 ) < 256) ? __outbc((0x00|irqrmap[dev->irq]),(ioaddr+0x0007 )) : __outb((0x00|irqrmap[dev->irq]),(ioaddr+0x0007))); | |||
1175 | ||||
1176 | PRIV(dev)((struct net_local *)(dev)->priv)->started = 0; | |||
1177 | outb(ASIC_RST|i586_RST,ioaddr+EEPROM_Ctrl)((__builtin_constant_p((ioaddr+0x000e)) && (ioaddr+0x000e ) < 256) ? __outbc((0x40|0x80),(ioaddr+0x000e)) : __outb(( 0x40|0x80),(ioaddr+0x000e))); | |||
1178 | while (succount<20) | |||
1179 | { | |||
1180 | if (wrval == 0xffff) | |||
1181 | wrval = 0x0001; | |||
1182 | outw(0,ioaddr+WRITE_PTR)((__builtin_constant_p((ioaddr+0x0002)) && (ioaddr+0x0002 ) < 256) ? __outwc((0),(ioaddr+0x0002)) : __outw((0),(ioaddr +0x0002))); | |||
1183 | outw(wrval,ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __outwc((wrval),(ioaddr)) : __outw((wrval),(ioaddr))); | |||
1184 | outw(0,ioaddr+READ_PTR)((__builtin_constant_p((ioaddr+0x0004)) && (ioaddr+0x0004 ) < 256) ? __outwc((0),(ioaddr+0x0004)) : __outw((0),(ioaddr +0x0004))); | |||
1185 | if (wrval++ == inw(ioaddr)((__builtin_constant_p((ioaddr)) && (ioaddr) < 256 ) ? __inwc(ioaddr) : __inw(ioaddr))) | |||
1186 | succount++; | |||
1187 | else | |||
1188 | { | |||
1189 | succount = 0; | |||
1190 | if (!boguscount--) | |||
1191 | { | |||
1192 | boguscount = 500; | |||
1193 | printk("%s: Having problems resetting EtherExpress ASIC, continuing...\n", | |||
1194 | dev->name); | |||
1195 | wrval = 0x0001; | |||
1196 | outb(ASIC_RST|i586_RST,ioaddr+EEPROM_Ctrl)((__builtin_constant_p((ioaddr+0x000e)) && (ioaddr+0x000e ) < 256) ? __outbc((0x40|0x80),(ioaddr+0x000e)) : __outb(( 0x40|0x80),(ioaddr+0x000e))); | |||
1197 | } | |||
1198 | } | |||
1199 | } | |||
1200 | outb(i586_RST,ioaddr+EEPROM_Ctrl)((__builtin_constant_p((ioaddr+0x000e)) && (ioaddr+0x000e ) < 256) ? __outbc((0x80),(ioaddr+0x000e)) : __outb((0x80) ,(ioaddr+0x000e))); | |||
1201 | } | |||
1202 | ||||
1203 | ||||
1204 | /* | |||
1205 | * Set or clear the multicast filter for this adaptor. | |||
1206 | * We have to do a complete 586 restart for this to take effect. | |||
1207 | * At the moment only promiscuous mode is supported. | |||
1208 | */ | |||
1209 | static void | |||
1210 | eexp_set_multicast(struct devicelinux_device *dev) | |||
1211 | { | |||
1212 | if ((dev->flags & IFF_PROMISC0x100) != PRIV(dev)((struct net_local *)(dev)->priv)->promisc) | |||
1213 | eexp_hw_init586(dev); | |||
1214 | } | |||
1215 | ||||
1216 | ||||
1217 | /* | |||
1218 | * MODULE stuff | |||
1219 | */ | |||
1220 | #ifdef MODULE | |||
1221 | ||||
1222 | #define EEXP_MAX_CARDS 4 /* max number of cards to support */ | |||
1223 | #define NAMELEN 8 /* max length of dev->name (inc null) */ | |||
1224 | ||||
1225 | static char namelist[NAMELEN * EEXP_MAX_CARDS] = { 0, }; | |||
1226 | ||||
1227 | static struct devicelinux_device dev_eexp[EEXP_MAX_CARDS] = | |||
1228 | { | |||
1229 | { NULL((void *) 0), /* will allocate dynamically */ | |||
1230 | 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL((void *) 0), express_probe }, | |||
1231 | }; | |||
1232 | ||||
1233 | int irq[EEXP_MAX_CARDS] = {0, }; | |||
1234 | int io[EEXP_MAX_CARDS] = {0, }; | |||
1235 | ||||
1236 | /* Ideally the user would give us io=, irq= for every card. If any parameters | |||
1237 | * are specified, we verify and then use them. If no parameters are given, we | |||
1238 | * autoprobe for one card only. | |||
1239 | */ | |||
1240 | int init_module(void) | |||
1241 | { | |||
1242 | int this_dev, found = 0; | |||
1243 | ||||
1244 | for (this_dev = 0; this_dev < EEXP_MAX_CARDS; this_dev++) { | |||
1245 | struct devicelinux_device *dev = &dev_eexp[this_dev]; | |||
1246 | dev->name = namelist + (NAMELEN*this_dev); | |||
1247 | dev->irq = irq[this_dev]; | |||
1248 | dev->base_addr = io[this_dev]; | |||
1249 | if (io[this_dev] == 0) { | |||
1250 | if (this_dev) break; | |||
1251 | printk(KERN_NOTICE"<5>" "eexpress.c: Module autoprobe not recommended, give io=xx.\n"); | |||
1252 | } | |||
1253 | if (register_netdev(dev) != 0) { | |||
1254 | printk(KERN_WARNING"<4>" "eexpress.c: Failed to register card at 0x%x.\n", io[this_dev]); | |||
1255 | if (found != 0) return 0; | |||
1256 | return -ENXIO6; | |||
1257 | } | |||
1258 | found++; | |||
1259 | } | |||
1260 | return 0; | |||
1261 | } | |||
1262 | ||||
1263 | void cleanup_module(void) | |||
1264 | { | |||
1265 | int this_dev; | |||
1266 | ||||
1267 | for (this_dev = 0; this_dev < EEXP_MAX_CARDS; this_dev++) { | |||
1268 | struct devicelinux_device *dev = &dev_eexp[this_dev]; | |||
1269 | if (dev->priv != NULL((void *) 0)) { | |||
1270 | kfreelinux_kfree(dev->priv); | |||
1271 | dev->priv = NULL((void *) 0); | |||
1272 | release_region(dev->base_addr, EEXP_IO_EXTENT16); | |||
1273 | unregister_netdev(dev); | |||
1274 | } | |||
1275 | } | |||
1276 | } | |||
1277 | #endif | |||
1278 | ||||
1279 | /* | |||
1280 | * Local Variables: | |||
1281 | * c-file-style: "linux" | |||
1282 | * tab-width: 8 | |||
1283 | * compile-command: "gcc -D__KERNEL__ -I/discs/bibble/src/linux-1.3.69/include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -fno-strength-reduce -pipe -m486 -DCPU=486 -DMODULE -c 3c505.c" | |||
1284 | * End: | |||
1285 | */ |