diff options
-rw-r--r-- | drivers/serial/serial_cs.c | 87 |
1 files changed, 23 insertions, 64 deletions
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index ff4617e21426..7bf02cf3123f 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c | |||
@@ -426,21 +426,6 @@ static int setup_serial(struct pcmcia_device *handle, struct serial_info * info, | |||
426 | 426 | ||
427 | /*====================================================================*/ | 427 | /*====================================================================*/ |
428 | 428 | ||
429 | static int | ||
430 | first_tuple(struct pcmcia_device *handle, tuple_t * tuple, cisparse_t * parse) | ||
431 | { | ||
432 | int i; | ||
433 | i = pcmcia_get_first_tuple(handle, tuple); | ||
434 | if (i != 0) | ||
435 | return i; | ||
436 | i = pcmcia_get_tuple_data(handle, tuple); | ||
437 | if (i != 0) | ||
438 | return i; | ||
439 | return pcmcia_parse_tuple(tuple, parse); | ||
440 | } | ||
441 | |||
442 | /*====================================================================*/ | ||
443 | |||
444 | static int simple_config_check(struct pcmcia_device *p_dev, | 429 | static int simple_config_check(struct pcmcia_device *p_dev, |
445 | cistpl_cftable_entry_t *cf, | 430 | cistpl_cftable_entry_t *cf, |
446 | cistpl_cftable_entry_t *dflt, | 431 | cistpl_cftable_entry_t *dflt, |
@@ -665,6 +650,25 @@ static int multi_config(struct pcmcia_device *link) | |||
665 | return 0; | 650 | return 0; |
666 | } | 651 | } |
667 | 652 | ||
653 | static int serial_check_for_multi(struct pcmcia_device *p_dev, | ||
654 | cistpl_cftable_entry_t *cf, | ||
655 | cistpl_cftable_entry_t *dflt, | ||
656 | unsigned int vcc, | ||
657 | void *priv_data) | ||
658 | { | ||
659 | struct serial_info *info = p_dev->priv; | ||
660 | |||
661 | if ((cf->io.nwin == 1) && (cf->io.win[0].len % 8 == 0)) | ||
662 | info->multi = cf->io.win[0].len >> 3; | ||
663 | |||
664 | if ((cf->io.nwin == 2) && (cf->io.win[0].len == 8) && | ||
665 | (cf->io.win[1].len == 8)) | ||
666 | info->multi = 2; | ||
667 | |||
668 | return 0; /* break */ | ||
669 | } | ||
670 | |||
671 | |||
668 | /*====================================================================== | 672 | /*====================================================================== |
669 | 673 | ||
670 | serial_config() is scheduled to run after a CARD_INSERTION event | 674 | serial_config() is scheduled to run after a CARD_INSERTION event |
@@ -676,46 +680,14 @@ static int multi_config(struct pcmcia_device *link) | |||
676 | static int serial_config(struct pcmcia_device * link) | 680 | static int serial_config(struct pcmcia_device * link) |
677 | { | 681 | { |
678 | struct serial_info *info = link->priv; | 682 | struct serial_info *info = link->priv; |
679 | struct serial_cfg_mem *cfg_mem; | 683 | int i; |
680 | tuple_t *tuple; | ||
681 | u_char *buf; | ||
682 | cisparse_t *parse; | ||
683 | cistpl_cftable_entry_t *cf; | ||
684 | int i, last_ret, last_fn; | ||
685 | 684 | ||
686 | DEBUG(0, "serial_config(0x%p)\n", link); | 685 | DEBUG(0, "serial_config(0x%p)\n", link); |
687 | 686 | ||
688 | cfg_mem = kmalloc(sizeof(struct serial_cfg_mem), GFP_KERNEL); | ||
689 | if (!cfg_mem) | ||
690 | goto failed; | ||
691 | |||
692 | tuple = &cfg_mem->tuple; | ||
693 | parse = &cfg_mem->parse; | ||
694 | cf = &parse->cftable_entry; | ||
695 | buf = cfg_mem->buf; | ||
696 | |||
697 | tuple->TupleData = (cisdata_t *) buf; | ||
698 | tuple->TupleOffset = 0; | ||
699 | tuple->TupleDataMax = 255; | ||
700 | tuple->Attributes = 0; | ||
701 | |||
702 | /* Get configuration register information */ | ||
703 | tuple->DesiredTuple = CISTPL_CONFIG; | ||
704 | last_ret = first_tuple(link, tuple, parse); | ||
705 | if (last_ret != 0) { | ||
706 | last_fn = ParseTuple; | ||
707 | goto cs_failed; | ||
708 | } | ||
709 | link->conf.ConfigBase = parse->config.base; | ||
710 | link->conf.Present = parse->config.rmask[0]; | ||
711 | |||
712 | /* Is this a compliant multifunction card? */ | 687 | /* Is this a compliant multifunction card? */ |
713 | tuple->DesiredTuple = CISTPL_LONGLINK_MFC; | 688 | info->multi = (link->socket->functions > 1); |
714 | tuple->Attributes = TUPLE_RETURN_COMMON | TUPLE_RETURN_LINK; | ||
715 | info->multi = (first_tuple(link, tuple, parse) == 0); | ||
716 | 689 | ||
717 | /* Is this a multiport card? */ | 690 | /* Is this a multiport card? */ |
718 | tuple->DesiredTuple = CISTPL_MANFID; | ||
719 | info->manfid = link->manf_id; | 691 | info->manfid = link->manf_id; |
720 | info->prodid = link->card_id; | 692 | info->prodid = link->card_id; |
721 | 693 | ||
@@ -730,20 +702,11 @@ static int serial_config(struct pcmcia_device * link) | |||
730 | 702 | ||
731 | /* Another check for dual-serial cards: look for either serial or | 703 | /* Another check for dual-serial cards: look for either serial or |
732 | multifunction cards that ask for appropriate IO port ranges */ | 704 | multifunction cards that ask for appropriate IO port ranges */ |
733 | tuple->DesiredTuple = CISTPL_FUNCID; | ||
734 | if ((info->multi == 0) && | 705 | if ((info->multi == 0) && |
735 | (link->has_func_id) && | 706 | (link->has_func_id) && |
736 | ((link->func_id == CISTPL_FUNCID_MULTI) || | 707 | ((link->func_id == CISTPL_FUNCID_MULTI) || |
737 | (link->func_id == CISTPL_FUNCID_SERIAL))) { | 708 | (link->func_id == CISTPL_FUNCID_SERIAL))) |
738 | tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY; | 709 | pcmcia_loop_config(link, serial_check_for_multi, info); |
739 | if (first_tuple(link, tuple, parse) == 0) { | ||
740 | if ((cf->io.nwin == 1) && (cf->io.win[0].len % 8 == 0)) | ||
741 | info->multi = cf->io.win[0].len >> 3; | ||
742 | if ((cf->io.nwin == 2) && (cf->io.win[0].len == 8) && | ||
743 | (cf->io.win[1].len == 8)) | ||
744 | info->multi = 2; | ||
745 | } | ||
746 | } | ||
747 | 710 | ||
748 | /* | 711 | /* |
749 | * Apply any multi-port quirk. | 712 | * Apply any multi-port quirk. |
@@ -768,14 +731,10 @@ static int serial_config(struct pcmcia_device * link) | |||
768 | goto failed; | 731 | goto failed; |
769 | 732 | ||
770 | link->dev_node = &info->node[0]; | 733 | link->dev_node = &info->node[0]; |
771 | kfree(cfg_mem); | ||
772 | return 0; | 734 | return 0; |
773 | 735 | ||
774 | cs_failed: | ||
775 | cs_error(link, last_fn, last_ret); | ||
776 | failed: | 736 | failed: |
777 | serial_remove(link); | 737 | serial_remove(link); |
778 | kfree(cfg_mem); | ||
779 | return -ENODEV; | 738 | return -ENODEV; |
780 | } | 739 | } |
781 | 740 | ||