aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/spectrum_cs.c
diff options
context:
space:
mode:
authorDominik Brodowski <linux@dominikbrodowski.net>2008-08-02 08:28:43 -0400
committerDominik Brodowski <linux@dominikbrodowski.net>2008-08-22 19:21:28 -0400
commitb54bf94bf91e4ca2a489eb02bca0424ddb55242a (patch)
tree4a5383d29173e24dd1fe71ce3ee4d010e60f391c /drivers/net/wireless/spectrum_cs.c
parent5fcd4da0090828bd34a1956cb322a483c6bf163c (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.c175
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
636struct spectrum_cs_config_data {
637 cistpl_cftable_entry_t dflt;
638 config_info_t conf;
639};
640
641static 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
703next_entry:
704 pcmcia_disable_device(p_dev);
705 return -ENODEV;
706};
707
636static int 708static int
637spectrum_cs_config(struct pcmcia_device *link) 709spectrum_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