diff options
Diffstat (limited to 'drivers/bluetooth/btuart_cs.c')
-rw-r--r-- | drivers/bluetooth/btuart_cs.c | 126 |
1 files changed, 51 insertions, 75 deletions
diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c index 68d1d258e6a4..8e556b7ff9f6 100644 --- a/drivers/bluetooth/btuart_cs.c +++ b/drivers/bluetooth/btuart_cs.c | |||
@@ -607,102 +607,78 @@ static void btuart_detach(struct pcmcia_device *link) | |||
607 | kfree(info); | 607 | kfree(info); |
608 | } | 608 | } |
609 | 609 | ||
610 | static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) | 610 | static int btuart_check_config(struct pcmcia_device *p_dev, |
611 | cistpl_cftable_entry_t *cf, | ||
612 | cistpl_cftable_entry_t *dflt, | ||
613 | unsigned int vcc, | ||
614 | void *priv_data) | ||
611 | { | 615 | { |
612 | int i; | 616 | int *try = priv_data; |
613 | 617 | ||
614 | i = pcmcia_get_tuple_data(handle, tuple); | 618 | if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM)) |
615 | if (i != CS_SUCCESS) | 619 | p_dev->conf.Vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000; |
616 | return i; | 620 | if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) && |
617 | 621 | (cf->io.win[0].base != 0)) { | |
618 | return pcmcia_parse_tuple(handle, tuple, parse); | 622 | p_dev->io.BasePort1 = cf->io.win[0].base; |
619 | } | 623 | p_dev->io.IOAddrLines = (*try == 0) ? 16 : |
620 | 624 | cf->io.flags & CISTPL_IO_LINES_MASK; | |
621 | static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) | 625 | if (!pcmcia_request_io(p_dev, &p_dev->io)) |
622 | { | 626 | return 0; |
623 | if (pcmcia_get_first_tuple(handle, tuple) != CS_SUCCESS) | 627 | } |
624 | return CS_NO_MORE_ITEMS; | 628 | return -ENODEV; |
625 | return get_tuple(handle, tuple, parse); | ||
626 | } | 629 | } |
627 | 630 | ||
628 | static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) | 631 | static int btuart_check_config_notpicky(struct pcmcia_device *p_dev, |
632 | cistpl_cftable_entry_t *cf, | ||
633 | cistpl_cftable_entry_t *dflt, | ||
634 | unsigned int vcc, | ||
635 | void *priv_data) | ||
629 | { | 636 | { |
630 | if (pcmcia_get_next_tuple(handle, tuple) != CS_SUCCESS) | 637 | static unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 }; |
631 | return CS_NO_MORE_ITEMS; | 638 | int j; |
632 | return get_tuple(handle, tuple, parse); | 639 | |
640 | if ((cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) { | ||
641 | for (j = 0; j < 5; j++) { | ||
642 | p_dev->io.BasePort1 = base[j]; | ||
643 | p_dev->io.IOAddrLines = base[j] ? 16 : 3; | ||
644 | if (!pcmcia_request_io(p_dev, &p_dev->io)) | ||
645 | return 0; | ||
646 | } | ||
647 | } | ||
648 | return -ENODEV; | ||
633 | } | 649 | } |
634 | 650 | ||
635 | static int btuart_config(struct pcmcia_device *link) | 651 | static int btuart_config(struct pcmcia_device *link) |
636 | { | 652 | { |
637 | static unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 }; | ||
638 | btuart_info_t *info = link->priv; | 653 | btuart_info_t *info = link->priv; |
639 | tuple_t tuple; | 654 | int i; |
640 | u_short buf[256]; | 655 | int try; |
641 | cisparse_t parse; | 656 | |
642 | cistpl_cftable_entry_t *cf = &parse.cftable_entry; | 657 | /* First pass: look for a config entry that looks normal. |
643 | int i, j, try; | 658 | Two tries: without IO aliases, then with aliases */ |
644 | 659 | for (try = 0; try < 2; try++) | |
645 | /* First pass: look for a config entry that looks normal. */ | 660 | if (!pcmcia_loop_config(link, btuart_check_config, &try)) |
646 | tuple.TupleData = (cisdata_t *) buf; | 661 | goto found_port; |
647 | tuple.TupleOffset = 0; | ||
648 | tuple.TupleDataMax = 255; | ||
649 | tuple.Attributes = 0; | ||
650 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | ||
651 | /* Two tries: without IO aliases, then with aliases */ | ||
652 | for (try = 0; try < 2; try++) { | ||
653 | i = first_tuple(link, &tuple, &parse); | ||
654 | while (i != CS_NO_MORE_ITEMS) { | ||
655 | if (i != CS_SUCCESS) | ||
656 | goto next_entry; | ||
657 | if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM)) | ||
658 | link->conf.Vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000; | ||
659 | if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) && (cf->io.win[0].base != 0)) { | ||
660 | link->conf.ConfigIndex = cf->index; | ||
661 | link->io.BasePort1 = cf->io.win[0].base; | ||
662 | link->io.IOAddrLines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK; | ||
663 | i = pcmcia_request_io(link, &link->io); | ||
664 | if (i == CS_SUCCESS) | ||
665 | goto found_port; | ||
666 | } | ||
667 | next_entry: | ||
668 | i = next_tuple(link, &tuple, &parse); | ||
669 | } | ||
670 | } | ||
671 | 662 | ||
672 | /* Second pass: try to find an entry that isn't picky about | 663 | /* Second pass: try to find an entry that isn't picky about |
673 | its base address, then try to grab any standard serial port | 664 | its base address, then try to grab any standard serial port |
674 | address, and finally try to get any free port. */ | 665 | address, and finally try to get any free port. */ |
675 | i = first_tuple(link, &tuple, &parse); | 666 | if (!pcmcia_loop_config(link, btuart_check_config_notpicky, NULL)) |
676 | while (i != CS_NO_MORE_ITEMS) { | 667 | goto found_port; |
677 | if ((i == CS_SUCCESS) && (cf->io.nwin > 0) | ||
678 | && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) { | ||
679 | link->conf.ConfigIndex = cf->index; | ||
680 | for (j = 0; j < 5; j++) { | ||
681 | link->io.BasePort1 = base[j]; | ||
682 | link->io.IOAddrLines = base[j] ? 16 : 3; | ||
683 | i = pcmcia_request_io(link, &link->io); | ||
684 | if (i == CS_SUCCESS) | ||
685 | goto found_port; | ||
686 | } | ||
687 | } | ||
688 | i = next_tuple(link, &tuple, &parse); | ||
689 | } | ||
690 | 668 | ||
691 | found_port: | 669 | BT_ERR("No usable port range found"); |
692 | if (i != CS_SUCCESS) { | 670 | cs_error(link, RequestIO, -ENODEV); |
693 | BT_ERR("No usable port range found"); | 671 | goto failed; |
694 | cs_error(link, RequestIO, i); | ||
695 | goto failed; | ||
696 | } | ||
697 | 672 | ||
673 | found_port: | ||
698 | i = pcmcia_request_irq(link, &link->irq); | 674 | i = pcmcia_request_irq(link, &link->irq); |
699 | if (i != CS_SUCCESS) { | 675 | if (i != 0) { |
700 | cs_error(link, RequestIRQ, i); | 676 | cs_error(link, RequestIRQ, i); |
701 | link->irq.AssignedIRQ = 0; | 677 | link->irq.AssignedIRQ = 0; |
702 | } | 678 | } |
703 | 679 | ||
704 | i = pcmcia_request_configuration(link, &link->conf); | 680 | i = pcmcia_request_configuration(link, &link->conf); |
705 | if (i != CS_SUCCESS) { | 681 | if (i != 0) { |
706 | cs_error(link, RequestConfiguration, i); | 682 | cs_error(link, RequestConfiguration, i); |
707 | goto failed; | 683 | goto failed; |
708 | } | 684 | } |