aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/bluetooth/btuart_cs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/bluetooth/btuart_cs.c')
-rw-r--r--drivers/bluetooth/btuart_cs.c126
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
610static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) 610static 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;
621static 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
628static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) 631static 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
635static int btuart_config(struct pcmcia_device *link) 651static 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 }
667next_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
691found_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
673found_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 }