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