diff options
author | Dominik Brodowski <linux@dominikbrodowski.net> | 2008-08-02 08:28:43 -0400 |
---|---|---|
committer | Dominik Brodowski <linux@dominikbrodowski.net> | 2008-08-22 19:21:28 -0400 |
commit | b54bf94bf91e4ca2a489eb02bca0424ddb55242a (patch) | |
tree | 4a5383d29173e24dd1fe71ce3ee4d010e60f391c /drivers/net/wireless/spectrum_cs.c | |
parent | 5fcd4da0090828bd34a1956cb322a483c6bf163c (diff) |
pcmcia: use pcmcia_loop_config in net pcmcia drivers
Use the config loop helper in (some) net pcmcia drivers.
CC: netdev@vger.kernel.org
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
Diffstat (limited to 'drivers/net/wireless/spectrum_cs.c')
-rw-r--r-- | drivers/net/wireless/spectrum_cs.c | 175 |
1 files changed, 85 insertions, 90 deletions
diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c index 98df9bc7836a..8e1951cfc152 100644 --- a/drivers/net/wireless/spectrum_cs.c +++ b/drivers/net/wireless/spectrum_cs.c | |||
@@ -633,23 +633,96 @@ 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 | struct spectrum_cs_config_data { | ||
637 | cistpl_cftable_entry_t dflt; | ||
638 | config_info_t conf; | ||
639 | }; | ||
640 | |||
641 | static int spectrum_cs_config_check(struct pcmcia_device *p_dev, | ||
642 | cistpl_cftable_entry_t *cfg, | ||
643 | void *priv_data) | ||
644 | { | ||
645 | struct spectrum_cs_config_data *cfg_mem = priv_data; | ||
646 | |||
647 | if (cfg->flags & CISTPL_CFTABLE_DEFAULT) | ||
648 | cfg_mem->dflt = *cfg; | ||
649 | if (cfg->index == 0) | ||
650 | goto next_entry; | ||
651 | p_dev->conf.ConfigIndex = cfg->index; | ||
652 | |||
653 | /* Use power settings for Vcc and Vpp if present */ | ||
654 | /* Note that the CIS values need to be rescaled */ | ||
655 | if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { | ||
656 | if (cfg_mem->conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) { | ||
657 | DEBUG(2, "spectrum_cs_config: Vcc mismatch (cfg_mem->conf.Vcc = %d, CIS = %d)\n", cfg_mem->conf.Vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000); | ||
658 | if (!ignore_cis_vcc) | ||
659 | goto next_entry; | ||
660 | } | ||
661 | } else if (cfg_mem->dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) { | ||
662 | if (cfg_mem->conf.Vcc != cfg_mem->dflt.vcc.param[CISTPL_POWER_VNOM] / 10000) { | ||
663 | DEBUG(2, "spectrum_cs_config: Vcc mismatch (cfg_mem->conf.Vcc = %d, CIS = %d)\n", cfg_mem->conf.Vcc, cfg_mem->dflt.vcc.param[CISTPL_POWER_VNOM] / 10000); | ||
664 | if (!ignore_cis_vcc) | ||
665 | goto next_entry; | ||
666 | } | ||
667 | } | ||
668 | |||
669 | if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) | ||
670 | p_dev->conf.Vpp = | ||
671 | cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; | ||
672 | else if (cfg_mem->dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) | ||
673 | p_dev->conf.Vpp = | ||
674 | cfg_mem->dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; | ||
675 | |||
676 | /* Do we need to allocate an interrupt? */ | ||
677 | p_dev->conf.Attributes |= CONF_ENABLE_IRQ; | ||
678 | |||
679 | /* IO window settings */ | ||
680 | p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0; | ||
681 | if ((cfg->io.nwin > 0) || (cfg_mem->dflt.io.nwin > 0)) { | ||
682 | cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &cfg_mem->dflt.io; | ||
683 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; | ||
684 | if (!(io->flags & CISTPL_IO_8BIT)) | ||
685 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; | ||
686 | if (!(io->flags & CISTPL_IO_16BIT)) | ||
687 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | ||
688 | p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; | ||
689 | p_dev->io.BasePort1 = io->win[0].base; | ||
690 | p_dev->io.NumPorts1 = io->win[0].len; | ||
691 | if (io->nwin > 1) { | ||
692 | p_dev->io.Attributes2 = p_dev->io.Attributes1; | ||
693 | p_dev->io.BasePort2 = io->win[1].base; | ||
694 | p_dev->io.NumPorts2 = io->win[1].len; | ||
695 | } | ||
696 | |||
697 | /* This reserves IO space but doesn't actually enable it */ | ||
698 | if (pcmcia_request_io(p_dev, &p_dev->io) != 0) | ||
699 | goto next_entry; | ||
700 | } | ||
701 | return 0; | ||
702 | |||
703 | next_entry: | ||
704 | pcmcia_disable_device(p_dev); | ||
705 | return -ENODEV; | ||
706 | }; | ||
707 | |||
636 | static int | 708 | static int |
637 | spectrum_cs_config(struct pcmcia_device *link) | 709 | spectrum_cs_config(struct pcmcia_device *link) |
638 | { | 710 | { |
711 | struct spectrum_cs_config_data *cfg_mem; | ||
639 | struct net_device *dev = link->priv; | 712 | struct net_device *dev = link->priv; |
640 | struct orinoco_private *priv = netdev_priv(dev); | 713 | struct orinoco_private *priv = netdev_priv(dev); |
641 | struct orinoco_pccard *card = priv->card; | 714 | struct orinoco_pccard *card = priv->card; |
642 | hermes_t *hw = &priv->hw; | 715 | hermes_t *hw = &priv->hw; |
643 | int last_fn, last_ret; | 716 | 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; | 717 | void __iomem *mem; |
649 | 718 | ||
719 | cfg_mem = kzalloc(sizeof(struct spectrum_cs_config_data), GFP_KERNEL); | ||
720 | if (!cfg_mem) | ||
721 | return -ENOMEM; | ||
722 | |||
650 | /* Look up the current Vcc */ | 723 | /* Look up the current Vcc */ |
651 | CS_CHECK(GetConfigurationInfo, | 724 | CS_CHECK(GetConfigurationInfo, |
652 | pcmcia_get_configuration_info(link, &conf)); | 725 | pcmcia_get_configuration_info(link, &cfg_mem->conf)); |
653 | 726 | ||
654 | /* | 727 | /* |
655 | * In this loop, we scan the CIS for configuration table | 728 | * In this loop, we scan the CIS for configuration table |
@@ -665,94 +738,14 @@ spectrum_cs_config(struct pcmcia_device *link) | |||
665 | * and most client drivers will only use the CIS to fill in | 738 | * and most client drivers will only use the CIS to fill in |
666 | * implementation-defined details. | 739 | * implementation-defined details. |
667 | */ | 740 | */ |
668 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 741 | last_ret = pcmcia_loop_config(link, spectrum_cs_config_check, cfg_mem); |
669 | tuple.Attributes = 0; | 742 | if (last_ret) { |
670 | tuple.TupleData = buf; | 743 | 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 " | 744 | printk(KERN_ERR PFX "GetNextTuple(): No matching " |
752 | "CIS configuration. Maybe you need the " | 745 | "CIS configuration. Maybe you need the " |
753 | "ignore_cis_vcc=1 parameter.\n"); | 746 | "ignore_cis_vcc=1 parameter.\n"); |
754 | goto cs_failed; | 747 | cs_error(link, RequestIO, last_ret); |
755 | } | 748 | goto failed; |
756 | } | 749 | } |
757 | 750 | ||
758 | /* | 751 | /* |
@@ -809,6 +802,7 @@ spectrum_cs_config(struct pcmcia_device *link) | |||
809 | link->irq.AssignedIRQ, link->io.BasePort1, | 802 | link->irq.AssignedIRQ, link->io.BasePort1, |
810 | link->io.BasePort1 + link->io.NumPorts1 - 1); | 803 | link->io.BasePort1 + link->io.NumPorts1 - 1); |
811 | 804 | ||
805 | kfree(cfg_mem); | ||
812 | return 0; | 806 | return 0; |
813 | 807 | ||
814 | cs_failed: | 808 | cs_failed: |
@@ -816,6 +810,7 @@ spectrum_cs_config(struct pcmcia_device *link) | |||
816 | 810 | ||
817 | failed: | 811 | failed: |
818 | spectrum_cs_release(link); | 812 | spectrum_cs_release(link); |
813 | kfree(cfg_mem); | ||
819 | return -ENODEV; | 814 | return -ENODEV; |
820 | } /* spectrum_cs_config */ | 815 | } /* spectrum_cs_config */ |
821 | 816 | ||