aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/spectrum_cs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/spectrum_cs.c')
-rw-r--r--drivers/net/wireless/spectrum_cs.c162
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
636static 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
695next_entry:
696 pcmcia_disable_device(p_dev);
697 return -ENODEV;
698};
699
636static int 700static int
637spectrum_cs_config(struct pcmcia_device *link) 701spectrum_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 /*