diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/net/ewrk3.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/net/ewrk3.c')
-rw-r--r-- | drivers/net/ewrk3.c | 2007 |
1 files changed, 2007 insertions, 0 deletions
diff --git a/drivers/net/ewrk3.c b/drivers/net/ewrk3.c new file mode 100644 index 000000000000..dcf969b20be9 --- /dev/null +++ b/drivers/net/ewrk3.c | |||
@@ -0,0 +1,2007 @@ | |||
1 | /* ewrk3.c: A DIGITAL EtherWORKS 3 ethernet driver for Linux. | ||
2 | |||
3 | Written 1994 by David C. Davies. | ||
4 | |||
5 | Copyright 1994 Digital Equipment Corporation. | ||
6 | |||
7 | This software may be used and distributed according to the terms of | ||
8 | the GNU General Public License, incorporated herein by reference. | ||
9 | |||
10 | This driver is written for the Digital Equipment Corporation series | ||
11 | of EtherWORKS ethernet cards: | ||
12 | |||
13 | DE203 Turbo (BNC) | ||
14 | DE204 Turbo (TP) | ||
15 | DE205 Turbo (TP BNC) | ||
16 | |||
17 | The driver has been tested on a relatively busy network using the DE205 | ||
18 | card and benchmarked with 'ttcp': it transferred 16M of data at 975kB/s | ||
19 | (7.8Mb/s) to a DECstation 5000/200. | ||
20 | |||
21 | The author may be reached at davies@maniac.ultranet.com. | ||
22 | |||
23 | ========================================================================= | ||
24 | This driver has been written substantially from scratch, although its | ||
25 | inheritance of style and stack interface from 'depca.c' and in turn from | ||
26 | Donald Becker's 'lance.c' should be obvious. | ||
27 | |||
28 | The DE203/4/5 boards all use a new proprietary chip in place of the | ||
29 | LANCE chip used in prior cards (DEPCA, DE100, DE200/1/2, DE210, DE422). | ||
30 | Use the depca.c driver in the standard distribution for the LANCE based | ||
31 | cards from DIGITAL; this driver will not work with them. | ||
32 | |||
33 | The DE203/4/5 cards have 2 main modes: shared memory and I/O only. I/O | ||
34 | only makes all the card accesses through I/O transactions and no high | ||
35 | (shared) memory is used. This mode provides a >48% performance penalty | ||
36 | and is deprecated in this driver, although allowed to provide initial | ||
37 | setup when hardstrapped. | ||
38 | |||
39 | The shared memory mode comes in 3 flavours: 2kB, 32kB and 64kB. There is | ||
40 | no point in using any mode other than the 2kB mode - their performances | ||
41 | are virtually identical, although the driver has been tested in the 2kB | ||
42 | and 32kB modes. I would suggest you uncomment the line: | ||
43 | |||
44 | FORCE_2K_MODE; | ||
45 | |||
46 | to allow the driver to configure the card as a 2kB card at your current | ||
47 | base address, thus leaving more room to clutter your system box with | ||
48 | other memory hungry boards. | ||
49 | |||
50 | As many ISA and EISA cards can be supported under this driver as you | ||
51 | wish, limited primarily by the available IRQ lines, rather than by the | ||
52 | available I/O addresses (24 ISA, 16 EISA). I have checked different | ||
53 | configurations of multiple depca cards and ewrk3 cards and have not | ||
54 | found a problem yet (provided you have at least depca.c v0.38) ... | ||
55 | |||
56 | The board IRQ setting must be at an unused IRQ which is auto-probed | ||
57 | using Donald Becker's autoprobe routines. All these cards are at | ||
58 | {5,10,11,15}. | ||
59 | |||
60 | No 16MB memory limitation should exist with this driver as DMA is not | ||
61 | used and the common memory area is in low memory on the network card (my | ||
62 | current system has 20MB and I've not had problems yet). | ||
63 | |||
64 | The ability to load this driver as a loadable module has been included | ||
65 | and used extensively during the driver development (to save those long | ||
66 | reboot sequences). To utilise this ability, you have to do 8 things: | ||
67 | |||
68 | 0) have a copy of the loadable modules code installed on your system. | ||
69 | 1) copy ewrk3.c from the /linux/drivers/net directory to your favourite | ||
70 | temporary directory. | ||
71 | 2) edit the source code near line 1898 to reflect the I/O address and | ||
72 | IRQ you're using. | ||
73 | 3) compile ewrk3.c, but include -DMODULE in the command line to ensure | ||
74 | that the correct bits are compiled (see end of source code). | ||
75 | 4) if you are wanting to add a new card, goto 5. Otherwise, recompile a | ||
76 | kernel with the ewrk3 configuration turned off and reboot. | ||
77 | 5) insmod ewrk3.o | ||
78 | [Alan Cox: Changed this so you can insmod ewrk3.o irq=x io=y] | ||
79 | [Adam Kropelin: now accepts irq=x1,x2 io=y1,y2 for multiple cards] | ||
80 | 6) run the net startup bits for your new eth?? interface manually | ||
81 | (usually /etc/rc.inet[12] at boot time). | ||
82 | 7) enjoy! | ||
83 | |||
84 | Note that autoprobing is not allowed in loadable modules - the system is | ||
85 | already up and running and you're messing with interrupts. | ||
86 | |||
87 | To unload a module, turn off the associated interface | ||
88 | 'ifconfig eth?? down' then 'rmmod ewrk3'. | ||
89 | |||
90 | Promiscuous mode has been turned off in this driver, but all the | ||
91 | multicast address bits have been turned on. This improved the send | ||
92 | performance on a busy network by about 13%. | ||
93 | |||
94 | Ioctl's have now been provided (primarily because I wanted to grab some | ||
95 | packet size statistics). They are patterned after 'plipconfig.c' from a | ||
96 | suggestion by Alan Cox. Using these ioctls, you can enable promiscuous | ||
97 | mode, add/delete multicast addresses, change the hardware address, get | ||
98 | packet size distribution statistics and muck around with the control and | ||
99 | status register. I'll add others if and when the need arises. | ||
100 | |||
101 | TO DO: | ||
102 | ------ | ||
103 | |||
104 | |||
105 | Revision History | ||
106 | ---------------- | ||
107 | |||
108 | Version Date Description | ||
109 | |||
110 | 0.1 26-aug-94 Initial writing. ALPHA code release. | ||
111 | 0.11 31-aug-94 Fixed: 2k mode memory base calc., | ||
112 | LeMAC version calc., | ||
113 | IRQ vector assignments during autoprobe. | ||
114 | 0.12 31-aug-94 Tested working on LeMAC2 (DE20[345]-AC) card. | ||
115 | Fixed up MCA hash table algorithm. | ||
116 | 0.20 4-sep-94 Added IOCTL functionality. | ||
117 | 0.21 14-sep-94 Added I/O mode. | ||
118 | 0.21axp 15-sep-94 Special version for ALPHA AXP Linux V1.0. | ||
119 | 0.22 16-sep-94 Added more IOCTLs & tidied up. | ||
120 | 0.23 21-sep-94 Added transmit cut through. | ||
121 | 0.24 31-oct-94 Added uid checks in some ioctls. | ||
122 | 0.30 1-nov-94 BETA code release. | ||
123 | 0.31 5-dec-94 Added check/allocate region code. | ||
124 | 0.32 16-jan-95 Broadcast packet fix. | ||
125 | 0.33 10-Feb-95 Fix recognition bug reported by <bkm@star.rl.ac.uk>. | ||
126 | 0.40 27-Dec-95 Rationalise MODULE and autoprobe code. | ||
127 | Rewrite for portability & updated. | ||
128 | ALPHA support from <jestabro@amt.tay1.dec.com> | ||
129 | Added verify_area() calls in ewrk3_ioctl() from | ||
130 | suggestion by <heiko@colossus.escape.de>. | ||
131 | Add new multicasting code. | ||
132 | 0.41 20-Jan-96 Fix IRQ set up problem reported by | ||
133 | <kenneth@bbs.sas.ntu.ac.sg>. | ||
134 | 0.42 22-Apr-96 Fix alloc_device() bug <jari@markkus2.fimr.fi> | ||
135 | 0.43 16-Aug-96 Update alloc_device() to conform to de4x5.c | ||
136 | 0.44 08-Nov-01 use library crc32 functions <Matt_Domsch@dell.com> | ||
137 | 0.45 19-Jul-02 fix unaligned access on alpha <martin@bruli.net> | ||
138 | 0.46 10-Oct-02 Multiple NIC support when module <akropel1@rochester.rr.com> | ||
139 | 0.47 18-Oct-02 ethtool support <akropel1@rochester.rr.com> | ||
140 | 0.48 18-Oct-02 cli/sti removal for 2.5 <vda@port.imtp.ilyichevsk.odessa.ua> | ||
141 | ioctl locking, signature search cleanup <akropel1@rochester.rr.com> | ||
142 | |||
143 | ========================================================================= | ||
144 | */ | ||
145 | |||
146 | #include <linux/module.h> | ||
147 | #include <linux/kernel.h> | ||
148 | #include <linux/string.h> | ||
149 | #include <linux/errno.h> | ||
150 | #include <linux/ioport.h> | ||
151 | #include <linux/slab.h> | ||
152 | #include <linux/interrupt.h> | ||
153 | #include <linux/delay.h> | ||
154 | #include <linux/init.h> | ||
155 | #include <linux/crc32.h> | ||
156 | #include <linux/netdevice.h> | ||
157 | #include <linux/etherdevice.h> | ||
158 | #include <linux/skbuff.h> | ||
159 | #include <linux/ethtool.h> | ||
160 | #include <linux/time.h> | ||
161 | #include <linux/types.h> | ||
162 | #include <linux/unistd.h> | ||
163 | #include <linux/ctype.h> | ||
164 | #include <linux/bitops.h> | ||
165 | |||
166 | #include <asm/io.h> | ||
167 | #include <asm/dma.h> | ||
168 | #include <asm/uaccess.h> | ||
169 | |||
170 | #include "ewrk3.h" | ||
171 | |||
172 | #define DRV_NAME "ewrk3" | ||
173 | #define DRV_VERSION "0.48" | ||
174 | |||
175 | static char version[] __initdata = | ||
176 | DRV_NAME ":v" DRV_VERSION " 2002/10/18 davies@maniac.ultranet.com\n"; | ||
177 | |||
178 | #ifdef EWRK3_DEBUG | ||
179 | static int ewrk3_debug = EWRK3_DEBUG; | ||
180 | #else | ||
181 | static int ewrk3_debug = 1; | ||
182 | #endif | ||
183 | |||
184 | #define EWRK3_NDA 0xffe0 /* No Device Address */ | ||
185 | |||
186 | #define PROBE_LENGTH 32 | ||
187 | #define ETH_PROM_SIG 0xAA5500FFUL | ||
188 | |||
189 | #ifndef EWRK3_SIGNATURE | ||
190 | #define EWRK3_SIGNATURE {"DE203","DE204","DE205",""} | ||
191 | #define EWRK3_STRLEN 8 | ||
192 | #endif | ||
193 | |||
194 | #ifndef EWRK3_RAM_BASE_ADDRESSES | ||
195 | #define EWRK3_RAM_BASE_ADDRESSES {0xc0000,0xd0000,0x00000} | ||
196 | #endif | ||
197 | |||
198 | /* | ||
199 | ** Sets up the I/O area for the autoprobe. | ||
200 | */ | ||
201 | #define EWRK3_IO_BASE 0x100 /* Start address for probe search */ | ||
202 | #define EWRK3_IOP_INC 0x20 /* I/O address increment */ | ||
203 | #define EWRK3_TOTAL_SIZE 0x20 /* required I/O address length */ | ||
204 | |||
205 | #ifndef MAX_NUM_EWRK3S | ||
206 | #define MAX_NUM_EWRK3S 21 | ||
207 | #endif | ||
208 | |||
209 | #ifndef EWRK3_EISA_IO_PORTS | ||
210 | #define EWRK3_EISA_IO_PORTS 0x0c00 /* I/O port base address, slot 0 */ | ||
211 | #endif | ||
212 | |||
213 | #ifndef MAX_EISA_SLOTS | ||
214 | #define MAX_EISA_SLOTS 16 | ||
215 | #define EISA_SLOT_INC 0x1000 | ||
216 | #endif | ||
217 | |||
218 | #define QUEUE_PKT_TIMEOUT (1*HZ) /* Jiffies */ | ||
219 | |||
220 | /* | ||
221 | ** EtherWORKS 3 shared memory window sizes | ||
222 | */ | ||
223 | #define IO_ONLY 0x00 | ||
224 | #define SHMEM_2K 0x800 | ||
225 | #define SHMEM_32K 0x8000 | ||
226 | #define SHMEM_64K 0x10000 | ||
227 | |||
228 | /* | ||
229 | ** EtherWORKS 3 IRQ ENABLE/DISABLE | ||
230 | */ | ||
231 | #define ENABLE_IRQs { \ | ||
232 | icr |= lp->irq_mask;\ | ||
233 | outb(icr, EWRK3_ICR); /* Enable the IRQs */\ | ||
234 | } | ||
235 | |||
236 | #define DISABLE_IRQs { \ | ||
237 | icr = inb(EWRK3_ICR);\ | ||
238 | icr &= ~lp->irq_mask;\ | ||
239 | outb(icr, EWRK3_ICR); /* Disable the IRQs */\ | ||
240 | } | ||
241 | |||
242 | /* | ||
243 | ** EtherWORKS 3 START/STOP | ||
244 | */ | ||
245 | #define START_EWRK3 { \ | ||
246 | csr = inb(EWRK3_CSR);\ | ||
247 | csr &= ~(CSR_TXD|CSR_RXD);\ | ||
248 | outb(csr, EWRK3_CSR); /* Enable the TX and/or RX */\ | ||
249 | } | ||
250 | |||
251 | #define STOP_EWRK3 { \ | ||
252 | csr = (CSR_TXD|CSR_RXD);\ | ||
253 | outb(csr, EWRK3_CSR); /* Disable the TX and/or RX */\ | ||
254 | } | ||
255 | |||
256 | /* | ||
257 | ** The EtherWORKS 3 private structure | ||
258 | */ | ||
259 | #define EWRK3_PKT_STAT_SZ 16 | ||
260 | #define EWRK3_PKT_BIN_SZ 128 /* Should be >=100 unless you | ||
261 | increase EWRK3_PKT_STAT_SZ */ | ||
262 | |||
263 | struct ewrk3_stats { | ||
264 | u32 bins[EWRK3_PKT_STAT_SZ]; | ||
265 | u32 unicast; | ||
266 | u32 multicast; | ||
267 | u32 broadcast; | ||
268 | u32 excessive_collisions; | ||
269 | u32 tx_underruns; | ||
270 | u32 excessive_underruns; | ||
271 | }; | ||
272 | |||
273 | struct ewrk3_private { | ||
274 | char adapter_name[80]; /* Name exported to /proc/ioports */ | ||
275 | u_long shmem_base; /* Shared memory start address */ | ||
276 | void __iomem *shmem; | ||
277 | u_long shmem_length; /* Shared memory window length */ | ||
278 | struct net_device_stats stats; /* Public stats */ | ||
279 | struct ewrk3_stats pktStats; /* Private stats counters */ | ||
280 | u_char irq_mask; /* Adapter IRQ mask bits */ | ||
281 | u_char mPage; /* Maximum 2kB Page number */ | ||
282 | u_char lemac; /* Chip rev. level */ | ||
283 | u_char hard_strapped; /* Don't allow a full open */ | ||
284 | u_char txc; /* Transmit cut through */ | ||
285 | void __iomem *mctbl; /* Pointer to the multicast table */ | ||
286 | u_char led_mask; /* Used to reserve LED access for ethtool */ | ||
287 | spinlock_t hw_lock; | ||
288 | }; | ||
289 | |||
290 | /* | ||
291 | ** Force the EtherWORKS 3 card to be in 2kB MODE | ||
292 | */ | ||
293 | #define FORCE_2K_MODE { \ | ||
294 | shmem_length = SHMEM_2K;\ | ||
295 | outb(((mem_start - 0x80000) >> 11), EWRK3_MBR);\ | ||
296 | } | ||
297 | |||
298 | /* | ||
299 | ** Public Functions | ||
300 | */ | ||
301 | static int ewrk3_open(struct net_device *dev); | ||
302 | static int ewrk3_queue_pkt(struct sk_buff *skb, struct net_device *dev); | ||
303 | static irqreturn_t ewrk3_interrupt(int irq, void *dev_id, struct pt_regs *regs); | ||
304 | static int ewrk3_close(struct net_device *dev); | ||
305 | static struct net_device_stats *ewrk3_get_stats(struct net_device *dev); | ||
306 | static void set_multicast_list(struct net_device *dev); | ||
307 | static int ewrk3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); | ||
308 | static struct ethtool_ops ethtool_ops_203; | ||
309 | static struct ethtool_ops ethtool_ops; | ||
310 | |||
311 | /* | ||
312 | ** Private functions | ||
313 | */ | ||
314 | static int ewrk3_hw_init(struct net_device *dev, u_long iobase); | ||
315 | static void ewrk3_init(struct net_device *dev); | ||
316 | static int ewrk3_rx(struct net_device *dev); | ||
317 | static int ewrk3_tx(struct net_device *dev); | ||
318 | static void ewrk3_timeout(struct net_device *dev); | ||
319 | |||
320 | static void EthwrkSignature(char *name, char *eeprom_image); | ||
321 | static int DevicePresent(u_long iobase); | ||
322 | static void SetMulticastFilter(struct net_device *dev); | ||
323 | static int EISA_signature(char *name, s32 eisa_id); | ||
324 | |||
325 | static int Read_EEPROM(u_long iobase, u_char eaddr); | ||
326 | static int Write_EEPROM(short data, u_long iobase, u_char eaddr); | ||
327 | static u_char get_hw_addr(struct net_device *dev, u_char * eeprom_image, char chipType); | ||
328 | |||
329 | static int ewrk3_probe1(struct net_device *dev, u_long iobase, int irq); | ||
330 | static int isa_probe(struct net_device *dev, u_long iobase); | ||
331 | static int eisa_probe(struct net_device *dev, u_long iobase); | ||
332 | |||
333 | static u_char irq[MAX_NUM_EWRK3S+1] = {5, 0, 10, 3, 11, 9, 15, 12}; | ||
334 | |||
335 | static char name[EWRK3_STRLEN + 1]; | ||
336 | static int num_ewrks3s; | ||
337 | |||
338 | /* | ||
339 | ** Miscellaneous defines... | ||
340 | */ | ||
341 | #define INIT_EWRK3 {\ | ||
342 | outb(EEPROM_INIT, EWRK3_IOPR);\ | ||
343 | mdelay(1);\ | ||
344 | } | ||
345 | |||
346 | #ifndef MODULE | ||
347 | struct net_device * __init ewrk3_probe(int unit) | ||
348 | { | ||
349 | struct net_device *dev = alloc_etherdev(sizeof(struct ewrk3_private)); | ||
350 | int err; | ||
351 | |||
352 | if (!dev) | ||
353 | return ERR_PTR(-ENOMEM); | ||
354 | |||
355 | if (unit >= 0) { | ||
356 | sprintf(dev->name, "eth%d", unit); | ||
357 | netdev_boot_setup_check(dev); | ||
358 | } | ||
359 | SET_MODULE_OWNER(dev); | ||
360 | |||
361 | err = ewrk3_probe1(dev, dev->base_addr, dev->irq); | ||
362 | if (err) | ||
363 | goto out; | ||
364 | return dev; | ||
365 | out: | ||
366 | free_netdev(dev); | ||
367 | return ERR_PTR(err); | ||
368 | |||
369 | } | ||
370 | #endif | ||
371 | |||
372 | static int __init ewrk3_probe1(struct net_device *dev, u_long iobase, int irq) | ||
373 | { | ||
374 | int err; | ||
375 | |||
376 | dev->base_addr = iobase; | ||
377 | dev->irq = irq; | ||
378 | |||
379 | /* Address PROM pattern */ | ||
380 | err = isa_probe(dev, iobase); | ||
381 | if (err != 0) | ||
382 | err = eisa_probe(dev, iobase); | ||
383 | |||
384 | if (err) | ||
385 | return err; | ||
386 | |||
387 | err = register_netdev(dev); | ||
388 | if (err) | ||
389 | release_region(dev->base_addr, EWRK3_TOTAL_SIZE); | ||
390 | |||
391 | return err; | ||
392 | } | ||
393 | |||
394 | static int __init | ||
395 | ewrk3_hw_init(struct net_device *dev, u_long iobase) | ||
396 | { | ||
397 | struct ewrk3_private *lp; | ||
398 | int i, status = 0; | ||
399 | u_long mem_start, shmem_length; | ||
400 | u_char cr, cmr, icr, nicsr, lemac, hard_strapped = 0; | ||
401 | u_char eeprom_image[EEPROM_MAX], chksum, eisa_cr = 0; | ||
402 | |||
403 | /* | ||
404 | ** Stop the EWRK3. Enable the DBR ROM. Disable interrupts and remote boot. | ||
405 | ** This also disables the EISA_ENABLE bit in the EISA Control Register. | ||
406 | */ | ||
407 | if (iobase > 0x400) | ||
408 | eisa_cr = inb(EISA_CR); | ||
409 | INIT_EWRK3; | ||
410 | |||
411 | nicsr = inb(EWRK3_CSR); | ||
412 | |||
413 | icr = inb(EWRK3_ICR); | ||
414 | icr &= 0x70; | ||
415 | outb(icr, EWRK3_ICR); /* Disable all the IRQs */ | ||
416 | |||
417 | if (nicsr == (CSR_TXD | CSR_RXD)) | ||
418 | return -ENXIO; | ||
419 | |||
420 | |||
421 | /* Check that the EEPROM is alive and well and not living on Pluto... */ | ||
422 | for (chksum = 0, i = 0; i < EEPROM_MAX; i += 2) { | ||
423 | union { | ||
424 | short val; | ||
425 | char c[2]; | ||
426 | } tmp; | ||
427 | |||
428 | tmp.val = (short) Read_EEPROM(iobase, (i >> 1)); | ||
429 | eeprom_image[i] = tmp.c[0]; | ||
430 | eeprom_image[i + 1] = tmp.c[1]; | ||
431 | chksum += eeprom_image[i] + eeprom_image[i + 1]; | ||
432 | } | ||
433 | |||
434 | if (chksum != 0) { /* Bad EEPROM Data! */ | ||
435 | printk("%s: Device has a bad on-board EEPROM.\n", dev->name); | ||
436 | return -ENXIO; | ||
437 | } | ||
438 | |||
439 | EthwrkSignature(name, eeprom_image); | ||
440 | if (*name == '\0') | ||
441 | return -ENXIO; | ||
442 | |||
443 | dev->base_addr = iobase; | ||
444 | |||
445 | if (iobase > 0x400) { | ||
446 | outb(eisa_cr, EISA_CR); /* Rewrite the EISA CR */ | ||
447 | } | ||
448 | lemac = eeprom_image[EEPROM_CHIPVER]; | ||
449 | cmr = inb(EWRK3_CMR); | ||
450 | |||
451 | if (((lemac == LeMAC) && ((cmr & CMR_NO_EEPROM) != CMR_NO_EEPROM)) || | ||
452 | ((lemac == LeMAC2) && !(cmr & CMR_HS))) { | ||
453 | printk("%s: %s at %#4lx", dev->name, name, iobase); | ||
454 | hard_strapped = 1; | ||
455 | } else if ((iobase & 0x0fff) == EWRK3_EISA_IO_PORTS) { | ||
456 | /* EISA slot address */ | ||
457 | printk("%s: %s at %#4lx (EISA slot %ld)", | ||
458 | dev->name, name, iobase, ((iobase >> 12) & 0x0f)); | ||
459 | } else { /* ISA port address */ | ||
460 | printk("%s: %s at %#4lx", dev->name, name, iobase); | ||
461 | } | ||
462 | |||
463 | printk(", h/w address "); | ||
464 | if (lemac != LeMAC2) | ||
465 | DevicePresent(iobase); /* need after EWRK3_INIT */ | ||
466 | status = get_hw_addr(dev, eeprom_image, lemac); | ||
467 | for (i = 0; i < ETH_ALEN - 1; i++) { /* get the ethernet addr. */ | ||
468 | printk("%2.2x:", dev->dev_addr[i]); | ||
469 | } | ||
470 | printk("%2.2x,\n", dev->dev_addr[i]); | ||
471 | |||
472 | if (status) { | ||
473 | printk(" which has an EEPROM CRC error.\n"); | ||
474 | return -ENXIO; | ||
475 | } | ||
476 | |||
477 | if (lemac == LeMAC2) { /* Special LeMAC2 CMR things */ | ||
478 | cmr &= ~(CMR_RA | CMR_WB | CMR_LINK | CMR_POLARITY | CMR_0WS); | ||
479 | if (eeprom_image[EEPROM_MISC0] & READ_AHEAD) | ||
480 | cmr |= CMR_RA; | ||
481 | if (eeprom_image[EEPROM_MISC0] & WRITE_BEHIND) | ||
482 | cmr |= CMR_WB; | ||
483 | if (eeprom_image[EEPROM_NETMAN0] & NETMAN_POL) | ||
484 | cmr |= CMR_POLARITY; | ||
485 | if (eeprom_image[EEPROM_NETMAN0] & NETMAN_LINK) | ||
486 | cmr |= CMR_LINK; | ||
487 | if (eeprom_image[EEPROM_MISC0] & _0WS_ENA) | ||
488 | cmr |= CMR_0WS; | ||
489 | } | ||
490 | if (eeprom_image[EEPROM_SETUP] & SETUP_DRAM) | ||
491 | cmr |= CMR_DRAM; | ||
492 | outb(cmr, EWRK3_CMR); | ||
493 | |||
494 | cr = inb(EWRK3_CR); /* Set up the Control Register */ | ||
495 | cr |= eeprom_image[EEPROM_SETUP] & SETUP_APD; | ||
496 | if (cr & SETUP_APD) | ||
497 | cr |= eeprom_image[EEPROM_SETUP] & SETUP_PS; | ||
498 | cr |= eeprom_image[EEPROM_MISC0] & FAST_BUS; | ||
499 | cr |= eeprom_image[EEPROM_MISC0] & ENA_16; | ||
500 | outb(cr, EWRK3_CR); | ||
501 | |||
502 | /* | ||
503 | ** Determine the base address and window length for the EWRK3 | ||
504 | ** RAM from the memory base register. | ||
505 | */ | ||
506 | mem_start = inb(EWRK3_MBR); | ||
507 | shmem_length = 0; | ||
508 | if (mem_start != 0) { | ||
509 | if ((mem_start >= 0x0a) && (mem_start <= 0x0f)) { | ||
510 | mem_start *= SHMEM_64K; | ||
511 | shmem_length = SHMEM_64K; | ||
512 | } else if ((mem_start >= 0x14) && (mem_start <= 0x1f)) { | ||
513 | mem_start *= SHMEM_32K; | ||
514 | shmem_length = SHMEM_32K; | ||
515 | } else if ((mem_start >= 0x40) && (mem_start <= 0xff)) { | ||
516 | mem_start = mem_start * SHMEM_2K + 0x80000; | ||
517 | shmem_length = SHMEM_2K; | ||
518 | } else { | ||
519 | return -ENXIO; | ||
520 | } | ||
521 | } | ||
522 | /* | ||
523 | ** See the top of this source code for comments about | ||
524 | ** uncommenting this line. | ||
525 | */ | ||
526 | /* FORCE_2K_MODE; */ | ||
527 | |||
528 | if (hard_strapped) { | ||
529 | printk(" is hard strapped.\n"); | ||
530 | } else if (mem_start) { | ||
531 | printk(" has a %dk RAM window", (int) (shmem_length >> 10)); | ||
532 | printk(" at 0x%.5lx", mem_start); | ||
533 | } else { | ||
534 | printk(" is in I/O only mode"); | ||
535 | } | ||
536 | |||
537 | lp = netdev_priv(dev); | ||
538 | lp->shmem_base = mem_start; | ||
539 | lp->shmem = ioremap(mem_start, shmem_length); | ||
540 | if (!lp->shmem) | ||
541 | return -ENOMEM; | ||
542 | lp->shmem_length = shmem_length; | ||
543 | lp->lemac = lemac; | ||
544 | lp->hard_strapped = hard_strapped; | ||
545 | lp->led_mask = CR_LED; | ||
546 | spin_lock_init(&lp->hw_lock); | ||
547 | |||
548 | lp->mPage = 64; | ||
549 | if (cmr & CMR_DRAM) | ||
550 | lp->mPage <<= 1; /* 2 DRAMS on module */ | ||
551 | |||
552 | sprintf(lp->adapter_name, "%s (%s)", name, dev->name); | ||
553 | |||
554 | lp->irq_mask = ICR_TNEM | ICR_TXDM | ICR_RNEM | ICR_RXDM; | ||
555 | |||
556 | if (!hard_strapped) { | ||
557 | /* | ||
558 | ** Enable EWRK3 board interrupts for autoprobing | ||
559 | */ | ||
560 | icr |= ICR_IE; /* Enable interrupts */ | ||
561 | outb(icr, EWRK3_ICR); | ||
562 | |||
563 | /* The DMA channel may be passed in on this parameter. */ | ||
564 | dev->dma = 0; | ||
565 | |||
566 | /* To auto-IRQ we enable the initialization-done and DMA err, | ||
567 | interrupts. For now we will always get a DMA error. */ | ||
568 | if (dev->irq < 2) { | ||
569 | #ifndef MODULE | ||
570 | u_char irqnum; | ||
571 | unsigned long irq_mask; | ||
572 | |||
573 | |||
574 | irq_mask = probe_irq_on(); | ||
575 | |||
576 | /* | ||
577 | ** Trigger a TNE interrupt. | ||
578 | */ | ||
579 | icr |= ICR_TNEM; | ||
580 | outb(1, EWRK3_TDQ); /* Write to the TX done queue */ | ||
581 | outb(icr, EWRK3_ICR); /* Unmask the TXD interrupt */ | ||
582 | |||
583 | irqnum = irq[((icr & IRQ_SEL) >> 4)]; | ||
584 | |||
585 | mdelay(20); | ||
586 | dev->irq = probe_irq_off(irq_mask); | ||
587 | if ((dev->irq) && (irqnum == dev->irq)) { | ||
588 | printk(" and uses IRQ%d.\n", dev->irq); | ||
589 | } else { | ||
590 | if (!dev->irq) { | ||
591 | printk(" and failed to detect IRQ line.\n"); | ||
592 | } else if ((irqnum == 1) && (lemac == LeMAC2)) { | ||
593 | printk(" and an illegal IRQ line detected.\n"); | ||
594 | } else { | ||
595 | printk(", but incorrect IRQ line detected.\n"); | ||
596 | } | ||
597 | iounmap(lp->shmem); | ||
598 | return -ENXIO; | ||
599 | } | ||
600 | |||
601 | DISABLE_IRQs; /* Mask all interrupts */ | ||
602 | |||
603 | #endif /* MODULE */ | ||
604 | } else { | ||
605 | printk(" and requires IRQ%d.\n", dev->irq); | ||
606 | } | ||
607 | } | ||
608 | |||
609 | if (ewrk3_debug > 1) { | ||
610 | printk(version); | ||
611 | } | ||
612 | /* The EWRK3-specific entries in the device structure. */ | ||
613 | dev->open = ewrk3_open; | ||
614 | dev->hard_start_xmit = ewrk3_queue_pkt; | ||
615 | dev->stop = ewrk3_close; | ||
616 | dev->get_stats = ewrk3_get_stats; | ||
617 | dev->set_multicast_list = set_multicast_list; | ||
618 | dev->do_ioctl = ewrk3_ioctl; | ||
619 | if (lp->adapter_name[4] == '3') | ||
620 | SET_ETHTOOL_OPS(dev, ðtool_ops_203); | ||
621 | else | ||
622 | SET_ETHTOOL_OPS(dev, ðtool_ops); | ||
623 | dev->tx_timeout = ewrk3_timeout; | ||
624 | dev->watchdog_timeo = QUEUE_PKT_TIMEOUT; | ||
625 | |||
626 | dev->mem_start = 0; | ||
627 | |||
628 | return 0; | ||
629 | } | ||
630 | |||
631 | |||
632 | static int ewrk3_open(struct net_device *dev) | ||
633 | { | ||
634 | struct ewrk3_private *lp = netdev_priv(dev); | ||
635 | u_long iobase = dev->base_addr; | ||
636 | int i, status = 0; | ||
637 | u_char icr, csr; | ||
638 | |||
639 | /* | ||
640 | ** Stop the TX and RX... | ||
641 | */ | ||
642 | STOP_EWRK3; | ||
643 | |||
644 | if (!lp->hard_strapped) { | ||
645 | if (request_irq(dev->irq, (void *) ewrk3_interrupt, 0, "ewrk3", dev)) { | ||
646 | printk("ewrk3_open(): Requested IRQ%d is busy\n", dev->irq); | ||
647 | status = -EAGAIN; | ||
648 | } else { | ||
649 | |||
650 | /* | ||
651 | ** Re-initialize the EWRK3... | ||
652 | */ | ||
653 | ewrk3_init(dev); | ||
654 | |||
655 | if (ewrk3_debug > 1) { | ||
656 | printk("%s: ewrk3 open with irq %d\n", dev->name, dev->irq); | ||
657 | printk(" physical address: "); | ||
658 | for (i = 0; i < 5; i++) { | ||
659 | printk("%2.2x:", (u_char) dev->dev_addr[i]); | ||
660 | } | ||
661 | printk("%2.2x\n", (u_char) dev->dev_addr[i]); | ||
662 | if (lp->shmem_length == 0) { | ||
663 | printk(" no shared memory, I/O only mode\n"); | ||
664 | } else { | ||
665 | printk(" start of shared memory: 0x%08lx\n", lp->shmem_base); | ||
666 | printk(" window length: 0x%04lx\n", lp->shmem_length); | ||
667 | } | ||
668 | printk(" # of DRAMS: %d\n", ((inb(EWRK3_CMR) & 0x02) ? 2 : 1)); | ||
669 | printk(" csr: 0x%02x\n", inb(EWRK3_CSR)); | ||
670 | printk(" cr: 0x%02x\n", inb(EWRK3_CR)); | ||
671 | printk(" icr: 0x%02x\n", inb(EWRK3_ICR)); | ||
672 | printk(" cmr: 0x%02x\n", inb(EWRK3_CMR)); | ||
673 | printk(" fmqc: 0x%02x\n", inb(EWRK3_FMQC)); | ||
674 | } | ||
675 | netif_start_queue(dev); | ||
676 | /* | ||
677 | ** Unmask EWRK3 board interrupts | ||
678 | */ | ||
679 | icr = inb(EWRK3_ICR); | ||
680 | ENABLE_IRQs; | ||
681 | |||
682 | } | ||
683 | } else { | ||
684 | printk(KERN_ERR "%s: ewrk3 available for hard strapped set up only.\n", dev->name); | ||
685 | printk(KERN_ERR " Run the 'ewrk3setup' utility or remove the hard straps.\n"); | ||
686 | return -EINVAL; | ||
687 | } | ||
688 | |||
689 | return status; | ||
690 | } | ||
691 | |||
692 | /* | ||
693 | ** Initialize the EtherWORKS 3 operating conditions | ||
694 | */ | ||
695 | static void ewrk3_init(struct net_device *dev) | ||
696 | { | ||
697 | struct ewrk3_private *lp = netdev_priv(dev); | ||
698 | u_char csr, page; | ||
699 | u_long iobase = dev->base_addr; | ||
700 | int i; | ||
701 | |||
702 | /* | ||
703 | ** Enable any multicasts | ||
704 | */ | ||
705 | set_multicast_list(dev); | ||
706 | |||
707 | /* | ||
708 | ** Set hardware MAC address. Address is initialized from the EEPROM | ||
709 | ** during startup but may have since been changed by the user. | ||
710 | */ | ||
711 | for (i=0; i<ETH_ALEN; i++) | ||
712 | outb(dev->dev_addr[i], EWRK3_PAR0 + i); | ||
713 | |||
714 | /* | ||
715 | ** Clean out any remaining entries in all the queues here | ||
716 | */ | ||
717 | while (inb(EWRK3_TQ)); | ||
718 | while (inb(EWRK3_TDQ)); | ||
719 | while (inb(EWRK3_RQ)); | ||
720 | while (inb(EWRK3_FMQ)); | ||
721 | |||
722 | /* | ||
723 | ** Write a clean free memory queue | ||
724 | */ | ||
725 | for (page = 1; page < lp->mPage; page++) { /* Write the free page numbers */ | ||
726 | outb(page, EWRK3_FMQ); /* to the Free Memory Queue */ | ||
727 | } | ||
728 | |||
729 | START_EWRK3; /* Enable the TX and/or RX */ | ||
730 | } | ||
731 | |||
732 | /* | ||
733 | * Transmit timeout | ||
734 | */ | ||
735 | |||
736 | static void ewrk3_timeout(struct net_device *dev) | ||
737 | { | ||
738 | struct ewrk3_private *lp = netdev_priv(dev); | ||
739 | u_char icr, csr; | ||
740 | u_long iobase = dev->base_addr; | ||
741 | |||
742 | if (!lp->hard_strapped) | ||
743 | { | ||
744 | printk(KERN_WARNING"%s: transmit timed/locked out, status %04x, resetting.\n", | ||
745 | dev->name, inb(EWRK3_CSR)); | ||
746 | |||
747 | /* | ||
748 | ** Mask all board interrupts | ||
749 | */ | ||
750 | DISABLE_IRQs; | ||
751 | |||
752 | /* | ||
753 | ** Stop the TX and RX... | ||
754 | */ | ||
755 | STOP_EWRK3; | ||
756 | |||
757 | ewrk3_init(dev); | ||
758 | |||
759 | /* | ||
760 | ** Unmask EWRK3 board interrupts | ||
761 | */ | ||
762 | ENABLE_IRQs; | ||
763 | |||
764 | dev->trans_start = jiffies; | ||
765 | netif_wake_queue(dev); | ||
766 | } | ||
767 | } | ||
768 | |||
769 | /* | ||
770 | ** Writes a socket buffer to the free page queue | ||
771 | */ | ||
772 | static int ewrk3_queue_pkt (struct sk_buff *skb, struct net_device *dev) | ||
773 | { | ||
774 | struct ewrk3_private *lp = netdev_priv(dev); | ||
775 | u_long iobase = dev->base_addr; | ||
776 | void __iomem *buf = NULL; | ||
777 | u_char icr; | ||
778 | u_char page; | ||
779 | |||
780 | spin_lock_irq (&lp->hw_lock); | ||
781 | DISABLE_IRQs; | ||
782 | |||
783 | /* if no resources available, exit, request packet be queued */ | ||
784 | if (inb (EWRK3_FMQC) == 0) { | ||
785 | printk (KERN_WARNING "%s: ewrk3_queue_pkt(): No free resources...\n", | ||
786 | dev->name); | ||
787 | printk (KERN_WARNING "%s: ewrk3_queue_pkt(): CSR: %02x ICR: %02x FMQC: %02x\n", | ||
788 | dev->name, inb (EWRK3_CSR), inb (EWRK3_ICR), | ||
789 | inb (EWRK3_FMQC)); | ||
790 | goto err_out; | ||
791 | } | ||
792 | |||
793 | /* | ||
794 | ** Get a free page from the FMQ | ||
795 | */ | ||
796 | if ((page = inb (EWRK3_FMQ)) >= lp->mPage) { | ||
797 | printk ("ewrk3_queue_pkt(): Invalid free memory page (%d).\n", | ||
798 | (u_char) page); | ||
799 | goto err_out; | ||
800 | } | ||
801 | |||
802 | |||
803 | /* | ||
804 | ** Set up shared memory window and pointer into the window | ||
805 | */ | ||
806 | if (lp->shmem_length == IO_ONLY) { | ||
807 | outb (page, EWRK3_IOPR); | ||
808 | } else if (lp->shmem_length == SHMEM_2K) { | ||
809 | buf = lp->shmem; | ||
810 | outb (page, EWRK3_MPR); | ||
811 | } else if (lp->shmem_length == SHMEM_32K) { | ||
812 | buf = (((short) page << 11) & 0x7800) + lp->shmem; | ||
813 | outb ((page >> 4), EWRK3_MPR); | ||
814 | } else if (lp->shmem_length == SHMEM_64K) { | ||
815 | buf = (((short) page << 11) & 0xf800) + lp->shmem; | ||
816 | outb ((page >> 5), EWRK3_MPR); | ||
817 | } else { | ||
818 | printk (KERN_ERR "%s: Oops - your private data area is hosed!\n", | ||
819 | dev->name); | ||
820 | BUG (); | ||
821 | } | ||
822 | |||
823 | /* | ||
824 | ** Set up the buffer control structures and copy the data from | ||
825 | ** the socket buffer to the shared memory . | ||
826 | */ | ||
827 | if (lp->shmem_length == IO_ONLY) { | ||
828 | int i; | ||
829 | u_char *p = skb->data; | ||
830 | outb ((char) (TCR_QMODE | TCR_PAD | TCR_IFC), EWRK3_DATA); | ||
831 | outb ((char) (skb->len & 0xff), EWRK3_DATA); | ||
832 | outb ((char) ((skb->len >> 8) & 0xff), EWRK3_DATA); | ||
833 | outb ((char) 0x04, EWRK3_DATA); | ||
834 | for (i = 0; i < skb->len; i++) { | ||
835 | outb (*p++, EWRK3_DATA); | ||
836 | } | ||
837 | outb (page, EWRK3_TQ); /* Start sending pkt */ | ||
838 | } else { | ||
839 | writeb ((char) (TCR_QMODE | TCR_PAD | TCR_IFC), buf); /* ctrl byte */ | ||
840 | buf += 1; | ||
841 | writeb ((char) (skb->len & 0xff), buf); /* length (16 bit xfer) */ | ||
842 | buf += 1; | ||
843 | if (lp->txc) { | ||
844 | writeb(((skb->len >> 8) & 0xff) | XCT, buf); | ||
845 | buf += 1; | ||
846 | writeb (0x04, buf); /* index byte */ | ||
847 | buf += 1; | ||
848 | writeb (0x00, (buf + skb->len)); /* Write the XCT flag */ | ||
849 | memcpy_toio (buf, skb->data, PRELOAD); /* Write PRELOAD bytes */ | ||
850 | outb (page, EWRK3_TQ); /* Start sending pkt */ | ||
851 | memcpy_toio (buf + PRELOAD, | ||
852 | skb->data + PRELOAD, | ||
853 | skb->len - PRELOAD); | ||
854 | writeb (0xff, (buf + skb->len)); /* Write the XCT flag */ | ||
855 | } else { | ||
856 | writeb ((skb->len >> 8) & 0xff, buf); | ||
857 | buf += 1; | ||
858 | writeb (0x04, buf); /* index byte */ | ||
859 | buf += 1; | ||
860 | memcpy_toio (buf, skb->data, skb->len); /* Write data bytes */ | ||
861 | outb (page, EWRK3_TQ); /* Start sending pkt */ | ||
862 | } | ||
863 | } | ||
864 | |||
865 | ENABLE_IRQs; | ||
866 | spin_unlock_irq (&lp->hw_lock); | ||
867 | |||
868 | lp->stats.tx_bytes += skb->len; | ||
869 | dev->trans_start = jiffies; | ||
870 | dev_kfree_skb (skb); | ||
871 | |||
872 | /* Check for free resources: stop Tx queue if there are none */ | ||
873 | if (inb (EWRK3_FMQC) == 0) | ||
874 | netif_stop_queue (dev); | ||
875 | |||
876 | return 0; | ||
877 | |||
878 | err_out: | ||
879 | ENABLE_IRQs; | ||
880 | spin_unlock_irq (&lp->hw_lock); | ||
881 | return 1; | ||
882 | } | ||
883 | |||
884 | /* | ||
885 | ** The EWRK3 interrupt handler. | ||
886 | */ | ||
887 | static irqreturn_t ewrk3_interrupt(int irq, void *dev_id, struct pt_regs *regs) | ||
888 | { | ||
889 | struct net_device *dev = dev_id; | ||
890 | struct ewrk3_private *lp; | ||
891 | u_long iobase; | ||
892 | u_char icr, cr, csr; | ||
893 | |||
894 | lp = netdev_priv(dev); | ||
895 | iobase = dev->base_addr; | ||
896 | |||
897 | /* get the interrupt information */ | ||
898 | csr = inb(EWRK3_CSR); | ||
899 | |||
900 | /* | ||
901 | ** Mask the EWRK3 board interrupts and turn on the LED | ||
902 | */ | ||
903 | spin_lock(&lp->hw_lock); | ||
904 | DISABLE_IRQs; | ||
905 | |||
906 | cr = inb(EWRK3_CR); | ||
907 | cr |= lp->led_mask; | ||
908 | outb(cr, EWRK3_CR); | ||
909 | |||
910 | if (csr & CSR_RNE) /* Rx interrupt (packet[s] arrived) */ | ||
911 | ewrk3_rx(dev); | ||
912 | |||
913 | if (csr & CSR_TNE) /* Tx interrupt (packet sent) */ | ||
914 | ewrk3_tx(dev); | ||
915 | |||
916 | /* | ||
917 | ** Now deal with the TX/RX disable flags. These are set when there | ||
918 | ** are no more resources. If resources free up then enable these | ||
919 | ** interrupts, otherwise mask them - failure to do this will result | ||
920 | ** in the system hanging in an interrupt loop. | ||
921 | */ | ||
922 | if (inb(EWRK3_FMQC)) { /* any resources available? */ | ||
923 | lp->irq_mask |= ICR_TXDM | ICR_RXDM; /* enable the interrupt source */ | ||
924 | csr &= ~(CSR_TXD | CSR_RXD); /* ensure restart of a stalled TX or RX */ | ||
925 | outb(csr, EWRK3_CSR); | ||
926 | netif_wake_queue(dev); | ||
927 | } else { | ||
928 | lp->irq_mask &= ~(ICR_TXDM | ICR_RXDM); /* disable the interrupt source */ | ||
929 | } | ||
930 | |||
931 | /* Unmask the EWRK3 board interrupts and turn off the LED */ | ||
932 | cr &= ~(lp->led_mask); | ||
933 | outb(cr, EWRK3_CR); | ||
934 | ENABLE_IRQs; | ||
935 | spin_unlock(&lp->hw_lock); | ||
936 | return IRQ_HANDLED; | ||
937 | } | ||
938 | |||
939 | /* Called with lp->hw_lock held */ | ||
940 | static int ewrk3_rx(struct net_device *dev) | ||
941 | { | ||
942 | struct ewrk3_private *lp = netdev_priv(dev); | ||
943 | u_long iobase = dev->base_addr; | ||
944 | int i, status = 0; | ||
945 | u_char page; | ||
946 | void __iomem *buf = NULL; | ||
947 | |||
948 | while (inb(EWRK3_RQC) && !status) { /* Whilst there's incoming data */ | ||
949 | if ((page = inb(EWRK3_RQ)) < lp->mPage) { /* Get next entry's buffer page */ | ||
950 | /* | ||
951 | ** Set up shared memory window and pointer into the window | ||
952 | */ | ||
953 | if (lp->shmem_length == IO_ONLY) { | ||
954 | outb(page, EWRK3_IOPR); | ||
955 | } else if (lp->shmem_length == SHMEM_2K) { | ||
956 | buf = lp->shmem; | ||
957 | outb(page, EWRK3_MPR); | ||
958 | } else if (lp->shmem_length == SHMEM_32K) { | ||
959 | buf = (((short) page << 11) & 0x7800) + lp->shmem; | ||
960 | outb((page >> 4), EWRK3_MPR); | ||
961 | } else if (lp->shmem_length == SHMEM_64K) { | ||
962 | buf = (((short) page << 11) & 0xf800) + lp->shmem; | ||
963 | outb((page >> 5), EWRK3_MPR); | ||
964 | } else { | ||
965 | status = -1; | ||
966 | printk("%s: Oops - your private data area is hosed!\n", dev->name); | ||
967 | } | ||
968 | |||
969 | if (!status) { | ||
970 | char rx_status; | ||
971 | int pkt_len; | ||
972 | |||
973 | if (lp->shmem_length == IO_ONLY) { | ||
974 | rx_status = inb(EWRK3_DATA); | ||
975 | pkt_len = inb(EWRK3_DATA); | ||
976 | pkt_len |= ((u_short) inb(EWRK3_DATA) << 8); | ||
977 | } else { | ||
978 | rx_status = readb(buf); | ||
979 | buf += 1; | ||
980 | pkt_len = readw(buf); | ||
981 | buf += 3; | ||
982 | } | ||
983 | |||
984 | if (!(rx_status & R_ROK)) { /* There was an error. */ | ||
985 | lp->stats.rx_errors++; /* Update the error stats. */ | ||
986 | if (rx_status & R_DBE) | ||
987 | lp->stats.rx_frame_errors++; | ||
988 | if (rx_status & R_CRC) | ||
989 | lp->stats.rx_crc_errors++; | ||
990 | if (rx_status & R_PLL) | ||
991 | lp->stats.rx_fifo_errors++; | ||
992 | } else { | ||
993 | struct sk_buff *skb; | ||
994 | |||
995 | if ((skb = dev_alloc_skb(pkt_len + 2)) != NULL) { | ||
996 | unsigned char *p; | ||
997 | skb->dev = dev; | ||
998 | skb_reserve(skb, 2); /* Align to 16 bytes */ | ||
999 | p = skb_put(skb, pkt_len); | ||
1000 | |||
1001 | if (lp->shmem_length == IO_ONLY) { | ||
1002 | *p = inb(EWRK3_DATA); /* dummy read */ | ||
1003 | for (i = 0; i < pkt_len; i++) { | ||
1004 | *p++ = inb(EWRK3_DATA); | ||
1005 | } | ||
1006 | } else { | ||
1007 | memcpy_fromio(p, buf, pkt_len); | ||
1008 | } | ||
1009 | |||
1010 | for (i = 1; i < EWRK3_PKT_STAT_SZ - 1; i++) { | ||
1011 | if (pkt_len < i * EWRK3_PKT_BIN_SZ) { | ||
1012 | lp->pktStats.bins[i]++; | ||
1013 | i = EWRK3_PKT_STAT_SZ; | ||
1014 | } | ||
1015 | } | ||
1016 | p = skb->data; /* Look at the dest addr */ | ||
1017 | if (p[0] & 0x01) { /* Multicast/Broadcast */ | ||
1018 | if ((*(s16 *) & p[0] == -1) && (*(s16 *) & p[2] == -1) && (*(s16 *) & p[4] == -1)) { | ||
1019 | lp->pktStats.broadcast++; | ||
1020 | } else { | ||
1021 | lp->pktStats.multicast++; | ||
1022 | } | ||
1023 | } else if ((*(s16 *) & p[0] == *(s16 *) & dev->dev_addr[0]) && | ||
1024 | (*(s16 *) & p[2] == *(s16 *) & dev->dev_addr[2]) && | ||
1025 | (*(s16 *) & p[4] == *(s16 *) & dev->dev_addr[4])) { | ||
1026 | lp->pktStats.unicast++; | ||
1027 | } | ||
1028 | lp->pktStats.bins[0]++; /* Duplicates stats.rx_packets */ | ||
1029 | if (lp->pktStats.bins[0] == 0) { /* Reset counters */ | ||
1030 | memset(&lp->pktStats, 0, sizeof(lp->pktStats)); | ||
1031 | } | ||
1032 | /* | ||
1033 | ** Notify the upper protocol layers that there is another | ||
1034 | ** packet to handle | ||
1035 | */ | ||
1036 | skb->protocol = eth_type_trans(skb, dev); | ||
1037 | netif_rx(skb); | ||
1038 | |||
1039 | /* | ||
1040 | ** Update stats | ||
1041 | */ | ||
1042 | dev->last_rx = jiffies; | ||
1043 | lp->stats.rx_packets++; | ||
1044 | lp->stats.rx_bytes += pkt_len; | ||
1045 | } else { | ||
1046 | printk("%s: Insufficient memory; nuking packet.\n", dev->name); | ||
1047 | lp->stats.rx_dropped++; /* Really, deferred. */ | ||
1048 | break; | ||
1049 | } | ||
1050 | } | ||
1051 | } | ||
1052 | /* | ||
1053 | ** Return the received buffer to the free memory queue | ||
1054 | */ | ||
1055 | outb(page, EWRK3_FMQ); | ||
1056 | } else { | ||
1057 | printk("ewrk3_rx(): Illegal page number, page %d\n", page); | ||
1058 | printk("ewrk3_rx(): CSR: %02x ICR: %02x FMQC: %02x\n", inb(EWRK3_CSR), inb(EWRK3_ICR), inb(EWRK3_FMQC)); | ||
1059 | } | ||
1060 | } | ||
1061 | return status; | ||
1062 | } | ||
1063 | |||
1064 | /* | ||
1065 | ** Buffer sent - check for TX buffer errors. | ||
1066 | ** Called with lp->hw_lock held | ||
1067 | */ | ||
1068 | static int ewrk3_tx(struct net_device *dev) | ||
1069 | { | ||
1070 | struct ewrk3_private *lp = netdev_priv(dev); | ||
1071 | u_long iobase = dev->base_addr; | ||
1072 | u_char tx_status; | ||
1073 | |||
1074 | while ((tx_status = inb(EWRK3_TDQ)) > 0) { /* Whilst there's old buffers */ | ||
1075 | if (tx_status & T_VSTS) { /* The status is valid */ | ||
1076 | if (tx_status & T_TXE) { | ||
1077 | lp->stats.tx_errors++; | ||
1078 | if (tx_status & T_NCL) | ||
1079 | lp->stats.tx_carrier_errors++; | ||
1080 | if (tx_status & T_LCL) | ||
1081 | lp->stats.tx_window_errors++; | ||
1082 | if (tx_status & T_CTU) { | ||
1083 | if ((tx_status & T_COLL) ^ T_XUR) { | ||
1084 | lp->pktStats.tx_underruns++; | ||
1085 | } else { | ||
1086 | lp->pktStats.excessive_underruns++; | ||
1087 | } | ||
1088 | } else if (tx_status & T_COLL) { | ||
1089 | if ((tx_status & T_COLL) ^ T_XCOLL) { | ||
1090 | lp->stats.collisions++; | ||
1091 | } else { | ||
1092 | lp->pktStats.excessive_collisions++; | ||
1093 | } | ||
1094 | } | ||
1095 | } else { | ||
1096 | lp->stats.tx_packets++; | ||
1097 | } | ||
1098 | } | ||
1099 | } | ||
1100 | |||
1101 | return 0; | ||
1102 | } | ||
1103 | |||
1104 | static int ewrk3_close(struct net_device *dev) | ||
1105 | { | ||
1106 | struct ewrk3_private *lp = netdev_priv(dev); | ||
1107 | u_long iobase = dev->base_addr; | ||
1108 | u_char icr, csr; | ||
1109 | |||
1110 | netif_stop_queue(dev); | ||
1111 | |||
1112 | if (ewrk3_debug > 1) { | ||
1113 | printk("%s: Shutting down ethercard, status was %2.2x.\n", | ||
1114 | dev->name, inb(EWRK3_CSR)); | ||
1115 | } | ||
1116 | /* | ||
1117 | ** We stop the EWRK3 here... mask interrupts and stop TX & RX | ||
1118 | */ | ||
1119 | DISABLE_IRQs; | ||
1120 | |||
1121 | STOP_EWRK3; | ||
1122 | |||
1123 | /* | ||
1124 | ** Clean out the TX and RX queues here (note that one entry | ||
1125 | ** may get added to either the TXD or RX queues if the TX or RX | ||
1126 | ** just starts processing a packet before the STOP_EWRK3 command | ||
1127 | ** is received. This will be flushed in the ewrk3_open() call). | ||
1128 | */ | ||
1129 | while (inb(EWRK3_TQ)); | ||
1130 | while (inb(EWRK3_TDQ)); | ||
1131 | while (inb(EWRK3_RQ)); | ||
1132 | |||
1133 | if (!lp->hard_strapped) { | ||
1134 | free_irq(dev->irq, dev); | ||
1135 | } | ||
1136 | return 0; | ||
1137 | } | ||
1138 | |||
1139 | static struct net_device_stats *ewrk3_get_stats(struct net_device *dev) | ||
1140 | { | ||
1141 | struct ewrk3_private *lp = netdev_priv(dev); | ||
1142 | |||
1143 | /* Null body since there is no framing error counter */ | ||
1144 | return &lp->stats; | ||
1145 | } | ||
1146 | |||
1147 | /* | ||
1148 | ** Set or clear the multicast filter for this adapter. | ||
1149 | */ | ||
1150 | static void set_multicast_list(struct net_device *dev) | ||
1151 | { | ||
1152 | struct ewrk3_private *lp = netdev_priv(dev); | ||
1153 | u_long iobase = dev->base_addr; | ||
1154 | u_char csr; | ||
1155 | |||
1156 | csr = inb(EWRK3_CSR); | ||
1157 | |||
1158 | if (lp->shmem_length == IO_ONLY) { | ||
1159 | lp->mctbl = NULL; | ||
1160 | } else { | ||
1161 | lp->mctbl = lp->shmem + PAGE0_HTE; | ||
1162 | } | ||
1163 | |||
1164 | csr &= ~(CSR_PME | CSR_MCE); | ||
1165 | if (dev->flags & IFF_PROMISC) { /* set promiscuous mode */ | ||
1166 | csr |= CSR_PME; | ||
1167 | outb(csr, EWRK3_CSR); | ||
1168 | } else { | ||
1169 | SetMulticastFilter(dev); | ||
1170 | csr |= CSR_MCE; | ||
1171 | outb(csr, EWRK3_CSR); | ||
1172 | } | ||
1173 | } | ||
1174 | |||
1175 | /* | ||
1176 | ** Calculate the hash code and update the logical address filter | ||
1177 | ** from a list of ethernet multicast addresses. | ||
1178 | ** Little endian crc one liner from Matt Thomas, DEC. | ||
1179 | ** | ||
1180 | ** Note that when clearing the table, the broadcast bit must remain asserted | ||
1181 | ** to receive broadcast messages. | ||
1182 | */ | ||
1183 | static void SetMulticastFilter(struct net_device *dev) | ||
1184 | { | ||
1185 | struct ewrk3_private *lp = netdev_priv(dev); | ||
1186 | struct dev_mc_list *dmi = dev->mc_list; | ||
1187 | u_long iobase = dev->base_addr; | ||
1188 | int i; | ||
1189 | char *addrs, bit, byte; | ||
1190 | short __iomem *p = lp->mctbl; | ||
1191 | u16 hashcode; | ||
1192 | u32 crc; | ||
1193 | |||
1194 | spin_lock_irq(&lp->hw_lock); | ||
1195 | |||
1196 | if (lp->shmem_length == IO_ONLY) { | ||
1197 | outb(0, EWRK3_IOPR); | ||
1198 | outw(PAGE0_HTE, EWRK3_PIR1); | ||
1199 | } else { | ||
1200 | outb(0, EWRK3_MPR); | ||
1201 | } | ||
1202 | |||
1203 | if (dev->flags & IFF_ALLMULTI) { | ||
1204 | for (i = 0; i < (HASH_TABLE_LEN >> 3); i++) { | ||
1205 | if (lp->shmem_length == IO_ONLY) { | ||
1206 | outb(0xff, EWRK3_DATA); | ||
1207 | } else { /* memset didn't work here */ | ||
1208 | writew(0xffff, p); | ||
1209 | p++; | ||
1210 | i++; | ||
1211 | } | ||
1212 | } | ||
1213 | } else { | ||
1214 | /* Clear table except for broadcast bit */ | ||
1215 | if (lp->shmem_length == IO_ONLY) { | ||
1216 | for (i = 0; i < (HASH_TABLE_LEN >> 4) - 1; i++) { | ||
1217 | outb(0x00, EWRK3_DATA); | ||
1218 | } | ||
1219 | outb(0x80, EWRK3_DATA); | ||
1220 | i++; /* insert the broadcast bit */ | ||
1221 | for (; i < (HASH_TABLE_LEN >> 3); i++) { | ||
1222 | outb(0x00, EWRK3_DATA); | ||
1223 | } | ||
1224 | } else { | ||
1225 | memset_io(lp->mctbl, 0, HASH_TABLE_LEN >> 3); | ||
1226 | writeb(0x80, lp->mctbl + (HASH_TABLE_LEN >> 4) - 1); | ||
1227 | } | ||
1228 | |||
1229 | /* Update table */ | ||
1230 | for (i = 0; i < dev->mc_count; i++) { /* for each address in the list */ | ||
1231 | addrs = dmi->dmi_addr; | ||
1232 | dmi = dmi->next; | ||
1233 | if ((*addrs & 0x01) == 1) { /* multicast address? */ | ||
1234 | crc = ether_crc_le(ETH_ALEN, addrs); | ||
1235 | hashcode = crc & ((1 << 9) - 1); /* hashcode is 9 LSb of CRC */ | ||
1236 | |||
1237 | byte = hashcode >> 3; /* bit[3-8] -> byte in filter */ | ||
1238 | bit = 1 << (hashcode & 0x07); /* bit[0-2] -> bit in byte */ | ||
1239 | |||
1240 | if (lp->shmem_length == IO_ONLY) { | ||
1241 | u_char tmp; | ||
1242 | |||
1243 | outw(PAGE0_HTE + byte, EWRK3_PIR1); | ||
1244 | tmp = inb(EWRK3_DATA); | ||
1245 | tmp |= bit; | ||
1246 | outw(PAGE0_HTE + byte, EWRK3_PIR1); | ||
1247 | outb(tmp, EWRK3_DATA); | ||
1248 | } else { | ||
1249 | writeb(readb(lp->mctbl + byte) | bit, lp->mctbl + byte); | ||
1250 | } | ||
1251 | } | ||
1252 | } | ||
1253 | } | ||
1254 | |||
1255 | spin_unlock_irq(&lp->hw_lock); | ||
1256 | } | ||
1257 | |||
1258 | /* | ||
1259 | ** ISA bus I/O device probe | ||
1260 | */ | ||
1261 | static int __init isa_probe(struct net_device *dev, u_long ioaddr) | ||
1262 | { | ||
1263 | int i = num_ewrks3s, maxSlots; | ||
1264 | int ret = -ENODEV; | ||
1265 | |||
1266 | u_long iobase; | ||
1267 | |||
1268 | if (ioaddr >= 0x400) | ||
1269 | goto out; | ||
1270 | |||
1271 | if (ioaddr == 0) { /* Autoprobing */ | ||
1272 | iobase = EWRK3_IO_BASE; /* Get the first slot address */ | ||
1273 | maxSlots = 24; | ||
1274 | } else { /* Probe a specific location */ | ||
1275 | iobase = ioaddr; | ||
1276 | maxSlots = i + 1; | ||
1277 | } | ||
1278 | |||
1279 | for (; (i < maxSlots) && (dev != NULL); | ||
1280 | iobase += EWRK3_IOP_INC, i++) | ||
1281 | { | ||
1282 | if (request_region(iobase, EWRK3_TOTAL_SIZE, DRV_NAME)) { | ||
1283 | if (DevicePresent(iobase) == 0) { | ||
1284 | int irq = dev->irq; | ||
1285 | ret = ewrk3_hw_init(dev, iobase); | ||
1286 | if (!ret) | ||
1287 | break; | ||
1288 | dev->irq = irq; | ||
1289 | } | ||
1290 | release_region(iobase, EWRK3_TOTAL_SIZE); | ||
1291 | } | ||
1292 | } | ||
1293 | out: | ||
1294 | |||
1295 | return ret; | ||
1296 | } | ||
1297 | |||
1298 | /* | ||
1299 | ** EISA bus I/O device probe. Probe from slot 1 since slot 0 is usually | ||
1300 | ** the motherboard. | ||
1301 | */ | ||
1302 | static int __init eisa_probe(struct net_device *dev, u_long ioaddr) | ||
1303 | { | ||
1304 | int i, maxSlots; | ||
1305 | u_long iobase; | ||
1306 | int ret = -ENODEV; | ||
1307 | |||
1308 | if (ioaddr < 0x1000) | ||
1309 | goto out; | ||
1310 | |||
1311 | if (ioaddr == 0) { /* Autoprobing */ | ||
1312 | iobase = EISA_SLOT_INC; /* Get the first slot address */ | ||
1313 | i = 1; | ||
1314 | maxSlots = MAX_EISA_SLOTS; | ||
1315 | } else { /* Probe a specific location */ | ||
1316 | iobase = ioaddr; | ||
1317 | i = (ioaddr >> 12); | ||
1318 | maxSlots = i + 1; | ||
1319 | } | ||
1320 | |||
1321 | for (i = 1; (i < maxSlots) && (dev != NULL); i++, iobase += EISA_SLOT_INC) { | ||
1322 | if (EISA_signature(name, EISA_ID) == 0) { | ||
1323 | if (request_region(iobase, EWRK3_TOTAL_SIZE, DRV_NAME) && | ||
1324 | DevicePresent(iobase) == 0) { | ||
1325 | int irq = dev->irq; | ||
1326 | ret = ewrk3_hw_init(dev, iobase); | ||
1327 | if (!ret) | ||
1328 | break; | ||
1329 | dev->irq = irq; | ||
1330 | } | ||
1331 | release_region(iobase, EWRK3_TOTAL_SIZE); | ||
1332 | } | ||
1333 | } | ||
1334 | |||
1335 | out: | ||
1336 | return ret; | ||
1337 | } | ||
1338 | |||
1339 | |||
1340 | /* | ||
1341 | ** Read the EWRK3 EEPROM using this routine | ||
1342 | */ | ||
1343 | static int Read_EEPROM(u_long iobase, u_char eaddr) | ||
1344 | { | ||
1345 | int i; | ||
1346 | |||
1347 | outb((eaddr & 0x3f), EWRK3_PIR1); /* set up 6 bits of address info */ | ||
1348 | outb(EEPROM_RD, EWRK3_IOPR); /* issue read command */ | ||
1349 | for (i = 0; i < 5000; i++) | ||
1350 | inb(EWRK3_CSR); /* wait 1msec */ | ||
1351 | |||
1352 | return inw(EWRK3_EPROM1); /* 16 bits data return */ | ||
1353 | } | ||
1354 | |||
1355 | /* | ||
1356 | ** Write the EWRK3 EEPROM using this routine | ||
1357 | */ | ||
1358 | static int Write_EEPROM(short data, u_long iobase, u_char eaddr) | ||
1359 | { | ||
1360 | int i; | ||
1361 | |||
1362 | outb(EEPROM_WR_EN, EWRK3_IOPR); /* issue write enable command */ | ||
1363 | for (i = 0; i < 5000; i++) | ||
1364 | inb(EWRK3_CSR); /* wait 1msec */ | ||
1365 | outw(data, EWRK3_EPROM1); /* write data to register */ | ||
1366 | outb((eaddr & 0x3f), EWRK3_PIR1); /* set up 6 bits of address info */ | ||
1367 | outb(EEPROM_WR, EWRK3_IOPR); /* issue write command */ | ||
1368 | for (i = 0; i < 75000; i++) | ||
1369 | inb(EWRK3_CSR); /* wait 15msec */ | ||
1370 | outb(EEPROM_WR_DIS, EWRK3_IOPR); /* issue write disable command */ | ||
1371 | for (i = 0; i < 5000; i++) | ||
1372 | inb(EWRK3_CSR); /* wait 1msec */ | ||
1373 | |||
1374 | return 0; | ||
1375 | } | ||
1376 | |||
1377 | /* | ||
1378 | ** Look for a particular board name in the on-board EEPROM. | ||
1379 | */ | ||
1380 | static void __init EthwrkSignature(char *name, char *eeprom_image) | ||
1381 | { | ||
1382 | int i; | ||
1383 | char *signatures[] = EWRK3_SIGNATURE; | ||
1384 | |||
1385 | for (i=0; *signatures[i] != '\0'; i++) | ||
1386 | if( !strncmp(eeprom_image+EEPROM_PNAME7, signatures[i], strlen(signatures[i])) ) | ||
1387 | break; | ||
1388 | |||
1389 | if (*signatures[i] != '\0') { | ||
1390 | memcpy(name, eeprom_image+EEPROM_PNAME7, EWRK3_STRLEN); | ||
1391 | name[EWRK3_STRLEN] = '\0'; | ||
1392 | } else | ||
1393 | name[0] = '\0'; | ||
1394 | |||
1395 | return; | ||
1396 | } | ||
1397 | |||
1398 | /* | ||
1399 | ** Look for a special sequence in the Ethernet station address PROM that | ||
1400 | ** is common across all EWRK3 products. | ||
1401 | ** | ||
1402 | ** Search the Ethernet address ROM for the signature. Since the ROM address | ||
1403 | ** counter can start at an arbitrary point, the search must include the entire | ||
1404 | ** probe sequence length plus the (length_of_the_signature - 1). | ||
1405 | ** Stop the search IMMEDIATELY after the signature is found so that the | ||
1406 | ** PROM address counter is correctly positioned at the start of the | ||
1407 | ** ethernet address for later read out. | ||
1408 | */ | ||
1409 | |||
1410 | static int __init DevicePresent(u_long iobase) | ||
1411 | { | ||
1412 | union { | ||
1413 | struct { | ||
1414 | u32 a; | ||
1415 | u32 b; | ||
1416 | } llsig; | ||
1417 | char Sig[sizeof(u32) << 1]; | ||
1418 | } | ||
1419 | dev; | ||
1420 | short sigLength; | ||
1421 | char data; | ||
1422 | int i, j, status = 0; | ||
1423 | |||
1424 | dev.llsig.a = ETH_PROM_SIG; | ||
1425 | dev.llsig.b = ETH_PROM_SIG; | ||
1426 | sigLength = sizeof(u32) << 1; | ||
1427 | |||
1428 | for (i = 0, j = 0; j < sigLength && i < PROBE_LENGTH + sigLength - 1; i++) { | ||
1429 | data = inb(EWRK3_APROM); | ||
1430 | if (dev.Sig[j] == data) { /* track signature */ | ||
1431 | j++; | ||
1432 | } else { /* lost signature; begin search again */ | ||
1433 | if (data == dev.Sig[0]) { | ||
1434 | j = 1; | ||
1435 | } else { | ||
1436 | j = 0; | ||
1437 | } | ||
1438 | } | ||
1439 | } | ||
1440 | |||
1441 | if (j != sigLength) { | ||
1442 | status = -ENODEV; /* search failed */ | ||
1443 | } | ||
1444 | return status; | ||
1445 | } | ||
1446 | |||
1447 | static u_char __init get_hw_addr(struct net_device *dev, u_char * eeprom_image, char chipType) | ||
1448 | { | ||
1449 | int i, j, k; | ||
1450 | u_short chksum; | ||
1451 | u_char crc, lfsr, sd, status = 0; | ||
1452 | u_long iobase = dev->base_addr; | ||
1453 | u16 tmp; | ||
1454 | |||
1455 | if (chipType == LeMAC2) { | ||
1456 | for (crc = 0x6a, j = 0; j < ETH_ALEN; j++) { | ||
1457 | sd = dev->dev_addr[j] = eeprom_image[EEPROM_PADDR0 + j]; | ||
1458 | outb(dev->dev_addr[j], EWRK3_PAR0 + j); | ||
1459 | for (k = 0; k < 8; k++, sd >>= 1) { | ||
1460 | lfsr = ((((crc & 0x02) >> 1) ^ (crc & 0x01)) ^ (sd & 0x01)) << 7; | ||
1461 | crc = (crc >> 1) + lfsr; | ||
1462 | } | ||
1463 | } | ||
1464 | if (crc != eeprom_image[EEPROM_PA_CRC]) | ||
1465 | status = -1; | ||
1466 | } else { | ||
1467 | for (i = 0, k = 0; i < ETH_ALEN;) { | ||
1468 | k <<= 1; | ||
1469 | if (k > 0xffff) | ||
1470 | k -= 0xffff; | ||
1471 | |||
1472 | k += (u_char) (tmp = inb(EWRK3_APROM)); | ||
1473 | dev->dev_addr[i] = (u_char) tmp; | ||
1474 | outb(dev->dev_addr[i], EWRK3_PAR0 + i); | ||
1475 | i++; | ||
1476 | k += (u_short) ((tmp = inb(EWRK3_APROM)) << 8); | ||
1477 | dev->dev_addr[i] = (u_char) tmp; | ||
1478 | outb(dev->dev_addr[i], EWRK3_PAR0 + i); | ||
1479 | i++; | ||
1480 | |||
1481 | if (k > 0xffff) | ||
1482 | k -= 0xffff; | ||
1483 | } | ||
1484 | if (k == 0xffff) | ||
1485 | k = 0; | ||
1486 | chksum = inb(EWRK3_APROM); | ||
1487 | chksum |= (inb(EWRK3_APROM) << 8); | ||
1488 | if (k != chksum) | ||
1489 | status = -1; | ||
1490 | } | ||
1491 | |||
1492 | return status; | ||
1493 | } | ||
1494 | |||
1495 | /* | ||
1496 | ** Look for a particular board name in the EISA configuration space | ||
1497 | */ | ||
1498 | static int __init EISA_signature(char *name, s32 eisa_id) | ||
1499 | { | ||
1500 | u_long i; | ||
1501 | char *signatures[] = EWRK3_SIGNATURE; | ||
1502 | char ManCode[EWRK3_STRLEN]; | ||
1503 | union { | ||
1504 | s32 ID; | ||
1505 | char Id[4]; | ||
1506 | } Eisa; | ||
1507 | int status = 0; | ||
1508 | |||
1509 | *name = '\0'; | ||
1510 | for (i = 0; i < 4; i++) { | ||
1511 | Eisa.Id[i] = inb(eisa_id + i); | ||
1512 | } | ||
1513 | |||
1514 | ManCode[0] = (((Eisa.Id[0] >> 2) & 0x1f) + 0x40); | ||
1515 | ManCode[1] = (((Eisa.Id[1] & 0xe0) >> 5) + ((Eisa.Id[0] & 0x03) << 3) + 0x40); | ||
1516 | ManCode[2] = (((Eisa.Id[2] >> 4) & 0x0f) + 0x30); | ||
1517 | ManCode[3] = ((Eisa.Id[2] & 0x0f) + 0x30); | ||
1518 | ManCode[4] = (((Eisa.Id[3] >> 4) & 0x0f) + 0x30); | ||
1519 | ManCode[5] = '\0'; | ||
1520 | |||
1521 | for (i = 0; (*signatures[i] != '\0') && (*name == '\0'); i++) { | ||
1522 | if (strstr(ManCode, signatures[i]) != NULL) { | ||
1523 | strcpy(name, ManCode); | ||
1524 | status = 1; | ||
1525 | } | ||
1526 | } | ||
1527 | |||
1528 | return status; /* return the device name string */ | ||
1529 | } | ||
1530 | |||
1531 | static void ewrk3_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) | ||
1532 | { | ||
1533 | int fwrev = Read_EEPROM(dev->base_addr, EEPROM_REVLVL); | ||
1534 | |||
1535 | strcpy(info->driver, DRV_NAME); | ||
1536 | strcpy(info->version, DRV_VERSION); | ||
1537 | sprintf(info->fw_version, "%d", fwrev); | ||
1538 | strcpy(info->bus_info, "N/A"); | ||
1539 | info->eedump_len = EEPROM_MAX; | ||
1540 | } | ||
1541 | |||
1542 | static int ewrk3_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) | ||
1543 | { | ||
1544 | struct ewrk3_private *lp = netdev_priv(dev); | ||
1545 | unsigned long iobase = dev->base_addr; | ||
1546 | u8 cr = inb(EWRK3_CR); | ||
1547 | |||
1548 | switch (lp->adapter_name[4]) { | ||
1549 | case '3': /* DE203 */ | ||
1550 | ecmd->supported = SUPPORTED_BNC; | ||
1551 | ecmd->port = PORT_BNC; | ||
1552 | break; | ||
1553 | |||
1554 | case '4': /* DE204 */ | ||
1555 | ecmd->supported = SUPPORTED_TP; | ||
1556 | ecmd->port = PORT_TP; | ||
1557 | break; | ||
1558 | |||
1559 | case '5': /* DE205 */ | ||
1560 | ecmd->supported = SUPPORTED_TP | SUPPORTED_BNC | SUPPORTED_AUI; | ||
1561 | ecmd->autoneg = !(cr & CR_APD); | ||
1562 | /* | ||
1563 | ** Port is only valid if autoneg is disabled | ||
1564 | ** and even then we don't know if AUI is jumpered. | ||
1565 | */ | ||
1566 | if (!ecmd->autoneg) | ||
1567 | ecmd->port = (cr & CR_PSEL) ? PORT_BNC : PORT_TP; | ||
1568 | break; | ||
1569 | } | ||
1570 | |||
1571 | ecmd->supported |= SUPPORTED_10baseT_Half; | ||
1572 | ecmd->speed = SPEED_10; | ||
1573 | ecmd->duplex = DUPLEX_HALF; | ||
1574 | return 0; | ||
1575 | } | ||
1576 | |||
1577 | static int ewrk3_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) | ||
1578 | { | ||
1579 | struct ewrk3_private *lp = netdev_priv(dev); | ||
1580 | unsigned long iobase = dev->base_addr; | ||
1581 | unsigned long flags; | ||
1582 | u8 cr; | ||
1583 | |||
1584 | /* DE205 is the only card with anything to set */ | ||
1585 | if (lp->adapter_name[4] != '5') | ||
1586 | return -EOPNOTSUPP; | ||
1587 | |||
1588 | /* Sanity-check parameters */ | ||
1589 | if (ecmd->speed != SPEED_10) | ||
1590 | return -EINVAL; | ||
1591 | if (ecmd->port != PORT_TP && ecmd->port != PORT_BNC) | ||
1592 | return -EINVAL; /* AUI is not software-selectable */ | ||
1593 | if (ecmd->transceiver != XCVR_INTERNAL) | ||
1594 | return -EINVAL; | ||
1595 | if (ecmd->duplex != DUPLEX_HALF) | ||
1596 | return -EINVAL; | ||
1597 | if (ecmd->phy_address != 0) | ||
1598 | return -EINVAL; | ||
1599 | |||
1600 | spin_lock_irqsave(&lp->hw_lock, flags); | ||
1601 | cr = inb(EWRK3_CR); | ||
1602 | |||
1603 | /* If Autoneg is set, change to Auto Port mode */ | ||
1604 | /* Otherwise, disable Auto Port and set port explicitly */ | ||
1605 | if (ecmd->autoneg) { | ||
1606 | cr &= ~CR_APD; | ||
1607 | } else { | ||
1608 | cr |= CR_APD; | ||
1609 | if (ecmd->port == PORT_TP) | ||
1610 | cr &= ~CR_PSEL; /* Force TP */ | ||
1611 | else | ||
1612 | cr |= CR_PSEL; /* Force BNC */ | ||
1613 | } | ||
1614 | |||
1615 | /* Commit the changes */ | ||
1616 | outb(cr, EWRK3_CR); | ||
1617 | spin_unlock_irqrestore(&lp->hw_lock, flags); | ||
1618 | return 0; | ||
1619 | } | ||
1620 | |||
1621 | static u32 ewrk3_get_link(struct net_device *dev) | ||
1622 | { | ||
1623 | unsigned long iobase = dev->base_addr; | ||
1624 | u8 cmr = inb(EWRK3_CMR); | ||
1625 | /* DE203 has BNC only and link status does not apply */ | ||
1626 | /* On DE204 this is always valid since TP is the only port. */ | ||
1627 | /* On DE205 this reflects TP status even if BNC or AUI is selected. */ | ||
1628 | return !(cmr & CMR_LINK); | ||
1629 | } | ||
1630 | |||
1631 | static int ewrk3_phys_id(struct net_device *dev, u32 data) | ||
1632 | { | ||
1633 | struct ewrk3_private *lp = netdev_priv(dev); | ||
1634 | unsigned long iobase = dev->base_addr; | ||
1635 | unsigned long flags; | ||
1636 | u8 cr; | ||
1637 | int count; | ||
1638 | |||
1639 | /* Toggle LED 4x per second */ | ||
1640 | count = data << 2; | ||
1641 | |||
1642 | spin_lock_irqsave(&lp->hw_lock, flags); | ||
1643 | |||
1644 | /* Bail if a PHYS_ID is already in progress */ | ||
1645 | if (lp->led_mask == 0) { | ||
1646 | spin_unlock_irqrestore(&lp->hw_lock, flags); | ||
1647 | return -EBUSY; | ||
1648 | } | ||
1649 | |||
1650 | /* Prevent ISR from twiddling the LED */ | ||
1651 | lp->led_mask = 0; | ||
1652 | |||
1653 | while (count--) { | ||
1654 | /* Toggle the LED */ | ||
1655 | cr = inb(EWRK3_CR); | ||
1656 | outb(cr ^ CR_LED, EWRK3_CR); | ||
1657 | |||
1658 | /* Wait a little while */ | ||
1659 | spin_unlock_irqrestore(&lp->hw_lock, flags); | ||
1660 | msleep(250); | ||
1661 | spin_lock_irqsave(&lp->hw_lock, flags); | ||
1662 | |||
1663 | /* Exit if we got a signal */ | ||
1664 | if (signal_pending(current)) | ||
1665 | break; | ||
1666 | } | ||
1667 | |||
1668 | lp->led_mask = CR_LED; | ||
1669 | cr = inb(EWRK3_CR); | ||
1670 | outb(cr & ~CR_LED, EWRK3_CR); | ||
1671 | spin_unlock_irqrestore(&lp->hw_lock, flags); | ||
1672 | return signal_pending(current) ? -ERESTARTSYS : 0; | ||
1673 | } | ||
1674 | |||
1675 | static struct ethtool_ops ethtool_ops_203 = { | ||
1676 | .get_drvinfo = ewrk3_get_drvinfo, | ||
1677 | .get_settings = ewrk3_get_settings, | ||
1678 | .set_settings = ewrk3_set_settings, | ||
1679 | .phys_id = ewrk3_phys_id, | ||
1680 | }; | ||
1681 | |||
1682 | static struct ethtool_ops ethtool_ops = { | ||
1683 | .get_drvinfo = ewrk3_get_drvinfo, | ||
1684 | .get_settings = ewrk3_get_settings, | ||
1685 | .set_settings = ewrk3_set_settings, | ||
1686 | .get_link = ewrk3_get_link, | ||
1687 | .phys_id = ewrk3_phys_id, | ||
1688 | }; | ||
1689 | |||
1690 | /* | ||
1691 | ** Perform IOCTL call functions here. Some are privileged operations and the | ||
1692 | ** effective uid is checked in those cases. | ||
1693 | */ | ||
1694 | static int ewrk3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | ||
1695 | { | ||
1696 | struct ewrk3_private *lp = netdev_priv(dev); | ||
1697 | struct ewrk3_ioctl *ioc = (struct ewrk3_ioctl *) &rq->ifr_ifru; | ||
1698 | u_long iobase = dev->base_addr; | ||
1699 | int i, j, status = 0; | ||
1700 | u_char csr; | ||
1701 | unsigned long flags; | ||
1702 | union ewrk3_addr { | ||
1703 | u_char addr[HASH_TABLE_LEN * ETH_ALEN]; | ||
1704 | u_short val[(HASH_TABLE_LEN * ETH_ALEN) >> 1]; | ||
1705 | }; | ||
1706 | |||
1707 | union ewrk3_addr *tmp; | ||
1708 | |||
1709 | /* All we handle are private IOCTLs */ | ||
1710 | if (cmd != EWRK3IOCTL) | ||
1711 | return -EOPNOTSUPP; | ||
1712 | |||
1713 | tmp = kmalloc(sizeof(union ewrk3_addr), GFP_KERNEL); | ||
1714 | if(tmp==NULL) | ||
1715 | return -ENOMEM; | ||
1716 | |||
1717 | switch (ioc->cmd) { | ||
1718 | case EWRK3_GET_HWADDR: /* Get the hardware address */ | ||
1719 | for (i = 0; i < ETH_ALEN; i++) { | ||
1720 | tmp->addr[i] = dev->dev_addr[i]; | ||
1721 | } | ||
1722 | ioc->len = ETH_ALEN; | ||
1723 | if (copy_to_user(ioc->data, tmp->addr, ioc->len)) | ||
1724 | status = -EFAULT; | ||
1725 | break; | ||
1726 | |||
1727 | case EWRK3_SET_HWADDR: /* Set the hardware address */ | ||
1728 | if (capable(CAP_NET_ADMIN)) { | ||
1729 | spin_lock_irqsave(&lp->hw_lock, flags); | ||
1730 | csr = inb(EWRK3_CSR); | ||
1731 | csr |= (CSR_TXD | CSR_RXD); | ||
1732 | outb(csr, EWRK3_CSR); /* Disable the TX and RX */ | ||
1733 | spin_unlock_irqrestore(&lp->hw_lock, flags); | ||
1734 | |||
1735 | if (copy_from_user(tmp->addr, ioc->data, ETH_ALEN)) { | ||
1736 | status = -EFAULT; | ||
1737 | break; | ||
1738 | } | ||
1739 | spin_lock_irqsave(&lp->hw_lock, flags); | ||
1740 | for (i = 0; i < ETH_ALEN; i++) { | ||
1741 | dev->dev_addr[i] = tmp->addr[i]; | ||
1742 | outb(tmp->addr[i], EWRK3_PAR0 + i); | ||
1743 | } | ||
1744 | |||
1745 | csr = inb(EWRK3_CSR); | ||
1746 | csr &= ~(CSR_TXD | CSR_RXD); /* Enable the TX and RX */ | ||
1747 | outb(csr, EWRK3_CSR); | ||
1748 | spin_unlock_irqrestore(&lp->hw_lock, flags); | ||
1749 | } else { | ||
1750 | status = -EPERM; | ||
1751 | } | ||
1752 | |||
1753 | break; | ||
1754 | case EWRK3_SET_PROM: /* Set Promiscuous Mode */ | ||
1755 | if (capable(CAP_NET_ADMIN)) { | ||
1756 | spin_lock_irqsave(&lp->hw_lock, flags); | ||
1757 | csr = inb(EWRK3_CSR); | ||
1758 | csr |= CSR_PME; | ||
1759 | csr &= ~CSR_MCE; | ||
1760 | outb(csr, EWRK3_CSR); | ||
1761 | spin_unlock_irqrestore(&lp->hw_lock, flags); | ||
1762 | } else { | ||
1763 | status = -EPERM; | ||
1764 | } | ||
1765 | |||
1766 | break; | ||
1767 | case EWRK3_CLR_PROM: /* Clear Promiscuous Mode */ | ||
1768 | if (capable(CAP_NET_ADMIN)) { | ||
1769 | spin_lock_irqsave(&lp->hw_lock, flags); | ||
1770 | csr = inb(EWRK3_CSR); | ||
1771 | csr &= ~CSR_PME; | ||
1772 | outb(csr, EWRK3_CSR); | ||
1773 | spin_unlock_irqrestore(&lp->hw_lock, flags); | ||
1774 | } else { | ||
1775 | status = -EPERM; | ||
1776 | } | ||
1777 | |||
1778 | break; | ||
1779 | case EWRK3_GET_MCA: /* Get the multicast address table */ | ||
1780 | spin_lock_irqsave(&lp->hw_lock, flags); | ||
1781 | if (lp->shmem_length == IO_ONLY) { | ||
1782 | outb(0, EWRK3_IOPR); | ||
1783 | outw(PAGE0_HTE, EWRK3_PIR1); | ||
1784 | for (i = 0; i < (HASH_TABLE_LEN >> 3); i++) { | ||
1785 | tmp->addr[i] = inb(EWRK3_DATA); | ||
1786 | } | ||
1787 | } else { | ||
1788 | outb(0, EWRK3_MPR); | ||
1789 | memcpy_fromio(tmp->addr, lp->shmem + PAGE0_HTE, (HASH_TABLE_LEN >> 3)); | ||
1790 | } | ||
1791 | spin_unlock_irqrestore(&lp->hw_lock, flags); | ||
1792 | |||
1793 | ioc->len = (HASH_TABLE_LEN >> 3); | ||
1794 | if (copy_to_user(ioc->data, tmp->addr, ioc->len)) | ||
1795 | status = -EFAULT; | ||
1796 | |||
1797 | break; | ||
1798 | case EWRK3_SET_MCA: /* Set a multicast address */ | ||
1799 | if (capable(CAP_NET_ADMIN)) { | ||
1800 | if (ioc->len > 1024) | ||
1801 | { | ||
1802 | status = -EINVAL; | ||
1803 | break; | ||
1804 | } | ||
1805 | if (copy_from_user(tmp->addr, ioc->data, ETH_ALEN * ioc->len)) { | ||
1806 | status = -EFAULT; | ||
1807 | break; | ||
1808 | } | ||
1809 | set_multicast_list(dev); | ||
1810 | } else { | ||
1811 | status = -EPERM; | ||
1812 | } | ||
1813 | |||
1814 | break; | ||
1815 | case EWRK3_CLR_MCA: /* Clear all multicast addresses */ | ||
1816 | if (capable(CAP_NET_ADMIN)) { | ||
1817 | set_multicast_list(dev); | ||
1818 | } else { | ||
1819 | status = -EPERM; | ||
1820 | } | ||
1821 | |||
1822 | break; | ||
1823 | case EWRK3_MCA_EN: /* Enable multicast addressing */ | ||
1824 | if (capable(CAP_NET_ADMIN)) { | ||
1825 | spin_lock_irqsave(&lp->hw_lock, flags); | ||
1826 | csr = inb(EWRK3_CSR); | ||
1827 | csr |= CSR_MCE; | ||
1828 | csr &= ~CSR_PME; | ||
1829 | outb(csr, EWRK3_CSR); | ||
1830 | spin_unlock_irqrestore(&lp->hw_lock, flags); | ||
1831 | } else { | ||
1832 | status = -EPERM; | ||
1833 | } | ||
1834 | |||
1835 | break; | ||
1836 | case EWRK3_GET_STATS: { /* Get the driver statistics */ | ||
1837 | struct ewrk3_stats *tmp_stats = | ||
1838 | kmalloc(sizeof(lp->pktStats), GFP_KERNEL); | ||
1839 | if (!tmp_stats) { | ||
1840 | status = -ENOMEM; | ||
1841 | break; | ||
1842 | } | ||
1843 | |||
1844 | spin_lock_irqsave(&lp->hw_lock, flags); | ||
1845 | memcpy(tmp_stats, &lp->pktStats, sizeof(lp->pktStats)); | ||
1846 | spin_unlock_irqrestore(&lp->hw_lock, flags); | ||
1847 | |||
1848 | ioc->len = sizeof(lp->pktStats); | ||
1849 | if (copy_to_user(ioc->data, tmp_stats, sizeof(lp->pktStats))) | ||
1850 | status = -EFAULT; | ||
1851 | kfree(tmp_stats); | ||
1852 | break; | ||
1853 | } | ||
1854 | case EWRK3_CLR_STATS: /* Zero out the driver statistics */ | ||
1855 | if (capable(CAP_NET_ADMIN)) { | ||
1856 | spin_lock_irqsave(&lp->hw_lock, flags); | ||
1857 | memset(&lp->pktStats, 0, sizeof(lp->pktStats)); | ||
1858 | spin_unlock_irqrestore(&lp->hw_lock,flags); | ||
1859 | } else { | ||
1860 | status = -EPERM; | ||
1861 | } | ||
1862 | |||
1863 | break; | ||
1864 | case EWRK3_GET_CSR: /* Get the CSR Register contents */ | ||
1865 | tmp->addr[0] = inb(EWRK3_CSR); | ||
1866 | ioc->len = 1; | ||
1867 | if (copy_to_user(ioc->data, tmp->addr, ioc->len)) | ||
1868 | status = -EFAULT; | ||
1869 | break; | ||
1870 | case EWRK3_SET_CSR: /* Set the CSR Register contents */ | ||
1871 | if (capable(CAP_NET_ADMIN)) { | ||
1872 | if (copy_from_user(tmp->addr, ioc->data, 1)) { | ||
1873 | status = -EFAULT; | ||
1874 | break; | ||
1875 | } | ||
1876 | outb(tmp->addr[0], EWRK3_CSR); | ||
1877 | } else { | ||
1878 | status = -EPERM; | ||
1879 | } | ||
1880 | |||
1881 | break; | ||
1882 | case EWRK3_GET_EEPROM: /* Get the EEPROM contents */ | ||
1883 | if (capable(CAP_NET_ADMIN)) { | ||
1884 | for (i = 0; i < (EEPROM_MAX >> 1); i++) { | ||
1885 | tmp->val[i] = (short) Read_EEPROM(iobase, i); | ||
1886 | } | ||
1887 | i = EEPROM_MAX; | ||
1888 | tmp->addr[i++] = inb(EWRK3_CMR); /* Config/Management Reg. */ | ||
1889 | for (j = 0; j < ETH_ALEN; j++) { | ||
1890 | tmp->addr[i++] = inb(EWRK3_PAR0 + j); | ||
1891 | } | ||
1892 | ioc->len = EEPROM_MAX + 1 + ETH_ALEN; | ||
1893 | if (copy_to_user(ioc->data, tmp->addr, ioc->len)) | ||
1894 | status = -EFAULT; | ||
1895 | } else { | ||
1896 | status = -EPERM; | ||
1897 | } | ||
1898 | |||
1899 | break; | ||
1900 | case EWRK3_SET_EEPROM: /* Set the EEPROM contents */ | ||
1901 | if (capable(CAP_NET_ADMIN)) { | ||
1902 | if (copy_from_user(tmp->addr, ioc->data, EEPROM_MAX)) { | ||
1903 | status = -EFAULT; | ||
1904 | break; | ||
1905 | } | ||
1906 | for (i = 0; i < (EEPROM_MAX >> 1); i++) { | ||
1907 | Write_EEPROM(tmp->val[i], iobase, i); | ||
1908 | } | ||
1909 | } else { | ||
1910 | status = -EPERM; | ||
1911 | } | ||
1912 | |||
1913 | break; | ||
1914 | case EWRK3_GET_CMR: /* Get the CMR Register contents */ | ||
1915 | tmp->addr[0] = inb(EWRK3_CMR); | ||
1916 | ioc->len = 1; | ||
1917 | if (copy_to_user(ioc->data, tmp->addr, ioc->len)) | ||
1918 | status = -EFAULT; | ||
1919 | break; | ||
1920 | case EWRK3_SET_TX_CUT_THRU: /* Set TX cut through mode */ | ||
1921 | if (capable(CAP_NET_ADMIN)) { | ||
1922 | lp->txc = 1; | ||
1923 | } else { | ||
1924 | status = -EPERM; | ||
1925 | } | ||
1926 | |||
1927 | break; | ||
1928 | case EWRK3_CLR_TX_CUT_THRU: /* Clear TX cut through mode */ | ||
1929 | if (capable(CAP_NET_ADMIN)) { | ||
1930 | lp->txc = 0; | ||
1931 | } else { | ||
1932 | status = -EPERM; | ||
1933 | } | ||
1934 | |||
1935 | break; | ||
1936 | default: | ||
1937 | status = -EOPNOTSUPP; | ||
1938 | } | ||
1939 | kfree(tmp); | ||
1940 | return status; | ||
1941 | } | ||
1942 | |||
1943 | #ifdef MODULE | ||
1944 | static struct net_device *ewrk3_devs[MAX_NUM_EWRK3S]; | ||
1945 | static int ndevs; | ||
1946 | static int io[MAX_NUM_EWRK3S+1] = { 0x300, 0, }; | ||
1947 | |||
1948 | /* '21' below should really be 'MAX_NUM_EWRK3S' */ | ||
1949 | module_param_array(io, int, NULL, 0); | ||
1950 | module_param_array(irq, int, NULL, 0); | ||
1951 | MODULE_PARM_DESC(io, "EtherWORKS 3 I/O base address(es)"); | ||
1952 | MODULE_PARM_DESC(irq, "EtherWORKS 3 IRQ number(s)"); | ||
1953 | |||
1954 | static __exit void ewrk3_exit_module(void) | ||
1955 | { | ||
1956 | int i; | ||
1957 | |||
1958 | for( i=0; i<ndevs; i++ ) { | ||
1959 | struct net_device *dev = ewrk3_devs[i]; | ||
1960 | struct ewrk3_private *lp = netdev_priv(dev); | ||
1961 | ewrk3_devs[i] = NULL; | ||
1962 | unregister_netdev(dev); | ||
1963 | release_region(dev->base_addr, EWRK3_TOTAL_SIZE); | ||
1964 | iounmap(lp->shmem); | ||
1965 | free_netdev(dev); | ||
1966 | } | ||
1967 | } | ||
1968 | |||
1969 | static __init int ewrk3_init_module(void) | ||
1970 | { | ||
1971 | int i=0; | ||
1972 | |||
1973 | while( io[i] && irq[i] ) { | ||
1974 | struct net_device *dev | ||
1975 | = alloc_etherdev(sizeof(struct ewrk3_private)); | ||
1976 | |||
1977 | if (!dev) | ||
1978 | break; | ||
1979 | |||
1980 | if (ewrk3_probe1(dev, io[i], irq[i]) != 0) { | ||
1981 | free_netdev(dev); | ||
1982 | break; | ||
1983 | } | ||
1984 | |||
1985 | ewrk3_devs[ndevs++] = dev; | ||
1986 | i++; | ||
1987 | } | ||
1988 | |||
1989 | return ndevs ? 0 : -EIO; | ||
1990 | } | ||
1991 | |||
1992 | |||
1993 | /* Hack for breakage in new module stuff */ | ||
1994 | module_exit(ewrk3_exit_module); | ||
1995 | module_init(ewrk3_init_module); | ||
1996 | #endif /* MODULE */ | ||
1997 | MODULE_LICENSE("GPL"); | ||
1998 | |||
1999 | |||
2000 | |||
2001 | /* | ||
2002 | * Local variables: | ||
2003 | * compile-command: "gcc -D__KERNEL__ -I/linux/include -Wall -Wstrict-prototypes -fomit-frame-pointer -fno-strength-reduce -malign-loops=2 -malign-jumps=2 -malign-functions=2 -O2 -m486 -c ewrk3.c" | ||
2004 | * | ||
2005 | * compile-command: "gcc -D__KERNEL__ -DMODULE -I/linux/include -Wall -Wstrict-prototypes -fomit-frame-pointer -fno-strength-reduce -malign-loops=2 -malign-jumps=2 -malign-functions=2 -O2 -m486 -c ewrk3.c" | ||
2006 | * End: | ||
2007 | */ | ||