OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [parport/] [parport_serial.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
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
 
28
enum 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 */
44
struct 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
 
65
static 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
 
76
static 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, { { 0, -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
 
91
static 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
};
159
MODULE_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
 */
168
static 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_BASE2 | 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
 
243
struct 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. */
251
static 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. */
269
static 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
 
321
static 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
 
357
static 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
377
static 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
 
391
static 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
 
418
static 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
 
430
static int __init parport_serial_init (void)
431
{
432
        return pci_register_driver (&parport_serial_pci_driver);
433
}
434
 
435
static void __exit parport_serial_exit (void)
436
{
437
        pci_unregister_driver (&parport_serial_pci_driver);
438
        return;
439
}
440
 
441
MODULE_AUTHOR("Tim Waugh <twaugh@redhat.com>");
442
MODULE_DESCRIPTION("Driver for common parallel+serial multi-I/O PCI cards");
443
MODULE_LICENSE("GPL");
444
 
445
module_init(parport_serial_init);
446
module_exit(parport_serial_exit);

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.