Commit | Line | Data |
---|---|---|
309231d7 HS |
1 | /* |
2 | * comedi_pcmcia.c | |
3 | * Comedi PCMCIA driver specific functions. | |
4 | * | |
5 | * COMEDI - Linux Control and Measurement Device Interface | |
6 | * Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org> | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or modify | |
9 | * it under the terms of the GNU General Public License as published by | |
10 | * the Free Software Foundation; either version 2 of the License, or | |
11 | * (at your option) any later version. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | * GNU General Public License for more details. | |
309231d7 HS |
17 | */ |
18 | ||
aae434b3 | 19 | #include <linux/module.h> |
309231d7 HS |
20 | #include <linux/kernel.h> |
21 | ||
a1d49aee | 22 | #include "comedi_pcmcia.h" |
309231d7 | 23 | |
1f021e1f | 24 | /** |
127a0cf9 IA |
25 | * comedi_to_pcmcia_dev() - Return PCMCIA device attached to COMEDI device |
26 | * @dev: COMEDI device. | |
27 | * | |
28 | * Assuming @dev->hw_dev is non-%NULL, it is assumed to be pointing to a | |
29 | * a &struct device embedded in a &struct pcmcia_device. | |
30 | * | |
31 | * Return: Attached PCMCIA device if @dev->hw_dev is non-%NULL. | |
32 | * Return %NULL if @dev->hw_dev is %NULL. | |
1f021e1f HS |
33 | */ |
34 | struct pcmcia_device *comedi_to_pcmcia_dev(struct comedi_device *dev) | |
35 | { | |
36 | return dev->hw_dev ? to_pcmcia_dev(dev->hw_dev) : NULL; | |
37 | } | |
38 | EXPORT_SYMBOL_GPL(comedi_to_pcmcia_dev); | |
39 | ||
ddb2d0a0 HS |
40 | static int comedi_pcmcia_conf_check(struct pcmcia_device *link, |
41 | void *priv_data) | |
42 | { | |
43 | if (link->config_index == 0) | |
44 | return -EINVAL; | |
45 | ||
46 | return pcmcia_request_io(link); | |
47 | } | |
48 | ||
49 | /** | |
127a0cf9 IA |
50 | * comedi_pcmcia_enable() - Request the regions and enable the PCMCIA device |
51 | * @dev: COMEDI device. | |
52 | * @conf_check: Optional callback to check each configuration option of the | |
53 | * PCMCIA device and request I/O regions. | |
54 | * | |
55 | * Assuming @dev->hw_dev is non-%NULL, it is assumed to be pointing to a a | |
56 | * &struct device embedded in a &struct pcmcia_device. The comedi PCMCIA | |
57 | * driver needs to set the 'config_flags' member in the &struct pcmcia_device, | |
58 | * as appropriate for that driver, before calling this function in order to | |
59 | * allow pcmcia_loop_config() to do its internal autoconfiguration. | |
60 | * | |
61 | * If @conf_check is %NULL it is set to a default function. If is | |
62 | * passed to pcmcia_loop_config() and should return %0 if the configuration | |
63 | * is valid and I/O regions requested successfully, otherwise it should return | |
64 | * a negative error value. The default function returns -%EINVAL if the | |
65 | * 'config_index' member is %0, otherwise it calls pcmcia_request_io() and | |
66 | * returns the result. | |
67 | * | |
68 | * If the above configuration check passes, pcmcia_enable_device() is called | |
69 | * to set up and activate the PCMCIA device. | |
ddb2d0a0 | 70 | * |
127a0cf9 IA |
71 | * If this function returns an error, comedi_pcmcia_disable() should be called |
72 | * to release requested resources. | |
73 | * | |
74 | * Return: | |
75 | * 0 on success, | |
76 | * -%ENODEV id @dev->hw_dev is %NULL, | |
77 | * a negative error number from pcmcia_loop_config() if it fails, | |
78 | * or a negative error number from pcmcia_enable_device() if it fails. | |
ddb2d0a0 | 79 | */ |
a3ac9519 HS |
80 | int comedi_pcmcia_enable(struct comedi_device *dev, |
81 | int (*conf_check)(struct pcmcia_device *, void *)) | |
ddb2d0a0 HS |
82 | { |
83 | struct pcmcia_device *link = comedi_to_pcmcia_dev(dev); | |
84 | int ret; | |
85 | ||
86 | if (!link) | |
87 | return -ENODEV; | |
88 | ||
a3ac9519 HS |
89 | if (!conf_check) |
90 | conf_check = comedi_pcmcia_conf_check; | |
91 | ||
92 | ret = pcmcia_loop_config(link, conf_check, NULL); | |
ddb2d0a0 HS |
93 | if (ret) |
94 | return ret; | |
95 | ||
96 | return pcmcia_enable_device(link); | |
97 | } | |
98 | EXPORT_SYMBOL_GPL(comedi_pcmcia_enable); | |
99 | ||
100 | /** | |
127a0cf9 IA |
101 | * comedi_pcmcia_disable() - Disable the PCMCIA device and release the regions |
102 | * @dev: COMEDI device. | |
103 | * | |
104 | * Assuming @dev->hw_dev is non-%NULL, it is assumed to be pointing to a | |
105 | * a &struct device embedded in a &struct pcmcia_device. Call | |
106 | * pcmcia_disable_device() to disable and clean up the PCMCIA device. | |
ddb2d0a0 HS |
107 | */ |
108 | void comedi_pcmcia_disable(struct comedi_device *dev) | |
109 | { | |
110 | struct pcmcia_device *link = comedi_to_pcmcia_dev(dev); | |
111 | ||
112 | if (link) | |
113 | pcmcia_disable_device(link); | |
114 | } | |
115 | EXPORT_SYMBOL_GPL(comedi_pcmcia_disable); | |
116 | ||
1f021e1f | 117 | /** |
127a0cf9 IA |
118 | * comedi_pcmcia_auto_config() - Configure/probe a PCMCIA COMEDI device |
119 | * @link: PCMCIA device. | |
120 | * @driver: Registered COMEDI driver. | |
121 | * | |
122 | * Typically called from the pcmcia_driver (*probe) function. Auto-configure | |
123 | * a COMEDI device, using a pointer to the &struct device embedded in *@link | |
124 | * as the hardware device. The @driver's "auto_attach" handler may call | |
125 | * comedi_to_pcmcia_dev() on the passed in COMEDI device to recover @link. | |
1f021e1f | 126 | * |
127a0cf9 IA |
127 | * Return: The result of calling comedi_auto_config() (0 on success, or a |
128 | * negative error number on failure). | |
1f021e1f HS |
129 | */ |
130 | int comedi_pcmcia_auto_config(struct pcmcia_device *link, | |
131 | struct comedi_driver *driver) | |
132 | { | |
133 | return comedi_auto_config(&link->dev, driver, 0); | |
134 | } | |
135 | EXPORT_SYMBOL_GPL(comedi_pcmcia_auto_config); | |
136 | ||
137 | /** | |
127a0cf9 IA |
138 | * comedi_pcmcia_auto_unconfig() - Unconfigure/remove a PCMCIA COMEDI device |
139 | * @link: PCMCIA device. | |
1f021e1f HS |
140 | * |
141 | * Typically called from the pcmcia_driver (*remove) function. | |
127a0cf9 IA |
142 | * Auto-unconfigure a COMEDI device attached to this PCMCIA device, using a |
143 | * pointer to the &struct device embedded in *@link as the hardware device. | |
144 | * The COMEDI driver's "detach" handler will be called during unconfiguration | |
145 | * of the COMEDI device. | |
146 | * | |
147 | * Note that the COMEDI device may have already been unconfigured using the | |
148 | * %COMEDI_DEVCONFIG ioctl, in which case this attempt to unconfigure it | |
149 | * again should be ignored. | |
1f021e1f HS |
150 | */ |
151 | void comedi_pcmcia_auto_unconfig(struct pcmcia_device *link) | |
152 | { | |
153 | comedi_auto_unconfig(&link->dev); | |
154 | } | |
155 | EXPORT_SYMBOL_GPL(comedi_pcmcia_auto_unconfig); | |
156 | ||
309231d7 | 157 | /** |
127a0cf9 IA |
158 | * comedi_pcmcia_driver_register() - Register a PCMCIA COMEDI driver |
159 | * @comedi_driver: COMEDI driver to be registered. | |
160 | * @pcmcia_driver: PCMCIA driver to be registered. | |
161 | * | |
162 | * This function is used for the module_init() of PCMCIA COMEDI driver modules | |
163 | * to register the COMEDI driver and the PCMCIA driver. Do not call it | |
164 | * directly, use the module_comedi_pcmcia_driver() helper macro instead. | |
309231d7 | 165 | * |
127a0cf9 | 166 | * Return: 0 on success, or a negative error number on failure. |
309231d7 HS |
167 | */ |
168 | int comedi_pcmcia_driver_register(struct comedi_driver *comedi_driver, | |
169 | struct pcmcia_driver *pcmcia_driver) | |
170 | { | |
171 | int ret; | |
172 | ||
173 | ret = comedi_driver_register(comedi_driver); | |
174 | if (ret < 0) | |
175 | return ret; | |
176 | ||
177 | ret = pcmcia_register_driver(pcmcia_driver); | |
178 | if (ret < 0) { | |
179 | comedi_driver_unregister(comedi_driver); | |
180 | return ret; | |
181 | } | |
182 | ||
183 | return 0; | |
184 | } | |
185 | EXPORT_SYMBOL_GPL(comedi_pcmcia_driver_register); | |
186 | ||
187 | /** | |
127a0cf9 IA |
188 | * comedi_pcmcia_driver_unregister() - Unregister a PCMCIA COMEDI driver |
189 | * @comedi_driver: COMEDI driver to be registered. | |
190 | * @pcmcia_driver: PCMCIA driver to be registered. | |
309231d7 | 191 | * |
127a0cf9 IA |
192 | * This function is called from the module_exit() of PCMCIA COMEDI driver |
193 | * modules to unregister the PCMCIA driver and the COMEDI driver. Do not call | |
194 | * it directly, use the module_comedi_pcmcia_driver() helper macro instead. | |
309231d7 HS |
195 | */ |
196 | void comedi_pcmcia_driver_unregister(struct comedi_driver *comedi_driver, | |
197 | struct pcmcia_driver *pcmcia_driver) | |
198 | { | |
199 | pcmcia_unregister_driver(pcmcia_driver); | |
200 | comedi_driver_unregister(comedi_driver); | |
201 | } | |
202 | EXPORT_SYMBOL_GPL(comedi_pcmcia_driver_unregister); | |
aae434b3 IA |
203 | |
204 | static int __init comedi_pcmcia_init(void) | |
205 | { | |
206 | return 0; | |
207 | } | |
208 | module_init(comedi_pcmcia_init); | |
209 | ||
210 | static void __exit comedi_pcmcia_exit(void) | |
211 | { | |
212 | } | |
213 | module_exit(comedi_pcmcia_exit); | |
214 | ||
215 | MODULE_AUTHOR("http://www.comedi.org"); | |
216 | MODULE_DESCRIPTION("Comedi PCMCIA interface module"); | |
217 | MODULE_LICENSE("GPL"); |