]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/pcmcia/pcmcia_resource.c
pcmcia: remove pcmcia_add_device_lock
[mirror_ubuntu-artful-kernel.git] / drivers / pcmcia / pcmcia_resource.c
CommitLineData
1a8d4663
DB
1/*
2 * PCMCIA 16-bit resource management functions
3 *
4 * The initial developer of the original code is David A. Hinds
5 * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
6 * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
7 *
8 * Copyright (C) 1999 David A. Hinds
9 * Copyright (C) 2004-2005 Dominik Brodowski
10 *
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
13 * published by the Free Software Foundation.
14 *
15 */
16
1a8d4663
DB
17#include <linux/module.h>
18#include <linux/kernel.h>
19#include <linux/interrupt.h>
20#include <linux/delay.h>
21#include <linux/pci.h>
22#include <linux/device.h>
91284224 23#include <linux/netdevice.h>
5a0e3ad6 24#include <linux/slab.h>
1a8d4663 25
6f0f38c4
DB
26#include <asm/irq.h>
27
1a8d4663
DB
28#include <pcmcia/cs_types.h>
29#include <pcmcia/ss.h>
30#include <pcmcia/cs.h>
1a8d4663
DB
31#include <pcmcia/cistpl.h>
32#include <pcmcia/cisreg.h>
33#include <pcmcia/ds.h>
34
35#include "cs_internal.h"
1a8d4663
DB
36
37
1a8d4663 38/* Access speed for IO windows */
9fea84f4 39static int io_speed;
1a8d4663
DB
40module_param(io_speed, int, 0444);
41
42
a3ac9af5
DB
43int pcmcia_validate_mem(struct pcmcia_socket *s)
44{
45 if (s->resource_ops->validate_mem)
46 return s->resource_ops->validate_mem(s);
47 /* if there is no callback, we can assume that everything is OK */
48 return 0;
49}
50
51struct resource *pcmcia_find_mem_region(u_long base, u_long num, u_long align,
52 int low, struct pcmcia_socket *s)
53{
54 if (s->resource_ops->find_mem)
55 return s->resource_ops->find_mem(base, num, align, low, s);
56 return NULL;
57}
58
1a8d4663 59
1a8d4663
DB
60/** alloc_io_space
61 *
62 * Special stuff for managing IO windows, because they are scarce
63 */
64
ecb8a847
OJ
65static int alloc_io_space(struct pcmcia_socket *s, u_int attr,
66 unsigned int *base, unsigned int num, u_int lines)
1a8d4663 67{
b19a7275 68 unsigned int align;
1a8d4663
DB
69
70 align = (*base) ? (lines ? 1<<lines : 0) : 1;
71 if (align && (align < num)) {
72 if (*base) {
d50dbec3 73 dev_dbg(&s->dev, "odd IO request: num %#x align %#x\n",
1a8d4663
DB
74 num, align);
75 align = 0;
76 } else
9fea84f4
DB
77 while (align && (align < num))
78 align <<= 1;
1a8d4663
DB
79 }
80 if (*base & ~(align-1)) {
d50dbec3 81 dev_dbg(&s->dev, "odd IO request: base %#x align %#x\n",
1a8d4663
DB
82 *base, align);
83 align = 0;
84 }
b19a7275
DB
85
86 return s->resource_ops->find_io(s, attr, base, num, align);
1a8d4663
DB
87} /* alloc_io_space */
88
89
ecb8a847
OJ
90static void release_io_space(struct pcmcia_socket *s, unsigned int base,
91 unsigned int num)
1a8d4663
DB
92{
93 int i;
94
95 for (i = 0; i < MAX_IO_WIN; i++) {
c7d00693
DB
96 if (!s->io[i].res)
97 continue;
98 if ((s->io[i].res->start <= base) &&
99 (s->io[i].res->end >= base+num-1)) {
1a8d4663
DB
100 s->io[i].InUse -= num;
101 /* Free the window if no one else is using it */
102 if (s->io[i].InUse == 0) {
1a8d4663
DB
103 release_resource(s->io[i].res);
104 kfree(s->io[i].res);
105 s->io[i].res = NULL;
106 }
107 }
108 }
109} /* release_io_space */
110
111
112/** pccard_access_configuration_register
113 *
114 * Access_configuration_register() reads and writes configuration
115 * registers in attribute memory. Memory window 0 is reserved for
116 * this and the tuple reading services.
117 */
118
855cdf13 119int pcmcia_access_configuration_register(struct pcmcia_device *p_dev,
1a8d4663
DB
120 conf_reg_t *reg)
121{
855cdf13 122 struct pcmcia_socket *s;
1a8d4663
DB
123 config_t *c;
124 int addr;
125 u_char val;
126
855cdf13 127 if (!p_dev || !p_dev->function_config)
3939c1ef 128 return -EINVAL;
1a8d4663 129
855cdf13 130 s = p_dev->socket;
94a819f8
DB
131
132 mutex_lock(&s->ops_mutex);
855cdf13 133 c = p_dev->function_config;
1a8d4663 134
6d9a299f
DB
135 if (!(c->state & CONFIG_LOCKED)) {
136 dev_dbg(&s->dev, "Configuration isnt't locked\n");
94a819f8 137 mutex_unlock(&s->ops_mutex);
943f70f1 138 return -EACCES;
6d9a299f 139 }
1a8d4663
DB
140
141 addr = (c->ConfigBase + reg->Offset) >> 1;
94a819f8 142 mutex_unlock(&s->ops_mutex);
1a8d4663
DB
143
144 switch (reg->Action) {
145 case CS_READ:
146 pcmcia_read_cis_mem(s, 1, addr, 1, &val);
147 reg->Value = val;
148 break;
149 case CS_WRITE:
150 val = reg->Value;
151 pcmcia_write_cis_mem(s, 1, addr, 1, &val);
152 break;
153 default:
6d9a299f 154 dev_dbg(&s->dev, "Invalid conf register request\n");
926c5402 155 return -EINVAL;
1a8d4663
DB
156 break;
157 }
4c89e88b 158 return 0;
855cdf13 159} /* pcmcia_access_configuration_register */
3448139b
DB
160EXPORT_SYMBOL(pcmcia_access_configuration_register);
161
1a8d4663 162
868575d1
MD
163int pcmcia_map_mem_page(struct pcmcia_device *p_dev, window_handle_t wh,
164 memreq_t *req)
1a8d4663 165{
0bdf9b3d 166 struct pcmcia_socket *s = p_dev->socket;
6b8e087b 167 int ret;
868575d1 168
0bdf9b3d
MD
169 wh--;
170 if (wh >= MAX_WIN)
ffb8da20 171 return -EINVAL;
610e2374 172 if (req->Page != 0) {
d50dbec3 173 dev_dbg(&s->dev, "failure: requested page is zero\n");
610e2374
DB
174 return -EINVAL;
175 }
6b8e087b 176 mutex_lock(&s->ops_mutex);
82f88e36 177 s->win[wh].card_start = req->CardOffset;
6b8e087b
DB
178 ret = s->ops->set_mem_map(s, &s->win[wh]);
179 if (ret)
180 dev_warn(&s->dev, "failed to set_mem_map\n");
181 mutex_unlock(&s->ops_mutex);
182 return ret;
1a8d4663
DB
183} /* pcmcia_map_mem_page */
184EXPORT_SYMBOL(pcmcia_map_mem_page);
185
186
187/** pcmcia_modify_configuration
188 *
189 * Modify a locked socket configuration
190 */
2bc5a9bd 191int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
1a8d4663
DB
192 modconf_t *mod)
193{
194 struct pcmcia_socket *s;
195 config_t *c;
4e06e240 196 int ret;
1a8d4663 197
2bc5a9bd 198 s = p_dev->socket;
94a819f8
DB
199
200 mutex_lock(&s->ops_mutex);
dbb22f0d
DB
201 c = p_dev->function_config;
202
6d9a299f
DB
203 if (!(s->state & SOCKET_PRESENT)) {
204 dev_dbg(&s->dev, "No card present\n");
4e06e240
JS
205 ret = -ENODEV;
206 goto unlock;
6d9a299f
DB
207 }
208 if (!(c->state & CONFIG_LOCKED)) {
209 dev_dbg(&s->dev, "Configuration isnt't locked\n");
4e06e240
JS
210 ret = -EACCES;
211 goto unlock;
6d9a299f 212 }
1a8d4663 213
0cb3c49c
DB
214 if (mod->Attributes & (CONF_IRQ_CHANGE_VALID | CONF_VCC_CHANGE_VALID)) {
215 dev_dbg(&s->dev,
216 "changing Vcc or IRQ is not allowed at this time\n");
4e06e240
JS
217 ret = -EINVAL;
218 goto unlock;
d8b0a49d 219 }
1a8d4663
DB
220
221 /* We only allow changing Vpp1 and Vpp2 to the same value */
222 if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) &&
223 (mod->Attributes & CONF_VPP2_CHANGE_VALID)) {
60df3de8 224 if (mod->Vpp1 != mod->Vpp2) {
d50dbec3 225 dev_dbg(&s->dev, "Vpp1 and Vpp2 must be the same\n");
4e06e240
JS
226 ret = -EINVAL;
227 goto unlock;
60df3de8 228 }
71ed90d8 229 s->socket.Vpp = mod->Vpp1;
d8b0a49d
DB
230 if (s->ops->set_socket(s, &s->socket)) {
231 dev_printk(KERN_WARNING, &s->dev,
232 "Unable to set VPP\n");
4e06e240
JS
233 ret = -EIO;
234 goto unlock;
d8b0a49d 235 }
1a8d4663 236 } else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) ||
d8b0a49d 237 (mod->Attributes & CONF_VPP2_CHANGE_VALID)) {
d50dbec3 238 dev_dbg(&s->dev, "changing Vcc is not allowed at this time\n");
4e06e240
JS
239 ret = -EINVAL;
240 goto unlock;
d8b0a49d 241 }
1a8d4663 242
4bbed523
DB
243 if (mod->Attributes & CONF_IO_CHANGE_WIDTH) {
244 pccard_io_map io_off = { 0, 0, 0, 0, 1 };
245 pccard_io_map io_on;
246 int i;
247
248 io_on.speed = io_speed;
249 for (i = 0; i < MAX_IO_WIN; i++) {
250 if (!s->io[i].res)
251 continue;
252 io_off.map = i;
253 io_on.map = i;
254
255 io_on.flags = MAP_ACTIVE | IO_DATA_PATH_WIDTH_8;
256 io_on.start = s->io[i].res->start;
257 io_on.stop = s->io[i].res->end;
258
259 s->ops->set_io_map(s, &io_off);
260 mdelay(40);
261 s->ops->set_io_map(s, &io_on);
262 }
263 }
4e06e240
JS
264 ret = 0;
265unlock:
94a819f8 266 mutex_unlock(&s->ops_mutex);
4bbed523 267
4e06e240 268 return ret;
1a8d4663
DB
269} /* modify_configuration */
270EXPORT_SYMBOL(pcmcia_modify_configuration);
271
272
2bc5a9bd 273int pcmcia_release_configuration(struct pcmcia_device *p_dev)
1a8d4663
DB
274{
275 pccard_io_map io = { 0, 0, 0, 0, 1 };
2bc5a9bd 276 struct pcmcia_socket *s = p_dev->socket;
94a819f8 277 config_t *c;
1a8d4663
DB
278 int i;
279
9e86749c 280 mutex_lock(&s->ops_mutex);
94a819f8 281 c = p_dev->function_config;
e2d40963
DB
282 if (p_dev->_locked) {
283 p_dev->_locked = 0;
1a8d4663
DB
284 if (--(s->lock_count) == 0) {
285 s->socket.flags = SS_OUTPUT_ENA; /* Is this correct? */
286 s->socket.Vpp = 0;
287 s->socket.io_irq = 0;
288 s->ops->set_socket(s, &s->socket);
289 }
5f2a71fc
DB
290 }
291 if (c->state & CONFIG_LOCKED) {
292 c->state &= ~CONFIG_LOCKED;
1a8d4663
DB
293 if (c->state & CONFIG_IO_REQ)
294 for (i = 0; i < MAX_IO_WIN; i++) {
c7d00693 295 if (!s->io[i].res)
1a8d4663
DB
296 continue;
297 s->io[i].Config--;
298 if (s->io[i].Config != 0)
299 continue;
300 io.map = i;
301 s->ops->set_io_map(s, &io);
302 }
1a8d4663 303 }
9e86749c 304 mutex_unlock(&s->ops_mutex);
1a8d4663 305
4c89e88b 306 return 0;
1a8d4663 307} /* pcmcia_release_configuration */
1a8d4663
DB
308
309
310/** pcmcia_release_io
311 *
312 * Release_io() releases the I/O ranges allocated by a client. This
313 * may be invoked some time after a card ejection has already dumped
314 * the actual socket configuration, so if the client is "stale", we
315 * don't bother checking the port ranges against the current socket
316 * values.
317 */
b4c88400 318static int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req)
1a8d4663 319{
2bc5a9bd 320 struct pcmcia_socket *s = p_dev->socket;
94a819f8
DB
321 int ret = -EINVAL;
322 config_t *c;
323
324 mutex_lock(&s->ops_mutex);
325 c = p_dev->function_config;
1a8d4663 326
9fea84f4 327 if (!p_dev->_io)
94a819f8 328 goto out;
5f2a71fc 329
e2d40963 330 p_dev->_io = 0;
1a8d4663 331
5f2a71fc
DB
332 if ((c->io.BasePort1 != req->BasePort1) ||
333 (c->io.NumPorts1 != req->NumPorts1) ||
334 (c->io.BasePort2 != req->BasePort2) ||
335 (c->io.NumPorts2 != req->NumPorts2))
94a819f8 336 goto out;
5f2a71fc
DB
337
338 c->state &= ~CONFIG_IO_REQ;
1a8d4663
DB
339
340 release_io_space(s, req->BasePort1, req->NumPorts1);
341 if (req->NumPorts2)
342 release_io_space(s, req->BasePort2, req->NumPorts2);
343
94a819f8
DB
344out:
345 mutex_unlock(&s->ops_mutex);
346
347 return ret;
1a8d4663 348} /* pcmcia_release_io */
1a8d4663
DB
349
350
f5560da5 351int pcmcia_release_window(struct pcmcia_device *p_dev, window_handle_t wh)
1a8d4663 352{
0bdf9b3d 353 struct pcmcia_socket *s = p_dev->socket;
82f88e36 354 pccard_mem_map *win;
1a8d4663 355
0bdf9b3d
MD
356 wh--;
357 if (wh >= MAX_WIN)
ffb8da20 358 return -EINVAL;
0bdf9b3d 359
6b8e087b 360 mutex_lock(&s->ops_mutex);
0bdf9b3d
MD
361 win = &s->win[wh];
362
363 if (!(p_dev->_win & CLIENT_WIN_REQ(wh))) {
6d9a299f 364 dev_dbg(&s->dev, "not releasing unknown window\n");
6b8e087b 365 mutex_unlock(&s->ops_mutex);
ffb8da20 366 return -EINVAL;
6d9a299f 367 }
1a8d4663
DB
368
369 /* Shut down memory window */
82f88e36
DB
370 win->flags &= ~MAP_ACTIVE;
371 s->ops->set_mem_map(s, win);
0bdf9b3d 372 s->state &= ~SOCKET_WIN_REQ(wh);
1a8d4663
DB
373
374 /* Release system memory */
82f88e36
DB
375 if (win->res) {
376 release_resource(win->res);
377 kfree(win->res);
378 win->res = NULL;
1a8d4663 379 }
0bdf9b3d 380 p_dev->_win &= ~CLIENT_WIN_REQ(wh);
6b8e087b 381 mutex_unlock(&s->ops_mutex);
1a8d4663 382
4c89e88b 383 return 0;
1a8d4663
DB
384} /* pcmcia_release_window */
385EXPORT_SYMBOL(pcmcia_release_window);
386
387
2bc5a9bd 388int pcmcia_request_configuration(struct pcmcia_device *p_dev,
1a8d4663
DB
389 config_req_t *req)
390{
391 int i;
392 u_int base;
2bc5a9bd 393 struct pcmcia_socket *s = p_dev->socket;
1a8d4663
DB
394 config_t *c;
395 pccard_io_map iomap;
396
1a8d4663 397 if (!(s->state & SOCKET_PRESENT))
d598de02 398 return -ENODEV;
1a8d4663 399
de6405e9 400 if (req->IntType & INT_CARDBUS) {
d50dbec3 401 dev_dbg(&s->dev, "IntType may not be INT_CARDBUS\n");
de6405e9
DB
402 return -EINVAL;
403 }
94a819f8
DB
404
405 mutex_lock(&s->ops_mutex);
dbb22f0d 406 c = p_dev->function_config;
6d9a299f 407 if (c->state & CONFIG_LOCKED) {
94a819f8 408 mutex_unlock(&s->ops_mutex);
6d9a299f 409 dev_dbg(&s->dev, "Configuration is locked\n");
943f70f1 410 return -EACCES;
6d9a299f 411 }
1a8d4663
DB
412
413 /* Do power control. We don't allow changes in Vcc. */
70294b46 414 s->socket.Vpp = req->Vpp;
d8b0a49d 415 if (s->ops->set_socket(s, &s->socket)) {
9e86749c 416 mutex_unlock(&s->ops_mutex);
d8b0a49d
DB
417 dev_printk(KERN_WARNING, &s->dev,
418 "Unable to set socket state\n");
419 return -EINVAL;
420 }
1a8d4663 421
1a8d4663
DB
422 /* Pick memory or I/O card, DMA mode, interrupt */
423 c->IntType = req->IntType;
424 c->Attributes = req->Attributes;
425 if (req->IntType & INT_MEMORY_AND_IO)
426 s->socket.flags |= SS_IOCARD;
427 if (req->IntType & INT_ZOOMED_VIDEO)
428 s->socket.flags |= SS_ZVCARD | SS_IOCARD;
429 if (req->Attributes & CONF_ENABLE_DMA)
430 s->socket.flags |= SS_DMA_MODE;
431 if (req->Attributes & CONF_ENABLE_SPKR)
432 s->socket.flags |= SS_SPKR_ENA;
433 if (req->Attributes & CONF_ENABLE_IRQ)
6f840afb 434 s->socket.io_irq = s->pcmcia_irq;
1a8d4663
DB
435 else
436 s->socket.io_irq = 0;
437 s->ops->set_socket(s, &s->socket);
438 s->lock_count++;
9e86749c 439 mutex_unlock(&s->ops_mutex);
1a8d4663
DB
440
441 /* Set up CIS configuration registers */
442 base = c->ConfigBase = req->ConfigBase;
1ae9c7d8 443 c->CardValues = req->Present;
1a8d4663
DB
444 if (req->Present & PRESENT_COPY) {
445 c->Copy = req->Copy;
446 pcmcia_write_cis_mem(s, 1, (base + CISREG_SCR)>>1, 1, &c->Copy);
447 }
448 if (req->Present & PRESENT_OPTION) {
449 if (s->functions == 1) {
450 c->Option = req->ConfigIndex & COR_CONFIG_MASK;
451 } else {
452 c->Option = req->ConfigIndex & COR_MFC_CONFIG_MASK;
453 c->Option |= COR_FUNC_ENA|COR_IREQ_ENA;
454 if (req->Present & PRESENT_IOBASE_0)
455 c->Option |= COR_ADDR_DECODE;
456 }
a7debe78
DB
457 if ((req->Attributes & CONF_ENABLE_IRQ) &&
458 !(req->Attributes & CONF_ENABLE_PULSE_IRQ))
459 c->Option |= COR_LEVEL_REQ;
1a8d4663
DB
460 pcmcia_write_cis_mem(s, 1, (base + CISREG_COR)>>1, 1, &c->Option);
461 mdelay(40);
462 }
463 if (req->Present & PRESENT_STATUS) {
464 c->Status = req->Status;
465 pcmcia_write_cis_mem(s, 1, (base + CISREG_CCSR)>>1, 1, &c->Status);
466 }
467 if (req->Present & PRESENT_PIN_REPLACE) {
468 c->Pin = req->Pin;
469 pcmcia_write_cis_mem(s, 1, (base + CISREG_PRR)>>1, 1, &c->Pin);
470 }
471 if (req->Present & PRESENT_EXT_STATUS) {
472 c->ExtStatus = req->ExtStatus;
473 pcmcia_write_cis_mem(s, 1, (base + CISREG_ESR)>>1, 1, &c->ExtStatus);
474 }
475 if (req->Present & PRESENT_IOBASE_0) {
476 u_char b = c->io.BasePort1 & 0xff;
477 pcmcia_write_cis_mem(s, 1, (base + CISREG_IOBASE_0)>>1, 1, &b);
478 b = (c->io.BasePort1 >> 8) & 0xff;
479 pcmcia_write_cis_mem(s, 1, (base + CISREG_IOBASE_1)>>1, 1, &b);
480 }
481 if (req->Present & PRESENT_IOSIZE) {
482 u_char b = c->io.NumPorts1 + c->io.NumPorts2 - 1;
483 pcmcia_write_cis_mem(s, 1, (base + CISREG_IOSIZE)>>1, 1, &b);
484 }
485
486 /* Configure I/O windows */
487 if (c->state & CONFIG_IO_REQ) {
8533ee31 488 mutex_lock(&s->ops_mutex);
1a8d4663
DB
489 iomap.speed = io_speed;
490 for (i = 0; i < MAX_IO_WIN; i++)
c7d00693 491 if (s->io[i].res) {
1a8d4663
DB
492 iomap.map = i;
493 iomap.flags = MAP_ACTIVE;
c7d00693 494 switch (s->io[i].res->flags & IO_DATA_PATH_WIDTH) {
1a8d4663
DB
495 case IO_DATA_PATH_WIDTH_16:
496 iomap.flags |= MAP_16BIT; break;
497 case IO_DATA_PATH_WIDTH_AUTO:
498 iomap.flags |= MAP_AUTOSZ; break;
499 default:
500 break;
501 }
c7d00693
DB
502 iomap.start = s->io[i].res->start;
503 iomap.stop = s->io[i].res->end;
1a8d4663
DB
504 s->ops->set_io_map(s, &iomap);
505 s->io[i].Config++;
506 }
8533ee31 507 mutex_unlock(&s->ops_mutex);
1a8d4663
DB
508 }
509
510 c->state |= CONFIG_LOCKED;
e2d40963 511 p_dev->_locked = 1;
4c89e88b 512 return 0;
1a8d4663
DB
513} /* pcmcia_request_configuration */
514EXPORT_SYMBOL(pcmcia_request_configuration);
515
516
517/** pcmcia_request_io
518 *
519 * Request_io() reserves ranges of port addresses for a socket.
520 * I have not implemented range sharing or alias addressing.
521 */
2bc5a9bd 522int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req)
1a8d4663 523{
2bc5a9bd 524 struct pcmcia_socket *s = p_dev->socket;
1a8d4663 525 config_t *c;
94a819f8
DB
526 int ret = -EINVAL;
527
528 mutex_lock(&s->ops_mutex);
1a8d4663 529
6d9a299f
DB
530 if (!(s->state & SOCKET_PRESENT)) {
531 dev_dbg(&s->dev, "No card present\n");
94a819f8 532 goto out;
6d9a299f 533 }
1a8d4663 534
1a8d4663 535 if (!req)
94a819f8
DB
536 goto out;
537
dbb22f0d 538 c = p_dev->function_config;
6d9a299f
DB
539 if (c->state & CONFIG_LOCKED) {
540 dev_dbg(&s->dev, "Configuration is locked\n");
94a819f8 541 goto out;
6d9a299f 542 }
f958095e 543 if (c->state & CONFIG_IO_REQ) {
d50dbec3 544 dev_dbg(&s->dev, "IO already configured\n");
94a819f8 545 goto out;
f958095e 546 }
610e2374 547 if (req->Attributes1 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS)) {
d50dbec3 548 dev_dbg(&s->dev, "bad attribute setting for IO region 1\n");
94a819f8 549 goto out;
610e2374 550 }
1a8d4663 551 if ((req->NumPorts2 > 0) &&
610e2374 552 (req->Attributes2 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS))) {
d50dbec3 553 dev_dbg(&s->dev, "bad attribute setting for IO region 2\n");
94a819f8 554 goto out;
610e2374 555 }
1a8d4663 556
d50dbec3 557 dev_dbg(&s->dev, "trying to allocate resource 1\n");
94a819f8
DB
558 ret = alloc_io_space(s, req->Attributes1, &req->BasePort1,
559 req->NumPorts1, req->IOAddrLines);
560 if (ret) {
d50dbec3 561 dev_dbg(&s->dev, "allocation of resource 1 failed\n");
94a819f8 562 goto out;
f958095e 563 }
1a8d4663
DB
564
565 if (req->NumPorts2) {
d50dbec3 566 dev_dbg(&s->dev, "trying to allocate resource 2\n");
94a819f8
DB
567 ret = alloc_io_space(s, req->Attributes2, &req->BasePort2,
568 req->NumPorts2, req->IOAddrLines);
569 if (ret) {
d50dbec3 570 dev_dbg(&s->dev, "allocation of resource 2 failed\n");
1a8d4663 571 release_io_space(s, req->BasePort1, req->NumPorts1);
94a819f8 572 goto out;
1a8d4663
DB
573 }
574 }
575
576 c->io = *req;
577 c->state |= CONFIG_IO_REQ;
e2d40963 578 p_dev->_io = 1;
94a819f8
DB
579 dev_dbg(&s->dev, "allocating resources succeeded: %d\n", ret);
580
581out:
582 mutex_unlock(&s->ops_mutex);
583
584 return ret;
1a8d4663
DB
585} /* pcmcia_request_io */
586EXPORT_SYMBOL(pcmcia_request_io);
587
588
eb14120f
DB
589/**
590 * pcmcia_request_irq() - attempt to request a IRQ for a PCMCIA device
1a8d4663 591 *
eb14120f
DB
592 * pcmcia_request_irq() is a wrapper around request_irq which will allow
593 * the PCMCIA core to clean up the registration in pcmcia_disable_device().
594 * Drivers are free to use request_irq() directly, but then they need to
595 * call free_irq themselfves, too. Also, only IRQF_SHARED capable IRQ
596 * handlers are allowed.
1a8d4663 597 */
eb14120f
DB
598int __must_check pcmcia_request_irq(struct pcmcia_device *p_dev,
599 irq_handler_t handler)
1a8d4663 600{
eb14120f 601 int ret;
1a8d4663 602
eb14120f
DB
603 if (!p_dev->irq)
604 return -EINVAL;
94a819f8 605
eb14120f
DB
606 ret = request_irq(p_dev->irq, handler, IRQF_SHARED,
607 p_dev->devname, p_dev->priv);
608 if (!ret)
609 p_dev->_irq = 1;
1a8d4663 610
eb14120f
DB
611 return ret;
612}
613EXPORT_SYMBOL(pcmcia_request_irq);
6f0f38c4 614
1a8d4663 615
eb14120f
DB
616/**
617 * pcmcia_request_exclusive_irq() - attempt to request an exclusive IRQ first
618 *
619 * pcmcia_request_exclusive_irq() is a wrapper around request_irq which
620 * attempts first to request an exclusive IRQ. If it fails, it also accepts
621 * a shared IRQ, but prints out a warning. PCMCIA drivers should allow for
622 * IRQ sharing and either use request_irq directly (then they need to call
623 * free_irq themselves, too), or the pcmcia_request_irq() function.
624 */
625int __must_check
b19a7275
DB
626__pcmcia_request_exclusive_irq(struct pcmcia_device *p_dev,
627 irq_handler_t handler)
eb14120f
DB
628{
629 int ret;
1a8d4663 630
eb14120f
DB
631 if (!p_dev->irq)
632 return -EINVAL;
1a8d4663 633
eb14120f
DB
634 ret = request_irq(p_dev->irq, handler, 0, p_dev->devname, p_dev->priv);
635 if (ret) {
636 ret = pcmcia_request_irq(p_dev, handler);
637 dev_printk(KERN_WARNING, &p_dev->dev, "pcmcia: "
638 "request for exclusive IRQ could not be fulfilled.\n");
639 dev_printk(KERN_WARNING, &p_dev->dev, "pcmcia: the driver "
640 "needs updating to supported shared IRQ lines.\n");
641 }
642 if (ret)
643 dev_printk(KERN_INFO, &p_dev->dev, "request_irq() failed\n");
644 else
645 p_dev->_irq = 1;
1a8d4663 646
94a819f8 647 return ret;
eb14120f 648} /* pcmcia_request_exclusive_irq */
b19a7275 649EXPORT_SYMBOL(__pcmcia_request_exclusive_irq);
1a8d4663
DB
650
651
6f0f38c4
DB
652#ifdef CONFIG_PCMCIA_PROBE
653
654/* mask of IRQs already reserved by other cards, we should avoid using them */
655static u8 pcmcia_used_irq[NR_IRQS];
656
657static irqreturn_t test_action(int cpl, void *dev_id)
658{
659 return IRQ_NONE;
660}
661
662/**
663 * pcmcia_setup_isa_irq() - determine whether an ISA IRQ can be used
664 * @p_dev - the associated PCMCIA device
665 *
666 * locking note: must be called with ops_mutex locked.
667 */
668static int pcmcia_setup_isa_irq(struct pcmcia_device *p_dev, int type)
669{
670 struct pcmcia_socket *s = p_dev->socket;
671 unsigned int try, irq;
672 u32 mask = s->irq_mask;
673 int ret = -ENODEV;
674
675 for (try = 0; try < 64; try++) {
676 irq = try % 32;
677
678 /* marked as available by driver, not blocked by userspace? */
679 if (!((mask >> irq) & 1))
680 continue;
681
682 /* avoid an IRQ which is already used by another PCMCIA card */
683 if ((try < 32) && pcmcia_used_irq[irq])
684 continue;
685
686 /* register the correct driver, if possible, to check whether
687 * registering a dummy handle works, i.e. if the IRQ isn't
688 * marked as used by the kernel resource management core */
689 ret = request_irq(irq, test_action, type, p_dev->devname,
690 p_dev);
691 if (!ret) {
692 free_irq(irq, p_dev);
eb14120f 693 p_dev->irq = s->pcmcia_irq = irq;
6f0f38c4
DB
694 pcmcia_used_irq[irq]++;
695 break;
696 }
697 }
698
699 return ret;
700}
701
702void pcmcia_cleanup_irq(struct pcmcia_socket *s)
703{
6f840afb
DB
704 pcmcia_used_irq[s->pcmcia_irq]--;
705 s->pcmcia_irq = 0;
6f0f38c4
DB
706}
707
708#else /* CONFIG_PCMCIA_PROBE */
709
710static int pcmcia_setup_isa_irq(struct pcmcia_device *p_dev, int type)
711{
712 return -EINVAL;
713}
714
715void pcmcia_cleanup_irq(struct pcmcia_socket *s)
716{
6f840afb 717 s->pcmcia_irq = 0;
6f0f38c4
DB
718 return;
719}
720
721#endif /* CONFIG_PCMCIA_PROBE */
722
723
724/**
725 * pcmcia_setup_irq() - determine IRQ to be used for device
726 * @p_dev - the associated PCMCIA device
727 *
728 * locking note: must be called with ops_mutex locked.
729 */
730int pcmcia_setup_irq(struct pcmcia_device *p_dev)
731{
732 struct pcmcia_socket *s = p_dev->socket;
733
eb14120f 734 if (p_dev->irq)
6f0f38c4
DB
735 return 0;
736
737 /* already assigned? */
6f840afb 738 if (s->pcmcia_irq) {
eb14120f 739 p_dev->irq = s->pcmcia_irq;
6f0f38c4
DB
740 return 0;
741 }
742
743 /* prefer an exclusive ISA irq */
744 if (!pcmcia_setup_isa_irq(p_dev, 0))
745 return 0;
746
747 /* but accept a shared ISA irq */
748 if (!pcmcia_setup_isa_irq(p_dev, IRQF_SHARED))
749 return 0;
750
751 /* but use the PCI irq otherwise */
752 if (s->pci_irq) {
eb14120f 753 p_dev->irq = s->pcmcia_irq = s->pci_irq;
6f0f38c4
DB
754 return 0;
755 }
756
757 return -EINVAL;
758}
759
760
1a8d4663
DB
761/** pcmcia_request_window
762 *
763 * Request_window() establishes a mapping between card memory space
764 * and system memory space.
765 */
6838b03f 766int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_handle_t *wh)
1a8d4663 767{
6838b03f 768 struct pcmcia_socket *s = p_dev->socket;
82f88e36 769 pccard_mem_map *win;
1a8d4663
DB
770 u_long align;
771 int w;
772
6d9a299f
DB
773 if (!(s->state & SOCKET_PRESENT)) {
774 dev_dbg(&s->dev, "No card present\n");
3939c1ef 775 return -ENODEV;
6d9a299f 776 }
610e2374 777 if (req->Attributes & (WIN_PAGED | WIN_SHARED)) {
d50dbec3 778 dev_dbg(&s->dev, "bad attribute setting for iomem region\n");
610e2374
DB
779 return -EINVAL;
780 }
1a8d4663
DB
781
782 /* Window size defaults to smallest available */
783 if (req->Size == 0)
784 req->Size = s->map_size;
785 align = (((s->features & SS_CAP_MEM_ALIGN) ||
786 (req->Attributes & WIN_STRICT_ALIGN)) ?
787 req->Size : s->map_size);
69ba4433 788 if (req->Size & (s->map_size-1)) {
d50dbec3 789 dev_dbg(&s->dev, "invalid map size\n");
69ba4433
DB
790 return -EINVAL;
791 }
1a8d4663 792 if ((req->Base && (s->features & SS_CAP_STATIC_MAP)) ||
69ba4433 793 (req->Base & (align-1))) {
d50dbec3 794 dev_dbg(&s->dev, "invalid base address\n");
69ba4433
DB
795 return -EINVAL;
796 }
1a8d4663
DB
797 if (req->Base)
798 align = 0;
799
800 /* Allocate system memory window */
801 for (w = 0; w < MAX_WIN; w++)
9fea84f4
DB
802 if (!(s->state & SOCKET_WIN_REQ(w)))
803 break;
f958095e 804 if (w == MAX_WIN) {
d50dbec3 805 dev_dbg(&s->dev, "all windows are used already\n");
f958095e
DB
806 return -EINVAL;
807 }
1a8d4663 808
6b8e087b 809 mutex_lock(&s->ops_mutex);
1a8d4663 810 win = &s->win[w];
1a8d4663
DB
811
812 if (!(s->features & SS_CAP_STATIC_MAP)) {
82f88e36 813 win->res = pcmcia_find_mem_region(req->Base, req->Size, align,
1a8d4663 814 (req->Attributes & WIN_MAP_BELOW_1MB), s);
82f88e36 815 if (!win->res) {
d50dbec3 816 dev_dbg(&s->dev, "allocating mem region failed\n");
6b8e087b 817 mutex_unlock(&s->ops_mutex);
f958095e
DB
818 return -EINVAL;
819 }
1a8d4663 820 }
6838b03f 821 p_dev->_win |= CLIENT_WIN_REQ(w);
1a8d4663
DB
822
823 /* Configure the socket controller */
82f88e36
DB
824 win->map = w+1;
825 win->flags = 0;
826 win->speed = req->AccessSpeed;
1a8d4663 827 if (req->Attributes & WIN_MEMORY_TYPE)
82f88e36 828 win->flags |= MAP_ATTRIB;
1a8d4663 829 if (req->Attributes & WIN_ENABLE)
82f88e36 830 win->flags |= MAP_ACTIVE;
1a8d4663 831 if (req->Attributes & WIN_DATA_WIDTH_16)
82f88e36 832 win->flags |= MAP_16BIT;
1a8d4663 833 if (req->Attributes & WIN_USE_WAIT)
82f88e36
DB
834 win->flags |= MAP_USE_WAIT;
835 win->card_start = 0;
6b8e087b 836
82f88e36 837 if (s->ops->set_mem_map(s, win) != 0) {
d50dbec3 838 dev_dbg(&s->dev, "failed to set memory mapping\n");
6b8e087b 839 mutex_unlock(&s->ops_mutex);
926c5402
DB
840 return -EIO;
841 }
1a8d4663
DB
842 s->state |= SOCKET_WIN_REQ(w);
843
844 /* Return window handle */
9fea84f4 845 if (s->features & SS_CAP_STATIC_MAP)
82f88e36 846 req->Base = win->static_start;
9fea84f4 847 else
82f88e36 848 req->Base = win->res->start;
9fea84f4 849
6b8e087b 850 mutex_unlock(&s->ops_mutex);
0bdf9b3d 851 *wh = w + 1;
1a8d4663 852
4c89e88b 853 return 0;
1a8d4663
DB
854} /* pcmcia_request_window */
855EXPORT_SYMBOL(pcmcia_request_window);
5f2a71fc 856
9fea84f4
DB
857void pcmcia_disable_device(struct pcmcia_device *p_dev)
858{
5f2a71fc 859 pcmcia_release_configuration(p_dev);
fd238232 860 pcmcia_release_io(p_dev, &p_dev->io);
eb14120f
DB
861 if (p_dev->_irq)
862 free_irq(p_dev->irq, p_dev->priv);
c1ac0228 863 if (p_dev->win)
f5560da5 864 pcmcia_release_window(p_dev, p_dev->win);
5f2a71fc
DB
865}
866EXPORT_SYMBOL(pcmcia_disable_device);