diff options
Diffstat (limited to 'drivers/bluetooth/bt3c_cs.c')
-rw-r--r-- | drivers/bluetooth/bt3c_cs.c | 125 |
1 files changed, 51 insertions, 74 deletions
diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c index 27058477cc8b..2cbe70b66470 100644 --- a/drivers/bluetooth/bt3c_cs.c +++ b/drivers/bluetooth/bt3c_cs.c | |||
@@ -678,101 +678,78 @@ static void bt3c_detach(struct pcmcia_device *link) | |||
678 | kfree(info); | 678 | kfree(info); |
679 | } | 679 | } |
680 | 680 | ||
681 | static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) | 681 | static int bt3c_check_config(struct pcmcia_device *p_dev, |
682 | cistpl_cftable_entry_t *cf, | ||
683 | cistpl_cftable_entry_t *dflt, | ||
684 | unsigned int vcc, | ||
685 | void *priv_data) | ||
682 | { | 686 | { |
683 | int i; | 687 | unsigned long try = (unsigned long) priv_data; |
684 | 688 | ||
685 | i = pcmcia_get_tuple_data(handle, tuple); | 689 | if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM)) |
686 | if (i != CS_SUCCESS) | 690 | p_dev->conf.Vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000; |
687 | return i; | 691 | if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) && |
688 | 692 | (cf->io.win[0].base != 0)) { | |
689 | return pcmcia_parse_tuple(handle, tuple, parse); | 693 | p_dev->io.BasePort1 = cf->io.win[0].base; |
690 | } | 694 | p_dev->io.IOAddrLines = (try == 0) ? 16 : |
691 | 695 | cf->io.flags & CISTPL_IO_LINES_MASK; | |
692 | static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) | 696 | if (!pcmcia_request_io(p_dev, &p_dev->io)) |
693 | { | 697 | return 0; |
694 | if (pcmcia_get_first_tuple(handle, tuple) != CS_SUCCESS) | 698 | } |
695 | return CS_NO_MORE_ITEMS; | 699 | return -ENODEV; |
696 | return get_tuple(handle, tuple, parse); | ||
697 | } | 700 | } |
698 | 701 | ||
699 | static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) | 702 | static int bt3c_check_config_notpicky(struct pcmcia_device *p_dev, |
703 | cistpl_cftable_entry_t *cf, | ||
704 | cistpl_cftable_entry_t *dflt, | ||
705 | unsigned int vcc, | ||
706 | void *priv_data) | ||
700 | { | 707 | { |
701 | if (pcmcia_get_next_tuple(handle, tuple) != CS_SUCCESS) | 708 | static unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 }; |
702 | return CS_NO_MORE_ITEMS; | 709 | int j; |
703 | return get_tuple(handle, tuple, parse); | 710 | |
711 | if ((cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) { | ||
712 | for (j = 0; j < 5; j++) { | ||
713 | p_dev->io.BasePort1 = base[j]; | ||
714 | p_dev->io.IOAddrLines = base[j] ? 16 : 3; | ||
715 | if (!pcmcia_request_io(p_dev, &p_dev->io)) | ||
716 | return 0; | ||
717 | } | ||
718 | } | ||
719 | return -ENODEV; | ||
704 | } | 720 | } |
705 | 721 | ||
706 | static int bt3c_config(struct pcmcia_device *link) | 722 | static int bt3c_config(struct pcmcia_device *link) |
707 | { | 723 | { |
708 | static unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 }; | ||
709 | bt3c_info_t *info = link->priv; | 724 | bt3c_info_t *info = link->priv; |
710 | tuple_t tuple; | 725 | int i; |
711 | u_short buf[256]; | 726 | unsigned long try; |
712 | cisparse_t parse; | 727 | |
713 | cistpl_cftable_entry_t *cf = &parse.cftable_entry; | 728 | /* First pass: look for a config entry that looks normal. |
714 | int i, j, try; | 729 | Two tries: without IO aliases, then with aliases */ |
715 | 730 | for (try = 0; try < 2; try++) | |
716 | /* First pass: look for a config entry that looks normal. */ | 731 | if (!pcmcia_loop_config(link, bt3c_check_config, (void *) try)) |
717 | tuple.TupleData = (cisdata_t *)buf; | 732 | goto found_port; |
718 | tuple.TupleOffset = 0; | ||
719 | tuple.TupleDataMax = 255; | ||
720 | tuple.Attributes = 0; | ||
721 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | ||
722 | /* Two tries: without IO aliases, then with aliases */ | ||
723 | for (try = 0; try < 2; try++) { | ||
724 | i = first_tuple(link, &tuple, &parse); | ||
725 | while (i != CS_NO_MORE_ITEMS) { | ||
726 | if (i != CS_SUCCESS) | ||
727 | goto next_entry; | ||
728 | if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM)) | ||
729 | link->conf.Vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000; | ||
730 | if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) && (cf->io.win[0].base != 0)) { | ||
731 | link->conf.ConfigIndex = cf->index; | ||
732 | link->io.BasePort1 = cf->io.win[0].base; | ||
733 | link->io.IOAddrLines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK; | ||
734 | i = pcmcia_request_io(link, &link->io); | ||
735 | if (i == CS_SUCCESS) | ||
736 | goto found_port; | ||
737 | } | ||
738 | next_entry: | ||
739 | i = next_tuple(link, &tuple, &parse); | ||
740 | } | ||
741 | } | ||
742 | 733 | ||
743 | /* Second pass: try to find an entry that isn't picky about | 734 | /* Second pass: try to find an entry that isn't picky about |
744 | its base address, then try to grab any standard serial port | 735 | its base address, then try to grab any standard serial port |
745 | address, and finally try to get any free port. */ | 736 | address, and finally try to get any free port. */ |
746 | i = first_tuple(link, &tuple, &parse); | 737 | if (!pcmcia_loop_config(link, bt3c_check_config_notpicky, NULL)) |
747 | while (i != CS_NO_MORE_ITEMS) { | 738 | goto found_port; |
748 | if ((i == CS_SUCCESS) && (cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) { | ||
749 | link->conf.ConfigIndex = cf->index; | ||
750 | for (j = 0; j < 5; j++) { | ||
751 | link->io.BasePort1 = base[j]; | ||
752 | link->io.IOAddrLines = base[j] ? 16 : 3; | ||
753 | i = pcmcia_request_io(link, &link->io); | ||
754 | if (i == CS_SUCCESS) | ||
755 | goto found_port; | ||
756 | } | ||
757 | } | ||
758 | i = next_tuple(link, &tuple, &parse); | ||
759 | } | ||
760 | 739 | ||
761 | found_port: | 740 | BT_ERR("No usable port range found"); |
762 | if (i != CS_SUCCESS) { | 741 | cs_error(link, RequestIO, -ENODEV); |
763 | BT_ERR("No usable port range found"); | 742 | goto failed; |
764 | cs_error(link, RequestIO, i); | ||
765 | goto failed; | ||
766 | } | ||
767 | 743 | ||
744 | found_port: | ||
768 | i = pcmcia_request_irq(link, &link->irq); | 745 | i = pcmcia_request_irq(link, &link->irq); |
769 | if (i != CS_SUCCESS) { | 746 | if (i != 0) { |
770 | cs_error(link, RequestIRQ, i); | 747 | cs_error(link, RequestIRQ, i); |
771 | link->irq.AssignedIRQ = 0; | 748 | link->irq.AssignedIRQ = 0; |
772 | } | 749 | } |
773 | 750 | ||
774 | i = pcmcia_request_configuration(link, &link->conf); | 751 | i = pcmcia_request_configuration(link, &link->conf); |
775 | if (i != CS_SUCCESS) { | 752 | if (i != 0) { |
776 | cs_error(link, RequestConfiguration, i); | 753 | cs_error(link, RequestConfiguration, i); |
777 | goto failed; | 754 | goto failed; |
778 | } | 755 | } |