diff options
Diffstat (limited to 'drivers/pcmcia/pcmcia_resource.c')
-rw-r--r-- | drivers/pcmcia/pcmcia_resource.c | 413 |
1 files changed, 251 insertions, 162 deletions
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index 9ba4dade69a4..e8c19def1b0f 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. | 6 | * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. |
7 | * | 7 | * |
8 | * Copyright (C) 1999 David A. Hinds | 8 | * Copyright (C) 1999 David A. Hinds |
9 | * Copyright (C) 2004-2005 Dominik Brodowski | 9 | * Copyright (C) 2004-2010 Dominik Brodowski |
10 | * | 10 | * |
11 | * This program is free software; you can redistribute it and/or modify | 11 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of the GNU General Public License version 2 as | 12 | * it under the terms of the GNU General Public License version 2 as |
@@ -26,7 +26,6 @@ | |||
26 | #include <asm/irq.h> | 26 | #include <asm/irq.h> |
27 | 27 | ||
28 | #include <pcmcia/ss.h> | 28 | #include <pcmcia/ss.h> |
29 | #include <pcmcia/cs.h> | ||
30 | #include <pcmcia/cistpl.h> | 29 | #include <pcmcia/cistpl.h> |
31 | #include <pcmcia/cisreg.h> | 30 | #include <pcmcia/cisreg.h> |
32 | #include <pcmcia/ds.h> | 31 | #include <pcmcia/ds.h> |
@@ -56,6 +55,12 @@ struct resource *pcmcia_find_mem_region(u_long base, u_long num, u_long align, | |||
56 | } | 55 | } |
57 | 56 | ||
58 | 57 | ||
58 | /** | ||
59 | * release_io_space() - release IO ports allocated with alloc_io_space() | ||
60 | * @s: pcmcia socket | ||
61 | * @res: resource to release | ||
62 | * | ||
63 | */ | ||
59 | static void release_io_space(struct pcmcia_socket *s, struct resource *res) | 64 | static void release_io_space(struct pcmcia_socket *s, struct resource *res) |
60 | { | 65 | { |
61 | resource_size_t num = resource_size(res); | 66 | resource_size_t num = resource_size(res); |
@@ -81,9 +86,14 @@ static void release_io_space(struct pcmcia_socket *s, struct resource *res) | |||
81 | } | 86 | } |
82 | } | 87 | } |
83 | } | 88 | } |
84 | } /* release_io_space */ | 89 | } |
90 | |||
85 | 91 | ||
86 | /** alloc_io_space | 92 | /** |
93 | * alloc_io_space() - allocate IO ports for use by a PCMCIA device | ||
94 | * @s: pcmcia socket | ||
95 | * @res: resource to allocate (begin: begin, end: size) | ||
96 | * @lines: number of IO lines decoded by the PCMCIA card | ||
87 | * | 97 | * |
88 | * Special stuff for managing IO windows, because they are scarce | 98 | * Special stuff for managing IO windows, because they are scarce |
89 | */ | 99 | */ |
@@ -135,7 +145,7 @@ static int alloc_io_space(struct pcmcia_socket *s, struct resource *res, | |||
135 | } | 145 | } |
136 | dev_dbg(&s->dev, "alloc_io_space request result %d: %pR\n", ret, res); | 146 | dev_dbg(&s->dev, "alloc_io_space request result %d: %pR\n", ret, res); |
137 | return ret; | 147 | return ret; |
138 | } /* alloc_io_space */ | 148 | } |
139 | 149 | ||
140 | 150 | ||
141 | /** | 151 | /** |
@@ -163,19 +173,19 @@ static int pcmcia_access_config(struct pcmcia_device *p_dev, | |||
163 | c = p_dev->function_config; | 173 | c = p_dev->function_config; |
164 | 174 | ||
165 | if (!(c->state & CONFIG_LOCKED)) { | 175 | if (!(c->state & CONFIG_LOCKED)) { |
166 | dev_dbg(&p_dev->dev, "Configuration isnt't locked\n"); | 176 | dev_dbg(&p_dev->dev, "Configuration isn't locked\n"); |
167 | mutex_unlock(&s->ops_mutex); | 177 | mutex_unlock(&s->ops_mutex); |
168 | return -EACCES; | 178 | return -EACCES; |
169 | } | 179 | } |
170 | 180 | ||
171 | addr = (c->ConfigBase + where) >> 1; | 181 | addr = (p_dev->config_base + where) >> 1; |
172 | 182 | ||
173 | ret = accessf(s, 1, addr, 1, val); | 183 | ret = accessf(s, 1, addr, 1, val); |
174 | 184 | ||
175 | mutex_unlock(&s->ops_mutex); | 185 | mutex_unlock(&s->ops_mutex); |
176 | 186 | ||
177 | return ret; | 187 | return ret; |
178 | } /* pcmcia_access_config */ | 188 | } |
179 | 189 | ||
180 | 190 | ||
181 | /** | 191 | /** |
@@ -204,11 +214,20 @@ int pcmcia_write_config_byte(struct pcmcia_device *p_dev, off_t where, u8 val) | |||
204 | EXPORT_SYMBOL(pcmcia_write_config_byte); | 214 | EXPORT_SYMBOL(pcmcia_write_config_byte); |
205 | 215 | ||
206 | 216 | ||
207 | int pcmcia_map_mem_page(struct pcmcia_device *p_dev, window_handle_t wh, | 217 | /** |
218 | * pcmcia_map_mem_page() - modify iomem window to point to a different offset | ||
219 | * @p_dev: pcmcia device | ||
220 | * @res: iomem resource already enabled by pcmcia_request_window() | ||
221 | * @offset: card_offset to map | ||
222 | * | ||
223 | * pcmcia_map_mem_page() modifies what can be read and written by accessing | ||
224 | * an iomem range previously enabled by pcmcia_request_window(), by setting | ||
225 | * the card_offset value to @offset. | ||
226 | */ | ||
227 | int pcmcia_map_mem_page(struct pcmcia_device *p_dev, struct resource *res, | ||
208 | unsigned int offset) | 228 | unsigned int offset) |
209 | { | 229 | { |
210 | struct pcmcia_socket *s = p_dev->socket; | 230 | struct pcmcia_socket *s = p_dev->socket; |
211 | struct resource *res = wh; | ||
212 | unsigned int w; | 231 | unsigned int w; |
213 | int ret; | 232 | int ret; |
214 | 233 | ||
@@ -223,98 +242,111 @@ int pcmcia_map_mem_page(struct pcmcia_device *p_dev, window_handle_t wh, | |||
223 | dev_warn(&p_dev->dev, "failed to set_mem_map\n"); | 242 | dev_warn(&p_dev->dev, "failed to set_mem_map\n"); |
224 | mutex_unlock(&s->ops_mutex); | 243 | mutex_unlock(&s->ops_mutex); |
225 | return ret; | 244 | return ret; |
226 | } /* pcmcia_map_mem_page */ | 245 | } |
227 | EXPORT_SYMBOL(pcmcia_map_mem_page); | 246 | EXPORT_SYMBOL(pcmcia_map_mem_page); |
228 | 247 | ||
229 | 248 | ||
230 | /** pcmcia_modify_configuration | 249 | /** |
250 | * pcmcia_fixup_iowidth() - reduce io width to 8bit | ||
251 | * @p_dev: pcmcia device | ||
231 | * | 252 | * |
232 | * Modify a locked socket configuration | 253 | * pcmcia_fixup_iowidth() allows a PCMCIA device driver to reduce the |
254 | * IO width to 8bit after having called pcmcia_enable_device() | ||
255 | * previously. | ||
233 | */ | 256 | */ |
234 | int pcmcia_modify_configuration(struct pcmcia_device *p_dev, | 257 | int pcmcia_fixup_iowidth(struct pcmcia_device *p_dev) |
235 | modconf_t *mod) | ||
236 | { | 258 | { |
237 | struct pcmcia_socket *s; | 259 | struct pcmcia_socket *s = p_dev->socket; |
238 | config_t *c; | 260 | pccard_io_map io_off = { 0, 0, 0, 0, 1 }; |
239 | int ret; | 261 | pccard_io_map io_on; |
240 | 262 | int i, ret = 0; | |
241 | s = p_dev->socket; | ||
242 | 263 | ||
243 | mutex_lock(&s->ops_mutex); | 264 | mutex_lock(&s->ops_mutex); |
244 | c = p_dev->function_config; | ||
245 | 265 | ||
246 | if (!(s->state & SOCKET_PRESENT)) { | 266 | dev_dbg(&p_dev->dev, "fixup iowidth to 8bit\n"); |
247 | dev_dbg(&p_dev->dev, "No card present\n"); | 267 | |
248 | ret = -ENODEV; | 268 | if (!(s->state & SOCKET_PRESENT) || |
249 | goto unlock; | 269 | !(p_dev->function_config->state & CONFIG_LOCKED)) { |
250 | } | 270 | dev_dbg(&p_dev->dev, "No card? Config not locked?\n"); |
251 | if (!(c->state & CONFIG_LOCKED)) { | ||
252 | dev_dbg(&p_dev->dev, "Configuration isnt't locked\n"); | ||
253 | ret = -EACCES; | 271 | ret = -EACCES; |
254 | goto unlock; | 272 | goto unlock; |
255 | } | 273 | } |
256 | 274 | ||
257 | if (mod->Attributes & (CONF_IRQ_CHANGE_VALID | CONF_VCC_CHANGE_VALID)) { | 275 | io_on.speed = io_speed; |
258 | dev_dbg(&p_dev->dev, | 276 | for (i = 0; i < MAX_IO_WIN; i++) { |
259 | "changing Vcc or IRQ is not allowed at this time\n"); | 277 | if (!s->io[i].res) |
260 | ret = -EINVAL; | 278 | continue; |
261 | goto unlock; | 279 | io_off.map = i; |
262 | } | 280 | io_on.map = i; |
263 | 281 | ||
264 | /* We only allow changing Vpp1 and Vpp2 to the same value */ | 282 | io_on.flags = MAP_ACTIVE | IO_DATA_PATH_WIDTH_8; |
265 | if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) && | 283 | io_on.start = s->io[i].res->start; |
266 | (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { | 284 | io_on.stop = s->io[i].res->end; |
267 | if (mod->Vpp1 != mod->Vpp2) { | 285 | |
268 | dev_dbg(&p_dev->dev, | 286 | s->ops->set_io_map(s, &io_off); |
269 | "Vpp1 and Vpp2 must be the same\n"); | 287 | mdelay(40); |
270 | ret = -EINVAL; | 288 | s->ops->set_io_map(s, &io_on); |
271 | goto unlock; | ||
272 | } | ||
273 | s->socket.Vpp = mod->Vpp1; | ||
274 | if (s->ops->set_socket(s, &s->socket)) { | ||
275 | dev_printk(KERN_WARNING, &p_dev->dev, | ||
276 | "Unable to set VPP\n"); | ||
277 | ret = -EIO; | ||
278 | goto unlock; | ||
279 | } | ||
280 | } else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) || | ||
281 | (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { | ||
282 | dev_dbg(&p_dev->dev, | ||
283 | "changing Vcc is not allowed at this time\n"); | ||
284 | ret = -EINVAL; | ||
285 | goto unlock; | ||
286 | } | 289 | } |
290 | unlock: | ||
291 | mutex_unlock(&s->ops_mutex); | ||
287 | 292 | ||
288 | if (mod->Attributes & CONF_IO_CHANGE_WIDTH) { | 293 | return ret; |
289 | pccard_io_map io_off = { 0, 0, 0, 0, 1 }; | 294 | } |
290 | pccard_io_map io_on; | 295 | EXPORT_SYMBOL(pcmcia_fixup_iowidth); |
291 | int i; | ||
292 | 296 | ||
293 | io_on.speed = io_speed; | ||
294 | for (i = 0; i < MAX_IO_WIN; i++) { | ||
295 | if (!s->io[i].res) | ||
296 | continue; | ||
297 | io_off.map = i; | ||
298 | io_on.map = i; | ||
299 | 297 | ||
300 | io_on.flags = MAP_ACTIVE | IO_DATA_PATH_WIDTH_8; | 298 | /** |
301 | io_on.start = s->io[i].res->start; | 299 | * pcmcia_fixup_vpp() - set Vpp to a new voltage level |
302 | io_on.stop = s->io[i].res->end; | 300 | * @p_dev: pcmcia device |
301 | * @new_vpp: new Vpp voltage | ||
302 | * | ||
303 | * pcmcia_fixup_vpp() allows a PCMCIA device driver to set Vpp to | ||
304 | * a new voltage level between calls to pcmcia_enable_device() | ||
305 | * and pcmcia_disable_device(). | ||
306 | */ | ||
307 | int pcmcia_fixup_vpp(struct pcmcia_device *p_dev, unsigned char new_vpp) | ||
308 | { | ||
309 | struct pcmcia_socket *s = p_dev->socket; | ||
310 | int ret = 0; | ||
303 | 311 | ||
304 | s->ops->set_io_map(s, &io_off); | 312 | mutex_lock(&s->ops_mutex); |
305 | mdelay(40); | 313 | |
306 | s->ops->set_io_map(s, &io_on); | 314 | dev_dbg(&p_dev->dev, "fixup Vpp to %d\n", new_vpp); |
307 | } | 315 | |
316 | if (!(s->state & SOCKET_PRESENT) || | ||
317 | !(p_dev->function_config->state & CONFIG_LOCKED)) { | ||
318 | dev_dbg(&p_dev->dev, "No card? Config not locked?\n"); | ||
319 | ret = -EACCES; | ||
320 | goto unlock; | ||
321 | } | ||
322 | |||
323 | s->socket.Vpp = new_vpp; | ||
324 | if (s->ops->set_socket(s, &s->socket)) { | ||
325 | dev_warn(&p_dev->dev, "Unable to set VPP\n"); | ||
326 | ret = -EIO; | ||
327 | goto unlock; | ||
308 | } | 328 | } |
309 | ret = 0; | 329 | p_dev->vpp = new_vpp; |
330 | |||
310 | unlock: | 331 | unlock: |
311 | mutex_unlock(&s->ops_mutex); | 332 | mutex_unlock(&s->ops_mutex); |
312 | 333 | ||
313 | return ret; | 334 | return ret; |
314 | } /* modify_configuration */ | 335 | } |
315 | EXPORT_SYMBOL(pcmcia_modify_configuration); | 336 | EXPORT_SYMBOL(pcmcia_fixup_vpp); |
316 | 337 | ||
317 | 338 | ||
339 | /** | ||
340 | * pcmcia_release_configuration() - physically disable a PCMCIA device | ||
341 | * @p_dev: pcmcia device | ||
342 | * | ||
343 | * pcmcia_release_configuration() is the 1:1 counterpart to | ||
344 | * pcmcia_enable_device(): If a PCMCIA device is no longer used by any | ||
345 | * driver, the Vpp voltage is set to 0, IRQs will no longer be generated, | ||
346 | * and I/O ranges will be disabled. As pcmcia_release_io() and | ||
347 | * pcmcia_release_window() still need to be called, device drivers are | ||
348 | * expected to call pcmcia_disable_device() instead. | ||
349 | */ | ||
318 | int pcmcia_release_configuration(struct pcmcia_device *p_dev) | 350 | int pcmcia_release_configuration(struct pcmcia_device *p_dev) |
319 | { | 351 | { |
320 | pccard_io_map io = { 0, 0, 0, 0, 1 }; | 352 | pccard_io_map io = { 0, 0, 0, 0, 1 }; |
@@ -327,7 +359,7 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev) | |||
327 | if (p_dev->_locked) { | 359 | if (p_dev->_locked) { |
328 | p_dev->_locked = 0; | 360 | p_dev->_locked = 0; |
329 | if (--(s->lock_count) == 0) { | 361 | if (--(s->lock_count) == 0) { |
330 | s->socket.flags = SS_OUTPUT_ENA; /* Is this correct? */ | 362 | s->socket.flags = SS_OUTPUT_ENA; /* Is this correct? */ |
331 | s->socket.Vpp = 0; | 363 | s->socket.Vpp = 0; |
332 | s->socket.io_irq = 0; | 364 | s->socket.io_irq = 0; |
333 | s->ops->set_socket(s, &s->socket); | 365 | s->ops->set_socket(s, &s->socket); |
@@ -349,16 +381,18 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev) | |||
349 | mutex_unlock(&s->ops_mutex); | 381 | mutex_unlock(&s->ops_mutex); |
350 | 382 | ||
351 | return 0; | 383 | return 0; |
352 | } /* pcmcia_release_configuration */ | 384 | } |
353 | 385 | ||
354 | 386 | ||
355 | /** pcmcia_release_io | 387 | /** |
388 | * pcmcia_release_io() - release I/O allocated by a PCMCIA device | ||
389 | * @p_dev: pcmcia device | ||
356 | * | 390 | * |
357 | * Release_io() releases the I/O ranges allocated by a client. This | 391 | * pcmcia_release_io() releases the I/O ranges allocated by a PCMCIA |
358 | * may be invoked some time after a card ejection has already dumped | 392 | * device. This may be invoked some time after a card ejection has |
359 | * the actual socket configuration, so if the client is "stale", we | 393 | * already dumped the actual socket configuration, so if the client is |
360 | * don't bother checking the port ranges against the current socket | 394 | * "stale", we don't bother checking the port ranges against the |
361 | * values. | 395 | * current socket values. |
362 | */ | 396 | */ |
363 | static int pcmcia_release_io(struct pcmcia_device *p_dev) | 397 | static int pcmcia_release_io(struct pcmcia_device *p_dev) |
364 | { | 398 | { |
@@ -387,6 +421,14 @@ out: | |||
387 | } /* pcmcia_release_io */ | 421 | } /* pcmcia_release_io */ |
388 | 422 | ||
389 | 423 | ||
424 | /** | ||
425 | * pcmcia_release_window() - release reserved iomem for PCMCIA devices | ||
426 | * @p_dev: pcmcia device | ||
427 | * @res: iomem resource to release | ||
428 | * | ||
429 | * pcmcia_release_window() releases &struct resource *res which was | ||
430 | * previously reserved by calling pcmcia_request_window(). | ||
431 | */ | ||
390 | int pcmcia_release_window(struct pcmcia_device *p_dev, struct resource *res) | 432 | int pcmcia_release_window(struct pcmcia_device *p_dev, struct resource *res) |
391 | { | 433 | { |
392 | struct pcmcia_socket *s = p_dev->socket; | 434 | struct pcmcia_socket *s = p_dev->socket; |
@@ -420,6 +462,8 @@ int pcmcia_release_window(struct pcmcia_device *p_dev, struct resource *res) | |||
420 | kfree(win->res); | 462 | kfree(win->res); |
421 | win->res = NULL; | 463 | win->res = NULL; |
422 | } | 464 | } |
465 | res->start = res->end = 0; | ||
466 | res->flags = IORESOURCE_MEM; | ||
423 | p_dev->_win &= ~CLIENT_WIN_REQ(w); | 467 | p_dev->_win &= ~CLIENT_WIN_REQ(w); |
424 | mutex_unlock(&s->ops_mutex); | 468 | mutex_unlock(&s->ops_mutex); |
425 | 469 | ||
@@ -428,23 +472,30 @@ int pcmcia_release_window(struct pcmcia_device *p_dev, struct resource *res) | |||
428 | EXPORT_SYMBOL(pcmcia_release_window); | 472 | EXPORT_SYMBOL(pcmcia_release_window); |
429 | 473 | ||
430 | 474 | ||
431 | int pcmcia_request_configuration(struct pcmcia_device *p_dev, | 475 | /** |
432 | config_req_t *req) | 476 | * pcmcia_enable_device() - set up and activate a PCMCIA device |
477 | * @p_dev: the associated PCMCIA device | ||
478 | * | ||
479 | * pcmcia_enable_device() physically enables a PCMCIA device. It parses | ||
480 | * the flags passed to in @flags and stored in @p_dev->flags and sets up | ||
481 | * the Vpp voltage, enables the speaker line, I/O ports and store proper | ||
482 | * values to configuration registers. | ||
483 | */ | ||
484 | int pcmcia_enable_device(struct pcmcia_device *p_dev) | ||
433 | { | 485 | { |
434 | int i; | 486 | int i; |
435 | u_int base; | 487 | unsigned int base; |
436 | struct pcmcia_socket *s = p_dev->socket; | 488 | struct pcmcia_socket *s = p_dev->socket; |
437 | config_t *c; | 489 | config_t *c; |
438 | pccard_io_map iomap; | 490 | pccard_io_map iomap; |
491 | unsigned char status = 0; | ||
492 | unsigned char ext_status = 0; | ||
493 | unsigned char option = 0; | ||
494 | unsigned int flags = p_dev->config_flags; | ||
439 | 495 | ||
440 | if (!(s->state & SOCKET_PRESENT)) | 496 | if (!(s->state & SOCKET_PRESENT)) |
441 | return -ENODEV; | 497 | return -ENODEV; |
442 | 498 | ||
443 | if (req->IntType & INT_CARDBUS) { | ||
444 | dev_dbg(&p_dev->dev, "IntType may not be INT_CARDBUS\n"); | ||
445 | return -EINVAL; | ||
446 | } | ||
447 | |||
448 | mutex_lock(&s->ops_mutex); | 499 | mutex_lock(&s->ops_mutex); |
449 | c = p_dev->function_config; | 500 | c = p_dev->function_config; |
450 | if (c->state & CONFIG_LOCKED) { | 501 | if (c->state & CONFIG_LOCKED) { |
@@ -454,7 +505,7 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, | |||
454 | } | 505 | } |
455 | 506 | ||
456 | /* Do power control. We don't allow changes in Vcc. */ | 507 | /* Do power control. We don't allow changes in Vcc. */ |
457 | s->socket.Vpp = req->Vpp; | 508 | s->socket.Vpp = p_dev->vpp; |
458 | if (s->ops->set_socket(s, &s->socket)) { | 509 | if (s->ops->set_socket(s, &s->socket)) { |
459 | mutex_unlock(&s->ops_mutex); | 510 | mutex_unlock(&s->ops_mutex); |
460 | dev_printk(KERN_WARNING, &p_dev->dev, | 511 | dev_printk(KERN_WARNING, &p_dev->dev, |
@@ -463,64 +514,76 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, | |||
463 | } | 514 | } |
464 | 515 | ||
465 | /* Pick memory or I/O card, DMA mode, interrupt */ | 516 | /* Pick memory or I/O card, DMA mode, interrupt */ |
466 | c->IntType = req->IntType; | 517 | if (p_dev->_io || flags & CONF_ENABLE_IRQ) |
467 | c->Attributes = req->Attributes; | 518 | flags |= CONF_ENABLE_IOCARD; |
468 | if (req->IntType & INT_MEMORY_AND_IO) | 519 | if (flags & CONF_ENABLE_IOCARD) |
469 | s->socket.flags |= SS_IOCARD; | 520 | s->socket.flags |= SS_IOCARD; |
470 | if (req->IntType & INT_ZOOMED_VIDEO) | 521 | if (flags & CONF_ENABLE_ZVCARD) |
471 | s->socket.flags |= SS_ZVCARD | SS_IOCARD; | 522 | s->socket.flags |= SS_ZVCARD | SS_IOCARD; |
472 | if (req->Attributes & CONF_ENABLE_DMA) | 523 | if (flags & CONF_ENABLE_SPKR) { |
473 | s->socket.flags |= SS_DMA_MODE; | ||
474 | if (req->Attributes & CONF_ENABLE_SPKR) | ||
475 | s->socket.flags |= SS_SPKR_ENA; | 524 | s->socket.flags |= SS_SPKR_ENA; |
476 | if (req->Attributes & CONF_ENABLE_IRQ) | 525 | status = CCSR_AUDIO_ENA; |
526 | if (!(p_dev->config_regs & PRESENT_STATUS)) | ||
527 | dev_warn(&p_dev->dev, "speaker requested, but " | ||
528 | "PRESENT_STATUS not set!\n"); | ||
529 | } | ||
530 | if (flags & CONF_ENABLE_IRQ) | ||
477 | s->socket.io_irq = s->pcmcia_irq; | 531 | s->socket.io_irq = s->pcmcia_irq; |
478 | else | 532 | else |
479 | s->socket.io_irq = 0; | 533 | s->socket.io_irq = 0; |
534 | if (flags & CONF_ENABLE_ESR) { | ||
535 | p_dev->config_regs |= PRESENT_EXT_STATUS; | ||
536 | ext_status = ESR_REQ_ATTN_ENA; | ||
537 | } | ||
480 | s->ops->set_socket(s, &s->socket); | 538 | s->ops->set_socket(s, &s->socket); |
481 | s->lock_count++; | 539 | s->lock_count++; |
482 | 540 | ||
541 | dev_dbg(&p_dev->dev, | ||
542 | "enable_device: V %d, flags %x, base %x, regs %x, idx %x\n", | ||
543 | p_dev->vpp, flags, p_dev->config_base, p_dev->config_regs, | ||
544 | p_dev->config_index); | ||
545 | |||
483 | /* Set up CIS configuration registers */ | 546 | /* Set up CIS configuration registers */ |
484 | base = c->ConfigBase = req->ConfigBase; | 547 | base = p_dev->config_base; |
485 | c->CardValues = req->Present; | 548 | if (p_dev->config_regs & PRESENT_COPY) { |
486 | if (req->Present & PRESENT_COPY) { | 549 | u16 tmp = 0; |
487 | c->Copy = req->Copy; | 550 | dev_dbg(&p_dev->dev, "clearing CISREG_SCR\n"); |
488 | pcmcia_write_cis_mem(s, 1, (base + CISREG_SCR)>>1, 1, &c->Copy); | 551 | pcmcia_write_cis_mem(s, 1, (base + CISREG_SCR)>>1, 1, &tmp); |
489 | } | 552 | } |
490 | if (req->Present & PRESENT_OPTION) { | 553 | if (p_dev->config_regs & PRESENT_PIN_REPLACE) { |
554 | u16 tmp = 0; | ||
555 | dev_dbg(&p_dev->dev, "clearing CISREG_PRR\n"); | ||
556 | pcmcia_write_cis_mem(s, 1, (base + CISREG_PRR)>>1, 1, &tmp); | ||
557 | } | ||
558 | if (p_dev->config_regs & PRESENT_OPTION) { | ||
491 | if (s->functions == 1) { | 559 | if (s->functions == 1) { |
492 | c->Option = req->ConfigIndex & COR_CONFIG_MASK; | 560 | option = p_dev->config_index & COR_CONFIG_MASK; |
493 | } else { | 561 | } else { |
494 | c->Option = req->ConfigIndex & COR_MFC_CONFIG_MASK; | 562 | option = p_dev->config_index & COR_MFC_CONFIG_MASK; |
495 | c->Option |= COR_FUNC_ENA|COR_IREQ_ENA; | 563 | option |= COR_FUNC_ENA|COR_IREQ_ENA; |
496 | if (req->Present & PRESENT_IOBASE_0) | 564 | if (p_dev->config_regs & PRESENT_IOBASE_0) |
497 | c->Option |= COR_ADDR_DECODE; | 565 | option |= COR_ADDR_DECODE; |
498 | } | 566 | } |
499 | if ((req->Attributes & CONF_ENABLE_IRQ) && | 567 | if ((flags & CONF_ENABLE_IRQ) && |
500 | !(req->Attributes & CONF_ENABLE_PULSE_IRQ)) | 568 | !(flags & CONF_ENABLE_PULSE_IRQ)) |
501 | c->Option |= COR_LEVEL_REQ; | 569 | option |= COR_LEVEL_REQ; |
502 | pcmcia_write_cis_mem(s, 1, (base + CISREG_COR)>>1, 1, &c->Option); | 570 | pcmcia_write_cis_mem(s, 1, (base + CISREG_COR)>>1, 1, &option); |
503 | mdelay(40); | 571 | mdelay(40); |
504 | } | 572 | } |
505 | if (req->Present & PRESENT_STATUS) { | 573 | if (p_dev->config_regs & PRESENT_STATUS) |
506 | c->Status = req->Status; | 574 | pcmcia_write_cis_mem(s, 1, (base + CISREG_CCSR)>>1, 1, &status); |
507 | pcmcia_write_cis_mem(s, 1, (base + CISREG_CCSR)>>1, 1, &c->Status); | 575 | |
508 | } | 576 | if (p_dev->config_regs & PRESENT_EXT_STATUS) |
509 | if (req->Present & PRESENT_PIN_REPLACE) { | 577 | pcmcia_write_cis_mem(s, 1, (base + CISREG_ESR)>>1, 1, |
510 | c->Pin = req->Pin; | 578 | &ext_status); |
511 | pcmcia_write_cis_mem(s, 1, (base + CISREG_PRR)>>1, 1, &c->Pin); | 579 | |
512 | } | 580 | if (p_dev->config_regs & PRESENT_IOBASE_0) { |
513 | if (req->Present & PRESENT_EXT_STATUS) { | ||
514 | c->ExtStatus = req->ExtStatus; | ||
515 | pcmcia_write_cis_mem(s, 1, (base + CISREG_ESR)>>1, 1, &c->ExtStatus); | ||
516 | } | ||
517 | if (req->Present & PRESENT_IOBASE_0) { | ||
518 | u8 b = c->io[0].start & 0xff; | 581 | u8 b = c->io[0].start & 0xff; |
519 | pcmcia_write_cis_mem(s, 1, (base + CISREG_IOBASE_0)>>1, 1, &b); | 582 | pcmcia_write_cis_mem(s, 1, (base + CISREG_IOBASE_0)>>1, 1, &b); |
520 | b = (c->io[0].start >> 8) & 0xff; | 583 | b = (c->io[0].start >> 8) & 0xff; |
521 | pcmcia_write_cis_mem(s, 1, (base + CISREG_IOBASE_1)>>1, 1, &b); | 584 | pcmcia_write_cis_mem(s, 1, (base + CISREG_IOBASE_1)>>1, 1, &b); |
522 | } | 585 | } |
523 | if (req->Present & PRESENT_IOSIZE) { | 586 | if (p_dev->config_regs & PRESENT_IOSIZE) { |
524 | u8 b = resource_size(&c->io[0]) + resource_size(&c->io[1]) - 1; | 587 | u8 b = resource_size(&c->io[0]) + resource_size(&c->io[1]) - 1; |
525 | pcmcia_write_cis_mem(s, 1, (base + CISREG_IOSIZE)>>1, 1, &b); | 588 | pcmcia_write_cis_mem(s, 1, (base + CISREG_IOSIZE)>>1, 1, &b); |
526 | } | 589 | } |
@@ -551,14 +614,15 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, | |||
551 | p_dev->_locked = 1; | 614 | p_dev->_locked = 1; |
552 | mutex_unlock(&s->ops_mutex); | 615 | mutex_unlock(&s->ops_mutex); |
553 | return 0; | 616 | return 0; |
554 | } /* pcmcia_request_configuration */ | 617 | } /* pcmcia_enable_device */ |
555 | EXPORT_SYMBOL(pcmcia_request_configuration); | 618 | EXPORT_SYMBOL(pcmcia_enable_device); |
556 | 619 | ||
557 | 620 | ||
558 | /** | 621 | /** |
559 | * pcmcia_request_io() - attempt to reserve port ranges for PCMCIA devices | 622 | * pcmcia_request_io() - attempt to reserve port ranges for PCMCIA devices |
623 | * @p_dev: the associated PCMCIA device | ||
560 | * | 624 | * |
561 | * pcmcia_request_io() attepts to reserve the IO port ranges specified in | 625 | * pcmcia_request_io() attempts to reserve the IO port ranges specified in |
562 | * &struct pcmcia_device @p_dev->resource[0] and @p_dev->resource[1]. The | 626 | * &struct pcmcia_device @p_dev->resource[0] and @p_dev->resource[1]. The |
563 | * "start" value is the requested start of the IO port resource; "end" | 627 | * "start" value is the requested start of the IO port resource; "end" |
564 | * reflects the number of ports requested. The number of IO lines requested | 628 | * reflects the number of ports requested. The number of IO lines requested |
@@ -622,11 +686,13 @@ EXPORT_SYMBOL(pcmcia_request_io); | |||
622 | 686 | ||
623 | /** | 687 | /** |
624 | * pcmcia_request_irq() - attempt to request a IRQ for a PCMCIA device | 688 | * pcmcia_request_irq() - attempt to request a IRQ for a PCMCIA device |
689 | * @p_dev: the associated PCMCIA device | ||
690 | * @handler: IRQ handler to register | ||
625 | * | 691 | * |
626 | * pcmcia_request_irq() is a wrapper around request_irq which will allow | 692 | * pcmcia_request_irq() is a wrapper around request_irq() which allows |
627 | * the PCMCIA core to clean up the registration in pcmcia_disable_device(). | 693 | * the PCMCIA core to clean up the registration in pcmcia_disable_device(). |
628 | * Drivers are free to use request_irq() directly, but then they need to | 694 | * Drivers are free to use request_irq() directly, but then they need to |
629 | * call free_irq themselfves, too. Also, only IRQF_SHARED capable IRQ | 695 | * call free_irq() themselfves, too. Also, only %IRQF_SHARED capable IRQ |
630 | * handlers are allowed. | 696 | * handlers are allowed. |
631 | */ | 697 | */ |
632 | int __must_check pcmcia_request_irq(struct pcmcia_device *p_dev, | 698 | int __must_check pcmcia_request_irq(struct pcmcia_device *p_dev, |
@@ -649,12 +715,14 @@ EXPORT_SYMBOL(pcmcia_request_irq); | |||
649 | 715 | ||
650 | /** | 716 | /** |
651 | * pcmcia_request_exclusive_irq() - attempt to request an exclusive IRQ first | 717 | * pcmcia_request_exclusive_irq() - attempt to request an exclusive IRQ first |
718 | * @p_dev: the associated PCMCIA device | ||
719 | * @handler: IRQ handler to register | ||
652 | * | 720 | * |
653 | * pcmcia_request_exclusive_irq() is a wrapper around request_irq which | 721 | * pcmcia_request_exclusive_irq() is a wrapper around request_irq() which |
654 | * attempts first to request an exclusive IRQ. If it fails, it also accepts | 722 | * attempts first to request an exclusive IRQ. If it fails, it also accepts |
655 | * a shared IRQ, but prints out a warning. PCMCIA drivers should allow for | 723 | * a shared IRQ, but prints out a warning. PCMCIA drivers should allow for |
656 | * IRQ sharing and either use request_irq directly (then they need to call | 724 | * IRQ sharing and either use request_irq directly (then they need to call |
657 | * free_irq themselves, too), or the pcmcia_request_irq() function. | 725 | * free_irq() themselves, too), or the pcmcia_request_irq() function. |
658 | */ | 726 | */ |
659 | int __must_check | 727 | int __must_check |
660 | __pcmcia_request_exclusive_irq(struct pcmcia_device *p_dev, | 728 | __pcmcia_request_exclusive_irq(struct pcmcia_device *p_dev, |
@@ -795,38 +863,47 @@ int pcmcia_setup_irq(struct pcmcia_device *p_dev) | |||
795 | } | 863 | } |
796 | 864 | ||
797 | 865 | ||
798 | /** pcmcia_request_window | 866 | /** |
867 | * pcmcia_request_window() - attempt to reserve iomem for PCMCIA devices | ||
868 | * @p_dev: the associated PCMCIA device | ||
869 | * @res: &struct resource pointing to p_dev->resource[2..5] | ||
870 | * @speed: access speed | ||
799 | * | 871 | * |
800 | * Request_window() establishes a mapping between card memory space | 872 | * pcmcia_request_window() attepts to reserve an iomem ranges specified in |
801 | * and system memory space. | 873 | * &struct resource @res pointing to one of the entries in |
874 | * &struct pcmcia_device @p_dev->resource[2..5]. The "start" value is the | ||
875 | * requested start of the IO mem resource; "end" reflects the size | ||
876 | * requested. | ||
802 | */ | 877 | */ |
803 | int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_handle_t *wh) | 878 | int pcmcia_request_window(struct pcmcia_device *p_dev, struct resource *res, |
879 | unsigned int speed) | ||
804 | { | 880 | { |
805 | struct pcmcia_socket *s = p_dev->socket; | 881 | struct pcmcia_socket *s = p_dev->socket; |
806 | pccard_mem_map *win; | 882 | pccard_mem_map *win; |
807 | u_long align; | 883 | u_long align; |
808 | struct resource *res; | ||
809 | int w; | 884 | int w; |
810 | 885 | ||
886 | dev_dbg(&p_dev->dev, "request_window %pR %d\n", res, speed); | ||
887 | |||
811 | if (!(s->state & SOCKET_PRESENT)) { | 888 | if (!(s->state & SOCKET_PRESENT)) { |
812 | dev_dbg(&p_dev->dev, "No card present\n"); | 889 | dev_dbg(&p_dev->dev, "No card present\n"); |
813 | return -ENODEV; | 890 | return -ENODEV; |
814 | } | 891 | } |
815 | 892 | ||
816 | /* Window size defaults to smallest available */ | 893 | /* Window size defaults to smallest available */ |
817 | if (req->Size == 0) | 894 | if (res->end == 0) |
818 | req->Size = s->map_size; | 895 | res->end = s->map_size; |
819 | align = (s->features & SS_CAP_MEM_ALIGN) ? req->Size : s->map_size; | 896 | align = (s->features & SS_CAP_MEM_ALIGN) ? res->end : s->map_size; |
820 | if (req->Size & (s->map_size-1)) { | 897 | if (res->end & (s->map_size-1)) { |
821 | dev_dbg(&p_dev->dev, "invalid map size\n"); | 898 | dev_dbg(&p_dev->dev, "invalid map size\n"); |
822 | return -EINVAL; | 899 | return -EINVAL; |
823 | } | 900 | } |
824 | if ((req->Base && (s->features & SS_CAP_STATIC_MAP)) || | 901 | if ((res->start && (s->features & SS_CAP_STATIC_MAP)) || |
825 | (req->Base & (align-1))) { | 902 | (res->start & (align-1))) { |
826 | dev_dbg(&p_dev->dev, "invalid base address\n"); | 903 | dev_dbg(&p_dev->dev, "invalid base address\n"); |
827 | return -EINVAL; | 904 | return -EINVAL; |
828 | } | 905 | } |
829 | if (req->Base) | 906 | if (res->start) |
830 | align = 0; | 907 | align = 0; |
831 | 908 | ||
832 | /* Allocate system memory window */ | 909 | /* Allocate system memory window */ |
@@ -843,7 +920,7 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha | |||
843 | win = &s->win[w]; | 920 | win = &s->win[w]; |
844 | 921 | ||
845 | if (!(s->features & SS_CAP_STATIC_MAP)) { | 922 | if (!(s->features & SS_CAP_STATIC_MAP)) { |
846 | win->res = pcmcia_find_mem_region(req->Base, req->Size, align, | 923 | win->res = pcmcia_find_mem_region(res->start, res->end, align, |
847 | 0, s); | 924 | 0, s); |
848 | if (!win->res) { | 925 | if (!win->res) { |
849 | dev_dbg(&p_dev->dev, "allocating mem region failed\n"); | 926 | dev_dbg(&p_dev->dev, "allocating mem region failed\n"); |
@@ -855,8 +932,8 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha | |||
855 | 932 | ||
856 | /* Configure the socket controller */ | 933 | /* Configure the socket controller */ |
857 | win->map = w+1; | 934 | win->map = w+1; |
858 | win->flags = req->Attributes; | 935 | win->flags = res->flags & WIN_FLAGS_MAP; |
859 | win->speed = req->AccessSpeed; | 936 | win->speed = speed; |
860 | win->card_start = 0; | 937 | win->card_start = 0; |
861 | 938 | ||
862 | if (s->ops->set_mem_map(s, win) != 0) { | 939 | if (s->ops->set_mem_map(s, win) != 0) { |
@@ -868,17 +945,14 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha | |||
868 | 945 | ||
869 | /* Return window handle */ | 946 | /* Return window handle */ |
870 | if (s->features & SS_CAP_STATIC_MAP) | 947 | if (s->features & SS_CAP_STATIC_MAP) |
871 | req->Base = win->static_start; | 948 | res->start = win->static_start; |
872 | else | 949 | else |
873 | req->Base = win->res->start; | 950 | res->start = win->res->start; |
874 | 951 | ||
875 | /* convert to new-style resources */ | 952 | /* convert to new-style resources */ |
876 | res = p_dev->resource[w + MAX_IO_WIN]; | 953 | res->end += res->start - 1; |
877 | res->start = req->Base; | 954 | res->flags &= ~WIN_FLAGS_REQ; |
878 | res->end = req->Base + req->Size - 1; | 955 | res->flags |= (win->map << 2) | IORESOURCE_MEM; |
879 | res->flags &= ~IORESOURCE_BITS; | ||
880 | res->flags |= (req->Attributes & WIN_FLAGS_MAP) | (win->map << 2); | ||
881 | res->flags |= IORESOURCE_MEM; | ||
882 | res->parent = win->res; | 956 | res->parent = win->res; |
883 | if (win->res) | 957 | if (win->res) |
884 | request_resource(&iomem_resource, res); | 958 | request_resource(&iomem_resource, res); |
@@ -886,15 +960,30 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha | |||
886 | dev_dbg(&p_dev->dev, "request_window results in %pR\n", res); | 960 | dev_dbg(&p_dev->dev, "request_window results in %pR\n", res); |
887 | 961 | ||
888 | mutex_unlock(&s->ops_mutex); | 962 | mutex_unlock(&s->ops_mutex); |
889 | *wh = res; | ||
890 | 963 | ||
891 | return 0; | 964 | return 0; |
892 | } /* pcmcia_request_window */ | 965 | } /* pcmcia_request_window */ |
893 | EXPORT_SYMBOL(pcmcia_request_window); | 966 | EXPORT_SYMBOL(pcmcia_request_window); |
894 | 967 | ||
968 | |||
969 | /** | ||
970 | * pcmcia_disable_device() - disable and clean up a PCMCIA device | ||
971 | * @p_dev: the associated PCMCIA device | ||
972 | * | ||
973 | * pcmcia_disable_device() is the driver-callable counterpart to | ||
974 | * pcmcia_enable_device(): If a PCMCIA device is no longer used, | ||
975 | * drivers are expected to clean up and disable the device by calling | ||
976 | * this function. Any I/O ranges (iomem and ioports) will be released, | ||
977 | * the Vpp voltage will be set to 0, and IRQs will no longer be | ||
978 | * generated -- at least if there is no other card function (of | ||
979 | * multifunction devices) being used. | ||
980 | */ | ||
895 | void pcmcia_disable_device(struct pcmcia_device *p_dev) | 981 | void pcmcia_disable_device(struct pcmcia_device *p_dev) |
896 | { | 982 | { |
897 | int i; | 983 | int i; |
984 | |||
985 | dev_dbg(&p_dev->dev, "disabling device\n"); | ||
986 | |||
898 | for (i = 0; i < MAX_WIN; i++) { | 987 | for (i = 0; i < MAX_WIN; i++) { |
899 | struct resource *res = p_dev->resource[MAX_IO_WIN + i]; | 988 | struct resource *res = p_dev->resource[MAX_IO_WIN + i]; |
900 | if (res->flags & WIN_FLAGS_REQ) | 989 | if (res->flags & WIN_FLAGS_REQ) |