diff options
Diffstat (limited to 'drivers/pcmcia/pcmcia_resource.c')
-rw-r--r-- | drivers/pcmcia/pcmcia_resource.c | 634 |
1 files changed, 162 insertions, 472 deletions
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index 7c3d03bb4f30..29f91fac1dff 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c | |||
@@ -23,6 +23,8 @@ | |||
23 | #include <linux/netdevice.h> | 23 | #include <linux/netdevice.h> |
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | 25 | ||
26 | #include <asm/irq.h> | ||
27 | |||
26 | #include <pcmcia/cs_types.h> | 28 | #include <pcmcia/cs_types.h> |
27 | #include <pcmcia/ss.h> | 29 | #include <pcmcia/ss.h> |
28 | #include <pcmcia/cs.h> | 30 | #include <pcmcia/cs.h> |
@@ -38,29 +40,6 @@ static int io_speed; | |||
38 | module_param(io_speed, int, 0444); | 40 | module_param(io_speed, int, 0444); |
39 | 41 | ||
40 | 42 | ||
41 | #ifdef CONFIG_PCMCIA_PROBE | ||
42 | #include <asm/irq.h> | ||
43 | /* mask of IRQs already reserved by other cards, we should avoid using them */ | ||
44 | static u8 pcmcia_used_irq[NR_IRQS]; | ||
45 | #endif | ||
46 | |||
47 | static int pcmcia_adjust_io_region(struct resource *res, unsigned long start, | ||
48 | unsigned long end, struct pcmcia_socket *s) | ||
49 | { | ||
50 | if (s->resource_ops->adjust_io_region) | ||
51 | return s->resource_ops->adjust_io_region(res, start, end, s); | ||
52 | return -ENOMEM; | ||
53 | } | ||
54 | |||
55 | static struct resource *pcmcia_find_io_region(unsigned long base, int num, | ||
56 | unsigned long align, | ||
57 | struct pcmcia_socket *s) | ||
58 | { | ||
59 | if (s->resource_ops->find_io) | ||
60 | return s->resource_ops->find_io(base, num, align, s); | ||
61 | return NULL; | ||
62 | } | ||
63 | |||
64 | int pcmcia_validate_mem(struct pcmcia_socket *s) | 43 | int pcmcia_validate_mem(struct pcmcia_socket *s) |
65 | { | 44 | { |
66 | if (s->resource_ops->validate_mem) | 45 | if (s->resource_ops->validate_mem) |
@@ -86,8 +65,7 @@ struct resource *pcmcia_find_mem_region(u_long base, u_long num, u_long align, | |||
86 | static int alloc_io_space(struct pcmcia_socket *s, u_int attr, | 65 | static int alloc_io_space(struct pcmcia_socket *s, u_int attr, |
87 | unsigned int *base, unsigned int num, u_int lines) | 66 | unsigned int *base, unsigned int num, u_int lines) |
88 | { | 67 | { |
89 | int i; | 68 | unsigned int align; |
90 | unsigned int try, align; | ||
91 | 69 | ||
92 | align = (*base) ? (lines ? 1<<lines : 0) : 1; | 70 | align = (*base) ? (lines ? 1<<lines : 0) : 1; |
93 | if (align && (align < num)) { | 71 | if (align && (align < num)) { |
@@ -104,50 +82,8 @@ static int alloc_io_space(struct pcmcia_socket *s, u_int attr, | |||
104 | *base, align); | 82 | *base, align); |
105 | align = 0; | 83 | align = 0; |
106 | } | 84 | } |
107 | if ((s->features & SS_CAP_STATIC_MAP) && s->io_offset) { | 85 | |
108 | *base = s->io_offset | (*base & 0x0fff); | 86 | return s->resource_ops->find_io(s, attr, base, num, align); |
109 | return 0; | ||
110 | } | ||
111 | /* Check for an already-allocated window that must conflict with | ||
112 | * what was asked for. It is a hack because it does not catch all | ||
113 | * potential conflicts, just the most obvious ones. | ||
114 | */ | ||
115 | for (i = 0; i < MAX_IO_WIN; i++) | ||
116 | if ((s->io[i].res) && *base && | ||
117 | ((s->io[i].res->start & (align-1)) == *base)) | ||
118 | return 1; | ||
119 | for (i = 0; i < MAX_IO_WIN; i++) { | ||
120 | if (!s->io[i].res) { | ||
121 | s->io[i].res = pcmcia_find_io_region(*base, num, align, s); | ||
122 | if (s->io[i].res) { | ||
123 | *base = s->io[i].res->start; | ||
124 | s->io[i].res->flags = (s->io[i].res->flags & ~IORESOURCE_BITS) | (attr & IORESOURCE_BITS); | ||
125 | s->io[i].InUse = num; | ||
126 | break; | ||
127 | } else | ||
128 | return 1; | ||
129 | } else if ((s->io[i].res->flags & IORESOURCE_BITS) != (attr & IORESOURCE_BITS)) | ||
130 | continue; | ||
131 | /* Try to extend top of window */ | ||
132 | try = s->io[i].res->end + 1; | ||
133 | if ((*base == 0) || (*base == try)) | ||
134 | if (pcmcia_adjust_io_region(s->io[i].res, s->io[i].res->start, | ||
135 | s->io[i].res->end + num, s) == 0) { | ||
136 | *base = try; | ||
137 | s->io[i].InUse += num; | ||
138 | break; | ||
139 | } | ||
140 | /* Try to extend bottom of window */ | ||
141 | try = s->io[i].res->start - num; | ||
142 | if ((*base == 0) || (*base == try)) | ||
143 | if (pcmcia_adjust_io_region(s->io[i].res, s->io[i].res->start - num, | ||
144 | s->io[i].res->end, s) == 0) { | ||
145 | *base = try; | ||
146 | s->io[i].InUse += num; | ||
147 | break; | ||
148 | } | ||
149 | } | ||
150 | return (i == MAX_IO_WIN); | ||
151 | } /* alloc_io_space */ | 87 | } /* alloc_io_space */ |
152 | 88 | ||
153 | 89 | ||
@@ -187,6 +123,7 @@ int pcmcia_access_configuration_register(struct pcmcia_device *p_dev, | |||
187 | config_t *c; | 123 | config_t *c; |
188 | int addr; | 124 | int addr; |
189 | u_char val; | 125 | u_char val; |
126 | int ret = 0; | ||
190 | 127 | ||
191 | if (!p_dev || !p_dev->function_config) | 128 | if (!p_dev || !p_dev->function_config) |
192 | return -EINVAL; | 129 | return -EINVAL; |
@@ -203,11 +140,10 @@ int pcmcia_access_configuration_register(struct pcmcia_device *p_dev, | |||
203 | } | 140 | } |
204 | 141 | ||
205 | addr = (c->ConfigBase + reg->Offset) >> 1; | 142 | addr = (c->ConfigBase + reg->Offset) >> 1; |
206 | mutex_unlock(&s->ops_mutex); | ||
207 | 143 | ||
208 | switch (reg->Action) { | 144 | switch (reg->Action) { |
209 | case CS_READ: | 145 | case CS_READ: |
210 | pcmcia_read_cis_mem(s, 1, addr, 1, &val); | 146 | ret = pcmcia_read_cis_mem(s, 1, addr, 1, &val); |
211 | reg->Value = val; | 147 | reg->Value = val; |
212 | break; | 148 | break; |
213 | case CS_WRITE: | 149 | case CS_WRITE: |
@@ -216,10 +152,11 @@ int pcmcia_access_configuration_register(struct pcmcia_device *p_dev, | |||
216 | break; | 152 | break; |
217 | default: | 153 | default: |
218 | dev_dbg(&s->dev, "Invalid conf register request\n"); | 154 | dev_dbg(&s->dev, "Invalid conf register request\n"); |
219 | return -EINVAL; | 155 | ret = -EINVAL; |
220 | break; | 156 | break; |
221 | } | 157 | } |
222 | return 0; | 158 | mutex_unlock(&s->ops_mutex); |
159 | return ret; | ||
223 | } /* pcmcia_access_configuration_register */ | 160 | } /* pcmcia_access_configuration_register */ |
224 | EXPORT_SYMBOL(pcmcia_access_configuration_register); | 161 | EXPORT_SYMBOL(pcmcia_access_configuration_register); |
225 | 162 | ||
@@ -275,19 +212,9 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, | |||
275 | goto unlock; | 212 | goto unlock; |
276 | } | 213 | } |
277 | 214 | ||
278 | if (mod->Attributes & CONF_IRQ_CHANGE_VALID) { | 215 | if (mod->Attributes & (CONF_IRQ_CHANGE_VALID | CONF_VCC_CHANGE_VALID)) { |
279 | if (mod->Attributes & CONF_ENABLE_IRQ) { | 216 | dev_dbg(&s->dev, |
280 | c->Attributes |= CONF_ENABLE_IRQ; | 217 | "changing Vcc or IRQ is not allowed at this time\n"); |
281 | s->socket.io_irq = s->irq.AssignedIRQ; | ||
282 | } else { | ||
283 | c->Attributes &= ~CONF_ENABLE_IRQ; | ||
284 | s->socket.io_irq = 0; | ||
285 | } | ||
286 | s->ops->set_socket(s, &s->socket); | ||
287 | } | ||
288 | |||
289 | if (mod->Attributes & CONF_VCC_CHANGE_VALID) { | ||
290 | dev_dbg(&s->dev, "changing Vcc is not allowed at this time\n"); | ||
291 | ret = -EINVAL; | 218 | ret = -EINVAL; |
292 | goto unlock; | 219 | goto unlock; |
293 | } | 220 | } |
@@ -422,52 +349,6 @@ out: | |||
422 | } /* pcmcia_release_io */ | 349 | } /* pcmcia_release_io */ |
423 | 350 | ||
424 | 351 | ||
425 | static int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req) | ||
426 | { | ||
427 | struct pcmcia_socket *s = p_dev->socket; | ||
428 | config_t *c; | ||
429 | int ret = -EINVAL; | ||
430 | |||
431 | mutex_lock(&s->ops_mutex); | ||
432 | |||
433 | c = p_dev->function_config; | ||
434 | |||
435 | if (!p_dev->_irq) | ||
436 | goto out; | ||
437 | |||
438 | p_dev->_irq = 0; | ||
439 | |||
440 | if (c->state & CONFIG_LOCKED) | ||
441 | goto out; | ||
442 | |||
443 | if (c->irq.Attributes != req->Attributes) { | ||
444 | dev_dbg(&s->dev, "IRQ attributes must match assigned ones\n"); | ||
445 | goto out; | ||
446 | } | ||
447 | if (s->irq.AssignedIRQ != req->AssignedIRQ) { | ||
448 | dev_dbg(&s->dev, "IRQ must match assigned one\n"); | ||
449 | goto out; | ||
450 | } | ||
451 | if (--s->irq.Config == 0) { | ||
452 | c->state &= ~CONFIG_IRQ_REQ; | ||
453 | s->irq.AssignedIRQ = 0; | ||
454 | } | ||
455 | |||
456 | if (req->Handler) | ||
457 | free_irq(req->AssignedIRQ, p_dev->priv); | ||
458 | |||
459 | #ifdef CONFIG_PCMCIA_PROBE | ||
460 | pcmcia_used_irq[req->AssignedIRQ]--; | ||
461 | #endif | ||
462 | ret = 0; | ||
463 | |||
464 | out: | ||
465 | mutex_unlock(&s->ops_mutex); | ||
466 | |||
467 | return ret; | ||
468 | } /* pcmcia_release_irq */ | ||
469 | |||
470 | |||
471 | int pcmcia_release_window(struct pcmcia_device *p_dev, window_handle_t wh) | 352 | int pcmcia_release_window(struct pcmcia_device *p_dev, window_handle_t wh) |
472 | { | 353 | { |
473 | struct pcmcia_socket *s = p_dev->socket; | 354 | struct pcmcia_socket *s = p_dev->socket; |
@@ -551,12 +432,11 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, | |||
551 | if (req->Attributes & CONF_ENABLE_SPKR) | 432 | if (req->Attributes & CONF_ENABLE_SPKR) |
552 | s->socket.flags |= SS_SPKR_ENA; | 433 | s->socket.flags |= SS_SPKR_ENA; |
553 | if (req->Attributes & CONF_ENABLE_IRQ) | 434 | if (req->Attributes & CONF_ENABLE_IRQ) |
554 | s->socket.io_irq = s->irq.AssignedIRQ; | 435 | s->socket.io_irq = s->pcmcia_irq; |
555 | else | 436 | else |
556 | s->socket.io_irq = 0; | 437 | s->socket.io_irq = 0; |
557 | s->ops->set_socket(s, &s->socket); | 438 | s->ops->set_socket(s, &s->socket); |
558 | s->lock_count++; | 439 | s->lock_count++; |
559 | mutex_unlock(&s->ops_mutex); | ||
560 | 440 | ||
561 | /* Set up CIS configuration registers */ | 441 | /* Set up CIS configuration registers */ |
562 | base = c->ConfigBase = req->ConfigBase; | 442 | base = c->ConfigBase = req->ConfigBase; |
@@ -574,9 +454,9 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, | |||
574 | if (req->Present & PRESENT_IOBASE_0) | 454 | if (req->Present & PRESENT_IOBASE_0) |
575 | c->Option |= COR_ADDR_DECODE; | 455 | c->Option |= COR_ADDR_DECODE; |
576 | } | 456 | } |
577 | if (c->state & CONFIG_IRQ_REQ) | 457 | if ((req->Attributes & CONF_ENABLE_IRQ) && |
578 | if (!(c->irq.Attributes & IRQ_FORCED_PULSE)) | 458 | !(req->Attributes & CONF_ENABLE_PULSE_IRQ)) |
579 | c->Option |= COR_LEVEL_REQ; | 459 | c->Option |= COR_LEVEL_REQ; |
580 | pcmcia_write_cis_mem(s, 1, (base + CISREG_COR)>>1, 1, &c->Option); | 460 | pcmcia_write_cis_mem(s, 1, (base + CISREG_COR)>>1, 1, &c->Option); |
581 | mdelay(40); | 461 | mdelay(40); |
582 | } | 462 | } |
@@ -605,7 +485,6 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, | |||
605 | 485 | ||
606 | /* Configure I/O windows */ | 486 | /* Configure I/O windows */ |
607 | if (c->state & CONFIG_IO_REQ) { | 487 | if (c->state & CONFIG_IO_REQ) { |
608 | mutex_lock(&s->ops_mutex); | ||
609 | iomap.speed = io_speed; | 488 | iomap.speed = io_speed; |
610 | for (i = 0; i < MAX_IO_WIN; i++) | 489 | for (i = 0; i < MAX_IO_WIN; i++) |
611 | if (s->io[i].res) { | 490 | if (s->io[i].res) { |
@@ -624,11 +503,11 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, | |||
624 | s->ops->set_io_map(s, &iomap); | 503 | s->ops->set_io_map(s, &iomap); |
625 | s->io[i].Config++; | 504 | s->io[i].Config++; |
626 | } | 505 | } |
627 | mutex_unlock(&s->ops_mutex); | ||
628 | } | 506 | } |
629 | 507 | ||
630 | c->state |= CONFIG_LOCKED; | 508 | c->state |= CONFIG_LOCKED; |
631 | p_dev->_locked = 1; | 509 | p_dev->_locked = 1; |
510 | mutex_unlock(&s->ops_mutex); | ||
632 | return 0; | 511 | return 0; |
633 | } /* pcmcia_request_configuration */ | 512 | } /* pcmcia_request_configuration */ |
634 | EXPORT_SYMBOL(pcmcia_request_configuration); | 513 | EXPORT_SYMBOL(pcmcia_request_configuration); |
@@ -706,137 +585,176 @@ out: | |||
706 | EXPORT_SYMBOL(pcmcia_request_io); | 585 | EXPORT_SYMBOL(pcmcia_request_io); |
707 | 586 | ||
708 | 587 | ||
709 | /** pcmcia_request_irq | 588 | /** |
589 | * pcmcia_request_irq() - attempt to request a IRQ for a PCMCIA device | ||
710 | * | 590 | * |
711 | * Request_irq() reserves an irq for this client. | 591 | * pcmcia_request_irq() is a wrapper around request_irq which will allow |
592 | * the PCMCIA core to clean up the registration in pcmcia_disable_device(). | ||
593 | * Drivers are free to use request_irq() directly, but then they need to | ||
594 | * call free_irq themselfves, too. Also, only IRQF_SHARED capable IRQ | ||
595 | * handlers are allowed. | ||
596 | */ | ||
597 | int __must_check pcmcia_request_irq(struct pcmcia_device *p_dev, | ||
598 | irq_handler_t handler) | ||
599 | { | ||
600 | int ret; | ||
601 | |||
602 | if (!p_dev->irq) | ||
603 | return -EINVAL; | ||
604 | |||
605 | ret = request_irq(p_dev->irq, handler, IRQF_SHARED, | ||
606 | p_dev->devname, p_dev->priv); | ||
607 | if (!ret) | ||
608 | p_dev->_irq = 1; | ||
609 | |||
610 | return ret; | ||
611 | } | ||
612 | EXPORT_SYMBOL(pcmcia_request_irq); | ||
613 | |||
614 | |||
615 | /** | ||
616 | * pcmcia_request_exclusive_irq() - attempt to request an exclusive IRQ first | ||
712 | * | 617 | * |
713 | * Also, since Linux only reserves irq's when they are actually | 618 | * pcmcia_request_exclusive_irq() is a wrapper around request_irq which |
714 | * hooked, we don't guarantee that an irq will still be available | 619 | * attempts first to request an exclusive IRQ. If it fails, it also accepts |
715 | * when the configuration is locked. Now that I think about it, | 620 | * a shared IRQ, but prints out a warning. PCMCIA drivers should allow for |
716 | * there might be a way to fix this using a dummy handler. | 621 | * IRQ sharing and either use request_irq directly (then they need to call |
622 | * free_irq themselves, too), or the pcmcia_request_irq() function. | ||
717 | */ | 623 | */ |
624 | int __must_check | ||
625 | __pcmcia_request_exclusive_irq(struct pcmcia_device *p_dev, | ||
626 | irq_handler_t handler) | ||
627 | { | ||
628 | int ret; | ||
629 | |||
630 | if (!p_dev->irq) | ||
631 | return -EINVAL; | ||
632 | |||
633 | ret = request_irq(p_dev->irq, handler, 0, p_dev->devname, p_dev->priv); | ||
634 | if (ret) { | ||
635 | ret = pcmcia_request_irq(p_dev, handler); | ||
636 | dev_printk(KERN_WARNING, &p_dev->dev, "pcmcia: " | ||
637 | "request for exclusive IRQ could not be fulfilled.\n"); | ||
638 | dev_printk(KERN_WARNING, &p_dev->dev, "pcmcia: the driver " | ||
639 | "needs updating to supported shared IRQ lines.\n"); | ||
640 | } | ||
641 | if (ret) | ||
642 | dev_printk(KERN_INFO, &p_dev->dev, "request_irq() failed\n"); | ||
643 | else | ||
644 | p_dev->_irq = 1; | ||
645 | |||
646 | return ret; | ||
647 | } /* pcmcia_request_exclusive_irq */ | ||
648 | EXPORT_SYMBOL(__pcmcia_request_exclusive_irq); | ||
649 | |||
718 | 650 | ||
719 | #ifdef CONFIG_PCMCIA_PROBE | 651 | #ifdef CONFIG_PCMCIA_PROBE |
652 | |||
653 | /* mask of IRQs already reserved by other cards, we should avoid using them */ | ||
654 | static u8 pcmcia_used_irq[NR_IRQS]; | ||
655 | |||
720 | static irqreturn_t test_action(int cpl, void *dev_id) | 656 | static irqreturn_t test_action(int cpl, void *dev_id) |
721 | { | 657 | { |
722 | return IRQ_NONE; | 658 | return IRQ_NONE; |
723 | } | 659 | } |
724 | #endif | ||
725 | 660 | ||
726 | int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) | 661 | /** |
662 | * pcmcia_setup_isa_irq() - determine whether an ISA IRQ can be used | ||
663 | * @p_dev - the associated PCMCIA device | ||
664 | * | ||
665 | * locking note: must be called with ops_mutex locked. | ||
666 | */ | ||
667 | static int pcmcia_setup_isa_irq(struct pcmcia_device *p_dev, int type) | ||
727 | { | 668 | { |
728 | struct pcmcia_socket *s = p_dev->socket; | 669 | struct pcmcia_socket *s = p_dev->socket; |
729 | config_t *c; | 670 | unsigned int try, irq; |
730 | int ret = -EINVAL, irq = 0; | 671 | u32 mask = s->irq_mask; |
731 | int type; | 672 | int ret = -ENODEV; |
732 | 673 | ||
733 | mutex_lock(&s->ops_mutex); | 674 | for (try = 0; try < 64; try++) { |
675 | irq = try % 32; | ||
734 | 676 | ||
735 | if (!(s->state & SOCKET_PRESENT)) { | 677 | /* marked as available by driver, not blocked by userspace? */ |
736 | dev_dbg(&s->dev, "No card present\n"); | 678 | if (!((mask >> irq) & 1)) |
737 | goto out; | 679 | continue; |
738 | } | 680 | |
739 | c = p_dev->function_config; | 681 | /* avoid an IRQ which is already used by another PCMCIA card */ |
740 | if (c->state & CONFIG_LOCKED) { | 682 | if ((try < 32) && pcmcia_used_irq[irq]) |
741 | dev_dbg(&s->dev, "Configuration is locked\n"); | 683 | continue; |
742 | goto out; | 684 | |
743 | } | 685 | /* register the correct driver, if possible, to check whether |
744 | if (c->state & CONFIG_IRQ_REQ) { | 686 | * registering a dummy handle works, i.e. if the IRQ isn't |
745 | dev_dbg(&s->dev, "IRQ already configured\n"); | 687 | * marked as used by the kernel resource management core */ |
746 | goto out; | 688 | ret = request_irq(irq, test_action, type, p_dev->devname, |
689 | p_dev); | ||
690 | if (!ret) { | ||
691 | free_irq(irq, p_dev); | ||
692 | p_dev->irq = s->pcmcia_irq = irq; | ||
693 | pcmcia_used_irq[irq]++; | ||
694 | break; | ||
695 | } | ||
747 | } | 696 | } |
748 | 697 | ||
749 | /* Decide what type of interrupt we are registering */ | 698 | return ret; |
750 | type = 0; | 699 | } |
751 | if (s->functions > 1) /* All of this ought to be handled higher up */ | ||
752 | type = IRQF_SHARED; | ||
753 | else if (req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) | ||
754 | type = IRQF_SHARED; | ||
755 | else | ||
756 | printk(KERN_WARNING "pcmcia: Driver needs updating to support IRQ sharing.\n"); | ||
757 | 700 | ||
758 | /* If the interrupt is already assigned, it must be the same */ | 701 | void pcmcia_cleanup_irq(struct pcmcia_socket *s) |
759 | if (s->irq.AssignedIRQ != 0) | 702 | { |
760 | irq = s->irq.AssignedIRQ; | 703 | pcmcia_used_irq[s->pcmcia_irq]--; |
704 | s->pcmcia_irq = 0; | ||
705 | } | ||
761 | 706 | ||
762 | #ifdef CONFIG_PCMCIA_PROBE | 707 | #else /* CONFIG_PCMCIA_PROBE */ |
763 | if (!irq) { | ||
764 | int try; | ||
765 | u32 mask = s->irq_mask; | ||
766 | void *data = p_dev; /* something unique to this device */ | ||
767 | 708 | ||
768 | for (try = 0; try < 64; try++) { | 709 | static int pcmcia_setup_isa_irq(struct pcmcia_device *p_dev, int type) |
769 | irq = try % 32; | 710 | { |
711 | return -EINVAL; | ||
712 | } | ||
770 | 713 | ||
771 | /* marked as available by driver, and not blocked by userspace? */ | 714 | void pcmcia_cleanup_irq(struct pcmcia_socket *s) |
772 | if (!((mask >> irq) & 1)) | 715 | { |
773 | continue; | 716 | s->pcmcia_irq = 0; |
717 | return; | ||
718 | } | ||
774 | 719 | ||
775 | /* avoid an IRQ which is already used by a PCMCIA card */ | 720 | #endif /* CONFIG_PCMCIA_PROBE */ |
776 | if ((try < 32) && pcmcia_used_irq[irq]) | ||
777 | continue; | ||
778 | 721 | ||
779 | /* register the correct driver, if possible, of check whether | ||
780 | * registering a dummy handle works, i.e. if the IRQ isn't | ||
781 | * marked as used by the kernel resource management core */ | ||
782 | ret = request_irq(irq, | ||
783 | (req->Handler) ? req->Handler : test_action, | ||
784 | type, | ||
785 | p_dev->devname, | ||
786 | (req->Handler) ? p_dev->priv : data); | ||
787 | if (!ret) { | ||
788 | if (!req->Handler) | ||
789 | free_irq(irq, data); | ||
790 | break; | ||
791 | } | ||
792 | } | ||
793 | } | ||
794 | #endif | ||
795 | /* only assign PCI irq if no IRQ already assigned */ | ||
796 | if (ret && !s->irq.AssignedIRQ) { | ||
797 | if (!s->pci_irq) { | ||
798 | dev_printk(KERN_INFO, &s->dev, "no IRQ found\n"); | ||
799 | goto out; | ||
800 | } | ||
801 | type = IRQF_SHARED; | ||
802 | irq = s->pci_irq; | ||
803 | } | ||
804 | 722 | ||
805 | if (ret && req->Handler) { | 723 | /** |
806 | ret = request_irq(irq, req->Handler, type, | 724 | * pcmcia_setup_irq() - determine IRQ to be used for device |
807 | p_dev->devname, p_dev->priv); | 725 | * @p_dev - the associated PCMCIA device |
808 | if (ret) { | 726 | * |
809 | dev_printk(KERN_INFO, &s->dev, | 727 | * locking note: must be called with ops_mutex locked. |
810 | "request_irq() failed\n"); | 728 | */ |
811 | goto out; | 729 | int pcmcia_setup_irq(struct pcmcia_device *p_dev) |
812 | } | 730 | { |
813 | } | 731 | struct pcmcia_socket *s = p_dev->socket; |
814 | 732 | ||
815 | /* Make sure the fact the request type was overridden is passed back */ | 733 | if (p_dev->irq) |
816 | if (type == IRQF_SHARED && !(req->Attributes & IRQ_TYPE_DYNAMIC_SHARING)) { | 734 | return 0; |
817 | req->Attributes |= IRQ_TYPE_DYNAMIC_SHARING; | 735 | |
818 | dev_printk(KERN_WARNING, &p_dev->dev, "pcmcia: " | 736 | /* already assigned? */ |
819 | "request for exclusive IRQ could not be fulfilled.\n"); | 737 | if (s->pcmcia_irq) { |
820 | dev_printk(KERN_WARNING, &p_dev->dev, "pcmcia: the driver " | 738 | p_dev->irq = s->pcmcia_irq; |
821 | "needs updating to supported shared IRQ lines.\n"); | 739 | return 0; |
822 | } | 740 | } |
823 | c->irq.Attributes = req->Attributes; | ||
824 | s->irq.AssignedIRQ = req->AssignedIRQ = irq; | ||
825 | s->irq.Config++; | ||
826 | 741 | ||
827 | c->state |= CONFIG_IRQ_REQ; | 742 | /* prefer an exclusive ISA irq */ |
828 | p_dev->_irq = 1; | 743 | if (!pcmcia_setup_isa_irq(p_dev, 0)) |
744 | return 0; | ||
829 | 745 | ||
830 | #ifdef CONFIG_PCMCIA_PROBE | 746 | /* but accept a shared ISA irq */ |
831 | pcmcia_used_irq[irq]++; | 747 | if (!pcmcia_setup_isa_irq(p_dev, IRQF_SHARED)) |
832 | #endif | 748 | return 0; |
833 | 749 | ||
834 | ret = 0; | 750 | /* but use the PCI irq otherwise */ |
835 | out: | 751 | if (s->pci_irq) { |
836 | mutex_unlock(&s->ops_mutex); | 752 | p_dev->irq = s->pcmcia_irq = s->pci_irq; |
837 | return ret; | 753 | return 0; |
838 | } /* pcmcia_request_irq */ | 754 | } |
839 | EXPORT_SYMBOL(pcmcia_request_irq); | 755 | |
756 | return -EINVAL; | ||
757 | } | ||
840 | 758 | ||
841 | 759 | ||
842 | /** pcmcia_request_window | 760 | /** pcmcia_request_window |
@@ -939,237 +857,9 @@ void pcmcia_disable_device(struct pcmcia_device *p_dev) | |||
939 | { | 857 | { |
940 | pcmcia_release_configuration(p_dev); | 858 | pcmcia_release_configuration(p_dev); |
941 | pcmcia_release_io(p_dev, &p_dev->io); | 859 | pcmcia_release_io(p_dev, &p_dev->io); |
942 | pcmcia_release_irq(p_dev, &p_dev->irq); | 860 | if (p_dev->_irq) |
861 | free_irq(p_dev->irq, p_dev->priv); | ||
943 | if (p_dev->win) | 862 | if (p_dev->win) |
944 | pcmcia_release_window(p_dev, p_dev->win); | 863 | pcmcia_release_window(p_dev, p_dev->win); |
945 | } | 864 | } |
946 | EXPORT_SYMBOL(pcmcia_disable_device); | 865 | EXPORT_SYMBOL(pcmcia_disable_device); |
947 | |||
948 | |||
949 | struct pcmcia_cfg_mem { | ||
950 | struct pcmcia_device *p_dev; | ||
951 | void *priv_data; | ||
952 | int (*conf_check) (struct pcmcia_device *p_dev, | ||
953 | cistpl_cftable_entry_t *cfg, | ||
954 | cistpl_cftable_entry_t *dflt, | ||
955 | unsigned int vcc, | ||
956 | void *priv_data); | ||
957 | cisparse_t parse; | ||
958 | cistpl_cftable_entry_t dflt; | ||
959 | }; | ||
960 | |||
961 | /** | ||
962 | * pcmcia_do_loop_config() - internal helper for pcmcia_loop_config() | ||
963 | * | ||
964 | * pcmcia_do_loop_config() is the internal callback for the call from | ||
965 | * pcmcia_loop_config() to pccard_loop_tuple(). Data is transferred | ||
966 | * by a struct pcmcia_cfg_mem. | ||
967 | */ | ||
968 | static int pcmcia_do_loop_config(tuple_t *tuple, cisparse_t *parse, void *priv) | ||
969 | { | ||
970 | cistpl_cftable_entry_t *cfg = &parse->cftable_entry; | ||
971 | struct pcmcia_cfg_mem *cfg_mem = priv; | ||
972 | |||
973 | /* default values */ | ||
974 | cfg_mem->p_dev->conf.ConfigIndex = cfg->index; | ||
975 | if (cfg->flags & CISTPL_CFTABLE_DEFAULT) | ||
976 | cfg_mem->dflt = *cfg; | ||
977 | |||
978 | return cfg_mem->conf_check(cfg_mem->p_dev, cfg, &cfg_mem->dflt, | ||
979 | cfg_mem->p_dev->socket->socket.Vcc, | ||
980 | cfg_mem->priv_data); | ||
981 | } | ||
982 | |||
983 | /** | ||
984 | * pcmcia_loop_config() - loop over configuration options | ||
985 | * @p_dev: the struct pcmcia_device which we need to loop for. | ||
986 | * @conf_check: function to call for each configuration option. | ||
987 | * It gets passed the struct pcmcia_device, the CIS data | ||
988 | * describing the configuration option, and private data | ||
989 | * being passed to pcmcia_loop_config() | ||
990 | * @priv_data: private data to be passed to the conf_check function. | ||
991 | * | ||
992 | * pcmcia_loop_config() loops over all configuration options, and calls | ||
993 | * the driver-specific conf_check() for each one, checking whether | ||
994 | * it is a valid one. Returns 0 on success or errorcode otherwise. | ||
995 | */ | ||
996 | int pcmcia_loop_config(struct pcmcia_device *p_dev, | ||
997 | int (*conf_check) (struct pcmcia_device *p_dev, | ||
998 | cistpl_cftable_entry_t *cfg, | ||
999 | cistpl_cftable_entry_t *dflt, | ||
1000 | unsigned int vcc, | ||
1001 | void *priv_data), | ||
1002 | void *priv_data) | ||
1003 | { | ||
1004 | struct pcmcia_cfg_mem *cfg_mem; | ||
1005 | int ret; | ||
1006 | |||
1007 | cfg_mem = kzalloc(sizeof(struct pcmcia_cfg_mem), GFP_KERNEL); | ||
1008 | if (cfg_mem == NULL) | ||
1009 | return -ENOMEM; | ||
1010 | |||
1011 | cfg_mem->p_dev = p_dev; | ||
1012 | cfg_mem->conf_check = conf_check; | ||
1013 | cfg_mem->priv_data = priv_data; | ||
1014 | |||
1015 | ret = pccard_loop_tuple(p_dev->socket, p_dev->func, | ||
1016 | CISTPL_CFTABLE_ENTRY, &cfg_mem->parse, | ||
1017 | cfg_mem, pcmcia_do_loop_config); | ||
1018 | |||
1019 | kfree(cfg_mem); | ||
1020 | return ret; | ||
1021 | } | ||
1022 | EXPORT_SYMBOL(pcmcia_loop_config); | ||
1023 | |||
1024 | |||
1025 | struct pcmcia_loop_mem { | ||
1026 | struct pcmcia_device *p_dev; | ||
1027 | void *priv_data; | ||
1028 | int (*loop_tuple) (struct pcmcia_device *p_dev, | ||
1029 | tuple_t *tuple, | ||
1030 | void *priv_data); | ||
1031 | }; | ||
1032 | |||
1033 | /** | ||
1034 | * pcmcia_do_loop_tuple() - internal helper for pcmcia_loop_config() | ||
1035 | * | ||
1036 | * pcmcia_do_loop_tuple() is the internal callback for the call from | ||
1037 | * pcmcia_loop_tuple() to pccard_loop_tuple(). Data is transferred | ||
1038 | * by a struct pcmcia_cfg_mem. | ||
1039 | */ | ||
1040 | static int pcmcia_do_loop_tuple(tuple_t *tuple, cisparse_t *parse, void *priv) | ||
1041 | { | ||
1042 | struct pcmcia_loop_mem *loop = priv; | ||
1043 | |||
1044 | return loop->loop_tuple(loop->p_dev, tuple, loop->priv_data); | ||
1045 | }; | ||
1046 | |||
1047 | /** | ||
1048 | * pcmcia_loop_tuple() - loop over tuples in the CIS | ||
1049 | * @p_dev: the struct pcmcia_device which we need to loop for. | ||
1050 | * @code: which CIS code shall we look for? | ||
1051 | * @priv_data: private data to be passed to the loop_tuple function. | ||
1052 | * @loop_tuple: function to call for each CIS entry of type @function. IT | ||
1053 | * gets passed the raw tuple and @priv_data. | ||
1054 | * | ||
1055 | * pcmcia_loop_tuple() loops over all CIS entries of type @function, and | ||
1056 | * calls the @loop_tuple function for each entry. If the call to @loop_tuple | ||
1057 | * returns 0, the loop exits. Returns 0 on success or errorcode otherwise. | ||
1058 | */ | ||
1059 | int pcmcia_loop_tuple(struct pcmcia_device *p_dev, cisdata_t code, | ||
1060 | int (*loop_tuple) (struct pcmcia_device *p_dev, | ||
1061 | tuple_t *tuple, | ||
1062 | void *priv_data), | ||
1063 | void *priv_data) | ||
1064 | { | ||
1065 | struct pcmcia_loop_mem loop = { | ||
1066 | .p_dev = p_dev, | ||
1067 | .loop_tuple = loop_tuple, | ||
1068 | .priv_data = priv_data}; | ||
1069 | |||
1070 | return pccard_loop_tuple(p_dev->socket, p_dev->func, code, NULL, | ||
1071 | &loop, pcmcia_do_loop_tuple); | ||
1072 | } | ||
1073 | EXPORT_SYMBOL(pcmcia_loop_tuple); | ||
1074 | |||
1075 | |||
1076 | struct pcmcia_loop_get { | ||
1077 | size_t len; | ||
1078 | cisdata_t **buf; | ||
1079 | }; | ||
1080 | |||
1081 | /** | ||
1082 | * pcmcia_do_get_tuple() - internal helper for pcmcia_get_tuple() | ||
1083 | * | ||
1084 | * pcmcia_do_get_tuple() is the internal callback for the call from | ||
1085 | * pcmcia_get_tuple() to pcmcia_loop_tuple(). As we're only interested in | ||
1086 | * the first tuple, return 0 unconditionally. Create a memory buffer large | ||
1087 | * enough to hold the content of the tuple, and fill it with the tuple data. | ||
1088 | * The caller is responsible to free the buffer. | ||
1089 | */ | ||
1090 | static int pcmcia_do_get_tuple(struct pcmcia_device *p_dev, tuple_t *tuple, | ||
1091 | void *priv) | ||
1092 | { | ||
1093 | struct pcmcia_loop_get *get = priv; | ||
1094 | |||
1095 | *get->buf = kzalloc(tuple->TupleDataLen, GFP_KERNEL); | ||
1096 | if (*get->buf) { | ||
1097 | get->len = tuple->TupleDataLen; | ||
1098 | memcpy(*get->buf, tuple->TupleData, tuple->TupleDataLen); | ||
1099 | } else | ||
1100 | dev_dbg(&p_dev->dev, "do_get_tuple: out of memory\n"); | ||
1101 | return 0; | ||
1102 | } | ||
1103 | |||
1104 | /** | ||
1105 | * pcmcia_get_tuple() - get first tuple from CIS | ||
1106 | * @p_dev: the struct pcmcia_device which we need to loop for. | ||
1107 | * @code: which CIS code shall we look for? | ||
1108 | * @buf: pointer to store the buffer to. | ||
1109 | * | ||
1110 | * pcmcia_get_tuple() gets the content of the first CIS entry of type @code. | ||
1111 | * It returns the buffer length (or zero). The caller is responsible to free | ||
1112 | * the buffer passed in @buf. | ||
1113 | */ | ||
1114 | size_t pcmcia_get_tuple(struct pcmcia_device *p_dev, cisdata_t code, | ||
1115 | unsigned char **buf) | ||
1116 | { | ||
1117 | struct pcmcia_loop_get get = { | ||
1118 | .len = 0, | ||
1119 | .buf = buf, | ||
1120 | }; | ||
1121 | |||
1122 | *get.buf = NULL; | ||
1123 | pcmcia_loop_tuple(p_dev, code, pcmcia_do_get_tuple, &get); | ||
1124 | |||
1125 | return get.len; | ||
1126 | } | ||
1127 | EXPORT_SYMBOL(pcmcia_get_tuple); | ||
1128 | |||
1129 | |||
1130 | /** | ||
1131 | * pcmcia_do_get_mac() - internal helper for pcmcia_get_mac_from_cis() | ||
1132 | * | ||
1133 | * pcmcia_do_get_mac() is the internal callback for the call from | ||
1134 | * pcmcia_get_mac_from_cis() to pcmcia_loop_tuple(). We check whether the | ||
1135 | * tuple contains a proper LAN_NODE_ID of length 6, and copy the data | ||
1136 | * to struct net_device->dev_addr[i]. | ||
1137 | */ | ||
1138 | static int pcmcia_do_get_mac(struct pcmcia_device *p_dev, tuple_t *tuple, | ||
1139 | void *priv) | ||
1140 | { | ||
1141 | struct net_device *dev = priv; | ||
1142 | int i; | ||
1143 | |||
1144 | if (tuple->TupleData[0] != CISTPL_FUNCE_LAN_NODE_ID) | ||
1145 | return -EINVAL; | ||
1146 | if (tuple->TupleDataLen < ETH_ALEN + 2) { | ||
1147 | dev_warn(&p_dev->dev, "Invalid CIS tuple length for " | ||
1148 | "LAN_NODE_ID\n"); | ||
1149 | return -EINVAL; | ||
1150 | } | ||
1151 | |||
1152 | if (tuple->TupleData[1] != ETH_ALEN) { | ||
1153 | dev_warn(&p_dev->dev, "Invalid header for LAN_NODE_ID\n"); | ||
1154 | return -EINVAL; | ||
1155 | } | ||
1156 | for (i = 0; i < 6; i++) | ||
1157 | dev->dev_addr[i] = tuple->TupleData[i+2]; | ||
1158 | return 0; | ||
1159 | } | ||
1160 | |||
1161 | /** | ||
1162 | * pcmcia_get_mac_from_cis() - read out MAC address from CISTPL_FUNCE | ||
1163 | * @p_dev: the struct pcmcia_device for which we want the address. | ||
1164 | * @dev: a properly prepared struct net_device to store the info to. | ||
1165 | * | ||
1166 | * pcmcia_get_mac_from_cis() reads out the hardware MAC address from | ||
1167 | * CISTPL_FUNCE and stores it into struct net_device *dev->dev_addr which | ||
1168 | * must be set up properly by the driver (see examples!). | ||
1169 | */ | ||
1170 | int pcmcia_get_mac_from_cis(struct pcmcia_device *p_dev, struct net_device *dev) | ||
1171 | { | ||
1172 | return pcmcia_loop_tuple(p_dev, CISTPL_FUNCE, pcmcia_do_get_mac, dev); | ||
1173 | } | ||
1174 | EXPORT_SYMBOL(pcmcia_get_mac_from_cis); | ||
1175 | |||