diff options
-rw-r--r-- | drivers/net/mac8390.c | 245 |
1 files changed, 175 insertions, 70 deletions
diff --git a/drivers/net/mac8390.c b/drivers/net/mac8390.c index a12bb64e3694..90b0c3ed4bb6 100644 --- a/drivers/net/mac8390.c +++ b/drivers/net/mac8390.c | |||
@@ -14,6 +14,8 @@ | |||
14 | /* 2001-05-15: support for Cabletron ported from old daynaport driver | 14 | /* 2001-05-15: support for Cabletron ported from old daynaport driver |
15 | * and fixed access to Sonic Sys card which masquerades as a Farallon | 15 | * and fixed access to Sonic Sys card which masquerades as a Farallon |
16 | * by rayk@knightsmanor.org */ | 16 | * by rayk@knightsmanor.org */ |
17 | /* 2002-12-30: Try to support more cards, some clues from NetBSD driver */ | ||
18 | /* 2003-12-26: Make sure Asante cards always work. */ | ||
17 | 19 | ||
18 | #include <linux/module.h> | 20 | #include <linux/module.h> |
19 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
@@ -61,25 +63,21 @@ static char version[] = | |||
61 | #define DAYNA_8390_BASE 0x80000 | 63 | #define DAYNA_8390_BASE 0x80000 |
62 | #define DAYNA_8390_MEM 0x00000 | 64 | #define DAYNA_8390_MEM 0x00000 |
63 | 65 | ||
64 | #define KINETICS_8390_BASE 0x80000 | ||
65 | #define KINETICS_8390_MEM 0x00000 | ||
66 | |||
67 | #define CABLETRON_8390_BASE 0x90000 | 66 | #define CABLETRON_8390_BASE 0x90000 |
68 | #define CABLETRON_8390_MEM 0x00000 | 67 | #define CABLETRON_8390_MEM 0x00000 |
69 | 68 | ||
69 | #define INTERLAN_8390_BASE 0xE0000 | ||
70 | #define INTERLAN_8390_MEM 0xD0000 | ||
71 | |||
70 | enum mac8390_type { | 72 | enum mac8390_type { |
71 | MAC8390_NONE = -1, | 73 | MAC8390_NONE = -1, |
72 | MAC8390_APPLE, | 74 | MAC8390_APPLE, |
73 | MAC8390_ASANTE, | 75 | MAC8390_ASANTE, |
74 | MAC8390_FARALLON, /* Apple, Asante, and Farallon are all compatible */ | 76 | MAC8390_FARALLON, |
75 | MAC8390_CABLETRON, | 77 | MAC8390_CABLETRON, |
76 | MAC8390_DAYNA, | 78 | MAC8390_DAYNA, |
77 | MAC8390_INTERLAN, | 79 | MAC8390_INTERLAN, |
78 | MAC8390_KINETICS, | 80 | MAC8390_KINETICS, |
79 | MAC8390_FOCUS, | ||
80 | MAC8390_SONICSYS, | ||
81 | MAC8390_DAYNA2, | ||
82 | MAC8390_DAYNA3, | ||
83 | }; | 81 | }; |
84 | 82 | ||
85 | static const char * cardname[] = { | 83 | static const char * cardname[] = { |
@@ -90,10 +88,6 @@ static const char * cardname[] = { | |||
90 | "dayna", | 88 | "dayna", |
91 | "interlan", | 89 | "interlan", |
92 | "kinetics", | 90 | "kinetics", |
93 | "focus", | ||
94 | "sonic systems", | ||
95 | "dayna2", | ||
96 | "dayna_lc", | ||
97 | }; | 91 | }; |
98 | 92 | ||
99 | static int word16[] = { | 93 | static int word16[] = { |
@@ -104,10 +98,6 @@ static int word16[] = { | |||
104 | 0, /* dayna */ | 98 | 0, /* dayna */ |
105 | 1, /* interlan */ | 99 | 1, /* interlan */ |
106 | 0, /* kinetics */ | 100 | 0, /* kinetics */ |
107 | 1, /* focus (??) */ | ||
108 | 1, /* sonic systems */ | ||
109 | 1, /* dayna2 */ | ||
110 | 1, /* dayna-lc */ | ||
111 | }; | 101 | }; |
112 | 102 | ||
113 | /* on which cards do we use NuBus resources? */ | 103 | /* on which cards do we use NuBus resources? */ |
@@ -119,10 +109,12 @@ static int useresources[] = { | |||
119 | 0, /* dayna */ | 109 | 0, /* dayna */ |
120 | 0, /* interlan */ | 110 | 0, /* interlan */ |
121 | 0, /* kinetics */ | 111 | 0, /* kinetics */ |
122 | 0, /* focus (??) */ | 112 | }; |
123 | 1, /* sonic systems */ | 113 | |
124 | 1, /* dayna2 */ | 114 | enum mac8390_access { |
125 | 1, /* dayna-lc */ | 115 | ACCESS_UNKNOWN = 0, |
116 | ACCESS_32, | ||
117 | ACCESS_16, | ||
126 | }; | 118 | }; |
127 | 119 | ||
128 | extern enum mac8390_type mac8390_ident(struct nubus_dev * dev); | 120 | extern enum mac8390_type mac8390_ident(struct nubus_dev * dev); |
@@ -134,8 +126,9 @@ static int mac8390_initdev(struct net_device * dev, struct nubus_dev * ndev, | |||
134 | static int mac8390_open(struct net_device * dev); | 126 | static int mac8390_open(struct net_device * dev); |
135 | static int mac8390_close(struct net_device * dev); | 127 | static int mac8390_close(struct net_device * dev); |
136 | static void mac8390_no_reset(struct net_device *dev); | 128 | static void mac8390_no_reset(struct net_device *dev); |
129 | static void interlan_reset(struct net_device *dev); | ||
137 | 130 | ||
138 | /* Sane (32-bit chunk memory read/write) - Apple/Asante/Farallon do this*/ | 131 | /* Sane (32-bit chunk memory read/write) - Some Farallon and Apple do this*/ |
139 | static void sane_get_8390_hdr(struct net_device *dev, | 132 | static void sane_get_8390_hdr(struct net_device *dev, |
140 | struct e8390_pkt_hdr *hdr, int ring_page); | 133 | struct e8390_pkt_hdr *hdr, int ring_page); |
141 | static void sane_block_input(struct net_device * dev, int count, | 134 | static void sane_block_input(struct net_device * dev, int count, |
@@ -172,23 +165,93 @@ static void word_memcpy_fromcard(void *tp, const void *fp, int count); | |||
172 | 165 | ||
173 | enum mac8390_type __init mac8390_ident(struct nubus_dev * dev) | 166 | enum mac8390_type __init mac8390_ident(struct nubus_dev * dev) |
174 | { | 167 | { |
175 | if (dev->dr_sw == NUBUS_DRSW_ASANTE) | 168 | switch (dev->dr_sw) { |
176 | return MAC8390_ASANTE; | 169 | case NUBUS_DRSW_3COM: |
177 | if (dev->dr_sw == NUBUS_DRSW_FARALLON) | 170 | switch (dev->dr_hw) { |
178 | return MAC8390_FARALLON; | 171 | case NUBUS_DRHW_APPLE_SONIC_NB: |
179 | if (dev->dr_sw == NUBUS_DRSW_KINETICS) | 172 | case NUBUS_DRHW_APPLE_SONIC_LC: |
180 | return MAC8390_KINETICS; | 173 | case NUBUS_DRHW_SONNET: |
181 | if (dev->dr_sw == NUBUS_DRSW_DAYNA) | 174 | return MAC8390_NONE; |
182 | return MAC8390_DAYNA; | 175 | break; |
183 | if (dev->dr_sw == NUBUS_DRSW_DAYNA2) | 176 | default: |
184 | return MAC8390_DAYNA2; | 177 | return MAC8390_APPLE; |
185 | if (dev->dr_sw == NUBUS_DRSW_DAYNA_LC) | 178 | break; |
186 | return MAC8390_DAYNA3; | 179 | } |
187 | if (dev->dr_hw == NUBUS_DRHW_CABLETRON) | 180 | break; |
188 | return MAC8390_CABLETRON; | 181 | |
182 | case NUBUS_DRSW_APPLE: | ||
183 | switch (dev->dr_hw) { | ||
184 | case NUBUS_DRHW_ASANTE_LC: | ||
185 | return MAC8390_NONE; | ||
186 | break; | ||
187 | case NUBUS_DRHW_CABLETRON: | ||
188 | return MAC8390_CABLETRON; | ||
189 | break; | ||
190 | default: | ||
191 | return MAC8390_APPLE; | ||
192 | break; | ||
193 | } | ||
194 | break; | ||
195 | |||
196 | case NUBUS_DRSW_ASANTE: | ||
197 | return MAC8390_ASANTE; | ||
198 | break; | ||
199 | |||
200 | case NUBUS_DRSW_TECHWORKS: | ||
201 | case NUBUS_DRSW_DAYNA2: | ||
202 | case NUBUS_DRSW_DAYNA_LC: | ||
203 | if (dev->dr_hw == NUBUS_DRHW_CABLETRON) | ||
204 | return MAC8390_CABLETRON; | ||
205 | else | ||
206 | return MAC8390_APPLE; | ||
207 | break; | ||
208 | |||
209 | case NUBUS_DRSW_FARALLON: | ||
210 | return MAC8390_FARALLON; | ||
211 | break; | ||
212 | |||
213 | case NUBUS_DRSW_KINETICS: | ||
214 | switch (dev->dr_hw) { | ||
215 | case NUBUS_DRHW_INTERLAN: | ||
216 | return MAC8390_INTERLAN; | ||
217 | break; | ||
218 | default: | ||
219 | return MAC8390_KINETICS; | ||
220 | break; | ||
221 | } | ||
222 | break; | ||
223 | |||
224 | case NUBUS_DRSW_DAYNA: | ||
225 | // These correspond to Dayna Sonic cards | ||
226 | // which use the macsonic driver | ||
227 | if (dev->dr_hw == NUBUS_DRHW_SMC9194 || | ||
228 | dev->dr_hw == NUBUS_DRHW_INTERLAN ) | ||
229 | return MAC8390_NONE; | ||
230 | else | ||
231 | return MAC8390_DAYNA; | ||
232 | break; | ||
233 | } | ||
189 | return MAC8390_NONE; | 234 | return MAC8390_NONE; |
190 | } | 235 | } |
191 | 236 | ||
237 | enum mac8390_access __init mac8390_testio(volatile unsigned long membase) | ||
238 | { | ||
239 | unsigned long outdata = 0xA5A0B5B0; | ||
240 | unsigned long indata = 0x00000000; | ||
241 | /* Try writing 32 bits */ | ||
242 | memcpy((char *)membase, (char *)&outdata, 4); | ||
243 | /* Now compare them */ | ||
244 | if (memcmp((char *)&outdata, (char *)membase, 4) == 0) | ||
245 | return ACCESS_32; | ||
246 | /* Write 16 bit output */ | ||
247 | word_memcpy_tocard((char *)membase, (char *)&outdata, 4); | ||
248 | /* Now read it back */ | ||
249 | word_memcpy_fromcard((char *)&indata, (char *)membase, 4); | ||
250 | if (outdata == indata) | ||
251 | return ACCESS_16; | ||
252 | return ACCESS_UNKNOWN; | ||
253 | } | ||
254 | |||
192 | int __init mac8390_memsize(unsigned long membase) | 255 | int __init mac8390_memsize(unsigned long membase) |
193 | { | 256 | { |
194 | unsigned long flags; | 257 | unsigned long flags; |
@@ -287,14 +350,6 @@ struct net_device * __init mac8390_probe(int unit) | |||
287 | continue; | 350 | continue; |
288 | } else { | 351 | } else { |
289 | nubus_get_rsrc_mem(dev->dev_addr, &ent, 6); | 352 | nubus_get_rsrc_mem(dev->dev_addr, &ent, 6); |
290 | /* Some Sonic Sys cards masquerade as Farallon */ | ||
291 | if (cardtype == MAC8390_FARALLON && | ||
292 | dev->dev_addr[0] == 0x0 && | ||
293 | dev->dev_addr[1] == 0x40 && | ||
294 | dev->dev_addr[2] == 0x10) { | ||
295 | /* This is really Sonic Sys card */ | ||
296 | cardtype = MAC8390_SONICSYS; | ||
297 | } | ||
298 | } | 353 | } |
299 | 354 | ||
300 | if (useresources[cardtype] == 1) { | 355 | if (useresources[cardtype] == 1) { |
@@ -334,6 +389,17 @@ struct net_device * __init mac8390_probe(int unit) | |||
334 | dev->mem_start + | 389 | dev->mem_start + |
335 | mac8390_memsize(dev->mem_start); | 390 | mac8390_memsize(dev->mem_start); |
336 | break; | 391 | break; |
392 | case MAC8390_INTERLAN: | ||
393 | dev->base_addr = | ||
394 | (int)(ndev->board->slot_addr + | ||
395 | INTERLAN_8390_BASE); | ||
396 | dev->mem_start = | ||
397 | (int)(ndev->board->slot_addr + | ||
398 | INTERLAN_8390_MEM); | ||
399 | dev->mem_end = | ||
400 | dev->mem_start + | ||
401 | mac8390_memsize(dev->mem_start); | ||
402 | break; | ||
337 | case MAC8390_CABLETRON: | 403 | case MAC8390_CABLETRON: |
338 | dev->base_addr = | 404 | dev->base_addr = |
339 | (int)(ndev->board->slot_addr + | 405 | (int)(ndev->board->slot_addr + |
@@ -356,8 +422,8 @@ struct net_device * __init mac8390_probe(int unit) | |||
356 | 422 | ||
357 | default: | 423 | default: |
358 | printk(KERN_ERR "Card type %s is" | 424 | printk(KERN_ERR "Card type %s is" |
359 | " unsupported, sorry\n", | 425 | " unsupported, sorry\n", |
360 | cardname[cardtype]); | 426 | ndev->board->name); |
361 | continue; | 427 | continue; |
362 | } | 428 | } |
363 | } | 429 | } |
@@ -438,7 +504,7 @@ static int __init mac8390_initdev(struct net_device * dev, struct nubus_dev * nd | |||
438 | 24, 26, 28, 30 | 504 | 24, 26, 28, 30 |
439 | }; | 505 | }; |
440 | 506 | ||
441 | int access_bitmode; | 507 | int access_bitmode = 0; |
442 | 508 | ||
443 | /* Now fill in our stuff */ | 509 | /* Now fill in our stuff */ |
444 | dev->open = &mac8390_open; | 510 | dev->open = &mac8390_open; |
@@ -468,29 +534,47 @@ static int __init mac8390_initdev(struct net_device * dev, struct nubus_dev * nd | |||
468 | 534 | ||
469 | /* Fill in model-specific information and functions */ | 535 | /* Fill in model-specific information and functions */ |
470 | switch(type) { | 536 | switch(type) { |
471 | case MAC8390_SONICSYS: | ||
472 | /* 16 bit card, register map is reversed */ | ||
473 | ei_status.reset_8390 = &mac8390_no_reset; | ||
474 | ei_status.block_input = &slow_sane_block_input; | ||
475 | ei_status.block_output = &slow_sane_block_output; | ||
476 | ei_status.get_8390_hdr = &slow_sane_get_8390_hdr; | ||
477 | ei_status.reg_offset = back4_offsets; | ||
478 | access_bitmode = 0; | ||
479 | break; | ||
480 | case MAC8390_FARALLON: | 537 | case MAC8390_FARALLON: |
481 | case MAC8390_APPLE: | 538 | case MAC8390_APPLE: |
539 | switch(mac8390_testio(dev->mem_start)) { | ||
540 | case ACCESS_UNKNOWN: | ||
541 | printk("Don't know how to access card memory!\n"); | ||
542 | return -ENODEV; | ||
543 | break; | ||
544 | |||
545 | case ACCESS_16: | ||
546 | /* 16 bit card, register map is reversed */ | ||
547 | ei_status.reset_8390 = &mac8390_no_reset; | ||
548 | ei_status.block_input = &slow_sane_block_input; | ||
549 | ei_status.block_output = &slow_sane_block_output; | ||
550 | ei_status.get_8390_hdr = &slow_sane_get_8390_hdr; | ||
551 | ei_status.reg_offset = back4_offsets; | ||
552 | break; | ||
553 | |||
554 | case ACCESS_32: | ||
555 | /* 32 bit card, register map is reversed */ | ||
556 | ei_status.reset_8390 = &mac8390_no_reset; | ||
557 | ei_status.block_input = &sane_block_input; | ||
558 | ei_status.block_output = &sane_block_output; | ||
559 | ei_status.get_8390_hdr = &sane_get_8390_hdr; | ||
560 | ei_status.reg_offset = back4_offsets; | ||
561 | access_bitmode = 1; | ||
562 | break; | ||
563 | } | ||
564 | break; | ||
565 | |||
482 | case MAC8390_ASANTE: | 566 | case MAC8390_ASANTE: |
483 | case MAC8390_DAYNA2: | 567 | /* Some Asante cards pass the 32 bit test |
484 | case MAC8390_DAYNA3: | 568 | * but overwrite system memory when run at 32 bit. |
485 | /* 32 bit card, register map is reversed */ | 569 | * so we run them all at 16 bit. |
486 | /* sane */ | 570 | */ |
487 | ei_status.reset_8390 = &mac8390_no_reset; | 571 | ei_status.reset_8390 = &mac8390_no_reset; |
488 | ei_status.block_input = &sane_block_input; | 572 | ei_status.block_input = &slow_sane_block_input; |
489 | ei_status.block_output = &sane_block_output; | 573 | ei_status.block_output = &slow_sane_block_output; |
490 | ei_status.get_8390_hdr = &sane_get_8390_hdr; | 574 | ei_status.get_8390_hdr = &slow_sane_get_8390_hdr; |
491 | ei_status.reg_offset = back4_offsets; | 575 | ei_status.reg_offset = back4_offsets; |
492 | access_bitmode = 1; | ||
493 | break; | 576 | break; |
577 | |||
494 | case MAC8390_CABLETRON: | 578 | case MAC8390_CABLETRON: |
495 | /* 16 bit card, register map is short forward */ | 579 | /* 16 bit card, register map is short forward */ |
496 | ei_status.reset_8390 = &mac8390_no_reset; | 580 | ei_status.reset_8390 = &mac8390_no_reset; |
@@ -498,21 +582,30 @@ static int __init mac8390_initdev(struct net_device * dev, struct nubus_dev * nd | |||
498 | ei_status.block_output = &slow_sane_block_output; | 582 | ei_status.block_output = &slow_sane_block_output; |
499 | ei_status.get_8390_hdr = &slow_sane_get_8390_hdr; | 583 | ei_status.get_8390_hdr = &slow_sane_get_8390_hdr; |
500 | ei_status.reg_offset = fwrd2_offsets; | 584 | ei_status.reg_offset = fwrd2_offsets; |
501 | access_bitmode = 0; | ||
502 | break; | 585 | break; |
586 | |||
503 | case MAC8390_DAYNA: | 587 | case MAC8390_DAYNA: |
504 | case MAC8390_KINETICS: | 588 | case MAC8390_KINETICS: |
505 | /* 16 bit memory */ | 589 | /* 16 bit memory, register map is forward */ |
506 | /* dayna and similar */ | 590 | /* dayna and similar */ |
507 | ei_status.reset_8390 = &mac8390_no_reset; | 591 | ei_status.reset_8390 = &mac8390_no_reset; |
508 | ei_status.block_input = &dayna_block_input; | 592 | ei_status.block_input = &dayna_block_input; |
509 | ei_status.block_output = &dayna_block_output; | 593 | ei_status.block_output = &dayna_block_output; |
510 | ei_status.get_8390_hdr = &dayna_get_8390_hdr; | 594 | ei_status.get_8390_hdr = &dayna_get_8390_hdr; |
511 | ei_status.reg_offset = fwrd4_offsets; | 595 | ei_status.reg_offset = fwrd4_offsets; |
512 | access_bitmode = 0; | ||
513 | break; | 596 | break; |
597 | |||
598 | case MAC8390_INTERLAN: | ||
599 | /* 16 bit memory, register map is forward */ | ||
600 | ei_status.reset_8390 = &interlan_reset; | ||
601 | ei_status.block_input = &slow_sane_block_input; | ||
602 | ei_status.block_output = &slow_sane_block_output; | ||
603 | ei_status.get_8390_hdr = &slow_sane_get_8390_hdr; | ||
604 | ei_status.reg_offset = fwrd4_offsets; | ||
605 | break; | ||
606 | |||
514 | default: | 607 | default: |
515 | printk(KERN_ERR "Card type %s is unsupported, sorry\n", cardname[type]); | 608 | printk(KERN_ERR "Card type %s is unsupported, sorry\n", ndev->board->name); |
516 | return -ENODEV; | 609 | return -ENODEV; |
517 | } | 610 | } |
518 | 611 | ||
@@ -530,9 +623,9 @@ static int __init mac8390_initdev(struct net_device * dev, struct nubus_dev * nd | |||
530 | printk(":"); | 623 | printk(":"); |
531 | } | 624 | } |
532 | } | 625 | } |
533 | printk(" IRQ %d, shared memory at %#lx-%#lx, %d-bit access.\n", | 626 | printk(" IRQ %d, %d KB shared memory at %#lx, %d-bit access.\n", |
534 | dev->irq, dev->mem_start, dev->mem_end-1, | 627 | dev->irq, (int)((dev->mem_end - dev->mem_start)/0x1000) * 4, |
535 | access_bitmode?32:16); | 628 | dev->mem_start, access_bitmode?32:16); |
536 | return 0; | 629 | return 0; |
537 | } | 630 | } |
538 | 631 | ||
@@ -561,6 +654,18 @@ static void mac8390_no_reset(struct net_device *dev) | |||
561 | return; | 654 | return; |
562 | } | 655 | } |
563 | 656 | ||
657 | static void interlan_reset(struct net_device *dev) | ||
658 | { | ||
659 | unsigned char *target=nubus_slot_addr(IRQ2SLOT(dev->irq)); | ||
660 | if (ei_debug > 1) | ||
661 | printk("Need to reset the NS8390 t=%lu...", jiffies); | ||
662 | ei_status.txing = 0; | ||
663 | target[0xC0000] = 0; | ||
664 | if (ei_debug > 1) | ||
665 | printk("reset complete\n"); | ||
666 | return; | ||
667 | } | ||
668 | |||
564 | /* dayna_memcpy_fromio/dayna_memcpy_toio */ | 669 | /* dayna_memcpy_fromio/dayna_memcpy_toio */ |
565 | /* directly from daynaport.c by Alan Cox */ | 670 | /* directly from daynaport.c by Alan Cox */ |
566 | static void dayna_memcpy_fromcard(struct net_device *dev, void *to, int from, int count) | 671 | static void dayna_memcpy_fromcard(struct net_device *dev, void *to, int from, int count) |