aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/serial/serial_cs.c
diff options
context:
space:
mode:
authorDominik Brodowski <linux@dominikbrodowski.net>2008-07-29 02:38:55 -0400
committerDominik Brodowski <linux@dominikbrodowski.net>2008-08-22 19:21:29 -0400
commit84e2d34004dcd0c90d1af43a143511b334f11a4d (patch)
tree1872000f78edc7368d34ebf1211fd8c56d395143 /drivers/serial/serial_cs.c
parentb54bf94bf91e4ca2a489eb02bca0424ddb55242a (diff)
pcmcia: use pcmcia_loop_config in misc pcmcia drivers
Use the config loop helper in misc pcmcia drivers. CC: Harald Welte <laforge@gnumonks.org> CC: <linux-parport@lists.infradead.org> CC: Russell King <rmk+kernel@arm.linux.org.uk> CC: Ed Okerson <eokerson@quicknet.net> CC: linux-serial@vger.kernel.org CC: boti@rocketmail.com CC: linux-usb@vger.kernel.org Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
Diffstat (limited to 'drivers/serial/serial_cs.c')
-rw-r--r--drivers/serial/serial_cs.c262
1 files changed, 107 insertions, 155 deletions
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index 164d2a42eb59..ac60cd288418 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -439,43 +439,55 @@ first_tuple(struct pcmcia_device *handle, tuple_t * tuple, cisparse_t * parse)
439 return pcmcia_parse_tuple(handle, tuple, parse); 439 return pcmcia_parse_tuple(handle, tuple, parse);
440} 440}
441 441
442static int 442/*====================================================================*/
443next_tuple(struct pcmcia_device *handle, tuple_t * tuple, cisparse_t * parse) 443
444static int simple_config_check(struct pcmcia_device *p_dev,
445 cistpl_cftable_entry_t *cf,
446 void *priv_data)
444{ 447{
445 int i; 448 static const int size_table[2] = { 8, 16 };
446 i = pcmcia_get_next_tuple(handle, tuple); 449 int *try = priv_data;
447 if (i != CS_SUCCESS) 450
448 return CS_NO_MORE_ITEMS; 451 if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
449 i = pcmcia_get_tuple_data(handle, tuple); 452 p_dev->conf.Vpp =
450 if (i != CS_SUCCESS) 453 cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
451 return i; 454
452 return pcmcia_parse_tuple(handle, tuple, parse); 455 if ((cf->io.nwin > 0) && (cf->io.win[0].len == size_table[(*try >> 1)])
456 && (cf->io.win[0].base != 0)) {
457 p_dev->conf.ConfigIndex = cf->index;
458 p_dev->io.BasePort1 = cf->io.win[0].base;
459 p_dev->io.IOAddrLines = ((*try & 0x1) == 0) ?
460 16 : cf->io.flags & CISTPL_IO_LINES_MASK;
461 if (!pcmcia_request_io(p_dev, &p_dev->io))
462 return 0;
463 }
464 return -EINVAL;
453} 465}
454 466
455/*====================================================================*/ 467static int simple_config_check_notpicky(struct pcmcia_device *p_dev,
468 cistpl_cftable_entry_t *cf,
469 void *priv_data)
470{
471 static const unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
472 int j;
473
474 if ((cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
475 p_dev->conf.ConfigIndex = cf->index;
476 for (j = 0; j < 5; j++) {
477 p_dev->io.BasePort1 = base[j];
478 p_dev->io.IOAddrLines = base[j] ? 16 : 3;
479 if (!pcmcia_request_io(p_dev, &p_dev->io))
480 return 0;
481 }
482 }
483 return -ENODEV;
484}
456 485
457static int simple_config(struct pcmcia_device *link) 486static int simple_config(struct pcmcia_device *link)
458{ 487{
459 static const unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
460 static const int size_table[2] = { 8, 16 };
461 struct serial_info *info = link->priv; 488 struct serial_info *info = link->priv;
462 struct serial_cfg_mem *cfg_mem;
463 tuple_t *tuple;
464 u_char *buf;
465 cisparse_t *parse;
466 cistpl_cftable_entry_t *cf;
467 config_info_t config; 489 config_info_t config;
468 int i, j, try; 490 int i, try;
469 int s;
470
471 cfg_mem = kmalloc(sizeof(struct serial_cfg_mem), GFP_KERNEL);
472 if (!cfg_mem)
473 return -1;
474
475 tuple = &cfg_mem->tuple;
476 parse = &cfg_mem->parse;
477 cf = &parse->cftable_entry;
478 buf = cfg_mem->buf;
479 491
480 /* If the card is already configured, look up the port and irq */ 492 /* If the card is already configured, look up the port and irq */
481 i = pcmcia_get_configuration_info(link, &config); 493 i = pcmcia_get_configuration_info(link, &config);
@@ -490,70 +502,28 @@ static int simple_config(struct pcmcia_device *link)
490 info->slave = 1; 502 info->slave = 1;
491 } 503 }
492 if (info->slave) { 504 if (info->slave) {
493 kfree(cfg_mem);
494 return setup_serial(link, info, port, config.AssignedIRQ); 505 return setup_serial(link, info, port, config.AssignedIRQ);
495 } 506 }
496 } 507 }
497 508
498 /* First pass: look for a config entry that looks normal. */ 509 /* First pass: look for a config entry that looks normal.
499 tuple->TupleData = (cisdata_t *) buf; 510 * Two tries: without IO aliases, then with aliases */
500 tuple->TupleOffset = 0; 511 for (try = 0; try < 4; try++)
501 tuple->TupleDataMax = 255; 512 if (!pcmcia_loop_config(link, simple_config_check, &try))
502 tuple->Attributes = 0; 513 goto found_port;
503 tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY; 514
504 /* Two tries: without IO aliases, then with aliases */
505 for (s = 0; s < 2; s++) {
506 for (try = 0; try < 2; try++) {
507 i = first_tuple(link, tuple, parse);
508 while (i != CS_NO_MORE_ITEMS) {
509 if (i != CS_SUCCESS)
510 goto next_entry;
511 if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
512 link->conf.Vpp =
513 cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
514 if ((cf->io.nwin > 0) && (cf->io.win[0].len == size_table[s]) &&
515 (cf->io.win[0].base != 0)) {
516 link->conf.ConfigIndex = cf->index;
517 link->io.BasePort1 = cf->io.win[0].base;
518 link->io.IOAddrLines = (try == 0) ?
519 16 : cf->io.flags & CISTPL_IO_LINES_MASK;
520 i = pcmcia_request_io(link, &link->io);
521 if (i == CS_SUCCESS)
522 goto found_port;
523 }
524next_entry:
525 i = next_tuple(link, tuple, parse);
526 }
527 }
528 }
529 /* Second pass: try to find an entry that isn't picky about 515 /* Second pass: try to find an entry that isn't picky about
530 its base address, then try to grab any standard serial port 516 its base address, then try to grab any standard serial port
531 address, and finally try to get any free port. */ 517 address, and finally try to get any free port. */
532 i = first_tuple(link, tuple, parse); 518 if (!pcmcia_loop_config(link, simple_config_check_notpicky, NULL))
533 while (i != CS_NO_MORE_ITEMS) { 519 goto found_port;
534 if ((i == CS_SUCCESS) && (cf->io.nwin > 0) &&
535 ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
536 link->conf.ConfigIndex = cf->index;
537 for (j = 0; j < 5; j++) {
538 link->io.BasePort1 = base[j];
539 link->io.IOAddrLines = base[j] ? 16 : 3;
540 i = pcmcia_request_io(link, &link->io);
541 if (i == CS_SUCCESS)
542 goto found_port;
543 }
544 }
545 i = next_tuple(link, tuple, parse);
546 }
547 520
548 found_port: 521 printk(KERN_NOTICE
549 if (i != CS_SUCCESS) { 522 "serial_cs: no usable port range found, giving up\n");
550 printk(KERN_NOTICE 523 cs_error(link, RequestIO, i);
551 "serial_cs: no usable port range found, giving up\n"); 524 return -1;
552 cs_error(link, RequestIO, i);
553 kfree(cfg_mem);
554 return -1;
555 }
556 525
526found_port:
557 i = pcmcia_request_irq(link, &link->irq); 527 i = pcmcia_request_irq(link, &link->irq);
558 if (i != CS_SUCCESS) { 528 if (i != CS_SUCCESS) {
559 cs_error(link, RequestIRQ, i); 529 cs_error(link, RequestIRQ, i);
@@ -571,86 +541,72 @@ next_entry:
571 i = pcmcia_request_configuration(link, &link->conf); 541 i = pcmcia_request_configuration(link, &link->conf);
572 if (i != CS_SUCCESS) { 542 if (i != CS_SUCCESS) {
573 cs_error(link, RequestConfiguration, i); 543 cs_error(link, RequestConfiguration, i);
574 kfree(cfg_mem);
575 return -1; 544 return -1;
576 } 545 }
577 kfree(cfg_mem);
578 return setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ); 546 return setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ);
579} 547}
580 548
581static int multi_config(struct pcmcia_device * link) 549static int multi_config_check(struct pcmcia_device *p_dev,
550 cistpl_cftable_entry_t *cf,
551 void *priv_data)
582{ 552{
583 struct serial_info *info = link->priv; 553 int *base2 = priv_data;
584 struct serial_cfg_mem *cfg_mem; 554
585 tuple_t *tuple; 555 /* The quad port cards have bad CIS's, so just look for a
586 u_char *buf; 556 window larger than 8 ports and assume it will be right */
587 cisparse_t *parse; 557 if ((cf->io.nwin == 1) && (cf->io.win[0].len > 8)) {
588 cistpl_cftable_entry_t *cf; 558 p_dev->conf.ConfigIndex = cf->index;
589 int i, rc, base2 = 0; 559 p_dev->io.BasePort1 = cf->io.win[0].base;
560 p_dev->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
561 if (!pcmcia_request_io(p_dev, &p_dev->io)) {
562 *base2 = p_dev->io.BasePort1 + 8;
563 return 0;
564 }
565 }
566 return -ENODEV;
567}
590 568
591 cfg_mem = kmalloc(sizeof(struct serial_cfg_mem), GFP_KERNEL); 569static int multi_config_check_notpicky(struct pcmcia_device *p_dev,
592 if (!cfg_mem) 570 cistpl_cftable_entry_t *cf,
593 return -1; 571 void *priv_data)
594 tuple = &cfg_mem->tuple; 572{
595 parse = &cfg_mem->parse; 573 int *base2 = priv_data;
596 cf = &parse->cftable_entry; 574
597 buf = cfg_mem->buf; 575 if (cf->io.nwin == 2) {
576 p_dev->conf.ConfigIndex = cf->index;
577 p_dev->io.BasePort1 = cf->io.win[0].base;
578 p_dev->io.BasePort2 = cf->io.win[1].base;
579 p_dev->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
580 if (!pcmcia_request_io(p_dev, &p_dev->io)) {
581 *base2 = p_dev->io.BasePort2;
582 return 0;
583 }
584 }
585 return -ENODEV;
586}
598 587
599 tuple->TupleData = (cisdata_t *) buf; 588static int multi_config(struct pcmcia_device *link)
600 tuple->TupleOffset = 0; 589{
601 tuple->TupleDataMax = 255; 590 struct serial_info *info = link->priv;
602 tuple->Attributes = 0; 591 int i, base2 = 0;
603 tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
604 592
605 /* First, look for a generic full-sized window */ 593 /* First, look for a generic full-sized window */
606 link->io.NumPorts1 = info->multi * 8; 594 link->io.NumPorts1 = info->multi * 8;
607 i = first_tuple(link, tuple, parse); 595 if (pcmcia_loop_config(link, multi_config_check, &base2)) {
608 while (i != CS_NO_MORE_ITEMS) { 596 /* If that didn't work, look for two windows */
609 /* The quad port cards have bad CIS's, so just look for a
610 window larger than 8 ports and assume it will be right */
611 if ((i == CS_SUCCESS) && (cf->io.nwin == 1) &&
612 (cf->io.win[0].len > 8)) {
613 link->conf.ConfigIndex = cf->index;
614 link->io.BasePort1 = cf->io.win[0].base;
615 link->io.IOAddrLines =
616 cf->io.flags & CISTPL_IO_LINES_MASK;
617 i = pcmcia_request_io(link, &link->io);
618 base2 = link->io.BasePort1 + 8;
619 if (i == CS_SUCCESS)
620 break;
621 }
622 i = next_tuple(link, tuple, parse);
623 }
624
625 /* If that didn't work, look for two windows */
626 if (i != CS_SUCCESS) {
627 link->io.NumPorts1 = link->io.NumPorts2 = 8; 597 link->io.NumPorts1 = link->io.NumPorts2 = 8;
628 info->multi = 2; 598 info->multi = 2;
629 i = first_tuple(link, tuple, parse); 599 if (pcmcia_loop_config(link, multi_config_check_notpicky,
630 while (i != CS_NO_MORE_ITEMS) { 600 &base2)) {
631 if ((i == CS_SUCCESS) && (cf->io.nwin == 2)) { 601 printk(KERN_NOTICE "serial_cs: no usable port range"
632 link->conf.ConfigIndex = cf->index; 602 "found, giving up\n");
633 link->io.BasePort1 = cf->io.win[0].base; 603 return -ENODEV;
634 link->io.BasePort2 = cf->io.win[1].base;
635 link->io.IOAddrLines =
636 cf->io.flags & CISTPL_IO_LINES_MASK;
637 i = pcmcia_request_io(link, &link->io);
638 base2 = link->io.BasePort2;
639 if (i == CS_SUCCESS)
640 break;
641 }
642 i = next_tuple(link, tuple, parse);
643 } 604 }
644 } 605 }
645 606
646 if (i != CS_SUCCESS) {
647 cs_error(link, RequestIO, i);
648 rc = -1;
649 goto free_cfg_mem;
650 }
651
652 i = pcmcia_request_irq(link, &link->irq); 607 i = pcmcia_request_irq(link, &link->irq);
653 if (i != CS_SUCCESS) { 608 if (i != CS_SUCCESS) {
609 /* FIXME: comment does not fit, error handling does not fit */
654 printk(KERN_NOTICE 610 printk(KERN_NOTICE
655 "serial_cs: no usable port range found, giving up\n"); 611 "serial_cs: no usable port range found, giving up\n");
656 cs_error(link, RequestIRQ, i); 612 cs_error(link, RequestIRQ, i);
@@ -666,8 +622,7 @@ static int multi_config(struct pcmcia_device * link)
666 i = pcmcia_request_configuration(link, &link->conf); 622 i = pcmcia_request_configuration(link, &link->conf);
667 if (i != CS_SUCCESS) { 623 if (i != CS_SUCCESS) {
668 cs_error(link, RequestConfiguration, i); 624 cs_error(link, RequestConfiguration, i);
669 rc = -1; 625 return -ENODEV;
670 goto free_cfg_mem;
671 } 626 }
672 627
673 /* The Oxford Semiconductor OXCF950 cards are in fact single-port: 628 /* The Oxford Semiconductor OXCF950 cards are in fact single-port:
@@ -678,7 +633,8 @@ static int multi_config(struct pcmcia_device * link)
678 info->prodid == PRODID_POSSIO_GCC)) { 633 info->prodid == PRODID_POSSIO_GCC)) {
679 int err; 634 int err;
680 635
681 if (cf->index == 1 || cf->index == 3) { 636 if (link->conf.ConfigIndex == 1 ||
637 link->conf.ConfigIndex == 3) {
682 err = setup_serial(link, info, base2, 638 err = setup_serial(link, info, base2,
683 link->irq.AssignedIRQ); 639 link->irq.AssignedIRQ);
684 base2 = link->io.BasePort1; 640 base2 = link->io.BasePort1;
@@ -695,18 +651,14 @@ static int multi_config(struct pcmcia_device * link)
695 if (info->quirk && info->quirk->wakeup) 651 if (info->quirk && info->quirk->wakeup)
696 info->quirk->wakeup(link); 652 info->quirk->wakeup(link);
697 653
698 rc = 0; 654 return 0;
699 goto free_cfg_mem;
700 } 655 }
701 656
702 setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ); 657 setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ);
703 for (i = 0; i < info->multi - 1; i++) 658 for (i = 0; i < info->multi - 1; i++)
704 setup_serial(link, info, base2 + (8 * i), 659 setup_serial(link, info, base2 + (8 * i),
705 link->irq.AssignedIRQ); 660 link->irq.AssignedIRQ);
706 rc = 0; 661 return 0;
707free_cfg_mem:
708 kfree(cfg_mem);
709 return rc;
710} 662}
711 663
712/*====================================================================== 664/*======================================================================