2 * rsrc_nonstatic.c -- Resource management routines for !SS_CAP_STATIC_MAP sockets
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
8 * The initial developer of the original code is David A. Hinds
9 * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
10 * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
12 * (C) 1999 David A. Hinds
15 #include <linux/module.h>
16 #include <linux/moduleparam.h>
17 #include <linux/init.h>
18 #include <linux/interrupt.h>
19 #include <linux/kernel.h>
20 #include <linux/errno.h>
21 #include <linux/types.h>
22 #include <linux/slab.h>
23 #include <linux/ioport.h>
24 #include <linux/timer.h>
25 #include <linux/pci.h>
26 #include <linux/device.h>
31 #include <pcmcia/cs_types.h>
32 #include <pcmcia/ss.h>
33 #include <pcmcia/cs.h>
34 #include <pcmcia/cistpl.h>
35 #include "cs_internal.h"
37 MODULE_AUTHOR("David A. Hinds, Dominik Brodowski");
38 MODULE_LICENSE("GPL");
40 /* Parameters that can be set with 'insmod' */
42 #define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0444)
44 INT_MODULE_PARM(probe_mem, 1); /* memory probe? */
45 #ifdef CONFIG_PCMCIA_PROBE
46 INT_MODULE_PARM(probe_io, 1); /* IO port probe? */
47 INT_MODULE_PARM(mem_limit, 0x10000);
50 /* for io_db and mem_db */
53 struct resource_map *next;
57 struct resource_map mem_db;
58 struct resource_map mem_db_valid;
59 struct resource_map io_db;
62 #define MEM_PROBE_LOW (1 << 0)
63 #define MEM_PROBE_HIGH (1 << 1)
66 /*======================================================================
68 Linux resource management extensions
70 ======================================================================*/
72 static struct resource *
73 make_resource(resource_size_t b, resource_size_t n, int flags, const char *name)
75 struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL);
86 static struct resource *
87 claim_region(struct pcmcia_socket *s, resource_size_t base,
88 resource_size_t size, int type, char *name)
90 struct resource *res, *parent;
92 parent = type & IORESOURCE_MEM ? &iomem_resource : &ioport_resource;
93 res = make_resource(base, size, type | IORESOURCE_BUSY, name);
98 parent = pci_find_parent_resource(s->cb_dev, res);
100 if (!parent || request_resource(parent, res)) {
108 static void free_region(struct resource *res)
111 release_resource(res);
116 /*======================================================================
118 These manage the internal databases of available resources.
120 ======================================================================*/
122 static int add_interval(struct resource_map *map, u_long base, u_long num)
124 struct resource_map *p, *q;
126 for (p = map; ; p = p->next) {
127 if ((p != map) && (p->base+p->num >= base)) {
128 p->num = max(num + base - p->base, p->num);
131 if ((p->next == map) || (p->next->base > base+num-1))
134 q = kmalloc(sizeof(struct resource_map), GFP_KERNEL);
136 printk(KERN_WARNING "out of memory to update resources\n");
139 q->base = base; q->num = num;
140 q->next = p->next; p->next = q;
144 /*====================================================================*/
146 static int sub_interval(struct resource_map *map, u_long base, u_long num)
148 struct resource_map *p, *q;
150 for (p = map; ; p = q) {
154 if ((q->base+q->num > base) && (base+num > q->base)) {
155 if (q->base >= base) {
156 if (q->base+q->num <= base+num) {
157 /* Delete whole block */
160 /* don't advance the pointer yet */
163 /* Cut off bit from the front */
164 q->num = q->base + q->num - base - num;
165 q->base = base + num;
167 } else if (q->base+q->num <= base+num) {
168 /* Cut off bit from the end */
169 q->num = base - q->base;
171 /* Split the block into two pieces */
172 p = kmalloc(sizeof(struct resource_map),
175 printk(KERN_WARNING "out of memory to update resources\n");
179 p->num = q->base+q->num - p->base;
180 q->num = base - q->base;
181 p->next = q->next ; q->next = p;
188 /*======================================================================
190 These routines examine a region of IO or memory addresses to
191 determine what ranges might be genuinely available.
193 ======================================================================*/
195 #ifdef CONFIG_PCMCIA_PROBE
196 static void do_io_probe(struct pcmcia_socket *s, unsigned int base,
199 struct resource *res;
200 struct socket_data *s_data = s->resource_data;
201 unsigned int i, j, bad;
203 u_char *b, hole, most;
205 dev_printk(KERN_INFO, &s->dev, "cs: IO port probe %#x-%#x:",
208 /* First, what does a floating port look like? */
209 b = kzalloc(256, GFP_KERNEL);
212 dev_printk(KERN_ERR, &s->dev,
213 "do_io_probe: unable to kmalloc 256 bytes");
216 for (i = base, most = 0; i < base+num; i += 8) {
217 res = claim_region(NULL, i, 8, IORESOURCE_IO, "PCMCIA ioprobe");
221 for (j = 1; j < 8; j++)
222 if (inb(i+j) != hole)
225 if ((j == 8) && (++b[hole] > b[most]))
233 for (i = base; i < base+num; i += 8) {
234 res = claim_region(NULL, i, 8, IORESOURCE_IO, "PCMCIA ioprobe");
237 for (j = 0; j < 8; j++)
238 if (inb(i+j) != most)
243 printk(" excluding");
248 sub_interval(&s_data->io_db, bad, i-bad);
249 printk(" %#x-%#x", bad, i-1);
255 if ((num > 16) && (bad == base) && (i == base+num)) {
256 printk(" nothing: probe failed.\n");
259 sub_interval(&s_data->io_db, bad, i-bad);
260 printk(" %#x-%#x", bad, i-1);
264 printk(any ? "\n" : " clean.\n");
268 /*======================================================================*/
271 * readable() - iomem validation function for cards with a valid CIS
273 static int readable(struct pcmcia_socket *s, struct resource *res,
279 dev_dbg(&s->dev, "fake CIS is being used: can't validate mem\n");
283 s->cis_mem.res = res;
284 s->cis_virt = ioremap(res->start, s->map_size);
286 mutex_unlock(&s->ops_mutex);
287 /* as we're only called from pcmcia.c, we're safe */
288 if (s->callback->validate)
289 ret = s->callback->validate(s, count);
290 /* invalidate mapping */
291 mutex_lock(&s->ops_mutex);
292 iounmap(s->cis_virt);
295 s->cis_mem.res = NULL;
296 if ((ret) || (*count == 0))
302 * checksum() - iomem validation function for simple memory cards
304 static int checksum(struct pcmcia_socket *s, struct resource *res,
308 int i, a = 0, b = -1, d;
311 virt = ioremap(res->start, s->map_size);
314 map.flags = MAP_ACTIVE;
318 s->ops->set_mem_map(s, &map);
320 /* Don't bother checking every word... */
321 for (i = 0; i < s->map_size; i += 44) {
328 s->ops->set_mem_map(s, &map);
342 * do_validate_mem() - low level validate a memory region for PCMCIA use
343 * @s: PCMCIA socket to validate
344 * @base: start address of resource to check
345 * @size: size of resource to check
346 * @validate: validation function to use
348 * do_validate_mem() splits up the memory region which is to be checked
349 * into two parts. Both are passed to the @validate() function. If
350 * @validate() returns non-zero, or the value parameter to @validate()
351 * is zero, or the value parameter is different between both calls,
352 * the check fails, and -EINVAL is returned. Else, 0 is returned.
354 static int do_validate_mem(struct pcmcia_socket *s,
355 unsigned long base, unsigned long size,
356 int validate (struct pcmcia_socket *s,
357 struct resource *res,
358 unsigned int *value))
360 struct socket_data *s_data = s->resource_data;
361 struct resource *res1, *res2;
362 unsigned int info1 = 1, info2 = 1;
365 res1 = claim_region(s, base, size/2, IORESOURCE_MEM, "PCMCIA memprobe");
366 res2 = claim_region(s, base + size/2, size/2, IORESOURCE_MEM,
372 ret = validate(s, res1, &info1);
373 ret += validate(s, res2, &info2);
380 dev_dbg(&s->dev, "cs: memory probe 0x%06lx-0x%06lx: %p %p %u %u %u",
381 base, base+size-1, res1, res2, ret, info1, info2);
383 if ((ret) || (info1 != info2) || (info1 == 0))
386 if (validate && !s->fake_cis) {
387 /* move it to the validated data set */
388 add_interval(&s_data->mem_db_valid, base, size);
389 sub_interval(&s_data->mem_db, base, size);
397 * do_mem_probe() - validate a memory region for PCMCIA use
398 * @s: PCMCIA socket to validate
399 * @base: start address of resource to check
400 * @num: size of resource to check
401 * @validate: validation function to use
402 * @fallback: validation function to use if validate fails
404 * do_mem_probe() checks a memory region for use by the PCMCIA subsystem.
405 * To do so, the area is split up into sensible parts, and then passed
406 * into the @validate() function. Only if @validate() and @fallback() fail,
407 * the area is marked as unavaibale for use by the PCMCIA subsystem. The
408 * function returns the size of the usable memory area.
410 static int do_mem_probe(struct pcmcia_socket *s, u_long base, u_long num,
411 int validate (struct pcmcia_socket *s,
412 struct resource *res,
413 unsigned int *value),
414 int fallback (struct pcmcia_socket *s,
415 struct resource *res,
416 unsigned int *value))
418 struct socket_data *s_data = s->resource_data;
419 u_long i, j, bad, fail, step;
421 dev_printk(KERN_INFO, &s->dev, "cs: memory probe 0x%06lx-0x%06lx:",
424 step = (num < 0x20000) ? 0x2000 : ((num>>4) & ~0x1fff);
425 /* don't allow too large steps */
428 /* cis_readable wants to map 2x map_size */
429 if (step < 2 * s->map_size)
430 step = 2 * s->map_size;
431 for (i = j = base; i < base+num; i = j + step) {
433 for (j = i; j < base+num; j += step) {
434 if (!do_validate_mem(s, j, step, validate))
437 fail = ((i == base) && (j == base+num));
439 if ((fail) && (fallback)) {
440 for (j = i; j < base+num; j += step)
441 if (!do_validate_mem(s, j, step, fallback))
446 printk(" excluding");
447 printk(" %#05lx-%#05lx", i, j-1);
448 sub_interval(&s_data->mem_db, i, j-i);
452 printk(bad ? "\n" : " clean.\n");
457 #ifdef CONFIG_PCMCIA_PROBE
460 * inv_probe() - top-to-bottom search for one usuable high memory area
461 * @s: PCMCIA socket to validate
462 * @m: resource_map to check
464 static u_long inv_probe(struct resource_map *m, struct pcmcia_socket *s)
466 struct socket_data *s_data = s->resource_data;
468 if (m == &s_data->mem_db)
470 ok = inv_probe(m->next, s);
472 if (m->base >= 0x100000)
473 sub_interval(&s_data->mem_db, m->base, m->num);
476 if (m->base < 0x100000)
478 return do_mem_probe(s, m->base, m->num, readable, checksum);
482 * validate_mem() - memory probe function
483 * @s: PCMCIA socket to validate
484 * @probe_mask: MEM_PROBE_LOW | MEM_PROBE_HIGH
486 * The memory probe. If the memory list includes a 64K-aligned block
487 * below 1MB, we probe in 64K chunks, and as soon as we accumulate at
488 * least mem_limit free space, we quit. Returns 0 on usuable ports.
490 static int validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
492 struct resource_map *m, mm;
493 static unsigned char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 };
494 unsigned long b, i, ok = 0;
495 struct socket_data *s_data = s->resource_data;
497 /* We do up to four passes through the list */
498 if (probe_mask & MEM_PROBE_HIGH) {
499 if (inv_probe(s_data->mem_db.next, s) > 0)
501 if (s_data->mem_db_valid.next != &s_data->mem_db_valid)
503 dev_printk(KERN_NOTICE, &s->dev,
504 "cs: warning: no high memory space available!\n");
508 for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) {
510 /* Only probe < 1 MB */
511 if (mm.base >= 0x100000)
513 if ((mm.base | mm.num) & 0xffff) {
514 ok += do_mem_probe(s, mm.base, mm.num, readable,
518 /* Special probe for 64K-aligned block */
519 for (i = 0; i < 4; i++) {
521 if ((b >= mm.base) && (b+0x10000 <= mm.base+mm.num)) {
523 sub_interval(&s_data->mem_db, b, 0x10000);
525 ok += do_mem_probe(s, b, 0x10000,
537 #else /* CONFIG_PCMCIA_PROBE */
540 * validate_mem() - memory probe function
541 * @s: PCMCIA socket to validate
542 * @probe_mask: ignored
544 * Returns 0 on usuable ports.
546 static int validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
548 struct resource_map *m, mm;
549 struct socket_data *s_data = s->resource_data;
550 unsigned long ok = 0;
552 for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) {
554 ok += do_mem_probe(s, mm.base, mm.num, readable, checksum);
561 #endif /* CONFIG_PCMCIA_PROBE */
565 * pcmcia_nonstatic_validate_mem() - try to validate iomem for PCMCIA use
566 * @s: PCMCIA socket to validate
568 * This is tricky... when we set up CIS memory, we try to validate
569 * the memory window space allocations.
571 * Locking note: Must be called with skt_mutex held!
573 static int pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s)
575 struct socket_data *s_data = s->resource_data;
576 unsigned int probe_mask = MEM_PROBE_LOW;
579 if (!probe_mem || !(s->state & SOCKET_PRESENT))
582 if (s->features & SS_CAP_PAGE_REGS)
583 probe_mask = MEM_PROBE_HIGH;
585 ret = validate_mem(s, probe_mask);
587 if (s_data->mem_db_valid.next != &s_data->mem_db_valid)
593 struct pcmcia_align_data {
595 unsigned long offset;
596 struct resource_map *map;
600 pcmcia_common_align(void *align_data, struct resource *res,
601 resource_size_t size, resource_size_t align)
603 struct pcmcia_align_data *data = align_data;
604 resource_size_t start;
606 * Ensure that we have the correct start address
608 start = (res->start & ~data->mask) + data->offset;
609 if (start < res->start)
610 start += data->mask + 1;
615 pcmcia_align(void *align_data, struct resource *res, resource_size_t size,
616 resource_size_t align)
618 struct pcmcia_align_data *data = align_data;
619 struct resource_map *m;
621 pcmcia_common_align(data, res, size, align);
623 for (m = data->map->next; m != data->map; m = m->next) {
624 unsigned long start = m->base;
625 unsigned long end = m->base + m->num - 1;
628 * If the lower resources are not available, try aligning
629 * to this entry of the resource database to see if it'll
632 if (res->start < start) {
634 pcmcia_common_align(data, res, size, align);
638 * If we're above the area which was passed in, there's
639 * no point proceeding.
641 if (res->start >= res->end)
644 if ((res->start + size - 1) <= end)
649 * If we failed to find something suitable, ensure we fail.
652 res->start = res->end;
656 * Adjust an existing IO region allocation, but making sure that we don't
657 * encroach outside the resources which the user supplied.
659 static int nonstatic_adjust_io_region(struct resource *res, unsigned long r_start,
660 unsigned long r_end, struct pcmcia_socket *s)
662 struct resource_map *m;
663 struct socket_data *s_data = s->resource_data;
666 for (m = s_data->io_db.next; m != &s_data->io_db; m = m->next) {
667 unsigned long start = m->base;
668 unsigned long end = m->base + m->num - 1;
670 if (start > r_start || r_end > end)
673 ret = adjust_resource(res, r_start, r_end - r_start + 1);
680 /*======================================================================
682 These find ranges of I/O ports or memory addresses that are not
683 currently allocated by other devices.
685 The 'align' field should reflect the number of bits of address
686 that need to be preserved from the initial value of *base. It
687 should be a power of two, greater than or equal to 'num'. A value
688 of 0 means that all bits of *base are significant. *base should
689 also be strictly less than 'align'.
691 ======================================================================*/
693 static struct resource *nonstatic_find_io_region(unsigned long base, int num,
694 unsigned long align, struct pcmcia_socket *s)
696 struct resource *res = make_resource(0, num, IORESOURCE_IO, dev_name(&s->dev));
697 struct socket_data *s_data = s->resource_data;
698 struct pcmcia_align_data data;
699 unsigned long min = base;
705 data.mask = align - 1;
706 data.offset = base & data.mask;
707 data.map = &s_data->io_db;
711 ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num, 1,
712 min, 0, pcmcia_align, &data);
715 ret = allocate_resource(&ioport_resource, res, num, min, ~0UL,
716 1, pcmcia_align, &data);
725 static struct resource *nonstatic_find_mem_region(u_long base, u_long num,
726 u_long align, int low, struct pcmcia_socket *s)
728 struct resource *res = make_resource(0, num, IORESOURCE_MEM, dev_name(&s->dev));
729 struct socket_data *s_data = s->resource_data;
730 struct pcmcia_align_data data;
731 unsigned long min, max;
734 low = low || !(s->features & SS_CAP_PAGE_REGS);
736 data.mask = align - 1;
737 data.offset = base & data.mask;
739 for (i = 0; i < 2; i++) {
740 data.map = &s_data->mem_db_valid;
743 min = base < max ? base : 0;
746 min = 0x100000UL + base;
749 for (j = 0; j < 2; j++) {
752 ret = pci_bus_alloc_resource(s->cb_dev->bus,
754 pcmcia_align, &data);
758 ret = allocate_resource(&iomem_resource,
759 res, num, min, max, 1,
760 pcmcia_align, &data);
764 data.map = &s_data->mem_db;
779 static int adjust_memory(struct pcmcia_socket *s, unsigned int action, unsigned long start, unsigned long end)
781 struct socket_data *data = s->resource_data;
782 unsigned long size = end - start + 1;
789 case ADD_MANAGED_RESOURCE:
790 ret = add_interval(&data->mem_db, start, size);
792 do_mem_probe(s, start, size, NULL, NULL);
794 case REMOVE_MANAGED_RESOURCE:
795 ret = sub_interval(&data->mem_db, start, size);
805 static int adjust_io(struct pcmcia_socket *s, unsigned int action, unsigned long start, unsigned long end)
807 struct socket_data *data = s->resource_data;
808 unsigned long size = end - start + 1;
814 if (end > IO_SPACE_LIMIT)
818 case ADD_MANAGED_RESOURCE:
819 if (add_interval(&data->io_db, start, size) != 0) {
823 #ifdef CONFIG_PCMCIA_PROBE
825 do_io_probe(s, start, size);
828 case REMOVE_MANAGED_RESOURCE:
829 sub_interval(&data->io_db, start, size);
841 static int nonstatic_autoadd_resources(struct pcmcia_socket *s)
843 struct resource *res;
846 if (!s->cb_dev || !s->cb_dev->bus)
849 #if defined(CONFIG_X86)
850 /* If this is the root bus, the risk of hitting
851 * some strange system devices which aren't protected
852 * by either ACPI resource tables or properly requested
853 * resources is too big. Therefore, don't do auto-adding
854 * of resources at the moment.
856 if (s->cb_dev->bus->number == 0)
860 for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) {
861 res = s->cb_dev->bus->resource[i];
865 if (res->flags & IORESOURCE_IO) {
866 if (res == &ioport_resource)
868 dev_printk(KERN_INFO, &s->cb_dev->dev,
869 "pcmcia: parent PCI bridge I/O "
870 "window: 0x%llx - 0x%llx\n",
871 (unsigned long long)res->start,
872 (unsigned long long)res->end);
873 if (!adjust_io(s, ADD_MANAGED_RESOURCE, res->start, res->end))
874 done |= IORESOURCE_IO;
878 if (res->flags & IORESOURCE_MEM) {
879 if (res == &iomem_resource)
881 dev_printk(KERN_INFO, &s->cb_dev->dev,
882 "pcmcia: parent PCI bridge Memory "
883 "window: 0x%llx - 0x%llx\n",
884 (unsigned long long)res->start,
885 (unsigned long long)res->end);
886 if (!adjust_memory(s, ADD_MANAGED_RESOURCE, res->start, res->end))
887 done |= IORESOURCE_MEM;
891 /* if we got at least one of IO, and one of MEM, we can be glad and
892 * activate the PCMCIA subsystem */
893 if (done == (IORESOURCE_MEM | IORESOURCE_IO))
894 s->resource_setup_done = 1;
901 static inline int nonstatic_autoadd_resources(struct pcmcia_socket *s)
909 static int nonstatic_init(struct pcmcia_socket *s)
911 struct socket_data *data;
913 data = kzalloc(sizeof(struct socket_data), GFP_KERNEL);
917 data->mem_db.next = &data->mem_db;
918 data->mem_db_valid.next = &data->mem_db_valid;
919 data->io_db.next = &data->io_db;
921 s->resource_data = (void *) data;
923 nonstatic_autoadd_resources(s);
928 static void nonstatic_release_resource_db(struct pcmcia_socket *s)
930 struct socket_data *data = s->resource_data;
931 struct resource_map *p, *q;
933 for (p = data->mem_db_valid.next; p != &data->mem_db_valid; p = q) {
937 for (p = data->mem_db.next; p != &data->mem_db; p = q) {
941 for (p = data->io_db.next; p != &data->io_db; p = q) {
948 struct pccard_resource_ops pccard_nonstatic_ops = {
949 .validate_mem = pcmcia_nonstatic_validate_mem,
950 .adjust_io_region = nonstatic_adjust_io_region,
951 .find_io = nonstatic_find_io_region,
952 .find_mem = nonstatic_find_mem_region,
954 .add_mem = adjust_memory,
955 .init = nonstatic_init,
956 .exit = nonstatic_release_resource_db,
958 EXPORT_SYMBOL(pccard_nonstatic_ops);
961 /* sysfs interface to the resource database */
963 static ssize_t show_io_db(struct device *dev,
964 struct device_attribute *attr, char *buf)
966 struct pcmcia_socket *s = dev_get_drvdata(dev);
967 struct socket_data *data;
968 struct resource_map *p;
971 mutex_lock(&s->ops_mutex);
972 data = s->resource_data;
974 for (p = data->io_db.next; p != &data->io_db; p = p->next) {
975 if (ret > (PAGE_SIZE - 10))
977 ret += snprintf(&buf[ret], (PAGE_SIZE - ret - 1),
978 "0x%08lx - 0x%08lx\n",
979 ((unsigned long) p->base),
980 ((unsigned long) p->base + p->num - 1));
983 mutex_unlock(&s->ops_mutex);
987 static ssize_t store_io_db(struct device *dev,
988 struct device_attribute *attr,
989 const char *buf, size_t count)
991 struct pcmcia_socket *s = dev_get_drvdata(dev);
992 unsigned long start_addr, end_addr;
993 unsigned int add = ADD_MANAGED_RESOURCE;
996 ret = sscanf(buf, "+ 0x%lx - 0x%lx", &start_addr, &end_addr);
998 ret = sscanf(buf, "- 0x%lx - 0x%lx", &start_addr, &end_addr);
999 add = REMOVE_MANAGED_RESOURCE;
1001 ret = sscanf(buf, "0x%lx - 0x%lx", &start_addr,
1003 add = ADD_MANAGED_RESOURCE;
1008 if (end_addr < start_addr)
1011 mutex_lock(&s->ops_mutex);
1012 ret = adjust_io(s, add, start_addr, end_addr);
1014 s->resource_setup_new = 1;
1015 mutex_unlock(&s->ops_mutex);
1017 return ret ? ret : count;
1019 static DEVICE_ATTR(available_resources_io, 0600, show_io_db, store_io_db);
1021 static ssize_t show_mem_db(struct device *dev,
1022 struct device_attribute *attr, char *buf)
1024 struct pcmcia_socket *s = dev_get_drvdata(dev);
1025 struct socket_data *data;
1026 struct resource_map *p;
1029 mutex_lock(&s->ops_mutex);
1030 data = s->resource_data;
1032 for (p = data->mem_db_valid.next; p != &data->mem_db_valid;
1034 if (ret > (PAGE_SIZE - 10))
1036 ret += snprintf(&buf[ret], (PAGE_SIZE - ret - 1),
1037 "0x%08lx - 0x%08lx\n",
1038 ((unsigned long) p->base),
1039 ((unsigned long) p->base + p->num - 1));
1042 for (p = data->mem_db.next; p != &data->mem_db; p = p->next) {
1043 if (ret > (PAGE_SIZE - 10))
1045 ret += snprintf(&buf[ret], (PAGE_SIZE - ret - 1),
1046 "0x%08lx - 0x%08lx\n",
1047 ((unsigned long) p->base),
1048 ((unsigned long) p->base + p->num - 1));
1051 mutex_unlock(&s->ops_mutex);
1055 static ssize_t store_mem_db(struct device *dev,
1056 struct device_attribute *attr,
1057 const char *buf, size_t count)
1059 struct pcmcia_socket *s = dev_get_drvdata(dev);
1060 unsigned long start_addr, end_addr;
1061 unsigned int add = ADD_MANAGED_RESOURCE;
1064 ret = sscanf(buf, "+ 0x%lx - 0x%lx", &start_addr, &end_addr);
1066 ret = sscanf(buf, "- 0x%lx - 0x%lx", &start_addr, &end_addr);
1067 add = REMOVE_MANAGED_RESOURCE;
1069 ret = sscanf(buf, "0x%lx - 0x%lx", &start_addr,
1071 add = ADD_MANAGED_RESOURCE;
1076 if (end_addr < start_addr)
1079 mutex_lock(&s->ops_mutex);
1080 ret = adjust_memory(s, add, start_addr, end_addr);
1082 s->resource_setup_new = 1;
1083 mutex_unlock(&s->ops_mutex);
1085 return ret ? ret : count;
1087 static DEVICE_ATTR(available_resources_mem, 0600, show_mem_db, store_mem_db);
1089 static struct attribute *pccard_rsrc_attributes[] = {
1090 &dev_attr_available_resources_io.attr,
1091 &dev_attr_available_resources_mem.attr,
1095 static const struct attribute_group rsrc_attributes = {
1096 .attrs = pccard_rsrc_attributes,
1099 static int __devinit pccard_sysfs_add_rsrc(struct device *dev,
1100 struct class_interface *class_intf)
1102 struct pcmcia_socket *s = dev_get_drvdata(dev);
1104 if (s->resource_ops != &pccard_nonstatic_ops)
1106 return sysfs_create_group(&dev->kobj, &rsrc_attributes);
1109 static void __devexit pccard_sysfs_remove_rsrc(struct device *dev,
1110 struct class_interface *class_intf)
1112 struct pcmcia_socket *s = dev_get_drvdata(dev);
1114 if (s->resource_ops != &pccard_nonstatic_ops)
1116 sysfs_remove_group(&dev->kobj, &rsrc_attributes);
1119 static struct class_interface pccard_rsrc_interface __refdata = {
1120 .class = &pcmcia_socket_class,
1121 .add_dev = &pccard_sysfs_add_rsrc,
1122 .remove_dev = __devexit_p(&pccard_sysfs_remove_rsrc),
1125 static int __init nonstatic_sysfs_init(void)
1127 return class_interface_register(&pccard_rsrc_interface);
1130 static void __exit nonstatic_sysfs_exit(void)
1132 class_interface_unregister(&pccard_rsrc_interface);
1135 module_init(nonstatic_sysfs_init);
1136 module_exit(nonstatic_sysfs_exit);