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;
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) <= end)
577 * If we failed to find something suitable, ensure we fail.
580 res->start = res->end;
583 /*======================================================================
585 These find ranges of I/O ports or memory addresses that are not
586 currently allocated by other devices.
588 The 'align' field should reflect the number of bits of address
589 that need to be preserved from the initial value of *base. It
590 should be a power of two, greater than or equal to 'num'. A value
591 of 0 means that all bits of *base are significant. *base should
592 also be strictly less than 'align'.
594 ======================================================================*/
596 int find_io_region(ioaddr_t *base, ioaddr_t num, unsigned long align,
597 char *name, struct pcmcia_socket *s)
599 struct resource *res = make_resource(0, num, IORESOURCE_IO, name);
600 struct pcmcia_align_data data;
601 unsigned long min = *base;
607 data.mask = align - 1;
608 data.offset = *base & data.mask;
613 ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num, 1,
614 min, 0, pcmcia_align, &data);
619 ret = allocate_resource(&ioport_resource, res, num, min, ~0UL, 0,
620 pcmcia_align, &data);
632 int find_mem_region(u_long *base, u_long num, u_long align,
633 int low, char *name, struct pcmcia_socket *s)
635 struct resource *res = make_resource(0, num, IORESOURCE_MEM, name);
636 struct pcmcia_align_data data;
637 unsigned long min, max;
640 low = low || !(s->features & SS_CAP_PAGE_REGS);
642 data.mask = align - 1;
643 data.offset = *base & data.mask;
646 for (i = 0; i < 2; i++) {
649 min = *base < max ? *base : 0;
652 min = 0x100000UL + *base;
657 ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num,
659 pcmcia_align, &data);
664 ret = allocate_resource(&iomem_resource, res, num, min,
665 max, 0, pcmcia_align, &data);
681 /*======================================================================
683 This checks to see if an interrupt is available, with support
684 for interrupt sharing. We don't support reserving interrupts
685 yet. If the interrupt is available, we allocate it.
687 ======================================================================*/
689 #ifdef CONFIG_PCMCIA_PROBE
691 static irqreturn_t fake_irq(int i, void *d, struct pt_regs *r) { return IRQ_NONE; }
692 static inline int check_irq(int irq)
694 if (request_irq(irq, fake_irq, 0, "bogus", NULL) != 0)
700 int try_irq(u_int Attributes, int irq, int specific)
702 irq_info_t *info = &irq_table[irq];
706 if (info->Attributes & RES_ALLOCATED) {
707 switch (Attributes & IRQ_TYPE) {
708 case IRQ_TYPE_EXCLUSIVE:
712 if ((info->Attributes & RES_IRQ_TYPE)
713 != RES_IRQ_TYPE_TIME) {
717 if (Attributes & IRQ_FIRST_SHARED) {
718 ret = CS_BAD_ATTRIBUTE;
721 info->Attributes |= RES_IRQ_TYPE_TIME | RES_ALLOCATED;
724 case IRQ_TYPE_DYNAMIC_SHARING:
725 if ((info->Attributes & RES_IRQ_TYPE)
726 != RES_IRQ_TYPE_DYNAMIC) {
730 if (Attributes & IRQ_FIRST_SHARED) {
731 ret = CS_BAD_ATTRIBUTE;
734 info->Attributes |= RES_IRQ_TYPE_DYNAMIC | RES_ALLOCATED;
739 if ((info->Attributes & RES_RESERVED) && !specific) {
743 if (check_irq(irq) != 0) {
747 switch (Attributes & IRQ_TYPE) {
748 case IRQ_TYPE_EXCLUSIVE:
749 info->Attributes |= RES_ALLOCATED;
752 if (!(Attributes & IRQ_FIRST_SHARED)) {
753 ret = CS_BAD_ATTRIBUTE;
756 info->Attributes |= RES_IRQ_TYPE_TIME | RES_ALLOCATED;
757 info->time_share = 1;
759 case IRQ_TYPE_DYNAMIC_SHARING:
760 if (!(Attributes & IRQ_FIRST_SHARED)) {
761 ret = CS_BAD_ATTRIBUTE;
764 info->Attributes |= RES_IRQ_TYPE_DYNAMIC | RES_ALLOCATED;
776 /*====================================================================*/
778 #ifdef CONFIG_PCMCIA_PROBE
780 void undo_irq(u_int Attributes, int irq)
784 info = &irq_table[irq];
786 switch (Attributes & IRQ_TYPE) {
787 case IRQ_TYPE_EXCLUSIVE:
788 info->Attributes &= RES_RESERVED;
792 if (info->time_share == 0)
793 info->Attributes &= RES_RESERVED;
795 case IRQ_TYPE_DYNAMIC_SHARING:
797 if (info->dyn_share == 0)
798 info->Attributes &= RES_RESERVED;
806 /*======================================================================
808 The various adjust_* calls form the external interface to the
811 ======================================================================*/
813 static int adjust_memory(adjust_t *adj)
818 base = adj->resource.memory.Base;
819 num = adj->resource.memory.Size;
820 if ((num == 0) || (base+num-1 < base))
826 switch (adj->Action) {
827 case ADD_MANAGED_RESOURCE:
828 ret = add_interval(&mem_db, base, num);
830 case REMOVE_MANAGED_RESOURCE:
831 ret = sub_interval(&mem_db, base, num);
832 if (ret == CS_SUCCESS) {
833 struct pcmcia_socket *socket;
834 down_read(&pcmcia_socket_list_rwsem);
835 list_for_each_entry(socket, &pcmcia_socket_list, socket_list)
836 release_cis_mem(socket);
837 up_read(&pcmcia_socket_list_rwsem);
841 ret = CS_UNSUPPORTED_FUNCTION;
848 /*====================================================================*/
850 static int adjust_io(adjust_t *adj)
852 int base, num, ret = CS_SUCCESS;
854 base = adj->resource.io.BasePort;
855 num = adj->resource.io.NumPorts;
856 if ((base < 0) || (base > 0xffff))
858 if ((num <= 0) || (base+num > 0x10000) || (base+num <= base))
862 switch (adj->Action) {
863 case ADD_MANAGED_RESOURCE:
864 if (add_interval(&io_db, base, num) != 0) {
868 #ifdef CONFIG_PCMCIA_PROBE
870 do_io_probe(base, num);
873 case REMOVE_MANAGED_RESOURCE:
874 sub_interval(&io_db, base, num);
877 ret = CS_UNSUPPORTED_FUNCTION;
885 /*====================================================================*/
887 static int adjust_irq(adjust_t *adj)
889 int ret = CS_SUCCESS;
890 #ifdef CONFIG_PCMCIA_PROBE
894 irq = adj->resource.irq.IRQ;
895 if ((irq < 0) || (irq > 15))
897 info = &irq_table[irq];
900 switch (adj->Action) {
901 case ADD_MANAGED_RESOURCE:
902 if (info->Attributes & RES_REMOVED)
903 info->Attributes &= ~(RES_REMOVED|RES_ALLOCATED);
905 if (adj->Attributes & RES_ALLOCATED) {
909 if (adj->Attributes & RES_RESERVED)
910 info->Attributes |= RES_RESERVED;
912 info->Attributes &= ~RES_RESERVED;
914 case REMOVE_MANAGED_RESOURCE:
915 if (info->Attributes & RES_REMOVED) {
919 if (info->Attributes & RES_ALLOCATED) {
923 info->Attributes |= RES_ALLOCATED|RES_REMOVED;
924 info->Attributes &= ~RES_RESERVED;
927 ret = CS_UNSUPPORTED_FUNCTION;
935 /*====================================================================*/
937 int pcmcia_adjust_resource_info(client_handle_t handle, adjust_t *adj)
939 if (CHECK_HANDLE(handle))
940 return CS_BAD_HANDLE;
942 switch (adj->Resource) {
943 case RES_MEMORY_RANGE:
944 return adjust_memory(adj);
947 return adjust_io(adj);
950 return adjust_irq(adj);
953 return CS_UNSUPPORTED_FUNCTION;
956 /*====================================================================*/
958 void release_resource_db(void)
960 resource_map_t *p, *q;
962 for (p = mem_db.next; p != &mem_db; p = q) {
966 for (p = io_db.next; p != &io_db; p = q) {