Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.1-rc8 576 lines 16 kB view raw
1/* smc-mca.c: A SMC Ultra ethernet driver for linux. */ 2/* 3 Most of this driver, except for ultramca_probe is nearly 4 verbatim from smc-ultra.c by Donald Becker. The rest is 5 written and copyright 1996 by David Weis, weisd3458@uni.edu 6 7 This is a driver for the SMC Ultra and SMC EtherEZ ethercards. 8 9 This driver uses the cards in the 8390-compatible, shared memory mode. 10 Most of the run-time complexity is handled by the generic code in 11 8390.c. 12 13 This driver enables the shared memory only when doing the actual data 14 transfers to avoid a bug in early version of the card that corrupted 15 data transferred by a AHA1542. 16 17 This driver does not support the programmed-I/O data transfer mode of 18 the EtherEZ. That support (if available) is smc-ez.c. Nor does it 19 use the non-8390-compatible "Altego" mode. (No support currently planned.) 20 21 Changelog: 22 23 Paul Gortmaker : multiple card support for module users. 24 David Weis : Micro Channel-ized it. 25 Tom Sightler : Added support for IBM PS/2 Ethernet Adapter/A 26 Christopher Turcksin : Changed MCA-probe so that multiple adapters are 27 found correctly (Jul 16, 1997) 28 Chris Beauregard : Tried to merge the two changes above (Dec 15, 1997) 29 Tom Sightler : Fixed minor detection bug caused by above merge 30 Tom Sightler : Added support for three more Western Digital 31 MCA-adapters 32 Tom Sightler : Added support for 2.2.x mca_find_unused_adapter 33 Hartmut Schmidt : - Modified parameter detection to handle each 34 card differently depending on a switch-list 35 - 'card_ver' removed from the adapter list 36 - Some minor bug fixes 37*/ 38 39#include <linux/mca.h> 40#include <linux/module.h> 41#include <linux/kernel.h> 42#include <linux/errno.h> 43#include <linux/string.h> 44#include <linux/init.h> 45#include <linux/interrupt.h> 46#include <linux/netdevice.h> 47#include <linux/etherdevice.h> 48 49#include <asm/io.h> 50#include <asm/system.h> 51 52#include "8390.h" 53 54#define DRV_NAME "smc-mca" 55 56static int ultramca_open(struct net_device *dev); 57static void ultramca_reset_8390(struct net_device *dev); 58static void ultramca_get_8390_hdr(struct net_device *dev, 59 struct e8390_pkt_hdr *hdr, 60 int ring_page); 61static void ultramca_block_input(struct net_device *dev, int count, 62 struct sk_buff *skb, 63 int ring_offset); 64static void ultramca_block_output(struct net_device *dev, int count, 65 const unsigned char *buf, 66 const int start_page); 67static int ultramca_close_card(struct net_device *dev); 68 69#define START_PG 0x00 /* First page of TX buffer */ 70 71#define ULTRA_CMDREG 0 /* Offset to ASIC command register. */ 72#define ULTRA_RESET 0x80 /* Board reset, in ULTRA_CMDREG. */ 73#define ULTRA_MEMENB 0x40 /* Enable the shared memory. */ 74#define ULTRA_NIC_OFFSET 16 /* NIC register offset from the base_addr. */ 75#define ULTRA_IO_EXTENT 32 76#define EN0_ERWCNT 0x08 /* Early receive warning count. */ 77 78#define _61c8_SMC_Ethercard_PLUS_Elite_A_BNC_AUI_WD8013EP_A 0 79#define _61c9_SMC_Ethercard_PLUS_Elite_A_UTP_AUI_WD8013EP_A 1 80#define _6fc0_WD_Ethercard_PLUS_A_WD8003E_A_OR_WD8003ET_A 2 81#define _6fc1_WD_Starcard_PLUS_A_WD8003ST_A 3 82#define _6fc2_WD_Ethercard_PLUS_10T_A_WD8003W_A 4 83#define _efd4_IBM_PS2_Adapter_A_for_Ethernet_UTP_AUI_WD8013WP_A 5 84#define _efd5_IBM_PS2_Adapter_A_for_Ethernet_BNC_AUI_WD8013WP_A 6 85#define _efe5_IBM_PS2_Adapter_A_for_Ethernet 7 86 87struct smc_mca_adapters_t { 88 unsigned int id; 89 char *name; 90}; 91 92#define MAX_ULTRAMCA_CARDS 4 /* Max number of Ultra cards per module */ 93 94static int ultra_io[MAX_ULTRAMCA_CARDS]; 95static int ultra_irq[MAX_ULTRAMCA_CARDS]; 96MODULE_LICENSE("GPL"); 97 98module_param_array(ultra_io, int, NULL, 0); 99module_param_array(ultra_irq, int, NULL, 0); 100MODULE_PARM_DESC(ultra_io, "SMC Ultra/EtherEZ MCA I/O base address(es)"); 101MODULE_PARM_DESC(ultra_irq, "SMC Ultra/EtherEZ MCA IRQ number(s)"); 102 103static const struct { 104 unsigned int base_addr; 105} addr_table[] = { 106 { 0x0800 }, 107 { 0x1800 }, 108 { 0x2800 }, 109 { 0x3800 }, 110 { 0x4800 }, 111 { 0x5800 }, 112 { 0x6800 }, 113 { 0x7800 }, 114 { 0x8800 }, 115 { 0x9800 }, 116 { 0xa800 }, 117 { 0xb800 }, 118 { 0xc800 }, 119 { 0xd800 }, 120 { 0xe800 }, 121 { 0xf800 } 122}; 123 124#define MEM_MASK 64 125 126static const struct { 127 unsigned char mem_index; 128 unsigned long mem_start; 129 unsigned char num_pages; 130} mem_table[] = { 131 { 16, 0x0c0000, 40 }, 132 { 18, 0x0c4000, 40 }, 133 { 20, 0x0c8000, 40 }, 134 { 22, 0x0cc000, 40 }, 135 { 24, 0x0d0000, 40 }, 136 { 26, 0x0d4000, 40 }, 137 { 28, 0x0d8000, 40 }, 138 { 30, 0x0dc000, 40 }, 139 {144, 0xfc0000, 40 }, 140 {148, 0xfc8000, 40 }, 141 {154, 0xfd0000, 40 }, 142 {156, 0xfd8000, 40 }, 143 { 0, 0x0c0000, 20 }, 144 { 1, 0x0c2000, 20 }, 145 { 2, 0x0c4000, 20 }, 146 { 3, 0x0c6000, 20 } 147}; 148 149#define IRQ_MASK 243 150static const struct { 151 unsigned char new_irq; 152 unsigned char old_irq; 153} irq_table[] = { 154 { 3, 3 }, 155 { 4, 4 }, 156 { 10, 10 }, 157 { 14, 15 } 158}; 159 160static short smc_mca_adapter_ids[] __initdata = { 161 0x61c8, 162 0x61c9, 163 0x6fc0, 164 0x6fc1, 165 0x6fc2, 166 0xefd4, 167 0xefd5, 168 0xefe5, 169 0x0000 170}; 171 172static char *smc_mca_adapter_names[] __initdata = { 173 "SMC Ethercard PLUS Elite/A BNC/AUI (WD8013EP/A)", 174 "SMC Ethercard PLUS Elite/A UTP/AUI (WD8013WP/A)", 175 "WD Ethercard PLUS/A (WD8003E/A or WD8003ET/A)", 176 "WD Starcard PLUS/A (WD8003ST/A)", 177 "WD Ethercard PLUS 10T/A (WD8003W/A)", 178 "IBM PS/2 Adapter/A for Ethernet UTP/AUI (WD8013WP/A)", 179 "IBM PS/2 Adapter/A for Ethernet BNC/AUI (WD8013EP/A)", 180 "IBM PS/2 Adapter/A for Ethernet", 181 NULL 182}; 183 184static int ultra_found = 0; 185 186 187static const struct net_device_ops ultramca_netdev_ops = { 188 .ndo_open = ultramca_open, 189 .ndo_stop = ultramca_close_card, 190 191 .ndo_start_xmit = ei_start_xmit, 192 .ndo_tx_timeout = ei_tx_timeout, 193 .ndo_get_stats = ei_get_stats, 194 .ndo_set_multicast_list = ei_set_multicast_list, 195 .ndo_validate_addr = eth_validate_addr, 196 .ndo_set_mac_address = eth_mac_addr, 197 .ndo_change_mtu = eth_change_mtu, 198#ifdef CONFIG_NET_POLL_CONTROLLER 199 .ndo_poll_controller = ei_poll, 200#endif 201}; 202 203static int __init ultramca_probe(struct device *gen_dev) 204{ 205 unsigned short ioaddr; 206 struct net_device *dev; 207 unsigned char reg4, num_pages; 208 struct mca_device *mca_dev = to_mca_device(gen_dev); 209 char slot = mca_dev->slot; 210 unsigned char pos2 = 0xff, pos3 = 0xff, pos4 = 0xff, pos5 = 0xff; 211 int i, rc; 212 int adapter = mca_dev->index; 213 int tbase = 0; 214 int tirq = 0; 215 int base_addr = ultra_io[ultra_found]; 216 int irq = ultra_irq[ultra_found]; 217 218 if (base_addr || irq) { 219 printk(KERN_INFO "Probing for SMC MCA adapter"); 220 if (base_addr) { 221 printk(KERN_INFO " at I/O address 0x%04x%c", 222 base_addr, irq ? ' ' : '\n'); 223 } 224 if (irq) { 225 printk(KERN_INFO "using irq %d\n", irq); 226 } 227 } 228 229 tirq = 0; 230 tbase = 0; 231 232 /* If we're trying to match a specificied irq or io address, 233 * we'll reject the adapter found unless it's the one we're 234 * looking for */ 235 236 pos2 = mca_device_read_stored_pos(mca_dev, 2); /* io_addr */ 237 pos3 = mca_device_read_stored_pos(mca_dev, 3); /* shared mem */ 238 pos4 = mca_device_read_stored_pos(mca_dev, 4); /* ROM bios addr range */ 239 pos5 = mca_device_read_stored_pos(mca_dev, 5); /* irq, media and RIPL */ 240 241 /* Test the following conditions: 242 * - If an irq parameter is supplied, compare it 243 * with the irq of the adapter we found 244 * - If a base_addr paramater is given, compare it 245 * with the base_addr of the adapter we found 246 * - Check that the irq and the base_addr of the 247 * adapter we found is not already in use by 248 * this driver 249 */ 250 251 switch (mca_dev->index) { 252 case _61c8_SMC_Ethercard_PLUS_Elite_A_BNC_AUI_WD8013EP_A: 253 case _61c9_SMC_Ethercard_PLUS_Elite_A_UTP_AUI_WD8013EP_A: 254 case _efd4_IBM_PS2_Adapter_A_for_Ethernet_UTP_AUI_WD8013WP_A: 255 case _efd5_IBM_PS2_Adapter_A_for_Ethernet_BNC_AUI_WD8013WP_A: 256 { 257 tbase = addr_table[(pos2 & 0xf0) >> 4].base_addr; 258 tirq = irq_table[(pos5 & 0xc) >> 2].new_irq; 259 break; 260 } 261 case _6fc0_WD_Ethercard_PLUS_A_WD8003E_A_OR_WD8003ET_A: 262 case _6fc1_WD_Starcard_PLUS_A_WD8003ST_A: 263 case _6fc2_WD_Ethercard_PLUS_10T_A_WD8003W_A: 264 case _efe5_IBM_PS2_Adapter_A_for_Ethernet: 265 { 266 tbase = ((pos2 & 0x0fe) * 0x10); 267 tirq = irq_table[(pos5 & 3)].old_irq; 268 break; 269 } 270 } 271 272 if(!tirq || !tbase || 273 (irq && irq != tirq) || 274 (base_addr && tbase != base_addr)) 275 /* FIXME: we're trying to force the ordering of the 276 * devices here, there should be a way of getting this 277 * to happen */ 278 return -ENXIO; 279 280 /* Adapter found. */ 281 dev = alloc_ei_netdev(); 282 if(!dev) 283 return -ENODEV; 284 285 SET_NETDEV_DEV(dev, gen_dev); 286 mca_device_set_name(mca_dev, smc_mca_adapter_names[adapter]); 287 mca_device_set_claim(mca_dev, 1); 288 289 printk(KERN_INFO "smc_mca: %s found in slot %d\n", 290 smc_mca_adapter_names[adapter], slot + 1); 291 292 ultra_found++; 293 294 dev->base_addr = ioaddr = mca_device_transform_ioport(mca_dev, tbase); 295 dev->irq = mca_device_transform_irq(mca_dev, tirq); 296 dev->mem_start = 0; 297 num_pages = 40; 298 299 switch (adapter) { /* card-# in const array above [hs] */ 300 case _61c8_SMC_Ethercard_PLUS_Elite_A_BNC_AUI_WD8013EP_A: 301 case _61c9_SMC_Ethercard_PLUS_Elite_A_UTP_AUI_WD8013EP_A: 302 { 303 for (i = 0; i < 16; i++) { /* taking 16 counts 304 * up to 15 [hs] */ 305 if (mem_table[i].mem_index == (pos3 & ~MEM_MASK)) { 306 dev->mem_start = (unsigned long) 307 mca_device_transform_memory(mca_dev, (void *)mem_table[i].mem_start); 308 num_pages = mem_table[i].num_pages; 309 } 310 } 311 break; 312 } 313 case _6fc0_WD_Ethercard_PLUS_A_WD8003E_A_OR_WD8003ET_A: 314 case _6fc1_WD_Starcard_PLUS_A_WD8003ST_A: 315 case _6fc2_WD_Ethercard_PLUS_10T_A_WD8003W_A: 316 case _efe5_IBM_PS2_Adapter_A_for_Ethernet: 317 { 318 dev->mem_start = (unsigned long) 319 mca_device_transform_memory(mca_dev, (void *)((pos3 & 0xfc) * 0x1000)); 320 num_pages = 0x40; 321 break; 322 } 323 case _efd4_IBM_PS2_Adapter_A_for_Ethernet_UTP_AUI_WD8013WP_A: 324 case _efd5_IBM_PS2_Adapter_A_for_Ethernet_BNC_AUI_WD8013WP_A: 325 { 326 /* courtesy of gamera@quartz.ocn.ne.jp, pos3 indicates 327 * the index of the 0x2000 step. 328 * beware different number of pages [hs] 329 */ 330 dev->mem_start = (unsigned long) 331 mca_device_transform_memory(mca_dev, (void *)(0xc0000 + (0x2000 * (pos3 & 0xf)))); 332 num_pages = 0x20 + (2 * (pos3 & 0x10)); 333 break; 334 } 335 } 336 337 /* sanity check, shouldn't happen */ 338 if (dev->mem_start == 0) { 339 rc = -ENODEV; 340 goto err_unclaim; 341 } 342 343 if (!request_region(ioaddr, ULTRA_IO_EXTENT, DRV_NAME)) { 344 rc = -ENODEV; 345 goto err_unclaim; 346 } 347 348 reg4 = inb(ioaddr + 4) & 0x7f; 349 outb(reg4, ioaddr + 4); 350 351 for (i = 0; i < 6; i++) 352 dev->dev_addr[i] = inb(ioaddr + 8 + i); 353 354 printk(KERN_INFO "smc_mca[%d]: Parameters: %#3x, %pM", 355 slot + 1, ioaddr, dev->dev_addr); 356 357 /* Switch from the station address to the alternate register set 358 * and read the useful registers there. 359 */ 360 361 outb(0x80 | reg4, ioaddr + 4); 362 363 /* Enable FINE16 mode to avoid BIOS ROM width mismatches @ reboot. 364 */ 365 366 outb(0x80 | inb(ioaddr + 0x0c), ioaddr + 0x0c); 367 368 /* Switch back to the station address register set so that 369 * the MS-DOS driver can find the card after a warm boot. 370 */ 371 372 outb(reg4, ioaddr + 4); 373 374 dev_set_drvdata(gen_dev, dev); 375 376 /* The 8390 isn't at the base address, so fake the offset 377 */ 378 379 dev->base_addr = ioaddr + ULTRA_NIC_OFFSET; 380 381 ei_status.name = "SMC Ultra MCA"; 382 ei_status.word16 = 1; 383 ei_status.tx_start_page = START_PG; 384 ei_status.rx_start_page = START_PG + TX_PAGES; 385 ei_status.stop_page = num_pages; 386 387 ei_status.mem = ioremap(dev->mem_start, (ei_status.stop_page - START_PG) * 256); 388 if (!ei_status.mem) { 389 rc = -ENOMEM; 390 goto err_release_region; 391 } 392 393 dev->mem_end = dev->mem_start + (ei_status.stop_page - START_PG) * 256; 394 395 printk(", IRQ %d memory %#lx-%#lx.\n", 396 dev->irq, dev->mem_start, dev->mem_end - 1); 397 398 ei_status.reset_8390 = &ultramca_reset_8390; 399 ei_status.block_input = &ultramca_block_input; 400 ei_status.block_output = &ultramca_block_output; 401 ei_status.get_8390_hdr = &ultramca_get_8390_hdr; 402 403 ei_status.priv = slot; 404 405 dev->netdev_ops = &ultramca_netdev_ops; 406 407 NS8390_init(dev, 0); 408 409 rc = register_netdev(dev); 410 if (rc) 411 goto err_unmap; 412 413 return 0; 414 415err_unmap: 416 iounmap(ei_status.mem); 417err_release_region: 418 release_region(ioaddr, ULTRA_IO_EXTENT); 419err_unclaim: 420 mca_device_set_claim(mca_dev, 0); 421 free_netdev(dev); 422 return rc; 423} 424 425static int ultramca_open(struct net_device *dev) 426{ 427 int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */ 428 int retval; 429 430 if ((retval = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev))) 431 return retval; 432 433 outb(ULTRA_MEMENB, ioaddr); /* Enable memory */ 434 outb(0x80, ioaddr + 5); /* ??? */ 435 outb(0x01, ioaddr + 6); /* Enable interrupts and memory. */ 436 outb(0x04, ioaddr + 5); /* ??? */ 437 438 /* Set the early receive warning level in window 0 high enough not 439 * to receive ERW interrupts. 440 */ 441 442 /* outb_p(E8390_NODMA + E8390_PAGE0, dev->base_addr); 443 * outb(0xff, dev->base_addr + EN0_ERWCNT); 444 */ 445 446 ei_open(dev); 447 return 0; 448} 449 450static void ultramca_reset_8390(struct net_device *dev) 451{ 452 int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */ 453 454 outb(ULTRA_RESET, ioaddr); 455 if (ei_debug > 1) 456 printk("resetting Ultra, t=%ld...", jiffies); 457 ei_status.txing = 0; 458 459 outb(0x80, ioaddr + 5); /* ??? */ 460 outb(0x01, ioaddr + 6); /* Enable interrupts and memory. */ 461 462 if (ei_debug > 1) 463 printk("reset done\n"); 464} 465 466/* Grab the 8390 specific header. Similar to the block_input routine, but 467 * we don't need to be concerned with ring wrap as the header will be at 468 * the start of a page, so we optimize accordingly. 469 */ 470 471static void ultramca_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page) 472{ 473 void __iomem *hdr_start = ei_status.mem + ((ring_page - START_PG) << 8); 474 475#ifdef notdef 476 /* Officially this is what we are doing, but the readl() is faster */ 477 memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr)); 478#else 479 ((unsigned int*)hdr)[0] = readl(hdr_start); 480#endif 481} 482 483/* Block input and output are easy on shared memory ethercards, the only 484 * complication is when the ring buffer wraps. 485 */ 486 487static void ultramca_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset) 488{ 489 void __iomem *xfer_start = ei_status.mem + ring_offset - START_PG * 256; 490 491 if (ring_offset + count > ei_status.stop_page * 256) { 492 /* We must wrap the input move. */ 493 int semi_count = ei_status.stop_page * 256 - ring_offset; 494 memcpy_fromio(skb->data, xfer_start, semi_count); 495 count -= semi_count; 496 memcpy_fromio(skb->data + semi_count, ei_status.mem + TX_PAGES * 256, count); 497 } else { 498 memcpy_fromio(skb->data, xfer_start, count); 499 } 500 501} 502 503static void ultramca_block_output(struct net_device *dev, int count, const unsigned char *buf, 504 int start_page) 505{ 506 void __iomem *shmem = ei_status.mem + ((start_page - START_PG) << 8); 507 508 memcpy_toio(shmem, buf, count); 509} 510 511static int ultramca_close_card(struct net_device *dev) 512{ 513 int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */ 514 515 netif_stop_queue(dev); 516 517 if (ei_debug > 1) 518 printk("%s: Shutting down ethercard.\n", dev->name); 519 520 outb(0x00, ioaddr + 6); /* Disable interrupts. */ 521 free_irq(dev->irq, dev); 522 523 NS8390_init(dev, 0); 524 /* We should someday disable shared memory and change to 8-bit mode 525 * "just in case"... 526 */ 527 528 return 0; 529} 530 531static int ultramca_remove(struct device *gen_dev) 532{ 533 struct mca_device *mca_dev = to_mca_device(gen_dev); 534 struct net_device *dev = dev_get_drvdata(gen_dev); 535 536 if (dev) { 537 /* NB: ultra_close_card() does free_irq */ 538 int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; 539 540 unregister_netdev(dev); 541 mca_device_set_claim(mca_dev, 0); 542 release_region(ioaddr, ULTRA_IO_EXTENT); 543 iounmap(ei_status.mem); 544 free_netdev(dev); 545 } 546 return 0; 547} 548 549 550static struct mca_driver ultra_driver = { 551 .id_table = smc_mca_adapter_ids, 552 .driver = { 553 .name = "smc-mca", 554 .bus = &mca_bus_type, 555 .probe = ultramca_probe, 556 .remove = ultramca_remove, 557 } 558}; 559 560static int __init ultramca_init_module(void) 561{ 562 if(!MCA_bus) 563 return -ENXIO; 564 565 mca_register_driver(&ultra_driver); 566 567 return ultra_found ? 0 : -ENXIO; 568} 569 570static void __exit ultramca_cleanup_module(void) 571{ 572 mca_unregister_driver(&ultra_driver); 573} 574module_init(ultramca_init_module); 575module_exit(ultramca_cleanup_module); 576