diff options
Diffstat (limited to 'drivers/pcmcia/pcmcia_resource.c')
-rw-r--r-- | drivers/pcmcia/pcmcia_resource.c | 482 |
1 files changed, 299 insertions, 183 deletions
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index d919e96c0afd..a8bf8c1b45ed 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
21 | #include <linux/pci.h> | 21 | #include <linux/pci.h> |
22 | #include <linux/device.h> | 22 | #include <linux/device.h> |
23 | #include <linux/netdevice.h> | ||
23 | 24 | ||
24 | #include <pcmcia/cs_types.h> | 25 | #include <pcmcia/cs_types.h> |
25 | #include <pcmcia/ss.h> | 26 | #include <pcmcia/ss.h> |
@@ -43,21 +44,6 @@ static u8 pcmcia_used_irq[NR_IRQS]; | |||
43 | #endif | 44 | #endif |
44 | 45 | ||
45 | 46 | ||
46 | #ifdef CONFIG_PCMCIA_DEBUG | ||
47 | extern int ds_pc_debug; | ||
48 | |||
49 | #define ds_dbg(skt, lvl, fmt, arg...) do { \ | ||
50 | if (ds_pc_debug >= lvl) \ | ||
51 | dev_printk(KERN_DEBUG, &skt->dev, \ | ||
52 | "pcmcia_resource: " fmt, \ | ||
53 | ## arg); \ | ||
54 | } while (0) | ||
55 | #else | ||
56 | #define ds_dbg(skt, lvl, fmt, arg...) do { } while (0) | ||
57 | #endif | ||
58 | |||
59 | |||
60 | |||
61 | /** alloc_io_space | 47 | /** alloc_io_space |
62 | * | 48 | * |
63 | * Special stuff for managing IO windows, because they are scarce | 49 | * Special stuff for managing IO windows, because they are scarce |
@@ -72,14 +58,14 @@ static int alloc_io_space(struct pcmcia_socket *s, u_int attr, | |||
72 | align = (*base) ? (lines ? 1<<lines : 0) : 1; | 58 | align = (*base) ? (lines ? 1<<lines : 0) : 1; |
73 | if (align && (align < num)) { | 59 | if (align && (align < num)) { |
74 | if (*base) { | 60 | if (*base) { |
75 | ds_dbg(s, 0, "odd IO request: num %#x align %#x\n", | 61 | dev_dbg(&s->dev, "odd IO request: num %#x align %#x\n", |
76 | num, align); | 62 | num, align); |
77 | align = 0; | 63 | align = 0; |
78 | } else | 64 | } else |
79 | while (align && (align < num)) align <<= 1; | 65 | while (align && (align < num)) align <<= 1; |
80 | } | 66 | } |
81 | if (*base & ~(align-1)) { | 67 | if (*base & ~(align-1)) { |
82 | ds_dbg(s, 0, "odd IO request: base %#x align %#x\n", | 68 | dev_dbg(&s->dev, "odd IO request: base %#x align %#x\n", |
83 | *base, align); | 69 | *base, align); |
84 | align = 0; | 70 | align = 0; |
85 | } | 71 | } |
@@ -173,8 +159,10 @@ int pcmcia_access_configuration_register(struct pcmcia_device *p_dev, | |||
173 | s = p_dev->socket; | 159 | s = p_dev->socket; |
174 | c = p_dev->function_config; | 160 | c = p_dev->function_config; |
175 | 161 | ||
176 | if (!(c->state & CONFIG_LOCKED)) | 162 | if (!(c->state & CONFIG_LOCKED)) { |
163 | dev_dbg(&s->dev, "Configuration isnt't locked\n"); | ||
177 | return -EACCES; | 164 | return -EACCES; |
165 | } | ||
178 | 166 | ||
179 | addr = (c->ConfigBase + reg->Offset) >> 1; | 167 | addr = (c->ConfigBase + reg->Offset) >> 1; |
180 | 168 | ||
@@ -188,6 +176,7 @@ int pcmcia_access_configuration_register(struct pcmcia_device *p_dev, | |||
188 | pcmcia_write_cis_mem(s, 1, addr, 1, &val); | 176 | pcmcia_write_cis_mem(s, 1, addr, 1, &val); |
189 | break; | 177 | break; |
190 | default: | 178 | default: |
179 | dev_dbg(&s->dev, "Invalid conf register request\n"); | ||
191 | return -EINVAL; | 180 | return -EINVAL; |
192 | break; | 181 | break; |
193 | } | 182 | } |
@@ -196,68 +185,21 @@ int pcmcia_access_configuration_register(struct pcmcia_device *p_dev, | |||
196 | EXPORT_SYMBOL(pcmcia_access_configuration_register); | 185 | EXPORT_SYMBOL(pcmcia_access_configuration_register); |
197 | 186 | ||
198 | 187 | ||
199 | /** pcmcia_get_window | 188 | int pcmcia_map_mem_page(struct pcmcia_device *p_dev, window_handle_t wh, |
200 | */ | 189 | memreq_t *req) |
201 | int pcmcia_get_window(struct pcmcia_socket *s, window_handle_t *handle, | ||
202 | int idx, win_req_t *req) | ||
203 | { | ||
204 | window_t *win; | ||
205 | int w; | ||
206 | |||
207 | if (!s || !(s->state & SOCKET_PRESENT)) | ||
208 | return -ENODEV; | ||
209 | for (w = idx; w < MAX_WIN; w++) | ||
210 | if (s->state & SOCKET_WIN_REQ(w)) | ||
211 | break; | ||
212 | if (w == MAX_WIN) | ||
213 | return -EINVAL; | ||
214 | win = &s->win[w]; | ||
215 | req->Base = win->ctl.res->start; | ||
216 | req->Size = win->ctl.res->end - win->ctl.res->start + 1; | ||
217 | req->AccessSpeed = win->ctl.speed; | ||
218 | req->Attributes = 0; | ||
219 | if (win->ctl.flags & MAP_ATTRIB) | ||
220 | req->Attributes |= WIN_MEMORY_TYPE_AM; | ||
221 | if (win->ctl.flags & MAP_ACTIVE) | ||
222 | req->Attributes |= WIN_ENABLE; | ||
223 | if (win->ctl.flags & MAP_16BIT) | ||
224 | req->Attributes |= WIN_DATA_WIDTH_16; | ||
225 | if (win->ctl.flags & MAP_USE_WAIT) | ||
226 | req->Attributes |= WIN_USE_WAIT; | ||
227 | *handle = win; | ||
228 | return 0; | ||
229 | } /* pcmcia_get_window */ | ||
230 | EXPORT_SYMBOL(pcmcia_get_window); | ||
231 | |||
232 | |||
233 | /** pcmcia_get_mem_page | ||
234 | * | ||
235 | * Change the card address of an already open memory window. | ||
236 | */ | ||
237 | int pcmcia_get_mem_page(window_handle_t win, memreq_t *req) | ||
238 | { | 190 | { |
239 | if ((win == NULL) || (win->magic != WINDOW_MAGIC)) | 191 | struct pcmcia_socket *s = p_dev->socket; |
240 | return -EINVAL; | ||
241 | req->Page = 0; | ||
242 | req->CardOffset = win->ctl.card_start; | ||
243 | return 0; | ||
244 | } /* pcmcia_get_mem_page */ | ||
245 | EXPORT_SYMBOL(pcmcia_get_mem_page); | ||
246 | |||
247 | 192 | ||
248 | int pcmcia_map_mem_page(window_handle_t win, memreq_t *req) | 193 | wh--; |
249 | { | 194 | if (wh >= MAX_WIN) |
250 | struct pcmcia_socket *s; | ||
251 | if ((win == NULL) || (win->magic != WINDOW_MAGIC)) | ||
252 | return -EINVAL; | 195 | return -EINVAL; |
253 | s = win->sock; | ||
254 | if (req->Page != 0) { | 196 | if (req->Page != 0) { |
255 | ds_dbg(s, 0, "failure: requested page is zero\n"); | 197 | dev_dbg(&s->dev, "failure: requested page is zero\n"); |
256 | return -EINVAL; | 198 | return -EINVAL; |
257 | } | 199 | } |
258 | win->ctl.card_start = req->CardOffset; | 200 | s->win[wh].card_start = req->CardOffset; |
259 | if (s->ops->set_mem_map(s, &win->ctl) != 0) { | 201 | if (s->ops->set_mem_map(s, &s->win[wh]) != 0) { |
260 | ds_dbg(s, 0, "failed to set_mem_map\n"); | 202 | dev_dbg(&s->dev, "failed to set_mem_map\n"); |
261 | return -EIO; | 203 | return -EIO; |
262 | } | 204 | } |
263 | return 0; | 205 | return 0; |
@@ -278,10 +220,14 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, | |||
278 | s = p_dev->socket; | 220 | s = p_dev->socket; |
279 | c = p_dev->function_config; | 221 | c = p_dev->function_config; |
280 | 222 | ||
281 | if (!(s->state & SOCKET_PRESENT)) | 223 | if (!(s->state & SOCKET_PRESENT)) { |
224 | dev_dbg(&s->dev, "No card present\n"); | ||
282 | return -ENODEV; | 225 | return -ENODEV; |
283 | if (!(c->state & CONFIG_LOCKED)) | 226 | } |
227 | if (!(c->state & CONFIG_LOCKED)) { | ||
228 | dev_dbg(&s->dev, "Configuration isnt't locked\n"); | ||
284 | return -EACCES; | 229 | return -EACCES; |
230 | } | ||
285 | 231 | ||
286 | if (mod->Attributes & CONF_IRQ_CHANGE_VALID) { | 232 | if (mod->Attributes & CONF_IRQ_CHANGE_VALID) { |
287 | if (mod->Attributes & CONF_ENABLE_IRQ) { | 233 | if (mod->Attributes & CONF_ENABLE_IRQ) { |
@@ -295,7 +241,7 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, | |||
295 | } | 241 | } |
296 | 242 | ||
297 | if (mod->Attributes & CONF_VCC_CHANGE_VALID) { | 243 | if (mod->Attributes & CONF_VCC_CHANGE_VALID) { |
298 | ds_dbg(s, 0, "changing Vcc is not allowed at this time\n"); | 244 | dev_dbg(&s->dev, "changing Vcc is not allowed at this time\n"); |
299 | return -EINVAL; | 245 | return -EINVAL; |
300 | } | 246 | } |
301 | 247 | ||
@@ -303,7 +249,7 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, | |||
303 | if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) && | 249 | if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) && |
304 | (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { | 250 | (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { |
305 | if (mod->Vpp1 != mod->Vpp2) { | 251 | if (mod->Vpp1 != mod->Vpp2) { |
306 | ds_dbg(s, 0, "Vpp1 and Vpp2 must be the same\n"); | 252 | dev_dbg(&s->dev, "Vpp1 and Vpp2 must be the same\n"); |
307 | return -EINVAL; | 253 | return -EINVAL; |
308 | } | 254 | } |
309 | s->socket.Vpp = mod->Vpp1; | 255 | s->socket.Vpp = mod->Vpp1; |
@@ -314,7 +260,7 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, | |||
314 | } | 260 | } |
315 | } else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) || | 261 | } else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) || |
316 | (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { | 262 | (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { |
317 | ds_dbg(s, 0, "changing Vcc is not allowed at this time\n"); | 263 | dev_dbg(&s->dev, "changing Vcc is not allowed at this time\n"); |
318 | return -EINVAL; | 264 | return -EINVAL; |
319 | } | 265 | } |
320 | 266 | ||
@@ -425,11 +371,11 @@ static int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req) | |||
425 | if (c->state & CONFIG_LOCKED) | 371 | if (c->state & CONFIG_LOCKED) |
426 | return -EACCES; | 372 | return -EACCES; |
427 | if (c->irq.Attributes != req->Attributes) { | 373 | if (c->irq.Attributes != req->Attributes) { |
428 | ds_dbg(s, 0, "IRQ attributes must match assigned ones\n"); | 374 | dev_dbg(&s->dev, "IRQ attributes must match assigned ones\n"); |
429 | return -EINVAL; | 375 | return -EINVAL; |
430 | } | 376 | } |
431 | if (s->irq.AssignedIRQ != req->AssignedIRQ) { | 377 | if (s->irq.AssignedIRQ != req->AssignedIRQ) { |
432 | ds_dbg(s, 0, "IRQ must match assigned one\n"); | 378 | dev_dbg(&s->dev, "IRQ must match assigned one\n"); |
433 | return -EINVAL; | 379 | return -EINVAL; |
434 | } | 380 | } |
435 | if (--s->irq.Config == 0) { | 381 | if (--s->irq.Config == 0) { |
@@ -437,8 +383,8 @@ static int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req) | |||
437 | s->irq.AssignedIRQ = 0; | 383 | s->irq.AssignedIRQ = 0; |
438 | } | 384 | } |
439 | 385 | ||
440 | if (req->Attributes & IRQ_HANDLE_PRESENT) { | 386 | if (req->Handler) { |
441 | free_irq(req->AssignedIRQ, req->Instance); | 387 | free_irq(req->AssignedIRQ, p_dev->priv); |
442 | } | 388 | } |
443 | 389 | ||
444 | #ifdef CONFIG_PCMCIA_PROBE | 390 | #ifdef CONFIG_PCMCIA_PROBE |
@@ -449,30 +395,34 @@ static int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req) | |||
449 | } /* pcmcia_release_irq */ | 395 | } /* pcmcia_release_irq */ |
450 | 396 | ||
451 | 397 | ||
452 | int pcmcia_release_window(window_handle_t win) | 398 | int pcmcia_release_window(struct pcmcia_device *p_dev, window_handle_t wh) |
453 | { | 399 | { |
454 | struct pcmcia_socket *s; | 400 | struct pcmcia_socket *s = p_dev->socket; |
401 | pccard_mem_map *win; | ||
455 | 402 | ||
456 | if ((win == NULL) || (win->magic != WINDOW_MAGIC)) | 403 | wh--; |
404 | if (wh >= MAX_WIN) | ||
457 | return -EINVAL; | 405 | return -EINVAL; |
458 | s = win->sock; | 406 | |
459 | if (!(win->handle->_win & CLIENT_WIN_REQ(win->index))) | 407 | win = &s->win[wh]; |
408 | |||
409 | if (!(p_dev->_win & CLIENT_WIN_REQ(wh))) { | ||
410 | dev_dbg(&s->dev, "not releasing unknown window\n"); | ||
460 | return -EINVAL; | 411 | return -EINVAL; |
412 | } | ||
461 | 413 | ||
462 | /* Shut down memory window */ | 414 | /* Shut down memory window */ |
463 | win->ctl.flags &= ~MAP_ACTIVE; | 415 | win->flags &= ~MAP_ACTIVE; |
464 | s->ops->set_mem_map(s, &win->ctl); | 416 | s->ops->set_mem_map(s, win); |
465 | s->state &= ~SOCKET_WIN_REQ(win->index); | 417 | s->state &= ~SOCKET_WIN_REQ(wh); |
466 | 418 | ||
467 | /* Release system memory */ | 419 | /* Release system memory */ |
468 | if (win->ctl.res) { | 420 | if (win->res) { |
469 | release_resource(win->ctl.res); | 421 | release_resource(win->res); |
470 | kfree(win->ctl.res); | 422 | kfree(win->res); |
471 | win->ctl.res = NULL; | 423 | win->res = NULL; |
472 | } | 424 | } |
473 | win->handle->_win &= ~CLIENT_WIN_REQ(win->index); | 425 | p_dev->_win &= ~CLIENT_WIN_REQ(wh); |
474 | |||
475 | win->magic = 0; | ||
476 | 426 | ||
477 | return 0; | 427 | return 0; |
478 | } /* pcmcia_release_window */ | 428 | } /* pcmcia_release_window */ |
@@ -492,12 +442,14 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, | |||
492 | return -ENODEV; | 442 | return -ENODEV; |
493 | 443 | ||
494 | if (req->IntType & INT_CARDBUS) { | 444 | if (req->IntType & INT_CARDBUS) { |
495 | ds_dbg(p_dev->socket, 0, "IntType may not be INT_CARDBUS\n"); | 445 | dev_dbg(&s->dev, "IntType may not be INT_CARDBUS\n"); |
496 | return -EINVAL; | 446 | return -EINVAL; |
497 | } | 447 | } |
498 | c = p_dev->function_config; | 448 | c = p_dev->function_config; |
499 | if (c->state & CONFIG_LOCKED) | 449 | if (c->state & CONFIG_LOCKED) { |
450 | dev_dbg(&s->dev, "Configuration is locked\n"); | ||
500 | return -EACCES; | 451 | return -EACCES; |
452 | } | ||
501 | 453 | ||
502 | /* Do power control. We don't allow changes in Vcc. */ | 454 | /* Do power control. We don't allow changes in Vcc. */ |
503 | s->socket.Vpp = req->Vpp; | 455 | s->socket.Vpp = req->Vpp; |
@@ -609,40 +561,44 @@ int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req) | |||
609 | struct pcmcia_socket *s = p_dev->socket; | 561 | struct pcmcia_socket *s = p_dev->socket; |
610 | config_t *c; | 562 | config_t *c; |
611 | 563 | ||
612 | if (!(s->state & SOCKET_PRESENT)) | 564 | if (!(s->state & SOCKET_PRESENT)) { |
565 | dev_dbg(&s->dev, "No card present\n"); | ||
613 | return -ENODEV; | 566 | return -ENODEV; |
567 | } | ||
614 | 568 | ||
615 | if (!req) | 569 | if (!req) |
616 | return -EINVAL; | 570 | return -EINVAL; |
617 | c = p_dev->function_config; | 571 | c = p_dev->function_config; |
618 | if (c->state & CONFIG_LOCKED) | 572 | if (c->state & CONFIG_LOCKED) { |
573 | dev_dbg(&s->dev, "Configuration is locked\n"); | ||
619 | return -EACCES; | 574 | return -EACCES; |
575 | } | ||
620 | if (c->state & CONFIG_IO_REQ) { | 576 | if (c->state & CONFIG_IO_REQ) { |
621 | ds_dbg(s, 0, "IO already configured\n"); | 577 | dev_dbg(&s->dev, "IO already configured\n"); |
622 | return -EBUSY; | 578 | return -EBUSY; |
623 | } | 579 | } |
624 | if (req->Attributes1 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS)) { | 580 | if (req->Attributes1 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS)) { |
625 | ds_dbg(s, 0, "bad attribute setting for IO region 1\n"); | 581 | dev_dbg(&s->dev, "bad attribute setting for IO region 1\n"); |
626 | return -EINVAL; | 582 | return -EINVAL; |
627 | } | 583 | } |
628 | if ((req->NumPorts2 > 0) && | 584 | if ((req->NumPorts2 > 0) && |
629 | (req->Attributes2 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS))) { | 585 | (req->Attributes2 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS))) { |
630 | ds_dbg(s, 0, "bad attribute setting for IO region 2\n"); | 586 | dev_dbg(&s->dev, "bad attribute setting for IO region 2\n"); |
631 | return -EINVAL; | 587 | return -EINVAL; |
632 | } | 588 | } |
633 | 589 | ||
634 | ds_dbg(s, 1, "trying to allocate resource 1\n"); | 590 | dev_dbg(&s->dev, "trying to allocate resource 1\n"); |
635 | if (alloc_io_space(s, req->Attributes1, &req->BasePort1, | 591 | if (alloc_io_space(s, req->Attributes1, &req->BasePort1, |
636 | req->NumPorts1, req->IOAddrLines)) { | 592 | req->NumPorts1, req->IOAddrLines)) { |
637 | ds_dbg(s, 0, "allocation of resource 1 failed\n"); | 593 | dev_dbg(&s->dev, "allocation of resource 1 failed\n"); |
638 | return -EBUSY; | 594 | return -EBUSY; |
639 | } | 595 | } |
640 | 596 | ||
641 | if (req->NumPorts2) { | 597 | if (req->NumPorts2) { |
642 | ds_dbg(s, 1, "trying to allocate resource 2\n"); | 598 | dev_dbg(&s->dev, "trying to allocate resource 2\n"); |
643 | if (alloc_io_space(s, req->Attributes2, &req->BasePort2, | 599 | if (alloc_io_space(s, req->Attributes2, &req->BasePort2, |
644 | req->NumPorts2, req->IOAddrLines)) { | 600 | req->NumPorts2, req->IOAddrLines)) { |
645 | ds_dbg(s, 0, "allocation of resource 2 failed\n"); | 601 | dev_dbg(&s->dev, "allocation of resource 2 failed\n"); |
646 | release_io_space(s, req->BasePort1, req->NumPorts1); | 602 | release_io_space(s, req->BasePort1, req->NumPorts1); |
647 | return -EBUSY; | 603 | return -EBUSY; |
648 | } | 604 | } |
@@ -680,13 +636,17 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) | |||
680 | int ret = -EINVAL, irq = 0; | 636 | int ret = -EINVAL, irq = 0; |
681 | int type; | 637 | int type; |
682 | 638 | ||
683 | if (!(s->state & SOCKET_PRESENT)) | 639 | if (!(s->state & SOCKET_PRESENT)) { |
640 | dev_dbg(&s->dev, "No card present\n"); | ||
684 | return -ENODEV; | 641 | return -ENODEV; |
642 | } | ||
685 | c = p_dev->function_config; | 643 | c = p_dev->function_config; |
686 | if (c->state & CONFIG_LOCKED) | 644 | if (c->state & CONFIG_LOCKED) { |
645 | dev_dbg(&s->dev, "Configuration is locked\n"); | ||
687 | return -EACCES; | 646 | return -EACCES; |
647 | } | ||
688 | if (c->state & CONFIG_IRQ_REQ) { | 648 | if (c->state & CONFIG_IRQ_REQ) { |
689 | ds_dbg(s, 0, "IRQ already configured\n"); | 649 | dev_dbg(&s->dev, "IRQ already configured\n"); |
690 | return -EBUSY; | 650 | return -EBUSY; |
691 | } | 651 | } |
692 | 652 | ||
@@ -704,7 +664,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) | |||
704 | /* if the underlying IRQ infrastructure allows for it, only allocate | 664 | /* if the underlying IRQ infrastructure allows for it, only allocate |
705 | * the IRQ, but do not enable it | 665 | * the IRQ, but do not enable it |
706 | */ | 666 | */ |
707 | if (!(req->Attributes & IRQ_HANDLE_PRESENT)) | 667 | if (!(req->Handler)) |
708 | type |= IRQ_NOAUTOEN; | 668 | type |= IRQ_NOAUTOEN; |
709 | #endif /* IRQ_NOAUTOEN */ | 669 | #endif /* IRQ_NOAUTOEN */ |
710 | 670 | ||
@@ -714,7 +674,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) | |||
714 | } else { | 674 | } else { |
715 | int try; | 675 | int try; |
716 | u32 mask = s->irq_mask; | 676 | u32 mask = s->irq_mask; |
717 | void *data = &p_dev->dev.driver; /* something unique to this device */ | 677 | void *data = p_dev; /* something unique to this device */ |
718 | 678 | ||
719 | for (try = 0; try < 64; try++) { | 679 | for (try = 0; try < 64; try++) { |
720 | irq = try % 32; | 680 | irq = try % 32; |
@@ -731,12 +691,12 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) | |||
731 | * registering a dummy handle works, i.e. if the IRQ isn't | 691 | * registering a dummy handle works, i.e. if the IRQ isn't |
732 | * marked as used by the kernel resource management core */ | 692 | * marked as used by the kernel resource management core */ |
733 | ret = request_irq(irq, | 693 | ret = request_irq(irq, |
734 | (req->Attributes & IRQ_HANDLE_PRESENT) ? req->Handler : test_action, | 694 | (req->Handler) ? req->Handler : test_action, |
735 | type, | 695 | type, |
736 | p_dev->devname, | 696 | p_dev->devname, |
737 | (req->Attributes & IRQ_HANDLE_PRESENT) ? req->Instance : data); | 697 | (req->Handler) ? p_dev->priv : data); |
738 | if (!ret) { | 698 | if (!ret) { |
739 | if (!(req->Attributes & IRQ_HANDLE_PRESENT)) | 699 | if (!req->Handler) |
740 | free_irq(irq, data); | 700 | free_irq(irq, data); |
741 | break; | 701 | break; |
742 | } | 702 | } |
@@ -745,17 +705,22 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) | |||
745 | #endif | 705 | #endif |
746 | /* only assign PCI irq if no IRQ already assigned */ | 706 | /* only assign PCI irq if no IRQ already assigned */ |
747 | if (ret && !s->irq.AssignedIRQ) { | 707 | if (ret && !s->irq.AssignedIRQ) { |
748 | if (!s->pci_irq) | 708 | if (!s->pci_irq) { |
709 | dev_printk(KERN_INFO, &s->dev, "no IRQ found\n"); | ||
749 | return ret; | 710 | return ret; |
711 | } | ||
750 | type = IRQF_SHARED; | 712 | type = IRQF_SHARED; |
751 | irq = s->pci_irq; | 713 | irq = s->pci_irq; |
752 | } | 714 | } |
753 | 715 | ||
754 | if (ret && (req->Attributes & IRQ_HANDLE_PRESENT)) { | 716 | if (ret && req->Handler) { |
755 | ret = request_irq(irq, req->Handler, type, | 717 | ret = request_irq(irq, req->Handler, type, |
756 | p_dev->devname, req->Instance); | 718 | p_dev->devname, p_dev->priv); |
757 | if (ret) | 719 | if (ret) { |
720 | dev_printk(KERN_INFO, &s->dev, | ||
721 | "request_irq() failed\n"); | ||
758 | return ret; | 722 | return ret; |
723 | } | ||
759 | } | 724 | } |
760 | 725 | ||
761 | /* Make sure the fact the request type was overridden is passed back */ | 726 | /* Make sure the fact the request type was overridden is passed back */ |
@@ -787,17 +752,19 @@ EXPORT_SYMBOL(pcmcia_request_irq); | |||
787 | * Request_window() establishes a mapping between card memory space | 752 | * Request_window() establishes a mapping between card memory space |
788 | * and system memory space. | 753 | * and system memory space. |
789 | */ | 754 | */ |
790 | int pcmcia_request_window(struct pcmcia_device **p_dev, win_req_t *req, window_handle_t *wh) | 755 | int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_handle_t *wh) |
791 | { | 756 | { |
792 | struct pcmcia_socket *s = (*p_dev)->socket; | 757 | struct pcmcia_socket *s = p_dev->socket; |
793 | window_t *win; | 758 | pccard_mem_map *win; |
794 | u_long align; | 759 | u_long align; |
795 | int w; | 760 | int w; |
796 | 761 | ||
797 | if (!(s->state & SOCKET_PRESENT)) | 762 | if (!(s->state & SOCKET_PRESENT)) { |
763 | dev_dbg(&s->dev, "No card present\n"); | ||
798 | return -ENODEV; | 764 | return -ENODEV; |
765 | } | ||
799 | if (req->Attributes & (WIN_PAGED | WIN_SHARED)) { | 766 | if (req->Attributes & (WIN_PAGED | WIN_SHARED)) { |
800 | ds_dbg(s, 0, "bad attribute setting for iomem region\n"); | 767 | dev_dbg(&s->dev, "bad attribute setting for iomem region\n"); |
801 | return -EINVAL; | 768 | return -EINVAL; |
802 | } | 769 | } |
803 | 770 | ||
@@ -808,12 +775,12 @@ int pcmcia_request_window(struct pcmcia_device **p_dev, win_req_t *req, window_h | |||
808 | (req->Attributes & WIN_STRICT_ALIGN)) ? | 775 | (req->Attributes & WIN_STRICT_ALIGN)) ? |
809 | req->Size : s->map_size); | 776 | req->Size : s->map_size); |
810 | if (req->Size & (s->map_size-1)) { | 777 | if (req->Size & (s->map_size-1)) { |
811 | ds_dbg(s, 0, "invalid map size\n"); | 778 | dev_dbg(&s->dev, "invalid map size\n"); |
812 | return -EINVAL; | 779 | return -EINVAL; |
813 | } | 780 | } |
814 | if ((req->Base && (s->features & SS_CAP_STATIC_MAP)) || | 781 | if ((req->Base && (s->features & SS_CAP_STATIC_MAP)) || |
815 | (req->Base & (align-1))) { | 782 | (req->Base & (align-1))) { |
816 | ds_dbg(s, 0, "invalid base address\n"); | 783 | dev_dbg(&s->dev, "invalid base address\n"); |
817 | return -EINVAL; | 784 | return -EINVAL; |
818 | } | 785 | } |
819 | if (req->Base) | 786 | if (req->Base) |
@@ -823,52 +790,48 @@ int pcmcia_request_window(struct pcmcia_device **p_dev, win_req_t *req, window_h | |||
823 | for (w = 0; w < MAX_WIN; w++) | 790 | for (w = 0; w < MAX_WIN; w++) |
824 | if (!(s->state & SOCKET_WIN_REQ(w))) break; | 791 | if (!(s->state & SOCKET_WIN_REQ(w))) break; |
825 | if (w == MAX_WIN) { | 792 | if (w == MAX_WIN) { |
826 | ds_dbg(s, 0, "all windows are used already\n"); | 793 | dev_dbg(&s->dev, "all windows are used already\n"); |
827 | return -EINVAL; | 794 | return -EINVAL; |
828 | } | 795 | } |
829 | 796 | ||
830 | win = &s->win[w]; | 797 | win = &s->win[w]; |
831 | win->magic = WINDOW_MAGIC; | ||
832 | win->index = w; | ||
833 | win->handle = *p_dev; | ||
834 | win->sock = s; | ||
835 | 798 | ||
836 | if (!(s->features & SS_CAP_STATIC_MAP)) { | 799 | if (!(s->features & SS_CAP_STATIC_MAP)) { |
837 | win->ctl.res = pcmcia_find_mem_region(req->Base, req->Size, align, | 800 | win->res = pcmcia_find_mem_region(req->Base, req->Size, align, |
838 | (req->Attributes & WIN_MAP_BELOW_1MB), s); | 801 | (req->Attributes & WIN_MAP_BELOW_1MB), s); |
839 | if (!win->ctl.res) { | 802 | if (!win->res) { |
840 | ds_dbg(s, 0, "allocating mem region failed\n"); | 803 | dev_dbg(&s->dev, "allocating mem region failed\n"); |
841 | return -EINVAL; | 804 | return -EINVAL; |
842 | } | 805 | } |
843 | } | 806 | } |
844 | (*p_dev)->_win |= CLIENT_WIN_REQ(w); | 807 | p_dev->_win |= CLIENT_WIN_REQ(w); |
845 | 808 | ||
846 | /* Configure the socket controller */ | 809 | /* Configure the socket controller */ |
847 | win->ctl.map = w+1; | 810 | win->map = w+1; |
848 | win->ctl.flags = 0; | 811 | win->flags = 0; |
849 | win->ctl.speed = req->AccessSpeed; | 812 | win->speed = req->AccessSpeed; |
850 | if (req->Attributes & WIN_MEMORY_TYPE) | 813 | if (req->Attributes & WIN_MEMORY_TYPE) |
851 | win->ctl.flags |= MAP_ATTRIB; | 814 | win->flags |= MAP_ATTRIB; |
852 | if (req->Attributes & WIN_ENABLE) | 815 | if (req->Attributes & WIN_ENABLE) |
853 | win->ctl.flags |= MAP_ACTIVE; | 816 | win->flags |= MAP_ACTIVE; |
854 | if (req->Attributes & WIN_DATA_WIDTH_16) | 817 | if (req->Attributes & WIN_DATA_WIDTH_16) |
855 | win->ctl.flags |= MAP_16BIT; | 818 | win->flags |= MAP_16BIT; |
856 | if (req->Attributes & WIN_USE_WAIT) | 819 | if (req->Attributes & WIN_USE_WAIT) |
857 | win->ctl.flags |= MAP_USE_WAIT; | 820 | win->flags |= MAP_USE_WAIT; |
858 | win->ctl.card_start = 0; | 821 | win->card_start = 0; |
859 | if (s->ops->set_mem_map(s, &win->ctl) != 0) { | 822 | if (s->ops->set_mem_map(s, win) != 0) { |
860 | ds_dbg(s, 0, "failed to set memory mapping\n"); | 823 | dev_dbg(&s->dev, "failed to set memory mapping\n"); |
861 | return -EIO; | 824 | return -EIO; |
862 | } | 825 | } |
863 | s->state |= SOCKET_WIN_REQ(w); | 826 | s->state |= SOCKET_WIN_REQ(w); |
864 | 827 | ||
865 | /* Return window handle */ | 828 | /* Return window handle */ |
866 | if (s->features & SS_CAP_STATIC_MAP) { | 829 | if (s->features & SS_CAP_STATIC_MAP) { |
867 | req->Base = win->ctl.static_start; | 830 | req->Base = win->static_start; |
868 | } else { | 831 | } else { |
869 | req->Base = win->ctl.res->start; | 832 | req->Base = win->res->start; |
870 | } | 833 | } |
871 | *wh = win; | 834 | *wh = w + 1; |
872 | 835 | ||
873 | return 0; | 836 | return 0; |
874 | } /* pcmcia_request_window */ | 837 | } /* pcmcia_request_window */ |
@@ -879,19 +842,46 @@ void pcmcia_disable_device(struct pcmcia_device *p_dev) { | |||
879 | pcmcia_release_io(p_dev, &p_dev->io); | 842 | pcmcia_release_io(p_dev, &p_dev->io); |
880 | pcmcia_release_irq(p_dev, &p_dev->irq); | 843 | pcmcia_release_irq(p_dev, &p_dev->irq); |
881 | if (p_dev->win) | 844 | if (p_dev->win) |
882 | pcmcia_release_window(p_dev->win); | 845 | pcmcia_release_window(p_dev, p_dev->win); |
883 | } | 846 | } |
884 | EXPORT_SYMBOL(pcmcia_disable_device); | 847 | EXPORT_SYMBOL(pcmcia_disable_device); |
885 | 848 | ||
886 | 849 | ||
887 | struct pcmcia_cfg_mem { | 850 | struct pcmcia_cfg_mem { |
888 | tuple_t tuple; | 851 | struct pcmcia_device *p_dev; |
852 | void *priv_data; | ||
853 | int (*conf_check) (struct pcmcia_device *p_dev, | ||
854 | cistpl_cftable_entry_t *cfg, | ||
855 | cistpl_cftable_entry_t *dflt, | ||
856 | unsigned int vcc, | ||
857 | void *priv_data); | ||
889 | cisparse_t parse; | 858 | cisparse_t parse; |
890 | u8 buf[256]; | ||
891 | cistpl_cftable_entry_t dflt; | 859 | cistpl_cftable_entry_t dflt; |
892 | }; | 860 | }; |
893 | 861 | ||
894 | /** | 862 | /** |
863 | * pcmcia_do_loop_config() - internal helper for pcmcia_loop_config() | ||
864 | * | ||
865 | * pcmcia_do_loop_config() is the internal callback for the call from | ||
866 | * pcmcia_loop_config() to pccard_loop_tuple(). Data is transferred | ||
867 | * by a struct pcmcia_cfg_mem. | ||
868 | */ | ||
869 | static int pcmcia_do_loop_config(tuple_t *tuple, cisparse_t *parse, void *priv) | ||
870 | { | ||
871 | cistpl_cftable_entry_t *cfg = &parse->cftable_entry; | ||
872 | struct pcmcia_cfg_mem *cfg_mem = priv; | ||
873 | |||
874 | /* default values */ | ||
875 | cfg_mem->p_dev->conf.ConfigIndex = cfg->index; | ||
876 | if (cfg->flags & CISTPL_CFTABLE_DEFAULT) | ||
877 | cfg_mem->dflt = *cfg; | ||
878 | |||
879 | return cfg_mem->conf_check(cfg_mem->p_dev, cfg, &cfg_mem->dflt, | ||
880 | cfg_mem->p_dev->socket->socket.Vcc, | ||
881 | cfg_mem->priv_data); | ||
882 | } | ||
883 | |||
884 | /** | ||
895 | * pcmcia_loop_config() - loop over configuration options | 885 | * pcmcia_loop_config() - loop over configuration options |
896 | * @p_dev: the struct pcmcia_device which we need to loop for. | 886 | * @p_dev: the struct pcmcia_device which we need to loop for. |
897 | * @conf_check: function to call for each configuration option. | 887 | * @conf_check: function to call for each configuration option. |
@@ -913,48 +903,174 @@ int pcmcia_loop_config(struct pcmcia_device *p_dev, | |||
913 | void *priv_data) | 903 | void *priv_data) |
914 | { | 904 | { |
915 | struct pcmcia_cfg_mem *cfg_mem; | 905 | struct pcmcia_cfg_mem *cfg_mem; |
916 | |||
917 | tuple_t *tuple; | ||
918 | int ret; | 906 | int ret; |
919 | unsigned int vcc; | ||
920 | 907 | ||
921 | cfg_mem = kzalloc(sizeof(struct pcmcia_cfg_mem), GFP_KERNEL); | 908 | cfg_mem = kzalloc(sizeof(struct pcmcia_cfg_mem), GFP_KERNEL); |
922 | if (cfg_mem == NULL) | 909 | if (cfg_mem == NULL) |
923 | return -ENOMEM; | 910 | return -ENOMEM; |
924 | 911 | ||
925 | /* get the current Vcc setting */ | 912 | cfg_mem->p_dev = p_dev; |
926 | vcc = p_dev->socket->socket.Vcc; | 913 | cfg_mem->conf_check = conf_check; |
914 | cfg_mem->priv_data = priv_data; | ||
927 | 915 | ||
928 | tuple = &cfg_mem->tuple; | 916 | ret = pccard_loop_tuple(p_dev->socket, p_dev->func, |
929 | tuple->TupleData = cfg_mem->buf; | 917 | CISTPL_CFTABLE_ENTRY, &cfg_mem->parse, |
930 | tuple->TupleDataMax = 255; | 918 | cfg_mem, pcmcia_do_loop_config); |
931 | tuple->TupleOffset = 0; | ||
932 | tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY; | ||
933 | tuple->Attributes = 0; | ||
934 | 919 | ||
935 | ret = pcmcia_get_first_tuple(p_dev, tuple); | 920 | kfree(cfg_mem); |
936 | while (!ret) { | 921 | return ret; |
937 | cistpl_cftable_entry_t *cfg = &cfg_mem->parse.cftable_entry; | 922 | } |
923 | EXPORT_SYMBOL(pcmcia_loop_config); | ||
924 | |||
925 | |||
926 | struct pcmcia_loop_mem { | ||
927 | struct pcmcia_device *p_dev; | ||
928 | void *priv_data; | ||
929 | int (*loop_tuple) (struct pcmcia_device *p_dev, | ||
930 | tuple_t *tuple, | ||
931 | void *priv_data); | ||
932 | }; | ||
933 | |||
934 | /** | ||
935 | * pcmcia_do_loop_tuple() - internal helper for pcmcia_loop_config() | ||
936 | * | ||
937 | * pcmcia_do_loop_tuple() is the internal callback for the call from | ||
938 | * pcmcia_loop_tuple() to pccard_loop_tuple(). Data is transferred | ||
939 | * by a struct pcmcia_cfg_mem. | ||
940 | */ | ||
941 | static int pcmcia_do_loop_tuple(tuple_t *tuple, cisparse_t *parse, void *priv) | ||
942 | { | ||
943 | struct pcmcia_loop_mem *loop = priv; | ||
944 | |||
945 | return loop->loop_tuple(loop->p_dev, tuple, loop->priv_data); | ||
946 | }; | ||
947 | |||
948 | /** | ||
949 | * pcmcia_loop_tuple() - loop over tuples in the CIS | ||
950 | * @p_dev: the struct pcmcia_device which we need to loop for. | ||
951 | * @code: which CIS code shall we look for? | ||
952 | * @priv_data: private data to be passed to the loop_tuple function. | ||
953 | * @loop_tuple: function to call for each CIS entry of type @function. IT | ||
954 | * gets passed the raw tuple and @priv_data. | ||
955 | * | ||
956 | * pcmcia_loop_tuple() loops over all CIS entries of type @function, and | ||
957 | * calls the @loop_tuple function for each entry. If the call to @loop_tuple | ||
958 | * returns 0, the loop exits. Returns 0 on success or errorcode otherwise. | ||
959 | */ | ||
960 | int pcmcia_loop_tuple(struct pcmcia_device *p_dev, cisdata_t code, | ||
961 | int (*loop_tuple) (struct pcmcia_device *p_dev, | ||
962 | tuple_t *tuple, | ||
963 | void *priv_data), | ||
964 | void *priv_data) | ||
965 | { | ||
966 | struct pcmcia_loop_mem loop = { | ||
967 | .p_dev = p_dev, | ||
968 | .loop_tuple = loop_tuple, | ||
969 | .priv_data = priv_data}; | ||
938 | 970 | ||
939 | if (pcmcia_get_tuple_data(p_dev, tuple)) | 971 | return pccard_loop_tuple(p_dev->socket, p_dev->func, code, NULL, |
940 | goto next_entry; | 972 | &loop, pcmcia_do_loop_tuple); |
973 | }; | ||
974 | EXPORT_SYMBOL(pcmcia_loop_tuple); | ||
941 | 975 | ||
942 | if (pcmcia_parse_tuple(tuple, &cfg_mem->parse)) | ||
943 | goto next_entry; | ||
944 | 976 | ||
945 | /* default values */ | 977 | struct pcmcia_loop_get { |
946 | p_dev->conf.ConfigIndex = cfg->index; | 978 | size_t len; |
947 | if (cfg->flags & CISTPL_CFTABLE_DEFAULT) | 979 | cisdata_t **buf; |
948 | cfg_mem->dflt = *cfg; | 980 | }; |
949 | 981 | ||
950 | ret = conf_check(p_dev, cfg, &cfg_mem->dflt, vcc, priv_data); | 982 | /** |
951 | if (!ret) | 983 | * pcmcia_do_get_tuple() - internal helper for pcmcia_get_tuple() |
952 | break; | 984 | * |
985 | * pcmcia_do_get_tuple() is the internal callback for the call from | ||
986 | * pcmcia_get_tuple() to pcmcia_loop_tuple(). As we're only interested in | ||
987 | * the first tuple, return 0 unconditionally. Create a memory buffer large | ||
988 | * enough to hold the content of the tuple, and fill it with the tuple data. | ||
989 | * The caller is responsible to free the buffer. | ||
990 | */ | ||
991 | static int pcmcia_do_get_tuple(struct pcmcia_device *p_dev, tuple_t *tuple, | ||
992 | void *priv) | ||
993 | { | ||
994 | struct pcmcia_loop_get *get = priv; | ||
995 | |||
996 | *get->buf = kzalloc(tuple->TupleDataLen, GFP_KERNEL); | ||
997 | if (*get->buf) { | ||
998 | get->len = tuple->TupleDataLen; | ||
999 | memcpy(*get->buf, tuple->TupleData, tuple->TupleDataLen); | ||
1000 | } else | ||
1001 | dev_dbg(&p_dev->dev, "do_get_tuple: out of memory\n"); | ||
1002 | return 0; | ||
1003 | }; | ||
953 | 1004 | ||
954 | next_entry: | 1005 | /** |
955 | ret = pcmcia_get_next_tuple(p_dev, tuple); | 1006 | * pcmcia_get_tuple() - get first tuple from CIS |
1007 | * @p_dev: the struct pcmcia_device which we need to loop for. | ||
1008 | * @code: which CIS code shall we look for? | ||
1009 | * @buf: pointer to store the buffer to. | ||
1010 | * | ||
1011 | * pcmcia_get_tuple() gets the content of the first CIS entry of type @code. | ||
1012 | * It returns the buffer length (or zero). The caller is responsible to free | ||
1013 | * the buffer passed in @buf. | ||
1014 | */ | ||
1015 | size_t pcmcia_get_tuple(struct pcmcia_device *p_dev, cisdata_t code, | ||
1016 | unsigned char **buf) | ||
1017 | { | ||
1018 | struct pcmcia_loop_get get = { | ||
1019 | .len = 0, | ||
1020 | .buf = buf, | ||
1021 | }; | ||
1022 | |||
1023 | *get.buf = NULL; | ||
1024 | pcmcia_loop_tuple(p_dev, code, pcmcia_do_get_tuple, &get); | ||
1025 | |||
1026 | return get.len; | ||
1027 | }; | ||
1028 | EXPORT_SYMBOL(pcmcia_get_tuple); | ||
1029 | |||
1030 | |||
1031 | /** | ||
1032 | * pcmcia_do_get_mac() - internal helper for pcmcia_get_mac_from_cis() | ||
1033 | * | ||
1034 | * pcmcia_do_get_mac() is the internal callback for the call from | ||
1035 | * pcmcia_get_mac_from_cis() to pcmcia_loop_tuple(). We check whether the | ||
1036 | * tuple contains a proper LAN_NODE_ID of length 6, and copy the data | ||
1037 | * to struct net_device->dev_addr[i]. | ||
1038 | */ | ||
1039 | static int pcmcia_do_get_mac(struct pcmcia_device *p_dev, tuple_t *tuple, | ||
1040 | void *priv) | ||
1041 | { | ||
1042 | struct net_device *dev = priv; | ||
1043 | int i; | ||
1044 | |||
1045 | if (tuple->TupleData[0] != CISTPL_FUNCE_LAN_NODE_ID) | ||
1046 | return -EINVAL; | ||
1047 | if (tuple->TupleDataLen < ETH_ALEN + 2) { | ||
1048 | dev_warn(&p_dev->dev, "Invalid CIS tuple length for " | ||
1049 | "LAN_NODE_ID\n"); | ||
1050 | return -EINVAL; | ||
956 | } | 1051 | } |
957 | 1052 | ||
958 | return ret; | 1053 | if (tuple->TupleData[1] != ETH_ALEN) { |
959 | } | 1054 | dev_warn(&p_dev->dev, "Invalid header for LAN_NODE_ID\n"); |
960 | EXPORT_SYMBOL(pcmcia_loop_config); | 1055 | return -EINVAL; |
1056 | } | ||
1057 | for (i = 0; i < 6; i++) | ||
1058 | dev->dev_addr[i] = tuple->TupleData[i+2]; | ||
1059 | return 0; | ||
1060 | }; | ||
1061 | |||
1062 | /** | ||
1063 | * pcmcia_get_mac_from_cis() - read out MAC address from CISTPL_FUNCE | ||
1064 | * @p_dev: the struct pcmcia_device for which we want the address. | ||
1065 | * @dev: a properly prepared struct net_device to store the info to. | ||
1066 | * | ||
1067 | * pcmcia_get_mac_from_cis() reads out the hardware MAC address from | ||
1068 | * CISTPL_FUNCE and stores it into struct net_device *dev->dev_addr which | ||
1069 | * must be set up properly by the driver (see examples!). | ||
1070 | */ | ||
1071 | int pcmcia_get_mac_from_cis(struct pcmcia_device *p_dev, struct net_device *dev) | ||
1072 | { | ||
1073 | return pcmcia_loop_tuple(p_dev, CISTPL_FUNCE, pcmcia_do_get_mac, dev); | ||
1074 | }; | ||
1075 | EXPORT_SYMBOL(pcmcia_get_mac_from_cis); | ||
1076 | |||