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;
121 res->flags = flags | IORESOURCE_BUSY;
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_virt = ioremap(res->start, s->map_size);
308 ret = pcmcia_validate_cis(s->clients, info);
309 /* invalidate mapping and CIS cache */
310 iounmap(s->cis_virt);
312 destroy_cis_cache(s);
314 s->cis_mem.sys_start = 0;
315 s->cis_mem.sys_stop = 0;
316 if ((ret != 0) || (info->Chains == 0))
321 /* Validation function for simple memory cards */
322 static int checksum(struct pcmcia_socket *s, struct resource *res)
325 int i, a = 0, b = -1, d;
328 virt = ioremap(res->start, s->map_size);
331 map.flags = MAP_ACTIVE;
333 map.sys_start = res->start;
334 map.sys_stop = res->end;
336 s->ops->set_mem_map(s, &map);
338 /* Don't bother checking every word... */
339 for (i = 0; i < s->map_size; i += 44) {
346 s->ops->set_mem_map(s, &map);
351 return (b == -1) ? -1 : (a>>1);
355 cis_readable(struct pcmcia_socket *s, unsigned long base, unsigned long size)
357 struct resource *res1, *res2;
358 cisinfo_t info1, info2;
361 res1 = claim_region(s, base, size/2, IORESOURCE_MEM, "cs memory probe");
362 res2 = claim_region(s, base + size/2, size/2, IORESOURCE_MEM, "cs memory probe");
365 ret = readable(s, res1, &info1);
366 ret += readable(s, res2, &info2);
372 return (ret == 2) && (info1.Chains == info2.Chains);
376 checksum_match(struct pcmcia_socket *s, unsigned long base, unsigned long size)
378 struct resource *res1, *res2;
381 res1 = claim_region(s, base, size/2, IORESOURCE_MEM, "cs memory probe");
382 res2 = claim_region(s, base + size/2, size/2, IORESOURCE_MEM, "cs memory probe");
385 a = checksum(s, res1);
386 b = checksum(s, res2);
392 return (a == b) && (a >= 0);
395 /*======================================================================
397 The memory probe. If the memory list includes a 64K-aligned block
398 below 1MB, we probe in 64K chunks, and as soon as we accumulate at
399 least mem_limit free space, we quit.
401 ======================================================================*/
403 static int do_mem_probe(u_long base, u_long num, struct pcmcia_socket *s)
405 u_long i, j, bad, fail, step;
407 printk(KERN_INFO "cs: memory probe 0x%06lx-0x%06lx:",
410 step = (num < 0x20000) ? 0x2000 : ((num>>4) & ~0x1fff);
411 /* cis_readable wants to map 2x map_size */
412 if (step < 2 * s->map_size)
413 step = 2 * s->map_size;
414 for (i = j = base; i < base+num; i = j + step) {
416 for (j = i; j < base+num; j += step) {
417 if (cis_readable(s, j, step))
420 fail = ((i == base) && (j == base+num));
423 for (j = i; j < base+num; j += 2*step)
424 if (checksum_match(s, j, step) &&
425 checksum_match(s, j + step, step))
429 if (!bad) printk(" excluding");
430 printk(" %#05lx-%#05lx", i, j-1);
431 sub_interval(&mem_db, i, j-i);
435 printk(bad ? "\n" : " clean.\n");
439 #ifdef CONFIG_PCMCIA_PROBE
441 static u_long inv_probe(resource_map_t *m, struct pcmcia_socket *s)
446 ok = inv_probe(m->next, s);
448 if (m->base >= 0x100000)
449 sub_interval(&mem_db, m->base, m->num);
452 if (m->base < 0x100000)
454 return do_mem_probe(m->base, m->num, s);
457 void validate_mem(struct pcmcia_socket *s)
459 resource_map_t *m, mm;
460 static u_char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 };
461 static int hi = 0, lo = 0;
463 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 void validate_mem(struct pcmcia_socket *s)
505 resource_map_t *m, mm;
508 if (probe_mem && done++ == 0) {
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 struct pcmcia_align_data {
523 unsigned long offset;
528 pcmcia_common_align(void *align_data, struct resource *res,
529 unsigned long size, unsigned long align)
531 struct pcmcia_align_data *data = align_data;
534 * Ensure that we have the correct start address
536 start = (res->start & ~data->mask) + data->offset;
537 if (start < res->start)
538 start += data->mask + 1;
543 pcmcia_align(void *align_data, struct resource *res,
544 unsigned long size, unsigned long align)
546 struct pcmcia_align_data *data = align_data;
549 pcmcia_common_align(data, res, size, align);
551 for (m = data->map->next; m != data->map; m = m->next) {
552 unsigned long start = m->base;
553 unsigned long end = m->base + m->num - 1;
556 * If the lower resources are not available, try aligning
557 * to this entry of the resource database to see if it'll
560 if (res->start < start) {
562 pcmcia_common_align(data, res, size, align);
566 * If we're above the area which was passed in, there's
567 * no point proceeding.
569 if (res->start >= res->end)
572 if ((res->start + size - 1) <= end)
577 * If we failed to find something suitable, ensure we fail.
580 res->start = res->end;
584 * Adjust an existing IO region allocation, but making sure that we don't
585 * encroach outside the resources which the user supplied.
587 int adjust_io_region(struct resource *res, unsigned long r_start,
588 unsigned long r_end, struct pcmcia_socket *s)
594 for (m = io_db.next; m != &io_db; m = m->next) {
595 unsigned long start = m->base;
596 unsigned long end = m->base + m->num - 1;
598 if (start > r_start || r_end > end)
601 ret = adjust_resource(res, r_start, r_end - r_start + 1);
609 /*======================================================================
611 These find ranges of I/O ports or memory addresses that are not
612 currently allocated by other devices.
614 The 'align' field should reflect the number of bits of address
615 that need to be preserved from the initial value of *base. It
616 should be a power of two, greater than or equal to 'num'. A value
617 of 0 means that all bits of *base are significant. *base should
618 also be strictly less than 'align'.
620 ======================================================================*/
622 struct resource *find_io_region(unsigned long base, int num,
623 unsigned long align, char *name, struct pcmcia_socket *s)
625 struct resource *res = make_resource(0, num, IORESOURCE_IO, name);
626 struct pcmcia_align_data data;
627 unsigned long min = base;
633 data.mask = align - 1;
634 data.offset = base & data.mask;
640 ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num, 1,
641 min, 0, pcmcia_align, &data);
644 ret = allocate_resource(&ioport_resource, res, num, min, ~0UL, 0,
645 pcmcia_align, &data);
655 int find_mem_region(u_long *base, u_long num, u_long align,
656 int low, char *name, struct pcmcia_socket *s)
658 struct resource *res = make_resource(0, num, IORESOURCE_MEM, name);
659 struct pcmcia_align_data data;
660 unsigned long min, max;
663 low = low || !(s->features & SS_CAP_PAGE_REGS);
665 data.mask = align - 1;
666 data.offset = *base & data.mask;
669 for (i = 0; i < 2; i++) {
672 min = *base < max ? *base : 0;
675 min = 0x100000UL + *base;
681 ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num,
683 pcmcia_align, &data);
686 ret = allocate_resource(&iomem_resource, res, num, min,
687 max, 0, pcmcia_align, &data);
702 /*======================================================================
704 This checks to see if an interrupt is available, with support
705 for interrupt sharing. We don't support reserving interrupts
706 yet. If the interrupt is available, we allocate it.
708 ======================================================================*/
710 #ifdef CONFIG_PCMCIA_PROBE
712 static irqreturn_t fake_irq(int i, void *d, struct pt_regs *r) { return IRQ_NONE; }
713 static inline int check_irq(int irq)
715 if (request_irq(irq, fake_irq, 0, "bogus", NULL) != 0)
721 int try_irq(u_int Attributes, int irq, int specific)
723 irq_info_t *info = &irq_table[irq];
727 if (info->Attributes & RES_ALLOCATED) {
728 switch (Attributes & IRQ_TYPE) {
729 case IRQ_TYPE_EXCLUSIVE:
733 if ((info->Attributes & RES_IRQ_TYPE)
734 != RES_IRQ_TYPE_TIME) {
738 if (Attributes & IRQ_FIRST_SHARED) {
739 ret = CS_BAD_ATTRIBUTE;
742 info->Attributes |= RES_IRQ_TYPE_TIME | RES_ALLOCATED;
745 case IRQ_TYPE_DYNAMIC_SHARING:
746 if ((info->Attributes & RES_IRQ_TYPE)
747 != RES_IRQ_TYPE_DYNAMIC) {
751 if (Attributes & IRQ_FIRST_SHARED) {
752 ret = CS_BAD_ATTRIBUTE;
755 info->Attributes |= RES_IRQ_TYPE_DYNAMIC | RES_ALLOCATED;
760 if ((info->Attributes & RES_RESERVED) && !specific) {
764 if (check_irq(irq) != 0) {
768 switch (Attributes & IRQ_TYPE) {
769 case IRQ_TYPE_EXCLUSIVE:
770 info->Attributes |= RES_ALLOCATED;
773 if (!(Attributes & IRQ_FIRST_SHARED)) {
774 ret = CS_BAD_ATTRIBUTE;
777 info->Attributes |= RES_IRQ_TYPE_TIME | RES_ALLOCATED;
778 info->time_share = 1;
780 case IRQ_TYPE_DYNAMIC_SHARING:
781 if (!(Attributes & IRQ_FIRST_SHARED)) {
782 ret = CS_BAD_ATTRIBUTE;
785 info->Attributes |= RES_IRQ_TYPE_DYNAMIC | RES_ALLOCATED;
797 /*====================================================================*/
799 #ifdef CONFIG_PCMCIA_PROBE
801 void undo_irq(u_int Attributes, int irq)
805 info = &irq_table[irq];
807 switch (Attributes & IRQ_TYPE) {
808 case IRQ_TYPE_EXCLUSIVE:
809 info->Attributes &= RES_RESERVED;
813 if (info->time_share == 0)
814 info->Attributes &= RES_RESERVED;
816 case IRQ_TYPE_DYNAMIC_SHARING:
818 if (info->dyn_share == 0)
819 info->Attributes &= RES_RESERVED;
827 /*======================================================================
829 The various adjust_* calls form the external interface to the
832 ======================================================================*/
834 static int adjust_memory(adjust_t *adj)
839 base = adj->resource.memory.Base;
840 num = adj->resource.memory.Size;
841 if ((num == 0) || (base+num-1 < base))
847 switch (adj->Action) {
848 case ADD_MANAGED_RESOURCE:
849 ret = add_interval(&mem_db, base, num);
851 case REMOVE_MANAGED_RESOURCE:
852 ret = sub_interval(&mem_db, base, num);
853 if (ret == CS_SUCCESS) {
854 struct pcmcia_socket *socket;
855 down_read(&pcmcia_socket_list_rwsem);
856 list_for_each_entry(socket, &pcmcia_socket_list, socket_list)
857 release_cis_mem(socket);
858 up_read(&pcmcia_socket_list_rwsem);
862 ret = CS_UNSUPPORTED_FUNCTION;
869 /*====================================================================*/
871 static int adjust_io(adjust_t *adj)
873 int base, num, ret = CS_SUCCESS;
875 base = adj->resource.io.BasePort;
876 num = adj->resource.io.NumPorts;
877 if ((base < 0) || (base > 0xffff))
879 if ((num <= 0) || (base+num > 0x10000) || (base+num <= base))
883 switch (adj->Action) {
884 case ADD_MANAGED_RESOURCE:
885 if (add_interval(&io_db, base, num) != 0) {
889 #ifdef CONFIG_PCMCIA_PROBE
891 do_io_probe(base, num);
894 case REMOVE_MANAGED_RESOURCE:
895 sub_interval(&io_db, base, num);
898 ret = CS_UNSUPPORTED_FUNCTION;
906 /*====================================================================*/
908 static int adjust_irq(adjust_t *adj)
910 int ret = CS_SUCCESS;
911 #ifdef CONFIG_PCMCIA_PROBE
915 irq = adj->resource.irq.IRQ;
916 if ((irq < 0) || (irq > 15))
918 info = &irq_table[irq];
921 switch (adj->Action) {
922 case ADD_MANAGED_RESOURCE:
923 if (info->Attributes & RES_REMOVED)
924 info->Attributes &= ~(RES_REMOVED|RES_ALLOCATED);
926 if (adj->Attributes & RES_ALLOCATED) {
930 if (adj->Attributes & RES_RESERVED)
931 info->Attributes |= RES_RESERVED;
933 info->Attributes &= ~RES_RESERVED;
935 case REMOVE_MANAGED_RESOURCE:
936 if (info->Attributes & RES_REMOVED) {
940 if (info->Attributes & RES_ALLOCATED) {
944 info->Attributes |= RES_ALLOCATED|RES_REMOVED;
945 info->Attributes &= ~RES_RESERVED;
948 ret = CS_UNSUPPORTED_FUNCTION;
956 /*====================================================================*/
958 int pcmcia_adjust_resource_info(client_handle_t handle, adjust_t *adj)
960 if (CHECK_HANDLE(handle))
961 return CS_BAD_HANDLE;
963 switch (adj->Resource) {
964 case RES_MEMORY_RANGE:
965 return adjust_memory(adj);
968 return adjust_io(adj);
971 return adjust_irq(adj);
974 return CS_UNSUPPORTED_FUNCTION;
977 /*====================================================================*/
979 void release_resource_db(void)
981 resource_map_t *p, *q;
983 for (p = mem_db.next; p != &mem_db; p = q) {
987 for (p = io_db.next; p != &io_db; p = q) {