File: | obj-scan-build/../linux/src/drivers/net/eexpress.c |
Location: | line 531, column 3 |
Description: | Value stored to 'txstatus' is never read |
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); |
Value stored to 'txstatus' is never read | |
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 | */ |