diff options
Diffstat (limited to 'drivers/net/wireless/spectrum_cs.c')
-rw-r--r-- | drivers/net/wireless/spectrum_cs.c | 162 |
1 files changed, 69 insertions, 93 deletions
diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c index 98df9bc7836a..d7e9d9c3042c 100644 --- a/drivers/net/wireless/spectrum_cs.c +++ b/drivers/net/wireless/spectrum_cs.c | |||
@@ -633,6 +633,70 @@ static void spectrum_cs_detach(struct pcmcia_device *link) | |||
633 | * device available to the system. | 633 | * device available to the system. |
634 | */ | 634 | */ |
635 | 635 | ||
636 | static int spectrum_cs_config_check(struct pcmcia_device *p_dev, | ||
637 | cistpl_cftable_entry_t *cfg, | ||
638 | cistpl_cftable_entry_t *dflt, | ||
639 | unsigned int vcc, | ||
640 | void *priv_data) | ||
641 | { | ||
642 | if (cfg->index == 0) | ||
643 | goto next_entry; | ||
644 | |||
645 | /* Use power settings for Vcc and Vpp if present */ | ||
646 | /* Note that the CIS values need to be rescaled */ | ||
647 | if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { | ||
648 | if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) { | ||
649 | DEBUG(2, "spectrum_cs_config: Vcc mismatch (vcc = %d, CIS = %d)\n", vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000); | ||
650 | if (!ignore_cis_vcc) | ||
651 | goto next_entry; | ||
652 | } | ||
653 | } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) { | ||
654 | if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000) { | ||
655 | DEBUG(2, "spectrum_cs_config: Vcc mismatch (vcc = %d, CIS = %d)\n", vcc, dflt->vcc.param[CISTPL_POWER_VNOM] / 10000); | ||
656 | if (!ignore_cis_vcc) | ||
657 | goto next_entry; | ||
658 | } | ||
659 | } | ||
660 | |||
661 | if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) | ||
662 | p_dev->conf.Vpp = | ||
663 | cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; | ||
664 | else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM)) | ||
665 | p_dev->conf.Vpp = | ||
666 | dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000; | ||
667 | |||
668 | /* Do we need to allocate an interrupt? */ | ||
669 | p_dev->conf.Attributes |= CONF_ENABLE_IRQ; | ||
670 | |||
671 | /* IO window settings */ | ||
672 | p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0; | ||
673 | if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { | ||
674 | cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; | ||
675 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; | ||
676 | if (!(io->flags & CISTPL_IO_8BIT)) | ||
677 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; | ||
678 | if (!(io->flags & CISTPL_IO_16BIT)) | ||
679 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | ||
680 | p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; | ||
681 | p_dev->io.BasePort1 = io->win[0].base; | ||
682 | p_dev->io.NumPorts1 = io->win[0].len; | ||
683 | if (io->nwin > 1) { | ||
684 | p_dev->io.Attributes2 = p_dev->io.Attributes1; | ||
685 | p_dev->io.BasePort2 = io->win[1].base; | ||
686 | p_dev->io.NumPorts2 = io->win[1].len; | ||
687 | } | ||
688 | |||
689 | /* This reserves IO space but doesn't actually enable it */ | ||
690 | if (pcmcia_request_io(p_dev, &p_dev->io) != 0) | ||
691 | goto next_entry; | ||
692 | } | ||
693 | return 0; | ||
694 | |||
695 | next_entry: | ||
696 | pcmcia_disable_device(p_dev); | ||
697 | return -ENODEV; | ||
698 | }; | ||
699 | |||
636 | static int | 700 | static int |
637 | spectrum_cs_config(struct pcmcia_device *link) | 701 | spectrum_cs_config(struct pcmcia_device *link) |
638 | { | 702 | { |
@@ -641,16 +705,8 @@ spectrum_cs_config(struct pcmcia_device *link) | |||
641 | struct orinoco_pccard *card = priv->card; | 705 | struct orinoco_pccard *card = priv->card; |
642 | hermes_t *hw = &priv->hw; | 706 | hermes_t *hw = &priv->hw; |
643 | int last_fn, last_ret; | 707 | int last_fn, last_ret; |
644 | u_char buf[64]; | ||
645 | config_info_t conf; | ||
646 | tuple_t tuple; | ||
647 | cisparse_t parse; | ||
648 | void __iomem *mem; | 708 | void __iomem *mem; |
649 | 709 | ||
650 | /* Look up the current Vcc */ | ||
651 | CS_CHECK(GetConfigurationInfo, | ||
652 | pcmcia_get_configuration_info(link, &conf)); | ||
653 | |||
654 | /* | 710 | /* |
655 | * In this loop, we scan the CIS for configuration table | 711 | * In this loop, we scan the CIS for configuration table |
656 | * entries, each of which describes a valid card | 712 | * entries, each of which describes a valid card |
@@ -665,94 +721,14 @@ spectrum_cs_config(struct pcmcia_device *link) | |||
665 | * and most client drivers will only use the CIS to fill in | 721 | * and most client drivers will only use the CIS to fill in |
666 | * implementation-defined details. | 722 | * implementation-defined details. |
667 | */ | 723 | */ |
668 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 724 | last_ret = pcmcia_loop_config(link, spectrum_cs_config_check, NULL); |
669 | tuple.Attributes = 0; | 725 | if (last_ret) { |
670 | tuple.TupleData = buf; | 726 | if (!ignore_cis_vcc) |
671 | tuple.TupleDataMax = sizeof(buf); | ||
672 | tuple.TupleOffset = 0; | ||
673 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | ||
674 | while (1) { | ||
675 | cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); | ||
676 | cistpl_cftable_entry_t dflt = { .index = 0 }; | ||
677 | |||
678 | if ( (pcmcia_get_tuple_data(link, &tuple) != 0) | ||
679 | || (pcmcia_parse_tuple(link, &tuple, &parse) != 0)) | ||
680 | goto next_entry; | ||
681 | |||
682 | if (cfg->flags & CISTPL_CFTABLE_DEFAULT) | ||
683 | dflt = *cfg; | ||
684 | if (cfg->index == 0) | ||
685 | goto next_entry; | ||
686 | link->conf.ConfigIndex = cfg->index; | ||
687 | |||
688 | /* Use power settings for Vcc and Vpp if present */ | ||
689 | /* Note that the CIS values need to be rescaled */ | ||
690 | if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { | ||
691 | if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) { | ||
692 | DEBUG(2, "spectrum_cs_config: Vcc mismatch (conf.Vcc = %d, CIS = %d)\n", conf.Vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000); | ||
693 | if (!ignore_cis_vcc) | ||
694 | goto next_entry; | ||
695 | } | ||
696 | } else if (dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) { | ||
697 | if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM] / 10000) { | ||
698 | DEBUG(2, "spectrum_cs_config: Vcc mismatch (conf.Vcc = %d, CIS = %d)\n", conf.Vcc, dflt.vcc.param[CISTPL_POWER_VNOM] / 10000); | ||
699 | if(!ignore_cis_vcc) | ||
700 | goto next_entry; | ||
701 | } | ||
702 | } | ||
703 | |||
704 | if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) | ||
705 | link->conf.Vpp = | ||
706 | cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; | ||
707 | else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) | ||
708 | link->conf.Vpp = | ||
709 | dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; | ||
710 | |||
711 | /* Do we need to allocate an interrupt? */ | ||
712 | link->conf.Attributes |= CONF_ENABLE_IRQ; | ||
713 | |||
714 | /* IO window settings */ | ||
715 | link->io.NumPorts1 = link->io.NumPorts2 = 0; | ||
716 | if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { | ||
717 | cistpl_io_t *io = | ||
718 | (cfg->io.nwin) ? &cfg->io : &dflt.io; | ||
719 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; | ||
720 | if (!(io->flags & CISTPL_IO_8BIT)) | ||
721 | link->io.Attributes1 = | ||
722 | IO_DATA_PATH_WIDTH_16; | ||
723 | if (!(io->flags & CISTPL_IO_16BIT)) | ||
724 | link->io.Attributes1 = | ||
725 | IO_DATA_PATH_WIDTH_8; | ||
726 | link->io.IOAddrLines = | ||
727 | io->flags & CISTPL_IO_LINES_MASK; | ||
728 | link->io.BasePort1 = io->win[0].base; | ||
729 | link->io.NumPorts1 = io->win[0].len; | ||
730 | if (io->nwin > 1) { | ||
731 | link->io.Attributes2 = | ||
732 | link->io.Attributes1; | ||
733 | link->io.BasePort2 = io->win[1].base; | ||
734 | link->io.NumPorts2 = io->win[1].len; | ||
735 | } | ||
736 | |||
737 | /* This reserves IO space but doesn't actually enable it */ | ||
738 | if (pcmcia_request_io(link, &link->io) != 0) | ||
739 | goto next_entry; | ||
740 | } | ||
741 | |||
742 | |||
743 | /* If we got this far, we're cool! */ | ||
744 | |||
745 | break; | ||
746 | |||
747 | next_entry: | ||
748 | pcmcia_disable_device(link); | ||
749 | last_ret = pcmcia_get_next_tuple(link, &tuple); | ||
750 | if (last_ret == CS_NO_MORE_ITEMS) { | ||
751 | printk(KERN_ERR PFX "GetNextTuple(): No matching " | 727 | printk(KERN_ERR PFX "GetNextTuple(): No matching " |
752 | "CIS configuration. Maybe you need the " | 728 | "CIS configuration. Maybe you need the " |
753 | "ignore_cis_vcc=1 parameter.\n"); | 729 | "ignore_cis_vcc=1 parameter.\n"); |
754 | goto cs_failed; | 730 | cs_error(link, RequestIO, last_ret); |
755 | } | 731 | goto failed; |
756 | } | 732 | } |
757 | 733 | ||
758 | /* | 734 | /* |