linux/drivers/parport/parport_serial.c
<<
>>
Prefs
   1/*
   2 * Support for common PCI multi-I/O cards (which is most of them)
   3 *
   4 * Copyright (C) 2001  Tim Waugh <twaugh@redhat.com>
   5 *
   6 * This program is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU General Public License
   8 * as published by the Free Software Foundation; either version
   9 * 2 of the License, or (at your option) any later version.
  10 *
  11 *
  12 * Multi-function PCI cards are supposed to present separate logical
  13 * devices on the bus.  A common thing to do seems to be to just use
  14 * one logical device with lots of base address registers for both
  15 * parallel ports and serial ports.  This driver is for dealing with
  16 * that.
  17 *
  18 */
  19
  20#include <linux/types.h>
  21#include <linux/module.h>
  22#include <linux/init.h>
  23#include <linux/pci.h>
  24#include <linux/parport.h>
  25#include <linux/parport_pc.h>
  26#include <linux/8250_pci.h>
  27
  28enum parport_pc_pci_cards {
  29        titan_110l = 0,
  30        titan_210l,
  31        netmos_9xx5_combo,
  32        netmos_9855,
  33        avlab_1s1p,
  34        avlab_1s2p,
  35        avlab_2s1p,
  36        siig_1s1p_10x,
  37        siig_2s1p_10x,
  38        siig_2p1s_20x,
  39        siig_1s1p_20x,
  40        siig_2s1p_20x,
  41};
  42
  43/* each element directly indexed from enum list, above */
  44struct parport_pc_pci {
  45        int numports;
  46        struct { /* BAR (base address registers) numbers in the config
  47                    space header */
  48                int lo;
  49                int hi; /* -1 if not there, >6 for offset-method (max
  50                           BAR is 6) */
  51        } addr[4];
  52
  53        /* If set, this is called immediately after pci_enable_device.
  54         * If it returns non-zero, no probing will take place and the
  55         * ports will not be used. */
  56        int (*preinit_hook) (struct pci_dev *pdev, struct parport_pc_pci *card,
  57                                int autoirq, int autodma);
  58
  59        /* If set, this is called after probing for ports.  If 'failed'
  60         * is non-zero we couldn't use any of the ports. */
  61        void (*postinit_hook) (struct pci_dev *pdev,
  62                                struct parport_pc_pci *card, int failed);
  63};
  64
  65static int __devinit netmos_parallel_init(struct pci_dev *dev, struct parport_pc_pci *card, int autoirq, int autodma)
  66{
  67        /*
  68         * Netmos uses the subdevice ID to indicate the number of parallel
  69         * and serial ports.  The form is 0x00PS, where <P> is the number of
  70         * parallel ports and <S> is the number of serial ports.
  71         */
  72        card->numports = (dev->subsystem_device & 0xf0) >> 4;
  73        return 0;
  74}
  75
  76static struct parport_pc_pci cards[] __devinitdata = {
  77        /* titan_110l */                { 1, { { 3, -1 }, } },
  78        /* titan_210l */                { 1, { { 3, -1 }, } },
  79        /* netmos_9xx5_combo */         { 1, { { 2, -1 }, }, netmos_parallel_init },
  80        /* netmos_9855 */               { 1, { { 2, -1 }, }, netmos_parallel_init },
  81        /* avlab_1s1p     */            { 1, { { 1, 2}, } },
  82        /* avlab_1s2p     */            { 2, { { 1, 2}, { 3, 4 },} },
  83        /* avlab_2s1p     */            { 1, { { 2, 3}, } },
  84        /* siig_1s1p_10x */             { 1, { { 3, 4 }, } },
  85        /* siig_2s1p_10x */             { 1, { { 4, 5 }, } },
  86        /* siig_2p1s_20x */             { 2, { { 1, 2 }, { 3, 4 }, } },
  87        /* siig_1s1p_20x */             { 1, { { 1, 2 }, } },
  88        /* siig_2s1p_20x */             { 1, { { 2, 3 }, } },
  89};
  90
  91static struct pci_device_id parport_serial_pci_tbl[] = {
  92        /* PCI cards */
  93        { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_110L,
  94          PCI_ANY_ID, PCI_ANY_ID, 0, 0, titan_110l },
  95        { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_210L,
  96          PCI_ANY_ID, PCI_ANY_ID, 0, 0, titan_210l },
  97        { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9735,
  98          PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9xx5_combo },
  99        { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9745,
 100          PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9xx5_combo },
 101        { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9835,
 102          PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9xx5_combo },
 103        { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9845,
 104          PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9xx5_combo },
 105        { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9855,
 106          PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9855 },
 107        /* PCI_VENDOR_ID_AVLAB/Intek21 has another bunch of cards ...*/
 108        { PCI_VENDOR_ID_AFAVLAB, 0x2110,
 109          PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p },
 110        { PCI_VENDOR_ID_AFAVLAB, 0x2111,
 111          PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p },
 112        { PCI_VENDOR_ID_AFAVLAB, 0x2112,
 113          PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p },
 114        { PCI_VENDOR_ID_AFAVLAB, 0x2140,
 115          PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s2p },
 116        { PCI_VENDOR_ID_AFAVLAB, 0x2141,
 117          PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s2p },
 118        { PCI_VENDOR_ID_AFAVLAB, 0x2142,
 119          PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s2p },
 120        { PCI_VENDOR_ID_AFAVLAB, 0x2160,
 121          PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2s1p },
 122        { PCI_VENDOR_ID_AFAVLAB, 0x2161,
 123          PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2s1p },
 124        { PCI_VENDOR_ID_AFAVLAB, 0x2162,
 125          PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2s1p },
 126        { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_550,
 127          PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_10x },
 128        { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_650,
 129          PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_10x },
 130        { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_850,
 131          PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_10x },
 132        { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_550,
 133          PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_10x },
 134        { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_650,
 135          PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_10x },
 136        { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_850,
 137          PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_10x },
 138        { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_550,
 139          PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2p1s_20x },
 140        { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_650,
 141          PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2p1s_20x },
 142        { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_850,
 143          PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2p1s_20x },
 144        { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_550,
 145          PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
 146        { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_650,
 147          PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_20x },
 148        { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_850,
 149          PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_20x },
 150        { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_550,
 151          PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
 152        { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_650,
 153          PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
 154        { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_850,
 155          PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
 156
 157        { 0, } /* terminate list */
 158};
 159MODULE_DEVICE_TABLE(pci,parport_serial_pci_tbl);
 160
 161/*
 162 * This table describes the serial "geometry" of these boards.  Any
 163 * quirks for these can be found in drivers/serial/8250_pci.c
 164 *
 165 * Cards not tested are marked n/t
 166 * If you have one of these cards and it works for you, please tell me..
 167 */
 168static struct pciserial_board pci_parport_serial_boards[] __devinitdata = {
 169        [titan_110l] = {
 170                .flags          = FL_BASE1 | FL_BASE_BARS,
 171                .num_ports      = 1,
 172                .base_baud      = 921600,
 173                .uart_offset    = 8,
 174        },
 175        [titan_210l] = {
 176                .flags          = FL_BASE1 | FL_BASE_BARS,
 177                .num_ports      = 2,
 178                .base_baud      = 921600,
 179                .uart_offset    = 8,
 180        },
 181        [netmos_9xx5_combo] = {
 182                .flags          = FL_BASE0 | FL_BASE_BARS,
 183                .num_ports      = 1,
 184                .base_baud      = 115200,
 185                .uart_offset    = 8,
 186        },
 187        [netmos_9855] = {
 188                .flags          = FL_BASE4 | FL_BASE_BARS,
 189                .num_ports      = 1,
 190                .base_baud      = 115200,
 191                .uart_offset    = 8,
 192        },
 193        [avlab_1s1p] = { /* n/t */
 194                .flags          = FL_BASE0 | FL_BASE_BARS,
 195                .num_ports      = 1,
 196                .base_baud      = 115200,
 197                .uart_offset    = 8,
 198        },
 199        [avlab_1s2p] = { /* n/t */
 200                .flags          = FL_BASE0 | FL_BASE_BARS,
 201                .num_ports      = 1,
 202                .base_baud      = 115200,
 203                .uart_offset    = 8,
 204        },
 205        [avlab_2s1p] = { /* n/t */
 206                .flags          = FL_BASE0 | FL_BASE_BARS,
 207                .num_ports      = 2,
 208                .base_baud      = 115200,
 209                .uart_offset    = 8,
 210        },
 211        [siig_1s1p_10x] = {
 212                .flags          = FL_BASE2,
 213                .num_ports      = 1,
 214                .base_baud      = 460800,
 215                .uart_offset    = 8,
 216        },
 217        [siig_2s1p_10x] = {
 218                .flags          = FL_BASE2,
 219                .num_ports      = 1,
 220                .base_baud      = 921600,
 221                .uart_offset    = 8,
 222        },
 223        [siig_2p1s_20x] = {
 224                .flags          = FL_BASE0,
 225                .num_ports      = 1,
 226                .base_baud      = 921600,
 227                .uart_offset    = 8,
 228        },
 229        [siig_1s1p_20x] = {
 230                .flags          = FL_BASE0,
 231                .num_ports      = 1,
 232                .base_baud      = 921600,
 233                .uart_offset    = 8,
 234        },
 235        [siig_2s1p_20x] = {
 236                .flags          = FL_BASE0,
 237                .num_ports      = 1,
 238                .base_baud      = 921600,
 239                .uart_offset    = 8,
 240        },
 241};
 242
 243struct parport_serial_private {
 244        struct serial_private   *serial;
 245        int num_par;
 246        struct parport *port[PARPORT_MAX];
 247        struct parport_pc_pci par;
 248};
 249
 250/* Register the serial port(s) of a PCI card. */
 251static int __devinit serial_register (struct pci_dev *dev,
 252                                      const struct pci_device_id *id)
 253{
 254        struct parport_serial_private *priv = pci_get_drvdata (dev);
 255        struct pciserial_board *board;
 256        struct serial_private *serial;
 257
 258        board = &pci_parport_serial_boards[id->driver_data];
 259        serial = pciserial_init_ports(dev, board);
 260
 261        if (IS_ERR(serial))
 262                return PTR_ERR(serial);
 263
 264        priv->serial = serial;
 265        return 0;
 266}
 267
 268/* Register the parallel port(s) of a PCI card. */
 269static int __devinit parport_register (struct pci_dev *dev,
 270                                       const struct pci_device_id *id)
 271{
 272        struct parport_pc_pci *card;
 273        struct parport_serial_private *priv = pci_get_drvdata (dev);
 274        int n, success = 0;
 275
 276        priv->par = cards[id->driver_data];
 277        card = &priv->par;
 278        if (card->preinit_hook &&
 279            card->preinit_hook (dev, card, PARPORT_IRQ_NONE, PARPORT_DMA_NONE))
 280                return -ENODEV;
 281
 282        for (n = 0; n < card->numports; n++) {
 283                struct parport *port;
 284                int lo = card->addr[n].lo;
 285                int hi = card->addr[n].hi;
 286                unsigned long io_lo, io_hi;
 287
 288                if (priv->num_par == ARRAY_SIZE (priv->port)) {
 289                        printk (KERN_WARNING
 290                                "parport_serial: %s: only %zu parallel ports "
 291                                "supported (%d reported)\n", pci_name (dev),
 292                                ARRAY_SIZE(priv->port), card->numports);
 293                        break;
 294                }
 295
 296                io_lo = pci_resource_start (dev, lo);
 297                io_hi = 0;
 298                if ((hi >= 0) && (hi <= 6))
 299                        io_hi = pci_resource_start (dev, hi);
 300                else if (hi > 6)
 301                        io_lo += hi; /* Reinterpret the meaning of
 302                                        "hi" as an offset (see SYBA
 303                                        def.) */
 304                /* TODO: test if sharing interrupts works */
 305                dev_dbg(&dev->dev, "PCI parallel port detected: I/O at "
 306                        "%#lx(%#lx)\n", io_lo, io_hi);
 307                port = parport_pc_probe_port (io_lo, io_hi, PARPORT_IRQ_NONE,
 308                                              PARPORT_DMA_NONE, &dev->dev);
 309                if (port) {
 310                        priv->port[priv->num_par++] = port;
 311                        success = 1;
 312                }
 313        }
 314
 315        if (card->postinit_hook)
 316                card->postinit_hook (dev, card, !success);
 317
 318        return 0;
 319}
 320
 321static int __devinit parport_serial_pci_probe (struct pci_dev *dev,
 322                                               const struct pci_device_id *id)
 323{
 324        struct parport_serial_private *priv;
 325        int err;
 326
 327        priv = kzalloc (sizeof *priv, GFP_KERNEL);
 328        if (!priv)
 329                return -ENOMEM;
 330        pci_set_drvdata (dev, priv);
 331
 332        err = pci_enable_device (dev);
 333        if (err) {
 334                pci_set_drvdata (dev, NULL);
 335                kfree (priv);
 336                return err;
 337        }
 338
 339        if (parport_register (dev, id)) {
 340                pci_set_drvdata (dev, NULL);
 341                kfree (priv);
 342                return -ENODEV;
 343        }
 344
 345        if (serial_register (dev, id)) {
 346                int i;
 347                for (i = 0; i < priv->num_par; i++)
 348                        parport_pc_unregister_port (priv->port[i]);
 349                pci_set_drvdata (dev, NULL);
 350                kfree (priv);
 351                return -ENODEV;
 352        }
 353
 354        return 0;
 355}
 356
 357static void __devexit parport_serial_pci_remove (struct pci_dev *dev)
 358{
 359        struct parport_serial_private *priv = pci_get_drvdata (dev);
 360        int i;
 361
 362        pci_set_drvdata(dev, NULL);
 363
 364        // Serial ports
 365        if (priv->serial)
 366                pciserial_remove_ports(priv->serial);
 367
 368        // Parallel ports
 369        for (i = 0; i < priv->num_par; i++)
 370                parport_pc_unregister_port (priv->port[i]);
 371
 372        kfree (priv);
 373        return;
 374}
 375
 376#ifdef CONFIG_PM
 377static int parport_serial_pci_suspend(struct pci_dev *dev, pm_message_t state)
 378{
 379        struct parport_serial_private *priv = pci_get_drvdata(dev);
 380
 381        if (priv->serial)
 382                pciserial_suspend_ports(priv->serial);
 383
 384        /* FIXME: What about parport? */
 385
 386        pci_save_state(dev);
 387        pci_set_power_state(dev, pci_choose_state(dev, state));
 388        return 0;
 389}
 390
 391static int parport_serial_pci_resume(struct pci_dev *dev)
 392{
 393        struct parport_serial_private *priv = pci_get_drvdata(dev);
 394        int err;
 395
 396        pci_set_power_state(dev, PCI_D0);
 397        pci_restore_state(dev);
 398
 399        /*
 400         * The device may have been disabled.  Re-enable it.
 401         */
 402        err = pci_enable_device(dev);
 403        if (err) {
 404                printk(KERN_ERR "parport_serial: %s: error enabling "
 405                        "device for resume (%d)\n", pci_name(dev), err);
 406                return err;
 407        }
 408
 409        if (priv->serial)
 410                pciserial_resume_ports(priv->serial);
 411
 412        /* FIXME: What about parport? */
 413
 414        return 0;
 415}
 416#endif
 417
 418static struct pci_driver parport_serial_pci_driver = {
 419        .name           = "parport_serial",
 420        .id_table       = parport_serial_pci_tbl,
 421        .probe          = parport_serial_pci_probe,
 422        .remove         = __devexit_p(parport_serial_pci_remove),
 423#ifdef CONFIG_PM
 424        .suspend        = parport_serial_pci_suspend,
 425        .resume         = parport_serial_pci_resume,
 426#endif
 427};
 428
 429
 430static int __init parport_serial_init (void)
 431{
 432        return pci_register_driver (&parport_serial_pci_driver);
 433}
 434
 435static void __exit parport_serial_exit (void)
 436{
 437        pci_unregister_driver (&parport_serial_pci_driver);
 438        return;
 439}
 440
 441MODULE_AUTHOR("Tim Waugh <twaugh@redhat.com>");
 442MODULE_DESCRIPTION("Driver for common parallel+serial multi-I/O PCI cards");
 443MODULE_LICENSE("GPL");
 444
 445module_init(parport_serial_init);
 446module_exit(parport_serial_exit);
 447
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.