[PATCH] pcmcia: remove dev_list from drivers
[linux-2.6] / drivers / parport / parport_cs.c
1 /*======================================================================
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/sched.h>
41 #include <linux/ptrace.h>
42 #include <linux/slab.h>
43 #include <linux/string.h>
44 #include <linux/timer.h>
45 #include <linux/ioport.h>
46 #include <linux/major.h>
47
48 #include <linux/parport.h>
49 #include <linux/parport_pc.h>
50
51 #include <pcmcia/cs_types.h>
52 #include <pcmcia/cs.h>
53 #include <pcmcia/cistpl.h>
54 #include <pcmcia/ds.h>
55 #include <pcmcia/cisreg.h>
56 #include <pcmcia/ciscode.h>
57
58 /*====================================================================*/
59
60 /* Module parameters */
61
62 MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
63 MODULE_DESCRIPTION("PCMCIA parallel port card driver");
64 MODULE_LICENSE("Dual MPL/GPL");
65
66 #define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0)
67
68 INT_MODULE_PARM(epp_mode, 1);
69
70 #ifdef PCMCIA_DEBUG
71 INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
72 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
73 static char *version =
74 "parport_cs.c 1.29 2002/10/11 06:57:41 (David Hinds)";
75 #else
76 #define DEBUG(n, args...)
77 #endif
78
79 /*====================================================================*/
80
81 #define FORCE_EPP_MODE  0x08
82
83 typedef struct parport_info_t {
84     dev_link_t          link;
85     int                 ndev;
86     dev_node_t          node;
87     struct parport      *port;
88 } parport_info_t;
89
90 static dev_link_t *parport_attach(void);
91 static void parport_detach(struct pcmcia_device *p_dev);
92 static void parport_config(dev_link_t *link);
93 static void parport_cs_release(dev_link_t *);
94 static int parport_event(event_t event, int priority,
95                          event_callback_args_t *args);
96
97 static dev_info_t dev_info = "parport_cs";
98
99 /*======================================================================
100
101     parport_attach() creates an "instance" of the driver, allocating
102     local data structures for one device.  The device is registered
103     with Card Services.
104
105 ======================================================================*/
106
107 static dev_link_t *parport_attach(void)
108 {
109     parport_info_t *info;
110     dev_link_t *link;
111     client_reg_t client_reg;
112     int ret;
113     
114     DEBUG(0, "parport_attach()\n");
115
116     /* Create new parport device */
117     info = kmalloc(sizeof(*info), GFP_KERNEL);
118     if (!info) return NULL;
119     memset(info, 0, sizeof(*info));
120     link = &info->link; link->priv = info;
121
122     link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
123     link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
124     link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
125     link->irq.IRQInfo1 = IRQ_LEVEL_ID;
126     link->conf.Attributes = CONF_ENABLE_IRQ;
127     link->conf.Vcc = 50;
128     link->conf.IntType = INT_MEMORY_AND_IO;
129     
130     /* Register with Card Services */
131     link->next = NULL;
132     client_reg.dev_info = &dev_info;
133     client_reg.Version = 0x0210;
134     client_reg.event_callback_args.client_data = link;
135     ret = pcmcia_register_client(&link->handle, &client_reg);
136     if (ret != CS_SUCCESS) {
137         cs_error(link->handle, RegisterClient, ret);
138         parport_detach(link->handle);
139         return NULL;
140     }
141     
142     return link;
143 } /* parport_attach */
144
145 /*======================================================================
146
147     This deletes a driver "instance".  The device is de-registered
148     with Card Services.  If it has been released, all local data
149     structures are freed.  Otherwise, the structures will be freed
150     when the device is released.
151
152 ======================================================================*/
153
154 static void parport_detach(struct pcmcia_device *p_dev)
155 {
156     dev_link_t *link = dev_to_instance(p_dev);
157
158     DEBUG(0, "parport_detach(0x%p)\n", link);
159
160     if (link->state & DEV_CONFIG)
161         parport_cs_release(link);
162
163     kfree(link->priv);
164 } /* parport_detach */
165
166 /*======================================================================
167
168     parport_config() is scheduled to run after a CARD_INSERTION event
169     is received, to configure the PCMCIA socket, and to make the
170     parport device available to the system.
171
172 ======================================================================*/
173
174 #define CS_CHECK(fn, ret) \
175 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
176
177 void parport_config(dev_link_t *link)
178 {
179     client_handle_t handle = link->handle;
180     parport_info_t *info = link->priv;
181     tuple_t tuple;
182     u_short buf[128];
183     cisparse_t parse;
184     config_info_t conf;
185     cistpl_cftable_entry_t *cfg = &parse.cftable_entry;
186     cistpl_cftable_entry_t dflt = { 0 };
187     struct parport *p;
188     int last_ret, last_fn;
189     
190     DEBUG(0, "parport_config(0x%p)\n", link);
191     
192     tuple.TupleData = (cisdata_t *)buf;
193     tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
194     tuple.Attributes = 0;
195     tuple.DesiredTuple = CISTPL_CONFIG;
196     CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
197     CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
198     CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
199     link->conf.ConfigBase = parse.config.base;
200     link->conf.Present = parse.config.rmask[0];
201     
202     /* Configure card */
203     link->state |= DEV_CONFIG;
204
205     /* Not sure if this is right... look up the current Vcc */
206     CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf));
207     
208     tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
209     tuple.Attributes = 0;
210     CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
211     while (1) {
212         if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
213                 pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
214             goto next_entry;
215
216         if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
217             cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
218             link->conf.ConfigIndex = cfg->index;
219             if (epp_mode)
220                 link->conf.ConfigIndex |= FORCE_EPP_MODE;
221             link->io.BasePort1 = io->win[0].base;
222             link->io.NumPorts1 = io->win[0].len;
223             link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
224             if (io->nwin == 2) {
225                 link->io.BasePort2 = io->win[1].base;
226                 link->io.NumPorts2 = io->win[1].len;
227             }
228             if (pcmcia_request_io(link->handle, &link->io) != 0)
229                 goto next_entry;
230             /* If we've got this far, we're done */
231             break;
232         }
233         
234     next_entry:
235         if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
236         CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
237     }
238     
239     CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
240     CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
241
242     release_region(link->io.BasePort1, link->io.NumPorts1);
243     if (link->io.NumPorts2)
244         release_region(link->io.BasePort2, link->io.NumPorts2);
245     p = parport_pc_probe_port(link->io.BasePort1, link->io.BasePort2,
246                               link->irq.AssignedIRQ, PARPORT_DMA_NONE,
247                               NULL);
248     if (p == NULL) {
249         printk(KERN_NOTICE "parport_cs: parport_pc_probe_port() at "
250                "0x%3x, irq %u failed\n", link->io.BasePort1,
251                link->irq.AssignedIRQ);
252         goto failed;
253     }
254
255     p->modes |= PARPORT_MODE_PCSPP;
256     if (epp_mode)
257         p->modes |= PARPORT_MODE_TRISTATE | PARPORT_MODE_EPP;
258     info->ndev = 1;
259     info->node.major = LP_MAJOR;
260     info->node.minor = p->number;
261     info->port = p;
262     strcpy(info->node.dev_name, p->name);
263     link->dev = &info->node;
264
265     link->state &= ~DEV_CONFIG_PENDING;
266     return;
267     
268 cs_failed:
269     cs_error(link->handle, last_fn, last_ret);
270 failed:
271     parport_cs_release(link);
272     link->state &= ~DEV_CONFIG_PENDING;
273
274 } /* parport_config */
275
276 /*======================================================================
277
278     After a card is removed, parport_cs_release() will unregister the
279     device, and release the PCMCIA configuration.  If the device is
280     still open, this will be postponed until it is closed.
281     
282 ======================================================================*/
283
284 void parport_cs_release(dev_link_t *link)
285 {
286     parport_info_t *info = link->priv;
287     
288     DEBUG(0, "parport_release(0x%p)\n", link);
289
290     if (info->ndev) {
291         struct parport *p = info->port;
292         parport_pc_unregister_port(p);
293         request_region(link->io.BasePort1, link->io.NumPorts1,
294                        info->node.dev_name);
295         if (link->io.NumPorts2)
296             request_region(link->io.BasePort2, link->io.NumPorts2,
297                            info->node.dev_name);
298     }
299     info->ndev = 0;
300     link->dev = NULL;
301     
302     pcmcia_release_configuration(link->handle);
303     pcmcia_release_io(link->handle, &link->io);
304     pcmcia_release_irq(link->handle, &link->irq);
305     
306     link->state &= ~DEV_CONFIG;
307
308 } /* parport_cs_release */
309
310 static int parport_suspend(struct pcmcia_device *dev)
311 {
312         dev_link_t *link = dev_to_instance(dev);
313
314         link->state |= DEV_SUSPEND;
315         if (link->state & DEV_CONFIG)
316                 pcmcia_release_configuration(link->handle);
317
318         return 0;
319 }
320
321 static int parport_resume(struct pcmcia_device *dev)
322 {
323         dev_link_t *link = dev_to_instance(dev);
324
325         link->state &= ~DEV_SUSPEND;
326         if (DEV_OK(link))
327                 pcmcia_request_configuration(link->handle, &link->conf);
328
329         return 0;
330 }
331
332 /*======================================================================
333
334     The card status event handler.  Mostly, this schedules other
335     stuff to run after an event is received.
336     
337 ======================================================================*/
338
339 int parport_event(event_t event, int priority,
340                   event_callback_args_t *args)
341 {
342     dev_link_t *link = args->client_data;
343
344     DEBUG(1, "parport_event(0x%06x)\n", event);
345     
346     switch (event) {
347     case CS_EVENT_CARD_INSERTION:
348         link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
349         parport_config(link);
350         break;
351     }
352     return 0;
353 } /* parport_event */
354
355 static struct pcmcia_device_id parport_ids[] = {
356         PCMCIA_DEVICE_FUNC_ID(3),
357         PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0003),
358         PCMCIA_DEVICE_NULL
359 };
360 MODULE_DEVICE_TABLE(pcmcia, parport_ids);
361
362 static struct pcmcia_driver parport_cs_driver = {
363         .owner          = THIS_MODULE,
364         .drv            = {
365                 .name   = "parport_cs",
366         },
367         .attach         = parport_attach,
368         .event          = parport_event,
369         .remove         = parport_detach,
370         .id_table       = parport_ids,
371         .suspend        = parport_suspend,
372         .resume         = parport_resume,
373 };
374
375 static int __init init_parport_cs(void)
376 {
377         return pcmcia_register_driver(&parport_cs_driver);
378 }
379
380 static void __exit exit_parport_cs(void)
381 {
382         pcmcia_unregister_driver(&parport_cs_driver);
383 }
384
385 module_init(init_parport_cs);
386 module_exit(exit_parport_cs);