powerpc: Set init_bootmem_done on NUMA platforms as well
[deliverable/linux.git] / drivers / parport / parport_cs.c
CommitLineData
1da177e4
LT
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>
1da177e4
LT
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>
51dcdfec 46#include <linux/interrupt.h>
1da177e4
LT
47
48#include <linux/parport.h>
49#include <linux/parport_pc.h>
50
1da177e4
LT
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
62MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
63MODULE_DESCRIPTION("PCMCIA parallel port card driver");
64MODULE_LICENSE("Dual MPL/GPL");
65
66#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0)
67
68INT_MODULE_PARM(epp_mode, 1);
69
70#ifdef PCMCIA_DEBUG
71INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
72#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
73static 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
83typedef struct parport_info_t {
fd238232 84 struct pcmcia_device *p_dev;
1da177e4
LT
85 int ndev;
86 dev_node_t node;
87 struct parport *port;
88} parport_info_t;
89
cc3b4866 90static void parport_detach(struct pcmcia_device *p_dev);
15b99ac1 91static int parport_config(struct pcmcia_device *link);
fba395ee 92static void parport_cs_release(struct pcmcia_device *);
1da177e4
LT
93
94/*======================================================================
95
96 parport_attach() creates an "instance" of the driver, allocating
97 local data structures for one device. The device is registered
98 with Card Services.
99
100======================================================================*/
101
15b99ac1 102static int parport_probe(struct pcmcia_device *link)
1da177e4
LT
103{
104 parport_info_t *info;
f8cfa618 105
1da177e4
LT
106 DEBUG(0, "parport_attach()\n");
107
108 /* Create new parport device */
dd00cc48 109 info = kzalloc(sizeof(*info), GFP_KERNEL);
f8cfa618 110 if (!info) return -ENOMEM;
fd238232 111 link->priv = info;
fba395ee 112 info->p_dev = link;
1da177e4
LT
113
114 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
115 link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
aafcf998 116 link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
1da177e4
LT
117 link->irq.IRQInfo1 = IRQ_LEVEL_ID;
118 link->conf.Attributes = CONF_ENABLE_IRQ;
1da177e4 119 link->conf.IntType = INT_MEMORY_AND_IO;
f8cfa618 120
15b99ac1 121 return parport_config(link);
1da177e4
LT
122} /* parport_attach */
123
124/*======================================================================
125
126 This deletes a driver "instance". The device is de-registered
127 with Card Services. If it has been released, all local data
128 structures are freed. Otherwise, the structures will be freed
129 when the device is released.
130
131======================================================================*/
132
fba395ee 133static void parport_detach(struct pcmcia_device *link)
1da177e4 134{
1da177e4 135 DEBUG(0, "parport_detach(0x%p)\n", link);
cc3b4866 136
e2d40963 137 parport_cs_release(link);
cc3b4866 138
1da177e4 139 kfree(link->priv);
1da177e4
LT
140} /* parport_detach */
141
142/*======================================================================
143
144 parport_config() is scheduled to run after a CARD_INSERTION event
145 is received, to configure the PCMCIA socket, and to make the
146 parport device available to the system.
147
148======================================================================*/
149
150#define CS_CHECK(fn, ret) \
151do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
152
84e2d340
DB
153static int parport_config_check(struct pcmcia_device *p_dev,
154 cistpl_cftable_entry_t *cfg,
8e2fc39d 155 cistpl_cftable_entry_t *dflt,
ad913c11 156 unsigned int vcc,
84e2d340
DB
157 void *priv_data)
158{
84e2d340
DB
159 if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
160 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
84e2d340
DB
161 if (epp_mode)
162 p_dev->conf.ConfigIndex |= FORCE_EPP_MODE;
163 p_dev->io.BasePort1 = io->win[0].base;
164 p_dev->io.NumPorts1 = io->win[0].len;
165 p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
166 if (io->nwin == 2) {
167 p_dev->io.BasePort2 = io->win[1].base;
168 p_dev->io.NumPorts2 = io->win[1].len;
169 }
170 if (pcmcia_request_io(p_dev, &p_dev->io) != 0)
8e2fc39d 171 return -ENODEV;
84e2d340
DB
172 return 0;
173 }
ad913c11 174 return -ENODEV;
84e2d340
DB
175}
176
15b99ac1 177static int parport_config(struct pcmcia_device *link)
1da177e4 178{
1da177e4 179 parport_info_t *info = link->priv;
1da177e4
LT
180 struct parport *p;
181 int last_ret, last_fn;
84e2d340 182
1da177e4 183 DEBUG(0, "parport_config(0x%p)\n", link);
84e2d340 184
8e2fc39d 185 last_ret = pcmcia_loop_config(link, parport_config_check, NULL);
84e2d340
DB
186 if (last_ret) {
187 cs_error(link, RequestIO, last_ret);
188 goto failed;
1da177e4 189 }
84e2d340 190
fba395ee
DB
191 CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
192 CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
1da177e4 193
1da177e4
LT
194 p = parport_pc_probe_port(link->io.BasePort1, link->io.BasePort2,
195 link->irq.AssignedIRQ, PARPORT_DMA_NONE,
51dcdfec 196 &link->dev, IRQF_SHARED);
1da177e4
LT
197 if (p == NULL) {
198 printk(KERN_NOTICE "parport_cs: parport_pc_probe_port() at "
199 "0x%3x, irq %u failed\n", link->io.BasePort1,
200 link->irq.AssignedIRQ);
201 goto failed;
202 }
203
204 p->modes |= PARPORT_MODE_PCSPP;
205 if (epp_mode)
206 p->modes |= PARPORT_MODE_TRISTATE | PARPORT_MODE_EPP;
207 info->ndev = 1;
208 info->node.major = LP_MAJOR;
209 info->node.minor = p->number;
210 info->port = p;
211 strcpy(info->node.dev_name, p->name);
fd238232 212 link->dev_node = &info->node;
1da177e4 213
15b99ac1
DB
214 return 0;
215
1da177e4 216cs_failed:
fba395ee 217 cs_error(link, last_fn, last_ret);
1da177e4
LT
218failed:
219 parport_cs_release(link);
15b99ac1 220 return -ENODEV;
1da177e4
LT
221} /* parport_config */
222
223/*======================================================================
224
225 After a card is removed, parport_cs_release() will unregister the
226 device, and release the PCMCIA configuration. If the device is
227 still open, this will be postponed until it is closed.
228
229======================================================================*/
230
23d5f96c 231static void parport_cs_release(struct pcmcia_device *link)
1da177e4 232{
5f2a71fc 233 parport_info_t *info = link->priv;
1da177e4 234
5f2a71fc
DB
235 DEBUG(0, "parport_release(0x%p)\n", link);
236
237 if (info->ndev) {
238 struct parport *p = info->port;
239 parport_pc_unregister_port(p);
240 }
241 info->ndev = 0;
1da177e4 242
fba395ee 243 pcmcia_disable_device(link);
1da177e4
LT
244} /* parport_cs_release */
245
98e4c28b 246
476835af
DB
247static struct pcmcia_device_id parport_ids[] = {
248 PCMCIA_DEVICE_FUNC_ID(3),
44e5e33e 249 PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial+Parallel Port: SP230",0x3beb8cf2,0xdb9e58bc),
476835af
DB
250 PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0003),
251 PCMCIA_DEVICE_NULL
252};
253MODULE_DEVICE_TABLE(pcmcia, parport_ids);
254
1da177e4
LT
255static struct pcmcia_driver parport_cs_driver = {
256 .owner = THIS_MODULE,
257 .drv = {
258 .name = "parport_cs",
259 },
15b99ac1 260 .probe = parport_probe,
cc3b4866 261 .remove = parport_detach,
476835af 262 .id_table = parport_ids,
1da177e4
LT
263};
264
265static int __init init_parport_cs(void)
266{
267 return pcmcia_register_driver(&parport_cs_driver);
268}
269
270static void __exit exit_parport_cs(void)
271{
272 pcmcia_unregister_driver(&parport_cs_driver);
1da177e4
LT
273}
274
275module_init(init_parport_cs);
276module_exit(exit_parport_cs);
This page took 0.479925 seconds and 5 git commands to generate.