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.c121
1 files changed, 48 insertions, 73 deletions
diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c
index 68d1d258e6a4..39cca285152d 100644
--- a/drivers/bluetooth/btuart_cs.c
+++ b/drivers/bluetooth/btuart_cs.c
@@ -607,94 +607,69 @@ 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 void *priv_data)
611{ 613{
612 int i; 614 unsigned long try = (unsigned long) priv_data;
613 615
614 i = pcmcia_get_tuple_data(handle, tuple); 616 if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
615 if (i != CS_SUCCESS) 617 p_dev->conf.Vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
616 return i; 618 if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) &&
617 619 (cf->io.win[0].base != 0)) {
618 return pcmcia_parse_tuple(handle, tuple, parse); 620 p_dev->conf.ConfigIndex = cf->index;
619} 621 p_dev->io.BasePort1 = cf->io.win[0].base;
620 622 p_dev->io.IOAddrLines = (try == 0) ? 16 :
621static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) 623 cf->io.flags & CISTPL_IO_LINES_MASK;
622{ 624 if (!pcmcia_request_io(p_dev, &p_dev->io))
623 if (pcmcia_get_first_tuple(handle, tuple) != CS_SUCCESS) 625 return 0;
624 return CS_NO_MORE_ITEMS; 626 }
625 return get_tuple(handle, tuple, parse); 627 return -ENODEV;
626} 628}
627 629
628static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) 630static int btuart_check_config_notpicky(struct pcmcia_device *p_dev,
631 cistpl_cftable_entry_t *cf,
632 void *priv_data)
629{ 633{
630 if (pcmcia_get_next_tuple(handle, tuple) != CS_SUCCESS) 634 static unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
631 return CS_NO_MORE_ITEMS; 635 int j;
632 return get_tuple(handle, tuple, parse); 636
637 if ((cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
638 p_dev->conf.ConfigIndex = cf->index;
639 for (j = 0; j < 5; j++) {
640 p_dev->io.BasePort1 = base[j];
641 p_dev->io.IOAddrLines = base[j] ? 16 : 3;
642 if (!pcmcia_request_io(p_dev, &p_dev->io))
643 return 0;
644 }
645 }
646 return -ENODEV;
633} 647}
634 648
635static int btuart_config(struct pcmcia_device *link) 649static int btuart_config(struct pcmcia_device *link)
636{ 650{
637 static unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
638 btuart_info_t *info = link->priv; 651 btuart_info_t *info = link->priv;
639 tuple_t tuple; 652 int i;
640 u_short buf[256]; 653 unsigned long try;
641 cisparse_t parse; 654
642 cistpl_cftable_entry_t *cf = &parse.cftable_entry; 655 /* First pass: look for a config entry that looks normal.
643 int i, j, try; 656 Two tries: without IO aliases, then with aliases */
644 657 for (try = 0; try < 2; try++)
645 /* First pass: look for a config entry that looks normal. */ 658 if (!pcmcia_loop_config(link, btuart_check_config,
646 tuple.TupleData = (cisdata_t *) buf; 659 (void *) try))
647 tuple.TupleOffset = 0; 660 goto found_port;
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 661
672 /* Second pass: try to find an entry that isn't picky about 662 /* Second pass: try to find an entry that isn't picky about
673 its base address, then try to grab any standard serial port 663 its base address, then try to grab any standard serial port
674 address, and finally try to get any free port. */ 664 address, and finally try to get any free port. */
675 i = first_tuple(link, &tuple, &parse); 665 if (!pcmcia_loop_config(link, btuart_check_config_notpicky, NULL))
676 while (i != CS_NO_MORE_ITEMS) { 666 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 667
691found_port: 668 BT_ERR("No usable port range found");
692 if (i != CS_SUCCESS) { 669 cs_error(link, RequestIO, -ENODEV);
693 BT_ERR("No usable port range found"); 670 goto failed;
694 cs_error(link, RequestIO, i);
695 goto failed;
696 }
697 671
672found_port:
698 i = pcmcia_request_irq(link, &link->irq); 673 i = pcmcia_request_irq(link, &link->irq);
699 if (i != CS_SUCCESS) { 674 if (i != CS_SUCCESS) {
700 cs_error(link, RequestIRQ, i); 675 cs_error(link, RequestIRQ, i);