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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [parport/] [parport_cs.c] - Blame information for rev 67

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*======================================================================
2
 
3
    A driver for PCMCIA parallel port adapters
4
 
5
    (specifically, for the Quatech SPP-100 EPP card: other cards will
6
    probably require driver tweaks)
7
 
8
    parport_cs.c 1.29 2002/10/11 06:57:41
9
 
10
    The contents of this file are subject to the Mozilla Public
11
    License Version 1.1 (the "License"); you may not use this file
12
    except in compliance with the License. You may obtain a copy of
13
    the License at http://www.mozilla.org/MPL/
14
 
15
    Software distributed under the License is distributed on an "AS
16
    IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
17
    implied. See the License for the specific language governing
18
    rights and limitations under the License.
19
 
20
    The initial developer of the original code is David A. Hinds
21
    <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
22
    are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
23
 
24
    Alternatively, the contents of this file may be used under the
25
    terms of the GNU General Public License version 2 (the "GPL"), in
26
    which case the provisions of the GPL are applicable instead of the
27
    above.  If you wish to allow the use of your version of this file
28
    only under the terms of the GPL and not to allow others to use
29
    your version of this file under the MPL, indicate your decision
30
    by deleting the provisions above and replace them with the notice
31
    and other provisions required by the GPL.  If you do not delete
32
    the provisions above, a recipient may use your version of this
33
    file under either the MPL or the GPL.
34
 
35
======================================================================*/
36
 
37
#include <linux/kernel.h>
38
#include <linux/module.h>
39
#include <linux/init.h>
40
#include <linux/ptrace.h>
41
#include <linux/slab.h>
42
#include <linux/string.h>
43
#include <linux/timer.h>
44
#include <linux/ioport.h>
45
#include <linux/major.h>
46
 
47
#include <linux/parport.h>
48
#include <linux/parport_pc.h>
49
 
50
#include <pcmcia/cs_types.h>
51
#include <pcmcia/cs.h>
52
#include <pcmcia/cistpl.h>
53
#include <pcmcia/ds.h>
54
#include <pcmcia/cisreg.h>
55
#include <pcmcia/ciscode.h>
56
 
57
/*====================================================================*/
58
 
59
/* Module parameters */
60
 
61
MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
62
MODULE_DESCRIPTION("PCMCIA parallel port card driver");
63
MODULE_LICENSE("Dual MPL/GPL");
64
 
65
#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0)
66
 
67
INT_MODULE_PARM(epp_mode, 1);
68
 
69
#ifdef PCMCIA_DEBUG
70
INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
71
#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
72
static char *version =
73
"parport_cs.c 1.29 2002/10/11 06:57:41 (David Hinds)";
74
#else
75
#define DEBUG(n, args...)
76
#endif
77
 
78
/*====================================================================*/
79
 
80
#define FORCE_EPP_MODE  0x08
81
 
82
typedef struct parport_info_t {
83
        struct pcmcia_device    *p_dev;
84
    int                 ndev;
85
    dev_node_t          node;
86
    struct parport      *port;
87
} parport_info_t;
88
 
89
static void parport_detach(struct pcmcia_device *p_dev);
90
static int parport_config(struct pcmcia_device *link);
91
static void parport_cs_release(struct pcmcia_device *);
92
 
93
/*======================================================================
94
 
95
    parport_attach() creates an "instance" of the driver, allocating
96
    local data structures for one device.  The device is registered
97
    with Card Services.
98
 
99
======================================================================*/
100
 
101
static int parport_probe(struct pcmcia_device *link)
102
{
103
    parport_info_t *info;
104
 
105
    DEBUG(0, "parport_attach()\n");
106
 
107
    /* Create new parport device */
108
    info = kzalloc(sizeof(*info), GFP_KERNEL);
109
    if (!info) return -ENOMEM;
110
    link->priv = info;
111
    info->p_dev = link;
112
 
113
    link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
114
    link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
115
    link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
116
    link->irq.IRQInfo1 = IRQ_LEVEL_ID;
117
    link->conf.Attributes = CONF_ENABLE_IRQ;
118
    link->conf.IntType = INT_MEMORY_AND_IO;
119
 
120
    return parport_config(link);
121
} /* parport_attach */
122
 
123
/*======================================================================
124
 
125
    This deletes a driver "instance".  The device is de-registered
126
    with Card Services.  If it has been released, all local data
127
    structures are freed.  Otherwise, the structures will be freed
128
    when the device is released.
129
 
130
======================================================================*/
131
 
132
static void parport_detach(struct pcmcia_device *link)
133
{
134
    DEBUG(0, "parport_detach(0x%p)\n", link);
135
 
136
    parport_cs_release(link);
137
 
138
    kfree(link->priv);
139
} /* parport_detach */
140
 
