diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2005-08-29 13:34:59 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-08-29 13:34:59 -0400 |
commit | 975f957dc408925805dd8f5aa4217b7eeea2d005 (patch) | |
tree | 2198bb72323a016d93c7440c9240bac94a5c0016 /drivers/serial | |
parent | 2321fbd2b87539edc1fbfc2e186528a1ef93835f (diff) | |
parent | 661299d9d0437a0ff72240f3d60016ac3a361a6e (diff) |
Merge HEAD from master.kernel.org:/home/rmk/linux-2.6-serial.git
Diffstat (limited to 'drivers/serial')
-rw-r--r-- | drivers/serial/8250_pci.c | 474 |
1 files changed, 177 insertions, 297 deletions
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c index 07f05e9d0955..0e21f583690e 100644 --- a/drivers/serial/8250_pci.c +++ b/drivers/serial/8250_pci.c | |||
@@ -34,36 +34,6 @@ | |||
34 | #undef SERIAL_DEBUG_PCI | 34 | #undef SERIAL_DEBUG_PCI |
35 | 35 | ||
36 | /* | 36 | /* |
37 | * Definitions for PCI support. | ||
38 | */ | ||
39 | #define FL_BASE_MASK 0x0007 | ||
40 | #define FL_BASE0 0x0000 | ||
41 | #define FL_BASE1 0x0001 | ||
42 | #define FL_BASE2 0x0002 | ||
43 | #define FL_BASE3 0x0003 | ||
44 | #define FL_BASE4 0x0004 | ||
45 | #define FL_GET_BASE(x) (x & FL_BASE_MASK) | ||
46 | |||
47 | /* Use successive BARs (PCI base address registers), | ||
48 | else use offset into some specified BAR */ | ||
49 | #define FL_BASE_BARS 0x0008 | ||
50 | |||
51 | /* do not assign an irq */ | ||
52 | #define FL_NOIRQ 0x0080 | ||
53 | |||
54 | /* Use the Base address register size to cap number of ports */ | ||
55 | #define FL_REGION_SZ_CAP 0x0100 | ||
56 | |||
57 | struct pci_board { | ||
58 | unsigned int flags; | ||
59 | unsigned int num_ports; | ||
60 | unsigned int base_baud; | ||
61 | unsigned int uart_offset; | ||
62 | unsigned int reg_shift; | ||
63 | unsigned int first_offset; | ||
64 | }; | ||
65 | |||
66 | /* | ||
67 | * init function returns: | 37 | * init function returns: |
68 | * > 0 - number of ports | 38 | * > 0 - number of ports |
69 | * = 0 - use board->num_ports | 39 | * = 0 - use board->num_ports |
@@ -75,14 +45,15 @@ struct pci_serial_quirk { | |||
75 | u32 subvendor; | 45 | u32 subvendor; |
76 | u32 subdevice; | 46 | u32 subdevice; |
77 | int (*init)(struct pci_dev *dev); | 47 | int (*init)(struct pci_dev *dev); |
78 | int (*setup)(struct pci_dev *dev, struct pci_board *board, | 48 | int (*setup)(struct serial_private *, struct pciserial_board *, |
79 | struct uart_port *port, int idx); | 49 | struct uart_port *, int); |
80 | void (*exit)(struct pci_dev *dev); | 50 | void (*exit)(struct pci_dev *dev); |
81 | }; | 51 | }; |
82 | 52 | ||
83 | #define PCI_NUM_BAR_RESOURCES 6 | 53 | #define PCI_NUM_BAR_RESOURCES 6 |
84 | 54 | ||
85 | struct serial_private { | 55 | struct serial_private { |
56 | struct pci_dev *dev; | ||
86 | unsigned int nr; | 57 | unsigned int nr; |
87 | void __iomem *remapped_bar[PCI_NUM_BAR_RESOURCES]; | 58 | void __iomem *remapped_bar[PCI_NUM_BAR_RESOURCES]; |
88 | struct pci_serial_quirk *quirk; | 59 | struct pci_serial_quirk *quirk; |
@@ -101,17 +72,18 @@ static void moan_device(const char *str, struct pci_dev *dev) | |||
101 | } | 72 | } |
102 | 73 | ||
103 | static int | 74 | static int |
104 | setup_port(struct pci_dev *dev, struct uart_port *port, | 75 | setup_port(struct serial_private *priv, struct uart_port *port, |
105 | int bar, int offset, int regshift) | 76 | int bar, int offset, int regshift) |
106 | { | 77 | { |
107 | struct serial_private *priv = pci_get_drvdata(dev); | 78 | struct pci_dev *dev = priv->dev; |
108 | unsigned long base, len; | 79 | unsigned long base, len; |
109 | 80 | ||
110 | if (bar >= PCI_NUM_BAR_RESOURCES) | 81 | if (bar >= PCI_NUM_BAR_RESOURCES) |
111 | return -EINVAL; | 82 | return -EINVAL; |
112 | 83 | ||
84 | base = pci_resource_start(dev, bar); | ||
85 | |||
113 | if (pci_resource_flags(dev, bar) & IORESOURCE_MEM) { | 86 | if (pci_resource_flags(dev, bar) & IORESOURCE_MEM) { |
114 | base = pci_resource_start(dev, bar); | ||
115 | len = pci_resource_len(dev, bar); | 87 | len = pci_resource_len(dev, bar); |
116 | 88 | ||
117 | if (!priv->remapped_bar[bar]) | 89 | if (!priv->remapped_bar[bar]) |
@@ -120,13 +92,16 @@ setup_port(struct pci_dev *dev, struct uart_port *port, | |||
120 | return -ENOMEM; | 92 | return -ENOMEM; |
121 | 93 | ||
122 | port->iotype = UPIO_MEM; | 94 | port->iotype = UPIO_MEM; |
95 | port->iobase = 0; | ||
123 | port->mapbase = base + offset; | 96 | port->mapbase = base + offset; |
124 | port->membase = priv->remapped_bar[bar] + offset; | 97 | port->membase = priv->remapped_bar[bar] + offset; |
125 | port->regshift = regshift; | 98 | port->regshift = regshift; |
126 | } else { | 99 | } else { |
127 | base = pci_resource_start(dev, bar) + offset; | ||
128 | port->iotype = UPIO_PORT; | 100 | port->iotype = UPIO_PORT; |
129 | port->iobase = base; | 101 | port->iobase = base + offset; |
102 | port->mapbase = 0; | ||
103 | port->membase = NULL; | ||
104 | port->regshift = 0; | ||
130 | } | 105 | } |
131 | return 0; | 106 | return 0; |
132 | } | 107 | } |
@@ -136,7 +111,7 @@ setup_port(struct pci_dev *dev, struct uart_port *port, | |||
136 | * Not that ugly ;) -- HW | 111 | * Not that ugly ;) -- HW |
137 | */ | 112 | */ |
138 | static int | 113 | static int |
139 | afavlab_setup(struct pci_dev *dev, struct pci_board *board, | 114 | afavlab_setup(struct serial_private *priv, struct pciserial_board *board, |
140 | struct uart_port *port, int idx) | 115 | struct uart_port *port, int idx) |
141 | { | 116 | { |
142 | unsigned int bar, offset = board->first_offset; | 117 | unsigned int bar, offset = board->first_offset; |
@@ -149,7 +124,7 @@ afavlab_setup(struct pci_dev *dev, struct pci_board *board, | |||
149 | offset += (idx - 4) * board->uart_offset; | 124 | offset += (idx - 4) * board->uart_offset; |
150 | } | 125 | } |
151 | 126 | ||
152 | return setup_port(dev, port, bar, offset, board->reg_shift); | 127 | return setup_port(priv, port, bar, offset, board->reg_shift); |
153 | } | 128 | } |
154 | 129 | ||
155 | /* | 130 | /* |
@@ -189,13 +164,13 @@ static int __devinit pci_hp_diva_init(struct pci_dev *dev) | |||
189 | * some serial ports are supposed to be hidden on certain models. | 164 | * some serial ports are supposed to be hidden on certain models. |
190 | */ | 165 | */ |
191 | static int | 166 | static int |
192 | pci_hp_diva_setup(struct pci_dev *dev, struct pci_board *board, | 167 | pci_hp_diva_setup(struct serial_private *priv, struct pciserial_board *board, |
193 | struct uart_port *port, int idx) | 168 | struct uart_port *port, int idx) |
194 | { | 169 | { |
195 | unsigned int offset = board->first_offset; | 170 | unsigned int offset = board->first_offset; |
196 | unsigned int bar = FL_GET_BASE(board->flags); | 171 | unsigned int bar = FL_GET_BASE(board->flags); |
197 | 172 | ||
198 | switch (dev->subsystem_device) { | 173 | switch (priv->dev->subsystem_device) { |
199 | case PCI_DEVICE_ID_HP_DIVA_MAESTRO: | 174 | case PCI_DEVICE_ID_HP_DIVA_MAESTRO: |
200 | if (idx == 3) | 175 | if (idx == 3) |
201 | idx++; | 176 | idx++; |
@@ -212,7 +187,7 @@ pci_hp_diva_setup(struct pci_dev *dev, struct pci_board *board, | |||
212 | 187 | ||
213 | offset += idx * board->uart_offset; | 188 | offset += idx * board->uart_offset; |
214 | 189 | ||
215 | return setup_port(dev, port, bar, offset, board->reg_shift); | 190 | return setup_port(priv, port, bar, offset, board->reg_shift); |
216 | } | 191 | } |
217 | 192 | ||
218 | /* | 193 | /* |
@@ -307,7 +282,7 @@ static void __devexit pci_plx9050_exit(struct pci_dev *dev) | |||
307 | 282 | ||
308 | /* SBS Technologies Inc. PMC-OCTPRO and P-OCTAL cards */ | 283 | /* SBS Technologies Inc. PMC-OCTPRO and P-OCTAL cards */ |
309 | static int | 284 | static int |
310 | sbs_setup(struct pci_dev *dev, struct pci_board *board, | 285 | sbs_setup(struct serial_private *priv, struct pciserial_board *board, |
311 | struct uart_port *port, int idx) | 286 | struct uart_port *port, int idx) |
312 | { | 287 | { |
313 | unsigned int bar, offset = board->first_offset; | 288 | unsigned int bar, offset = board->first_offset; |
@@ -323,7 +298,7 @@ sbs_setup(struct pci_dev *dev, struct pci_board *board, | |||
323 | } else /* we have only 8 ports on PMC-OCTALPRO */ | 298 | } else /* we have only 8 ports on PMC-OCTALPRO */ |
324 | return 1; | 299 | return 1; |
325 | 300 | ||
326 | return setup_port(dev, port, bar, offset, board->reg_shift); | 301 | return setup_port(priv, port, bar, offset, board->reg_shift); |
327 | } | 302 | } |
328 | 303 | ||
329 | /* | 304 | /* |
@@ -389,6 +364,9 @@ static void __devexit sbs_exit(struct pci_dev *dev) | |||
389 | * - 10x cards have control registers in IO and/or memory space; | 364 | * - 10x cards have control registers in IO and/or memory space; |
390 | * - 20x cards have control registers in standard PCI configuration space. | 365 | * - 20x cards have control registers in standard PCI configuration space. |
391 | * | 366 | * |
367 | * Note: all 10x cards have PCI device ids 0x10.. | ||
368 | * all 20x cards have PCI device ids 0x20.. | ||
369 | * | ||
392 | * There are also Quartet Serial cards which use Oxford Semiconductor | 370 | * There are also Quartet Serial cards which use Oxford Semiconductor |
393 | * 16954 quad UART PCI chip clocked by 18.432 MHz quartz. | 371 | * 16954 quad UART PCI chip clocked by 18.432 MHz quartz. |
394 | * | 372 | * |
@@ -445,24 +423,18 @@ static int pci_siig20x_init(struct pci_dev *dev) | |||
445 | return 0; | 423 | return 0; |
446 | } | 424 | } |
447 | 425 | ||
448 | int pci_siig10x_fn(struct pci_dev *dev, int enable) | 426 | static int pci_siig_init(struct pci_dev *dev) |
449 | { | 427 | { |
450 | int ret = 0; | 428 | unsigned int type = dev->device & 0xff00; |
451 | if (enable) | ||
452 | ret = pci_siig10x_init(dev); | ||
453 | return ret; | ||
454 | } | ||
455 | 429 | ||
456 | int pci_siig20x_fn(struct pci_dev *dev, int enable) | 430 | if (type == 0x1000) |
457 | { | 431 | return pci_siig10x_init(dev); |
458 | int ret = 0; | 432 | else if (type == 0x2000) |
459 | if (enable) | 433 | return pci_siig20x_init(dev); |
460 | ret = pci_siig20x_init(dev); | ||
461 | return ret; | ||
462 | } | ||
463 | 434 | ||
464 | EXPORT_SYMBOL(pci_siig10x_fn); | 435 | moan_device("Unknown SIIG card", dev); |
465 | EXPORT_SYMBOL(pci_siig20x_fn); | 436 | return -ENODEV; |
437 | } | ||
466 | 438 | ||
467 | /* | 439 | /* |
468 | * Timedia has an explosion of boards, and to avoid the PCI table from | 440 | * Timedia has an explosion of boards, and to avoid the PCI table from |
@@ -523,7 +495,7 @@ static int __devinit pci_timedia_init(struct pci_dev *dev) | |||
523 | * Ugh, this is ugly as all hell --- TYT | 495 | * Ugh, this is ugly as all hell --- TYT |
524 | */ | 496 | */ |
525 | static int | 497 | static int |
526 | pci_timedia_setup(struct pci_dev *dev, struct pci_board *board, | 498 | pci_timedia_setup(struct serial_private *priv, struct pciserial_board *board, |
527 | struct uart_port *port, int idx) | 499 | struct uart_port *port, int idx) |
528 | { | 500 | { |
529 | unsigned int bar = 0, offset = board->first_offset; | 501 | unsigned int bar = 0, offset = board->first_offset; |
@@ -549,14 +521,15 @@ pci_timedia_setup(struct pci_dev *dev, struct pci_board *board, | |||
549 | bar = idx - 2; | 521 | bar = idx - 2; |
550 | } | 522 | } |
551 | 523 | ||
552 | return setup_port(dev, port, bar, offset, board->reg_shift); | 524 | return setup_port(priv, port, bar, offset, board->reg_shift); |
553 | } | 525 | } |
554 | 526 | ||
555 | /* | 527 | /* |
556 | * Some Titan cards are also a little weird | 528 | * Some Titan cards are also a little weird |
557 | */ | 529 | */ |
558 | static int | 530 | static int |
559 | titan_400l_800l_setup(struct pci_dev *dev, struct pci_board *board, | 531 | titan_400l_800l_setup(struct serial_private *priv, |
532 | struct pciserial_board *board, | ||
560 | struct uart_port *port, int idx) | 533 | struct uart_port *port, int idx) |
561 | { | 534 | { |
562 | unsigned int bar, offset = board->first_offset; | 535 | unsigned int bar, offset = board->first_offset; |
@@ -573,7 +546,7 @@ titan_400l_800l_setup(struct pci_dev *dev, struct pci_board *board, | |||
573 | offset = (idx - 2) * board->uart_offset; | 546 | offset = (idx - 2) * board->uart_offset; |
574 | } | 547 | } |
575 | 548 | ||
576 | return setup_port(dev, port, bar, offset, board->reg_shift); | 549 | return setup_port(priv, port, bar, offset, board->reg_shift); |
577 | } | 550 | } |
578 | 551 | ||
579 | static int __devinit pci_xircom_init(struct pci_dev *dev) | 552 | static int __devinit pci_xircom_init(struct pci_dev *dev) |
@@ -593,7 +566,7 @@ static int __devinit pci_netmos_init(struct pci_dev *dev) | |||
593 | } | 566 | } |
594 | 567 | ||
595 | static int | 568 | static int |
596 | pci_default_setup(struct pci_dev *dev, struct pci_board *board, | 569 | pci_default_setup(struct serial_private *priv, struct pciserial_board *board, |
597 | struct uart_port *port, int idx) | 570 | struct uart_port *port, int idx) |
598 | { | 571 | { |
599 | unsigned int bar, offset = board->first_offset, maxnr; | 572 | unsigned int bar, offset = board->first_offset, maxnr; |
@@ -604,13 +577,13 @@ pci_default_setup(struct pci_dev *dev, struct pci_board *board, | |||
604 | else | 577 | else |
605 | offset += idx * board->uart_offset; | 578 | offset += idx * board->uart_offset; |
606 | 579 | ||
607 | maxnr = (pci_resource_len(dev, bar) - board->first_offset) / | 580 | maxnr = (pci_resource_len(priv->dev, bar) - board->first_offset) / |
608 | (8 << board->reg_shift); | 581 | (8 << board->reg_shift); |
609 | 582 | ||
610 | if (board->flags & FL_REGION_SZ_CAP && idx >= maxnr) | 583 | if (board->flags & FL_REGION_SZ_CAP && idx >= maxnr) |
611 | return 1; | 584 | return 1; |
612 | 585 | ||
613 | return setup_port(dev, port, bar, offset, board->reg_shift); | 586 | return setup_port(priv, port, bar, offset, board->reg_shift); |
614 | } | 587 | } |
615 | 588 | ||
616 | /* This should be in linux/pci_ids.h */ | 589 | /* This should be in linux/pci_ids.h */ |
@@ -754,152 +727,15 @@ static struct pci_serial_quirk pci_serial_quirks[] = { | |||
754 | .setup = sbs_setup, | 727 | .setup = sbs_setup, |
755 | .exit = __devexit_p(sbs_exit), | 728 | .exit = __devexit_p(sbs_exit), |
756 | }, | 729 | }, |
757 | |||
758 | /* | 730 | /* |
759 | * SIIG cards. | 731 | * SIIG cards. |
760 | * It is not clear whether these could be collapsed. | ||
761 | */ | 732 | */ |
762 | { | 733 | { |
763 | .vendor = PCI_VENDOR_ID_SIIG, | 734 | .vendor = PCI_VENDOR_ID_SIIG, |
764 | .device = PCI_DEVICE_ID_SIIG_1S_10x_550, | 735 | .device = PCI_ANY_ID, |
765 | .subvendor = PCI_ANY_ID, | ||
766 | .subdevice = PCI_ANY_ID, | ||
767 | .init = pci_siig10x_init, | ||
768 | .setup = pci_default_setup, | ||
769 | }, | ||
770 | { | ||
771 | .vendor = PCI_VENDOR_ID_SIIG, | ||
772 | .device = PCI_DEVICE_ID_SIIG_1S_10x_650, | ||
773 | .subvendor = PCI_ANY_ID, | ||
774 | .subdevice = PCI_ANY_ID, | ||
775 | .init = pci_siig10x_init, | ||
776 | .setup = pci_default_setup, | ||
777 | }, | ||
778 | { | ||
779 | .vendor = PCI_VENDOR_ID_SIIG, | ||
780 | .device = PCI_DEVICE_ID_SIIG_1S_10x_850, | ||
781 | .subvendor = PCI_ANY_ID, | ||
782 | .subdevice = PCI_ANY_ID, | ||
783 | .init = pci_siig10x_init, | ||
784 | .setup = pci_default_setup, | ||
785 | }, | ||
786 | { | ||
787 | .vendor = PCI_VENDOR_ID_SIIG, | ||
788 | .device = PCI_DEVICE_ID_SIIG_2S_10x_550, | ||
789 | .subvendor = PCI_ANY_ID, | ||
790 | .subdevice = PCI_ANY_ID, | ||
791 | .init = pci_siig10x_init, | ||
792 | .setup = pci_default_setup, | ||
793 | }, | ||
794 | { | ||
795 | .vendor = PCI_VENDOR_ID_SIIG, | ||
796 | .device = PCI_DEVICE_ID_SIIG_2S_10x_650, | ||
797 | .subvendor = PCI_ANY_ID, | ||
798 | .subdevice = PCI_ANY_ID, | ||
799 | .init = pci_siig10x_init, | ||
800 | .setup = pci_default_setup, | ||
801 | }, | ||
802 | { | ||
803 | .vendor = PCI_VENDOR_ID_SIIG, | ||
804 | .device = PCI_DEVICE_ID_SIIG_2S_10x_850, | ||
805 | .subvendor = PCI_ANY_ID, | ||
806 | .subdevice = PCI_ANY_ID, | ||
807 | .init = pci_siig10x_init, | ||
808 | .setup = pci_default_setup, | ||
809 | }, | ||
810 | { | ||
811 | .vendor = PCI_VENDOR_ID_SIIG, | ||
812 | .device = PCI_DEVICE_ID_SIIG_4S_10x_550, | ||
813 | .subvendor = PCI_ANY_ID, | ||
814 | .subdevice = PCI_ANY_ID, | ||
815 | .init = pci_siig10x_init, | ||
816 | .setup = pci_default_setup, | ||
817 | }, | ||
818 | { | ||
819 | .vendor = PCI_VENDOR_ID_SIIG, | ||
820 | .device = PCI_DEVICE_ID_SIIG_4S_10x_650, | ||
821 | .subvendor = PCI_ANY_ID, | ||
822 | .subdevice = PCI_ANY_ID, | ||
823 | .init = pci_siig10x_init, | ||
824 | .setup = pci_default_setup, | ||
825 | }, | ||
826 | { | ||
827 | .vendor = PCI_VENDOR_ID_SIIG, | ||
828 | .device = PCI_DEVICE_ID_SIIG_4S_10x_850, | ||
829 | .subvendor = PCI_ANY_ID, | ||
830 | .subdevice = PCI_ANY_ID, | ||
831 | .init = pci_siig10x_init, | ||
832 | .setup = pci_default_setup, | ||
833 | }, | ||
834 | { | ||
835 | .vendor = PCI_VENDOR_ID_SIIG, | ||
836 | .device = PCI_DEVICE_ID_SIIG_1S_20x_550, | ||
837 | .subvendor = PCI_ANY_ID, | ||
838 | .subdevice = PCI_ANY_ID, | ||
839 | .init = pci_siig20x_init, | ||
840 | .setup = pci_default_setup, | ||
841 | }, | ||
842 | { | ||
843 | .vendor = PCI_VENDOR_ID_SIIG, | ||
844 | .device = PCI_DEVICE_ID_SIIG_1S_20x_650, | ||
845 | .subvendor = PCI_ANY_ID, | ||
846 | .subdevice = PCI_ANY_ID, | ||
847 | .init = pci_siig20x_init, | ||
848 | .setup = pci_default_setup, | ||
849 | }, | ||
850 | { | ||
851 | .vendor = PCI_VENDOR_ID_SIIG, | ||
852 | .device = PCI_DEVICE_ID_SIIG_1S_20x_850, | ||
853 | .subvendor = PCI_ANY_ID, | ||
854 | .subdevice = PCI_ANY_ID, | ||
855 | .init = pci_siig20x_init, | ||
856 | .setup = pci_default_setup, | ||
857 | }, | ||
858 | { | ||
859 | .vendor = PCI_VENDOR_ID_SIIG, | ||
860 | .device = PCI_DEVICE_ID_SIIG_2S_20x_550, | ||
861 | .subvendor = PCI_ANY_ID, | ||
862 | .subdevice = PCI_ANY_ID, | ||
863 | .init = pci_siig20x_init, | ||
864 | .setup = pci_default_setup, | ||
865 | }, | ||
866 | { .vendor = PCI_VENDOR_ID_SIIG, | ||
867 | .device = PCI_DEVICE_ID_SIIG_2S_20x_650, | ||
868 | .subvendor = PCI_ANY_ID, | ||
869 | .subdevice = PCI_ANY_ID, | ||
870 | .init = pci_siig20x_init, | ||
871 | .setup = pci_default_setup, | ||
872 | }, | ||
873 | { | ||
874 | .vendor = PCI_VENDOR_ID_SIIG, | ||
875 | .device = PCI_DEVICE_ID_SIIG_2S_20x_850, | ||
876 | .subvendor = PCI_ANY_ID, | ||
877 | .subdevice = PCI_ANY_ID, | ||
878 | .init = pci_siig20x_init, | ||
879 | .setup = pci_default_setup, | ||
880 | }, | ||
881 | { | ||
882 | .vendor = PCI_VENDOR_ID_SIIG, | ||
883 | .device = PCI_DEVICE_ID_SIIG_4S_20x_550, | ||
884 | .subvendor = PCI_ANY_ID, | ||
885 | .subdevice = PCI_ANY_ID, | ||
886 | .init = pci_siig20x_init, | ||
887 | .setup = pci_default_setup, | ||
888 | }, | ||
889 | { | ||
890 | .vendor = PCI_VENDOR_ID_SIIG, | ||
891 | .device = PCI_DEVICE_ID_SIIG_4S_20x_650, | ||
892 | .subvendor = PCI_ANY_ID, | ||
893 | .subdevice = PCI_ANY_ID, | ||
894 | .init = pci_siig20x_init, | ||
895 | .setup = pci_default_setup, | ||
896 | }, | ||
897 | { | ||
898 | .vendor = PCI_VENDOR_ID_SIIG, | ||
899 | .device = PCI_DEVICE_ID_SIIG_4S_20x_850, | ||
900 | .subvendor = PCI_ANY_ID, | 736 | .subvendor = PCI_ANY_ID, |
901 | .subdevice = PCI_ANY_ID, | 737 | .subdevice = PCI_ANY_ID, |
902 | .init = pci_siig20x_init, | 738 | .init = pci_siig_init, |
903 | .setup = pci_default_setup, | 739 | .setup = pci_default_setup, |
904 | }, | 740 | }, |
905 | /* | 741 | /* |
@@ -990,7 +826,7 @@ static struct pci_serial_quirk *find_quirk(struct pci_dev *dev) | |||
990 | } | 826 | } |
991 | 827 | ||
992 | static _INLINE_ int | 828 | static _INLINE_ int |
993 | get_pci_irq(struct pci_dev *dev, struct pci_board *board, int idx) | 829 | get_pci_irq(struct pci_dev *dev, struct pciserial_board *board) |
994 | { | 830 | { |
995 | if (board->flags & FL_NOIRQ) | 831 | if (board->flags & FL_NOIRQ) |
996 | return 0; | 832 | return 0; |
@@ -1115,7 +951,7 @@ enum pci_board_num_t { | |||
1115 | * see first lines of serial_in() and serial_out() in 8250.c | 951 | * see first lines of serial_in() and serial_out() in 8250.c |
1116 | */ | 952 | */ |
1117 | 953 | ||
1118 | static struct pci_board pci_boards[] __devinitdata = { | 954 | static struct pciserial_board pci_boards[] __devinitdata = { |
1119 | [pbn_default] = { | 955 | [pbn_default] = { |
1120 | .flags = FL_BASE0, | 956 | .flags = FL_BASE0, |
1121 | .num_ports = 1, | 957 | .num_ports = 1, |
@@ -1575,7 +1411,7 @@ static struct pci_board pci_boards[] __devinitdata = { | |||
1575 | * serial specs. Returns 0 on success, 1 on failure. | 1411 | * serial specs. Returns 0 on success, 1 on failure. |
1576 | */ | 1412 | */ |
1577 | static int __devinit | 1413 | static int __devinit |
1578 | serial_pci_guess_board(struct pci_dev *dev, struct pci_board *board) | 1414 | serial_pci_guess_board(struct pci_dev *dev, struct pciserial_board *board) |
1579 | { | 1415 | { |
1580 | int num_iomem, num_port, first_port = -1, i; | 1416 | int num_iomem, num_port, first_port = -1, i; |
1581 | 1417 | ||
@@ -1640,7 +1476,8 @@ serial_pci_guess_board(struct pci_dev *dev, struct pci_board *board) | |||
1640 | } | 1476 | } |
1641 | 1477 | ||
1642 | static inline int | 1478 | static inline int |
1643 | serial_pci_matches(struct pci_board *board, struct pci_board *guessed) | 1479 | serial_pci_matches(struct pciserial_board *board, |
1480 | struct pciserial_board *guessed) | ||
1644 | { | 1481 | { |
1645 | return | 1482 | return |
1646 | board->num_ports == guessed->num_ports && | 1483 | board->num_ports == guessed->num_ports && |
@@ -1650,58 +1487,14 @@ serial_pci_matches(struct pci_board *board, struct pci_board *guessed) | |||
1650 | board->first_offset == guessed->first_offset; | 1487 | board->first_offset == guessed->first_offset; |
1651 | } | 1488 | } |
1652 | 1489 | ||
1653 | /* | 1490 | struct serial_private * |
1654 | * Probe one serial board. Unfortunately, there is no rhyme nor reason | 1491 | pciserial_init_ports(struct pci_dev *dev, struct pciserial_board *board) |
1655 | * to the arrangement of serial ports on a PCI card. | ||
1656 | */ | ||
1657 | static int __devinit | ||
1658 | pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent) | ||
1659 | { | 1492 | { |
1493 | struct uart_port serial_port; | ||
1660 | struct serial_private *priv; | 1494 | struct serial_private *priv; |
1661 | struct pci_board *board, tmp; | ||
1662 | struct pci_serial_quirk *quirk; | 1495 | struct pci_serial_quirk *quirk; |
1663 | int rc, nr_ports, i; | 1496 | int rc, nr_ports, i; |
1664 | 1497 | ||
1665 | if (ent->driver_data >= ARRAY_SIZE(pci_boards)) { | ||
1666 | printk(KERN_ERR "pci_init_one: invalid driver_data: %ld\n", | ||
1667 | ent->driver_data); | ||
1668 | return -EINVAL; | ||
1669 | } | ||
1670 | |||
1671 | board = &pci_boards[ent->driver_data]; | ||
1672 | |||
1673 | rc = pci_enable_device(dev); | ||
1674 | if (rc) | ||
1675 | return rc; | ||
1676 | |||
1677 | if (ent->driver_data == pbn_default) { | ||
1678 | /* | ||
1679 | * Use a copy of the pci_board entry for this; | ||
1680 | * avoid changing entries in the table. | ||
1681 | */ | ||
1682 | memcpy(&tmp, board, sizeof(struct pci_board)); | ||
1683 | board = &tmp; | ||
1684 | |||
1685 | /* | ||
1686 | * We matched one of our class entries. Try to | ||
1687 | * determine the parameters of this board. | ||
1688 | */ | ||
1689 | rc = serial_pci_guess_board(dev, board); | ||
1690 | if (rc) | ||
1691 | goto disable; | ||
1692 | } else { | ||
1693 | /* | ||
1694 | * We matched an explicit entry. If we are able to | ||
1695 | * detect this boards settings with our heuristic, | ||
1696 | * then we no longer need this entry. | ||
1697 | */ | ||
1698 | memcpy(&tmp, &pci_boards[pbn_default], sizeof(struct pci_board)); | ||
1699 | rc = serial_pci_guess_board(dev, &tmp); | ||
1700 | if (rc == 0 && serial_pci_matches(board, &tmp)) | ||
1701 | moan_device("Redundant entry in serial pci_table.", | ||
1702 | dev); | ||
1703 | } | ||
1704 | |||
1705 | nr_ports = board->num_ports; | 1498 | nr_ports = board->num_ports; |
1706 | 1499 | ||
1707 | /* | 1500 | /* |
@@ -1718,8 +1511,10 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent) | |||
1718 | */ | 1511 | */ |
1719 | if (quirk->init) { | 1512 | if (quirk->init) { |
1720 | rc = quirk->init(dev); | 1513 | rc = quirk->init(dev); |
1721 | if (rc < 0) | 1514 | if (rc < 0) { |
1722 | goto disable; | 1515 | priv = ERR_PTR(rc); |
1516 | goto err_out; | ||
1517 | } | ||
1723 | if (rc) | 1518 | if (rc) |
1724 | nr_ports = rc; | 1519 | nr_ports = rc; |
1725 | } | 1520 | } |
@@ -1728,27 +1523,26 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent) | |||
1728 | sizeof(unsigned int) * nr_ports, | 1523 | sizeof(unsigned int) * nr_ports, |
1729 | GFP_KERNEL); | 1524 | GFP_KERNEL); |
1730 | if (!priv) { | 1525 | if (!priv) { |
1731 | rc = -ENOMEM; | 1526 | priv = ERR_PTR(-ENOMEM); |
1732 | goto deinit; | 1527 | goto err_deinit; |
1733 | } | 1528 | } |
1734 | 1529 | ||
1735 | memset(priv, 0, sizeof(struct serial_private) + | 1530 | memset(priv, 0, sizeof(struct serial_private) + |
1736 | sizeof(unsigned int) * nr_ports); | 1531 | sizeof(unsigned int) * nr_ports); |
1737 | 1532 | ||
1533 | priv->dev = dev; | ||
1738 | priv->quirk = quirk; | 1534 | priv->quirk = quirk; |
1739 | pci_set_drvdata(dev, priv); | 1535 | |
1536 | memset(&serial_port, 0, sizeof(struct uart_port)); | ||
1537 | serial_port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ; | ||
1538 | serial_port.uartclk = board->base_baud * 16; | ||
1539 | serial_port.irq = get_pci_irq(dev, board); | ||
1540 | serial_port.dev = &dev->dev; | ||
1740 | 1541 | ||
1741 | for (i = 0; i < nr_ports; i++) { | 1542 | for (i = 0; i < nr_ports; i++) { |
1742 | struct uart_port serial_port; | 1543 | if (quirk->setup(priv, board, &serial_port, i)) |
1743 | memset(&serial_port, 0, sizeof(struct uart_port)); | ||
1744 | |||
1745 | serial_port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | | ||
1746 | UPF_SHARE_IRQ; | ||
1747 | serial_port.uartclk = board->base_baud * 16; | ||
1748 | serial_port.irq = get_pci_irq(dev, board, i); | ||
1749 | serial_port.dev = &dev->dev; | ||
1750 | if (quirk->setup(dev, board, &serial_port, i)) | ||
1751 | break; | 1544 | break; |
1545 | |||
1752 | #ifdef SERIAL_DEBUG_PCI | 1546 | #ifdef SERIAL_DEBUG_PCI |
1753 | printk("Setup PCI port: port %x, irq %d, type %d\n", | 1547 | printk("Setup PCI port: port %x, irq %d, type %d\n", |
1754 | serial_port.iobase, serial_port.irq, serial_port.iotype); | 1548 | serial_port.iobase, serial_port.irq, serial_port.iotype); |
@@ -1763,24 +1557,21 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent) | |||
1763 | 1557 | ||
1764 | priv->nr = i; | 1558 | priv->nr = i; |
1765 | 1559 | ||
1766 | return 0; | 1560 | return priv; |
1767 | 1561 | ||
1768 | deinit: | 1562 | err_deinit: |
1769 | if (quirk->exit) | 1563 | if (quirk->exit) |
1770 | quirk->exit(dev); | 1564 | quirk->exit(dev); |
1771 | disable: | 1565 | err_out: |
1772 | pci_disable_device(dev); | 1566 | return priv; |
1773 | return rc; | ||
1774 | } | 1567 | } |
1568 | EXPORT_SYMBOL_GPL(pciserial_init_ports); | ||
1775 | 1569 | ||
1776 | static void __devexit pciserial_remove_one(struct pci_dev *dev) | 1570 | void pciserial_remove_ports(struct serial_private *priv) |
1777 | { | 1571 | { |
1778 | struct serial_private *priv = pci_get_drvdata(dev); | ||
1779 | struct pci_serial_quirk *quirk; | 1572 | struct pci_serial_quirk *quirk; |
1780 | int i; | 1573 | int i; |
1781 | 1574 | ||
1782 | pci_set_drvdata(dev, NULL); | ||
1783 | |||
1784 | for (i = 0; i < priv->nr; i++) | 1575 | for (i = 0; i < priv->nr; i++) |
1785 | serial8250_unregister_port(priv->line[i]); | 1576 | serial8250_unregister_port(priv->line[i]); |
1786 | 1577 | ||
@@ -1793,25 +1584,123 @@ static void __devexit pciserial_remove_one(struct pci_dev *dev) | |||
1793 | /* | 1584 | /* |
1794 | * Find the exit quirks. | 1585 | * Find the exit quirks. |
1795 | */ | 1586 | */ |
1796 | quirk = find_quirk(dev); | 1587 | quirk = find_quirk(priv->dev); |
1797 | if (quirk->exit) | 1588 | if (quirk->exit) |
1798 | quirk->exit(dev); | 1589 | quirk->exit(priv->dev); |
1590 | |||
1591 | kfree(priv); | ||
1592 | } | ||
1593 | EXPORT_SYMBOL_GPL(pciserial_remove_ports); | ||
1594 | |||
1595 | void pciserial_suspend_ports(struct serial_private *priv) | ||
1596 | { | ||
1597 | int i; | ||
1598 | |||
1599 | for (i = 0; i < priv->nr; i++) | ||
1600 | if (priv->line[i] >= 0) | ||
1601 | serial8250_suspend_port(priv->line[i]); | ||
1602 | } | ||
1603 | EXPORT_SYMBOL_GPL(pciserial_suspend_ports); | ||
1604 | |||
1605 | void pciserial_resume_ports(struct serial_private *priv) | ||
1606 | { | ||
1607 | int i; | ||
1608 | |||
1609 | /* | ||
1610 | * Ensure that the board is correctly configured. | ||
1611 | */ | ||
1612 | if (priv->quirk->init) | ||
1613 | priv->quirk->init(priv->dev); | ||
1614 | |||
1615 | for (i = 0; i < priv->nr; i++) | ||
1616 | if (priv->line[i] >= 0) | ||
1617 | serial8250_resume_port(priv->line[i]); | ||
1618 | } | ||
1619 | EXPORT_SYMBOL_GPL(pciserial_resume_ports); | ||
1620 | |||
1621 | /* | ||
1622 | * Probe one serial board. Unfortunately, there is no rhyme nor reason | ||
1623 | * to the arrangement of serial ports on a PCI card. | ||
1624 | */ | ||
1625 | static int __devinit | ||
1626 | pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent) | ||
1627 | { | ||
1628 | struct serial_private *priv; | ||
1629 | struct pciserial_board *board, tmp; | ||
1630 | int rc; | ||
1631 | |||
1632 | if (ent->driver_data >= ARRAY_SIZE(pci_boards)) { | ||
1633 | printk(KERN_ERR "pci_init_one: invalid driver_data: %ld\n", | ||
1634 | ent->driver_data); | ||
1635 | return -EINVAL; | ||
1636 | } | ||
1637 | |||
1638 | board = &pci_boards[ent->driver_data]; | ||
1639 | |||
1640 | rc = pci_enable_device(dev); | ||
1641 | if (rc) | ||
1642 | return rc; | ||
1643 | |||
1644 | if (ent->driver_data == pbn_default) { | ||
1645 | /* | ||
1646 | * Use a copy of the pci_board entry for this; | ||
1647 | * avoid changing entries in the table. | ||
1648 | */ | ||
1649 | memcpy(&tmp, board, sizeof(struct pciserial_board)); | ||
1650 | board = &tmp; | ||
1651 | |||
1652 | /* | ||
1653 | * We matched one of our class entries. Try to | ||
1654 | * determine the parameters of this board. | ||
1655 | */ | ||
1656 | rc = serial_pci_guess_board(dev, board); | ||
1657 | if (rc) | ||
1658 | goto disable; | ||
1659 | } else { | ||
1660 | /* | ||
1661 | * We matched an explicit entry. If we are able to | ||
1662 | * detect this boards settings with our heuristic, | ||
1663 | * then we no longer need this entry. | ||
1664 | */ | ||
1665 | memcpy(&tmp, &pci_boards[pbn_default], | ||
1666 | sizeof(struct pciserial_board)); | ||
1667 | rc = serial_pci_guess_board(dev, &tmp); | ||
1668 | if (rc == 0 && serial_pci_matches(board, &tmp)) | ||
1669 | moan_device("Redundant entry in serial pci_table.", | ||
1670 | dev); | ||
1671 | } | ||
1799 | 1672 | ||
1673 | priv = pciserial_init_ports(dev, board); | ||
1674 | if (!IS_ERR(priv)) { | ||
1675 | pci_set_drvdata(dev, priv); | ||
1676 | return 0; | ||
1677 | } | ||
1678 | |||
1679 | rc = PTR_ERR(priv); | ||
1680 | |||
1681 | disable: | ||
1800 | pci_disable_device(dev); | 1682 | pci_disable_device(dev); |
1683 | return rc; | ||
1684 | } | ||
1801 | 1685 | ||
1802 | kfree(priv); | 1686 | static void __devexit pciserial_remove_one(struct pci_dev *dev) |
1687 | { | ||
1688 | struct serial_private *priv = pci_get_drvdata(dev); | ||
1689 | |||
1690 | pci_set_drvdata(dev, NULL); | ||
1691 | |||
1692 | pciserial_remove_ports(priv); | ||
1693 | |||
1694 | pci_disable_device(dev); | ||
1803 | } | 1695 | } |
1804 | 1696 | ||
1805 | static int pciserial_suspend_one(struct pci_dev *dev, pm_message_t state) | 1697 | static int pciserial_suspend_one(struct pci_dev *dev, pm_message_t state) |
1806 | { | 1698 | { |
1807 | struct serial_private *priv = pci_get_drvdata(dev); | 1699 | struct serial_private *priv = pci_get_drvdata(dev); |
1808 | 1700 | ||
1809 | if (priv) { | 1701 | if (priv) |
1810 | int i; | 1702 | pciserial_suspend_ports(priv); |
1811 | 1703 | ||
1812 | for (i = 0; i < priv->nr; i++) | ||
1813 | serial8250_suspend_port(priv->line[i]); | ||
1814 | } | ||
1815 | pci_save_state(dev); | 1704 | pci_save_state(dev); |
1816 | pci_set_power_state(dev, pci_choose_state(dev, state)); | 1705 | pci_set_power_state(dev, pci_choose_state(dev, state)); |
1817 | return 0; | 1706 | return 0; |
@@ -1825,21 +1714,12 @@ static int pciserial_resume_one(struct pci_dev *dev) | |||
1825 | pci_restore_state(dev); | 1714 | pci_restore_state(dev); |
1826 | 1715 | ||
1827 | if (priv) { | 1716 | if (priv) { |
1828 | int i; | ||
1829 | |||
1830 | /* | 1717 | /* |
1831 | * The device may have been disabled. Re-enable it. | 1718 | * The device may have been disabled. Re-enable it. |
1832 | */ | 1719 | */ |
1833 | pci_enable_device(dev); | 1720 | pci_enable_device(dev); |
1834 | 1721 | ||
1835 | /* | 1722 | pciserial_resume_ports(priv); |
1836 | * Ensure that the board is correctly configured. | ||
1837 | */ | ||
1838 | if (priv->quirk->init) | ||
1839 | priv->quirk->init(dev); | ||
1840 | |||
1841 | for (i = 0; i < priv->nr; i++) | ||
1842 | serial8250_resume_port(priv->line[i]); | ||
1843 | } | 1723 | } |
1844 | return 0; | 1724 | return 0; |
1845 | } | 1725 | } |