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/hostap | |
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/hostap')
-rw-r--r-- | drivers/net/wireless/hostap/hostap_cs.c | 227 |
1 files changed, 108 insertions, 119 deletions
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index 3b4e55cf33cd..3d914dde5de0 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c | |||
@@ -532,145 +532,134 @@ static void prism2_detach(struct pcmcia_device *link) | |||
532 | #define CS_CHECK(fn, ret) \ | 532 | #define CS_CHECK(fn, ret) \ |
533 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | 533 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) |
534 | 534 | ||
535 | #define CFG_CHECK2(fn, retf) \ | ||
536 | do { int _ret = (retf); \ | ||
537 | if (_ret != 0) { \ | ||
538 | PDEBUG(DEBUG_EXTRA, "CardServices(" #fn ") returned %d\n", _ret); \ | ||
539 | cs_error(link, fn, _ret); \ | ||
540 | goto next_entry; \ | ||
541 | } \ | ||
542 | } while (0) | ||
543 | |||
544 | 535 | ||
545 | /* run after a CARD_INSERTION event is received to configure the PCMCIA | 536 | /* run after a CARD_INSERTION event is received to configure the PCMCIA |
546 | * socket and make the device available to the system */ | 537 | * socket and make the device available to the system */ |
538 | |||
539 | struct prism2_config_data { | ||
540 | cistpl_cftable_entry_t dflt; | ||
541 | config_info_t conf; | ||
542 | }; | ||
543 | |||
544 | static int prism2_config_check(struct pcmcia_device *p_dev, | ||
545 | cistpl_cftable_entry_t *cfg, | ||
546 | void *priv_data) | ||
547 | { | ||
548 | struct prism2_config_data *cfg_mem = priv_data; | ||
549 | |||
550 | if (cfg->flags & CISTPL_CFTABLE_DEFAULT) | ||
551 | cfg_mem->dflt = *cfg; | ||
552 | if (cfg->index == 0) | ||
553 | return -ENODEV; | ||
554 | |||
555 | p_dev->conf.ConfigIndex = cfg->index; | ||
556 | PDEBUG(DEBUG_EXTRA, "Checking CFTABLE_ENTRY 0x%02X " | ||
557 | "(default 0x%02X)\n", cfg->index, cfg_mem->dflt.index); | ||
558 | |||
559 | /* Does this card need audio output? */ | ||
560 | if (cfg->flags & CISTPL_CFTABLE_AUDIO) { | ||
561 | p_dev->conf.Attributes |= CONF_ENABLE_SPKR; | ||
562 | p_dev->conf.Status = CCSR_AUDIO_ENA; | ||
563 | } | ||
564 | |||
565 | /* Use power settings for Vcc and Vpp if present */ | ||
566 | /* Note that the CIS values need to be rescaled */ | ||
567 | if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { | ||
568 | if (cfg_mem->conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / | ||
569 | 10000 && !ignore_cis_vcc) { | ||
570 | PDEBUG(DEBUG_EXTRA, " Vcc mismatch - skipping" | ||
571 | " this entry\n"); | ||
572 | return -ENODEV; | ||
573 | } | ||
574 | } else if (cfg_mem->dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) { | ||
575 | if (cfg_mem->conf.Vcc != cfg_mem->dflt.vcc.param[CISTPL_POWER_VNOM] / | ||
576 | 10000 && !ignore_cis_vcc) { | ||
577 | PDEBUG(DEBUG_EXTRA, " Vcc (default) mismatch " | ||
578 | "- skipping this entry\n"); | ||
579 | return -ENODEV; | ||
580 | } | ||
581 | } | ||
582 | |||
583 | if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) | ||
584 | p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; | ||
585 | else if (cfg_mem->dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) | ||
586 | p_dev->conf.Vpp = cfg_mem->dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; | ||
587 | |||
588 | /* Do we need to allocate an interrupt? */ | ||
589 | if (cfg->irq.IRQInfo1 || cfg_mem->dflt.irq.IRQInfo1) | ||
590 | p_dev->conf.Attributes |= CONF_ENABLE_IRQ; | ||
591 | else if (!(p_dev->conf.Attributes & CONF_ENABLE_IRQ)) { | ||
592 | /* At least Compaq WL200 does not have IRQInfo1 set, | ||
593 | * but it does not work without interrupts.. */ | ||
594 | printk(KERN_WARNING "Config has no IRQ info, but trying to " | ||
595 | "enable IRQ anyway..\n"); | ||
596 | p_dev->conf.Attributes |= CONF_ENABLE_IRQ; | ||
597 | } | ||
598 | |||
599 | /* IO window settings */ | ||
600 | PDEBUG(DEBUG_EXTRA, "IO window settings: cfg->io.nwin=%d " | ||
601 | "cfg_mem->dflt.io.nwin=%d\n", | ||
602 | cfg->io.nwin, cfg_mem->dflt.io.nwin); | ||
603 | p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0; | ||
604 | if ((cfg->io.nwin > 0) || (cfg_mem->dflt.io.nwin > 0)) { | ||
605 | cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &cfg_mem->dflt.io; | ||
606 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; | ||
607 | PDEBUG(DEBUG_EXTRA, "io->flags = 0x%04X, " | ||
608 | "io.base=0x%04x, len=%d\n", io->flags, | ||
609 | io->win[0].base, io->win[0].len); | ||
610 | if (!(io->flags & CISTPL_IO_8BIT)) | ||
611 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; | ||
612 | if (!(io->flags & CISTPL_IO_16BIT)) | ||
613 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | ||
614 | p_dev->io.IOAddrLines = io->flags & | ||
615 | CISTPL_IO_LINES_MASK; | ||
616 | p_dev->io.BasePort1 = io->win[0].base; | ||
617 | p_dev->io.NumPorts1 = io->win[0].len; | ||
618 | if (io->nwin > 1) { | ||
619 | p_dev->io.Attributes2 = p_dev->io.Attributes1; | ||
620 | p_dev->io.BasePort2 = io->win[1].base; | ||
621 | p_dev->io.NumPorts2 = io->win[1].len; | ||
622 | } | ||
623 | } | ||
624 | |||
625 | /* This reserves IO space but doesn't actually enable it */ | ||
626 | return pcmcia_request_io(p_dev, &p_dev->io); | ||
627 | } | ||
628 | |||
547 | static int prism2_config(struct pcmcia_device *link) | 629 | static int prism2_config(struct pcmcia_device *link) |
548 | { | 630 | { |
549 | struct net_device *dev; | 631 | struct net_device *dev; |
550 | struct hostap_interface *iface; | 632 | struct hostap_interface *iface; |
633 | struct prism2_config_data *cfg_mem; | ||
551 | local_info_t *local; | 634 | local_info_t *local; |
552 | int ret = 1; | 635 | int ret = 1; |
553 | tuple_t tuple; | ||
554 | cisparse_t *parse; | ||
555 | int last_fn, last_ret; | 636 | int last_fn, last_ret; |
556 | u_char buf[64]; | ||
557 | config_info_t conf; | ||
558 | cistpl_cftable_entry_t dflt = { 0 }; | ||
559 | struct hostap_cs_priv *hw_priv; | 637 | struct hostap_cs_priv *hw_priv; |
560 | 638 | ||
561 | PDEBUG(DEBUG_FLOW, "prism2_config()\n"); | 639 | PDEBUG(DEBUG_FLOW, "prism2_config()\n"); |
562 | 640 | ||
563 | parse = kmalloc(sizeof(cisparse_t), GFP_KERNEL); | 641 | cfg_mem = kzalloc(sizeof(struct prism2_config_data), GFP_KERNEL); |
642 | if (!cfg_mem) | ||
643 | return -ENOMEM; | ||
644 | |||
564 | hw_priv = kzalloc(sizeof(*hw_priv), GFP_KERNEL); | 645 | hw_priv = kzalloc(sizeof(*hw_priv), GFP_KERNEL); |
565 | if (parse == NULL || hw_priv == NULL) { | 646 | if (hw_priv == NULL) { |
566 | ret = -ENOMEM; | 647 | ret = -ENOMEM; |
567 | goto failed; | 648 | goto failed; |
568 | } | 649 | } |
569 | 650 | ||
570 | tuple.Attributes = 0; | ||
571 | tuple.TupleData = buf; | ||
572 | tuple.TupleDataMax = sizeof(buf); | ||
573 | tuple.TupleOffset = 0; | ||
574 | |||
575 | CS_CHECK(GetConfigurationInfo, | 651 | CS_CHECK(GetConfigurationInfo, |
576 | pcmcia_get_configuration_info(link, &conf)); | 652 | pcmcia_get_configuration_info(link, &cfg_mem->conf)); |
577 | 653 | ||
578 | /* Look for an appropriate configuration table entry in the CIS */ | 654 | /* Look for an appropriate configuration table entry in the CIS */ |
579 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 655 | last_ret = pcmcia_loop_config(link, prism2_config_check, cfg_mem); |
580 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | 656 | if (last_ret) { |
581 | for (;;) { | 657 | if (!ignore_cis_vcc) |
582 | cistpl_cftable_entry_t *cfg = &(parse->cftable_entry); | 658 | printk(KERN_ERR "GetNextTuple(): No matching " |
583 | CFG_CHECK2(GetTupleData, | 659 | "CIS configuration. Maybe you need the " |
584 | pcmcia_get_tuple_data(link, &tuple)); | 660 | "ignore_cis_vcc=1 parameter.\n"); |
585 | CFG_CHECK2(ParseTuple, | 661 | cs_error(link, RequestIO, last_ret); |
586 | pcmcia_parse_tuple(link, &tuple, parse)); | 662 | goto failed; |
587 | |||
588 | if (cfg->flags & CISTPL_CFTABLE_DEFAULT) | ||
589 | dflt = *cfg; | ||
590 | if (cfg->index == 0) | ||
591 | goto next_entry; | ||
592 | link->conf.ConfigIndex = cfg->index; | ||
593 | PDEBUG(DEBUG_EXTRA, "Checking CFTABLE_ENTRY 0x%02X " | ||
594 | "(default 0x%02X)\n", cfg->index, dflt.index); | ||
595 | |||
596 | /* Does this card need audio output? */ | ||
597 | if (cfg->flags & CISTPL_CFTABLE_AUDIO) { | ||
598 | link->conf.Attributes |= CONF_ENABLE_SPKR; | ||
599 | link->conf.Status = CCSR_AUDIO_ENA; | ||
600 | } | ||
601 | |||
602 | /* Use power settings for Vcc and Vpp if present */ | ||
603 | /* Note that the CIS values need to be rescaled */ | ||
604 | if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { | ||
605 | if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / | ||
606 | 10000 && !ignore_cis_vcc) { | ||
607 | PDEBUG(DEBUG_EXTRA, " Vcc mismatch - skipping" | ||
608 | " this entry\n"); | ||
609 | goto next_entry; | ||
610 | } | ||
611 | } else if (dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) { | ||
612 | if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM] / | ||
613 | 10000 && !ignore_cis_vcc) { | ||
614 | PDEBUG(DEBUG_EXTRA, " Vcc (default) mismatch " | ||
615 | "- skipping this entry\n"); | ||
616 | goto next_entry; | ||
617 | } | ||
618 | } | ||
619 | |||
620 | if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) | ||
621 | link->conf.Vpp = | ||
622 | cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; | ||
623 | else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) | ||
624 | link->conf.Vpp = | ||
625 | dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; | ||
626 | |||
627 | /* Do we need to allocate an interrupt? */ | ||
628 | if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) | ||
629 | link->conf.Attributes |= CONF_ENABLE_IRQ; | ||
630 | else if (!(link->conf.Attributes & CONF_ENABLE_IRQ)) { | ||
631 | /* At least Compaq WL200 does not have IRQInfo1 set, | ||
632 | * but it does not work without interrupts.. */ | ||
633 | printk("Config has no IRQ info, but trying to enable " | ||
634 | "IRQ anyway..\n"); | ||
635 | link->conf.Attributes |= CONF_ENABLE_IRQ; | ||
636 | } | ||
637 | |||
638 | /* IO window settings */ | ||
639 | PDEBUG(DEBUG_EXTRA, "IO window settings: cfg->io.nwin=%d " | ||
640 | "dflt.io.nwin=%d\n", | ||
641 | cfg->io.nwin, dflt.io.nwin); | ||
642 | link->io.NumPorts1 = link->io.NumPorts2 = 0; | ||
643 | if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { | ||
644 | cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; | ||
645 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; | ||
646 | PDEBUG(DEBUG_EXTRA, "io->flags = 0x%04X, " | ||
647 | "io.base=0x%04x, len=%d\n", io->flags, | ||
648 | io->win[0].base, io->win[0].len); | ||
649 | if (!(io->flags & CISTPL_IO_8BIT)) | ||
650 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; | ||
651 | if (!(io->flags & CISTPL_IO_16BIT)) | ||
652 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | ||
653 | link->io.IOAddrLines = io->flags & | ||
654 | CISTPL_IO_LINES_MASK; | ||
655 | link->io.BasePort1 = io->win[0].base; | ||
656 | link->io.NumPorts1 = io->win[0].len; | ||
657 | if (io->nwin > 1) { | ||
658 | link->io.Attributes2 = link->io.Attributes1; | ||
659 | link->io.BasePort2 = io->win[1].base; | ||
660 | link->io.NumPorts2 = io->win[1].len; | ||
661 | } | ||
662 | } | ||
663 | |||
664 | /* This reserves IO space but doesn't actually enable it */ | ||
665 | CFG_CHECK2(RequestIO, | ||
666 | pcmcia_request_io(link, &link->io)); | ||
667 | |||
668 | /* This configuration table entry is OK */ | ||
669 | break; | ||
670 | |||
671 | next_entry: | ||
672 | CS_CHECK(GetNextTuple, | ||
673 | pcmcia_get_next_tuple(link, &tuple)); | ||
674 | } | 663 | } |
675 | 664 | ||
676 | /* Need to allocate net_device before requesting IRQ handler */ | 665 | /* Need to allocate net_device before requesting IRQ handler */ |
@@ -738,15 +727,15 @@ static int prism2_config(struct pcmcia_device *link) | |||
738 | if (ret == 0 && local->ddev) | 727 | if (ret == 0 && local->ddev) |
739 | strcpy(hw_priv->node.dev_name, local->ddev->name); | 728 | strcpy(hw_priv->node.dev_name, local->ddev->name); |
740 | } | 729 | } |
741 | kfree(parse); | 730 | kfree(cfg_mem); |
742 | return ret; | 731 | return ret; |
743 | 732 | ||
744 | cs_failed: | 733 | cs_failed: |
745 | cs_error(link, last_fn, last_ret); | 734 | cs_error(link, last_fn, last_ret); |
746 | 735 | ||
747 | failed: | 736 | failed: |
748 | kfree(parse); | ||
749 | kfree(hw_priv); | 737 | kfree(hw_priv); |
738 | kfree(cfg_mem); | ||
750 | prism2_release((u_long)link); | 739 | prism2_release((u_long)link); |
751 | return ret; | 740 | return ret; |
752 | } | 741 | } |