linux/drivers/pcmcia/rsrc_nonstatic.c
<<
>>
Prefs
   1/*
   2 * rsrc_nonstatic.c -- Resource management routines for !SS_CAP_STATIC_MAP sockets
   3 *
   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.
   7 *
   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.
  11 *
  12 * (C) 1999             David A. Hinds
  13 */
  14
  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>
  27
  28#include <asm/irq.h>
  29#include <asm/io.h>
  30
  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"
  36
  37MODULE_AUTHOR("David A. Hinds, Dominik Brodowski");
  38MODULE_LICENSE("GPL");
  39
  40/* Parameters that can be set with 'insmod' */
  41
  42#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0444)
  43
  44INT_MODULE_PARM(probe_mem,      1);             /* memory probe? */
  45#ifdef CONFIG_PCMCIA_PROBE
  46INT_MODULE_PARM(probe_io,       1);             /* IO port probe? */
  47INT_MODULE_PARM(mem_limit,      0x10000);
  48#endif
  49
  50/* for io_db and mem_db */
  51struct resource_map {
  52        u_long                  base, num;
  53        struct resource_map     *next;
  54};
  55
  56struct socket_data {
  57        struct resource_map             mem_db;
  58        struct resource_map             io_db;
  59        unsigned int                    rsrc_mem_probe;
  60};
  61
  62static DEFINE_MUTEX(rsrc_mutex);
  63#define MEM_PROBE_LOW   (1 << 0)
  64#define MEM_PROBE_HIGH  (1 << 1)
  65
  66
  67/*======================================================================
  68
  69    Linux resource management extensions
  70
  71======================================================================*/
  72
  73static struct resource *
  74make_resource(resource_size_t b, resource_size_t n, int flags, const char *name)
  75{
  76        struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL);
  77
  78        if (res) {
  79                res->name = name;
  80                res->start = b;
  81                res->end = b + n - 1;
  82                res->flags = flags;
  83        }
  84        return res;
  85}
  86
  87static struct resource *
  88claim_region(struct pcmcia_socket *s, resource_size_t base,
  89                resource_size_t size, int type, char *name)
  90{
  91        struct resource *res, *parent;
  92
  93        parent = type & IORESOURCE_MEM ? &iomem_resource : &ioport_resource;
  94        res = make_resource(base, size, type | IORESOURCE_BUSY, name);
  95
  96        if (res) {
  97#ifdef CONFIG_PCI
  98                if (s && s->cb_dev)
  99                        parent = pci_find_parent_resource(s->cb_dev, res);
 100#endif
 101                if (!parent || request_resource(parent, res)) {
 102                        kfree(res);
 103                        res = NULL;
 104                }
 105        }
 106        return res;
 107}
 108
 109static void free_region(struct resource *res)
 110{
 111        if (res) {
 112                release_resource(res);
 113                kfree(res);
 114        }
 115}
 116
 117/*======================================================================
 118
 119    These manage the internal databases of available resources.
 120
 121======================================================================*/
 122
 123static int add_interval(struct resource_map *map, u_long base, u_long num)
 124{
 125        struct resource_map *p, *q;
 126
 127        for (p = map; ; p = p->next) {
 128                if ((p != map) && (p->base+p->num-1 >= base))
 129                        return -1;
 130                if ((p->next == map) || (p->next->base > base+num-1))
 131                        break;
 132        }
 133        q = kmalloc(sizeof(struct resource_map), GFP_KERNEL);
 134        if (!q) {
 135                printk(KERN_WARNING "out of memory to update resources\n");
 136                return -ENOMEM;
 137        }
 138        q->base = base; q->num = num;
 139        q->next = p->next; p->next = q;
 140        return 0;
 141}
 142
 143/*====================================================================*/
 144
 145static int sub_interval(struct resource_map *map, u_long base, u_long num)
 146{
 147    struct resource_map *p, *q;
 148
 149    for (p = map; ; p = q) {
 150        q = p->next;
 151        if (q == map)
 152            break;
 153        if ((q->base+q->num > base) && (base+num > q->base)) {
 154            if (q->base >= base) {
 155                if (q->base+q->num <= base+num) {
 156                    /* Delete whole block */
 157                    p->next = q->next;
 158                    kfree(q);
 159                    /* don't advance the pointer yet */
 160                    q = p;
 161                } else {
 162                    /* Cut off bit from the front */
 163                    q->num = q->base + q->num - base - num;
 164                    q->base = base + num;
 165                }
 166            } else if (q->base+q->num <= base+num) {
 167                /* Cut off bit from the end */
 168                q->num = base - q->base;
 169            } else {
 170                /* Split the block into two pieces */
 171                p = kmalloc(sizeof(struct resource_map), GFP_KERNEL);
 172                if (!p) {
 173                    printk(KERN_WARNING "out of memory to update resources\n");
 174                    return -ENOMEM;
 175                }
 176                p->base = base+num;
 177                p->num = q->base+q->num - p->base;
 178                q->num = base - q->base;
 179                p->next = q->next ; q->next = p;
 180            }
 181        }
 182    }
 183    return 0;
 184}
 185
 186/*======================================================================
 187
 188    These routines examine a region of IO or memory addresses to
 189    determine what ranges might be genuinely available.
 190
 191======================================================================*/
 192
 193#ifdef CONFIG_PCMCIA_PROBE
 194static void do_io_probe(struct pcmcia_socket *s, unsigned int base,
 195                        unsigned int num)
 196{
 197    struct resource *res;
 198    struct socket_data *s_data = s->resource_data;
 199    unsigned int i, j, bad;
 200    int any;
 201    u_char *b, hole, most;
 202
 203    dev_printk(KERN_INFO, &s->dev, "cs: IO port probe %#x-%#x:",
 204               base, base+num-1);
 205
 206    /* First, what does a floating port look like? */
 207    b = kzalloc(256, GFP_KERNEL);
 208    if (!b) {
 209            printk("\n");
 210            dev_printk(KERN_ERR, &s->dev,
 211                   "do_io_probe: unable to kmalloc 256 bytes");
 212            return;
 213    }
 214    for (i = base, most = 0; i < base+num; i += 8) {
 215        res = claim_region(NULL, i, 8, IORESOURCE_IO, "PCMCIA IO probe");
 216        if (!res)
 217            continue;
 218        hole = inb(i);
 219        for (j = 1; j < 8; j++)
 220            if (inb(i+j) != hole) break;
 221        free_region(res);
 222        if ((j == 8) && (++b[hole] > b[most]))
 223            most = hole;
 224        if (b[most] == 127) break;
 225    }
 226    kfree(b);
 227
 228    bad = any = 0;
 229    for (i = base; i < base+num; i += 8) {
 230        res = claim_region(NULL, i, 8, IORESOURCE_IO, "PCMCIA IO probe");
 231        if (!res)
 232            continue;
 233        for (j = 0; j < 8; j++)
 234            if (inb(i+j) != most) break;
 235        free_region(res);
 236        if (j < 8) {
 237            if (!any)
 238                printk(" excluding");
 239            if (!bad)
 240                bad = any = i;
 241        } else {
 242            if (bad) {
 243                sub_interval(&s_data->io_db, bad, i-bad);
 244                printk(" %#x-%#x", bad, i-1);
 245                bad = 0;
 246            }
 247        }
 248    }
 249    if (bad) {
 250        if ((num > 16) && (bad == base) && (i == base+num)) {
 251            printk(" nothing: probe failed.\n");
 252            return;
 253        } else {
 254            sub_interval(&s_data->io_db, bad, i-bad);
 255            printk(" %#x-%#x", bad, i-1);
 256        }
 257    }
 258
 259    printk(any ? "\n" : " clean.\n");
 260}
 261#endif
 262
 263/*======================================================================
 264
 265    This is tricky... when we set up CIS memory, we try to validate
 266    the memory window space allocations.
 267
 268======================================================================*/
 269
 270/* Validation function for cards with a valid CIS */
 271static int readable(struct pcmcia_socket *s, struct resource *res,
 272                    unsigned int *count)
 273{
 274        int ret = -1;
 275
 276        s->cis_mem.res = res;
 277        s->cis_virt = ioremap(res->start, s->map_size);
 278        if (s->cis_virt) {
 279                ret = pccard_validate_cis(s, count);
 280                /* invalidate mapping and CIS cache */
 281                iounmap(s->cis_virt);
 282                s->cis_virt = NULL;
 283                destroy_cis_cache(s);
 284        }
 285        s->cis_mem.res = NULL;
 286        if ((ret != 0) || (*count == 0))
 287                return 0;
 288        return 1;
 289}
 290
 291/* Validation function for simple memory cards */
 292static int checksum(struct pcmcia_socket *s, struct resource *res)
 293{
 294        pccard_mem_map map;
 295        int i, a = 0, b = -1, d;
 296        void __iomem *virt;
 297
 298        virt = ioremap(res->start, s->map_size);
 299        if (virt) {
 300                map.map = 0;
 301                map.flags = MAP_ACTIVE;
 302                map.speed = 0;
 303                map.res = res;
 304                map.card_start = 0;
 305                s->ops->set_mem_map(s, &map);
 306
 307                /* Don't bother checking every word... */
 308                for (i = 0; i < s->map_size; i += 44) {
 309                        d = readl(virt+i);
 310                        a += d;
 311                        b &= d;
 312                }
 313
 314                map.flags = 0;
 315                s->ops->set_mem_map(s, &map);
 316
 317                iounmap(virt);
 318        }
 319
 320        return (b == -1) ? -1 : (a>>1);
 321}
 322
 323static int
 324cis_readable(struct pcmcia_socket *s, unsigned long base, unsigned long size)
 325{
 326        struct resource *res1, *res2;
 327        unsigned int info1, info2;
 328        int ret = 0;
 329
 330        res1 = claim_region(s, base, size/2, IORESOURCE_MEM, "cs memory probe");
 331        res2 = claim_region(s, base + size/2, size/2, IORESOURCE_MEM, "cs memory probe");
 332
 333        if (res1 && res2) {
 334                ret = readable(s, res1, &info1);
 335                ret += readable(s, res2, &info2);
 336        }
 337
 338        free_region(res2);
 339        free_region(res1);
 340
 341        return (ret == 2) && (info1 == info2);
 342}
 343
 344static int
 345checksum_match(struct pcmcia_socket *s, unsigned long base, unsigned long size)
 346{
 347        struct resource *res1, *res2;
 348        int a = -1, b = -1;
 349
 350        res1 = claim_region(s, base, size/2, IORESOURCE_MEM, "cs memory probe");
 351        res2 = claim_region(s, base + size/2, size/2, IORESOURCE_MEM, "cs memory probe");
 352
 353        if (res1 && res2) {
 354                a = checksum(s, res1);
 355                b = checksum(s, res2);
 356        }
 357
 358        free_region(res2);
 359        free_region(res1);
 360
 361        return (a == b) && (a >= 0);
 362}
 363
 364/*======================================================================
 365
 366    The memory probe.  If the memory list includes a 64K-aligned block
 367    below 1MB, we probe in 64K chunks, and as soon as we accumulate at
 368    least mem_limit free space, we quit.
 369
 370======================================================================*/
 371
 372static int do_mem_probe(u_long base, u_long num, struct pcmcia_socket *s)
 373{
 374    struct socket_data *s_data = s->resource_data;
 375    u_long i, j, bad, fail, step;
 376
 377    dev_printk(KERN_INFO, &s->dev, "cs: memory probe 0x%06lx-0x%06lx:",
 378               base, base+num-1);
 379    bad = fail = 0;
 380    step = (num < 0x20000) ? 0x2000 : ((num>>4) & ~0x1fff);
 381    /* don't allow too large steps */
 382    if (step > 0x800000)
 383        step = 0x800000;
 384    /* cis_readable wants to map 2x map_size */
 385    if (step < 2 * s->map_size)
 386        step = 2 * s->map_size;
 387    for (i = j = base; i < base+num; i = j + step) {
 388        if (!fail) {
 389            for (j = i; j < base+num; j += step) {
 390                if (cis_readable(s, j, step))
 391                    break;
 392            }
 393            fail = ((i == base) && (j == base+num));
 394        }
 395        if (fail) {
 396            for (j = i; j < base+num; j += 2*step)
 397                if (checksum_match(s, j, step) &&
 398                    checksum_match(s, j + step, step))
 399                    break;
 400        }
 401        if (i != j) {
 402            if (!bad) printk(" excluding");
 403            printk(" %#05lx-%#05lx", i, j-1);
 404            sub_interval(&s_data->mem_db, i, j-i);
 405            bad += j-i;
 406        }
 407    }
 408    printk(bad ? "\n" : " clean.\n");
 409    return (num - bad);
 410}
 411
 412#ifdef CONFIG_PCMCIA_PROBE
 413
 414static u_long inv_probe(struct resource_map *m, struct pcmcia_socket *s)
 415{
 416        struct socket_data *s_data = s->resource_data;
 417        u_long ok;
 418        if (m == &s_data->mem_db)
 419                return 0;
 420        ok = inv_probe(m->next, s);
 421        if (ok) {
 422                if (m->base >= 0x100000)
 423                        sub_interval(&s_data->mem_db, m->base, m->num);
 424                return ok;
 425        }
 426        if (m->base < 0x100000)
 427                return 0;
 428        return do_mem_probe(m->base, m->num, s);
 429}
 430
 431static int validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
 432{
 433        struct resource_map *m, mm;
 434        static unsigned char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 };
 435        unsigned long b, i, ok = 0;
 436        struct socket_data *s_data = s->resource_data;
 437
 438        /* We do up to four passes through the list */
 439        if (probe_mask & MEM_PROBE_HIGH) {
 440                if (inv_probe(s_data->mem_db.next, s) > 0)
 441                        return 0;
 442                dev_printk(KERN_NOTICE, &s->dev,
 443                           "cs: warning: no high memory space available!\n");
 444                return -ENODEV;
 445        }
 446
 447        for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) {
 448                mm = *m;
 449                /* Only probe < 1 MB */
 450                if (mm.base >= 0x100000)
 451                        continue;
 452                if ((mm.base | mm.num) & 0xffff) {
 453                        ok += do_mem_probe(mm.base, mm.num, s);
 454                        continue;
 455                }
 456                /* Special probe for 64K-aligned block */
 457                for (i = 0; i < 4; i++) {
 458                        b = order[i] << 12;
 459                        if ((b >= mm.base) && (b+0x10000 <= mm.base+mm.num)) {
 460                                if (ok >= mem_limit)
 461                                        sub_interval(&s_data->mem_db, b, 0x10000);
 462                                else
 463                                        ok += do_mem_probe(b, 0x10000, s);
 464                        }
 465                }
 466        }
 467
 468        if (ok > 0)
 469                return 0;
 470
 471        return -ENODEV;
 472}
 473
 474#else /* CONFIG_PCMCIA_PROBE */
 475
 476static int validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
 477{
 478        struct resource_map *m, mm;
 479        struct socket_data *s_data = s->resource_data;
 480        unsigned long ok = 0;
 481
 482        for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) {
 483                mm = *m;
 484                ok += do_mem_probe(mm.base, mm.num, s);
 485        }
 486        if (ok > 0)
 487                return 0;
 488        return -ENODEV;
 489}
 490
 491#endif /* CONFIG_PCMCIA_PROBE */
 492
 493
 494/*
 495 * Locking note: Must be called with skt_mutex held!
 496 */
 497static int pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s)
 498{
 499        struct socket_data *s_data = s->resource_data;
 500        unsigned int probe_mask = MEM_PROBE_LOW;
 501        int ret = 0;
 502
 503        if (!probe_mem)
 504                return 0;
 505
 506        mutex_lock(&rsrc_mutex);
 507
 508        if (s->features & SS_CAP_PAGE_REGS)
 509                probe_mask = MEM_PROBE_HIGH;
 510
 511        if (probe_mask & ~s_data->rsrc_mem_probe) {
 512                if (s->state & SOCKET_PRESENT)
 513                        ret = validate_mem(s, probe_mask);
 514                if (!ret)
 515                        s_data->rsrc_mem_probe |= probe_mask;
 516        }
 517
 518        mutex_unlock(&rsrc_mutex);
 519
 520        return ret;
 521}
 522
 523struct pcmcia_align_data {
 524        unsigned long   mask;
 525        unsigned long   offset;
 526        struct resource_map     *map;
 527};
 528
 529static void
 530pcmcia_common_align(void *align_data, struct resource *res,
 531                        resource_size_t size, resource_size_t align)
 532{
 533        struct pcmcia_align_data *data = align_data;
 534        resource_size_t start;
 535        /*
 536         * Ensure that we have the correct start address
 537         */
 538        start = (res->start & ~data->mask) + data->offset;
 539        if (start < res->start)
 540                start += data->mask + 1;
 541        res->start = start;
 542}
 543
 544static void
 545pcmcia_align(void *align_data, struct resource *res, resource_size_t size,
 546                resource_size_t align)
 547{
 548        struct pcmcia_align_data *data = align_data;
 549        struct resource_map *m;
 550
 551        pcmcia_common_align(data, res, size, align);
 552
 553        for (m = data->map->next; m != data->map; m = m->next) {
 554                unsigned long start = m->base;
 555                unsigned long end = m->base + m->num - 1;
 556
 557                /*
 558                 * If the lower resources are not available, try aligning
 559                 * to this entry of the resource database to see if it'll
 560                 * fit here.
 561                 */
 562                if (res->start < start) {
 563                        res->start = start;
 564                        pcmcia_common_align(data, res, size, align);
 565                }
 566
 567                /*
 568                 * If we're above the area which was passed in, there's
 569                 * no point proceeding.
 570                 */
 571                if (res->start >= res->end)
 572                        break;
 573
 574                if ((res->start + size - 1) <= end)
 575                        break;
 576        }
 577
 578        /*
 579         * If we failed to find something suitable, ensure we fail.
 580         */
 581        if (m == data->map)
 582                res->start = res->end;
 583}
 584
 585/*
 586 * Adjust an existing IO region allocation, but making sure that we don't
 587 * encroach outside the resources which the user supplied.
 588 */
 589static int nonstatic_adjust_io_region(struct resource *res, unsigned long r_start,
 590                                      unsigned long r_end, struct pcmcia_socket *s)
 591{
 592        struct resource_map *m;
 593        struct socket_data *s_data = s->resource_data;
 594        int ret = -ENOMEM;
 595
 596        mutex_lock(&rsrc_mutex);
 597        for (m = s_data->io_db.next; m != &s_data->io_db; m = m->next) {
 598                unsigned long start = m->base;
 599                unsigned long end = m->base + m->num - 1;
 600
 601                if (start > r_start || r_end > end)
 602                        continue;
 603
 604                ret = adjust_resource(res, r_start, r_end - r_start + 1);
 605                break;
 606        }
 607        mutex_unlock(&rsrc_mutex);
 608
 609        return ret;
 610}
 611
 612/*======================================================================
 613
 614    These find ranges of I/O ports or memory addresses that are not
 615    currently allocated by other devices.
 616
 617    The 'align' field should reflect the number of bits of address
 618    that need to be preserved from the initial value of *base.  It
 619    should be a power of two, greater than or equal to 'num'.  A value
 620    of 0 means that all bits of *base are significant.  *base should
 621    also be strictly less than 'align'.
 622
 623======================================================================*/
 624
 625static struct resource *nonstatic_find_io_region(unsigned long base, int num,
 626                   unsigned long align, struct pcmcia_socket *s)
 627{
 628        struct resource *res = make_resource(0, num, IORESOURCE_IO, dev_name(&s->dev));
 629        struct socket_data *s_data = s->resource_data;
 630        struct pcmcia_align_data data;
 631        unsigned long min = base;
 632        int ret;
 633
 634        if (align == 0)
 635                align = 0x10000;
 636
 637        data.mask = align - 1;
 638        data.offset = base & data.mask;
 639        data.map = &s_data->io_db;
 640
 641        mutex_lock(&rsrc_mutex);
 642#ifdef CONFIG_PCI
 643        if (s->cb_dev) {
 644                ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num, 1,
 645                                             min, 0, pcmcia_align, &data);
 646        } else
 647#endif
 648                ret = allocate_resource(&ioport_resource, res, num, min, ~0UL,
 649                                        1, pcmcia_align, &data);
 650        mutex_unlock(&rsrc_mutex);
 651
 652        if (ret != 0) {
 653                kfree(res);
 654                res = NULL;
 655        }
 656        return res;
 657}
 658
 659static struct resource * nonstatic_find_mem_region(u_long base, u_long num,
 660                u_long align, int low, struct pcmcia_socket *s)
 661{
 662        struct resource *res = make_resource(0, num, IORESOURCE_MEM, dev_name(&s->dev));
 663        struct socket_data *s_data = s->resource_data;
 664        struct pcmcia_align_data data;
 665        unsigned long min, max;
 666        int ret, i;
 667
 668        low = low || !(s->features & SS_CAP_PAGE_REGS);
 669
 670        data.mask = align - 1;
 671        data.offset = base & data.mask;
 672        data.map = &s_data->mem_db;
 673
 674        for (i = 0; i < 2; i++) {
 675                if (low) {
 676                        max = 0x100000UL;
 677                        min = base < max ? base : 0;
 678                } else {
 679                        max = ~0UL;
 680                        min = 0x100000UL + base;
 681                }
 682
 683                mutex_lock(&rsrc_mutex);
 684#ifdef CONFIG_PCI
 685                if (s->cb_dev) {
 686                        ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num,
 687                                                     1, min, 0,
 688                                                     pcmcia_align, &data);
 689                } else
 690#endif
 691                        ret = allocate_resource(&iomem_resource, res, num, min,
 692                                                max, 1, pcmcia_align, &data);
 693                mutex_unlock(&rsrc_mutex);
 694                if (ret == 0 || low)
 695                        break;
 696                low = 1;
 697        }
 698
 699        if (ret != 0) {
 700                kfree(res);
 701                res = NULL;
 702        }
 703        return res;
 704}
 705
 706
 707static int adjust_memory(struct pcmcia_socket *s, unsigned int action, unsigned long start, unsigned long end)
 708{
 709        struct socket_data *data = s->resource_data;
 710        unsigned long size = end - start + 1;
 711        int ret = 0;
 712
 713        if (end < start)
 714                return -EINVAL;
 715
 716        mutex_lock(&rsrc_mutex);
 717        switch (action) {
 718        case ADD_MANAGED_RESOURCE:
 719                ret = add_interval(&data->mem_db, start, size);
 720                break;
 721        case REMOVE_MANAGED_RESOURCE:
 722                ret = sub_interval(&data->mem_db, start, size);
 723                if (!ret) {
 724                        struct pcmcia_socket *socket;
 725                        down_read(&pcmcia_socket_list_rwsem);
 726                        list_for_each_entry(socket, &pcmcia_socket_list, socket_list)
 727                                release_cis_mem(socket);
 728                        up_read(&pcmcia_socket_list_rwsem);
 729                }
 730                break;
 731        default:
 732                ret = -EINVAL;
 733        }
 734        mutex_unlock(&rsrc_mutex);
 735
 736        return ret;
 737}
 738
 739
 740static int adjust_io(struct pcmcia_socket *s, unsigned int action, unsigned long start, unsigned long end)
 741{
 742        struct socket_data *data = s->resource_data;
 743        unsigned long size = end - start + 1;
 744        int ret = 0;
 745
 746        if (end < start)
 747                return -EINVAL;
 748
 749        if (end > IO_SPACE_LIMIT)
 750                return -EINVAL;
 751
 752        mutex_lock(&rsrc_mutex);
 753        switch (action) {
 754        case ADD_MANAGED_RESOURCE:
 755                if (add_interval(&data->io_db, start, size) != 0) {
 756                        ret = -EBUSY;
 757                        break;
 758                }
 759#ifdef CONFIG_PCMCIA_PROBE
 760                if (probe_io)
 761                        do_io_probe(s, start, size);
 762#endif
 763                break;
 764        case REMOVE_MANAGED_RESOURCE:
 765                sub_interval(&data->io_db, start, size);
 766                break;
 767        default:
 768                ret = -EINVAL;
 769                break;
 770        }
 771        mutex_unlock(&rsrc_mutex);
 772
 773        return ret;
 774}
 775
 776
 777#ifdef CONFIG_PCI
 778static int nonstatic_autoadd_resources(struct pcmcia_socket *s)
 779{
 780        struct resource *res;
 781        int i, done = 0;
 782
 783        if (!s->cb_dev || !s->cb_dev->bus)
 784                return -ENODEV;
 785
 786#if defined(CONFIG_X86)
 787        /* If this is the root bus, the risk of hitting
 788         * some strange system devices which aren't protected
 789         * by either ACPI resource tables or properly requested
 790         * resources is too big. Therefore, don't do auto-adding
 791         * of resources at the moment.
 792         */
 793        if (s->cb_dev->bus->number == 0)
 794                return -EINVAL;
 795#endif
 796
 797        for (i=0; i < PCI_BUS_NUM_RESOURCES; i++) {
 798                res = s->cb_dev->bus->resource[i];
 799                if (!res)
 800                        continue;
 801
 802                if (res->flags & IORESOURCE_IO) {
 803                        if (res == &ioport_resource)
 804                                continue;
 805                        dev_printk(KERN_INFO, &s->cb_dev->dev,
 806                                   "pcmcia: parent PCI bridge I/O "
 807                                   "window: 0x%llx - 0x%llx\n",
 808                                   (unsigned long long)res->start,
 809                                   (unsigned long long)res->end);
 810                        if (!adjust_io(s, ADD_MANAGED_RESOURCE, res->start, res->end))
 811                                done |= IORESOURCE_IO;
 812
 813                }
 814
 815                if (res->flags & IORESOURCE_MEM) {
 816                        if (res == &iomem_resource)
 817                                continue;
 818                        dev_printk(KERN_INFO, &s->cb_dev->dev,
 819                                   "pcmcia: parent PCI bridge Memory "
 820                                   "window: 0x%llx - 0x%llx\n",
 821                                   (unsigned long long)res->start,
 822                                   (unsigned long long)res->end);
 823                        if (!adjust_memory(s, ADD_MANAGED_RESOURCE, res->start, res->end))
 824                                done |= IORESOURCE_MEM;
 825                }
 826        }
 827
 828        /* if we got at least one of IO, and one of MEM, we can be glad and
 829         * activate the PCMCIA subsystem */
 830        if (done == (IORESOURCE_MEM | IORESOURCE_IO))
 831                s->resource_setup_done = 1;
 832
 833        return 0;
 834}
 835
 836#else
 837
 838static inline int nonstatic_autoadd_resources(struct pcmcia_socket *s)
 839{
 840        return -ENODEV;
 841}
 842
 843#endif
 844
 845
 846static int nonstatic_init(struct pcmcia_socket *s)
 847{
 848        struct socket_data *data;
 849
 850        data = kzalloc(sizeof(struct socket_data), GFP_KERNEL);
 851        if (!data)
 852                return -ENOMEM;
 853
 854        data->mem_db.next = &data->mem_db;
 855        data->io_db.next = &data->io_db;
 856
 857        s->resource_data = (void *) data;
 858
 859        nonstatic_autoadd_resources(s);
 860
 861        return 0;
 862}
 863
 864static void nonstatic_release_resource_db(struct pcmcia_socket *s)
 865{
 866        struct socket_data *data = s->resource_data;
 867        struct resource_map *p, *q;
 868
 869        mutex_lock(&rsrc_mutex);
 870        for (p = data->mem_db.next; p != &data->mem_db; p = q) {
 871                q = p->next;
 872                kfree(p);
 873        }
 874        for (p = data->io_db.next; p != &data->io_db; p = q) {
 875                q = p->next;
 876                kfree(p);
 877        }
 878        mutex_unlock(&rsrc_mutex);
 879}
 880
 881
 882struct pccard_resource_ops pccard_nonstatic_ops = {
 883        .validate_mem = pcmcia_nonstatic_validate_mem,
 884        .adjust_io_region = nonstatic_adjust_io_region,
 885        .find_io = nonstatic_find_io_region,
 886        .find_mem = nonstatic_find_mem_region,
 887        .add_io = adjust_io,
 888        .add_mem = adjust_memory,
 889        .init = nonstatic_init,
 890        .exit = nonstatic_release_resource_db,
 891};
 892EXPORT_SYMBOL(pccard_nonstatic_ops);
 893
 894
 895/* sysfs interface to the resource database */
 896
 897static ssize_t show_io_db(struct device *dev,
 898                          struct device_attribute *attr, char *buf)
 899{
 900        struct pcmcia_socket *s = dev_get_drvdata(dev);
 901        struct socket_data *data;
 902        struct resource_map *p;
 903        ssize_t ret = 0;
 904
 905        mutex_lock(&rsrc_mutex);
 906        data = s->resource_data;
 907
 908        for (p = data->io_db.next; p != &data->io_db; p = p->next) {
 909                if (ret > (PAGE_SIZE - 10))
 910                        continue;
 911                ret += snprintf (&buf[ret], (PAGE_SIZE - ret - 1),
 912                                 "0x%08lx - 0x%08lx\n",
 913                                 ((unsigned long) p->base),
 914                                 ((unsigned long) p->base + p->num - 1));
 915        }
 916
 917        mutex_unlock(&rsrc_mutex);
 918        return (ret);
 919}
 920
 921static ssize_t store_io_db(struct device *dev,
 922                           struct device_attribute *attr,
 923                           const char *buf, size_t count)
 924{
 925        struct pcmcia_socket *s = dev_get_drvdata(dev);
 926        unsigned long start_addr, end_addr;
 927        unsigned int add = ADD_MANAGED_RESOURCE;
 928        ssize_t ret = 0;
 929
 930        ret = sscanf (buf, "+ 0x%lx - 0x%lx", &start_addr, &end_addr);
 931        if (ret != 2) {
 932                ret = sscanf (buf, "- 0x%lx - 0x%lx", &start_addr, &end_addr);
 933                add = REMOVE_MANAGED_RESOURCE;
 934                if (ret != 2) {
 935                        ret = sscanf (buf, "0x%lx - 0x%lx", &start_addr, &end_addr);
 936                        add = ADD_MANAGED_RESOURCE;
 937                        if (ret != 2)
 938                                return -EINVAL;
 939                }
 940        }
 941        if (end_addr < start_addr)
 942                return -EINVAL;
 943
 944        ret = adjust_io(s, add, start_addr, end_addr);
 945        if (!ret)
 946                s->resource_setup_new = 1;
 947
 948        return ret ? ret : count;
 949}
 950static DEVICE_ATTR(available_resources_io, 0600, show_io_db, store_io_db);
 951
 952static ssize_t show_mem_db(struct device *dev,
 953                           struct device_attribute *attr, char *buf)
 954{
 955        struct pcmcia_socket *s = dev_get_drvdata(dev);
 956        struct socket_data *data;
 957        struct resource_map *p;
 958        ssize_t ret = 0;
 959
 960        mutex_lock(&rsrc_mutex);
 961        data = s->resource_data;
 962
 963        for (p = data->mem_db.next; p != &data->mem_db; p = p->next) {
 964                if (ret > (PAGE_SIZE - 10))
 965                        continue;
 966                ret += snprintf (&buf[ret], (PAGE_SIZE - ret - 1),
 967                                 "0x%08lx - 0x%08lx\n",
 968                                 ((unsigned long) p->base),
 969                                 ((unsigned long) p->base + p->num - 1));
 970        }
 971
 972        mutex_unlock(&rsrc_mutex);
 973        return (ret);
 974}
 975
 976static ssize_t store_mem_db(struct device *dev,
 977                            struct device_attribute *attr,
 978                            const char *buf, size_t count)
 979{
 980        struct pcmcia_socket *s = dev_get_drvdata(dev);
 981        unsigned long start_addr, end_addr;
 982        unsigned int add = ADD_MANAGED_RESOURCE;
 983        ssize_t ret = 0;
 984
 985        ret = sscanf (buf, "+ 0x%lx - 0x%lx", &start_addr, &end_addr);
 986        if (ret != 2) {
 987                ret = sscanf (buf, "- 0x%lx - 0x%lx", &start_addr, &end_addr);
 988                add = REMOVE_MANAGED_RESOURCE;
 989                if (ret != 2) {
 990                        ret = sscanf (buf, "0x%lx - 0x%lx", &start_addr, &end_addr);
 991                        add = ADD_MANAGED_RESOURCE;
 992                        if (ret != 2)
 993                                return -EINVAL;
 994                }
 995        }
 996        if (end_addr < start_addr)
 997                return -EINVAL;
 998
 999        ret = adjust_memory(s, add, start_addr, end_addr);
1000        if (!ret)
1001                s->resource_setup_new = 1;
1002
1003        return ret ? ret : count;
1004}
1005static DEVICE_ATTR(available_resources_mem, 0600, show_mem_db, store_mem_db);
1006
1007static struct attribute *pccard_rsrc_attributes[] = {
1008        &dev_attr_available_resources_io.attr,
1009        &dev_attr_available_resources_mem.attr,
1010        NULL,
1011};
1012
1013static const struct attribute_group rsrc_attributes = {
1014        .attrs = pccard_rsrc_attributes,
1015};
1016
1017static int __devinit pccard_sysfs_add_rsrc(struct device *dev,
1018                                           struct class_interface *class_intf)
1019{
1020        struct pcmcia_socket *s = dev_get_drvdata(dev);
1021
1022        if (s->resource_ops != &pccard_nonstatic_ops)
1023                return 0;
1024        return sysfs_create_group(&dev->kobj, &rsrc_attributes);
1025}
1026
1027static void __devexit pccard_sysfs_remove_rsrc(struct device *dev,
1028                                               struct class_interface *class_intf)
1029{
1030        struct pcmcia_socket *s = dev_get_drvdata(dev);
1031
1032        if (s->resource_ops != &pccard_nonstatic_ops)
1033                return;
1034        sysfs_remove_group(&dev->kobj, &rsrc_attributes);
1035}
1036
1037static struct class_interface pccard_rsrc_interface __refdata = {
1038        .class = &pcmcia_socket_class,
1039        .add_dev = &pccard_sysfs_add_rsrc,
1040        .remove_dev = __devexit_p(&pccard_sysfs_remove_rsrc),
1041};
1042
1043static int __init nonstatic_sysfs_init(void)
1044{
1045        return class_interface_register(&pccard_rsrc_interface);
1046}
1047
1048static void __exit nonstatic_sysfs_exit(void)
1049{
1050        class_interface_unregister(&pccard_rsrc_interface);
1051}
1052
1053module_init(nonstatic_sysfs_init);
1054module_exit(nonstatic_sysfs_exit);
1055