diff options
Diffstat (limited to 'drivers/net/pcmcia/pcnet_cs.c')
-rw-r--r-- | drivers/net/pcmcia/pcnet_cs.c | 139 |
1 files changed, 83 insertions, 56 deletions
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index e180832c278f..c94311aed1ab 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c | |||
@@ -506,7 +506,8 @@ static int pcnet_confcheck(struct pcmcia_device *p_dev, | |||
506 | unsigned int vcc, | 506 | unsigned int vcc, |
507 | void *priv_data) | 507 | void *priv_data) |
508 | { | 508 | { |
509 | int *has_shmem = priv_data; | 509 | int *priv = priv_data; |
510 | int try = (*priv & 0x1); | ||
510 | int i; | 511 | int i; |
511 | cistpl_io_t *io = &cfg->io; | 512 | cistpl_io_t *io = &cfg->io; |
512 | 513 | ||
@@ -523,77 +524,103 @@ static int pcnet_confcheck(struct pcmcia_device *p_dev, | |||
523 | i = p_dev->resource[1]->end = 0; | 524 | i = p_dev->resource[1]->end = 0; |
524 | } | 525 | } |
525 | 526 | ||
526 | *has_shmem = ((cfg->mem.nwin == 1) && | 527 | *priv &= ((cfg->mem.nwin == 1) && |
527 | (cfg->mem.win[0].len >= 0x4000)); | 528 | (cfg->mem.win[0].len >= 0x4000)) ? 0x10 : ~0x10; |
529 | |||
528 | p_dev->resource[0]->start = io->win[i].base; | 530 | p_dev->resource[0]->start = io->win[i].base; |
529 | p_dev->resource[0]->end = io->win[i].len; | 531 | p_dev->resource[0]->end = io->win[i].len; |
530 | p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK; | 532 | if (!try) |
533 | p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK; | ||
534 | else | ||
535 | p_dev->io_lines = 16; | ||
531 | if (p_dev->resource[0]->end + p_dev->resource[1]->end >= 32) | 536 | if (p_dev->resource[0]->end + p_dev->resource[1]->end >= 32) |
532 | return try_io_port(p_dev); | 537 | return try_io_port(p_dev); |
533 | 538 | ||
534 | return 0; | 539 | return -EINVAL; |
540 | } | ||
541 | |||
542 | static hw_info_t *pcnet_try_config(struct pcmcia_device *link, | ||
543 | int *has_shmem, int try) | ||
544 | { | ||
545 | struct net_device *dev = link->priv; | ||
546 | hw_info_t *local_hw_info; | ||
547 | pcnet_dev_t *info = PRIV(dev); | ||
548 | int priv = try; | ||
549 | int ret; | ||
550 | |||
551 | ret = pcmcia_loop_config(link, pcnet_confcheck, &priv); | ||
552 | if (ret) { | ||
553 | dev_warn(&link->dev, "no useable port range found\n"); | ||
554 | return NULL; | ||
555 | } | ||
556 | *has_shmem = (priv & 0x10); | ||
557 | |||
558 | if (!link->irq) | ||
559 | return NULL; | ||
560 | |||
561 | if (resource_size(link->resource[1]) == 8) { | ||
562 | link->conf.Attributes |= CONF_ENABLE_SPKR; | ||
563 | link->conf.Status = CCSR_AUDIO_ENA; | ||
564 | } | ||
565 | if ((link->manf_id == MANFID_IBM) && | ||
566 | (link->card_id == PRODID_IBM_HOME_AND_AWAY)) | ||
567 | link->conf.ConfigIndex |= 0x10; | ||
568 | |||
569 | ret = pcmcia_request_configuration(link, &link->conf); | ||
570 | if (ret) | ||
571 | return NULL; | ||
572 | |||
573 | dev->irq = link->irq; | ||
574 | dev->base_addr = link->resource[0]->start; | ||
575 | |||
576 | if (info->flags & HAS_MISC_REG) { | ||
577 | if ((if_port == 1) || (if_port == 2)) | ||
578 | dev->if_port = if_port; | ||
579 | else | ||
580 | dev_notice(&link->dev, "invalid if_port requested\n"); | ||
581 | } else | ||
582 | dev->if_port = 0; | ||
583 | |||
584 | if ((link->conf.ConfigBase == 0x03c0) && | ||
585 | (link->manf_id == 0x149) && (link->card_id == 0xc1ab)) { | ||
586 | dev_info(&link->dev, | ||
587 | "this is an AX88190 card - use axnet_cs instead.\n"); | ||
588 | return NULL; | ||
589 | } | ||
590 | |||
591 | local_hw_info = get_hwinfo(link); | ||
592 | if (!local_hw_info) | ||
593 | local_hw_info = get_prom(link); | ||
594 | if (!local_hw_info) | ||
595 | local_hw_info = get_dl10019(link); | ||
596 | if (!local_hw_info) | ||
597 | local_hw_info = get_ax88190(link); | ||
598 | if (!local_hw_info) | ||
599 | local_hw_info = get_hwired(link); | ||
600 | |||
601 | return local_hw_info; | ||
535 | } | 602 | } |
536 | 603 | ||
537 | static int pcnet_config(struct pcmcia_device *link) | 604 | static int pcnet_config(struct pcmcia_device *link) |
538 | { | 605 | { |
539 | struct net_device *dev = link->priv; | 606 | struct net_device *dev = link->priv; |
540 | pcnet_dev_t *info = PRIV(dev); | 607 | pcnet_dev_t *info = PRIV(dev); |
541 | int ret, start_pg, stop_pg, cm_offset; | 608 | int start_pg, stop_pg, cm_offset; |
542 | int has_shmem = 0; | 609 | int has_shmem = 0; |
543 | hw_info_t *local_hw_info; | 610 | hw_info_t *local_hw_info; |
544 | 611 | ||
545 | dev_dbg(&link->dev, "pcnet_config\n"); | 612 | dev_dbg(&link->dev, "pcnet_config\n"); |
546 | 613 | ||
547 | ret = pcmcia_loop_config(link, pcnet_confcheck, &has_shmem); | 614 | local_hw_info = pcnet_try_config(link, &has_shmem, 0); |
548 | if (ret) | 615 | if (!local_hw_info) { |
549 | goto failed; | 616 | /* check whether forcing io_lines to 16 helps... */ |
550 | 617 | pcmcia_disable_device(link); | |
551 | if (!link->irq) | 618 | local_hw_info = pcnet_try_config(link, &has_shmem, 1); |
552 | goto failed; | 619 | if (local_hw_info == NULL) { |
553 | 620 | dev_notice(&link->dev, "unable to read hardware net" | |
554 | if (resource_size(link->resource[1]) == 8) { | 621 | " address for io base %#3lx\n", dev->base_addr); |
555 | link->conf.Attributes |= CONF_ENABLE_SPKR; | 622 | goto failed; |
556 | link->conf.Status = CCSR_AUDIO_ENA; | 623 | } |
557 | } | ||
558 | if ((link->manf_id == MANFID_IBM) && | ||
559 | (link->card_id == PRODID_IBM_HOME_AND_AWAY)) | ||
560 | link->conf.ConfigIndex |= 0x10; | ||
561 | |||
562 | ret = pcmcia_request_configuration(link, &link->conf); | ||
563 | if (ret) | ||
564 | goto failed; | ||
565 | dev->irq = link->irq; | ||
566 | dev->base_addr = link->resource[0]->start; | ||
567 | if (info->flags & HAS_MISC_REG) { | ||
568 | if ((if_port == 1) || (if_port == 2)) | ||
569 | dev->if_port = if_port; | ||
570 | else | ||
571 | pr_notice("invalid if_port requested\n"); | ||
572 | } else { | ||
573 | dev->if_port = 0; | ||
574 | } | ||
575 | |||
576 | if ((link->conf.ConfigBase == 0x03c0) && | ||
577 | (link->manf_id == 0x149) && (link->card_id == 0xc1ab)) { | ||
578 | pr_notice("this is an AX88190 card!\n"); | ||
579 | pr_notice("use axnet_cs instead.\n"); | ||
580 | goto failed; | ||
581 | } | ||
582 | |||
583 | local_hw_info = get_hwinfo(link); | ||
584 | if (local_hw_info == NULL) | ||
585 | local_hw_info = get_prom(link); | ||
586 | if (local_hw_info == NULL) | ||
587 | local_hw_info = get_dl10019(link); | ||
588 | if (local_hw_info == NULL) | ||
589 | local_hw_info = get_ax88190(link); | ||
590 | if (local_hw_info == NULL) | ||
591 | local_hw_info = get_hwired(link); | ||
592 | |||
593 | if (local_hw_info == NULL) { | ||
594 | pr_notice("unable to read hardware net address for io base %#3lx\n", | ||
595 | dev->base_addr); | ||
596 | goto failed; | ||
597 | } | 624 | } |
598 | 625 | ||
599 | info->flags = local_hw_info->flags; | 626 | info->flags = local_hw_info->flags; |