aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/mxser_new.c175
1 files changed, 88 insertions, 87 deletions
diff --git a/drivers/char/mxser_new.c b/drivers/char/mxser_new.c
index 792524ab348e..c06c5920bf1c 100644
--- a/drivers/char/mxser_new.c
+++ b/drivers/char/mxser_new.c
@@ -283,8 +283,7 @@ struct mxser_port {
283}; 283};
284 284
285struct mxser_board { 285struct mxser_board {
286 struct pci_dev *pdev; /* temporary (until pci probing) */ 286 unsigned int idx;
287
288 int irq; 287 int irq;
289 const struct mxser_cardinfo *info; 288 const struct mxser_cardinfo *info;
290 unsigned long vector; 289 unsigned long vector;
@@ -2383,10 +2382,9 @@ static const struct tty_operations mxser_ops = {
2383 * The MOXA Smartio/Industio serial driver boot-time initialization code! 2382 * The MOXA Smartio/Industio serial driver boot-time initialization code!
2384 */ 2383 */
2385 2384
2386static void mxser_release_res(struct mxser_board *brd, unsigned int irq) 2385static void mxser_release_res(struct mxser_board *brd, struct pci_dev *pdev,
2386 unsigned int irq)
2387{ 2387{
2388 struct pci_dev *pdev = brd->pdev;
2389
2390 if (irq) 2388 if (irq)
2391 free_irq(brd->irq, brd); 2389 free_irq(brd->irq, brd);
2392 if (pdev != NULL) { /* PCI */ 2390 if (pdev != NULL) { /* PCI */
@@ -2399,7 +2397,8 @@ static void mxser_release_res(struct mxser_board *brd, unsigned int irq)
2399 } 2397 }
2400} 2398}
2401 2399
2402static int __devinit mxser_initbrd(struct mxser_board *brd) 2400static int __devinit mxser_initbrd(struct mxser_board *brd,
2401 struct pci_dev *pdev)
2403{ 2402{
2404 struct mxser_port *info; 2403 struct mxser_port *info;
2405 unsigned int i; 2404 unsigned int i;
@@ -2450,7 +2449,7 @@ static int __devinit mxser_initbrd(struct mxser_board *brd)
2450 "conflict with another device.\n", 2449 "conflict with another device.\n",
2451 brd->info->name, brd->irq); 2450 brd->info->name, brd->irq);
2452 /* We hold resources, we need to release them. */ 2451 /* We hold resources, we need to release them. */
2453 mxser_release_res(brd, 0); 2452 mxser_release_res(brd, pdev, 0);
2454 return retval; 2453 return retval;
2455 } 2454 }
2456 return 0; 2455 return 0;
@@ -2552,20 +2551,43 @@ static int __init mxser_get_ISA_conf(int cap, struct mxser_board *brd)
2552 return brd->info->nports; 2551 return brd->info->nports;
2553} 2552}
2554 2553
2555static int __init mxser_get_PCI_conf(const struct pci_device_id *ent, 2554static int __devinit mxser_probe(struct pci_dev *pdev,
2556 struct mxser_board *brd, struct pci_dev *pdev) 2555 const struct pci_device_id *ent)
2557{ 2556{
2557 struct mxser_board *brd;
2558 unsigned int i, j; 2558 unsigned int i, j;
2559 unsigned long ioaddress; 2559 unsigned long ioaddress;
2560 int retval; 2560 int retval = -EINVAL;
2561
2562 for (i = 0; i < MXSER_BOARDS; i++)
2563 if (mxser_boards[i].info == NULL)
2564 break;
2565
2566 if (i >= MXSER_BOARDS) {
2567 printk(KERN_ERR "Too many Smartio/Industio family boards found "
2568 "(maximum %d), board not configured\n", MXSER_BOARDS);
2569 goto err;
2570 }
2571
2572 brd = &mxser_boards[i];
2573 brd->idx = i * MXSER_PORTS_PER_BOARD;
2574 printk(KERN_INFO "Found MOXA %s board (BusNo=%d, DevNo=%d)\n",
2575 mxser_cards[ent->driver_data].name,
2576 pdev->bus->number, PCI_SLOT(pdev->devfn));
2577
2578 retval = pci_enable_device(pdev);
2579 if (retval) {
2580 printk(KERN_ERR "Moxa SmartI/O PCI enable fail !\n");
2581 goto err;
2582 }
2561 2583
2562 /* io address */ 2584 /* io address */
2563 brd->info = &mxser_cards[ent->driver_data];
2564 ioaddress = pci_resource_start(pdev, 2); 2585 ioaddress = pci_resource_start(pdev, 2);
2565 retval = pci_request_region(pdev, 2, "mxser(IO)"); 2586 retval = pci_request_region(pdev, 2, "mxser(IO)");
2566 if (retval) 2587 if (retval)
2567 goto err; 2588 goto err;
2568 2589
2590 brd->info = &mxser_cards[ent->driver_data];
2569 for (i = 0; i < brd->info->nports; i++) 2591 for (i = 0; i < brd->info->nports; i++)
2570 brd->ports[i].ioaddr = ioaddress + 8 * i; 2592 brd->ports[i].ioaddr = ioaddress + 8 * i;
2571 2593
@@ -2612,20 +2634,50 @@ static int __init mxser_get_PCI_conf(const struct pci_device_id *ent,
2612 brd->vector_mask |= (1 << i); 2634 brd->vector_mask |= (1 << i);
2613 brd->ports[i].baud_base = 921600; 2635 brd->ports[i].baud_base = 921600;
2614 } 2636 }
2637
2638 /* mxser_initbrd will hook ISR. */
2639 if (mxser_initbrd(brd, pdev) < 0)
2640 goto err_relvec;
2641
2642 for (i = 0; i < brd->info->nports; i++)
2643 tty_register_device(mxvar_sdriver, brd->idx + i, &pdev->dev);
2644
2645 pci_set_drvdata(pdev, brd);
2646
2615 return 0; 2647 return 0;
2648err_relvec:
2649 pci_release_region(pdev, 3);
2616err_relio: 2650err_relio:
2617 pci_release_region(pdev, 2); 2651 pci_release_region(pdev, 2);
2652 brd->info = NULL;
2618err: 2653err:
2619 return retval; 2654 return retval;
2620} 2655}
2621 2656
2657static void __devexit mxser_remove(struct pci_dev *pdev)
2658{
2659 struct mxser_board *brd = pci_get_drvdata(pdev);
2660 unsigned int i;
2661
2662 for (i = 0; i < brd->info->nports; i++)
2663 tty_unregister_device(mxvar_sdriver, brd->idx + i);
2664
2665 mxser_release_res(brd, pdev, 1);
2666}
2667
2668static struct pci_driver mxser_driver = {
2669 .name = "mxser",
2670 .id_table = mxser_pcibrds,
2671 .probe = mxser_probe,
2672 .remove = __devexit_p(mxser_remove)
2673};
2674
2622static int __init mxser_module_init(void) 2675static int __init mxser_module_init(void)
2623{ 2676{
2624 struct pci_dev *pdev = NULL;
2625 struct mxser_board *brd; 2677 struct mxser_board *brd;
2626 unsigned long cap; 2678 unsigned long cap;
2627 unsigned int i, m, isaloop; 2679 unsigned int i, m, isaloop;
2628 int retval, b, n; 2680 int retval, b;
2629 2681
2630 pr_debug("Loading module mxser ...\n"); 2682 pr_debug("Loading module mxser ...\n");
2631 2683
@@ -2696,87 +2748,31 @@ static int __init mxser_module_init(void)
2696 printk(KERN_ERR "Invalid I/O address, " 2748 printk(KERN_ERR "Invalid I/O address, "
2697 "board not configured\n"); 2749 "board not configured\n");
2698 2750
2751 brd->info = NULL;
2699 continue; 2752 continue;
2700 } 2753 }
2701 2754
2702 brd->pdev = NULL;
2703
2704 /* mxser_initbrd will hook ISR. */ 2755 /* mxser_initbrd will hook ISR. */
2705 if (mxser_initbrd(brd) < 0) 2756 if (mxser_initbrd(brd, NULL) < 0) {
2706 continue; 2757 brd->info = NULL;
2707
2708 for (i = 0; i < brd->info->nports; i++)
2709 tty_register_device(mxvar_sdriver,
2710 m * MXSER_PORTS_PER_BOARD + i, NULL);
2711
2712 m++;
2713 }
2714
2715 /* start finding PCI board here */
2716 n = ARRAY_SIZE(mxser_pcibrds) - 1;
2717 b = 0;
2718 while (b < n) {
2719 pdev = pci_get_device(mxser_pcibrds[b].vendor,
2720 mxser_pcibrds[b].device, pdev);
2721 if (pdev == NULL) {
2722 b++;
2723 continue;
2724 }
2725 printk(KERN_INFO "Found MOXA %s board(BusNo=%d,DevNo=%d)\n",
2726 mxser_cards[mxser_pcibrds[b].driver_data].name,
2727 pdev->bus->number, PCI_SLOT(pdev->devfn));
2728 if (m >= MXSER_BOARDS)
2729 printk(KERN_ERR
2730 "Too many Smartio/Industio family boards find "
2731 "(maximum %d), board not configured\n",
2732 MXSER_BOARDS);
2733 else {
2734 if (pci_enable_device(pdev)) {
2735 printk(KERN_ERR "Moxa SmartI/O PCI enable "
2736 "fail !\n");
2737 continue;
2738 }
2739 brd = &mxser_boards[m];
2740 brd->pdev = pdev;
2741 retval = mxser_get_PCI_conf(&mxser_pcibrds[b],
2742 brd, pdev);
2743 if (retval < 0) {
2744 if (retval == MXSER_ERR_IRQ)
2745 printk(KERN_ERR
2746 "Invalid interrupt number, "
2747 "board not configured\n");
2748 else if (retval == MXSER_ERR_IRQ_CONFLIT)
2749 printk(KERN_ERR
2750 "Invalid interrupt number, "
2751 "board not configured\n");
2752 else if (retval == MXSER_ERR_VECTOR)
2753 printk(KERN_ERR
2754 "Invalid interrupt vector, "
2755 "board not configured\n");
2756 else if (retval == MXSER_ERR_IOADDR)
2757 printk(KERN_ERR
2758 "Invalid I/O address, "
2759 "board not configured\n");
2760 continue; 2758 continue;
2761 } 2759 }
2762 /* mxser_initbrd will hook ISR. */ 2760
2763 if (mxser_initbrd(brd) < 0) 2761 brd->idx = m * MXSER_PORTS_PER_BOARD;
2764 continue;
2765 for (i = 0; i < brd->info->nports; i++) 2762 for (i = 0; i < brd->info->nports; i++)
2766 tty_register_device(mxvar_sdriver, 2763 tty_register_device(mxvar_sdriver, brd->idx + i,
2767 m * MXSER_PORTS_PER_BOARD + i, 2764 NULL);
2768 &pdev->dev);
2769 2765
2770 m++; 2766 m++;
2771 /* Keep an extra reference if we succeeded. It will
2772 be returned at unload time */
2773 pci_dev_get(pdev);
2774 } 2767 }
2775 }
2776 2768
2777 if (!m) { 2769 retval = pci_register_driver(&mxser_driver);
2778 retval = -ENODEV; 2770 if (retval) {
2779 goto err_unr; 2771 printk(KERN_ERR "Can't register pci driver\n");
2772 if (!m) {
2773 retval = -ENODEV;
2774 goto err_unr;
2775 } /* else: we have some ISA cards under control */
2780 } 2776 }
2781 2777
2782 pr_debug("Done.\n"); 2778 pr_debug("Done.\n");
@@ -2791,18 +2787,23 @@ err_put:
2791 2787
2792static void __exit mxser_module_exit(void) 2788static void __exit mxser_module_exit(void)
2793{ 2789{
2794 unsigned int i; 2790 unsigned int i, j;
2795 2791
2796 pr_debug("Unloading module mxser ...\n"); 2792 pr_debug("Unloading module mxser ...\n");
2797 2793
2798 for (i = 0; i < MXSER_PORTS; i++) 2794 pci_unregister_driver(&mxser_driver);
2799 tty_unregister_device(mxvar_sdriver, i); 2795
2796 for (i = 0; i < MXSER_BOARDS; i++) /* ISA remains */
2797 if (mxser_boards[i].info != NULL)
2798 for (j = 0; j < mxser_boards[i].info->nports; j++)
2799 tty_unregister_device(mxvar_sdriver,
2800 mxser_boards[i].idx + j);
2800 tty_unregister_driver(mxvar_sdriver); 2801 tty_unregister_driver(mxvar_sdriver);
2801 put_tty_driver(mxvar_sdriver); 2802 put_tty_driver(mxvar_sdriver);
2802 2803
2803 for (i = 0; i < MXSER_BOARDS; i++) 2804 for (i = 0; i < MXSER_BOARDS; i++)
2804 if (mxser_boards[i].info != NULL) 2805 if (mxser_boards[i].info != NULL)
2805 mxser_release_res(&mxser_boards[i], 1); 2806 mxser_release_res(&mxser_boards[i], NULL, 1);
2806 2807
2807 pr_debug("Done.\n"); 2808 pr_debug("Done.\n");
2808} 2809}