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/slab.h>
  24#include <linux/pci.h>
  25#include <linux/interrupt.h>
  26#include <linux/parport.h>
  27#include <linux/parport_pc.h>
  28#include <linux/8250_pci.h>
  29
  30enum parport_pc_pci_cards {
  31        titan_110l = 0,
  32        titan_210l,
  33        netmos_9xx5_combo,
  34        netmos_9855,
  35        netmos_9855_2p,
  36        netmos_9900,
  37        netmos_9900_2p,
  38        netmos_99xx_1p,
  39        avlab_1s1p,
  40        avlab_1s2p,
  41        avlab_2s1p,
  42        siig_1s1p_10x,
  43        siig_2s1p_10x,
  44        siig_2p1s_20x,
  45        siig_1s1p_20x,
  46        siig_2s1p_20x,
  47        timedia_4078a,
  48        timedia_4079h,
  49        timedia_4085h,
  50        timedia_4088a,
  51        timedia_4089a,
  52        timedia_4095a,
  53        timedia_4096a,
  54        timedia_4078u,
  55        timedia_4079a,
  56        timedia_4085u,
  57        timedia_4079r,
  58        timedia_4079s,
  59        timedia_4079d,
  60        timedia_4079e,
  61        timedia_4079f,
  62        timedia_9079a,
  63        timedia_9079b,
  64        timedia_9079c,
  65        wch_ch353_2s1p,
  66};
  67
  68/* each element directly indexed from enum list, above */
  69struct parport_pc_pci {
  70        int numports;
  71        struct { /* BAR (base address registers) numbers in the config
  72                    space header */
  73                int lo;
  74                int hi; /* -1 if not there, >6 for offset-method (max
  75                           BAR is 6) */
  76        } addr[4];
  77
  78        /* If set, this is called immediately after pci_enable_device.
  79         * If it returns non-zero, no probing will take place and the
  80         * ports will not be used. */
  81        int (*preinit_hook) (struct pci_dev *pdev, struct parport_pc_pci *card,
  82                                int autoirq, int autodma);
  83
  84        /* If set, this is called after probing for ports.  If 'failed'
  85         * is non-zero we couldn't use any of the ports. */
  86        void (*postinit_hook) (struct pci_dev *pdev,
  87                                struct parport_pc_pci *card, int failed);
  88};
  89
  90static int netmos_parallel_init(struct pci_dev *dev, struct parport_pc_pci *par,
  91                                int autoirq, int autodma)
  92{
  93        /* the rule described below doesn't hold for this device */
  94        if (dev->device == PCI_DEVICE_ID_NETMOS_9835 &&
  95                        dev->subsystem_vendor == PCI_VENDOR_ID_IBM &&
  96                        dev->subsystem_device == 0x0299)
  97                return -ENODEV;
  98
  99        if (dev->device == PCI_DEVICE_ID_NETMOS_9912) {
 100                par->numports = 1;
 101        } else {
 102                /*
 103                 * Netmos uses the subdevice ID to indicate the number of parallel
 104                 * and serial ports.  The form is 0x00PS, where <P> is the number of
 105                 * parallel ports and <S> is the number of serial ports.
 106                 */
 107                par->numports = (dev->subsystem_device & 0xf0) >> 4;
 108                if (par->numports > ARRAY_SIZE(par->addr))
 109                        par->numports = ARRAY_SIZE(par->addr);
 110        }
 111
 112        return 0;
 113}
 114
 115static struct parport_pc_pci cards[] = {
 116        /* titan_110l */                { 1, { { 3, -1 }, } },
 117        /* titan_210l */                { 1, { { 3, -1 }, } },
 118        /* netmos_9xx5_combo */         { 1, { { 2, -1 }, }, netmos_parallel_init },
 119        /* netmos_9855 */               { 1, { { 0, -1 }, }, netmos_parallel_init },
 120        /* netmos_9855_2p */            { 2, { { 0, -1 }, { 2, -1 }, } },
 121        /* netmos_9900 */               {1, { { 3, 4 }, }, netmos_parallel_init },
 122        /* netmos_9900_2p */            {2, { { 0, 1 }, { 3, 4 }, } },
 123        /* netmos_99xx_1p */            {1, { { 0, 1 }, } },
 124        /* avlab_1s1p     */            { 1, { { 1, 2}, } },
 125        /* avlab_1s2p     */            { 2, { { 1, 2}, { 3, 4 },} },
 126        /* avlab_2s1p     */            { 1, { { 2, 3}, } },
 127        /* siig_1s1p_10x */             { 1, { { 3, 4 }, } },
 128        /* siig_2s1p_10x */             { 1, { { 4, 5 }, } },
 129        /* siig_2p1s_20x */             { 2, { { 1, 2 }, { 3, 4 }, } },
 130        /* siig_1s1p_20x */             { 1, { { 1, 2 }, } },
 131        /* siig_2s1p_20x */             { 1, { { 2, 3 }, } },
 132        /* timedia_4078a */             { 1, { { 2, -1 }, } },
 133        /* timedia_4079h */             { 1, { { 2, 3 }, } },
 134        /* timedia_4085h */             { 2, { { 2, -1 }, { 4, -1 }, } },
 135        /* timedia_4088a */             { 2, { { 2, 3 }, { 4, 5 }, } },
 136        /* timedia_4089a */             { 2, { { 2, 3 }, { 4, 5 }, } },
 137        /* timedia_4095a */             { 2, { { 2, 3 }, { 4, 5 }, } },
 138        /* timedia_4096a */             { 2, { { 2, 3 }, { 4, 5 }, } },
 139        /* timedia_4078u */             { 1, { { 2, -1 }, } },
 140        /* timedia_4079a */             { 1, { { 2, 3 }, } },
 141        /* timedia_4085u */             { 2, { { 2, -1 }, { 4, -1 }, } },
 142        /* timedia_4079r */             { 1, { { 2, 3 }, } },
 143        /* timedia_4079s */             { 1, { { 2, 3 }, } },
 144        /* timedia_4079d */             { 1, { { 2, 3 }, } },
 145        /* timedia_4079e */             { 1, { { 2, 3 }, } },
 146        /* timedia_4079f */             { 1, { { 2, 3 }, } },
 147        /* timedia_9079a */             { 1, { { 2, 3 }, } },
 148        /* timedia_9079b */             { 1, { { 2, 3 }, } },
 149        /* timedia_9079c */             { 1, { { 2, 3 }, } },
 150        /* wch_ch353_2s1p*/             { 1, { { 2, -1}, } },
 151};
 152
 153static struct pci_device_id parport_serial_pci_tbl[] = {
 154        /* PCI cards */
 155        { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_110L,
 156          PCI_ANY_ID, PCI_ANY_ID, 0, 0, titan_110l },
 157        { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_210L,
 158          PCI_ANY_ID, PCI_ANY_ID, 0, 0, titan_210l },
 159        { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9735,
 160          PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9xx5_combo },
 161        { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9745,
 162          PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9xx5_combo },
 163        { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9835,
 164          PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9xx5_combo },
 165        { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9845,
 166          PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9xx5_combo },
 167        { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9855,
 168          0x1000, 0x0020, 0, 0, netmos_9855_2p },
 169        { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9855,
 170          0x1000, 0x0022, 0, 0, netmos_9855_2p },
 171        { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9855,
 172          PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9855 },
 173        { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900,
 174          0xA000, 0x3011, 0, 0, netmos_9900 },
 175        { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900,
 176          0xA000, 0x3012, 0, 0, netmos_9900 },
 177        { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900,
 178          0xA000, 0x3020, 0, 0, netmos_9900_2p },
 179        { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9912,
 180          0xA000, 0x2000, 0, 0, netmos_99xx_1p },
 181        /* PCI_VENDOR_ID_AVLAB/Intek21 has another bunch of cards ...*/
 182        { PCI_VENDOR_ID_AFAVLAB, 0x2110,
 183          PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p },
 184        { PCI_VENDOR_ID_AFAVLAB, 0x2111,
 185          PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p },
 186        { PCI_VENDOR_ID_AFAVLAB, 0x2112,
 187          PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p },
 188        { PCI_VENDOR_ID_AFAVLAB, 0x2140,
 189          PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s2p },
 190        { PCI_VENDOR_ID_AFAVLAB, 0x2141,
 191          PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s2p },
 192        { PCI_VENDOR_ID_AFAVLAB, 0x2142,
 193          PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s2p },
 194        { PCI_VENDOR_ID_AFAVLAB, 0x2160,
 195          PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2s1p },
 196        { PCI_VENDOR_ID_AFAVLAB, 0x2161,
 197          PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2s1p },
 198        { PCI_VENDOR_ID_AFAVLAB, 0x2162,
 199          PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2s1p },
 200        { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_550,
 201          PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_10x },
 202        { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_650,
 203          PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_10x },
 204        { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_850,
 205          PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_10x },
 206        { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_550,
 207          PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_10x },
 208        { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_650,
 209          PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_10x },
 210        { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_850,
 211          PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_10x },
 212        { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_550,
 213          PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2p1s_20x },
 214        { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_650,
 215          PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2p1s_20x },
 216        { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_850,
 217          PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2p1s_20x },
 218        { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_550,
 219          PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
 220        { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_650,
 221          PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_20x },
 222        { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_850,
 223          PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_20x },
 224        { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_550,
 225          PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
 226        { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_650,
 227          PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
 228        { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_850,
 229          PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
 230        /* PCI_VENDOR_ID_TIMEDIA/SUNIX has many differing cards ...*/
 231        { 0x1409, 0x7168, 0x1409, 0x4078, 0, 0, timedia_4078a },
 232        { 0x1409, 0x7168, 0x1409, 0x4079, 0, 0, timedia_4079h },
 233        { 0x1409, 0x7168, 0x1409, 0x4085, 0, 0, timedia_4085h },
 234        { 0x1409, 0x7168, 0x1409, 0x4088, 0, 0, timedia_4088a },
 235        { 0x1409, 0x7168, 0x1409, 0x4089, 0, 0, timedia_4089a },
 236        { 0x1409, 0x7168, 0x1409, 0x4095, 0, 0, timedia_4095a },
 237        { 0x1409, 0x7168, 0x1409, 0x4096, 0, 0, timedia_4096a },
 238        { 0x1409, 0x7168, 0x1409, 0x5078, 0, 0, timedia_4078u },
 239        { 0x1409, 0x7168, 0x1409, 0x5079, 0, 0, timedia_4079a },
 240        { 0x1409, 0x7168, 0x1409, 0x5085, 0, 0, timedia_4085u },
 241        { 0x1409, 0x7168, 0x1409, 0x6079, 0, 0, timedia_4079r },
 242        { 0x1409, 0x7168, 0x1409, 0x7079, 0, 0, timedia_4079s },
 243        { 0x1409, 0x7168, 0x1409, 0x8079, 0, 0, timedia_4079d },
 244        { 0x1409, 0x7168, 0x1409, 0x9079, 0, 0, timedia_4079e },
 245        { 0x1409, 0x7168, 0x1409, 0xa079, 0, 0, timedia_4079f },
 246        { 0x1409, 0x7168, 0x1409, 0xb079, 0, 0, timedia_9079a },
 247        { 0x1409, 0x7168, 0x1409, 0xc079, 0, 0, timedia_9079b },
 248        { 0x1409, 0x7168, 0x1409, 0xd079, 0, 0, timedia_9079c },
 249        /* WCH CARDS */
 250        { 0x4348, 0x7053, 0x4348, 0x3253, 0, 0, wch_ch353_2s1p},
 251        { 0, } /* terminate list */
 252};
 253MODULE_DEVICE_TABLE(pci,parport_serial_pci_tbl);
 254
 255/*
 256 * This table describes the serial "geometry" of these boards.  Any
 257 * quirks for these can be found in drivers/serial/8250_pci.c
 258 *
 259 * Cards not tested are marked n/t
 260 * If you have one of these cards and it works for you, please tell me..
 261 */
 262static struct pciserial_board pci_parport_serial_boards[] = {
 263        [titan_110l] = {
 264                .flags          = FL_BASE1 | FL_BASE_BARS,
 265                .num_ports      = 1,
 266                .base_baud      = 921600,
 267                .uart_offset    = 8,
 268        },
 269        [titan_210l] = {
 270                .flags          = FL_BASE1 | FL_BASE_BARS,
 271                .num_ports      = 2,
 272                .base_baud      = 921600,
 273                .uart_offset    = 8,
 274        },
 275        [netmos_9xx5_combo] = {
 276                .flags          = FL_BASE0 | FL_BASE_BARS,
 277                .num_ports      = 1,
 278                .base_baud      = 115200,
 279                .uart_offset    = 8,
 280        },
 281        [netmos_9855] = {
 282                .flags          = FL_BASE2 | FL_BASE_BARS,
 283                .num_ports      = 1,
 284                .base_baud      = 115200,
 285                .uart_offset    = 8,
 286        },
 287        [netmos_9855_2p] = {
 288                .flags          = FL_BASE4 | FL_BASE_BARS,
 289                .num_ports      = 1,
 290                .base_baud      = 115200,
 291                .uart_offset    = 8,
 292        },
 293        [netmos_9900] = { /* n/t */
 294                .flags          = FL_BASE0 | FL_BASE_BARS,
 295                .num_ports      = 1,
 296                .base_baud      = 115200,
 297                .uart_offset    = 8,
 298        },
 299        [netmos_9900_2p] = { /* parallel only */ /* n/t */
 300                .flags          = FL_BASE0,
 301                .num_ports      = 0,
 302                .base_baud      = 115200,
 303                .uart_offset    = 8,
 304        },
 305        [netmos_99xx_1p] = { /* parallel only */ /* n/t */
 306                .flags          = FL_BASE0,
 307                .num_ports      = 0,
 308                .base_baud      = 115200,
 309                .uart_offset    = 8,
 310        },
 311        [avlab_1s1p] = { /* n/t */
 312                .flags          = FL_BASE0 | FL_BASE_BARS,
 313                .num_ports      = 1,
 314                .base_baud      = 115200,
 315                .uart_offset    = 8,
 316        },
 317        [avlab_1s2p] = { /* n/t */
 318                .flags          = FL_BASE0 | FL_BASE_BARS,
 319                .num_ports      = 1,
 320                .base_baud      = 115200,
 321                .uart_offset    = 8,
 322        },
 323        [avlab_2s1p] = { /* n/t */
 324                .flags          = FL_BASE0 | FL_BASE_BARS,
 325                .num_ports      = 2,
 326                .base_baud      = 115200,
 327                .uart_offset    = 8,
 328        },
 329        [siig_1s1p_10x] = {
 330                .flags          = FL_BASE2,
 331                .num_ports      = 1,
 332                .base_baud      = 460800,
 333                .uart_offset    = 8,
 334        },
 335        [siig_2s1p_10x] = {
 336                .flags          = FL_BASE2,
 337                .num_ports      = 1,
 338                .base_baud      = 921600,
 339                .uart_offset    = 8,
 340        },
 341        [siig_2p1s_20x] = {
 342                .flags          = FL_BASE0,
 343                .num_ports      = 1,
 344                .base_baud      = 921600,
 345                .uart_offset    = 8,
 346        },
 347        [siig_1s1p_20x] = {
 348                .flags          = FL_BASE0,
 349                .num_ports      = 1,
 350                .base_baud      = 921600,
 351                .uart_offset    = 8,
 352        },
 353        [siig_2s1p_20x] = {
 354                .flags          = FL_BASE0,
 355                .num_ports      = 1,
 356                .base_baud      = 921600,
 357                .uart_offset    = 8,
 358        },
 359        [timedia_4078a] = {
 360                .flags          = FL_BASE0|FL_BASE_BARS,
 361                .num_ports      = 1,
 362                .base_baud      = 921600,
 363                .uart_offset    = 8,
 364        },
 365        [timedia_4079h] = {
 366                .flags          = FL_BASE0|FL_BASE_BARS,
 367                .num_ports      = 1,
 368                .base_baud      = 921600,
 369                .uart_offset    = 8,
 370        },
 371        [timedia_4085h] = {
 372                .flags          = FL_BASE0|FL_BASE_BARS,
 373                .num_ports      = 1,
 374                .base_baud      = 921600,
 375                .uart_offset    = 8,
 376        },
 377        [timedia_4088a] = {
 378                .flags          = FL_BASE0|FL_BASE_BARS,
 379                .num_ports      = 1,
 380                .base_baud      = 921600,
 381                .uart_offset    = 8,
 382        },
 383        [timedia_4089a] = {
 384                .flags          = FL_BASE0|FL_BASE_BARS,
 385                .num_ports      = 1,
 386                .base_baud      = 921600,
 387                .uart_offset    = 8,
 388        },
 389        [timedia_4095a] = {
 390                .flags          = FL_BASE0|FL_BASE_BARS,
 391                .num_ports      = 1,
 392                .base_baud      = 921600,
 393                .uart_offset    = 8,
 394        },
 395        [timedia_4096a] = {
 396                .flags          = FL_BASE0|FL_BASE_BARS,
 397                .num_ports      = 1,
 398                .base_baud      = 921600,
 399                .uart_offset    = 8,
 400        },
 401        [timedia_4078u] = {
 402                .flags          = FL_BASE0|FL_BASE_BARS,
 403                .num_ports      = 1,
 404                .base_baud      = 921600,
 405                .uart_offset    = 8,
 406        },
 407        [timedia_4079a] = {
 408                .flags          = FL_BASE0|FL_BASE_BARS,
 409                .num_ports      = 1,
 410                .base_baud      = 921600,
 411                .uart_offset    = 8,
 412        },
 413        [timedia_4085u] = {
 414                .flags          = FL_BASE0|FL_BASE_BARS,
 415                .num_ports      = 1,
 416                .base_baud      = 921600,
 417                .uart_offset    = 8,
 418        },
 419        [timedia_4079r] = {
 420                .flags          = FL_BASE0|FL_BASE_BARS,
 421                .num_ports      = 1,
 422                .base_baud      = 921600,
 423                .uart_offset    = 8,
 424        },
 425        [timedia_4079s] = {
 426                .flags          = FL_BASE0|FL_BASE_BARS,
 427                .num_ports      = 1,
 428                .base_baud      = 921600,
 429                .uart_offset    = 8,
 430        },
 431        [timedia_4079d] = {
 432                .flags          = FL_BASE0|FL_BASE_BARS,
 433                .num_ports      = 1,
 434                .base_baud      = 921600,
 435                .uart_offset    = 8,
 436        },
 437        [timedia_4079e] = {
 438                .flags          = FL_BASE0|FL_BASE_BARS,
 439                .num_ports      = 1,
 440                .base_baud      = 921600,
 441                .uart_offset    = 8,
 442        },
 443        [timedia_4079f] = {
 444                .flags          = FL_BASE0|FL_BASE_BARS,
 445                .num_ports      = 1,
 446                .base_baud      = 921600,
 447                .uart_offset    = 8,
 448        },
 449        [timedia_9079a] = {
 450                .flags          = FL_BASE0|FL_BASE_BARS,
 451                .num_ports      = 1,
 452                .base_baud      = 921600,
 453                .uart_offset    = 8,
 454        },
 455        [timedia_9079b] = {
 456                .flags          = FL_BASE0|FL_BASE_BARS,
 457                .num_ports      = 1,
 458                .base_baud      = 921600,
 459                .uart_offset    = 8,
 460        },
 461        [timedia_9079c] = {
 462                .flags          = FL_BASE0|FL_BASE_BARS,
 463                .num_ports      = 1,
 464                .base_baud      = 921600,
 465                .uart_offset    = 8,
 466        },
 467        [wch_ch353_2s1p] = {
 468                .flags          = FL_BASE0|FL_BASE_BARS,
 469                .num_ports      = 2,
 470                .base_baud      = 115200,
 471                .uart_offset    = 8,
 472        },
 473};
 474
 475struct parport_serial_private {
 476        struct serial_private   *serial;
 477        int num_par;
 478        struct parport *port[PARPORT_MAX];
 479        struct parport_pc_pci par;
 480};
 481
 482/* Register the serial port(s) of a PCI card. */
 483static int serial_register(struct pci_dev *dev, const struct pci_device_id *id)
 484{
 485        struct parport_serial_private *priv = pci_get_drvdata (dev);
 486        struct pciserial_board *board;
 487        struct serial_private *serial;
 488
 489        board = &pci_parport_serial_boards[id->driver_data];
 490
 491        if (board->num_ports == 0)
 492                return 0;
 493
 494        serial = pciserial_init_ports(dev, board);
 495
 496        if (IS_ERR(serial))
 497                return PTR_ERR(serial);
 498
 499        priv->serial = serial;
 500        return 0;
 501}
 502
 503/* Register the parallel port(s) of a PCI card. */
 504static int parport_register(struct pci_dev *dev, const struct pci_device_id *id)
 505{
 506        struct parport_pc_pci *card;
 507        struct parport_serial_private *priv = pci_get_drvdata (dev);
 508        int n, success = 0;
 509
 510        priv->par = cards[id->driver_data];
 511        card = &priv->par;
 512        if (card->preinit_hook &&
 513            card->preinit_hook (dev, card, PARPORT_IRQ_NONE, PARPORT_DMA_NONE))
 514                return -ENODEV;
 515
 516        for (n = 0; n < card->numports; n++) {
 517                struct parport *port;
 518                int lo = card->addr[n].lo;
 519                int hi = card->addr[n].hi;
 520                unsigned long io_lo, io_hi;
 521                int irq;
 522
 523                if (priv->num_par == ARRAY_SIZE (priv->port)) {
 524                        printk (KERN_WARNING
 525                                "parport_serial: %s: only %zu parallel ports "
 526                                "supported (%d reported)\n", pci_name (dev),
 527                                ARRAY_SIZE(priv->port), card->numports);
 528                        break;
 529                }
 530
 531                io_lo = pci_resource_start (dev, lo);
 532                io_hi = 0;
 533                if ((hi >= 0) && (hi <= 6))
 534                        io_hi = pci_resource_start (dev, hi);
 535                else if (hi > 6)
 536                        io_lo += hi; /* Reinterpret the meaning of
 537                                        "hi" as an offset (see SYBA
 538                                        def.) */
 539                /* TODO: test if sharing interrupts works */
 540                irq = dev->irq;
 541                if (irq == IRQ_NONE) {
 542                        dev_dbg(&dev->dev,
 543                        "PCI parallel port detected: I/O at %#lx(%#lx)\n",
 544                                io_lo, io_hi);
 545                        irq = PARPORT_IRQ_NONE;
 546                } else {
 547                        dev_dbg(&dev->dev,
 548                "PCI parallel port detected: I/O at %#lx(%#lx), IRQ %d\n",
 549                                io_lo, io_hi, irq);
 550                }
 551                port = parport_pc_probe_port (io_lo, io_hi, irq,
 552                              PARPORT_DMA_NONE, &dev->dev, IRQF_SHARED);
 553                if (port) {
 554                        priv->port[priv->num_par++] = port;
 555                        success = 1;
 556                }
 557        }
 558
 559        if (card->postinit_hook)
 560                card->postinit_hook (dev, card, !success);
 561
 562        return 0;
 563}
 564
 565static int parport_serial_pci_probe(struct pci_dev *dev,
 566                                    const struct pci_device_id *id)
 567{
 568        struct parport_serial_private *priv;
 569        int err;
 570
 571        priv = kzalloc (sizeof *priv, GFP_KERNEL);
 572        if (!priv)
 573                return -ENOMEM;
 574        pci_set_drvdata (dev, priv);
 575
 576        err = pci_enable_device (dev);
 577        if (err) {
 578                pci_set_drvdata (dev, NULL);
 579                kfree (priv);
 580                return err;
 581        }
 582
 583        if (parport_register (dev, id)) {
 584                pci_set_drvdata (dev, NULL);
 585                kfree (priv);
 586                return -ENODEV;
 587        }
 588
 589        if (serial_register (dev, id)) {
 590                int i;
 591                for (i = 0; i < priv->num_par; i++)
 592                        parport_pc_unregister_port (priv->port[i]);
 593                pci_set_drvdata (dev, NULL);
 594                kfree (priv);
 595                return -ENODEV;
 596        }
 597
 598        return 0;
 599}
 600
 601static void parport_serial_pci_remove(struct pci_dev *dev)
 602{
 603        struct parport_serial_private *priv = pci_get_drvdata (dev);
 604        int i;
 605
 606        pci_set_drvdata(dev, NULL);
 607
 608        // Serial ports
 609        if (priv->serial)
 610                pciserial_remove_ports(priv->serial);
 611
 612        // Parallel ports
 613        for (i = 0; i < priv->num_par; i++)
 614                parport_pc_unregister_port (priv->port[i]);
 615
 616        kfree (priv);
 617        return;
 618}
 619
 620#ifdef CONFIG_PM
 621static int parport_serial_pci_suspend(struct pci_dev *dev, pm_message_t state)
 622{
 623        struct parport_serial_private *priv = pci_get_drvdata(dev);
 624
 625        if (priv->serial)
 626                pciserial_suspend_ports(priv->serial);
 627
 628        /* FIXME: What about parport? */
 629
 630        pci_save_state(dev);
 631        pci_set_power_state(dev, pci_choose_state(dev, state));
 632        return 0;
 633}
 634
 635static int parport_serial_pci_resume(struct pci_dev *dev)
 636{
 637        struct parport_serial_private *priv = pci_get_drvdata(dev);
 638        int err;
 639
 640        pci_set_power_state(dev, PCI_D0);
 641        pci_restore_state(dev);
 642
 643        /*
 644         * The device may have been disabled.  Re-enable it.
 645         */
 646        err = pci_enable_device(dev);
 647        if (err) {
 648                printk(KERN_ERR "parport_serial: %s: error enabling "
 649                        "device for resume (%d)\n", pci_name(dev), err);
 650                return err;
 651        }
 652
 653        if (priv->serial)
 654                pciserial_resume_ports(priv->serial);
 655
 656        /* FIXME: What about parport? */
 657
 658        return 0;
 659}
 660#endif
 661
 662static struct pci_driver parport_serial_pci_driver = {
 663        .name           = "parport_serial",
 664        .id_table       = parport_serial_pci_tbl,
 665        .probe          = parport_serial_pci_probe,
 666        .remove         = parport_serial_pci_remove,
 667#ifdef CONFIG_PM
 668        .suspend        = parport_serial_pci_suspend,
 669        .resume         = parport_serial_pci_resume,
 670#endif
 671};
 672
 673
 674static int __init parport_serial_init (void)
 675{
 676        return pci_register_driver (&parport_serial_pci_driver);
 677}
 678
 679static void __exit parport_serial_exit (void)
 680{
 681        pci_unregister_driver (&parport_serial_pci_driver);
 682        return;
 683}
 684
 685MODULE_AUTHOR("Tim Waugh <twaugh@redhat.com>");
 686MODULE_DESCRIPTION("Driver for common parallel+serial multi-I/O PCI cards");
 687MODULE_LICENSE("GPL");
 688
 689module_init(parport_serial_init);
 690module_exit(parport_serial_exit);
 691
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.