File: | obj-scan-build/../linux/src/drivers/net/at1700.c |
Location: | line 703, column 4 |
Description: | Function call argument is an uninitialized value |
1 | /* at1700.c: A network device driver for the Allied Telesis AT1700. | |||||
2 | ||||||
3 | Written 1993-98 by Donald Becker. | |||||
4 | ||||||
5 | Copyright 1993 United States Government as represented by the | |||||
6 | Director, National Security Agency. | |||||
7 | ||||||
8 | This software may be used and distributed according to the terms | |||||
9 | of the GNU Public License, incorporated herein by reference. | |||||
10 | ||||||
11 | The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O | |||||
12 | Center of Excellence in Space Data and Information Sciences | |||||
13 | Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 | |||||
14 | ||||||
15 | This is a device driver for the Allied Telesis AT1700, which is a | |||||
16 | straight-forward Fujitsu MB86965 implementation. | |||||
17 | ||||||
18 | Sources: | |||||
19 | The Fujitsu MB86965 datasheet. | |||||
20 | ||||||
21 | After the initial version of this driver was written Gerry Sawkins of | |||||
22 | ATI provided their EEPROM configuration code header file. | |||||
23 | Thanks to NIIBE Yutaka <gniibe@mri.co.jp> for bug fixes. | |||||
24 | ||||||
25 | Bugs: | |||||
26 | The MB86965 has a design flaw that makes all probes unreliable. Not | |||||
27 | only is it difficult to detect, it also moves around in I/O space in | |||||
28 | response to inb()s from other device probes! | |||||
29 | */ | |||||
30 | ||||||
31 | static const char *version = | |||||
32 | "at1700.c:v1.15 4/7/98 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n"; | |||||
33 | ||||||
34 | #include <linux/module.h> | |||||
35 | ||||||
36 | #include <linux/kernel.h> | |||||
37 | #include <linux/sched.h> | |||||
38 | #include <linux/types.h> | |||||
39 | #include <linux/fcntl.h> | |||||
40 | #include <linux/interrupt.h> | |||||
41 | #include <linux/ptrace.h> | |||||
42 | #include <linux/ioport.h> | |||||
43 | #include <linux/in.h> | |||||
44 | #include <linux/malloc.h> | |||||
45 | #include <linux/string.h> | |||||
46 | #include <asm/system.h> | |||||
47 | #include <asm/bitops.h> | |||||
48 | #include <asm/io.h> | |||||
49 | #include <asm/dma.h> | |||||
50 | #include <linux/errno.h> | |||||
51 | ||||||
52 | #include <linux/netdevice.h> | |||||
53 | #include <linux/etherdevice.h> | |||||
54 | #include <linux/skbuff.h> | |||||
55 | ||||||
56 | /* Tunable parameters. */ | |||||
57 | ||||||
58 | /* When to switch from the 64-entry multicast filter to Rx-all-multicast. */ | |||||
59 | #define MC_FILTERBREAK64 64 | |||||
60 | ||||||
61 | /* These unusual address orders are used to verify the CONFIG register. */ | |||||
62 | static int at1700_probe_list[] = | |||||
63 | {0x260, 0x280, 0x2a0, 0x240, 0x340, 0x320, 0x380, 0x300, 0}; | |||||
64 | static int fmv18x_probe_list[] = | |||||
65 | {0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x300, 0x340, 0}; | |||||
66 | ||||||
67 | ||||||
68 | /* use 0 for production, 1 for verification, >2 for debug */ | |||||
69 | #ifndef NET_DEBUG1 | |||||
70 | #define NET_DEBUG1 1 | |||||
71 | #endif | |||||
72 | static unsigned int net_debug = NET_DEBUG1; | |||||
73 | ||||||
74 | typedef unsigned char uchar; | |||||
75 | ||||||
76 | /* Information that need to be kept for each board. */ | |||||
77 | struct net_local { | |||||
78 | struct enet_statistics stats; | |||||
79 | unsigned char mc_filter[8]; | |||||
80 | uint jumpered:1; /* Set iff the board has jumper config. */ | |||||
81 | uint tx_started:1; /* Packets are on the Tx queue. */ | |||||
82 | uint invalid_irq:1; | |||||
83 | uchar tx_queue; /* Number of packet on the Tx queue. */ | |||||
84 | ushort tx_queue_len; /* Current length of the Tx queue. */ | |||||
85 | }; | |||||
86 | ||||||
87 | ||||||
88 | /* Offsets from the base address. */ | |||||
89 | #define STATUS0 0 | |||||
90 | #define TX_STATUS0 0 | |||||
91 | #define RX_STATUS1 1 | |||||
92 | #define TX_INTR2 2 /* Bit-mapped interrupt enable registers. */ | |||||
93 | #define RX_INTR3 3 | |||||
94 | #define TX_MODE4 4 | |||||
95 | #define RX_MODE5 5 | |||||
96 | #define CONFIG_06 6 /* Misc. configuration settings. */ | |||||
97 | #define CONFIG_17 7 | |||||
98 | /* Run-time register bank 2 definitions. */ | |||||
99 | #define DATAPORT8 8 /* Word-wide DMA or programmed-I/O dataport. */ | |||||
100 | #define TX_START10 10 | |||||
101 | #define MODE1313 13 | |||||
102 | /* Configuration registers only on the '865A/B chips. */ | |||||
103 | #define EEPROM_Ctrl16 16 | |||||
104 | #define EEPROM_Data17 17 | |||||
105 | #define IOCONFIG18 18 /* Either read the jumper, or move the I/O. */ | |||||
106 | #define IOCONFIG119 19 | |||||
107 | #define SAPROM20 20 /* The station address PROM, if no EEPROM. */ | |||||
108 | #define RESET31 31 /* Write to reset some parts of the chip. */ | |||||
109 | #define AT1700_IO_EXTENT32 32 | |||||
110 | /* Index to functions, as function prototypes. */ | |||||
111 | ||||||
112 | extern int at1700_probe(struct devicelinux_device *dev); | |||||
113 | ||||||
114 | static int at1700_probe1(struct devicelinux_device *dev, int ioaddr); | |||||
115 | static int read_eeprom(int ioaddr, int location); | |||||
116 | static int net_open(struct devicelinux_device *dev); | |||||
117 | static int net_send_packet(struct sk_buff *skb, struct devicelinux_device *dev); | |||||
118 | static void net_interrupt(int irq, void *dev_id, struct pt_regs *regs); | |||||
119 | static void net_rx(struct devicelinux_device *dev); | |||||
120 | static int net_close(struct devicelinux_device *dev); | |||||
121 | static struct enet_statistics *net_get_stats(struct devicelinux_device *dev); | |||||
122 | static void set_rx_mode(struct devicelinux_device *dev); | |||||
123 | ||||||
124 | ||||||
125 | /* Check for a network adaptor of this type, and return '0' iff one exists. | |||||
126 | If dev->base_addr == 0, probe all likely locations. | |||||
127 | If dev->base_addr == 1, always return failure. | |||||
128 | If dev->base_addr == 2, allocate space for the device and return success | |||||
129 | (detachable devices only). | |||||
130 | */ | |||||
131 | #ifdef HAVE_DEVLIST | |||||
132 | /* Support for a alternate probe manager, which will eliminate the | |||||
133 | boilerplate below. */ | |||||
134 | struct netdev_entry at1700_drv = | |||||
135 | {"at1700", at1700_probe1, AT1700_IO_EXTENT32, at1700_probe_list}; | |||||
136 | #else | |||||
137 | int | |||||
138 | at1700_probe(struct devicelinux_device *dev) | |||||
139 | { | |||||
140 | int i; | |||||
141 | int base_addr = dev ? dev->base_addr : 0; | |||||
142 | ||||||
143 | if (base_addr > 0x1ff) /* Check a single specified location. */ | |||||
144 | return at1700_probe1(dev, base_addr); | |||||
145 | else if (base_addr != 0) /* Don't probe at all. */ | |||||
146 | return ENXIO6; | |||||
147 | ||||||
148 | for (i = 0; at1700_probe_list[i]; i++) { | |||||
149 | int ioaddr = at1700_probe_list[i]; | |||||
150 | if (check_region(ioaddr, AT1700_IO_EXTENT32)) | |||||
151 | continue; | |||||
152 | if (at1700_probe1(dev, ioaddr) == 0) | |||||
153 | return 0; | |||||
154 | } | |||||
155 | ||||||
156 | return ENODEV19; | |||||
157 | } | |||||
158 | #endif | |||||
159 | ||||||
160 | /* The Fujitsu datasheet suggests that the NIC be probed for by checking its | |||||
161 | "signature", the default bit pattern after a reset. This *doesn't* work -- | |||||
162 | there is no way to reset the bus interface without a complete power-cycle! | |||||
163 | ||||||
164 | It turns out that ATI came to the same conclusion I did: the only thing | |||||
165 | that can be done is checking a few bits and then diving right into an | |||||
166 | EEPROM read. */ | |||||
167 | ||||||
168 | int at1700_probe1(struct devicelinux_device *dev, int ioaddr) | |||||
169 | { | |||||
170 | char fmv_irqmap[4] = {3, 7, 10, 15}; | |||||
171 | char at1700_irqmap[8] = {3, 4, 5, 9, 10, 11, 14, 15}; | |||||
172 | unsigned int i, irq, is_fmv18x = 0, is_at1700 = 0; | |||||
173 | ||||||
174 | /* Resetting the chip doesn't reset the ISA interface, so don't bother. | |||||
175 | That means we have to be careful with the register values we probe for. | |||||
176 | */ | |||||
177 | #ifdef notdef | |||||
178 | printk("at1700 probe at %#x, eeprom is %4.4x %4.4x %4.4x ctrl %4.4x.\n", | |||||
179 | ioaddr, read_eeprom(ioaddr, 4), read_eeprom(ioaddr, 5), | |||||
180 | read_eeprom(ioaddr, 6), inw(ioaddr + EEPROM_Ctrl)((__builtin_constant_p((ioaddr + 16)) && (ioaddr + 16 ) < 256) ? __inwc(ioaddr + 16) : __inw(ioaddr + 16))); | |||||
181 | #endif | |||||
182 | /* We must check for the EEPROM-config boards first, else accessing | |||||
183 | IOCONFIG0 will move the board! */ | |||||
184 | if (at1700_probe_list[inb(ioaddr + IOCONFIG1)((__builtin_constant_p((ioaddr + 19)) && (ioaddr + 19 ) < 256) ? __inbc(ioaddr + 19) : __inb(ioaddr + 19)) & 0x07] == ioaddr | |||||
185 | && read_eeprom(ioaddr, 4) == 0x0000 | |||||
186 | && (read_eeprom(ioaddr, 5) & 0xff00) == 0xF400) | |||||
187 | is_at1700 = 1; | |||||
188 | else if (fmv18x_probe_list[inb(ioaddr + IOCONFIG)((__builtin_constant_p((ioaddr + 18)) && (ioaddr + 18 ) < 256) ? __inbc(ioaddr + 18) : __inb(ioaddr + 18)) & 0x07] == ioaddr | |||||
189 | && inb(ioaddr + SAPROM )((__builtin_constant_p((ioaddr + 20)) && (ioaddr + 20 ) < 256) ? __inbc(ioaddr + 20) : __inb(ioaddr + 20)) == 0x00 | |||||
190 | && inb(ioaddr + SAPROM + 1)((__builtin_constant_p((ioaddr + 20 + 1)) && (ioaddr + 20 + 1) < 256) ? __inbc(ioaddr + 20 + 1) : __inb(ioaddr + 20 + 1)) == 0x00 | |||||
191 | && inb(ioaddr + SAPROM + 2)((__builtin_constant_p((ioaddr + 20 + 2)) && (ioaddr + 20 + 2) < 256) ? __inbc(ioaddr + 20 + 2) : __inb(ioaddr + 20 + 2)) == 0x0e) | |||||
192 | is_fmv18x = 1; | |||||
193 | else | |||||
194 | return -ENODEV19; | |||||
195 | ||||||
196 | /* Reset the internal state machines. */ | |||||
197 | outb(0, ioaddr + RESET)((__builtin_constant_p((ioaddr + 31)) && (ioaddr + 31 ) < 256) ? __outbc((0),(ioaddr + 31)) : __outb((0),(ioaddr + 31))); | |||||
198 | ||||||
199 | /* Allocate a new 'dev' if needed. */ | |||||
200 | if (dev == NULL((void *) 0)) | |||||
201 | dev = init_etherdev(0, sizeof(struct net_local)); | |||||
202 | ||||||
203 | if (is_at1700) | |||||
204 | irq = at1700_irqmap[(read_eeprom(ioaddr, 12)&0x04) | |||||
205 | | (read_eeprom(ioaddr, 0)>>14)]; | |||||
206 | else | |||||
207 | irq = fmv_irqmap[(inb(ioaddr + IOCONFIG)((__builtin_constant_p((ioaddr + 18)) && (ioaddr + 18 ) < 256) ? __inbc(ioaddr + 18) : __inb(ioaddr + 18))>>6) & 0x03]; | |||||
208 | ||||||
209 | /* Grab the region so that we can find another board if the IRQ request | |||||
210 | fails. */ | |||||
211 | request_region(ioaddr, AT1700_IO_EXTENT32, dev->name); | |||||
212 | ||||||
213 | printk("%s: AT1700 found at %#3x, IRQ %d, address ", dev->name, | |||||
214 | ioaddr, irq); | |||||
215 | ||||||
216 | dev->base_addr = ioaddr; | |||||
217 | dev->irq = irq; | |||||
218 | ||||||
219 | for(i = 0; i < 3; i++) { | |||||
220 | unsigned short eeprom_val = read_eeprom(ioaddr, 4+i); | |||||
221 | printk("%04x", eeprom_val); | |||||
222 | ((unsigned short *)dev->dev_addr)[i] = ntohs(eeprom_val); | |||||
223 | } | |||||
224 | ||||||
225 | /* The EEPROM word 12 bit 0x0400 means use regular 100 ohm 10baseT signals, | |||||
226 | rather than 150 ohm shielded twisted pair compensation. | |||||
227 | 0x0000 == auto-sense the interface | |||||
228 | 0x0800 == use TP interface | |||||
229 | 0x1800 == use coax interface | |||||
230 | */ | |||||
231 | { | |||||
232 | const char *porttype[] = {"auto-sense", "10baseT", "auto-sense", "10base2"}; | |||||
233 | ushort setup_value = read_eeprom(ioaddr, 12); | |||||
234 | ||||||
235 | dev->if_port = setup_value >> 8; | |||||
236 | printk(" %s interface.\n", porttype[(dev->if_port>>3) & 3]); | |||||
237 | } | |||||
238 | ||||||
239 | /* Set the station address in bank zero. */ | |||||
240 | outb(0xe0, ioaddr + CONFIG_1)((__builtin_constant_p((ioaddr + 7)) && (ioaddr + 7) < 256) ? __outbc((0xe0),(ioaddr + 7)) : __outb((0xe0),(ioaddr + 7))); | |||||
241 | for (i = 0; i < 6; i++) | |||||
242 | outb(dev->dev_addr[i], ioaddr + 8 + i)((__builtin_constant_p((ioaddr + 8 + i)) && (ioaddr + 8 + i) < 256) ? __outbc((dev->dev_addr[i]),(ioaddr + 8 + i)) : __outb((dev->dev_addr[i]),(ioaddr + 8 + i))); | |||||
243 | ||||||
244 | /* Switch to bank 1 and set the multicast table to accept none. */ | |||||
245 | outb(0xe4, ioaddr + CONFIG_1)((__builtin_constant_p((ioaddr + 7)) && (ioaddr + 7) < 256) ? __outbc((0xe4),(ioaddr + 7)) : __outb((0xe4),(ioaddr + 7))); | |||||
246 | for (i = 0; i < 8; i++) | |||||
247 | outb(0x00, ioaddr + 8 + i)((__builtin_constant_p((ioaddr + 8 + i)) && (ioaddr + 8 + i) < 256) ? __outbc((0x00),(ioaddr + 8 + i)) : __outb ((0x00),(ioaddr + 8 + i))); | |||||
248 | ||||||
249 | /* Set the configuration register 0 to 32K 100ns. byte-wide memory, 16 bit | |||||
250 | bus access, two 4K Tx queues, and disabled Tx and Rx. */ | |||||
251 | outb(0xda, ioaddr + CONFIG_0)((__builtin_constant_p((ioaddr + 6)) && (ioaddr + 6) < 256) ? __outbc((0xda),(ioaddr + 6)) : __outb((0xda),(ioaddr + 6))); | |||||
252 | ||||||
253 | /* Switch to bank 2 and lock our I/O address. */ | |||||
254 | outb(0xe8, ioaddr + CONFIG_1)((__builtin_constant_p((ioaddr + 7)) && (ioaddr + 7) < 256) ? __outbc((0xe8),(ioaddr + 7)) : __outb((0xe8),(ioaddr + 7))); | |||||
255 | outb(dev->if_port, MODE13)((__builtin_constant_p((13)) && (13) < 256) ? __outbc ((dev->if_port),(13)) : __outb((dev->if_port),(13))); | |||||
256 | ||||||
257 | /* Power-down the chip. Aren't we green! */ | |||||
258 | outb(0x00, ioaddr + CONFIG_1)((__builtin_constant_p((ioaddr + 7)) && (ioaddr + 7) < 256) ? __outbc((0x00),(ioaddr + 7)) : __outb((0x00),(ioaddr + 7))); | |||||
259 | ||||||
260 | if (net_debug) | |||||
261 | printk(version); | |||||
262 | ||||||
263 | /* Initialize the device structure. */ | |||||
264 | dev->priv = kmalloclinux_kmalloc(sizeof(struct net_local), GFP_KERNEL0x03); | |||||
265 | if (dev->priv == NULL((void *) 0)) | |||||
266 | return -ENOMEM12; | |||||
267 | memset(dev->priv, 0, sizeof(struct net_local))(__builtin_constant_p(0) ? (__builtin_constant_p((sizeof(struct net_local))) ? __constant_c_and_count_memset(((dev->priv) ),((0x01010101UL*(unsigned char)(0))),((sizeof(struct net_local )))) : __constant_c_memset(((dev->priv)),((0x01010101UL*(unsigned char)(0))),((sizeof(struct net_local))))) : (__builtin_constant_p ((sizeof(struct net_local))) ? __memset_generic((((dev->priv ))),(((0))),(((sizeof(struct net_local))))) : __memset_generic (((dev->priv)),((0)),((sizeof(struct net_local)))))); | |||||
268 | ||||||
269 | dev->open = net_open; | |||||
270 | dev->stop = net_close; | |||||
271 | dev->hard_start_xmit = net_send_packet; | |||||
272 | dev->get_stats = net_get_stats; | |||||
273 | dev->set_multicast_list = &set_rx_mode; | |||||
274 | ||||||
275 | /* Fill in the fields of 'dev' with ethernet-generic values. */ | |||||
276 | ether_setup(dev); | |||||
277 | ||||||
278 | { | |||||
279 | struct net_local *lp = (struct net_local *)dev->priv; | |||||
280 | lp->jumpered = is_fmv18x; | |||||
281 | /* Snarf the interrupt vector now. */ | |||||
282 | if (request_irq(irq, &net_interrupt, 0, dev->name, dev)) { | |||||
283 | printk (" AT1700 at %#3x is unusable due to a conflict on" | |||||
284 | "IRQ %d.\n", ioaddr, irq); | |||||
285 | lp->invalid_irq = 1; | |||||
286 | return 0; | |||||
287 | } | |||||
288 | } | |||||
289 | ||||||
290 | return 0; | |||||
291 | } | |||||
292 | ||||||
293 | ||||||
294 | /* EEPROM_Ctrl bits. */ | |||||
295 | #define EE_SHIFT_CLK0x40 0x40 /* EEPROM shift clock, in reg. 16. */ | |||||
296 | #define EE_CS0x20 0x20 /* EEPROM chip select, in reg. 16. */ | |||||
297 | #define EE_DATA_WRITE0x80 0x80 /* EEPROM chip data in, in reg. 17. */ | |||||
298 | #define EE_DATA_READ0x80 0x80 /* EEPROM chip data out, in reg. 17. */ | |||||
299 | ||||||
300 | /* Delay between EEPROM clock transitions. */ | |||||
301 | #define eeprom_delay()do {} while (0); do {} while (0); | |||||
302 | ||||||
303 | /* The EEPROM commands include the alway-set leading bit. */ | |||||
304 | #define EE_WRITE_CMD(5 << 6) (5 << 6) | |||||
305 | #define EE_READ_CMD(6 << 6) (6 << 6) | |||||
306 | #define EE_ERASE_CMD(7 << 6) (7 << 6) | |||||
307 | ||||||
308 | static int read_eeprom(int ioaddr, int location) | |||||
309 | { | |||||
310 | int i; | |||||
311 | unsigned short retval = 0; | |||||
312 | int ee_addr = ioaddr + EEPROM_Ctrl16; | |||||
313 | int ee_daddr = ioaddr + EEPROM_Data17; | |||||
314 | int read_cmd = location | EE_READ_CMD(6 << 6); | |||||
315 | ||||||
316 | /* Shift the read command bits out. */ | |||||
317 | for (i = 9; i >= 0; i--) { | |||||
318 | short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE0x80 : 0; | |||||
319 | outb(EE_CS, ee_addr)((__builtin_constant_p((ee_addr)) && (ee_addr) < 256 ) ? __outbc((0x20),(ee_addr)) : __outb((0x20),(ee_addr))); | |||||
320 | outb(dataval, ee_daddr)((__builtin_constant_p((ee_daddr)) && (ee_daddr) < 256) ? __outbc((dataval),(ee_daddr)) : __outb((dataval),(ee_daddr ))); | |||||
321 | eeprom_delay()do {} while (0);; | |||||
322 | outb(EE_CS | EE_SHIFT_CLK, ee_addr)((__builtin_constant_p((ee_addr)) && (ee_addr) < 256 ) ? __outbc((0x20 | 0x40),(ee_addr)) : __outb((0x20 | 0x40),( ee_addr))); /* EEPROM clock tick. */ | |||||
323 | eeprom_delay()do {} while (0);; | |||||
324 | } | |||||
325 | outb(EE_DATA_WRITE, ee_daddr)((__builtin_constant_p((ee_daddr)) && (ee_daddr) < 256) ? __outbc((0x80),(ee_daddr)) : __outb((0x80),(ee_daddr) )); | |||||
326 | for (i = 16; i > 0; i--) { | |||||
327 | outb(EE_CS, ee_addr)((__builtin_constant_p((ee_addr)) && (ee_addr) < 256 ) ? __outbc((0x20),(ee_addr)) : __outb((0x20),(ee_addr))); | |||||
328 | eeprom_delay()do {} while (0);; | |||||
329 | outb(EE_CS | EE_SHIFT_CLK, ee_addr)((__builtin_constant_p((ee_addr)) && (ee_addr) < 256 ) ? __outbc((0x20 | 0x40),(ee_addr)) : __outb((0x20 | 0x40),( ee_addr))); | |||||
330 | eeprom_delay()do {} while (0);; | |||||
331 | retval = (retval << 1) | ((inb(ee_daddr)((__builtin_constant_p((ee_daddr)) && (ee_daddr) < 256) ? __inbc(ee_daddr) : __inb(ee_daddr)) & EE_DATA_READ0x80) ? 1 : 0); | |||||
332 | } | |||||
333 | ||||||
334 | /* Terminate the EEPROM access. */ | |||||
335 | outb(EE_CS, ee_addr)((__builtin_constant_p((ee_addr)) && (ee_addr) < 256 ) ? __outbc((0x20),(ee_addr)) : __outb((0x20),(ee_addr))); | |||||
336 | eeprom_delay()do {} while (0);; | |||||
337 | outb(EE_SHIFT_CLK, ee_addr)((__builtin_constant_p((ee_addr)) && (ee_addr) < 256 ) ? __outbc((0x40),(ee_addr)) : __outb((0x40),(ee_addr))); | |||||
338 | outb(0, ee_addr)((__builtin_constant_p((ee_addr)) && (ee_addr) < 256 ) ? __outbc((0),(ee_addr)) : __outb((0),(ee_addr))); | |||||
339 | return retval; | |||||
340 | } | |||||
341 | ||||||
342 | ||||||
343 | ||||||
344 | static int net_open(struct devicelinux_device *dev) | |||||
345 | { | |||||
346 | struct net_local *lp = (struct net_local *)dev->priv; | |||||
347 | int ioaddr = dev->base_addr; | |||||
348 | int i; | |||||
349 | ||||||
350 | /* Powerup the chip, initialize config register 1, and select bank 0. */ | |||||
351 | outb(0xe0, ioaddr + CONFIG_1)((__builtin_constant_p((ioaddr + 7)) && (ioaddr + 7) < 256) ? __outbc((0xe0),(ioaddr + 7)) : __outb((0xe0),(ioaddr + 7))); | |||||
352 | ||||||
353 | /* Set the station address in bank zero. */ | |||||
354 | for (i = 0; i < 6; i++) | |||||
355 | outb(dev->dev_addr[i], ioaddr + 8 + i)((__builtin_constant_p((ioaddr + 8 + i)) && (ioaddr + 8 + i) < 256) ? __outbc((dev->dev_addr[i]),(ioaddr + 8 + i)) : __outb((dev->dev_addr[i]),(ioaddr + 8 + i))); | |||||
356 | ||||||
357 | /* Switch to bank 1 and set the multicast table to accept none. */ | |||||
358 | outb(0xe4, ioaddr + CONFIG_1)((__builtin_constant_p((ioaddr + 7)) && (ioaddr + 7) < 256) ? __outbc((0xe4),(ioaddr + 7)) : __outb((0xe4),(ioaddr + 7))); | |||||
359 | for (i = 0; i < 8; i++) | |||||
360 | outb(0x00, ioaddr + 8 + i)((__builtin_constant_p((ioaddr + 8 + i)) && (ioaddr + 8 + i) < 256) ? __outbc((0x00),(ioaddr + 8 + i)) : __outb ((0x00),(ioaddr + 8 + i))); | |||||
361 | ||||||
362 | /* Set the configuration register 0 to 32K 100ns. byte-wide memory, 16 bit | |||||
363 | bus access, and two 4K Tx queues. */ | |||||
364 | outb(0xda, ioaddr + CONFIG_0)((__builtin_constant_p((ioaddr + 6)) && (ioaddr + 6) < 256) ? __outbc((0xda),(ioaddr + 6)) : __outb((0xda),(ioaddr + 6))); | |||||
365 | ||||||
366 | /* Switch to register bank 2, enable the Rx and Tx. */ | |||||
367 | outw(0xe85a, ioaddr + CONFIG_0)((__builtin_constant_p((ioaddr + 6)) && (ioaddr + 6) < 256) ? __outwc((0xe85a),(ioaddr + 6)) : __outw((0xe85a),(ioaddr + 6))); | |||||
368 | ||||||
369 | lp->tx_started = 0; | |||||
370 | lp->tx_queue = 0; | |||||
371 | lp->tx_queue_len = 0; | |||||
372 | ||||||
373 | /* Turn on Rx interrupts, leave Tx interrupts off until packet Tx. */ | |||||
374 | outb(0x00, ioaddr + TX_INTR)((__builtin_constant_p((ioaddr + 2)) && (ioaddr + 2) < 256) ? __outbc((0x00),(ioaddr + 2)) : __outb((0x00),(ioaddr + 2))); | |||||
375 | outb(0x81, ioaddr + RX_INTR)((__builtin_constant_p((ioaddr + 3)) && (ioaddr + 3) < 256) ? __outbc((0x81),(ioaddr + 3)) : __outb((0x81),(ioaddr + 3))); | |||||
376 | ||||||
377 | dev->tbusy = 0; | |||||
378 | dev->interrupt = 0; | |||||
379 | dev->start = 1; | |||||
380 | ||||||
381 | MOD_INC_USE_COUNTdo { } while (0); | |||||
382 | ||||||
383 | return 0; | |||||
384 | } | |||||
385 | ||||||
386 | static int | |||||
387 | net_send_packet(struct sk_buff *skb, struct devicelinux_device *dev) | |||||
388 | { | |||||
389 | struct net_local *lp = (struct net_local *)dev->priv; | |||||
390 | int ioaddr = dev->base_addr; | |||||
391 | ||||||
392 | if (dev->tbusy) { | |||||
393 | /* If we get here, some higher level has decided we are broken. | |||||
394 | There should really be a "kick me" function call instead. */ | |||||
395 | int tickssofar = jiffies - dev->trans_start; | |||||
396 | if (tickssofar < 10) | |||||
397 | return 1; | |||||
398 | printk("%s: transmit timed out with status %04x, %s?\n", dev->name, | |||||
399 | inw(ioaddr + STATUS)((__builtin_constant_p((ioaddr + 0)) && (ioaddr + 0) < 256) ? __inwc(ioaddr + 0) : __inw(ioaddr + 0)), inb(ioaddr + TX_STATUS)((__builtin_constant_p((ioaddr + 0)) && (ioaddr + 0) < 256) ? __inbc(ioaddr + 0) : __inb(ioaddr + 0)) & 0x80 | |||||
400 | ? "IRQ conflict" : "network cable problem"); | |||||
401 | printk("%s: timeout registers: %04x %04x %04x %04x %04x %04x %04x %04x.\n", | |||||
402 | dev->name, inw(ioaddr + 0)((__builtin_constant_p((ioaddr + 0)) && (ioaddr + 0) < 256) ? __inwc(ioaddr + 0) : __inw(ioaddr + 0)), inw(ioaddr + 2)((__builtin_constant_p((ioaddr + 2)) && (ioaddr + 2) < 256) ? __inwc(ioaddr + 2) : __inw(ioaddr + 2)), inw(ioaddr + 4)((__builtin_constant_p((ioaddr + 4)) && (ioaddr + 4) < 256) ? __inwc(ioaddr + 4) : __inw(ioaddr + 4)), | |||||
403 | inw(ioaddr + 6)((__builtin_constant_p((ioaddr + 6)) && (ioaddr + 6) < 256) ? __inwc(ioaddr + 6) : __inw(ioaddr + 6)), inw(ioaddr + 8)((__builtin_constant_p((ioaddr + 8)) && (ioaddr + 8) < 256) ? __inwc(ioaddr + 8) : __inw(ioaddr + 8)), inw(ioaddr + 10)((__builtin_constant_p((ioaddr + 10)) && (ioaddr + 10 ) < 256) ? __inwc(ioaddr + 10) : __inw(ioaddr + 10)), | |||||
404 | inw(ioaddr + 12)((__builtin_constant_p((ioaddr + 12)) && (ioaddr + 12 ) < 256) ? __inwc(ioaddr + 12) : __inw(ioaddr + 12)), inw(ioaddr + 14)((__builtin_constant_p((ioaddr + 14)) && (ioaddr + 14 ) < 256) ? __inwc(ioaddr + 14) : __inw(ioaddr + 14))); | |||||
405 | lp->stats.tx_errors++; | |||||
406 | /* ToDo: We should try to restart the adaptor... */ | |||||
407 | outw(0xffff, ioaddr + 24)((__builtin_constant_p((ioaddr + 24)) && (ioaddr + 24 ) < 256) ? __outwc((0xffff),(ioaddr + 24)) : __outw((0xffff ),(ioaddr + 24))); | |||||
408 | outw(0xffff, ioaddr + TX_STATUS)((__builtin_constant_p((ioaddr + 0)) && (ioaddr + 0) < 256) ? __outwc((0xffff),(ioaddr + 0)) : __outw((0xffff),(ioaddr + 0))); | |||||
409 | outw(0xe85a, ioaddr + CONFIG_0)((__builtin_constant_p((ioaddr + 6)) && (ioaddr + 6) < 256) ? __outwc((0xe85a),(ioaddr + 6)) : __outw((0xe85a),(ioaddr + 6))); | |||||
410 | outw(0x8100, ioaddr + TX_INTR)((__builtin_constant_p((ioaddr + 2)) && (ioaddr + 2) < 256) ? __outwc((0x8100),(ioaddr + 2)) : __outw((0x8100),(ioaddr + 2))); | |||||
411 | dev->tbusy=0; | |||||
412 | dev->trans_start = jiffies; | |||||
413 | lp->tx_started = 0; | |||||
414 | lp->tx_queue = 0; | |||||
415 | lp->tx_queue_len = 0; | |||||
416 | } | |||||
417 | ||||||
418 | /* If some higher layer thinks we've missed an tx-done interrupt | |||||
419 | we are passed NULL. Caution: dev_tint() handles the cli()/sti() | |||||
420 | itself. */ | |||||
421 | if (skb == NULL((void *) 0)) { | |||||
422 | dev_tint(dev); | |||||
423 | return 0; | |||||
424 | } | |||||
425 | ||||||
426 | /* Block a timer-based transmit from overlapping. This could better be | |||||
427 | done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ | |||||
428 | if (set_bit(0, (void*)&dev->tbusy) != 0) | |||||
429 | printk("%s: Transmitter access conflict.\n", dev->name); | |||||
430 | else { | |||||
431 | short length = ETH_ZLEN60 < skb->len ? skb->len : ETH_ZLEN60; | |||||
432 | unsigned char *buf = skb->data; | |||||
433 | ||||||
434 | /* Turn off the possible Tx interrupts. */ | |||||
435 | outb(0x00, ioaddr + TX_INTR)((__builtin_constant_p((ioaddr + 2)) && (ioaddr + 2) < 256) ? __outbc((0x00),(ioaddr + 2)) : __outb((0x00),(ioaddr + 2))); | |||||
436 | ||||||
437 | outw(length, ioaddr + DATAPORT)((__builtin_constant_p((ioaddr + 8)) && (ioaddr + 8) < 256) ? __outwc((length),(ioaddr + 8)) : __outw((length),(ioaddr + 8))); | |||||
438 | outsw(ioaddr + DATAPORT8, buf, (length + 1) >> 1); | |||||
439 | ||||||
440 | lp->tx_queue++; | |||||
441 | lp->tx_queue_len += length + 2; | |||||
442 | ||||||
443 | if (lp->tx_started == 0) { | |||||
444 | /* If the Tx is idle, always trigger a transmit. */ | |||||
445 | outb(0x80 | lp->tx_queue, ioaddr + TX_START)((__builtin_constant_p((ioaddr + 10)) && (ioaddr + 10 ) < 256) ? __outbc((0x80 | lp->tx_queue),(ioaddr + 10)) : __outb((0x80 | lp->tx_queue),(ioaddr + 10))); | |||||
446 | lp->tx_queue = 0; | |||||
447 | lp->tx_queue_len = 0; | |||||
448 | dev->trans_start = jiffies; | |||||
449 | lp->tx_started = 1; | |||||
450 | dev->tbusy = 0; | |||||
451 | } else if (lp->tx_queue_len < 4096 - 1502) | |||||
452 | /* Yes, there is room for one more packet. */ | |||||
453 | dev->tbusy = 0; | |||||
454 | ||||||
455 | /* Turn on Tx interrupts back on. */ | |||||
456 | outb(0x82, ioaddr + TX_INTR)((__builtin_constant_p((ioaddr + 2)) && (ioaddr + 2) < 256) ? __outbc((0x82),(ioaddr + 2)) : __outb((0x82),(ioaddr + 2))); | |||||
457 | } | |||||
458 | dev_kfree_skb (skb, FREE_WRITE0); | |||||
459 | ||||||
460 | return 0; | |||||
461 | } | |||||
462 | ||||||
463 | /* The typical workload of the driver: | |||||
464 | Handle the network interface interrupts. */ | |||||
465 | static void | |||||
466 | net_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||||
467 | { | |||||
468 | struct devicelinux_device *dev = dev_id; | |||||
469 | struct net_local *lp; | |||||
470 | int ioaddr, status; | |||||
471 | ||||||
472 | if (dev == NULL((void *) 0)) { | |||||
473 | printk ("at1700_interrupt(): irq %d for unknown device.\n", irq); | |||||
474 | return; | |||||
475 | } | |||||
476 | dev->interrupt = 1; | |||||
477 | ||||||
478 | ioaddr = dev->base_addr; | |||||
479 | lp = (struct net_local *)dev->priv; | |||||
480 | status = inw(ioaddr + TX_STATUS)((__builtin_constant_p((ioaddr + 0)) && (ioaddr + 0) < 256) ? __inwc(ioaddr + 0) : __inw(ioaddr + 0)); | |||||
481 | outw(status, ioaddr + TX_STATUS)((__builtin_constant_p((ioaddr + 0)) && (ioaddr + 0) < 256) ? __outwc((status),(ioaddr + 0)) : __outw((status),(ioaddr + 0))); | |||||
482 | ||||||
483 | if (net_debug > 4) | |||||
484 | printk("%s: Interrupt with status %04x.\n", dev->name, status); | |||||
485 | if (status & 0xff00 | |||||
486 | || (inb(ioaddr + RX_MODE)((__builtin_constant_p((ioaddr + 5)) && (ioaddr + 5) < 256) ? __inbc(ioaddr + 5) : __inb(ioaddr + 5)) & 0x40) == 0) { /* Got a packet(s). */ | |||||
487 | net_rx(dev); | |||||
488 | } | |||||
489 | if (status & 0x00ff) { | |||||
490 | if (status & 0x80) { | |||||
491 | lp->stats.tx_packets++; | |||||
492 | if (lp->tx_queue) { | |||||
493 | outb(0x80 | lp->tx_queue, ioaddr + TX_START)((__builtin_constant_p((ioaddr + 10)) && (ioaddr + 10 ) < 256) ? __outbc((0x80 | lp->tx_queue),(ioaddr + 10)) : __outb((0x80 | lp->tx_queue),(ioaddr + 10))); | |||||
494 | lp->tx_queue = 0; | |||||
495 | lp->tx_queue_len = 0; | |||||
496 | dev->trans_start = jiffies; | |||||
497 | dev->tbusy = 0; | |||||
498 | mark_bh(NET_BH); /* Inform upper layers. */ | |||||
499 | } else { | |||||
500 | lp->tx_started = 0; | |||||
501 | /* Turn on Tx interrupts off. */ | |||||
502 | outb(0x00, ioaddr + TX_INTR)((__builtin_constant_p((ioaddr + 2)) && (ioaddr + 2) < 256) ? __outbc((0x00),(ioaddr + 2)) : __outb((0x00),(ioaddr + 2))); | |||||
503 | dev->tbusy = 0; | |||||
504 | mark_bh(NET_BH); /* Inform upper layers. */ | |||||
505 | } | |||||
506 | } | |||||
507 | } | |||||
508 | ||||||
509 | dev->interrupt = 0; | |||||
510 | return; | |||||
511 | } | |||||
512 | ||||||
513 | /* We have a good packet(s), get it/them out of the buffers. */ | |||||
514 | static void | |||||
515 | net_rx(struct devicelinux_device *dev) | |||||
516 | { | |||||
517 | struct net_local *lp = (struct net_local *)dev->priv; | |||||
518 | int ioaddr = dev->base_addr; | |||||
519 | int boguscount = 5; | |||||
520 | ||||||
521 | while ((inb(ioaddr + RX_MODE)((__builtin_constant_p((ioaddr + 5)) && (ioaddr + 5) < 256) ? __inbc(ioaddr + 5) : __inb(ioaddr + 5)) & 0x40) == 0) { | |||||
522 | ushort status = inw(ioaddr + DATAPORT)((__builtin_constant_p((ioaddr + 8)) && (ioaddr + 8) < 256) ? __inwc(ioaddr + 8) : __inw(ioaddr + 8)); | |||||
523 | ushort pkt_len = inw(ioaddr + DATAPORT)((__builtin_constant_p((ioaddr + 8)) && (ioaddr + 8) < 256) ? __inwc(ioaddr + 8) : __inw(ioaddr + 8)); | |||||
524 | ||||||
525 | if (net_debug > 4) | |||||
526 | printk("%s: Rxing packet mode %02x status %04x.\n", | |||||
527 | dev->name, inb(ioaddr + RX_MODE)((__builtin_constant_p((ioaddr + 5)) && (ioaddr + 5) < 256) ? __inbc(ioaddr + 5) : __inb(ioaddr + 5)), status); | |||||
528 | #ifndef final_version | |||||
529 | if (status == 0) { | |||||
530 | outb(0x05, ioaddr + 14)((__builtin_constant_p((ioaddr + 14)) && (ioaddr + 14 ) < 256) ? __outbc((0x05),(ioaddr + 14)) : __outb((0x05),( ioaddr + 14))); | |||||
531 | break; | |||||
532 | } | |||||
533 | #endif | |||||
534 | ||||||
535 | if ((status & 0xF0) != 0x20) { /* There was an error. */ | |||||
536 | lp->stats.rx_errors++; | |||||
537 | if (status & 0x08) lp->stats.rx_length_errors++; | |||||
538 | if (status & 0x04) lp->stats.rx_frame_errors++; | |||||
539 | if (status & 0x02) lp->stats.rx_crc_errors++; | |||||
540 | if (status & 0x01) lp->stats.rx_over_errors++; | |||||
541 | } else { | |||||
542 | /* Malloc up new buffer. */ | |||||
543 | struct sk_buff *skb; | |||||
544 | ||||||
545 | if (pkt_len > 1550) { | |||||
546 | printk("%s: The AT1700 claimed a very large packet, size %d.\n", | |||||
547 | dev->name, pkt_len); | |||||
548 | /* Prime the FIFO and then flush the packet. */ | |||||
549 | inw(ioaddr + DATAPORT)((__builtin_constant_p((ioaddr + 8)) && (ioaddr + 8) < 256) ? __inwc(ioaddr + 8) : __inw(ioaddr + 8)); inw(ioaddr + DATAPORT)((__builtin_constant_p((ioaddr + 8)) && (ioaddr + 8) < 256) ? __inwc(ioaddr + 8) : __inw(ioaddr + 8)); | |||||
550 | outb(0x05, ioaddr + 14)((__builtin_constant_p((ioaddr + 14)) && (ioaddr + 14 ) < 256) ? __outbc((0x05),(ioaddr + 14)) : __outb((0x05),( ioaddr + 14))); | |||||
551 | lp->stats.rx_errors++; | |||||
552 | break; | |||||
553 | } | |||||
554 | skb = dev_alloc_skb(pkt_len+3); | |||||
555 | if (skb == NULL((void *) 0)) { | |||||
556 | printk("%s: Memory squeeze, dropping packet (len %d).\n", | |||||
557 | dev->name, pkt_len); | |||||
558 | /* Prime the FIFO and then flush the packet. */ | |||||
559 | inw(ioaddr + DATAPORT)((__builtin_constant_p((ioaddr + 8)) && (ioaddr + 8) < 256) ? __inwc(ioaddr + 8) : __inw(ioaddr + 8)); inw(ioaddr + DATAPORT)((__builtin_constant_p((ioaddr + 8)) && (ioaddr + 8) < 256) ? __inwc(ioaddr + 8) : __inw(ioaddr + 8)); | |||||
560 | outb(0x05, ioaddr + 14)((__builtin_constant_p((ioaddr + 14)) && (ioaddr + 14 ) < 256) ? __outbc((0x05),(ioaddr + 14)) : __outb((0x05),( ioaddr + 14))); | |||||
561 | lp->stats.rx_dropped++; | |||||
562 | break; | |||||
563 | } | |||||
564 | skb->dev = dev; | |||||
565 | skb_reserve(skb,2); | |||||
566 | ||||||
567 | insw(ioaddr + DATAPORT8, skb_put(skb,pkt_len), (pkt_len + 1) >> 1); | |||||
568 | skb->protocol=eth_type_trans(skb, dev)((unsigned short)0); | |||||
569 | netif_rx(skb); | |||||
570 | lp->stats.rx_packets++; | |||||
571 | } | |||||
572 | if (--boguscount <= 0) | |||||
573 | break; | |||||
574 | } | |||||
575 | ||||||
576 | /* If any worth-while packets have been received, dev_rint() | |||||
577 | has done a mark_bh(NET_BH) for us and will work on them | |||||
578 | when we get to the bottom-half routine. */ | |||||
579 | { | |||||
580 | int i; | |||||
581 | for (i = 0; i < 20; i++) { | |||||
582 | if ((inb(ioaddr + RX_MODE)((__builtin_constant_p((ioaddr + 5)) && (ioaddr + 5) < 256) ? __inbc(ioaddr + 5) : __inb(ioaddr + 5)) & 0x40) == 0x40) | |||||
583 | break; | |||||
584 | inw(ioaddr + DATAPORT)((__builtin_constant_p((ioaddr + 8)) && (ioaddr + 8) < 256) ? __inwc(ioaddr + 8) : __inw(ioaddr + 8)); /* dummy status read */ | |||||
585 | outb(0x05, ioaddr + 14)((__builtin_constant_p((ioaddr + 14)) && (ioaddr + 14 ) < 256) ? __outbc((0x05),(ioaddr + 14)) : __outb((0x05),( ioaddr + 14))); | |||||
586 | } | |||||
587 | ||||||
588 | if (net_debug > 5) | |||||
589 | printk("%s: Exint Rx packet with mode %02x after %d ticks.\n", | |||||
590 | dev->name, inb(ioaddr + RX_MODE)((__builtin_constant_p((ioaddr + 5)) && (ioaddr + 5) < 256) ? __inbc(ioaddr + 5) : __inb(ioaddr + 5)), i); | |||||
591 | } | |||||
592 | return; | |||||
593 | } | |||||
594 | ||||||
595 | /* The inverse routine to net_open(). */ | |||||
596 | static int net_close(struct devicelinux_device *dev) | |||||
597 | { | |||||
598 | #if 0 | |||||
599 | struct net_local *lp = (struct net_local *)dev->priv; | |||||
600 | #endif | |||||
601 | int ioaddr = dev->base_addr; | |||||
602 | ||||||
603 | dev->tbusy = 1; | |||||
604 | dev->start = 0; | |||||
605 | ||||||
606 | /* Set configuration register 0 to disable Tx and Rx. */ | |||||
607 | outb(0xda, ioaddr + CONFIG_0)((__builtin_constant_p((ioaddr + 6)) && (ioaddr + 6) < 256) ? __outbc((0xda),(ioaddr + 6)) : __outb((0xda),(ioaddr + 6))); | |||||
608 | ||||||
609 | /* No statistic counters on the chip to update. */ | |||||
610 | ||||||
611 | #if 0 | |||||
612 | /* Disable the IRQ on boards where it is feasible. */ | |||||
613 | if (lp->jumpered) { | |||||
614 | outb(0x00, ioaddr + IOCONFIG1)((__builtin_constant_p((ioaddr + 19)) && (ioaddr + 19 ) < 256) ? __outbc((0x00),(ioaddr + 19)) : __outb((0x00),( ioaddr + 19))); | |||||
615 | free_irq(dev->irq, dev); | |||||
616 | } | |||||
617 | #endif | |||||
618 | ||||||
619 | /* Power-down the chip. Green, green, green! */ | |||||
620 | outb(0x00, ioaddr + CONFIG_1)((__builtin_constant_p((ioaddr + 7)) && (ioaddr + 7) < 256) ? __outbc((0x00),(ioaddr + 7)) : __outb((0x00),(ioaddr + 7))); | |||||
621 | ||||||
622 | MOD_DEC_USE_COUNTdo { } while (0); | |||||
623 | ||||||
624 | return 0; | |||||
625 | } | |||||
626 | ||||||
627 | /* Get the current statistics. | |||||
628 | This may be called with the card open or closed. | |||||
629 | There are no on-chip counters, so this function is trivial. | |||||
630 | */ | |||||
631 | static struct enet_statistics * | |||||
632 | net_get_stats(struct devicelinux_device *dev) | |||||
633 | { | |||||
634 | struct net_local *lp = (struct net_local *)dev->priv; | |||||
635 | return &lp->stats; | |||||
636 | } | |||||
637 | ||||||
638 | /* | |||||
639 | Set the multicast/promiscuous mode for this adaptor. | |||||
640 | */ | |||||
641 | ||||||
642 | /* The little-endian AUTODIN II ethernet CRC calculation. | |||||
643 | N.B. Do not use for bulk data, use a table-based routine instead. | |||||
644 | This is common code and should be moved to net/core/crc.c */ | |||||
645 | static unsigned const ethernet_polynomial_le = 0xedb88320U; | |||||
646 | static inlineinline __attribute__((always_inline)) unsigned ether_crc_le(int length, unsigned char *data) | |||||
647 | { | |||||
648 | unsigned int crc = 0xffffffff; /* Initial value. */ | |||||
649 | while(--length >= 0) { | |||||
650 | unsigned char current_octet = *data++; | |||||
651 | int bit; | |||||
652 | for (bit = 8; --bit >= 0; current_octet >>= 1) { | |||||
653 | if ((crc ^ current_octet) & 1) { | |||||
654 | crc >>= 1; | |||||
655 | crc ^= ethernet_polynomial_le; | |||||
656 | } else | |||||
657 | crc >>= 1; | |||||
658 | } | |||||
659 | } | |||||
660 | return crc; | |||||
661 | } | |||||
662 | ||||||
663 | static void | |||||
664 | set_rx_mode(struct devicelinux_device *dev) | |||||
665 | { | |||||
666 | int ioaddr = dev->base_addr; | |||||
667 | struct net_local *lp = (struct net_local *)dev->priv; | |||||
668 | unsigned char mc_filter[8]; /* Multicast hash filter */ | |||||
669 | long flags; | |||||
670 | int i; | |||||
671 | ||||||
672 | if (dev->flags & IFF_PROMISC0x100) { | |||||
| ||||||
673 | /* Unconditionally log net taps. */ | |||||
674 | printk("%s: Promiscuous mode enabled.\n", dev->name); | |||||
675 | memset(mc_filter, 0xff, sizeof(mc_filter))(__builtin_constant_p(0xff) ? (__builtin_constant_p((sizeof(mc_filter ))) ? __constant_c_and_count_memset(((mc_filter)),((0x01010101UL *(unsigned char)(0xff))),((sizeof(mc_filter)))) : __constant_c_memset (((mc_filter)),((0x01010101UL*(unsigned char)(0xff))),((sizeof (mc_filter))))) : (__builtin_constant_p((sizeof(mc_filter))) ? __memset_generic((((mc_filter))),(((0xff))),(((sizeof(mc_filter ))))) : __memset_generic(((mc_filter)),((0xff)),((sizeof(mc_filter )))))); | |||||
676 | outb(3, ioaddr + RX_MODE)((__builtin_constant_p((ioaddr + 5)) && (ioaddr + 5) < 256) ? __outbc((3),(ioaddr + 5)) : __outb((3),(ioaddr + 5))); /* Enable promiscuous mode */ | |||||
677 | } else if (dev->mc_count > MC_FILTERBREAK64 | |||||
678 | || (dev->flags & IFF_ALLMULTI0x200)) { | |||||
679 | /* Too many to filter perfectly -- accept all multicasts. */ | |||||
680 | memset(mc_filter, 0xff, sizeof(mc_filter))(__builtin_constant_p(0xff) ? (__builtin_constant_p((sizeof(mc_filter ))) ? __constant_c_and_count_memset(((mc_filter)),((0x01010101UL *(unsigned char)(0xff))),((sizeof(mc_filter)))) : __constant_c_memset (((mc_filter)),((0x01010101UL*(unsigned char)(0xff))),((sizeof (mc_filter))))) : (__builtin_constant_p((sizeof(mc_filter))) ? __memset_generic((((mc_filter))),(((0xff))),(((sizeof(mc_filter ))))) : __memset_generic(((mc_filter)),((0xff)),((sizeof(mc_filter )))))); | |||||
681 | outb(2, ioaddr + RX_MODE)((__builtin_constant_p((ioaddr + 5)) && (ioaddr + 5) < 256) ? __outbc((2),(ioaddr + 5)) : __outb((2),(ioaddr + 5))); /* Use normal mode. */ | |||||
682 | } else if (dev->mc_count == 0) { | |||||
683 | memset(mc_filter, 0x00, sizeof(mc_filter))(__builtin_constant_p(0x00) ? (__builtin_constant_p((sizeof(mc_filter ))) ? __constant_c_and_count_memset(((mc_filter)),((0x01010101UL *(unsigned char)(0x00))),((sizeof(mc_filter)))) : __constant_c_memset (((mc_filter)),((0x01010101UL*(unsigned char)(0x00))),((sizeof (mc_filter))))) : (__builtin_constant_p((sizeof(mc_filter))) ? __memset_generic((((mc_filter))),(((0x00))),(((sizeof(mc_filter ))))) : __memset_generic(((mc_filter)),((0x00)),((sizeof(mc_filter )))))); | |||||
684 | outb(1, ioaddr + RX_MODE)((__builtin_constant_p((ioaddr + 5)) && (ioaddr + 5) < 256) ? __outbc((1),(ioaddr + 5)) : __outb((1),(ioaddr + 5))); /* Ignore almost all multicasts. */ | |||||
685 | } else { | |||||
686 | struct dev_mc_list *mclist; | |||||
687 | int i; | |||||
688 | ||||||
689 | memset(mc_filter, 0, sizeof(mc_filter))(__builtin_constant_p(0) ? (__builtin_constant_p((sizeof(mc_filter ))) ? __constant_c_and_count_memset(((mc_filter)),((0x01010101UL *(unsigned char)(0))),((sizeof(mc_filter)))) : __constant_c_memset (((mc_filter)),((0x01010101UL*(unsigned char)(0))),((sizeof(mc_filter ))))) : (__builtin_constant_p((sizeof(mc_filter))) ? __memset_generic ((((mc_filter))),(((0))),(((sizeof(mc_filter))))) : __memset_generic (((mc_filter)),((0)),((sizeof(mc_filter)))))); | |||||
690 | for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; | |||||
691 | i++, mclist = mclist->next) | |||||
692 | set_bit(ether_crc_le(ETH_ALEN6, mclist->dmi_addr) >> 26, | |||||
693 | mc_filter); | |||||
694 | } | |||||
695 | ||||||
696 | save_flags(flags)__asm__ __volatile__("pushf ; pop %0" : "=r" (flags): :"memory" ); | |||||
697 | cli()__asm__ __volatile__ ("cli": : :"memory"); | |||||
698 | if (memcmp__builtin_memcmp(mc_filter, lp->mc_filter, sizeof(mc_filter))) { | |||||
699 | int saved_bank = inw(ioaddr + CONFIG_0)((__builtin_constant_p((ioaddr + 6)) && (ioaddr + 6) < 256) ? __inwc(ioaddr + 6) : __inw(ioaddr + 6)); | |||||
700 | /* Switch to bank 1 and set the multicast table. */ | |||||
701 | outw((saved_bank & ~0x0C00) | 0x0480, ioaddr + CONFIG_0)((__builtin_constant_p((ioaddr + 6)) && (ioaddr + 6) < 256) ? __outwc(((saved_bank & ~0x0C00) | 0x0480),(ioaddr + 6)) : __outw(((saved_bank & ~0x0C00) | 0x0480),(ioaddr + 6))); | |||||
702 | for (i = 0; i < 8; i++) | |||||
703 | outb(mc_filter[i], ioaddr + 8 + i)((__builtin_constant_p((ioaddr + 8 + i)) && (ioaddr + 8 + i) < 256) ? __outbc((mc_filter[i]),(ioaddr + 8 + i)) : __outb((mc_filter[i]),(ioaddr + 8 + i))); | |||||
| ||||||
704 | memcpy(lp->mc_filter, mc_filter, sizeof(mc_filter))(__builtin_constant_p(sizeof(mc_filter)) ? __constant_memcpy( (lp->mc_filter),(mc_filter),(sizeof(mc_filter))) : __memcpy ((lp->mc_filter),(mc_filter),(sizeof(mc_filter)))); | |||||
705 | outw(saved_bank, ioaddr + CONFIG_0)((__builtin_constant_p((ioaddr + 6)) && (ioaddr + 6) < 256) ? __outwc((saved_bank),(ioaddr + 6)) : __outw((saved_bank ),(ioaddr + 6))); | |||||
706 | } | |||||
707 | restore_flags(flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); | |||||
708 | return; | |||||
709 | } | |||||
710 | ||||||
711 | #ifdef MODULE | |||||
712 | static char devicename[9] = { 0, }; | |||||
713 | static struct devicelinux_device dev_at1700 = { | |||||
714 | devicename, /* device name is inserted by linux/drivers/net/net_init.c */ | |||||
715 | 0, 0, 0, 0, | |||||
716 | 0, 0, | |||||
717 | 0, 0, 0, NULL((void *) 0), at1700_probe }; | |||||
718 | ||||||
719 | static int io = 0x260; | |||||
720 | static int irq = 0; | |||||
721 | ||||||
722 | int init_module(void) | |||||
723 | { | |||||
724 | if (io == 0) | |||||
725 | printk("at1700: You should not use auto-probing with insmod!\n"); | |||||
726 | dev_at1700.base_addr = io; | |||||
727 | dev_at1700.irq = irq; | |||||
728 | if (register_netdev(&dev_at1700) != 0) { | |||||
729 | printk("at1700: register_netdev() returned non-zero.\n"); | |||||
730 | return -EIO5; | |||||
731 | } | |||||
732 | return 0; | |||||
733 | } | |||||
734 | ||||||
735 | void | |||||
736 | cleanup_module(void) | |||||
737 | { | |||||
738 | unregister_netdev(&dev_at1700); | |||||
739 | kfreelinux_kfree(dev_at1700.priv); | |||||
740 | dev_at1700.priv = NULL((void *) 0); | |||||
741 | ||||||
742 | /* If we don't do this, we can't re-insmod it later. */ | |||||
743 | free_irq(dev_at1700.irq, NULL((void *) 0)); | |||||
744 | release_region(dev_at1700.base_addr, AT1700_IO_EXTENT32); | |||||
745 | } | |||||
746 | #endif /* MODULE */ | |||||
747 | ||||||
748 | /* | |||||
749 | * Local variables: | |||||
750 | * compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c at1700.c" | |||||
751 | * alt-compile-command: "gcc -DMODVERSIONS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c at1700.c" | |||||
752 | * tab-width: 4 | |||||
753 | * c-basic-offset: 4 | |||||
754 | * c-indent-level: 4 | |||||
755 | * End: | |||||
756 | */ |