aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/pcmcia/synclink_cs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/pcmcia/synclink_cs.c')
-rw-r--r--drivers/char/pcmcia/synclink_cs.c116
1 files changed, 41 insertions, 75 deletions
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index e6b714b6390d..07213454c458 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -228,7 +228,7 @@ typedef struct _mgslpc_info {
228 struct _input_signal_events input_signal_events; 228 struct _input_signal_events input_signal_events;
229 229
230 /* PCMCIA support */ 230 /* PCMCIA support */
231 dev_link_t link; 231 struct pcmcia_device *p_dev;
232 dev_node_t node; 232 dev_node_t node;
233 int stop; 233 int stop;
234 234
@@ -484,7 +484,7 @@ static void mgslpc_wait_until_sent(struct tty_struct *tty, int timeout);
484 484
485/* PCMCIA prototypes */ 485/* PCMCIA prototypes */
486 486
487static void mgslpc_config(dev_link_t *link); 487static int mgslpc_config(struct pcmcia_device *link);
488static void mgslpc_release(u_long arg); 488static void mgslpc_release(u_long arg);
489static void mgslpc_detach(struct pcmcia_device *p_dev); 489static void mgslpc_detach(struct pcmcia_device *p_dev);
490 490
@@ -533,14 +533,14 @@ static void ldisc_receive_buf(struct tty_struct *tty,
533 } 533 }
534} 534}
535 535
536static int mgslpc_attach(struct pcmcia_device *p_dev) 536static int mgslpc_probe(struct pcmcia_device *link)
537{ 537{
538 MGSLPC_INFO *info; 538 MGSLPC_INFO *info;
539 dev_link_t *link; 539 int ret;
540 540
541 if (debug_level >= DEBUG_LEVEL_INFO) 541 if (debug_level >= DEBUG_LEVEL_INFO)
542 printk("mgslpc_attach\n"); 542 printk("mgslpc_attach\n");
543 543
544 info = (MGSLPC_INFO *)kmalloc(sizeof(MGSLPC_INFO), GFP_KERNEL); 544 info = (MGSLPC_INFO *)kmalloc(sizeof(MGSLPC_INFO), GFP_KERNEL);
545 if (!info) { 545 if (!info) {
546 printk("Error can't allocate device instance data\n"); 546 printk("Error can't allocate device instance data\n");
@@ -565,25 +565,22 @@ static int mgslpc_attach(struct pcmcia_device *p_dev)
565 info->imrb_value = 0xffff; 565 info->imrb_value = 0xffff;
566 info->pim_value = 0xff; 566 info->pim_value = 0xff;
567 567
568 link = &info->link; 568 info->p_dev = link;
569 link->priv = info; 569 link->priv = info;
570 570
571 /* Initialize the dev_link_t structure */ 571 /* Initialize the struct pcmcia_device structure */
572 572
573 /* Interrupt setup */ 573 /* Interrupt setup */
574 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; 574 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
575 link->irq.IRQInfo1 = IRQ_LEVEL_ID; 575 link->irq.IRQInfo1 = IRQ_LEVEL_ID;
576 link->irq.Handler = NULL; 576 link->irq.Handler = NULL;
577 577
578 link->conf.Attributes = 0; 578 link->conf.Attributes = 0;
579 link->conf.Vcc = 50;
580 link->conf.IntType = INT_MEMORY_AND_IO; 579 link->conf.IntType = INT_MEMORY_AND_IO;
581 580
582 link->handle = p_dev; 581 ret = mgslpc_config(link);
583 p_dev->instance = link; 582 if (ret)
584 583 return ret;
585 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
586 mgslpc_config(link);
587 584
588 mgslpc_add_device(info); 585 mgslpc_add_device(info);
589 586
@@ -596,15 +593,13 @@ static int mgslpc_attach(struct pcmcia_device *p_dev)
596#define CS_CHECK(fn, ret) \ 593#define CS_CHECK(fn, ret) \
597do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) 594do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
598 595
599static void mgslpc_config(dev_link_t *link) 596static int mgslpc_config(struct pcmcia_device *link)
600{ 597{
601 client_handle_t handle = link->handle;
602 MGSLPC_INFO *info = link->priv; 598 MGSLPC_INFO *info = link->priv;
603 tuple_t tuple; 599 tuple_t tuple;
604 cisparse_t parse; 600 cisparse_t parse;
605 int last_fn, last_ret; 601 int last_fn, last_ret;
606 u_char buf[64]; 602 u_char buf[64];
607 config_info_t conf;
608 cistpl_cftable_entry_t dflt = { 0 }; 603 cistpl_cftable_entry_t dflt = { 0 };
609 cistpl_cftable_entry_t *cfg; 604 cistpl_cftable_entry_t *cfg;
610 605
@@ -617,27 +612,20 @@ static void mgslpc_config(dev_link_t *link)
617 tuple.TupleData = buf; 612 tuple.TupleData = buf;
618 tuple.TupleDataMax = sizeof(buf); 613 tuple.TupleDataMax = sizeof(buf);
619 tuple.TupleOffset = 0; 614 tuple.TupleOffset = 0;
620 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); 615 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
621 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); 616 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
622 CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); 617 CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
623 link->conf.ConfigBase = parse.config.base; 618 link->conf.ConfigBase = parse.config.base;
624 link->conf.Present = parse.config.rmask[0]; 619 link->conf.Present = parse.config.rmask[0];
625
626 /* Configure card */
627 link->state |= DEV_CONFIG;
628
629 /* Look up the current Vcc */
630 CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf));
631 link->conf.Vcc = conf.Vcc;
632 620
633 /* get CIS configuration entry */ 621 /* get CIS configuration entry */
634 622
635 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; 623 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
636 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); 624 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
637 625
638 cfg = &(parse.cftable_entry); 626 cfg = &(parse.cftable_entry);
639 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); 627 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
640 CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); 628 CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
641 629
642 if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; 630 if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
643 if (cfg->index == 0) 631 if (cfg->index == 0)
@@ -658,11 +646,10 @@ static void mgslpc_config(dev_link_t *link)
658 link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; 646 link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
659 link->io.BasePort1 = io->win[0].base; 647 link->io.BasePort1 = io->win[0].base;
660 link->io.NumPorts1 = io->win[0].len; 648 link->io.NumPorts1 = io->win[0].len;
661 CS_CHECK(RequestIO, pcmcia_request_io(link->handle, &link->io)); 649 CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io));
662 } 650 }
663 651
664 link->conf.Attributes = CONF_ENABLE_IRQ; 652 link->conf.Attributes = CONF_ENABLE_IRQ;
665 link->conf.Vcc = 50;
666 link->conf.IntType = INT_MEMORY_AND_IO; 653 link->conf.IntType = INT_MEMORY_AND_IO;
667 link->conf.ConfigIndex = 8; 654 link->conf.ConfigIndex = 8;
668 link->conf.Present = PRESENT_OPTION; 655 link->conf.Present = PRESENT_OPTION;
@@ -670,9 +657,9 @@ static void mgslpc_config(dev_link_t *link)
670 link->irq.Attributes |= IRQ_HANDLE_PRESENT; 657 link->irq.Attributes |= IRQ_HANDLE_PRESENT;
671 link->irq.Handler = mgslpc_isr; 658 link->irq.Handler = mgslpc_isr;
672 link->irq.Instance = info; 659 link->irq.Instance = info;
673 CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); 660 CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
674 661
675 CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); 662 CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
676 663
677 info->io_base = link->io.BasePort1; 664 info->io_base = link->io.BasePort1;
678 info->irq_level = link->irq.AssignedIRQ; 665 info->irq_level = link->irq.AssignedIRQ;
@@ -680,7 +667,7 @@ static void mgslpc_config(dev_link_t *link)
680 /* add to linked list of devices */ 667 /* add to linked list of devices */
681 sprintf(info->node.dev_name, "mgslpc0"); 668 sprintf(info->node.dev_name, "mgslpc0");
682 info->node.major = info->node.minor = 0; 669 info->node.major = info->node.minor = 0;
683 link->dev = &info->node; 670 link->dev_node = &info->node;
684 671
685 printk(KERN_INFO "%s: index 0x%02x:", 672 printk(KERN_INFO "%s: index 0x%02x:",
686 info->node.dev_name, link->conf.ConfigIndex); 673 info->node.dev_name, link->conf.ConfigIndex);
@@ -690,13 +677,12 @@ static void mgslpc_config(dev_link_t *link)
690 printk(", io 0x%04x-0x%04x", link->io.BasePort1, 677 printk(", io 0x%04x-0x%04x", link->io.BasePort1,
691 link->io.BasePort1+link->io.NumPorts1-1); 678 link->io.BasePort1+link->io.NumPorts1-1);
692 printk("\n"); 679 printk("\n");
693 680 return 0;
694 link->state &= ~DEV_CONFIG_PENDING;
695 return;
696 681
697cs_failed: 682cs_failed:
698 cs_error(link->handle, last_fn, last_ret); 683 cs_error(link, last_fn, last_ret);
699 mgslpc_release((u_long)link); 684 mgslpc_release((u_long)link);
685 return -ENODEV;
700} 686}
701 687
702/* Card has been removed. 688/* Card has been removed.
@@ -705,58 +691,38 @@ cs_failed:
705 */ 691 */
706static void mgslpc_release(u_long arg) 692static void mgslpc_release(u_long arg)
707{ 693{
708 dev_link_t *link = (dev_link_t *)arg; 694 struct pcmcia_device *link = (struct pcmcia_device *)arg;
709 695
710 if (debug_level >= DEBUG_LEVEL_INFO) 696 if (debug_level >= DEBUG_LEVEL_INFO)
711 printk("mgslpc_release(0x%p)\n", link); 697 printk("mgslpc_release(0x%p)\n", link);
712
713 /* Unlink the device chain */
714 link->dev = NULL;
715 link->state &= ~DEV_CONFIG;
716 698
717 pcmcia_release_configuration(link->handle); 699 pcmcia_disable_device(link);
718 if (link->io.NumPorts1)
719 pcmcia_release_io(link->handle, &link->io);
720 if (link->irq.AssignedIRQ)
721 pcmcia_release_irq(link->handle, &link->irq);
722} 700}
723 701
724static void mgslpc_detach(struct pcmcia_device *p_dev) 702static void mgslpc_detach(struct pcmcia_device *link)
725{ 703{
726 dev_link_t *link = dev_to_instance(p_dev); 704 if (debug_level >= DEBUG_LEVEL_INFO)
727 705 printk("mgslpc_detach(0x%p)\n", link);
728 if (debug_level >= DEBUG_LEVEL_INFO)
729 printk("mgslpc_detach(0x%p)\n", link);
730 706
731 if (link->state & DEV_CONFIG) { 707 ((MGSLPC_INFO *)link->priv)->stop = 1;
732 ((MGSLPC_INFO *)link->priv)->stop = 1; 708 mgslpc_release((u_long)link);
733 mgslpc_release((u_long)link);
734 }
735 709
736 mgslpc_remove_device((MGSLPC_INFO *)link->priv); 710 mgslpc_remove_device((MGSLPC_INFO *)link->priv);
737} 711}
738 712
739static int mgslpc_suspend(struct pcmcia_device *dev) 713static int mgslpc_suspend(struct pcmcia_device *link)
740{ 714{
741 dev_link_t *link = dev_to_instance(dev);
742 MGSLPC_INFO *info = link->priv; 715 MGSLPC_INFO *info = link->priv;
743 716
744 link->state |= DEV_SUSPEND;
745 info->stop = 1; 717 info->stop = 1;
746 if (link->state & DEV_CONFIG)
747 pcmcia_release_configuration(link->handle);
748 718
749 return 0; 719 return 0;
750} 720}
751 721
752static int mgslpc_resume(struct pcmcia_device *dev) 722static int mgslpc_resume(struct pcmcia_device *link)
753{ 723{
754 dev_link_t *link = dev_to_instance(dev);
755 MGSLPC_INFO *info = link->priv; 724 MGSLPC_INFO *info = link->priv;
756 725
757 link->state &= ~DEV_SUSPEND;
758 if (link->state & DEV_CONFIG)
759 pcmcia_request_configuration(link->handle, &link->conf);
760 info->stop = 0; 726 info->stop = 0;
761 727
762 return 0; 728 return 0;
@@ -1280,7 +1246,7 @@ static irqreturn_t mgslpc_isr(int irq, void *dev_id, struct pt_regs * regs)
1280 if (!info) 1246 if (!info)
1281 return IRQ_NONE; 1247 return IRQ_NONE;
1282 1248
1283 if (!(info->link.state & DEV_CONFIG)) 1249 if (!(info->p_dev->_locked))
1284 return IRQ_HANDLED; 1250 return IRQ_HANDLED;
1285 1251
1286 spin_lock(&info->lock); 1252 spin_lock(&info->lock);
@@ -3033,7 +2999,7 @@ static struct pcmcia_driver mgslpc_driver = {
3033 .drv = { 2999 .drv = {
3034 .name = "synclink_cs", 3000 .name = "synclink_cs",
3035 }, 3001 },
3036 .probe = mgslpc_attach, 3002 .probe = mgslpc_probe,
3037 .remove = mgslpc_detach, 3003 .remove = mgslpc_detach,
3038 .id_table = mgslpc_ids, 3004 .id_table = mgslpc_ids,
3039 .suspend = mgslpc_suspend, 3005 .suspend = mgslpc_suspend,