1 /*======================================================================
3 Resource management routines
5 rsrc_mgr.c 1.79 2000/08/30 20:23:58
7 The contents of this file are subject to the Mozilla Public
8 License Version 1.1 (the "License"); you may not use this file
9 except in compliance with the License. You may obtain a copy of
10 the License at http://www.mozilla.org/MPL/
12 Software distributed under the License is distributed on an "AS
13 IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
14 implied. See the License for the specific language governing
15 rights and limitations under the License.
17 The initial developer of the original code is David A. Hinds
18 <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
19 are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
21 Alternatively, the contents of this file may be used under the
22 terms of the GNU General Public License version 2 (the "GPL"), in which
23 case the provisions of the GPL are applicable instead of the
24 above. If you wish to allow the use of your version of this file
25 only under the terms of the GPL and not to allow others to use
26 your version of this file under the MPL, indicate your decision
27 by deleting the provisions above and replace them with the notice
28 and other provisions required by the GPL. If you do not delete
29 the provisions above, a recipient may use your version of this
30 file under either the MPL or the GPL.
32 ======================================================================*/
34 #include <linux/config.h>
35 #include <linux/module.h>
36 #include <linux/moduleparam.h>
37 #include <linux/init.h>
38 #include <linux/interrupt.h>
39 #include <linux/kernel.h>
40 #include <linux/errno.h>
41 #include <linux/types.h>
42 #include <linux/slab.h>
43 #include <linux/ioport.h>
44 #include <linux/timer.h>
45 #include <linux/pci.h>
49 #include <pcmcia/cs_types.h>
50 #include <pcmcia/ss.h>
51 #include <pcmcia/cs.h>
52 #include <pcmcia/bulkmem.h>
53 #include <pcmcia/cistpl.h>
54 #include "cs_internal.h"
56 /*====================================================================*/
58 /* Parameters that can be set with 'insmod' */
60 #define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0444)
62 INT_MODULE_PARM(probe_mem, 1); /* memory probe? */
63 #ifdef CONFIG_PCMCIA_PROBE
64 INT_MODULE_PARM(probe_io, 1); /* IO port probe? */
65 INT_MODULE_PARM(mem_limit, 0x10000);
68 /*======================================================================
70 The resource_map_t structures are used to track what resources are
71 available for allocation for PC Card devices.
73 ======================================================================*/
75 typedef struct resource_map_t {
77 struct resource_map_t *next;
80 /* Memory resource database */
81 static resource_map_t mem_db = {
85 /* IO port resource database */
86 static resource_map_t io_db = {
90 static DECLARE_MUTEX(rsrc_sem);
92 #ifdef CONFIG_PCMCIA_PROBE
94 typedef struct irq_info_t {
96 int time_share, dyn_share;
97 struct pcmcia_socket *Socket;
100 /* Table of IRQ assignments */
101 static irq_info_t irq_table[NR_IRQS];
105 /*======================================================================
107 Linux resource management extensions
109 ======================================================================*/
111 static struct resource *
112 make_resource(unsigned long b, unsigned long n, int flags, char *name)
114 struct resource *res = kmalloc(sizeof(*res), GFP_KERNEL);
117 memset(res, 0, sizeof(*res));
120 res->end = b + n - 1;
126 static struct resource *
127 claim_region(struct pcmcia_socket *s, unsigned long base, unsigned long size,
128 int type, char *name)
130 struct resource *res, *parent;
132 parent = type & IORESOURCE_MEM ? &iomem_resource : &ioport_resource;
133 res = make_resource(base, size, type | IORESOURCE_BUSY, name);
138 parent = pci_find_parent_resource(s->cb_dev, res);
140 if (!parent || request_resource(parent, res)) {
148 static void free_region(struct resource *res)
151 release_resource(res);
156 /*======================================================================
158 These manage the internal databases of available resources.
160 ======================================================================*/
162 static int add_interval(resource_map_t *map, u_long base, u_long num)
164 resource_map_t *p, *q;
166 for (p = map; ; p = p->next) {
167 if ((p != map) && (p->base+p->num-1 >= base))
169 if ((p->next == map) || (p->next->base > base+num-1))
172 q = kmalloc(sizeof(resource_map_t), GFP_KERNEL);
173 if (!q) return CS_OUT_OF_RESOURCE;
174 q->base = base; q->num = num;
175 q->next = p->next; p->next = q;
179 /*====================================================================*/
181 static int sub_interval(resource_map_t *map, u_long base, u_long num)
183 resource_map_t *p, *q;
185 for (p = map; ; p = q) {
189 if ((q->base+q->num > base) && (base+num > q->base)) {
190 if (q->base >= base) {
191 if (q->base+q->num <= base+num) {
192 /* Delete whole block */
195 /* don't advance the pointer yet */
198 /* Cut off bit from the front */
199 q->num = q->base + q->num - base - num;
200 q->base = base + num;
202 } else if (q->base+q->num <= base+num) {
203 /* Cut off bit from the end */
204 q->num = base - q->base;
206 /* Split the block into two pieces */
207 p = kmalloc(sizeof(resource_map_t), GFP_KERNEL);
208 if (!p) return CS_OUT_OF_RESOURCE;
210 p->num = q->base+q->num - p->base;
211 q->num = base - q->base;
212 p->next = q->next ; q->next = p;
219 /*======================================================================
221 These routines examine a region of IO or memory addresses to
222 determine what ranges might be genuinely available.
224 ======================================================================*/
226 #ifdef CONFIG_PCMCIA_PROBE
227 static void do_io_probe(ioaddr_t base, ioaddr_t num)
229 struct resource *res;
230 ioaddr_t i, j, bad, any;
231 u_char *b, hole, most;
233 printk(KERN_INFO "cs: IO port probe 0x%04x-0x%04x:",
236 /* First, what does a floating port look like? */
237 b = kmalloc(256, GFP_KERNEL);
239 printk(KERN_ERR "do_io_probe: unable to kmalloc 256 bytes");
243 for (i = base, most = 0; i < base+num; i += 8) {
244 res = claim_region(NULL, i, 8, IORESOURCE_IO, "PCMCIA IO probe");
248 for (j = 1; j < 8; j++)
249 if (inb(i+j) != hole) break;
251 if ((j == 8) && (++b[hole] > b[most]))
253 if (b[most] == 127) break;
258 for (i = base; i < base+num; i += 8) {
259 res = claim_region(NULL, i, 8, IORESOURCE_IO, "PCMCIA IO probe");
262 for (j = 0; j < 8; j++)
263 if (inb(i+j) != most) break;
267 printk(" excluding");
272 sub_interval(&io_db, bad, i-bad);
273 printk(" %#04x-%#04x", bad, i-1);
279 if ((num > 16) && (bad == base) && (i == base+num)) {
280 printk(" nothing: probe failed.\n");
283 sub_interval(&io_db, bad, i-bad);
284 printk(" %#04x-%#04x", bad, i-1);
288 printk(any ? "\n" : " clean.\n");
292 /*======================================================================
294 This is tricky... when we set up CIS memory, we try to validate
295 the memory window space allocations.
297 ======================================================================*/
299 /* Validation function for cards with a valid CIS */
300 static int readable(struct pcmcia_socket *s, struct resource *res, cisinfo_t *info)
304 s->cis_mem.sys_start = res->start;
305 s->cis_mem.sys_stop = res->end;
306 s->cis_mem.res = res;
307 s->cis_virt = ioremap(res->start, s->map_size);
309 ret = pcmcia_validate_cis(s->clients, info);
310 /* invalidate mapping and CIS cache */
311 iounmap(s->cis_virt);
313 destroy_cis_cache(s);
315 s->cis_mem.sys_start = 0;
316 s->cis_mem.sys_stop = 0;
317 s->cis_mem.res = NULL;
318 if ((ret != 0) || (info->Chains == 0))
323 /* Validation function for simple memory cards */
324 static int checksum(struct pcmcia_socket *s, struct resource *res)
327 int i, a = 0, b = -1, d;
330 virt = ioremap(res->start, s->map_size);
333 map.flags = MAP_ACTIVE;
335 map.sys_start = res->start;
336 map.sys_stop = res->end;
339 s->ops->set_mem_map(s, &map);
341 /* Don't bother checking every word... */
342 for (i = 0; i < s->map_size; i += 44) {
349 s->ops->set_mem_map(s, &map);
354 return (b == -1) ? -1 : (a>>1);
358 cis_readable(struct pcmcia_socket *s, unsigned long base, unsigned long size)
360 struct resource *res1, *res2;
361 cisinfo_t info1, info2;
364 res1 = claim_region(s, base, size/2, IORESOURCE_MEM, "cs memory probe");
365 res2 = claim_region(s, base + size/2, size/2, IORESOURCE_MEM, "cs memory probe");
368 ret = readable(s, res1, &info1);
369 ret += readable(s, res2, &info2);
375 return (ret == 2) && (info1.Chains == info2.Chains);
379 checksum_match(struct pcmcia_socket *s, unsigned long base, unsigned long size)
381 struct resource *res1, *res2;
384 res1 = claim_region(s, base, size/2, IORESOURCE_MEM, "cs memory probe");
385 res2 = claim_region(s, base + size/2, size/2, IORESOURCE_MEM, "cs memory probe");
388 a = checksum(s, res1);
389 b = checksum(s, res2);
395 return (a == b) && (a >= 0);
398 /*======================================================================
400 The memory probe. If the memory list includes a 64K-aligned block
401 below 1MB, we probe in 64K chunks, and as soon as we accumulate at
402 least mem_limit free space, we quit.
404 ======================================================================*/
406 static int do_mem_probe(u_long base, u_long num, struct pcmcia_socket *s)
408 u_long i, j, bad, fail, step;
410 printk(KERN_INFO "cs: memory probe 0x%06lx-0x%06lx:",
413 step = (num < 0x20000) ? 0x2000 : ((num>>4) & ~0x1fff);
414 /* cis_readable wants to map 2x map_size */
415 if (step < 2 * s->map_size)
416 step = 2 * s->map_size;
417 for (i = j = base; i < base+num; i = j + step) {
419 for (j = i; j < base+num; j += step) {
420 if (cis_readable(s, j, step))
423 fail = ((i == base) && (j == base+num));
426 for (j = i; j < base+num; j += 2*step)
427 if (checksum_match(s, j, step) &&
428 checksum_match(s, j + step, step))
432 if (!bad) printk(" excluding");
433 printk(" %#05lx-%#05lx", i, j-1);
434 sub_interval(&mem_db, i, j-i);
438 printk(bad ? "\n" : " clean.\n");
442 #ifdef CONFIG_PCMCIA_PROBE
444 static u_long inv_probe(resource_map_t *m, struct pcmcia_socket *s)
449 ok = inv_probe(m->next, s);
451 if (m->base >= 0x100000)
452 sub_interval(&mem_db, m->base, m->num);
455 if (m->base < 0x100000)
457 return do_mem_probe(m->base, m->num, s);
460 static void validate_mem(struct pcmcia_socket *s)
462 resource_map_t *m, mm;
463 static u_char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 };
464 static int hi = 0, lo = 0;
466 int force_low = !(s->features & SS_CAP_PAGE_REGS);
469 /* We do up to four passes through the list */
471 if (hi++ || (inv_probe(mem_db.next, s) > 0))
473 printk(KERN_NOTICE "cs: warning: no high memory space "
478 for (m = mem_db.next; m != &mem_db; m = mm.next) {
480 /* Only probe < 1 MB */
481 if (mm.base >= 0x100000) continue;
482 if ((mm.base | mm.num) & 0xffff) {
483 ok += do_mem_probe(mm.base, mm.num, s);
486 /* Special probe for 64K-aligned block */
487 for (i = 0; i < 4; i++) {
489 if ((b >= mm.base) && (b+0x10000 <= mm.base+mm.num)) {
491 sub_interval(&mem_db, b, 0x10000);
493 ok += do_mem_probe(b, 0x10000, s);
501 #else /* CONFIG_PCMCIA_PROBE */
503 static void validate_mem(struct pcmcia_socket *s)
505 resource_map_t *m, mm;
510 for (m = mem_db.next; m != &mem_db; m = mm.next) {
512 if (do_mem_probe(mm.base, mm.num, s))
519 #endif /* CONFIG_PCMCIA_PROBE */
521 void pcmcia_validate_mem(struct pcmcia_socket *s)
525 if (probe_mem && s->state & SOCKET_PRESENT)
531 EXPORT_SYMBOL(pcmcia_validate_mem);
533 struct pcmcia_align_data {
535 unsigned long offset;
540 pcmcia_common_align(void *align_data, struct resource *res,
541 unsigned long size, unsigned long align)
543 struct pcmcia_align_data *data = align_data;
546 * Ensure that we have the correct start address
548 start = (res->start & ~data->mask) + data->offset;
549 if (start < res->start)
550 start += data->mask + 1;
555 pcmcia_align(void *align_data, struct resource *res,
556 unsigned long size, unsigned long align)
558 struct pcmcia_align_data *data = align_data;
561 pcmcia_common_align(data, res, size, align);
563 for (m = data->map->next; m != data->map; m = m->next) {
564 unsigned long start = m->base;
565 unsigned long end = m->base + m->num - 1;
568 * If the lower resources are not available, try aligning
569 * to this entry of the resource database to see if it'll
572 if (res->start < start) {
574 pcmcia_common_align(data, res, size, align);
578 * If we're above the area which was passed in, there's
579 * no point proceeding.
581 if (res->start >= res->end)
584 if ((res->start + size - 1) <= end)
589 * If we failed to find something suitable, ensure we fail.
592 res->start = res->end;
596 * Adjust an existing IO region allocation, but making sure that we don't
597 * encroach outside the resources which the user supplied.
599 int adjust_io_region(struct resource *res, unsigned long r_start,
600 unsigned long r_end, struct pcmcia_socket *s)
606 for (m = io_db.next; m != &io_db; m = m->next) {
607 unsigned long start = m->base;
608 unsigned long end = m->base + m->num - 1;
610 if (start > r_start || r_end > end)
613 ret = adjust_resource(res, r_start, r_end - r_start + 1);
621 /*======================================================================
623 These find ranges of I/O ports or memory addresses that are not
624 currently allocated by other devices.
626 The 'align' field should reflect the number of bits of address
627 that need to be preserved from the initial value of *base. It
628 should be a power of two, greater than or equal to 'num'. A value
629 of 0 means that all bits of *base are significant. *base should
630 also be strictly less than 'align'.
632 ======================================================================*/
634 struct resource *find_io_region(unsigned long base, int num,
635 unsigned long align, char *name, struct pcmcia_socket *s)
637 struct resource *res = make_resource(0, num, IORESOURCE_IO, s->dev.class_id);
638 struct pcmcia_align_data data;
639 unsigned long min = base;
645 data.mask = align - 1;
646 data.offset = base & data.mask;
652 ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num, 1,
653 min, 0, pcmcia_align, &data);
656 ret = allocate_resource(&ioport_resource, res, num, min, ~0UL,
657 1, pcmcia_align, &data);
667 struct resource *find_mem_region(u_long base, u_long num, u_long align,
668 int low, char *name, struct pcmcia_socket *s)
670 struct resource *res = make_resource(0, num, IORESOURCE_MEM, s->dev.class_id);
671 struct pcmcia_align_data data;
672 unsigned long min, max;
675 low = low || !(s->features & SS_CAP_PAGE_REGS);
677 data.mask = align - 1;
678 data.offset = base & data.mask;
681 for (i = 0; i < 2; i++) {
684 min = base < max ? base : 0;
687 min = 0x100000UL + base;
693 ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num,
695 pcmcia_align, &data);
698 ret = allocate_resource(&iomem_resource, res, num, min,
699 max, 1, pcmcia_align, &data);
713 /*======================================================================
715 This checks to see if an interrupt is available, with support
716 for interrupt sharing. We don't support reserving interrupts
717 yet. If the interrupt is available, we allocate it.
719 ======================================================================*/
721 #ifdef CONFIG_PCMCIA_PROBE
723 static irqreturn_t fake_irq(int i, void *d, struct pt_regs *r) { return IRQ_NONE; }
724 static inline int check_irq(int irq)
726 if (request_irq(irq, fake_irq, 0, "bogus", NULL) != 0)
732 int try_irq(u_int Attributes, int irq, int specific)
734 irq_info_t *info = &irq_table[irq];
738 if (info->Attributes & RES_ALLOCATED) {
739 switch (Attributes & IRQ_TYPE) {
740 case IRQ_TYPE_EXCLUSIVE:
744 if ((info->Attributes & RES_IRQ_TYPE)
745 != RES_IRQ_TYPE_TIME) {
749 if (Attributes & IRQ_FIRST_SHARED) {
750 ret = CS_BAD_ATTRIBUTE;
753 info->Attributes |= RES_IRQ_TYPE_TIME | RES_ALLOCATED;
756 case IRQ_TYPE_DYNAMIC_SHARING:
757 if ((info->Attributes & RES_IRQ_TYPE)
758 != RES_IRQ_TYPE_DYNAMIC) {
762 if (Attributes & IRQ_FIRST_SHARED) {
763 ret = CS_BAD_ATTRIBUTE;
766 info->Attributes |= RES_IRQ_TYPE_DYNAMIC | RES_ALLOCATED;
771 if ((info->Attributes & RES_RESERVED) && !specific) {
775 if (check_irq(irq) != 0) {
779 switch (Attributes & IRQ_TYPE) {
780 case IRQ_TYPE_EXCLUSIVE:
781 info->Attributes |= RES_ALLOCATED;
784 if (!(Attributes & IRQ_FIRST_SHARED)) {
785 ret = CS_BAD_ATTRIBUTE;
788 info->Attributes |= RES_IRQ_TYPE_TIME | RES_ALLOCATED;
789 info->time_share = 1;
791 case IRQ_TYPE_DYNAMIC_SHARING:
792 if (!(Attributes & IRQ_FIRST_SHARED)) {
793 ret = CS_BAD_ATTRIBUTE;
796 info->Attributes |= RES_IRQ_TYPE_DYNAMIC | RES_ALLOCATED;
808 /*====================================================================*/
810 #ifdef CONFIG_PCMCIA_PROBE
812 void undo_irq(u_int Attributes, int irq)
816 info = &irq_table[irq];
818 switch (Attributes & IRQ_TYPE) {
819 case IRQ_TYPE_EXCLUSIVE:
820 info->Attributes &= RES_RESERVED;
824 if (info->time_share == 0)
825 info->Attributes &= RES_RESERVED;
827 case IRQ_TYPE_DYNAMIC_SHARING:
829 if (info->dyn_share == 0)
830 info->Attributes &= RES_RESERVED;
838 /*======================================================================
840 The various adjust_* calls form the external interface to the
843 ======================================================================*/
845 static int adjust_memory(adjust_t *adj)
850 base = adj->resource.memory.Base;
851 num = adj->resource.memory.Size;
852 if ((num == 0) || (base+num-1 < base))
858 switch (adj->Action) {
859 case ADD_MANAGED_RESOURCE:
860 ret = add_interval(&mem_db, base, num);
862 case REMOVE_MANAGED_RESOURCE:
863 ret = sub_interval(&mem_db, base, num);
864 if (ret == CS_SUCCESS) {
865 struct pcmcia_socket *socket;
866 down_read(&pcmcia_socket_list_rwsem);
867 list_for_each_entry(socket, &pcmcia_socket_list, socket_list)
868 release_cis_mem(socket);
869 up_read(&pcmcia_socket_list_rwsem);
873 ret = CS_UNSUPPORTED_FUNCTION;
880 /*====================================================================*/
882 static int adjust_io(adjust_t *adj)
884 int base, num, ret = CS_SUCCESS;
886 base = adj->resource.io.BasePort;
887 num = adj->resource.io.NumPorts;
888 if ((base < 0) || (base > 0xffff))
890 if ((num <= 0) || (base+num > 0x10000) || (base+num <= base))
894 switch (adj->Action) {
895 case ADD_MANAGED_RESOURCE:
896 if (add_interval(&io_db, base, num) != 0) {
900 #ifdef CONFIG_PCMCIA_PROBE
902 do_io_probe(base, num);
905 case REMOVE_MANAGED_RESOURCE:
906 sub_interval(&io_db, base, num);
909 ret = CS_UNSUPPORTED_FUNCTION;
917 /*====================================================================*/
919 static int adjust_irq(adjust_t *adj)
921 int ret = CS_SUCCESS;
922 #ifdef CONFIG_PCMCIA_PROBE
926 irq = adj->resource.irq.IRQ;
927 if ((irq < 0) || (irq > 15))
929 info = &irq_table[irq];
932 switch (adj->Action) {
933 case ADD_MANAGED_RESOURCE:
934 if (info->Attributes & RES_REMOVED)
935 info->Attributes &= ~(RES_REMOVED|RES_ALLOCATED);
937 if (adj->Attributes & RES_ALLOCATED) {
941 if (adj->Attributes & RES_RESERVED)
942 info->Attributes |= RES_RESERVED;
944 info->Attributes &= ~RES_RESERVED;
946 case REMOVE_MANAGED_RESOURCE:
947 if (info->Attributes & RES_REMOVED) {
951 if (info->Attributes & RES_ALLOCATED) {
955 info->Attributes |= RES_ALLOCATED|RES_REMOVED;
956 info->Attributes &= ~RES_RESERVED;
959 ret = CS_UNSUPPORTED_FUNCTION;
967 /*====================================================================*/
969 int pcmcia_adjust_resource_info(client_handle_t handle, adjust_t *adj)
971 if (CHECK_HANDLE(handle))
972 return CS_BAD_HANDLE;
974 switch (adj->Resource) {
975 case RES_MEMORY_RANGE:
976 return adjust_memory(adj);
979 return adjust_io(adj);
982 return adjust_irq(adj);
985 return CS_UNSUPPORTED_FUNCTION;
988 /*====================================================================*/
990 void release_resource_db(void)
992 resource_map_t *p, *q;
994 for (p = mem_db.next; p != &mem_db; p = q) {
998 for (p = io_db.next; p != &io_db; p = q) {