aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pcmcia/pcmcia_resource.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-08-06 15:25:06 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-08-06 15:25:06 -0400
commit1685e633b396b0f3dabbc9fa5d65dfefe6435250 (patch)
treeee83e26e2468ca1518a1b065c690159e12c8def9 /drivers/pcmcia/pcmcia_resource.c
parent1cfd2bda8c486ae0e7a8005354758ebb68172bca (diff)
parent127c03cdbad9bd5af5d7f33bd31a1015a90cb77f (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/brodo/pcmcia-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/brodo/pcmcia-2.6: pcmcia: avoid buffer overflow in pcmcia_setup_isa_irq pcmcia: do not request windows if you don't need to pcmcia: insert PCMCIA device resources into resource tree pcmcia: export resource information to sysfs pcmcia: use struct resource for PCMCIA devices, part 2 pcmcia: remove memreq_t pcmcia: move local definitions out of include/pcmcia/cs.h pcmcia: do not use io_req_t when calling pcmcia_request_io() pcmcia: do not use io_req_t after call to pcmcia_request_io() pcmcia: use struct resource for PCMCIA devices pcmcia: clean up cs.h pcmcia: use pcmica_{read,write}_config_byte pcmcia: remove cs_types.h pcmcia: remove unused flag, simplify headers pcmcia: remove obsolete CS_EVENT_ definitions pcmcia: split up central event handler pcmcia: simplify event callback pcmcia: remove obsolete ioctl Conflicts in: - drivers/staging/comedi/drivers/* - drivers/staging/wlags49_h2/wl_cs.c due to dev_info_t and whitespace changes
Diffstat (limited to 'drivers/pcmcia/pcmcia_resource.c')
-rw-r--r--drivers/pcmcia/pcmcia_resource.c331
1 files changed, 183 insertions, 148 deletions
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
index a4cd9adfcbc0..54aa1c238cb3 100644
--- a/drivers/pcmcia/pcmcia_resource.c
+++ b/drivers/pcmcia/pcmcia_resource.c
@@ -25,7 +25,6 @@
25 25
26#include <asm/irq.h> 26#include <asm/irq.h>
27 27
28#include <pcmcia/cs_types.h>
29#include <pcmcia/ss.h> 28#include <pcmcia/ss.h>
30#include <pcmcia/cs.h> 29#include <pcmcia/cs.h>
31#include <pcmcia/cistpl.h> 30#include <pcmcia/cistpl.h>
@@ -57,77 +56,107 @@ struct resource *pcmcia_find_mem_region(u_long base, u_long num, u_long align,
57} 56}
58 57
59 58
59static void release_io_space(struct pcmcia_socket *s, struct resource *res)
60{
61 resource_size_t num = resource_size(res);
62 int i;
63
64 dev_dbg(&s->dev, "release_io_space for %pR\n", res);
65
66 for (i = 0; i < MAX_IO_WIN; i++) {
67 if (!s->io[i].res)
68 continue;
69 if ((s->io[i].res->start <= res->start) &&
70 (s->io[i].res->end >= res->end)) {
71 s->io[i].InUse -= num;
72 if (res->parent)
73 release_resource(res);
74 res->start = res->end = 0;
75 res->flags = IORESOURCE_IO;
76 /* Free the window if no one else is using it */
77 if (s->io[i].InUse == 0) {
78 release_resource(s->io[i].res);
79 kfree(s->io[i].res);
80 s->io[i].res = NULL;
81 }
82 }
83 }
84} /* release_io_space */
85
60/** alloc_io_space 86/** alloc_io_space
61 * 87 *
62 * Special stuff for managing IO windows, because they are scarce 88 * Special stuff for managing IO windows, because they are scarce
63 */ 89 */
64 90static int alloc_io_space(struct pcmcia_socket *s, struct resource *res,
65static int alloc_io_space(struct pcmcia_socket *s, u_int attr, 91 unsigned int lines)
66 unsigned int *base, unsigned int num, u_int lines)
67{ 92{
68 unsigned int align; 93 unsigned int align;
94 unsigned int base = res->start;
95 unsigned int num = res->end;
96 int ret;
69 97
70 align = (*base) ? (lines ? 1<<lines : 0) : 1; 98 res->flags |= IORESOURCE_IO;
99
100 dev_dbg(&s->dev, "alloc_io_space request for %pR, %d lines\n",
101 res, lines);
102
103 align = base ? (lines ? 1<<lines : 0) : 1;
71 if (align && (align < num)) { 104 if (align && (align < num)) {
72 if (*base) { 105 if (base) {
73 dev_dbg(&s->dev, "odd IO request: num %#x align %#x\n", 106 dev_dbg(&s->dev, "odd IO request\n");
74 num, align);
75 align = 0; 107 align = 0;
76 } else 108 } else
77 while (align && (align < num)) 109 while (align && (align < num))
78 align <<= 1; 110 align <<= 1;
79 } 111 }
80 if (*base & ~(align-1)) { 112 if (base & ~(align-1)) {
81 dev_dbg(&s->dev, "odd IO request: base %#x align %#x\n", 113 dev_dbg(&s->dev, "odd IO request\n");
82 *base, align);
83 align = 0; 114 align = 0;
84 } 115 }
85 116
86 return s->resource_ops->find_io(s, attr, base, num, align); 117 ret = s->resource_ops->find_io(s, res->flags, &base, num, align,
87} /* alloc_io_space */ 118 &res->parent);
88 119 if (ret) {
120 dev_dbg(&s->dev, "alloc_io_space request failed (%d)\n", ret);
121 return -EINVAL;
122 }
89 123
90static void release_io_space(struct pcmcia_socket *s, unsigned int base, 124 res->start = base;
91 unsigned int num) 125 res->end = res->start + num - 1;
92{
93 int i;
94 126
95 for (i = 0; i < MAX_IO_WIN; i++) { 127 if (res->parent) {
96 if (!s->io[i].res) 128 ret = request_resource(res->parent, res);
97 continue; 129 if (ret) {
98 if ((s->io[i].res->start <= base) && 130 dev_warn(&s->dev,
99 (s->io[i].res->end >= base+num-1)) { 131 "request_resource %pR failed: %d\n", res, ret);
100 s->io[i].InUse -= num; 132 res->parent = NULL;
101 /* Free the window if no one else is using it */ 133 release_io_space(s, res);
102 if (s->io[i].InUse == 0) {
103 release_resource(s->io[i].res);
104 kfree(s->io[i].res);
105 s->io[i].res = NULL;
106 }
107 } 134 }
108 } 135 }
109} /* release_io_space */ 136 dev_dbg(&s->dev, "alloc_io_space request result %d: %pR\n", ret, res);
137 return ret;
138} /* alloc_io_space */
110 139
111 140
112/** pccard_access_configuration_register 141/**
142 * pcmcia_access_config() - read or write card configuration registers
113 * 143 *
114 * Access_configuration_register() reads and writes configuration 144 * pcmcia_access_config() reads and writes configuration registers in
115 * registers in attribute memory. Memory window 0 is reserved for 145 * attribute memory. Memory window 0 is reserved for this and the tuple
116 * this and the tuple reading services. 146 * reading services. Drivers must use pcmcia_read_config_byte() or
147 * pcmcia_write_config_byte().
117 */ 148 */
118 149static int pcmcia_access_config(struct pcmcia_device *p_dev,
119int pcmcia_access_configuration_register(struct pcmcia_device *p_dev, 150 off_t where, u8 *val,
120 conf_reg_t *reg) 151 int (*accessf) (struct pcmcia_socket *s,
152 int attr, unsigned int addr,
153 unsigned int len, void *ptr))
121{ 154{
122 struct pcmcia_socket *s; 155 struct pcmcia_socket *s;
123 config_t *c; 156 config_t *c;
124 int addr; 157 int addr;
125 u_char val;
126 int ret = 0; 158 int ret = 0;
127 159
128 if (!p_dev || !p_dev->function_config)
129 return -EINVAL;
130
131 s = p_dev->socket; 160 s = p_dev->socket;
132 161
133 mutex_lock(&s->ops_mutex); 162 mutex_lock(&s->ops_mutex);
@@ -139,44 +168,57 @@ int pcmcia_access_configuration_register(struct pcmcia_device *p_dev,
139 return -EACCES; 168 return -EACCES;
140 } 169 }
141 170
142 addr = (c->ConfigBase + reg->Offset) >> 1; 171 addr = (c->ConfigBase + where) >> 1;
172
173 ret = accessf(s, 1, addr, 1, val);
143 174
144 switch (reg->Action) {
145 case CS_READ:
146 ret = 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:
154 dev_dbg(&s->dev, "Invalid conf register request\n");
155 ret = -EINVAL;
156 break;
157 }
158 mutex_unlock(&s->ops_mutex); 175 mutex_unlock(&s->ops_mutex);
176
159 return ret; 177 return ret;
160} /* pcmcia_access_configuration_register */ 178} /* pcmcia_access_config */
161EXPORT_SYMBOL(pcmcia_access_configuration_register); 179
180
181/**
182 * pcmcia_read_config_byte() - read a byte from a card configuration register
183 *
184 * pcmcia_read_config_byte() reads a byte from a configuration register in
185 * attribute memory.
186 */
187int pcmcia_read_config_byte(struct pcmcia_device *p_dev, off_t where, u8 *val)
188{
189 return pcmcia_access_config(p_dev, where, val, pcmcia_read_cis_mem);
190}
191EXPORT_SYMBOL(pcmcia_read_config_byte);
192
193
194/**
195 * pcmcia_write_config_byte() - write a byte to a card configuration register
196 *
197 * pcmcia_write_config_byte() writes a byte to a configuration register in
198 * attribute memory.
199 */
200int pcmcia_write_config_byte(struct pcmcia_device *p_dev, off_t where, u8 val)
201{
202 return pcmcia_access_config(p_dev, where, &val, pcmcia_write_cis_mem);
203}
204EXPORT_SYMBOL(pcmcia_write_config_byte);
162 205
163 206
164int pcmcia_map_mem_page(struct pcmcia_device *p_dev, window_handle_t wh, 207int pcmcia_map_mem_page(struct pcmcia_device *p_dev, window_handle_t wh,
165 memreq_t *req) 208 unsigned int offset)
166{ 209{
167 struct pcmcia_socket *s = p_dev->socket; 210 struct pcmcia_socket *s = p_dev->socket;
211 struct resource *res = wh;
212 unsigned int w;
168 int ret; 213 int ret;
169 214
170 wh--; 215 w = ((res->flags & IORESOURCE_BITS & WIN_FLAGS_REQ) >> 2) - 1;
171 if (wh >= MAX_WIN) 216 if (w >= MAX_WIN)
172 return -EINVAL; 217 return -EINVAL;
173 if (req->Page != 0) { 218
174 dev_dbg(&s->dev, "failure: requested page is zero\n");
175 return -EINVAL;
176 }
177 mutex_lock(&s->ops_mutex); 219 mutex_lock(&s->ops_mutex);
178 s->win[wh].card_start = req->CardOffset; 220 s->win[w].card_start = offset;
179 ret = s->ops->set_mem_map(s, &s->win[wh]); 221 ret = s->ops->set_mem_map(s, &s->win[w]);
180 if (ret) 222 if (ret)
181 dev_warn(&s->dev, "failed to set_mem_map\n"); 223 dev_warn(&s->dev, "failed to set_mem_map\n");
182 mutex_unlock(&s->ops_mutex); 224 mutex_unlock(&s->ops_mutex);
@@ -316,31 +358,25 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev)
316 * don't bother checking the port ranges against the current socket 358 * don't bother checking the port ranges against the current socket
317 * values. 359 * values.
318 */ 360 */
319static int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req) 361static int pcmcia_release_io(struct pcmcia_device *p_dev)
320{ 362{
321 struct pcmcia_socket *s = p_dev->socket; 363 struct pcmcia_socket *s = p_dev->socket;
322 int ret = -EINVAL; 364 int ret = -EINVAL;
323 config_t *c; 365 config_t *c;
324 366
325 mutex_lock(&s->ops_mutex); 367 mutex_lock(&s->ops_mutex);
326 c = p_dev->function_config;
327
328 if (!p_dev->_io) 368 if (!p_dev->_io)
329 goto out; 369 goto out;
330 370
331 p_dev->_io = 0; 371 c = p_dev->function_config;
332 372
333 if ((c->io.BasePort1 != req->BasePort1) || 373 release_io_space(s, &c->io[0]);
334 (c->io.NumPorts1 != req->NumPorts1) ||
335 (c->io.BasePort2 != req->BasePort2) ||
336 (c->io.NumPorts2 != req->NumPorts2))
337 goto out;
338 374
339 c->state &= ~CONFIG_IO_REQ; 375 if (c->io[1].end)
376 release_io_space(s, &c->io[1]);
340 377
341 release_io_space(s, req->BasePort1, req->NumPorts1); 378 p_dev->_io = 0;
342 if (req->NumPorts2) 379 c->state &= ~CONFIG_IO_REQ;
343 release_io_space(s, req->BasePort2, req->NumPorts2);
344 380
345out: 381out:
346 mutex_unlock(&s->ops_mutex); 382 mutex_unlock(&s->ops_mutex);
@@ -349,19 +385,22 @@ out:
349} /* pcmcia_release_io */ 385} /* pcmcia_release_io */
350 386
351 387
352int pcmcia_release_window(struct pcmcia_device *p_dev, window_handle_t wh) 388int pcmcia_release_window(struct pcmcia_device *p_dev, struct resource *res)
353{ 389{
354 struct pcmcia_socket *s = p_dev->socket; 390 struct pcmcia_socket *s = p_dev->socket;
355 pccard_mem_map *win; 391 pccard_mem_map *win;
392 unsigned int w;
393
394 dev_dbg(&p_dev->dev, "releasing window %pR\n", res);
356 395
357 wh--; 396 w = ((res->flags & IORESOURCE_BITS & WIN_FLAGS_REQ) >> 2) - 1;
358 if (wh >= MAX_WIN) 397 if (w >= MAX_WIN)
359 return -EINVAL; 398 return -EINVAL;
360 399
361 mutex_lock(&s->ops_mutex); 400 mutex_lock(&s->ops_mutex);
362 win = &s->win[wh]; 401 win = &s->win[w];
363 402
364 if (!(p_dev->_win & CLIENT_WIN_REQ(wh))) { 403 if (!(p_dev->_win & CLIENT_WIN_REQ(w))) {
365 dev_dbg(&s->dev, "not releasing unknown window\n"); 404 dev_dbg(&s->dev, "not releasing unknown window\n");
366 mutex_unlock(&s->ops_mutex); 405 mutex_unlock(&s->ops_mutex);
367 return -EINVAL; 406 return -EINVAL;
@@ -370,15 +409,16 @@ int pcmcia_release_window(struct pcmcia_device *p_dev, window_handle_t wh)
370 /* Shut down memory window */ 409 /* Shut down memory window */
371 win->flags &= ~MAP_ACTIVE; 410 win->flags &= ~MAP_ACTIVE;
372 s->ops->set_mem_map(s, win); 411 s->ops->set_mem_map(s, win);
373 s->state &= ~SOCKET_WIN_REQ(wh); 412 s->state &= ~SOCKET_WIN_REQ(w);
374 413
375 /* Release system memory */ 414 /* Release system memory */
376 if (win->res) { 415 if (win->res) {
416 release_resource(res);
377 release_resource(win->res); 417 release_resource(win->res);
378 kfree(win->res); 418 kfree(win->res);
379 win->res = NULL; 419 win->res = NULL;
380 } 420 }
381 p_dev->_win &= ~CLIENT_WIN_REQ(wh); 421 p_dev->_win &= ~CLIENT_WIN_REQ(w);
382 mutex_unlock(&s->ops_mutex); 422 mutex_unlock(&s->ops_mutex);
383 423
384 return 0; 424 return 0;
@@ -473,13 +513,13 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
473 pcmcia_write_cis_mem(s, 1, (base + CISREG_ESR)>>1, 1, &c->ExtStatus); 513 pcmcia_write_cis_mem(s, 1, (base + CISREG_ESR)>>1, 1, &c->ExtStatus);
474 } 514 }
475 if (req->Present & PRESENT_IOBASE_0) { 515 if (req->Present & PRESENT_IOBASE_0) {
476 u_char b = c->io.BasePort1 & 0xff; 516 u8 b = c->io[0].start & 0xff;
477 pcmcia_write_cis_mem(s, 1, (base + CISREG_IOBASE_0)>>1, 1, &b); 517 pcmcia_write_cis_mem(s, 1, (base + CISREG_IOBASE_0)>>1, 1, &b);
478 b = (c->io.BasePort1 >> 8) & 0xff; 518 b = (c->io[0].start >> 8) & 0xff;
479 pcmcia_write_cis_mem(s, 1, (base + CISREG_IOBASE_1)>>1, 1, &b); 519 pcmcia_write_cis_mem(s, 1, (base + CISREG_IOBASE_1)>>1, 1, &b);
480 } 520 }
481 if (req->Present & PRESENT_IOSIZE) { 521 if (req->Present & PRESENT_IOSIZE) {
482 u_char b = c->io.NumPorts1 + c->io.NumPorts2 - 1; 522 u8 b = resource_size(&c->io[0]) + resource_size(&c->io[1]) - 1;
483 pcmcia_write_cis_mem(s, 1, (base + CISREG_IOSIZE)>>1, 1, &b); 523 pcmcia_write_cis_mem(s, 1, (base + CISREG_IOSIZE)>>1, 1, &b);
484 } 524 }
485 525
@@ -513,28 +553,29 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
513EXPORT_SYMBOL(pcmcia_request_configuration); 553EXPORT_SYMBOL(pcmcia_request_configuration);
514 554
515 555
516/** pcmcia_request_io 556/**
557 * pcmcia_request_io() - attempt to reserve port ranges for PCMCIA devices
517 * 558 *
518 * Request_io() reserves ranges of port addresses for a socket. 559 * pcmcia_request_io() attepts to reserve the IO port ranges specified in
519 * I have not implemented range sharing or alias addressing. 560 * &struct pcmcia_device @p_dev->resource[0] and @p_dev->resource[1]. The
561 * "start" value is the requested start of the IO port resource; "end"
562 * reflects the number of ports requested. The number of IO lines requested
563 * is specified in &struct pcmcia_device @p_dev->io_lines.
520 */ 564 */
521int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req) 565int pcmcia_request_io(struct pcmcia_device *p_dev)
522{ 566{
523 struct pcmcia_socket *s = p_dev->socket; 567 struct pcmcia_socket *s = p_dev->socket;
524 config_t *c; 568 config_t *c = p_dev->function_config;
525 int ret = -EINVAL; 569 int ret = -EINVAL;
526 570
527 mutex_lock(&s->ops_mutex); 571 mutex_lock(&s->ops_mutex);
572 dev_dbg(&s->dev, "pcmcia_request_io: %pR , %pR", &c->io[0], &c->io[1]);
528 573
529 if (!(s->state & SOCKET_PRESENT)) { 574 if (!(s->state & SOCKET_PRESENT)) {
530 dev_dbg(&s->dev, "No card present\n"); 575 dev_dbg(&s->dev, "pcmcia_request_io: No card present\n");
531 goto out; 576 goto out;
532 } 577 }
533 578
534 if (!req)
535 goto out;
536
537 c = p_dev->function_config;
538 if (c->state & CONFIG_LOCKED) { 579 if (c->state & CONFIG_LOCKED) {
539 dev_dbg(&s->dev, "Configuration is locked\n"); 580 dev_dbg(&s->dev, "Configuration is locked\n");
540 goto out; 581 goto out;
@@ -543,40 +584,25 @@ int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req)
543 dev_dbg(&s->dev, "IO already configured\n"); 584 dev_dbg(&s->dev, "IO already configured\n");
544 goto out; 585 goto out;
545 } 586 }
546 if (req->Attributes1 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS)) {
547 dev_dbg(&s->dev, "bad attribute setting for IO region 1\n");
548 goto out;
549 }
550 if ((req->NumPorts2 > 0) &&
551 (req->Attributes2 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS))) {
552 dev_dbg(&s->dev, "bad attribute setting for IO region 2\n");
553 goto out;
554 }
555 587
556 dev_dbg(&s->dev, "trying to allocate resource 1\n"); 588 ret = alloc_io_space(s, &c->io[0], p_dev->io_lines);
557 ret = alloc_io_space(s, req->Attributes1, &req->BasePort1, 589 if (ret)
558 req->NumPorts1, req->IOAddrLines);
559 if (ret) {
560 dev_dbg(&s->dev, "allocation of resource 1 failed\n");
561 goto out; 590 goto out;
562 }
563 591
564 if (req->NumPorts2) { 592 if (c->io[1].end) {
565 dev_dbg(&s->dev, "trying to allocate resource 2\n"); 593 ret = alloc_io_space(s, &c->io[1], p_dev->io_lines);
566 ret = alloc_io_space(s, req->Attributes2, &req->BasePort2,
567 req->NumPorts2, req->IOAddrLines);
568 if (ret) { 594 if (ret) {
569 dev_dbg(&s->dev, "allocation of resource 2 failed\n"); 595 release_io_space(s, &c->io[0]);
570 release_io_space(s, req->BasePort1, req->NumPorts1);
571 goto out; 596 goto out;
572 } 597 }
573 } 598 } else
599 c->io[1].start = 0;
574 600
575 c->io = *req;
576 c->state |= CONFIG_IO_REQ; 601 c->state |= CONFIG_IO_REQ;
577 p_dev->_io = 1; 602 p_dev->_io = 1;
578 dev_dbg(&s->dev, "allocating resources succeeded: %d\n", ret);
579 603
604 dev_dbg(&s->dev, "pcmcia_request_io succeeded: %pR , %pR",
605 &c->io[0], &c->io[1]);
580out: 606out:
581 mutex_unlock(&s->ops_mutex); 607 mutex_unlock(&s->ops_mutex);
582 608
@@ -651,7 +677,7 @@ EXPORT_SYMBOL(__pcmcia_request_exclusive_irq);
651#ifdef CONFIG_PCMCIA_PROBE 677#ifdef CONFIG_PCMCIA_PROBE
652 678
653/* mask of IRQs already reserved by other cards, we should avoid using them */ 679/* mask of IRQs already reserved by other cards, we should avoid using them */
654static u8 pcmcia_used_irq[NR_IRQS]; 680static u8 pcmcia_used_irq[32];
655 681
656static irqreturn_t test_action(int cpl, void *dev_id) 682static irqreturn_t test_action(int cpl, void *dev_id)
657{ 683{
@@ -674,6 +700,9 @@ static int pcmcia_setup_isa_irq(struct pcmcia_device *p_dev, int type)
674 for (try = 0; try < 64; try++) { 700 for (try = 0; try < 64; try++) {
675 irq = try % 32; 701 irq = try % 32;
676 702
703 if (irq > NR_IRQS)
704 continue;
705
677 /* marked as available by driver, not blocked by userspace? */ 706 /* marked as available by driver, not blocked by userspace? */
678 if (!((mask >> irq) & 1)) 707 if (!((mask >> irq) & 1))
679 continue; 708 continue;
@@ -767,23 +796,18 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha
767 struct pcmcia_socket *s = p_dev->socket; 796 struct pcmcia_socket *s = p_dev->socket;
768 pccard_mem_map *win; 797 pccard_mem_map *win;
769 u_long align; 798 u_long align;
799 struct resource *res;
770 int w; 800 int w;
771 801
772 if (!(s->state & SOCKET_PRESENT)) { 802 if (!(s->state & SOCKET_PRESENT)) {
773 dev_dbg(&s->dev, "No card present\n"); 803 dev_dbg(&s->dev, "No card present\n");
774 return -ENODEV; 804 return -ENODEV;
775 } 805 }
776 if (req->Attributes & (WIN_PAGED | WIN_SHARED)) {
777 dev_dbg(&s->dev, "bad attribute setting for iomem region\n");
778 return -EINVAL;
779 }
780 806
781 /* Window size defaults to smallest available */ 807 /* Window size defaults to smallest available */
782 if (req->Size == 0) 808 if (req->Size == 0)
783 req->Size = s->map_size; 809 req->Size = s->map_size;
784 align = (((s->features & SS_CAP_MEM_ALIGN) || 810 align = (s->features & SS_CAP_MEM_ALIGN) ? req->Size : s->map_size;
785 (req->Attributes & WIN_STRICT_ALIGN)) ?
786 req->Size : s->map_size);
787 if (req->Size & (s->map_size-1)) { 811 if (req->Size & (s->map_size-1)) {
788 dev_dbg(&s->dev, "invalid map size\n"); 812 dev_dbg(&s->dev, "invalid map size\n");
789 return -EINVAL; 813 return -EINVAL;
@@ -797,20 +821,21 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha
797 align = 0; 821 align = 0;
798 822
799 /* Allocate system memory window */ 823 /* Allocate system memory window */
824 mutex_lock(&s->ops_mutex);
800 for (w = 0; w < MAX_WIN; w++) 825 for (w = 0; w < MAX_WIN; w++)
801 if (!(s->state & SOCKET_WIN_REQ(w))) 826 if (!(s->state & SOCKET_WIN_REQ(w)))
802 break; 827 break;
803 if (w == MAX_WIN) { 828 if (w == MAX_WIN) {
804 dev_dbg(&s->dev, "all windows are used already\n"); 829 dev_dbg(&s->dev, "all windows are used already\n");
830 mutex_unlock(&s->ops_mutex);
805 return -EINVAL; 831 return -EINVAL;
806 } 832 }
807 833
808 mutex_lock(&s->ops_mutex);
809 win = &s->win[w]; 834 win = &s->win[w];
810 835
811 if (!(s->features & SS_CAP_STATIC_MAP)) { 836 if (!(s->features & SS_CAP_STATIC_MAP)) {
812 win->res = pcmcia_find_mem_region(req->Base, req->Size, align, 837 win->res = pcmcia_find_mem_region(req->Base, req->Size, align,
813 (req->Attributes & WIN_MAP_BELOW_1MB), s); 838 0, s);
814 if (!win->res) { 839 if (!win->res) {
815 dev_dbg(&s->dev, "allocating mem region failed\n"); 840 dev_dbg(&s->dev, "allocating mem region failed\n");
816 mutex_unlock(&s->ops_mutex); 841 mutex_unlock(&s->ops_mutex);
@@ -821,16 +846,8 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha
821 846
822 /* Configure the socket controller */ 847 /* Configure the socket controller */
823 win->map = w+1; 848 win->map = w+1;
824 win->flags = 0; 849 win->flags = req->Attributes;
825 win->speed = req->AccessSpeed; 850 win->speed = req->AccessSpeed;
826 if (req->Attributes & WIN_MEMORY_TYPE)
827 win->flags |= MAP_ATTRIB;
828 if (req->Attributes & WIN_ENABLE)
829 win->flags |= MAP_ACTIVE;
830 if (req->Attributes & WIN_DATA_WIDTH_16)
831 win->flags |= MAP_16BIT;
832 if (req->Attributes & WIN_USE_WAIT)
833 win->flags |= MAP_USE_WAIT;
834 win->card_start = 0; 851 win->card_start = 0;
835 852
836 if (s->ops->set_mem_map(s, win) != 0) { 853 if (s->ops->set_mem_map(s, win) != 0) {
@@ -846,8 +863,21 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha
846 else 863 else
847 req->Base = win->res->start; 864 req->Base = win->res->start;
848 865
866 /* convert to new-style resources */
867 res = p_dev->resource[w + MAX_IO_WIN];
868 res->start = req->Base;
869 res->end = req->Base + req->Size - 1;
870 res->flags &= ~IORESOURCE_BITS;
871 res->flags |= (req->Attributes & WIN_FLAGS_MAP) | (win->map << 2);
872 res->flags |= IORESOURCE_MEM;
873 res->parent = win->res;
874 if (win->res)
875 request_resource(&iomem_resource, res);
876
877 dev_dbg(&s->dev, "request_window results in %pR\n", res);
878
849 mutex_unlock(&s->ops_mutex); 879 mutex_unlock(&s->ops_mutex);
850 *wh = w + 1; 880 *wh = res;
851 881
852 return 0; 882 return 0;
853} /* pcmcia_request_window */ 883} /* pcmcia_request_window */
@@ -855,13 +885,18 @@ EXPORT_SYMBOL(pcmcia_request_window);
855 885
856void pcmcia_disable_device(struct pcmcia_device *p_dev) 886void pcmcia_disable_device(struct pcmcia_device *p_dev)
857{ 887{
888 int i;
889 for (i = 0; i < MAX_WIN; i++) {
890 struct resource *res = p_dev->resource[MAX_IO_WIN + i];
891 if (res->flags & WIN_FLAGS_REQ)
892 pcmcia_release_window(p_dev, res);
893 }
894
858 pcmcia_release_configuration(p_dev); 895 pcmcia_release_configuration(p_dev);
859 pcmcia_release_io(p_dev, &p_dev->io); 896 pcmcia_release_io(p_dev);
860 if (p_dev->_irq) { 897 if (p_dev->_irq) {
861 free_irq(p_dev->irq, p_dev->priv); 898 free_irq(p_dev->irq, p_dev->priv);
862 p_dev->_irq = 0; 899 p_dev->_irq = 0;
863 } 900 }
864 if (p_dev->win)
865 pcmcia_release_window(p_dev, p_dev->win);
866} 901}
867EXPORT_SYMBOL(pcmcia_disable_device); 902EXPORT_SYMBOL(pcmcia_disable_device);