aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/serial/serial_cs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/serial/serial_cs.c')
-rw-r--r--drivers/serial/serial_cs.c302
1 files changed, 129 insertions, 173 deletions
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index 164d2a42eb59..7546aa887fa7 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -431,131 +431,103 @@ first_tuple(struct pcmcia_device *handle, tuple_t * tuple, cisparse_t * parse)
431{ 431{
432 int i; 432 int i;
433 i = pcmcia_get_first_tuple(handle, tuple); 433 i = pcmcia_get_first_tuple(handle, tuple);
434 if (i != CS_SUCCESS) 434 if (i != 0)
435 return CS_NO_MORE_ITEMS;
436 i = pcmcia_get_tuple_data(handle, tuple);
437 if (i != CS_SUCCESS)
438 return i; 435 return i;
439 return pcmcia_parse_tuple(handle, tuple, parse);
440}
441
442static int
443next_tuple(struct pcmcia_device *handle, tuple_t * tuple, cisparse_t * parse)
444{
445 int i;
446 i = pcmcia_get_next_tuple(handle, tuple);
447 if (i != CS_SUCCESS)
448 return CS_NO_MORE_ITEMS;
449 i = pcmcia_get_tuple_data(handle, tuple); 436 i = pcmcia_get_tuple_data(handle, tuple);
450 if (i != CS_SUCCESS) 437 if (i != 0)
451 return i; 438 return i;
452 return pcmcia_parse_tuple(handle, tuple, parse); 439 return pcmcia_parse_tuple(tuple, parse);
453} 440}
454 441
455/*====================================================================*/ 442/*====================================================================*/
456 443
457static int simple_config(struct pcmcia_device *link) 444static int simple_config_check(struct pcmcia_device *p_dev,
445 cistpl_cftable_entry_t *cf,
446 cistpl_cftable_entry_t *dflt,
447 unsigned int vcc,
448 void *priv_data)
458{ 449{
459 static const unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
460 static const int size_table[2] = { 8, 16 }; 450 static const int size_table[2] = { 8, 16 };
461 struct serial_info *info = link->priv; 451 int *try = priv_data;
462 struct serial_cfg_mem *cfg_mem; 452
463 tuple_t *tuple; 453 if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
464 u_char *buf; 454 p_dev->conf.Vpp =
465 cisparse_t *parse; 455 cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
466 cistpl_cftable_entry_t *cf; 456
467 config_info_t config; 457 if ((cf->io.nwin > 0) && (cf->io.win[0].len == size_table[(*try >> 1)])
468 int i, j, try; 458 && (cf->io.win[0].base != 0)) {
469 int s; 459 p_dev->io.BasePort1 = cf->io.win[0].base;
460 p_dev->io.IOAddrLines = ((*try & 0x1) == 0) ?
461 16 : cf->io.flags & CISTPL_IO_LINES_MASK;
462 if (!pcmcia_request_io(p_dev, &p_dev->io))
463 return 0;
464 }
465 return -EINVAL;
466}
470 467
471 cfg_mem = kmalloc(sizeof(struct serial_cfg_mem), GFP_KERNEL); 468static int simple_config_check_notpicky(struct pcmcia_device *p_dev,
472 if (!cfg_mem) 469 cistpl_cftable_entry_t *cf,
473 return -1; 470 cistpl_cftable_entry_t *dflt,
471 unsigned int vcc,
472 void *priv_data)
473{
474 static const unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
475 int j;
476
477 if ((cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
478 for (j = 0; j < 5; j++) {
479 p_dev->io.BasePort1 = base[j];
480 p_dev->io.IOAddrLines = base[j] ? 16 : 3;
481 if (!pcmcia_request_io(p_dev, &p_dev->io))
482 return 0;
483 }
484 }
485 return -ENODEV;
486}
474 487
475 tuple = &cfg_mem->tuple; 488static int simple_config(struct pcmcia_device *link)
476 parse = &cfg_mem->parse; 489{
477 cf = &parse->cftable_entry; 490 struct serial_info *info = link->priv;
478 buf = cfg_mem->buf; 491 int i = -ENODEV, try;
479 492
480 /* If the card is already configured, look up the port and irq */ 493 /* If the card is already configured, look up the port and irq */
481 i = pcmcia_get_configuration_info(link, &config); 494 if (link->function_config) {
482 if ((i == CS_SUCCESS) && (config.Attributes & CONF_VALID_CLIENT)) {
483 unsigned int port = 0; 495 unsigned int port = 0;
484 if ((config.BasePort2 != 0) && (config.NumPorts2 == 8)) { 496 if ((link->io.BasePort2 != 0) &&
485 port = config.BasePort2; 497 (link->io.NumPorts2 == 8)) {
498 port = link->io.BasePort2;
486 info->slave = 1; 499 info->slave = 1;
487 } else if ((info->manfid == MANFID_OSITECH) && 500 } else if ((info->manfid == MANFID_OSITECH) &&
488 (config.NumPorts1 == 0x40)) { 501 (link->io.NumPorts1 == 0x40)) {
489 port = config.BasePort1 + 0x28; 502 port = link->io.BasePort1 + 0x28;
490 info->slave = 1; 503 info->slave = 1;
491 } 504 }
492 if (info->slave) { 505 if (info->slave) {
493 kfree(cfg_mem); 506 return setup_serial(link, info, port,
494 return setup_serial(link, info, port, config.AssignedIRQ); 507 link->irq.AssignedIRQ);
495 } 508 }
496 } 509 }
497 510
498 /* First pass: look for a config entry that looks normal. */ 511 /* First pass: look for a config entry that looks normal.
499 tuple->TupleData = (cisdata_t *) buf; 512 * Two tries: without IO aliases, then with aliases */
500 tuple->TupleOffset = 0; 513 for (try = 0; try < 4; try++)
501 tuple->TupleDataMax = 255; 514 if (!pcmcia_loop_config(link, simple_config_check, &try))
502 tuple->Attributes = 0; 515 goto found_port;
503 tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY; 516
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 517 /* Second pass: try to find an entry that isn't picky about
530 its base address, then try to grab any standard serial port 518 its base address, then try to grab any standard serial port
531 address, and finally try to get any free port. */ 519 address, and finally try to get any free port. */
532 i = first_tuple(link, tuple, parse); 520 if (!pcmcia_loop_config(link, simple_config_check_notpicky, NULL))
533 while (i != CS_NO_MORE_ITEMS) { 521 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 522
548 found_port: 523 printk(KERN_NOTICE
549 if (i != CS_SUCCESS) { 524 "serial_cs: no usable port range found, giving up\n");
550 printk(KERN_NOTICE 525 cs_error(link, RequestIO, i);
551 "serial_cs: no usable port range found, giving up\n"); 526 return -1;
552 cs_error(link, RequestIO, i);
553 kfree(cfg_mem);
554 return -1;
555 }
556 527
528found_port:
557 i = pcmcia_request_irq(link, &link->irq); 529 i = pcmcia_request_irq(link, &link->irq);
558 if (i != CS_SUCCESS) { 530 if (i != 0) {
559 cs_error(link, RequestIRQ, i); 531 cs_error(link, RequestIRQ, i);
560 link->irq.AssignedIRQ = 0; 532 link->irq.AssignedIRQ = 0;
561 } 533 }
@@ -569,88 +541,76 @@ next_entry:
569 info->quirk->config(link); 541 info->quirk->config(link);
570 542
571 i = pcmcia_request_configuration(link, &link->conf); 543 i = pcmcia_request_configuration(link, &link->conf);
572 if (i != CS_SUCCESS) { 544 if (i != 0) {
573 cs_error(link, RequestConfiguration, i); 545 cs_error(link, RequestConfiguration, i);
574 kfree(cfg_mem);
575 return -1; 546 return -1;
576 } 547 }
577 kfree(cfg_mem);
578 return setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ); 548 return setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ);
579} 549}
580 550
581static int multi_config(struct pcmcia_device * link) 551static int multi_config_check(struct pcmcia_device *p_dev,
552 cistpl_cftable_entry_t *cf,
553 cistpl_cftable_entry_t *dflt,
554 unsigned int vcc,
555 void *priv_data)
582{ 556{
583 struct serial_info *info = link->priv; 557 int *base2 = priv_data;
584 struct serial_cfg_mem *cfg_mem; 558
585 tuple_t *tuple; 559 /* The quad port cards have bad CIS's, so just look for a
586 u_char *buf; 560 window larger than 8 ports and assume it will be right */
587 cisparse_t *parse; 561 if ((cf->io.nwin == 1) && (cf->io.win[0].len > 8)) {
588 cistpl_cftable_entry_t *cf; 562 p_dev->io.BasePort1 = cf->io.win[0].base;
589 int i, rc, base2 = 0; 563 p_dev->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
564 if (!pcmcia_request_io(p_dev, &p_dev->io)) {
565 *base2 = p_dev->io.BasePort1 + 8;
566 return 0;
567 }
568 }
569 return -ENODEV;
570}
590 571
591 cfg_mem = kmalloc(sizeof(struct serial_cfg_mem), GFP_KERNEL); 572static int multi_config_check_notpicky(struct pcmcia_device *p_dev,
592 if (!cfg_mem) 573 cistpl_cftable_entry_t *cf,
593 return -1; 574 cistpl_cftable_entry_t *dflt,
594 tuple = &cfg_mem->tuple; 575 unsigned int vcc,
595 parse = &cfg_mem->parse; 576 void *priv_data)
596 cf = &parse->cftable_entry; 577{
597 buf = cfg_mem->buf; 578 int *base2 = priv_data;
579
580 if (cf->io.nwin == 2) {
581 p_dev->io.BasePort1 = cf->io.win[0].base;
582 p_dev->io.BasePort2 = cf->io.win[1].base;
583 p_dev->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
584 if (!pcmcia_request_io(p_dev, &p_dev->io)) {
585 *base2 = p_dev->io.BasePort2;
586 return 0;
587 }
588 }
589 return -ENODEV;
590}
598 591
599 tuple->TupleData = (cisdata_t *) buf; 592static int multi_config(struct pcmcia_device *link)
600 tuple->TupleOffset = 0; 593{
601 tuple->TupleDataMax = 255; 594 struct serial_info *info = link->priv;
602 tuple->Attributes = 0; 595 int i, base2 = 0;
603 tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
604 596
605 /* First, look for a generic full-sized window */ 597 /* First, look for a generic full-sized window */
606 link->io.NumPorts1 = info->multi * 8; 598 link->io.NumPorts1 = info->multi * 8;
607 i = first_tuple(link, tuple, parse); 599 if (pcmcia_loop_config(link, multi_config_check, &base2)) {
608 while (i != CS_NO_MORE_ITEMS) { 600 /* 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; 601 link->io.NumPorts1 = link->io.NumPorts2 = 8;
628 info->multi = 2; 602 info->multi = 2;
629 i = first_tuple(link, tuple, parse); 603 if (pcmcia_loop_config(link, multi_config_check_notpicky,
630 while (i != CS_NO_MORE_ITEMS) { 604 &base2)) {
631 if ((i == CS_SUCCESS) && (cf->io.nwin == 2)) { 605 printk(KERN_NOTICE "serial_cs: no usable port range"
632 link->conf.ConfigIndex = cf->index; 606 "found, giving up\n");
633 link->io.BasePort1 = cf->io.win[0].base; 607 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 } 608 }
644 } 609 }
645 610
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); 611 i = pcmcia_request_irq(link, &link->irq);
653 if (i != CS_SUCCESS) { 612 if (i != 0) {
613 /* FIXME: comment does not fit, error handling does not fit */
654 printk(KERN_NOTICE 614 printk(KERN_NOTICE
655 "serial_cs: no usable port range found, giving up\n"); 615 "serial_cs: no usable port range found, giving up\n");
656 cs_error(link, RequestIRQ, i); 616 cs_error(link, RequestIRQ, i);
@@ -664,10 +624,9 @@ static int multi_config(struct pcmcia_device * link)
664 info->quirk->config(link); 624 info->quirk->config(link);
665 625
666 i = pcmcia_request_configuration(link, &link->conf); 626 i = pcmcia_request_configuration(link, &link->conf);
667 if (i != CS_SUCCESS) { 627 if (i != 0) {
668 cs_error(link, RequestConfiguration, i); 628 cs_error(link, RequestConfiguration, i);
669 rc = -1; 629 return -ENODEV;
670 goto free_cfg_mem;
671 } 630 }
672 631
673 /* The Oxford Semiconductor OXCF950 cards are in fact single-port: 632 /* The Oxford Semiconductor OXCF950 cards are in fact single-port:
@@ -678,7 +637,8 @@ static int multi_config(struct pcmcia_device * link)
678 info->prodid == PRODID_POSSIO_GCC)) { 637 info->prodid == PRODID_POSSIO_GCC)) {
679 int err; 638 int err;
680 639
681 if (cf->index == 1 || cf->index == 3) { 640 if (link->conf.ConfigIndex == 1 ||
641 link->conf.ConfigIndex == 3) {
682 err = setup_serial(link, info, base2, 642 err = setup_serial(link, info, base2,
683 link->irq.AssignedIRQ); 643 link->irq.AssignedIRQ);
684 base2 = link->io.BasePort1; 644 base2 = link->io.BasePort1;
@@ -695,18 +655,14 @@ static int multi_config(struct pcmcia_device * link)
695 if (info->quirk && info->quirk->wakeup) 655 if (info->quirk && info->quirk->wakeup)
696 info->quirk->wakeup(link); 656 info->quirk->wakeup(link);
697 657
698 rc = 0; 658 return 0;
699 goto free_cfg_mem;
700 } 659 }
701 660
702 setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ); 661 setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ);
703 for (i = 0; i < info->multi - 1; i++) 662 for (i = 0; i < info->multi - 1; i++)
704 setup_serial(link, info, base2 + (8 * i), 663 setup_serial(link, info, base2 + (8 * i),
705 link->irq.AssignedIRQ); 664 link->irq.AssignedIRQ);
706 rc = 0; 665 return 0;
707free_cfg_mem:
708 kfree(cfg_mem);
709 return rc;
710} 666}
711 667
712/*====================================================================== 668/*======================================================================
@@ -746,7 +702,7 @@ static int serial_config(struct pcmcia_device * link)
746 /* Is this a compliant multifunction card? */ 702 /* Is this a compliant multifunction card? */
747 tuple->DesiredTuple = CISTPL_LONGLINK_MFC; 703 tuple->DesiredTuple = CISTPL_LONGLINK_MFC;
748 tuple->Attributes = TUPLE_RETURN_COMMON | TUPLE_RETURN_LINK; 704 tuple->Attributes = TUPLE_RETURN_COMMON | TUPLE_RETURN_LINK;
749 info->multi = (first_tuple(link, tuple, parse) == CS_SUCCESS); 705 info->multi = (first_tuple(link, tuple, parse) == 0);
750 706
751 /* Is this a multiport card? */ 707 /* Is this a multiport card? */
752 tuple->DesiredTuple = CISTPL_MANFID; 708 tuple->DesiredTuple = CISTPL_MANFID;
@@ -770,7 +726,7 @@ static int serial_config(struct pcmcia_device * link)
770 ((link->func_id == CISTPL_FUNCID_MULTI) || 726 ((link->func_id == CISTPL_FUNCID_MULTI) ||
771 (link->func_id == CISTPL_FUNCID_SERIAL))) { 727 (link->func_id == CISTPL_FUNCID_SERIAL))) {
772 tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY; 728 tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
773 if (first_tuple(link, tuple, parse) == CS_SUCCESS) { 729 if (first_tuple(link, tuple, parse) == 0) {
774 if ((cf->io.nwin == 1) && (cf->io.win[0].len % 8 == 0)) 730 if ((cf->io.nwin == 1) && (cf->io.win[0].len % 8 == 0))
775 info->multi = cf->io.win[0].len >> 3; 731 info->multi = cf->io.win[0].len >> 3;
776 if ((cf->io.nwin == 2) && (cf->io.win[0].len == 8) && 732 if ((cf->io.nwin == 2) && (cf->io.win[0].len == 8) &&