File: | obj-scan-build/../linux/src/drivers/net/ewrk3.c |
Location: | line 1345, column 5 |
Description: | Value stored to 'i' is never read |
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 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 | 6) run the net startup bits for your new eth?? interface manually |
80 | (usually /etc/rc.inet[12] at boot time). |
81 | 7) enjoy! |
82 | |
83 | Note that autoprobing is not allowed in loadable modules - the system is |
84 | already up and running and you're messing with interrupts. |
85 | |
86 | To unload a module, turn off the associated interface |
87 | 'ifconfig eth?? down' then 'rmmod ewrk3'. |
88 | |
89 | Promiscuous mode has been turned off in this driver, but all the |
90 | multicast address bits have been turned on. This improved the send |
91 | performance on a busy network by about 13%. |
92 | |
93 | Ioctl's have now been provided (primarily because I wanted to grab some |
94 | packet size statistics). They are patterned after 'plipconfig.c' from a |
95 | suggestion by Alan Cox. Using these ioctls, you can enable promiscuous |
96 | mode, add/delete multicast addresses, change the hardware address, get |
97 | packet size distribution statistics and muck around with the control and |
98 | status register. I'll add others if and when the need arises. |
99 | |
100 | TO DO: |
101 | ------ |
102 | |
103 | |
104 | Revision History |
105 | ---------------- |
106 | |
107 | Version Date Description |
108 | |
109 | 0.1 26-aug-94 Initial writing. ALPHA code release. |
110 | 0.11 31-aug-94 Fixed: 2k mode memory base calc., |
111 | LeMAC version calc., |
112 | IRQ vector assignments during autoprobe. |
113 | 0.12 31-aug-94 Tested working on LeMAC2 (DE20[345]-AC) card. |
114 | Fixed up MCA hash table algorithm. |
115 | 0.20 4-sep-94 Added IOCTL functionality. |
116 | 0.21 14-sep-94 Added I/O mode. |
117 | 0.21axp 15-sep-94 Special version for ALPHA AXP Linux V1.0. |
118 | 0.22 16-sep-94 Added more IOCTLs & tidied up. |
119 | 0.23 21-sep-94 Added transmit cut through. |
120 | 0.24 31-oct-94 Added uid checks in some ioctls. |
121 | 0.30 1-nov-94 BETA code release. |
122 | 0.31 5-dec-94 Added check/allocate region code. |
123 | 0.32 16-jan-95 Broadcast packet fix. |
124 | 0.33 10-Feb-95 Fix recognition bug reported by <bkm@star.rl.ac.uk>. |
125 | 0.40 27-Dec-95 Rationalise MODULE and autoprobe code. |
126 | Rewrite for portability & updated. |
127 | ALPHA support from <jestabro@amt.tay1.dec.com> |
128 | Added verify_area() calls in ewrk3_ioctl() from |
129 | suggestion by <heiko@colossus.escape.de>. |
130 | Add new multicasting code. |
131 | 0.41 20-Jan-96 Fix IRQ set up problem reported by |
132 | <kenneth@bbs.sas.ntu.ac.sg>. |
133 | 0.42 22-Apr-96 Fix alloc_device() bug <jari@markkus2.fimr.fi> |
134 | 0.43 16-Aug-96 Update alloc_device() to conform to de4x5.c |
135 | |
136 | ========================================================================= |
137 | */ |
138 | |
139 | static const char *version = "ewrk3.c:v0.43 96/8/16 davies@maniac.ultranet.com\n"; |
140 | |
141 | #include <linux/module.h> |
142 | |
143 | #include <linux/kernel.h> |
144 | #include <linux/sched.h> |
145 | #include <linux/string.h> |
146 | #include <linux/ptrace.h> |
147 | #include <linux/errno.h> |
148 | #include <linux/ioport.h> |
149 | #include <linux/malloc.h> |
150 | #include <linux/interrupt.h> |
151 | #include <linux/delay.h> |
152 | #include <asm/bitops.h> |
153 | #include <asm/io.h> |
154 | #include <asm/dma.h> |
155 | #include <asm/segment.h> |
156 | |
157 | #include <linux/netdevice.h> |
158 | #include <linux/etherdevice.h> |
159 | #include <linux/skbuff.h> |
160 | |
161 | #include <linux/time.h> |
162 | #include <linux/types.h> |
163 | #include <linux/unistd.h> |
164 | #include <linux/ctype.h> |
165 | |
166 | #include "ewrk3.h" |
167 | |
168 | #ifdef EWRK3_DEBUG |
169 | static int ewrk3_debug = EWRK3_DEBUG; |
170 | #else |
171 | static int ewrk3_debug = 1; |
172 | #endif |
173 | |
174 | #define EWRK3_NDA0xffe0 0xffe0 /* No Device Address */ |
175 | |
176 | #define PROBE_LENGTH32 32 |
177 | #define ETH_PROM_SIG0xAA5500FFUL 0xAA5500FFUL |
178 | |
179 | #ifndef EWRK3_SIGNATURE{"DE203","DE204","DE205",""} |
180 | #define EWRK3_SIGNATURE{"DE203","DE204","DE205",""} {"DE203","DE204","DE205",""} |
181 | #define EWRK3_STRLEN8 8 |
182 | #endif |
183 | |
184 | #ifndef EWRK3_RAM_BASE_ADDRESSES{0xc0000,0xd0000,0x00000} |
185 | #define EWRK3_RAM_BASE_ADDRESSES{0xc0000,0xd0000,0x00000} {0xc0000,0xd0000,0x00000} |
186 | #endif |
187 | |
188 | /* |
189 | ** Sets up the I/O area for the autoprobe. |
190 | */ |
191 | #define EWRK3_IO_BASE0x100 0x100 /* Start address for probe search */ |
192 | #define EWRK3_IOP_INC0x20 0x20 /* I/O address increment */ |
193 | #define EWRK3_TOTAL_SIZE0x20 0x20 /* required I/O address length */ |
194 | |
195 | #ifndef MAX_NUM_EWRK3S21 |
196 | #define MAX_NUM_EWRK3S21 21 |
197 | #endif |
198 | |
199 | #ifndef EWRK3_EISA_IO_PORTS0x0c00 |
200 | #define EWRK3_EISA_IO_PORTS0x0c00 0x0c00 /* I/O port base address, slot 0 */ |
201 | #endif |
202 | |
203 | #ifndef MAX_EISA_SLOTS16 |
204 | #define MAX_EISA_SLOTS16 16 |
205 | #define EISA_SLOT_INC0x1000 0x1000 |
206 | #endif |
207 | |
208 | #define CRC_POLYNOMIAL_BE0x04c11db7UL 0x04c11db7UL /* Ethernet CRC, big endian */ |
209 | #define CRC_POLYNOMIAL_LE0xedb88320UL 0xedb88320UL /* Ethernet CRC, little endian */ |
210 | |
211 | #define QUEUE_PKT_TIMEOUT(1*100) (1*HZ100) /* Jiffies */ |
212 | |
213 | /* |
214 | ** EtherWORKS 3 shared memory window sizes |
215 | */ |
216 | #define IO_ONLY0x00 0x00 |
217 | #define SHMEM_2K0x800 0x800 |
218 | #define SHMEM_32K0x8000 0x8000 |
219 | #define SHMEM_64K0x10000 0x10000 |
220 | |
221 | /* |
222 | ** EtherWORKS 3 IRQ ENABLE/DISABLE |
223 | */ |
224 | #define ENABLE_IRQs{ icr |= lp->irq_mask; ((__builtin_constant_p((iobase+0x02 )) && (iobase+0x02) < 256) ? __outbc((icr),(iobase +0x02)) : __outb((icr),(iobase+0x02))); } { \ |
225 | icr |= lp->irq_mask;\ |
226 | outb(icr, EWRK3_ICR)((__builtin_constant_p((iobase+0x02)) && (iobase+0x02 ) < 256) ? __outbc((icr),(iobase+0x02)) : __outb((icr),(iobase +0x02))); /* Enable the IRQs */\ |
227 | } |
228 | |
229 | #define DISABLE_IRQs{ icr = ((__builtin_constant_p((iobase+0x02)) && (iobase +0x02) < 256) ? __inbc(iobase+0x02) : __inb(iobase+0x02)); icr &= ~lp->irq_mask; ((__builtin_constant_p((iobase+ 0x02)) && (iobase+0x02) < 256) ? __outbc((icr),(iobase +0x02)) : __outb((icr),(iobase+0x02))); } { \ |
230 | icr = inb(EWRK3_ICR)((__builtin_constant_p((iobase+0x02)) && (iobase+0x02 ) < 256) ? __inbc(iobase+0x02) : __inb(iobase+0x02));\ |
231 | icr &= ~lp->irq_mask;\ |
232 | outb(icr, EWRK3_ICR)((__builtin_constant_p((iobase+0x02)) && (iobase+0x02 ) < 256) ? __outbc((icr),(iobase+0x02)) : __outb((icr),(iobase +0x02))); /* Disable the IRQs */\ |
233 | } |
234 | |
235 | /* |
236 | ** EtherWORKS 3 START/STOP |
237 | */ |
238 | #define START_EWRK3{ csr = ((__builtin_constant_p((iobase+0x00)) && (iobase +0x00) < 256) ? __inbc(iobase+0x00) : __inb(iobase+0x00)); csr &= ~(0x02|0x01); ((__builtin_constant_p((iobase+0x00 )) && (iobase+0x00) < 256) ? __outbc((csr),(iobase +0x00)) : __outb((csr),(iobase+0x00))); } { \ |
239 | csr = inb(EWRK3_CSR)((__builtin_constant_p((iobase+0x00)) && (iobase+0x00 ) < 256) ? __inbc(iobase+0x00) : __inb(iobase+0x00));\ |
240 | csr &= ~(CSR_TXD0x02|CSR_RXD0x01);\ |
241 | outb(csr, EWRK3_CSR)((__builtin_constant_p((iobase+0x00)) && (iobase+0x00 ) < 256) ? __outbc((csr),(iobase+0x00)) : __outb((csr),(iobase +0x00))); /* Enable the TX and/or RX */\ |
242 | } |
243 | |
244 | #define STOP_EWRK3{ csr = (0x02|0x01); ((__builtin_constant_p((iobase+0x00)) && (iobase+0x00) < 256) ? __outbc((csr),(iobase+0x00)) : __outb ((csr),(iobase+0x00))); } { \ |
245 | csr = (CSR_TXD0x02|CSR_RXD0x01);\ |
246 | outb(csr, EWRK3_CSR)((__builtin_constant_p((iobase+0x00)) && (iobase+0x00 ) < 256) ? __outbc((csr),(iobase+0x00)) : __outb((csr),(iobase +0x00))); /* Disable the TX and/or RX */\ |
247 | } |
248 | |
249 | /* |
250 | ** The EtherWORKS 3 private structure |
251 | */ |
252 | #define EWRK3_PKT_STAT_SZ16 16 |
253 | #define EWRK3_PKT_BIN_SZ128 128 /* Should be >=100 unless you |
254 | increase EWRK3_PKT_STAT_SZ */ |
255 | |
256 | struct ewrk3_private { |
257 | char adapter_name[80]; /* Name exported to /proc/ioports */ |
258 | u_long shmem_base; /* Shared memory start address */ |
259 | u_long shmem_length; /* Shared memory window length */ |
260 | struct enet_statistics stats; /* Public stats */ |
261 | struct { |
262 | u32 bins[EWRK3_PKT_STAT_SZ16]; /* Private stats counters */ |
263 | u32 unicast; |
264 | u32 multicast; |
265 | u32 broadcast; |
266 | u32 excessive_collisions; |
267 | u32 tx_underruns; |
268 | u32 excessive_underruns; |
269 | } pktStats; |
270 | u_char irq_mask; /* Adapter IRQ mask bits */ |
271 | u_char mPage; /* Maximum 2kB Page number */ |
272 | u_char lemac; /* Chip rev. level */ |
273 | u_char hard_strapped; /* Don't allow a full open */ |
274 | u_char lock; /* Lock the page register */ |
275 | u_char txc; /* Transmit cut through */ |
276 | u_char *mctbl; /* Pointer to the multicast table */ |
277 | }; |
278 | |
279 | /* |
280 | ** Force the EtherWORKS 3 card to be in 2kB MODE |
281 | */ |
282 | #define FORCE_2K_MODE{ shmem_length = 0x800; ((__builtin_constant_p((iobase+0x14)) && (iobase+0x14) < 256) ? __outbc((((mem_start - 0x80000 ) >> 11)),(iobase+0x14)) : __outb((((mem_start - 0x80000 ) >> 11)),(iobase+0x14)));} { \ |
283 | shmem_length = SHMEM_2K0x800;\ |
284 | outb(((mem_start - 0x80000) >> 11), EWRK3_MBR)((__builtin_constant_p((iobase+0x14)) && (iobase+0x14 ) < 256) ? __outbc((((mem_start - 0x80000) >> 11)),( iobase+0x14)) : __outb((((mem_start - 0x80000) >> 11)), (iobase+0x14)));\ |
285 | } |
286 | |
287 | /* |
288 | ** Public Functions |
289 | */ |
290 | static int ewrk3_open(struct devicelinux_device *dev); |
291 | static int ewrk3_queue_pkt(struct sk_buff *skb, struct devicelinux_device *dev); |
292 | static void ewrk3_interrupt(int irq, void *dev_id, struct pt_regs *regs); |
293 | static int ewrk3_close(struct devicelinux_device *dev); |
294 | static struct enet_statistics *ewrk3_get_stats(struct devicelinux_device *dev); |
295 | static void set_multicast_list(struct devicelinux_device *dev); |
296 | static int ewrk3_ioctl(struct devicelinux_device *dev, struct ifreq *rq, int cmd); |
297 | |
298 | /* |
299 | ** Private functions |
300 | */ |
301 | static int ewrk3_hw_init(struct devicelinux_device *dev, u_long iobase); |
302 | static void ewrk3_init(struct devicelinux_device *dev); |
303 | static int ewrk3_rx(struct devicelinux_device *dev); |
304 | static int ewrk3_tx(struct devicelinux_device *dev); |
305 | |
306 | static void EthwrkSignature(char * name, char *eeprom_image); |
307 | static int DevicePresent(u_long iobase); |
308 | static void SetMulticastFilter(struct devicelinux_device *dev); |
309 | static int EISA_signature(char *name, s32 eisa_id); |
310 | |
311 | static int Read_EEPROM(u_long iobase, u_char eaddr); |
312 | static int Write_EEPROM(short data, u_long iobase, u_char eaddr); |
313 | static u_char get_hw_addr (struct devicelinux_device *dev, u_char *eeprom_image, char chipType); |
314 | |
315 | static void isa_probe(struct devicelinux_device *dev, u_long iobase); |
316 | static void eisa_probe(struct devicelinux_device *dev, u_long iobase); |
317 | static struct devicelinux_device *alloc_device(struct devicelinux_device *dev, u_long iobase); |
318 | static int ewrk3_dev_index(char *s); |
319 | static struct devicelinux_device *insert_device(struct devicelinux_device *dev, u_long iobase, int (*init)(struct devicelinux_device *)); |
320 | |
321 | |
322 | #ifdef MODULE |
323 | int init_module(void); |
324 | void cleanup_module(void); |
325 | static int autoprobed = 1, loading_module = 1; |
326 | |
327 | # else |
328 | static u_char irq[] = {5,0,10,3,11,9,15,12}; |
329 | static int autoprobed = 0, loading_module = 0; |
330 | |
331 | #endif /* MODULE */ |
332 | |
333 | static char name[EWRK3_STRLEN8 + 1]; |
334 | static int num_ewrk3s = 0, num_eth = 0; |
335 | |
336 | /* |
337 | ** Miscellaneous defines... |
338 | */ |
339 | #define INIT_EWRK3{ ((__builtin_constant_p((iobase+0x11)) && (iobase+0x11 ) < 256) ? __outbc((0xc0),(iobase+0x11)) : __outb((0xc0),( iobase+0x11))); (__builtin_constant_p(1000) ? __const_udelay( (1000) * 0x10c6ul) : __udelay(1000));} {\ |
340 | outb(EEPROM_INIT, EWRK3_IOPR)((__builtin_constant_p((iobase+0x11)) && (iobase+0x11 ) < 256) ? __outbc((0xc0),(iobase+0x11)) : __outb((0xc0),( iobase+0x11)));\ |
341 | udelay(1000)(__builtin_constant_p(1000) ? __const_udelay((1000) * 0x10c6ul ) : __udelay(1000));\ |
342 | } |
343 | |
344 | |
345 | |
346 | |
347 | int ewrk3_probe(struct devicelinux_device *dev) |
348 | { |
349 | int tmp = num_ewrk3s, status = -ENODEV19; |
350 | u_long iobase = dev->base_addr; |
351 | |
352 | if ((iobase == 0) && loading_module){ |
353 | printk("Autoprobing is not supported when loading a module based driver.\n"); |
354 | status = -EIO5; |
355 | } else { /* First probe for the Ethernet */ |
356 | /* Address PROM pattern */ |
357 | isa_probe(dev, iobase); |
358 | eisa_probe(dev, iobase); |
359 | |
360 | if ((tmp == num_ewrk3s) && (iobase != 0) && loading_module) { |
361 | printk("%s: ewrk3_probe() cannot find device at 0x%04lx.\n", dev->name, |
362 | iobase); |
363 | } |
364 | |
365 | /* |
366 | ** Walk the device list to check that at least one device |
367 | ** initialised OK |
368 | */ |
369 | for (; (dev->priv == NULL((void *) 0)) && (dev->next != NULL((void *) 0)); dev = dev->next); |
370 | |
371 | if (dev->priv) status = 0; |
372 | if (iobase == 0) autoprobed = 1; |
373 | } |
374 | |
375 | return status; |
376 | } |
377 | |
378 | static int |
379 | ewrk3_hw_init(struct devicelinux_device *dev, u_long iobase) |
380 | { |
381 | struct ewrk3_private *lp; |
382 | int i, status=0; |
383 | u_long mem_start, shmem_length; |
384 | u_char cr, cmr, icr, nicsr, lemac, hard_strapped = 0; |
385 | u_char eeprom_image[EEPROM_MAX32], chksum, eisa_cr = 0; |
386 | |
387 | /* |
388 | ** Stop the EWRK3. Enable the DBR ROM. Disable interrupts and remote boot. |
389 | ** This also disables the EISA_ENABLE bit in the EISA Control Register. |
390 | */ |
391 | if (iobase > 0x400) eisa_cr = inb(EISA_CR)((__builtin_constant_p((iobase + 0x0c84)) && (iobase + 0x0c84) < 256) ? __inbc(iobase + 0x0c84) : __inb(iobase + 0x0c84)); |
392 | INIT_EWRK3{ ((__builtin_constant_p((iobase+0x11)) && (iobase+0x11 ) < 256) ? __outbc((0xc0),(iobase+0x11)) : __outb((0xc0),( iobase+0x11))); (__builtin_constant_p(1000) ? __const_udelay( (1000) * 0x10c6ul) : __udelay(1000));}; |
393 | |
394 | nicsr = inb(EWRK3_CSR)((__builtin_constant_p((iobase+0x00)) && (iobase+0x00 ) < 256) ? __inbc(iobase+0x00) : __inb(iobase+0x00)); |
395 | |
396 | icr = inb(EWRK3_ICR)((__builtin_constant_p((iobase+0x02)) && (iobase+0x02 ) < 256) ? __inbc(iobase+0x02) : __inb(iobase+0x02)); |
397 | icr &= 0x70; |
398 | outb(icr, EWRK3_ICR)((__builtin_constant_p((iobase+0x02)) && (iobase+0x02 ) < 256) ? __outbc((icr),(iobase+0x02)) : __outb((icr),(iobase +0x02))); /* Disable all the IRQs */ |
399 | |
400 | if (nicsr == (CSR_TXD0x02|CSR_RXD0x01)) { |
401 | |
402 | /* Check that the EEPROM is alive and well and not living on Pluto... */ |
403 | for (chksum=0, i=0; i<EEPROM_MAX32; i+=2) { |
404 | union { |
405 | short val; |
406 | char c[2]; |
407 | } tmp; |
408 | |
409 | tmp.val = (short)Read_EEPROM(iobase, (i>>1)); |
410 | eeprom_image[i] = tmp.c[0]; |
411 | eeprom_image[i+1] = tmp.c[1]; |
412 | chksum += eeprom_image[i] + eeprom_image[i+1]; |
413 | } |
414 | |
415 | if (chksum != 0) { /* Bad EEPROM Data! */ |
416 | printk("%s: Device has a bad on-board EEPROM.\n", dev->name); |
417 | status = -ENXIO6; |
418 | } else { |
419 | EthwrkSignature(name, eeprom_image); |
420 | if (*name != '\0') { /* found a EWRK3 device */ |
421 | dev->base_addr = iobase; |
422 | |
423 | if (iobase > 0x400) { |
424 | outb(eisa_cr, EISA_CR)((__builtin_constant_p((iobase + 0x0c84)) && (iobase + 0x0c84) < 256) ? __outbc((eisa_cr),(iobase + 0x0c84)) : __outb ((eisa_cr),(iobase + 0x0c84))); /* Rewrite the EISA CR */ |
425 | } |
426 | |
427 | lemac = eeprom_image[EEPROM_CHIPVER0x16]; |
428 | cmr = inb(EWRK3_CMR)((__builtin_constant_p((iobase+0x1e)) && (iobase+0x1e ) < 256) ? __inbc(iobase+0x1e) : __inb(iobase+0x1e)); |
429 | |
430 | if (((lemac == LeMAC0x11) && ((cmr & CMR_NO_EEPROM0x0c) != CMR_NO_EEPROM0x0c)) || |
431 | ((lemac == LeMAC20x12) && !(cmr & CMR_HS0x08))) { |
432 | printk("%s: %s at %#4lx", dev->name, name, iobase); |
433 | hard_strapped = 1; |
434 | } else if ((iobase&0x0fff)==EWRK3_EISA_IO_PORTS0x0c00) { |
435 | /* EISA slot address */ |
436 | printk("%s: %s at %#4lx (EISA slot %ld)", |
437 | dev->name, name, iobase, ((iobase>>12)&0x0f)); |
438 | } else { /* ISA port address */ |
439 | printk("%s: %s at %#4lx", dev->name, name, iobase); |
440 | } |
441 | |
442 | if (!status) { |
443 | printk(", h/w address "); |
444 | if (lemac!=LeMAC20x12) DevicePresent(iobase);/* need after EWRK3_INIT */ |
445 | status = get_hw_addr(dev, eeprom_image, lemac); |
446 | for (i = 0; i < ETH_ALEN6 - 1; i++) { /* get the ethernet addr. */ |
447 | printk("%2.2x:", dev->dev_addr[i]); |
448 | } |
449 | printk("%2.2x,\n", dev->dev_addr[i]); |
450 | |
451 | if (status) { |
452 | printk(" which has an EEPROM CRC error.\n"); |
453 | status = -ENXIO6; |
454 | } else { |
455 | if (lemac == LeMAC20x12) { /* Special LeMAC2 CMR things */ |
456 | cmr &= ~(CMR_RA0x80 | CMR_WB0x40 | CMR_LINK0x20 | CMR_POLARITY0x10 | CMR_0WS0x01); |
457 | if (eeprom_image[EEPROM_MISC00x06] & READ_AHEAD0x0080) cmr |= CMR_RA0x80; |
458 | if (eeprom_image[EEPROM_MISC00x06] & WRITE_BEHIND0x0002) cmr |= CMR_WB0x40; |
459 | if (eeprom_image[EEPROM_NETMAN00x14] & NETMAN_POL0x04) cmr |= CMR_POLARITY0x10; |
460 | if (eeprom_image[EEPROM_NETMAN00x14] & NETMAN_LINK0x02) cmr |= CMR_LINK0x20; |
461 | if (eeprom_image[EEPROM_MISC00x06] & _0WS_ENA0x0001) cmr |= CMR_0WS0x01; |
462 | } |
463 | if (eeprom_image[EEPROM_SETUP0x17] & SETUP_DRAM0x02) cmr |= CMR_DRAM0x02; |
464 | outb(cmr, EWRK3_CMR)((__builtin_constant_p((iobase+0x1e)) && (iobase+0x1e ) < 256) ? __outbc((cmr),(iobase+0x1e)) : __outb((cmr),(iobase +0x1e))); |
465 | |
466 | cr = inb(EWRK3_CR)((__builtin_constant_p((iobase+0x01)) && (iobase+0x01 ) < 256) ? __inbc(iobase+0x01) : __inb(iobase+0x01)); /* Set up the Control Register */ |
467 | cr |= eeprom_image[EEPROM_SETUP0x17] & SETUP_APD0x80; |
468 | if (cr & SETUP_APD0x80) cr |= eeprom_image[EEPROM_SETUP0x17] & SETUP_PS0x40; |
469 | cr |= eeprom_image[EEPROM_MISC00x06] & FAST_BUS0x0008; |
470 | cr |= eeprom_image[EEPROM_MISC00x06] & ENA_160x0004; |
471 | outb(cr, EWRK3_CR)((__builtin_constant_p((iobase+0x01)) && (iobase+0x01 ) < 256) ? __outbc((cr),(iobase+0x01)) : __outb((cr),(iobase +0x01))); |
472 | |
473 | /* |
474 | ** Determine the base address and window length for the EWRK3 |
475 | ** RAM from the memory base register. |
476 | */ |
477 | mem_start = inb(EWRK3_MBR)((__builtin_constant_p((iobase+0x14)) && (iobase+0x14 ) < 256) ? __inbc(iobase+0x14) : __inb(iobase+0x14)); |
478 | shmem_length = 0; |
479 | if (mem_start != 0) { |
480 | if ((mem_start >= 0x0a) && (mem_start <= 0x0f)) { |
481 | mem_start *= SHMEM_64K0x10000; |
482 | shmem_length = SHMEM_64K0x10000; |
483 | } else if ((mem_start >= 0x14) && (mem_start <= 0x1f)) { |
484 | mem_start *= SHMEM_32K0x8000; |
485 | shmem_length = SHMEM_32K0x8000; |
486 | } else if ((mem_start >= 0x40) && (mem_start <= 0xff)) { |
487 | mem_start = mem_start * SHMEM_2K0x800 + 0x80000; |
488 | shmem_length = SHMEM_2K0x800; |
489 | } else { |
490 | status = -ENXIO6; |
491 | } |
492 | } |
493 | |
494 | /* |
495 | ** See the top of this source code for comments about |
496 | ** uncommenting this line. |
497 | */ |
498 | /* FORCE_2K_MODE;*/ |
499 | |
500 | if (!status) { |
501 | if (hard_strapped) { |
502 | printk(" is hard strapped.\n"); |
503 | } else if (mem_start) { |
504 | printk(" has a %dk RAM window", (int)(shmem_length >> 10)); |
505 | printk(" at 0x%.5lx", mem_start); |
506 | } else { |
507 | printk(" is in I/O only mode"); |
508 | } |
509 | |
510 | /* private area & initialise */ |
511 | dev->priv = (void *) kmalloclinux_kmalloc(sizeof(struct ewrk3_private), |
512 | GFP_KERNEL0x03); |
513 | if (dev->priv == NULL((void *) 0)) { |
514 | return -ENOMEM12; |
515 | } |
516 | lp = (struct ewrk3_private *)dev->priv; |
517 | memset(dev->priv, 0, sizeof(struct ewrk3_private))(__builtin_constant_p(0) ? (__builtin_constant_p((sizeof(struct ewrk3_private))) ? __constant_c_and_count_memset(((dev->priv )),((0x01010101UL*(unsigned char)(0))),((sizeof(struct ewrk3_private )))) : __constant_c_memset(((dev->priv)),((0x01010101UL*(unsigned char)(0))),((sizeof(struct ewrk3_private))))) : (__builtin_constant_p ((sizeof(struct ewrk3_private))) ? __memset_generic((((dev-> priv))),(((0))),(((sizeof(struct ewrk3_private))))) : __memset_generic (((dev->priv)),((0)),((sizeof(struct ewrk3_private)))))); |
518 | lp->shmem_base = mem_start; |
519 | lp->shmem_length = shmem_length; |
520 | lp->lemac = lemac; |
521 | lp->hard_strapped = hard_strapped; |
522 | |
523 | lp->mPage = 64; |
524 | if (cmr & CMR_DRAM0x02) lp->mPage <<= 1 ;/* 2 DRAMS on module */ |
525 | |
526 | sprintflinux_sprintf(lp->adapter_name,"%s (%s)", name, dev->name); |
527 | request_region(iobase, EWRK3_TOTAL_SIZE0x20, lp->adapter_name); |
528 | |
529 | lp->irq_mask = ICR_TNEM0x08|ICR_TXDM0x02|ICR_RNEM0x04|ICR_RXDM0x01; |
530 | |
531 | if (!hard_strapped) { |
532 | /* |
533 | ** Enable EWRK3 board interrupts for autoprobing |
534 | */ |
535 | icr |= ICR_IE0x80; /* Enable interrupts */ |
536 | outb(icr, EWRK3_ICR)((__builtin_constant_p((iobase+0x02)) && (iobase+0x02 ) < 256) ? __outbc((icr),(iobase+0x02)) : __outb((icr),(iobase +0x02))); |
537 | |
538 | /* The DMA channel may be passed in on this parameter. */ |
539 | dev->dma = 0; |
540 | |
541 | /* To auto-IRQ we enable the initialization-done and DMA err, |
542 | interrupts. For now we will always get a DMA error. */ |
543 | if (dev->irq < 2) { |
544 | #ifndef MODULE |
545 | u_char irqnum; |
546 | |
547 | autoirq_setup(0); |
548 | |
549 | /* |
550 | ** Trigger a TNE interrupt. |
551 | */ |
552 | icr |=ICR_TNEM0x08; |
553 | outb(1,EWRK3_TDQ)((__builtin_constant_p((iobase+0x0c)) && (iobase+0x0c ) < 256) ? __outbc((1),(iobase+0x0c)) : __outb((1),(iobase +0x0c))); /* Write to the TX done queue */ |
554 | outb(icr, EWRK3_ICR)((__builtin_constant_p((iobase+0x02)) && (iobase+0x02 ) < 256) ? __outbc((icr),(iobase+0x02)) : __outb((icr),(iobase +0x02))); /* Unmask the TXD interrupt */ |
555 | |
556 | irqnum = irq[((icr & IRQ_SEL0x0060) >> 4)]; |
557 | |
558 | dev->irq = autoirq_report(1); |
559 | if ((dev->irq) && (irqnum == dev->irq)) { |
560 | printk(" and uses IRQ%d.\n", dev->irq); |
561 | } else { |
562 | if (!dev->irq) { |
563 | printk(" and failed to detect IRQ line.\n"); |
564 | } else if ((irqnum == 1) && (lemac == LeMAC20x12)) { |
565 | printk(" and an illegal IRQ line detected.\n"); |
566 | } else { |
567 | printk(", but incorrect IRQ line detected.\n"); |
568 | } |
569 | status = -ENXIO6; |
570 | } |
571 | |
572 | DISABLE_IRQs{ icr = ((__builtin_constant_p((iobase+0x02)) && (iobase +0x02) < 256) ? __inbc(iobase+0x02) : __inb(iobase+0x02)); icr &= ~lp->irq_mask; ((__builtin_constant_p((iobase+ 0x02)) && (iobase+0x02) < 256) ? __outbc((icr),(iobase +0x02)) : __outb((icr),(iobase+0x02))); }; /* Mask all interrupts */ |
573 | |
574 | #endif /* MODULE */ |
575 | } else { |
576 | printk(" and requires IRQ%d.\n", dev->irq); |
577 | } |
578 | } |
579 | if (status) release_region(iobase, EWRK3_TOTAL_SIZE0x20); |
580 | } else { |
581 | status = -ENXIO6; |
582 | } |
583 | } |
584 | } |
585 | } else { |
586 | status = -ENXIO6; |
587 | } |
588 | } |
589 | |
590 | if (!status) { |
591 | if (ewrk3_debug > 1) { |
592 | printk(version); |
593 | } |
594 | |
595 | /* The EWRK3-specific entries in the device structure. */ |
596 | dev->open = &ewrk3_open; |
597 | dev->hard_start_xmit = &ewrk3_queue_pkt; |
598 | dev->stop = &ewrk3_close; |
599 | dev->get_stats = &ewrk3_get_stats; |
600 | dev->set_multicast_list = &set_multicast_list; |
601 | dev->do_ioctl = &ewrk3_ioctl; |
602 | |
603 | dev->mem_start = 0; |
604 | |
605 | /* Fill in the generic field of the device structure. */ |
606 | ether_setup(dev); |
607 | } |
608 | } else { |
609 | status = -ENXIO6; |
610 | } |
611 | |
612 | return status; |
613 | } |
614 | |
615 | |
616 | static int |
617 | ewrk3_open(struct devicelinux_device *dev) |
618 | { |
619 | struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv; |
620 | u_long iobase = dev->base_addr; |
621 | int i, status = 0; |
622 | u_char icr, csr; |
623 | |
624 | /* |
625 | ** Stop the TX and RX... |
626 | */ |
627 | STOP_EWRK3{ csr = (0x02|0x01); ((__builtin_constant_p((iobase+0x00)) && (iobase+0x00) < 256) ? __outbc((csr),(iobase+0x00)) : __outb ((csr),(iobase+0x00))); }; |
628 | |
629 | if (!lp->hard_strapped) { |
630 | irq2dev_map[dev->irq] = dev; /* For latched interrupts */ |
631 | |
632 | if (request_irq(dev->irq, (void *)ewrk3_interrupt, 0, "ewrk3", NULL((void *) 0))) { |
633 | printk("ewrk3_open(): Requested IRQ%d is busy\n",dev->irq); |
634 | status = -EAGAIN11; |
635 | } else { |
636 | |
637 | /* |
638 | ** Re-initialize the EWRK3... |
639 | */ |
640 | ewrk3_init(dev); |
641 | |
642 | if (ewrk3_debug > 1){ |
643 | printk("%s: ewrk3 open with irq %d\n",dev->name,dev->irq); |
644 | printk(" physical address: "); |
645 | for (i=0;i<5;i++){ |
646 | printk("%2.2x:",(u_char)dev->dev_addr[i]); |
647 | } |
648 | printk("%2.2x\n",(u_char)dev->dev_addr[i]); |
649 | if (lp->shmem_length == 0) { |
650 | printk(" no shared memory, I/O only mode\n"); |
651 | } else { |
652 | printk(" start of shared memory: 0x%08lx\n",lp->shmem_base); |
653 | printk(" window length: 0x%04lx\n",lp->shmem_length); |
654 | } |
655 | printk(" # of DRAMS: %d\n",((inb(EWRK3_CMR)((__builtin_constant_p((iobase+0x1e)) && (iobase+0x1e ) < 256) ? __inbc(iobase+0x1e) : __inb(iobase+0x1e)) & 0x02) ? 2 : 1)); |
656 | printk(" csr: 0x%02x\n", inb(EWRK3_CSR)((__builtin_constant_p((iobase+0x00)) && (iobase+0x00 ) < 256) ? __inbc(iobase+0x00) : __inb(iobase+0x00))); |
657 | printk(" cr: 0x%02x\n", inb(EWRK3_CR)((__builtin_constant_p((iobase+0x01)) && (iobase+0x01 ) < 256) ? __inbc(iobase+0x01) : __inb(iobase+0x01))); |
658 | printk(" icr: 0x%02x\n", inb(EWRK3_ICR)((__builtin_constant_p((iobase+0x02)) && (iobase+0x02 ) < 256) ? __inbc(iobase+0x02) : __inb(iobase+0x02))); |
659 | printk(" cmr: 0x%02x\n", inb(EWRK3_CMR)((__builtin_constant_p((iobase+0x1e)) && (iobase+0x1e ) < 256) ? __inbc(iobase+0x1e) : __inb(iobase+0x1e))); |
660 | printk(" fmqc: 0x%02x\n", inb(EWRK3_FMQC)((__builtin_constant_p((iobase+0x07)) && (iobase+0x07 ) < 256) ? __inbc(iobase+0x07) : __inb(iobase+0x07))); |
661 | } |
662 | |
663 | dev->tbusy = 0; |
664 | dev->start = 1; |
665 | dev->interrupt = UNMASK_INTERRUPTS0; |
666 | |
667 | /* |
668 | ** Unmask EWRK3 board interrupts |
669 | */ |
670 | icr = inb(EWRK3_ICR)((__builtin_constant_p((iobase+0x02)) && (iobase+0x02 ) < 256) ? __inbc(iobase+0x02) : __inb(iobase+0x02)); |
671 | ENABLE_IRQs{ icr |= lp->irq_mask; ((__builtin_constant_p((iobase+0x02 )) && (iobase+0x02) < 256) ? __outbc((icr),(iobase +0x02)) : __outb((icr),(iobase+0x02))); }; |
672 | |
673 | } |
674 | } else { |
675 | dev->start = 0; |
676 | dev->tbusy = 1; |
677 | printk("%s: ewrk3 available for hard strapped set up only.\n", dev->name); |
678 | printk(" Run the 'ewrk3setup' utility or remove the hard straps.\n"); |
679 | } |
680 | |
681 | MOD_INC_USE_COUNTdo { } while (0); |
682 | |
683 | return status; |
684 | } |
685 | |
686 | /* |
687 | ** Initialize the EtherWORKS 3 operating conditions |
688 | */ |
689 | static void |
690 | ewrk3_init(struct devicelinux_device *dev) |
691 | { |
692 | struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv; |
693 | u_char csr, page; |
694 | u_long iobase = dev->base_addr; |
695 | |
696 | /* |
697 | ** Enable any multicasts |
698 | */ |
699 | set_multicast_list(dev); |
700 | |
701 | /* |
702 | ** Clean out any remaining entries in all the queues here |
703 | */ |
704 | while (inb(EWRK3_TQ)((__builtin_constant_p((iobase+0x0a)) && (iobase+0x0a ) < 256) ? __inbc(iobase+0x0a) : __inb(iobase+0x0a))); |
705 | while (inb(EWRK3_TDQ)((__builtin_constant_p((iobase+0x0c)) && (iobase+0x0c ) < 256) ? __inbc(iobase+0x0c) : __inb(iobase+0x0c))); |
706 | while (inb(EWRK3_RQ)((__builtin_constant_p((iobase+0x08)) && (iobase+0x08 ) < 256) ? __inbc(iobase+0x08) : __inb(iobase+0x08))); |
707 | while (inb(EWRK3_FMQ)((__builtin_constant_p((iobase+0x06)) && (iobase+0x06 ) < 256) ? __inbc(iobase+0x06) : __inb(iobase+0x06))); |
708 | |
709 | /* |
710 | ** Write a clean free memory queue |
711 | */ |
712 | for (page=1;page<lp->mPage;page++) { /* Write the free page numbers */ |
713 | outb(page, EWRK3_FMQ)((__builtin_constant_p((iobase+0x06)) && (iobase+0x06 ) < 256) ? __outbc((page),(iobase+0x06)) : __outb((page),( iobase+0x06))); /* to the Free Memory Queue */ |
714 | } |
715 | |
716 | lp->lock = 0; /* Ensure there are no locks */ |
717 | |
718 | START_EWRK3{ csr = ((__builtin_constant_p((iobase+0x00)) && (iobase +0x00) < 256) ? __inbc(iobase+0x00) : __inb(iobase+0x00)); csr &= ~(0x02|0x01); ((__builtin_constant_p((iobase+0x00 )) && (iobase+0x00) < 256) ? __outbc((csr),(iobase +0x00)) : __outb((csr),(iobase+0x00))); }; /* Enable the TX and/or RX */ |
719 | } |
720 | |
721 | /* |
722 | ** Writes a socket buffer to the free page queue |
723 | */ |
724 | static int |
725 | ewrk3_queue_pkt(struct sk_buff *skb, struct devicelinux_device *dev) |
726 | { |
727 | struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv; |
728 | u_long iobase = dev->base_addr; |
729 | int status = 0; |
730 | u_char icr, csr; |
731 | |
732 | /* Transmitter timeout, serious problems. */ |
733 | if (dev->tbusy || lp->lock) { |
734 | int tickssofar = jiffies - dev->trans_start; |
735 | if (tickssofar < QUEUE_PKT_TIMEOUT(1*100)) { |
736 | status = -1; |
737 | } else if (!lp->hard_strapped) { |
738 | printk("%s: transmit timed/locked out, status %04x, resetting.\n", |
739 | dev->name, inb(EWRK3_CSR)((__builtin_constant_p((iobase+0x00)) && (iobase+0x00 ) < 256) ? __inbc(iobase+0x00) : __inb(iobase+0x00))); |
740 | |
741 | /* |
742 | ** Mask all board interrupts |
743 | */ |
744 | DISABLE_IRQs{ icr = ((__builtin_constant_p((iobase+0x02)) && (iobase +0x02) < 256) ? __inbc(iobase+0x02) : __inb(iobase+0x02)); icr &= ~lp->irq_mask; ((__builtin_constant_p((iobase+ 0x02)) && (iobase+0x02) < 256) ? __outbc((icr),(iobase +0x02)) : __outb((icr),(iobase+0x02))); }; |
745 | |
746 | /* |
747 | ** Stop the TX and RX... |
748 | */ |
749 | STOP_EWRK3{ csr = (0x02|0x01); ((__builtin_constant_p((iobase+0x00)) && (iobase+0x00) < 256) ? __outbc((csr),(iobase+0x00)) : __outb ((csr),(iobase+0x00))); }; |
750 | |
751 | ewrk3_init(dev); |
752 | |
753 | /* |
754 | ** Unmask EWRK3 board interrupts |
755 | */ |
756 | ENABLE_IRQs{ icr |= lp->irq_mask; ((__builtin_constant_p((iobase+0x02 )) && (iobase+0x02) < 256) ? __outbc((icr),(iobase +0x02)) : __outb((icr),(iobase+0x02))); }; |
757 | |
758 | dev->tbusy=0; |
759 | dev->trans_start = jiffies; |
760 | dev_kfree_skb(skb, FREE_WRITE0); |
761 | } |
762 | } else if (skb == NULL((void *) 0)) { |
763 | dev_tint(dev); |
764 | } else if (skb->len > 0) { |
765 | |
766 | /* |
767 | ** Block a timer-based transmit from overlapping. This could better be |
768 | ** done with atomic_swap(1, dev->tbusy), but set_bit() works as well. |
769 | */ |
770 | if (set_bit(0, (void*)&dev->tbusy) != 0) |
771 | printk("%s: Transmitter access conflict.\n", dev->name); |
772 | |
773 | DISABLE_IRQs{ icr = ((__builtin_constant_p((iobase+0x02)) && (iobase +0x02) < 256) ? __inbc(iobase+0x02) : __inb(iobase+0x02)); icr &= ~lp->irq_mask; ((__builtin_constant_p((iobase+ 0x02)) && (iobase+0x02) < 256) ? __outbc((icr),(iobase +0x02)) : __outb((icr),(iobase+0x02))); }; /* So that the page # remains correct */ |
774 | |
775 | /* |
776 | ** Get a free page from the FMQ when resources are available |
777 | */ |
778 | if (inb(EWRK3_FMQC)((__builtin_constant_p((iobase+0x07)) && (iobase+0x07 ) < 256) ? __inbc(iobase+0x07) : __inb(iobase+0x07)) > 0) { |
779 | u_long buf = 0; |
780 | u_char page; |
781 | |
782 | if ((page = inb(EWRK3_FMQ)((__builtin_constant_p((iobase+0x06)) && (iobase+0x06 ) < 256) ? __inbc(iobase+0x06) : __inb(iobase+0x06))) < lp->mPage) { |
783 | /* |
784 | ** Set up shared memory window and pointer into the window |
785 | */ |
786 | while (set_bit(0, (void *)&lp->lock) != 0); /* Wait for lock to free */ |
787 | if (lp->shmem_length == IO_ONLY0x00) { |
788 | outb(page, EWRK3_IOPR)((__builtin_constant_p((iobase+0x11)) && (iobase+0x11 ) < 256) ? __outbc((page),(iobase+0x11)) : __outb((page),( iobase+0x11))); |
789 | } else if (lp->shmem_length == SHMEM_2K0x800) { |
790 | buf = lp->shmem_base; |
791 | outb(page, EWRK3_MPR)((__builtin_constant_p((iobase+0x13)) && (iobase+0x13 ) < 256) ? __outbc((page),(iobase+0x13)) : __outb((page),( iobase+0x13))); |
792 | } else if (lp->shmem_length == SHMEM_32K0x8000) { |
793 | buf = ((((short)page << 11) & 0x7800) + lp->shmem_base); |
794 | outb((page >> 4), EWRK3_MPR)((__builtin_constant_p((iobase+0x13)) && (iobase+0x13 ) < 256) ? __outbc(((page >> 4)),(iobase+0x13)) : __outb (((page >> 4)),(iobase+0x13))); |
795 | } else if (lp->shmem_length == SHMEM_64K0x10000) { |
796 | buf = ((((short)page << 11) & 0xf800) + lp->shmem_base); |
797 | outb((page >> 5), EWRK3_MPR)((__builtin_constant_p((iobase+0x13)) && (iobase+0x13 ) < 256) ? __outbc(((page >> 5)),(iobase+0x13)) : __outb (((page >> 5)),(iobase+0x13))); |
798 | } else { |
799 | status = -1; |
800 | printk("%s: Oops - your private data area is hosed!\n",dev->name); |
801 | } |
802 | |
803 | if (!status) { |
804 | |
805 | /* |
806 | ** Set up the buffer control structures and copy the data from |
807 | ** the socket buffer to the shared memory . |
808 | */ |
809 | |
810 | if (lp->shmem_length == IO_ONLY0x00) { |
811 | int i; |
812 | u_char *p = skb->data; |
813 | |
814 | outb((char)(TCR_QMODE | TCR_PAD | TCR_IFC), EWRK3_DATA)((__builtin_constant_p((iobase+0x10)) && (iobase+0x10 ) < 256) ? __outbc(((char)(0x10 | 0x04 | 0x02)),(iobase+0x10 )) : __outb(((char)(0x10 | 0x04 | 0x02)),(iobase+0x10))); |
815 | outb((char)(skb->len & 0xff), EWRK3_DATA)((__builtin_constant_p((iobase+0x10)) && (iobase+0x10 ) < 256) ? __outbc(((char)(skb->len & 0xff)),(iobase +0x10)) : __outb(((char)(skb->len & 0xff)),(iobase+0x10 ))); |
816 | outb((char)((skb->len >> 8) & 0xff), EWRK3_DATA)((__builtin_constant_p((iobase+0x10)) && (iobase+0x10 ) < 256) ? __outbc(((char)((skb->len >> 8) & 0xff )),(iobase+0x10)) : __outb(((char)((skb->len >> 8) & 0xff)),(iobase+0x10))); |
817 | outb((char)0x04, EWRK3_DATA)((__builtin_constant_p((iobase+0x10)) && (iobase+0x10 ) < 256) ? __outbc(((char)0x04),(iobase+0x10)) : __outb((( char)0x04),(iobase+0x10))); |
818 | for (i=0; i<skb->len; i++) { |
819 | outb(*p++, EWRK3_DATA)((__builtin_constant_p((iobase+0x10)) && (iobase+0x10 ) < 256) ? __outbc((*p++),(iobase+0x10)) : __outb((*p++),( iobase+0x10))); |
820 | } |
821 | outb(page, EWRK3_TQ)((__builtin_constant_p((iobase+0x0a)) && (iobase+0x0a ) < 256) ? __outbc((page),(iobase+0x0a)) : __outb((page),( iobase+0x0a))); /* Start sending pkt */ |
822 | } else { |
823 | writeb((char)(TCR_QMODE|TCR_PAD|TCR_IFC), (char *)buf)((*(volatile unsigned char *) ((char *)buf)) = ((char)(0x10|0x04 |0x02)));/* ctrl byte*/ |
824 | buf+=1; |
825 | writeb((char)(skb->len & 0xff), (char *)buf)((*(volatile unsigned char *) ((char *)buf)) = ((char)(skb-> len & 0xff)));/* length (16 bit xfer)*/ |
826 | buf+=1; |
827 | if (lp->txc) { |
828 | writeb((char)(((skb->len >> 8) & 0xff) | XCT), (char *)buf)((*(volatile unsigned char *) ((char *)buf)) = ((char)(((skb-> len >> 8) & 0xff) | 0x80))); |
829 | buf+=1; |
830 | writeb(0x04, (char *)buf)((*(volatile unsigned char *) ((char *)buf)) = (0x04)); /* index byte */ |
831 | buf+=1; |
832 | writeb(0x00, (char *)(buf + skb->len))((*(volatile unsigned char *) ((char *)(buf + skb->len))) = (0x00)); /* Write the XCT flag */ |
833 | memcpy_toio(buf, skb->data, PRELOAD)(__builtin_constant_p((16)) ? __constant_memcpy(((void *)(buf )),((skb->data)),((16))) : __memcpy(((void *)(buf)),((skb-> data)),((16))));/* Write PRELOAD bytes*/ |
834 | outb(page, EWRK3_TQ)((__builtin_constant_p((iobase+0x0a)) && (iobase+0x0a ) < 256) ? __outbc((page),(iobase+0x0a)) : __outb((page),( iobase+0x0a))); /* Start sending pkt */ |
835 | memcpy_toio(buf+PRELOAD, skb->data+PRELOAD, skb->len-PRELOAD)(__builtin_constant_p((skb->len-16)) ? __constant_memcpy(( (void *)(buf+16)),((skb->data+16)),((skb->len-16))) : __memcpy (((void *)(buf+16)),((skb->data+16)),((skb->len-16)))); |
836 | writeb(0xff, (char *)(buf + skb->len))((*(volatile unsigned char *) ((char *)(buf + skb->len))) = (0xff)); /* Write the XCT flag */ |
837 | } else { |
838 | writeb((char)((skb->len >> 8) & 0xff), (char *)buf)((*(volatile unsigned char *) ((char *)buf)) = ((char)((skb-> len >> 8) & 0xff))); |
839 | buf+=1; |
840 | writeb(0x04, (char *)buf)((*(volatile unsigned char *) ((char *)buf)) = (0x04)); /* index byte */ |
841 | buf+=1; |
842 | memcpy_toio((char *)buf, skb->data, skb->len)(__builtin_constant_p((skb->len)) ? __constant_memcpy(((void *)((char *)buf)),((skb->data)),((skb->len))) : __memcpy (((void *)((char *)buf)),((skb->data)),((skb->len))));/* Write data bytes */ |
843 | outb(page, EWRK3_TQ)((__builtin_constant_p((iobase+0x0a)) && (iobase+0x0a ) < 256) ? __outbc((page),(iobase+0x0a)) : __outb((page),( iobase+0x0a))); /* Start sending pkt */ |
844 | } |
845 | } |
846 | |
847 | dev->trans_start = jiffies; |
848 | dev_kfree_skb (skb, FREE_WRITE0); |
849 | |
850 | } else { /* return unused page to the free memory queue */ |
851 | outb(page, EWRK3_FMQ)((__builtin_constant_p((iobase+0x06)) && (iobase+0x06 ) < 256) ? __outbc((page),(iobase+0x06)) : __outb((page),( iobase+0x06))); |
852 | } |
853 | lp->lock = 0; /* unlock the page register */ |
854 | } else { |
855 | printk("ewrk3_queue_pkt(): Invalid free memory page (%d).\n", |
856 | (u_char) page); |
857 | } |
858 | } else { |
859 | printk("ewrk3_queue_pkt(): No free resources...\n"); |
860 | printk("ewrk3_queue_pkt(): CSR: %02x ICR: %02x FMQC: %02x\n",inb(EWRK3_CSR)((__builtin_constant_p((iobase+0x00)) && (iobase+0x00 ) < 256) ? __inbc(iobase+0x00) : __inb(iobase+0x00)),inb(EWRK3_ICR)((__builtin_constant_p((iobase+0x02)) && (iobase+0x02 ) < 256) ? __inbc(iobase+0x02) : __inb(iobase+0x02)),inb(EWRK3_FMQC)((__builtin_constant_p((iobase+0x07)) && (iobase+0x07 ) < 256) ? __inbc(iobase+0x07) : __inb(iobase+0x07))); |
861 | } |
862 | |
863 | /* Check for free resources: clear 'tbusy' if there are some */ |
864 | if (inb(EWRK3_FMQC)((__builtin_constant_p((iobase+0x07)) && (iobase+0x07 ) < 256) ? __inbc(iobase+0x07) : __inb(iobase+0x07)) > 0) { |
865 | dev->tbusy = 0; |
866 | } |
867 | |
868 | ENABLE_IRQs{ icr |= lp->irq_mask; ((__builtin_constant_p((iobase+0x02 )) && (iobase+0x02) < 256) ? __outbc((icr),(iobase +0x02)) : __outb((icr),(iobase+0x02))); }; |
869 | } |
870 | |
871 | return status; |
872 | } |
873 | |
874 | /* |
875 | ** The EWRK3 interrupt handler. |
876 | */ |
877 | static void |
878 | ewrk3_interrupt(int irq, void *dev_id, struct pt_regs * regs) |
879 | { |
880 | struct devicelinux_device *dev = (struct devicelinux_device *)(irq2dev_map[irq]); |
881 | struct ewrk3_private *lp; |
882 | u_long iobase; |
883 | u_char icr, cr, csr; |
884 | |
885 | if (dev == NULL((void *) 0)) { |
886 | printk ("ewrk3_interrupt(): irq %d for unknown device.\n", irq); |
887 | } else { |
888 | lp = (struct ewrk3_private *)dev->priv; |
889 | iobase = dev->base_addr; |
890 | |
891 | if (dev->interrupt) |
892 | printk("%s: Re-entering the interrupt handler.\n", dev->name); |
893 | |
894 | dev->interrupt = MASK_INTERRUPTS1; |
895 | |
896 | /* get the interrupt information */ |
897 | csr = inb(EWRK3_CSR)((__builtin_constant_p((iobase+0x00)) && (iobase+0x00 ) < 256) ? __inbc(iobase+0x00) : __inb(iobase+0x00)); |
898 | |
899 | /* |
900 | ** Mask the EWRK3 board interrupts and turn on the LED |
901 | */ |
902 | DISABLE_IRQs{ icr = ((__builtin_constant_p((iobase+0x02)) && (iobase +0x02) < 256) ? __inbc(iobase+0x02) : __inb(iobase+0x02)); icr &= ~lp->irq_mask; ((__builtin_constant_p((iobase+ 0x02)) && (iobase+0x02) < 256) ? __outbc((icr),(iobase +0x02)) : __outb((icr),(iobase+0x02))); }; |
903 | |
904 | cr = inb(EWRK3_CR)((__builtin_constant_p((iobase+0x01)) && (iobase+0x01 ) < 256) ? __inbc(iobase+0x01) : __inb(iobase+0x01)); |
905 | cr |= CR_LED0x02; |
906 | outb(cr, EWRK3_CR)((__builtin_constant_p((iobase+0x01)) && (iobase+0x01 ) < 256) ? __outbc((cr),(iobase+0x01)) : __outb((cr),(iobase +0x01))); |
907 | |
908 | if (csr & CSR_RNE0x04) /* Rx interrupt (packet[s] arrived) */ |
909 | ewrk3_rx(dev); |
910 | |
911 | if (csr & CSR_TNE0x08) /* Tx interrupt (packet sent) */ |
912 | ewrk3_tx(dev); |
913 | |
914 | /* |
915 | ** Now deal with the TX/RX disable flags. These are set when there |
916 | ** are no more resources. If resources free up then enable these |
917 | ** interrupts, otherwise mask them - failure to do this will result |
918 | ** in the system hanging in an interrupt loop. |
919 | */ |
920 | if (inb(EWRK3_FMQC)((__builtin_constant_p((iobase+0x07)) && (iobase+0x07 ) < 256) ? __inbc(iobase+0x07) : __inb(iobase+0x07))) { /* any resources available? */ |
921 | lp->irq_mask |= ICR_TXDM0x02|ICR_RXDM0x01;/* enable the interrupt source */ |
922 | csr &= ~(CSR_TXD0x02|CSR_RXD0x01);/* ensure restart of a stalled TX or RX */ |
923 | outb(csr, EWRK3_CSR)((__builtin_constant_p((iobase+0x00)) && (iobase+0x00 ) < 256) ? __outbc((csr),(iobase+0x00)) : __outb((csr),(iobase +0x00))); |
924 | dev->tbusy = 0; /* clear TX busy flag */ |
925 | mark_bh(NET_BH); |
926 | } else { |
927 | lp->irq_mask &= ~(ICR_TXDM0x02|ICR_RXDM0x01);/* disable the interrupt source */ |
928 | } |
929 | |
930 | /* Unmask the EWRK3 board interrupts and turn off the LED */ |
931 | cr &= ~CR_LED0x02; |
932 | outb(cr, EWRK3_CR)((__builtin_constant_p((iobase+0x01)) && (iobase+0x01 ) < 256) ? __outbc((cr),(iobase+0x01)) : __outb((cr),(iobase +0x01))); |
933 | |
934 | dev->interrupt = UNMASK_INTERRUPTS0; |
935 | ENABLE_IRQs{ icr |= lp->irq_mask; ((__builtin_constant_p((iobase+0x02 )) && (iobase+0x02) < 256) ? __outbc((icr),(iobase +0x02)) : __outb((icr),(iobase+0x02))); }; |
936 | } |
937 | |
938 | return; |
939 | } |
940 | |
941 | static int |
942 | ewrk3_rx(struct devicelinux_device *dev) |
943 | { |
944 | struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv; |
945 | u_long iobase = dev->base_addr; |
946 | int i, status = 0; |
947 | u_char page, tmpPage = 0, tmpLock = 0; |
948 | u_long buf = 0; |
949 | |
950 | while (inb(EWRK3_RQC)((__builtin_constant_p((iobase+0x09)) && (iobase+0x09 ) < 256) ? __inbc(iobase+0x09) : __inb(iobase+0x09)) && !status) { /* Whilst there's incoming data */ |
951 | if ((page = inb(EWRK3_RQ)((__builtin_constant_p((iobase+0x08)) && (iobase+0x08 ) < 256) ? __inbc(iobase+0x08) : __inb(iobase+0x08))) < lp->mPage) {/* Get next entry's buffer page */ |
952 | /* |
953 | ** Preempt any process using the current page register. Check for |
954 | ** an existing lock to reduce time taken in I/O transactions. |
955 | */ |
956 | if ((tmpLock = set_bit(0, (void *)&lp->lock)) == 1) { /* Assert lock */ |
957 | if (lp->shmem_length == IO_ONLY0x00) { /* Get existing page */ |
958 | tmpPage = inb(EWRK3_IOPR)((__builtin_constant_p((iobase+0x11)) && (iobase+0x11 ) < 256) ? __inbc(iobase+0x11) : __inb(iobase+0x11)); |
959 | } else { |
960 | tmpPage = inb(EWRK3_MPR)((__builtin_constant_p((iobase+0x13)) && (iobase+0x13 ) < 256) ? __inbc(iobase+0x13) : __inb(iobase+0x13)); |
961 | } |
962 | } |
963 | |
964 | /* |
965 | ** Set up shared memory window and pointer into the window |
966 | */ |
967 | if (lp->shmem_length == IO_ONLY0x00) { |
968 | outb(page, EWRK3_IOPR)((__builtin_constant_p((iobase+0x11)) && (iobase+0x11 ) < 256) ? __outbc((page),(iobase+0x11)) : __outb((page),( iobase+0x11))); |
969 | } else if (lp->shmem_length == SHMEM_2K0x800) { |
970 | buf = lp->shmem_base; |
971 | outb(page, EWRK3_MPR)((__builtin_constant_p((iobase+0x13)) && (iobase+0x13 ) < 256) ? __outbc((page),(iobase+0x13)) : __outb((page),( iobase+0x13))); |
972 | } else if (lp->shmem_length == SHMEM_32K0x8000) { |
973 | buf = ((((short)page << 11) & 0x7800) + lp->shmem_base); |
974 | outb((page >> 4), EWRK3_MPR)((__builtin_constant_p((iobase+0x13)) && (iobase+0x13 ) < 256) ? __outbc(((page >> 4)),(iobase+0x13)) : __outb (((page >> 4)),(iobase+0x13))); |
975 | } else if (lp->shmem_length == SHMEM_64K0x10000) { |
976 | buf = ((((short)page << 11) & 0xf800) + lp->shmem_base); |
977 | outb((page >> 5), EWRK3_MPR)((__builtin_constant_p((iobase+0x13)) && (iobase+0x13 ) < 256) ? __outbc(((page >> 5)),(iobase+0x13)) : __outb (((page >> 5)),(iobase+0x13))); |
978 | } else { |
979 | status = -1; |
980 | printk("%s: Oops - your private data area is hosed!\n",dev->name); |
981 | } |
982 | |
983 | if (!status) { |
984 | char rx_status; |
985 | int pkt_len; |
986 | |
987 | if (lp->shmem_length == IO_ONLY0x00) { |
988 | rx_status = inb(EWRK3_DATA)((__builtin_constant_p((iobase+0x10)) && (iobase+0x10 ) < 256) ? __inbc(iobase+0x10) : __inb(iobase+0x10)); |
989 | pkt_len = inb(EWRK3_DATA)((__builtin_constant_p((iobase+0x10)) && (iobase+0x10 ) < 256) ? __inbc(iobase+0x10) : __inb(iobase+0x10)); |
990 | pkt_len |= ((u_short)inb(EWRK3_DATA)((__builtin_constant_p((iobase+0x10)) && (iobase+0x10 ) < 256) ? __inbc(iobase+0x10) : __inb(iobase+0x10)) << 8); |
991 | } else { |
992 | rx_status = readb(buf)(*(volatile unsigned char *) (buf)); |
993 | buf+=1; |
994 | pkt_len = readw(buf)(*(volatile unsigned short *) (buf)); |
995 | buf+=3; |
996 | } |
997 | |
998 | if (!(rx_status & R_ROK0x80)) { /* There was an error. */ |
999 | lp->stats.rx_errors++; /* Update the error stats. */ |
1000 | if (rx_status & R_DBE0x04) lp->stats.rx_frame_errors++; |
1001 | if (rx_status & R_CRC0x02) lp->stats.rx_crc_errors++; |
1002 | if (rx_status & R_PLL0x01) lp->stats.rx_fifo_errors++; |
1003 | } else { |
1004 | struct sk_buff *skb; |
1005 | |
1006 | if ((skb = dev_alloc_skb(pkt_len+2)) != NULL((void *) 0)) { |
1007 | unsigned char *p; |
1008 | skb->dev = dev; |
1009 | skb_reserve(skb,2); /* Align to 16 bytes */ |
1010 | p = skb_put(skb,pkt_len); |
1011 | |
1012 | if (lp->shmem_length == IO_ONLY0x00) { |
1013 | *p = inb(EWRK3_DATA)((__builtin_constant_p((iobase+0x10)) && (iobase+0x10 ) < 256) ? __inbc(iobase+0x10) : __inb(iobase+0x10)); /* dummy read */ |
1014 | for (i=0; i<pkt_len; i++) { |
1015 | *p++ = inb(EWRK3_DATA)((__builtin_constant_p((iobase+0x10)) && (iobase+0x10 ) < 256) ? __inbc(iobase+0x10) : __inb(iobase+0x10)); |
1016 | } |
1017 | } else { |
1018 | memcpy_fromio(p, buf, pkt_len)(__builtin_constant_p((pkt_len)) ? __constant_memcpy(((p)),(( void *)(buf)),((pkt_len))) : __memcpy(((p)),((void *)(buf)),( (pkt_len)))); |
1019 | } |
1020 | |
1021 | /* |
1022 | ** Notify the upper protocol layers that there is another |
1023 | ** packet to handle |
1024 | */ |
1025 | skb->protocol=eth_type_trans(skb,dev)((unsigned short)0); |
1026 | netif_rx(skb); |
1027 | |
1028 | /* |
1029 | ** Update stats |
1030 | */ |
1031 | lp->stats.rx_packets++; |
1032 | for (i=1; i<EWRK3_PKT_STAT_SZ16-1; i++) { |
1033 | if (pkt_len < i*EWRK3_PKT_BIN_SZ128) { |
1034 | lp->pktStats.bins[i]++; |
1035 | i = EWRK3_PKT_STAT_SZ16; |
1036 | } |
1037 | } |
1038 | p = skb->data; /* Look at the dest addr */ |
1039 | if (p[0] & 0x01) { /* Multicast/Broadcast */ |
1040 | if ((*(s32 *)&p[0] == -1) && (*(s16 *)&p[4] == -1)) { |
1041 | lp->pktStats.broadcast++; |
1042 | } else { |
1043 | lp->pktStats.multicast++; |
1044 | } |
1045 | } else if ((*(s32 *)&p[0] == *(s32 *)&dev->dev_addr[0]) && |
1046 | (*(s16 *)&p[4] == *(s16 *)&dev->dev_addr[4])) { |
1047 | lp->pktStats.unicast++; |
1048 | } |
1049 | |
1050 | lp->pktStats.bins[0]++; /* Duplicates stats.rx_packets */ |
1051 | if (lp->pktStats.bins[0] == 0) { /* Reset counters */ |
1052 | memset(&lp->pktStats, 0, sizeof(lp->pktStats))(__builtin_constant_p(0) ? (__builtin_constant_p((sizeof(lp-> pktStats))) ? __constant_c_and_count_memset(((&lp->pktStats )),((0x01010101UL*(unsigned char)(0))),((sizeof(lp->pktStats )))) : __constant_c_memset(((&lp->pktStats)),((0x01010101UL *(unsigned char)(0))),((sizeof(lp->pktStats))))) : (__builtin_constant_p ((sizeof(lp->pktStats))) ? __memset_generic((((&lp-> pktStats))),(((0))),(((sizeof(lp->pktStats))))) : __memset_generic (((&lp->pktStats)),((0)),((sizeof(lp->pktStats))))) ); |
1053 | } |
1054 | } else { |
1055 | printk("%s: Insufficient memory; nuking packet.\n", dev->name); |
1056 | lp->stats.rx_dropped++; /* Really, deferred. */ |
1057 | break; |
1058 | } |
1059 | } |
1060 | } |
1061 | /* |
1062 | ** Return the received buffer to the free memory queue |
1063 | */ |
1064 | outb(page, EWRK3_FMQ)((__builtin_constant_p((iobase+0x06)) && (iobase+0x06 ) < 256) ? __outbc((page),(iobase+0x06)) : __outb((page),( iobase+0x06))); |
1065 | |
1066 | if (tmpLock) { /* If a lock was preempted */ |
1067 | if (lp->shmem_length == IO_ONLY0x00) { /* Replace old page */ |
1068 | outb(tmpPage, EWRK3_IOPR)((__builtin_constant_p((iobase+0x11)) && (iobase+0x11 ) < 256) ? __outbc((tmpPage),(iobase+0x11)) : __outb((tmpPage ),(iobase+0x11))); |
1069 | } else { |
1070 | outb(tmpPage, EWRK3_MPR)((__builtin_constant_p((iobase+0x13)) && (iobase+0x13 ) < 256) ? __outbc((tmpPage),(iobase+0x13)) : __outb((tmpPage ),(iobase+0x13))); |
1071 | } |
1072 | } |
1073 | lp->lock = 0; /* Unlock the page register */ |
1074 | } else { |
1075 | printk("ewrk3_rx(): Illegal page number, page %d\n",page); |
1076 | printk("ewrk3_rx(): CSR: %02x ICR: %02x FMQC: %02x\n",inb(EWRK3_CSR)((__builtin_constant_p((iobase+0x00)) && (iobase+0x00 ) < 256) ? __inbc(iobase+0x00) : __inb(iobase+0x00)),inb(EWRK3_ICR)((__builtin_constant_p((iobase+0x02)) && (iobase+0x02 ) < 256) ? __inbc(iobase+0x02) : __inb(iobase+0x02)),inb(EWRK3_FMQC)((__builtin_constant_p((iobase+0x07)) && (iobase+0x07 ) < 256) ? __inbc(iobase+0x07) : __inb(iobase+0x07))); |
1077 | } |
1078 | } |
1079 | return status; |
1080 | } |
1081 | |
1082 | /* |
1083 | ** Buffer sent - check for TX buffer errors. |
1084 | */ |
1085 | static int |
1086 | ewrk3_tx(struct devicelinux_device *dev) |
1087 | { |
1088 | struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv; |
1089 | u_long iobase = dev->base_addr; |
1090 | u_char tx_status; |
1091 | |
1092 | while ((tx_status = inb(EWRK3_TDQ)((__builtin_constant_p((iobase+0x0c)) && (iobase+0x0c ) < 256) ? __inbc(iobase+0x0c) : __inb(iobase+0x0c))) > 0) { /* Whilst there's old buffers */ |
1093 | if (tx_status & T_VSTS0x80) { /* The status is valid */ |
1094 | if (tx_status & T_TXE0x7f) { |
1095 | lp->stats.tx_errors++; |
1096 | if (tx_status & T_NCL0x10) lp->stats.tx_carrier_errors++; |
1097 | if (tx_status & T_LCL0x08) lp->stats.tx_window_errors++; |
1098 | if (tx_status & T_CTU0x40) { |
1099 | if ((tx_status & T_COLL0x03) ^ T_XUR0x03) { |
1100 | lp->pktStats.tx_underruns++; |
1101 | } else { |
1102 | lp->pktStats.excessive_underruns++; |
1103 | } |
1104 | } else if (tx_status & T_COLL0x03) { |
1105 | if ((tx_status & T_COLL0x03) ^ T_XCOLL0x03) { |
1106 | lp->stats.collisions++; |
1107 | } else { |
1108 | lp->pktStats.excessive_collisions++; |
1109 | } |
1110 | } |
1111 | } else { |
1112 | lp->stats.tx_packets++; |
1113 | } |
1114 | } |
1115 | } |
1116 | |
1117 | return 0; |
1118 | } |
1119 | |
1120 | static int |
1121 | ewrk3_close(struct devicelinux_device *dev) |
1122 | { |
1123 | struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv; |
1124 | u_long iobase = dev->base_addr; |
1125 | u_char icr, csr; |
1126 | |
1127 | dev->start = 0; |
1128 | dev->tbusy = 1; |
1129 | |
1130 | if (ewrk3_debug > 1) { |
1131 | printk("%s: Shutting down ethercard, status was %2.2x.\n", |
1132 | dev->name, inb(EWRK3_CSR)((__builtin_constant_p((iobase+0x00)) && (iobase+0x00 ) < 256) ? __inbc(iobase+0x00) : __inb(iobase+0x00))); |
1133 | } |
1134 | |
1135 | /* |
1136 | ** We stop the EWRK3 here... mask interrupts and stop TX & RX |
1137 | */ |
1138 | DISABLE_IRQs{ icr = ((__builtin_constant_p((iobase+0x02)) && (iobase +0x02) < 256) ? __inbc(iobase+0x02) : __inb(iobase+0x02)); icr &= ~lp->irq_mask; ((__builtin_constant_p((iobase+ 0x02)) && (iobase+0x02) < 256) ? __outbc((icr),(iobase +0x02)) : __outb((icr),(iobase+0x02))); }; |
1139 | |
1140 | STOP_EWRK3{ csr = (0x02|0x01); ((__builtin_constant_p((iobase+0x00)) && (iobase+0x00) < 256) ? __outbc((csr),(iobase+0x00)) : __outb ((csr),(iobase+0x00))); }; |
1141 | |
1142 | /* |
1143 | ** Clean out the TX and RX queues here (note that one entry |
1144 | ** may get added to either the TXD or RX queues if the TX or RX |
1145 | ** just starts processing a packet before the STOP_EWRK3 command |
1146 | ** is received. This will be flushed in the ewrk3_open() call). |
1147 | */ |
1148 | while (inb(EWRK3_TQ)((__builtin_constant_p((iobase+0x0a)) && (iobase+0x0a ) < 256) ? __inbc(iobase+0x0a) : __inb(iobase+0x0a))); |
1149 | while (inb(EWRK3_TDQ)((__builtin_constant_p((iobase+0x0c)) && (iobase+0x0c ) < 256) ? __inbc(iobase+0x0c) : __inb(iobase+0x0c))); |
1150 | while (inb(EWRK3_RQ)((__builtin_constant_p((iobase+0x08)) && (iobase+0x08 ) < 256) ? __inbc(iobase+0x08) : __inb(iobase+0x08))); |
1151 | |
1152 | if (!lp->hard_strapped) { |
1153 | free_irq(dev->irq, NULL((void *) 0)); |
1154 | |
1155 | irq2dev_map[dev->irq] = 0; |
1156 | } |
1157 | |
1158 | MOD_DEC_USE_COUNTdo { } while (0); |
1159 | |
1160 | return 0; |
1161 | } |
1162 | |
1163 | static struct enet_statistics * |
1164 | ewrk3_get_stats(struct devicelinux_device *dev) |
1165 | { |
1166 | struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv; |
1167 | |
1168 | /* Null body since there is no framing error counter */ |
1169 | |
1170 | return &lp->stats; |
1171 | } |
1172 | |
1173 | /* |
1174 | ** Set or clear the multicast filter for this adapter. |
1175 | */ |
1176 | static void |
1177 | set_multicast_list(struct devicelinux_device *dev) |
1178 | { |
1179 | struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv; |
1180 | u_long iobase = dev->base_addr; |
1181 | u_char csr; |
1182 | |
1183 | if (irq2dev_map[dev->irq] != NULL((void *) 0)) { |
1184 | csr = inb(EWRK3_CSR)((__builtin_constant_p((iobase+0x00)) && (iobase+0x00 ) < 256) ? __inbc(iobase+0x00) : __inb(iobase+0x00)); |
1185 | |
1186 | if (lp->shmem_length == IO_ONLY0x00) { |
1187 | lp->mctbl = (char *) PAGE0_HTE0x200; |
1188 | } else { |
1189 | lp->mctbl = (char *)(lp->shmem_base + PAGE0_HTE0x200); |
1190 | } |
1191 | |
1192 | csr &= ~(CSR_PME0x40 | CSR_MCE0x20); |
1193 | if (dev->flags & IFF_PROMISC0x100) { /* set promiscuous mode */ |
1194 | csr |= CSR_PME0x40; |
1195 | outb(csr, EWRK3_CSR)((__builtin_constant_p((iobase+0x00)) && (iobase+0x00 ) < 256) ? __outbc((csr),(iobase+0x00)) : __outb((csr),(iobase +0x00))); |
1196 | } else { |
1197 | SetMulticastFilter(dev); |
1198 | csr |= CSR_MCE0x20; |
1199 | outb(csr, EWRK3_CSR)((__builtin_constant_p((iobase+0x00)) && (iobase+0x00 ) < 256) ? __outbc((csr),(iobase+0x00)) : __outb((csr),(iobase +0x00))); |
1200 | } |
1201 | } |
1202 | } |
1203 | |
1204 | /* |
1205 | ** Calculate the hash code and update the logical address filter |
1206 | ** from a list of ethernet multicast addresses. |
1207 | ** Little endian crc one liner from Matt Thomas, DEC. |
1208 | ** |
1209 | ** Note that when clearing the table, the broadcast bit must remain asserted |
1210 | ** to receive broadcast messages. |
1211 | */ |
1212 | static void SetMulticastFilter(struct devicelinux_device *dev) |
1213 | { |
1214 | struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv; |
1215 | struct dev_mc_list *dmi=dev->mc_list; |
1216 | u_long iobase = dev->base_addr; |
1217 | int i; |
1218 | char *addrs, j, bit, byte; |
1219 | short *p = (short *) lp->mctbl; |
1220 | u16 hashcode; |
1221 | s32 crc, poly = CRC_POLYNOMIAL_LE0xedb88320UL; |
1222 | |
1223 | while (set_bit(0, (void *)&lp->lock) != 0); /* Wait for lock to free */ |
1224 | |
1225 | if (lp->shmem_length == IO_ONLY0x00) { |
1226 | outb(0, EWRK3_IOPR)((__builtin_constant_p((iobase+0x11)) && (iobase+0x11 ) < 256) ? __outbc((0),(iobase+0x11)) : __outb((0),(iobase +0x11))); |
1227 | outw(EEPROM_OFFSET(lp->mctbl), EWRK3_PIR1)((__builtin_constant_p((iobase+0x0e)) && (iobase+0x0e ) < 256) ? __outwc((((u_short)((u_long)(lp->mctbl)))),( iobase+0x0e)) : __outw((((u_short)((u_long)(lp->mctbl)))), (iobase+0x0e))); |
1228 | } else { |
1229 | outb(0, EWRK3_MPR)((__builtin_constant_p((iobase+0x13)) && (iobase+0x13 ) < 256) ? __outbc((0),(iobase+0x13)) : __outb((0),(iobase +0x13))); |
1230 | } |
1231 | |
1232 | if (dev->flags & IFF_ALLMULTI0x200) { |
1233 | for (i=0; i<(HASH_TABLE_LEN512 >> 3); i++) { |
1234 | if (lp->shmem_length == IO_ONLY0x00) { |
1235 | outb(0xff, EWRK3_DATA)((__builtin_constant_p((iobase+0x10)) && (iobase+0x10 ) < 256) ? __outbc((0xff),(iobase+0x10)) : __outb((0xff),( iobase+0x10))); |
1236 | } else { /* memset didn't work here */ |
1237 | writew(0xffff, p)((*(volatile unsigned short *) (p)) = (0xffff)); |
1238 | p++; i++; |
1239 | } |
1240 | } |
1241 | } else { |
1242 | /* Clear table except for broadcast bit */ |
1243 | if (lp->shmem_length == IO_ONLY0x00) { |
1244 | for (i=0; i<(HASH_TABLE_LEN512 >> 4) - 1; i++) { |
1245 | outb(0x00, EWRK3_DATA)((__builtin_constant_p((iobase+0x10)) && (iobase+0x10 ) < 256) ? __outbc((0x00),(iobase+0x10)) : __outb((0x00),( iobase+0x10))); |
1246 | } |
1247 | outb(0x80, EWRK3_DATA)((__builtin_constant_p((iobase+0x10)) && (iobase+0x10 ) < 256) ? __outbc((0x80),(iobase+0x10)) : __outb((0x80),( iobase+0x10))); i++; /* insert the broadcast bit */ |
1248 | for (; i<(HASH_TABLE_LEN512 >> 3); i++) { |
1249 | outb(0x00, EWRK3_DATA)((__builtin_constant_p((iobase+0x10)) && (iobase+0x10 ) < 256) ? __outbc((0x00),(iobase+0x10)) : __outb((0x00),( iobase+0x10))); |
1250 | } |
1251 | } else { |
1252 | memset_io(lp->mctbl, 0, (HASH_TABLE_LEN >> 3))(__builtin_constant_p((0)) ? (__builtin_constant_p((((512 >> 3)))) ? __constant_c_and_count_memset((((void *)(lp->mctbl ))),((0x01010101UL*(unsigned char)((0)))),((((512 >> 3) )))) : __constant_c_memset((((void *)(lp->mctbl))),((0x01010101UL *(unsigned char)((0)))),((((512 >> 3)))))) : (__builtin_constant_p ((((512 >> 3)))) ? __memset_generic(((((void *)(lp-> mctbl)))),((((0)))),(((((512 >> 3)))))) : __memset_generic ((((void *)(lp->mctbl))),(((0))),((((512 >> 3))))))); |
1253 | writeb(0x80, (char *)(lp->mctbl + (HASH_TABLE_LEN >> 4) - 1))((*(volatile unsigned char *) ((char *)(lp->mctbl + (512 >> 4) - 1))) = (0x80)); |
1254 | } |
1255 | |
1256 | /* Update table */ |
1257 | for (i=0;i<dev->mc_count;i++) { /* for each address in the list */ |
1258 | addrs=dmi->dmi_addr; |
1259 | dmi=dmi->next; |
1260 | if ((*addrs & 0x01) == 1) { /* multicast address? */ |
1261 | crc = 0xffffffff; /* init CRC for each address */ |
1262 | for (byte=0;byte<ETH_ALEN6;byte++) { /* for each address byte */ |
1263 | /* process each address bit */ |
1264 | for (bit = *addrs++,j=0;j<8;j++, bit>>=1) { |
1265 | crc = (crc >> 1) ^ (((crc ^ bit) & 0x01) ? poly : 0); |
1266 | } |
1267 | } |
1268 | hashcode = crc & ((1 << 9) - 1); /* hashcode is 9 LSb of CRC */ |
1269 | |
1270 | byte = hashcode >> 3; /* bit[3-8] -> byte in filter */ |
1271 | bit = 1 << (hashcode & 0x07); /* bit[0-2] -> bit in byte */ |
1272 | |
1273 | if (lp->shmem_length == IO_ONLY0x00) { |
1274 | u_char tmp; |
1275 | |
1276 | outw((short)((long)lp->mctbl) + byte, EWRK3_PIR1)((__builtin_constant_p((iobase+0x0e)) && (iobase+0x0e ) < 256) ? __outwc(((short)((long)lp->mctbl) + byte),(iobase +0x0e)) : __outw(((short)((long)lp->mctbl) + byte),(iobase +0x0e))); |
1277 | tmp = inb(EWRK3_DATA)((__builtin_constant_p((iobase+0x10)) && (iobase+0x10 ) < 256) ? __inbc(iobase+0x10) : __inb(iobase+0x10)); |
1278 | tmp |= bit; |
1279 | outw((short)((long)lp->mctbl) + byte, EWRK3_PIR1)((__builtin_constant_p((iobase+0x0e)) && (iobase+0x0e ) < 256) ? __outwc(((short)((long)lp->mctbl) + byte),(iobase +0x0e)) : __outw(((short)((long)lp->mctbl) + byte),(iobase +0x0e))); |
1280 | outb(tmp, EWRK3_DATA)((__builtin_constant_p((iobase+0x10)) && (iobase+0x10 ) < 256) ? __outbc((tmp),(iobase+0x10)) : __outb((tmp),(iobase +0x10))); |
1281 | } else { |
1282 | writeb(readb(lp->mctbl + byte) | bit, lp->mctbl + byte)((*(volatile unsigned char *) (lp->mctbl + byte)) = ((*(volatile unsigned char *) (lp->mctbl + byte)) | bit)); |
1283 | } |
1284 | } |
1285 | } |
1286 | } |
1287 | |
1288 | lp->lock = 0; /* Unlock the page register */ |
1289 | |
1290 | return; |
1291 | } |
1292 | |
1293 | /* |
1294 | ** ISA bus I/O device probe |
1295 | */ |
1296 | static void isa_probe(struct devicelinux_device *dev, u_long ioaddr) |
1297 | { |
1298 | int i = num_ewrk3s, maxSlots; |
1299 | u_long iobase; |
1300 | |
1301 | if (!ioaddr && autoprobed) return ; /* Been here before ! */ |
1302 | if (ioaddr >= 0x400) return; /* Not ISA */ |
1303 | |
1304 | if (ioaddr == 0) { /* Autoprobing */ |
1305 | iobase = EWRK3_IO_BASE0x100; /* Get the first slot address */ |
1306 | maxSlots = 24; |
1307 | } else { /* Probe a specific location */ |
1308 | iobase = ioaddr; |
1309 | maxSlots = i + 1; |
1310 | } |
1311 | |
1312 | for (; (i<maxSlots) && (dev!=NULL((void *) 0));iobase+=EWRK3_IOP_INC0x20, i++) { |
1313 | if (!check_region(iobase, EWRK3_TOTAL_SIZE0x20)) { |
1314 | if (DevicePresent(iobase) == 0) { |
1315 | if ((dev = alloc_device(dev, iobase)) != NULL((void *) 0)) { |
1316 | if (ewrk3_hw_init(dev, iobase) == 0) { |
1317 | num_ewrk3s++; |
1318 | } |
1319 | num_eth++; |
1320 | } |
1321 | } |
1322 | } else if (autoprobed) { |
1323 | printk("%s: region already allocated at 0x%04lx.\n", dev->name, iobase); |
1324 | } |
1325 | } |
1326 | |
1327 | return; |
1328 | } |
1329 | |
1330 | /* |
1331 | ** EISA bus I/O device probe. Probe from slot 1 since slot 0 is usually |
1332 | ** the motherboard. |
1333 | */ |
1334 | static void eisa_probe(struct devicelinux_device *dev, u_long ioaddr) |
1335 | { |
1336 | int i, maxSlots; |
1337 | u_long iobase; |
1338 | char name[EWRK3_STRLEN8]; |
1339 | |
1340 | if (!ioaddr && autoprobed) return ; /* Been here before ! */ |
1341 | if (ioaddr < 0x1000) return; /* Not EISA */ |
1342 | |
1343 | if (ioaddr == 0) { /* Autoprobing */ |
1344 | iobase = EISA_SLOT_INC0x1000; /* Get the first slot address */ |
1345 | i = 1; |
Value stored to 'i' is never read | |
1346 | maxSlots = MAX_EISA_SLOTS16; |
1347 | } else { /* Probe a specific location */ |
1348 | iobase = ioaddr; |
1349 | i = (ioaddr >> 12); |
1350 | maxSlots = i + 1; |
1351 | } |
1352 | |
1353 | for (i=1; (i<maxSlots) && (dev!=NULL((void *) 0)); i++, iobase+=EISA_SLOT_INC0x1000) { |
1354 | if (EISA_signature(name, EISA_IDiobase + 0x0c80) == 0) { |
1355 | if (!check_region(iobase, EWRK3_TOTAL_SIZE0x20)) { |
1356 | if (DevicePresent(iobase) == 0) { |
1357 | if ((dev = alloc_device(dev, iobase)) != NULL((void *) 0)) { |
1358 | if (ewrk3_hw_init(dev, iobase) == 0) { |
1359 | num_ewrk3s++; |
1360 | } |
1361 | num_eth++; |
1362 | } |
1363 | } |
1364 | } else if (autoprobed) { |
1365 | printk("%s: region already allocated at 0x%04lx.\n", dev->name, iobase); |
1366 | } |
1367 | } |
1368 | } |
1369 | |
1370 | return; |
1371 | } |
1372 | |
1373 | /* |
1374 | ** Search the entire 'eth' device list for a fixed probe. If a match isn't |
1375 | ** found then check for an autoprobe or unused device location. If they |
1376 | ** are not available then insert a new device structure at the end of |
1377 | ** the current list. |
1378 | */ |
1379 | static struct devicelinux_device * |
1380 | alloc_device(struct devicelinux_device *dev, u_long iobase) |
1381 | { |
1382 | struct devicelinux_device *adev = NULL((void *) 0); |
1383 | int fixed = 0, new_dev = 0; |
1384 | |
1385 | num_eth = ewrk3_dev_index(dev->name); |
1386 | if (loading_module) return dev; |
1387 | |
1388 | while (1) { |
1389 | if (((dev->base_addr == EWRK3_NDA0xffe0) || (dev->base_addr==0)) && !adev) { |
1390 | adev=dev; |
1391 | } else if ((dev->priv == NULL((void *) 0)) && (dev->base_addr==iobase)) { |
1392 | fixed = 1; |
1393 | } else { |
1394 | if (dev->next == NULL((void *) 0)) { |
1395 | new_dev = 1; |
1396 | } else if (strncmp(dev->next->name, "eth", 3) != 0) { |
1397 | new_dev = 1; |
1398 | } |
1399 | } |
1400 | if ((dev->next == NULL((void *) 0)) || new_dev || fixed) break; |
1401 | dev = dev->next; |
1402 | num_eth++; |
1403 | } |
1404 | if (adev && !fixed) { |
1405 | dev = adev; |
1406 | num_eth = ewrk3_dev_index(dev->name); |
1407 | new_dev = 0; |
1408 | } |
1409 | |
1410 | if (((dev->next == NULL((void *) 0)) && |
1411 | ((dev->base_addr != EWRK3_NDA0xffe0) && (dev->base_addr != 0)) && !fixed) || |
1412 | new_dev) { |
1413 | num_eth++; /* New device */ |
1414 | dev = insert_device(dev, iobase, ewrk3_probe); |
1415 | } |
1416 | |
1417 | return dev; |
1418 | } |
1419 | |
1420 | /* |
1421 | ** If at end of eth device list and can't use current entry, malloc |
1422 | ** one up. If memory could not be allocated, print an error message. |
1423 | */ |
1424 | static struct devicelinux_device * |
1425 | insert_device(struct devicelinux_device *dev, u_long iobase, int (*init)(struct devicelinux_device *)) |
1426 | { |
1427 | struct devicelinux_device *new; |
1428 | |
1429 | new = (struct devicelinux_device *)kmalloclinux_kmalloc(sizeof(struct devicelinux_device)+8, GFP_KERNEL0x03); |
1430 | if (new == NULL((void *) 0)) { |
1431 | printk("eth%d: Device not initialised, insufficient memory\n",num_eth); |
1432 | return NULL((void *) 0); |
1433 | } else { |
1434 | new->next = dev->next; |
1435 | dev->next = new; |
1436 | dev = dev->next; /* point to the new device */ |
1437 | dev->name = (char *)(dev + 1); |
1438 | if (num_eth > 9999) { |
1439 | sprintflinux_sprintf(dev->name,"eth????");/* New device name */ |
1440 | } else { |
1441 | sprintflinux_sprintf(dev->name,"eth%d", num_eth);/* New device name */ |
1442 | } |
1443 | dev->base_addr = iobase; /* assign the io address */ |
1444 | dev->init = init; /* initialisation routine */ |
1445 | } |
1446 | |
1447 | return dev; |
1448 | } |
1449 | |
1450 | static int |
1451 | ewrk3_dev_index(char *s) |
1452 | { |
1453 | int i=0, j=0; |
1454 | |
1455 | for (;*s; s++) { |
1456 | if (isdigit(*s)(((_ctype[(int)(unsigned char)(*s)])&(0x04)) != 0)) { |
1457 | j=1; |
1458 | i = (i * 10) + (*s - '0'); |
1459 | } else if (j) break; |
1460 | } |
1461 | |
1462 | return i; |
1463 | } |
1464 | |
1465 | /* |
1466 | ** Read the EWRK3 EEPROM using this routine |
1467 | */ |
1468 | static int Read_EEPROM(u_long iobase, u_char eaddr) |
1469 | { |
1470 | int i; |
1471 | |
1472 | outb((eaddr & 0x3f), EWRK3_PIR1)((__builtin_constant_p((iobase+0x0e)) && (iobase+0x0e ) < 256) ? __outbc(((eaddr & 0x3f)),(iobase+0x0e)) : __outb (((eaddr & 0x3f)),(iobase+0x0e))); /* set up 6 bits of address info */ |
1473 | outb(EEPROM_RD, EWRK3_IOPR)((__builtin_constant_p((iobase+0x11)) && (iobase+0x11 ) < 256) ? __outbc((0xe0),(iobase+0x11)) : __outb((0xe0),( iobase+0x11))); /* issue read command */ |
1474 | for (i=0;i<5000;i++) inb(EWRK3_CSR)((__builtin_constant_p((iobase+0x00)) && (iobase+0x00 ) < 256) ? __inbc(iobase+0x00) : __inb(iobase+0x00)); /* wait 1msec */ |
1475 | |
1476 | return inw(EWRK3_EPROM1)((__builtin_constant_p((iobase+0x16)) && (iobase+0x16 ) < 256) ? __inwc(iobase+0x16) : __inw(iobase+0x16)); /* 16 bits data return */ |
1477 | } |
1478 | |
1479 | /* |
1480 | ** Write the EWRK3 EEPROM using this routine |
1481 | */ |
1482 | static int Write_EEPROM(short data, u_long iobase, u_char eaddr) |
1483 | { |
1484 | int i; |
1485 | |
1486 | outb(EEPROM_WR_EN, EWRK3_IOPR)((__builtin_constant_p((iobase+0x11)) && (iobase+0x11 ) < 256) ? __outbc((0xc8),(iobase+0x11)) : __outb((0xc8),( iobase+0x11))); /* issue write enable command */ |
1487 | for (i=0;i<5000;i++) inb(EWRK3_CSR)((__builtin_constant_p((iobase+0x00)) && (iobase+0x00 ) < 256) ? __inbc(iobase+0x00) : __inb(iobase+0x00)); /* wait 1msec */ |
1488 | outw(data, EWRK3_EPROM1)((__builtin_constant_p((iobase+0x16)) && (iobase+0x16 ) < 256) ? __outwc((data),(iobase+0x16)) : __outw((data),( iobase+0x16))); /* write data to register */ |
1489 | outb((eaddr & 0x3f), EWRK3_PIR1)((__builtin_constant_p((iobase+0x0e)) && (iobase+0x0e ) < 256) ? __outbc(((eaddr & 0x3f)),(iobase+0x0e)) : __outb (((eaddr & 0x3f)),(iobase+0x0e))); /* set up 6 bits of address info */ |
1490 | outb(EEPROM_WR, EWRK3_IOPR)((__builtin_constant_p((iobase+0x11)) && (iobase+0x11 ) < 256) ? __outbc((0xd0),(iobase+0x11)) : __outb((0xd0),( iobase+0x11))); /* issue write command */ |
1491 | for (i=0;i<75000;i++) inb(EWRK3_CSR)((__builtin_constant_p((iobase+0x00)) && (iobase+0x00 ) < 256) ? __inbc(iobase+0x00) : __inb(iobase+0x00)); /* wait 15msec */ |
1492 | outb(EEPROM_WR_DIS, EWRK3_IOPR)((__builtin_constant_p((iobase+0x11)) && (iobase+0x11 ) < 256) ? __outbc((0xd8),(iobase+0x11)) : __outb((0xd8),( iobase+0x11))); /* issue write disable command */ |
1493 | for (i=0;i<5000;i++) inb(EWRK3_CSR)((__builtin_constant_p((iobase+0x00)) && (iobase+0x00 ) < 256) ? __inbc(iobase+0x00) : __inb(iobase+0x00)); /* wait 1msec */ |
1494 | |
1495 | return 0; |
1496 | } |
1497 | |
1498 | /* |
1499 | ** Look for a particular board name in the on-board EEPROM. |
1500 | */ |
1501 | static void EthwrkSignature(char *name, char *eeprom_image) |
1502 | { |
1503 | u_long i,j,k; |
1504 | char *signatures[] = EWRK3_SIGNATURE{"DE203","DE204","DE205",""}; |
1505 | |
1506 | strcpy(name, ""); |
1507 | for (i=0;*signatures[i] != '\0' && *name == '\0';i++) { |
1508 | for (j=EEPROM_PNAME70x08,k=0;j<=EEPROM_PNAME00x0f && k<strlen(signatures[i]);j++) { |
1509 | if (signatures[i][k] == eeprom_image[j]) { /* track signature */ |
1510 | k++; |
1511 | } else { /* lost signature; begin search again */ |
1512 | k=0; |
1513 | } |
1514 | } |
1515 | if (k == strlen(signatures[i])) { |
1516 | for (k=0; k<EWRK3_STRLEN8; k++) { |
1517 | name[k] = eeprom_image[EEPROM_PNAME70x08 + k]; |
1518 | name[EWRK3_STRLEN8] = '\0'; |
1519 | } |
1520 | } |
1521 | } |
1522 | |
1523 | return; /* return the device name string */ |
1524 | } |
1525 | |
1526 | /* |
1527 | ** Look for a special sequence in the Ethernet station address PROM that |
1528 | ** is common across all EWRK3 products. |
1529 | ** |
1530 | ** Search the Ethernet address ROM for the signature. Since the ROM address |
1531 | ** counter can start at an arbitrary point, the search must include the entire |
1532 | ** probe sequence length plus the (length_of_the_signature - 1). |
1533 | ** Stop the search IMMEDIATELY after the signature is found so that the |
1534 | ** PROM address counter is correctly positioned at the start of the |
1535 | ** ethernet address for later read out. |
1536 | */ |
1537 | |
1538 | static int DevicePresent(u_long iobase) |
1539 | { |
1540 | union { |
1541 | struct { |
1542 | u32 a; |
1543 | u32 b; |
1544 | } llsig; |
1545 | char Sig[sizeof(u32) << 1]; |
1546 | } dev; |
1547 | short sigLength; |
1548 | char data; |
1549 | int i, j, status = 0; |
1550 | |
1551 | dev.llsig.a = ETH_PROM_SIG0xAA5500FFUL; |
1552 | dev.llsig.b = ETH_PROM_SIG0xAA5500FFUL; |
1553 | sigLength = sizeof(u32) << 1; |
1554 | |
1555 | for (i=0,j=0;j<sigLength && i<PROBE_LENGTH32+sigLength-1;i++) { |
1556 | data = inb(EWRK3_APROM)((__builtin_constant_p((iobase+0x15)) && (iobase+0x15 ) < 256) ? __inbc(iobase+0x15) : __inb(iobase+0x15)); |
1557 | if (dev.Sig[j] == data) { /* track signature */ |
1558 | j++; |
1559 | } else { /* lost signature; begin search again */ |
1560 | if (data == dev.Sig[0]) { |
1561 | j=1; |
1562 | } else { |
1563 | j=0; |
1564 | } |
1565 | } |
1566 | } |
1567 | |
1568 | if (j!=sigLength) { |
1569 | status = -ENODEV19; /* search failed */ |
1570 | } |
1571 | |
1572 | return status; |
1573 | } |
1574 | |
1575 | static u_char get_hw_addr(struct devicelinux_device *dev, u_char *eeprom_image, char chipType) |
1576 | { |
1577 | int i, j, k; |
1578 | u_short chksum; |
1579 | u_char crc, lfsr, sd, status = 0; |
1580 | u_long iobase = dev->base_addr; |
1581 | u16 tmp; |
1582 | |
1583 | if (chipType == LeMAC20x12) { |
1584 | for (crc=0x6a, j=0; j<ETH_ALEN6; j++) { |
1585 | sd = dev->dev_addr[j] = eeprom_image[EEPROM_PADDR00x18 + j]; |
1586 | outb(dev->dev_addr[j], EWRK3_PAR0 + j)((__builtin_constant_p((iobase+0x18 + j)) && (iobase+ 0x18 + j) < 256) ? __outbc((dev->dev_addr[j]),(iobase+0x18 + j)) : __outb((dev->dev_addr[j]),(iobase+0x18 + j))); |
1587 | for (k=0; k<8; k++, sd >>= 1) { |
1588 | lfsr = ((((crc & 0x02) >> 1) ^ (crc & 0x01)) ^ (sd & 0x01)) << 7; |
1589 | crc = (crc >> 1) + lfsr; |
1590 | } |
1591 | } |
1592 | if (crc != eeprom_image[EEPROM_PA_CRC0x1e]) status = -1; |
1593 | } else { |
1594 | for (i=0,k=0;i<ETH_ALEN6;) { |
1595 | k <<= 1 ; |
1596 | if (k > 0xffff) k-=0xffff; |
1597 | |
1598 | k += (u_char) (tmp = inb(EWRK3_APROM)((__builtin_constant_p((iobase+0x15)) && (iobase+0x15 ) < 256) ? __inbc(iobase+0x15) : __inb(iobase+0x15))); |
1599 | dev->dev_addr[i] = (u_char) tmp; |
1600 | outb(dev->dev_addr[i], EWRK3_PAR0 + i)((__builtin_constant_p((iobase+0x18 + i)) && (iobase+ 0x18 + i) < 256) ? __outbc((dev->dev_addr[i]),(iobase+0x18 + i)) : __outb((dev->dev_addr[i]),(iobase+0x18 + i))); |
1601 | i++; |
1602 | k += (u_short) ((tmp = inb(EWRK3_APROM)((__builtin_constant_p((iobase+0x15)) && (iobase+0x15 ) < 256) ? __inbc(iobase+0x15) : __inb(iobase+0x15))) << 8); |
1603 | dev->dev_addr[i] = (u_char) tmp; |
1604 | outb(dev->dev_addr[i], EWRK3_PAR0 + i)((__builtin_constant_p((iobase+0x18 + i)) && (iobase+ 0x18 + i) < 256) ? __outbc((dev->dev_addr[i]),(iobase+0x18 + i)) : __outb((dev->dev_addr[i]),(iobase+0x18 + i))); |
1605 | i++; |
1606 | |
1607 | if (k > 0xffff) k-=0xffff; |
1608 | } |
1609 | if (k == 0xffff) k=0; |
1610 | chksum = inb(EWRK3_APROM)((__builtin_constant_p((iobase+0x15)) && (iobase+0x15 ) < 256) ? __inbc(iobase+0x15) : __inb(iobase+0x15)); |
1611 | chksum |= (inb(EWRK3_APROM)((__builtin_constant_p((iobase+0x15)) && (iobase+0x15 ) < 256) ? __inbc(iobase+0x15) : __inb(iobase+0x15))<<8); |
1612 | if (k != chksum) status = -1; |
1613 | } |
1614 | |
1615 | return status; |
1616 | } |
1617 | |
1618 | /* |
1619 | ** Look for a particular board name in the EISA configuration space |
1620 | */ |
1621 | static int EISA_signature(char *name, s32 eisa_id) |
1622 | { |
1623 | u_long i; |
1624 | char *signatures[] = EWRK3_SIGNATURE{"DE203","DE204","DE205",""}; |
1625 | char ManCode[EWRK3_STRLEN8]; |
1626 | union { |
1627 | s32 ID; |
1628 | char Id[4]; |
1629 | } Eisa; |
1630 | int status = 0; |
1631 | |
1632 | *name = '\0'; |
1633 | for (i=0; i<4; i++) { |
1634 | Eisa.Id[i] = inb(eisa_id + i)((__builtin_constant_p((eisa_id + i)) && (eisa_id + i ) < 256) ? __inbc(eisa_id + i) : __inb(eisa_id + i)); |
1635 | } |
1636 | |
1637 | ManCode[0]=(((Eisa.Id[0]>>2)&0x1f)+0x40); |
1638 | ManCode[1]=(((Eisa.Id[1]&0xe0)>>5)+((Eisa.Id[0]&0x03)<<3)+0x40); |
1639 | ManCode[2]=(((Eisa.Id[2]>>4)&0x0f)+0x30); |
1640 | ManCode[3]=((Eisa.Id[2]&0x0f)+0x30); |
1641 | ManCode[4]=(((Eisa.Id[3]>>4)&0x0f)+0x30); |
1642 | ManCode[5]='\0'; |
1643 | |
1644 | for (i=0;(*signatures[i] != '\0') && (*name == '\0');i++) { |
1645 | if (strstr(ManCode, signatures[i]) != NULL((void *) 0)) { |
1646 | strcpy(name,ManCode); |
1647 | status = 1; |
1648 | } |
1649 | } |
1650 | |
1651 | return status; /* return the device name string */ |
1652 | } |
1653 | |
1654 | /* |
1655 | ** Perform IOCTL call functions here. Some are privileged operations and the |
1656 | ** effective uid is checked in those cases. |
1657 | */ |
1658 | static int ewrk3_ioctl(struct devicelinux_device *dev, struct ifreq *rq, int cmd) |
1659 | { |
1660 | struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv; |
1661 | struct ewrk3_ioctl *ioc = (struct ewrk3_ioctl *) &rq->ifr_dataifr_ifru.ifru_data; |
1662 | u_long iobase = dev->base_addr; |
1663 | int i, j, status = 0; |
1664 | u_char csr; |
1665 | union { |
1666 | u_char addr[HASH_TABLE_LEN512 * ETH_ALEN6]; |
1667 | u_short val[(HASH_TABLE_LEN512 * ETH_ALEN6) >> 1]; |
1668 | } tmp; |
1669 | |
1670 | switch(ioc->cmd) { |
1671 | case EWRK3_GET_HWADDR0x01: /* Get the hardware address */ |
1672 | for (i=0; i<ETH_ALEN6; i++) { |
1673 | tmp.addr[i] = dev->dev_addr[i]; |
1674 | } |
1675 | ioc->len = ETH_ALEN6; |
1676 | if (!(status = verify_area(VERIFY_WRITE1, (void *)ioc->data, ioc->len))) { |
1677 | memcpy_tofs(ioc->data, tmp.addr, ioc->len); |
1678 | } |
1679 | |
1680 | break; |
1681 | case EWRK3_SET_HWADDR0x02: /* Set the hardware address */ |
1682 | if (suser()) { |
1683 | if (!(status = verify_area(VERIFY_READ0, (void *)ioc->data, ETH_ALEN6))) { |
1684 | csr = inb(EWRK3_CSR)((__builtin_constant_p((iobase+0x00)) && (iobase+0x00 ) < 256) ? __inbc(iobase+0x00) : __inb(iobase+0x00)); |
1685 | csr |= (CSR_TXD0x02|CSR_RXD0x01); |
1686 | outb(csr, EWRK3_CSR)((__builtin_constant_p((iobase+0x00)) && (iobase+0x00 ) < 256) ? __outbc((csr),(iobase+0x00)) : __outb((csr),(iobase +0x00))); /* Disable the TX and RX */ |
1687 | |
1688 | memcpy_fromfs(tmp.addr,ioc->data,ETH_ALEN6); |
1689 | for (i=0; i<ETH_ALEN6; i++) { |
1690 | dev->dev_addr[i] = tmp.addr[i]; |
1691 | outb(tmp.addr[i], EWRK3_PAR0 + i)((__builtin_constant_p((iobase+0x18 + i)) && (iobase+ 0x18 + i) < 256) ? __outbc((tmp.addr[i]),(iobase+0x18 + i) ) : __outb((tmp.addr[i]),(iobase+0x18 + i))); |
1692 | } |
1693 | |
1694 | csr &= ~(CSR_TXD0x02|CSR_RXD0x01); /* Enable the TX and RX */ |
1695 | outb(csr, EWRK3_CSR)((__builtin_constant_p((iobase+0x00)) && (iobase+0x00 ) < 256) ? __outbc((csr),(iobase+0x00)) : __outb((csr),(iobase +0x00))); |
1696 | } |
1697 | } else { |
1698 | status = -EPERM1; |
1699 | } |
1700 | |
1701 | break; |
1702 | case EWRK3_SET_PROM0x03: /* Set Promiscuous Mode */ |
1703 | if (suser()) { |
1704 | csr = inb(EWRK3_CSR)((__builtin_constant_p((iobase+0x00)) && (iobase+0x00 ) < 256) ? __inbc(iobase+0x00) : __inb(iobase+0x00)); |
1705 | csr |= CSR_PME0x40; |
1706 | csr &= ~CSR_MCE0x20; |
1707 | outb(csr, EWRK3_CSR)((__builtin_constant_p((iobase+0x00)) && (iobase+0x00 ) < 256) ? __outbc((csr),(iobase+0x00)) : __outb((csr),(iobase +0x00))); |
1708 | } else { |
1709 | status = -EPERM1; |
1710 | } |
1711 | |
1712 | break; |
1713 | case EWRK3_CLR_PROM0x04: /* Clear Promiscuous Mode */ |
1714 | if (suser()) { |
1715 | csr = inb(EWRK3_CSR)((__builtin_constant_p((iobase+0x00)) && (iobase+0x00 ) < 256) ? __inbc(iobase+0x00) : __inb(iobase+0x00)); |
1716 | csr &= ~CSR_PME0x40; |
1717 | outb(csr, EWRK3_CSR)((__builtin_constant_p((iobase+0x00)) && (iobase+0x00 ) < 256) ? __outbc((csr),(iobase+0x00)) : __outb((csr),(iobase +0x00))); |
1718 | } else { |
1719 | status = -EPERM1; |
1720 | } |
1721 | |
1722 | break; |
1723 | case EWRK3_SAY_BOO0x05: /* Say "Boo!" to the kernel log file */ |
1724 | printk("%s: Boo!\n", dev->name); |
1725 | |
1726 | break; |
1727 | case EWRK3_GET_MCA0x06: /* Get the multicast address table */ |
1728 | if (!(status = verify_area(VERIFY_WRITE1, ioc->data, ioc->len))) { |
1729 | while (set_bit(0, (void *)&lp->lock) != 0); /* Wait for lock to free */ |
1730 | if (lp->shmem_length == IO_ONLY0x00) { |
1731 | outb(0, EWRK3_IOPR)((__builtin_constant_p((iobase+0x11)) && (iobase+0x11 ) < 256) ? __outbc((0),(iobase+0x11)) : __outb((0),(iobase +0x11))); |
1732 | outw(PAGE0_HTE, EWRK3_PIR1)((__builtin_constant_p((iobase+0x0e)) && (iobase+0x0e ) < 256) ? __outwc((0x200),(iobase+0x0e)) : __outw((0x200) ,(iobase+0x0e))); |
1733 | for (i=0; i<(HASH_TABLE_LEN512 >> 3); i++) { |
1734 | tmp.addr[i] = inb(EWRK3_DATA)((__builtin_constant_p((iobase+0x10)) && (iobase+0x10 ) < 256) ? __inbc(iobase+0x10) : __inb(iobase+0x10)); |
1735 | } |
1736 | } else { |
1737 | outb(0, EWRK3_MPR)((__builtin_constant_p((iobase+0x13)) && (iobase+0x13 ) < 256) ? __outbc((0),(iobase+0x13)) : __outb((0),(iobase +0x13))); |
1738 | memcpy_fromio(tmp.addr, (char *)(lp->shmem_base + PAGE0_HTE), (HASH_TABLE_LEN >> 3))(__builtin_constant_p(((512 >> 3))) ? __constant_memcpy (((tmp.addr)),((void *)((char *)(lp->shmem_base + 0x200))) ,(((512 >> 3)))) : __memcpy(((tmp.addr)),((void *)((char *)(lp->shmem_base + 0x200))),(((512 >> 3))))); |
1739 | } |
1740 | ioc->len = (HASH_TABLE_LEN512 >> 3); |
1741 | memcpy_tofs(ioc->data, tmp.addr, ioc->len); |
1742 | } |
1743 | lp->lock = 0; /* Unlock the page register */ |
1744 | |
1745 | break; |
1746 | case EWRK3_SET_MCA0x07: /* Set a multicast address */ |
1747 | if (suser()) { |
1748 | if (!(status=verify_area(VERIFY_READ0, ioc->data, ETH_ALEN6*ioc->len))) { |
1749 | memcpy_fromfs(tmp.addr, ioc->data, ETH_ALEN6 * ioc->len); |
1750 | set_multicast_list(dev); |
1751 | } |
1752 | } else { |
1753 | status = -EPERM1; |
1754 | } |
1755 | |
1756 | break; |
1757 | case EWRK3_CLR_MCA0x08: /* Clear all multicast addresses */ |
1758 | if (suser()) { |
1759 | set_multicast_list(dev); |
1760 | } else { |
1761 | status = -EPERM1; |
1762 | } |
1763 | |
1764 | break; |
1765 | case EWRK3_MCA_EN0x09: /* Enable multicast addressing */ |
1766 | if (suser()) { |
1767 | csr = inb(EWRK3_CSR)((__builtin_constant_p((iobase+0x00)) && (iobase+0x00 ) < 256) ? __inbc(iobase+0x00) : __inb(iobase+0x00)); |
1768 | csr |= CSR_MCE0x20; |
1769 | csr &= ~CSR_PME0x40; |
1770 | outb(csr, EWRK3_CSR)((__builtin_constant_p((iobase+0x00)) && (iobase+0x00 ) < 256) ? __outbc((csr),(iobase+0x00)) : __outb((csr),(iobase +0x00))); |
1771 | } else { |
1772 | status = -EPERM1; |
1773 | } |
1774 | |
1775 | break; |
1776 | case EWRK3_GET_STATS0x0a: /* Get the driver statistics */ |
1777 | cli()__asm__ __volatile__ ("cli": : :"memory"); |
1778 | ioc->len = sizeof(lp->pktStats); |
1779 | if (!(status=verify_area(VERIFY_WRITE1, ioc->data, ioc->len))) { |
1780 | memcpy_tofs(ioc->data, &lp->pktStats, ioc->len); |
1781 | } |
1782 | sti()__asm__ __volatile__ ("sti": : :"memory"); |
1783 | |
1784 | break; |
1785 | case EWRK3_CLR_STATS0x0b: /* Zero out the driver statistics */ |
1786 | if (suser()) { |
1787 | cli()__asm__ __volatile__ ("cli": : :"memory"); |
1788 | memset(&lp->pktStats, 0, sizeof(lp->pktStats))(__builtin_constant_p(0) ? (__builtin_constant_p((sizeof(lp-> pktStats))) ? __constant_c_and_count_memset(((&lp->pktStats )),((0x01010101UL*(unsigned char)(0))),((sizeof(lp->pktStats )))) : __constant_c_memset(((&lp->pktStats)),((0x01010101UL *(unsigned char)(0))),((sizeof(lp->pktStats))))) : (__builtin_constant_p ((sizeof(lp->pktStats))) ? __memset_generic((((&lp-> pktStats))),(((0))),(((sizeof(lp->pktStats))))) : __memset_generic (((&lp->pktStats)),((0)),((sizeof(lp->pktStats))))) ); |
1789 | sti()__asm__ __volatile__ ("sti": : :"memory"); |
1790 | } else { |
1791 | status = -EPERM1; |
1792 | } |
1793 | |
1794 | break; |
1795 | case EWRK3_GET_CSR0x0c: /* Get the CSR Register contents */ |
1796 | tmp.addr[0] = inb(EWRK3_CSR)((__builtin_constant_p((iobase+0x00)) && (iobase+0x00 ) < 256) ? __inbc(iobase+0x00) : __inb(iobase+0x00)); |
1797 | ioc->len = 1; |
1798 | if (!(status=verify_area(VERIFY_WRITE1, ioc->data, ioc->len))) { |
1799 | memcpy_tofs(ioc->data, tmp.addr, ioc->len); |
1800 | } |
1801 | |
1802 | break; |
1803 | case EWRK3_SET_CSR0x0d: /* Set the CSR Register contents */ |
1804 | if (suser()) { |
1805 | if (!(status=verify_area(VERIFY_READ0, ioc->data, 1))) { |
1806 | memcpy_fromfs(tmp.addr, ioc->data, 1); |
1807 | outb(tmp.addr[0], EWRK3_CSR)((__builtin_constant_p((iobase+0x00)) && (iobase+0x00 ) < 256) ? __outbc((tmp.addr[0]),(iobase+0x00)) : __outb(( tmp.addr[0]),(iobase+0x00))); |
1808 | } |
1809 | } else { |
1810 | status = -EPERM1; |
1811 | } |
1812 | |
1813 | break; |
1814 | case EWRK3_GET_EEPROM0x0e: /* Get the EEPROM contents */ |
1815 | if (suser()) { |
1816 | for (i=0; i<(EEPROM_MAX32>>1); i++) { |
1817 | tmp.val[i] = (short)Read_EEPROM(iobase, i); |
1818 | } |
1819 | i = EEPROM_MAX32; |
1820 | tmp.addr[i++] = inb(EWRK3_CMR)((__builtin_constant_p((iobase+0x1e)) && (iobase+0x1e ) < 256) ? __inbc(iobase+0x1e) : __inb(iobase+0x1e)); /* Config/Management Reg. */ |
1821 | for (j=0;j<ETH_ALEN6;j++) { |
1822 | tmp.addr[i++] = inb(EWRK3_PAR0 + j)((__builtin_constant_p((iobase+0x18 + j)) && (iobase+ 0x18 + j) < 256) ? __inbc(iobase+0x18 + j) : __inb(iobase+ 0x18 + j)); |
1823 | } |
1824 | ioc->len = EEPROM_MAX32 + 1 + ETH_ALEN6; |
1825 | if (!(status=verify_area(VERIFY_WRITE1, ioc->data, ioc->len))) { |
1826 | memcpy_tofs(ioc->data, tmp.addr, ioc->len); |
1827 | } |
1828 | } else { |
1829 | status = -EPERM1; |
1830 | } |
1831 | |
1832 | break; |
1833 | case EWRK3_SET_EEPROM0x0f: /* Set the EEPROM contents */ |
1834 | if (suser()) { |
1835 | if (!(status=verify_area(VERIFY_READ0, ioc->data, EEPROM_MAX32))) { |
1836 | memcpy_fromfs(tmp.addr, ioc->data, EEPROM_MAX32); |
1837 | for (i=0; i<(EEPROM_MAX32>>1); i++) { |
1838 | Write_EEPROM(tmp.val[i], iobase, i); |
1839 | } |
1840 | } |
1841 | } else { |
1842 | status = -EPERM1; |
1843 | } |
1844 | |
1845 | break; |
1846 | case EWRK3_GET_CMR0x10: /* Get the CMR Register contents */ |
1847 | tmp.addr[0] = inb(EWRK3_CMR)((__builtin_constant_p((iobase+0x1e)) && (iobase+0x1e ) < 256) ? __inbc(iobase+0x1e) : __inb(iobase+0x1e)); |
1848 | ioc->len = 1; |
1849 | if (!(status=verify_area(VERIFY_WRITE1, ioc->data, ioc->len))) { |
1850 | memcpy_tofs(ioc->data, tmp.addr, ioc->len); |
1851 | } |
1852 | |
1853 | break; |
1854 | case EWRK3_SET_TX_CUT_THRU0x12: /* Set TX cut through mode */ |
1855 | if (suser()) { |
1856 | lp->txc = 1; |
1857 | } else { |
1858 | status = -EPERM1; |
1859 | } |
1860 | |
1861 | break; |
1862 | case EWRK3_CLR_TX_CUT_THRU0x11: /* Clear TX cut through mode */ |
1863 | if (suser()) { |
1864 | lp->txc = 0; |
1865 | } else { |
1866 | status = -EPERM1; |
1867 | } |
1868 | |
1869 | break; |
1870 | default: |
1871 | status = -EOPNOTSUPP95; |
1872 | } |
1873 | |
1874 | return status; |
1875 | } |
1876 | |
1877 | #ifdef MODULE |
1878 | static char devicename[9] = { 0, }; |
1879 | static struct devicelinux_device thisEthwrk = { |
1880 | devicename, /* device name is inserted by /linux/drivers/net/net_init.c */ |
1881 | 0, 0, 0, 0, |
1882 | 0x300, 5, /* I/O address, IRQ */ |
1883 | 0, 0, 0, NULL((void *) 0), ewrk3_probe }; |
1884 | |
1885 | static int io=0x300; /* <--- EDIT THESE LINES FOR YOUR CONFIGURATION */ |
1886 | static int irq=5; /* or use the insmod io= irq= options */ |
1887 | |
1888 | int |
1889 | init_module(void) |
1890 | { |
1891 | thisEthwrk.base_addr=io; |
1892 | thisEthwrk.irq=irq; |
1893 | if (register_netdev(&thisEthwrk) != 0) |
1894 | return -EIO5; |
1895 | return 0; |
1896 | } |
1897 | |
1898 | void |
1899 | cleanup_module(void) |
1900 | { |
1901 | if (thisEthwrk.priv) { |
1902 | kfreelinux_kfree(thisEthwrk.priv); |
1903 | thisEthwrk.priv = NULL((void *) 0); |
1904 | } |
1905 | thisEthwrk.irq = 0; |
1906 | |
1907 | unregister_netdev(&thisEthwrk); |
1908 | release_region(thisEthwrk.base_addr, EWRK3_TOTAL_SIZE0x20); |
1909 | } |
1910 | #endif /* MODULE */ |
1911 | |
1912 | |
1913 | /* |
1914 | * Local variables: |
1915 | * 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" |
1916 | * |
1917 | * 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" |
1918 | * End: |
1919 | */ |
1920 |