diff options
Diffstat (limited to 'drivers/pcmcia/rsrc_mgr.c')
-rw-r--r-- | drivers/pcmcia/rsrc_mgr.c | 108 |
1 files changed, 106 insertions, 2 deletions
diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c index 0668384ebc8b..514609369836 100644 --- a/drivers/pcmcia/rsrc_mgr.c +++ b/drivers/pcmcia/rsrc_mgr.c | |||
@@ -98,10 +98,12 @@ int pcmcia_adjust_resource_info(adjust_t *adj) | |||
98 | } | 98 | } |
99 | EXPORT_SYMBOL(pcmcia_adjust_resource_info); | 99 | EXPORT_SYMBOL(pcmcia_adjust_resource_info); |
100 | 100 | ||
101 | void pcmcia_validate_mem(struct pcmcia_socket *s) | 101 | int pcmcia_validate_mem(struct pcmcia_socket *s) |
102 | { | 102 | { |
103 | if (s->resource_ops->validate_mem) | 103 | if (s->resource_ops->validate_mem) |
104 | s->resource_ops->validate_mem(s); | 104 | return s->resource_ops->validate_mem(s); |
105 | /* if there is no callback, we can assume that everything is OK */ | ||
106 | return 0; | ||
105 | } | 107 | } |
106 | EXPORT_SYMBOL(pcmcia_validate_mem); | 108 | EXPORT_SYMBOL(pcmcia_validate_mem); |
107 | 109 | ||
@@ -164,3 +166,105 @@ struct pccard_resource_ops pccard_static_ops = { | |||
164 | .exit = NULL, | 166 | .exit = NULL, |
165 | }; | 167 | }; |
166 | 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 */ | ||