141
/*======================================================================
142
 
143
    parport_config() is scheduled to run after a CARD_INSERTION event
144
    is received, to configure the PCMCIA socket, and to make the
145
    parport device available to the system.
146
 
147
======================================================================*/
148
 
149
#define CS_CHECK(fn, ret) \
150
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
151
 
152
static int parport_config(struct pcmcia_device *link)
153
{
154
    parport_info_t *info = link->priv;
155
    tuple_t tuple;
156
    u_short buf[128];
157
    cisparse_t parse;
158
    cistpl_cftable_entry_t *cfg = &parse.cftable_entry;
159
    cistpl_cftable_entry_t dflt = { 0 };
160
    struct parport *p;
161
    int last_ret, last_fn;
162
 
163
    DEBUG(0, "parport_config(0x%p)\n", link);
164
 
165
    tuple.TupleData = (cisdata_t *)buf;
166
    tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
167
    tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
168
    tuple.Attributes = 0;
169
    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
170
    while (1) {
171
        if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
172
                pcmcia_parse_tuple(link, &tuple, &parse) != 0)
173
            goto next_entry;
174
 
175
        if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
176
            cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
177
            link->conf.ConfigIndex = cfg->index;
178
            if (epp_mode)
179
                link->conf.ConfigIndex |= FORCE_EPP_MODE;
180
            link->io.BasePort1 = io->win[0].base;
181
            link->io.NumPorts1 = io->win[0].len;
182
            link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
183
            if (io->nwin == 2) {
184
                link->io.BasePort2 = io->win[1].base;
185
                link->io.NumPorts2 = io->win[1].len;
186
            }
187
            if (pcmcia_request_io(link, &link->io) != 0)
188
                goto next_entry;
189
            /* If we've got this far, we're done */
190
            break;
191
        }
192
 
193
    next_entry:
194
        if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
195
        CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
196
    }
197
 
198
    CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
199
    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
200
 
201
    p = parport_pc_probe_port(link->io.BasePort1, link->io.BasePort2,
202
                              link->irq.AssignedIRQ, PARPORT_DMA_NONE,
203
                              &link->dev);
204
    if (p == NULL) {
205
        printk(KERN_NOTICE "parport_cs: parport_pc_probe_port() at "
206
               "0x%3x, irq %u failed\n", link->io.BasePort1,
207
               link->irq.AssignedIRQ);
208
        goto failed;
209
    }
210
 
211
    p->modes |= PARPORT_MODE_PCSPP;
212
    if (epp_mode)
213
        p->modes |= PARPORT_MODE_TRISTATE | PARPORT_MODE_EPP;
214
    info->ndev = 1;
215
    info->node.major = LP_MAJOR;
216
    info->node.minor = p->number;
217
    info->port = p;
218
    strcpy(info->node.dev_name, p->name);
219
    link->dev_node = &info->node;
220
 
221
    return 0;
222
 
223
cs_failed:
224
    cs_error(link, last_fn, last_ret);
225
failed:
226
    parport_cs_release(link);
227
    return -ENODEV;
228
} /* parport_config */
229
 
230
/*======================================================================
231
 
232
    After a card is removed, parport_cs_release() will unregister the
233
    device, and release the PCMCIA configuration.  If the device is
234
    still open, this will be postponed until it is closed.
235
 
236
======================================================================*/
237
 
238
void parport_cs_release(struct pcmcia_device *link)
239
{
240
        parport_info_t *info = link->priv;
241
 
242
        DEBUG(0, "parport_release(0x%p)\n", link);
243
 
244
        if (info->ndev) {
245
                struct parport *p = info->port;
246
                parport_pc_unregister_port(p);
247
        }
248
        info->ndev = 0;
249
 
250
        pcmcia_disable_device(link);
251
} /* parport_cs_release */
252
 
253
 
254
static struct pcmcia_device_id parport_ids[] = {
255
        PCMCIA_DEVICE_FUNC_ID(3),
256
        PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial+Parallel Port: SP230",0x3beb8cf2,0xdb9e58bc),
257
        PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0003),
258
        PCMCIA_DEVICE_NULL
259
};
260
MODULE_DEVICE_TABLE(pcmcia, parport_ids);
261
 
262
static struct pcmcia_driver parport_cs_driver = {
263
        .owner          = THIS_MODULE,
264
        .drv            = {
265
                .name   = "parport_cs",
266
        },
267
        .probe          = parport_probe,
268
        .remove         = parport_detach,
269
        .id_table       = parport_ids,
270
};
271
 
272
static int __init init_parport_cs(void)
273
{
274
        return pcmcia_register_driver(&parport_cs_driver);
275
}
276
 
277
static void __exit exit_parport_cs(void)
278
{
279
        pcmcia_unregister_driver(&parport_cs_driver);
280
}
281
 
282
module_init(init_parport_cs);
283
module_exit(exit_parport_cs);

powered by: WebSVN 2.1.0

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