diff options
author | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2011-06-11 04:13:22 -0400 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2011-08-12 03:22:08 -0400 |
commit | 5346ebf6db077d963e9d81af9df290d7f5532492 (patch) | |
tree | 599c964dc98a13be7af437172b1002b5bf2cbf71 /drivers/net/eth16i.c | |
parent | f2148a472883ddf77626fff52b070655a8a0a788 (diff) |
eth16i: Move the Allied Telesis/Fujitsu drivers
Move the Allied Telesis/Fujitsu drivers into drivers/net/ethernet/fujitsu/
and make the necessary Kconfig and Makefile changes.
CC: Shingo Fujimoto <shingo@flab.fujitsu.co.jp>
CC: Yutaka Tamiya <tamy@flab.fujitsu.co.jp>
CC: Rene Schmit <rene@bss.lu>
CC: Mika Kuoppala <miku@iki.fi>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/eth16i.c')
-rw-r--r-- | drivers/net/eth16i.c | 1484 |
1 files changed, 0 insertions, 1484 deletions
diff --git a/drivers/net/eth16i.c b/drivers/net/eth16i.c deleted file mode 100644 index 12d28e9d0cb7..000000000000 --- a/drivers/net/eth16i.c +++ /dev/null | |||
@@ -1,1484 +0,0 @@ | |||
1 | /* eth16i.c An ICL EtherTeam 16i and 32 EISA ethernet driver for Linux | ||
2 | |||
3 | Written 1994-1999 by Mika Kuoppala | ||
4 | |||
5 | Copyright (C) 1994-1999 by Mika Kuoppala | ||
6 | Based on skeleton.c and heavily on at1700.c by Donald Becker | ||
7 | |||
8 | This software may be used and distributed according to the terms | ||
9 | of the GNU General Public License, incorporated herein by reference. | ||
10 | |||
11 | The author may be reached as miku@iki.fi | ||
12 | |||
13 | This driver supports following cards : | ||
14 | - ICL EtherTeam 16i | ||
15 | - ICL EtherTeam 32 EISA | ||
16 | (Uses true 32 bit transfers rather than 16i compatibility mode) | ||
17 | |||
18 | Example Module usage: | ||
19 | insmod eth16i.o io=0x2a0 mediatype=bnc | ||
20 | |||
21 | mediatype can be one of the following: bnc,tp,dix,auto,eprom | ||
22 | |||
23 | 'auto' will try to autoprobe mediatype. | ||
24 | 'eprom' will use whatever type defined in eprom. | ||
25 | |||
26 | I have benchmarked driver with PII/300Mhz as a ftp client | ||
27 | and 486/33Mhz as a ftp server. Top speed was 1128.37 kilobytes/sec. | ||
28 | |||
29 | Sources: | ||
30 | - skeleton.c a sample network driver core for linux, | ||
31 | written by Donald Becker <becker@scyld.com> | ||
32 | - at1700.c a driver for Allied Telesis AT1700, written | ||
33 | by Donald Becker. | ||
34 | - e16iSRV.asm a Netware 3.X Server Driver for ICL EtherTeam16i | ||
35 | written by Markku Viima | ||
36 | - The Fujitsu MB86965 databook. | ||
37 | |||
38 | Author thanks following persons due to their valueble assistance: | ||
39 | Markku Viima (ICL) | ||
40 | Ari Valve (ICL) | ||
41 | Donald Becker | ||
42 | Kurt Huwig <kurt@huwig.de> | ||
43 | |||
44 | Revision history: | ||
45 | |||
46 | Version Date Description | ||
47 | |||
48 | 0.01 15.12-94 Initial version (card detection) | ||
49 | 0.02 23.01-95 Interrupt is now hooked correctly | ||
50 | 0.03 01.02-95 Rewrote initialization part | ||
51 | 0.04 07.02-95 Base skeleton done... | ||
52 | Made a few changes to signature checking | ||
53 | to make it a bit reliable. | ||
54 | - fixed bug in tx_buf mapping | ||
55 | - fixed bug in initialization (DLC_EN | ||
56 | wasn't enabled when initialization | ||
57 | was done.) | ||
58 | 0.05 08.02-95 If there were more than one packet to send, | ||
59 | transmit was jammed due to invalid | ||
60 | register write...now fixed | ||
61 | 0.06 19.02-95 Rewrote interrupt handling | ||
62 | 0.07 13.04-95 Wrote EEPROM read routines | ||
63 | Card configuration now set according to | ||
64 | data read from EEPROM | ||
65 | 0.08 23.06-95 Wrote part that tries to probe used interface | ||
66 | port if AUTO is selected | ||
67 | |||
68 | 0.09 01.09-95 Added module support | ||
69 | |||
70 | 0.10 04.09-95 Fixed receive packet allocation to work | ||
71 | with kernels > 1.3.x | ||
72 | |||
73 | 0.20 20.09-95 Added support for EtherTeam32 EISA | ||
74 | |||
75 | 0.21 17.10-95 Removed the unnecessary extern | ||
76 | init_etherdev() declaration. Some | ||
77 | other cleanups. | ||
78 | |||
79 | 0.22 22.02-96 Receive buffer was not flushed | ||
80 | correctly when faulty packet was | ||
81 | received. Now fixed. | ||
82 | |||
83 | 0.23 26.02-96 Made resetting the adapter | ||
84 | more reliable. | ||
85 | |||
86 | 0.24 27.02-96 Rewrote faulty packet handling in eth16i_rx | ||
87 | |||
88 | 0.25 22.05-96 kfree() was missing from cleanup_module. | ||
89 | |||
90 | 0.26 11.06-96 Sometimes card was not found by | ||
91 | check_signature(). Now made more reliable. | ||
92 | |||
93 | 0.27 23.06-96 Oops. 16 consecutive collisions halted | ||
94 | adapter. Now will try to retransmit | ||
95 | MAX_COL_16 times before finally giving up. | ||
96 | |||
97 | 0.28 28.10-97 Added dev_id parameter (NULL) for free_irq | ||
98 | |||
99 | 0.29 29.10-97 Multiple card support for module users | ||
100 | |||
101 | 0.30 30.10-97 Fixed irq allocation bug. | ||
102 | (request_irq moved from probe to open) | ||
103 | |||
104 | 0.30a 21.08-98 Card detection made more relaxed. Driver | ||
105 | had problems with some TCP/IP-PROM boots | ||
106 | to find the card. Suggested by | ||
107 | Kurt Huwig <kurt@huwig.de> | ||
108 | |||
109 | 0.31 28.08-98 Media interface port can now be selected | ||
110 | with module parameters or kernel | ||
111 | boot parameters. | ||
112 | |||
113 | 0.32 31.08-98 IRQ was never freed if open/close | ||
114 | pair wasn't called. Now fixed. | ||
115 | |||
116 | 0.33 10.09-98 When eth16i_open() was called after | ||
117 | eth16i_close() chip never recovered. | ||
118 | Now more shallow reset is made on | ||
119 | close. | ||
120 | |||
121 | 0.34 29.06-99 Fixed one bad #ifdef. | ||
122 | Changed ioaddr -> io for consistency | ||
123 | |||
124 | 0.35 01.07-99 transmit,-receive bytes were never | ||
125 | updated in stats. | ||
126 | |||
127 | Bugs: | ||
128 | In some cases the media interface autoprobing code doesn't find | ||
129 | the correct interface type. In this case you can | ||
130 | manually choose the interface type in DOS with E16IC.EXE which is | ||
131 | configuration software for EtherTeam16i and EtherTeam32 cards. | ||
132 | This is also true for IRQ setting. You cannot use module | ||
133 | parameter to configure IRQ of the card (yet). | ||
134 | |||
135 | To do: | ||
136 | - Real multicast support | ||
137 | - Rewrite the media interface autoprobing code. Its _horrible_ ! | ||
138 | - Possibly merge all the MB86965 specific code to external | ||
139 | module for use by eth16.c and Donald's at1700.c | ||
140 | - IRQ configuration with module parameter. I will do | ||
141 | this when i will get enough info about setting | ||
142 | irq without configuration utility. | ||
143 | */ | ||
144 | |||
145 | static char *version = | ||
146 | "eth16i.c: v0.35 01-Jul-1999 Mika Kuoppala (miku@iki.fi)\n"; | ||
147 | |||
148 | #include <linux/module.h> | ||
149 | #include <linux/kernel.h> | ||
150 | #include <linux/types.h> | ||
151 | #include <linux/fcntl.h> | ||
152 | #include <linux/interrupt.h> | ||
153 | #include <linux/ioport.h> | ||
154 | #include <linux/in.h> | ||
155 | #include <linux/string.h> | ||
156 | #include <linux/errno.h> | ||
157 | #include <linux/init.h> | ||
158 | #include <linux/spinlock.h> | ||
159 | #include <linux/netdevice.h> | ||
160 | #include <linux/etherdevice.h> | ||
161 | #include <linux/skbuff.h> | ||
162 | #include <linux/bitops.h> | ||
163 | #include <linux/jiffies.h> | ||
164 | #include <linux/io.h> | ||
165 | |||
166 | #include <asm/system.h> | ||
167 | #include <asm/dma.h> | ||
168 | |||
169 | |||
170 | |||
171 | /* Few macros */ | ||
172 | #define BITSET(ioaddr, bnum) ((outb(((inb(ioaddr)) | (bnum)), ioaddr))) | ||
173 | #define BITCLR(ioaddr, bnum) ((outb(((inb(ioaddr)) & (~(bnum))), ioaddr))) | ||
174 | |||
175 | /* This is the I/O address space for Etherteam 16i adapter. */ | ||
176 | #define ETH16I_IO_EXTENT 32 | ||
177 | |||
178 | /* Ticks before deciding that transmit has timed out */ | ||
179 | #define TX_TIMEOUT (400*HZ/1000) | ||
180 | |||
181 | /* Maximum loop count when receiving packets */ | ||
182 | #define MAX_RX_LOOP 20 | ||
183 | |||
184 | /* Some interrupt masks */ | ||
185 | #define ETH16I_INTR_ON 0xef8a /* Higher is receive mask */ | ||
186 | #define ETH16I_INTR_OFF 0x0000 | ||
187 | |||
188 | /* Buffers header status byte meanings */ | ||
189 | #define PKT_GOOD BIT(5) | ||
190 | #define PKT_GOOD_RMT BIT(4) | ||
191 | #define PKT_SHORT BIT(3) | ||
192 | #define PKT_ALIGN_ERR BIT(2) | ||
193 | #define PKT_CRC_ERR BIT(1) | ||
194 | #define PKT_RX_BUF_OVERFLOW BIT(0) | ||
195 | |||
196 | /* Transmit status register (DLCR0) */ | ||
197 | #define TX_STATUS_REG 0 | ||
198 | #define TX_DONE BIT(7) | ||
199 | #define NET_BUSY BIT(6) | ||
200 | #define TX_PKT_RCD BIT(5) | ||
201 | #define CR_LOST BIT(4) | ||
202 | #define TX_JABBER_ERR BIT(3) | ||
203 | #define COLLISION BIT(2) | ||
204 | #define COLLISIONS_16 BIT(1) | ||
205 | |||
206 | /* Receive status register (DLCR1) */ | ||
207 | #define RX_STATUS_REG 1 | ||
208 | #define RX_PKT BIT(7) /* Packet received */ | ||
209 | #define BUS_RD_ERR BIT(6) | ||
210 | #define SHORT_PKT_ERR BIT(3) | ||
211 | #define ALIGN_ERR BIT(2) | ||
212 | #define CRC_ERR BIT(1) | ||
213 | #define RX_BUF_OVERFLOW BIT(0) | ||
214 | |||
215 | /* Transmit Interrupt Enable Register (DLCR2) */ | ||
216 | #define TX_INTR_REG 2 | ||
217 | #define TX_INTR_DONE BIT(7) | ||
218 | #define TX_INTR_COL BIT(2) | ||
219 | #define TX_INTR_16_COL BIT(1) | ||
220 | |||
221 | /* Receive Interrupt Enable Register (DLCR3) */ | ||
222 | #define RX_INTR_REG 3 | ||
223 | #define RX_INTR_RECEIVE BIT(7) | ||
224 | #define RX_INTR_SHORT_PKT BIT(3) | ||
225 | #define RX_INTR_CRC_ERR BIT(1) | ||
226 | #define RX_INTR_BUF_OVERFLOW BIT(0) | ||
227 | |||
228 | /* Transmit Mode Register (DLCR4) */ | ||
229 | #define TRANSMIT_MODE_REG 4 | ||
230 | #define LOOPBACK_CONTROL BIT(1) | ||
231 | #define CONTROL_OUTPUT BIT(2) | ||
232 | |||
233 | /* Receive Mode Register (DLCR5) */ | ||
234 | #define RECEIVE_MODE_REG 5 | ||
235 | #define RX_BUFFER_EMPTY BIT(6) | ||
236 | #define ACCEPT_BAD_PACKETS BIT(5) | ||
237 | #define RECEIVE_SHORT_ADDR BIT(4) | ||
238 | #define ACCEPT_SHORT_PACKETS BIT(3) | ||
239 | #define REMOTE_RESET BIT(2) | ||
240 | |||
241 | #define ADDRESS_FILTER_MODE BIT(1) | BIT(0) | ||
242 | #define REJECT_ALL 0 | ||
243 | #define ACCEPT_ALL 3 | ||
244 | #define MODE_1 1 /* NODE ID, BC, MC, 2-24th bit */ | ||
245 | #define MODE_2 2 /* NODE ID, BC, MC, Hash Table */ | ||
246 | |||
247 | /* Configuration Register 0 (DLCR6) */ | ||
248 | #define CONFIG_REG_0 6 | ||
249 | #define DLC_EN BIT(7) | ||
250 | #define SRAM_CYCLE_TIME_100NS BIT(6) | ||
251 | #define SYSTEM_BUS_WIDTH_8 BIT(5) /* 1 = 8bit, 0 = 16bit */ | ||
252 | #define BUFFER_WIDTH_8 BIT(4) /* 1 = 8bit, 0 = 16bit */ | ||
253 | #define TBS1 BIT(3) | ||
254 | #define TBS0 BIT(2) | ||
255 | #define SRAM_BS1 BIT(1) /* 00=8kb, 01=16kb */ | ||
256 | #define SRAM_BS0 BIT(0) /* 10=32kb, 11=64kb */ | ||
257 | |||
258 | #ifndef ETH16I_TX_BUF_SIZE /* 0 = 2kb, 1 = 4kb */ | ||
259 | #define ETH16I_TX_BUF_SIZE 3 /* 2 = 8kb, 3 = 16kb */ | ||
260 | #endif | ||
261 | #define TX_BUF_1x2048 0 | ||
262 | #define TX_BUF_2x2048 1 | ||
263 | #define TX_BUF_2x4098 2 | ||
264 | #define TX_BUF_2x8192 3 | ||
265 | |||
266 | /* Configuration Register 1 (DLCR7) */ | ||
267 | #define CONFIG_REG_1 7 | ||
268 | #define POWERUP BIT(5) | ||
269 | |||
270 | /* Transmit start register */ | ||
271 | #define TRANSMIT_START_REG 10 | ||
272 | #define TRANSMIT_START_RB 2 | ||
273 | #define TX_START BIT(7) /* Rest of register bit indicate*/ | ||
274 | /* number of packets in tx buffer*/ | ||
275 | /* Node ID registers (DLCR8-13) */ | ||
276 | #define NODE_ID_0 8 | ||
277 | #define NODE_ID_RB 0 | ||
278 | |||
279 | /* Hash Table registers (HT8-15) */ | ||
280 | #define HASH_TABLE_0 8 | ||
281 | #define HASH_TABLE_RB 1 | ||
282 | |||
283 | /* Buffer memory ports */ | ||
284 | #define BUFFER_MEM_PORT_LB 8 | ||
285 | #define DATAPORT BUFFER_MEM_PORT_LB | ||
286 | #define BUFFER_MEM_PORT_HB 9 | ||
287 | |||
288 | /* 16 Collision control register (BMPR11) */ | ||
289 | #define COL_16_REG 11 | ||
290 | #define HALT_ON_16 0x00 | ||
291 | #define RETRANS_AND_HALT_ON_16 0x02 | ||
292 | |||
293 | /* Maximum number of attempts to send after 16 concecutive collisions */ | ||
294 | #define MAX_COL_16 10 | ||
295 | |||
296 | /* DMA Burst and Transceiver Mode Register (BMPR13) */ | ||
297 | #define TRANSCEIVER_MODE_REG 13 | ||
298 | #define TRANSCEIVER_MODE_RB 2 | ||
299 | #define IO_BASE_UNLOCK BIT(7) | ||
300 | #define LOWER_SQUELCH_TRESH BIT(6) | ||
301 | #define LINK_TEST_DISABLE BIT(5) | ||
302 | #define AUI_SELECT BIT(4) | ||
303 | #define DIS_AUTO_PORT_SEL BIT(3) | ||
304 | |||
305 | /* Filter Self Receive Register (BMPR14) */ | ||
306 | #define FILTER_SELF_RX_REG 14 | ||
307 | #define SKIP_RX_PACKET BIT(2) | ||
308 | #define FILTER_SELF_RECEIVE BIT(0) | ||
309 | |||
310 | /* EEPROM Control Register (BMPR 16) */ | ||
311 | #define EEPROM_CTRL_REG 16 | ||
312 | |||
313 | /* EEPROM Data Register (BMPR 17) */ | ||
314 | #define EEPROM_DATA_REG 17 | ||
315 | |||
316 | /* NMC93CSx6 EEPROM Control Bits */ | ||
317 | #define CS_0 0x00 | ||
318 | #define CS_1 0x20 | ||
319 | #define SK_0 0x00 | ||
320 | #define SK_1 0x40 | ||
321 | #define DI_0 0x00 | ||
322 | #define DI_1 0x80 | ||
323 | |||
324 | /* NMC93CSx6 EEPROM Instructions */ | ||
325 | #define EEPROM_READ 0x80 | ||
326 | |||
327 | /* NMC93CSx6 EEPROM Addresses */ | ||
328 | #define E_NODEID_0 0x02 | ||
329 | #define E_NODEID_1 0x03 | ||
330 | #define E_NODEID_2 0x04 | ||
331 | #define E_PORT_SELECT 0x14 | ||
332 | #define E_PORT_BNC 0x00 | ||
333 | #define E_PORT_DIX 0x01 | ||
334 | #define E_PORT_TP 0x02 | ||
335 | #define E_PORT_AUTO 0x03 | ||
336 | #define E_PORT_FROM_EPROM 0x04 | ||
337 | #define E_PRODUCT_CFG 0x30 | ||
338 | |||
339 | |||
340 | /* Macro to slow down io between EEPROM clock transitions */ | ||
341 | #define eeprom_slow_io() do { int _i = 40; while(--_i > 0) { inb(0x80); }}while(0) | ||
342 | |||
343 | /* Jumperless Configuration Register (BMPR19) */ | ||
344 | #define JUMPERLESS_CONFIG 19 | ||
345 | |||
346 | /* ID ROM registers, writing to them also resets some parts of chip */ | ||
347 | #define ID_ROM_0 24 | ||
348 | #define ID_ROM_7 31 | ||
349 | #define RESET ID_ROM_0 | ||
350 | |||
351 | /* This is the I/O address list to be probed when seeking the card */ | ||
352 | static unsigned int eth16i_portlist[] __initdata = { | ||
353 | 0x260, 0x280, 0x2A0, 0x240, 0x340, 0x320, 0x380, 0x300, 0 | ||
354 | }; | ||
355 | |||
356 | static unsigned int eth32i_portlist[] __initdata = { | ||
357 | 0x1000, 0x2000, 0x3000, 0x4000, 0x5000, 0x6000, 0x7000, 0x8000, | ||
358 | 0x9000, 0xA000, 0xB000, 0xC000, 0xD000, 0xE000, 0xF000, 0 | ||
359 | }; | ||
360 | |||
361 | /* This is the Interrupt lookup table for Eth16i card */ | ||
362 | static unsigned int eth16i_irqmap[] __initdata = { 9, 10, 5, 15, 0 }; | ||
363 | #define NUM_OF_ISA_IRQS 4 | ||
364 | |||
365 | /* This is the Interrupt lookup table for Eth32i card */ | ||
366 | static unsigned int eth32i_irqmap[] __initdata = { 3, 5, 7, 9, 10, 11, 12, 15, 0 }; | ||
367 | #define EISA_IRQ_REG 0xc89 | ||
368 | #define NUM_OF_EISA_IRQS 8 | ||
369 | |||
370 | static unsigned int eth16i_tx_buf_map[] = { 2048, 2048, 4096, 8192 }; | ||
371 | |||
372 | /* Use 0 for production, 1 for verification, >2 for debug */ | ||
373 | #ifndef ETH16I_DEBUG | ||
374 | #define ETH16I_DEBUG 0 | ||
375 | #endif | ||
376 | static unsigned int eth16i_debug = ETH16I_DEBUG; | ||
377 | |||
378 | /* Information for each board */ | ||
379 | |||
380 | struct eth16i_local { | ||
381 | unsigned char tx_started; | ||
382 | unsigned char tx_buf_busy; | ||
383 | unsigned short tx_queue; /* Number of packets in transmit buffer */ | ||
384 | unsigned short tx_queue_len; | ||
385 | unsigned int tx_buf_size; | ||
386 | unsigned long open_time; | ||
387 | unsigned long tx_buffered_packets; | ||
388 | unsigned long tx_buffered_bytes; | ||
389 | unsigned long col_16; | ||
390 | spinlock_t lock; | ||
391 | }; | ||
392 | |||
393 | /* Function prototypes */ | ||
394 | |||
395 | static int eth16i_probe1(struct net_device *dev, int ioaddr); | ||
396 | static int eth16i_check_signature(int ioaddr); | ||
397 | static int eth16i_probe_port(int ioaddr); | ||
398 | static void eth16i_set_port(int ioaddr, int porttype); | ||
399 | static int eth16i_send_probe_packet(int ioaddr, unsigned char *b, int l); | ||
400 | static int eth16i_receive_probe_packet(int ioaddr); | ||
401 | static int eth16i_get_irq(int ioaddr); | ||
402 | static int eth16i_read_eeprom(int ioaddr, int offset); | ||
403 | static int eth16i_read_eeprom_word(int ioaddr); | ||
404 | static void eth16i_eeprom_cmd(int ioaddr, unsigned char command); | ||
405 | static int eth16i_open(struct net_device *dev); | ||
406 | static int eth16i_close(struct net_device *dev); | ||
407 | static netdev_tx_t eth16i_tx(struct sk_buff *skb, struct net_device *dev); | ||
408 | static void eth16i_rx(struct net_device *dev); | ||
409 | static void eth16i_timeout(struct net_device *dev); | ||
410 | static irqreturn_t eth16i_interrupt(int irq, void *dev_id); | ||
411 | static void eth16i_reset(struct net_device *dev); | ||
412 | static void eth16i_timeout(struct net_device *dev); | ||
413 | static void eth16i_skip_packet(struct net_device *dev); | ||
414 | static void eth16i_multicast(struct net_device *dev); | ||
415 | static void eth16i_select_regbank(unsigned char regbank, int ioaddr); | ||
416 | static void eth16i_initialize(struct net_device *dev, int boot); | ||
417 | |||
418 | #if 0 | ||
419 | static int eth16i_set_irq(struct net_device *dev); | ||
420 | #endif | ||
421 | |||
422 | #ifdef MODULE | ||
423 | static ushort eth16i_parse_mediatype(const char* s); | ||
424 | #endif | ||
425 | |||
426 | static char cardname[] __initdata = "ICL EtherTeam 16i/32"; | ||
427 | |||
428 | static int __init do_eth16i_probe(struct net_device *dev) | ||
429 | { | ||
430 | int i; | ||
431 | int ioaddr; | ||
432 | int base_addr = dev->base_addr; | ||
433 | |||
434 | if(eth16i_debug > 4) | ||
435 | printk(KERN_DEBUG "Probing started for %s\n", cardname); | ||
436 | |||
437 | if(base_addr > 0x1ff) /* Check only single location */ | ||
438 | return eth16i_probe1(dev, base_addr); | ||
439 | else if(base_addr != 0) /* Don't probe at all */ | ||
440 | return -ENXIO; | ||
441 | |||
442 | /* Seek card from the ISA io address space */ | ||
443 | for(i = 0; (ioaddr = eth16i_portlist[i]) ; i++) | ||
444 | if(eth16i_probe1(dev, ioaddr) == 0) | ||
445 | return 0; | ||
446 | |||
447 | /* Seek card from the EISA io address space */ | ||
448 | for(i = 0; (ioaddr = eth32i_portlist[i]) ; i++) | ||
449 | if(eth16i_probe1(dev, ioaddr) == 0) | ||
450 | return 0; | ||
451 | |||
452 | return -ENODEV; | ||
453 | } | ||
454 | |||
455 | #ifndef MODULE | ||
456 | struct net_device * __init eth16i_probe(int unit) | ||
457 | { | ||
458 | struct net_device *dev = alloc_etherdev(sizeof(struct eth16i_local)); | ||
459 | int err; | ||
460 | |||
461 | if (!dev) | ||
462 | return ERR_PTR(-ENOMEM); | ||
463 | |||
464 | sprintf(dev->name, "eth%d", unit); | ||
465 | netdev_boot_setup_check(dev); | ||
466 | |||
467 | err = do_eth16i_probe(dev); | ||
468 | if (err) | ||
469 | goto out; | ||
470 | return dev; | ||
471 | out: | ||
472 | free_netdev(dev); | ||
473 | return ERR_PTR(err); | ||
474 | } | ||
475 | #endif | ||
476 | |||
477 | static const struct net_device_ops eth16i_netdev_ops = { | ||
478 | .ndo_open = eth16i_open, | ||
479 | .ndo_stop = eth16i_close, | ||
480 | .ndo_start_xmit = eth16i_tx, | ||
481 | .ndo_set_multicast_list = eth16i_multicast, | ||
482 | .ndo_tx_timeout = eth16i_timeout, | ||
483 | .ndo_change_mtu = eth_change_mtu, | ||
484 | .ndo_set_mac_address = eth_mac_addr, | ||
485 | .ndo_validate_addr = eth_validate_addr, | ||
486 | }; | ||
487 | |||
488 | static int __init eth16i_probe1(struct net_device *dev, int ioaddr) | ||
489 | { | ||
490 | struct eth16i_local *lp = netdev_priv(dev); | ||
491 | static unsigned version_printed; | ||
492 | int retval; | ||
493 | |||
494 | /* Let's grab the region */ | ||
495 | if (!request_region(ioaddr, ETH16I_IO_EXTENT, cardname)) | ||
496 | return -EBUSY; | ||
497 | |||
498 | /* | ||
499 | The MB86985 chip has on register which holds information in which | ||
500 | io address the chip lies. First read this register and compare | ||
501 | it to our current io address and if match then this could | ||
502 | be our chip. | ||
503 | */ | ||
504 | |||
505 | if(ioaddr < 0x1000) { | ||
506 | if(eth16i_portlist[(inb(ioaddr + JUMPERLESS_CONFIG) & 0x07)] | ||
507 | != ioaddr) { | ||
508 | retval = -ENODEV; | ||
509 | goto out; | ||
510 | } | ||
511 | } | ||
512 | |||
513 | /* Now we will go a bit deeper and try to find the chip's signature */ | ||
514 | |||
515 | if(eth16i_check_signature(ioaddr) != 0) { | ||
516 | retval = -ENODEV; | ||
517 | goto out; | ||
518 | } | ||
519 | |||
520 | /* | ||
521 | Now it seems that we have found a ethernet chip in this particular | ||
522 | ioaddr. The MB86985 chip has this feature, that when you read a | ||
523 | certain register it will increase it's io base address to next | ||
524 | configurable slot. Now when we have found the chip, first thing is | ||
525 | to make sure that the chip's ioaddr will hold still here. | ||
526 | */ | ||
527 | |||
528 | eth16i_select_regbank(TRANSCEIVER_MODE_RB, ioaddr); | ||
529 | outb(0x00, ioaddr + TRANSCEIVER_MODE_REG); | ||
530 | |||
531 | outb(0x00, ioaddr + RESET); /* Reset some parts of chip */ | ||
532 | BITSET(ioaddr + CONFIG_REG_0, BIT(7)); /* Disable the data link */ | ||
533 | |||
534 | if( (eth16i_debug & version_printed++) == 0) | ||
535 | printk(KERN_INFO "%s", version); | ||
536 | |||
537 | dev->base_addr = ioaddr; | ||
538 | dev->irq = eth16i_get_irq(ioaddr); | ||
539 | |||
540 | /* Try to obtain interrupt vector */ | ||
541 | |||
542 | if ((retval = request_irq(dev->irq, (void *)ð16i_interrupt, 0, cardname, dev))) { | ||
543 | printk(KERN_WARNING "%s at %#3x, but is unusable due to conflicting IRQ %d.\n", | ||
544 | cardname, ioaddr, dev->irq); | ||
545 | goto out; | ||
546 | } | ||
547 | |||
548 | printk(KERN_INFO "%s: %s at %#3x, IRQ %d, ", | ||
549 | dev->name, cardname, ioaddr, dev->irq); | ||
550 | |||
551 | |||
552 | /* Now we will have to lock the chip's io address */ | ||
553 | eth16i_select_regbank(TRANSCEIVER_MODE_RB, ioaddr); | ||
554 | outb(0x38, ioaddr + TRANSCEIVER_MODE_REG); | ||
555 | |||
556 | eth16i_initialize(dev, 1); /* Initialize rest of the chip's registers */ | ||
557 | |||
558 | /* Now let's same some energy by shutting down the chip ;) */ | ||
559 | BITCLR(ioaddr + CONFIG_REG_1, POWERUP); | ||
560 | |||
561 | /* Initialize the device structure */ | ||
562 | dev->netdev_ops = ð16i_netdev_ops; | ||
563 | dev->watchdog_timeo = TX_TIMEOUT; | ||
564 | spin_lock_init(&lp->lock); | ||
565 | |||
566 | retval = register_netdev(dev); | ||
567 | if (retval) | ||
568 | goto out1; | ||
569 | return 0; | ||
570 | out1: | ||
571 | free_irq(dev->irq, dev); | ||
572 | out: | ||
573 | release_region(ioaddr, ETH16I_IO_EXTENT); | ||
574 | return retval; | ||
575 | } | ||
576 | |||
577 | |||
578 | static void eth16i_initialize(struct net_device *dev, int boot) | ||
579 | { | ||
580 | int ioaddr = dev->base_addr; | ||
581 | int i, node_w = 0; | ||
582 | unsigned char node_byte = 0; | ||
583 | |||
584 | /* Setup station address */ | ||
585 | eth16i_select_regbank(NODE_ID_RB, ioaddr); | ||
586 | for(i = 0 ; i < 3 ; i++) { | ||
587 | unsigned short node_val = eth16i_read_eeprom(ioaddr, E_NODEID_0 + i); | ||
588 | ((unsigned short *)dev->dev_addr)[i] = ntohs(node_val); | ||
589 | } | ||
590 | |||
591 | for(i = 0; i < 6; i++) { | ||
592 | outb( ((unsigned char *)dev->dev_addr)[i], ioaddr + NODE_ID_0 + i); | ||
593 | if(boot) { | ||
594 | printk("%02x", inb(ioaddr + NODE_ID_0 + i)); | ||
595 | if(i != 5) | ||
596 | printk(":"); | ||
597 | } | ||
598 | } | ||
599 | |||
600 | /* Now we will set multicast addresses to accept none */ | ||
601 | eth16i_select_regbank(HASH_TABLE_RB, ioaddr); | ||
602 | for(i = 0; i < 8; i++) | ||
603 | outb(0x00, ioaddr + HASH_TABLE_0 + i); | ||
604 | |||
605 | /* | ||
606 | Now let's disable the transmitter and receiver, set the buffer ram | ||
607 | cycle time, bus width and buffer data path width. Also we shall | ||
608 | set transmit buffer size and total buffer size. | ||
609 | */ | ||
610 | |||
611 | eth16i_select_regbank(2, ioaddr); | ||
612 | |||
613 | node_byte = 0; | ||
614 | node_w = eth16i_read_eeprom(ioaddr, E_PRODUCT_CFG); | ||
615 | |||
616 | if( (node_w & 0xFF00) == 0x0800) | ||
617 | node_byte |= BUFFER_WIDTH_8; | ||
618 | |||
619 | node_byte |= SRAM_BS1; | ||
620 | |||
621 | if( (node_w & 0x00FF) == 64) | ||
622 | node_byte |= SRAM_BS0; | ||
623 | |||
624 | node_byte |= DLC_EN | SRAM_CYCLE_TIME_100NS | (ETH16I_TX_BUF_SIZE << 2); | ||
625 | |||
626 | outb(node_byte, ioaddr + CONFIG_REG_0); | ||
627 | |||
628 | /* We shall halt the transmitting, if 16 collisions are detected */ | ||
629 | outb(HALT_ON_16, ioaddr + COL_16_REG); | ||
630 | |||
631 | #ifdef MODULE | ||
632 | /* if_port already set by init_module() */ | ||
633 | #else | ||
634 | dev->if_port = (dev->mem_start < E_PORT_FROM_EPROM) ? | ||
635 | dev->mem_start : E_PORT_FROM_EPROM; | ||
636 | #endif | ||
637 | |||
638 | /* Set interface port type */ | ||
639 | if(boot) { | ||
640 | static const char * const porttype[] = { | ||
641 | "BNC", "DIX", "TP", "AUTO", "FROM_EPROM" | ||
642 | }; | ||
643 | |||
644 | switch(dev->if_port) | ||
645 | { | ||
646 | |||
647 | case E_PORT_FROM_EPROM: | ||
648 | dev->if_port = eth16i_read_eeprom(ioaddr, E_PORT_SELECT); | ||
649 | break; | ||
650 | |||
651 | case E_PORT_AUTO: | ||
652 | dev->if_port = eth16i_probe_port(ioaddr); | ||
653 | break; | ||
654 | |||
655 | case E_PORT_BNC: | ||
656 | case E_PORT_TP: | ||
657 | case E_PORT_DIX: | ||
658 | break; | ||
659 | } | ||
660 | |||
661 | printk(" %s interface.\n", porttype[dev->if_port]); | ||
662 | |||
663 | eth16i_set_port(ioaddr, dev->if_port); | ||
664 | } | ||
665 | |||
666 | /* Set Receive Mode to normal operation */ | ||
667 | outb(MODE_2, ioaddr + RECEIVE_MODE_REG); | ||
668 | } | ||
669 | |||
670 | static int eth16i_probe_port(int ioaddr) | ||
671 | { | ||
672 | int i; | ||
673 | int retcode; | ||
674 | unsigned char dummy_packet[64]; | ||
675 | |||
676 | /* Powerup the chip */ | ||
677 | outb(0xc0 | POWERUP, ioaddr + CONFIG_REG_1); | ||
678 | |||
679 | BITSET(ioaddr + CONFIG_REG_0, DLC_EN); | ||
680 | |||
681 | eth16i_select_regbank(NODE_ID_RB, ioaddr); | ||
682 | |||
683 | for(i = 0; i < 6; i++) { | ||
684 | dummy_packet[i] = inb(ioaddr + NODE_ID_0 + i); | ||
685 | dummy_packet[i+6] = inb(ioaddr + NODE_ID_0 + i); | ||
686 | } | ||
687 | |||
688 | dummy_packet[12] = 0x00; | ||
689 | dummy_packet[13] = 0x04; | ||
690 | memset(dummy_packet + 14, 0, sizeof(dummy_packet) - 14); | ||
691 | |||
692 | eth16i_select_regbank(2, ioaddr); | ||
693 | |||
694 | for(i = 0; i < 3; i++) { | ||
695 | BITSET(ioaddr + CONFIG_REG_0, DLC_EN); | ||
696 | BITCLR(ioaddr + CONFIG_REG_0, DLC_EN); | ||
697 | eth16i_set_port(ioaddr, i); | ||
698 | |||
699 | if(eth16i_debug > 1) | ||
700 | printk(KERN_DEBUG "Set port number %d\n", i); | ||
701 | |||
702 | retcode = eth16i_send_probe_packet(ioaddr, dummy_packet, 64); | ||
703 | if(retcode == 0) { | ||
704 | retcode = eth16i_receive_probe_packet(ioaddr); | ||
705 | if(retcode != -1) { | ||
706 | if(eth16i_debug > 1) | ||
707 | printk(KERN_DEBUG "Eth16i interface port found at %d\n", i); | ||
708 | return i; | ||
709 | } | ||
710 | } | ||
711 | else { | ||
712 | if(eth16i_debug > 1) | ||
713 | printk(KERN_DEBUG "TRANSMIT_DONE timeout when probing interface port\n"); | ||
714 | } | ||
715 | } | ||
716 | |||
717 | if( eth16i_debug > 1) | ||
718 | printk(KERN_DEBUG "Using default port\n"); | ||
719 | |||
720 | return E_PORT_BNC; | ||
721 | } | ||
722 | |||
723 | static void eth16i_set_port(int ioaddr, int porttype) | ||
724 | { | ||
725 | unsigned short temp = 0; | ||
726 | |||
727 | eth16i_select_regbank(TRANSCEIVER_MODE_RB, ioaddr); | ||
728 | outb(LOOPBACK_CONTROL, ioaddr + TRANSMIT_MODE_REG); | ||
729 | |||
730 | temp |= DIS_AUTO_PORT_SEL; | ||
731 | |||
732 | switch(porttype) { | ||
733 | |||
734 | case E_PORT_BNC : | ||
735 | temp |= AUI_SELECT; | ||
736 | break; | ||
737 | |||
738 | case E_PORT_TP : | ||
739 | break; | ||
740 | |||
741 | case E_PORT_DIX : | ||
742 | temp |= AUI_SELECT; | ||
743 | BITSET(ioaddr + TRANSMIT_MODE_REG, CONTROL_OUTPUT); | ||
744 | break; | ||
745 | } | ||
746 | |||
747 | outb(temp, ioaddr + TRANSCEIVER_MODE_REG); | ||
748 | |||
749 | if(eth16i_debug > 1) { | ||
750 | printk(KERN_DEBUG "TRANSMIT_MODE_REG = %x\n", inb(ioaddr + TRANSMIT_MODE_REG)); | ||
751 | printk(KERN_DEBUG "TRANSCEIVER_MODE_REG = %x\n", | ||
752 | inb(ioaddr+TRANSCEIVER_MODE_REG)); | ||
753 | } | ||
754 | } | ||
755 | |||
756 | static int eth16i_send_probe_packet(int ioaddr, unsigned char *b, int l) | ||
757 | { | ||
758 | unsigned long starttime; | ||
759 | |||
760 | outb(0xff, ioaddr + TX_STATUS_REG); | ||
761 | |||
762 | outw(l, ioaddr + DATAPORT); | ||
763 | outsw(ioaddr + DATAPORT, (unsigned short *)b, (l + 1) >> 1); | ||
764 | |||
765 | starttime = jiffies; | ||
766 | outb(TX_START | 1, ioaddr + TRANSMIT_START_REG); | ||
767 | |||
768 | while( (inb(ioaddr + TX_STATUS_REG) & 0x80) == 0) { | ||
769 | if( time_after(jiffies, starttime + TX_TIMEOUT)) { | ||
770 | return -1; | ||
771 | } | ||
772 | } | ||
773 | |||
774 | return 0; | ||
775 | } | ||
776 | |||
777 | static int eth16i_receive_probe_packet(int ioaddr) | ||
778 | { | ||
779 | unsigned long starttime; | ||
780 | |||
781 | starttime = jiffies; | ||
782 | |||
783 | while((inb(ioaddr + TX_STATUS_REG) & 0x20) == 0) { | ||
784 | if( time_after(jiffies, starttime + TX_TIMEOUT)) { | ||
785 | |||
786 | if(eth16i_debug > 1) | ||
787 | printk(KERN_DEBUG "Timeout occurred waiting transmit packet received\n"); | ||
788 | starttime = jiffies; | ||
789 | while((inb(ioaddr + RX_STATUS_REG) & 0x80) == 0) { | ||
790 | if( time_after(jiffies, starttime + TX_TIMEOUT)) { | ||
791 | if(eth16i_debug > 1) | ||
792 | printk(KERN_DEBUG "Timeout occurred waiting receive packet\n"); | ||
793 | return -1; | ||
794 | } | ||
795 | } | ||
796 | |||
797 | if(eth16i_debug > 1) | ||
798 | printk(KERN_DEBUG "RECEIVE_PACKET\n"); | ||
799 | return 0; /* Found receive packet */ | ||
800 | } | ||
801 | } | ||
802 | |||
803 | if(eth16i_debug > 1) { | ||
804 | printk(KERN_DEBUG "TRANSMIT_PACKET_RECEIVED %x\n", inb(ioaddr + TX_STATUS_REG)); | ||
805 | printk(KERN_DEBUG "RX_STATUS_REG = %x\n", inb(ioaddr + RX_STATUS_REG)); | ||
806 | } | ||
807 | |||
808 | return 0; /* Return success */ | ||
809 | } | ||
810 | |||
811 | #if 0 | ||
812 | static int eth16i_set_irq(struct net_device* dev) | ||
813 | { | ||
814 | const int ioaddr = dev->base_addr; | ||
815 | const int irq = dev->irq; | ||
816 | int i = 0; | ||
817 | |||
818 | if(ioaddr < 0x1000) { | ||
819 | while(eth16i_irqmap[i] && eth16i_irqmap[i] != irq) | ||
820 | i++; | ||
821 | |||
822 | if(i < NUM_OF_ISA_IRQS) { | ||
823 | u8 cbyte = inb(ioaddr + JUMPERLESS_CONFIG); | ||
824 | cbyte = (cbyte & 0x3F) | (i << 6); | ||
825 | outb(cbyte, ioaddr + JUMPERLESS_CONFIG); | ||
826 | return 0; | ||
827 | } | ||
828 | } | ||
829 | else { | ||
830 | printk(KERN_NOTICE "%s: EISA Interrupt cannot be set. Use EISA Configuration utility.\n", dev->name); | ||
831 | } | ||
832 | |||
833 | return -1; | ||
834 | |||
835 | } | ||
836 | #endif | ||
837 | |||
838 | static int __init eth16i_get_irq(int ioaddr) | ||
839 | { | ||
840 | unsigned char cbyte; | ||
841 | |||
842 | if( ioaddr < 0x1000) { | ||
843 | cbyte = inb(ioaddr + JUMPERLESS_CONFIG); | ||
844 | return eth16i_irqmap[((cbyte & 0xC0) >> 6)]; | ||
845 | } else { /* Oh..the card is EISA so method getting IRQ different */ | ||
846 | unsigned short index = 0; | ||
847 | cbyte = inb(ioaddr + EISA_IRQ_REG); | ||
848 | while( (cbyte & 0x01) == 0) { | ||
849 | cbyte = cbyte >> 1; | ||
850 | index++; | ||
851 | } | ||
852 | return eth32i_irqmap[index]; | ||
853 | } | ||
854 | } | ||
855 | |||
856 | static int __init eth16i_check_signature(int ioaddr) | ||
857 | { | ||
858 | int i; | ||
859 | unsigned char creg[4] = { 0 }; | ||
860 | |||
861 | for(i = 0; i < 4 ; i++) { | ||
862 | |||
863 | creg[i] = inb(ioaddr + TRANSMIT_MODE_REG + i); | ||
864 | |||
865 | if(eth16i_debug > 1) | ||
866 | printk("eth16i: read signature byte %x at %x\n", | ||
867 | creg[i], | ||
868 | ioaddr + TRANSMIT_MODE_REG + i); | ||
869 | } | ||
870 | |||
871 | creg[0] &= 0x0F; /* Mask collision cnr */ | ||
872 | creg[2] &= 0x7F; /* Mask DCLEN bit */ | ||
873 | |||
874 | #if 0 | ||
875 | /* | ||
876 | This was removed because the card was sometimes left to state | ||
877 | from which it couldn't be find anymore. If there is need | ||
878 | to more strict check still this have to be fixed. | ||
879 | */ | ||
880 | if( ! ((creg[0] == 0x06) && (creg[1] == 0x41)) ) { | ||
881 | if(creg[1] != 0x42) | ||
882 | return -1; | ||
883 | } | ||
884 | #endif | ||
885 | |||
886 | if( !((creg[2] == 0x36) && (creg[3] == 0xE0)) ) { | ||
887 | creg[2] &= 0x40; | ||
888 | creg[3] &= 0x03; | ||
889 | |||
890 | if( !((creg[2] == 0x40) && (creg[3] == 0x00)) ) | ||
891 | return -1; | ||
892 | } | ||
893 | |||
894 | if(eth16i_read_eeprom(ioaddr, E_NODEID_0) != 0) | ||
895 | return -1; | ||
896 | |||
897 | if((eth16i_read_eeprom(ioaddr, E_NODEID_1) & 0xFF00) != 0x4B00) | ||
898 | return -1; | ||
899 | |||
900 | return 0; | ||
901 | } | ||
902 | |||
903 | static int eth16i_read_eeprom(int ioaddr, int offset) | ||
904 | { | ||
905 | int data = 0; | ||
906 | |||
907 | eth16i_eeprom_cmd(ioaddr, EEPROM_READ | offset); | ||
908 | outb(CS_1, ioaddr + EEPROM_CTRL_REG); | ||
909 | data = eth16i_read_eeprom_word(ioaddr); | ||
910 | outb(CS_0 | SK_0, ioaddr + EEPROM_CTRL_REG); | ||
911 | |||
912 | return data; | ||
913 | } | ||
914 | |||
915 | static int eth16i_read_eeprom_word(int ioaddr) | ||
916 | { | ||
917 | int i; | ||
918 | int data = 0; | ||
919 | |||
920 | for(i = 16; i > 0; i--) { | ||
921 | outb(CS_1 | SK_0, ioaddr + EEPROM_CTRL_REG); | ||
922 | eeprom_slow_io(); | ||
923 | outb(CS_1 | SK_1, ioaddr + EEPROM_CTRL_REG); | ||
924 | eeprom_slow_io(); | ||
925 | data = (data << 1) | | ||
926 | ((inb(ioaddr + EEPROM_DATA_REG) & DI_1) ? 1 : 0); | ||
927 | |||
928 | eeprom_slow_io(); | ||
929 | } | ||
930 | |||
931 | return data; | ||
932 | } | ||
933 | |||
934 | static void eth16i_eeprom_cmd(int ioaddr, unsigned char command) | ||
935 | { | ||
936 | int i; | ||
937 | |||
938 | outb(CS_0 | SK_0, ioaddr + EEPROM_CTRL_REG); | ||
939 | outb(DI_0, ioaddr + EEPROM_DATA_REG); | ||
940 | outb(CS_1 | SK_0, ioaddr + EEPROM_CTRL_REG); | ||
941 | outb(DI_1, ioaddr + EEPROM_DATA_REG); | ||
942 | outb(CS_1 | SK_1, ioaddr + EEPROM_CTRL_REG); | ||
943 | |||
944 | for(i = 7; i >= 0; i--) { | ||
945 | short cmd = ( (command & (1 << i)) ? DI_1 : DI_0 ); | ||
946 | outb(cmd, ioaddr + EEPROM_DATA_REG); | ||
947 | outb(CS_1 | SK_0, ioaddr + EEPROM_CTRL_REG); | ||
948 | eeprom_slow_io(); | ||
949 | outb(CS_1 | SK_1, ioaddr + EEPROM_CTRL_REG); | ||
950 | eeprom_slow_io(); | ||
951 | } | ||
952 | } | ||
953 | |||
954 | static int eth16i_open(struct net_device *dev) | ||
955 | { | ||
956 | struct eth16i_local *lp = netdev_priv(dev); | ||
957 | int ioaddr = dev->base_addr; | ||
958 | |||
959 | /* Powerup the chip */ | ||
960 | outb(0xc0 | POWERUP, ioaddr + CONFIG_REG_1); | ||
961 | |||
962 | /* Initialize the chip */ | ||
963 | eth16i_initialize(dev, 0); | ||
964 | |||
965 | /* Set the transmit buffer size */ | ||
966 | lp->tx_buf_size = eth16i_tx_buf_map[ETH16I_TX_BUF_SIZE & 0x03]; | ||
967 | |||
968 | if(eth16i_debug > 0) | ||
969 | printk(KERN_DEBUG "%s: transmit buffer size %d\n", | ||
970 | dev->name, lp->tx_buf_size); | ||
971 | |||
972 | /* Now enable Transmitter and Receiver sections */ | ||
973 | BITCLR(ioaddr + CONFIG_REG_0, DLC_EN); | ||
974 | |||
975 | /* Now switch to register bank 2, for run time operation */ | ||
976 | eth16i_select_regbank(2, ioaddr); | ||
977 | |||
978 | lp->open_time = jiffies; | ||
979 | lp->tx_started = 0; | ||
980 | lp->tx_queue = 0; | ||
981 | lp->tx_queue_len = 0; | ||
982 | |||
983 | /* Turn on interrupts*/ | ||
984 | outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG); | ||
985 | |||
986 | netif_start_queue(dev); | ||
987 | return 0; | ||
988 | } | ||
989 | |||
990 | static int eth16i_close(struct net_device *dev) | ||
991 | { | ||
992 | struct eth16i_local *lp = netdev_priv(dev); | ||
993 | int ioaddr = dev->base_addr; | ||
994 | |||
995 | eth16i_reset(dev); | ||
996 | |||
997 | /* Turn off interrupts*/ | ||
998 | outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG); | ||
999 | |||
1000 | netif_stop_queue(dev); | ||
1001 | |||
1002 | lp->open_time = 0; | ||
1003 | |||
1004 | /* Disable transmit and receive */ | ||
1005 | BITSET(ioaddr + CONFIG_REG_0, DLC_EN); | ||
1006 | |||
1007 | /* Reset the chip */ | ||
1008 | /* outb(0xff, ioaddr + RESET); */ | ||
1009 | /* outw(0xffff, ioaddr + TX_STATUS_REG); */ | ||
1010 | |||
1011 | outb(0x00, ioaddr + CONFIG_REG_1); | ||
1012 | |||
1013 | return 0; | ||
1014 | } | ||
1015 | |||
1016 | static void eth16i_timeout(struct net_device *dev) | ||
1017 | { | ||
1018 | struct eth16i_local *lp = netdev_priv(dev); | ||
1019 | int ioaddr = dev->base_addr; | ||
1020 | /* | ||
1021 | If we get here, some higher level has decided that | ||
1022 | we are broken. There should really be a "kick me" | ||
1023 | function call instead. | ||
1024 | */ | ||
1025 | |||
1026 | outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG); | ||
1027 | printk(KERN_WARNING "%s: transmit timed out with status %04x, %s ?\n", | ||
1028 | dev->name, | ||
1029 | inw(ioaddr + TX_STATUS_REG), (inb(ioaddr + TX_STATUS_REG) & TX_DONE) ? | ||
1030 | "IRQ conflict" : "network cable problem"); | ||
1031 | |||
1032 | dev->trans_start = jiffies; /* prevent tx timeout */ | ||
1033 | |||
1034 | /* Let's dump all registers */ | ||
1035 | if(eth16i_debug > 0) { | ||
1036 | printk(KERN_DEBUG "%s: timeout: %02x %02x %02x %02x %02x %02x %02x %02x.\n", | ||
1037 | dev->name, inb(ioaddr + 0), | ||
1038 | inb(ioaddr + 1), inb(ioaddr + 2), | ||
1039 | inb(ioaddr + 3), inb(ioaddr + 4), | ||
1040 | inb(ioaddr + 5), | ||
1041 | inb(ioaddr + 6), inb(ioaddr + 7)); | ||
1042 | |||
1043 | printk(KERN_DEBUG "%s: transmit start reg: %02x. collision reg %02x\n", | ||
1044 | dev->name, inb(ioaddr + TRANSMIT_START_REG), | ||
1045 | inb(ioaddr + COL_16_REG)); | ||
1046 | printk(KERN_DEBUG "lp->tx_queue = %d\n", lp->tx_queue); | ||
1047 | printk(KERN_DEBUG "lp->tx_queue_len = %d\n", lp->tx_queue_len); | ||
1048 | printk(KERN_DEBUG "lp->tx_started = %d\n", lp->tx_started); | ||
1049 | } | ||
1050 | dev->stats.tx_errors++; | ||
1051 | eth16i_reset(dev); | ||
1052 | dev->trans_start = jiffies; /* prevent tx timeout */ | ||
1053 | outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG); | ||
1054 | netif_wake_queue(dev); | ||
1055 | } | ||
1056 | |||
1057 | static netdev_tx_t eth16i_tx(struct sk_buff *skb, struct net_device *dev) | ||
1058 | { | ||
1059 | struct eth16i_local *lp = netdev_priv(dev); | ||
1060 | int ioaddr = dev->base_addr; | ||
1061 | int status = 0; | ||
1062 | ushort length = skb->len; | ||
1063 | unsigned char *buf; | ||
1064 | unsigned long flags; | ||
1065 | |||
1066 | if (length < ETH_ZLEN) { | ||
1067 | if (skb_padto(skb, ETH_ZLEN)) | ||
1068 | return NETDEV_TX_OK; | ||
1069 | length = ETH_ZLEN; | ||
1070 | } | ||
1071 | buf = skb->data; | ||
1072 | |||
1073 | netif_stop_queue(dev); | ||
1074 | |||
1075 | /* Turn off TX interrupts */ | ||
1076 | outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG); | ||
1077 | |||
1078 | /* We would be better doing the disable_irq tricks the 3c509 does, | ||
1079 | that would make this suck a lot less */ | ||
1080 | |||
1081 | spin_lock_irqsave(&lp->lock, flags); | ||
1082 | |||
1083 | if( (length + 2) > (lp->tx_buf_size - lp->tx_queue_len)) { | ||
1084 | if(eth16i_debug > 0) | ||
1085 | printk(KERN_WARNING "%s: Transmit buffer full.\n", dev->name); | ||
1086 | } | ||
1087 | else { | ||
1088 | outw(length, ioaddr + DATAPORT); | ||
1089 | |||
1090 | if( ioaddr < 0x1000 ) | ||
1091 | outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1); | ||
1092 | else { | ||
1093 | unsigned char frag = length % 4; | ||
1094 | outsl(ioaddr + DATAPORT, buf, length >> 2); | ||
1095 | if( frag != 0 ) { | ||
1096 | outsw(ioaddr + DATAPORT, (buf + (length & 0xFFFC)), 1); | ||
1097 | if( frag == 3 ) | ||
1098 | outsw(ioaddr + DATAPORT, | ||
1099 | (buf + (length & 0xFFFC) + 2), 1); | ||
1100 | } | ||
1101 | } | ||
1102 | lp->tx_buffered_packets++; | ||
1103 | lp->tx_buffered_bytes = length; | ||
1104 | lp->tx_queue++; | ||
1105 | lp->tx_queue_len += length + 2; | ||
1106 | } | ||
1107 | lp->tx_buf_busy = 0; | ||
1108 | |||
1109 | if(lp->tx_started == 0) { | ||
1110 | /* If the transmitter is idle..always trigger a transmit */ | ||
1111 | outb(TX_START | lp->tx_queue, ioaddr + TRANSMIT_START_REG); | ||
1112 | lp->tx_queue = 0; | ||
1113 | lp->tx_queue_len = 0; | ||
1114 | lp->tx_started = 1; | ||
1115 | netif_wake_queue(dev); | ||
1116 | } | ||
1117 | else if(lp->tx_queue_len < lp->tx_buf_size - (ETH_FRAME_LEN + 2)) { | ||
1118 | /* There is still more room for one more packet in tx buffer */ | ||
1119 | netif_wake_queue(dev); | ||
1120 | } | ||
1121 | |||
1122 | spin_unlock_irqrestore(&lp->lock, flags); | ||
1123 | |||
1124 | outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG); | ||
1125 | /* Turn TX interrupts back on */ | ||
1126 | /* outb(TX_INTR_DONE | TX_INTR_16_COL, ioaddr + TX_INTR_REG); */ | ||
1127 | status = 0; | ||
1128 | dev_kfree_skb(skb); | ||
1129 | return NETDEV_TX_OK; | ||
1130 | } | ||
1131 | |||
1132 | static void eth16i_rx(struct net_device *dev) | ||
1133 | { | ||
1134 | int ioaddr = dev->base_addr; | ||
1135 | int boguscount = MAX_RX_LOOP; | ||
1136 | |||
1137 | /* Loop until all packets have been read */ | ||
1138 | while( (inb(ioaddr + RECEIVE_MODE_REG) & RX_BUFFER_EMPTY) == 0) { | ||
1139 | |||
1140 | /* Read status byte from receive buffer */ | ||
1141 | ushort status = inw(ioaddr + DATAPORT); | ||
1142 | |||
1143 | /* Get the size of the packet from receive buffer */ | ||
1144 | ushort pkt_len = inw(ioaddr + DATAPORT); | ||
1145 | |||
1146 | if(eth16i_debug > 4) | ||
1147 | printk(KERN_DEBUG "%s: Receiving packet mode %02x status %04x.\n", | ||
1148 | dev->name, | ||
1149 | inb(ioaddr + RECEIVE_MODE_REG), status); | ||
1150 | |||
1151 | if( !(status & PKT_GOOD) ) { | ||
1152 | dev->stats.rx_errors++; | ||
1153 | |||
1154 | if( (pkt_len < ETH_ZLEN) || (pkt_len > ETH_FRAME_LEN) ) { | ||
1155 | dev->stats.rx_length_errors++; | ||
1156 | eth16i_reset(dev); | ||
1157 | return; | ||
1158 | } | ||
1159 | else { | ||
1160 | eth16i_skip_packet(dev); | ||
1161 | dev->stats.rx_dropped++; | ||
1162 | } | ||
1163 | } | ||
1164 | else { /* Ok so now we should have a good packet */ | ||
1165 | struct sk_buff *skb; | ||
1166 | |||
1167 | skb = dev_alloc_skb(pkt_len + 3); | ||
1168 | if( skb == NULL ) { | ||
1169 | printk(KERN_WARNING "%s: Could'n allocate memory for packet (len %d)\n", | ||
1170 | dev->name, pkt_len); | ||
1171 | eth16i_skip_packet(dev); | ||
1172 | dev->stats.rx_dropped++; | ||
1173 | break; | ||
1174 | } | ||
1175 | |||
1176 | skb_reserve(skb,2); | ||
1177 | |||
1178 | /* | ||
1179 | Now let's get the packet out of buffer. | ||
1180 | size is (pkt_len + 1) >> 1, cause we are now reading words | ||
1181 | and it have to be even aligned. | ||
1182 | */ | ||
1183 | |||
1184 | if(ioaddr < 0x1000) | ||
1185 | insw(ioaddr + DATAPORT, skb_put(skb, pkt_len), | ||
1186 | (pkt_len + 1) >> 1); | ||
1187 | else { | ||
1188 | unsigned char *buf = skb_put(skb, pkt_len); | ||
1189 | unsigned char frag = pkt_len % 4; | ||
1190 | |||
1191 | insl(ioaddr + DATAPORT, buf, pkt_len >> 2); | ||
1192 | |||
1193 | if(frag != 0) { | ||
1194 | unsigned short rest[2]; | ||
1195 | rest[0] = inw( ioaddr + DATAPORT ); | ||
1196 | if(frag == 3) | ||
1197 | rest[1] = inw( ioaddr + DATAPORT ); | ||
1198 | |||
1199 | memcpy(buf + (pkt_len & 0xfffc), (char *)rest, frag); | ||
1200 | } | ||
1201 | } | ||
1202 | |||
1203 | skb->protocol=eth_type_trans(skb, dev); | ||
1204 | |||
1205 | if( eth16i_debug > 5 ) { | ||
1206 | int i; | ||
1207 | printk(KERN_DEBUG "%s: Received packet of length %d.\n", | ||
1208 | dev->name, pkt_len); | ||
1209 | for(i = 0; i < 14; i++) | ||
1210 | printk(KERN_DEBUG " %02x", skb->data[i]); | ||
1211 | printk(KERN_DEBUG ".\n"); | ||
1212 | } | ||
1213 | netif_rx(skb); | ||
1214 | dev->stats.rx_packets++; | ||
1215 | dev->stats.rx_bytes += pkt_len; | ||
1216 | |||
1217 | } /* else */ | ||
1218 | |||
1219 | if(--boguscount <= 0) | ||
1220 | break; | ||
1221 | |||
1222 | } /* while */ | ||
1223 | } | ||
1224 | |||
1225 | static irqreturn_t eth16i_interrupt(int irq, void *dev_id) | ||
1226 | { | ||
1227 | struct net_device *dev = dev_id; | ||
1228 | struct eth16i_local *lp; | ||
1229 | int ioaddr = 0, status; | ||
1230 | int handled = 0; | ||
1231 | |||
1232 | ioaddr = dev->base_addr; | ||
1233 | lp = netdev_priv(dev); | ||
1234 | |||
1235 | /* Turn off all interrupts from adapter */ | ||
1236 | outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG); | ||
1237 | |||
1238 | /* eth16i_tx won't be called */ | ||
1239 | spin_lock(&lp->lock); | ||
1240 | |||
1241 | status = inw(ioaddr + TX_STATUS_REG); /* Get the status */ | ||
1242 | outw(status, ioaddr + TX_STATUS_REG); /* Clear status bits */ | ||
1243 | |||
1244 | if (status) | ||
1245 | handled = 1; | ||
1246 | |||
1247 | if(eth16i_debug > 3) | ||
1248 | printk(KERN_DEBUG "%s: Interrupt with status %04x.\n", dev->name, status); | ||
1249 | |||
1250 | if( status & 0x7f00 ) { | ||
1251 | |||
1252 | dev->stats.rx_errors++; | ||
1253 | |||
1254 | if(status & (BUS_RD_ERR << 8) ) | ||
1255 | printk(KERN_WARNING "%s: Bus read error.\n",dev->name); | ||
1256 | if(status & (SHORT_PKT_ERR << 8) ) dev->stats.rx_length_errors++; | ||
1257 | if(status & (ALIGN_ERR << 8) ) dev->stats.rx_frame_errors++; | ||
1258 | if(status & (CRC_ERR << 8) ) dev->stats.rx_crc_errors++; | ||
1259 | if(status & (RX_BUF_OVERFLOW << 8) ) dev->stats.rx_over_errors++; | ||
1260 | } | ||
1261 | if( status & 0x001a) { | ||
1262 | |||
1263 | dev->stats.tx_errors++; | ||
1264 | |||
1265 | if(status & CR_LOST) dev->stats.tx_carrier_errors++; | ||
1266 | if(status & TX_JABBER_ERR) dev->stats.tx_window_errors++; | ||
1267 | |||
1268 | #if 0 | ||
1269 | if(status & COLLISION) { | ||
1270 | dev->stats.collisions += | ||
1271 | ((inb(ioaddr+TRANSMIT_MODE_REG) & 0xF0) >> 4); | ||
1272 | } | ||
1273 | #endif | ||
1274 | if(status & COLLISIONS_16) { | ||
1275 | if(lp->col_16 < MAX_COL_16) { | ||
1276 | lp->col_16++; | ||
1277 | dev->stats.collisions++; | ||
1278 | /* Resume transmitting, skip failed packet */ | ||
1279 | outb(0x02, ioaddr + COL_16_REG); | ||
1280 | } | ||
1281 | else { | ||
1282 | printk(KERN_WARNING "%s: bailing out due to many consecutive 16-in-a-row collisions. Network cable problem?\n", dev->name); | ||
1283 | } | ||
1284 | } | ||
1285 | } | ||
1286 | |||
1287 | if( status & 0x00ff ) { /* Let's check the transmit status reg */ | ||
1288 | |||
1289 | if(status & TX_DONE) { /* The transmit has been done */ | ||
1290 | dev->stats.tx_packets = lp->tx_buffered_packets; | ||
1291 | dev->stats.tx_bytes += lp->tx_buffered_bytes; | ||
1292 | lp->col_16 = 0; | ||
1293 | |||
1294 | if(lp->tx_queue) { /* Is there still packets ? */ | ||
1295 | /* There was packet(s) so start transmitting and write also | ||
1296 | how many packets there is to be sended */ | ||
1297 | outb(TX_START | lp->tx_queue, ioaddr + TRANSMIT_START_REG); | ||
1298 | lp->tx_queue = 0; | ||
1299 | lp->tx_queue_len = 0; | ||
1300 | lp->tx_started = 1; | ||
1301 | } | ||
1302 | else { | ||
1303 | lp->tx_started = 0; | ||
1304 | } | ||
1305 | netif_wake_queue(dev); | ||
1306 | } | ||
1307 | } | ||
1308 | |||
1309 | if( ( status & 0x8000 ) || | ||
1310 | ( (inb(ioaddr + RECEIVE_MODE_REG) & RX_BUFFER_EMPTY) == 0) ) { | ||
1311 | eth16i_rx(dev); /* We have packet in receive buffer */ | ||
1312 | } | ||
1313 | |||
1314 | /* Turn interrupts back on */ | ||
1315 | outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG); | ||
1316 | |||
1317 | if(lp->tx_queue_len < lp->tx_buf_size - (ETH_FRAME_LEN + 2)) { | ||
1318 | /* There is still more room for one more packet in tx buffer */ | ||
1319 | netif_wake_queue(dev); | ||
1320 | } | ||
1321 | |||
1322 | spin_unlock(&lp->lock); | ||
1323 | |||
1324 | return IRQ_RETVAL(handled); | ||
1325 | } | ||
1326 | |||
1327 | static void eth16i_skip_packet(struct net_device *dev) | ||
1328 | { | ||
1329 | int ioaddr = dev->base_addr; | ||
1330 | |||
1331 | inw(ioaddr + DATAPORT); | ||
1332 | inw(ioaddr + DATAPORT); | ||
1333 | inw(ioaddr + DATAPORT); | ||
1334 | |||
1335 | outb(SKIP_RX_PACKET, ioaddr + FILTER_SELF_RX_REG); | ||
1336 | while( inb( ioaddr + FILTER_SELF_RX_REG ) != 0); | ||
1337 | } | ||
1338 | |||
1339 | static void eth16i_reset(struct net_device *dev) | ||
1340 | { | ||
1341 | struct eth16i_local *lp = netdev_priv(dev); | ||
1342 | int ioaddr = dev->base_addr; | ||
1343 | |||
1344 | if(eth16i_debug > 1) | ||
1345 | printk(KERN_DEBUG "%s: Resetting device.\n", dev->name); | ||
1346 | |||
1347 | BITSET(ioaddr + CONFIG_REG_0, DLC_EN); | ||
1348 | outw(0xffff, ioaddr + TX_STATUS_REG); | ||
1349 | eth16i_select_regbank(2, ioaddr); | ||
1350 | |||
1351 | lp->tx_started = 0; | ||
1352 | lp->tx_buf_busy = 0; | ||
1353 | lp->tx_queue = 0; | ||
1354 | lp->tx_queue_len = 0; | ||
1355 | BITCLR(ioaddr + CONFIG_REG_0, DLC_EN); | ||
1356 | } | ||
1357 | |||
1358 | static void eth16i_multicast(struct net_device *dev) | ||
1359 | { | ||
1360 | int ioaddr = dev->base_addr; | ||
1361 | |||
1362 | if (!netdev_mc_empty(dev) || dev->flags&(IFF_ALLMULTI|IFF_PROMISC)) | ||
1363 | { | ||
1364 | outb(3, ioaddr + RECEIVE_MODE_REG); | ||
1365 | } else { | ||
1366 | outb(2, ioaddr + RECEIVE_MODE_REG); | ||
1367 | } | ||
1368 | } | ||
1369 | |||
1370 | static void eth16i_select_regbank(unsigned char banknbr, int ioaddr) | ||
1371 | { | ||
1372 | unsigned char data; | ||
1373 | |||
1374 | data = inb(ioaddr + CONFIG_REG_1); | ||
1375 | outb( ((data & 0xF3) | ( (banknbr & 0x03) << 2)), ioaddr + CONFIG_REG_1); | ||
1376 | } | ||
1377 | |||
1378 | #ifdef MODULE | ||
1379 | |||
1380 | static ushort eth16i_parse_mediatype(const char* s) | ||
1381 | { | ||
1382 | if(!s) | ||
1383 | return E_PORT_FROM_EPROM; | ||
1384 | |||
1385 | if (!strncmp(s, "bnc", 3)) | ||
1386 | return E_PORT_BNC; | ||
1387 | else if (!strncmp(s, "tp", 2)) | ||
1388 | return E_PORT_TP; | ||
1389 | else if (!strncmp(s, "dix", 3)) | ||
1390 | return E_PORT_DIX; | ||
1391 | else if (!strncmp(s, "auto", 4)) | ||
1392 | return E_PORT_AUTO; | ||
1393 | else | ||
1394 | return E_PORT_FROM_EPROM; | ||
1395 | } | ||
1396 | |||
1397 | #define MAX_ETH16I_CARDS 4 /* Max number of Eth16i cards per module */ | ||
1398 | |||
1399 | static struct net_device *dev_eth16i[MAX_ETH16I_CARDS]; | ||
1400 | static int io[MAX_ETH16I_CARDS]; | ||
1401 | #if 0 | ||
1402 | static int irq[MAX_ETH16I_CARDS]; | ||
1403 | #endif | ||
1404 | static char* mediatype[MAX_ETH16I_CARDS]; | ||
1405 | static int debug = -1; | ||
1406 | |||
1407 | MODULE_AUTHOR("Mika Kuoppala <miku@iki.fi>"); | ||
1408 | MODULE_DESCRIPTION("ICL EtherTeam 16i/32 driver"); | ||
1409 | MODULE_LICENSE("GPL"); | ||
1410 | |||
1411 | |||
1412 | module_param_array(io, int, NULL, 0); | ||
1413 | MODULE_PARM_DESC(io, "eth16i I/O base address(es)"); | ||
1414 | |||
1415 | #if 0 | ||
1416 | module_param_array(irq, int, NULL, 0); | ||
1417 | MODULE_PARM_DESC(irq, "eth16i interrupt request number"); | ||
1418 | #endif | ||
1419 | |||
1420 | module_param_array(mediatype, charp, NULL, 0); | ||
1421 | MODULE_PARM_DESC(mediatype, "eth16i media type of interface(s) (bnc,tp,dix,auto,eprom)"); | ||
1422 | |||
1423 | module_param(debug, int, 0); | ||
1424 | MODULE_PARM_DESC(debug, "eth16i debug level (0-6)"); | ||
1425 | |||
1426 | int __init init_module(void) | ||
1427 | { | ||
1428 | int this_dev, found = 0; | ||
1429 | struct net_device *dev; | ||
1430 | |||
1431 | for (this_dev = 0; this_dev < MAX_ETH16I_CARDS; this_dev++) { | ||
1432 | dev = alloc_etherdev(sizeof(struct eth16i_local)); | ||
1433 | if (!dev) | ||
1434 | break; | ||
1435 | |||
1436 | dev->base_addr = io[this_dev]; | ||
1437 | |||
1438 | if(debug != -1) | ||
1439 | eth16i_debug = debug; | ||
1440 | |||
1441 | if(eth16i_debug > 1) | ||
1442 | printk(KERN_NOTICE "eth16i(%d): interface type %s\n", this_dev, mediatype[this_dev] ? mediatype[this_dev] : "none" ); | ||
1443 | |||
1444 | dev->if_port = eth16i_parse_mediatype(mediatype[this_dev]); | ||
1445 | |||
1446 | if(io[this_dev] == 0) { | ||
1447 | if (this_dev != 0) { /* Only autoprobe 1st one */ | ||
1448 | free_netdev(dev); | ||
1449 | break; | ||
1450 | } | ||
1451 | |||
1452 | printk(KERN_NOTICE "eth16i.c: Presently autoprobing (not recommended) for a single card.\n"); | ||
1453 | } | ||
1454 | |||
1455 | if (do_eth16i_probe(dev) == 0) { | ||
1456 | dev_eth16i[found++] = dev; | ||
1457 | continue; | ||
1458 | } | ||
1459 | printk(KERN_WARNING "eth16i.c No Eth16i card found (i/o = 0x%x).\n", | ||
1460 | io[this_dev]); | ||
1461 | free_netdev(dev); | ||
1462 | break; | ||
1463 | } | ||
1464 | if (found) | ||
1465 | return 0; | ||
1466 | return -ENXIO; | ||
1467 | } | ||
1468 | |||
1469 | void __exit cleanup_module(void) | ||
1470 | { | ||
1471 | int this_dev; | ||
1472 | |||
1473 | for(this_dev = 0; this_dev < MAX_ETH16I_CARDS; this_dev++) { | ||
1474 | struct net_device *dev = dev_eth16i[this_dev]; | ||
1475 | |||
1476 | if (netdev_priv(dev)) { | ||
1477 | unregister_netdev(dev); | ||
1478 | free_irq(dev->irq, dev); | ||
1479 | release_region(dev->base_addr, ETH16I_IO_EXTENT); | ||
1480 | free_netdev(dev); | ||
1481 | } | ||
1482 | } | ||
1483 | } | ||
1484 | #endif /* MODULE */ | ||