aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/serial/serial_cs.c87
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
429static int
430first_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
444static int simple_config_check(struct pcmcia_device *p_dev, 429static 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
653static 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)
676static int serial_config(struct pcmcia_device * link) 680static 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
774cs_failed:
775 cs_error(link, last_fn, last_ret);
776failed: 736failed:
777 serial_remove(link); 737 serial_remove(link);
778 kfree(cfg_mem);
779 return -ENODEV; 738 return -ENODEV;
780} 739}
781 740