diff options
Diffstat (limited to 'drivers/pcmcia/rsrc_mgr.c')
-rw-r--r-- | drivers/pcmcia/rsrc_mgr.c | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c index b02598a5a912..514609369836 100644 --- a/drivers/pcmcia/rsrc_mgr.c +++ b/drivers/pcmcia/rsrc_mgr.c | |||
@@ -166,3 +166,105 @@ struct pccard_resource_ops pccard_static_ops = { | |||
166 | .exit = NULL, | 166 | .exit = NULL, |
167 | }; | 167 | }; |
168 | EXPORT_SYMBOL(pccard_static_ops); | 168 | EXPORT_SYMBOL(pccard_static_ops); |
169 | |||
170 | |||
171 | #ifdef CONFIG_PCCARD_IODYN | ||
172 | |||
173 | static struct resource * | ||
174 | make_resource(unsigned long b, unsigned long n, int flags, char *name) | ||
175 | { | ||
176 | struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL); | ||
177 | |||
178 | if (res) { | ||
179 | res->name = name; | ||
180 | res->start = b; | ||
181 | res->end = b + n - 1; | ||
182 | res->flags = flags; | ||
183 | } | ||
184 | return res; | ||
185 | } | ||
186 | |||
187 | struct pcmcia_align_data { | ||
188 | unsigned long mask; | ||
189 | unsigned long offset; | ||
190 | }; | ||
191 | |||
192 | static void pcmcia_align(void *align_data, struct resource *res, | ||
193 | unsigned long size, unsigned long align) | ||
194 | { | ||
195 | struct pcmcia_align_data *data = align_data; | ||
196 | unsigned long start; | ||
197 | |||
198 | start = (res->start & ~data->mask) + data->offset; | ||
199 | if (start < res->start) | ||
200 | start += data->mask + 1; | ||
201 | res->start = start; | ||
202 | |||
203 | #ifdef CONFIG_X86 | ||
204 | if (res->flags & IORESOURCE_IO) { | ||
205 | if (start & 0x300) { | ||
206 | start = (start + 0x3ff) & ~0x3ff; | ||
207 | res->start = start; | ||
208 | } | ||
209 | } | ||
210 | #endif | ||
211 | |||
212 | #ifdef CONFIG_M68K | ||
213 | if (res->flags & IORESOURCE_IO) { | ||
214 | if ((res->start + size - 1) >= 1024) | ||
215 | res->start = res->end; | ||
216 | } | ||
217 | #endif | ||
218 | } | ||
219 | |||
220 | |||
221 | static int iodyn_adjust_io_region(struct resource *res, unsigned long r_start, | ||
222 | unsigned long r_end, struct pcmcia_socket *s) | ||
223 | { | ||
224 | return adjust_resource(res, r_start, r_end - r_start + 1); | ||
225 | } | ||
226 | |||
227 | |||
228 | static struct resource *iodyn_find_io_region(unsigned long base, int num, | ||
229 | unsigned long align, struct pcmcia_socket *s) | ||
230 | { | ||
231 | struct resource *res = make_resource(0, num, IORESOURCE_IO, | ||
232 | s->dev.class_id); | ||
233 | struct pcmcia_align_data data; | ||
234 | unsigned long min = base; | ||
235 | int ret; | ||
236 | |||
237 | if (align == 0) | ||
238 | align = 0x10000; | ||
239 | |||
240 | data.mask = align - 1; | ||
241 | data.offset = base & data.mask; | ||
242 | |||
243 | #ifdef CONFIG_PCI | ||
244 | if (s->cb_dev) { | ||
245 | ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num, 1, | ||
246 | min, 0, pcmcia_align, &data); | ||
247 | } else | ||
248 | #endif | ||
249 | ret = allocate_resource(&ioport_resource, res, num, min, ~0UL, | ||
250 | 1, pcmcia_align, &data); | ||
251 | |||
252 | if (ret != 0) { | ||
253 | kfree(res); | ||
254 | res = NULL; | ||
255 | } | ||
256 | return res; | ||
257 | } | ||
258 | |||
259 | struct pccard_resource_ops pccard_iodyn_ops = { | ||
260 | .validate_mem = NULL, | ||
261 | .adjust_io_region = iodyn_adjust_io_region, | ||
262 | .find_io = iodyn_find_io_region, | ||
263 | .find_mem = NULL, | ||
264 | .adjust_resource = NULL, | ||
265 | .init = static_init, | ||
266 | .exit = NULL, | ||
267 | }; | ||
268 | EXPORT_SYMBOL(pccard_iodyn_ops); | ||
269 | |||
270 | #endif /* CONFIG_PCCARD_IODYN */ | ||