aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/hostap/hostap_cs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/hostap/hostap_cs.c')
-rw-r--r--drivers/net/wireless/hostap/hostap_cs.c227
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 3b4e55cf33c..3d914dde5de 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) \
533do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) 533do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
534 534
535#define CFG_CHECK2(fn, retf) \
536do { int _ret = (retf); \
537if (_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
539struct prism2_config_data {
540 cistpl_cftable_entry_t dflt;
541 config_info_t conf;
542};
543
544static 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
547static int prism2_config(struct pcmcia_device *link) 629static 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}